fontisan 0.2.17 → 0.2.22

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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +14 -90
  3. data/README.adoc +257 -1
  4. data/docs/.vitepress/config.ts +68 -8
  5. data/docs/.vitepress/theme/style.css +570 -272
  6. data/docs/CONVERSION_GUIDE.adoc +31 -8
  7. data/docs/EXTRACT_TTC_MIGRATION.md +1 -1
  8. data/docs/WOFF_WOFF2_FORMATS.adoc +53 -0
  9. data/docs/api/conversion-options.md +37 -14
  10. data/docs/cli/audit.md +337 -0
  11. data/docs/cli/convert.md +20 -1
  12. data/docs/cli/index.md +31 -0
  13. data/docs/guide/color.md +1 -1
  14. data/docs/guide/conversion/options.md +32 -3
  15. data/docs/guide/conversion/ttf-otf.md +1 -1
  16. data/docs/guide/conversion/type1.md +1 -1
  17. data/docs/guide/conversion/web.md +91 -32
  18. data/docs/guide/conversion.md +6 -5
  19. data/docs/guide/formats/woff.md +35 -11
  20. data/docs/guide/index.md +2 -2
  21. data/docs/guide/migrations/extract-ttc.md +1 -1
  22. data/docs/guide/quick-start.md +4 -4
  23. data/docs/guide/type1.md +4 -4
  24. data/docs/guide/woff.md +19 -17
  25. data/docs/index.md +2 -0
  26. data/docs/lychee.toml +5 -1
  27. data/docs/package.json +1 -1
  28. data/docs/public/robots.txt +4 -0
  29. data/docs/scripts/post-build.mjs +81 -0
  30. data/lib/fontisan/audit/codepoint_range_coalescer.rb +41 -0
  31. data/lib/fontisan/audit/context.rb +122 -0
  32. data/lib/fontisan/audit/differ.rb +124 -0
  33. data/lib/fontisan/audit/extractors/aggregations.rb +54 -0
  34. data/lib/fontisan/audit/extractors/base.rb +26 -0
  35. data/lib/fontisan/audit/extractors/color_capabilities.rb +141 -0
  36. data/lib/fontisan/audit/extractors/coverage.rb +48 -0
  37. data/lib/fontisan/audit/extractors/hinting.rb +197 -0
  38. data/lib/fontisan/audit/extractors/identity.rb +52 -0
  39. data/lib/fontisan/audit/extractors/language_coverage.rb +37 -0
  40. data/lib/fontisan/audit/extractors/licensing.rb +79 -0
  41. data/lib/fontisan/audit/extractors/metrics.rb +103 -0
  42. data/lib/fontisan/audit/extractors/opentype_layout.rb +69 -0
  43. data/lib/fontisan/audit/extractors/provenance.rb +29 -0
  44. data/lib/fontisan/audit/extractors/style.rb +32 -0
  45. data/lib/fontisan/audit/extractors/variation_detail.rb +99 -0
  46. data/lib/fontisan/audit/extractors.rb +27 -0
  47. data/lib/fontisan/audit/library_aggregator.rb +83 -0
  48. data/lib/fontisan/audit/library_auditor.rb +90 -0
  49. data/lib/fontisan/audit/registry.rb +60 -0
  50. data/lib/fontisan/audit/style_extractor.rb +80 -0
  51. data/lib/fontisan/audit.rb +20 -0
  52. data/lib/fontisan/base_collection.rb +23 -9
  53. data/lib/fontisan/binary/structures.rb +0 -2
  54. data/lib/fontisan/binary.rb +11 -0
  55. data/lib/fontisan/cldr/aggregator.rb +33 -0
  56. data/lib/fontisan/cldr/cache_manager.rb +110 -0
  57. data/lib/fontisan/cldr/config.rb +59 -0
  58. data/lib/fontisan/cldr/download_error.rb +9 -0
  59. data/lib/fontisan/cldr/downloader.rb +79 -0
  60. data/lib/fontisan/cldr/error.rb +8 -0
  61. data/lib/fontisan/cldr/index.rb +64 -0
  62. data/lib/fontisan/cldr/index_builder.rb +72 -0
  63. data/lib/fontisan/cldr/unicode_set_parser.rb +172 -0
  64. data/lib/fontisan/cldr/unknown_version_error.rb +9 -0
  65. data/lib/fontisan/cldr/version_resolver.rb +91 -0
  66. data/lib/fontisan/cldr.rb +23 -0
  67. data/lib/fontisan/cli/cldr_cli.rb +85 -0
  68. data/lib/fontisan/cli/ucd_cli.rb +97 -0
  69. data/lib/fontisan/cli.rb +201 -2
  70. data/lib/fontisan/collection/builder.rb +0 -4
  71. data/lib/fontisan/collection/dfont_builder.rb +0 -4
  72. data/lib/fontisan/collection/shared_logic.rb +0 -2
  73. data/lib/fontisan/collection/writer.rb +0 -3
  74. data/lib/fontisan/collection.rb +15 -0
  75. data/lib/fontisan/commands/audit_command.rb +123 -0
  76. data/lib/fontisan/commands/audit_compare_command.rb +66 -0
  77. data/lib/fontisan/commands/audit_library_command.rb +46 -0
  78. data/lib/fontisan/commands/base_command.rb +0 -3
  79. data/lib/fontisan/commands/convert_command.rb +25 -20
  80. data/lib/fontisan/commands/dump_table_command.rb +0 -3
  81. data/lib/fontisan/commands/export_command.rb +0 -4
  82. data/lib/fontisan/commands/features_command.rb +0 -3
  83. data/lib/fontisan/commands/instance_command.rb +0 -5
  84. data/lib/fontisan/commands/ls_command.rb +0 -6
  85. data/lib/fontisan/commands/optical_size_command.rb +0 -3
  86. data/lib/fontisan/commands/pack_command.rb +0 -5
  87. data/lib/fontisan/commands/scripts_command.rb +0 -2
  88. data/lib/fontisan/commands/subset_command.rb +0 -3
  89. data/lib/fontisan/commands/unicode_command.rb +0 -3
  90. data/lib/fontisan/commands/unpack_command.rb +0 -7
  91. data/lib/fontisan/commands/validate_command.rb +0 -8
  92. data/lib/fontisan/commands/variable_command.rb +0 -3
  93. data/lib/fontisan/commands.rb +29 -0
  94. data/lib/fontisan/config/cldr.yml +22 -0
  95. data/lib/fontisan/config/conversion_matrix.yml +38 -0
  96. data/lib/fontisan/config/ucd.yml +23 -0
  97. data/lib/fontisan/constants.rb +19 -0
  98. data/lib/fontisan/conversion_options.rb +30 -19
  99. data/lib/fontisan/converters/cff_table_builder.rb +0 -3
  100. data/lib/fontisan/converters/collection_converter.rb +0 -8
  101. data/lib/fontisan/converters/conversion_strategy.rb +161 -46
  102. data/lib/fontisan/converters/format_converter.rb +143 -32
  103. data/lib/fontisan/converters/glyf_table_builder.rb +0 -2
  104. data/lib/fontisan/converters/outline_converter.rb +0 -19
  105. data/lib/fontisan/converters/outline_extraction.rb +0 -5
  106. data/lib/fontisan/converters/outline_optimizer.rb +0 -5
  107. data/lib/fontisan/converters/svg_generator.rb +0 -4
  108. data/lib/fontisan/converters/table_copier.rb +0 -2
  109. data/lib/fontisan/converters/type1_converter.rb +0 -11
  110. data/lib/fontisan/converters/woff2_encoder.rb +49 -20
  111. data/lib/fontisan/converters/woff_writer.rb +211 -282
  112. data/lib/fontisan/converters.rb +21 -0
  113. data/lib/fontisan/dfont_collection.rb +29 -10
  114. data/lib/fontisan/export/exporter.rb +0 -6
  115. data/lib/fontisan/export/transformers/font_to_ttx.rb +0 -9
  116. data/lib/fontisan/export/transformers/head_transformer.rb +0 -2
  117. data/lib/fontisan/export/transformers/hhea_transformer.rb +0 -2
  118. data/lib/fontisan/export/transformers/maxp_transformer.rb +0 -2
  119. data/lib/fontisan/export/transformers/name_transformer.rb +0 -2
  120. data/lib/fontisan/export/transformers/os2_transformer.rb +0 -2
  121. data/lib/fontisan/export/transformers/post_transformer.rb +0 -2
  122. data/lib/fontisan/export/transformers.rb +17 -0
  123. data/lib/fontisan/export.rb +13 -0
  124. data/lib/fontisan/font_loader.rb +14 -19
  125. data/lib/fontisan/font_writer.rb +0 -1
  126. data/lib/fontisan/formatters/audit_diff_text_renderer.rb +122 -0
  127. data/lib/fontisan/formatters/audit_text_renderer.rb +324 -0
  128. data/lib/fontisan/formatters/library_summary_text_renderer.rb +99 -0
  129. data/lib/fontisan/formatters/text_formatter.rb +6 -0
  130. data/lib/fontisan/formatters.rb +12 -0
  131. data/lib/fontisan/hints/hint_converter.rb +0 -1
  132. data/lib/fontisan/hints/postscript_hint_applier.rb +0 -9
  133. data/lib/fontisan/hints/postscript_hint_extractor.rb +0 -2
  134. data/lib/fontisan/hints/truetype_hint_extractor.rb +0 -2
  135. data/lib/fontisan/hints.rb +16 -0
  136. data/lib/fontisan/metrics_calculator.rb +0 -2
  137. data/lib/fontisan/models/all_scripts_features_info.rb +0 -1
  138. data/lib/fontisan/models/audit/audit_axis.rb +30 -0
  139. data/lib/fontisan/models/audit/audit_block.rb +32 -0
  140. data/lib/fontisan/models/audit/audit_diff.rb +77 -0
  141. data/lib/fontisan/models/audit/audit_report.rb +153 -0
  142. data/lib/fontisan/models/audit/codepoint_range.rb +40 -0
  143. data/lib/fontisan/models/audit/codepoint_set_diff.rb +34 -0
  144. data/lib/fontisan/models/audit/color_capabilities.rb +93 -0
  145. data/lib/fontisan/models/audit/duplicate_group.rb +23 -0
  146. data/lib/fontisan/models/audit/embedding_type.rb +76 -0
  147. data/lib/fontisan/models/audit/field_change.rb +28 -0
  148. data/lib/fontisan/models/audit/fs_selection_flags.rb +61 -0
  149. data/lib/fontisan/models/audit/gasp_range.rb +63 -0
  150. data/lib/fontisan/models/audit/hinting.rb +93 -0
  151. data/lib/fontisan/models/audit/library_summary.rb +40 -0
  152. data/lib/fontisan/models/audit/licensing.rb +48 -0
  153. data/lib/fontisan/models/audit/metrics.rb +111 -0
  154. data/lib/fontisan/models/audit/named_instance.rb +41 -0
  155. data/lib/fontisan/models/audit/opentype_layout.rb +40 -0
  156. data/lib/fontisan/models/audit/script_coverage_row.rb +26 -0
  157. data/lib/fontisan/models/audit/script_features.rb +28 -0
  158. data/lib/fontisan/models/audit/variation_detail.rb +44 -0
  159. data/lib/fontisan/models/audit.rb +33 -0
  160. data/lib/fontisan/models/cldr/language_coverage.rb +31 -0
  161. data/lib/fontisan/models/cldr.rb +12 -0
  162. data/lib/fontisan/models/collection_brief_info.rb +0 -1
  163. data/lib/fontisan/models/collection_info.rb +0 -2
  164. data/lib/fontisan/models/collection_list_info.rb +0 -1
  165. data/lib/fontisan/models/collection_validation_report.rb +0 -2
  166. data/lib/fontisan/models/color_glyph.rb +0 -1
  167. data/lib/fontisan/models/font_report.rb +0 -1
  168. data/lib/fontisan/models/ttx/tables.rb +21 -0
  169. data/lib/fontisan/models/ttx/ttfont.rb +0 -8
  170. data/lib/fontisan/models/ttx.rb +14 -0
  171. data/lib/fontisan/models/ucd/ucd.rb +38 -0
  172. data/lib/fontisan/models/ucd/ucd_char.rb +67 -0
  173. data/lib/fontisan/models/ucd.rb +19 -0
  174. data/lib/fontisan/models.rb +47 -0
  175. data/lib/fontisan/open_type_collection.rb +6 -5
  176. data/lib/fontisan/open_type_font.rb +8 -2
  177. data/lib/fontisan/open_type_font_extensions.rb +9 -9
  178. data/lib/fontisan/optimizers/pattern_analyzer.rb +0 -1
  179. data/lib/fontisan/optimizers.rb +14 -0
  180. data/lib/fontisan/outline_extractor.rb +0 -2
  181. data/lib/fontisan/parsers/dfont_parser.rb +0 -1
  182. data/lib/fontisan/parsers.rb +10 -0
  183. data/lib/fontisan/pipeline/format_detector.rb +29 -102
  184. data/lib/fontisan/pipeline/output_writer.rb +11 -9
  185. data/lib/fontisan/pipeline/strategies/instance_strategy.rb +0 -4
  186. data/lib/fontisan/pipeline/strategies/named_strategy.rb +0 -4
  187. data/lib/fontisan/pipeline/strategies/preserve_strategy.rb +0 -2
  188. data/lib/fontisan/pipeline/strategies.rb +14 -0
  189. data/lib/fontisan/pipeline/transformation_pipeline.rb +0 -7
  190. data/lib/fontisan/pipeline/variation_resolver.rb +0 -7
  191. data/lib/fontisan/pipeline.rb +13 -0
  192. data/lib/fontisan/sfnt_font.rb +29 -14
  193. data/lib/fontisan/sfnt_table.rb +0 -4
  194. data/lib/fontisan/subset/builder.rb +0 -6
  195. data/lib/fontisan/subset.rb +13 -0
  196. data/lib/fontisan/svg/font_generator.rb +0 -4
  197. data/lib/fontisan/svg/glyph_generator.rb +0 -2
  198. data/lib/fontisan/svg.rb +12 -0
  199. data/lib/fontisan/tables/cbdt.rb +0 -1
  200. data/lib/fontisan/tables/cblc.rb +0 -1
  201. data/lib/fontisan/tables/cff/charset.rb +0 -1
  202. data/lib/fontisan/tables/cff/charstring.rb +0 -1
  203. data/lib/fontisan/tables/cff/charstring_rebuilder.rb +0 -4
  204. data/lib/fontisan/tables/cff/charstrings_index.rb +0 -3
  205. data/lib/fontisan/tables/cff/dict.rb +0 -1
  206. data/lib/fontisan/tables/cff/encoding.rb +0 -1
  207. data/lib/fontisan/tables/cff/header.rb +0 -2
  208. data/lib/fontisan/tables/cff/hint_operation_injector.rb +0 -2
  209. data/lib/fontisan/tables/cff/index.rb +0 -1
  210. data/lib/fontisan/tables/cff/private_dict.rb +0 -2
  211. data/lib/fontisan/tables/cff/private_dict_writer.rb +0 -2
  212. data/lib/fontisan/tables/cff/table_builder.rb +0 -6
  213. data/lib/fontisan/tables/cff/top_dict.rb +0 -2
  214. data/lib/fontisan/tables/cff.rb +22 -15
  215. data/lib/fontisan/tables/cff2/charstring_parser.rb +0 -2
  216. data/lib/fontisan/tables/cff2/table_builder.rb +0 -11
  217. data/lib/fontisan/tables/cff2/table_reader.rb +0 -2
  218. data/lib/fontisan/tables/cff2.rb +13 -14
  219. data/lib/fontisan/tables/cmap.rb +24 -2
  220. data/lib/fontisan/tables/cmap_table.rb +0 -3
  221. data/lib/fontisan/tables/colr.rb +0 -1
  222. data/lib/fontisan/tables/cpal.rb +0 -1
  223. data/lib/fontisan/tables/cvar.rb +0 -2
  224. data/lib/fontisan/tables/fvar.rb +0 -1
  225. data/lib/fontisan/tables/glyf/compound_glyph_resolver.rb +0 -2
  226. data/lib/fontisan/tables/glyf/glyph_builder.rb +0 -3
  227. data/lib/fontisan/tables/glyf.rb +0 -6
  228. data/lib/fontisan/tables/glyf_table.rb +0 -3
  229. data/lib/fontisan/tables/gpos.rb +0 -2
  230. data/lib/fontisan/tables/gsub.rb +0 -2
  231. data/lib/fontisan/tables/gvar.rb +0 -2
  232. data/lib/fontisan/tables/head.rb +0 -2
  233. data/lib/fontisan/tables/head_table.rb +0 -3
  234. data/lib/fontisan/tables/hhea.rb +0 -2
  235. data/lib/fontisan/tables/hhea_table.rb +0 -3
  236. data/lib/fontisan/tables/hmtx.rb +0 -2
  237. data/lib/fontisan/tables/hmtx_table.rb +0 -3
  238. data/lib/fontisan/tables/hvar.rb +0 -3
  239. data/lib/fontisan/tables/loca.rb +0 -2
  240. data/lib/fontisan/tables/loca_table.rb +0 -3
  241. data/lib/fontisan/tables/maxp.rb +0 -2
  242. data/lib/fontisan/tables/maxp_table.rb +0 -3
  243. data/lib/fontisan/tables/mvar.rb +0 -3
  244. data/lib/fontisan/tables/name.rb +0 -2
  245. data/lib/fontisan/tables/name_table.rb +0 -3
  246. data/lib/fontisan/tables/os2_table.rb +0 -3
  247. data/lib/fontisan/tables/post_table.rb +0 -3
  248. data/lib/fontisan/tables/sbix.rb +0 -1
  249. data/lib/fontisan/tables/svg.rb +0 -1
  250. data/lib/fontisan/tables/variation_common.rb +0 -1
  251. data/lib/fontisan/tables/vvar.rb +0 -3
  252. data/lib/fontisan/tables.rb +54 -0
  253. data/lib/fontisan/true_type_collection.rb +6 -14
  254. data/lib/fontisan/true_type_font.rb +8 -2
  255. data/lib/fontisan/true_type_font_extensions.rb +9 -9
  256. data/lib/fontisan/type1/afm_generator.rb +0 -4
  257. data/lib/fontisan/type1/conversion_options.rb +0 -2
  258. data/lib/fontisan/type1/encodings.rb +0 -2
  259. data/lib/fontisan/type1/generator.rb +0 -8
  260. data/lib/fontisan/type1/pfa_generator.rb +0 -3
  261. data/lib/fontisan/type1/pfb_generator.rb +0 -5
  262. data/lib/fontisan/type1/pfm_generator.rb +0 -4
  263. data/lib/fontisan/type1.rb +42 -69
  264. data/lib/fontisan/type1_font.rb +40 -11
  265. data/lib/fontisan/ucd/aggregator.rb +73 -0
  266. data/lib/fontisan/ucd/cache_manager.rb +111 -0
  267. data/lib/fontisan/ucd/config.rb +59 -0
  268. data/lib/fontisan/ucd/download_error.rb +9 -0
  269. data/lib/fontisan/ucd/downloader.rb +88 -0
  270. data/lib/fontisan/ucd/error.rb +8 -0
  271. data/lib/fontisan/ucd/index.rb +103 -0
  272. data/lib/fontisan/ucd/index_builder.rb +107 -0
  273. data/lib/fontisan/ucd/range_entry.rb +56 -0
  274. data/lib/fontisan/ucd/unknown_version_error.rb +9 -0
  275. data/lib/fontisan/ucd/version_resolver.rb +79 -0
  276. data/lib/fontisan/ucd.rb +23 -0
  277. data/lib/fontisan/utilities/checksum_calculator.rb +0 -1
  278. data/lib/fontisan/utilities.rb +10 -0
  279. data/lib/fontisan/utils.rb +10 -0
  280. data/lib/fontisan/validation/collection_validator.rb +0 -2
  281. data/lib/fontisan/validation.rb +9 -0
  282. data/lib/fontisan/validators/basic_validator.rb +0 -2
  283. data/lib/fontisan/validators/font_book_validator.rb +0 -2
  284. data/lib/fontisan/validators/opentype_validator.rb +0 -2
  285. data/lib/fontisan/validators/profile_loader.rb +0 -5
  286. data/lib/fontisan/validators/validator.rb +0 -2
  287. data/lib/fontisan/validators/web_font_validator.rb +0 -2
  288. data/lib/fontisan/validators.rb +14 -0
  289. data/lib/fontisan/variable/delta_applicator.rb +0 -4
  290. data/lib/fontisan/variable/instancer.rb +0 -3
  291. data/lib/fontisan/variable/static_font_builder.rb +0 -3
  292. data/lib/fontisan/variable.rb +16 -0
  293. data/lib/fontisan/variation/blend_applier.rb +0 -2
  294. data/lib/fontisan/variation/cache.rb +0 -2
  295. data/lib/fontisan/variation/converter.rb +0 -3
  296. data/lib/fontisan/variation/data_extractor.rb +0 -2
  297. data/lib/fontisan/variation/delta_applier.rb +0 -5
  298. data/lib/fontisan/variation/inspector.rb +0 -1
  299. data/lib/fontisan/variation/instance_generator.rb +0 -6
  300. data/lib/fontisan/variation/instance_writer.rb +0 -5
  301. data/lib/fontisan/variation/metrics_adjuster.rb +0 -4
  302. data/lib/fontisan/variation/optimizer.rb +0 -3
  303. data/lib/fontisan/variation/parallel_generator.rb +0 -3
  304. data/lib/fontisan/variation/subsetter.rb +0 -4
  305. data/lib/fontisan/variation/tuple_variation_header.rb +0 -2
  306. data/lib/fontisan/variation/variable_svg_generator.rb +0 -3
  307. data/lib/fontisan/variation/variation_context.rb +0 -3
  308. data/lib/fontisan/variation/variation_preserver.rb +0 -3
  309. data/lib/fontisan/variation.rb +31 -0
  310. data/lib/fontisan/version.rb +1 -1
  311. data/lib/fontisan/woff2.rb +13 -0
  312. data/lib/fontisan/woff2_font.rb +31 -9
  313. data/lib/fontisan/woff_font.rb +31 -2
  314. data/lib/fontisan.rb +124 -196
  315. metadata +114 -7
  316. data/fontisan.gemspec +0 -48
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../../binary/base_record"
5
- require_relative "../cff/charstring"
6
4
 
