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 https://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.
96 97 98 |
# File 'lib/fontisan/tables/colr.rb', line 96 def base_glyph_records @base_glyph_records end |
#base_glyph_records_offset ⇒ Integer (readonly)
Returns Offset to base glyph records array.
84 85 86 |
# File 'lib/fontisan/tables/colr.rb', line 84 def base_glyph_records_offset @base_glyph_records_offset end |
#layer_records ⇒ Array<LayerRecord> (readonly)
Returns Parsed layer records.
99 100 101 |
# File 'lib/fontisan/tables/colr.rb', line 99 def layer_records @layer_records end |
#layer_records_offset ⇒ Integer (readonly)
Returns Offset to layer records array.
87 88 89 |
# File 'lib/fontisan/tables/colr.rb', line 87 def layer_records_offset @layer_records_offset end |
#num_base_glyph_records ⇒ Integer (readonly)
Returns Number of base glyph records.
81 82 83 |
# File 'lib/fontisan/tables/colr.rb', line 81 def num_base_glyph_records @num_base_glyph_records end |
#num_layer_records ⇒ Integer (readonly)
Returns Number of layer records.
90 91 92 |
# File 'lib/fontisan/tables/colr.rb', line 90 def num_layer_records @num_layer_records end |
#raw_data ⇒ String (readonly)
Returns Raw binary data for the entire COLR table.
93 94 95 |
# File 'lib/fontisan/tables/colr.rb', line 93 def raw_data @raw_data end |
#version ⇒ Integer (readonly)
Returns COLR version (0 for version 0).
78 79 80 |
# File 'lib/fontisan/tables/colr.rb', line 78 def version @version end |
Class Method Details
.read(io) ⇒ Colr
Override read to parse COLR structure
105 106 107 108 109 110 111 112 |
# File 'lib/fontisan/tables/colr.rb', line 105 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
168 169 170 |
# File 'lib/fontisan/tables/colr.rb', line 168 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
161 162 163 |
# File 'lib/fontisan/tables/colr.rb', line 161 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.
142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/fontisan/tables/colr.rb', line 142 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
175 176 177 |
# File 'lib/fontisan/tables/colr.rb', line 175 def num_color_glyphs num_base_glyph_records end |
#parse!(data) ⇒ Object
Parse the COLR table structure
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/fontisan/tables/colr.rb', line 118 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
182 183 184 185 186 187 188 189 190 191 |
# File 'lib/fontisan/tables/colr.rb', line 182 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 |