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,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "validator"
4
- require_relative "optimizer"
5
- require_relative "table_accessor"
6
-
7
3
  module Fontisan
8
4
  module Variation
9
5
  # Subset variable fonts while preserving variation
@@ -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 Variation
7
5
  # Tuple variation header structure
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "instance_generator"
4
- require_relative "../converters/svg_generator"
5
-
6
3
  module Fontisan
7
4
  module Variation
8
5
  # Generates SVG fonts from variable fonts at specific coordinates
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "interpolator"
4
- require_relative "region_matcher"
5
-
6
3
  module Fontisan
7
4
  module Variation
8
5
  # Provides shared context for variation operations
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "variation_context"
4
- require_relative "../error"
5
-
6
3
  module Fontisan
7
4
  module Variation
8
5
  # Preserves variation data when converting between compatible font formats
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Autoload hub for the Fontisan::Variation namespace.
4
+
5
+ module Fontisan
6
+ module Variation
7
+ autoload :BlendApplier, "fontisan/variation/blend_applier"
8
+ autoload :Cache, "fontisan/variation/cache"
9
+ autoload :CacheKeyBuilder, "fontisan/variation/cache_key_builder"
10
+ autoload :Converter, "fontisan/variation/converter"
11
+ autoload :DataExtractor, "fontisan/variation/data_extractor"
12
+ autoload :DeltaApplier, "fontisan/variation/delta_applier"
13
+ autoload :DeltaParser, "fontisan/variation/delta_parser"
14
+ autoload :Inspector, "fontisan/variation/inspector"
15
+ autoload :InstanceGenerator, "fontisan/variation/instance_generator"
16
+ autoload :InstanceWriter, "fontisan/variation/instance_writer"
17
+ autoload :Interpolator, "fontisan/variation/interpolator"
18
+ autoload :MetricsAdjuster, "fontisan/variation/metrics_adjuster"
19
+ autoload :Optimizer, "fontisan/variation/optimizer"
20
+ autoload :ParallelGenerator, "fontisan/variation/parallel_generator"
21
+ autoload :RegionMatcher, "fontisan/variation/region_matcher"
22
+ autoload :Subsetter, "fontisan/variation/subsetter"
23
+ autoload :TableAccessor, "fontisan/variation/table_accessor"
24
+ autoload :ThreadSafeCache, "fontisan/variation/cache"
25
+ autoload :TupleVariationHeader, "fontisan/variation/tuple_variation_header"
26
+ autoload :Validator, "fontisan/variation/validator"
27
+ autoload :VariableSvgGenerator, "fontisan/variation/variable_svg_generator"
28
+ autoload :VariationContext, "fontisan/variation/variation_context"
29
+ autoload :VariationPreserver, "fontisan/variation/variation_preserver"
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fontisan
4
- VERSION = "0.2.17"
4
+ VERSION = "0.2.22"
5
5
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Autoload hub for the Fontisan::Woff2 namespace.
4
+
5
+ module Fontisan
6
+ module Woff2
7
+ autoload :Directory, "fontisan/woff2/directory"
8
+ autoload :GlyfTransformer, "fontisan/woff2/glyf_transformer"
9
+ autoload :HmtxTransformer, "fontisan/woff2/hmtx_transformer"
10
+ autoload :TableTransformer, "fontisan/woff2/table_transformer"
11
+ autoload :Woff2Header, "fontisan/woff2/header"
12
+ end
13
+ end
@@ -3,15 +3,6 @@
3
3
  require "bindata"
4
4
  require "brotli"
5
5
  require "stringio"
6
- require_relative "constants"
7
- require_relative "loading_modes"
8
- require_relative "utilities/checksum_calculator"
9
- require_relative "woff2/header"
10
- require_relative "woff2/glyf_transformer"
11
- require_relative "woff2/hmtx_transformer"
12
- require_relative "true_type_font"
13
- require_relative "open_type_font"
14
- require_relative "error"
15
6
 
16
7
  module Fontisan
17
8
  # WOFF2 Table Directory Entry structure
@@ -82,6 +73,12 @@ module Fontisan
82
73
  # puts font.header.flavor
83
74
  # puts font.table_names
84
75
  class Woff2Font
