gnu.java.awt.font.opentype.truetype
Class VirtualMachine

java.lang.Object
  |
  +--gnu.java.awt.font.opentype.truetype.VirtualMachine

class VirtualMachine
extends java.lang.Object

A virtual machine for interpreting TrueType bytecodes.

Lack of Thread Safety: The virtual machine is intentionally not safe to access from multiple concurrent threads. Synchronization needs to be performed externally. Usually, the font has already obtained a lock before calling the scaler, which in turn calls the VM. It would be wasteful to acquire additional locks for the VM.

Implementation Status: The current implementation can execute pre-programs of fonts, but it does not yet actually move any points. Control flow and arithmeti instructions are implemented, but most geometric instructions are not working yet. So, the VirtualMachine class is currently a no-op. However, not very much is missing. You are more than welcome to complete the implementation.

Patents: Apple Computer holds three United States Patents for the mathematical algorithms that are used by TrueType instructions. The monopoly granted by these patents will expire in October 2009. Before the expiration date, a license must be obtained from Apple Computer to use the patented technology inside the United States. For other countries, different dates might apply, or no license might be needed.

The default build of this class does not use the patented algorithms. If you have obtained a license from Apple, or if the patent protection has expired, or if no license is required for your contry, you can set a flag in the source file which will enable the use of the patented mathematical algorithms.

The relevant patents are listed subsequently.

  1. United States Patent 5155805, Method and Apparatus for Moving Control Points in Displaying Digital Typeface on Raster Output Devices, invented by Sampo Kaasila, assigned to Apple Computer. Filing date: May 8, 1989. Date of patent: October 13, 1992.
  2. United States Patent 5159668, Method and Apparatus for Manipulating Outlines in Improving Digital Typeface on Raster Output Devices, invented by Sampo Kaasila, assigned to Apple Computer. Filing date: May 8, 1989. Date of patent: October 27, 1992.
  3. United States Patent 5325479, Method and Apparatus for Moving Control Points in Displaying Digital Typeface on Raster Output Devices, invented by Sampo Kaasila, assigned to Apple Computer. Filing date: May 28, 1989. Date of patent: June 28, 1994 (with a statement that “[t]he portion of the term of this patent subsequent to Oct. 13, 2009 has been disclaimed”).

Author:
Sascha Brawer (brawer@dandelis.ch)

Field Summary
private  boolean antialiased
          Indicates whether or not scan-line conversion will use anti-aliasing (with gray levels).
private  int cachedPixelsPerEM
          A cache for the number of pixels per EM.
private  java.nio.ShortBuffer controlValueTable
          The original Control Value Table, sometimes abbreviated as CVT.
private  int[] cvt
          The scaled values inside the control value table.
private  int cvtCutIn
           
private  int deltaBase
           
private  int deltaShift
           
private  java.awt.geom.AffineTransform deviceTransform
           
private  short dualX
           
private  short dualY
           
private  int engineCompensation
          A value that is used by rounding operations to compensate for dot gain.
private  boolean executeGlyphInstructions
          Indicates whether or not the instructions that are associated with individual glyphs shall be executed.
private  java.nio.ByteBuffer[] fdefBuffer
          fdefBuffer[i] is the buffer that contains the TrueType instructions of function #i.
private  int[] fdefEntryPoint
          fdefEntryPoint[i] is the position in fdefBuffer[i] where the first TrueType instruction after the FDEF is located.
private  java.nio.ByteBuffer fontProgram
          The contents of the font’s fpgm table, or null after the font program has been executed once.
private  short freeX
           
private  short freeY
           
private  Zone glyphZone
           
private  boolean ignoreCVTProgram
          Indicates whether to ignore any modifications to the control value table that the font’s pre-program might have performed.
private static java.lang.String[] INST_NAME
           
private  int loop
           
private  int maxStackElements
          The maximum number of stack elements.
private  int minimumDistance
           
private  int numTwilightPoints
          The number of points in the Twilight Zone.
