Class: Fontisan::Tables::CmapTable

Inherits:
SfntTable
  • Object
show all
Defined in:
lib/fontisan/tables/cmap_table.rb

Overview

OOP representation of the ‘cmap’ (Character to Glyph Index Mapping) table

The cmap table maps character codes to glyph indices, supporting multiple encoding formats for different character sets and Unicode planes.

This class extends SfntTable to provide cmap-specific validation and convenience methods for character-to-glyph mapping.

Examples:

Mapping characters to glyphs

cmap = font.sfnt_table("cmap")
cmap.glyph_for('A')        # => 36
cmap.glyph_for(0x0041)     # => 36 (same as 'A')
cmap.has_glyph?('')       # => true
cmap.character_count       # => 1234

Instance Attribute Summary

Attributes inherited from SfntTable

#data, #entry, #font, #parsed

Instance Method Summary collapse

Methods inherited from SfntTable

#available?, #calculate_checksum, #checksum, #data_loaded?, #human_name, #initialize, #inspect, #length, #load_data!, #offset, #parse, #parsed?, #required?, #tag, #to_s, #validate!

Constructor Details

This class inherits a constructor from Fontisan::SfntTable

Instance Method Details

#character_codesArray<Integer>

Get all mapped character codes

Returns:

  • (Array<Integer>)

    Array of Unicode codepoints



67
68
69
# File 'lib/fontisan/tables/cmap_table.rb', line 67

def character_codes
  unicode_mappings.keys.sort
end

#character_countInteger

Get the number of mapped characters

Returns:

  • (Integer)

    Number of unique character mappings



60
61
62
# File 'lib/fontisan/tables/cmap_table.rb', line 60

def character_count
  unicode_mappings.size
end

#glyph_for(char) ⇒ Integer?

Get glyph ID for a character

Parameters:

  • char (String, Integer)

    Character (string or Unicode codepoint)

Returns:

  • (Integer, nil)

    Glyph ID, or nil if character not mapped



36
37
38
39
# File 'lib/fontisan/tables/cmap_table.rb', line 36

def glyph_for(char)
  codepoint = char.is_a?(String) ? char.ord : char
  unicode_mappings[codepoint]
end

#glyph_idsArray<Integer>

Get all mapped glyphs

Returns:

  • (Array<Integer>)

    Array of glyph IDs



74
75
76
# File 'lib/fontisan/tables/cmap_table.rb', line 74

def glyph_ids
  unicode_mappings.values.uniq.sort
end

#glyph_sequence_for(text) ⇒ Array<Integer>

Create a simple text rendering glyph sequence

Parameters:

  • text (String)

    Text string

Returns:

  • (Array<Integer>)

    Array of glyph IDs for rendering



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

def glyph_sequence_for(text)
  glyphs_for_text(text)
end

#glyphs_for_text(text) ⇒ Array<Integer>

Get glyph IDs for a string of characters

Parameters:

  • text (String)

    Text string

Returns:

  • (Array<Integer>)

    Array of glyph IDs



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

def glyphs_for_text(text)
  text.chars.map { |char| glyph_for(char) || 0 }
end

#has_basic_latin?Boolean

Check if common Latin characters are mapped

Returns:

  • (Boolean)

    true if A-Z, a-z are mapped



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

def has_basic_latin?
  # Check uppercase A-Z
  return false unless has_glyphs?(*(0x0041..0x005A).to_a)

  # Check lowercase a-z
  has_glyphs?(*(0x0061..0x007A).to_a)
end

#has_basic_punctuation?Boolean

Check if common punctuation is mapped

Returns:

  • (Boolean)

    true if common punctuation marks are mapped



125
126
127
128
129
# File 'lib/fontisan/tables/cmap_table.rb', line 125

def has_basic_punctuation?
  required = [0x0020, 0x0021, 0x0022, 0x0027, 0x0028, 0x0029, 0x002C, 0x002E,
              0x003A, 0x003B, 0x003F, 0x005F] # space !"()',.:;?_
  has_required_characters?(*required)
end

#has_bmp_coverage?Boolean

Check if BMP (Basic Multilingual Plane) coverage exists

