1:
37:
38:
39: package ;
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:
59: public class GdkFontPeer extends ClasspathFontPeer
60: {
61: static native void initStaticState();
62: private final int native_state = GtkGenericPeer.getUniqueInteger ();
63: private static ResourceBundle bundle;
64:
65:
68: private HashMap metricsCache;
69:
70: static
71: {
72: System.loadLibrary("gtkpeer");
73:
74: initStaticState ();
75:
76: try
77: {
78: bundle = ResourceBundle.getBundle ("gnu.java.awt.peer.gtk.font");
79: }
80: catch (Throwable ignored)
81: {
82: bundle = null;
83: }
84: }
85:
86: private ByteBuffer nameTable = null;
87:
88: private native void initState ();
89: private native void dispose ();
90: private native void setFont (String family, int style, int size);
91:
92: native void getFontMetrics(double [] metrics);
93: native void getTextMetrics(String str, double [] metrics);
94:
95: native void releasePeerGraphicsResource();
96:
97:
98: protected void finalize ()
99: {
100: releasePeerGraphicsResource();
101: dispose ();
102: }
103:
104:
110:
111: private String buildString(CharacterIterator iter)
112: {
113: StringBuffer sb = new StringBuffer();
114: for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next())
115: sb.append(c);
116: return sb.toString();
117: }
118:
119: private String buildString(CharacterIterator iter, int begin, int limit)
120: {
121: StringBuffer sb = new StringBuffer();
122: int i = 0;
123: for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next(), i++)
124: {
125: if (begin <= i)
126: sb.append(c);
127: if (limit <= i)
128: break;
129: }
130: return sb.toString();
131: }
132:
133: private String buildString(char[] chars, int begin, int limit)
134: {
135: return new String(chars, begin, limit - begin);
136: }
137:
138:
139:
140: public GdkFontPeer (String name, int style)
141: {
142:
143: this(name, style, 12);
144: }
145:
146: public GdkFontPeer (String name, int style, int size)
147: {
148: super(name, style, size);
149: initState ();
150: setFont (this.familyName, this.style, (int)this.size);
151: metricsCache = new HashMap();
152: }
153:
154: public GdkFontPeer (String name, Map attributes)
155: {
156: super(name, attributes);
157: initState ();
158: setFont (this.familyName, this.style, (int)this.size);
159: metricsCache = new HashMap();
160: }
161:
162:
165: public String getSubFamilyName(Font font, Locale locale)
166: {
167: String name;
168:
169: if (locale == null)
170: locale = Locale.getDefault();
171:
172: name = getName(NameDecoder.NAME_SUBFAMILY, locale);
173: if (name == null)
174: {
175: name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
176: if ("Regular".equals(name))
177: name = null;
178: }
179:
180: return name;
181: }
182:
183:
191: private native byte[] getTrueTypeTable(byte n, byte a, byte m, byte e);
192:
193:
197: public String getPostScriptName(Font font)
198: {
199: String name = getName(NameDecoder.NAME_POSTSCRIPT,
200: null);
201: if( name == null )
202: return this.familyName;
203:
204: return name;
205: }
206:
207:
217: private String getName(int name, Locale locale)
218: {
219: if (nameTable == null)
220: {
221: byte[] data = getTrueTypeTable((byte)'n', (byte) 'a',
222: (byte) 'm', (byte) 'e');
223: if( data == null )
224: return null;
225:
226: nameTable = ByteBuffer.wrap( data );
227: }
228:
229: return NameDecoder.getName(nameTable, name, locale);
230: }
231:
232: public boolean canDisplay (Font font, char c)
233: {
234:
235: return true;
236: }
237:
238: public int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit)
239: {
240:
241: return -1;
242: }
243:
244: public GlyphVector createGlyphVector (Font font,
245: FontRenderContext ctx,
246: CharacterIterator i)
247: {
248: return new FreetypeGlyphVector(font, buildString (i), ctx);
249: }
250:
251: public GlyphVector createGlyphVector (Font font,
252: FontRenderContext ctx,
253: int[] glyphCodes)
254: {
255: return new FreetypeGlyphVector(font, glyphCodes, ctx);
256: }
257:
258: public byte getBaselineFor (Font font, char c)
259: {
260:
261: return Font.ROMAN_BASELINE;
262: }
263:
264: private static class GdkFontLineMetrics extends LineMetrics
265: {
266: private FontMetrics fm;
267: private int nchars;
268: private float strikethroughOffset, strikethroughThickness,
269: underlineOffset, underlineThickness;
270:
271: public GdkFontLineMetrics (GdkFontPeer fp, FontMetrics m, int n)
272: {
273: fm = m;
274: nchars = n;
275: strikethroughOffset = 0f;
276: underlineOffset = 0f;
277: strikethroughThickness = ((float)fp.getSize(null)) / 12f;
278: underlineThickness = strikethroughThickness;
279: }
280:
281: public float getAscent()
282: {
283: return (float) fm.getAscent ();
284: }
285:
286: public int getBaselineIndex()
287: {
288:
289: return Font.ROMAN_BASELINE;
290: }
291:
292: public float[] getBaselineOffsets()
293: {
294: return new float[3];
295: }
296:
297: public float getDescent()
298: {
299: return (float) fm.getDescent ();
300: }
301:
302: public float getHeight()
303: {
304: return (float) fm.getHeight ();
305: }
306:
307: public float getLeading() { return 0.f; }
308: public int getNumChars() { return nchars; }
309: public float getStrikethroughOffset() { return 0.f; }
310: public float getStrikethroughThickness() { return 0.f; }
311: public float getUnderlineOffset() { return 0.f; }
312: public float getUnderlineThickness() { return 0.f; }
313:
314: }
315:
316: public LineMetrics getLineMetrics (Font font, CharacterIterator ci,
317: int begin, int limit, FontRenderContext rc)
318: {
319: return new GdkFontLineMetrics (this, getFontMetrics (font), limit - begin);
320: }
321:
322: public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc)
323: {
324: throw new UnsupportedOperationException ();
325: }
326:
327: public int getMissingGlyphCode (Font font)
328: {
329: throw new UnsupportedOperationException ();
330: }
331:
332: public String getGlyphName (Font font, int glyphIndex)
333: {
334: throw new UnsupportedOperationException ();
335: }
336:
337: public int getNumGlyphs (Font font)
338: {
339: byte[] data = getTrueTypeTable((byte)'m', (byte) 'a',
340: (byte)'x', (byte) 'p');
341: if( data == null )
342: return -1;
343:
344: ByteBuffer buf = ByteBuffer.wrap( data );
345: return buf.getShort(4);
346: }
347:
348: public Rectangle2D getStringBounds (Font font, CharacterIterator ci,
349: int begin, int limit, FontRenderContext frc)
350: {
351: GlyphVector gv = new FreetypeGlyphVector( font,
352: buildString(ci, begin, limit),
353: frc);
354: return gv.getVisualBounds();
355: }
356:
357: public boolean hasUniformLineMetrics (Font font)
358: {
359: return true;
360: }
361:
362: public GlyphVector layoutGlyphVector (Font font, FontRenderContext frc,
363: char[] chars, int start, int limit,
364: int flags)
365: {
366: return new FreetypeGlyphVector( font, new String( chars, start,
367: limit - start),
368: frc, flags);
369: }
370:
371: public LineMetrics getLineMetrics (Font font, String str,
372: FontRenderContext frc)
373: {
374: return new GdkFontLineMetrics (this, getFontMetrics (font), str.length ());
375: }
376:
377: public FontMetrics getFontMetrics (Font font)
378: {
379:
380:
381: return Toolkit.getDefaultToolkit().getFontMetrics (font);
382: }
383:
384:
388: GlyphMetrics getGlyphMetrics( int glyphCode )
389: {
390: return (GlyphMetrics)metricsCache.get( new Integer( glyphCode ) );
391: }
392:
393:
396: void putGlyphMetrics( int glyphCode, Object metrics )
397: {
398: metricsCache.put( new Integer( glyphCode ), metrics );
399: }
400: }