1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
# frozen_string_literal: true
require_relative '../table'
module TTFunk
class Table
# Horizontal Header (`hhea`) table.
class Hhea < Table
# Table version
# @return [Integer]
attr_reader :version
# Typographic ascent.
# @return [Integer]
attr_reader :ascent
# Typographic descent.
# @return [Integer]
attr_reader :descent
# Typographic line gap.
# @return [Integer]
attr_reader :line_gap
# Maximum advance width value in `hmtx` table.
# @return [Integer]
attr_reader :advance_width_max
# Minimum left sidebearing value in `hmtx` table for glyphs with contours
# (empty glyphs should be ignored).
# @return [Integer]
attr_reader :min_left_side_bearing
# Minimum right sidebearing value.
# @return [Integer]
attr_reader :min_right_side_bearing
# Maximum extent.
# @return [Integer]
attr_reader :x_max_extent
# Caret slope rise.
# @return [Integer]
attr_reader :caret_slope_rise
# @deprecated Use {caret_slope_rise} instead.
# @!parse attr_reader :carot_slope_rise
# @return [Integer]
def carot_slope_rise
@caret_slope_rise
end
# Caret slope run.
# @return [Integer]
attr_reader :caret_slope_run
# @deprecated Use {caret_slope_run} instead.
# @!parse attr_reader :carot_slope_run
# @return [Integer]
def carot_slope_run
@caret_slope_run
end
# Caret offset.
# @return [Integer]
attr_reader :caret_offset
# Metric data format. `0` for current format.
# @return [Integer]
attr_reader :metric_data_format
# Number of hMetric entries in `hmtx` table.
# @return [Integer]
attr_reader :number_of_metrics
class << self
# Encode table.
#
# @param hhea [TTFunk::Table::Hhea] table to encode.
# @param hmtx [TTFunk::Table::Hmtx]
# @param original [TTFunk::File] original font file.
# @param mapping [Hash{Integer => Integer}] keys are new glyph IDs, values
# are old glyph IDs
# @return [String]
def encode(hhea, hmtx, original, mapping)
''.b.tap do |table|
table << [hhea.version].pack('N')
table << [
hhea.ascent, hhea.descent, hhea.line_gap,
*min_max_values_for(original, mapping),
hhea.caret_slope_rise, hhea.caret_slope_run, hhea.caret_offset,
0, 0, 0, 0, hhea.metric_data_format, hmtx[:number_of_metrics],
].pack('n*')
end
end
private
def min_max_values_for(original, mapping)
min_lsb = Min.new
min_rsb = Min.new
max_aw = Max.new
max_extent = Max.new
mapping.each_value do |old_glyph_id|
horiz_metrics = original.horizontal_metrics.for(old_glyph_id)
next unless horiz_metrics
min_lsb << horiz_metrics.left_side_bearing
max_aw << horiz_metrics.advance_width
glyph = original.find_glyph(old_glyph_id)
next unless glyph
x_delta = glyph.x_max - glyph.x_min
min_rsb << (horiz_metrics.advance_width - horiz_metrics.left_side_bearing - x_delta)
max_extent << (horiz_metrics.left_side_bearing + x_delta)
end
[
max_aw.value_or(0), min_lsb.value_or(0),
min_rsb.value_or(0), max_extent.value_or(0),
]
end
end
private
def parse!
@version = read(4, 'N').first
@ascent, @descent, @line_gap = read_signed(3)
@advance_width_max = read(2, 'n').first
@min_left_side_bearing, @min_right_side_bearing, @x_max_extent,
@caret_slope_rise, @caret_slope_run, @caret_offset,
_reserved, _reserved, _reserved, _reserved,
@metric_data_format = read_signed(11)
@number_of_metrics = read(2, 'n').first
end
end
end
end
|