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 java.awt.Color;
37 import java.awt.Font;
38 import java.awt.FontFormatException;
39 import java.awt.FontMetrics;
40 import java.awt.Graphics2D;
41 import java.awt.RenderingHints;
42 import java.awt.font.FontRenderContext;
43 import java.awt.font.TextLayout;
44 import java.awt.geom.Rectangle2D;
45 import java.awt.image.BufferedImage;
46 import java.awt.image.RenderedImage;
47 import java.io.File;
48 import java.io.FileInputStream;
49 import java.io.IOException;
50 import java.io.InputStream;
51
52 import javax.imageio.ImageIO;
53
54
55
56
57
58
59 public class Text2PngFactory {
60
61
62
63
64 private String fontname;
65
66
67
68
69 private int fontsize;
70
71
72
73
74 private String text = "";
75
76
77
78
79 private int r = 0;
80
81 private int g = 0;
82
83 private int b = 0;
84
85
86
87
88 private int br = 0xff;
89
90 private int bg = 0xff;
91
92 private int bb = 0xff;
93
94
95
96
97 private Graphics2D g2;
98
99
100
101
102 private Font cachedFont;
103
104
105
106
107 public Text2PngFactory() {
108
109 this.g2 = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR).createGraphics();
110
111 setOptimalRenderQuality(this.g2);
112 }
113
114
115
116
117
118
119
120
121
122 public Text2PngFactory(String fontname, int fontsize) throws IOException, FontFormatException {
123 this(fontname, fontsize, "");
124 }
125
126
127
128
129
130
131
132
133
134
135 public Text2PngFactory(String fontname, int fontsize, String text) throws IOException, FontFormatException {
136
137
138 this.g2 = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR).createGraphics();
139
140 setOptimalRenderQuality(this.g2);
141 this.setFontFace(fontname);
142 this.setFontSize(fontsize);
143 this.setText(text);
144 }
145
146
147
148
149
150
151
152 public void createPngFile(String location) throws IOException {
153 createPngFile(new File(location));
154 }
155
156
157
158
159
160
161
162 public void createPngFile(File location) throws IOException {
163 ImageIO.write(createImage(), "png", location);
164 }
165
166
167
168
169
170
171
172 public RenderedImage createImage() throws IOException {
173
174 if (this.fontname == null) {
175 throw new IOException("No font name given!");
176 }
177
178
179 FontRenderContext frc = this.g2.getFontRenderContext();
180 TextLayout layout = new TextLayout(this.text, this.cachedFont, frc);
181 Rectangle2D bounds = layout.getBounds();
182
183
184
185 int stringWidth = (int) (Math.ceil(bounds.getWidth())) + 2;
186
187
188
189
190 FontMetrics fm = this.g2.getFontMetrics();
191 int stringHeight = fm.getHeight();
192
193
194 BufferedImage im = new BufferedImage(stringWidth, stringHeight, BufferedImage.TYPE_3BYTE_BGR);
195
196
197 Graphics2D graphics = im.createGraphics();
198
199
200 setOptimalRenderQuality(graphics);
201
202
203 graphics.setBackground(new Color(this.br, this.bg, this.bb));
204 graphics.setColor(new Color(this.r, this.g, this.b));
205 graphics.clearRect(0, 0, stringWidth, stringHeight);
206
207
208 graphics.setFont(getFont());
209
210
211
212 layout.draw(graphics, -(float) Math.floor(bounds.getX()), fm.getMaxAscent());
213
214
215 return im;
216 }
217
218
219
220
221
222
223 public void setText(String text) {
224 this.text = text;
225 }
226
227
228
229
230
231
232
233
234 public void setTextRGB(int r, int g, int b) {
235 this.r = r;
236 this.g = g;
237 this.b = b;
238 }
239
240
241
242
243
244
245
246
247 public void setBackgroundRGB(int r, int g, int b) {
248 this.br = r;
249 this.bg = g;
250 this.bb = b;
251 }
252
253
254
255
256
257
258 public void setFontFace(String fontname) throws IOException, FontFormatException {
259
260 if (!fontname.equals(this.fontname)) {
261 this.fontname = fontname;
262 updateFace();
263 }
264 }
265
266
267
268
269
270
271 public void setFontSize(int fontsize) {
272 if (fontsize != this.fontsize) {
273 this.fontsize = fontsize;
274 updateSize();
275 }
276 }
277
278
279
280
281
282
283
284 private void updateFace() throws IOException, FontFormatException {
285 Font createdFont = null;
286
287
288 String fontpath = "fonts/" + this.fontname + ".ttf";
289
290 InputStream fontStream = this.getClass().getClassLoader().getResourceAsStream(fontpath);
291 if (fontStream != null) {
292 createdFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
293 fontStream.close();
294 }
295
296 if (createdFont == null) {
297 Font tempFont = new Font(this.fontname, Font.PLAIN, 1);
298
299
300 if (tempFont.getFamily().equals(this.fontname)) {
301
302 createdFont = tempFont;
303 }
304 }
305
306 if (createdFont == null) {
307 fontStream = new FileInputStream(this.fontname);
308 createdFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
309 fontStream.close();
310 }
311
312 if (createdFont == null) {
313 throw new IOException("Can't locate font: " + this.fontname);
314 }
315
316
317 this.cachedFont = createdFont.deriveFont((float) this.fontsize);
318
319
320 this.g2.setFont(this.cachedFont);
321 }
322
323
324
325
326 private void updateSize() {
327
328 if (this.cachedFont == null) {
329 return;
330 }
331
332
333 this.cachedFont = this.cachedFont.deriveFont((float) this.fontsize);
334
335
336 this.g2.setFont(this.cachedFont);
337 }
338
339
340
341
342
343
344 private FontMetrics getFontMetrics() {
345
346 return this.g2.getFontMetrics();
347 }
348
349
350
351
352
353
354 private Font getFont() {
355
356 return this.cachedFont;
357 }
358
359
360
361
362
363
364 private void setOptimalRenderQuality(Graphics2D graphics) {
365
366 graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
367 graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
368 graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
369 graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
370 }
371
372 @Override
373 public String toString() {
374 return this.fontname + ", " + this.fontsize + "pt: " + this.text;
375 }
376 }