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 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
# frozen_string_literal: true
require_relative '../table'
module TTFunk
class Table
# Font Header (`head`) Table.
class Head < TTFunk::Table
# Table version.
# @return [Integer]
attr_reader :version
# Font revision.
# @return [Integer]
attr_reader :font_revision
# Checksum adjustment.
# @return [Integer]
attr_reader :checksum_adjustment
# Magic number.
# @return [Integer] must be `0x5F0F3CF5`
attr_reader :magic_number
# Flags.
# @return [Integer]
attr_reader :flags
# Units per Em.
# @return [Integer]
attr_reader :units_per_em
# Font creation time.
# @return [Integer] Long Date Time timestamp.
attr_reader :created
# Font modification time.
# @return [Integer] Long Date Time timestamp.
attr_reader :modified
# Minimum x coordinate across all glyph bounding boxes.
# @return [Integer]
attr_reader :x_min
# Minimum y coordinate across all glyph bounding boxes.
# @return [Integer]
attr_reader :y_min
# Maximum x coordinate across all glyph bounding boxes.
# @return [Integer]
attr_reader :x_max
# Maximum y coordinate across all glyph bounding boxes.
# @return [Integer]
attr_reader :y_max
# Mac font style.
# @return [Integer]
attr_reader :mac_style
# Smallest readable size in pixels.
# @return [Integer]
attr_reader :lowest_rec_ppem
# Font direction hint. Deprecated, set to 2.
# @return [Integer]
attr_reader :font_direction_hint
# Index to Location format.
# @return [Integer]
attr_reader :index_to_loc_format
# Glyph data format.
# @return [Integer]
attr_reader :glyph_data_format
class << self
# Long date time (used in TTF headers).
# January 1, 1904 00:00:00 UTC basis used by Long date time.
# @see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html
# TrueType Font Tables
LONG_DATE_TIME_BASIS = Time.new(1904, 1, 1, 0, 0, 0, 0).to_i
private_constant :LONG_DATE_TIME_BASIS
# Encode table.
#
# @param head [TTFunk::Table::Head]
# @param loca [Hash] result of encoding Index to Location (`loca`) table
# @param mapping [Hash{Integer => Integer}] keys are new glyph IDs, values
# are old glyph IDs
# @return [EncodedString]
def encode(head, loca, mapping)
EncodedString.new do |table|
table <<
[head.version, head.font_revision].pack('N2') <<
Placeholder.new(:checksum, length: 4) <<
[
head.magic_number,
head.flags, head.units_per_em,
head.created, head.modified,
*min_max_values_for(head, mapping),
head.mac_style, head.lowest_rec_ppem, head.font_direction_hint,
loca[:type] || 0, head.glyph_data_format,
].pack('Nn2q>2n*')
end
end
# Convert Long Date Time timestamp to Time.
# @param ldt [Float, Integer]
# @return [Time]
def from_long_date_time(ldt)
Time.at(ldt + LONG_DATE_TIME_BASIS, in: 'UTC')
end
# Convert Time to Long Date Time timestamp
# @param time [Time]
# @return [Integer]
def to_long_date_time(time)
Integer(time) - LONG_DATE_TIME_BASIS
end
private
def min_max_values_for(head, mapping)
x_min = Min.new
x_max = Max.new
y_min = Min.new
y_max = Max.new
mapping.each_value do |old_glyph_id|
glyph = head.file.find_glyph(old_glyph_id)
next unless glyph
x_min << glyph.x_min
x_max << glyph.x_max
y_min << glyph.y_min
y_max << glyph.y_max
end
[
x_min.value_or(0), y_min.value_or(0),
x_max.value_or(0), y_max.value_or(0),
]
end
end
private
def parse!
@version, @font_revision, @check_sum_adjustment, @magic_number,
@flags, @units_per_em, @created, @modified = read(36, 'N4n2q>2')
@x_min, @y_min, @x_max, @y_max = read_signed(4)
@mac_style, @lowest_rec_ppem, @font_direction_hint,
@index_to_loc_format, @glyph_data_format = read(10, 'n*')
end
end
end
end
|