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