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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +56 -196
- data/Gemfile +1 -1
- data/docs/.gitignore +17 -0
- data/docs/.vitepress/config.ts +317 -0
- data/docs/.vitepress/theme/components/ApiMethod.vue +127 -0
- data/docs/.vitepress/theme/components/Badge.vue +51 -0
- data/docs/.vitepress/theme/components/FeatureComparison.vue +87 -0
- data/docs/.vitepress/theme/components/HeroCodeBlock.vue +98 -0
- data/docs/.vitepress/theme/components/WithinHero.vue +30 -0
- data/docs/.vitepress/theme/index.ts +22 -0
- data/docs/.vitepress/theme/style.css +330 -0
- data/docs/api/conversion-options.md +141 -0
- data/docs/api/converters/curve-converter.md +34 -0
- data/docs/api/converters/hint-converter.md +34 -0
- data/docs/api/converters/outline-converter.md +27 -0
- data/docs/api/font-loader.md +111 -0
- data/docs/api/font-writer.md +103 -0
- data/docs/api/index.md +79 -0
- data/docs/api/models/glyph-accessor.md +43 -0
- data/docs/api/models/glyph.md +40 -0
- data/docs/api/models/table-analyzer.md +35 -0
- data/docs/api/sfnt-font.md +53 -0
- data/docs/api/type1-font.md +43 -0
- data/docs/api/validators/font-validator.md +31 -0
- data/docs/api/validators/helper.md +36 -0
- data/docs/api/validators/profile.md +39 -0
- data/docs/cli/convert.md +87 -0
- data/docs/cli/dump-table.md +110 -0
- data/docs/cli/export.md +176 -0
- data/docs/cli/features.md +124 -0
- data/docs/cli/glyphs.md +90 -0
- data/docs/cli/index.md +208 -0
- data/docs/cli/info.md +254 -0
- data/docs/cli/instance.md +122 -0
- data/docs/cli/ls.md +95 -0
- data/docs/cli/optical-size.md +94 -0
- data/docs/cli/pack.md +125 -0
- data/docs/cli/scripts.md +105 -0
- data/docs/cli/subset.md +39 -0
- data/docs/cli/tables.md +84 -0
- data/docs/cli/unicode.md +101 -0
- data/docs/cli/validate.md +48 -0
- data/docs/cli/variable.md +126 -0
- data/docs/cli/version.md +46 -0
- data/docs/guide/cli/convert.md +108 -0
- data/docs/guide/cli/export.md +138 -0
- data/docs/guide/cli/index.md +99 -0
- data/docs/guide/cli/info.md +144 -0
- data/docs/guide/cli/pack.md +155 -0
- data/docs/guide/cli/subset.md +118 -0
- data/docs/guide/cli/validate.md +139 -0
- data/docs/guide/color-fonts/bitmaps.md +177 -0
- data/docs/guide/color-fonts/colr-cpal.md +175 -0
- data/docs/guide/color-fonts/index.md +140 -0
- data/docs/guide/color-fonts/svg.md +154 -0
- data/docs/guide/color.md +51 -0
- data/docs/guide/comparisons/font-validator.md +222 -0
- data/docs/guide/comparisons/fonttools.md +200 -0
- data/docs/guide/comparisons/index.md +83 -0
- data/docs/guide/comparisons/lcdf-typetools.md +205 -0
- data/docs/guide/contributing.md +279 -0
- data/docs/guide/conversion/collections.md +251 -0
- data/docs/guide/conversion/curves.md +246 -0
- data/docs/guide/conversion/index.md +157 -0
- data/docs/guide/conversion/options.md +251 -0
- data/docs/guide/conversion/ttf-otf.md +184 -0
- data/docs/guide/conversion/type1.md +208 -0
- data/docs/guide/conversion/web.md +240 -0
- data/docs/guide/conversion.md +39 -0
- data/docs/guide/formats/collections.md +147 -0
- data/docs/guide/formats/dfont.md +99 -0
- data/docs/guide/formats/index.md +65 -0
- data/docs/guide/formats/otf.md +103 -0
- data/docs/guide/formats/svg.md +97 -0
- data/docs/guide/formats/ttf.md +105 -0
- data/docs/guide/formats/type1.md +118 -0
- data/docs/guide/formats/woff.md +115 -0
- data/docs/guide/hinting/autohint.md +141 -0
- data/docs/guide/hinting/conversion.md +161 -0
- data/docs/guide/hinting/index.md +86 -0
- data/docs/guide/hinting/postscript.md +149 -0
- data/docs/guide/hinting/truetype.md +135 -0
- data/docs/guide/hinting.md +44 -0
- data/docs/guide/index.md +152 -0
- data/docs/guide/installation.md +116 -0
- data/docs/guide/migrations/extract-ttc.md +549 -0
- data/docs/guide/migrations/font-validator.md +260 -0
- data/docs/guide/migrations/fonttools.md +208 -0
- data/docs/guide/migrations/index.md +64 -0
- data/docs/guide/migrations/otfinfo.md +197 -0
- data/docs/guide/quick-start.md +204 -0
- data/docs/guide/type1.md +58 -0
- data/docs/guide/universal-outline.md +151 -0
- data/docs/guide/validation/custom.md +195 -0
- data/docs/guide/validation/helpers.md +188 -0
- data/docs/guide/validation/index.md +132 -0
- data/docs/guide/validation/profiles.md +156 -0
- data/docs/guide/validation.md +47 -0
- data/docs/guide/variable-fonts/advanced.md +231 -0
- data/docs/guide/variable-fonts/axes.md +209 -0
- data/docs/guide/variable-fonts/conversion.md +197 -0
- data/docs/guide/variable-fonts/index.md +84 -0
- data/docs/guide/variable-fonts/instances.md +187 -0
- data/docs/guide/variable-fonts/named-instances.md +194 -0
- data/docs/guide/variable-fonts/static.md +168 -0
- data/docs/guide/variable.md +58 -0
- data/docs/guide/woff.md +59 -0
- data/docs/index.md +136 -0
- data/docs/lychee.toml +37 -0
- data/docs/package-lock.json +2560 -0
- data/docs/package.json +15 -0
- data/docs/public/apple-touch-icon.png +0 -0
- data/docs/public/favicon-96x96.png +0 -0
- data/docs/public/favicon.ico +0 -0
- data/docs/public/favicon.svg +1 -0
- data/docs/public/logo-full.svg +1 -0
- data/docs/public/logo.svg +1 -0
- data/docs/public/site.webmanifest +21 -0
- data/docs/public/web-app-manifest-192x192.png +0 -0
- data/docs/public/web-app-manifest-512x512.png +0 -0
- data/fontisan.gemspec +1 -1
- data/lib/fontisan/commands/features_command.rb +0 -1
- data/lib/fontisan/commands/info_command.rb +5 -5
- data/lib/fontisan/commands/scripts_command.rb +0 -1
- data/lib/fontisan/converters/format_converter.rb +2 -1
- data/lib/fontisan/converters/type1_converter.rb +65 -60
- data/lib/fontisan/hints/hint_converter.rb +2 -1
- data/lib/fontisan/loading_modes.rb +0 -2
- data/lib/fontisan/open_type_font.rb +0 -40
- data/lib/fontisan/sfnt_font.rb +41 -22
- data/lib/fontisan/tables/glyf/compound_glyph.rb +0 -1
- data/lib/fontisan/true_type_collection.rb +8 -8
- data/lib/fontisan/true_type_font.rb +1 -59
- data/lib/fontisan/type1/afm_parser.rb +2 -1
- data/lib/fontisan/type1/cff_to_type1_converter.rb +24 -19
- data/lib/fontisan/type1/private_dict.rb +28 -7
- data/lib/fontisan/type1/seac_expander.rb +22 -17
- data/lib/fontisan/variable/delta_applicator.rb +3 -3
- data/lib/fontisan/variation/optimizer.rb +0 -1
- data/lib/fontisan/version.rb +1 -1
- data/lib/fontisan/woff2_font.rb +2 -2
- data/lib/fontisan/woff_font.rb +3 -3
- data/lib/fontisan.rb +3 -2
- 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
|