Frames | No Frames |
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.Scaler; 41: 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; 47: 48: 49: /** 50: * A scaler for fonts whose outlines are described in the TrueType 51: * format. 52: * 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 57: * the scaler. 58: * 59: * @author Sascha Brawer (brawer@dandelis.ch) 60: */ 61: public final class TrueTypeScaler 62: extends Scaler 63: { 64: /** 65: * The TrueType or OpenType table that contains the glyph outlines. 66: */ 67: private ByteBuffer glyfTable; 68: 69: 70: /** 71: * A helper object for loading glyph outlines. 72: */ 73: private GlyphLoader glyphLoader; 74: 75: 76: /** 77: * A helper object for measuring the advance width and height of a 78: * glyph. 79: */ 80: private final GlyphMeasurer glyphMeasurer; 81: 82: private final Zone glyphZone; 83: 84: 85: /** 86: * The number of units per em. A typical value is 2048, but some 87: * font use other numbers as well. 88: */ 89: private int unitsPerEm; 90: 91: 92: /** 93: * Constructs a new TrueTypeScaler. 94: * 95: * @param unitsPerEm the number of font units per em. This value can 96: * be retrieved from the font’s <code>head</code> table. 97: * 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. 101: * 102: * @param controlValueTable the <code>cvt</code> table of the font, 103: * which contains the initial values of the control value table. 104: * 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 108: * the interpreter. 109: * 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" 115: * >font header</a>. 116: * 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>. 120: * 121: * @param glyf the <code>glyf</code> table of the font, which 122: * contains the outline data for all glyphs in the font. 123: * 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>. 130: * 131: * @throws FontFormatException if <code>format</code> is neither 0 132: * nor 1. 133: */ 134: public TrueTypeScaler(int unitsPerEm, 135: ByteBuffer hhea, 136: ByteBuffer htmx, 137: ByteBuffer vhea, 138: ByteBuffer vtmx, 139: ByteBuffer maxp, 140: ByteBuffer controlValueTable, 141: ByteBuffer fpgm, 142: int locaFormat, ByteBuffer loca, 143: ByteBuffer glyf, 144: ByteBuffer preProgram) 145: throws FontFormatException 146: { 147: int maxContours, maxPoints; 148: VirtualMachine vm; 149: 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; 156: 157: 158: glyphZone = new Zone(maxPoints + /* four phantom points */ 4); 159: this.glyfTable = glyf; 160: vm = new VirtualMachine(unitsPerEm, maxp, 161: controlValueTable, fpgm, 162: preProgram); 163: 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, 168: glyphMeasurer); 169: 170: this.unitsPerEm = unitsPerEm; 171: } 172: 173: 174: /** 175: * Retrieves the scaled outline of a glyph, adjusting control points 176: * to the raster grid if necessary. 177: * 178: * @param glyphIndex the glyph number whose outline is retrieved. 179: * 180: * @param pointSize the point size for the glyph. 181: * 182: * @param deviceTransform an affine transformation for the device. 183: * 184: * @param antialias whether or not the rasterizer will perform 185: * anti-aliasing on the returned path. 186: * 187: * @param fractionalMetrics <code>false</code> for adjusting glyph 188: * positions to the raster grid of device space. 189: */ 190: public GeneralPath getOutline(int glyphIndex, 191: float pointSize, 192: AffineTransform deviceTransform, 193: boolean antialias, 194: boolean fractionalMetrics) 195: { 196: glyphLoader.loadGlyph(glyphIndex, pointSize, deviceTransform, 197: antialias, glyphZone); 198: return glyphZone.getPath(); 199: } 200: 201: 202: /** 203: * Determines the advance width and height for a glyph. 204: * 205: * @param glyphIndex the glyph whose advance width and height is to 206: * be determined. 207: * 208: * @param pointSize the point size of the font. 209: * 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 214: * glyphs. 215: * 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. 219: * 220: * @param fractionalMetrics <code>true</code> for fractional metrics, 221: * <code>false</code> for rounding the result to a pixel boundary. 222: * 223: * @param horizontal <code>true</code> for horizontal line layout, 224: * <code>false</code> for vertical line layout. 225: * 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 230: * fonts. 231: */ 232: public void getAdvance(int glyphIndex, 233: float pointSize, 234: AffineTransform transform, 235: boolean antialias, 236: boolean fractionalMetrics, 237: boolean horizontal, 238: Point2D advance) 239: { 240: double x, y; 241: double scaleFactor = (double) pointSize / unitsPerEm; 242: 243: /* FIXME: Should grid-fit if needed. Also, use cache if present 244: * in the font. 245: */ 246: advance.setLocation( 247: scaleFactor * glyphMeasurer.getAdvanceWidth(glyphIndex, horizontal), 248: scaleFactor * glyphMeasurer.getAdvanceHeight(glyphIndex, horizontal)); 249: 250: transform.transform(advance, advance); 251: } 252: 253: 254: /** 255: * Scales a value from font units to pixels, given the point size 256: * and the transform. 257: * 258: * @param pointSize the point size of the font. 259: * 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. 263: * 264: * @param fractionalMetrics <code>true</code> for fractional 265: * metrics, <code>false</code> for rounding the result to a pixel 266: * boundary. 267: * 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 270: * y axis. 271: */ 272: private float scaleFromFUnits(int funits, 273: float pointSize, 274: AffineTransform transform, 275: boolean fractionalMetrics, 276: boolean horizontal) 277: { 278: double s; 279: 280: s = (double) pointSize / unitsPerEm; 281: if (transform != null) 282: s *= horizontal ? transform.getScaleY() : transform.getScaleX(); 283: s *= funits; 284: if (!fractionalMetrics) 285: s = Math.round(s); 286: return (float) s; 287: } 288: 289: 290: /** 291: * Determines the distance between the base line and the highest 292: * ascender. 293: * 294: * @param pointSize the point size of the font. 295: * 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 300: * glyphs. 301: * 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. 305: * 306: * @param fractionalMetrics <code>true</code> for fractional metrics, 307: * <code>false</code> for rounding the result to a pixel boundary. 308: * 309: * @param horizontal <code>true</code> for horizontal line layout, 310: * <code>false</code> for vertical line layout. 311: * 312: * @return the ascent, which usually is a positive number. 313: */ 314: public float getAscent(float pointSize, 315: AffineTransform transform, 316: boolean antialias, 317: boolean fractionalMetrics, 318: boolean horizontal) 319: { 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. 323: */ 324: return scaleFromFUnits(glyphMeasurer.getAscent(horizontal), 325: pointSize, 326: transform, 327: fractionalMetrics, 328: /* reverse */ !horizontal); 329: } 330: 331: 332: /** 333: * Determines the distance between the base line and the lowest 334: * descender. 335: * 336: * @param pointSize the point size of the font. 337: * 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 342: * glyphs. 343: * 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. 347: * 348: * @param fractionalMetrics <code>true</code> for fractional metrics, 349: * <code>false</code> for rounding the result to a pixel boundary. 350: * 351: * @param horizontal <code>true</code> for horizontal line layout, 352: * <code>false</code> for vertical line layout. 353: * 354: * @return the descent, which usually is a nagative number. 355: */ 356: public float getDescent(float pointSize, 357: AffineTransform transform, 358: boolean antialiased, 359: boolean fractionalMetrics, 360: boolean horizontal) 361: { 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. 365: */ 366: return scaleFromFUnits(glyphMeasurer.getDescent(horizontal), 367: pointSize, 368: transform, 369: fractionalMetrics, 370: /* reverse */ !horizontal); 371: } 372: }