private static short ONE_214
          The value 1 in 2-dot-14 fixed notation.
private static boolean PATENTED_HINTING
          Indicates whether or not to perform hinting operations that are protected by a number of US patents, two of which will expire on October 13, 2009, and one of which will expire on October 27, 2009.
private  int pointSize
          The current point size of the scaled font.
private  java.nio.ByteBuffer preProgram
          The prep table of the font, which contains a program that is executed whenever the point size or the device transform have changed.
private  short projX
           
private  short projY
           
private  int roundPeriod
          The length of the space between rounded values.
private  int roundPhase
          The offset of the rounded values from multiples of roundPeriod.
private  int roundThreshold
           
private  int rp0
           
private  int rp1
           
private  int rp2
           
private  int scaleX
           
private  int scaleY
           
private  boolean scanControl
           
private  int scanType
           
private  int shearX
           
private  int shearY
           
private  int singleWidthValue
           
private  int sp
          The current stack pointer of the virtual machine.
private  int[] stack
          The stack.
private  int[] storage
          The storage area of the virtual machine.
private static boolean TRACE_EXECUTION
          Indicates whether the execution of the Virtual Machine is traced to System.out.
private  Zone twilightZone
           
private  int unitsPerEm
          The number of font units per EM.
private  Zone zp0
           
private  Zone zp1
           
private  Zone zp2
           
 
Constructor Summary
(package private) VirtualMachine(int unitsPerEm, java.nio.ByteBuffer maxp, java.nio.ByteBuffer controlValueTable, java.nio.ByteBuffer fontProgram, java.nio.ByteBuffer preProgram)
          Constructs a new Virtual Machine for executing TrueType instructions.
 
Method Summary
private  int applyCTM_x(int x, int y)
           
private  int applyCTM_y(int x, int y)
           
private  void deltaC(int[] pairs, int offset, int numPairs, int base)
          Implements the DELTAC instructions.
private  void dumpInstruction(java.nio.ByteBuffer inst)
          Writes a textual description of the current TrueType instruction, including the top stack elements, to System.out.
private  void dumpVectors()
           
private  void execute(java.nio.ByteBuffer instructions, int pos)
          Executes a stream of TrueType instructions.
private  boolean executeInstruction(java.nio.ByteBuffer inst)
          Executes a single TrueType instruction.
private  int funitsToPixels(int funits)
          Scales a value from font unites to pixels.
private  int getDualProjection(int x, int y)
          Projects the specified vector along the current dual projection vector.
private  int getFreeDotProj()
           
private static java.lang.String getHex(byte b)
           
private static java.lang.String getHex(short b)
           
private static int getInstructionLength(int opcode)
          Returns the number of bytes that a TrueType instruction occupies.
private static char getNibble(int i, int rightShift)
           
private  int getOriginalProjection(Zone zone, int point)
           
private  int getPixelsPerEM()
          Returns how many pixels there are per EM, in direction of the current projection vector.
private  int getProjection(int x, int y)
          Projects the specified vector along the current projection vector.
private  int getProjection(Zone zone, int point)
           
private  Zone getZone(int zoneNumber)
           
private  void handleIP()
           
private  void handleISECT(int a0, int a1, int b0, int b1, int p)
           
private  void handleMDAP(int point, boolean round)
           
private  void handleMIAP(int cvtIndex, int point, boolean round)
           
private  void handleMIRP(int bcode, int point, int cvtIndex)
           
private  boolean isRotated()
          Determines whether the current glyph is rotated.
private  boolean isStretched()
          Determines whether the current glyph is stretched.
private  void movePoint(Zone zone, int point, int distance)
           
private static int muldiv(int a, int b, int c)
           
private static int nround(int distance, int compensation)
           
private  void reloadControlValueTable()
          Reloads the control value table and scales each entry from font units to pixel values.
private  void resetGraphicsState()
          Sets the graphics state to default values.
private  int round(int distance, int compensation)
           
private  void setDualVector(short x, short y)
           
