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();
203 * Determines the advance width and height for a glyph.
205 * @param glyphIndex the glyph whose advance width and height is to
208 * @param pointSize the point size of the font.
210 * @param transform a transform that is applied in addition to
211 * scaling to the specified point size. This is often used for
212 * scaling according to the device resolution. Those who lack any
213 * aesthetic sense may also use the transform to slant or stretch
216 * @param antialias <code>true</code> for anti-aliased rendering,
217 * <code>false</code> for normal rendering. For hinted fonts,
218 * this parameter may indeed affect the result.
220 * @param fractionalMetrics <code>true</code> for fractional metrics,
221 * <code>false</code> for rounding the result to a pixel boundary.
223 * @param horizontal <code>true</code> for horizontal line layout,
224 * <code>false</code> for vertical line layout.
226 * @param advance a point whose <code>x</code> and <code>y</code>
227 * fields will hold the advance in each direction. It is possible
228 * that both values are non-zero, for example if
229 * <code>transform</code> is a rotation, or in the case of Urdu
232 public void getAdvance(int glyphIndex
,
234 AffineTransform transform
,
236 boolean fractionalMetrics
,
241 double scaleFactor
= (double) pointSize
/ unitsPerEm
;
243 /* FIXME: Should grid-fit if needed. Also, use cache if present
247 scaleFactor
* glyphMeasurer
.getAdvanceWidth(glyphIndex
, horizontal
),
248 scaleFactor
* glyphMeasurer
.getAdvanceHeight(glyphIndex
, horizontal
));
250 transform
.transform(advance
, advance
);
255 * Scales a value from font units to pixels, given the point size
258 * @param pointSize the point size of the font.
260 * @param transform a transform that is applied in addition to
261 * scaling to the specified point size. This is often used for
262 * scaling according to the device resolution.
264 * @param fractionalMetrics <code>true</code> for fractional
265 * metrics, <code>false</code> for rounding the result to a pixel
268 * @param horizontal <code>true</code> if the <code>funits</code>
269 * value is along the x axis, <code>false</code> if it is along the
272 private float scaleFromFUnits(int funits
,
274 AffineTransform transform
,
275 boolean fractionalMetrics
,
280 s
= (double) pointSize
/ unitsPerEm
;
281 if (transform
!= null)
282 s
*= horizontal ? transform
.getScaleY() : transform
.getScaleX();
284 if (!fractionalMetrics
)
291 * Determines the distance between the base line and the highest
294 * @param pointSize the point size of the font.
296 * @param transform a transform that is applied in addition to
297 * scaling to the specified point size. This is often used for
298 * scaling according to the device resolution. Those who lack any
299 * aesthetic sense may also use the transform to slant or stretch
302 * @param antialias <code>true</code> for anti-aliased rendering,
303 * <code>false</code> for normal rendering. For hinted fonts,
304 * this parameter may indeed affect the result.
306 * @param fractionalMetrics <code>true</code> for fractional metrics,
307 * <code>false</code> for rounding the result to a pixel boundary.
309 * @param horizontal <code>true</code> for horizontal line layout,
310 * <code>false</code> for vertical line layout.
312 * @return the ascent, which usually is a positive number.
314 public float getAscent(float pointSize
,
315 AffineTransform transform
,
317 boolean fractionalMetrics
,
320 /* Note that the ascent is orthogonal to the direction of line
321 * layout: If the line direction is horizontal, the measurement of
322 * ascent is along the vertical axis, and vice versa.
324 return scaleFromFUnits(glyphMeasurer
.getAscent(horizontal
),
328 /* reverse */ !horizontal
);
333 * Determines the distance between the base line and the lowest
336 * @param pointSize the point size of the font.
338 * @param transform a transform that is applied in addition to
339 * scaling to the specified point size. This is often used for
340 * scaling according to the device resolution. Those who lack any
341 * aesthetic sense may also use the transform to slant or stretch
344 * @param antialiased <code>true</code> for anti-aliased rendering,
345 * <code>false</code> for normal rendering. For hinted fonts,
346 * this parameter may indeed affect the result.
348 * @param fractionalMetrics <code>true</code> for fractional metrics,
349 * <code>false</code> for rounding the result to a pixel boundary.
351 * @param horizontal <code>true</code> for horizontal line layout,
352 * <code>false</code> for vertical line layout.
354 * @return the descent, which usually is a nagative number.
356 public float getDescent(float pointSize
,
357 AffineTransform transform
,
359 boolean fractionalMetrics
,
362 /* Note that the descent is orthogonal to the direction of line
363 * layout: If the line direction is horizontal, the measurement of
364 * descent is along the vertical axis, and vice versa.
366 return scaleFromFUnits(glyphMeasurer
.getDescent(horizontal
),
370 /* reverse */ !horizontal
);