7
5
  module Fontisan
8
6
  module Tables
@@ -1,12 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../cff/table_builder"
4
- require_relative "table_reader"
5
- require_relative "private_dict_blend_handler"
6
- require_relative "../cff/charstring_parser"
7
- require_relative "../cff/charstring_builder"
8
- require_relative "../cff/hint_operation_injector"
9
- require_relative "../cff/dict_builder"
10
3
  require "stringio"
11
4
 
12
5
  module Fontisan
@@ -493,8 +486,6 @@ vstore:)
493
486
  # @param dict [Hash] Top DICT hash with integer operator keys
494
487
  # @return [String] Binary DICT data
495
488
  def serialize_top_dict(dict)
496
- require_relative "../cff/dict_builder"
497
-
498
489
  # Convert integer operator keys to symbol keys for DictBuilder
499
490
  symbol_dict = convert_operators_to_symbols(dict)
500
491
  Cff::DictBuilder.build(symbol_dict)
@@ -505,8 +496,6 @@ vstore:)
505
496
  # @param dict [Hash] Private DICT hash
506
497
  # @return [String] Binary DICT data
507
498
  def serialize_private_dict(dict)
508
- require_relative "../cff/dict_builder"
509
-
510
499
  # Convert integer operator keys to symbol keys for DictBuilder
