OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [awt/] [peer/] [gtk/] [GdkFontPeer.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* GdkFontPeer.java -- Implements FontPeer with GTK+
2
   Copyright (C) 1999, 2004, 2005, 2006  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
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.
10
 
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.
15
 
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.
20
 
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.
25
 
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. */
37
 
38
 
39
package gnu.java.awt.peer.gtk;
40
 
41
import gnu.classpath.Configuration;
42
import gnu.classpath.Pointer;
43
 
44
import gnu.java.awt.ClasspathToolkit;
45
import gnu.java.awt.peer.ClasspathFontPeer;
46
import gnu.java.awt.font.opentype.NameDecoder;
47
 
48
import gnu.java.lang.CPStringBuilder;
49
 
50
import java.awt.Font;
51
import java.awt.FontMetrics;
52
import java.awt.Toolkit;
53
import java.awt.font.FontRenderContext;
54
import java.awt.font.GlyphVector;
55
import java.awt.font.GlyphMetrics;
56
import java.awt.font.LineMetrics;
57
import java.awt.font.TextLayout;
58
import java.awt.geom.Rectangle2D;
59
import java.text.CharacterIterator;
60
import java.util.Locale;
61
import java.util.Map;
62
import java.nio.ByteBuffer;
63
import java.util.HashMap;
64
 
65
public class GdkFontPeer extends ClasspathFontPeer
66
{
67
  static final FontRenderContext DEFAULT_CTX =
68
    new FontRenderContext(null, false, false);
69
 
70
  /**
71
   * Caches TextLayout instances for use in charsWidth() and drawString().
72
   * The size of the cache has been chosen so that relativly large GUIs with
73
   * text documents are still efficient.
74
   */
75
  HashMap<String,TextLayout> textLayoutCache = new GtkToolkit.LRUCache<String,TextLayout>(500);
76
 
77
  private class GdkFontMetrics extends FontMetrics
78
  {
79
 
80
    public GdkFontMetrics (Font font)
81
    {
82
      super(initFont(font));
83
    }
84
 
85
    public int stringWidth (String str)
86
    {
87
      TextLayout tl = textLayoutCache.get(str);
88
      if (tl == null)
89
        {
90
          tl = new TextLayout(str, font, DEFAULT_CTX);
91
          textLayoutCache.put(str, tl);
92
        }
93
      return (int) tl.getAdvance();
94
    }
95
 
96
    public int charWidth (char ch)
97
    {
98
      return stringWidth (new String (new char[] { ch }));
99
    }
100
 
101
    public int charsWidth (char data[], int off, int len)
102
    {
103
      return stringWidth (new String (data, off, len));
104
    }
105
 
106
    public int getHeight()
107
    {
108
      return (int) height;
109
    }
110
 
111
    public int getLeading ()
112
    {
113
      return (int) (height - (ascent + descent));
114
    }
115
 
116
    public int getAscent ()
117
    {
118
      return (int) ascent;
119
    }
120
 
121
    public int getMaxAscent ()
122
    {
123
      return (int) ascent;
124
    }
125
 
126
    public int getDescent ()
127
    {
128
      return (int) descent;
129
    }
130
 
131
    public int getMaxDescent ()
132
    {
133
      return (int) maxDescent;
134
    }
135
 
136
    public int getMaxAdvance ()
137
    {
138
      return (int) maxAdvance;
139
    }
140
  }
141
 
142
  static native void initStaticState();
143
  private final int native_state = GtkGenericPeer.getUniqueInteger ();
144
 
145
  /**
146
   * Cache GlyphMetrics objects.
147
   */
148
  private HashMap<Integer,GlyphMetrics> metricsCache;
149
 
150
  private static final int FONT_METRICS_ASCENT = 0;
151
  private static final int FONT_METRICS_MAX_ASCENT = 1;
152
  private static final int FONT_METRICS_DESCENT = 2;
153
  private static final int FONT_METRICS_MAX_DESCENT = 3;
154
  private static final int FONT_METRICS_MAX_ADVANCE = 4;
155
  private static final int FONT_METRICS_HEIGHT = 5;
156
  private static final int FONT_METRICS_UNDERLINE_OFFSET = 6;
157
  private static final int FONT_METRICS_UNDERLINE_THICKNESS = 7;
158
 
159
  float ascent;
160
  float descent;
161
  float maxAscent;
162
  float maxDescent;
163
  float maxAdvance;
164
  float height;
165
  float underlineOffset;
166
  float underlineThickness;
167
 
168
  GdkFontMetrics metrics;
169
 
170
  static
171
  {
172
    if (true) // GCJ LOCAL
173
      {
174
        System.loadLibrary("gtkpeer");
175
      }
176
 
177
    initStaticState ();
178
 
179
  }
180
 
181
  private ByteBuffer nameTable = null;
182
 
183
  /**
184
   * The pointer to the native font data.
185
   *
186
   * This field is manipulated by native code. Don't change or remove
187
   * without adjusting the native code.
188
   */
189
  private Pointer nativeFont;
190
 
191
  private native void initState ();
192
  private native void dispose ();
193
  private native void setFont (String family, int style, int size);
194
 
195
  native synchronized void getFontMetrics(double [] metrics);
196
  native synchronized void getTextMetrics(String str, double [] metrics);
197
 
198
  native void releasePeerGraphicsResource();
199
 
200
 
201
  protected void finalize ()
202
  {
203
    releasePeerGraphicsResource();
204
    dispose ();
205
  }
206
 
207
  /*
208
   * Helpers for the 3-way overloading that this class seems to suffer
209
   * from. Remove them if you feel like they're a performance bottleneck,
210
   * for the time being I prefer my code not be written and debugged in
211
   * triplicate.
212
   */
213
 
214
  private String buildString(CharacterIterator iter)
215
  {
216
    CPStringBuilder sb = new CPStringBuilder();
217
    for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next())
218
      sb.append(c);
219
    return sb.toString();
220
  }
221
 
222
  private String buildString(CharacterIterator iter, int begin, int limit)
223
  {
224
    CPStringBuilder sb = new CPStringBuilder();
225
    int i = 0;
226
    for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next(), i++)
227
      {
228
        if (begin <= i)
229
          sb.append(c);
230
        if (limit <= i)
231
          break;
232
      }
233
    return sb.toString();
234
  }
