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,149 @@
1
+ ---
2
+ title: PostScript Hinting
3
+ ---
4
+
5
+ # PostScript Hinting
6
+
7
+ PostScript hints are declarative values stored in the CFF Private dictionary.
8
+
9
+ ## Hint Parameters
10
+
11
+ ### Blue Values
12
+
13
+ Alignment zones for vertical positioning:
14
+
15
+ | Parameter | Description | Max Values |
16
+ |-----------|-------------|------------|
17
+ | `blue_values` | Baseline and top zones | 14 (7 pairs) |
18
+ | `other_blues` | Descender zones | 10 (5 pairs) |
19
+
20
+ ```ruby
21
+ # Example blue values
22
+ blue_values = [-20, 0, 700, 720] # Baseline zone and cap height zone
23
+ other_blues = [-250, -230] # Descender zone
24
+ ```
25
+
26
+ ### Stem Widths
27
+
28
+ Standard stem dimensions:
29
+
30
+ | Parameter | Description | Max Values |
31
+ |-----------|-------------|------------|
32
+ | `std_hw` | Standard horizontal stem | 1 |
33
+ | `std_vw` | Standard vertical stem | 1 |
34
+ | `stem_snap_h` | Horizontal stem snap values | 12 |
35
+ | `stem_snap_v` | Vertical stem snap values | 12 |
36
+
37
+ ```ruby
38
+ # Example stem values
39
+ std_hw = 80 # Standard horizontal stem width
40
+ std_vw = 100 # Standard vertical stem width
41
+ stem_snap_h = [80, 90, 100] # Common H stem widths
42
+ stem_snap_v = [100, 110, 120] # Common V stem widths
43
+ ```
44
+
45
+ ### Other Parameters
46
+
47
+ | Parameter | Description | Default |
48
+ |-----------|-------------|---------|
49
+ | `blue_scale` | Threshold for alignment zones | 0.039625 |
50
+ | `blue_shift` | Overshoot threshold | 7 |
51
+ | `blue_fuzz` | Blue zone expansion | 1 |
52
+ | `force_bold` | Force bold rendering | false |
53
+ | `language_group` | 0=Latin, 1=CJK | 0 |
54
+
55
+ ## Reading Hints
56
+
57
+ ```ruby
58
+ font = Fontisan::FontLoader.load('font.otf')
59
+ cff = font.tables['CFF']
60
+
61
+ # Get Private DICT
62
+ private = cff.top_dicts.first[:private]
63
+
64
+ # Read hint parameters
65
+ puts "Blue scale: #{private[:blue_scale]}"
66
+ puts "Std H width: #{private[:std_hw]}"
67
+ puts "Std V width: #{private[:std_vw]}"
68
+ puts "Blue values: #{private[:blue_values]}"
69
+ puts "Other blues: #{private[:other_blues]}"
70
+ puts "Stem snap H: #{private[:stem_snap_h]}"
71
+ puts "Stem snap V: #{private[:stem_snap_v]}"
72
+ ```
73
+
74
+ ## Validation
75
+
76
+ ```ruby
77
+ validator = Fontisan::Hints::HintValidator.new
78
+
79
+ hints = {
80
+ blue_scale: 0.039625,
81
+ std_hw: 80,
82
+ blue_values: [-20, 0, 700, 720]
83
+ }
84
+
85
+ result = validator.validate_postscript_hints(hints)
86
+
87
+ if result[:valid]
88
+ puts "Valid PostScript hints"
89
+ else
90
+ result[:errors].each { |err| puts "Error: #{err}" }
91
+ end
92
+ ```
93
+
94
+ ### Validation Checks
95
+
96
+ - **Value Ranges** — Validates hint parameter bounds
97
+ - **Pair Validation** — Ensures blue zones are in pairs (even count)
98
+ - **Array Limits** — Enforces CFF specification limits
99
+ - **Positive Values** — Verifies stem widths are positive
100
+ - **Language Group** — Validates value is 0 or 1
101
+
102
+ ## Blue Zone Examples
103
+
104
+ ### Latin Font
105
+
106
+ ```ruby
107
+ blue_values = [
108
+ -20, 0, # Baseline zone (-20 to 0)
109
+ 470, 490, # x-height zone (470 to 490)
110
+ 700, 720 # Cap height zone (700 to 720)
111
+ ]
112
+
113
+ other_blues = [
114
+ -250, -230 # Descender zone (-250 to -230)
115
+ ]
116
+ ```
117
+
118
+ ### CJK Font
119
+
120
+ ```ruby
121
+ blue_values = [
122
+ -20, 0, # Baseline
123
+ 880, 900 # Top zone
124
+ ]
125
+
126
+ other_blues = []
127
+
128
+ language_group = 1 # CJK
129
+ ```
130
+
131
+ ## Stem Snap Values
132
+
133
+ Stem snaps tell the rasterizer which widths are "standard":
134
+
135
+ ```ruby
136
+ # If stems in the font are primarily 80, 90, or 100 units
137
+ stem_snap_h = [80, 90, 100]
138
+
139
+ # The rasterizer will snap stems to these values
140
+ # when they're close enough
141
+ ```
142
+
143
+ ## Best Practices
144
+
145
+ 1. **Keep blue zones in pairs** — Each zone needs top and bottom
146
+ 2. **Use realistic values** — Stems should match actual glyph stems
147
+ 3. **Don't over-specify** — 4-5 blue zones are usually enough
148
+ 4. **Test at small sizes** — Verify hints improve rendering
149
+ 5. **Consider font size** — Adjust blue_scale for text vs display
@@ -0,0 +1,135 @@
1
+ ---
2
+ title: TrueType Hinting
3
+ ---
4
+
5
+ # TrueType Hinting
6
+
7
+ TrueType hinting uses bytecode instructions to control glyph rendering.
8
+
9
+ ## Storage
10
+
11
+ TrueType hints are stored in three tables:
12
+
13
+ | Table | Purpose |
14
+ |-------|---------|
15
+ | `prep` | Control Value Program |
16
+ | `fpgm` | Font Program |
17
+ | `cvt` | Control Value Table |
18
+
19
+ ## Instructions
20
+
21
+ ### Stack Operations
22
+
23
+ | Opcode | Name | Purpose |
24
+ |--------|------|---------|
25
+ | `0x40` | NPUSHB | Push n bytes onto stack |
26
+ | `0x41` | NPUSHW | Push n words onto stack |
27
+ | `0xB0-0xB7` | PUSHB[0-7] | Push 1-8 bytes |
28
+ | `0xB8-0xBF` | PUSHW[0-7] | Push 1-8 words |
29
+
30
+ ### Control Value Instructions
31
+
32
+ | Opcode | Name | Purpose |
33
+ |--------|------|---------|
34
+ | `0x1D` | SCVTCI | Set CVT cut-in |
35
+ | `0x1E` | SSWCI | Set single width cut-in |
36
+ | `0x1F` | SSW | Set single width |
37
+ | `0x44` | WCVTP | Write CVT in pixels |
38
+ | `0x70` | WCVTF | Write CVT in FUnits |
39
+
40
+ ## Reading Instructions
41
+
42
+ ```ruby
43
+ font = Fontisan::FontLoader.load('font.ttf')
44
+
45
+ # Get prep table
46
+ prep = font.tables['prep']
47
+ if prep
48
+ puts "Prep program: #{prep.bytecode.length} bytes"
49
+
50
+ # Parse instructions
51
+ parser = Fontisan::Hints::InstructionParser.new
52
+ instructions = parser.parse(prep.bytecode)
53
+
54
+ instructions.each do |inst|
55
+ puts "#{inst.opcode.to_s(16)}: #{inst.name}"
56
+ end
57
+ end
58
+
59
+ # Get CVT table
60
+ cvt = font.tables['cvt']
61
+ if cvt
62
+ puts "CVT entries: #{cvt.values.length}"
63
+ cvt.values.each_with_index do |value, i|
64
+ puts " CVT[#{i}] = #{value}"
65
+ end
66
+ end
67
+ ```
68
+
69
+ ## Validation
70
+
71
+ ```ruby
72
+ validator = Fontisan::Hints::HintValidator.new
73
+
74
+ # Validate prep instructions
75
+ prep = font.tables['prep']
76
+ result = validator.validate_truetype_instructions(prep.bytecode)
77
+
78
+ if result[:valid]
79
+ puts "Valid instructions"
80
+ else
81
+ result[:errors].each do |error|
82
+ puts "Error: #{error}"
83
+ end
84
+ end
85
+ ```
86
+
87
+ ### Validation Checks
88
+
89
+ - **Bytecode Structure** — Validates instruction opcodes and parameters
90
+ - **Stack Operations** — Ensures proper stack depth management
91
+ - **Parameter Counts** — Verifies correct number of operands
92
+ - **Truncation Detection** — Identifies incomplete instructions
93
+ - **Stack Neutrality** — Checks if sequences maintain stack balance
94
+
95
+ ## Instruction Encoding
96
+
97
+ The generator automatically selects efficient encoding:
98
+
99
+ ### Byte Values (0-255)
100
+
101
+ ```
102
+ Value 17: PUSHB[0] 17 (2 bytes)
103
+ Values [10,20,30]: NPUSHB 3 10 20 30 (5 bytes)
104
+ ```
105
+
106
+ ### Word Values (256-65535)
107
+
108
+ ```
109
+ Value 300: PUSHW[0] 0x01 0x2C (3 bytes, big-endian)
110
+ Values [300,400]: NPUSHW 2 0x01 0x2C 0x01 0x90 (7 bytes)
111
+ ```
112
+
113
+ ## CVT Values
114
+
115
+ The Control Value Table stores frequently used values:
116
+
117
+ ```ruby
118
+ cvt = font.tables['cvt']
119
+
120
+ # Typical CVT layout
121
+ # CVT[0] - Standard vertical stem width
122
+ # CVT[1] - Standard horizontal stem width
123
+ # CVT[2-7] - Blue zone values
124
+ # CVT[8+] - Other common values
125
+
126
+ puts "Standard V stem: #{cvt.values[0]}"
127
+ puts "Standard H stem: #{cvt.values[1]}"
128
+ ```
129
+
130
+ ## Best Practices
131
+
132
+ 1. **Use CVT for common values** — Reduces bytecode size
133
+ 2. **Keep prep simple** — Complex programs can cause compatibility issues
134
+ 3. **Test cross-platform** — Hinting behavior varies by rasterizer
135
+ 4. **Validate before release** — Ensure instructions are well-formed
@@ -0,0 +1,44 @@
1
+ # Font Hinting
2
+
3
+ Fontisan provides tools for working with font hinting data.
4
+
5
+ ## Overview
6
+
7
+ Font hinting (also known as instructing) is the process of adjusting the display of fonts to align with a pixel grid, improving legibility at small sizes.
8
+
9
+ ## Hinting Formats
10
+
11
+ - **fpgm/cvt/prep** - TrueType instructions
12
+ - **gasp** - Grid-fitting and scan-conversion procedure
13
+ - **GPOS/GSUB** - OpenType positioning and substitution
14
+
15
+ ## Reading Hinting Data
16
+
17
+ ```ruby
18
+ require 'fontisan'
19
+
20
+ font = Fontisan.load('font.ttf')
21
+
22
+ # Check for TrueType instructions
23
+ if font.trueType_instructions?
24
+ puts "Font has TrueType hinting"
25
+ end
26
+
27
+ # Get gasp table
28
+ if font.gasp_table
29
+ font.gasp_table.ranges.each do |range|
30
+ puts "Size #{range.range_max_ppem}: #{range.behavior}"
31
+ end
32
+ end
33
+ ```
34
+
35
+ ## Auto-Hinting
36
+
37
+ ```ruby
38
+ # Apply auto-hinting
39
+ Fontisan.autohint('font.ttf', output: 'font-hinted.ttf')
40
+ ```
41
+
42
+ ## Related
43
+
44
+ - [Font Conversion](/guide/conversion) - Convert fonts while preserving hinting
@@ -0,0 +1,152 @@
1
+ ---
2
+ title: Getting Started
3
+ ---
4
+
5
+ # Getting Started
6
+
7
+ Fontisan is a font processing library for Ruby that provides tools for font conversion, validation, and manipulation.
8
+
9
+ ::: warning Font License Considerations
10
+ Commercial fonts often come with restrictive licenses that may prohibit:
11
+
12
+ - **Subsetting** — Reducing the character set
13
+ - **Format conversion** — Converting between TTF, OTF, WOFF, etc.
14
+ - **Variable font instancing** — Generating static instances
15
+ - **Glyph modification** — Altering or extracting individual glyphs
16
+ - **Redistribution** — Sharing converted or modified fonts
17
+
18
+ Always check your font's End User License Agreement (EULA) before processing. Many foundries require additional licenses for web embedding, subsetting, or format conversion. **Fontisan provides the tools — you are responsible for ensuring you have the rights to use them.**
19
+ :::
20
+
21
+ ## Features
22
+
23
+ Fontisan provides comprehensive font processing capabilities:
24
+
25
+ - **🔄 Font Conversion** — Convert between TTF, OTF, WOFF, WOFF2, Type 1, and SVG formats
26
+ - **✅ Font Validation** — Validate fonts with 5 profiles and 56 helpers
27
+ - **📦 Type 1 Support** — Adobe Type 1 fonts (PFB/PFA) with eexec decryption
28
+ - **🎨 Color Fonts** — COLR/CPAL, sbix, and SVG color fonts
29
+ - **⚡ Variable Fonts** — Instance generation, format conversion, named instances
30
+ - **🔧 Font Hinting** — Bidirectional TrueType ↔ PostScript hint conversion
31
+ - **📚 Collections** — TTC/OTC/dfont pack, unpack, and deduplication
32
+ - **💎 Pure Ruby** — No Python, no C++, no C# dependencies
33
+
34
+ ## Installation
35
+
36
+ Add this line to your application's Gemfile:
37
+
38
+ ```ruby
39
+ gem 'fontisan'
40
+ ```
41
+
42
+ And then execute:
43
+
44
+ ```bash
45
+ bundle install
46
+ ```
47
+
48
+ Or install it yourself as:
49
+
50
+ ```bash
51
+ gem install fontisan
52
+ ```
53
+
54
+ ## Quick Start
55
+
56
+ ### Load a Font
57
+
58
+ ```ruby
59
+ require 'fontisan'
60
+
61
+ # Automatic format detection
62
+ font = Fontisan::FontLoader.load('font.ttf')
63
+
64
+ # Works with any format
65
+ font = Fontisan::FontLoader.load('font.otf') # OpenType
66
+ font = Fontisan::FontLoader.load('font.woff2') # WOFF2
67
+ font = Fontisan::FontLoader.load('font.pfb') # Type 1
68
+ font = Fontisan::FontLoader.load('fonts.ttc') # Collection
69
+ ```
70
+
71
+ ### Get Font Information
72
+
73
+ ```ruby
74
+ # Get basic info
75
+ info = Fontisan::Commands::InfoCommand.new(font: font).run
76
+ puts info.family_name
77
+ puts info.style
78
+ puts info.version
79
+
80
+ # Get table information
81
+ tables = font.tables
82
+ puts tables.keys
83
+ ```
84
+
85
+ ### Convert Fonts
86
+
87
+ ```ruby
88
+ # Simple conversion
89
+ Fontisan.convert('input.ttf', output_format: :woff2)
90
+
91
+ # With custom options
92
+ options = Fontisan::ConversionOptions.new(
93
+ from: :ttf,
94
+ to: :otf,
95
+ opening: { autohint: true, convert_curves: true }
96
+ )
97
+ Fontisan.convert('input.ttf', output_format: :otf, options: options)
98
+ ```
99
+
100
+ ### Validate Fonts
101
+
102
+ ```ruby
103
+ # Validate with a profile
104
+ result = Fontisan::FontValidator.validate('font.ttf', profile: :google_fonts)
105
+
106
+ # Check results
107
+ if result.passed?
108
+ puts "Font is valid!"
109
+ else
110
+ result.errors.each do |error|
111
+ puts "#{error.code}: #{error.message}"
112
+ end
113
+ end
114
+ ```
115
+
116
+ ## CLI Usage
117
+
118
+ Fontisan includes a comprehensive CLI:
119
+
120
+ ```bash
121
+ # Get font information
122
+ fontisan info font.ttf
123
+
124
+ # List fonts in a collection
125
+ fontisan ls fonts.ttc
126
+
127
+ # Convert fonts
128
+ fontisan convert input.ttf --to otf --output output.otf
129
+
130
+ # Validate fonts
131
+ fontisan validate font.ttf --profile google_fonts
132
+
133
+ # Extract fonts from collection
134
+ fontisan unpack fonts.ttc --output-dir ./extracted
135
+
136
+ # Pack fonts into collection
137
+ fontisan pack font1.ttf font2.ttf --output fonts.ttc
138
+
139
+ # Export to TTX
140
+ fontisan export font.ttf --format ttx
141
+
142
+ # Subset fonts
143
+ fontisan subset font.ttf --chars "ABC123"
144
+ ```
145
+
146
+ ## Next Steps
147
+
148
+ - [Installation Details](/guide/installation) — Detailed installation options
149
+ - [Quick Start Guide](/guide/quick-start) — Common workflows
150
+ - [CLI Reference](/guide/cli/) — Command-line documentation
151
+ - [Font Formats](/guide/formats/) — Supported format details
152
+ - [Conversion Guide](/guide/conversion/) — Conversion options and best practices
@@ -0,0 +1,116 @@
1
+ ---
2
+ title: Installation
3
+ ---
4
+
5
+ # Installation
6
+
7
+ ## Requirements
8
+
9
+ - Ruby 3.0 or higher
10
+ - No external dependencies (pure Ruby)
11
+
12
+ ## Installing the Gem
13
+
14
+ ### With Bundler
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'fontisan'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ ```bash
25
+ bundle install
26
+ ```
27
+
28
+ ### Manual Installation
29
+
30
+ Install it yourself as:
31
+
32
+ ```bash
33
+ gem install fontisan
34
+ ```
35
+
36
+ ## Verifying Installation
37
+
38
+ ```bash
39
+ # Check if CLI is available
40
+ fontisan --version
41
+
42
+ # Get help
43
+ fontisan --help
44
+ ```
45
+
46
+ ## Installing from Source
47
+
48
+ For development or to use the latest features:
49
+
50
+ ```bash
51
+ git clone https://github.com/fontist/fontisan.git
52
+ cd fontisan
53
+ bundle install
54
+ bundle exec rake install
55
+ ```
56
+
57
+ ## Dependencies
58
+
59
+ Fontisan is **100% pure Ruby** with no external dependencies:
60
+
61
+ - No Python required
62
+ - No C++ compilation needed
63
+ - No native extensions
64
+ - Works on Linux, macOS, Windows, and BSD
65
+
66
+ ### Optional Dependencies
67
+
68
+ For development:
69
+
70
+ ```bash
71
+ # Install development dependencies
72
+ bundle install
73
+
74
+ # Run tests
75
+ bundle exec rspec
76
+
77
+ # Run linter
78
+ bundle exec rubocop
79
+ ```
80
+
81
+ ## Troubleshooting
82
+
83
+ ### Ruby Version
84
+
85
+ Fontisan requires Ruby 3.0 or higher. Check your version:
86
+
87
+ ```bash
88
+ ruby --version
89
+ ```
90
+
91
+ ### Permission Issues
92
+
93
+ If you encounter permission errors, try:
94
+
95
+ ```bash
96
+ # Install to user directory
97
+ gem install fontisan --user-install
98
+
99
+ # Or use sudo (not recommended)
100
+ sudo gem install fontisan
101
+ ```
102
+
103
+ ### Bundler Issues
104
+
105
+ If Bundler has issues:
106
+
107
+ ```bash
108
+ # Update Bundler
109
+ gem update bundler
110
+
111
+ # Clear cache
112
+ bundle clean --force
113
+
114
+ # Reinstall
115
+ bundle install --redownload
116
+ ```