511
500
  symbol_dict = convert_operators_to_symbols(dict)
512
501
  Cff::DictBuilder.build(symbol_dict)
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../../binary/base_record"
5
4
 
6
5
  module Fontisan
7
6
  module Tables
@@ -233,7 +232,6 @@ module Fontisan
233
232
  # @return [Cff::Index] CharStrings INDEX
234
233
  def read_charstrings(offset)
235
234
  @io.seek(offset)
236
- require_relative "../cff/index"
237
235
  Cff::Index.new(@io, start_offset: offset)
238
236
  end
239
237
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../binary/base_record"
5
4
 
6
5
  module Fontisan
7
6
  module Tables
@@ -21,6 +20,19 @@ module Fontisan
21
20
  # cff2 = Fontisan::Tables::Cff2.read(data)
22
21
  # num_glyphs = cff2.glyph_count
23
22
  class Cff2 < Binary::BaseRecord
23
+ # Inner namespace autoloads — declared here so Cff2::* constants
24
+ # resolve on first reference without require_relative.
25
+ autoload :BlendOperator, "fontisan/tables/cff2/blend_operator"
26
+ autoload :CharstringParser, "fontisan/tables/cff2/charstring_parser"
27
+ autoload :OperandStack, "fontisan/tables/cff2/operand_stack"
28
+ autoload :PrivateDictBlendHandler,
29
+ "fontisan/tables/cff2/private_dict_blend_handler"
30
+ autoload :RegionMatcher, "fontisan/tables/cff2/region_matcher"
31
+ autoload :TableBuilder, "fontisan/tables/cff2/table_builder"
32
+ autoload :TableReader, "fontisan/tables/cff2/table_reader"
33
+ autoload :VariationDataExtractor,
34
+ "fontisan/tables/cff2/variation_data_extractor"
35
+
24
36
  # CFF2 header structure
