fontisan 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +529 -65
  3. data/Gemfile +1 -0
  4. data/LICENSE +5 -1
  5. data/README.adoc +1301 -275
  6. data/Rakefile +27 -2
  7. data/benchmark/variation_quick_bench.rb +47 -0
  8. data/docs/EXTRACT_TTC_MIGRATION.md +549 -0
  9. data/fontisan.gemspec +4 -1
  10. data/lib/fontisan/binary/base_record.rb +22 -1
  11. data/lib/fontisan/cli.rb +309 -0
  12. data/lib/fontisan/collection/builder.rb +260 -0
  13. data/lib/fontisan/collection/offset_calculator.rb +227 -0
  14. data/lib/fontisan/collection/table_analyzer.rb +204 -0
  15. data/lib/fontisan/collection/table_deduplicator.rb +241 -0
  16. data/lib/fontisan/collection/writer.rb +306 -0
  17. data/lib/fontisan/commands/base_command.rb +8 -1
  18. data/lib/fontisan/commands/convert_command.rb +291 -0
  19. data/lib/fontisan/commands/export_command.rb +161 -0
  20. data/lib/fontisan/commands/info_command.rb +40 -6
  21. data/lib/fontisan/commands/instance_command.rb +295 -0
  22. data/lib/fontisan/commands/ls_command.rb +113 -0
  23. data/lib/fontisan/commands/pack_command.rb +241 -0
  24. data/lib/fontisan/commands/subset_command.rb +245 -0
  25. data/lib/fontisan/commands/unpack_command.rb +338 -0
  26. data/lib/fontisan/commands/validate_command.rb +178 -0
  27. data/lib/fontisan/commands/variable_command.rb +30 -1
  28. data/lib/fontisan/config/collection_settings.yml +56 -0
  29. data/lib/fontisan/config/conversion_matrix.yml +212 -0
  30. data/lib/fontisan/config/export_settings.yml +66 -0
  31. data/lib/fontisan/config/subset_profiles.yml +100 -0
  32. data/lib/fontisan/config/svg_settings.yml +60 -0
  33. data/lib/fontisan/config/validation_rules.yml +149 -0
  34. data/lib/fontisan/config/variable_settings.yml +99 -0
  35. data/lib/fontisan/config/woff2_settings.yml +77 -0
  36. data/lib/fontisan/constants.rb +69 -0
  37. data/lib/fontisan/converters/conversion_strategy.rb +96 -0
  38. data/lib/fontisan/converters/format_converter.rb +259 -0
  39. data/lib/fontisan/converters/outline_converter.rb +936 -0
  40. data/lib/fontisan/converters/svg_generator.rb +244 -0
  41. data/lib/fontisan/converters/table_copier.rb +117 -0
  42. data/lib/fontisan/converters/woff2_encoder.rb +416 -0
  43. data/lib/fontisan/converters/woff_writer.rb +391 -0
  44. data/lib/fontisan/error.rb +203 -0
  45. data/lib/fontisan/export/exporter.rb +262 -0
  46. data/lib/fontisan/export/table_serializer.rb +255 -0
  47. data/lib/fontisan/export/transformers/font_to_ttx.rb +172 -0
  48. data/lib/fontisan/export/transformers/head_transformer.rb +96 -0
  49. data/lib/fontisan/export/transformers/hhea_transformer.rb +59 -0
  50. data/lib/fontisan/export/transformers/maxp_transformer.rb +63 -0
  51. data/lib/fontisan/export/transformers/name_transformer.rb +63 -0
  52. data/lib/fontisan/export/transformers/os2_transformer.rb +121 -0
  53. data/lib/fontisan/export/transformers/post_transformer.rb +51 -0
  54. data/lib/fontisan/export/ttx_generator.rb +527 -0
  55. data/lib/fontisan/export/ttx_parser.rb +300 -0
  56. data/lib/fontisan/font_loader.rb +121 -12
  57. data/lib/fontisan/font_writer.rb +301 -0
  58. data/lib/fontisan/formatters/text_formatter.rb +102 -0
  59. data/lib/fontisan/glyph_accessor.rb +503 -0
  60. data/lib/fontisan/hints/hint_converter.rb +177 -0
  61. data/lib/fontisan/hints/postscript_hint_applier.rb +185 -0
  62. data/lib/fontisan/hints/postscript_hint_extractor.rb +254 -0
  63. data/lib/fontisan/hints/truetype_hint_applier.rb +71 -0
  64. data/lib/fontisan/hints/truetype_hint_extractor.rb +162 -0
  65. data/lib/fontisan/loading_modes.rb +113 -0
  66. data/lib/fontisan/metrics_calculator.rb +277 -0
  67. data/lib/fontisan/models/collection_font_summary.rb +52 -0
  68. data/lib/fontisan/models/collection_info.rb +76 -0
  69. data/lib/fontisan/models/collection_list_info.rb +37 -0
  70. data/lib/fontisan/models/font_export.rb +158 -0
  71. data/lib/fontisan/models/font_summary.rb +48 -0
  72. data/lib/fontisan/models/glyph_outline.rb +343 -0
  73. data/lib/fontisan/models/hint.rb +233 -0
  74. data/lib/fontisan/models/outline.rb +664 -0
  75. data/lib/fontisan/models/table_sharing_info.rb +40 -0
  76. data/lib/fontisan/models/ttx/glyph_order.rb +31 -0
  77. data/lib/fontisan/models/ttx/tables/binary_table.rb +67 -0
  78. data/lib/fontisan/models/ttx/tables/head_table.rb +74 -0
  79. data/lib/fontisan/models/ttx/tables/hhea_table.rb +74 -0
  80. data/lib/fontisan/models/ttx/tables/maxp_table.rb +55 -0
  81. data/lib/fontisan/models/ttx/tables/name_table.rb +45 -0
  82. data/lib/fontisan/models/ttx/tables/os2_table.rb +157 -0
  83. data/lib/fontisan/models/ttx/tables/post_table.rb +50 -0
  84. data/lib/fontisan/models/ttx/ttfont.rb +49 -0
  85. data/lib/fontisan/models/validation_report.rb +203 -0
  86. data/lib/fontisan/open_type_collection.rb +156 -2
  87. data/lib/fontisan/open_type_font.rb +296 -10
  88. data/lib/fontisan/optimizers/charstring_rewriter.rb +161 -0
  89. data/lib/fontisan/optimizers/pattern_analyzer.rb +308 -0
  90. data/lib/fontisan/optimizers/stack_tracker.rb +246 -0
  91. data/lib/fontisan/optimizers/subroutine_builder.rb +134 -0
  92. data/lib/fontisan/optimizers/subroutine_generator.rb +207 -0
  93. data/lib/fontisan/optimizers/subroutine_optimizer.rb +107 -0
  94. data/lib/fontisan/outline_extractor.rb +423 -0
  95. data/lib/fontisan/subset/builder.rb +268 -0
  96. data/lib/fontisan/subset/glyph_mapping.rb +215 -0
  97. data/lib/fontisan/subset/options.rb +142 -0
  98. data/lib/fontisan/subset/profile.rb +152 -0
  99. data/lib/fontisan/subset/table_subsetter.rb +461 -0
  100. data/lib/fontisan/svg/font_face_generator.rb +278 -0
  101. data/lib/fontisan/svg/font_generator.rb +264 -0
  102. data/lib/fontisan/svg/glyph_generator.rb +168 -0
  103. data/lib/fontisan/svg/view_box_calculator.rb +137 -0
  104. data/lib/fontisan/tables/cff/cff_glyph.rb +176 -0
  105. data/lib/fontisan/tables/cff/charset.rb +282 -0
  106. data/lib/fontisan/tables/cff/charstring.rb +905 -0
  107. data/lib/fontisan/tables/cff/charstring_builder.rb +322 -0
  108. data/lib/fontisan/tables/cff/charstrings_index.rb +162 -0
  109. data/lib/fontisan/tables/cff/dict.rb +351 -0
  110. data/lib/fontisan/tables/cff/dict_builder.rb +242 -0
  111. data/lib/fontisan/tables/cff/encoding.rb +274 -0
  112. data/lib/fontisan/tables/cff/header.rb +102 -0
  113. data/lib/fontisan/tables/cff/index.rb +237 -0
  114. data/lib/fontisan/tables/cff/index_builder.rb +170 -0
  115. data/lib/fontisan/tables/cff/private_dict.rb +284 -0
  116. data/lib/fontisan/tables/cff/top_dict.rb +236 -0
  117. data/lib/fontisan/tables/cff.rb +487 -0
  118. data/lib/fontisan/tables/cff2/blend_operator.rb +240 -0
  119. data/lib/fontisan/tables/cff2/charstring_parser.rb +591 -0
  120. data/lib/fontisan/tables/cff2/operand_stack.rb +232 -0
  121. data/lib/fontisan/tables/cff2.rb +341 -0
  122. data/lib/fontisan/tables/cvar.rb +242 -0
  123. data/lib/fontisan/tables/fvar.rb +2 -2
  124. data/lib/fontisan/tables/glyf/compound_glyph.rb +483 -0
  125. data/lib/fontisan/tables/glyf/compound_glyph_resolver.rb +136 -0
  126. data/lib/fontisan/tables/glyf/curve_converter.rb +343 -0
  127. data/lib/fontisan/tables/glyf/glyph_builder.rb +450 -0
  128. data/lib/fontisan/tables/glyf/simple_glyph.rb +382 -0
  129. data/lib/fontisan/tables/glyf.rb +235 -0
  130. data/lib/fontisan/tables/gvar.rb +270 -0
  131. data/lib/fontisan/tables/hhea.rb +124 -0
  132. data/lib/fontisan/tables/hmtx.rb +287 -0
  133. data/lib/fontisan/tables/hvar.rb +191 -0
  134. data/lib/fontisan/tables/loca.rb +322 -0
  135. data/lib/fontisan/tables/maxp.rb +192 -0
  136. data/lib/fontisan/tables/mvar.rb +185 -0
  137. data/lib/fontisan/tables/name.rb +99 -30
  138. data/lib/fontisan/tables/variation_common.rb +346 -0
  139. data/lib/fontisan/tables/vvar.rb +234 -0
  140. data/lib/fontisan/true_type_collection.rb +156 -2
  141. data/lib/fontisan/true_type_font.rb +297 -11
  142. data/lib/fontisan/utilities/brotli_wrapper.rb +159 -0
  143. data/lib/fontisan/utilities/checksum_calculator.rb +18 -0
  144. data/lib/fontisan/utils/thread_pool.rb +134 -0
  145. data/lib/fontisan/validation/checksum_validator.rb +170 -0
  146. data/lib/fontisan/validation/consistency_validator.rb +197 -0
  147. data/lib/fontisan/validation/structure_validator.rb +198 -0
  148. data/lib/fontisan/validation/table_validator.rb +158 -0
  149. data/lib/fontisan/validation/validator.rb +152 -0
  150. data/lib/fontisan/variable/axis_normalizer.rb +215 -0
  151. data/lib/fontisan/variable/delta_applicator.rb +313 -0
  152. data/lib/fontisan/variable/glyph_delta_processor.rb +218 -0
  153. data/lib/fontisan/variable/instancer.rb +344 -0
  154. data/lib/fontisan/variable/metric_delta_processor.rb +282 -0
  155. data/lib/fontisan/variable/region_matcher.rb +208 -0
  156. data/lib/fontisan/variable/static_font_builder.rb +213 -0
  157. data/lib/fontisan/variable/table_updater.rb +219 -0
  158. data/lib/fontisan/variation/blend_applier.rb +199 -0
  159. data/lib/fontisan/variation/cache.rb +298 -0
  160. data/lib/fontisan/variation/cache_key_builder.rb +162 -0
  161. data/lib/fontisan/variation/converter.rb +268 -0
  162. data/lib/fontisan/variation/data_extractor.rb +86 -0
  163. data/lib/fontisan/variation/delta_applier.rb +266 -0
  164. data/lib/fontisan/variation/delta_parser.rb +228 -0
  165. data/lib/fontisan/variation/inspector.rb +275 -0
  166. data/lib/fontisan/variation/instance_generator.rb +273 -0
  167. data/lib/fontisan/variation/interpolator.rb +231 -0
  168. data/lib/fontisan/variation/metrics_adjuster.rb +318 -0
  169. data/lib/fontisan/variation/optimizer.rb +418 -0
  170. data/lib/fontisan/variation/parallel_generator.rb +150 -0
  171. data/lib/fontisan/variation/region_matcher.rb +221 -0
  172. data/lib/fontisan/variation/subsetter.rb +463 -0
  173. data/lib/fontisan/variation/table_accessor.rb +105 -0
  174. data/lib/fontisan/variation/validator.rb +345 -0
  175. data/lib/fontisan/variation/variation_context.rb +211 -0
  176. data/lib/fontisan/version.rb +1 -1
  177. data/lib/fontisan/woff2/directory.rb +257 -0
  178. data/lib/fontisan/woff2/header.rb +101 -0
  179. data/lib/fontisan/woff2/table_transformer.rb +163 -0
  180. data/lib/fontisan/woff2_font.rb +712 -0
  181. data/lib/fontisan/woff_font.rb +483 -0
  182. data/lib/fontisan.rb +120 -0
  183. data/scripts/compare_stack_aware.rb +187 -0
  184. data/scripts/measure_optimization.rb +141 -0
  185. metadata +205 -4
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Fontisan
6
+ module Models
7
+ module Ttx
8
+ # GlyphID entry in GlyphOrder
9
+ class GlyphId < Lutaml::Model::Serializable
10
+ attribute :id, :integer
11
+ attribute :name, :string
12
+
13
+ xml do
14
+ root "GlyphID"
15
+ map_attribute "id", to: :id
16
+ map_attribute "name", to: :name
17
+ end
18
+ end
19
+
20
+ # GlyphOrder section in TTX
21
+ class GlyphOrder < Lutaml::Model::Serializable
22
+ attribute :glyph_ids, GlyphId, collection: true
23
+
24
+ xml do
25
+ root "GlyphOrder"
26
+ map_element "GlyphID", to: :glyph_ids
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Fontisan
6
+ module Models
7
+ module Ttx
8
+ module Tables
9
+ # BinaryTable represents unparsed tables in TTX format
10
+ #
11
+ # Used as a fallback for tables that don't have specific
12
+ # parsers, storing them as hexdata following fonttools format.
13
+ class BinaryTable < Lutaml::Model::Serializable
14
+ attribute :tag, :string
15
+ attribute :hexdata, :string
16
+
17
+ # Custom serialization since we need dynamic root element
18
+ # based on table tag
19
+ def to_xml(options = {})
20
+ builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
21
+ xml.send(tag.to_sym) do
22
+ xml.hexdata do
23
+ xml.text("\n #{format_hexdata(hexdata)}\n ")
24
+ end
25
+ end
26
+ end
27
+
28
+ if options[:pretty]
29
+ builder.doc.root.to_xml(indent: options.fetch(:indent, 2))
30
+ else
31
+ builder.to_xml
32
+ end
33
+ end
34
+
35
+ # Parse from XML
36
+ def self.from_xml(xml_string, tag)
37
+ doc = Nokogiri::XML(xml_string)
38
+ table_elem = doc.at_xpath("//#{tag}")
39
+ return nil unless table_elem
40
+
41
+ hexdata_elem = table_elem.at_xpath("hexdata")
42
+ hexdata = hexdata_elem ? parse_hexdata(hexdata_elem.text) : ""
43
+
44
+ new(tag: tag, hexdata: hexdata)
45
+ end
46
+
47
+ private
48
+
49
+ # Format hexdata for output
50
+ def format_hexdata(data)
51
+ return "" if data.nil? || data.empty?
52
+
53
+ hex = data.unpack1("H*")
54
+ # Format in lines of 64 hex chars (32 bytes)
55
+ hex.scan(/.{1,64}/).join("\n ")
56
+ end
57
+
58
+ # Parse hexdata from XML
59
+ def self.parse_hexdata(hex_str)
60
+ hex_clean = hex_str.gsub(/\s+/, "")
61
+ [hex_clean].pack("H*")
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Fontisan
6
+ module Models
7
+ module Ttx
8
+ module Tables
9
+ # HeadTable represents the 'head' table in TTX format
10
+ #
11
+ # Contains global font metrics and metadata following the OpenType
12
+ # specification for the head table.
13
+ class HeadTable < Lutaml::Model::Serializable
14
+ attribute :table_version, :float
15
+ attribute :font_revision, :float
16
+ attribute :checksum_adjustment, :integer
17
+ attribute :magic_number, :integer
18
+ attribute :flags, :integer
19
+ attribute :units_per_em, :integer
20
+ attribute :created, :string
21
+ attribute :modified, :string
22
+ attribute :x_min, :integer
23
+ attribute :y_min, :integer
24
+ attribute :x_max, :integer
25
+ attribute :y_max, :integer
26
+ attribute :mac_style, :string
27
+ attribute :lowest_rec_ppem, :integer
28
+ attribute :font_direction_hint, :integer
29
+ attribute :index_to_loc_format, :integer
30
+ attribute :glyph_data_format, :integer
31
+
32
+ xml do
33
+ root "head"
34
+
35
+ map_element "tableVersion", to: :table_version,
36
+ render_default: true
37
+ map_element "fontRevision", to: :font_revision,
38
+ render_default: true
39
+ map_element "checkSumAdjustment", to: :checksum_adjustment,
40
+ render_default: true
41
+ map_element "magicNumber", to: :magic_number,
42
+ render_default: true
43
+ map_element "flags", to: :flags,
44
+ render_default: true
45
+ map_element "unitsPerEm", to: :units_per_em,
46
+ render_default: true
47
+ map_element "created", to: :created,
48
+ render_default: true
49
+ map_element "modified", to: :modified,
50
+ render_default: true
51
+ map_element "xMin", to: :x_min,
52
+ render_default: true
53
+ map_element "yMin", to: :y_min,
54
+ render_default: true
55
+ map_element "xMax", to: :x_max,
56
+ render_default: true
57
+ map_element "yMax", to: :y_max,
58
+ render_default: true
59
+ map_element "macStyle", to: :mac_style,
60
+ render_default: true
61
+ map_element "lowestRecPPEM", to: :lowest_rec_ppem,
62
+ render_default: true
63
+ map_element "fontDirectionHint", to: :font_direction_hint,
64
+ render_default: true
65
+ map_element "indexToLocFormat", to: :index_to_loc_format,
66
+ render_default: true
67
+ map_element "glyphDataFormat", to: :glyph_data_format,
68
+ render_default: true
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Fontisan
6
+ module Models
7
+ module Ttx
8
+ module Tables
9
+ # HheaTable represents the 'hhea' table in TTX format
10
+ #
11
+ # Contains horizontal header information following the OpenType
12
+ # specification for the hhea table.
13
+ class HheaTable < Lutaml::Model::Serializable
14
+ attribute :table_version, :string
15
+ attribute :ascent, :integer
16
+ attribute :descent, :integer
17
+ attribute :line_gap, :integer
18
+ attribute :advance_width_max, :integer
19
+ attribute :min_left_side_bearing, :integer
20
+ attribute :min_right_side_bearing, :integer
21
+ attribute :x_max_extent, :integer
22
+ attribute :caret_slope_rise, :integer
23
+ attribute :caret_slope_run, :integer
24
+ attribute :caret_offset, :integer
25
+ attribute :reserved0, :integer, default: -> { 0 }
26
+ attribute :reserved1, :integer, default: -> { 0 }
27
+ attribute :reserved2, :integer, default: -> { 0 }
28
+ attribute :reserved3, :integer, default: -> { 0 }
29
+ attribute :metric_data_format, :integer
30
+ attribute :number_of_h_metrics, :integer
31
+
32
+ xml do
33
+ root "hhea"
34
+
35
+ map_element "tableVersion", to: :table_version,
36
+ render_default: true
37
+ map_element "ascent", to: :ascent,
38
+ render_default: true
39
+ map_element "descent", to: :descent,
40
+ render_default: true
41
+ map_element "lineGap", to: :line_gap,
42
+ render_default: true
43
+ map_element "advanceWidthMax", to: :advance_width_max,
44
+ render_default: true
45
+ map_element "minLeftSideBearing", to: :min_left_side_bearing,
46
+ render_default: true
47
+ map_element "minRightSideBearing", to: :min_right_side_bearing,
48
+ render_default: true
49
+ map_element "xMaxExtent", to: :x_max_extent,
50
+ render_default: true
51
+ map_element "caretSlopeRise", to: :caret_slope_rise,
52
+ render_default: true
53
+ map_element "caretSlopeRun", to: :caret_slope_run,
54
+ render_default: true
55
+ map_element "caretOffset", to: :caret_offset,
56
+ render_default: true
57
+ map_element "reserved0", to: :reserved0,
58
+ render_default: true
59
+ map_element "reserved1", to: :reserved1,
60
+ render_default: true
61
+ map_element "reserved2", to: :reserved2,
62
+ render_default: true
63
+ map_element "reserved3", to: :reserved3,
64
+ render_default: true
65
+ map_element "metricDataFormat", to: :metric_data_format,
66
+ render_default: true
67
+ map_element "numberOfHMetrics", to: :number_of_h_metrics,
68
+ render_default: true
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Fontisan
6
+ module Models
7
+ module Ttx
8
+ module Tables
9
+ # MaxpTable represents the 'maxp' table in TTX format
10
+ #
11
+ # Contains maximum profile information following the OpenType
12
+ # specification for the maxp table.
13
+ class MaxpTable < Lutaml::Model::Serializable
14
+ attribute :table_version, :string
15
+ attribute :num_glyphs, :integer
16
+ attribute :max_points, :integer
17
+ attribute :max_contours, :integer
18
+ attribute :max_composite_points, :integer
19
+ attribute :max_composite_contours, :integer
20
+ attribute :max_zones, :integer
21
+ attribute :max_twilight_points, :integer
22
+ attribute :max_storage, :integer
23
+ attribute :max_function_defs, :integer
24
+ attribute :max_instruction_defs, :integer
25
+ attribute :max_stack_elements, :integer
26
+ attribute :max_size_of_instructions, :integer
27
+ attribute :max_component_elements, :integer
28
+ attribute :max_component_depth, :integer
29
+
30
+ xml do
31
+ root "maxp"
32
+
33
+ map_element "tableVersion", to: :table_version,
34
+ render_default: true
35
+ map_element "numGlyphs", to: :num_glyphs,
36
+ render_default: true
37
+ map_element "maxPoints", to: :max_points
38
+ map_element "maxContours", to: :max_contours
39
+ map_element "maxCompositePoints", to: :max_composite_points
40
+ map_element "maxCompositeContours", to: :max_composite_contours
41
+ map_element "maxZones", to: :max_zones
42
+ map_element "maxTwilightPoints", to: :max_twilight_points
43
+ map_element "maxStorage", to: :max_storage
44
+ map_element "maxFunctionDefs", to: :max_function_defs
45
+ map_element "maxInstructionDefs", to: :max_instruction_defs
46
+ map_element "maxStackElements", to: :max_stack_elements
47
+ map_element "maxSizeOfInstructions", to: :max_size_of_instructions
48
+ map_element "maxComponentElements", to: :max_component_elements
49
+ map_element "maxComponentDepth", to: :max_component_depth
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Fontisan
6
+ module Models
7
+ module Ttx
8
+ module Tables
9
+ # NameRecord represents a single name record in the name table
10
+ class NameRecord < Lutaml::Model::Serializable
11
+ attribute :name_id, :integer
12
+ attribute :platform_id, :integer
13
+ attribute :plat_enc_id, :integer
14
+ attribute :lang_id, :string
15
+ attribute :string, :string
16
+
17
+ xml do
18
+ root "namerecord"
19
+
20
+ map_attribute "nameID", to: :name_id
21
+ map_attribute "platformID", to: :platform_id
22
+ map_attribute "platEncID", to: :plat_enc_id
23
+ map_attribute "langID", to: :lang_id
24
+
25
+ map_content to: :string
26
+ end
27
+ end
28
+
29
+ # NameTable represents the 'name' table in TTX format
30
+ #
31
+ # Contains human-readable information about the font following
32
+ # the OpenType specification for the name table.
33
+ class NameTable < Lutaml::Model::Serializable
34
+ attribute :name_records, NameRecord, collection: true
35
+
36
+ xml do
37
+ root "name"
38
+
39
+ map_element "namerecord", to: :name_records
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Fontisan
6
+ module Models
7
+ module Ttx
8
+ module Tables
9
+ # Panose classification in OS/2 table
10
+ class Panose < Lutaml::Model::Serializable
11
+ attribute :b_family_type, :integer
12
+ attribute :b_serif_style, :integer
13
+ attribute :b_weight, :integer
14
+ attribute :b_proportion, :integer
15
+ attribute :b_contrast, :integer
16
+ attribute :b_stroke_variation, :integer
17
+ attribute :b_arm_style, :integer
18
+ attribute :b_letter_form, :integer
19
+ attribute :b_midline, :integer
20
+ attribute :b_x_height, :integer
21
+
22
+ xml do
23
+ root "panose"
24
+
25
+ map_element "bFamilyType", to: :b_family_type,
26
+ render_default: true
27
+ map_element "bSerifStyle", to: :b_serif_style,
28
+ render_default: true
29
+ map_element "bWeight", to: :b_weight,
30
+ render_default: true
31
+ map_element "bProportion", to: :b_proportion,
32
+ render_default: true
33
+ map_element "bContrast", to: :b_contrast,
34
+ render_default: true
35
+ map_element "bStrokeVariation", to: :b_stroke_variation,
36
+ render_default: true
37
+ map_element "bArmStyle", to: :b_arm_style,
38
+ render_default: true
39
+ map_element "bLetterForm", to: :b_letter_form,
40
+ render_default: true
41
+ map_element "bMidline", to: :b_midline,
42
+ render_default: true
43
+ map_element "bXHeight", to: :b_x_height,
44
+ render_default: true
45
+ end
46
+ end
47
+
48
+ # Os2Table represents the 'OS/2' table in TTX format
49
+ #
50
+ # Contains OS/2 and Windows-specific metrics following the
51
+ # OpenType specification for the OS/2 table.
52
+ class Os2Table < Lutaml::Model::Serializable
53
+ attribute :version, :integer
54
+ attribute :x_avg_char_width, :integer
55
+ attribute :us_weight_class, :integer
56
+ attribute :us_width_class, :integer
57
+ attribute :fs_type, :string
58
+ attribute :y_subscript_x_size, :integer
59
+ attribute :y_subscript_y_size, :integer
60
+ attribute :y_subscript_x_offset, :integer
61
+ attribute :y_subscript_y_offset, :integer
62
+ attribute :y_superscript_x_size, :integer
63
+ attribute :y_superscript_y_size, :integer
64
+ attribute :y_superscript_x_offset, :integer
65
+ attribute :y_superscript_y_offset, :integer
66
+ attribute :y_strikeout_size, :integer
67
+ attribute :y_strikeout_position, :integer
68
+ attribute :s_family_class, :integer
69
+ attribute :panose, Panose
70
+ attribute :ul_unicode_range_1, :string
71
+ attribute :ul_unicode_range_2, :string
72
+ attribute :ul_unicode_range_3, :string
73
+ attribute :ul_unicode_range_4, :string
74
+ attribute :ach_vend_id, :string
75
+ attribute :fs_selection, :string
76
+ attribute :us_first_char_index, :integer
77
+ attribute :us_last_char_index, :integer
78
+ attribute :s_typo_ascender, :integer
79
+ attribute :s_typo_descender, :integer
80
+ attribute :s_typo_line_gap, :integer
81
+ attribute :us_win_ascent, :integer
82
+ attribute :us_win_descent, :integer
83
+ attribute :ul_code_page_range_1, :string
84
+ attribute :ul_code_page_range_2, :string
85
+
86
+ xml do
87
+ root "OS_2"
88
+
89
+ map_element "version", to: :version,
90
+ render_default: true
91
+ map_element "xAvgCharWidth", to: :x_avg_char_width,
92
+ render_default: true
93
+ map_element "usWeightClass", to: :us_weight_class,
94
+ render_default: true
95
+ map_element "usWidthClass", to: :us_width_class,
96
+ render_default: true
97
+ map_element "fsType", to: :fs_type,
98
+ render_default: true
99
+ map_element "ySubscriptXSize", to: :y_subscript_x_size,
100
+ render_default: true
101
+ map_element "ySubscriptYSize", to: :y_subscript_y_size,
102
+ render_default: true
103
+ map_element "ySubscriptXOffset", to: :y_subscript_x_offset,
104
+ render_default: true
105
+ map_element "ySubscriptYOffset", to: :y_subscript_y_offset,
106
+ render_default: true
107
+ map_element "ySuperscriptXSize", to: :y_superscript_x_size,
108
+ render_default: true
109
+ map_element "ySuperscriptYSize", to: :y_superscript_y_size,
110
+ render_default: true
111
+ map_element "ySuperscriptXOffset", to: :y_superscript_x_offset,
112
+ render_default: true
113
+ map_element "ySuperscriptYOffset", to: :y_superscript_y_offset,
114
+ render_default: true
115
+ map_element "yStrikeoutSize", to: :y_strikeout_size,
116
+ render_default: true
117
+ map_element "yStrikeoutPosition", to: :y_strikeout_position,
118
+ render_default: true
119
+ map_element "sFamilyClass", to: :s_family_class,
120
+ render_default: true
121
+ map_element "panose", to: :panose
122
+ map_element "ulUnicodeRange1", to: :ul_unicode_range_1,
123
+ render_default: true
124
+ map_element "ulUnicodeRange2", to: :ul_unicode_range_2,
125
+ render_default: true
126
+ map_element "ulUnicodeRange3", to: :ul_unicode_range_3,
127
+ render_default: true
128
+ map_element "ulUnicodeRange4", to: :ul_unicode_range_4,
129
+ render_default: true
130
+ map_element "achVendID", to: :ach_vend_id,
131
+ render_default: true
132
+ map_element "fsSelection", to: :fs_selection,
133
+ render_default: true
134
+ map_element "usFirstCharIndex", to: :us_first_char_index,
135
+ render_default: true
136
+ map_element "usLastCharIndex", to: :us_last_char_index,
137
+ render_default: true
138
+ map_element "sTypoAscender", to: :s_typo_ascender,
139
+ render_default: true
140
+ map_element "sTypoDescender", to: :s_typo_descender,
141
+ render_default: true
142
+ map_element "sTypoLineGap", to: :s_typo_line_gap,
143
+ render_default: true
144
+ map_element "usWinAscent", to: :us_win_ascent,
145
+ render_default: true
146
+ map_element "usWinDescent", to: :us_win_descent,
147
+ render_default: true
148
+ map_element "ulCodePageRange1", to: :ul_code_page_range_1,
149
+ render_default: true
150
+ map_element "ulCodePageRange2", to: :ul_code_page_range_2,
151
+ render_default: true
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Fontisan
6
+ module Models
7
+ module Ttx
8
+ module Tables
9
+ # PostTable represents the 'post' table in TTX format
10
+ #
11
+ # Contains PostScript information following the OpenType
12
+ # specification for the post table.
13
+ class PostTable < Lutaml::Model::Serializable
14
+ attribute :format_type, :float
15
+ attribute :italic_angle, :float
16
+ attribute :underline_position, :integer
17
+ attribute :underline_thickness, :integer
18
+ attribute :is_fixed_pitch, :integer
19
+ attribute :min_mem_type42, :integer
20
+ attribute :max_mem_type42, :integer
21
+ attribute :min_mem_type1, :integer
22
+ attribute :max_mem_type1, :integer
23
+
24
+ xml do
25
+ root "post"
26
+
27
+ map_element "formatType", to: :format_type,
28
+ render_default: true
29
+ map_element "italicAngle", to: :italic_angle,
30
+ render_default: true
31
+ map_element "underlinePosition", to: :underline_position,
32
+ render_default: true
33
+ map_element "underlineThickness", to: :underline_thickness,
34
+ render_default: true
35
+ map_element "isFixedPitch", to: :is_fixed_pitch,
36
+ render_default: true
37
+ map_element "minMemType42", to: :min_mem_type42,
38
+ render_default: true
39
+ map_element "maxMemType42", to: :max_mem_type42,
40
+ render_default: true
41
+ map_element "minMemType1", to: :min_mem_type1,
42
+ render_default: true
43
+ map_element "maxMemType1", to: :max_mem_type1,
44
+ render_default: true
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+ require_relative "glyph_order"
5
+ require_relative "tables/head_table"
6
+ require_relative "tables/name_table"
7
+ require_relative "tables/maxp_table"
8
+ require_relative "tables/hhea_table"
9
+ require_relative "tables/os2_table"
10
+ require_relative "tables/post_table"
11
+ require_relative "tables/binary_table"
12
+
13
+ module Fontisan
14
+ module Models
15
+ module Ttx
16
+ # Root TTFont element for TTX format
17
+ #
18
+ # Represents the complete TTX XML structure following fonttools format.
19
+ # This is the main container for all font data in TTX format.
20
+ class TtFont < Lutaml::Model::Serializable
21
+ attribute :sfnt_version, :string
22
+ attribute :ttlib_version, :string, default: -> { "4.0" }
23
+ attribute :glyph_order, GlyphOrder
24
+ attribute :head_table, Tables::HeadTable
25
+ attribute :hhea_table, Tables::HheaTable
26
+ attribute :maxp_table, Tables::MaxpTable
27
+ attribute :name_table, Tables::NameTable
28
+ attribute :os2_table, Tables::Os2Table
29
+ attribute :post_table, Tables::PostTable
30
+ attribute :binary_tables, Tables::BinaryTable, collection: true
31
+
32
+ xml do
33
+ root "ttFont"
34
+
35
+ map_attribute "sfntVersion", to: :sfnt_version
36
+ map_attribute "ttLibVersion", to: :ttlib_version
37
+
38
+ map_element "GlyphOrder", to: :glyph_order
39
+ map_element "head", to: :head_table
40
+ map_element "hhea", to: :hhea_table
41
+ map_element "maxp", to: :maxp_table
42
+ map_element "name", to: :name_table
43
+ map_element "OS_2", to: :os2_table
44
+ map_element "post", to: :post_table
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end