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