Class: Fontisan::Hints::TrueTypeInstructionGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/hints/truetype_instruction_generator.rb

Overview

Generates TrueType instruction bytecode from PostScript hint parameters

This class is the inverse of TrueTypeInstructionAnalyzer - it takes PostScript hint parameters and generates equivalent TrueType prep/fpgm programs and CVT values.

TrueType Instruction Opcodes:

  • NPUSHB (0x40): Push n bytes

  • NPUSHW (0x41): Push n words (16-bit)

  • PUSHB (0xB0-0xB7): Push 1-8 bytes

  • PUSHW (0xB8-0xBF): Push 1-8 words

  • SSW (0x1F): Set Single Width

  • SSWCI (0x1E): Set Single Width Cut-In

  • SCVTCI (0x1D): Set CVT Cut-In

  • WCVTP (0x44): Write CVT in Pixels

  • WCVTF (0x70): Write CVT in FUnits

Examples:

Generate TrueType programs

generator = TrueTypeInstructionGenerator.new
programs = generator.generate({
  blue_scale: 0.039625,
  std_hw: 80,
  std_vw: 90
})
programs[:prep] # => Binary prep program
programs[:fpgm] # => Binary fpgm program (usually empty)
programs[:cvt]  # => Array of CVT values

Constant Summary collapse

NPUSHB =

TrueType instruction opcodes

0x40
NPUSHW =

Push n bytes

0x41
PUSHB_BASE =

Push n words (16-bit)

0xB0
PUSHW_BASE =

PUSHB through PUSHB

0xB8
SSW =

PUSHW through PUSHW

0x1F
SSWCI =

Set Single Width

0x1E
SCVTCI =

Set Single Width Cut-In

0x1D
WCVTP =

Set CVT Cut-In

0x44
WCVTF =

Write CVT in Pixels

0x70
MAX_PUSHB_INLINE =

Size thresholds for instruction selection

8
MAX_PUSHW_INLINE =

Maximum bytes for PUSHB

8
BYTE_MAX =

Maximum words for PUSHW

255
WORD_MAX =

Maximum value for byte

65535

Instance Method Summary collapse

Instance Method Details

#generate(ps_params) ⇒ Hash

Generate TrueType programs and CVT from PostScript parameters

Parameters:

  • ps_params (Hash)

    PostScript hint parameters

Options Hash (ps_params):

  • :blue_scale (Float)

    Blue scale value (0.0-1.0)

  • :std_hw (Integer)

    Standard horizontal width

  • :std_vw (Integer)

    Standard vertical width

  • :stem_snap_h (Array<Integer>)

    Horizontal stem snap values

  • :stem_snap_v (Array<Integer>)

    Vertical stem snap values

  • :blue_values (Array<Integer>)

    Blue zone values

  • :other_blues (Array<Integer>)

    Other blue zone values

Returns:

  • (Hash)

    Hash with :prep, :fpgm, and :cvt keys



61
62
63
64
65
66
67
68
69
70
# File 'lib/fontisan/hints/truetype_instruction_generator.rb', line 61

def generate(ps_params)
  # Normalize keys to symbols
  ps_params = normalize_keys(ps_params)

  {
    fpgm: generate_fpgm(ps_params),
    prep: generate_prep(ps_params),
    cvt: generate_cvt(ps_params)
  }
end

#generate_cvt(ps_params) ⇒ Array<Integer>

Generate CVT (Control Value Table) from PostScript parameters

CVT entries are derived from:

  • stem_snap_h/stem_snap_v: Stem widths

  • blue_values/other_blues: Alignment zones

  • std_hw/std_vw: Standard widths

Duplicates are removed and values sorted for optimal CVT organization.

Parameters:

  • ps_params (Hash)

    PostScript parameters

Returns:

  • (Array<Integer>)

    Array of 16-bit signed integers



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/fontisan/hints/truetype_instruction_generator.rb', line 132

def generate_cvt(ps_params)
  cvt = []

  # Add standard widths to CVT
  cvt << ps_params[:std_hw] if ps_params[:std_hw]
  cvt << ps_params[:std_vw] if ps_params[:std_vw]

  # Add stem snap values
  if ps_params[:stem_snap_h]
    cvt.concat(ps_params[:stem_snap_h])
  end

  if ps_params[:stem_snap_v]
    cvt.concat(ps_params[:stem_snap_v])
  end

  # Add blue zone values (as pairs: bottom, top)
  if ps_params[:blue_values]
    cvt.concat(ps_params[:blue_values])
  end

  if ps_params[:other_blues]
    cvt.concat(ps_params[:other_blues])
  end

  # Remove duplicates and sort for optimal CVT organization
  cvt.uniq.sort
end

#generate_fpgm(_ps_params) ⇒ String

Generate fpgm (Font Program) from PostScript parameters

For converted fonts, fpgm is typically empty as font-level functions are not needed for basic hint conversion.

Parameters:

  • _ps_params (Hash)

    PostScript parameters (unused)

Returns:

  • (String)

    Binary instruction bytes (empty for converted fonts)



115
116
117
118
119
# File 'lib/fontisan/hints/truetype_instruction_generator.rb', line 115

def generate_fpgm(_ps_params)
  # For converted fonts, fpgm is typically empty
  # Advanced implementations might generate function definitions here
  "".b
end

#generate_prep(ps_params) ⇒ String

Generate prep (Control Value Program) from PostScript parameters

The prep program sets up global hint parameters:

  • CVT Cut-In (from blue_scale)

  • Single Width Cut-In (from std_hw/std_vw)

  • Single Width (from std_hw or std_vw)

Parameters:

  • ps_params (Hash)

    PostScript parameters

Returns:

  • (String)

    Binary instruction bytes



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/fontisan/hints/truetype_instruction_generator.rb', line 81

def generate_prep(ps_params)
  instructions = []

  # Set CVT Cut-In from blue_scale if present
  if ps_params[:blue_scale]
    cvt_cut_in = calculate_cvt_cut_in(ps_params[:blue_scale])
    instructions.concat(push_value(cvt_cut_in))
    instructions << SCVTCI
  end

  # Set Single Width Cut-In if we have stem widths
  if ps_params[:std_hw] || ps_params[:std_vw]
    sw_cut_in = calculate_sw_cut_in(ps_params)
    instructions.concat(push_value(sw_cut_in))
    instructions << SSWCI
  end

  # Set Single Width (prefer horizontal, fall back to vertical)
  single_width = ps_params[:std_hw] || ps_params[:std_vw]
  if single_width
    instructions.concat(push_value(single_width))
    instructions << SSW
  end

  instructions.pack("C*")
end