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,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
|
+
```
|