76
+ # High-level pipeline format identifier. Owned by the font class so the
77
+ # conversion pipeline can dispatch without case statements (OCP).
78
+ #
79
+ # @return [Symbol] :woff2
80
+ def format = :woff2
81
+
85
82
  # Simple struct for storing file path
86
83
  IOSource = Struct.new(:path)
87
84
 
@@ -145,6 +142,31 @@ module Fontisan
145
142
  @table_entries.any? { |entry| entry.tag == tag }
146
143
  end
147
144
 
145
+ # Whether this object represents a font collection rather than a single
146
+ # font. Each font class is the authority on this question.
147
+ #
148
+ # @return [Boolean]
149
+ def collection? = false
150
+
151
+ # Variation profile. WOFF2 wraps a single SFNT font; variation tables, if
152
+ # present on the wrapped font, are reported here.
153
+ #
154
+ # @return [Symbol] :static, :gvar, or :cff2
155
+ def variation_type
156
+ return :static unless has_table?("fvar")
157
+ return :gvar if has_table?("gvar")
158
+ return :cff2 if has_table?("CFF2")
159
+
160
+ :static
161
+ end
162
+
163
+ # Outline representation, derived from the wrapped SFNT flavor.
164
+ #
165
+ # @return [Symbol] :truetype or :cff
166
+ def outline_type
167
+ truetype? ? :truetype : :cff
168
+ end
169
+
148
170
  # Find table entry by tag
149
171
  def find_table_entry(tag)
150
172
  @table_entries.find { |entry| entry.tag == tag }
@@ -2,8 +2,6 @@
2
2
 
3
3
  require "bindata"
4
4
  require "zlib"
5
- require_relative "constants"
6
- require_relative "utilities/checksum_calculator"
7
5
 
8
6
  module Fontisan
9
7
  # WOFF Header structure
@@ -55,6 +53,12 @@ module Fontisan
55
53
  # woff.to_ttf("output.ttf") # if TrueType flavored
56
54
  # woff.to_otf("output.otf") # if CFF flavored
57
55
  class WoffFont < BinData::Record
56
+ # High-level pipeline format identifier. Owned by the font class so the
57
+ # conversion pipeline can dispatch without case statements (OCP).
58
+ #
59
+ # @return [Symbol] :woff
60
+ def format = :woff
61
+
58
62
  endian :big
59
63
 
60
64
  woff_header :header
@@ -142,6 +146,31 @@ module Fontisan
142
146
  end
143
147
  end
144
148
 
149
+ # Whether this object represents a font collection rather than a single
150
+ # font. Each font class is the authority on this question.
151
+ #
152
+ # @return [Boolean]
153
+ def collection? = false
154
+
155
+ # Variation profile. WOFF wraps a single SFNT font; variation tables, if
156
+ # present on the wrapped font, are reported here.
157
+ #
158
+ # @return [Symbol] :static, :gvar, or :cff2
159
+ def variation_type
160
+ return :static unless has_table?("fvar")
161
+ return :gvar if has_table?("gvar")
162
+ return :cff2 if has_table?("CFF2")
163
+
164
+ :static
165
+ end
166
+
167
+ # Outline representation, derived from the wrapped SFNT flavor.
168
+ #
169
+ # @return [Symbol] :truetype or :cff
170
+ def outline_type
171
+ truetype? ? :truetype : :cff
172
+ end
173
+
145
174
  # Check if font is TrueType flavored
146
175
  #
147
176
  # @return [Boolean] true if TrueType, false if CFF
data/lib/fontisan.rb CHANGED
@@ -39,203 +39,96 @@ Lutaml::Model::Config.configure do |config|
39
39
  config.xml_adapter_type = :nokogiri
40
40
  end
41
41
 