Returns:

  • (Boolean)

    true if BMP characters (U+0000-U+FFFF) are mapped



81
82
83
84
85
# File 'lib/fontisan/tables/cmap_table.rb', line 81

def has_bmp_coverage?
  return false unless parsed

  parsed.has_bmp_coverage?
end

#has_digits?Boolean

Check if digits are mapped

Returns:

  • (Boolean)

    true if 0-9 are mapped



118
119
120
# File 'lib/fontisan/tables/cmap_table.rb', line 118

def has_digits?
  has_glyphs?(*(0x0030..0x0039).to_a)
end

#has_full_unicode?Boolean

Check if font has full Unicode coverage

Returns:

  • (Boolean)

    true if characters beyond BMP are mapped



166
167
168
169
# File 'lib/fontisan/tables/cmap_table.rb', line 166

def has_full_unicode?
  max_cp = max_codepoint
  !max_cp.nil? && max_cp > 0xFFFF
end

#has_glyph?(char) ⇒ Boolean

Check if a character has a glyph mapping

Parameters:

  • char (String, Integer)

    Character (string or Unicode codepoint)

Returns:

  • (Boolean)

    true if character is mapped to a glyph



45
46
47
# File 'lib/fontisan/tables/cmap_table.rb', line 45

def has_glyph?(char)
  !glyph_for(char).nil?
end

#has_glyphs?(*chars) ⇒ Boolean

Check if multiple characters have glyph mappings

Parameters:

  • chars (Array<String, Integer>)

    Characters to check

Returns:

  • (Boolean)

    true if all characters are mapped



53
54
55
# File 'lib/fontisan/tables/cmap_table.rb', line 53

def has_glyphs?(*chars)
  chars.all? { |char| has_glyph?(char) }
end

#has_required_characters?(*chars) ⇒ Boolean

Check if specific required characters are mapped

Parameters:

  • chars (Array<Integer>)

    Unicode codepoints that must be present

Returns:

  • (Boolean)

    true if all required characters are mapped



91
92
93
94
95
# File 'lib/fontisan/tables/cmap_table.rb', line 91

def has_required_characters?(*chars)
  return false unless parsed

  parsed.has_required_characters?(*chars)
end

#has_space?Boolean

Check if space character is mapped

Returns:

  • (Boolean)

    true if U+0020 (space) is mapped



100
101
102
# File 'lib/fontisan/tables/cmap_table.rb', line 100

def has_space?
  has_glyph?(0x0020)
end

#max_codepointInteger?

Get the highest Unicode codepoint mapped

Returns:

  • (Integer, nil)

    Maximum codepoint, or nil if no mappings



150
151
152
153
# File 'lib/fontisan/tables/cmap_table.rb', line 150

def max_codepoint
  codes = character_codes
  codes.last unless codes.empty?
end

#min_codepointInteger?

Get the lowest Unicode codepoint mapped

Returns:

  • (Integer, nil)

    Minimum codepoint, or nil if no mappings



158
159
160
161
# File 'lib/fontisan/tables/cmap_table.rb', line 158

def min_codepoint
  codes = character_codes
  codes.first unless codes.empty?
end

#statisticsHash

Get mapping statistics

Returns:

  • (Hash)

    Statistics about the character mapping



174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/fontisan/tables/cmap_table.rb', line 174

def statistics
  {
    character_count: character_count,
    glyph_count: glyph_ids.size,
    min_codepoint: min_codepoint,
    max_codepoint: max_codepoint,
    has_bmp: has_bmp_coverage?,
    has_full_unicode: has_full_unicode?,
    has_space: has_space?,
    has_basic_latin: has_basic_latin?,
    has_digits: has_digits?,
  }
end

#unicode_mappingsHash<Integer, Integer>

Get Unicode character to glyph index mappings

Returns:

  • (Hash<Integer, Integer>)

    Mapping from Unicode codepoints to glyph IDs



26
27
28
29
30
# File 'lib/fontisan/tables/cmap_table.rb', line 26

def unicode_mappings
  return {} unless parsed

  parsed.unicode_mappings || {}
end