25
37
  class Cff2Header < Binary::BaseRecord
26
38
  uint8 :major_version
@@ -105,7 +117,6 @@ module Fontisan
105
117
  return nil if charstring_data.nil?
106
118
 
107
119
  # Parse with CFF2 CharString parser
108
- require_relative "cff2/charstring_parser"
109
120
  CharstringParser.new(
110
121
  charstring_data,
111
122
  @num_axes,
@@ -159,7 +170,6 @@ module Fontisan
159
170
  io = StringIO.new(data)
160
171
  io.seek(offset)
161
172
 
162
- require_relative "cff/index"
163
173
  Cff::Index.new(io, start_offset: offset)
164
174
  rescue StandardError => e
165
175
  warn "Failed to parse Global Subr INDEX: #{e.message}"
@@ -212,7 +222,6 @@ module Fontisan
212
222
  io = StringIO.new(data)
213
223
  io.seek(offset)
214
224
 
215
- require_relative "cff/index"
216
225
  Cff::Index.new(io, start_offset: offset)
217
226
  rescue StandardError => e
218
227
  warn "Failed to parse CharStrings INDEX: #{e.message}"
@@ -334,13 +343,3 @@ module Fontisan
334
343
  end
335
344
  end
336
345
  end
337
-
338
- # Load CFF2 subcomponents
339
- require_relative "cff2/charstring_parser"
340
- require_relative "cff2/blend_operator"
341
- require_relative "cff2/operand_stack"
342
- require_relative "cff2/table_reader"
343
- require_relative "cff2/variation_data_extractor"
344
- require_relative "cff2/region_matcher"
345
- require_relative "cff2/private_dict_blend_handler"
346
- require_relative "cff2/table_builder"
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # Parser for the 'cmap' (Character to Glyph Index Mapping) table
@@ -347,6 +345,30 @@ module Fontisan
347
345
  false
348
346
  end
349
347
 
348
+ # Distinct subtable formats present in this cmap, sorted ascending.
349
+ #
350
+ # Each encoding record's subtable begins with a uint16 format tag.
351
+ # Returns the unique set of those formats across all records. Useful
352
+ # for audit reports that need to record which cmap subtables
353
+ # contributed to the Unicode mappings.
354
+ #
355
+ # @return [Array<Integer>] sorted unique format numbers
356
+ def subtable_formats
357
+ data = to_binary_s
358
+ records = read_encoding_records(data)
359
+
360
+ formats = records.filter_map do |record|
361
+ subtable_data = extract_subtable_data(record, data)
362
+ next nil unless subtable_data && subtable_data.length >= 2
363
+
364
+ subtable_data[0, 2].unpack1("n")
365
+ end
366
+
367
+ formats.uniq.sort
368
+ rescue StandardError
369
+ []
370
+ end
371
+
350
372
  # Validation helper: Check if glyph indices are within bounds
351
373
  #
352
374
  # @param max_glyph_id [Integer] Maximum valid glyph ID from maxp table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "cmap"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'cmap' (Character to Glyph Index Mapping) table
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../binary/base_record"
5
4
 
6
5
  module Fontisan
7
6
  module Tables
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../binary/base_record"
5
4
 
6
5
  module Fontisan
7
6
  module Tables
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../binary/base_record"
5
- require_relative "../variation/tuple_variation_header"
6
4
 
7
5
  module Fontisan
8
6
  module Tables
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../binary/base_record"
5
4
 
6
5
  module Fontisan
7
6
  module Tables
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../models/outline"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # Resolves compound glyphs into simple outlines
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../models/outline"
4
- require_relative "curve_converter"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # Builds binary TrueType glyph data from universal outline representation
@@ -1,11 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
- require_relative "glyf/simple_glyph"
5
- require_relative "glyf/compound_glyph"
6
- require_relative "glyf/curve_converter"
7
- require_relative "glyf/glyph_builder"
8
-
9
3
  module Fontisan
10
4
  module Tables
11
5
  # Parser for the 'glyf' (Glyph Data) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "glyf"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'glyf' (Glyph Data) table
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "layout_common"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # GPOS (Glyph Positioning) table parser
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "layout_common"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # GSUB (Glyph Substitution) table parser
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../binary/base_record"
5
- require_relative "../variation/tuple_variation_header"
6
4
 
7
5
  module Fontisan
8
6
  module Tables
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # BinData structure for the 'head' (Font Header) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "head"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'head' (Font Header) table
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # BinData structure for the 'hhea' (Horizontal Header) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "hhea"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'hhea' (Horizontal Header) table
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # Parser for the 'hmtx' (Horizontal Metrics) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "hmtx"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'hmtx' (Horizontal Metrics) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
- require_relative "variation_common"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # Parser for the 'HVAR' (Horizontal Metrics Variations) table
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # Parser for the 'loca' (Index to Location) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "loca"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'loca' (Index to Location) table
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # BinData structure for the 'maxp' (Maximum Profile) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "maxp"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'maxp' (Maximum Profile) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
- require_relative "variation_common"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # Parser for the 'MVAR' (Metrics Variations) table
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
-
5
3
  module Fontisan
6
4
  module Tables
7
5
  # BinData structure for a single name record
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "name"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'name' (Naming) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "os2"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'OS/2' (OS/2 and Windows Metrics) table
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../sfnt_table"
4
- require_relative "post"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # OOP representation of the 'post' (PostScript) table
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../binary/base_record"
5
4
 
6
5
  module Fontisan
7
6
  module Tables
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "stringio"
4
4
  require "zlib"
5
- require_relative "../binary/base_record"
6
5
 
7
6
  module Fontisan
8
7
  module Tables
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "stringio"
4
- require_relative "../binary/base_record"
5
4
 
6
5
  module Fontisan
7
6
  module Tables
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../binary/base_record"
4
- require_relative "variation_common"
5
-
6
3
  module Fontisan
7
4
  module Tables
8
5
  # Parser for the 'VVAR' (Vertical Metrics Variations) table
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Autoload hub for the Fontisan::Tables namespace.
4
+
5
+ module Fontisan
6
+ module Tables
7
+ autoload :Cbdt, "fontisan/tables/cbdt"
8
+ autoload :Cblc, "fontisan/tables/cblc"
9
+ autoload :Cff, "fontisan/tables/cff"
10
+ autoload :Cff2, "fontisan/tables/cff2"
11
+ autoload :Cmap, "fontisan/tables/cmap"
12
+ autoload :CmapTable, "fontisan/tables/cmap_table"
13
+ autoload :Colr, "fontisan/tables/colr"
14
+ autoload :CompoundGlyph, "fontisan/tables/glyf/compound_glyph"
15
+ autoload :CompoundGlyphResolver, "fontisan/tables/glyf/compound_glyph_resolver"
16
+ autoload :Cpal, "fontisan/tables/cpal"
17
+ autoload :CurveConverter, "fontisan/tables/glyf/curve_converter"
18
+ autoload :Cvar, "fontisan/tables/cvar"
19
+ autoload :Fvar, "fontisan/tables/fvar"
20
+ autoload :Glyf, "fontisan/tables/glyf"
21
+ autoload :GlyfTable, "fontisan/tables/glyf_table"
22
+ autoload :GlyphBuilder, "fontisan/tables/glyf/glyph_builder"
23
+ autoload :Gpos, "fontisan/tables/gpos"
24
+ autoload :Gsub, "fontisan/tables/gsub"
25
+ autoload :Gvar, "fontisan/tables/gvar"
26
+ autoload :Head, "fontisan/tables/head"
27
+ autoload :HeadTable, "fontisan/tables/head_table"
28
+ autoload :Hhea, "fontisan/tables/hhea"
29
+ autoload :HheaTable, "fontisan/tables/hhea_table"
30
+ autoload :Hmtx, "fontisan/tables/hmtx"
31
+ autoload :HmtxTable, "fontisan/tables/hmtx_table"
32
+ autoload :Hvar, "fontisan/tables/hvar"
33
+ autoload :InstanceRecord, "fontisan/tables/fvar"
34
+ autoload :LayoutCommon, "fontisan/tables/layout_common"
35
+ autoload :Loca, "fontisan/tables/loca"
36
+ autoload :LocaTable, "fontisan/tables/loca_table"
37
+ autoload :Maxp, "fontisan/tables/maxp"
38
+ autoload :MaxpTable, "fontisan/tables/maxp_table"
39
+ autoload :Mvar, "fontisan/tables/mvar"
40
+ autoload :Name, "fontisan/tables/name"
41
+ autoload :NameRecord, "fontisan/tables/name"
42
+ autoload :NameTable, "fontisan/tables/name_table"
43
+ autoload :Os2, "fontisan/tables/os2"
44
+ autoload :Os2Table, "fontisan/tables/os2_table"
45
+ autoload :Post, "fontisan/tables/post"
46
+ autoload :PostTable, "fontisan/tables/post_table"
47
+ autoload :Sbix, "fontisan/tables/sbix"
48
+ autoload :SimpleGlyph, "fontisan/tables/glyf/simple_glyph"
49
+ autoload :Svg, "fontisan/tables/svg"
50
+ autoload :VariationAxisRecord, "fontisan/tables/fvar"
51
+ autoload :VariationCommon, "fontisan/tables/variation_common"
52
+ autoload :Vvar, "fontisan/tables/vvar"
53
+ end
54
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base_collection"
4
-
5
3
  module Fontisan
6
4
  # TrueType Collection domain object
7
5
  #
@@ -15,11 +13,16 @@ module Fontisan
15
13
  # fonts = ttc.extract_fonts(io) # => [TrueTypeFont, TrueTypeFont, ...]
16
14
  # end
17
15
  class TrueTypeCollection < BaseCollection
16
+ # High-level pipeline format identifier. Owned by the collection class
17
+ # so the conversion pipeline can dispatch without case statements (OCP).
18
+ #
19
+ # @return [Symbol] :ttc
20
+ def format = :ttc
21
+
18
22
  # Get the font class for TrueType collections
19
23
  #
20
24
  # @return [Class] TrueTypeFont class
21
25
  def self.font_class
22
- require_relative "true_type_font"
23
26
  TrueTypeFont
24
27
  end
25
28
 
@@ -41,7 +44,6 @@ module Fontisan
41
44
  def font(index, io, mode: LoadingModes::FULL)
42
45
  return nil if index >= num_fonts
43
46
 
44
- require_relative "true_type_font"
45
47
  TrueTypeFont.from_collection(io, font_offsets[index], mode: mode)
46
48
  end
47
49
 
@@ -53,8 +55,6 @@ module Fontisan
53
55
  # @param io [IO] Open file handle to read fonts from
54
56
  # @return [Array<TrueTypeFont>] Array of font objects
55
57
  def extract_fonts(io)
56
- require_relative "true_type_font"
57
-
58
58
  font_offsets.map do |offset|
59
59
  TrueTypeFont.from_collection(io, offset)
60
60
  end
@@ -67,11 +67,6 @@ module Fontisan
67
67
  # @param io [IO] Open file handle to read fonts from
68
68
  # @return [CollectionListInfo] List of fonts with metadata
69
69
  def list_fonts(io)
70
- require_relative "models/collection_list_info"
71
- require_relative "models/collection_font_summary"
72
- require_relative "true_type_font"
73
- require_relative "tables/name"
74
-
75
70
  fonts = font_offsets.map.with_index do |offset, index|
76
71
  font = TrueTypeFont.from_collection(io, offset)
77
72
 
@@ -124,9 +119,6 @@ module Fontisan
124
119
  # @param io [IO] Open file handle
125
120
  # @return [TableSharingInfo] Sharing statistics
126
121
  def calculate_table_sharing(io)
127
- require_relative "models/table_sharing_info"
128
- require_relative "true_type_font"
129
-
130
122
  # Extract all fonts
131
123
  fonts = font_offsets.map do |offset|
132
124
  TrueTypeFont.from_collection(io, offset)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "sfnt_font"
4
-
5
3
  module Fontisan
6
4
  # TrueType Font domain object
7
5
  #
@@ -25,6 +23,14 @@ module Fontisan
25
23
  # @example Reading from TTC collection
26
24
  # ttf = TrueTypeFont.from_collection(io, offset)
27
25
  class TrueTypeFont < SfntFont
26
+ extend TrueTypeFontExtensions
27
+
28
+ # High-level pipeline format identifier. Owned by the font class so the
29
+ # conversion pipeline can dispatch without case statements (OCP).
30
+ #
31
+ # @return [Symbol] :ttf
32
+ def format = :ttf
33
+
28
34
  # Check if font is TrueType flavored
29
35
  #
30
36
  # @return [Boolean] true for TrueType fonts
@@ -1,24 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fontisan
4
- # Extensions to TrueTypeFont for table-based construction
5
- class TrueTypeFont
4
+ # Extension module for {TrueTypeFont} providing table-based construction.
5
+ #
6
+ # Extended into TrueTypeFont from +true_type_font.rb+ so that
7
+ # +TrueTypeFont.from_tables(...)+ is available whenever the class
8
+ # itself is loaded.
9
+ module TrueTypeFontExtensions
6
10
  # Create font from hash of tables
7
11
  #
8
12
  # This is used during font conversion when we have tables but not a file.
9
13
  #
10
14
  # @param tables [Hash<String, String>] Map of table tag to binary data
11
15
  # @return [TrueTypeFont] New font instance
12
- def self.from_tables(tables)
13
- # Create minimal header structure
16
+ def from_tables(tables)
14
17
  font = new
15
18
  font.initialize_storage
16
19
  font.loading_mode = LoadingModes::FULL
17
20
 
18
- # Store table data
19
21
  font.table_data = tables
20
22
 
21
- # Build header from tables
22
23
  num_tables = tables.size
23
24
  max_power = 0
24
25
  n = num_tables
@@ -37,13 +38,12 @@ module Fontisan
37
38
  font.header.entry_selector = entry_selector
38
39
  font.header.range_shift = range_shift
39
40
 
40
- # Build table directory
41
41
  font.tables.clear
42
42
  tables.each_key do |tag|
43
43
  entry = TableDirectory.new
44
44
  entry.tag = tag
45
- entry.checksum = 0 # Will be calculated on write
46
- entry.offset = 0 # Will be calculated on write
45
+ entry.checksum = 0
46
+ entry.offset = 0
47
47
  entry.table_length = tables[tag].bytesize
48
48
  font.tables << entry
49
49
  end