42
- # Core
43
- require_relative "fontisan/version"
44
- require_relative "fontisan/error"
45
- require_relative "fontisan/constants"
46
-
47
- # Binary structures and parsers
48
- require_relative "fontisan/parsers/tag"
49
- require_relative "fontisan/binary/base_record"
50
-
51
- # Table parsers
52
- require_relative "fontisan/tables/head"
53
- require_relative "fontisan/tables/hhea"
54
- require_relative "fontisan/tables/hmtx"
55
- require_relative "fontisan/tables/maxp"
56
- require_relative "fontisan/tables/loca"
57
- require_relative "fontisan/tables/glyf"
58
- require_relative "fontisan/tables/name"
59
- require_relative "fontisan/tables/os2"
60
- require_relative "fontisan/tables/post"
61
- require_relative "fontisan/tables/cmap"
62
- require_relative "fontisan/tables/fvar"
63
- require_relative "fontisan/tables/variation_common"
64
- require_relative "fontisan/tables/hvar"
65
- require_relative "fontisan/tables/vvar"
66
- require_relative "fontisan/tables/mvar"
67
- require_relative "fontisan/tables/gvar"
68
- require_relative "fontisan/tables/cvar"
69
- require_relative "fontisan/tables/cff"
70
- require_relative "fontisan/tables/layout_common"
71
- require_relative "fontisan/tables/gsub"
72
- require_relative "fontisan/tables/gpos"
73
- require_relative "fontisan/tables/colr"
74
- require_relative "fontisan/tables/cpal"
75
- require_relative "fontisan/tables/svg"
76
- require_relative "fontisan/tables/sbix"
77
- require_relative "fontisan/tables/cblc"
78
- require_relative "fontisan/tables/cbdt"
79
-
80
- # Domain objects (BinData::Record)
81
- require_relative "fontisan/true_type_font"
82
- require_relative "fontisan/open_type_font"
83
- require_relative "fontisan/true_type_collection"
84
- require_relative "fontisan/open_type_collection"
85
- require_relative "fontisan/woff_font"
86
- require_relative "fontisan/woff2_font"
87
- require_relative "fontisan/type1_font"
88
-
89
- # Font extensions for table-based construction
90
- require_relative "fontisan/true_type_font_extensions"
91
- require_relative "fontisan/open_type_font_extensions"
92
-
93
- # Font loading
94
- require_relative "fontisan/font_loader"
95
-
96
- # Utilities
97
- require_relative "fontisan/metrics_calculator"
98
- require_relative "fontisan/glyph_accessor"
99
- require_relative "fontisan/outline_extractor"
100
- require_relative "fontisan/utilities/checksum_calculator"
101
- require_relative "fontisan/font_writer"
102
-
103
- # Information models (Lutaml::Model)
104
- require_relative "fontisan/models/bitmap_strike"
105
- require_relative "fontisan/models/bitmap_glyph"
106
- require_relative "fontisan/models/font_info"
107
- require_relative "fontisan/models/table_info"
108
- require_relative "fontisan/models/glyph_info"
109
- require_relative "fontisan/models/glyph_outline"
110
- require_relative "fontisan/models/unicode_mappings"
111
- require_relative "fontisan/models/variable_font_info"
112
- require_relative "fontisan/models/optical_size_info"
113
- require_relative "fontisan/models/scripts_info"
114
- require_relative "fontisan/models/features_info"
115
- require_relative "fontisan/models/all_scripts_features_info"
116
- require_relative "fontisan/models/validation_report"
117
- require_relative "fontisan/models/font_report"
118
- require_relative "fontisan/models/collection_validation_report"
119
- require_relative "fontisan/models/font_export"
120
- require_relative "fontisan/models/collection_font_summary"
121
- require_relative "fontisan/models/collection_info"
122
- require_relative "fontisan/models/collection_brief_info"
123
- require_relative "fontisan/models/collection_list_info"
124
- require_relative "fontisan/models/font_summary"
125
- require_relative "fontisan/models/table_sharing_info"
126
- require_relative "fontisan/models/color_glyph"
127
- require_relative "fontisan/models/color_layer"
128
- require_relative "fontisan/models/color_palette"
129
- require_relative "fontisan/models/svg_glyph"
130
-
131
- # Validators infrastructure (NEW - DSL-based framework from Week 2+)
132
- require_relative "fontisan/validators/validator"
133
- require_relative "fontisan/validators/basic_validator"
134
- require_relative "fontisan/validators/font_book_validator"
135
- require_relative "fontisan/validators/opentype_validator"
136
- require_relative "fontisan/validators/web_font_validator"
137
- require_relative "fontisan/validators/profile_loader"
138
-
139
- # Export infrastructure
140
- require_relative "fontisan/export/table_serializer"
141
- require_relative "fontisan/export/ttx_generator"
142
- require_relative "fontisan/export/ttx_parser"
143
- require_relative "fontisan/export/exporter"
144
-
145
- # Validation infrastructure (OLD - commented out for new DSL framework)
146
- # Week 1 deleted these, Week 2-5 building new DSL-based framework
147
- # require_relative "fontisan/validation/checks/base_check"
148
- # require_relative "fontisan/validation/check_registry"
149
- # require_relative "fontisan/validation/profile"
150
- # require_relative "fontisan/validation/table_validator"
151
- # require_relative "fontisan/validation/structure_validator"
152
- # require_relative "fontisan/validation/consistency_validator"
153
- # require_relative "fontisan/validation/checksum_validator"
154
- # require_relative "fontisan/validation/validator"
155
-
156
- # Subsetting infrastructure
157
- require_relative "fontisan/subset/options"
158
- require_relative "fontisan/subset/profile"
159
- require_relative "fontisan/subset/glyph_mapping"
160
- require_relative "fontisan/subset/table_subsetter"
161
- require_relative "fontisan/subset/builder"
162
-
163
- # Collection infrastructure
164
- require_relative "fontisan/collection/table_analyzer"
165
- require_relative "fontisan/collection/table_deduplicator"
166
- require_relative "fontisan/collection/offset_calculator"
167
- require_relative "fontisan/collection/writer"
168
- require_relative "fontisan/collection/builder"
169
-
170
- # Format conversion infrastructure
171
- require_relative "fontisan/conversion_options"
172
- require_relative "fontisan/converters/conversion_strategy"
173
- require_relative "fontisan/converters/table_copier"
174
- require_relative "fontisan/converters/outline_converter"
175
- require_relative "fontisan/converters/format_converter"
176
-
177
- # Variation infrastructure
178
- require_relative "fontisan/variation/interpolator"
179
- require_relative "fontisan/variation/region_matcher"
180
- require_relative "fontisan/variation/data_extractor"
181
- require_relative "fontisan/variation/instance_generator"
182
- require_relative "fontisan/variation/metrics_adjuster"
183
- require_relative "fontisan/variation/converter"
184
- require_relative "fontisan/variation/variation_preserver"
185
- require_relative "fontisan/variation/delta_parser"
186
- require_relative "fontisan/variation/delta_applier"
187
- require_relative "fontisan/variation/blend_applier"
188
- require_relative "fontisan/variation/variable_svg_generator"
189
-
190
- # Pipeline infrastructure
191
- require_relative "fontisan/pipeline/format_detector"
192
- require_relative "fontisan/pipeline/variation_resolver"
193
- require_relative "fontisan/pipeline/output_writer"
194
- require_relative "fontisan/pipeline/transformation_pipeline"
195
-
196
- # Optimization infrastructure
197
- require_relative "fontisan/optimizers/pattern_analyzer"
198
- require_relative "fontisan/optimizers/subroutine_builder"
199
- require_relative "fontisan/optimizers/charstring_rewriter"
200
- require_relative "fontisan/optimizers/subroutine_optimizer"
201
- require_relative "fontisan/optimizers/subroutine_generator"
202
-
203
- # Hints infrastructure
204
- require_relative "fontisan/models/hint"
205
- require_relative "fontisan/hints/truetype_instruction_analyzer"
206
- require_relative "fontisan/hints/truetype_instruction_generator"
207
- require_relative "fontisan/hints/truetype_hint_extractor"
208
- require_relative "fontisan/hints/truetype_hint_applier"
209
- require_relative "fontisan/hints/postscript_hint_extractor"
210
- require_relative "fontisan/hints/postscript_hint_applier"
211
- require_relative "fontisan/hints/hint_converter"
212
- require_relative "fontisan/hints/hint_validator"
213
-
214
- # Commands
215
- require_relative "fontisan/commands/base_command"
216
- require_relative "fontisan/commands/info_command"
217
- require_relative "fontisan/commands/ls_command"
218
- require_relative "fontisan/commands/tables_command"
219
- require_relative "fontisan/commands/glyphs_command"
220
- require_relative "fontisan/commands/unicode_command"
221
- require_relative "fontisan/commands/variable_command"
222
- require_relative "fontisan/commands/optical_size_command"
223
- require_relative "fontisan/commands/scripts_command"
224
- require_relative "fontisan/commands/features_command"
225
- require_relative "fontisan/commands/dump_table_command"
226
- require_relative "fontisan/commands/subset_command"
227
- require_relative "fontisan/commands/convert_command"
228
- require_relative "fontisan/commands/pack_command"
229
- require_relative "fontisan/commands/unpack_command"
230
- require_relative "fontisan/commands/validate_command"
231
-
232
- # Formatters
233
- require_relative "fontisan/formatters/text_formatter"
234
-
235
- # CLI
236
- require_relative "fontisan/cli"
237
-
238
42
  module Fontisan
