Class: Fontisan::Subset::TableStrategy::GlyfLocaBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/subset/table_strategy/glyf_loca_builder.rb

Overview

Glyf + Loca are emitted together because loca is just an offset index into glyf. This builder walks the subset's glyph mapping, extracts each glyph's bytes (remapping composite component refs), and produces the new glyf bytes, the new loca offsets, and the union bounding box over the subset's glyphs.

Extracted as a collaborator so both the Glyf and Loca strategies can share a single build pass without coupling to each other or to TableSubsetter internals.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(font:, mapping:) ⇒ GlyfLocaBuilder

Returns a new instance of GlyfLocaBuilder.

Parameters:



18
19
20
21
# File 'lib/fontisan/subset/table_strategy/glyf_loca_builder.rb', line 18

def initialize(font:, mapping:)
  @font = font
  @mapping = mapping
end

Instance Attribute Details

#bboxArray(Integer, Integer, Integer, Integer)? (readonly)

Returns union bbox as [x_min, y_min, x_max, y_max], or nil if all glyphs empty.

Returns:

  • (Array(Integer, Integer, Integer, Integer), nil)

    union bbox as [x_min, y_min, x_max, y_max], or nil if all glyphs empty



31
32
33
# File 'lib/fontisan/subset/table_strategy/glyf_loca_builder.rb', line 31

def bbox
  @bbox
end

#glyf_dataString (readonly)

Returns new glyf bytes.

Returns:

  • (String)

    new glyf bytes



24
25
26
# File 'lib/fontisan/subset/table_strategy/glyf_loca_builder.rb', line 24

def glyf_data
  @glyf_data
end

#loca_offsetsArray<Integer> (readonly)

Returns loca offsets (one per glyph + 1).

Returns:

  • (Array<Integer>)

    loca offsets (one per glyph + 1)



27
28
29
# File 'lib/fontisan/subset/table_strategy/glyf_loca_builder.rb', line 27

def loca_offsets
  @loca_offsets
end

Instance Method Details

#buildself

Build glyf + loca + bbox. Idempotent — re-calling is a no-op.

Returns:

  • (self)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/fontisan/subset/table_strategy/glyf_loca_builder.rb', line 36

def build
  return self if @glyf_data

  glyf = @font.table("glyf")
  loca = @font.table("loca")
  head = @font.table("head")

  ensure_loca_parsed!(loca, head)

  @glyf_data = String.new(encoding: Encoding::BINARY)
  @loca_offsets = []
  current_offset = 0

  bbox_x_min = 1 << 30
  bbox_y_min = 1 << 30
  bbox_x_max = -(1 << 30)
  bbox_y_max = -(1 << 30)

  @mapping.old_ids.each do |old_id|
    @loca_offsets << current_offset

    offset = loca.offset_for(old_id)
    size = loca.size_of(old_id)
    next if size.nil? || size.zero?

    glyph_data = glyf.raw_data[offset, size]

    if glyph_data.bytesize >= 10
      _n, gx_min, gy_min, gx_max, gy_max = glyph_data[0,
                                                      10].unpack("n5")
      gx_min = to_signed_16(gx_min)
      gy_min = to_signed_16(gy_min)
      gx_max = to_signed_16(gx_max)
      gy_max = to_signed_16(gy_max)
      bbox_x_min = gx_min if gx_min < bbox_x_min
      bbox_y_min = gy_min if gy_min < bbox_y_min
      bbox_x_max = gx_max if gx_max > bbox_x_max
      bbox_y_max = gy_max if gy_max > bbox_y_max
    end

    glyph_data = remap_compound!(glyph_data) if compound?(glyph_data)

    @glyf_data << glyph_data
    current_offset += glyph_data.bytesize
  end

  @loca_offsets << current_offset

  return if bbox_x_min > bbox_x_max

  @bbox = [bbox_x_min, bbox_y_min, bbox_x_max, bbox_y_max]
  self
end