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,205 @@
1
+ ---
2
+ title: vs lcdf-typetools
3
+ ---
4
+
5
+ # Fontisan vs lcdf-typetools
6
+
7
+ Compare Fontisan with the lcdf-typetools suite (otfinfo, cfftot1, t1dotlessj, etc.).
8
+
9
+ ## Overview
10
+
11
+ lcdf-typetools is a C++ suite including:
12
+ - `otfinfo` — Font information
13
+ - `cfftot1` — CFF to Type 1 conversion
14
+ - `t1dotlessj` — Type 1 manipulation
15
+ - `t1reencode` — Type 1 reencoding
16
+ - `ttf2otf` — TTF to OTF conversion
17
+
18
+ | | lcdf-typetools | Fontisan |
19
+ |---|----------------|----------|
20
+ | Language | C++ | Ruby |
21
+ | Compilation | Required | None |
22
+ | Installation | Complex | `gem install` |
23
+ | Cross-platform | Limited | Full |
24
+
25
+ ## Tool Equivalents
26
+
27
+ ### otfinfo
28
+
29
+ | otfinfo | Fontisan |
30
+ |---------|----------|
31
+ | `otfinfo -i font.ttf` | `fontisan info font.ttf` |
32
+ | `otfinfo -s font.ttf` | `fontisan info font.ttf --features` |
33
+ | `otfinfo -f font.ttf` | `fontisan info font.ttf --features` |
34
+ | `otfinfo -g font.ttf` | `fontisan info font.ttf --glyphs` |
35
+ | `otfinfo -u font.ttf` | `fontisan info font.ttf --unicode` |
36
+ | `otfinfo -t font.ttf` | `fontisan info font.ttf --tables` |
37
+
38
+ ### cfftot1
39
+
40
+ | cfftot1 | Fontisan |
41
+ |---------|----------|
42
+ | `cfftot1 font.otf` | `fontisan convert font.otf --to type1 --output font.pfb` |
43
+
44
+ ### t1reencode
45
+
46
+ | t1reencode | Fontisan |
47
+ |------------|----------|
48
+ | `t1reencode font.pfb` | `fontisan convert font.pfb --to type1 --auto-encoding` |
49
+
50
+ ### ttf2otf
51
+
52
+ | ttf2otf | Fontisan |
53
+ |---------|----------|
54
+ | `ttf2otf font.ttf` | `fontisan convert font.ttf --to otf --output font.otf` |
55
+
56
+ ## Feature Comparison
57
+
58
+ ### Font Information
59
+
60
+ | Feature | otfinfo | Fontisan |
61
+ |---------|---------|----------|
62
+ | Basic info | ✅ | ✅ |
63
+ | Script info | ✅ | ✅ |
64
+ | Feature info | ✅ | ✅ |
65
+ | Glyph info | ✅ | ✅ |
66
+ | Unicode info | ✅ | ✅ |
67
+ | Table info | ✅ | ✅ |
68
+ | YAML/JSON | ❌ | ✅ |
69
+
70
+ ### Font Conversion
71
+
72
+ | Feature | lcdf-typetools | Fontisan |
73
+ |---------|----------------|----------|
74
+ | TTF → OTF | ✅ (ttf2otf) | ✅ |
75
+ | OTF → TTF | ❌ | ✅ |
76
+ | OTF → Type 1 | ✅ (cfftot1) | ✅ |
77
+ | Type 1 → OTF | ❌ | ✅ |
78
+ | TTF → WOFF2 | ❌ | ✅ |
79
+
80
+ ### Hinting
81
+
82
+ | Feature | lcdf-typetools | Fontisan |
83
+ |---------|----------------|----------|
84
+ | TrueType hints | Read | Read |
85
+ | PostScript hints | Read | Read |
86
+ | Hint conversion | Partial | ✅ |
87
+ | Bidirectional | ❌ | ✅ |
88
+
89
+ ### Validation
90
+
91
+ | Feature | lcdf-typetools | Fontisan |
92
+ |---------|----------------|----------|
93
+ | Validation | ❌ | ✅ |
94
+ | Profiles | ❌ | ✅ (5) |
95
+ | Helpers | ❌ | ✅ (56) |
96
+
97
+ ### Collections
98
+
99
+ | Feature | lcdf-typetools | Fontisan |
100
+ |---------|----------------|----------|
101
+ | TTC/OTC reading | ❌ | ✅ |
102
+ | TTC/OTC writing | ❌ | ✅ |
103
+ | dfont support | ❌ | ✅ |
104
+
105
+ ## Unique Features
106
+
107
+ ### Fontisan Unique
108
+
109
+ - **Pure Ruby** — No C++ compilation
110
+ - **Built-in validation** — Comprehensive checking
111
+ - **Bidirectional hint conversion** — TrueType ↔ PostScript
112
+ - **Full collection support** — TTC/OTC/dfont
113
+ - **Type 1 → OTF** — Reverse conversion
114
+ - **WOFF/WOFF2** — Web font support
115
+
116
+ ### lcdf-typetools Unique
117
+
118
+ - **t1dotlessj** — Specialized Type 1 manipulation
119
+ - **t1lint** — Type 1 linting
120
+ - **Fast C++** — Native performance
121
+ - **Mature** — Long history
122
+
123
+ ## Installation Comparison
124
+
125
+ ### lcdf-typetools
126
+
127
+ ```bash
128
+ # macOS
129
+ brew install lcdf-typetools
130
+
131
+ # Linux
132
+ apt install lcdf-typetools
133
+ # or compile from source
134
+
135
+ # Windows
136
+ # Requires MSYS2 or WSL
137
+ ```
138
+
139
+ ### Fontisan
140
+
141
+ ```bash
142
+ # All platforms
143
+ gem install fontisan
144
+ ```
145
+
146
+ ## Use Case Recommendations
147
+
148
+ ### Use Fontisan When:
149
+
150
+ - You need validation
151
+ - You need WOFF/WOFF2
152
+ - You need collection support
153
+ - You want minimal installation
154
+ - You need Type 1 → OTF conversion
155
+
156
+ ### Use lcdf-typetools When:
157
+
158
+ - You need t1dotlessj
159
+ - You need t1lint
160
+ - You're in a C++ environment
161
+ - You have existing workflows
162
+
163
+ ## Code Comparison
164
+
165
+ ### Get Font Info
166
+
167
+ ```bash
168
+ # otfinfo
169
+ otfinfo -i font.ttf | grep Family
170
+
171
+ # Fontisan
172
+ fontisan info font.ttf --format json | jq '.family'
173
+ ```
174
+
175
+ ### Convert TTF to OTF
176
+
177
+ ```bash
178
+ # ttf2otf
179
+ ttf2otf font.ttf font.otf
180
+
181
+ # Fontisan
182
+ fontisan convert font.ttf --to otf --output font.otf
183
+ ```
184
+
185
+ ### Convert OTF to Type 1
186
+
187
+ ```bash
188
+ # cfftot1
189
+ cfftot1 font.otf font.pfb
190
+
191
+ # Fontisan
192
+ fontisan convert font.otf --to type1 --output font.pfb
193
+ ```
194
+
195
+ ## Conclusion
196
+
197
+ | Need | Recommendation |
198
+ |------|----------------|
199
+ | Ruby environment | Fontisan |
200
+ | Validation | Fontisan |
201
+ | WOFF/WOFF2 | Fontisan |
202
+ | Collections | Fontisan |
203
+ | t1dotlessj | lcdf-typetools |
204
+ | Type 1 linting | lcdf-typetools |
205
+ | Minimal installation | Fontisan |
@@ -0,0 +1,279 @@
1
+ ---
2
+ title: Contributing Guide
3
+ ---
4
+
5
+ # Contributing Guide
6
+
7
+ Thank you for your interest in contributing to Fontisan! This guide covers how to set up your development environment and run tests.
8
+
9
+ ## Development Setup
10
+
11
+ ### Prerequisites
12
+
13
+ - Ruby 3.0 or higher
14
+ - Bundler gem
15
+ - Git
16
+
17
+ ### Clone and Setup
18
+
19
+ ```bash
20
+ # Clone the repository
21
+ git clone https://github.com/fontist/fontisan.git
22
+ cd fontisan
23
+
24
+ # Install dependencies
25
+ bundle install
26
+
27
+ # Verify installation
28
+ bundle exec fontisan version
29
+ ```
30
+
31
+ ## Running Tests
32
+
33
+ ### Full Test Suite
34
+
35
+ ```bash
36
+ # Run all tests
37
+ bundle exec rspec
38
+
39
+ # Run with documentation format
40
+ bundle exec rspec --format documentation
41
+
42
+ # Run with progress format (default)
43
+ bundle exec rspec --format progress
44
+ ```
45
+
46
+ ### Running Specific Tests
47
+
48
+ ```bash
49
+ # Run specific file
50
+ bundle exec rspec spec/fontisan/tables/maxp_spec.rb
51
+
52
+ # Run specific test by line number
53
+ bundle exec rspec spec/fontisan/tables/maxp_spec.rb:42
54
+
55
+ # Run all table tests
56
+ bundle exec rspec spec/fontisan/tables/
57
+
58
+ # Run all CLI tests
59
+ bundle exec rspec spec/fontisan/cli/
60
+ ```
61
+
62
+ ### Running Tests by Tag
63
+
64
+ ```bash
65
+ # Run only unit tests
66
+ bundle exec rspec --tag ~integration
67
+
68
+ # Run only integration tests
69
+ bundle exec rspec --tag integration
70
+
71
+ # Run only slow tests
72
+ bundle exec rspec --tag slow
73
+ ```
74
+
75
+ ## Test Fixtures
76
+
77
+ Fontisan uses a centralized fixture configuration system for test fonts.
78
+
79
+ ### Automatic Fixture Download
80
+
81
+ Test fixtures are automatically downloaded before tests run:
82
+
83
+ ```bash
84
+ # Run tests (fixtures download automatically)
85
+ bundle exec rspec
86
+
87
+ # Manual fixture management
88
+ bundle exec rake fixtures:download # Download all test fonts
89
+ bundle exec rake fixtures:clean # Remove downloaded fonts
90
+ bundle exec rake fixtures:list # List all fixtures
91
+ ```
92
+
93
+ ### Fixture Locations
94
+
95
+ Fixtures are stored in `spec/fixtures/`:
96
+
97
+ ```
98
+ spec/fixtures/
99
+ ├── fonts/
100
+ │ ├── libertinus/ # Libertinus Serif test fonts
101
+ │ ├── MonaSans/ # Mona Sans variable fonts
102
+ │ └── NotoSerifCJK/ # CJK collection fonts
103
+ └── expected/ # Expected output files
104
+ ```
105
+
106
+ ### Adding New Fixtures
107
+
108
+ 1. Add fixture URL to `spec/fixtures/fixtures.yml`
109
+ 2. Run `bundle exec rake fixtures:download`
110
+ 3. Reference in your tests
111
+
112
+ ```ruby
113
+ # Example test using fixture
114
+ RSpec.describe Fontisan::Tables::Maxp do
115
+ let(:font_path) { 'spec/fixtures/fonts/libertinus/ttf/LibertinusSerif-Regular.ttf' }
116
+
117
+ it 'reads maxp table' do
118
+ font = Fontisan::FontLoader.load(font_path)
119
+ expect(font.table('maxp').num_glyphs).to eq(2731)
120
+ end
121
+ end
122
+ ```
123
+
124
+ ## Test Organization
125
+
126
+ ### Directory Structure
127
+
128
+ ```
129
+ spec/
130
+ ├── spec_helper.rb # Test configuration
131
+ ├── fixtures/ # Test font files
132
+ ├── fontisan/
133
+ │ ├── cli/ # CLI command tests
134
+ │ ├── tables/ # OpenType table tests
135
+ │ ├── converters/ # Converter tests
136
+ │ ├── validators/ # Validator tests
137
+ │ └── fontisan_spec.rb # Main module tests
138
+ └── support/ # Test helpers and matchers
139
+ ```
140
+
141
+ ### Test Categories
142
+
143
+ | Category | Location | Description |
144
+ |----------|----------|-------------|
145
+ | Unit | `spec/fontisan/` | Individual component tests |
146
+ | Integration | `spec/integration/` | End-to-end workflow tests |
147
+ | CLI | `spec/fontisan/cli/` | Command-line interface tests |
148
+
149
+ ## Writing Tests
150
+
151
+ ### Basic Test Structure
152
+
153
+ ```ruby
154
+ require 'spec_helper'
155
+
156
+ RSpec.describe Fontisan::Tables::Head do
157
+ let(:font) { Fontisan::FontLoader.load(fixture_path) }
158
+ let(:head_table) { font.table('head') }
159
+
160
+ describe '#units_per_em' do
161
+ it 'returns the units per em value' do
162
+ expect(head_table.units_per_em).to eq(1000)
163
+ end
164
+ end
165
+
166
+ describe '#valid_magic?' do
167
+ it 'validates the magic number' do
168
+ expect(head_table.valid_magic?).to be true
169
+ end
170
+ end
171
+ end
172
+ ```
173
+
174
+ ### Testing CLI Commands
175
+
176
+ ```ruby
177
+ require 'spec_helper'
178
+
179
+ RSpec.describe 'fontisan info' do
180
+ it 'displays font information' do
181
+ output = `bundle exec fontisan info #{fixture_path}`
182
+
183
+ expect(output).to include('Family:')
184
+ expect(output).to include('Style:')
185
+ end
186
+ end
187
+ ```
188
+
189
+ ### Custom Matchers
190
+
191
+ Fontisan provides custom RSpec matchers:
192
+
193
+ ```ruby
194
+ # Check if output is valid font
195
+ expect(output_font).to be_valid_font
196
+
197
+ # Check if font has table
198
+ expect(font).to have_table('head')
199
+
200
+ # Check if font is valid TrueType
201
+ expect(font).to be_truetype_font
202
+ ```
203
+
204
+ ## Debugging Tests
205
+
206
+ ### Verbose Output
207
+
208
+ ```bash
209
+ # Run with verbose output
210
+ bundle exec rspec --format documentation
211
+
212
+ # Run with backtraces
213
+ bundle exec rspec --backtrace
214
+ ```
215
+
216
+ ### Debugging Single Test
217
+
218
+ ```ruby
219
+ # Add to test for debugging
220
+ it 'debugs something' do
221
+ require 'pry'; binding.pry
222
+ # Test code here
223
+ end
224
+ ```
225
+
226
+ ## Continuous Integration
227
+
228
+ Tests run automatically on GitHub Actions for:
229
+
230
+ - Ruby 3.0, 3.1, 3.2, 3.3
231
+ - Ubuntu, macOS, Windows
232
+
233
+ ### CI Configuration
234
+
235
+ See `.github/workflows/rake.yml` for CI configuration.
236
+
237
+ ## Code Quality
238
+
239
+ ### Linting
240
+
241
+ ```bash
242
+ # Run RuboCop
243
+ bundle exec rubocop
244
+
245
+ # Auto-correct issues
246
+ bundle exec rubocop -a
247
+ ```
248
+
249
+ ### Documentation
250
+
251
+ ```bash
252
+ # Generate YARD documentation
253
+ bundle exec yard doc
254
+ ```
255
+
256
+ ## Reporting Issues
257
+
258
+ When reporting issues, please include:
259
+
260
+ 1. Ruby version (`ruby -v`)
261
+ 2. Fontisan version (`fontisan version`)
262
+ 3. Sample font file (if possible)
263
+ 4. Command that failed
264
+ 5. Expected vs actual behavior
265
+
266
+ ## Pull Requests
267
+
268
+ 1. Fork the repository
269
+ 2. Create a feature branch
270
+ 3. Add tests for new functionality
271
+ 4. Ensure all tests pass
272
+ 5. Submit pull request
273
+
274
+ ### PR Checklist
275
+
276
+ - [ ] Tests pass (`bundle exec rspec`)
277
+ - [ ] Code passes linting (`bundle exec rubocop`)
278
+ - [ ] Documentation updated (if applicable)
279
+ - [ ] CHANGELOG updated (if applicable)
@@ -0,0 +1,251 @@
1
+ ---
2
+ title: Font Collections
3
+ ---
4
+
5
+ # Font Collections
6
+
7
+ Fontisan supports font collections (TTC, OTC, dfont) with pack, unpack, and format conversion capabilities.
8
+
9
+ ## Overview
10
+
11
+ | Format | Description | Font Types |
12
+ |--------|-------------|------------|
13
+ | TTC | TrueType Collection | TrueType fonts only |
14
+ | OTC | OpenType Collection | CFF/OpenType fonts only |
15
+ | dfont | Apple Data Fork Font | Mixed TrueType and CFF |
16
+
17
+ ## Listing Fonts in Collections
18
+
19
+ ### CLI
20
+
21
+ ```bash
22
+ # List fonts in a collection
23
+ fontisan ls fonts.ttc
24
+
25
+ # Output example:
26
+ # Collection: fonts.ttc
27
+ # Fonts: 2
28
+ #
29
+ # 0. Helvetica Regular
30
+ # PostScript: Helvetica-Regular
31
+ # Format: TrueType
32
+ # Glyphs: 268, Tables: 14
33
+ #
34
+ # 1. Helvetica Bold
35
+ # PostScript: Helvetica-Bold
36
+ # Format: TrueType
37
+ # Glyphs: 268, Tables: 14
38
+ ```
39
+
40
+ ### API
41
+
42
+ ```ruby
43
+ collection = Fontisan::FontLoader.load('fonts.ttc')
44
+
45
+ collection.each_with_index do |font, index|
46
+ puts "#{index}. #{font.family_name} #{font.style}"
47
+ end
48
+ ```
49
+
50
+ ## Extracting Fonts (Unpack)
51
+
52
+ ### CLI
53
+
54
+ ```bash
55
+ # Extract all fonts from collection
56
+ fontisan unpack fonts.ttc --output-dir ./extracted
57
+
58
+ # Extract specific font by index
59
+ fontisan unpack fonts.ttc --index 0 --output first.ttf
60
+
61
+ # Extract with format conversion
62
+ fontisan unpack fonts.ttc --output-dir ./extracted --format otf
63
+ ```
64
+
65
+ ### API
66
+
67
+ ```ruby
68
+ collection = Fontisan::FontLoader.load('fonts.ttc')
69
+
70
+ collection.each_with_index do |font, index|
71
+ output = "extracted/font-#{index}.ttf"
72
+ Fontisan::FontWriter.write(font, output)
73
+ end
74
+ ```
75
+
76
+ ## Creating Collections (Pack)
77
+
78
+ ### CLI
79
+
80
+ ```bash
81
+ # Pack fonts into TTC
82
+ fontisan pack font1.ttf font2.ttf font3.ttf --output family.ttc
83
+
84
+ # Pack with deduplication
85
+ fontisan pack font1.ttf font2.ttf --output family.ttc --deduplicate
86
+
87
+ # Pack as OTC (OpenType collection)
88
+ fontisan pack font1.otf font2.otf --output family.otc
89
+ ```
90
+
91
+ ### API
92
+
93
+ ```ruby
94
+ fonts = [
95
+ Fontisan::FontLoader.load('regular.ttf'),
96
+ Fontisan::FontLoader.load('bold.ttf'),
97
+ Fontisan::FontLoader.load('italic.ttf')
98
+ ]
99
+
100
+ Fontisan::CollectionWriter.pack(fonts, 'family.ttc')
101
+ ```
102
+
103
+ ## Collection Conversions
104
+
105
+ ### TTC → OTC
106
+
107
+ ```ruby
108
+ Fontisan::ConversionOptions.recommended(from: :ttc, to: :otc)
109
+ # opening: { convert_curves: true, decompose_composites: false, autohint: false }
110
+ # generating: { target_format: "otf", decompose_on_output: false,
111
+ # hinting_mode: "preserve" }
112
+ ```
113
+
114
+ Converts all TrueType fonts to OpenType/CFF, then repacks as OTC.
115
+
116
+ ```bash
117
+ fontisan convert family.ttc --to otc --output family.otc --target-format otf
118
+ ```
119
+
120
+ ### OTC → TTC
121
+
122
+ ```ruby
123
+ Fontisan::ConversionOptions.recommended(from: :otc, to: :ttc)
124
+ # opening: { convert_curves: true, decompose_composites: false, interpret_ot: true }
125
+ # generating: { target_format: "ttf", decompose_on_output: false,
126
+ # hinting_mode: "auto" }
127
+ ```
128
+
129
+ Converts all OpenType/CFF fonts to TrueType, then repacks as TTC.
130
+
131
+ ```bash
132
+ fontisan convert family.otc --to ttc --output family.ttc --target-format ttf
133
+ ```
134
+
135
+ ### TTC/OTC → dfont
136
+
137
+ ```ruby
138
+ Fontisan::ConversionOptions.recommended(from: :ttc, to: :dfont)
139
+ # opening: {}
140
+ # generating: { target_format: "preserve", decompose_on_output: false,
141
+ # write_custom_tables: true }
142
+ ```
143
+
144
+ Notes: dfont supports both TrueType and OpenType/CFF, or mixed formats.
145
+
146
+ ```bash
147
+ fontisan convert family.ttc --to dfont --output family.dfont
148
+ ```
149
+
150
+ ## Table Sharing
151
+
152
+ Collections share common tables to reduce file size:
153
+
154
+ - `cmap` — Character mappings
155
+ - `loca` — Glyph locations (TrueType)
156
+ - `maxp` — Maximum profile
157
+ - `name` — Font names
158
+ - `post` — PostScript names
159
+
160
+ ### Analyzing Table Sharing
161
+
162
+ ```bash
163
+ fontisan info fonts.ttc
164
+
165
+ # Output includes:
166
+ # Table Sharing Statistics:
167
+ # Shared tables: 4
168
+ # Unique tables per font: 10
169
+ # Space saved: 45%
170
+ ```
171
+
172
+ ## Deduplication
173
+
174
+ When packing collections, Fontisan can deduplicate tables:
175
+
176
+ ```bash
177
+ fontisan pack font1.ttf font2.ttf --output family.ttc --deduplicate
178
+ ```
179
+
180
+ ### How It Works
181
+
182
+ 1. Analyze all tables across fonts
183
+ 2. Identify identical tables by checksum
184
+ 3. Share tables where possible
185
+ 4. Reduce overall file size
186
+
187
+ ## Presets
188
+
189
+ ### archive_to_modern
190
+
191
+ Convert font archives to modern format:
192
+
193
+ ```ruby
194
+ Fontisan::ConversionOptions.from_preset(:archive_to_modern)
195
+ # From: :ttc, To: :otf
196
+ # opening: { convert_curves: true, decompose_composites: false }
197
+ # generating: { target_format: "otf", hinting_mode: "preserve" }
198
+ ```
199
+
200
+ Use cases:
201
+ - Extracting fonts from TTC archives
202
+ - Standardizing collection formats
203
+ - Converting legacy font collections
204
+
205
+ ## Examples
206
+
207
+ ### Extract and Convert Collection
208
+
209
+ ```bash
210
+ # Extract all fonts as OTF
211
+ fontisan unpack fonts.ttc --output-dir ./family --format otf
212
+
213
+ # Results in:
214
+ # family/font-0.otf
215
+ # family/font-1.otf
216
+ # family/font-2.otf
217
+ ```
218
+
219
+ ### Convert Collection Format
220
+
221
+ ```bash
222
+ # Convert TTC to OTC
223
+ fontisan convert truetype-collection.ttc --to otc \
224
+ --output opentype-collection.otc \
225
+ --target-format otf \
226
+ --hinting-mode auto
227
+ ```
228
+
229
+ ### Merge Multiple Collections
230
+
231
+ ```ruby
232
+ # Load multiple collections
233
+ collection1 = Fontisan::FontLoader.load('set1.ttc')
234
+ collection2 = Fontisan::FontLoader.load('set2.ttc')
235
+
236
+ # Combine fonts
237
+ all_fonts = collection1.to_a + collection2.to_a
238
+
239
+ # Pack as new collection
240
+ Fontisan::CollectionWriter.pack(all_fonts, 'combined.ttc')
241
+ ```
242
+
243
+ ### Optimize Collection
244
+
245
+ ```bash
246
+ # Pack with deduplication
247
+ fontisan pack *.ttf --output optimized.ttc --deduplicate
248
+
249
+ # Check space savings
250
+ fontisan info optimized.ttc
251
+ ```