fontisan 0.2.14 → 0.2.17
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 +79 -4
- data/Gemfile +6 -3
- 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 +117 -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 +2 -1
- data/lib/fontisan/commands/features_command.rb +0 -1
- data/lib/fontisan/commands/scripts_command.rb +0 -1
- data/lib/fontisan/constants.rb +29 -6
- data/lib/fontisan/font_loader.rb +184 -318
- data/lib/fontisan/loading_modes.rb +0 -2
- data/lib/fontisan/sfnt_font.rb +4 -3
- data/lib/fontisan/tables/glyf/compound_glyph.rb +0 -1
- 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.rb +3 -2
- metadata +136 -4
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: COLR/CPAL Color Fonts
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# COLR/CPAL Color Fonts
|
|
6
|
+
|
|
7
|
+
COLR/CPAL is a modern color font format using layered vector glyphs.
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
- **COLR** — Defines glyph layers and their order
|
|
12
|
+
- **CPAL** — Defines color palettes
|
|
13
|
+
|
|
14
|
+
## Structure
|
|
15
|
+
|
|
16
|
+
### COLR Table
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
colr = font.tables['COLR']
|
|
20
|
+
|
|
21
|
+
# Base glyphs (color emoji)
|
|
22
|
+
base_glyphs = colr.base_glyphs
|
|
23
|
+
|
|
24
|
+
# Layers for a base glyph
|
|
25
|
+
layers = colr.layers_for(glyph_id)
|
|
26
|
+
# Returns array of { glyph_id:, palette_index: }
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### CPAL Table
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
cpal = font.tables['CPAL']
|
|
33
|
+
|
|
34
|
+
# Number of palettes
|
|
35
|
+
num_palettes = cpal.num_palettes
|
|
36
|
+
|
|
37
|
+
# Colors in a palette
|
|
38
|
+
palette_colors = cpal.palette(0) # First palette
|
|
39
|
+
|
|
40
|
+
# Get specific color
|
|
41
|
+
color = cpal.color(palette_index)
|
|
42
|
+
# Returns { r:, g:, b:, a: }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Working with COLR/CPAL
|
|
46
|
+
|
|
47
|
+
### List Color Glyphs
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
font = Fontisan::FontLoader.load('color-font.ttf')
|
|
51
|
+
colr = font.tables['COLR']
|
|
52
|
+
|
|
53
|
+
colr.base_glyphs.each do |glyph_id|
|
|
54
|
+
glyph_name = font.glyph_name(glyph_id)
|
|
55
|
+
puts "#{glyph_name} (#{glyph_id})"
|
|
56
|
+
end
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Get Layer Colors
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
colr = font.tables['COLR']
|
|
63
|
+
cpal = font.tables['CPAL']
|
|
64
|
+
|
|
65
|
+
colr.base_glyphs.each do |glyph_id|
|
|
66
|
+
puts "Glyph #{glyph_id}:"
|
|
67
|
+
|
|
68
|
+
colr.layers_for(glyph_id).each do |layer|
|
|
69
|
+
color = cpal.color(layer[:palette_index])
|
|
70
|
+
layer_name = font.glyph_name(layer[:glyph_id])
|
|
71
|
+
puts " #{layer_name}: rgba(#{color[:r]}, #{color[:g]}, #{color[:b]}, #{color[:a]})"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Color Palettes
|
|
77
|
+
|
|
78
|
+
### Default Palette
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
cpal = font.tables['CPAL']
|
|
82
|
+
|
|
83
|
+
# First palette (default)
|
|
84
|
+
default_palette = cpal.palette(0)
|
|
85
|
+
puts "Default palette has #{default_palette.length} colors"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Multiple Palettes
|
|
89
|
+
|
|
90
|
+
Some fonts have alternative color schemes:
|
|
91
|
+
|
|
92
|
+
```ruby
|
|
93
|
+
cpal = font.tables['CPAL']
|
|
94
|
+
|
|
95
|
+
(0...cpal.num_palettes).each do |palette_index|
|
|
96
|
+
puts "Palette #{palette_index}:"
|
|
97
|
+
cpal.palette(palette_index).each_with_index do |color, i|
|
|
98
|
+
puts " Color #{i}: rgba(#{color[:r]}, #{color[:g]}, #{color[:b]}, #{color[:a]})"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Conversion
|
|
104
|
+
|
|
105
|
+
### Preserve COLR/CPAL
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# COLR/CPAL is preserved during same-format conversion
|
|
109
|
+
fontisan convert color-font.ttf --to otf --output color-font.otf
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Flatten to PNG
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Export color glyphs as PNG images
|
|
116
|
+
fontisan export color-font.ttf --format png --output ./images/
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Creating COLR/CPAL
|
|
120
|
+
|
|
121
|
+
Currently Fontisan focuses on reading and preserving COLR/CPAL. For creation, consider:
|
|
122
|
+
|
|
123
|
+
1. Design glyphs in layers
|
|
124
|
+
2. Assign palette indices
|
|
125
|
+
3. Define color palettes
|
|
126
|
+
4. Use font editor (Glyphs, FontForge)
|
|
127
|
+
|
|
128
|
+
## Browser Support
|
|
129
|
+
|
|
130
|
+
| Browser | Version |
|
|
131
|
+
|---------|---------|
|
|
132
|
+
| Chrome | 98+ |
|
|
133
|
+
| Firefox | 105+ |
|
|
134
|
+
| Safari | 15.4+ |
|
|
135
|
+
| Edge | 98+ |
|
|
136
|
+
|
|
137
|
+
## Validation
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Validate color font
|
|
141
|
+
fontisan validate color-font.ttf
|
|
142
|
+
|
|
143
|
+
# Check COLR structure
|
|
144
|
+
fontisan info color-font.ttf
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Example
|
|
148
|
+
|
|
149
|
+
### Analyze Color Emoji Font
|
|
150
|
+
|
|
151
|
+
```ruby
|
|
152
|
+
font = Fontisan::FontLoader.load('emoji.ttf')
|
|
153
|
+
colr = font.tables['COLR']
|
|
154
|
+
cpal = font.tables['CPAL']
|
|
155
|
+
|
|
156
|
+
puts "Color glyphs: #{colr.base_glyphs.length}"
|
|
157
|
+
puts "Palettes: #{cpal.num_palettes}"
|
|
158
|
+
|
|
159
|
+
# Find glyph for specific character
|
|
160
|
+
cmap = font.tables['cmap']
|
|
161
|
+
glyph_id = cmap.glyph_id_for('😀')
|
|
162
|
+
|
|
163
|
+
if colr.base_glyphs.include?(glyph_id)
|
|
164
|
+
puts "😀 is a color glyph"
|
|
165
|
+
|
|
166
|
+
layers = colr.layers_for(glyph_id)
|
|
167
|
+
puts "Composed of #{layers.length} layers:"
|
|
168
|
+
|
|
169
|
+
layers.each do |layer|
|
|
170
|
+
layer_name = font.glyph_name(layer[:glyph_id])
|
|
171
|
+
color = cpal.color(layer[:palette_index])
|
|
172
|
+
puts " #{layer_name}: rgba(#{color[:r]}, #{color[:g]}, #{color[:b]})"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
```
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Color Fonts Overview
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Color Fonts Overview
|
|
6
|
+
|
|
7
|
+
Fontisan supports multiple color font formats for modern typography.
|
|
8
|
+
|
|
9
|
+
## Supported Formats
|
|
10
|
+
|
|
11
|
+
| Format | Tables | Description |
|
|
12
|
+
|--------|--------|-------------|
|
|
13
|
+
| COLR/CPAL | COLR, CPAL | Layered vector glyphs |
|
|
14
|
+
| sbix | sbix | Bitmap images (Apple) |
|
|
15
|
+
| CBDT/CBLC | CBDT, CBLC | Bitmap images (Google) |
|
|
16
|
+
| SVG | SVG | SVG embedded in font |
|
|
17
|
+
|
|
18
|
+
## COLR/CPAL
|
|
19
|
+
|
|
20
|
+
COLR/CPAL uses layered vector glyphs with palette-based coloring.
|
|
21
|
+
|
|
22
|
+
### Advantages
|
|
23
|
+
|
|
24
|
+
- **Scalable** — Vectors scale to any size
|
|
25
|
+
- **Small file size** — Efficient compression
|
|
26
|
+
- **Variable support** — Works with variable fonts
|
|
27
|
+
- **Wide support** — Modern browsers and apps
|
|
28
|
+
|
|
29
|
+
### Structure
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
COLR table:
|
|
33
|
+
- Glyph layers (which glyphs make up each color glyph)
|
|
34
|
+
- Layer order (back to front)
|
|
35
|
+
|
|
36
|
+
CPAL table:
|
|
37
|
+
- Color palettes (sets of colors)
|
|
38
|
+
- Color values (RGBA for each palette entry)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## sbix
|
|
42
|
+
|
|
43
|
+
sbix stores bitmap images at multiple resolutions (Apple format).
|
|
44
|
+
|
|
45
|
+
### Advantages
|
|
46
|
+
|
|
47
|
+
- **Photo-realistic** — Any image quality
|
|
48
|
+
- **Multiple sizes** — Different bitmaps for different sizes
|
|
49
|
+
|
|
50
|
+
### Structure
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
sbix table:
|
|
54
|
+
- Strikes (image sets at different sizes)
|
|
55
|
+
- Per-glyph images (PNG, JPG, etc.)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## CBDT/CBLC
|
|
59
|
+
|
|
60
|
+
CBDT/CBLC stores bitmap images (Google/Android format).
|
|
61
|
+
|
|
62
|
+
### Advantages
|
|
63
|
+
|
|
64
|
+
- **Android support** — Primary Android bitmap format
|
|
65
|
+
- **Multiple sizes** — Different bitmaps per ppem
|
|
66
|
+
|
|
67
|
+
### Structure
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
CBLC table:
|
|
71
|
+
- Location data (where each bitmap is)
|
|
72
|
+
- Size information
|
|
73
|
+
|
|
74
|
+
CBDT table:
|
|
75
|
+
- Bitmap data (actual images)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## SVG Color Fonts
|
|
79
|
+
|
|
80
|
+
SVG fonts embed complete SVG documents.
|
|
81
|
+
|
|
82
|
+
### Advantages
|
|
83
|
+
|
|
84
|
+
- **Full SVG features** — Gradients, effects, etc.
|
|
85
|
+
- **Standalone** — No external resources
|
|
86
|
+
|
|
87
|
+
### Limitations
|
|
88
|
+
|
|
89
|
+
- **Large file size** — XML overhead
|
|
90
|
+
- **Limited support** — Not all browsers
|
|
91
|
+
|
|
92
|
+
## Guides
|
|
93
|
+
|
|
94
|
+
- [COLR/CPAL](/guide/color-fonts/colr-cpal) — Vector layered color fonts
|
|
95
|
+
- [Bitmaps](/guide/color-fonts/bitmaps) — sbix and CBDT/CBLC
|
|
96
|
+
- [SVG Color](/guide/color-fonts/svg) — SVG-based color fonts
|
|
97
|
+
|
|
98
|
+
## Quick Start
|
|
99
|
+
|
|
100
|
+
### Check for Color Tables
|
|
101
|
+
|
|
102
|
+
```ruby
|
|
103
|
+
font = Fontisan::FontLoader.load('font.ttf')
|
|
104
|
+
|
|
105
|
+
if font.tables['COLR']
|
|
106
|
+
puts "COLR/CPAL color font"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
if font.tables['sbix']
|
|
110
|
+
puts "sbix bitmap font"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
if font.tables['CBDT']
|
|
114
|
+
puts "CBDT/CBLC bitmap font"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
if font.tables['SVG']
|
|
118
|
+
puts "SVG color font"
|
|
119
|
+
end
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Get Color Information
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
colr = font.tables['COLR']
|
|
126
|
+
cpal = font.tables['CPAL']
|
|
127
|
+
|
|
128
|
+
if colr && cpal
|
|
129
|
+
# Get base glyphs (color emoji)
|
|
130
|
+
colr.base_glyphs.each do |glyph_id|
|
|
131
|
+
puts "Base glyph: #{glyph_id}"
|
|
132
|
+
puts " Layers: #{colr.layers_for(glyph_id).length}"
|
|
133
|
+
|
|
134
|
+
colr.layers_for(glyph_id).each do |layer|
|
|
135
|
+
color = cpal.color(layer[:palette_index])
|
|
136
|
+
puts " Layer #{layer[:glyph_id]}: #{color}"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
```
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: SVG Color Fonts
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# SVG Color Fonts
|
|
6
|
+
|
|
7
|
+
SVG color fonts embed complete SVG documents for each glyph.
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
SVG color fonts contain:
|
|
12
|
+
- Full SVG documents with shapes, gradients, effects
|
|
13
|
+
- Can be extremely detailed and complex
|
|
14
|
+
- Self-contained (no external resources)
|
|
15
|
+
|
|
16
|
+
## Structure
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
svg = font.tables['SVG']
|
|
20
|
+
|
|
21
|
+
# SVG documents by glyph ID
|
|
22
|
+
svg.documents.each do |glyph_id, doc|
|
|
23
|
+
puts "Glyph #{glyph_id}:"
|
|
24
|
+
puts doc # Complete SVG XML
|
|
25
|
+
end
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Reading SVG Fonts
|
|
29
|
+
|
|
30
|
+
### List SVG Glyphs
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
font = Fontisan::FontLoader.load('svg-font.ttf')
|
|
34
|
+
svg = font.tables['SVG']
|
|
35
|
+
|
|
36
|
+
if svg
|
|
37
|
+
svg.documents.each do |glyph_id, doc|
|
|
38
|
+
glyph_name = font.glyph_name(glyph_id)
|
|
39
|
+
puts "#{glyph_name}: #{doc.length} bytes"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Parse SVG Content
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
require 'nokogiri'
|
|
48
|
+
|
|
49
|
+
svg = font.tables['SVG']
|
|
50
|
+
doc = svg.documents[42] # SVG for glyph 42
|
|
51
|
+
|
|
52
|
+
parsed = Nokogiri::XML(doc)
|
|
53
|
+
|
|
54
|
+
# Find elements
|
|
55
|
+
paths = parsed.css('path')
|
|
56
|
+
puts "Paths: #{paths.length}"
|
|
57
|
+
|
|
58
|
+
rects = parsed.css('rect')
|
|
59
|
+
puts "Rectangles: #{rects.length}"
|
|
60
|
+
|
|
61
|
+
# Find gradients
|
|
62
|
+
gradients = parsed.css('linearGradient', 'radialGradient')
|
|
63
|
+
puts "Gradients: #{gradients.length}"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## SVG Features
|
|
67
|
+
|
|
68
|
+
SVG fonts can include:
|
|
69
|
+
|
|
70
|
+
| Feature | Support |
|
|
71
|
+
|---------|---------|
|
|
72
|
+
| Paths | ✓ |
|
|
73
|
+
| Basic shapes | ✓ |
|
|
74
|
+
| Gradients | ✓ |
|
|
75
|
+
| Patterns | ✓ |
|
|
76
|
+
| Clip paths | ✓ |
|
|
77
|
+
| Masks | ✓ |
|
|
78
|
+
| Filters | Limited |
|
|
79
|
+
| Animations | No |
|
|
80
|
+
| Scripts | No |
|
|
81
|
+
|
|
82
|
+
## Exporting
|
|
83
|
+
|
|
84
|
+
### Export SVG Files
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
font = Fontisan::FontLoader.load('svg-font.ttf')
|
|
88
|
+
svg = font.tables['SVG']
|
|
89
|
+
|
|
90
|
+
Dir.mkdir('svg-glyphs') unless Dir.exist?('svg-glyphs')
|
|
91
|
+
|
|
92
|
+
svg.documents.each do |glyph_id, doc|
|
|
93
|
+
glyph_name = font.glyph_name(glyph_id) || "glyph-#{glyph_id}"
|
|
94
|
+
filename = "svg-glyphs/#{glyph_name}.svg"
|
|
95
|
+
File.write(filename, doc)
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Conversion
|
|
100
|
+
|
|
101
|
+
### SVG to Other Formats
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# SVG is preserved during conversion
|
|
105
|
+
fontisan convert svg-font.ttf --to otf --output svg-font.otf
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Remove SVG
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Create version without SVG
|
|
112
|
+
fontisan convert svg-font.ttf --to ttf --no-svg --output no-svg.ttf
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Limitations
|
|
116
|
+
|
|
117
|
+
### File Size
|
|
118
|
+
|
|
119
|
+
SVG fonts can be very large:
|
|
120
|
+
- XML text overhead
|
|
121
|
+
- Duplicate content across glyphs
|
|
122
|
+
- Embedded gradients and filters
|
|
123
|
+
|
|
124
|
+
### Browser Support
|
|
125
|
+
|
|
126
|
+
| Browser | Support |
|
|
127
|
+
|---------|---------|
|
|
128
|
+
| Firefox | Full |
|
|
129
|
+
| Safari | Full |
|
|
130
|
+
| Chrome | Full (since v98) |
|
|
131
|
+
| Edge | Full |
|
|
132
|
+
|
|
133
|
+
### Performance
|
|
134
|
+
|
|
135
|
+
- **Parsing** — SVG requires XML parsing
|
|
136
|
+
- **Rendering** — Complex effects are slow
|
|
137
|
+
- **Memory** — Large documents use more memory
|
|
138
|
+
|
|
139
|
+
## Comparison with COLR/CPAL
|
|
140
|
+
|
|
141
|
+
| Feature | SVG | COLR/CPAL |
|
|
142
|
+
|---------|-----|-----------|
|
|
143
|
+
| File size | Large | Small |
|
|
144
|
+
| Effects | Full | Limited |
|
|
145
|
+
| Gradients | Full | Limited |
|
|
146
|
+
| Browser support | Good | Good |
|
|
147
|
+
| Variable fonts | No | Yes |
|
|
148
|
+
|
|
149
|
+
## Best Practices
|
|
150
|
+
|
|
151
|
+
1. **Optimize SVGs** — Minimize file size
|
|
152
|
+
2. **Use COLR/CPAL if possible** — Better performance
|
|
153
|
+
3. **Test rendering** — Complex effects may not work everywhere
|
|
154
|
+
4. **Provide fallbacks** — Not all platforms support SVG fonts
|
data/docs/guide/color.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Color Fonts
|
|
2
|
+
|
|
3
|
+
Fontisan supports working with color fonts in various formats.
|
|
4
|
+
|
|
5
|
+
## Supported Formats
|
|
6
|
+
|
|
7
|
+
- **COLR/CPAL** - OpenType color font tables
|
|
8
|
+
- **SVG** - SVG-based color fonts
|
|
9
|
+
- **CBDT/CBLC** - Color bitmap fonts
|
|
10
|
+
|
|
11
|
+
## Reading Color Fonts
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
require 'fontisan'
|
|
15
|
+
|
|
16
|
+
# Load a color font
|
|
17
|
+
font = Fontisan.load('color-font.ttf')
|
|
18
|
+
|
|
19
|
+
# Check if font has color
|
|
20
|
+
if font.color?
|
|
21
|
+
puts "This is a color font"
|
|
22
|
+
puts "Format: #{font.color_format}"
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Color Palettes
|
|
27
|
+
|
|
28
|
+
For COLR/CPAL fonts:
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
# Get color palettes
|
|
32
|
+
palettes = font.color_palettes
|
|
33
|
+
|
|
34
|
+
palettes.each do |palette|
|
|
35
|
+
puts "Palette:"
|
|
36
|
+
palette.colors.each do |color|
|
|
37
|
+
puts " ##{color.hex}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Converting Color Fonts
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
# Convert color font to WOFF2
|
|
46
|
+
Fontisan.convert('color-font.ttf', output_format: :woff2)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Related
|
|
50
|
+
|
|
51
|
+
- [Variable Fonts](/guide/variable) - Variable font support
|