1
2 package org.freehep.graphicsio.svg;
3
4 import java.awt.Font;
5 import java.awt.font.FontRenderContext;
6 import java.awt.font.GlyphVector;
7 import java.awt.font.TextAttribute;
8 import java.awt.font.TextLayout;
9 import java.awt.geom.AffineTransform;
10 import java.util.Enumeration;
11 import java.util.Hashtable;
12 import java.util.Iterator;
13 import java.util.Map;
14 import java.util.Properties;
15
16 import org.freehep.graphics2d.font.FontUtilities;
17 import org.freehep.graphicsio.font.FontTable;
18
19
20
21
22
23
24
25
26
27
28
29 public class SVGFontTable {
30
31
32
33
34
35 private Hashtable
36 new Hashtable
37
38
39
40
41
42
43
44
45 private SVGGlyph addGlyph(int c, Font font) {
46
47 Hashtable
48
49
50 SVGGlyph result = (SVGGlyph) glyphs.get(String.valueOf(c));
51
52
53 if (result == null) {
54
55 result = createGlyph(c, font);
56 glyphs.put(String.valueOf(c), result);
57 }
58
59 return result;
60 }
61
62
63
64
65
66
67 private SVGGlyph createGlyph(int c, Font font) {
68 GlyphVector glyphVector = font.createGlyphVector(
69
70 new FontRenderContext(null, true, true),
71
72 String.valueOf((char) c));
73
74
75 return new SVGGlyph(
76 glyphVector.getGlyphOutline(0),
77 c,
78 glyphVector.getGlyphMetrics(0));
79 }
80
81
82
83
84
85
86
87 protected void addGlyphs(String string, Font font) {
88 font = untransform(font);
89
90
91 for (int i = 0; i < string.length(); i ++) {
92 addGlyph(string.charAt(i), font);
93 }
94 }
95
96
97
98
99
100 private Hashtable
101
102 font = untransform(font);
103
104 Hashtable
105 (Hashtable
106 if (result == null) {
107 result = new Hashtable
108 glyphs.put(font, result);
109 }
110 return result;
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124 public String toString() {
125 StringBuffer result = new StringBuffer();
126
127 Enumeration
128 while (fonts.hasMoreElements()) {
129 Font font = (Font) fonts.nextElement();
130
131
132 Map
133
134
135 normalize(attributes);
136
137
138 result.append("<font id=\"");
139 result.append(attributes.get(TextAttribute.FAMILY));
140 result.append("\">\n");
141
142
143 result.append("<font-face font-family=\"");
144 result.append(attributes.get(TextAttribute.FAMILY));
145 result.append("\" ");
146
147
148 if (TextAttribute.WEIGHT_BOLD.equals(attributes.get(TextAttribute.WEIGHT))) {
149 result.append("font-weight=\"bold\" ");
150 } else {
151 result.append("font-weight=\"normal\" ");
152 }
153
154
155 if (TextAttribute.POSTURE_OBLIQUE.equals(attributes.get(TextAttribute.POSTURE))) {
156 result.append("font-style=\"italic\" ");
157 } else {
158 result.append("font-style=\"normal\" ");
159 }
160
161
162 Float size = (Float) attributes.get(TextAttribute.SIZE);
163 result.append("font-size=\"");
164 result.append(SVGGraphics2D.fixedPrecision(size.floatValue()));
165 result.append("\" ");
166
167
168
169 result.append("units-per-em=\"");
170 result.append(SVGGraphics2D.fixedPrecision(SVGGlyph.FONT_SIZE));
171 result.append("\" ");
172
173 TextLayout tl = new TextLayout("By", font, new FontRenderContext(new AffineTransform(), true, true));
174
175
176
177
178
179 result.append("ascent=\"");
180 result.append(tl.getAscent());
181 result.append("\" ");
182
183
184
185
186 result.append("desscent=\"");
187 result.append(tl.getDescent());
188 result.append("\" ");
189
190
191
192
193
194
195 result.append("/>\n");
196
197
198 SVGGlyph glyph = createGlyph(font.getMissingGlyphCode(), font);
199 result.append("<missing-glyph ");
200 result.append(glyph.getHorizontalAdvanceXString());
201 result.append(" ");
202 result.append(glyph.getPathString());
203 result.append("/>\n");
204
205
206 Iterator glyphs = getGlyphs(font).values().iterator();
207 while (glyphs.hasNext()) {
208 result.append(glyphs.next().toString());
209 result.append("\n");
210 }
211
212
213 result.append("</font>\n");
214 }
215
216 return result.toString();
217 }
218
219
220
221
222
223
224
225
226
227
228
229
230
231 private Font untransform(Font font) {
232
233 Map
234
235
236 attributes.put(TextAttribute.SIZE, new Float(SVGGlyph.FONT_SIZE));
237
238
239 attributes.remove(TextAttribute.TRANSFORM);
240 attributes.remove(TextAttribute.SUPERSCRIPT);
241
242 return new Font(attributes);
243 }
244
245
246
247
248
249 private static final Properties replaceFonts = new Properties();
250 static {
251 replaceFonts.setProperty("dialog", "Helvetica");
252 replaceFonts.setProperty("dialoginput", "Courier New");
253
254
255 replaceFonts.setProperty("serif", "Times");
256 replaceFonts.setProperty("timesroman", "Times");
257 replaceFonts.setProperty("sansserif", "Helvetica");
258
259
260 replaceFonts.setProperty("monospaced", "Courier New");
261
262 replaceFonts.setProperty("zapfdingbats", "Wingdings");
263 }
264
265
266
267
268
269
270
271
272
273
274
275
276
277 public static void normalize(Map
278
279 FontTable.normalize(attributes);
280
281
282 String family = replaceFonts.getProperty(
283 ((String) attributes.get(TextAttribute.FAMILY)).toLowerCase());
284 if (family == null) {
285 family = (String) attributes.get(TextAttribute.FAMILY);
286 }
287
288
289 attributes.put(TextAttribute.FAMILY, family);
290 }
291 }