Class: Fontisan::Tables::Cff::CharStringParser
- Inherits:
-
Object
- Object
- Fontisan::Tables::Cff::CharStringParser
- Defined in:
- lib/fontisan/tables/cff/charstring_parser.rb
Overview
CharString parser that converts binary CharString data to operation list
Unlike CharString which
interprets and executes CharStrings for rendering, CharStringParser
parses CharStrings into a list of operations that can be modified and
rebuilt. This enables CharString manipulation for hint injection,
subroutine optimization, and other transformations.
Operation Format:
{
type: :operator,
name: :rmoveto,
operands: [100, 200]
}
Reference: Adobe Type 2 CharString Format https://adobe-type-tools.github.io/font-tech-notes/pdfs/5177.Type2.pdf
Constant Summary collapse
- OPERATORS =
Type 2 CharString operators (from CharString class)
{ # Path construction operators 1 => :hstem, 3 => :vstem, 4 => :vmoveto, 5 => :rlineto, 6 => :hlineto, 7 => :vlineto, 8 => :rrcurveto, 10 => :callsubr, 11 => :return, 14 => :endchar, 18 => :hstemhm, 19 => :hintmask, 20 => :cntrmask, 21 => :rmoveto, 22 => :hmoveto, 23 => :vstemhm, 24 => :rcurveline, 25 => :rlinecurve, 26 => :vvcurveto, 27 => :hhcurveto, 28 => :shortint, 29 => :callgsubr, 30 => :vhcurveto, 31 => :hvcurveto, # 12 prefix for two-byte operators [12, 3] => :and, [12, 4] => :or, [12, 5] => :not, [12, 9] => :abs, [12, 10] => :add, [12, 11] => :sub, [12, 12] => :div, [12, 14] => :neg, [12, 15] => :eq, [12, 18] => :drop, [12, 20] => :put, [12, 21] => :get, [12, 22] => :ifelse, [12, 23] => :random, [12, 24] => :mul, [12, 26] => :sqrt, [12, 27] => :dup, [12, 28] => :exch, [12, 29] => :index, [12, 30] => :roll, [12, 34] => :hflex, [12, 35] => :flex, [12, 36] => :hflex1, [12, 37] => :flex1, }.freeze
- HINTMASK_OPERATORS =
Operators that require hint mask bytes
%i[hintmask cntrmask].freeze
Instance Attribute Summary collapse
-
#data ⇒ String
readonly
Binary CharString data.
-
#operations ⇒ Array<Hash>
readonly
Parsed operations.
Instance Method Summary collapse
-
#initialize(data, stem_count: 0) ⇒ CharStringParser
constructor
Initialize parser with CharString data.
-
#parse ⇒ Array<Hash>
Parse CharString to operation list.
-
#stem_count=(count) ⇒ Object
Update stem count (needed for hintmask operations).
Constructor Details
#initialize(data, stem_count: 0) ⇒ CharStringParser
Initialize parser with CharString data
100 101 102 103 104 |
# File 'lib/fontisan/tables/cff/charstring_parser.rb', line 100 def initialize(data, stem_count: 0) @data = data @stem_count = stem_count @operations = [] end |
Instance Attribute Details
#data ⇒ String (readonly)
Returns Binary CharString data.
91 92 93 |
# File 'lib/fontisan/tables/cff/charstring_parser.rb', line 91 def data @data end |
#operations ⇒ Array<Hash> (readonly)
Returns Parsed operations.
94 95 96 |
# File 'lib/fontisan/tables/cff/charstring_parser.rb', line 94 def operations @operations end |
Instance Method Details
#parse ⇒ Array<Hash>
Parse CharString to operation list
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/fontisan/tables/cff/charstring_parser.rb', line 109 def parse @operations = [] io = StringIO.new(@data) operand_stack = [] until io.eof? byte = io.getbyte if operator_byte?(byte) # Operator byte - read operator and create operation operator = read_operator(io, byte) # Read hint mask data if needed hint_data = nil if HINTMASK_OPERATORS.include?(operator) hint_bytes = (@stem_count + 7) / 8 hint_data = io.read(hint_bytes) if hint_bytes.positive? end # Create operation @operations << { type: :operator, name: operator, operands: operand_stack.dup, hint_data: hint_data, } # Clear operand stack operand_stack.clear else # Operand byte - read number and push to stack io.pos -= 1 number = read_number(io) operand_stack << number end end @operations rescue StandardError => e raise CorruptedTableError, "Failed to parse CharString: #{e.}" end |
#stem_count=(count) ⇒ Object
Update stem count (needed for hintmask operations)
155 156 157 |
# File 'lib/fontisan/tables/cff/charstring_parser.rb', line 155 def stem_count=(count) @stem_count = count end |