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