235
 
236
  private String buildString(char[] chars, int begin, int limit)
237
  {
238
    return new String(chars, begin, limit - begin);
239
  }
240
 
241
  /* Public API */
242
 
243
  public GdkFontPeer (String name, int style)
244
  {
245
    // All fonts get a default size of 12 if size is not specified.
246
    this(name, style, 12);
247
  }
248
 
249
  public GdkFontPeer (String name, int style, int size)
250
  {
251
    super(name, style, size);
252
    initState ();
253
    setFont (this.familyName, this.style, (int)this.size);
254
    metricsCache = new HashMap<Integer,GlyphMetrics>();
255
    setupMetrics();
256
  }
257
 
258
  public GdkFontPeer (String name, Map attributes)
259
  {
260
    super(name, attributes);
261
    initState ();
262
    setFont (this.familyName, this.style, (int)this.size);
263
    metricsCache = new HashMap<Integer,GlyphMetrics>();
264
    setupMetrics();
265
  }
266
 
267
 
268
  /**
269
   * Makes sure to return a Font based on the given Font that has as
270
   * peer a GdkFontPeer. Used in the initializer.
271
   */
272
  static Font initFont(Font font)
273
  {
274
    if (font == null)
275
      return new Font("Dialog", Font.PLAIN, 12);
276
    else if (font.getPeer() instanceof GdkFontPeer)
277
      return font;
278
    else
279
      {
280
        ClasspathToolkit toolkit;
281
        toolkit = (ClasspathToolkit) Toolkit.getDefaultToolkit();
282
        return toolkit.getFont(font.getName(), font.getAttributes());
283
      }
284
  }
