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



64
65
66
# File 'lib/fontisan/tables/cmap_table.rb', line 64

def character_codes
  unicode_mappings.keys.sort
end

#character_countInteger

Get the number of mapped characters

Returns:

  • (Integer)

    Number of unique character mappings



57
58
59
# File 'lib/fontisan/tables/cmap_table.rb', line 57

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



33
34
35
36
# File 'lib/fontisan/tables/cmap_table.rb', line 33

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



71
72
73
# File 'lib/fontisan/tables/cmap_table.rb', line 71

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



140
141
142
# File 'lib/fontisan/tables/cmap_table.rb', line 140

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



132
133
134
# File 'lib/fontisan/tables/cmap_table.rb', line 132

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



104
105
106
107
108
109
110
# File 'lib/fontisan/tables/cmap_table.rb', line 104

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



122
123
124
125
126
# File 'lib/fontisan/tables/cmap_table.rb', line 122

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



78
79
80
81
82
# File 'lib/fontisan/tables/cmap_table.rb', line 78

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



115
116
117
# File 'lib/fontisan/tables/cmap_table.rb', line 115

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



163
164
165
166
# File 'lib/fontisan/tables/cmap_table.rb', line 163

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



42
43
44
# File 'lib/fontisan/tables/cmap_table.rb', line 42

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



50
51
52
# File 'lib/fontisan/tables/cmap_table.rb', line 50

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



88
89
90
91
92
# File 'lib/fontisan/tables/cmap_table.rb', line 88

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



97
98
99
# File 'lib/fontisan/tables/cmap_table.rb', line 97

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



147
148
149
150
# File 'lib/fontisan/tables/cmap_table.rb', line 147

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



155
156
157
158
# File 'lib/fontisan/tables/cmap_table.rb', line 155

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

#statisticsHash

Get mapping statistics

Returns:

  • (Hash)

    Statistics about the character mapping



171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/fontisan/tables/cmap_table.rb', line 171

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



23
24
25
26
27
# File 'lib/fontisan/tables/cmap_table.rb', line 23

def unicode_mappings
  return {} unless parsed

  parsed.unicode_mappings || {}
end