diff options
Diffstat (limited to 'libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java')
-rw-r--r-- | libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java b/libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java new file mode 100644 index 00000000000..e4d7309cb55 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java @@ -0,0 +1,372 @@ +/* TrueTypeScaler.java -- Font scaler for TrueType outlines. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.font.opentype.truetype; + +import gnu.java.awt.font.opentype.Scaler; + +import java.awt.FontFormatException; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.nio.ByteBuffer; + + +/** + * A scaler for fonts whose outlines are described in the TrueType + * format. + * + * <p><b>Lack of Thread Safety:</b> Font scalers are intentionally + * <i>not</i> safe to access from multiple concurrent threads. + * Synchronization needs to be performed externally. Usually, the font + * that uses this scaler already has obtained a lock before calling + * the scaler. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public final class TrueTypeScaler + extends Scaler +{ + /** + * The TrueType or OpenType table that contains the glyph outlines. + */ + private ByteBuffer glyfTable; + + + /** + * A helper object for loading glyph outlines. + */ + private GlyphLoader glyphLoader; + + + /** + * A helper object for measuring the advance width and height of a + * glyph. + */ + private final GlyphMeasurer glyphMeasurer; + + private final Zone glyphZone; + + + /** + * The number of units per em. A typical value is 2048, but some + * font use other numbers as well. + */ + private int unitsPerEm; + + + /** + * Constructs a new TrueTypeScaler. + * + * @param unitsPerEm the number of font units per em. This value can + * be retrieved from the font’s <code>head</code> table. + * + * @param maxp the <code>maxp</code> table of the font, which + * contains various constants needed for setting up the virtual + * machine that interprets TrueType bytecodes. + * + * @param controlValueTable the <code>cvt</code> table of the font, + * which contains the initial values of the control value table. + * + * @param fpgm the <code>fpgm</code> table of the font, which + * contains a font program that is executed exactly once. The + * purpose of the font program is to define functions and to patch + * the interpreter. + * + * @param locaFormat the format of the <code>loca</code> table. The + * value must be 0 for two-byte offsets, or 1 for four-byte + * offsets. TrueType and OpenType fonts indicate the format in the + * <code>indexToLoc</code> field of the <a href= + * "http://partners.adobe.com/asn/tech/type/opentype/head.html" + * >font header</a>. + * + * @param loca the <code>loca</code> table of the font, which + * contains for each glyph the offset of its outline data + * in <code>glyf</code>. + * + * @param glyf the <code>glyf</code> table of the font, which + * contains the outline data for all glyphs in the font. + * + * @param preProgram the <code>prep</code> table of the font, which + * contains a program that is executed whenever the point size or + * the device transform have changed. This program is called + * pre-program because it gets executed before the instructions of + * the individual glyphs. If the font does not contain a + * pre-program, pass <code>null</code>. + * + * @throws FontFormatException if <code>format</code> is neither 0 + * nor 1. + */ + public TrueTypeScaler(int unitsPerEm, + ByteBuffer hhea, + ByteBuffer htmx, + ByteBuffer vhea, + ByteBuffer vtmx, + ByteBuffer maxp, + ByteBuffer controlValueTable, + ByteBuffer fpgm, + int locaFormat, ByteBuffer loca, + ByteBuffer glyf, + ByteBuffer preProgram) + throws FontFormatException + { + int maxContours, maxPoints; + VirtualMachine vm; + + maxContours = Math.max(/* maxContours */ (int) maxp.getChar(8), + /* maxCompositeContours */ (int) maxp.getChar(12)) + + /* fix for some broken fonts */ 8; + maxPoints = Math.max(/* maxPoints */ (int) maxp.getChar(6), + /* maxCompositePoints */ (int) maxp.getChar(10)) + + /* fix for some broken fonts */ 12; + + + glyphZone = new Zone(maxPoints + /* four phantom points */ 4); + this.glyfTable = glyf; + vm = new VirtualMachine(unitsPerEm, maxp, + controlValueTable, fpgm, + preProgram); + + GlyphLocator locator = GlyphLocator.forTable(locaFormat, loca, glyf); + glyphMeasurer = new GlyphMeasurer(hhea, htmx, vhea, vtmx); + glyphLoader = new GlyphLoader(locator, vm, unitsPerEm, + maxContours, maxPoints, + glyphMeasurer); + + this.unitsPerEm = unitsPerEm; + } + + + /** + * Retrieves the scaled outline of a glyph, adjusting control points + * to the raster grid if necessary. + * + * @param glyphIndex the glyph number whose outline is retrieved. + * + * @param pointSize the point size for the glyph. + * + * @param deviceTransform an affine transformation for the device. + * + * @param antialias whether or not the rasterizer will perform + * anti-aliasing on the returned path. + * + * @param fractionalMetrics <code>false</code> for adjusting glyph + * positions to the raster grid of device space. + */ + public GeneralPath getOutline(int glyphIndex, + float pointSize, + AffineTransform deviceTransform, + boolean antialias, + boolean fractionalMetrics) + { + glyphLoader.loadGlyph(glyphIndex, pointSize, deviceTransform, + antialias, glyphZone); + return glyphZone.getPath(); + } + + + /** + * Determines the advance width and height for a glyph. + * + * @param glyphIndex the glyph whose advance width and height is to + * be determined. + * + * @param pointSize the point size of the font. + * + * @param transform a transform that is applied in addition to + * scaling to the specified point size. This is often used for + * scaling according to the device resolution. Those who lack any + * aesthetic sense may also use the transform to slant or stretch + * glyphs. + * + * @param antialias <code>true</code> for anti-aliased rendering, + * <code>false</code> for normal rendering. For hinted fonts, + * this parameter may indeed affect the result. + * + * @param fractionalMetrics <code>true</code> for fractional metrics, + * <code>false</code> for rounding the result to a pixel boundary. + * + * @param horizontal <code>true</code> for horizontal line layout, + * <code>false</code> for vertical line layout. + * + * @param advance a point whose <code>x</code> and <code>y</code> + * fields will hold the advance in each direction. It is possible + * that both values are non-zero, for example if + * <code>transform</code> is a rotation, or in the case of Urdu + * fonts. + */ + public void getAdvance(int glyphIndex, + float pointSize, + AffineTransform transform, + boolean antialias, + boolean fractionalMetrics, + boolean horizontal, + Point2D advance) + { + double x, y; + double scaleFactor = (double) pointSize / unitsPerEm; + + /* FIXME: Should grid-fit if needed. Also, use cache if present + * in the font. + */ + advance.setLocation( + scaleFactor * glyphMeasurer.getAdvanceWidth(glyphIndex, horizontal), + scaleFactor * glyphMeasurer.getAdvanceHeight(glyphIndex, horizontal)); + + transform.transform(advance, advance); + } + + + /** + * Scales a value from font units to pixels, given the point size + * and the transform. + * + * @param pointSize the point size of the font. + * + * @param transform a transform that is applied in addition to + * scaling to the specified point size. This is often used for + * scaling according to the device resolution. + * + * @param fractionalMetrics <code>true</code> for fractional + * metrics, <code>false</code> for rounding the result to a pixel + * boundary. + * + * @param horizontal <code>true</code> if the <code>funits</code> + * value is along the x axis, <code>false</code> if it is along the + * y axis. + */ + private float scaleFromFUnits(int funits, + float pointSize, + AffineTransform transform, + boolean fractionalMetrics, + boolean horizontal) + { + double s; + + s = (double) pointSize / unitsPerEm; + if (transform != null) + s *= horizontal ? transform.getScaleY() : transform.getScaleX(); + s *= funits; + if (!fractionalMetrics) + s = Math.round(s); + return (float) s; + } + + + /** + * Determines the distance between the base line and the highest + * ascender. + * + * @param pointSize the point size of the font. + * + * @param transform a transform that is applied in addition to + * scaling to the specified point size. This is often used for + * scaling according to the device resolution. Those who lack any + * aesthetic sense may also use the transform to slant or stretch + * glyphs. + * + * @param antialias <code>true</code> for anti-aliased rendering, + * <code>false</code> for normal rendering. For hinted fonts, + * this parameter may indeed affect the result. + * + * @param fractionalMetrics <code>true</code> for fractional metrics, + * <code>false</code> for rounding the result to a pixel boundary. + * + * @param horizontal <code>true</code> for horizontal line layout, + * <code>false</code> for vertical line layout. + * + * @return the ascent, which usually is a positive number. + */ + public float getAscent(float pointSize, + AffineTransform transform, + boolean antialias, + boolean fractionalMetrics, + boolean horizontal) + { + /* Note that the ascent is orthogonal to the direction of line + * layout: If the line direction is horizontal, the measurement of + * ascent is along the vertical axis, and vice versa. + */ + return scaleFromFUnits(glyphMeasurer.getAscent(horizontal), + pointSize, + transform, + fractionalMetrics, + /* reverse */ !horizontal); + } + + + /** + * Determines the distance between the base line and the lowest + * descender. + * + * @param pointSize the point size of the font. + * + * @param transform a transform that is applied in addition to + * scaling to the specified point size. This is often used for + * scaling according to the device resolution. Those who lack any + * aesthetic sense may also use the transform to slant or stretch + * glyphs. + * + * @param antialiased <code>true</code> for anti-aliased rendering, + * <code>false</code> for normal rendering. For hinted fonts, + * this parameter may indeed affect the result. + * + * @param fractionalMetrics <code>true</code> for fractional metrics, + * <code>false</code> for rounding the result to a pixel boundary. + * + * @param horizontal <code>true</code> for horizontal line layout, + * <code>false</code> for vertical line layout. + * + * @return the descent, which usually is a nagative number. + */ + public float getDescent(float pointSize, + AffineTransform transform, + boolean antialiased, + boolean fractionalMetrics, + boolean horizontal) + { + /* Note that the descent is orthogonal to the direction of line + * layout: If the line direction is horizontal, the measurement of + * descent is along the vertical axis, and vice versa. + */ + return scaleFromFUnits(glyphMeasurer.getDescent(horizontal), + pointSize, + transform, + fractionalMetrics, + /* reverse */ !horizontal); + } +} |