fontisan 0.4.22 → 0.4.24
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 +240 -24
- data/Gemfile +6 -0
- data/Rakefile +9 -6
- data/benchmark/compile_benchmark.rb +13 -5
- data/docs/.vitepress/config.ts +1 -0
- data/docs/STITCHER_GUIDE.adoc +47 -3
- data/docs/api/layer.md +89 -0
- data/docs/cli/subset.md +25 -6
- data/docs/guide/cli/subset.md +31 -0
- data/docs/guide/color-fonts/bitmaps.md +17 -0
- data/lib/fontisan/cli.rb +2 -1
- data/lib/fontisan/collection/writer.rb +2 -1
- data/lib/fontisan/commands/validate_collection_command.rb +7 -1
- data/lib/fontisan/commands.rb +2 -1
- data/lib/fontisan/config/subset_profiles.yml +2 -0
- data/lib/fontisan/converters/collection_converter.rb +6 -1
- data/lib/fontisan/converters/svg_generator.rb +3 -1
- data/lib/fontisan/stitcher/cbdt_propagator.rb +44 -22
- data/lib/fontisan/stitcher/collection_result.rb +2 -1
- data/lib/fontisan/stitcher/glyph_cloner.rb +41 -0
- data/lib/fontisan/stitcher/glyph_copier.rb +5 -34
- data/lib/fontisan/stitcher/partition_strategy/by_block.rb +3 -1
- data/lib/fontisan/stitcher/partition_strategy/by_script.rb +6 -2
- data/lib/fontisan/stitcher/source.rb +2 -1
- data/lib/fontisan/stitcher/unique_glyph_name.rb +46 -0
- data/lib/fontisan/stitcher.rb +4 -1
- data/lib/fontisan/subset/shared_state.rb +42 -0
- data/lib/fontisan/subset/subset_context.rb +20 -0
- data/lib/fontisan/subset/table_strategy/cbdt.rb +30 -0
- data/lib/fontisan/subset/table_strategy/cblc.rb +27 -0
- data/lib/fontisan/subset/table_strategy/cmap.rb +146 -0
- data/lib/fontisan/subset/table_strategy/color_bitmap_placement.rb +20 -0
- data/lib/fontisan/subset/table_strategy/color_bitmap_strike_plan.rb +45 -0
- data/lib/fontisan/subset/table_strategy/color_bitmap_subset_plan.rb +62 -0
- data/lib/fontisan/subset/table_strategy/color_bitmap_subsetter.rb +182 -0
- data/lib/fontisan/subset/table_strategy/color_bitmap_subtable_plan.rb +59 -0
- data/lib/fontisan/subset/table_strategy/glyf.rb +29 -0
- data/lib/fontisan/subset/table_strategy/glyf_loca_builder.rb +146 -0
- data/lib/fontisan/subset/table_strategy/head.rb +42 -0
- data/lib/fontisan/subset/table_strategy/hhea.rb +67 -0
- data/lib/fontisan/subset/table_strategy/hmtx.rb +52 -0
- data/lib/fontisan/subset/table_strategy/loca.rb +41 -0
- data/lib/fontisan/subset/table_strategy/maxp.rb +23 -0
- data/lib/fontisan/subset/table_strategy/name.rb +19 -0
- data/lib/fontisan/subset/table_strategy/os2.rb +21 -0
- data/lib/fontisan/subset/table_strategy/pass_through.rb +20 -0
- data/lib/fontisan/subset/table_strategy/post.rb +37 -0
- data/lib/fontisan/subset/table_strategy.rb +75 -0
- data/lib/fontisan/subset/table_subsetter.rb +49 -616
- data/lib/fontisan/subset.rb +3 -0
- data/lib/fontisan/svg/standalone_glyph.rb +4 -1
- data/lib/fontisan/svg_to_glyf/assembler.rb +6 -3
- data/lib/fontisan/svg_to_glyf/geometry/transform_parser.rb +11 -4
- data/lib/fontisan/svg_to_glyf/geometry.rb +4 -2
- data/lib/fontisan/tables/cbdt.rb +66 -121
- data/lib/fontisan/tables/cblc.rb +110 -231
- data/lib/fontisan/tables/cblc_big_glyph_metrics.rb +28 -0
- data/lib/fontisan/tables/cblc_bitmap_size.rb +67 -0
- data/lib/fontisan/tables/cblc_glyph_bitmap_location.rb +28 -0
- data/lib/fontisan/tables/cblc_index_subtable.rb +104 -0
- data/lib/fontisan/tables/cblc_index_subtable_array_entry.rb +20 -0
- data/lib/fontisan/tables/cblc_index_subtable_format_parser.rb +150 -0
- data/lib/fontisan/tables/cblc_index_subtable_header.rb +18 -0
- data/lib/fontisan/tables/cblc_sbit_line_metrics.rb +28 -0
- data/lib/fontisan/tables/cff/cff2_charstring_builder.rb +11 -5
- data/lib/fontisan/tables/cff.rb +2 -1
- data/lib/fontisan/tables/cff2/index_builder.rb +2 -1
- data/lib/fontisan/tables.rb +12 -0
- data/lib/fontisan/ufo/cli.rb +4 -1
- data/lib/fontisan/ufo/compile/cbdt_cblc.rb +2 -1
- data/lib/fontisan/ufo/compile/cff.rb +6 -2
- data/lib/fontisan/ufo/compile/cmap.rb +11 -5
- data/lib/fontisan/ufo/compile/cpal.rb +2 -1
- data/lib/fontisan/ufo/compile/feature_writers/gdef.rb +3 -1
- data/lib/fontisan/ufo/compile/feature_writers/mark_family_base.rb +3 -1
- data/lib/fontisan/ufo/compile/feature_writers.rb +2 -1
- data/lib/fontisan/ufo/compile/filters/cubic_to_quadratic.rb +4 -2
- data/lib/fontisan/ufo/compile/filters/remove_overlaps.rb +2 -1
- data/lib/fontisan/ufo/compile/fvar.rb +7 -3
- data/lib/fontisan/ufo/compile/glyf_loca.rb +4 -2
- data/lib/fontisan/ufo/compile/gvar.rb +5 -2
- data/lib/fontisan/ufo/compile/head.rb +2 -1
- data/lib/fontisan/ufo/compile/item_variation_store.rb +2 -1
- data/lib/fontisan/ufo/compile/name.rb +3 -1
- data/lib/fontisan/ufo/compile/sbix.rb +2 -1
- data/lib/fontisan/ufo/compile/stat.rb +6 -3
- data/lib/fontisan/ufo/convert/from_bin_data.rb +6 -2
- data/lib/fontisan/ufo/convert/to_dfont.rb +6 -2
- data/lib/fontisan/ufo/convert/to_otc.rb +4 -1
- data/lib/fontisan/ufo/convert/to_postscript.rb +8 -3
- data/lib/fontisan/ufo/convert/to_woff.rb +8 -3
- data/lib/fontisan/ufo/convert/to_woff2.rb +8 -3
- data/lib/fontisan/ufo/convert.rb +4 -1
- data/lib/fontisan/ufo/glyph_exists_error.rb +23 -0
- data/lib/fontisan/ufo/info.rb +4 -2
- data/lib/fontisan/ufo/layer.rb +42 -2
- data/lib/fontisan/ufo/plist.rb +7 -2
- data/lib/fontisan/ufo/reader.rb +3 -1
- data/lib/fontisan/ufo/writer.rb +13 -5
- data/lib/fontisan/ufo.rb +2 -1
- data/lib/fontisan/version.rb +1 -1
- data/lib/fontisan/woff2/collection_decoder.rb +4 -1
- data/lib/fontisan/woff2/collection_encoder.rb +4 -1
- data/lib/fontisan/woff2/glyf_canonicalizer.rb +2 -1
- data/lib/fontisan/woff2/glyf_loca_reconstruct.rb +5 -2
- data/lib/fontisan/woff2/sfnt_checksum.rb +2 -1
- data/lib/fontisan.rb +0 -1
- metadata +36 -4
- data/lib/fontisan/tasks/fixture_downloader.rb +0 -162
- data/lib/fontisan/tasks.rb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 556befd056a62c96c03bfaab023a7027b098df4145148415f4735db53da719ee
|
|
4
|
+
data.tar.gz: 41ddfe5df546ee2b1855644d0eddb1caed472f61e88030ad653038e536393ee6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 057fc2598f2ad7a02b1847d502f6c0363f6f23382806de361a5dd87bb2b4c99d00993f2e272ab3f2c35697dc0b8843235df05301047b1c3cdbf0e0147498282d
|
|
7
|
+
data.tar.gz: 1669c95792cc2a7731f4495e2d91e2e89b545412e213f8aff78e0dfc625a60c9f9403dc9960e4e487da1563e794fb2d3a6d5126f4ab6ef35e6ebe42e9950fd5d
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-07-
|
|
3
|
+
# on 2026-07-09 14:55:09 UTC using RuboCop version 1.86.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -12,20 +12,190 @@ Gemspec/RequiredRubyVersion:
|
|
|
12
12
|
- 'docs/node_modules/speakingurl/speakingurl-rails.gemspec'
|
|
13
13
|
- 'fontisan.gemspec'
|
|
14
14
|
|
|
15
|
-
# Offense count:
|
|
15
|
+
# Offense count: 276
|
|
16
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
17
|
+
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
18
|
+
# SupportedStyles: with_first_argument, with_fixed_indentation
|
|
19
|
+
Layout/ArgumentAlignment:
|
|
20
|
+
Enabled: false
|
|
21
|
+
|
|
22
|
+
# Offense count: 22
|
|
23
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
24
|
+
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
25
|
+
# SupportedStyles: with_first_element, with_fixed_indentation
|
|
26
|
+
Layout/ArrayAlignment:
|
|
27
|
+
Exclude:
|
|
28
|
+
- 'lib/fontisan/collection/writer.rb'
|
|
29
|
+
- 'lib/fontisan/tables/cff2/index_builder.rb'
|
|
30
|
+
- 'lib/fontisan/ufo/compile/cbdt_cblc.rb'
|
|
31
|
+
- 'lib/fontisan/ufo/compile/cff.rb'
|
|
32
|
+
- 'lib/fontisan/ufo/compile/cmap.rb'
|
|
33
|
+
- 'lib/fontisan/ufo/compile/cpal.rb'
|
|
34
|
+
- 'lib/fontisan/ufo/compile/gvar.rb'
|
|
35
|
+
- 'lib/fontisan/ufo/compile/item_variation_store.rb'
|
|
36
|
+
- 'lib/fontisan/ufo/compile/sbix.rb'
|
|
37
|
+
- 'lib/fontisan/ufo/compile/stat.rb'
|
|
38
|
+
- 'lib/fontisan/ufo/info.rb'
|
|
39
|
+
- 'spec/fontisan/stitcher/glyph_signature_spec.rb'
|
|
40
|
+
- 'spec/fontisan/svg_to_glyf/contour_builder_spec.rb'
|
|
41
|
+
- 'spec/fontisan/ufo/compile/feature_writers/mkmk_spec.rb'
|
|
42
|
+
- 'spec/fontisan/ufo/compile/filters/transformations_spec.rb'
|
|
43
|
+
|
|
44
|
+
# Offense count: 1
|
|
45
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
46
|
+
# Configuration parameters: IndentationWidth.
|
|
47
|
+
Layout/AssignmentIndentation:
|
|
48
|
+
Exclude:
|
|
49
|
+
- 'lib/fontisan/woff2/glyf_loca_reconstruct.rb'
|
|
50
|
+
|
|
51
|
+
# Offense count: 58
|
|
52
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
53
|
+
# Configuration parameters: EnforcedStyleAlignWith.
|
|
54
|
+
# SupportedStylesAlignWith: either, start_of_block, start_of_line
|
|
55
|
+
Layout/BlockAlignment:
|
|
56
|
+
Enabled: false
|
|
57
|
+
|
|
58
|
+
# Offense count: 55
|
|
59
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
60
|
+
Layout/BlockEndNewline:
|
|
61
|
+
Enabled: false
|
|
62
|
+
|
|
63
|
+
# Offense count: 29
|
|
64
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
65
|
+
Layout/ClosingParenthesisIndentation:
|
|
66
|
+
Exclude:
|
|
67
|
+
- 'benchmark/compile_benchmark.rb'
|
|
68
|
+
- 'lib/fontisan/ufo/compile/fvar.rb'
|
|
69
|
+
- 'lib/fontisan/ufo/writer.rb'
|
|
70
|
+
- 'spec/fontisan/stitcher/deduplicator_spec.rb'
|
|
71
|
+
- 'spec/fontisan/stitcher/include_codepoints_map_spec.rb'
|
|
72
|
+
- 'spec/fontisan/svg_to_glyf/affine_transform_spec.rb'
|
|
73
|
+
- 'spec/fontisan/ufo/compile/filters/propagate_anchors_spec.rb'
|
|
74
|
+
- 'spec/fontisan/ufo/compile_gvar_spec.rb'
|
|
75
|
+
- 'spec/fontisan/ufo/compile_item_variation_store_spec.rb'
|
|
76
|
+
- 'spec/fontisan/ufo/filters_spec.rb'
|
|
77
|
+
|
|
78
|
+
# Offense count: 2
|
|
79
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
80
|
+
# Configuration parameters: AllowForAlignment.
|
|
81
|
+
Layout/CommentIndentation:
|
|
82
|
+
Exclude:
|
|
83
|
+
- 'lib/fontisan/ufo/compile/cff.rb'
|
|
84
|
+
|
|
85
|
+
# Offense count: 4
|
|
86
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
87
|
+
Layout/ElseAlignment:
|
|
88
|
+
Exclude:
|
|
89
|
+
- 'lib/fontisan/commands/validate_collection_command.rb'
|
|
90
|
+
- 'lib/fontisan/converters/collection_converter.rb'
|
|
91
|
+
- 'spec/fontisan/woff2/sfnt_checksum_spec.rb'
|
|
92
|
+
|
|
93
|
+
# Offense count: 4
|
|
94
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
95
|
+
# Configuration parameters: EnforcedStyleAlignWith.
|
|
96
|
+
# SupportedStylesAlignWith: keyword, variable, start_of_line
|
|
97
|
+
Layout/EndAlignment:
|
|
98
|
+
Exclude:
|
|
99
|
+
- 'lib/fontisan/commands/validate_collection_command.rb'
|
|
100
|
+
- 'lib/fontisan/converters/collection_converter.rb'
|
|
101
|
+
- 'spec/fontisan/woff2/sfnt_checksum_spec.rb'
|
|
102
|
+
|
|
103
|
+
# Offense count: 29
|
|
104
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
105
|
+
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
106
|
+
# SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses
|
|
107
|
+
Layout/FirstArgumentIndentation:
|
|
108
|
+
Exclude:
|
|
109
|
+
- 'benchmark/compile_benchmark.rb'
|
|
110
|
+
- 'lib/fontisan/ufo/compile/fvar.rb'
|
|
111
|
+
- 'lib/fontisan/ufo/writer.rb'
|
|
112
|
+
- 'spec/fontisan/stitcher/deduplicator_spec.rb'
|
|
113
|
+
- 'spec/fontisan/stitcher/include_codepoints_map_spec.rb'
|
|
114
|
+
- 'spec/fontisan/svg_to_glyf/affine_transform_spec.rb'
|
|
115
|
+
- 'spec/fontisan/ufo/compile/filters/propagate_anchors_spec.rb'
|
|
116
|
+
- 'spec/fontisan/ufo/compile_gvar_spec.rb'
|
|
117
|
+
- 'spec/fontisan/ufo/compile_item_variation_store_spec.rb'
|
|
118
|
+
- 'spec/fontisan/ufo/filters_spec.rb'
|
|
119
|
+
|
|
120
|
+
# Offense count: 14
|
|
121
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
122
|
+
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
123
|
+
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
|
|
124
|
+
Layout/FirstArrayElementIndentation:
|
|
125
|
+
Exclude:
|
|
126
|
+
- 'spec/fontisan/stitcher/glyph_signature_spec.rb'
|
|
127
|
+
- 'spec/fontisan/ufo/compile/feature_writers/mark_spec.rb'
|
|
128
|
+
|
|
129
|
+
# Offense count: 194
|
|
130
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
131
|
+
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
|
132
|
+
# SupportedHashRocketStyles: key, separator, table
|
|
133
|
+
# SupportedColonStyles: key, separator, table
|
|
134
|
+
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
|
135
|
+
Layout/HashAlignment:
|
|
136
|
+
Enabled: false
|
|
137
|
+
|
|
138
|
+
# Offense count: 1
|
|
139
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
140
|
+
# Configuration parameters: EnforcedStyle.
|
|
141
|
+
# SupportedStyles: normal, indented_internal_methods
|
|
142
|
+
Layout/IndentationConsistency:
|
|
143
|
+
Exclude:
|
|
144
|
+
- 'lib/fontisan/ufo/compile/cff.rb'
|
|
145
|
+
|
|
146
|
+
# Offense count: 121
|
|
147
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
148
|
+
# Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns.
|
|
149
|
+
# SupportedStylesAlignWith: start_of_line, relative_to_receiver
|
|
150
|
+
Layout/IndentationWidth:
|
|
151
|
+
Enabled: false
|
|
152
|
+
|
|
153
|
+
# Offense count: 2235
|
|
16
154
|
# This cop supports safe autocorrection (--autocorrect).
|
|
17
155
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
18
156
|
# URISchemes: http, https
|
|
19
157
|
Layout/LineLength:
|
|
20
158
|
Enabled: false
|
|
21
159
|
|
|
160
|
+
# Offense count: 7
|
|
161
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
162
|
+
# Configuration parameters: EnforcedStyle.
|
|
163
|
+
# SupportedStyles: symmetrical, new_line, same_line
|
|
164
|
+
Layout/MultilineArrayBraceLayout:
|
|
165
|
+
Exclude:
|
|
166
|
+
- 'spec/fontisan/stitcher/glyph_signature_spec.rb'
|
|
167
|
+
- 'spec/fontisan/ufo/compile/feature_writers/mark_spec.rb'
|
|
168
|
+
|
|
169
|
+
# Offense count: 29
|
|
170
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
171
|
+
# Configuration parameters: EnforcedStyle.
|
|
172
|
+
# SupportedStyles: symmetrical, new_line, same_line
|
|
173
|
+
Layout/MultilineMethodCallBraceLayout:
|
|
174
|
+
Exclude:
|
|
175
|
+
- 'benchmark/compile_benchmark.rb'
|
|
176
|
+
- 'lib/fontisan/ufo/compile/fvar.rb'
|
|
177
|
+
- 'lib/fontisan/ufo/writer.rb'
|
|
178
|
+
- 'spec/fontisan/stitcher/deduplicator_spec.rb'
|
|
179
|
+
- 'spec/fontisan/stitcher/include_codepoints_map_spec.rb'
|
|
180
|
+
- 'spec/fontisan/svg_to_glyf/affine_transform_spec.rb'
|
|
181
|
+
- 'spec/fontisan/ufo/compile/filters/propagate_anchors_spec.rb'
|
|
182
|
+
- 'spec/fontisan/ufo/compile_gvar_spec.rb'
|
|
183
|
+
- 'spec/fontisan/ufo/compile_item_variation_store_spec.rb'
|
|
184
|
+
- 'spec/fontisan/ufo/filters_spec.rb'
|
|
185
|
+
|
|
186
|
+
# Offense count: 225
|
|
187
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
188
|
+
# Configuration parameters: AllowInHeredoc.
|
|
189
|
+
Layout/TrailingWhitespace:
|
|
190
|
+
Enabled: false
|
|
191
|
+
|
|
22
192
|
# Offense count: 2
|
|
23
193
|
Lint/CopDirectiveSyntax:
|
|
24
194
|
Exclude:
|
|
25
195
|
- 'lib/fontisan/woff2_font.rb'
|
|
26
196
|
- 'spec/fontisan/variation/cache_spec.rb'
|
|
27
197
|
|
|
28
|
-
# Offense count:
|
|
198
|
+
# Offense count: 54
|
|
29
199
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
30
200
|
Lint/DuplicateBranch:
|
|
31
201
|
Enabled: false
|
|
@@ -78,16 +248,12 @@ Lint/StructNewOverride:
|
|
|
78
248
|
Exclude:
|
|
79
249
|
- 'lib/fontisan/optimizers/pattern_analyzer.rb'
|
|
80
250
|
|
|
81
|
-
# Offense count:
|
|
251
|
+
# Offense count: 24
|
|
82
252
|
# This cop supports safe autocorrection (--autocorrect).
|
|
83
253
|
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
|
|
84
254
|
# NotImplementedExceptions: NotImplementedError
|
|
85
255
|
Lint/UnusedMethodArgument:
|
|
86
|
-
|
|
87
|
-
- 'lib/fontisan.rb'
|
|
88
|
-
- 'lib/fontisan/tables/cff2/private_dict_blend_handler.rb'
|
|
89
|
-
- 'lib/fontisan/variation/table_accessor.rb'
|
|
90
|
-
- 'lib/fontisan/woff_font.rb'
|
|
256
|
+
Enabled: false
|
|
91
257
|
|
|
92
258
|
# Offense count: 5
|
|
93
259
|
Lint/UselessConstantScoping:
|
|
@@ -95,12 +261,12 @@ Lint/UselessConstantScoping:
|
|
|
95
261
|
- 'lib/fontisan/conversion_options.rb'
|
|
96
262
|
- 'lib/fontisan/type1/charstrings.rb'
|
|
97
263
|
|
|
98
|
-
# Offense count:
|
|
264
|
+
# Offense count: 715
|
|
99
265
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
100
266
|
Metrics/AbcSize:
|
|
101
267
|
Enabled: false
|
|
102
268
|
|
|
103
|
-
# Offense count:
|
|
269
|
+
# Offense count: 34
|
|
104
270
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
105
271
|
# AllowedMethods: refine
|
|
106
272
|
Metrics/BlockLength:
|
|
@@ -118,28 +284,28 @@ Metrics/CollectionLiteralLength:
|
|
|
118
284
|
- 'lib/fontisan/type1/agl.rb'
|
|
119
285
|
- 'lib/fontisan/type1/encodings.rb'
|
|
120
286
|
|
|
121
|
-
# Offense count:
|
|
287
|
+
# Offense count: 367
|
|
122
288
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
123
289
|
Metrics/CyclomaticComplexity:
|
|
124
290
|
Enabled: false
|
|
125
291
|
|
|
126
|
-
# Offense count:
|
|
292
|
+
# Offense count: 990
|
|
127
293
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
128
294
|
Metrics/MethodLength:
|
|
129
295
|
Max: 135
|
|
130
296
|
|
|
131
|
-
# Offense count:
|
|
297
|
+
# Offense count: 30
|
|
132
298
|
# Configuration parameters: CountKeywordArgs.
|
|
133
299
|
Metrics/ParameterLists:
|
|
134
300
|
Max: 39
|
|
135
301
|
MaxOptionalParameters: 4
|
|
136
302
|
|
|
137
|
-
# Offense count:
|
|
303
|
+
# Offense count: 279
|
|
138
304
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
139
305
|
Metrics/PerceivedComplexity:
|
|
140
306
|
Enabled: false
|
|
141
307
|
|
|
142
|
-
# Offense count:
|
|
308
|
+
# Offense count: 202
|
|
143
309
|
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
|
144
310
|
# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
|
|
145
311
|
Naming/MethodParameterName:
|
|
@@ -182,7 +348,7 @@ Naming/VariableName:
|
|
|
182
348
|
- 'lib/fontisan/type1/pfm_generator.rb'
|
|
183
349
|
- 'lib/fontisan/type1/pfm_parser.rb'
|
|
184
350
|
|
|
185
|
-
# Offense count:
|
|
351
|
+
# Offense count: 124
|
|
186
352
|
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
|
187
353
|
# SupportedStyles: snake_case, normalcase, non_integer
|
|
188
354
|
# AllowedIdentifiers: TLS1_1, TLS1_2, capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
|
|
@@ -199,13 +365,13 @@ RSpec/AnyInstance:
|
|
|
199
365
|
- 'spec/fontisan/variation/parallel_generator_spec.rb'
|
|
200
366
|
- 'spec/integration/format_conversion_spec.rb'
|
|
201
367
|
|
|
202
|
-
# Offense count:
|
|
368
|
+
# Offense count: 128
|
|
203
369
|
# Configuration parameters: Prefixes, AllowedPatterns.
|
|
204
370
|
# Prefixes: when, with, without
|
|
205
371
|
RSpec/ContextWording:
|
|
206
372
|
Enabled: false
|
|
207
373
|
|
|
208
|
-
# Offense count:
|
|
374
|
+
# Offense count: 39
|
|
209
375
|
# Configuration parameters: IgnoredMetadata.
|
|
210
376
|
RSpec/DescribeClass:
|
|
211
377
|
Enabled: false
|
|
@@ -221,7 +387,7 @@ RSpec/DescribeMethod:
|
|
|
221
387
|
- 'spec/fontisan/type1/seac_expander_spec.rb'
|
|
222
388
|
- 'spec/fontisan/type1_real_fonts_spec.rb'
|
|
223
389
|
|
|
224
|
-
# Offense count:
|
|
390
|
+
# Offense count: 1710
|
|
225
391
|
# Configuration parameters: CountAsOne.
|
|
226
392
|
RSpec/ExampleLength:
|
|
227
393
|
Max: 66
|
|
@@ -273,7 +439,7 @@ RSpec/IteratedExpectation:
|
|
|
273
439
|
Exclude:
|
|
274
440
|
- 'spec/fontisan/tables/glyf_spec.rb'
|
|
275
441
|
|
|
276
|
-
# Offense count:
|
|
442
|
+
# Offense count: 27
|
|
277
443
|
# Configuration parameters: EnforcedStyle.
|
|
278
444
|
# SupportedStyles: have_received, receive
|
|
279
445
|
RSpec/MessageSpies:
|
|
@@ -289,6 +455,7 @@ RSpec/MessageSpies:
|
|
|
289
455
|
- 'spec/fontisan/subset/builder_spec.rb'
|
|
290
456
|
- 'spec/fontisan/variation/instance_writer_spec.rb'
|
|
291
457
|
- 'spec/fontisan/woff2_font_spec.rb'
|
|
458
|
+
- 'spec/support/fixture_downloader_spec.rb'
|
|
292
459
|
|
|
293
460
|
# Offense count: 4
|
|
294
461
|
RSpec/MultipleDescribes:
|
|
@@ -298,7 +465,7 @@ RSpec/MultipleDescribes:
|
|
|
298
465
|
- 'spec/fontisan/utils/thread_pool_spec.rb'
|
|
299
466
|
- 'spec/fontisan/variation/cache_spec.rb'
|
|
300
467
|
|
|
301
|
-
# Offense count:
|
|
468
|
+
# Offense count: 2126
|
|
302
469
|
RSpec/MultipleExpectations:
|
|
303
470
|
Max: 19
|
|
304
471
|
|
|
@@ -330,7 +497,7 @@ RSpec/RepeatedExample:
|
|
|
330
497
|
- 'spec/fontisan/metrics_calculator_spec.rb'
|
|
331
498
|
- 'spec/fontisan/tables/os2_spec.rb'
|
|
332
499
|
|
|
333
|
-
# Offense count:
|
|
500
|
+
# Offense count: 51
|
|
334
501
|
# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
|
|
335
502
|
# SupportedInflectors: default, active_support
|
|
336
503
|
RSpec/SpecFilePathFormat:
|
|
@@ -341,10 +508,11 @@ RSpec/SpecFilePathSuffix:
|
|
|
341
508
|
Exclude:
|
|
342
509
|
- 'spec/benchmarks/subroutine_optimization_benchmark.rb'
|
|
343
510
|
|
|
344
|
-
# Offense count:
|
|
511
|
+
# Offense count: 2
|
|
345
512
|
RSpec/StubbedMock:
|
|
346
513
|
Exclude:
|
|
347
514
|
- 'spec/fontisan/woff2_font_spec.rb'
|
|
515
|
+
- 'spec/support/fixture_downloader_spec.rb'
|
|
348
516
|
|
|
349
517
|
# Offense count: 10
|
|
350
518
|
RSpec/SubjectStub:
|
|
@@ -361,6 +529,16 @@ Rake/MethodDefinitionInTask:
|
|
|
361
529
|
Exclude:
|
|
362
530
|
- 'Rakefile'
|
|
363
531
|
|
|
532
|
+
# Offense count: 68
|
|
533
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
534
|
+
# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
|
|
535
|
+
# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
|
|
536
|
+
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
|
|
537
|
+
# FunctionalMethods: let, let!, subject, watch
|
|
538
|
+
# AllowedMethods: lambda, proc, it
|
|
539
|
+
Style/BlockDelimiters:
|
|
540
|
+
Enabled: false
|
|
541
|
+
|
|
364
542
|
# Offense count: 6
|
|
365
543
|
# This cop supports safe autocorrection (--autocorrect).
|
|
366
544
|
Style/ComparableClamp:
|
|
@@ -395,9 +573,47 @@ Style/HashLikeCase:
|
|
|
395
573
|
- 'lib/fontisan/commands/unpack_command.rb'
|
|
396
574
|
- 'lib/fontisan/models/validation_report.rb'
|
|
397
575
|
|
|
576
|
+
# Offense count: 16
|
|
577
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
578
|
+
Style/MultilineIfModifier:
|
|
579
|
+
Exclude:
|
|
580
|
+
- 'lib/fontisan/svg/standalone_glyph.rb'
|
|
581
|
+
- 'lib/fontisan/svg_to_glyf/geometry/transform_parser.rb'
|
|
582
|
+
- 'lib/fontisan/ufo/cli.rb'
|
|
583
|
+
- 'lib/fontisan/ufo/convert.rb'
|
|
584
|
+
- 'lib/fontisan/ufo/convert/from_bin_data.rb'
|
|
585
|
+
- 'lib/fontisan/ufo/convert/to_dfont.rb'
|
|
586
|
+
- 'lib/fontisan/ufo/convert/to_otc.rb'
|
|
587
|
+
- 'lib/fontisan/ufo/convert/to_postscript.rb'
|
|
588
|
+
- 'lib/fontisan/ufo/convert/to_woff.rb'
|
|
589
|
+
- 'lib/fontisan/ufo/convert/to_woff2.rb'
|
|
590
|
+
- 'lib/fontisan/ufo/plist.rb'
|
|
591
|
+
- 'lib/fontisan/woff2/collection_decoder.rb'
|
|
592
|
+
- 'lib/fontisan/woff2/collection_encoder.rb'
|
|
593
|
+
- 'spec/support/fixture_downloader.rb'
|
|
594
|
+
|
|
595
|
+
# Offense count: 4
|
|
596
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
597
|
+
Style/MultilineTernaryOperator:
|
|
598
|
+
Exclude:
|
|
599
|
+
- 'lib/fontisan/commands/validate_collection_command.rb'
|
|
600
|
+
- 'lib/fontisan/converters/collection_converter.rb'
|
|
601
|
+
- 'spec/fontisan/woff2/sfnt_checksum_spec.rb'
|
|
602
|
+
|
|
398
603
|
# Offense count: 1
|
|
399
604
|
# Configuration parameters: AllowedMethods.
|
|
400
605
|
# AllowedMethods: respond_to_missing?
|
|
401
606
|
Style/OptionalBooleanParameter:
|
|
402
607
|
Exclude:
|
|
403
608
|
- 'lib/fontisan/conversion_options.rb'
|
|
609
|
+
|
|
610
|
+
# Offense count: 22
|
|
611
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
612
|
+
# Configuration parameters: EnforcedStyleForMultiline.
|
|
613
|
+
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
|
614
|
+
Style/TrailingCommaInArguments:
|
|
615
|
+
Exclude:
|
|
616
|
+
- 'benchmark/compile_benchmark.rb'
|
|
617
|
+
- 'spec/fontisan/ufo/compile/filters/propagate_anchors_spec.rb'
|
|
618
|
+
- 'spec/fontisan/ufo/compile_gvar_spec.rb'
|
|
619
|
+
- 'spec/fontisan/ufo/filters_spec.rb'
|
data/Gemfile
CHANGED
|
@@ -10,6 +10,12 @@ gem "benchmark"
|
|
|
10
10
|
gem "bigdecimal"
|
|
11
11
|
gem "canon", "~> 0.1.3"
|
|
12
12
|
gem "get_process_mem", "~> 0.2"
|
|
13
|
+
# Octokit provides authenticated GitHub API access for the test-only
|
|
14
|
+
# fixture downloader (spec/support/fixture_downloader.rb). CI sets
|
|
15
|
+
# GITHUB_TOKEN, the downloader auto-detects it and routes GitHub URLs
|
|
16
|
+
# through Octokit to lift the 60/hr anonymous rate limit. NOT in
|
|
17
|
+
# fontisan.gemspec — production installs never pull this in.
|
|
18
|
+
gem "octokit", group: :test
|
|
13
19
|
gem "openssl", "~> 3.0"
|
|
14
20
|
gem "rake"
|
|
15
21
|
gem "rspec"
|
data/Rakefile
CHANGED
|
@@ -10,21 +10,24 @@ RuboCop::RakeTask.new
|
|
|
10
10
|
|
|
11
11
|
# rubocop:disable Metrics/BlockLength
|
|
12
12
|
namespace :fixtures do
|
|
13
|
-
# Load centralized fixture configuration
|
|
13
|
+
# Load centralized fixture configuration and the test-only downloader.
|
|
14
|
+
# The downloader lives under spec/support (not lib/) because it is
|
|
15
|
+
# purely test infrastructure — fontisan-the-gem never downloads
|
|
16
|
+
# fonts at runtime.
|
|
14
17
|
require_relative "spec/support/fixture_fonts"
|
|
15
|
-
|
|
18
|
+
require_relative "spec/support/fixture_downloader"
|
|
16
19
|
|
|
17
20
|
# Helper method to download a single file
|
|
18
21
|
def download_single_file(name, url, target_path)
|
|
19
22
|
puts "[fixtures:download] Downloading #{name}..."
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
FixtureFonts::Downloader.new(
|
|
22
25
|
url: url,
|
|
23
26
|
destination: target_path,
|
|
24
27
|
).call
|
|
25
28
|
|
|
26
29
|
puts "[fixtures:download] #{name} downloaded successfully"
|
|
27
|
-
rescue
|
|
30
|
+
rescue FixtureFonts::Downloader::Error => e
|
|
28
31
|
warn "[fixtures:download] #{name} failed after retries: #{e.message}"
|
|
29
32
|
raise
|
|
30
33
|
end
|
|
@@ -41,7 +44,7 @@ namespace :fixtures do
|
|
|
41
44
|
"fontisan_#{name}_#{Process.pid}_#{rand(10000)}.zip")
|
|
42
45
|
|
|
43
46
|
begin
|
|
44
|
-
|
|
47
|
+
FixtureFonts::Downloader.new(
|
|
45
48
|
url: url,
|
|
46
49
|
destination: temp_path,
|
|
47
50
|
).call
|
|
@@ -89,7 +92,7 @@ namespace :fixtures do
|
|
|
89
92
|
end
|
|
90
93
|
|
|
91
94
|
puts "[fixtures:download] #{name} downloaded successfully"
|
|
92
|
-
rescue
|
|
95
|
+
rescue FixtureFonts::Downloader::Error => e
|
|
93
96
|
warn "[fixtures:download] #{name} failed after retries: #{e.message}"
|
|
94
97
|
raise
|
|
95
98
|
rescue LoadError => e
|
|
@@ -24,10 +24,17 @@ module FontisanBench
|
|
|
24
24
|
g.width = 500
|
|
25
25
|
g.add_unicode(0xE000 + i) if i < 0x1000
|
|
26
26
|
g.add_contour(Fontisan::Ufo::Contour.new([
|
|
27
|
-
Fontisan::Ufo::Point.new(x: 0,
|
|
28
|
-
|
|
29
|
-
Fontisan::Ufo::Point.new(
|
|
30
|
-
|
|
27
|
+
Fontisan::Ufo::Point.new(x: 0,
|
|
28
|
+
y: 0, type: "line"),
|
|
29
|
+
Fontisan::Ufo::Point.new(
|
|
30
|
+
x: 100, y: 0, type: "line",
|
|
31
|
+
),
|
|
32
|
+
Fontisan::Ufo::Point.new(
|
|
33
|
+
x: 100, y: 100, type: "offcurve",
|
|
34
|
+
),
|
|
35
|
+
Fontisan::Ufo::Point.new(
|
|
36
|
+
x: 50, y: 150, type: "curve",
|
|
37
|
+
),
|
|
31
38
|
]))
|
|
32
39
|
font.glyphs["g#{i}"] = g
|
|
33
40
|
end
|
|
@@ -38,7 +45,8 @@ module FontisanBench
|
|
|
38
45
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
39
46
|
yield
|
|
40
47
|
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
|
41
|
-
puts format("%-40<label>s %8.<elapsed>.2f ms", label: label,
|
|
48
|
+
puts format("%-40<label>s %8.<elapsed>.2f ms", label: label,
|
|
49
|
+
elapsed: elapsed * 1000)
|
|
42
50
|
elapsed
|
|
43
51
|
end
|
|
44
52
|
end
|
data/docs/.vitepress/config.ts
CHANGED
|
@@ -322,6 +322,7 @@ export default defineConfig({
|
|
|
322
322
|
{ text: "ConversionOptions", link: "/api/conversion-options" },
|
|
323
323
|
{ text: "SfntFont", link: "/api/sfnt-font" },
|
|
324
324
|
{ text: "Type1Font", link: "/api/type1-font" },
|
|
325
|
+
{ text: "Ufo::Layer", link: "/api/layer" },
|
|
325
326
|
],
|
|
326
327
|
},
|
|
327
328
|
{
|
data/docs/STITCHER_GUIDE.adoc
CHANGED
|
@@ -364,12 +364,56 @@ stitcher.write_to("out.ttf", format: :ttf, subfont: :main)
|
|
|
364
364
|
# → out.ttf has glyf + CBDT + CBLC, emoji renders correctly
|
|
365
365
|
----
|
|
366
366
|
|
|
367
|
-
|
|
367
|
+
=== Outline-first cmap priority
|
|
368
|
+
|
|
369
|
+
When a codepoint is covered by BOTH an outline donor and the CBDT
|
|
370
|
+
donor, the cmap maps it to the outline glyph — never to the CBDT
|
|
371
|
+
placeholder. The Cmap compiler follows first-wins semantics, and
|
|
372
|
+
`GlyphCopier` runs before `CbdtPropagator` so the outline GID is
|
|
373
|
+
registered first. This was the fix for the Emoticons cmap-loss bug
|
|
374
|
+
where shared codepoints silently dropped out of the cmap.
|
|
375
|
+
|
|
376
|
+
=== Placeholder name deconfliction
|
|
377
|
+
|
|
378
|
+
CBDT placeholders are named after the source's glyph IDs
|
|
379
|
+
(`"gid1"`, `"gid2"`, …), which is the SAME naming scheme
|
|
380
|
+
`Source#extract_truetype_glyph` uses for outline glyphs from TTF
|
|
381
|
+
donors. Without protection, a placeholder at `"gid110"` would
|
|
382
|
+
silently overwrite an outline glyph at `"gid110"` from a different
|
|
383
|
+
donor via `Layer#add` — the original cmap-loss vector for the
|
|
384
|
+
Essenfont CJK Ext G regression.
|
|
385
|
+
|
|
386
|
+
The Stitcher resolves this with two pieces:
|
|
387
|
+
|
|
388
|
+
* `Ufo::Layer#add` RAISES `Ufo::GlyphExistsError` on name conflict.
|
|
389
|
+
Silent overwrites are no longer possible. Callers that want to
|
|
390
|
+
replace an existing glyph use the explicit `Ufo::Layer#put`.
|
|
391
|
+
* `Stitcher::UniqueGlyphName.in(target, base)` allocates a
|
|
392
|
+
non-colliding name (`"gid110"`, then `"gid110.1"`, `"gid110.2"`,
|
|
393
|
+
…). `GlyphCopier` and `CbdtPropagator` both call it before every
|
|
394
|
+
`Layer#add`, so each glyph lands at its own GID slot without
|
|
395
|
+
touching the others.
|
|
396
|
+
|
|
397
|
+
=== Limitations
|
|
368
398
|
|
|
369
399
|
* Only ONE CBDT source per Stitcher. Multiple CBDT sources raise
|
|
370
400
|
`Fontisan::MultipleCbdtSourcesError`.
|
|
371
|
-
*
|
|
372
|
-
|
|
401
|
+
* **GID stability for overlapping codepoint ranges.** The raw-bytes
|
|
402
|
+
CBDT/CBLC propagation (`CbdtPropagator#propagate_tables_into`)
|
|
403
|
+
copies the source's CBLC verbatim. CBLC indexes glyphs by SOURCE
|
|
404
|
+
GID. After placeholder renaming (`"gid110"` → `"gid110.1"`), the
|
|
405
|
+
compiled GID no longer matches the source GID, so CBLC's source-
|
|
406
|
+
GID-indexed bitmaps can dangle. This is masked in the typical
|
|
407
|
+
Essenfont case (CBDT donor NotoColorEmoji and outline donors
|
|
408
|
+
cover disjoint codepoint ranges) but would produce wrong bitmaps
|
|
409
|
+
for any stitch where CBDT and outline sources share codepoint
|
|
410
|
+
ranges. A proper fix requires a CBLC rebuild pass that walks the
|
|
411
|
+
compiled cmap to remap source GIDs to compiled GIDs — tracked as
|
|
412
|
+
follow-up.
|
|
413
|
+
* **Collection-mode single-face coverage.** Each face is compiled
|
|
414
|
+
independently; `CbdtPropagator` currently requires at least one
|
|
415
|
+
outline codepoint per face. Collection-mode coverage of the
|
|
416
|
+
outline-first cmap-priority invariant is tracked as follow-up.
|
|
373
417
|
|
|
374
418
|
== CLI
|
|
375
419
|
|
data/docs/api/layer.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Ufo::Layer
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# `Ufo::Layer`
|
|
6
|
+
|
|
7
|
+
A single layer in a UFO source. A `Layer` holds a set of glyphs keyed by name. The default layer is `public.default` per UFO 3.
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
layer = Fontisan::Ufo::Layer.new # => "public.default"
|
|
11
|
+
layer.add(Fontisan::Ufo::Glyph.new(name: "A"))
|
|
12
|
+
layer["A"] # => the glyph
|
|
13
|
+
layer.size # => 1
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Naming contract
|
|
17
|
+
|
|
18
|
+
Glyph names are the layer's primary key. Two distinct glyphs with the same name cannot coexist — adding the second would silently destroy the first, a class of bug that has historically cost real data (e.g. the CJK Ext G cmap loss when CBDT placeholders collided with outline glyphs sharing `"gid{N}"` names).
|
|
19
|
+
|
|
20
|
+
To make that contract unbreakable, the API exposes two methods with named semantics:
|
|
21
|
+
|
|
22
|
+
| Method | Behavior on conflict |
|
|
23
|
+
|--------|----------------------|
|
|
24
|
+
| `Layer#add(glyph)` | **Raises** `Ufo::GlyphExistsError` (the safe default) |
|
|
25
|
+
| `Layer#put(glyph)` | Overwrites the existing glyph (explicit replace) |
|
|
26
|
+
|
|
27
|
+
Callers that need auto-renaming — insert without giving up on a collision — call `Stitcher::UniqueGlyphName.in(target, base)` first to allocate a free name, then `Layer#add` the glyph under that name.
|
|
28
|
+
|
|
29
|
+
## API
|
|
30
|
+
|
|
31
|
+
### `Layer.new(name = "public.default")`
|
|
32
|
+
|
|
33
|
+
Initialize an empty layer.
|
|
34
|
+
|
|
35
|
+
### `#add(glyph) -> Glyph`
|
|
36
|
+
|
|
37
|
+
Insert `glyph`. Raises `Ufo::GlyphExistsError` if a glyph with the same name is already present.
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
layer = Fontisan::Ufo::Layer.new
|
|
41
|
+
layer.add(Fontisan::Ufo::Glyph.new(name: "A"))
|
|
42
|
+
|
|
43
|
+
layer.add(Fontisan::Ufo::Glyph.new(name: "A"))
|
|
44
|
+
# => raises Fontisan::Ufo::GlyphExistsError: a glyph named "A" already exists
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The original glyph is preserved when the second `add` raises — the layer is never partially mutated.
|
|
48
|
+
|
|
49
|
+
### `#put(glyph) -> Glyph`
|
|
50
|
+
|
|
51
|
+
Insert `glyph`, replacing any existing glyph with the same name. Use this when the caller has positively decided the previous glyph (if any) should be discarded.
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
layer.put(Fontisan::Ufo::Glyph.new(name: "A")) # overwrites the prior "A"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### `#[](glyph_name) -> Glyph, nil`
|
|
58
|
+
|
|
59
|
+
Look up a glyph by name.
|
|
60
|
+
|
|
61
|
+
### `#each { |glyph| ... }`
|
|
62
|
+
|
|
63
|
+
Iterate over glyphs (no ordering guarantee).
|
|
64
|
+
|
|
65
|
+
### `#size -> Integer`
|
|
66
|
+
|
|
67
|
+
Number of glyphs in the layer.
|
|
68
|
+
|
|
69
|
+
## `Ufo::GlyphExistsError`
|
|
70
|
+
|
|
71
|
+
Raised by `Layer#add` on a name conflict. Carries the colliding name so callers can branch programmatically:
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
begin
|
|
75
|
+
layer.add(glyph)
|
|
76
|
+
rescue Fontisan::Ufo::GlyphExistsError => e
|
|
77
|
+
puts "name #{e.name.inspect} already taken"
|
|
78
|
+
# Decide: layer.put(glyph) to overwrite, or
|
|
79
|
+
# unique = Fontisan::Stitcher::UniqueGlyphName.in(target, e.name)
|
|
80
|
+
# layer.add(glyph.dup_as(name: unique))
|
|
81
|
+
end
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The error class is a sibling of `Layer` (not nested inside it) so the namespace stays flat — both `Ufo::Layer` and `Ufo::GlyphExistsError` live directly under `Fontisan::Ufo`.
|
|
85
|
+
|
|
86
|
+
## See also
|
|
87
|
+
|
|
88
|
+
- `docs/STITCHER_GUIDE.adoc` — `UniqueGlyphName`, `GlyphCopier`, and `CbdtPropagator` all build on the Layer naming contract.
|
|
89
|
+
- `docs/UFO_COMPILATION.adoc` — how layers feed the TTF/OTF/CFF2 compilers.
|