Class: Fontisan::Tables::LocaTable

Inherits:
SfntTable
  • Object
show all
Defined in:
lib/fontisan/tables/loca_table.rb

Overview

OOP representation of the ‘loca’ (Index to Location) table

The loca table provides offsets to glyph data in the glyf table. Each glyph has an entry indicating where its data begins in the glyf table.

This class extends SfntTable to provide loca-specific convenience methods for accessing glyph locations. The loca table requires context from the head and maxp tables to function properly.

Examples:

Accessing glyph locations

loca = font.sfnt_table("loca")
head = font.table("head")
maxp = font.table("maxp")

loca.parse_with_context(head.index_to_loc_format, maxp.num_glyphs)
offset = loca.offset_for(42)  # Get offset for glyph 42
size = loca.size_of(42)       # Get size of glyph 42
loca.empty?(32)              # Check if glyph 32 is empty

Constant Summary collapse

FORMAT_SHORT =

Short format constant

0
FORMAT_LONG =

Long format constant

1

Instance Attribute Summary collapse

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 Attribute Details

#index_to_loc_formatObject (readonly)

Cache for context



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

def index_to_loc_format
  @index_to_loc_format
end

#num_glyphsObject (readonly)

Cache for context



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

def num_glyphs
  @num_glyphs
end

Instance Method Details

#all_offsetsArray<Integer>

Get all offsets

Returns:

  • (Array<Integer>)

    Array of glyph offsets



133
134
135
136
137
# File 'lib/fontisan/tables/loca_table.rb', line 133

def all_offsets
  return [] unless parsed?

  parsed.offsets || []
end

#all_sizesArray<Integer>

Get all glyph sizes

Returns:

  • (Array<Integer>)

    Array of glyph sizes



142
143
144
145
146
# File 'lib/fontisan/tables/loca_table.rb', line 142

def all_sizes
  return [] unless has_context?

  (0...num_glyphs).map { |gid| size_of(gid) || 0 }
end

#empty?(glyph_id) ⇒ Boolean?

Check if a glyph has no outline data

Parameters:

  • glyph_id (Integer)

    Glyph ID (0-based)

Returns:

  • (Boolean, nil)

    True if empty, false if has data, nil if invalid

Raises:

  • (ArgumentError)

    if context not set



98
99
100
101
102
103
# File 'lib/fontisan/tables/loca_table.rb', line 98

def empty?(glyph_id)
  ensure_context!
  return nil unless parsed

  parsed.empty?(glyph_id)
end

#empty_glyph_idsArray<Integer>

Get empty glyph IDs

Returns:

  • (Array<Integer>)

    Array of empty glyph IDs



151
152
153
154
155
# File 'lib/fontisan/tables/loca_table.rb', line 151

def empty_glyph_ids
  return [] unless has_context?

  (0...num_glyphs).select { |gid| empty?(gid) }
end

#format_nameString

Get format name

Returns:

  • (String)

    “short” or “long”



126
127
128
# File 'lib/fontisan/tables/loca_table.rb', line 126

def format_name
  short_format? ? "short" : "long"
end

#has_context?Boolean

Check if table has been parsed with context

Returns:

  • (Boolean)

    true if context is available



65
66
67
# File 'lib/fontisan/tables/loca_table.rb', line 65

def has_context?
  !@index_to_loc_format.nil? && !@num_glyphs.nil?
end

#long_format?Boolean

Check if using long format (format 1)

Returns:

  • (Boolean)

    true if long format



117
118
119
120
121
# File 'lib/fontisan/tables/loca_table.rb', line 117

def long_format?
  return false unless parsed?

  @index_to_loc_format == FORMAT_LONG
end

#non_empty_glyph_idsArray<Integer>

Get non-empty glyph IDs

Returns:

  • (Array<Integer>)

    Array of glyph IDs with data



160
161
162
163
164
# File 'lib/fontisan/tables/loca_table.rb', line 160

def non_empty_glyph_ids
  return [] unless has_context?

  (0...num_glyphs).reject { |gid| empty?(gid) }
end

#offset_for(glyph_id) ⇒ Integer?

Get the offset for a glyph ID in the glyf table

Parameters:

  • glyph_id (Integer)

    Glyph ID (0-based)

Returns:

  • (Integer, nil)

    Byte offset in glyf table, or nil if invalid

Raises:

  • (ArgumentError)

    if context not set



74
75
76
77
78
79
# File 'lib/fontisan/tables/loca_table.rb', line 74

def offset_for(glyph_id)
  ensure_context!
  return nil unless parsed

  parsed.offset_for(glyph_id)
end

#parse_with_context(index_to_loc_format, num_glyphs) ⇒ self

Parse the loca table with required context

The loca table cannot be used without context from head and maxp tables.

Parameters:

  • index_to_loc_format (Integer)

    Format (0 = short, 1 = long) from head

  • num_glyphs (Integer)

    Total number of glyphs from maxp

Returns:

  • (self)

    Returns self for chaining

Raises:

  • (ArgumentError)

    if context is invalid



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/fontisan/tables/loca_table.rb', line 44

def parse_with_context(index_to_loc_format, num_glyphs)
  unless index_to_loc_format && num_glyphs
    raise ArgumentError,
          "loca table requires index_to_loc_format and num_glyphs"
  end

  @index_to_loc_format = index_to_loc_format
  @num_glyphs = num_glyphs

  # Ensure parsed data is loaded
  parse

  # Parse with context
  parsed.parse_with_context(index_to_loc_format, num_glyphs)

  self
end

#short_format?Boolean

Check if using short format (format 0)

Returns:

  • (Boolean)

    true if short format



108
109
110
111
112
# File 'lib/fontisan/tables/loca_table.rb', line 108

def short_format?
  return false unless parsed?

  @index_to_loc_format == FORMAT_SHORT
end

#size_of(glyph_id) ⇒ Integer?

Calculate the size of glyph data for a glyph ID

Parameters:

  • glyph_id (Integer)

    Glyph ID (0-based)

Returns:

  • (Integer, nil)

    Size in bytes, or nil if invalid

Raises:

  • (ArgumentError)

    if context not set



86
87
88
89
90
91
# File 'lib/fontisan/tables/loca_table.rb', line 86

def size_of(glyph_id)
  ensure_context!
  return nil unless parsed

  parsed.size_of(glyph_id)
end

#statisticsHash

Get statistics about glyph locations

Returns:

  • (Hash)

    Statistics about loca table



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

def statistics
  return {} unless has_context?

  sizes = all_sizes
  offsets = all_offsets

  {
    num_glyphs: num_glyphs,
    format: format_name,
    empty_glyph_count: empty_glyph_ids.length,
    non_empty_glyph_count: non_empty_glyph_ids.length,
    min_size: sizes.compact.min,
    max_size: sizes.compact.max,
    total_data_size: sizes.sum,
    glyf_table_size: offsets.last || 0,
  }
end