Class: Fontisan::Tables::Cbdt

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

Overview

CBDT (Color Bitmap Data) table parser

The CBDT table contains the actual bitmap data for color glyphs. It works together with the CBLC table which provides the location information for finding bitmaps in this table.

CBDT Table Structure:

CBDT Table = Header (8 bytes)
           + Bitmap Data (variable length)

Header (8 bytes):

  • majorVersion (uint16): Major version (2 or 3)
  • minorVersion (uint16): Minor version (0)
  • reserved (uint32): Reserved, set to 0

The bitmap data format depends on the index subtable format in CBLC. Common formats include:

  • Format 17: Small metrics, PNG data
  • Format 18: Big metrics, PNG data
  • Format 19: Metrics in CBLC, PNG data

This parser provides low-level access to bitmap data. For proper bitmap extraction, use together with CBLC table which contains the index.

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

Examples:

Reading a CBDT table

data = font.table_data['CBDT']
cbdt = Fontisan::Tables::Cbdt.read(data)
bitmap_data = cbdt.bitmap_data_at(offset, length)

Constant Summary collapse

TAG =

OpenType table tag for CBDT

"CBDT"
VERSION_2_0 =

Supported CBDT versions

0x0002_0000
VERSION_3_0 =
0x0003_0000

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#major_versionInteger (readonly)

Returns Major version (2 or 3).

Returns:

  • (Integer)

    Major version (2 or 3)



49
50
51
# File 'lib/fontisan/tables/cbdt.rb', line 49

def major_version
  @major_version
end

#minor_versionInteger (readonly)

Returns Minor version (0).

Returns:

  • (Integer)

    Minor version (0)



52
53
54
# File 'lib/fontisan/tables/cbdt.rb', line 52

def minor_version
  @minor_version
end

#raw_dataString (readonly)

Returns Raw binary data for the entire CBDT table.

Returns:

  • (String)

    Raw binary data for the entire CBDT table



55
56
57
# File 'lib/fontisan/tables/cbdt.rb', line 55

def raw_data
  @raw_data
end

Class Method Details

.read(io) ⇒ Cbdt

Override read to parse CBDT structure

Parameters:

  • io (IO, String)

    Binary data to read

Returns:

  • (Cbdt)

    Parsed CBDT table



61
62
63
64
65
66
67
68
# File 'lib/fontisan/tables/cbdt.rb', line 61

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

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

Instance Method Details

#bitmap_data_at(offset, length) ⇒ String?

Get bitmap data at specific offset and length

Used together with CBLC index to extract bitmap data.

Parameters:

  • offset (Integer)

    Offset from start of table

  • length (Integer)

    Length of bitmap data

Returns:

  • (String, nil)

    Binary bitmap data or nil



92
93
94
95
96
97
98
# File 'lib/fontisan/tables/cbdt.rb', line 92

def bitmap_data_at(offset, length)
  return nil if offset.nil? || length.nil?
  return nil if offset.negative? || length.negative?
  return nil if offset + length > raw_data.length

  raw_data[offset, length]
end

#data_sizeInteger

Get table data size

Returns:

  • (Integer)

    Size of CBDT table in bytes



112
113
114
# File 'lib/fontisan/tables/cbdt.rb', line 112

def data_size
  raw_data&.length || 0
end

#parse!(data) ⇒ Object

Parse the CBDT table structure

Parameters:

  • data (String)

    Binary data for the CBDT table

Raises:



74
75
76
77
78
79
80
81
82
83
# File 'lib/fontisan/tables/cbdt.rb', line 74

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

  # Parse CBDT header (8 bytes)
  parse_header(io)
  validate_header!
rescue StandardError => e
  raise CorruptedTableError, "Failed to parse CBDT table: #{e.message}"
end

#valid?Boolean

Validate the CBDT table structure

Returns:

  • (Boolean)

    True if valid



130
131
132
133
134
135
136
137
# File 'lib/fontisan/tables/cbdt.rb', line 130

def valid?
  return false if major_version.nil? || minor_version.nil?
  return false unless [2, 3].include?(major_version)
  return false unless minor_version.zero?
  return false unless raw_data

  true
end

#valid_offset?(offset) ⇒ Boolean

Check if offset is valid for this table

Parameters:

  • offset (Integer)

    Offset to check

Returns:

  • (Boolean)

    True if offset is within table bounds



120
121
122
123
124
125
# File 'lib/fontisan/tables/cbdt.rb', line 120

def valid_offset?(offset)
  return false if offset.nil? || offset.negative?
  return false if raw_data.nil?

  offset < raw_data.length
end

#versionInteger

Get combined version number

Returns:

  • (Integer)

    Combined version (e.g., 0x00020000 for v2.0)



103
104
105
106
107
# File 'lib/fontisan/tables/cbdt.rb', line 103

def version
  return nil if major_version.nil? || minor_version.nil?

  (major_version << 16) | minor_version
end