Class: Fontisan::Tables::Colr
- Inherits:
-
Binary::BaseRecord
- Object
- BinData::Record
- Binary::BaseRecord
- Fontisan::Tables::Colr
- Defined in:
- lib/fontisan/tables/colr.rb
Overview
COLR (Color) table parser
The COLR table defines layered color glyphs where each layer references a glyph ID and a palette index from the CPAL table. This enables fonts to display multi-colored glyphs such as emoji or brand logos.
COLR Table Structure: “‘ COLR Table = Header (14 bytes)
+ Base Glyph Records (6 bytes each)
+ Layer Records (4 bytes each)
“‘
Version 0 Structure:
-
version (uint16): Table version (0)
-
numBaseGlyphRecords (uint16): Number of base glyphs
-
baseGlyphRecordsOffset (uint32): Offset to base glyph records array
-
layerRecordsOffset (uint32): Offset to layer records array
-
numLayerRecords (uint16): Number of layer records
The COLR table must be used together with the CPAL (Color Palette) table which defines the actual RGB color values referenced by palette indices.
Reference: OpenType COLR specification docs.microsoft.com/en-us/typography/opentype/spec/colr
Defined Under Namespace
Classes: BaseGlyphRecord, LayerRecord
Constant Summary collapse
- TAG =
OpenType table tag for COLR
"COLR"
Instance Attribute Summary collapse
-
#base_glyph_records ⇒ Array<BaseGlyphRecord>
readonly
Parsed base glyph records.
-
#base_glyph_records_offset ⇒ Integer
readonly
Offset to base glyph records array.
-
#layer_records ⇒ Array<LayerRecord>
readonly
Parsed layer records.
-
#layer_records_offset ⇒ Integer
readonly
Offset to layer records array.
-
#num_base_glyph_records ⇒ Integer
readonly
Number of base glyph records.
-
#num_layer_records ⇒ Integer
readonly
Number of layer records.
-
#raw_data ⇒ String
readonly
Raw binary data for the entire COLR table.
-
#version ⇒ Integer
readonly
COLR version (0 for version 0).
Class Method Summary collapse
-
.read(io) ⇒ Colr
Override read to parse COLR structure.
Instance Method Summary collapse
-
#color_glyph_ids ⇒ Array<Integer>
Get all glyph IDs that have color data.
-
#has_color_glyph?(glyph_id) ⇒ Boolean
Check if COLR table has color data for a specific glyph.
-
#layers_for_glyph(glyph_id) ⇒ Array<LayerRecord>
Get color layers for a specific glyph ID.
-
#num_color_glyphs ⇒ Integer
Get the number of color glyphs in this table.
-
#parse!(data) ⇒ Object
Parse the COLR table structure.
-
#valid? ⇒ Boolean
Validate the COLR table structure.
Instance Attribute Details
#base_glyph_records ⇒ Array<BaseGlyphRecord> (readonly)
Returns Parsed base glyph records.
97 98 99 |
# File 'lib/fontisan/tables/colr.rb', line 97 def base_glyph_records @base_glyph_records end |
#base_glyph_records_offset ⇒ Integer (readonly)
Returns Offset to base glyph records array.
85 86 87 |
# File 'lib/fontisan/tables/colr.rb', line 85 def base_glyph_records_offset @base_glyph_records_offset end |
#layer_records ⇒ Array<LayerRecord> (readonly)
Returns Parsed layer records.
100 101 102 |
# File 'lib/fontisan/tables/colr.rb', line 100 def layer_records @layer_records end |
#layer_records_offset ⇒ Integer (readonly)
Returns Offset to layer records array.
88 89 90 |
# File 'lib/fontisan/tables/colr.rb', line 88 def layer_records_offset @layer_records_offset end |
#num_base_glyph_records ⇒ Integer (readonly)
Returns Number of base glyph records.
82 83 84 |
# File 'lib/fontisan/tables/colr.rb', line 82 def num_base_glyph_records @num_base_glyph_records end |
#num_layer_records ⇒ Integer (readonly)
Returns Number of layer records.
91 92 93 |
# File 'lib/fontisan/tables/colr.rb', line 91 def num_layer_records @num_layer_records end |
#raw_data ⇒ String (readonly)
Returns Raw binary data for the entire COLR table.
94 95 96 |
# File 'lib/fontisan/tables/colr.rb', line 94 def raw_data @raw_data end |
#version ⇒ Integer (readonly)
Returns COLR version (0 for version 0).
79 80 81 |
# File 'lib/fontisan/tables/colr.rb', line 79 def version @version end |
Class Method Details
.read(io) ⇒ Colr
Override read to parse COLR structure
106 107 108 109 110 111 112 113 |
# File 'lib/fontisan/tables/colr.rb', line 106 def self.read(io) colr = new return colr if io.nil? data = io.is_a?(String) ? io : io.read colr.parse!(data) colr end |
Instance Method Details
#color_glyph_ids ⇒ Array<Integer>
Get all glyph IDs that have color data
169 170 171 |
# File 'lib/fontisan/tables/colr.rb', line 169 def color_glyph_ids base_glyph_records.map(&:glyph_id) end |
#has_color_glyph?(glyph_id) ⇒ Boolean
Check if COLR table has color data for a specific glyph
162 163 164 |
# File 'lib/fontisan/tables/colr.rb', line 162 def has_color_glyph?(glyph_id) !layers_for_glyph(glyph_id).empty? end |
#layers_for_glyph(glyph_id) ⇒ Array<LayerRecord>
Get color layers for a specific glyph ID
Returns an array of LayerRecord objects for the specified glyph. Returns empty array if glyph has no color layers.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/fontisan/tables/colr.rb', line 143 def layers_for_glyph(glyph_id) # Find base glyph record for this glyph ID base_record = find_base_glyph_record(glyph_id) return [] unless base_record # Extract layers for this glyph first_index = base_record.first_layer_index num_layers = base_record.num_layers return [] if num_layers.zero? # Return slice of layer records layer_records[first_index, num_layers] || [] end |
#num_color_glyphs ⇒ Integer
Get the number of color glyphs in this table
176 177 178 |
# File 'lib/fontisan/tables/colr.rb', line 176 def num_color_glyphs num_base_glyph_records end |
#parse!(data) ⇒ Object
Parse the COLR table structure
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/fontisan/tables/colr.rb', line 119 def parse!(data) @raw_data = data io = StringIO.new(data) # Parse COLR header (14 bytes) parse_header(io) validate_header! # Parse base glyph records parse_base_glyph_records(io) # Parse layer records parse_layer_records(io) rescue StandardError => e raise CorruptedTableError, "Failed to parse COLR table: #{e.}" end |
#valid? ⇒ Boolean
Validate the COLR table structure
183 184 185 186 187 188 189 190 191 192 |
# File 'lib/fontisan/tables/colr.rb', line 183 def valid? return false if version.nil? return false if version != 0 # Only version 0 supported currently return false if num_base_glyph_records.nil? || num_base_glyph_records.negative? return false if num_layer_records.nil? || num_layer_records.negative? return false unless base_glyph_records return false unless layer_records true end |