Class: Fontisan::Optimizers::CharstringRewriter

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/optimizers/charstring_rewriter.rb

Overview

Rewrites CharStrings by replacing repeated patterns with subroutine calls. Uses position-aware replacement to handle multiple patterns per glyph without offset corruption.

Examples:

Basic usage

builder = SubroutineBuilder.new(patterns, type: :local)
builder.build
subroutine_map = patterns.each_with_index.to_h { |p, i| [p.bytes, i] }
rewriter = CharstringRewriter.new(subroutine_map, builder)
rewritten = rewriter.rewrite(charstring, patterns_for_glyph)
valid = rewriter.validate(rewritten)

See Also:

  • docs/SUBROUTINE_ARCHITECTUREdocs/SUBROUTINE_ARCHITECTURE.md

Instance Method Summary collapse

Constructor Details

#initialize(subroutine_map, builder) ⇒ CharstringRewriter

Initialize rewriter with subroutine map and builder

Parameters:

  • subroutine_map (Hash<String, Integer>)

    pattern bytes => subroutine_id

  • builder (SubroutineBuilder)

    builder for creating calls



22
23
24
25
# File 'lib/fontisan/optimizers/charstring_rewriter.rb', line 22

def initialize(subroutine_map, builder)
  @subroutine_map = subroutine_map
  @builder = builder
end

Instance Method Details

#rewrite(charstring, patterns) ⇒ String

Rewrite a CharString by replacing patterns with subroutine calls Sorts patterns by position (descending) to avoid offset issues when replacing multiple patterns in the same CharString.

Parameters:

  • charstring (String)

    original CharString bytes

  • patterns (Array<Pattern>)

    patterns to replace in this CharString

Returns:

  • (String)

    rewritten CharString with subroutine calls



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/fontisan/optimizers/charstring_rewriter.rb', line 34

def rewrite(charstring, patterns)
  return charstring if patterns.empty?

  # Build list of all replacements: [position, pattern]
  replacements = build_replacement_list(charstring, patterns)

  # Remove overlapping replacements
  replacements = remove_overlaps(replacements)

  # Sort by position (descending) to avoid offset corruption
  replacements.sort_by! { |pos, _pattern| -pos }

  # Apply each replacement
  rewritten = charstring.dup
  replacements.each do |position, pattern|
    subroutine_id = @subroutine_map[pattern.bytes]
    next if subroutine_id.nil?

    call = @builder.create_call(subroutine_id)

    # Replace pattern with call at position
    rewritten[position, pattern.length] = call
  end

  rewritten
end

#validate(charstring) ⇒ Boolean

Validate rewritten CharString for structural correctness For now, performs basic validation. Future: full CFF parsing.

Parameters:

  • charstring (String)

    CharString to validate

Returns:

  • (Boolean)

    true if valid, false otherwise



66
67
68
69
70
71
72
73
74
75
# File 'lib/fontisan/optimizers/charstring_rewriter.rb', line 66

def validate(charstring)
  return false if charstring.nil? || charstring.empty?

  # Basic validation: check for return operator at end
  # and reasonable length
  return false if charstring.empty?

  # More comprehensive validation can be added later
  true
end