fontisan 0.2.16 → 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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +14 -90
- data/Gemfile +6 -3
- data/README.adoc +257 -1
- data/docs/.vitepress/config.ts +68 -8
- data/docs/.vitepress/theme/style.css +570 -272
- data/docs/CONVERSION_GUIDE.adoc +31 -8
- data/docs/EXTRACT_TTC_MIGRATION.md +1 -1
- data/docs/WOFF_WOFF2_FORMATS.adoc +53 -0
- data/docs/api/conversion-options.md +37 -14
- data/docs/api/font-loader.md +21 -15
- data/docs/cli/audit.md +337 -0
- data/docs/cli/convert.md +20 -1
- data/docs/cli/index.md +31 -0
- data/docs/guide/color.md +1 -1
- data/docs/guide/conversion/options.md +32 -3
- data/docs/guide/conversion/ttf-otf.md +1 -1
- data/docs/guide/conversion/type1.md +1 -1
- data/docs/guide/conversion/web.md +91 -32
- data/docs/guide/conversion.md +6 -5
- data/docs/guide/formats/woff.md +35 -11
- data/docs/guide/index.md +2 -2
- data/docs/guide/migrations/extract-ttc.md +1 -1
- data/docs/guide/quick-start.md +4 -4
- data/docs/guide/type1.md +4 -4
- data/docs/guide/woff.md +19 -17
- data/docs/index.md +2 -0
- data/docs/lychee.toml +5 -1
- data/docs/package.json +1 -1
- data/docs/public/robots.txt +4 -0
- data/docs/scripts/post-build.mjs +81 -0
- data/lib/fontisan/audit/codepoint_range_coalescer.rb +41 -0
- data/lib/fontisan/audit/context.rb +122 -0
- data/lib/fontisan/audit/differ.rb +124 -0
- data/lib/fontisan/audit/extractors/aggregations.rb +54 -0
- data/lib/fontisan/audit/extractors/base.rb +26 -0
- data/lib/fontisan/audit/extractors/color_capabilities.rb +141 -0
- data/lib/fontisan/audit/extractors/coverage.rb +48 -0
- data/lib/fontisan/audit/extractors/hinting.rb +197 -0
- data/lib/fontisan/audit/extractors/identity.rb +52 -0
- data/lib/fontisan/audit/extractors/language_coverage.rb +37 -0
- data/lib/fontisan/audit/extractors/licensing.rb +79 -0
- data/lib/fontisan/audit/extractors/metrics.rb +103 -0
- data/lib/fontisan/audit/extractors/opentype_layout.rb +69 -0
- data/lib/fontisan/audit/extractors/provenance.rb +29 -0
- data/lib/fontisan/audit/extractors/style.rb +32 -0
- data/lib/fontisan/audit/extractors/variation_detail.rb +99 -0
- data/lib/fontisan/audit/extractors.rb +27 -0
- data/lib/fontisan/audit/library_aggregator.rb +83 -0
- data/lib/fontisan/audit/library_auditor.rb +90 -0
- data/lib/fontisan/audit/registry.rb +60 -0
- data/lib/fontisan/audit/style_extractor.rb +80 -0
- data/lib/fontisan/audit.rb +20 -0
- data/lib/fontisan/base_collection.rb +23 -9
- data/lib/fontisan/binary/structures.rb +0 -2
- data/lib/fontisan/binary.rb +11 -0
- data/lib/fontisan/cldr/aggregator.rb +33 -0
- data/lib/fontisan/cldr/cache_manager.rb +110 -0
- data/lib/fontisan/cldr/config.rb +59 -0
- data/lib/fontisan/cldr/download_error.rb +9 -0
- data/lib/fontisan/cldr/downloader.rb +79 -0
- data/lib/fontisan/cldr/error.rb +8 -0
- data/lib/fontisan/cldr/index.rb +64 -0
- data/lib/fontisan/cldr/index_builder.rb +72 -0
- data/lib/fontisan/cldr/unicode_set_parser.rb +172 -0
- data/lib/fontisan/cldr/unknown_version_error.rb +9 -0
- data/lib/fontisan/cldr/version_resolver.rb +91 -0
- data/lib/fontisan/cldr.rb +23 -0
- data/lib/fontisan/cli/cldr_cli.rb +85 -0
- data/lib/fontisan/cli/ucd_cli.rb +97 -0
- data/lib/fontisan/cli.rb +201 -2
- data/lib/fontisan/collection/builder.rb +0 -4
- data/lib/fontisan/collection/dfont_builder.rb +0 -4
- data/lib/fontisan/collection/shared_logic.rb +0 -2
- data/lib/fontisan/collection/writer.rb +0 -3
- data/lib/fontisan/collection.rb +15 -0
- data/lib/fontisan/commands/audit_command.rb +123 -0
- data/lib/fontisan/commands/audit_compare_command.rb +66 -0
- data/lib/fontisan/commands/audit_library_command.rb +46 -0
- data/lib/fontisan/commands/base_command.rb +0 -3
- data/lib/fontisan/commands/convert_command.rb +25 -20
- data/lib/fontisan/commands/dump_table_command.rb +0 -3
- data/lib/fontisan/commands/export_command.rb +0 -4
- data/lib/fontisan/commands/features_command.rb +0 -3
- data/lib/fontisan/commands/instance_command.rb +0 -5
- data/lib/fontisan/commands/ls_command.rb +0 -6
- data/lib/fontisan/commands/optical_size_command.rb +0 -3
- data/lib/fontisan/commands/pack_command.rb +0 -5
- data/lib/fontisan/commands/scripts_command.rb +0 -2
- data/lib/fontisan/commands/subset_command.rb +0 -3
- data/lib/fontisan/commands/unicode_command.rb +0 -3
- data/lib/fontisan/commands/unpack_command.rb +0 -7
- data/lib/fontisan/commands/validate_command.rb +0 -8
- data/lib/fontisan/commands/variable_command.rb +0 -3
- data/lib/fontisan/commands.rb +29 -0
- data/lib/fontisan/config/cldr.yml +22 -0
- data/lib/fontisan/config/conversion_matrix.yml +38 -0
- data/lib/fontisan/config/ucd.yml +23 -0
- data/lib/fontisan/constants.rb +48 -6
- data/lib/fontisan/conversion_options.rb +30 -19
- data/lib/fontisan/converters/cff_table_builder.rb +0 -3
- data/lib/fontisan/converters/collection_converter.rb +0 -8
- data/lib/fontisan/converters/conversion_strategy.rb +161 -46
- data/lib/fontisan/converters/format_converter.rb +143 -32
- data/lib/fontisan/converters/glyf_table_builder.rb +0 -2
- data/lib/fontisan/converters/outline_converter.rb +0 -19
- data/lib/fontisan/converters/outline_extraction.rb +0 -5
- data/lib/fontisan/converters/outline_optimizer.rb +0 -5
- data/lib/fontisan/converters/svg_generator.rb +0 -4
- data/lib/fontisan/converters/table_copier.rb +0 -2
- data/lib/fontisan/converters/type1_converter.rb +0 -11
- data/lib/fontisan/converters/woff2_encoder.rb +49 -20
- data/lib/fontisan/converters/woff_writer.rb +211 -282
- data/lib/fontisan/converters.rb +21 -0
- data/lib/fontisan/dfont_collection.rb +29 -10
- data/lib/fontisan/export/exporter.rb +0 -6
- data/lib/fontisan/export/transformers/font_to_ttx.rb +0 -9
- data/lib/fontisan/export/transformers/head_transformer.rb +0 -2
- data/lib/fontisan/export/transformers/hhea_transformer.rb +0 -2
- data/lib/fontisan/export/transformers/maxp_transformer.rb +0 -2
- data/lib/fontisan/export/transformers/name_transformer.rb +0 -2
- data/lib/fontisan/export/transformers/os2_transformer.rb +0 -2
- data/lib/fontisan/export/transformers/post_transformer.rb +0 -2
- data/lib/fontisan/export/transformers.rb +17 -0
- data/lib/fontisan/export.rb +13 -0
- data/lib/fontisan/font_loader.rb +189 -328
- data/lib/fontisan/font_writer.rb +0 -1
- data/lib/fontisan/formatters/audit_diff_text_renderer.rb +122 -0
- data/lib/fontisan/formatters/audit_text_renderer.rb +324 -0
- data/lib/fontisan/formatters/library_summary_text_renderer.rb +99 -0
- data/lib/fontisan/formatters/text_formatter.rb +6 -0
- data/lib/fontisan/formatters.rb +12 -0
- data/lib/fontisan/hints/hint_converter.rb +0 -1
- data/lib/fontisan/hints/postscript_hint_applier.rb +0 -9
- data/lib/fontisan/hints/postscript_hint_extractor.rb +0 -2
- data/lib/fontisan/hints/truetype_hint_extractor.rb +0 -2
- data/lib/fontisan/hints.rb +16 -0
- data/lib/fontisan/metrics_calculator.rb +0 -2
- data/lib/fontisan/models/all_scripts_features_info.rb +0 -1
- data/lib/fontisan/models/audit/audit_axis.rb +30 -0
- data/lib/fontisan/models/audit/audit_block.rb +32 -0
- data/lib/fontisan/models/audit/audit_diff.rb +77 -0
- data/lib/fontisan/models/audit/audit_report.rb +153 -0
- data/lib/fontisan/models/audit/codepoint_range.rb +40 -0
- data/lib/fontisan/models/audit/codepoint_set_diff.rb +34 -0
- data/lib/fontisan/models/audit/color_capabilities.rb +93 -0
- data/lib/fontisan/models/audit/duplicate_group.rb +23 -0
- data/lib/fontisan/models/audit/embedding_type.rb +76 -0
- data/lib/fontisan/models/audit/field_change.rb +28 -0
- data/lib/fontisan/models/audit/fs_selection_flags.rb +61 -0
- data/lib/fontisan/models/audit/gasp_range.rb +63 -0
- data/lib/fontisan/models/audit/hinting.rb +93 -0
- data/lib/fontisan/models/audit/library_summary.rb +40 -0
- data/lib/fontisan/models/audit/licensing.rb +48 -0
- data/lib/fontisan/models/audit/metrics.rb +111 -0
- data/lib/fontisan/models/audit/named_instance.rb +41 -0
- data/lib/fontisan/models/audit/opentype_layout.rb +40 -0
- data/lib/fontisan/models/audit/script_coverage_row.rb +26 -0
- data/lib/fontisan/models/audit/script_features.rb +28 -0
- data/lib/fontisan/models/audit/variation_detail.rb +44 -0
- data/lib/fontisan/models/audit.rb +33 -0
- data/lib/fontisan/models/cldr/language_coverage.rb +31 -0
- data/lib/fontisan/models/cldr.rb +12 -0
- data/lib/fontisan/models/collection_brief_info.rb +0 -1
- data/lib/fontisan/models/collection_info.rb +0 -2
- data/lib/fontisan/models/collection_list_info.rb +0 -1
- data/lib/fontisan/models/collection_validation_report.rb +0 -2
- data/lib/fontisan/models/color_glyph.rb +0 -1
- data/lib/fontisan/models/font_report.rb +0 -1
- data/lib/fontisan/models/ttx/tables.rb +21 -0
- data/lib/fontisan/models/ttx/ttfont.rb +0 -8
- data/lib/fontisan/models/ttx.rb +14 -0
- data/lib/fontisan/models/ucd/ucd.rb +38 -0
- data/lib/fontisan/models/ucd/ucd_char.rb +67 -0
- data/lib/fontisan/models/ucd.rb +19 -0
- data/lib/fontisan/models.rb +47 -0
- data/lib/fontisan/open_type_collection.rb +6 -5
- data/lib/fontisan/open_type_font.rb +8 -2
- data/lib/fontisan/open_type_font_extensions.rb +9 -9
- data/lib/fontisan/optimizers/pattern_analyzer.rb +0 -1
- data/lib/fontisan/optimizers.rb +14 -0
- data/lib/fontisan/outline_extractor.rb +0 -2
- data/lib/fontisan/parsers/dfont_parser.rb +0 -1
- data/lib/fontisan/parsers.rb +10 -0
- data/lib/fontisan/pipeline/format_detector.rb +29 -102
- data/lib/fontisan/pipeline/output_writer.rb +11 -9
- data/lib/fontisan/pipeline/strategies/instance_strategy.rb +0 -4
- data/lib/fontisan/pipeline/strategies/named_strategy.rb +0 -4
- data/lib/fontisan/pipeline/strategies/preserve_strategy.rb +0 -2
- data/lib/fontisan/pipeline/strategies.rb +14 -0
- data/lib/fontisan/pipeline/transformation_pipeline.rb +0 -7
- data/lib/fontisan/pipeline/variation_resolver.rb +0 -7
- data/lib/fontisan/pipeline.rb +13 -0
- data/lib/fontisan/sfnt_font.rb +29 -14
- data/lib/fontisan/sfnt_table.rb +0 -4
- data/lib/fontisan/subset/builder.rb +0 -6
- data/lib/fontisan/subset.rb +13 -0
- data/lib/fontisan/svg/font_generator.rb +0 -4
- data/lib/fontisan/svg/glyph_generator.rb +0 -2
- data/lib/fontisan/svg.rb +12 -0
- data/lib/fontisan/tables/cbdt.rb +0 -1
- data/lib/fontisan/tables/cblc.rb +0 -1
- data/lib/fontisan/tables/cff/charset.rb +0 -1
- data/lib/fontisan/tables/cff/charstring.rb +0 -1
- data/lib/fontisan/tables/cff/charstring_rebuilder.rb +0 -4
- data/lib/fontisan/tables/cff/charstrings_index.rb +0 -3
- data/lib/fontisan/tables/cff/dict.rb +0 -1
- data/lib/fontisan/tables/cff/encoding.rb +0 -1
- data/lib/fontisan/tables/cff/header.rb +0 -2
- data/lib/fontisan/tables/cff/hint_operation_injector.rb +0 -2
- data/lib/fontisan/tables/cff/index.rb +0 -1
- data/lib/fontisan/tables/cff/private_dict.rb +0 -2
- data/lib/fontisan/tables/cff/private_dict_writer.rb +0 -2
- data/lib/fontisan/tables/cff/table_builder.rb +0 -6
- data/lib/fontisan/tables/cff/top_dict.rb +0 -2
- data/lib/fontisan/tables/cff.rb +22 -15
- data/lib/fontisan/tables/cff2/charstring_parser.rb +0 -2
- data/lib/fontisan/tables/cff2/table_builder.rb +0 -11
- data/lib/fontisan/tables/cff2/table_reader.rb +0 -2
- data/lib/fontisan/tables/cff2.rb +13 -14
- data/lib/fontisan/tables/cmap.rb +24 -2
- data/lib/fontisan/tables/cmap_table.rb +0 -3
- data/lib/fontisan/tables/colr.rb +0 -1
- data/lib/fontisan/tables/cpal.rb +0 -1
- data/lib/fontisan/tables/cvar.rb +0 -2
- data/lib/fontisan/tables/fvar.rb +0 -1
- data/lib/fontisan/tables/glyf/compound_glyph_resolver.rb +0 -2
- data/lib/fontisan/tables/glyf/glyph_builder.rb +0 -3
- data/lib/fontisan/tables/glyf.rb +0 -6
- data/lib/fontisan/tables/glyf_table.rb +0 -3
- data/lib/fontisan/tables/gpos.rb +0 -2
- data/lib/fontisan/tables/gsub.rb +0 -2
- data/lib/fontisan/tables/gvar.rb +0 -2
- data/lib/fontisan/tables/head.rb +0 -2
- data/lib/fontisan/tables/head_table.rb +0 -3
- data/lib/fontisan/tables/hhea.rb +0 -2
- data/lib/fontisan/tables/hhea_table.rb +0 -3
- data/lib/fontisan/tables/hmtx.rb +0 -2
- data/lib/fontisan/tables/hmtx_table.rb +0 -3
- data/lib/fontisan/tables/hvar.rb +0 -3
- data/lib/fontisan/tables/loca.rb +0 -2
- data/lib/fontisan/tables/loca_table.rb +0 -3
- data/lib/fontisan/tables/maxp.rb +0 -2
- data/lib/fontisan/tables/maxp_table.rb +0 -3
- data/lib/fontisan/tables/mvar.rb +0 -3
- data/lib/fontisan/tables/name.rb +0 -2
- data/lib/fontisan/tables/name_table.rb +0 -3
- data/lib/fontisan/tables/os2_table.rb +0 -3
- data/lib/fontisan/tables/post_table.rb +0 -3
- data/lib/fontisan/tables/sbix.rb +0 -1
- data/lib/fontisan/tables/svg.rb +0 -1
- data/lib/fontisan/tables/variation_common.rb +0 -1
- data/lib/fontisan/tables/vvar.rb +0 -3
- data/lib/fontisan/tables.rb +54 -0
- data/lib/fontisan/true_type_collection.rb +6 -14
- data/lib/fontisan/true_type_font.rb +8 -2
- data/lib/fontisan/true_type_font_extensions.rb +9 -9
- data/lib/fontisan/type1/afm_generator.rb +0 -4
- data/lib/fontisan/type1/conversion_options.rb +0 -2
- data/lib/fontisan/type1/encodings.rb +0 -2
- data/lib/fontisan/type1/generator.rb +0 -8
- data/lib/fontisan/type1/pfa_generator.rb +0 -3
- data/lib/fontisan/type1/pfb_generator.rb +0 -5
- data/lib/fontisan/type1/pfm_generator.rb +0 -4
- data/lib/fontisan/type1.rb +42 -69
- data/lib/fontisan/type1_font.rb +40 -11
- data/lib/fontisan/ucd/aggregator.rb +73 -0
- data/lib/fontisan/ucd/cache_manager.rb +111 -0
- data/lib/fontisan/ucd/config.rb +59 -0
- data/lib/fontisan/ucd/download_error.rb +9 -0
- data/lib/fontisan/ucd/downloader.rb +88 -0
- data/lib/fontisan/ucd/error.rb +8 -0
- data/lib/fontisan/ucd/index.rb +103 -0
- data/lib/fontisan/ucd/index_builder.rb +107 -0
- data/lib/fontisan/ucd/range_entry.rb +56 -0
- data/lib/fontisan/ucd/unknown_version_error.rb +9 -0
- data/lib/fontisan/ucd/version_resolver.rb +79 -0
- data/lib/fontisan/ucd.rb +23 -0
- data/lib/fontisan/utilities/checksum_calculator.rb +0 -1
- data/lib/fontisan/utilities.rb +10 -0
- data/lib/fontisan/utils.rb +10 -0
- data/lib/fontisan/validation/collection_validator.rb +0 -2
- data/lib/fontisan/validation.rb +9 -0
- data/lib/fontisan/validators/basic_validator.rb +0 -2
- data/lib/fontisan/validators/font_book_validator.rb +0 -2
- data/lib/fontisan/validators/opentype_validator.rb +0 -2
- data/lib/fontisan/validators/profile_loader.rb +0 -5
- data/lib/fontisan/validators/validator.rb +0 -2
- data/lib/fontisan/validators/web_font_validator.rb +0 -2
- data/lib/fontisan/validators.rb +14 -0
- data/lib/fontisan/variable/delta_applicator.rb +0 -4
- data/lib/fontisan/variable/instancer.rb +0 -3
- data/lib/fontisan/variable/static_font_builder.rb +0 -3
- data/lib/fontisan/variable.rb +16 -0
- data/lib/fontisan/variation/blend_applier.rb +0 -2
- data/lib/fontisan/variation/cache.rb +0 -2
- data/lib/fontisan/variation/converter.rb +0 -3
- data/lib/fontisan/variation/data_extractor.rb +0 -2
- data/lib/fontisan/variation/delta_applier.rb +0 -5
- data/lib/fontisan/variation/inspector.rb +0 -1
- data/lib/fontisan/variation/instance_generator.rb +0 -6
- data/lib/fontisan/variation/instance_writer.rb +0 -5
- data/lib/fontisan/variation/metrics_adjuster.rb +0 -4
- data/lib/fontisan/variation/optimizer.rb +0 -3
- data/lib/fontisan/variation/parallel_generator.rb +0 -3
- data/lib/fontisan/variation/subsetter.rb +0 -4
- data/lib/fontisan/variation/tuple_variation_header.rb +0 -2
- data/lib/fontisan/variation/variable_svg_generator.rb +0 -3
- data/lib/fontisan/variation/variation_context.rb +0 -3
- data/lib/fontisan/variation/variation_preserver.rb +0 -3
- data/lib/fontisan/variation.rb +31 -0
- data/lib/fontisan/version.rb +1 -1
- data/lib/fontisan/woff2.rb +13 -0
- data/lib/fontisan/woff2_font.rb +31 -9
- data/lib/fontisan/woff_font.rb +31 -2
- data/lib/fontisan.rb +124 -196
- metadata +128 -7
- data/fontisan.gemspec +0 -47
data/docs/CONVERSION_GUIDE.adoc
CHANGED
|
@@ -113,12 +113,21 @@ Generating options control how the output font is written.
|
|
|
113
113
|
| `optimize_tables` | Boolean | Enable table optimization | Reduce file size |
|
|
114
114
|
| `reencode_first_256` | Boolean | Reencode first 256 glyphs | Type 1 output |
|
|
115
115
|
| `encoding_vector` | String | Custom encoding vector | Type 1 output |
|
|
116
|
-
| `
|
|
117
|
-
| `
|
|
116
|
+
| `zlib_level` | Integer (0–9) | zlib compression level | WOFF output (default 6) |
|
|
117
|
+
| `uncompressed` | Boolean | Store tables uncompressed | WOFF only (legal per WOFF 1.0 §5.1) |
|
|
118
|
+
| `compression_threshold` | Integer | Skip compression for tables < N bytes | WOFF only (default 100) |
|
|
119
|
+
| `brotli_quality` | Integer (0–11) | Brotli quality | WOFF2 output (default 11) |
|
|
120
|
+
| `transform_tables` | Boolean | Apply glyf/loca + hmtx transformations | WOFF2 only |
|
|
121
|
+
| `metadata_xml` | String | Optional WOFF metadata XML | WOFF only |
|
|
122
|
+
| `private_data` | String | Optional WOFF private data | WOFF only |
|
|
118
123
|
| `preserve_metadata` | Boolean | Preserve copyright/license metadata | Maintain font metadata |
|
|
119
124
|
| `strip_metadata` | Boolean | Remove metadata | Reduce file size |
|
|
120
125
|
| `target_format` | String | Collection target format | Collection conversions |
|
|
121
126
|
|
|
127
|
+
Compression knobs are declared by each strategy (`WoffWriter`, `Woff2Encoder`)
|
|
128
|
+
via the `ConversionStrategy` DSL. `FormatConverter.validate_options_for_target!`
|
|
129
|
+
rejects knobs that don't apply to the requested target format.
|
|
130
|
+
|
|
122
131
|
=== CLI Option Mapping
|
|
123
132
|
|
|
124
133
|
==== Opening Options
|
|
@@ -388,7 +397,7 @@ Notes: dfont supports both TrueType and OpenType/CFF, or mixed formats.
|
|
|
388
397
|
Fontisan::ConversionOptions.from_preset(:web_optimized)
|
|
389
398
|
# From: :otf, To: :woff2
|
|
390
399
|
# opening: {}
|
|
391
|
-
# generating: {
|
|
400
|
+
# generating: { brotli_quality: 11, transform_tables: true,
|
|
392
401
|
# optimize_tables: true, preserve_metadata: true }
|
|
393
402
|
----
|
|
394
403
|
|
|
@@ -398,8 +407,10 @@ Benefits: 30-50% smaller than TTF/OTF
|
|
|
398
407
|
|
|
399
408
|
[source,ruby]
|
|
400
409
|
----
|
|
401
|
-
|
|
402
|
-
#
|
|
410
|
+
Fontisan::ConversionOptions.from_preset(:legacy_web)
|
|
411
|
+
# From: :otf, To: :woff
|
|
412
|
+
# generating: { zlib_level: 9, optimize_tables: true,
|
|
413
|
+
# preserve_metadata: true }
|
|
403
414
|
----
|
|
404
415
|
|
|
405
416
|
==== Type 1 → WOFF/WOFF2
|
|
@@ -410,8 +421,8 @@ Workflow: Type 1 → OTF → WOFF2
|
|
|
410
421
|
----
|
|
411
422
|
# Via OTF intermediate
|
|
412
423
|
# opening: { decompose_composites: false, generate_unicode: true }
|
|
413
|
-
# generating: {
|
|
414
|
-
# OR
|
|
424
|
+
# generating: { brotli_quality: 11 } # WOFF2
|
|
425
|
+
# OR generating: { zlib_level: 9 } # WOFF
|
|
415
426
|
----
|
|
416
427
|
|
|
417
428
|
=== SVG Font Generation
|
|
@@ -481,7 +492,7 @@ Optimize fonts for web delivery:
|
|
|
481
492
|
Fontisan::ConversionOptions.from_preset(:web_optimized)
|
|
482
493
|
# From: :otf, To: :woff2
|
|
483
494
|
# opening: {}
|
|
484
|
-
# generating: {
|
|
495
|
+
# generating: { brotli_quality: 11, transform_tables: true,
|
|
485
496
|
# optimize_tables: true, preserve_metadata: true }
|
|
486
497
|
----
|
|
487
498
|
|
|
@@ -491,6 +502,18 @@ Use cases:
|
|
|
491
502
|
* Reducing page load time
|
|
492
503
|
* Bandwidth optimization
|
|
493
504
|
|
|
505
|
+
=== legacy_web
|
|
506
|
+
|
|
507
|
+
WOFF with maximum zlib compression for legacy browser reach (IE 9+):
|
|
508
|
+
|
|
509
|
+
[source,ruby]
|
|
510
|
+
----
|
|
511
|
+
Fontisan::ConversionOptions.from_preset(:legacy_web)
|
|
512
|
+
# From: :otf, To: :woff
|
|
513
|
+
# generating: { zlib_level: 9, optimize_tables: true,
|
|
514
|
+
# preserve_metadata: true }
|
|
515
|
+
----
|
|
516
|
+
|
|
494
517
|
=== archive_to_modern
|
|
495
518
|
|
|
496
519
|
Convert font archives to modern format:
|
|
@@ -246,7 +246,7 @@ fontisan maintains 100% backward compatibility:
|
|
|
246
246
|
|
|
247
247
|
= ExtractTTC to Fontisan Migration Guide
|
|
248
248
|
|
|
249
|
-
This guide helps users migrate from https://github.com/fontist/extract_ttc
|
|
249
|
+
This guide helps users migrate from [ExtractTTC](https://github.com/fontist/extract_ttc) to Fontisan.
|
|
250
250
|
|
|
251
251
|
Fontisan provides complete compatibility with all ExtractTTC functionality while adding comprehensive font analysis, subsetting, validation, and format conversion capabilities.
|
|
252
252
|
|
|
@@ -74,6 +74,59 @@ $ fontisan convert INPUT.ttf --to woff --output output.woff
|
|
|
74
74
|
$ fontisan convert INPUT.ttf --to woff2 --output output.woff2
|
|
75
75
|
----
|
|
76
76
|
|
|
77
|
+
=== Choosing between WOFF and WOFF2
|
|
78
|
+
|
|
79
|
+
WOFF and WOFF2 use different compression algorithms, fixed by their specs.
|
|
80
|
+
The format you choose **is** the choice of algorithm — there is no separate
|
|
81
|
+
`--compression` flag.
|
|
82
|
+
|
|
83
|
+
[options="header"]
|
|
84
|
+
|====
|
|
85
|
+
| Format | Algorithm | Compatibility | Typical size
|
|
86
|
+
| WOFF | zlib | All browsers (legacy-safe) | baseline
|
|
87
|
+
| WOFF2 | Brotli | Modern browsers only | ~30% smaller than WOFF
|
|
88
|
+
|====
|
|
89
|
+
|
|
90
|
+
If you need to support old browsers that lack Brotli decoders, use WOFF:
|
|
91
|
+
|
|
92
|
+
[source,shell]
|
|
93
|
+
----
|
|
94
|
+
$ fontisan convert INPUT.ttf --to woff --output out.woff --zlib-level 9
|
|
95
|
+
----
|
|
96
|
+
|
|
97
|
+
For modern-only delivery, WOFF2 is preferred:
|
|
98
|
+
|
|
99
|
+
[source,shell]
|
|
100
|
+
----
|
|
101
|
+
$ fontisan convert INPUT.ttf --to woff2 --output out.woff2
|
|
102
|
+
----
|
|
103
|
+
|
|
104
|
+
Note: WOFF2 mandates Brotli, WOFF mandates zlib. The container format is the
|
|
105
|
+
algorithm selector — you cannot mix and match.
|
|
106
|
+
|
|
107
|
+
==== Per-format compression knobs
|
|
108
|
+
|
|
109
|
+
Each container exposes only the knobs that apply to it. Options declared for
|
|
110
|
+
the wrong target format raise a clear `ArgumentError` at convert time.
|
|
111
|
+
|
|
112
|
+
[options="header"]
|
|
113
|
+
|====
|
|
114
|
+
| Format | Knob | Range / values | Default
|
|
115
|
+
| WOFF | `--zlib-level` | 0–9 | 6
|
|
116
|
+
| WOFF | `--uncompressed` | (flag) | off
|
|
117
|
+
| WOFF | `--compression-threshold` | bytes | 100
|
|
118
|
+
| WOFF2 | `--brotli-quality` | 0–11 | 11
|
|
119
|
+
| WOFF2 | `--[no-]transform-tables` | (flag) | off
|
|
120
|
+
|====
|
|
121
|
+
|
|
122
|
+
The same knobs are available on the Ruby API via keyword arguments:
|
|
123
|
+
|
|
124
|
+
[source,ruby]
|
|
125
|
+
----
|
|
126
|
+
Fontisan.convert("f.ttf", to: :woff, output: "f.woff", zlib_level: 9)
|
|
127
|
+
Fontisan.convert("f.ttf", to: :woff2, output: "f.woff2", brotli_quality: 11)
|
|
128
|
+
----
|
|
129
|
+
|
|
77
130
|
.Conversion with optimization
|
|
78
131
|
[example]
|
|
79
132
|
====
|
|
@@ -51,6 +51,7 @@ options = Fontisan::ConversionOptions.from_preset(:type1_to_modern)
|
|
|
51
51
|
| `type1_to_modern` | Type 1 | OTF |
|
|
52
52
|
| `modern_to_type1` | OTF | Type 1 |
|
|
53
53
|
| `web_optimized` | OTF | WOFF2 |
|
|
54
|
+
| `legacy_web` | OTF | WOFF |
|
|
54
55
|
| `archive_to_modern` | TTC | OTF |
|
|
55
56
|
|
|
56
57
|
### new(**kwargs)
|
|
@@ -96,19 +97,28 @@ Opening options control source font processing.
|
|
|
96
97
|
|
|
97
98
|
Generating options control output font writing.
|
|
98
99
|
|
|
99
|
-
| Option | Type | Default |
|
|
100
|
-
|
|
101
|
-
| `write_pfm` | Boolean | false |
|
|
102
|
-
| `write_afm` | Boolean | false |
|
|
103
|
-
| `write_inf` | Boolean | false |
|
|
104
|
-
| `select_encoding_automatically` | Boolean | false |
|
|
105
|
-
| `hinting_mode` | String | 'preserve' |
|
|
106
|
-
| `decompose_on_output` | Boolean | false |
|
|
107
|
-
| `write_custom_tables` | Boolean | true |
|
|
108
|
-
| `optimize_tables` | Boolean | false |
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
100
|
+
| Option | Type | Default | Applies to |
|
|
101
|
+
|--------|------|---------|------------|
|
|
102
|
+
| `write_pfm` | Boolean | false | Type 1 output |
|
|
103
|
+
| `write_afm` | Boolean | false | Type 1 output |
|
|
104
|
+
| `write_inf` | Boolean | false | Type 1 output |
|
|
105
|
+
| `select_encoding_automatically` | Boolean | false | Type 1 output |
|
|
106
|
+
| `hinting_mode` | String | 'preserve' | All outline conversions |
|
|
107
|
+
| `decompose_on_output` | Boolean | false | All outline conversions |
|
|
108
|
+
| `write_custom_tables` | Boolean | true | All |
|
|
109
|
+
| `optimize_tables` | Boolean | false | All |
|
|
110
|
+
| `zlib_level` | Integer (0–9) | 6 | WOFF only |
|
|
111
|
+
| `uncompressed` | Boolean | false | WOFF only |
|
|
112
|
+
| `compression_threshold` | Integer (bytes) | 100 | WOFF only |
|
|
113
|
+
| `brotli_quality` | Integer (0–11) | 11 | WOFF2 only |
|
|
114
|
+
| `transform_tables` | Boolean | false | WOFF2 only |
|
|
115
|
+
| `metadata_xml` | String | nil | WOFF only |
|
|
116
|
+
| `private_data` | String | nil | WOFF only |
|
|
117
|
+
| `preserve_metadata` | Boolean | true | All |
|
|
118
|
+
|
|
119
|
+
Compression knobs are declared by each strategy (`WoffWriter`, `Woff2Encoder`)
|
|
120
|
+
via the `ConversionStrategy` DSL. `FormatConverter.validate_options_for_target!`
|
|
121
|
+
rejects knobs that don't apply to the requested target format.
|
|
112
122
|
|
|
113
123
|
## Examples
|
|
114
124
|
|
|
@@ -131,11 +141,24 @@ Fontisan::FontWriter.write(font, 'output.woff2', options: options)
|
|
|
131
141
|
|
|
132
142
|
```ruby
|
|
133
143
|
options = Fontisan::ConversionOptions.new(
|
|
144
|
+
from: :ttf,
|
|
145
|
+
to: :woff2,
|
|
134
146
|
opening: { autohint: true },
|
|
135
147
|
generating: {
|
|
136
148
|
hinting_mode: 'auto',
|
|
137
149
|
optimize_tables: true,
|
|
138
|
-
|
|
150
|
+
brotli_quality: 11,
|
|
151
|
+
transform_tables: true
|
|
139
152
|
}
|
|
140
153
|
)
|
|
141
154
|
```
|
|
155
|
+
|
|
156
|
+
### WOFF with Max zlib (Legacy Browser Reach)
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
options = Fontisan::ConversionOptions.new(
|
|
160
|
+
from: :ttf,
|
|
161
|
+
to: :woff,
|
|
162
|
+
generating: { zlib_level: 9, preserve_metadata: true }
|
|
163
|
+
)
|
|
164
|
+
```
|
data/docs/api/font-loader.md
CHANGED
|
@@ -40,9 +40,11 @@ font = Fontisan::FontLoader.load(File.read('font.ttf', mode: 'rb'))
|
|
|
40
40
|
|
|
41
41
|
**Raises:** Fontisan::FormatError if format is unsupported
|
|
42
42
|
|
|
43
|
-
### detect_format(
|
|
43
|
+
### detect_format(path)
|
|
44
44
|
|
|
45
|
-
Detect font format
|
|
45
|
+
Detect a font's on-disk format from its content (magic bytes). The file
|
|
46
|
+
extension is ignored — a `.ttc` that actually contains a single OpenType-CFF
|
|
47
|
+
font is reported as `:otf`.
|
|
46
48
|
|
|
47
49
|
```ruby
|
|
48
50
|
format = Fontisan::FontLoader.detect_format('font.ttf')
|
|
@@ -52,24 +54,28 @@ format = Fontisan::FontLoader.detect_format('font.otf')
|
|
|
52
54
|
# => :otf
|
|
53
55
|
|
|
54
56
|
format = Fontisan::FontLoader.detect_format('font.pfb')
|
|
55
|
-
# => :
|
|
57
|
+
# => :pfb
|
|
58
|
+
|
|
59
|
+
format = Fontisan::FontLoader.detect_format('font.pfa')
|
|
60
|
+
# => :pfa
|
|
56
61
|
```
|
|
57
62
|
|
|
58
|
-
**Returns:** Symbol
|
|
63
|
+
**Returns:** Symbol (`:ttf`, `:otf`, `:ttc`, `:otc`, `:woff`, `:woff2`,
|
|
64
|
+
`:dfont`, `:pfa`, `:pfb`) or `nil` if the format is not recognised.
|
|
59
65
|
|
|
60
66
|
## Supported Formats
|
|
61
67
|
|
|
62
|
-
|
|
|
63
|
-
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
| dfont | Magic
|
|
68
|
+
| Symbol | Detection | Notes |
|
|
69
|
+
|---------|-------------|--------------------------------|
|
|
70
|
+
| `:ttf` | Magic bytes | TrueType |
|
|
71
|
+
| `:otf` | Magic bytes | OpenType / CFF |
|
|
72
|
+
| `:ttc` | Magic bytes | TrueType Collection |
|
|
73
|
+
| `:otc` | Magic bytes | OpenType Collection |
|
|
74
|
+
| `:woff` | Magic bytes | Web Open Font Format |
|
|
75
|
+
| `:woff2` | Magic bytes | Web Open Font Format 2 |
|
|
76
|
+
| `:pfb` | Marker byte | Adobe Type 1 Binary |
|
|
77
|
+
| `:pfa` | Text header | Adobe Type 1 ASCII |
|
|
78
|
+
| `:dfont` | Magic bytes | Apple Data-Fork resource fork |
|
|
73
79
|
|
|
74
80
|
## Examples
|
|
75
81
|
|
data/docs/cli/audit.md
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: audit
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# audit
|
|
6
|
+
|
|
7
|
+
Produce a complete per-face font audit report — identity, style, metrics,
|
|
8
|
+
coverage, licensing, hinting, color capabilities, variable-font detail,
|
|
9
|
+
OpenType layout features, and Unicode/CLDR aggregation.
|
|
10
|
+
|
|
11
|
+
`audit` is the successor to `otfinfo`: it covers everything `otfinfo`
|
|
12
|
+
reports plus a great deal more (coverage, hinting, color, variation,
|
|
13
|
+
layout, language coverage), and supports collections, compare mode, and
|
|
14
|
+
whole-library summaries.
|
|
15
|
+
|
|
16
|
+
## Quick Reference
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# One face
|
|
20
|
+
fontisan audit FONT.ttf
|
|
21
|
+
|
|
22
|
+
# Collection (one report per face)
|
|
23
|
+
fontisan audit COLLECTION.ttc
|
|
24
|
+
|
|
25
|
+
# Whole library
|
|
26
|
+
fontisan audit DIR/ --recursive --summary
|
|
27
|
+
|
|
28
|
+
# Compare two fonts or saved reports
|
|
29
|
+
fontisan audit --compare A.ttf B.ttf
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Variants
|
|
33
|
+
|
|
34
|
+
| Variant | What it does | Output |
|
|
35
|
+
|---------|-------------|--------|
|
|
36
|
+
| `audit FONT.ttf` | One AuditReport for the single face | `AuditReport` |
|
|
37
|
+
| `audit COLLECTION.ttc` | One AuditReport per face (in source order) | `Array<AuditReport>` |
|
|
38
|
+
| `audit DIR/ --recursive --summary` | Walk the directory, summarize the library | `LibrarySummary` |
|
|
39
|
+
| `audit --compare A B` | Diff two faces or two saved reports | `AuditDiff` |
|
|
40
|
+
|
|
41
|
+
## Options
|
|
42
|
+
|
|
43
|
+
| Option | Description |
|
|
44
|
+
|--------|-------------|
|
|
45
|
+
| `--format FORMAT` | Output format: `text` (default), `yaml`, `json` |
|
|
46
|
+
| `--output PATH`, `-o` | Write to a directory (collection/library), a file (single/compare), or stdout |
|
|
47
|
+
| `--font-index N` | Audit only face N of a collection (default: all) |
|
|
48
|
+
| `--brief` | Fast inventory — skip metrics/hinting/color/layout/UCD/CLDR |
|
|
49
|
+
| `--all-codepoints` | Include the full per-codepoint list (defaults to a compact range view) |
|
|
50
|
+
| `--ucd-version VER` | Aggregate against this UCD version (`latest` to probe) |
|
|
51
|
+
| `--with-language-coverage` | Compute CLDR language coverage % (auto-downloads CLDR on first use) |
|
|
52
|
+
| `--cldr-version VER` | CLDR version to use (`latest` to probe) |
|
|
53
|
+
| `--compare` | Diff two inputs (requires exactly two paths) |
|
|
54
|
+
| `--recursive` | Library mode: walk into subdirectories |
|
|
55
|
+
| `--summary` | Library mode: produce a `LibrarySummary` over a directory |
|
|
56
|
+
|
|
57
|
+
## Brief Mode
|
|
58
|
+
|
|
59
|
+
`--brief` runs only the cheap name-table extractors (provenance, identity,
|
|
60
|
+
style, licensing, coverage) and skips metrics, hinting, color,
|
|
61
|
+
variation, OpenType layout, UCD block/script aggregation, and CLDR
|
|
62
|
+
language coverage. Useful for taking a fast inventory of large libraries.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
fontisan audit FONT.ttf --brief
|
|
66
|
+
fontisan audit DIR/ --recursive --summary --brief
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Note: `audit --brief` is distinct from `info --brief`. `info --brief`
|
|
70
|
+
loads only 6 tables; `audit --brief` still loads the full font (Coverage
|
|
71
|
+
reads `cmap`) but selects a cheaper extractor subset.
|
|
72
|
+
|
|
73
|
+
## Single-Face Audit
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Text formatter (default)
|
|
77
|
+
fontisan audit FONT.ttf
|
|
78
|
+
|
|
79
|
+
# YAML (machine-readable)
|
|
80
|
+
fontisan audit FONT.ttf --format yaml
|
|
81
|
+
|
|
82
|
+
# JSON
|
|
83
|
+
fontisan audit FONT.ttf --format json | jq '.licensing'
|
|
84
|
+
|
|
85
|
+
# Write to disk
|
|
86
|
+
fontisan audit FONT.ttf -o report.yaml
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Sample text output (truncated):
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
NotoSans-Regular
|
|
93
|
+
================================================================================
|
|
94
|
+
generated_at: 2026-06-24T18:11:39Z fontisan: 0.2.20
|
|
95
|
+
source_sha256: f5f552c8c5edb61fe6efb824baf4d4de47b1a8689ab4925ff43f7bd6a4ebece5
|
|
96
|
+
source_file: /path/to/NotoSans-Regular.ttf
|
|
97
|
+
source_format: ttf layout: single face (1/1)
|
|
98
|
+
|
|
99
|
+
IDENTITY
|
|
100
|
+
Family: Noto Sans
|
|
101
|
+
Subfamily: Regular
|
|
102
|
+
Full name: Noto Sans Regular
|
|
103
|
+
PostScript: NotoSans-Regular
|
|
104
|
+
Version: Version 2.015; ttfautohint (v1.8.4.7-5d5b)
|
|
105
|
+
Revision: 2.0149993896484375
|
|
106
|
+
|
|
107
|
+
STYLE
|
|
108
|
+
Weight class: 400 (Regular)
|
|
109
|
+
Width class: 5 (Medium)
|
|
110
|
+
Bold: no
|
|
111
|
+
Italic: no
|
|
112
|
+
PANOSE: 2 11 5 2 4 5 4 2 2 4
|
|
113
|
+
|
|
114
|
+
COVERAGE
|
|
115
|
+
Codepoints: 3094
|
|
116
|
+
Glyphs: 4515
|
|
117
|
+
cmap subtables: 4, 12
|
|
118
|
+
Ranges (top 10): U+0000-U+0000, U+000D-U+000D, U+0020-U+007E, ...
|
|
119
|
+
Unicode scripts: Latin, ...
|
|
120
|
+
|
|
121
|
+
LICENSING
|
|
122
|
+
License URL: https://scripts.sil.org/OFL
|
|
123
|
+
Embedding: 0x0000 (Editable embedding)
|
|
124
|
+
|
|
125
|
+
METRICS
|
|
126
|
+
Units per em: 1000
|
|
127
|
+
Ascender: 1160
|
|
128
|
+
Descender: -288
|
|
129
|
+
...
|
|
130
|
+
|
|
131
|
+
UNICODE BLOCKS
|
|
132
|
+
Basic Latin 95 / 128 74.2%
|
|
133
|
+
Latin-1 Supplement 96 / 128 75.0%
|
|
134
|
+
...
|
|
135
|
+
|
|
136
|
+
VARIABLE FONT
|
|
137
|
+
Axes: wght (100–900, default 400)
|
|
138
|
+
Named instances: 9
|
|
139
|
+
|
|
140
|
+
OPENTYPE LAYOUT
|
|
141
|
+
Scripts: latn, cyrl, grek, ...
|
|
142
|
+
Features: c2sc, calt, case, dlig, dnom, frac, kern, liga, ...
|
|
143
|
+
|
|
144
|
+
LANGUAGE COVERAGE
|
|
145
|
+
en: 99.2%
|
|
146
|
+
fr: 97.4%
|
|
147
|
+
...
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Collections
|
|
151
|
+
|
|
152
|
+
For TTC/OTC/dfont, one report is produced per face in source order.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Audit every face
|
|
156
|
+
fontisan audit COLLECTION.ttc
|
|
157
|
+
|
|
158
|
+
# Audit only face 2
|
|
159
|
+
fontisan audit COLLECTION.ttc --font-index 2
|
|
160
|
+
|
|
161
|
+
# Write one file per face into a directory
|
|
162
|
+
fontisan audit COLLECTION.ttc -o reports/
|
|
163
|
+
|
|
164
|
+
# Resulting files use the postscript name with a 2-digit index prefix:
|
|
165
|
+
# 00-NotoSans-Regular.yaml
|
|
166
|
+
# 01-NotoSans-Bold.yaml
|
|
167
|
+
# 02-NotoSerif-Italic.yaml
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Compare Mode
|
|
171
|
+
|
|
172
|
+
`--compare` diffs two inputs. Each input is one of:
|
|
173
|
+
|
|
174
|
+
- A previously saved audit report (`.yaml` / `.yml` / `.json`)
|
|
175
|
+
- A font file (audited on-the-fly)
|
|
176
|
+
|
|
177
|
+
Mixed inputs are allowed — useful for tracking a font's evolution
|
|
178
|
+
against a checked-in baseline.
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Two live fonts
|
|
182
|
+
fontisan audit --compare a.ttf b.ttf
|
|
183
|
+
|
|
184
|
+
# Saved baseline vs. live
|
|
185
|
+
fontisan audit --compare baseline.yaml new.ttf
|
|
186
|
+
|
|
187
|
+
# Two saved reports
|
|
188
|
+
fontisan audit --compare v1.yaml v2.yaml -o diff.yaml
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The output is an `AuditDiff` containing:
|
|
192
|
+
|
|
193
|
+
- `field_changes` — scalar field-level changes (e.g. weight_class 400 → 700)
|
|
194
|
+
- `codepoints` — added/removed/unchanged codepoint counts
|
|
195
|
+
- `added_features` / `removed_features`
|
|
196
|
+
- `added_scripts` / `removed_scripts`
|
|
197
|
+
- `added_blocks` / `removed_blocks`
|
|
198
|
+
- `added_languages` / `removed_languages`
|
|
199
|
+
|
|
200
|
+
## Library Mode
|
|
201
|
+
|
|
202
|
+
Point `audit` at a directory with `--recursive` and/or `--summary` to
|
|
203
|
+
scan a whole library of fonts.
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Flat directory
|
|
207
|
+
fontisan audit lib/ --summary
|
|
208
|
+
|
|
209
|
+
# Walk subdirectories
|
|
210
|
+
fontisan audit lib/ --recursive --summary
|
|
211
|
+
|
|
212
|
+
# YAML for downstream processing
|
|
213
|
+
fontisan audit lib/ --recursive --summary --format yaml -o library.yaml
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The output is a `LibrarySummary` containing:
|
|
217
|
+
|
|
218
|
+
- `root_path`, `total_files`, `total_faces`, `scanned_extensions`
|
|
219
|
+
- `aggregate_metrics` — total codepoints/glyphs/bytes summed across faces
|
|
220
|
+
- `script_coverage` — per-script face counts and lists
|
|
221
|
+
- `duplicate_groups` — files grouped by `source_sha256` (size > 1)
|
|
222
|
+
- `license_distribution` — face counts per `license_url`
|
|
223
|
+
- `per_face_reports` — the full per-face reports used to aggregate
|
|
224
|
+
|
|
225
|
+
Files that fail to load (corrupt, unsupported) are listed on stderr as
|
|
226
|
+
`skipped <path>` and excluded from the summary.
|
|
227
|
+
|
|
228
|
+
## UCD Aggregation
|
|
229
|
+
|
|
230
|
+
By default, audit aggregates codepoints against the configured-default
|
|
231
|
+
UCD version, producing:
|
|
232
|
+
|
|
233
|
+
- `blocks` — per-Unicode-block coverage rows (name, range, total, covered, fill_ratio, complete)
|
|
234
|
+
- `unicode_scripts` — distinct scripts present in the font
|
|
235
|
+
|
|
236
|
+
Override with `--ucd-version`:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
# Use a specific UCD version
|
|
240
|
+
fontisan audit FONT.ttf --ucd-version 16.0.0
|
|
241
|
+
|
|
242
|
+
# Probe and use the latest
|
|
243
|
+
fontisan audit FONT.ttf --ucd-version latest
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Manage the local UCD cache with `fontisan ucd`:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
fontisan ucd status
|
|
250
|
+
fontisan ucd list
|
|
251
|
+
fontisan ucd download 17.0.0
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## CLDR Language Coverage
|
|
255
|
+
|
|
256
|
+
`--with-language-coverage` computes per-language coverage % using CLDR
|
|
257
|
+
exemplar sets. The first invocation downloads the CLDR data
|
|
258
|
+
(~MBs); subsequent invocations use the cache.
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
fontisan audit FONT.ttf --with-language-coverage
|
|
262
|
+
|
|
263
|
+
# Use a specific CLDR version
|
|
264
|
+
fontisan audit FONT.ttf --with-language-coverage --cldr-version 45
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Manage the CLDR cache with `fontisan cldr`:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
fontisan cldr status
|
|
271
|
+
fontisan cldr list
|
|
272
|
+
fontisan cldr download 45
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Ruby API
|
|
276
|
+
|
|
277
|
+
### Single face
|
|
278
|
+
|
|
279
|
+
```ruby
|
|
280
|
+
require "fontisan"
|
|
281
|
+
|
|
282
|
+
# Returns an AuditReport for a single font, or an Array<AuditReport>
|
|
283
|
+
# for a collection (one per face).
|
|
284
|
+
report = Fontisan::Commands::AuditCommand.new("font.ttf",
|
|
285
|
+
ucd_version: "17.0.0").run
|
|
286
|
+
|
|
287
|
+
puts report.family_name
|
|
288
|
+
puts report.total_codepoints
|
|
289
|
+
puts report.licensing.license_url
|
|
290
|
+
puts report.blocks.first.fill_ratio
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Compare
|
|
294
|
+
|
|
295
|
+
```ruby
|
|
296
|
+
diff = Fontisan::Commands::AuditCompareCommand.new(
|
|
297
|
+
"baseline.yaml", "new.ttf", ucd_version: "17.0.0"
|
|
298
|
+
).run
|
|
299
|
+
|
|
300
|
+
diff.field_changes.each { |c| puts "#{c.field}: #{c.left} → #{c.right}" }
|
|
301
|
+
puts "added codepoints: #{diff.codepoints.added_count}"
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Library summary
|
|
305
|
+
|
|
306
|
+
```ruby
|
|
307
|
+
cmd = Fontisan::Commands::AuditLibraryCommand.new(
|
|
308
|
+
"lib/", recursive: true, options: { ucd_version: "17.0.0" }
|
|
309
|
+
)
|
|
310
|
+
summary = cmd.run
|
|
311
|
+
cmd.skipped.each { |path| warn "skipped #{path}" }
|
|
312
|
+
|
|
313
|
+
summary.script_coverage.each do |row|
|
|
314
|
+
puts "#{row.script}: #{row.face_count} faces"
|
|
315
|
+
end
|
|
316
|
+
summary.duplicate_groups.each do |group|
|
|
317
|
+
puts "duplicate #{group.source_sha256[0,8]}: #{group.files.join(', ')}"
|
|
318
|
+
end
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Brief mode
|
|
322
|
+
|
|
323
|
+
```ruby
|
|
324
|
+
# Use the audit_brief: key (NOT brief:, which would trigger metadata-only
|
|
325
|
+
# font loading via BaseCommand).
|
|
326
|
+
report = Fontisan::Commands::AuditCommand.new(
|
|
327
|
+
"font.ttf", audit_brief: true, ucd_version: "17.0.0"
|
|
328
|
+
).run
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Related Commands
|
|
332
|
+
|
|
333
|
+
- [info](/cli/info) — Lighter-weight font metadata (replaces `otfinfo -i`)
|
|
334
|
+
- [tables](/cli/tables) — Raw OpenType table listing
|
|
335
|
+
- [features](/cli/features) — Just GSUB/GPOS features
|
|
336
|
+
- [scripts](/cli/scripts) — Just supported scripts
|
|
337
|
+
- [validate](/cli/validate) — Pass/fail quality checks (audit is descriptive; validate is prescriptive)
|
data/docs/cli/convert.md
CHANGED
|
@@ -36,6 +36,15 @@ These are individual font formats that can be converted:
|
|
|
36
36
|
| `--output FILE` | Output file path |
|
|
37
37
|
| `--optimize` | Enable outline optimization |
|
|
38
38
|
| `--flatten` | Flatten composite glyphs |
|
|
39
|
+
| `--zlib-level=N` | WOFF only: zlib compression level (0–9, default 6) |
|
|
40
|
+
| `--uncompressed` | WOFF only: store tables uncompressed (legal per WOFF 1.0 §5.1) |
|
|
41
|
+
| `--compression-threshold=N` | WOFF only: skip compression for tables smaller than N bytes (default 100) |
|
|
42
|
+
| `--brotli-quality=N` | WOFF2 only: Brotli quality (0–11, default 11) |
|
|
43
|
+
| `--transform-tables` / `--no-transform-tables` | WOFF2 only: apply glyf/loca + hmtx transformations |
|
|
44
|
+
|
|
45
|
+
The format you pick (`--to woff` vs `--to woff2`) **is** the algorithm
|
|
46
|
+
choice — WOFF mandates zlib, WOFF2 mandates Brotli. Passing a WOFF knob
|
|
47
|
+
to a WOFF2 target (or vice versa) exits 1 with a clear error.
|
|
39
48
|
|
|
40
49
|
## Common Workflows
|
|
41
50
|
|
|
@@ -45,8 +54,18 @@ These are individual font formats that can be converted:
|
|
|
45
54
|
# TTF to WOFF2 (recommended for modern browsers)
|
|
46
55
|
fontisan convert font.ttf --to woff2 --output font.woff2
|
|
47
56
|
|
|
48
|
-
# OTF to WOFF (broader compatibility)
|
|
57
|
+
# OTF to WOFF (broader compatibility — works on IE 9+)
|
|
49
58
|
fontisan convert font.otf --to woff --output font.woff
|
|
59
|
+
|
|
60
|
+
# Smallest possible WOFF2 (max Brotli + table transforms)
|
|
61
|
+
fontisan convert font.ttf --to woff2 --output font.woff2 \
|
|
62
|
+
--brotli-quality 11 --transform-tables
|
|
63
|
+
|
|
64
|
+
# WOFF with max zlib compression
|
|
65
|
+
fontisan convert font.ttf --to woff --output font.woff --zlib-level 9
|
|
66
|
+
|
|
67
|
+
# WOFF stored uncompressed (legal per WOFF 1.0 §5.1; useful for tooling)
|
|
68
|
+
fontisan convert font.ttf --to woff --output font.woff --uncompressed
|
|
50
69
|
```
|
|
51
70
|
|
|
52
71
|
### Convert Between Outline Formats
|