1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.templating.jsp.taglib;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.ItemType;
38 import info.magnolia.cms.util.ContentUtil;
39
40 import java.awt.FontFormatException;
41 import java.awt.Graphics2D;
42 import java.awt.Image;
43 import java.awt.image.BufferedImage;
44 import java.io.File;
45 import java.io.FileNotFoundException;
46 import java.io.IOException;
47 import java.util.StringTokenizer;
48
49 import javax.imageio.ImageIO;
50 import javax.jcr.AccessDeniedException;
51 import javax.jcr.PathNotFoundException;
52 import javax.jcr.RepositoryException;
53 import javax.servlet.http.HttpServletRequest;
54 import javax.servlet.jsp.JspException;
55 import javax.servlet.jsp.JspWriter;
56 import javax.servlet.jsp.PageContext;
57
58 import org.apache.commons.lang.SystemUtils;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 import org.tldgen.annotations.BodyContent;
63 import org.tldgen.annotations.Tag;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 @Tag(name="txt2img", bodyContent=BodyContent.EMPTY)
100
101 public class TextToImageTag extends BaseImageTag {
102
103
104
105
106
107
108 private static final double SCALE_FACTOR = SystemUtils.IS_OS_WINDOWS ? 4 : 1;
109
110
111
112
113 private static final String CSS_CHARACTER_IMAGE = "character-image";
114
115
116
117
118 private static final String CSS_WORD_IMAGE = "word-image";
119
120
121
122
123 private static final String CSS_TEXT_IMAGE = "text-image";
124
125
126
127
128 private static final String TEXT_SPLIT_NONE = "none";
129
130
131
132
133 private static final String TEXT_SPLIT_WORDS = "words";
134
135
136
137
138 private static final String TEXT_SPLIT_CHARACTERS = "characters";
139
140 private static final Logger log = LoggerFactory.getLogger(BaseImageTag.class);
141
142 private String text;
143 private String textFontFace;
144 private int textFontSize;
145 private String textFontColor;
146 private String textBackColor;
147 private String textSplit;
148 private String divCSS;
149
150
151
152
153
154 public void setText(String text) {
155 this.text = text;
156 }
157
158
159
160
161
162 @Override
163 public void setImageContentNodeName(String imageContentNodeName) {
164 this.imageContentNodeName = imageContentNodeName;
165 }
166
167
168
169
170
171 @Override
172 public void setParentContentNodeName(String parentContentNodeName) {
173 this.parentContentNodeName = parentContentNodeName;
174 }
175
176
177
178
179
180 public void setTextFontFace(String textFontFace) {
181 this.textFontFace = textFontFace;
182 }
183
184
185
186
187
188 public void setTextFontSize(int textFontSize) {
189 this.textFontSize = textFontSize;
190 }
191
192
193
194
195
196 public void setTextFontColor(String textFontColor) {
197 this.textFontColor = textFontColor;
198 }
199
200
201
202
203
204 public void setTextBackColor(String textBackColor) {
205 this.textBackColor = textBackColor;
206 }
207
208
209
210
211
212 public void setTextSplit(String textSplit) {
213 this.textSplit = textSplit;
214 }
215
216
217
218
219
220
221 public void setDivCSS(String divCSS) {
222 this.divCSS = divCSS;
223 }
224
225
226
227
228 @Override
229 protected String getFilename() {
230 return "textImage";
231 }
232
233
234
235
236 public void setUp() {
237
238
239 if (this.text == null) {
240 this.text = "Test Test Test";
241 }
242 if (this.textFontFace == null) {
243 this.textFontFace = SystemUtils.IS_OS_WINDOWS ? "Arial" : "Helvetica";
244 }
245 if (this.textFontSize == 0) {
246 this.textFontSize = 12;
247 }
248 if (this.textFontColor == null) {
249 this.textFontColor = "000000";
250 }
251 if (this.textBackColor == null) {
252 this.textBackColor = "ffffff";
253 }
254 if (this.textSplit == null) {
255 this.textSplit = TEXT_SPLIT_NONE;
256 }
257 else if (!((this.textSplit.equals(TEXT_SPLIT_WORDS)) || (this.textSplit.equals(TEXT_SPLIT_CHARACTERS)))) {
258 this.textSplit = TEXT_SPLIT_NONE;
259 }
260 if (this.divCSS == null) {
261 this.divCSS = "text-box";
262 }
263 }
264
265 @Override
266 public void doTag() throws JspException {
267
268 this.setUp();
269
270 try {
271 Content imageContentNode = ContentUtil.asContent(getImageContentNode());
272
273 String[] subStrings = this.getTextSubStrings(this.text);
274 String[] imageURIs = this.getImageURIs(
275 subStrings,
276 (HttpServletRequest) ((PageContext) this.getJspContext()).getRequest(),
277 imageContentNode);
278 this.drawTextImages(imageURIs, subStrings);
279 }
280 catch (PathNotFoundException e) {
281 log.error("PathNotFoundException occured during text-to-image conversion: " + e.getMessage(), e);
282 }
283 catch (AccessDeniedException e) {
284 log.error("AccessDeniedException occured during text-to-image conversion: " + e.getMessage(), e);
285 }
286 catch (RepositoryException e) {
287 log.error("RepositoryException occured during text-to-image conversion: " + e.getMessage(), e);
288 }
289 catch (FileNotFoundException e) {
290 log.error("FileNotFoundException occured during text-to-image conversion: " + e.getMessage(), e);
291 }
292 catch (IOException e) {
293 log.error("IOException occured during text-to-image conversion: " + e.getMessage(), e);
294 }
295 catch (FontFormatException e) {
296 log.error("FontFormatException occured during text-to-image conversion: " + e.getMessage(), e);
297 }
298 this.cleanUp();
299 }
300
301
302
303
304 public void cleanUp() {
305 this.parentContentNodeName = null;
306 this.imageContentNodeName = null;
307 this.text = null;
308 this.textFontFace = null;
309 this.textFontSize = 0;
310 this.textFontColor = null;
311 this.textBackColor = null;
312 this.textSplit = null;
313 this.divCSS = null;
314 }
315
316
317
318
319
320
321
322 private void drawTextImages(String[] imageURIs, String[] subStrings) throws IOException {
323 JspWriter out = this.getJspContext().getOut();
324
325 if (this.divCSS != null) {
326 out.print("<div class=\"");
327 out.print(this.divCSS);
328 out.print("\">");
329 }
330
331 for (int i = 0; i < imageURIs.length; i++) {
332 out.print("<img class=\"");
333 if (this.textSplit.equals(TEXT_SPLIT_CHARACTERS)) {
334 out.print(CSS_CHARACTER_IMAGE);
335 }
336 else if (this.textSplit.equals(TEXT_SPLIT_WORDS)) {
337 out.print(CSS_WORD_IMAGE);
338 }
339 else {
340 out.print(CSS_TEXT_IMAGE);
341 }
342 out.print("\" src=\"");
343 out.print(imageURIs[i]);
344 out.print("\" alt=\"");
345 out.print(subStrings[i]);
346 out.print("\" />");
347 }
348
349 if (this.divCSS != null) {
350 out.print("</div>");
351 }
352 }
353
354
355
356
357
358
359
360 private String[] getTextSubStrings(String text) {
361 String[] subStrings = null;
362 if (this.textSplit.equals(TEXT_SPLIT_CHARACTERS)) {
363 subStrings = new String[text.length()];
364 for (int i = 0; i < text.length(); i++) {
365 subStrings[i] = text.substring(i, i + 1);
366 }
367 }
368 else if (this.textSplit.equals(TEXT_SPLIT_WORDS)) {
369 StringTokenizer st = new StringTokenizer(text, " ");
370 subStrings = new String[st.countTokens()];
371 for (int i = 0; st.hasMoreTokens(); i++) {
372 subStrings[i] = st.nextToken().trim();
373 }
374 }
375 else {
376 subStrings = new String[]{text};
377 }
378 return subStrings;
379 }
380
381
382
383
384
385
386 private String[] getImageURIs(String[] subStrings, HttpServletRequest req, Content imageContentNode)
387 throws PathNotFoundException, AccessDeniedException, RepositoryException, FileNotFoundException, IOException,
388 FontFormatException {
389
390 String[] imageURIs = new String[subStrings.length];
391 for (int i = 0; i < subStrings.length; i++) {
392
393 String tmpImgNodeName = subStrings[i]
394 + this.textBackColor
395 + this.textFontColor
396 + this.textFontFace
397 + this.textFontSize;
398 String imageNodeName = this.convertToSimpleString(tmpImgNodeName);
399
400 if (!imageContentNode.hasContent(imageNodeName)) {
401 File image = createImage(subStrings[i]);
402
403
404 Content imageNode = imageContentNode.createContent(imageNodeName, ItemType.CONTENTNODE);
405
406 this.createImageNode(image, imageNode);
407 }
408
409 String contextPath = req.getContextPath();
410 String handle = imageContentNode.getHandle();
411 String imageURI = contextPath
412 + handle
413 + "/"
414 + imageNodeName
415 + "/"
416 + getFilename()
417 + "."
418 + PROPERTIES_EXTENSION_VALUE;
419 imageURIs[i] = imageURI;
420 }
421 return imageURIs;
422 }
423
424
425
426
427
428
429 private File createImage(String subString) throws FileNotFoundException, IOException, FontFormatException {
430
431
432 File imageFile = File.createTempFile(getClass().getName(), "png");
433 imageFile.createNewFile();
434
435
436
437
438 Text2PngFactory tpf = new Text2PngFactory();
439 tpf.setFontFace(this.textFontFace);
440 tpf.setFontSize((int) (this.textFontSize * SCALE_FACTOR));
441 int[] textRGB = this.convertHexToRGB(this.textFontColor);
442 int[] backRGB = this.convertHexToRGB(this.textBackColor);
443 tpf.setTextRGB(textRGB[0], textRGB[1], textRGB[2]);
444 tpf.setBackgroundRGB(backRGB[0], backRGB[1], backRGB[2]);
445 tpf.setText(subString);
446
447 BufferedImage bigImgBuff = (BufferedImage) tpf.createImage();
448 if (SCALE_FACTOR != 1) {
449 BufferedImage smallImgBuff = this.scaleImage(bigImgBuff, (1.0 / SCALE_FACTOR));
450 ImageIO.write(smallImgBuff, "png", imageFile);
451 smallImgBuff = null;
452 }
453 else {
454 ImageIO.write(bigImgBuff, "png", imageFile);
455 }
456 bigImgBuff = null;
457 return imageFile;
458 }
459
460
461
462
463
464
465
466 private BufferedImage scaleImage(BufferedImage oriImgBuff, double scaleFactor) {
467
468
469 int oriWidth = oriImgBuff.getWidth();
470 int oriHeight = oriImgBuff.getHeight();
471
472 int newWidth = new Double(oriWidth * scaleFactor).intValue();
473 int newHeight = new Double(oriHeight * scaleFactor).intValue();
474
475 Image newImg = oriImgBuff.getScaledInstance(newWidth, newHeight, Image.SCALE_AREA_AVERAGING);
476 BufferedImage newImgBuff = new BufferedImage(
477 newImg.getWidth(null),
478 newImg.getHeight(null),
479 BufferedImage.TYPE_INT_RGB);
480 Graphics2D g = newImgBuff.createGraphics();
481 g.drawImage(newImg, 0, 0, null);
482 g.dispose();
483
484 return newImgBuff;
485 }
486
487 }