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.Hinter;
41 import gnu.java.awt.font.opentype.Scaler;
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;
51 * A scaler for fonts whose outlines are described in the TrueType
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
60 * @author Sascha Brawer (brawer@dandelis.ch)
62 public final class TrueTypeScaler
66 * The TrueType or OpenType table that contains the glyph outlines.
68 private ByteBuffer glyfTable;
72 * A helper object for loading glyph outlines.
74 private GlyphLoader glyphLoader;
78 * A helper object for measuring the advance width and height of a
81 private final GlyphMeasurer glyphMeasurer;
83 private final Zone glyphZone;
87 * The number of units per em. A typical value is 2048, but some
88 * font use other numbers as well.
90 private int unitsPerEm;
94 * Constructs a new TrueTypeScaler.
96 * @param unitsPerEm the number of font units per em. This value can
97 * be retrieved from the font’s <code>head</code> table.
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.
103 * @param controlValueTable the <code>cvt</code> table of the font,
104 * which contains the initial values of the control value table.
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
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"
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>.
122 * @param glyf the <code>glyf</code> table of the font, which
123 * contains the outline data for all glyphs in the font.
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>.
132 * @throws FontFormatException if <code>format</code> is neither 0
135 public TrueTypeScaler(int unitsPerEm,
141 ByteBuffer controlValueTable,
143 int locaFormat, ByteBuffer loca,
145 ByteBuffer preProgram)
146 throws FontFormatException
148 int maxContours, maxPoints;
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;
159 glyphZone = new Zone(maxPoints + /* four phantom points */ 4);
160 this.glyfTable = glyf;
161 vm = new VirtualMachine(unitsPerEm, maxp,
162 controlValueTable, fpgm,
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,
171 this.unitsPerEm = unitsPerEm;
176 * Retrieves the scaled outline of a glyph, adjusting control points
177 * to the raster grid if necessary.
179 * @param glyphIndex the glyph number whose outline is retrieved.
181 * @param pointSize the point size for the glyph.
183 * @param deviceTransform an affine transformation for the device.
185 * @param antialias whether or not the rasterizer will perform
186 * anti-aliasing on the returned path.
188 * @param fractionalMetrics <code>false</code> for adjusting glyph
189 * positions to the raster grid of device space.
191 public GeneralPath getOutline(int glyphIndex,
193 AffineTransform deviceTransform,
195 boolean fractionalMetrics, Hinter hinter,
198 glyphLoader.loadGlyph(glyphIndex, pointSize, deviceTransform,
199 antialias, glyphZone, hinter);
200 return glyphZone.getPath(type);
203 public Zone getRawOutline(int glyphIndex, AffineTransform transform)
205 Zone zone = new Zone(glyphZone.getCapacity());
206 glyphLoader.loadGlyph(glyphIndex, transform, zone, null);
211 * Determines the advance width and height for a glyph.
213 * @param glyphIndex the glyph whose advance width and height is to
216 * @param pointSize the point size of the font.
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
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.
228 * @param fractionalMetrics <code>true</code> for fractional metrics,
229 * <code>false</code> for rounding the result to a pixel boundary.
231 * @param horizontal <code>true</code> for horizontal line layout,
232 * <code>false</code> for vertical line layout.
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
240 public void getAdvance(int glyphIndex,
242 AffineTransform transform,
244 boolean fractionalMetrics,
249 double scaleFactor = (double) pointSize / unitsPerEm;
251 /* FIXME: Should grid-fit if needed. Also, use cache if present
255 scaleFactor * glyphMeasurer.getAdvanceWidth(glyphIndex, horizontal),
256 scaleFactor * glyphMeasurer.getAdvanceHeight(glyphIndex, horizontal));
258 transform.transform(advance, advance);
263 * Scales a value from font units to pixels, given the point size
266 * @param pointSize the point size of the font.
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.
272 * @param fractionalMetrics <code>true</code> for fractional
273 * metrics, <code>false</code> for rounding the result to a pixel
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
280 private float scaleFromFUnits(int funits,
282 AffineTransform transform,
283 boolean fractionalMetrics,
288 s = (double) pointSize / unitsPerEm;
289 if (transform != null)
290 s *= horizontal ? transform.getScaleY() : transform.getScaleX();
292 if (!fractionalMetrics)
299 * Determines the distance between the base line and the highest
302 * @param pointSize the point size of the font.
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
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.
314 * @param fractionalMetrics <code>true</code> for fractional metrics,
315 * <code>false</code> for rounding the result to a pixel boundary.
317 * @param horizontal <code>true</code> for horizontal line layout,
318 * <code>false</code> for vertical line layout.
320 * @return the ascent, which usually is a positive number.
322 public float getAscent(float pointSize,
323 AffineTransform transform,
325 boolean fractionalMetrics,
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.
332 return scaleFromFUnits(glyphMeasurer.getAscent(horizontal),
336 /* reverse */ !horizontal);
341 * Determines the distance between the base line and the lowest
344 * @param pointSize the point size of the font.
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
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.
356 * @param fractionalMetrics <code>true</code> for fractional metrics,
357 * <code>false</code> for rounding the result to a pixel boundary.
359 * @param horizontal <code>true</code> for horizontal line layout,
360 * <code>false</code> for vertical line layout.
362 * @return the descent, which usually is a nagative number.
364 public float getDescent(float pointSize,
365 AffineTransform transform,
367 boolean fractionalMetrics,
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.
374 return scaleFromFUnits(glyphMeasurer.getDescent(horizontal),
378 /* reverse */ !horizontal);