libjava/classpath/ChangeLog.gcj:
[official-gcc.git] / libjava / classpath / gnu / java / awt / peer / gtk / GdkFontPeer.java
blobc3c94d8a93528c2d33ac14504539878dd2cf8dbe
1 /* GdkFontPeer.java -- Implements FontPeer with GTK+
2 Copyright (C) 1999, 2004, 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.java.awt.peer.gtk;
41 import gnu.java.awt.ClasspathToolkit;
42 import gnu.java.awt.peer.ClasspathFontPeer;
43 import gnu.java.awt.font.opentype.NameDecoder;
45 import java.awt.Font;
46 import java.awt.FontMetrics;
47 import java.awt.Toolkit;
48 import java.awt.font.FontRenderContext;
49 import java.awt.font.GlyphVector;
50 import java.awt.font.GlyphMetrics;
51 import java.awt.font.LineMetrics;
52 import java.awt.font.TextLayout;
53 import java.awt.geom.Rectangle2D;
54 import java.text.CharacterIterator;
55 import java.util.Locale;
56 import java.util.Map;
57 import java.nio.ByteBuffer;
58 import java.util.HashMap;
60 public class GdkFontPeer extends ClasspathFontPeer
62 static final FontRenderContext DEFAULT_CTX =
63 new FontRenderContext(null, false, false);
65 /**
66 * Caches TextLayout instances for use in charsWidth() and drawString().
67 * The size of the cache has been chosen so that relativly large GUIs with
68 * text documents are still efficient.
70 HashMap<String,TextLayout> textLayoutCache = new GtkToolkit.LRUCache<String,TextLayout>(500);
72 private class GdkFontMetrics extends FontMetrics
75 public GdkFontMetrics (Font font)
77 super(initFont(font));
80 public int stringWidth (String str)
82 TextLayout tl = textLayoutCache.get(str);
83 if (tl == null)
85 tl = new TextLayout(str, font, DEFAULT_CTX);
86 textLayoutCache.put(str, tl);
88 return (int) tl.getAdvance();
91 public int charWidth (char ch)
93 return stringWidth (new String (new char[] { ch }));
96 public int charsWidth (char data[], int off, int len)
98 return stringWidth (new String (data, off, len));
101 public int getHeight()
103 return (int) height;
106 public int getLeading ()
108 return (int) (height - (ascent + descent));
111 public int getAscent ()
113 return (int) ascent;
116 public int getMaxAscent ()
118 return (int) ascent;
121 public int getDescent ()
123 return (int) descent;
126 public int getMaxDescent ()
128 return (int) maxDescent;
131 public int getMaxAdvance ()
133 return (int) maxAdvance;
137 static native void initStaticState();
138 private final int native_state = GtkGenericPeer.getUniqueInteger ();
141 * Cache GlyphMetrics objects.
143 private HashMap<Integer,GlyphMetrics> metricsCache;
145 private static final int FONT_METRICS_ASCENT = 0;
146 private static final int FONT_METRICS_MAX_ASCENT = 1;
147 private static final int FONT_METRICS_DESCENT = 2;
148 private static final int FONT_METRICS_MAX_DESCENT = 3;
149 private static final int FONT_METRICS_MAX_ADVANCE = 4;
150 private static final int FONT_METRICS_HEIGHT = 5;
151 private static final int FONT_METRICS_UNDERLINE_OFFSET = 6;
152 private static final int FONT_METRICS_UNDERLINE_THICKNESS = 7;
154 float ascent;
155 float descent;
156 float maxAscent;
157 float maxDescent;
158 float maxAdvance;
159 float height;
160 float underlineOffset;
161 float underlineThickness;
163 GdkFontMetrics metrics;
165 static
167 System.loadLibrary("gtkpeer");
169 initStaticState ();
173 private ByteBuffer nameTable = null;
175 private native void initState ();
176 private native void dispose ();
177 private native void setFont (String family, int style, int size);
179 native synchronized void getFontMetrics(double [] metrics);
180 native synchronized void getTextMetrics(String str, double [] metrics);
182 native void releasePeerGraphicsResource();
185 protected void finalize ()
187 releasePeerGraphicsResource();
188 dispose ();
192 * Helpers for the 3-way overloading that this class seems to suffer
193 * from. Remove them if you feel like they're a performance bottleneck,
194 * for the time being I prefer my code not be written and debugged in
195 * triplicate.
198 private String buildString(CharacterIterator iter)
200 StringBuffer sb = new StringBuffer();
201 for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next())
202 sb.append(c);
203 return sb.toString();
206 private String buildString(CharacterIterator iter, int begin, int limit)
208 StringBuffer sb = new StringBuffer();
209 int i = 0;
210 for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next(), i++)
212 if (begin <= i)
213 sb.append(c);
214 if (limit <= i)
215 break;
217 return sb.toString();
220 private String buildString(char[] chars, int begin, int limit)
222 return new String(chars, begin, limit - begin);
225 /* Public API */
227 public GdkFontPeer (String name, int style)
229 // All fonts get a default size of 12 if size is not specified.
230 this(name, style, 12);
233 public GdkFontPeer (String name, int style, int size)
235 super(name, style, size);
236 initState ();
237 setFont (this.familyName, this.style, (int)this.size);
238 metricsCache = new HashMap<Integer,GlyphMetrics>();
239 setupMetrics();
242 public GdkFontPeer (String name, Map attributes)
244 super(name, attributes);
245 initState ();
246 setFont (this.familyName, this.style, (int)this.size);
247 metricsCache = new HashMap<Integer,GlyphMetrics>();
248 setupMetrics();
253 * Makes sure to return a Font based on the given Font that has as
254 * peer a GdkFontPeer. Used in the initializer.
256 static Font initFont(Font font)
258 if (font == null)
259 return new Font("Dialog", Font.PLAIN, 12);
260 else if (font.getPeer() instanceof GdkFontPeer)
261 return font;
262 else
264 ClasspathToolkit toolkit;
265 toolkit = (ClasspathToolkit) Toolkit.getDefaultToolkit();
266 return toolkit.getFont(font.getName(), font.getAttributes());
270 private void setupMetrics()
272 double [] hires = new double[8];
273 getFontMetrics(hires);
274 ascent = (float) hires[FONT_METRICS_ASCENT];
275 maxAscent = (float) hires[FONT_METRICS_MAX_ASCENT];
276 descent = (float) hires[FONT_METRICS_DESCENT];
277 maxDescent = (float) hires[FONT_METRICS_MAX_DESCENT];
278 maxAdvance = (float) hires[FONT_METRICS_MAX_ADVANCE];
279 height = (float) hires[FONT_METRICS_HEIGHT];
280 underlineOffset = (float) hires[FONT_METRICS_UNDERLINE_OFFSET];
281 underlineThickness = (float) hires[FONT_METRICS_UNDERLINE_THICKNESS];
285 * Unneeded, but implemented anyway.
287 public String getSubFamilyName(Font font, Locale locale)
289 String name;
291 if (locale == null)
292 locale = Locale.getDefault();
294 name = getName(NameDecoder.NAME_SUBFAMILY, locale);
295 if (name == null)
297 name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
298 if ("Regular".equals(name))
299 name = null;
302 return name;
306 * Returns the bytes belonging to a TrueType/OpenType table,
307 * Parameters n,a,m,e identify the 4-byte ASCII tag of the table.
309 * Returns null if the font is not TT, the table is nonexistant,
310 * or if some other unexpected error occured.
313 private native byte[] getTrueTypeTable(byte n, byte a, byte m, byte e);
316 * Returns the PostScript name of the font, defaults to the familyName if
317 * a PS name could not be retrieved.
319 public String getPostScriptName(Font font)
321 String name = getName(NameDecoder.NAME_POSTSCRIPT,
322 /* any language */ null);
323 if( name == null )
324 return this.familyName;
326 return name;
330 * Extracts a String from the font&#x2019;s name table.
332 * @param name the numeric TrueType or OpenType name ID.
334 * @param locale the locale for which names shall be localized, or
335 * <code>null</code> if the locale does mot matter because the name
336 * is known to be language-independent (for example, because it is
337 * the PostScript name).
339 private String getName(int name, Locale locale)
341 if (nameTable == null)
343 byte[] data = getTrueTypeTable((byte)'n', (byte) 'a',
344 (byte) 'm', (byte) 'e');
345 if( data == null )
346 return null;
348 nameTable = ByteBuffer.wrap( data );
351 return NameDecoder.getName(nameTable, name, locale);
354 public boolean canDisplay (Font font, char c)
356 // FIXME: inquire with pango
357 return true;
360 public int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit)
362 // FIXME: inquire with pango
363 return -1;
366 public GlyphVector createGlyphVector (Font font,
367 FontRenderContext ctx,
368 CharacterIterator i)
370 return new FreetypeGlyphVector(font, buildString (i), ctx);
373 public GlyphVector createGlyphVector (Font font,
374 FontRenderContext ctx,
375 int[] glyphCodes)
377 return new FreetypeGlyphVector(font, glyphCodes, ctx);
380 public byte getBaselineFor (Font font, char c)
382 // FIXME: Actually check.
383 return Font.ROMAN_BASELINE;
386 private class GdkFontLineMetrics extends LineMetrics
388 private int nchars;
389 public GdkFontLineMetrics (GdkFontPeer fp, int n)
391 nchars = n;
394 public float getAscent()
396 return ascent;
399 public int getBaselineIndex()
401 // FIXME
402 return Font.ROMAN_BASELINE;
405 public float[] getBaselineOffsets()
407 return new float[3];
410 public float getDescent()
412 return descent;
415 public float getHeight()
417 return height;
420 public float getLeading()
422 return height - (ascent + descent);
425 public int getNumChars()
427 return nchars;
430 public float getStrikethroughOffset()
432 // FreeType doesn't seem to provide a value here.
433 return ascent / 2;
436 public float getStrikethroughThickness()
438 // FreeType doesn't seem to provide a value here.
439 return 1.f;
442 public float getUnderlineOffset()
444 return underlineOffset;
447 public float getUnderlineThickness()
449 return underlineThickness;
454 public LineMetrics getLineMetrics (Font font, CharacterIterator ci,
455 int begin, int limit, FontRenderContext rc)
457 return new GdkFontLineMetrics (this, limit - begin);
460 public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc)
462 throw new UnsupportedOperationException ();
465 public int getMissingGlyphCode (Font font)
467 throw new UnsupportedOperationException ();
470 public String getGlyphName (Font font, int glyphIndex)
472 throw new UnsupportedOperationException ();
475 public int getNumGlyphs (Font font)
477 byte[] data = getTrueTypeTable((byte)'m', (byte) 'a',
478 (byte)'x', (byte) 'p');
479 if( data == null )
480 return -1;
482 ByteBuffer buf = ByteBuffer.wrap( data );
483 return buf.getShort(4);
486 public boolean hasUniformLineMetrics (Font font)
488 return true;
491 public GlyphVector layoutGlyphVector (Font font, FontRenderContext frc,
492 char[] chars, int start, int limit,
493 int flags)
495 return new FreetypeGlyphVector(font, chars, start, limit - start,
496 frc, flags);
499 public LineMetrics getLineMetrics (Font font, String str,
500 FontRenderContext frc)
502 return new GdkFontLineMetrics (this, str.length ());
505 public FontMetrics getFontMetrics (Font font)
507 if (metrics == null)
508 metrics = new GdkFontMetrics(font);
509 return metrics;
513 * Returns a cached GlyphMetrics object for a given glyphcode,
514 * or null if it doesn't exist in the cache.
516 GlyphMetrics getGlyphMetrics( int glyphCode )
518 return metricsCache.get(new Integer(glyphCode));
522 * Put a GlyphMetrics object in the cache.
524 void putGlyphMetrics( int glyphCode, GlyphMetrics metrics )
526 metricsCache.put( new Integer( glyphCode ), metrics );