Source for gnu.java.awt.font.opentype.truetype.TrueTypeScaler

   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&#x2019;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: }