Class: Fontisan::Tables::Cff::CharStringRebuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/tables/cff/charstring_rebuilder.rb

Overview

Rebuilds CharStrings INDEX with modified CharStrings

CharStringRebuilder provides high-level interface for modifying CharStrings in a CFF font. It extracts all CharStrings from the source INDEX, allows modifications through a callback, and rebuilds the INDEX with updated CharString data.

Use Cases:

  • Per-glyph hint injection
  • CharString optimization
  • Subroutine insertion
  • Any operation requiring CharString modification

Examples:

Inject hints into specific glyphs

rebuilder = CharStringRebuilder.new(charstrings_index)
rebuilder.modify_charstring(42) do |operations|
  # Insert hint operations at beginning
  hint_ops = [
    { type: :operator, name: :hstem, operands: [10, 20] }
  ]
  hint_ops + operations
end
new_index_data = rebuilder.rebuild

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source_index, stem_count: 0) ⇒ CharStringRebuilder

Initialize rebuilder with source CharStrings INDEX

Parameters:

  • source_index (CharstringsIndex)

    Source CharStrings INDEX

  • stem_count (Integer) (defaults to: 0)

    Number of stem hints (for parsing hintmask)



40
41
42
43
44
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 40

def initialize(source_index, stem_count: 0)
  @source_index = source_index
  @stem_count = stem_count
  @modifications = {}
end

Instance Attribute Details

#modificationsHash (readonly)

Returns Modified CharString data by glyph index.

Returns:

  • (Hash)

    Modified CharString data by glyph index



34
35
36
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 34

def modifications
  @modifications
end

#source_indexCharstringsIndex (readonly)

Returns Source CharStrings INDEX.

Returns:



31
32
33
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 31

def source_index
  @source_index
end

Instance Method Details

#batch_modify(glyph_indices) {|glyph_index, operations| ... } ⇒ Object

Batch modify multiple CharStrings

More efficient than calling modify_charstring multiple times.

Parameters:

  • glyph_indices (Array<Integer>)

    Glyph indices to modify

Yields:

  • (glyph_index, operations)

    Block to modify each glyph

Yield Parameters:

  • glyph_index (Integer)

    Current glyph index

  • operations (Array<Hash>)

    Parsed operations

Yield Returns:

  • (Array<Hash>)

    Modified operations



107
108
109
110
111
112
113
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 107

def batch_modify(glyph_indices)
  glyph_indices.each do |glyph_index|
    modify_charstring(glyph_index) do |operations|
      yield(glyph_index, operations)
    end
  end
end

#charstring_data(glyph_index) ⇒ String

Get CharString data (modified or original)

Parameters:

  • glyph_index (Integer)

    Glyph index

Returns:

  • (String)

    CharString binary data



135
136
137
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 135

def charstring_data(glyph_index)
  @modifications[glyph_index] || @source_index[glyph_index]
end

#clear_modificationsObject

Clear all modifications



155
156
157
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 155

def clear_modifications
  @modifications.clear
end

#modification_countInteger

Get count of modified glyphs

Returns:

  • (Integer)

    Number of modified glyphs



150
151
152
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 150

def modification_count
  @modifications.size
end

#modified?(glyph_index) ⇒ Boolean

Check if glyph has been modified

Parameters:

  • glyph_index (Integer)

    Glyph index

Returns:

  • (Boolean)

    True if modified



143
144
145
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 143

def modified?(glyph_index)
  @modifications.key?(glyph_index)
end

#modify_all {|glyph_index, operations| ... } ⇒ Object

Modify all CharStrings

Applies the same modification to every glyph.

Yields:

  • (glyph_index, operations)

    Block to modify each glyph

Yield Parameters:

  • glyph_index (Integer)

    Current glyph index

  • operations (Array<Hash>)

    Parsed operations

Yield Returns:

  • (Array<Hash>)

    Modified operations



123
124
125
126
127
128
129
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 123

def modify_all
  (0...@source_index.count).each do |i|
    modify_charstring(i) do |operations|
      yield(i, operations)
    end
  end
end

#modify_charstring(glyph_index) {|operations| ... } ⇒ Object

Modify a CharString by glyph index

The block receives the parsed operations for the glyph and should return modified operations.

Parameters:

  • glyph_index (Integer)

    Glyph index (0 = .notdef)

Yields:

  • (operations)

    Block to modify operations

Yield Parameters:

  • operations (Array<Hash>)

    Parsed operations

Yield Returns:

  • (Array<Hash>)

    Modified operations



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 55

def modify_charstring(glyph_index)
  # Get original CharString data
  original_data = @source_index[glyph_index]
  return unless original_data

  # Parse to operations
  parser = CharStringParser.new(original_data, stem_count: @stem_count)
  operations = parser.parse

  # Apply modification
  modified_operations = yield(operations)

  # Build new CharString
  new_data = CharStringBuilder.build_from_operations(modified_operations)

  # Store modification
  @modifications[glyph_index] = new_data
end

#rebuildString

Rebuild CharStrings INDEX with modifications

Creates new INDEX with modified CharStrings, keeping unmodified CharStrings unchanged.

Returns:

  • (String)

    Binary CharStrings INDEX data



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 80

def rebuild
  # Collect all CharString data (modified and unmodified)
  charstrings = []

  (0...@source_index.count).each do |i|
    charstrings << if @modifications.key?(i)
                     # Use modified CharString
                     @modifications[i]
                   else
                     # Use original CharString
                     @source_index[i]
                   end
  end

  # Build INDEX
  IndexBuilder.build(charstrings)
end

#stem_count=(count) ⇒ Object

Update stem count (needed for hintmask parsing)

Parameters:

  • count (Integer)

    Number of stem hints



162
163
164
# File 'lib/fontisan/tables/cff/charstring_rebuilder.rb', line 162

def stem_count=(count)
  @stem_count = count
end