private  void setFreedomVector(short x, short y)
           
private  void setProjectionVector(short x, short y)
           
private  void setRoundingMode(int period, int mode)
          Sets the rounding mode.
 boolean setup(double pointSize, java.awt.geom.AffineTransform deviceTransform, boolean antialiased)
          Sets up the virtual machine for the specified parameters.
private static void skipAfter(java.nio.ByteBuffer inst, int opcode1, int opcode2, int illegalCode1, int illegalCode2, boolean handleNestedIfClauses)
          Skips any instructions until the specified opcode has been encoutered.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

PATENTED_HINTING

private static final boolean PATENTED_HINTING
Indicates whether or not to perform hinting operations that are protected by a number of US patents, two of which will expire on October 13, 2009, and one of which will expire on October 27, 2009.

See Also:
Constant Field Values

TRACE_EXECUTION

private static final boolean TRACE_EXECUTION
Indicates whether the execution of the Virtual Machine is traced to System.out.

See Also:
Constant Field Values

ONE_214

private static final short ONE_214
The value 1 in 2-dot-14 fixed notation.

See Also:
Constant Field Values

storage

private final int[] storage
The storage area of the virtual machine.


stack

private int[] stack
The stack. The stack grows from bottom to top, so sp[0] gets used before sp[1].


maxStackElements

private final int maxStackElements
The maximum number of stack elements.


sp

private int sp
The current stack pointer of the virtual machine.


fdefBuffer

private java.nio.ByteBuffer[] fdefBuffer
fdefBuffer[i] is the buffer that contains the TrueType instructions of function #i. Most of the time, functions are defined in the font program, but a font may also re-define functions in its CVT program.


fdefEntryPoint

private int[] fdefEntryPoint
fdefEntryPoint[i] is the position in fdefBuffer[i] where the first TrueType instruction after the FDEF is located.


controlValueTable

private java.nio.ShortBuffer controlValueTable
The original Control Value Table, sometimes abbreviated as CVT. The table contains signed 16-bit FUnits. Some fonts have no CVT, in which case the field will be null.


cvt

private int[] cvt
The scaled values inside the control value table.


engineCompensation

private int engineCompensation
A value that is used by rounding operations to compensate for dot gain.


fontProgram

private java.nio.ByteBuffer fontProgram
The contents of the font’s fpgm table, or null after the font program has been executed once.


preProgram

private java.nio.ByteBuffer preProgram
The prep 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, the value of this field is null.


numTwilightPoints

private int numTwilightPoints
The number of points in the Twilight Zone.


pointSize

private int pointSize
The current point size of the scaled font. The value is in Fixed 26.6 notation.


deviceTransform

private java.awt.geom.AffineTransform deviceTransform

scaleX

private int scaleX

scaleY

private int scaleY

shearX

private int shearX

shearY

private int shearY

antialiased

private boolean antialiased
Indicates whether or not scan-line conversion will use anti-aliasing (with gray levels). Font programs can ask for this value with the GETINFO instruction, and some programs may behave differently according to this setting.


cvtCutIn

private int cvtCutIn

deltaBase

private int deltaBase

deltaShift

private int deltaShift

freeX

private short freeX

freeY

private short freeY

loop

private int loop

minimumDistance

private int minimumDistance

projX

private short projX

projY

private short projY

dualX

private short dualX

dualY

private short dualY

rp0

private int rp0

rp1

private int rp1

rp2

private int rp2

scanControl

private boolean scanControl

scanType

private int scanType

singleWidthValue

private int singleWidthValue

zp0

private Zone zp0

zp1

private Zone zp1

zp2

private Zone zp2

twilightZone

private Zone twilightZone

glyphZone

private Zone glyphZone

executeGlyphInstructions

private boolean executeGlyphInstructions
Indicates whether or not the instructions that are associated with individual glyphs shall be executed. Set as a side effect of executing the pre-program when the point size, device transform or some other relevant parameter have changed.


ignoreCVTProgram