43
+ #
44
+ # Each namespace under Fontisan has a hub file at lib/fontisan/<ns>.rb
45
+ # that declares autoloads for its children. This file autoloads those
46
+ # hubs plus the flat Fontisan::* classes. Files are loaded lazily on
47
+ # first reference.
48
+
49
+ # Core
50
+ require "fontisan/version"
51
+ autoload :Constants, "fontisan/constants"
52
+ autoload :LoadingModes, "fontisan/loading_modes"
53
+ autoload :ConversionOptions, "fontisan/conversion_options"
54
+
55
+ # Errors (all defined in fontisan/error)
56
+ autoload :Error, "fontisan/error"
57
+ autoload :InvalidFontError, "fontisan/error"
58
+ autoload :UnsupportedFormatError, "fontisan/error"
59
+ autoload :CorruptedTableError, "fontisan/error"
60
+ autoload :MissingTableError, "fontisan/error"
61
+ autoload :ParseError, "fontisan/error"
62
+ autoload :SubsettingError, "fontisan/error"
63
+ autoload :VariationError, "fontisan/error"
64
+ autoload :InvalidCoordinatesError, "fontisan/error"
65
+ autoload :MissingVariationTableError, "fontisan/error"
66
+ autoload :InvalidAxisError, "fontisan/error"
67
+ autoload :RegionOverlapError, "fontisan/error"
68
+ autoload :DeltaMismatchError, "fontisan/error"
69
+ autoload :InvalidInstanceIndexError, "fontisan/error"
70
+ autoload :CorruptedVariationDataError, "fontisan/error"
71
+ autoload :InvalidVariationDataError, "fontisan/error"
72
+ autoload :VariationDataCorruptedError, "fontisan/error"
73
+
74
+ # Namespace hubs (each hub declares its own child autoloads)
75
+ autoload :Audit, "fontisan/audit"
76
+ autoload :Binary, "fontisan/binary"
77
+ autoload :Cldr, "fontisan/cldr"
78
+ autoload :Collection, "fontisan/collection"
79
+ autoload :Commands, "fontisan/commands"
80
+ autoload :Converters, "fontisan/converters"
81
+ autoload :Export, "fontisan/export"
82
+ autoload :Formatters, "fontisan/formatters"
83
+ autoload :Hints, "fontisan/hints"
84
+ autoload :Models, "fontisan/models"
85
+ autoload :Optimizers, "fontisan/optimizers"
86
+ autoload :Parsers, "fontisan/parsers"
87
+ autoload :Pipeline, "fontisan/pipeline"
88
+ autoload :Subset, "fontisan/subset"
89
+ autoload :Svg, "fontisan/svg"
90
+ autoload :Tables, "fontisan/tables"
91
+ autoload :Type1, "fontisan/type1"
92
+ autoload :Ucd, "fontisan/ucd"
93
+ autoload :Utilities, "fontisan/utilities"
94
+ autoload :Utils, "fontisan/utils"
95
+ autoload :Validation, "fontisan/validation"
96
+ autoload :Validators, "fontisan/validators"
97
+ autoload :Variable, "fontisan/variable"
98
+ autoload :Variation, "fontisan/variation"
99
+ autoload :Woff2, "fontisan/woff2"
100
+
101
+ # Flat classes (no inner namespace)
102
+ autoload :BaseCollection, "fontisan/base_collection"
103
+ autoload :Cli, "fontisan/cli"
104
+ autoload :DfontCollection, "fontisan/dfont_collection"
105
+ autoload :FontLoader, "fontisan/font_loader"
106
+ autoload :FontWriter, "fontisan/font_writer"
107
+ autoload :GlyphAccessor, "fontisan/glyph_accessor"
108
+ autoload :MetricsCalculator, "fontisan/metrics_calculator"
109
+ autoload :OpenTypeCollection, "fontisan/open_type_collection"
110
+ autoload :OpenTypeFont, "fontisan/open_type_font"
111
+ autoload :OpenTypeFontExtensions, "fontisan/open_type_font_extensions"
112
+ autoload :OutlineExtractor, "fontisan/outline_extractor"
113
+ autoload :SfntFont, "fontisan/sfnt_font"
114
+ autoload :SfntTable, "fontisan/sfnt_table"
115
+ autoload :TrueTypeCollection, "fontisan/true_type_collection"
116
+ autoload :TrueTypeFont, "fontisan/true_type_font"
117
+ autoload :TrueTypeFontExtensions, "fontisan/true_type_font_extensions"
118
+ autoload :Type1Font, "fontisan/type1_font"
119
+ autoload :UcdCli, "fontisan/cli/ucd_cli"
120
+ autoload :CldrCli, "fontisan/cli/cldr_cli"
121
+ autoload :Woff2Font, "fontisan/woff2_font"
122
+ autoload :WoffFont, "fontisan/woff_font"
123
+
124
+ # SFNT offset table and table directory (defined in sfnt_font.rb)
125
+ autoload :OffsetTable, "fontisan/sfnt_font"
126
+ autoload :TableDirectory, "fontisan/sfnt_font"
127
+
128
+ # WOFF headers and table directory entries
129
+ autoload :WoffHeader, "fontisan/woff_font"
130
+ autoload :WoffTableDirectoryEntry, "fontisan/woff_font"
131
+ autoload :Woff2TableDirectoryEntry, "fontisan/woff2_font"
239
132
  class << self
