1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
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:
62: import ;
63: import ;
64: import ;
65:
66:
71: public class XFontPeer
72: extends ClasspathFontPeer
73: {
74:
75:
78: private static Properties fontProperties;
79: static
80: {
81: fontProperties = new Properties();
82: InputStream in = XFontPeer.class.getResourceAsStream("xfonts.properties");
83: try
84: {
85: fontProperties.load(in);
86: }
87: catch (IOException e)
88: {
89: e.printStackTrace();
90: }
91: }
92:
93:
96: private class XFontMetrics
97: extends FontMetrics
98: {
99:
102: int ascent;
103:
104:
107: int descent;
108:
109:
112: private int maxAdvance;
113:
114:
117: int leading;
118:
119:
123: private HashMap metricsCache;
124:
125:
128: private int[] charWidths;
129:
130:
135: protected XFontMetrics(Font font)
136: {
137: super(font);
138: metricsCache = new HashMap();
139: Fontable.FontInfo info = getXFont().info();
140: ascent = info.font_ascent();
141: descent = info.font_descent();
142: maxAdvance = info.max_bounds().character_width();
143: leading = 0;
144:
145: if (info.min_byte1() == 0 && info.max_byte1() == 0)
146: readCharWidthsLinear(info);
147: else
148: readCharWidthsNonLinear(info);
149: }
150:
151:
157: private void readCharWidthsLinear(Fontable.FontInfo info)
158: {
159: int startIndex = info.min_char_or_byte2();
160: int endIndex = info.max_char_or_byte2();
161: charWidths = new int[endIndex + 1];
162:
163: for (int i = 0; i < startIndex; i++)
164: {
165: charWidths[i] = 0;
166: }
167:
168: int index = startIndex;
169: Fontable.FontInfo.CharInfo[] charInfos = info.char_infos();
170: for (Fontable.FontInfo.CharInfo charInfo : charInfos)
171: {
172: charWidths[index] = charInfo.character_width();
173: index++;
174: }
175: }
176:
177: private void readCharWidthsNonLinear(Fontable.FontInfo info)
178: {
179:
180: throw new UnsupportedOperationException("Not yet implemented");
181: }
182:
183:
188: public int getAscent()
189: {
190: return ascent;
191: }
192:
193:
198: public int getDescent()
199: {
200: return descent;
201: }
202:
203:
209: public int getHeight()
210: {
211: return ascent + descent;
212: }
213:
214:
219: public int getLeading()
220: {
221: return leading;
222: }
223:
224:
229: public int getMaxAdvance()
230: {
231: return maxAdvance;
232: }
233:
234:
241: public int charWidth(char c)
242: {
243: int width;
244: if (c > charWidths.length)
245: width = charWidths['?'];
246: else
247: width = charWidths[c];
248: return width;
249: }
250:
251:
260: public int charsWidth(char[] c, int offset, int length)
261: {
262: int width = 0;
263: if (c.length > 0 && length > 0)
264: {
265: String s = new String(c, offset, length);
266: width = stringWidth(s);
267: }
268: return width;
269: }
270:
271:
278: public int stringWidth(String s)
279: {
280: int width = 0;
281: if (s.length() > 0)
282: {
283: if (metricsCache.containsKey(s))
284: {
285: width = ((Integer) metricsCache.get(s)).intValue();
286: }
287: else
288: {
289: Fontable.TextExtentInfo extents = getXFont().text_extent(s);
290:
300: width = extents.overall_width();
301:
302: metricsCache.put(s, new Integer(width));
303: }
304: }
305:
306:
307: return width;
308: }
309: }
310:
311:
314: private class XLineMetrics
315: extends LineMetrics
316: {
317:
318:
323: public float getAscent()
324: {
325: return fontMetrics.ascent;
326: }
327:
328: public int getBaselineIndex()
329: {
330:
331: throw new UnsupportedOperationException();
332: }
333:
334: public float[] getBaselineOffsets()
335: {
336:
337: throw new UnsupportedOperationException();
338: }
339:
340:
345: public float getDescent()
346: {
347: return fontMetrics.descent;
348: }
349:
350:
356: public float getHeight()
357: {
358: return fontMetrics.ascent + fontMetrics.descent;
359: }
360:
361:
366: public float getLeading()
367: {
368: return fontMetrics.leading;
369: }
370:
371: public int getNumChars()
372: {
373:
374: throw new UnsupportedOperationException();
375: }
376:
377: public float getStrikethroughOffset()
378: {
379: return 0.F;
380: }
381:
382: public float getStrikethroughThickness()
383: {
384: return 1.F;
385: }
386:
387: public float getUnderlineOffset()
388: {
389: return 0.F;
390: }
391:
392: public float getUnderlineThickness()
393: {
394: return 1.F;
395: }
396:
397: }
398:
399:
402: private gnu.x11.Font xfont;
403:
404: private String name;
405:
406: private int style;
407:
408: private int size;
409:
410:
413: XFontMetrics fontMetrics;
414:
415:
422: public XFontPeer(String name, int style, int size)
423: {
424: super(name, style, size);
425: this.name = name;
426: this.style = style;
427: this.size = size;
428: }
429:
430:
437: public XFontPeer(String name, Map atts)
438: {
439: super(name, atts);
440: String family = name;
441: if (family == null || family.equals(""))
442: family = (String) atts.get(TextAttribute.FAMILY);
443: if (family == null)
444: family = "SansSerif";
445:
446: int size = 12;
447: Float sizeFl = (Float) atts.get(TextAttribute.SIZE);
448: if (sizeFl != null)
449: size = sizeFl.intValue();
450:
451: int style = 0;
452:
453: Float posture = (Float) atts.get(TextAttribute.POSTURE);
454: if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR))
455: style |= Font.ITALIC;
456:
457:
458: Float weight = (Float) atts.get(TextAttribute.WEIGHT);
459: if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0)
460: style |= Font.BOLD;
461:
462: this.name = name;
463: this.style = style;
464: this.size = size;
465: }
466:
467:
475: private void init(String name, int style, int size)
476: {
477: if (name == null)
478: {
479: name = "SansSerif";
480: }
481: GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
482: GraphicsDevice dev = env.getDefaultScreenDevice();
483: if (dev instanceof XGraphicsDevice)
484: {
485: Display display = ((XGraphicsDevice) dev).getDisplay();
486: String fontDescr = encodeFont(name, style, size);
487: if (XToolkit.DEBUG)
488: System.err.println("XLFD font description: " + fontDescr);
489: xfont = new gnu.x11.Font(display, fontDescr);
490: }
491: else
492: {
493: throw new AWTError("Local GraphicsEnvironment is not XWindowGraphicsEnvironment");
494: }
495: }
496:
497: public boolean canDisplay(Font font, int c)
498: {
499:
500: throw new UnsupportedOperationException("Not yet implemented.");
501: }
502:
503: public int canDisplayUpTo(Font font, CharacterIterator i, int start, int limit)
504: {
505:
506: throw new UnsupportedOperationException("Not yet implemented.");
507: }
508:
509: public String getSubFamilyName(Font font, Locale locale)
510: {
511:
512: throw new UnsupportedOperationException("Not yet implemented.");
513: }
514:
515: public String getPostScriptName(Font font)
516: {
517:
518: throw new UnsupportedOperationException("Not yet implemented.");
519: }
520:
521: public int getNumGlyphs(Font font)
522: {
523:
524: throw new UnsupportedOperationException("Not yet implemented.");
525: }
526:
527: public int getMissingGlyphCode(Font font)
528: {
529:
530: throw new UnsupportedOperationException("Not yet implemented.");
531: }
532:
533: public byte getBaselineFor(Font font, char c)
534: {
535:
536: throw new UnsupportedOperationException("Not yet implemented.");
537: }
538:
539: public String getGlyphName(Font font, int glyphIndex)
540: {
541:
542: throw new UnsupportedOperationException("Not yet implemented.");
543: }
544:
545: public GlyphVector createGlyphVector(Font font, FontRenderContext frc,
546: CharacterIterator ci)
547: {
548:
549: throw new UnsupportedOperationException("Not yet implemented.");
550: }
551:
552: public GlyphVector createGlyphVector(Font font, FontRenderContext ctx,
553: int[] glyphCodes)
554: {
555:
556: throw new UnsupportedOperationException("Not yet implemented.");
557: }
558:
559: public GlyphVector layoutGlyphVector(Font font, FontRenderContext frc,
560: char[] chars, int start, int limit,
561: int flags)
562: {
563:
564: throw new UnsupportedOperationException("Not yet implemented.");
565: }
566:
567:
574: public FontMetrics getFontMetrics(Font font)
575: {
576: if (font.getPeer() != this)
577: throw new AWTError("The specified font has a different peer than this");
578:
579: if (fontMetrics == null)
580: fontMetrics = new XFontMetrics(font);
581: return fontMetrics;
582: }
583:
584:
587: protected void finalize()
588: {
589: if (xfont != null)
590: xfont.close();
591: }
592:
593: public boolean hasUniformLineMetrics(Font font)
594: {
595:
596: throw new UnsupportedOperationException("Not yet implemented.");
597: }
598:
599:
603: public LineMetrics getLineMetrics(Font font, CharacterIterator ci, int begin,
604: int limit, FontRenderContext rc)
605: {
606: return new XLineMetrics();
607: }
608:
609: public Rectangle2D getMaxCharBounds(Font font, FontRenderContext rc)
610: {
611:
612: throw new UnsupportedOperationException("Not yet implemented.");
613: }
614:
615: public Rectangle2D getStringBounds(Font font, CharacterIterator ci,
616: int begin, int limit, FontRenderContext frc)
617: {
618:
619: throw new UnsupportedOperationException("Not yet implemented.");
620: }
621:
622:
636: static String encodeFont(String name, Map atts)
637: {
638: String family = name;
639: if (family == null || family.equals(""))
640: family = (String) atts.get(TextAttribute.FAMILY);
641: if (family == null)
642: family = "SansSerif";
643:
644: int size = 12;
645: Float sizeFl = (Float) atts.get(TextAttribute.SIZE);
646: if (sizeFl != null)
647: size = sizeFl.intValue();
648:
649: int style = 0;
650:
651: Float posture = (Float) atts.get(TextAttribute.POSTURE);
652: if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR))
653: style |= Font.ITALIC;
654:
655:
656: Float weight = (Float) atts.get(TextAttribute.WEIGHT);
657: if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0)
658: style |= Font.BOLD;
659:
660: return encodeFont(family, style, size);
661: }
662:
663:
678: static String encodeFont(String name, int style, int size)
679: {
680: CPStringBuilder key = new CPStringBuilder();
681: key.append(validName(name));
682: key.append('.');
683: switch (style)
684: {
685: case Font.BOLD:
686: key.append("bold");
687: break;
688: case Font.ITALIC:
689: key.append("italic");
690: break;
691: case (Font.BOLD | Font.ITALIC):
692: key.append("bolditalic");
693: break;
694: case Font.PLAIN:
695: default:
696: key.append("plain");
697:
698: }
699:
700: String protoType = fontProperties.getProperty(key.toString());
701: int s = validSize(size);
702: return protoType.replaceFirst("%d", String.valueOf(s));
703: }
704:
705:
713: static String validName(String name)
714: {
715: String retVal;
716: if (name.equalsIgnoreCase("sansserif")
717: || name.equalsIgnoreCase("serif")
718: || name.equalsIgnoreCase("monospaced")
719: || name.equalsIgnoreCase("dialog")
720: || name.equalsIgnoreCase("dialoginput"))
721: {
722: retVal = name.toLowerCase();
723: }
724: else
725: {
726: retVal = "sansserif";
727: }
728: return retVal;
729: }
730:
731:
738: private static final int validSize(int size)
739: {
740: int val;
741: if (size <= 9)
742: val = 8;
743: else if (size <= 11)
744: val = 10;
745: else if (size <= 13)
746: val = 12;
747: else if (size <= 17)
748: val = 14;
749: else if (size <= 23)
750: val = 18;
751: else
752: val = 24;
753: return val;
754: }
755:
756:
762: gnu.x11.Font getXFont()
763: {
764: if (xfont == null)
765: {
766: init(name, style, size);
767: }
768: return xfont;
769: }
770: }