1 /* TrueTypeScaler.java -- Font scaler for TrueType outlines.
2 Copyright (C) 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)
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
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
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. */
38 package gnu.java.awt.font.opentype.truetype;
40 import gnu.java.awt.font.opentype.Scaler;
42 import java.awt.FontFormatException;
43 import java.awt.geom.AffineTransform;
44 import java.awt.geom.GeneralPath;
45 import java.awt.geom.Point2D;
46 import java.nio.ByteBuffer;
50 * A scaler for fonts whose outlines are described in the TrueType
53 * <p><b>Lack of Thread Safety:</b> Font scalers are intentionally
54 * <i>not</i> safe to access from multiple concurrent threads.
55 * Synchronization needs to be performed externally. Usually, the font
56 * that uses this scaler already has obtained a lock before calling
59 * @author Sascha Brawer (brawer@dandelis.ch)
61 public final class TrueTypeScaler
65 * The TrueType or OpenType table that contains the glyph outlines.
67 private ByteBuffer glyfTable;
71 * A helper object for loading glyph outlines.
73 private GlyphLoader glyphLoader;
77 * A helper object for measuring the advance width and height of a
80 private final GlyphMeasurer glyphMeasurer;
82 private final Zone glyphZone;
86 * The number of units per em. A typical value is 2048, but some
87 * font use other numbers as well.
89 private int unitsPerEm;
93 * Constructs a new TrueTypeScaler.
95 * @param unitsPerEm the number of font units per em. This value can
96 * be retrieved from the font’s <code>head</code> table.
98 * @param maxp the <code>maxp</code> table of the font, which
99 * contains various constants needed for setting up the virtual
100 * machine that interprets TrueType bytecodes.
102 * @param controlValueTable the <code>cvt</code> table of the font,
103 * which contains the initial values of the control value table.
105 * @param fpgm the <code>fpgm</code> table of the font, which
106 * contains a font program that is executed exactly once. The
107 * purpose of the font program is to define functions and to patch
110 * @param locaFormat the format of the <code>loca</code> table. The
111 * value must be 0 for two-byte offsets, or 1 for four-byte
112 * offsets. TrueType and OpenType fonts indicate the format in the
113 * <code>indexToLoc</code> field of the <a href=
114 * "http://partners.adobe.com/asn/tech/type/opentype/head.html"
117 * @param loca the <code>loca</code> table of the font, which
118 * contains for each glyph the offset of its outline data
119 * in <code>glyf</code>.
121 * @param glyf the <code>glyf</code> table of the font, which
122 * contains the outline data for all glyphs in the font.
124 * @param preProgram the <code>prep</code> table of the font, which
125 * contains a program that is executed whenever the point size or
126 * the device transform have changed. This program is called
127 * pre-program because it gets executed before the instructions of
128 * the individual glyphs. If the font does not contain a
129 * pre-program, pass <code>null</code>.
131 * @throws FontFormatException if <code>format</code> is neither 0
134 public TrueTypeScaler(int unitsPerEm,
140 ByteBuffer controlValueTable,
142 int locaFormat, ByteBuffer loca,
144 ByteBuffer preProgram)
145 throws FontFormatException
147 int maxContours, maxPoints;
150 maxContours = Math.max(/* maxContours */ (int) maxp.getChar(8),
151 /* maxCompositeContours */ (int) maxp.getChar(12))
152 + /* fix for some broken fonts */ 8;
153 maxPoints = Math.max(/* maxPoints */ (int) maxp.getChar(6),
154 /* maxCompositePoints */ (int) maxp.getChar(10))
155 + /* fix for some broken fonts */ 12;
158 glyphZone = new Zone(maxPoints + /* four phantom points */ 4);
159 this.glyfTable = glyf;
160 vm = new VirtualMachine(unitsPerEm, maxp,
161 controlValueTable, fpgm,
164 GlyphLocator locator = GlyphLocator.forTable(locaFormat, loca, glyf);
165 glyphMeasurer = new GlyphMeasurer(hhea, htmx, vhea, vtmx);
166 glyphLoader = new GlyphLoader(locator, vm, unitsPerEm,
167 maxContours, maxPoints,
170 this.unitsPerEm = unitsPerEm;
175 * Retrieves the scaled outline of a glyph, adjusting control points
176 * to the raster grid if necessary.
178 * @param glyphIndex the glyph number whose outline is retrieved.
180 * @param pointSize the point size for the glyph.
182 * @param deviceTransform an affine transformation for the device.
184 * @param antialias whether or not the rasterizer will perform
185 * anti-aliasing on the returned path.
187 * @param fractionalMetrics <code>false</code> for adjusting glyph
188 * positions to the raster grid of device space.
190 public GeneralPath getOutline(int glyphIndex,
192 AffineTransform deviceTransform,
194 boolean fractionalMetrics)
196 glyphLoader.loadGlyph(glyphIndex, pointSize, deviceTransform,
197 antialias, glyphZone);
198 return glyphZone.getPath();
201 public Zone getRawOutline(int glyphIndex, AffineTransform transform)
203 Zone zone = new Zone(glyphZone.getCapacity());
204 glyphLoader.loadGlyph(glyphIndex, transform, zone);
209 * Determines the advance width and height for a glyph.
211 * @param glyphIndex the glyph whose advance width and height is to
214 * @param pointSize the point size of the font.
216 * @param transform a transform that is applied in addition to
217 * scaling to the specified point size. This is often used for
218 * scaling according to the device resolution. Those who lack any
219 * aesthetic sense may also use the transform to slant or stretch
222 * @param antialias <code>true</code> for anti-aliased rendering,
223 * <code>false</code> for normal rendering. For hinted fonts,
224 * this parameter may indeed affect the result.
226 * @param fractionalMetrics <code>true</code> for fractional metrics,
227 * <code>false</code> for rounding the result to a pixel boundary.
229 * @param horizontal <code>true</code> for horizontal line layout,
230 * <code>false</code> for vertical line layout.
232 * @param advance a point whose <code>x</code> and <code>y</code>
233 * fields will hold the advance in each direction. It is possible
234 * that both values are non-zero, for example if
235 * <code>transform</code> is a rotation, or in the case of Urdu
238 public void getAdvance(int glyphIndex,
240 AffineTransform transform,
242 boolean fractionalMetrics,
247 double scaleFactor = (double) pointSize / unitsPerEm;
249 /* FIXME: Should grid-fit if needed. Also, use cache if present
253 scaleFactor * glyphMeasurer.getAdvanceWidth(glyphIndex, horizontal),
254 scaleFactor * glyphMeasurer.getAdvanceHeight(glyphIndex, horizontal));
256 transform.transform(advance, advance);
261 * Scales a value from font units to pixels, given the point size
264 * @param pointSize the point size of the font.
266 * @param transform a transform that is applied in addition to
267 * scaling to the specified point size. This is often used for
268 * scaling according to the device resolution.
270 * @param fractionalMetrics <code>true</code> for fractional
271 * metrics, <code>false</code> for rounding the result to a pixel
274 * @param horizontal <code>true</code> if the <code>funits</code>
275 * value is along the x axis, <code>false</code> if it is along the
278 private float scaleFromFUnits(int funits,
280 AffineTransform transform,
281 boolean fractionalMetrics,
286 s = (double) pointSize / unitsPerEm;
287 if (transform != null)
288 s *= horizontal ? transform.getScaleY() : transform.getScaleX();
290 if (!fractionalMetrics)
297 * Determines the distance between the base line and the highest
300 * @param pointSize the point size of the font.
302 * @param transform a transform that is applied in addition to
303 * scaling to the specified point size. This is often used for
304 * scaling according to the device resolution. Those who lack any
305 * aesthetic sense may also use the transform to slant or stretch
308 * @param antialias <code>true</code> for anti-aliased rendering,
309 * <code>false</code> for normal rendering. For hinted fonts,
310 * this parameter may indeed affect the result.
312 * @param fractionalMetrics <code>true</code> for fractional metrics,
313 * <code>false</code> for rounding the result to a pixel boundary.
315 * @param horizontal <code>true</code> for horizontal line layout,
316 * <code>false</code> for vertical line layout.
318 * @return the ascent, which usually is a positive number.
320 public float getAscent(float pointSize,
321 AffineTransform transform,
323 boolean fractionalMetrics,
326 /* Note that the ascent is orthogonal to the direction of line
327 * layout: If the line direction is horizontal, the measurement of
328 * ascent is along the vertical axis, and vice versa.
330 return scaleFromFUnits(glyphMeasurer.getAscent(horizontal),
334 /* reverse */ !horizontal);
339 * Determines the distance between the base line and the lowest
342 * @param pointSize the point size of the font.
344 * @param transform a transform that is applied in addition to
345 * scaling to the specified point size. This is often used for
346 * scaling according to the device resolution. Those who lack any
347 * aesthetic sense may also use the transform to slant or stretch
350 * @param antialiased <code>true</code> for anti-aliased rendering,
351 * <code>false</code> for normal rendering. For hinted fonts,
352 * this parameter may indeed affect the result.
354 * @param fractionalMetrics <code>true</code> for fractional metrics,
355 * <code>false</code> for rounding the result to a pixel boundary.
357 * @param horizontal <code>true</code> for horizontal line layout,
358 * <code>false</code> for vertical line layout.
360 * @return the descent, which usually is a nagative number.
362 public float getDescent(float pointSize,
363 AffineTransform transform,
365 boolean fractionalMetrics,
368 /* Note that the descent is orthogonal to the direction of line
369 * layout: If the line direction is horizontal, the measurement of
370 * descent is along the vertical axis, and vice versa.
372 return scaleFromFUnits(glyphMeasurer.getDescent(horizontal),
376 /* reverse */ !horizontal);