Class: Fontisan::Tables::Cblc

Inherits:
Binary::BaseRecord show all
Defined in:
lib/fontisan/tables/cblc.rb

Overview

CBLC (Color Bitmap Location) table parser

The CBLC table contains location information for bitmap glyphs at various sizes (strikes). It works together with the CBDT table which contains the actual bitmap data.

CBLC Table Structure:

CBLC Table = Header (8 bytes)
           + BitmapSize Records (48 bytes each)

Header (8 bytes):

  • version (uint32): Table version (0x00020000 or 0x00030000)
  • numSizes (uint32): Number of BitmapSize records

Each BitmapSize record (48 bytes) contains:

  • indexSubTableArrayOffset (uint32): Offset to index subtable array
  • indexTablesSize (uint32): Size of index subtables
  • numberOfIndexSubTables (uint32): Number of index subtables
  • colorRef (uint32): Not used, set to 0
  • hori (SbitLineMetrics, 12 bytes): Horizontal line metrics
  • vert (SbitLineMetrics, 12 bytes): Vertical line metrics
  • startGlyphIndex (uint16): First glyph ID in strike
  • endGlyphIndex (uint16): Last glyph ID in strike
  • ppemX (uint8): Horizontal pixels per em
  • ppemY (uint8): Vertical pixels per em
  • bitDepth (uint8): Bit depth (1, 2, 4, 8, 32)
  • flags (int8): Flags

Reference: OpenType CBLC specification https://docs.microsoft.com/en-us/typography/opentype/spec/cblc

Examples:

Reading a CBLC table

data = font.table_data['CBLC']
cblc = Fontisan::Tables::Cblc.read(data)
strikes = cblc.strikes
puts "Font has #{strikes.length} bitmap strikes"

Defined Under Namespace

Classes: BitmapSize, SbitLineMetrics

Constant Summary collapse

TAG =

OpenType table tag for CBLC

"CBLC"
VERSION_2_0 =

Supported CBLC versions

0x00020000
VERSION_3_0 =
0x00030000

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#bitmap_sizesArray<BitmapSize> (readonly)

Returns Parsed bitmap size records.

Returns:

  • (Array<BitmapSize>)

    Parsed bitmap size records



149
150
151
# File 'lib/fontisan/tables/cblc.rb', line 149

def bitmap_sizes
  @bitmap_sizes
end

#num_sizesInteger (readonly)

Returns Number of bitmap size records.

Returns:

  • (Integer)

    Number of bitmap size records



146
147
148
# File 'lib/fontisan/tables/cblc.rb', line 146

def num_sizes
  @num_sizes
end

#raw_dataString (readonly)

Returns Raw binary data for the entire CBLC table.

Returns:

  • (String)

    Raw binary data for the entire CBLC table



152
153
154
# File 'lib/fontisan/tables/cblc.rb', line 152

def raw_data
  @raw_data
end

#versionInteger (readonly)

Returns CBLC version.

Returns:

  • (Integer)

    CBLC version



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

def version
  @version
end

Class Method Details

.read(io) ⇒ Cblc

Override read to parse CBLC structure

Parameters:

  • io (IO, String)

    Binary data to read

Returns:

  • (Cblc)

    Parsed CBLC table



158
159
160
161
162
163
164
165
# File 'lib/fontisan/tables/cblc.rb', line 158

def self.read(io)
  cblc = new
  return cblc if io.nil?

  data = io.is_a?(String) ? io : io.read
  cblc.parse!(data)
  cblc
end

Instance Method Details

#glyph_ids_with_bitmapsArray<Integer>

Get all glyph IDs that have bitmaps across all strikes

Returns:

  • (Array<Integer>)

    Array of glyph IDs



221
222
223
# File 'lib/fontisan/tables/cblc.rb', line 221

def glyph_ids_with_bitmaps
  strikes.flat_map { |strike| strike.glyph_range.to_a }.uniq.sort
end

#has_bitmap_for_glyph?(glyph_id, ppem) ⇒ Boolean

Check if glyph has bitmap at ppem size

Parameters:

  • glyph_id (Integer)

    Glyph ID

  • ppem (Integer)

    Pixels per em

Returns:

  • (Boolean)

    True if glyph has bitmap



205
206
207
208
209
# File 'lib/fontisan/tables/cblc.rb', line 205

def has_bitmap_for_glyph?(glyph_id, ppem)
  strikes_for_ppem(ppem).any? do |strike|
    strike.includes_glyph?(glyph_id)
  end
end

#num_strikesInteger

Get the number of bitmap strikes

Returns:

  • (Integer)

    Number of strikes



236
237
238
# File 'lib/fontisan/tables/cblc.rb', line 236

def num_strikes
  num_sizes || 0
end

#parse!(data) ⇒ Object

Parse the CBLC table structure

Parameters:

  • data (String)

    Binary data for the CBLC table

Raises:



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

def parse!(data)
  @raw_data = data
  io = StringIO.new(data)

  # Parse CBLC header (8 bytes)
  parse_header(io)
  validate_header!

  # Parse bitmap size records
  parse_bitmap_sizes(io)
rescue StandardError => e
  raise CorruptedTableError, "Failed to parse CBLC table: #{e.message}"
end

#ppem_sizesArray<Integer>

Get all available ppem sizes

Returns:

  • (Array<Integer>)

    Sorted array of ppem sizes



214
215
216
# File 'lib/fontisan/tables/cblc.rb', line 214

def ppem_sizes
  strikes.map(&:ppem).uniq.sort
end

#strikesArray<BitmapSize>

Get bitmap strikes (sizes)

Returns:



188
189
190
# File 'lib/fontisan/tables/cblc.rb', line 188

def strikes
  bitmap_sizes || []
end

#strikes_for_glyph(glyph_id) ⇒ Array<BitmapSize>

Get strikes that include a specific glyph ID

Parameters:

  • glyph_id (Integer)

    Glyph ID

Returns:

  • (Array<BitmapSize>)

    Strikes containing glyph



229
230
231
# File 'lib/fontisan/tables/cblc.rb', line 229

def strikes_for_glyph(glyph_id)
  strikes.select { |strike| strike.includes_glyph?(glyph_id) }
end

#strikes_for_ppem(ppem) ⇒ Array<BitmapSize>

Get strikes for specific ppem size

Parameters:

  • ppem (Integer)

    Pixels per em

Returns:



196
197
198
# File 'lib/fontisan/tables/cblc.rb', line 196

def strikes_for_ppem(ppem)
  strikes.select { |size| size.ppem == ppem }
end

#valid?Boolean

Validate the CBLC table structure

Returns:

  • (Boolean)

    True if valid



243
244
245
246
247
248
249
250
# File 'lib/fontisan/tables/cblc.rb', line 243

def valid?
  return false if version.nil?
  return false unless [VERSION_2_0, VERSION_3_0].include?(version)
  return false if num_sizes.nil? || num_sizes.negative?
  return false unless bitmap_sizes

  true
end