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



31
32
33
# File 'lib/fontisan/tables/loca_table.rb', line 31

def index_to_loc_format
  @index_to_loc_format
end

#num_glyphsObject (readonly)

Cache for context



31
32
33
# File 'lib/fontisan/tables/loca_table.rb', line 31

def num_glyphs
  @num_glyphs
end

Instance Method Details

#all_offsetsArray<Integer>

Get all offsets

Returns:

  • (Array<Integer>)

    Array of glyph offsets



130
131
132
133
134
# File 'lib/fontisan/tables/loca_table.rb', line 130

def all_offsets
  return [] unless parsed?

  parsed.offsets || []
end

#all_sizesArray<Integer>

Get all glyph sizes

Returns:

  • (Array<Integer>)

    Array of glyph sizes



139
140
141
142
143
# File 'lib/fontisan/tables/loca_table.rb', line 139

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



95
96
97
98
99
100
# File 'lib/fontisan/tables/loca_table.rb', line 95

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



148
149
150
151
152
# File 'lib/fontisan/tables/loca_table.rb', line 148

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"



123
124
125
# File 'lib/fontisan/tables/loca_table.rb', line 123

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



62
63
64
# File 'lib/fontisan/tables/loca_table.rb', line 62

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



114
115
116
117
118
# File 'lib/fontisan/tables/loca_table.rb', line 114

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



157
158
159
160
161
# File 'lib/fontisan/tables/loca_table.rb', line 157

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



71
72
73
74
75
76
# File 'lib/fontisan/tables/loca_table.rb', line 71

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



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

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



105
106
107
108
109
# File 'lib/fontisan/tables/loca_table.rb', line 105

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



83
84
85
86
87
88
# File 'lib/fontisan/tables/loca_table.rb', line 83

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



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

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