Class: Fontisan::Tables::Head
- Inherits:
-
Binary::BaseRecord
- Object
- BinData::Record
- Binary::BaseRecord
- Fontisan::Tables::Head
- Defined in:
- lib/fontisan/tables/head.rb
Overview
BinData structure for the 'head' (Font Header) table
The head table contains global information about the font, including metadata about the font file, bounding box, and indexing information.
Reference: OpenType specification, head table
Constant Summary collapse
- MAGIC_NUMBER =
Magic number that must be present in the head table
0x5F0F3CF5- FLAG_LOSSLESS_MODIFYING =
Bit flags for the
flagsfield (uint16), per OpenType spec. Only bits we currently reference are named here; see the OpenTypeheadtable specification for the full list.Bit 11 indicates the font data has been losslessly modified (e.g. by subsetting or WOFF2 encoding). Per WOFF2 spec section 5, encoders MUST set this bit. Chrome's OpenType Sanitizer (OTS) rejects WOFF2 files where it is not set.
0x0800- MAC_EPOCH_OFFSET =
Difference between 1904-01-01 00:00:00 UTC (Mac epoch, used by LONGDATETIME fields) and 1970-01-01 00:00:00 UTC (Unix epoch). Single source of truth for converting between the two — head's created/modified fields are LONGDATETIME.
2_082_844_800
Class Method Summary collapse
-
.longdatetime_to_time(seconds) ⇒ Time
Convert LONGDATETIME to Ruby Time.
-
.now_longdatetime ⇒ Integer
Current wall clock time as a LONGDATETIME integer (seconds since Mac epoch).
-
.to_longdatetime(time = Time.now) ⇒ Integer
Convert a Unix-epoch
Time(or Integer seconds) to a LONGDATETIME integer (Mac-epoch seconds).
Instance Method Summary collapse
-
#created ⇒ Time
Convert created timestamp to Time object.
-
#font_revision ⇒ Float
Convert font revision from fixed-point to float.
-
#modified ⇒ Time
Convert modified timestamp to Time object.
-
#valid? ⇒ Boolean
Validate that the magic number is correct.
-
#valid_bounding_box? ⇒ Boolean
Validation helper: Check if bounding box is valid.
-
#valid_glyph_data_format? ⇒ Boolean
Validation helper: Check if glyph_data_format is valid.
-
#valid_index_to_loc_format? ⇒ Boolean
Validation helper: Check if index_to_loc_format is valid.
-
#valid_magic? ⇒ Boolean
Validation helper: Check if magic number is valid.
-
#valid_units_per_em? ⇒ Boolean
Validation helper: Check if units per em is valid.
-
#valid_version? ⇒ Boolean
Validation helper: Check if version is valid.
-
#validate_magic_number! ⇒ Object
(also: #validate!)
Validate magic number and raise error if invalid.
-
#version ⇒ Float
Convert version from fixed-point to float.
Methods inherited from Binary::BaseRecord
Class Method Details
.longdatetime_to_time(seconds) ⇒ Time
Convert LONGDATETIME to Ruby Time
200 201 202 |
# File 'lib/fontisan/tables/head.rb', line 200 def self.longdatetime_to_time(seconds) Time.at(seconds - MAC_EPOCH_OFFSET) end |
.now_longdatetime ⇒ Integer
Current wall clock time as a LONGDATETIME integer (seconds since
Mac epoch). Used wherever a created/modified timestamp needs
to be set to a meaningful "now" value (WOFF2 encoder, Type 1
converter, UFO compile fallback).
165 166 167 |
# File 'lib/fontisan/tables/head.rb', line 165 def self.now_longdatetime to_longdatetime(Time.now) end |
.to_longdatetime(time = Time.now) ⇒ Integer
Convert a Unix-epoch Time (or Integer seconds) to a LONGDATETIME
integer (Mac-epoch seconds). Symmetric with #longdatetime_to_time
— pair them whenever you convert across the epoch boundary.
175 176 177 |
# File 'lib/fontisan/tables/head.rb', line 175 def self.to_longdatetime(time = Time.now) time.to_i + MAC_EPOCH_OFFSET end |
Instance Method Details
#created ⇒ Time
Convert created timestamp to Time object
81 82 83 |
# File 'lib/fontisan/tables/head.rb', line 81 def created self.class.longdatetime_to_time(created_raw) end |
#font_revision ⇒ Float
Convert font revision from fixed-point to float
74 75 76 |
# File 'lib/fontisan/tables/head.rb', line 74 def font_revision fixed_to_float(font_revision_raw) end |
#modified ⇒ Time
Convert modified timestamp to Time object
88 89 90 |
# File 'lib/fontisan/tables/head.rb', line 88 def modified self.class.longdatetime_to_time(modified_raw) end |
#valid? ⇒ Boolean
Validate that the magic number is correct
95 96 97 |
# File 'lib/fontisan/tables/head.rb', line 95 def valid? magic_number == MAGIC_NUMBER end |
#valid_bounding_box? ⇒ Boolean
Validation helper: Check if bounding box is valid
The bounding box should have xMin < xMax and yMin < yMax
137 138 139 |
# File 'lib/fontisan/tables/head.rb', line 137 def valid_bounding_box? x_min < x_max && y_min < y_max end |
#valid_glyph_data_format? ⇒ Boolean
Validation helper: Check if glyph_data_format is valid
Must be 0 for current format
155 156 157 |
# File 'lib/fontisan/tables/head.rb', line 155 def valid_glyph_data_format? glyph_data_format.zero? end |
#valid_index_to_loc_format? ⇒ Boolean
Validation helper: Check if index_to_loc_format is valid
Must be 0 (short) or 1 (long)
146 147 148 |
# File 'lib/fontisan/tables/head.rb', line 146 def valid_index_to_loc_format? [0, 1].include?(index_to_loc_format) end |
#valid_magic? ⇒ Boolean
Validation helper: Check if magic number is valid
102 103 104 |
# File 'lib/fontisan/tables/head.rb', line 102 def valid_magic? magic_number == MAGIC_NUMBER end |
#valid_units_per_em? ⇒ Boolean
Validation helper: Check if units per em is valid
Units per em should be a power of 2 between 16 and 16384
120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/fontisan/tables/head.rb', line 120 def valid_units_per_em? return false if units_per_em.nil? || units_per_em.zero? # Must be between 16 and 16384 return false unless units_per_em.between?(16, 16384) # Should be a power of 2 (recommended but not required) # Common values: 1000, 1024, 2048 # We'll allow any value in range for flexibility true end |
#valid_version? ⇒ Boolean
Validation helper: Check if version is valid
OpenType spec requires version to be 1.0
111 112 113 |
# File 'lib/fontisan/tables/head.rb', line 111 def valid_version? version_raw == 0x00010000 # Version 1.0 end |
#validate_magic_number! ⇒ Object Also known as: validate!
Validate magic number and raise error if invalid
182 183 184 185 186 187 188 189 190 191 |
# File 'lib/fontisan/tables/head.rb', line 182 def validate_magic_number! return if valid? = "Invalid magic number in head table: " \ "expected 0x#{MAGIC_NUMBER.to_s(16).upcase}, " \ "got 0x#{magic_number.to_s(16).upcase}" error = Fontisan::CorruptedTableError.new() error.set_backtrace(caller) Kernel.raise(error) end |
#version ⇒ Float
Convert version from fixed-point to float
67 68 69 |
# File 'lib/fontisan/tables/head.rb', line 67 def version fixed_to_float(version_raw) end |