OSDN Git Service

libjava/classpath/ChangeLog.gcj:
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / awt / font / opentype / truetype / TrueTypeScaler.java
1 /* TrueTypeScaler.java -- Font scaler for TrueType outlines.
2    Copyright (C) 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 package gnu.java.awt.font.opentype.truetype;
39
40 import gnu.java.awt.font.opentype.Hinter;
41 import gnu.java.awt.font.opentype.Scaler;
42
43 import java.awt.FontFormatException;
44 import java.awt.geom.AffineTransform;
45 import java.awt.geom.GeneralPath;
46 import java.awt.geom.Point2D;
47 import java.nio.ByteBuffer;
48
49
50 /**
51  * A scaler for fonts whose outlines are described in the TrueType
52  * format.
53  *
54  * <p><b>Lack of Thread Safety:</b> Font scalers are intentionally
55  * <i>not</i> safe to access from multiple concurrent threads.
56  * Synchronization needs to be performed externally. Usually, the font
57  * that uses this scaler already has obtained a lock before calling
58  * the scaler.
59  *
60  * @author Sascha Brawer (brawer@dandelis.ch)
61  */
62 public final class TrueTypeScaler
63   extends Scaler
64 {
65   /**
66    * The TrueType or OpenType table that contains the glyph outlines.
67    */
68   private ByteBuffer glyfTable;
69
70
71   /**
72    * A helper object for loading glyph outlines.
73    */
74   private GlyphLoader glyphLoader;
75
76
77   /**
78    * A helper object for measuring the advance width and height of a
79    * glyph.
80    */
81   private final GlyphMeasurer glyphMeasurer;
82
83   private final Zone glyphZone;
84
85
86   /**
87    * The number of units per em. A typical value is 2048, but some
88    * font use other numbers as well.
89    */
90   private int unitsPerEm;
91
92
93   /**
94    * Constructs a new TrueTypeScaler.
95    *
96    * @param unitsPerEm the number of font units per em. This value can
97    * be retrieved from the font&#x2019;s <code>head</code> table.
98    *
99    * @param maxp the <code>maxp</code> table of the font, which
100    * contains various constants needed for setting up the virtual
101    * machine that interprets TrueType bytecodes.
102    *
103    * @param controlValueTable the <code>cvt</code> table of the font,
104    * which contains the initial values of the control value table.
105    *
106    * @param fpgm the <code>fpgm</code> table of the font, which
107    * contains a font program that is executed exactly once.  The
108    * purpose of the font program is to define functions and to patch
109    * the interpreter.
110    *
111    * @param locaFormat the format of the <code>loca</code> table.  The
112    * value must be 0 for two-byte offsets, or 1 for four-byte
113    * offsets. TrueType and OpenType fonts indicate the format in the
114    * <code>indexToLoc</code> field of the <a href=
115    * "http://partners.adobe.com/asn/tech/type/opentype/head.html"
116    * >font header</a>.
117    *
118    * @param loca the <code>loca</code> table of the font, which
119    * contains for each glyph the offset of its outline data
120    * in <code>glyf</code>.
121    *
122    * @param glyf the <code>glyf</code> table of the font, which
123    * contains the outline data for all glyphs in the font.
124    *
125    * @param preProgram the <code>prep</code> table of the font, which
126    * contains a program that is executed whenever the point size or
127    * the device transform have changed.  This program is called
128    * pre-program because it gets executed before the instructions of
129    * the individual glyphs.  If the font does not contain a
130    * pre-program, pass <code>null</code>.
131    *
132    * @throws FontFormatException if <code>format</code> is neither 0
133    * nor 1.
134    */
135   public TrueTypeScaler(int unitsPerEm,
136                         ByteBuffer hhea,
137                         ByteBuffer htmx,
138                         ByteBuffer vhea,
139                         ByteBuffer vtmx,
140                         ByteBuffer maxp,                        
141                         ByteBuffer controlValueTable,
142                         ByteBuffer fpgm,
143                         int locaFormat, ByteBuffer loca,
144                         ByteBuffer glyf,
145                         ByteBuffer preProgram)
146     throws FontFormatException
147   {
148     int maxContours, maxPoints;
149     VirtualMachine vm;
150
151     maxContours = Math.max(/* maxContours */ (int) maxp.getChar(8),
152                            /* maxCompositeContours */ (int) maxp.getChar(12))
153       + /* fix for some broken fonts */ 8;
154     maxPoints = Math.max(/* maxPoints */ (int) maxp.getChar(6),
155                          /* maxCompositePoints */ (int) maxp.getChar(10))
156       + /* fix for some broken fonts */ 12;
157
158
159     glyphZone = new Zone(maxPoints + /* four phantom points */ 4);
160     this.glyfTable = glyf;
161     vm = new VirtualMachine(unitsPerEm, maxp,
162                             controlValueTable, fpgm,
163                             preProgram);
164
165     GlyphLocator locator = GlyphLocator.forTable(locaFormat, loca, glyf);
166     glyphMeasurer = new GlyphMeasurer(hhea, htmx, vhea, vtmx);
167     glyphLoader = new GlyphLoader(locator, vm, unitsPerEm,
168                                   maxContours, maxPoints,
169                                   glyphMeasurer);
170
171     this.unitsPerEm = unitsPerEm;
172   }
173
174
175   /**
176    * Retrieves the scaled outline of a glyph, adjusting control points
177    * to the raster grid if necessary.
178    *
179    * @param glyphIndex the glyph number whose outline is retrieved.
180    *
181    * @param pointSize the point size for the glyph.
182    *
183    * @param deviceTransform an affine transformation for the device.
184    *
185    * @param antialias whether or not the rasterizer will perform
186    * anti-aliasing on the returned path.
187    *
188    * @param fractionalMetrics <code>false</code> for adjusting glyph
189    * positions to the raster grid of device space.
190    */
191   public GeneralPath getOutline(int glyphIndex,
192                                 float pointSize,
193                                 AffineTransform deviceTransform,
194                                 boolean antialias,
195                                 boolean fractionalMetrics, Hinter hinter,
196                                 int type)
197   {
198     glyphLoader.loadGlyph(glyphIndex, pointSize, deviceTransform,
199                           antialias, glyphZone, hinter);
200     return glyphZone.getPath(type);
201   }
202
203   public Zone getRawOutline(int glyphIndex, AffineTransform transform)
204   {
205     Zone zone = new Zone(glyphZone.getCapacity());
206     glyphLoader.loadGlyph(glyphIndex, transform, zone, null);
207     return zone;
208   }
209
210   /**
211    * Determines the advance width and height for a glyph.
212    *
213    * @param glyphIndex the glyph whose advance width and height is to
214    * be determined.
215    *
216    * @param pointSize the point size of the font.
217    *
218    * @param transform a transform that is applied in addition to
219    * scaling to the specified point size. This is often used for
220    * scaling according to the device resolution. Those who lack any
221    * aesthetic sense may also use the transform to slant or stretch
222    * glyphs.
223    *
224    * @param antialias <code>true</code> for anti-aliased rendering,
225    * <code>false</code> for normal rendering. For hinted fonts,
226    * this parameter may indeed affect the result.
227    *
228    * @param fractionalMetrics <code>true</code> for fractional metrics,
229    * <code>false</code> for rounding the result to a pixel boundary.
230    *
231    * @param horizontal <code>true</code> for horizontal line layout,
232    * <code>false</code> for vertical line layout.
233    *
234    * @param advance a point whose <code>x</code> and <code>y</code>
235    * fields will hold the advance in each direction. It is possible
236    * that both values are non-zero, for example if
237    * <code>transform</code> is a rotation, or in the case of Urdu
238    * fonts.
239    */
240   public void getAdvance(int glyphIndex,
241                          float pointSize,
242                          AffineTransform transform,
243                          boolean antialias,
244                          boolean fractionalMetrics,
245                          boolean horizontal,
246                          Point2D advance)
247   {
248     double x, y;
249     double scaleFactor = (double) pointSize / unitsPerEm;
250
251     /* FIXME: Should grid-fit if needed. Also, use cache if present
252      * in the font.
253      */
254     advance.setLocation(
255       scaleFactor * glyphMeasurer.getAdvanceWidth(glyphIndex, horizontal),
256       scaleFactor * glyphMeasurer.getAdvanceHeight(glyphIndex, horizontal));
257     
258     transform.transform(advance, advance);
259   }
260
261
262   /**
263    * Scales a value from font units to pixels, given the point size
264    * and the transform.
265    *
266    * @param pointSize the point size of the font.
267    *
268    * @param transform a transform that is applied in addition to
269    * scaling to the specified point size. This is often used for
270    * scaling according to the device resolution.
271    *
272    * @param fractionalMetrics <code>true</code> for fractional
273    * metrics, <code>false</code> for rounding the result to a pixel
274    * boundary.
275    *
276    * @param horizontal <code>true</code> if the <code>funits</code>
277    * value is along the x axis, <code>false</code> if it is along the
278    * y axis.
279    */
280   private float scaleFromFUnits(int funits,
281                                 float pointSize,
282                                 AffineTransform transform,
283                                 boolean fractionalMetrics,
284                                 boolean horizontal)
285   {
286     double s;
287
288     s = (double) pointSize / unitsPerEm;
289     if (transform != null)
290       s *= horizontal ? transform.getScaleY() : transform.getScaleX();
291     s *= funits;
292     if (!fractionalMetrics)
293       s = Math.round(s);
294     return (float) s;
295   }
296
297
298   /**
299    * Determines the distance between the base line and the highest
300    * ascender.
301    *
302    * @param pointSize the point size of the font.
303    *
304    * @param transform a transform that is applied in addition to
305    * scaling to the specified point size. This is often used for
306    * scaling according to the device resolution. Those who lack any
307    * aesthetic sense may also use the transform to slant or stretch
308    * glyphs.
309    *
310    * @param antialias <code>true</code> for anti-aliased rendering,
311    * <code>false</code> for normal rendering. For hinted fonts,
312    * this parameter may indeed affect the result.
313    *
314    * @param fractionalMetrics <code>true</code> for fractional metrics,
315    * <code>false</code> for rounding the result to a pixel boundary.
316    *
317    * @param horizontal <code>true</code> for horizontal line layout,
318    * <code>false</code> for vertical line layout.
319    *
320    * @return the ascent, which usually is a positive number.
321    */
322   public float getAscent(float pointSize,
323                          AffineTransform transform,
324                          boolean antialias,
325                          boolean fractionalMetrics,
326                          boolean horizontal)
327   {
328     /* Note that the ascent is orthogonal to the direction of line
329      * layout: If the line direction is horizontal, the measurement of
330      * ascent is along the vertical axis, and vice versa.
331      */
332     return scaleFromFUnits(glyphMeasurer.getAscent(horizontal),
333                            pointSize,
334                            transform,
335                            fractionalMetrics,
336                            /* reverse */ !horizontal);
337   }
338
339
340   /**
341    * Determines the distance between the base line and the lowest
342    * descender.
343    *
344    * @param pointSize the point size of the font.
345    *
346    * @param transform a transform that is applied in addition to
347    * scaling to the specified point size. This is often used for
348    * scaling according to the device resolution. Those who lack any
349    * aesthetic sense may also use the transform to slant or stretch
350    * glyphs.
351    *
352    * @param antialiased <code>true</code> for anti-aliased rendering,
353    * <code>false</code> for normal rendering. For hinted fonts,
354    * this parameter may indeed affect the result.
355    *
356    * @param fractionalMetrics <code>true</code> for fractional metrics,
357    * <code>false</code> for rounding the result to a pixel boundary.
358    *
359    * @param horizontal <code>true</code> for horizontal line layout,
360    * <code>false</code> for vertical line layout.
361    *
362    * @return the descent, which usually is a nagative number.
363    */
364   public float getDescent(float pointSize,
365                           AffineTransform transform,
366                           boolean antialiased,
367                           boolean fractionalMetrics,
368                           boolean horizontal)
369   {
370     /* Note that the descent is orthogonal to the direction of line
371      * layout: If the line direction is horizontal, the measurement of
372      * descent is along the vertical axis, and vice versa.
373      */
374     return scaleFromFUnits(glyphMeasurer.getDescent(horizontal),
375                            pointSize,
376                            transform,
377                            fractionalMetrics,
378                            /* reverse */ !horizontal);
379   }
380 }