285
 
286
  private void setupMetrics()
287
  {
288
    double [] hires = new double[8];
289
    getFontMetrics(hires);
290
    ascent = (float) hires[FONT_METRICS_ASCENT];
291
    maxAscent = (float) hires[FONT_METRICS_MAX_ASCENT];
292
    descent = (float) hires[FONT_METRICS_DESCENT];
293
    maxDescent = (float) hires[FONT_METRICS_MAX_DESCENT];
294
    maxAdvance = (float) hires[FONT_METRICS_MAX_ADVANCE];
295
    height = (float) hires[FONT_METRICS_HEIGHT];
296
    underlineOffset = (float) hires[FONT_METRICS_UNDERLINE_OFFSET];
297
    underlineThickness = (float) hires[FONT_METRICS_UNDERLINE_THICKNESS];
298
  }
299
 
300
  /**
301
   * Unneeded, but implemented anyway.
302
   */
303
  public String getSubFamilyName(Font font, Locale locale)
304
  {
305
    String name;
306
 
307
    if (locale == null)
308
      locale = Locale.getDefault();
309
 
310
    name = getName(NameDecoder.NAME_SUBFAMILY, locale);
311
    if (name == null)
312
      {
313
        name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
314
        if ("Regular".equals(name))
315
          name = null;
316
      }
317
 
318
    return name;
319
  }
320
 
321
  /**
322
   * Returns the bytes belonging to a TrueType/OpenType table,
323
   * Parameters n,a,m,e identify the 4-byte ASCII tag of the table.
324
   *
325
   * Returns null if the font is not TT, the table is nonexistant,
326
   * or if some other unexpected error occured.
327
   *
328
   */
329
  private native byte[] getTrueTypeTable(byte n, byte a, byte m, byte e);
330
 
331
  /**
332
   * Returns the PostScript name of the font, defaults to the familyName if
333
   * a PS name could not be retrieved.
334
   */
335
  public String getPostScriptName(Font font)
336
  {
337
    String name = getName(NameDecoder.NAME_POSTSCRIPT,
338
                          /* any language */ null);
339
    if( name == null )
340
      return this.familyName;
341
 
342
    return name;
343
  }
344
 
345
  /**
346
   * Extracts a String from the font&#x2019;s name table.
347
   *
348
   * @param name the numeric TrueType or OpenType name ID.
349
   *
350
   * @param locale the locale for which names shall be localized, or
351
   * <code>null</code> if the locale does mot matter because the name
352
   * is known to be language-independent (for example, because it is
353
   * the PostScript name).
354
   */
355
  private String getName(int name, Locale locale)
356
  {
357
    if (nameTable == null)
358
      {
359
        byte[] data = getTrueTypeTable((byte)'n', (byte) 'a',
360
                                       (byte) 'm', (byte) 'e');
361
        if( data == null )
362
          return null;
363
 
364
        nameTable = ByteBuffer.wrap( data );
365
      }
366
 
367
    return NameDecoder.getName(nameTable, name, locale);
368
  }
369
 
370
  public boolean canDisplay (Font font, int c)
371
  {
372
    // FIXME: inquire with pango
373
    return true;
374
  }
375
 
376
  public int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit)
377
  {
378
    // FIXME: inquire with pango
379
    return -1;
380
  }
381
 
382
  public GlyphVector createGlyphVector (Font font,
383
                                        FontRenderContext ctx,
384
                                        CharacterIterator i)
385
  {
386
    return new FreetypeGlyphVector(font, buildString (i), ctx);
387
  }
388
 
389
  public GlyphVector createGlyphVector (Font font,
390
                                        FontRenderContext ctx,
391
                                        int[] glyphCodes)
392
  {
393
    return new FreetypeGlyphVector(font, glyphCodes, ctx);
394
  }
395
 
396
  public byte getBaselineFor (Font font, char c)
397
  {
398
    // FIXME: Actually check.
399
    return Font.ROMAN_BASELINE;
400
  }
