fontisan 0.2.13 → 0.2.16

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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +56 -196
  3. data/Gemfile +1 -1
  4. data/docs/.gitignore +17 -0
  5. data/docs/.vitepress/config.ts +317 -0
  6. data/docs/.vitepress/theme/components/ApiMethod.vue +127 -0
  7. data/docs/.vitepress/theme/components/Badge.vue +51 -0
  8. data/docs/.vitepress/theme/components/FeatureComparison.vue +87 -0
  9. data/docs/.vitepress/theme/components/HeroCodeBlock.vue +98 -0
  10. data/docs/.vitepress/theme/components/WithinHero.vue +30 -0
  11. data/docs/.vitepress/theme/index.ts +22 -0
  12. data/docs/.vitepress/theme/style.css +330 -0
  13. data/docs/api/conversion-options.md +141 -0
  14. data/docs/api/converters/curve-converter.md +34 -0
  15. data/docs/api/converters/hint-converter.md +34 -0
  16. data/docs/api/converters/outline-converter.md +27 -0
  17. data/docs/api/font-loader.md +111 -0
  18. data/docs/api/font-writer.md +103 -0
  19. data/docs/api/index.md +79 -0
  20. data/docs/api/models/glyph-accessor.md +43 -0
  21. data/docs/api/models/glyph.md +40 -0
  22. data/docs/api/models/table-analyzer.md +35 -0
  23. data/docs/api/sfnt-font.md +53 -0
  24. data/docs/api/type1-font.md +43 -0
  25. data/docs/api/validators/font-validator.md +31 -0
  26. data/docs/api/validators/helper.md +36 -0
  27. data/docs/api/validators/profile.md +39 -0
  28. data/docs/cli/convert.md +87 -0
  29. data/docs/cli/dump-table.md +110 -0
  30. data/docs/cli/export.md +176 -0
  31. data/docs/cli/features.md +124 -0
  32. data/docs/cli/glyphs.md +90 -0
  33. data/docs/cli/index.md +208 -0
  34. data/docs/cli/info.md +254 -0
  35. data/docs/cli/instance.md +122 -0
  36. data/docs/cli/ls.md +95 -0
  37. data/docs/cli/optical-size.md +94 -0
  38. data/docs/cli/pack.md +125 -0
  39. data/docs/cli/scripts.md +105 -0
  40. data/docs/cli/subset.md +39 -0
  41. data/docs/cli/tables.md +84 -0
  42. data/docs/cli/unicode.md +101 -0
  43. data/docs/cli/validate.md +48 -0
  44. data/docs/cli/variable.md +126 -0
  45. data/docs/cli/version.md +46 -0
  46. data/docs/guide/cli/convert.md +108 -0
  47. data/docs/guide/cli/export.md +138 -0
  48. data/docs/guide/cli/index.md +99 -0
  49. data/docs/guide/cli/info.md +144 -0
  50. data/docs/guide/cli/pack.md +155 -0
  51. data/docs/guide/cli/subset.md +118 -0
  52. data/docs/guide/cli/validate.md +139 -0
  53. data/docs/guide/color-fonts/bitmaps.md +177 -0
  54. data/docs/guide/color-fonts/colr-cpal.md +175 -0
  55. data/docs/guide/color-fonts/index.md +140 -0
  56. data/docs/guide/color-fonts/svg.md +154 -0
  57. data/docs/guide/color.md +51 -0
  58. data/docs/guide/comparisons/font-validator.md +222 -0
  59. data/docs/guide/comparisons/fonttools.md +200 -0
  60. data/docs/guide/comparisons/index.md +83 -0
  61. data/docs/guide/comparisons/lcdf-typetools.md +205 -0
  62. data/docs/guide/contributing.md +279 -0
  63. data/docs/guide/conversion/collections.md +251 -0
  64. data/docs/guide/conversion/curves.md +246 -0
  65. data/docs/guide/conversion/index.md +157 -0
  66. data/docs/guide/conversion/options.md +251 -0
  67. data/docs/guide/conversion/ttf-otf.md +184 -0
  68. data/docs/guide/conversion/type1.md +208 -0
  69. data/docs/guide/conversion/web.md +240 -0
  70. data/docs/guide/conversion.md +39 -0
  71. data/docs/guide/formats/collections.md +147 -0
  72. data/docs/guide/formats/dfont.md +99 -0
  73. data/docs/guide/formats/index.md +65 -0
  74. data/docs/guide/formats/otf.md +103 -0
  75. data/docs/guide/formats/svg.md +97 -0
  76. data/docs/guide/formats/ttf.md +105 -0
  77. data/docs/guide/formats/type1.md +118 -0
  78. data/docs/guide/formats/woff.md +115 -0
  79. data/docs/guide/hinting/autohint.md +141 -0
  80. data/docs/guide/hinting/conversion.md +161 -0
  81. data/docs/guide/hinting/index.md +86 -0
  82. data/docs/guide/hinting/postscript.md +149 -0
  83. data/docs/guide/hinting/truetype.md +135 -0
  84. data/docs/guide/hinting.md +44 -0
  85. data/docs/guide/index.md +152 -0
  86. data/docs/guide/installation.md +116 -0
  87. data/docs/guide/migrations/extract-ttc.md +549 -0
  88. data/docs/guide/migrations/font-validator.md +260 -0
  89. data/docs/guide/migrations/fonttools.md +208 -0
  90. data/docs/guide/migrations/index.md +64 -0
  91. data/docs/guide/migrations/otfinfo.md +197 -0
  92. data/docs/guide/quick-start.md +204 -0
  93. data/docs/guide/type1.md +58 -0
  94. data/docs/guide/universal-outline.md +151 -0
  95. data/docs/guide/validation/custom.md +195 -0
  96. data/docs/guide/validation/helpers.md +188 -0
  97. data/docs/guide/validation/index.md +132 -0
  98. data/docs/guide/validation/profiles.md +156 -0
  99. data/docs/guide/validation.md +47 -0
  100. data/docs/guide/variable-fonts/advanced.md +231 -0
  101. data/docs/guide/variable-fonts/axes.md +209 -0
  102. data/docs/guide/variable-fonts/conversion.md +197 -0
  103. data/docs/guide/variable-fonts/index.md +84 -0
  104. data/docs/guide/variable-fonts/instances.md +187 -0
  105. data/docs/guide/variable-fonts/named-instances.md +194 -0
  106. data/docs/guide/variable-fonts/static.md +168 -0
  107. data/docs/guide/variable.md +58 -0
  108. data/docs/guide/woff.md +59 -0
  109. data/docs/index.md +136 -0
  110. data/docs/lychee.toml +37 -0
  111. data/docs/package-lock.json +2560 -0
  112. data/docs/package.json +15 -0
  113. data/docs/public/apple-touch-icon.png +0 -0
  114. data/docs/public/favicon-96x96.png +0 -0
  115. data/docs/public/favicon.ico +0 -0
  116. data/docs/public/favicon.svg +1 -0
  117. data/docs/public/logo-full.svg +1 -0
  118. data/docs/public/logo.svg +1 -0
  119. data/docs/public/site.webmanifest +21 -0
  120. data/docs/public/web-app-manifest-192x192.png +0 -0
  121. data/docs/public/web-app-manifest-512x512.png +0 -0
  122. data/fontisan.gemspec +1 -1
  123. data/lib/fontisan/commands/features_command.rb +0 -1
  124. data/lib/fontisan/commands/info_command.rb +5 -5
  125. data/lib/fontisan/commands/scripts_command.rb +0 -1
  126. data/lib/fontisan/converters/format_converter.rb +2 -1
  127. data/lib/fontisan/converters/type1_converter.rb +65 -60
  128. data/lib/fontisan/hints/hint_converter.rb +2 -1
  129. data/lib/fontisan/loading_modes.rb +0 -2
  130. data/lib/fontisan/open_type_font.rb +0 -40
  131. data/lib/fontisan/sfnt_font.rb +41 -22
  132. data/lib/fontisan/tables/glyf/compound_glyph.rb +0 -1
  133. data/lib/fontisan/true_type_collection.rb +8 -8
  134. data/lib/fontisan/true_type_font.rb +1 -59
  135. data/lib/fontisan/type1/afm_parser.rb +2 -1
  136. data/lib/fontisan/type1/cff_to_type1_converter.rb +24 -19
  137. data/lib/fontisan/type1/private_dict.rb +28 -7
  138. data/lib/fontisan/type1/seac_expander.rb +22 -17
  139. data/lib/fontisan/variable/delta_applicator.rb +3 -3
  140. data/lib/fontisan/variation/optimizer.rb +0 -1
  141. data/lib/fontisan/version.rb +1 -1
  142. data/lib/fontisan/woff2_font.rb +2 -2
  143. data/lib/fontisan/woff_font.rb +3 -3
  144. data/lib/fontisan.rb +3 -2
  145. metadata +122 -4