private boolean ignoreCVTProgram
Indicates whether to ignore any modifications to the control value table that the font’s pre-program might have performed. Set as a side effect of executing the pre-program when the point size, device transform or some other relevant parameter have changed.


roundPeriod

private int roundPeriod
The length of the space between rounded values. A value of zero means that rounding has been switched off.


roundPhase

private int roundPhase
The offset of the rounded values from multiples of roundPeriod.


roundThreshold

private int roundThreshold

cachedPixelsPerEM

private int cachedPixelsPerEM
A cache for the number of pixels per EM. The value is a normal integer, not a fixed point notation.

See Also:
getPixelsPerEM()

unitsPerEm

private int unitsPerEm
The number of font units per EM.


INST_NAME

private static final java.lang.String[] INST_NAME
Constructor Detail

VirtualMachine

VirtualMachine(int unitsPerEm,
               java.nio.ByteBuffer maxp,
               java.nio.ByteBuffer controlValueTable,
               java.nio.ByteBuffer fontProgram,
               java.nio.ByteBuffer preProgram)
         throws java.awt.FontFormatException
Constructs a new Virtual Machine for executing TrueType instructions.

Parameters:
unitsPerEm - the number of font units in one typographic em.
preProgram - the prep 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 null.
Method Detail

resetGraphicsState

private void resetGraphicsState()
Sets the graphics state to default values.


reloadControlValueTable

private void reloadControlValueTable()
Reloads the control value table and scales each entry from font units to pixel values.


funitsToPixels

private int funitsToPixels(int funits)
Scales a value from font unites to pixels.

Returns:
the scaled value.

setup

public boolean setup(double pointSize,
                     java.awt.geom.AffineTransform deviceTransform,
                     boolean antialiased)
Sets up the virtual machine for the specified parameters. If there is no change to the last set-up, the method will quickly return. Otherwise, the font’s pre-program will be executed.

Parameters:
pointSize - the point size of the scaled font.
deviceTransform - an affine transformation which gets applied in addition to scaling by pointSize. Font programs can separately inquire about the point size. For this reason, it is not recommended to pre-multiply the point size to the device transformation.
antialiased - true if the scan-line conversion algorithm will use gray levels to give a smoother appearance, false otherwise. Font programs can ask for this value with the GETINFO instruction, and some programs may behave differently according to this setting.

execute

private void execute(java.nio.ByteBuffer instructions,
                     int pos)
Executes a stream of TrueType instructions.


dumpInstruction

private void dumpInstruction(java.nio.ByteBuffer inst)
Writes a textual description of the current TrueType instruction, including the top stack elements, to System.out. This is useful for debugging.

Parameters:
inst - the instruction stream, positioned at the current instruction.

getNibble

private static char getNibble(int i,
                              int rightShift)

getHex

private static java.lang.String getHex(byte b)

getHex

private static java.lang.String getHex(short b)

skipAfter

private static void skipAfter(java.nio.ByteBuffer inst,
                              int opcode1,
                              int opcode2,
                              int illegalCode1,
                              int illegalCode2,
                              boolean handleNestedIfClauses)
Skips any instructions until the specified opcode has been encoutered.

Parameters:
inst - the current instruction stream. After the call, the position of inst is right after the first occurence of opcode.
opcode1 - the opcode for which to look.
opcode2 - another opcode for which to look. Pass -1 if only opcode1 would terminate skipping.
illegalCode1 - an opcode that must not be encountered while skipping. Pass -1 if any opcode is acceptable.
illegalCode2 - another opcode that must not be encountered while skipping. Pass -1 to perform no check.
handleNestedIfClauses - true to handle nested IF [ELSE] EIF clauses, false to ignore them. From the TrueType specification document, one would think that nested if clauses would not be valid, but they do appear in some fonts.
Throws:
java.lang.IllegalStateException - if illegalCode1 or illegalCode2 has been encountered while skipping.

getInstructionLength

