Class: Fontisan::Type1::CharStrings

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/type1/charstrings.rb

Overview

Type 1 CharStrings parser

CharStrings parses and stores the CharStrings dictionary from a Type 1 font, which contains glyph outline descriptions.

CharStrings in Type 1 fonts use a stack-based language with commands for drawing curves, lines, and composite glyphs (via the seac operator).

Examples:

Parse CharStrings from decrypted font data

charstrings = Fontisan::Type1::CharStrings.parse(decrypted_data, private_dict)
outline = charstrings.outline_for("A")

See Also:

Defined Under Namespace

Classes: CharStringParser

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(private_dict = nil) ⇒ CharStrings

Initialize a new CharStrings parser

Parameters:

  • private_dict (PrivateDict, nil) (defaults to: nil)

    Private dictionary for lenIV



42
43
44
45
# File 'lib/fontisan/type1/charstrings.rb', line 42

def initialize(private_dict = nil)
  @private_dict = private_dict || PrivateDict.new
  @charstrings = {}
end

Instance Attribute Details

#charstringsHash (readonly)

Returns Glyph name to CharString data mapping.

Returns:

  • (Hash)

    Glyph name to CharString data mapping



21
22
23
# File 'lib/fontisan/type1/charstrings.rb', line 21

def charstrings
  @charstrings
end

#private_dictPrivateDict (readonly)

Returns Private dictionary for decryption.

Returns:



24
25
26
# File 'lib/fontisan/type1/charstrings.rb', line 24

def private_dict
  @private_dict
end

Class Method Details

.parse(data, private_dict = nil) ⇒ CharStrings

Parse CharStrings dictionary from decrypted Type 1 font data

Examples:

Parse from decrypted font data

charstrings = Fontisan::Type1::CharStrings.parse(decrypted_data, private_dict)

Parameters:

  • data (String)

    Decrypted Type 1 font data

  • private_dict (PrivateDict) (defaults to: nil)

    Private dictionary for lenIV

Returns:

Raises:



35
36
37
# File 'lib/fontisan/type1/charstrings.rb', line 35

def self.parse(data, private_dict = nil)
  new(private_dict).parse(data)
end

Instance Method Details

#[](glyph_name) ⇒ String?

Get CharString data for glyph

Parameters:

  • glyph_name (String)

    Glyph name

Returns:

  • (String, nil)

    CharString data or nil if not found



100
101
102
# File 'lib/fontisan/type1/charstrings.rb', line 100

def [](glyph_name)
  @charstrings[glyph_name]
end

#charstring(glyph_name) ⇒ String?

Alias for #[]

Parameters:

  • glyph_name (String)

    Glyph name

Returns:

  • (String, nil)

    CharString data or nil if not found



108
109
110
# File 'lib/fontisan/type1/charstrings.rb', line 108

def charstring(glyph_name)
  @charstrings[glyph_name]
end

#components_for(glyph_name) ⇒ Hash?

Get components for composite glyph

Parameters:

  • glyph_name (String)

    Glyph name

Returns:

  • (Hash, nil)

    Component info :accent or nil



141
142
143
144
145
146
147
148
149
# File 'lib/fontisan/type1/charstrings.rb', line 141

def components_for(glyph_name)
  return nil unless composite?(glyph_name)

  charstring = @charstrings[glyph_name]
  parser = CharStringParser.new(@private_dict)
  parser.parse(charstring)

  parser.seac_components
end

#composite?(glyph_name) ⇒ Boolean

Check if glyph is composite (uses seac)

Parameters:

  • glyph_name (String)

    Glyph name

Returns:

  • (Boolean)

    True if glyph uses seac operator



130
131
132
133
134
135
# File 'lib/fontisan/type1/charstrings.rb', line 130

def composite?(glyph_name)
  charstring = @charstrings[glyph_name]
  return false if charstring.nil?

  charstring.include?(SEAC_OPCODE)
end

#countInteger

Get the number of charstrings

Returns:

  • (Integer)

    Number of charstrings



67
68
69
# File 'lib/fontisan/type1/charstrings.rb', line 67

def count
  @charstrings.size
end

#each_charstring {|glyph_name, charstring_data| ... } ⇒ Enumerator

Iterate over all charstrings

Yields:

  • (glyph_name, charstring_data)

    Each glyph name and its charstring data

Returns:

  • (Enumerator)

    If no block given



82
83
84
85
86
# File 'lib/fontisan/type1/charstrings.rb', line 82

def each_charstring(&)
  return enum_for(:each_charstring) unless block_given?

  @charstrings.each(&)
end

#encodingHash

Get encoding map

Returns:

  • (Hash)

    Character code to glyph name mapping



74
75
76
# File 'lib/fontisan/type1/charstrings.rb', line 74

def encoding
  @encoding ||= build_standard_encoding
end

#glyph_namesArray<String>

Get list of glyph names

Returns:

  • (Array<String>)

    Glyph names



60
61
62
# File 'lib/fontisan/type1/charstrings.rb', line 60

def glyph_names
  @charstrings.keys
end

#has_glyph?(glyph_name) ⇒ Boolean

Check if glyph exists

Parameters:

  • glyph_name (String)

    Glyph name

Returns:

  • (Boolean)

    True if glyph exists



92
93
94
# File 'lib/fontisan/type1/charstrings.rb', line 92

def has_glyph?(glyph_name)
  @charstrings.key?(glyph_name)
end

#outline_for(glyph_name) ⇒ Array

Get outline for glyph by name

Parses the CharString and returns outline commands.

Parameters:

  • glyph_name (String)

    Glyph name

Returns:

  • (Array)

    Outline commands



118
119
120
121
122
123
124
# File 'lib/fontisan/type1/charstrings.rb', line 118

def outline_for(glyph_name)
  charstring = @charstrings[glyph_name]
  return nil if charstring.nil?

  parser = CharStringParser.new(@private_dict)
  parser.parse(charstring)
end

#parse(data) ⇒ CharStrings

Parse CharStrings dictionary from decrypted Type 1 font data

Parameters:

  • data (String)

    Decrypted Type 1 font data

Returns:



51
52
53
54
55
# File 'lib/fontisan/type1/charstrings.rb', line 51

def parse(data)
  extract_charstrings(data)
  decrypt_charstrings
  self
end