240
133
  attr_accessor :logger
241
134
 
@@ -279,6 +172,41 @@ module Fontisan
279
172
  Commands::InfoCommand.new(path, brief: brief, font_index: font_index).run
280
173
  end
281
174
 
175
+ # Convert a font to a different format.
176
+ #
177
+ # Delegates to {Commands::ConvertCommand}. Format-specific compression knobs
178
+ # are declared by each strategy (single source of truth) and forwarded
179
+ # through the transformation pipeline.
180
+ #
181
+ # WOFF uses zlib and runs on every browser that supports web fonts (IE9+,
182
+ # all evergreen browsers). WOFF2 uses Brotli for ~30% smaller output but
183
+ # requires modern browsers — use WOFF when legacy support matters.
184
+ #
185
+ # @param path [String] Input font file
186
+ # @param to [Symbol, String] Target format: :ttf, :otf, :type1, :woff,
187
+ # :woff2, :svg, :ttc, :otc, :dfont
188
+ # @param output [String] Output font file path
189
+ # @param opts [Hash] Conversion options. Format-specific knobs:
190
+ # - WOFF: :zlib_level (0–9, default 6), :uncompressed (bool),
191
+ # :compression_threshold (bytes)
192
+ # - WOFF2: :brotli_quality (0–11, default 11), :transform_tables (bool)
193
+ # - Variable fonts: :coordinates, :instance_index, :preserve_variation
194
+ # - Collections: :target_format ("preserve"|"ttf"|"otf")
195
+ # @return [Hash] Result hash with :success, :output_path, source/target
196
+ # format, input/output sizes, and variation strategy.
197
+ #
198
+ # @example TTF → WOFF2 (modern browsers)
199
+ # Fontisan.convert("f.ttf", to: :woff2, output: "f.woff2", brotli_quality: 11)
200
+ #
201
+ # @example TTF → WOFF (legacy browsers, max zlib)
202
+ # Fontisan.convert("f.ttf", to: :woff, output: "f.woff", zlib_level: 9)
203
+ #
204
+ # @example WOFF with no compression (legal per WOFF 1.0 §5.1)
205
+ # Fontisan.convert("f.ttf", to: :woff, output: "f.woff", uncompressed: true)
206
+ def self.convert(path, to:, output:, **)
207
+ Commands::ConvertCommand.new(path, { to: to, output: output, ** }).run
208
+ end
209
+
282
210
  # Validate a font file using specified profile
283
211
  #
284
212
  # Validates fonts against quality checks, structural integrity, and OpenType