private static int getInstructionLength(int opcode)
Returns the number of bytes that a TrueType instruction occupies.

Parameters:
opcode - the instruction.
Returns:
the number of bytes occupied by the instructions and its operands. For NPUSHB and NPUSHW, where the instruction length depends on the first operand byte, the result is -1.

executeInstruction

private boolean executeInstruction(java.nio.ByteBuffer inst)
Executes a single TrueType instruction. This is the core routine of the Virtual Machine.

Returns:
true if another instruction shall be executed in the same call frame; false if the current call frame shall be popped.

setRoundingMode

private void setRoundingMode(int period,
                             int mode)
Sets the rounding mode.

Parameters:
period - the grid period in fixed-point notation, such as Fixed.ONE for the SROUND instruction or sqrt(2)/2 for the S45ROUND instruction.
mode - a byte whose bits are set according to the TrueType specification for SROUND and S45ROUND parameters.

deltaC

private void deltaC(int[] pairs,
                    int offset,
                    int numPairs,
                    int base)
Implements the DELTAC instructions. These instructions check whether the current number of pixels per em is contained in an exception table. If it is, a delta value is determined, and the specified entry in the Control Value Table is modified according to the delta.

Parameters:
pairs - the delta table. Because the delta table is on the stack, callers usually just want to pass the stack array.
offset - the offset of the first pair in pairs.
numPairs - the number of pairs.
base - 0 for DELTAC1, 16 for DELTAC2, or 32 for DELTAC2.
See Also:
Apple’s documentation for DELTAC1, DELTAC2, and DELTAC3

getZone

private Zone getZone(int zoneNumber)

getProjection

private int getProjection(int x,
                          int y)
Projects the specified vector along the current projection vector.

Parameters:
x - the x component of the input vector, in 26.6 fixed-point notation.
y - the y component of the input vector, in 26.6 fixed-point notation.
Returns:
the projected distance, in 26.6 fixed-point notation.

getDualProjection

private int getDualProjection(int x,
                              int y)
Projects the specified vector along the current dual projection vector.

Parameters:
x - the x component of the input vector, in 26.6 fixed-point notation.
y - the y component of the input vector, in 26.6 fixed-point notation.
Returns:
the projected distance, in 26.6 fixed-point notation.

getProjection

private int getProjection(Zone zone,
                          int point)

getOriginalProjection

private int getOriginalProjection(Zone zone,
                                  int point)

handleISECT

private void handleISECT(int a0,
                         int a1,
                         int b0,
                         int b1,
                         int p)

muldiv

private static int muldiv(int a,
                          int b,
                          int c)

getFreeDotProj

private int getFreeDotProj()

movePoint

private void movePoint(Zone zone,
                       int point,
                       int distance)

dumpVectors

private void dumpVectors()

handleIP

private void handleIP()

handleMDAP

private void handleMDAP(int point,
                        boolean round)

handleMIAP

private void handleMIAP(int cvtIndex,
                        int point,
                        boolean round)

handleMIRP

private void handleMIRP(int bcode,
                        int point,
                        int cvtIndex)

round

private int round(int distance,
                  int compensation)

nround

private static int nround(int distance,
                          int compensation)

isRotated

private boolean isRotated()
Determines whether the current glyph is rotated.

Returns:
false if the shearing factors for the x and y axes are zero; true if they are non-zero.

isStretched

private boolean isStretched()
Determines whether the current glyph is stretched.

Returns:
false if the scaling factors for the x and y axes are are equal; true if they differ.

getPixelsPerEM

private int getPixelsPerEM()
Returns how many pixels there are per EM, in direction of the current projection vector. The result is a normal integer, not a Fixed.


setProjectionVector

private void setProjectionVector(short x,
                                 short y)

setFreedomVector

private void setFreedomVector(short x,
                              short y)

setDualVector

private void setDualVector(short x,
                           short y)

applyCTM_x

private int applyCTM_x(int x,
                       int y)

applyCTM_y

private int applyCTM_y(int x,
                       int y)