@@ -0,0 +1,184 @@
1
+ ---
2
+ title: TTF ↔ OTF Conversion
3
+ ---
4
+
5
+ # TTF ↔ OTF Conversion
6
+
7
+ Converting between TrueType (TTF) and OpenType/CFF (OTF) formats involves curve conversion and hinting system changes.
8
+
9
+ ## Overview
10
+
11
+ | Source | Target | Curve Type | Hinting System |
12
+ |--------|--------|------------|----------------|
13
+ | TTF | OTF | Quadratic → Cubic | TrueType → CFF |
14
+ | OTF | TTF | Cubic → Quadratic | CFF → TrueType |
15
+
16
+ ## TTF → OTF
17
+
18
+ Convert TrueType fonts to OpenType/CFF format.
19
+
20
+ ### Recommended Options
21
+
22
+ ```ruby
23
+ Fontisan::ConversionOptions.recommended(from: :ttf, to: :otf)
24
+ # Returns:
25
+ # opening: { convert_curves: true, scale_to_1000: true, autohint: true,
26
+ # decompose_composites: false, store_custom_tables: true }
27
+ # generating: { hinting_mode: "auto", decompose_on_output: true }
28
+ ```
29
+
30
+ ### CLI
31
+
32
+ ```bash
33
+ # Basic conversion
34
+ fontisan convert font.ttf --to otf --output font.otf
35
+
36
+ # With autohint
37
+ fontisan convert font.ttf --to otf --autohint --output font.otf
38
+
39
+ # Show options that will be used
40
+ fontisan convert font.ttf --to otf --show-options
41
+ ```
42
+
43
+ ### Key Considerations
44
+
45
+ - **Curve conversion**: Quadratic → Cubic (mathematically exact, but may increase point count)
46
+ - **Hinting**: TrueType instructions → CFF hints (lossy conversion)
47
+ - **Scaling**: Typically 2048 UPM → 1000 UPM
48
+
49
+ ### Limitations
50
+
51
+ - TrueType hinting instructions are NOT converted to CFF hints
52
+ - GSUB/GPOS features preserved but table format changes
53
+
54
+ ## OTF → TTF
55
+
56
+ Convert OpenType/CFF fonts to TrueType format.
57
+
58
+ ### Recommended Options
59
+
60
+ ```ruby
61
+ Fontisan::ConversionOptions.recommended(from: :otf, to: :ttf)
62
+ # Returns:
63
+ # opening: { decompose_composites: false, read_all_records: true,
64
+ # interpret_ot: true, store_custom_tables: true,
65
+ # store_native_hinting: false }
66
+ # generating: { hinting_mode: "full", reencode_first_256: false }
67
+ ```
68
+
69
+ ### CLI
70
+
71
+ ```bash
72
+ # Basic conversion
73
+ fontisan convert font.otf --to ttf --output font.ttf
74
+
75
+ # With full hinting
76
+ fontisan convert font.otf --to ttf --hinting-mode full --output font.ttf
77
+ ```
78
+
79
+ ### Key Considerations
80
+
81
+ - **Curve conversion**: Cubic → Quadratic (requires approximation)
82
+ - **Hinting**: CFF hints → TrueType instructions (lossy conversion)
83
+ - **OpenType features**: Interpreted before conversion
84
+
85
+ ### Limitations
86
+
87
+ - CFF cubic curves must be approximated as TrueType quadratic curves
88
+ - Multiple quadratic curves may be needed for accuracy
89
+ - Some precision loss in curve approximation is unavoidable
90
+
91
+ ## Same-Format Copy
92
+
93
+ ### TTF → TTF
94
+
95
+ ```ruby
96
+ Fontisan::ConversionOptions.recommended(from: :ttf, to: :ttf)
97
+ # opening: { convert_curves: false, scale_to_1000: false,
98
+ # decompose_composites: false, autohint: false,
99
+ # store_custom_tables: true, store_native_hinting: true }
100
+ # generating: { hinting_mode: "preserve", write_custom_tables: true,
101
+ # optimize_tables: true }
102
+ ```
103
+
104
+ Use cases: Copy with optimization, metadata updates
105
+
106
+ ### OTF → OTF
107
+
108
+ ```ruby
109
+ Fontisan::ConversionOptions.recommended(from: :otf, to: :otf)
110
+ # opening: { decompose_composites: false, store_custom_tables: true,
111
+ # interpret_ot: true }
112
+ # generating: { hinting_mode: "preserve", decompose_on_output: false,
113
+ # write_custom_tables: true, optimize_tables: true }
114
+ ```
115
+
116
+ Use cases: Copy with optimization, metadata updates
117
+
118
+ ## Curve Conversion Details
119
+
120
+ ### Quadratic → Cubic (TTF → OTF)
121
+
122
+ This conversion is mathematically exact:
123
+
124
+ ```ruby
125
+ # TrueType quadratic Bézier
126
+ # P0, P1, P2 where P1 is the control point
127
+
128
+ # Converts to cubic Bézier
129
+ # P0, C1, C2, P2 where:
130
+ # C1 = P0 + (2/3)(P1 - P0)
131
+ # C2 = P2 + (2/3)(P1 - P2)
132
+ ```
133
+
134
+ Result: Exact representation, but may increase point count.
135
+
136
+ ### Cubic → Quadratic (OTF → TTF)
137
+
138
+ This conversion requires approximation:
139
+
140
+ ```ruby
141
+ # Cubic Bézier cannot be exactly represented as quadratic
142
+ # Requires splitting into multiple quadratic curves
143
+
144
+ # Approximation tolerance controls accuracy
145
+ options = Fontisan::ConversionOptions.new(
146
+ curve_tolerance: 0.5 # Lower = more accurate, more points
147
+ )
148
+ ```
149
+
150
+ Result: Some precision loss unavoidable.
151
+
152
+ ## Examples
153
+
154
+ ### Batch Conversion
155
+
156
+ ```ruby
157
+ # Convert all TTF files in a directory
158
+ Dir.glob('fonts/*.ttf').each do |input|
159
+ output = input.sub('.ttf', '.otf')
160
+ Fontisan.convert(input, output_format: :otf, output_path: output)
161
+ end
162
+ ```
163
+
164
+ ### With Custom Options
165
+
166
+ ```ruby
167
+ options = Fontisan::ConversionOptions.new(
168
+ from: :ttf,
169
+ to: :otf,
170
+ opening: {
171
+ convert_curves: true,
172
+ scale_to_1000: true,
173
+ autohint: true
174
+ },
175
+ generating: {
176
+ hinting_mode: 'auto',
177
+ optimize_tables: true
178
+ }
179
+ )
180
+
181
+ converter = Fontisan::Converters::OutlineConverter.new
182
+ result = converter.convert(font, options: options)
183
+ Fontisan::FontWriter.write(result, 'output.otf')
184
+ ```
@@ -0,0 +1,208 @@
1
+ ---
2
+ title: Type 1 to Modern Formats
3
+ ---
4
+
5
+ # Type 1 to Modern Formats
6
+
7
+ Adobe Type 1 fonts (PFB/PFA) are legacy PostScript fonts. Fontisan provides comprehensive support for converting them to modern formats.
8
+
9
+ ## Overview
10
+
11
+ Type 1 fonts use:
12
+ - **Cubic Bézier curves** — Compatible with CFF/OpenType
13
+ - **PostScript hints** — Different from TrueType instructions
14
+ - **Custom encoding** — May lack Unicode mappings
15
+
16
+ ## Type 1 → OTF
17
+
18
+ Convert Type 1 fonts to OpenType/CFF format.
19
+
20
+ ### Recommended Options
21
+
22
+ ```ruby
23
+ Fontisan::ConversionOptions.recommended(from: :type1, to: :otf)
24
+ # Returns:
25
+ # opening: { decompose_composites: false, generate_unicode: true }
26
+ # generating: { hinting_mode: "none", decompose_on_output: true }
27
+ ```
28
+
29
+ ### CLI
30
+
31
+ ```bash
32
+ # Basic conversion
33
+ fontisan convert font.pfb --to otf --output font.otf
34
+
35
+ # With preset
36
+ fontisan convert font.pfb --to otf --preset type1_to_modern --output font.otf
37
+
38
+ # With Unicode generation
39
+ fontisan convert font.pfb --to otf --generate-unicode --output font.otf
40
+ ```
41
+
42
+ ### Key Considerations
43
+
44
+ - **Unicode**: Generated from Adobe Glyph List
45
+ - **CharStrings**: Type 1 → CFF format (direct conversion)
46
+ - **Hinting**: PostScript hints preserved in CFF
47
+ - **seac composites**: Must be expanded (CFF doesn't support seac)
48
+
49
+ ## Type 1 → TTF
50
+
51
+ Convert Type 1 fonts to TrueType format.
52
+
53
+ ### Recommended Options
54
+
55
+ ```ruby
56
+ Fontisan::ConversionOptions.recommended(from: :type1, to: :ttf)
57
+ # Returns:
58
+ # opening: { decompose_composites: false, generate_unicode: true }
59
+ # generating: { hinting_mode: "full" }
60
+ ```
61
+
62
+ ### Workflow
63
+
64
+ ```
65
+ Type 1 → CFF (OTF) → TTF
66
+ ```
67
+
68
+ ### Key Considerations
69
+
70
+ - Two-step conversion compounds approximation errors
71
+ - Curve conversion: CFF cubic → TrueType quadratic
72
+ - Unicode: Generated from glyph names
73
+
74
+ ### CLI
75
+
76
+ ```bash
77
+ fontisan convert font.pfb --to ttf --autohint --output font.ttf
78
+ ```
79
+
80
+ ## OTF → Type 1
81
+
82
+ Convert OpenType fonts back to Type 1 for legacy systems.
83
+
84
+ ### Recommended Options
85
+
86
+ ```ruby
87
+ Fontisan::ConversionOptions.recommended(from: :otf, to: :type1)
88
+ # opening: { decompose_composites: false }
89
+ # generating: { write_pfm: true, write_afm: true, write_inf: true,
90
+ # select_encoding_automatically: true, hinting_mode: "preserve",
91
+ # decompose_on_output: false }
92
+ ```
93
+
94
+ ### CLI
95
+
96
+ ```bash
97
+ fontisan convert font.otf --to type1 --output font.pfb
98
+ ```
99
+
100
+ ### Limitations
101
+
102
+ - Reverse conversion from CFF to Type 1
103
+ - Modern OpenType features (GPOS, GSUB variations) lost in Type 1
104
+ - CFF hints may not translate exactly to Type 1 hints
105
+
106
+ ## Type 1 → Type 1 (Copy)
107
+
108
+ Re-encode Type 1 font or regenerate metrics files.
109
+
110
+ ### Recommended Options
111
+
112
+ ```ruby
113
+ Fontisan::ConversionOptions.recommended(from: :type1, to: :type1)
114
+ # opening: { decompose_composites: false, generate_unicode: true }
115
+ # generating: { write_pfm: true, write_afm: true, write_inf: true,
116
+ # select_encoding_automatically: true, hinting_mode: "preserve" }
117
+ ```
118
+
119
+ ### CLI
120
+
121
+ ```bash
122
+ # Regenerate metrics files
123
+ fontisan convert font.pfb --to type1 --write-pfm --write-afm --output font-copy.pfb
124
+ ```
125
+
126
+ ## seac Composite Handling
127
+
128
+ Type 1 fonts use `seac` (Standard Encoding Accented Character) for composite glyphs. CFF doesn't support seac, so these must be expanded.
129
+
130
+ ```ruby
131
+ # seac composites are automatically decomposed
132
+ options = Fontisan::ConversionOptions.new(
133
+ opening: { decompose_composites: true }
134
+ )
135
+ ```
136
+
137
+ ### What seac Does
138
+
139
+ ```
140
+ # seac combines two glyphs:
141
+ # Example: é = e + ´ (acute accent)
142
+ #
143
+ # In Type 1:
144
+ # /eacute { seac (e) (acute) } def
145
+ #
146
+ # In CFF/OTF:
147
+ # Must be expanded to actual outlines
148
+ ```
149
+
150
+ ## Presets
151
+
152
+ ### type1_to_modern
153
+
154
+ Optimize Type 1 fonts for modern use:
155
+
156
+ ```ruby
157
+ Fontisan::ConversionOptions.from_preset(:type1_to_modern)
158
+ # From: :type1, To: :otf
159
+ # opening: { generate_unicode: true, decompose_composites: false }
160
+ # generating: { hinting_mode: "preserve", decompose_on_output: true }
161
+ ```
162
+
163
+ Use cases:
164
+ - Modernizing legacy Type 1 fonts
165
+ - Preparing fonts for web use
166
+ - Converting fonts for modern applications
167
+
168
+ ### modern_to_type1
169
+
170
+ Convert modern fonts back to Type 1:
171
+
172
+ ```ruby
173
+ Fontisan::ConversionOptions.from_preset(:modern_to_type1)
174
+ # From: :otf, To: :type1
175
+ # opening: { convert_curves: true, scale_to_1000: true,
176
+ # autohint: true, decompose_composites: false,
177
+ # store_custom_tables: false }
178
+ # generating: { write_pfm: true, write_afm: true, write_inf: true,
179
+ # select_encoding_automatically: true,
180
+ # hinting_mode: "preserve" }
181
+ ```
182
+
183
+ Use cases:
184
+ - Legacy system compatibility
185
+ - Font distribution for older applications
186
+ - Working with Type 1 workflows
187
+
188
+ ## Examples
189
+
190
+ ### Convert Type 1 to Web Font
191
+
192
+ ```bash
193
+ # Direct to WOFF2
194
+ fontisan convert font.pfb --to woff2 --output font.woff2 --preset type1_to_modern
195
+
196
+ # With custom options
197
+ fontisan convert font.pfb --to woff2 --output font.woff2 \
198
+ --generate-unicode --optimize-tables
199
+ ```
200
+
201
+ ### Batch Convert Directory
202
+
203
+ ```ruby
204
+ Dir.glob('legacy/*.pfb').each do |input|
205
+ output = input.sub('.pfb', '.otf').sub('legacy/', 'modern/')
206
+ Fontisan.convert(input, output_format: :otf, output_path: output)
207
+ end
208
+ ```
@@ -0,0 +1,240 @@
1
+ ---
2
+ title: Web Font Formats
3
+ ---
4
+
5
+ # Web Font Formats
6
+
7
+ Fontisan supports conversion to web-optimized formats (WOFF and WOFF2) for optimal web delivery.
8
+
9
+ ## Overview
10
+
11
+ | Format | Compression | Browser Support | Use Case |
12
+ |--------|-------------|-----------------|----------|
13
+ | WOFF | zlib | All modern browsers | Wide compatibility |
14
+ | WOFF2 | brotli | Modern browsers | Smallest size |
15
+
16
+ ## WOFF2
17
+
18
+ WOFF2 provides 30-50% smaller files than TTF/OTF.
19
+
20
+ ### Conversion
21
+
22
+ ```bash
23
+ # Basic WOFF2 conversion
24
+ fontisan convert font.ttf --to woff2 --output font.woff2
25
+
26
+ # From any format
27
+ fontisan convert font.otf --to woff2 --output font.woff2
28
+ fontisan convert font.pfb --to woff2 --output font.woff2
29
+ ```
30
+
31
+ ### Recommended Options
32
+
33
+ ```ruby
34
+ Fontisan::ConversionOptions.from_preset(:web_optimized)
35
+ # From: :otf, To: :woff2
36
+ # opening: {}
37
+ # generating: { compression: "brotli", transform_tables: true,
38
+ # optimize_tables: true, preserve_metadata: true }
39
+ ```
40
+
41
+ ### WOFF2 Benefits
42
+
43
+ - 30-50% smaller than TTF/OTF
44
+ - Broader browser support
45
+ - Preprocessing transforms for better compression
46
+
47
+ ## WOFF
48
+
49
+ WOFF provides wider compatibility with older browsers.
50
+
51
+ ### Conversion
52
+
53
+ ```bash
54
+ # Basic WOFF conversion
55
+ fontisan convert font.ttf --to woff --output font.woff
56
+ ```
57
+
58
+ ### Options
59
+
60
+ ```ruby
61
+ options = Fontisan::ConversionOptions.new(
62
+ to: :woff,
63
+ generating: {
64
+ compression: "zlib",
65
+ preserve_metadata: true,
66
+ add_private_data: false
67
+ }
68
+ )
69
+ ```
70
+
71
+ ## web_optimized Preset
72
+
73
+ Optimize fonts for web delivery:
74
+
75
+ ```ruby
76
+ Fontisan::ConversionOptions.from_preset(:web_optimized)
77
+ # From: :otf, To: :woff2
78
+ # opening: {}
79
+ # generating: { compression: "brotli", transform_tables: true,
80
+ # optimize_tables: true, preserve_metadata: true }
81
+ ```
82
+
83
+ ### Use Cases
84
+
85
+ - Web font delivery
86
+ - Reducing page load time
87
+ - Bandwidth optimization
88
+
89
+ ## Type 1 → Web Fonts
90
+
91
+ Convert legacy Type 1 fonts to web formats.
92
+
93
+ ### Workflow
94
+
95
+ ```
96
+ Type 1 → OTF → WOFF2
97
+ ```
98
+
99
+ ### CLI
100
+
101
+ ```bash
102
+ # Direct conversion
103
+ fontisan convert font.pfb --to woff2 --output font.woff2 --preset type1_to_modern
104
+
105
+ # Step by step
106
+ fontisan convert font.pfb --to otf --output font.otf --generate-unicode
107
+ fontisan convert font.otf --to woff2 --output font.woff2
108
+ ```
109
+
110
+ ### Options
111
+
112
+ ```ruby
113
+ # Via OTF intermediate
114
+ options = Fontisan::ConversionOptions.new(
115
+ opening: { decompose_composites: false, generate_unicode: true },
116
+ generating: { compression: "brotli" } # WOFF2
117
+ # OR: generating: { compression: "zlib" } # WOFF
118
+ )
119
+ ```
120
+
121
+ ## Compression Options
122
+
123
+ ### brotli (WOFF2)
124
+
125
+ ```ruby
126
+ generating: { compression: "brotli" }
127
+ ```
128
+
129
+ - Best compression ratio
130
+ - Requires modern browsers
131
+ - Transforms tables for better compression
132
+
133
+ ### zlib (WOFF)
134
+
135
+ ```ruby
136
+ generating: { compression: "zlib" }
137
+ ```
138
+
139
+ - Good compression
140
+ - Wide browser support
141
+ - No table transforms
142
+
143
+ ### none
144
+
145
+ ```ruby
146
+ generating: { compression: "none" }
147
+ ```
148
+
149
+ - No compression
150
+ - For debugging
151
+
152
+ ## Table Transforms
153
+
154
+ WOFF2 supports table transformations for better compression:
155
+
156
+ | Table | Transform |
157
+ |-------|-----------|
158
+ | glyf | Combined with loca, bbox deltas |
159
+ | hmtx | Combined with hhea |
160
+ | CFF | De-subroutinization |
161
+
162
+ ```ruby
163
+ options = Fontisan::ConversionOptions.new(
164
+ to: :woff2,
165
+ generating: { transform_tables: true }
166
+ )
167
+ ```
168
+
169
+ ## Metadata Handling
170
+
171
+ ### Preserve Metadata
172
+
173
+ ```bash
174
+ fontisan convert font.ttf --to woff2 --preserve-metadata
175
+ ```
176
+
177
+ Keeps copyright, license, and other metadata intact.
178
+
179
+ ### Strip Metadata
180
+
181
+ ```bash
182
+ fontisan convert font.ttf --to woff2 --strip-metadata
183
+ ```
184
+
185
+ Removes metadata for smaller file size (check license first).
186
+
187
+ ## Examples
188
+
189
+ ### Complete Web Font Workflow
190
+
191
+ ```ruby
192
+ require 'fontisan'
193
+
194
+ # Load source
195
+ font = Fontisan::FontLoader.load('source.ttf')
196
+
197
+ # Create WOFF2
198
+ woff2_options = Fontisan::ConversionOptions.from_preset(:web_optimized)
199
+ Fontisan::FontWriter.write(font, 'font.woff2', options: woff2_options)
200
+
201
+ # Create WOFF for older browsers
202
+ woff_options = Fontisan::ConversionOptions.new(
203
+ to: :woff,
204
+ generating: { compression: "zlib", preserve_metadata: true }
205
+ )
206
+ Fontisan::FontWriter.write(font, 'font.woff', options: woff_options)
207
+ ```
208
+
209
+ ### Batch Web Conversion
210
+
211
+ ```bash
212
+ # Convert all TTF files to WOFF2
213
+ for f in fonts/*.ttf; do
214
+ fontisan convert "$f" --to woff2 --output "web/$(basename "${f%.ttf}.woff2")"
215
+ done
216
+ ```
217
+
218
+ ### Compare File Sizes
219
+
220
+ ```bash
221
+ # Check file sizes
222
+ ls -la font.ttf font.woff font.woff2
223
+
224
+ # Example output:
225
+ # -rw-r--r-- font.ttf 124,500 bytes
226
+ # -rw-r--r-- font.woff 98,200 bytes (21% smaller)
227
+ # -rw-r--r-- font.woff2 62,300 bytes (50% smaller)
228
+ ```
229
+
230
+ ## Browser Support
231
+
232
+ | Browser | WOFF | WOFF2 |
233
+ |---------|------|-------|
234
+ | Chrome | 5+ | 36+ |
235
+ | Firefox | 3.6+ | 35+ |
236
+ | Safari | 5.1+ | 12+ |
237
+ | Edge | All | 14+ |
238
+ | IE | 9+ | — |
239
+
240
+ For maximum compatibility, provide both WOFF and WOFF2.
@@ -0,0 +1,39 @@
1
+ # Font Conversion
2
+
3
+ Fontisan supports conversion between various font formats.
4
+
5
+ ## Supported Formats
6
+
7
+ | Input | Output Formats |
8
+ |-------|---------------|
9
+ | TrueType (.ttf) | OTF, WOFF, WOFF2 |
10
+ | OpenType (.otf) | TTF, WOFF, WOFF2 |
11
+ | Type 1 (.pfb) | TTF, OTF, WOFF, WOFF2 |
12
+ | WOFF | TTF, OTF |
13
+ | WOFF2 | TTF, OTF |
14
+
15
+ ## Basic Conversion
16
+
17
+ ```ruby
18
+ require 'fontisan'
19
+
20
+ # Convert TTF to WOFF2
21
+ Fontisan.convert('font.ttf', output_format: :woff2)
22
+
23
+ # Convert with custom output path
24
+ Fontisan.convert('font.ttf', output_path: 'output/font.woff2')
25
+ ```
26
+
27
+ ## Batch Conversion
28
+
29
+ ```ruby
30
+ # Convert multiple files
31
+ fonts = Dir.glob('fonts/*.ttf')
32
+ fonts.each do |font|
33
+ Fontisan.convert(font, output_format: :otf)
34
+ end
35
+ ```
36
+
37
+ ## Related
38
+
39
+ - [WOFF/WOFF2 Formats](/guide/woff) - Details on web font formats