1:
37:
38: package ;
39:
40:
41: import ;
42: import ;
43:
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67:
68: public class OpenTypeFontPeer
69: extends ClasspathFontPeer
70: {
71:
72:
75: private static Properties fontProperties;
76:
77:
80: private static Set<String> availableFontNames;
81:
82:
85: private static Map<String,Map<String,String>> fontToFileMap;
86:
87: static
88: {
89: fontProperties = new Properties();
90: InputStream in = OpenTypeFontPeer.class.getResourceAsStream("fonts.properties");
91: try
92: {
93: fontProperties.load(in);
94: }
95: catch (IOException e)
96: {
97: e.printStackTrace();
98: }
99: }
100:
101: private class XLineMetrics
102: extends LineMetrics
103: {
104:
105: private Font font;
106: private GlyphVector glyphVector;
107:
108:
109:
110: private FontRenderContext fontRenderContext;
111: XLineMetrics(Font f, CharacterIterator ci, int b, int l,
112: FontRenderContext rc)
113: {
114: font = f;
115:
116:
117:
118: fontRenderContext = rc;
119: glyphVector = fontDelegate.createGlyphVector(font, fontRenderContext,
120: ci);
121: }
122:
123: public float getAscent()
124: {
125: return fontDelegate.getAscent(font.getSize(), fontRenderContext.getTransform(),
126: fontRenderContext.isAntiAliased(),
127: fontRenderContext.usesFractionalMetrics(), true);
128: }
129:
130: public int getBaselineIndex()
131: {
132:
133: throw new UnsupportedOperationException("Not yet implemented");
134: }
135:
136: public float[] getBaselineOffsets()
137: {
138:
139: throw new UnsupportedOperationException("Not yet implemented");
140: }
141:
142: public float getDescent()
143: {
144: return (int) fontDelegate.getDescent(font.getSize(), IDENDITY, false,
145: false, false);
146: }
147:
148: public float getHeight()
149: {
150: return (float) glyphVector.getLogicalBounds().getHeight();
151: }
152:
153: public float getLeading()
154: {
155: return getHeight() - getAscent() - getDescent();
156: }
157:
158: public int getNumChars()
159: {
160:
161: throw new UnsupportedOperationException("Not yet implemented");
162: }
163:
164: public float getStrikethroughOffset()
165: {
166: return 0.F;
167: }
168:
169: public float getStrikethroughThickness()
170: {
171: return 0.F;
172: }
173:
174: public float getUnderlineOffset()
175: {
176: return 0.F;
177: }
178:
179: public float getUnderlineThickness()
180: {
181: return 0.F;
182: }
183:
184: }
185:
186: private class XFontMetrics
187: extends FontMetrics
188: {
189:
192: private Point2D cachedPoint = new Point2D.Double();
193:
194: XFontMetrics(Font f)
195: {
196: super(f);
197: }
198:
199: public int getAscent()
200: {
201: return (int) fontDelegate.getAscent(getFont().getSize(), IDENDITY,
202: false, false, false);
203: }
204:
205: public int getDescent()
206: {
207: return (int) fontDelegate.getDescent(getFont().getSize(), IDENDITY,
208: false, false, false);
209: }
210:
211: public int getHeight()
212: {
213: GlyphVector gv = fontDelegate.createGlyphVector(getFont(),
214: new FontRenderContext(IDENDITY, false, false),
215: new StringCharacterIterator("m"));
216: Rectangle2D b = gv.getVisualBounds();
217: return (int) b.getHeight();
218: }
219:
220: public int charWidth(char c)
221: {
222: int code = fontDelegate.getGlyphIndex(c);
223: Point2D advance = cachedPoint;
224: fontDelegate.getAdvance(code, font.getSize2D(), IDENDITY,
225: false, false, true, advance);
226: return (int) advance.getX();
227: }
228:
229: public int charsWidth(char[] chars, int offs, int len)
230: {
231: return stringWidth(new String(chars, offs, len));
232: }
233:
234: public int stringWidth(String s)
235: {
236: GlyphVector gv = fontDelegate.createGlyphVector(getFont(),
237: new FontRenderContext(IDENDITY, false, false),
238: new StringCharacterIterator(s));
239: Rectangle2D b = gv.getVisualBounds();
240: return (int) b.getWidth();
241: }
242: }
243:
244:
247: private static final AffineTransform IDENDITY = new AffineTransform();
248:
249: private FontDelegate fontDelegate;
250:
251: public OpenTypeFontPeer(String name, int style, int size)
252: {
253: super(name, style, size);
254: try
255: {
256: String fontSpec = encodeFont(name, style);
257: String filename = mapFontToFilename(fontSpec);
258: File fontfile = new File(filename);
259: FileInputStream in = new FileInputStream(fontfile);
260: FileChannel ch = in.getChannel();
261: ByteBuffer buffer = ch.map(FileChannel.MapMode.READ_ONLY, 0,
262: fontfile.length());
263: fontDelegate = FontFactory.createFonts(buffer)[0];
264: }
265: catch (Exception ex)
266: {
267: ex.printStackTrace();
268: }
269: }
270:
271: public OpenTypeFontPeer(String name, Map atts)
272: {
273: super(name, atts);
274: try
275: {
276: String fontSpec = encodeFont(name, atts);
277: String filename = mapFontToFilename(fontSpec);
278: File fontfile = new File(filename);
279: FileInputStream in = new FileInputStream(fontfile);
280: FileChannel ch = in.getChannel();
281: ByteBuffer buffer = ch.map(FileChannel.MapMode.READ_ONLY, 0,
282: fontfile.length());
283: fontDelegate = FontFactory.createFonts(buffer)[0];
284: }
285: catch (Exception ex)
286: {
287: ex.printStackTrace();
288: }
289: }
290:
291: public boolean canDisplay(Font font, int c)
292: {
293:
294: throw new UnsupportedOperationException("Not yet implemented");
295: }
296:
297: public int canDisplayUpTo(Font font, CharacterIterator i, int start, int limit)
298: {
299:
300: throw new UnsupportedOperationException("Not yet implemented");
301: }
302:
303: public String getSubFamilyName(Font font, Locale locale)
304: {
305:
306: throw new UnsupportedOperationException("Not yet implemented");
307: }
308:
309: public String getPostScriptName(Font font)
310: {
311:
312: throw new UnsupportedOperationException("Not yet implemented");
313: }
314:
315: public int getNumGlyphs(Font font)
316: {
317:
318: throw new UnsupportedOperationException("Not yet implemented");
319: }
320:
321: public int getMissingGlyphCode(Font font)
322: {
323:
324: throw new UnsupportedOperationException("Not yet implemented");
325: }
326:
327: public byte getBaselineFor(Font font, char c)
328: {
329:
330: throw new UnsupportedOperationException("Not yet implemented");
331: }
332:
333: public String getGlyphName(Font font, int glyphIndex)
334: {
335:
336: throw new UnsupportedOperationException("Not yet implemented");
337: }
338:
339: public GlyphVector createGlyphVector(Font font, FontRenderContext frc, CharacterIterator ci)
340: {
341: return fontDelegate.createGlyphVector(font, frc, ci);
342: }
343:
344: public GlyphVector createGlyphVector(Font font, FontRenderContext ctx, int[] glyphCodes)
345: {
346:
347: throw new UnsupportedOperationException("Not yet implemented");
348: }
349:
350: public GlyphVector layoutGlyphVector(Font font, FontRenderContext frc, char[] chars, int start, int limit, int flags)
351: {
352: StringCharacterIterator i = new StringCharacterIterator(new String(chars), start, limit, 0);
353: return fontDelegate.createGlyphVector(font, frc, i);
354: }
355:
356: public FontMetrics getFontMetrics(Font font)
357: {
358: return new XFontMetrics(font);
359: }
360:
361: public boolean hasUniformLineMetrics(Font font)
362: {
363:
364: throw new UnsupportedOperationException("Not yet implemented");
365: }
366:
367: public LineMetrics getLineMetrics(Font font, CharacterIterator ci, int begin, int limit, FontRenderContext rc)
368: {
369: return new XLineMetrics(font, ci, begin, limit, rc);
370: }
371:
372: public Rectangle2D getMaxCharBounds(Font font, FontRenderContext rc)
373: {
374:
375: throw new UnsupportedOperationException("Not yet implemented");
376: }
377:
378:
392: public static String encodeFont(String name, Map atts)
393: {
394: String family = name;
395: if (family == null || family.equals(""))
396: family = (String) atts.get(TextAttribute.FAMILY);
397: if (family == null)
398: family = "SansSerif";
399:
400: int style = 0;
401:
402: Float posture = (Float) atts.get(TextAttribute.POSTURE);
403: if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR))
404: style |= Font.ITALIC;
405:
406:
407: Float weight = (Float) atts.get(TextAttribute.WEIGHT);
408: if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0)
409: style |= Font.BOLD;
410:
411: return encodeFont(name, style);
412: }
413:
414:
425: static String encodeFont(String name, int style)
426: {
427: CPStringBuilder key = new CPStringBuilder();
428: key.append(validName(name));
429: key.append('/');
430: switch (style)
431: {
432: case Font.BOLD:
433: key.append("b");
434: break;
435: case Font.ITALIC:
436: key.append("i");
437: break;
438: case (Font.BOLD | Font.ITALIC):
439: key.append("bi");
440: break;
441: case Font.PLAIN:
442: default:
443: key.append("p");
444:
445: }
446:
447: return key.toString();
448: }
449:
450:
458: static String validName(String name)
459: {
460: String retVal;
461: Set<String> fontNames = getFontNames();
462: if (fontNames.contains(name))
463: {
464: retVal = name;
465: }
466: else
467: {
468: retVal = "SansSerif";
469: }
470: return retVal;
471: }
472:
473: public static String[] getAvailableFontFamilyNames(Locale l)
474: {
475: Set<String> fontNames = getFontNames();
476: int numNames = fontNames.size();
477: String[] ret = fontNames.toArray(new String[numNames]);
478: return ret;
479: }
480:
481: private static synchronized Set<String> getFontNames()
482: {
483: if (availableFontNames == null)
484: {
485: HashSet<String> familyNames = new HashSet<String>();
486: for (Object o : fontProperties.keySet())
487: {
488: if (o instanceof String)
489: {
490: String key = (String) o;
491: int slashIndex = key.indexOf('/');
492: String name = key.substring(0, slashIndex);
493: familyNames.add(name);
494: }
495: }
496: availableFontNames = familyNames;
497: }
498: return availableFontNames;
499: }
500:
501:
511: private synchronized String mapFontToFilename(String fontSpec)
512: {
513: if (fontToFileMap == null)
514: {
515: fontToFileMap = new HashMap<String,Map<String,String>>();
516:
517:
518:
519: for (Object o : fontProperties.keySet())
520: {
521: if (o instanceof String)
522: {
523: String key = (String) o;
524: int slashIndex = key.indexOf('/');
525: String name = key.substring(0, slashIndex);
526: String spec = key.substring(slashIndex + 1);
527:
528: if (! spec.equals("a"))
529: {
530: Map<String,String> specToFileMap = fontToFileMap.get(name);
531: if (specToFileMap == null)
532: {
533: specToFileMap = new HashMap<String,String>();
534: fontToFileMap.put(name, specToFileMap);
535: }
536: specToFileMap.put(spec, fontProperties.getProperty(key));
537: }
538: }
539: }
540:
541: for (Object o : fontProperties.keySet())
542: {
543: if (o instanceof String)
544: {
545: String key = (String) o;
546: int slashIndex = key.indexOf('/');
547: String name = key.substring(0, slashIndex);
548: String spec = key.substring(slashIndex + 1);
549:
550: if (spec.equals("a"))
551: {
552: String alias = fontProperties.getProperty(key);
553: Map<String,String> specToFileMap = fontToFileMap.get(alias);
554: fontToFileMap.put(name, specToFileMap);
555: }
556: }
557: }
558: }
559:
560: int slashIndex = fontSpec.indexOf('/');
561: String name = fontSpec.substring(0, slashIndex);
562: String spec = fontSpec.substring(slashIndex + 1);
563: return fontToFileMap.get(name).get(spec);
564: }
565: }