401
 
402
  private class GdkFontLineMetrics extends LineMetrics
403
  {
404
    private int nchars;
405
    public GdkFontLineMetrics (GdkFontPeer fp, int n)
406
    {
407
      nchars = n;
408
    }
409
 
410
    public float getAscent()
411
    {
412
      return ascent;
413
    }
414
 
415
    public int getBaselineIndex()
416
    {
417
      // FIXME
418
      return Font.ROMAN_BASELINE;
419
    }
420
 
421
    public float[] getBaselineOffsets()
422
    {
423
      return new float[3];
424
    }
425
 
426
    public float getDescent()
427
    {
428
      return descent;
429
    }
430
 
431
    public float getHeight()
432
    {
433
      return height;
434
    }
435
 
436
    public float getLeading()
437
    {
438
      return height - (ascent + descent);
439
    }
440
 
441
    public int getNumChars()
442
    {
443
      return nchars;
444
    }
445
 
446
    public float getStrikethroughOffset()
447
    {
448
      // FreeType doesn't seem to provide a value here.
449
      return ascent / 2;
450
    }
451
 
452
    public float getStrikethroughThickness()
453
    {
454
      // FreeType doesn't seem to provide a value here.
455
      return 1.f;
456
    }
457
 
458
    public float getUnderlineOffset()
459
    {
460
      return underlineOffset;
461
    }
462
 
463
    public float getUnderlineThickness()
464
    {
465
      return underlineThickness;
466
    }
467
 
468
  }
469
 
470
  public LineMetrics getLineMetrics (Font font, CharacterIterator ci,
471
                                     int begin, int limit, FontRenderContext rc)
472
  {
473
    return new GdkFontLineMetrics (this, limit - begin);
474
  }
475
 
476
  public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc)
477
  {
478
    throw new UnsupportedOperationException ();
479
  }
480
 
481
  public int getMissingGlyphCode (Font font)
482
  {
483
    throw new UnsupportedOperationException ();
484
  }
485
 
486
  public String getGlyphName (Font font, int glyphIndex)
487
  {
488
    throw new UnsupportedOperationException ();
489
  }
490
 
491
  public int getNumGlyphs (Font font)
492
  {
493
    byte[] data = getTrueTypeTable((byte)'m', (byte) 'a',
494
                                   (byte)'x', (byte) 'p');
495
    if( data == null )
496
      return -1;
497
 
498
    ByteBuffer buf = ByteBuffer.wrap( data );
499
    return buf.getShort(4);
500
  }
501
 
502
  public boolean hasUniformLineMetrics (Font font)
503
  {
504
    return true;
505
  }
506
 
507
  public GlyphVector layoutGlyphVector (Font font, FontRenderContext frc,
508
                                        char[] chars, int start, int limit,
509
                                        int flags)
510
  {
511
    return new FreetypeGlyphVector(font, chars, start, limit - start,
512
                                   frc, flags);
513
  }
514
 
515
  public LineMetrics getLineMetrics (Font font, String str,
516
                                     FontRenderContext frc)
517
  {
518
    return new GdkFontLineMetrics (this, str.length ());
519
  }
520
 
521
  public FontMetrics getFontMetrics (Font font)
522
  {
523
    if (metrics == null)
524
      metrics = new GdkFontMetrics(font);
525
    return metrics;
526
  }
527
 
528
  /**
529
   * Returns a cached GlyphMetrics object for a given glyphcode,
530
   * or null if it doesn't exist in the cache.
531
   */
532
  GlyphMetrics getGlyphMetrics( int glyphCode )
533
  {
534
    return metricsCache.get(new Integer(glyphCode));
535
  }
536
 
537
  /**
538
   * Put a GlyphMetrics object in the cache.
539
   */
540
  void putGlyphMetrics( int glyphCode, GlyphMetrics metrics )
541
  {
542
    metricsCache.put( new Integer( glyphCode ), metrics );
543
  }
544
 
545
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.