fontisan 0.4.46 → 0.4.48
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/BENCHMARKS.md +56 -0
- data/CHANGELOG.md +12 -0
- data/Cargo.lock +550 -0
- data/Cargo.toml +12 -0
- data/Gemfile +10 -0
- data/README.adoc +52 -0
- data/Rakefile +5 -1
- data/benchmark/baseline.json +5 -0
- data/benchmark/ci_gate.rb +217 -0
- data/benchmark/corpus/harness.rb +175 -0
- data/benchmark/corpus/ops.rb +150 -0
- data/benchmark/corpus/run.rb +182 -0
- data/benchmark/corpus/scan_child.rb +8 -0
- data/benchmark/corpus/tiers.rb +176 -0
- data/benchmark/tier_baseline.json +12 -0
- data/docs/.vitepress/config.ts +2 -1
- data/docs/guide/engines.md +117 -0
- data/docs/reference-facade.md +130 -0
- data/ext/fontisan_cdylib/Cargo.lock +313 -0
- data/ext/fontisan_cdylib/Cargo.toml +18 -0
- data/ext/fontisan_cdylib/build.rs +22 -0
- data/ext/fontisan_cdylib/extconf.rb +36 -0
- data/ext/fontisan_cdylib/src/lib.rs +13 -0
- data/ext/fontisan_native/Cargo.toml +21 -0
- data/ext/fontisan_native/build.rs +22 -0
- data/ext/fontisan_native/clippy.toml +10 -0
- data/ext/fontisan_native/extconf.rb +59 -0
- data/ext/fontisan_native/src/lib.rs +463 -0
- data/lib/fontisan/audit/checks/cmap_check.rb +7 -0
- data/lib/fontisan/audit/checks/hinting_check.rb +1 -1
- data/lib/fontisan/audit/checks/maxp_check.rb +1 -1
- data/lib/fontisan/audit/checks/opentype_conformance_check.rb +5 -2
- data/lib/fontisan/base_collection.rb +30 -0
- data/lib/fontisan/byte_ops.rb +219 -0
- data/lib/fontisan/cli.rb +5 -5
- data/lib/fontisan/commands/audit_command.rb +38 -43
- data/lib/fontisan/commands/convert_command.rb +53 -0
- data/lib/fontisan/commands/instance_command.rb +75 -0
- data/lib/fontisan/commands/subset_command.rb +43 -0
- data/lib/fontisan/commands/unpack_command.rb +56 -0
- data/lib/fontisan/converters/cff_table_builder.rb +1 -1
- data/lib/fontisan/converters/collection_converter.rb +13 -5
- data/lib/fontisan/converters/format_converter.rb +1 -1
- data/lib/fontisan/converters/woff2_encoder.rb +8 -6
- data/lib/fontisan/converters/woff_writer.rb +6 -5
- data/lib/fontisan/engine.rb +350 -0
- data/lib/fontisan/ffi/client.rb +121 -0
- data/lib/fontisan/ffi.rb +343 -0
- data/lib/fontisan/ffi_platform.rb +24 -0
- data/lib/fontisan/font_loader.rb +5 -1
- data/lib/fontisan/font_writer.rb +13 -1
- data/lib/fontisan/native.rb +231 -0
- data/lib/fontisan/pipeline/transformation_pipeline.rb +10 -8
- data/lib/fontisan/pipeline.rb +1 -1
- data/lib/fontisan/reference/table_digests.rb +251 -0
- data/lib/fontisan/reference.rb +619 -0
- data/lib/fontisan/scan.rb +372 -0
- data/lib/fontisan/sfnt_directory.rb +41 -0
- data/lib/fontisan/sfnt_font.rb +16 -6
- data/lib/fontisan/subset/builder.rb +2 -1
- data/lib/fontisan/tables/cff/charstring.rb +16 -0
- data/lib/fontisan/tables/cff.rb +15 -5
- data/lib/fontisan/tables/cmap.rb +11 -1
- data/lib/fontisan/tables/glyf.rb +4 -6
- data/lib/fontisan/tables/gpos.rb +7 -0
- data/lib/fontisan/tables/gsub.rb +7 -0
- data/lib/fontisan/tables/layout_common.rb +172 -0
- data/lib/fontisan/tables/name.rb +10 -4
- data/lib/fontisan/utilities/brotli_wrapper.rb +39 -4
- data/lib/fontisan/validators/opentype_validator.rb +15 -3
- data/lib/fontisan/variable/instancer.rb +23 -192
- data/lib/fontisan/variable/static_font_builder.rb +4 -1
- data/lib/fontisan/variable/table_updater.rb +4 -2
- data/lib/fontisan/variation/instance_generator.rb +3 -149
- data/lib/fontisan/variation/instancing/axis_space.rb +136 -0
- data/lib/fontisan/variation/instancing/glyph_outline.rb +204 -0
- data/lib/fontisan/variation/instancing/gvar_reader.rb +146 -0
- data/lib/fontisan/variation/instancing/item_variation_store.rb +92 -0
- data/lib/fontisan/variation/instancing/name_rewriter.rb +90 -0
- data/lib/fontisan/variation/instancing/true_type_instancer.rb +326 -0
- data/lib/fontisan/variation/instancing.rb +20 -0
- data/lib/fontisan/variation/variable_svg_generator.rb +19 -1
- data/lib/fontisan/variation.rb +1 -0
- data/lib/fontisan/version.rb +1 -1
- data/lib/fontisan/woff2/collection_decoder.rb +15 -1
- data/lib/fontisan/woff2/collection_encoder.rb +29 -6
- data/lib/fontisan/woff2/encoder_rules.rb +12 -4
- data/lib/fontisan/woff2/glyf_loca_reconstruct.rb +1 -1
- data/lib/fontisan/woff2_collection.rb +7 -5
- data/lib/fontisan/woff2_font.rb +12 -3
- data/lib/fontisan/woff_container.rb +83 -0
- data/lib/fontisan/woff_font.rb +24 -20
- data/lib/fontisan.rb +24 -1
- data/rakelib/bench.rake +9 -0
- data/rakelib/cdylib.rake +39 -0
- data/rakelib/corpus.rake +272 -0
- data/rakelib/corpus_convert.rake +43 -0
- data/rakelib/corpus_goldens.rake +22 -0
- data/rakelib/corpus_malformed.rake +20 -0
- data/rakelib/corpus_scan.rake +24 -0
- data/rakelib/java.rake +61 -0
- data/rakelib/native.rake +43 -0
- data/scripts/build-woff2.sh +57 -0
- data/scripts/corpus/generate_convert_goldens.rb +478 -0
- data/scripts/corpus/generate_goldens.rb +282 -0
- data/scripts/corpus/generate_malformed_goldens.rb +254 -0
- data/scripts/corpus/generate_scan_goldens.rb +98 -0
- data/scripts/tier_fallback.rb +219 -0
- data/scripts/tier_smoke.rb +64 -0
- metadata +75 -3
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "adler2"
|
|
7
|
+
version = "2.0.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "alloc-no-stdlib"
|
|
13
|
+
version = "2.0.4"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "alloc-stdlib"
|
|
19
|
+
version = "0.2.4"
|
|
20
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
+
checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195"
|
|
22
|
+
dependencies = [
|
|
23
|
+
"alloc-no-stdlib",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[[package]]
|
|
27
|
+
name = "block-buffer"
|
|
28
|
+
version = "0.10.4"
|
|
29
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
30
|
+
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
|
31
|
+
dependencies = [
|
|
32
|
+
"generic-array",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[[package]]
|
|
36
|
+
name = "brotli"
|
|
37
|
+
version = "8.0.4"
|
|
38
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
39
|
+
checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3"
|
|
40
|
+
dependencies = [
|
|
41
|
+
"alloc-no-stdlib",
|
|
42
|
+
"alloc-stdlib",
|
|
43
|
+
"brotli-decompressor",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[[package]]
|
|
47
|
+
name = "brotli-decompressor"
|
|
48
|
+
version = "5.0.3"
|
|
49
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
50
|
+
checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583"
|
|
51
|
+
dependencies = [
|
|
52
|
+
"alloc-no-stdlib",
|
|
53
|
+
"alloc-stdlib",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[[package]]
|
|
57
|
+
name = "bytemuck"
|
|
58
|
+
version = "1.25.2"
|
|
59
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
60
|
+
checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797"
|
|
61
|
+
dependencies = [
|
|
62
|
+
"bytemuck_derive",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[[package]]
|
|
66
|
+
name = "bytemuck_derive"
|
|
67
|
+
version = "1.12.1"
|
|
68
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
69
|
+
checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c"
|
|
70
|
+
dependencies = [
|
|
71
|
+
"proc-macro2",
|
|
72
|
+
"quote",
|
|
73
|
+
"syn",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
[[package]]
|
|
77
|
+
name = "cfg-if"
|
|
78
|
+
version = "1.0.5"
|
|
79
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
80
|
+
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
|
81
|
+
|
|
82
|
+
[[package]]
|
|
83
|
+
name = "cpufeatures"
|
|
84
|
+
version = "0.2.17"
|
|
85
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
86
|
+
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
|
87
|
+
dependencies = [
|
|
88
|
+
"libc",
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
[[package]]
|
|
92
|
+
name = "crypto-common"
|
|
93
|
+
version = "0.1.7"
|
|
94
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
95
|
+
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
|
96
|
+
dependencies = [
|
|
97
|
+
"generic-array",
|
|
98
|
+
"typenum",
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
[[package]]
|
|
102
|
+
name = "digest"
|
|
103
|
+
version = "0.10.7"
|
|
104
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
105
|
+
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
|
106
|
+
dependencies = [
|
|
107
|
+
"block-buffer",
|
|
108
|
+
"crypto-common",
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
[[package]]
|
|
112
|
+
name = "foldhash"
|
|
113
|
+
version = "0.2.0"
|
|
114
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
115
|
+
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
|
116
|
+
|
|
117
|
+
[[package]]
|
|
118
|
+
name = "font-types"
|
|
119
|
+
version = "0.12.7"
|
|
120
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
121
|
+
checksum = "835ae9d781464a79026cde387f9cbc650c9a4909d7cf7e658b127e3c35d2f35d"
|
|
122
|
+
dependencies = [
|
|
123
|
+
"bytemuck",
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
[[package]]
|
|
127
|
+
name = "fontisan"
|
|
128
|
+
version = "0.0.0"
|
|
129
|
+
source = "git+https://github.com/fontist/fontisan-rs?rev=daffb3f45b67517e924a3e5d0e113a2ecbde9959#daffb3f45b67517e924a3e5d0e113a2ecbde9959"
|
|
130
|
+
dependencies = [
|
|
131
|
+
"brotli",
|
|
132
|
+
"brotli-decompressor",
|
|
133
|
+
"miniz_oxide",
|
|
134
|
+
"read-fonts",
|
|
135
|
+
"sha2",
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
[[package]]
|
|
139
|
+
name = "fontisan_cdylib"
|
|
140
|
+
version = "0.0.0"
|
|
141
|
+
dependencies = [
|
|
142
|
+
"fontisan",
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
[[package]]
|
|
146
|
+
name = "generic-array"
|
|
147
|
+
version = "0.14.7"
|
|
148
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
149
|
+
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|
150
|
+
dependencies = [
|
|
151
|
+
"typenum",
|
|
152
|
+
"version_check",
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
[[package]]
|
|
156
|
+
name = "libc"
|
|
157
|
+
version = "0.2.191"
|
|
158
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
159
|
+
checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
|
|
160
|
+
|
|
161
|
+
[[package]]
|
|
162
|
+
name = "miniz_oxide"
|
|
163
|
+
version = "0.8.9"
|
|
164
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
165
|
+
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
|
166
|
+
dependencies = [
|
|
167
|
+
"adler2",
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
[[package]]
|
|
171
|
+
name = "once_cell"
|
|
172
|
+
version = "1.21.4"
|
|
173
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
174
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
175
|
+
|
|
176
|
+
[[package]]
|
|
177
|
+
name = "proc-macro2"
|
|
178
|
+
version = "1.0.107"
|
|
179
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
180
|
+
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
|
181
|
+
dependencies = [
|
|
182
|
+
"unicode-ident",
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
[[package]]
|
|
186
|
+
name = "quote"
|
|
187
|
+
version = "1.0.47"
|
|
188
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
189
|
+
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
|
190
|
+
dependencies = [
|
|
191
|
+
"proc-macro2",
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
[[package]]
|
|
195
|
+
name = "read-fonts"
|
|
196
|
+
version = "0.46.0"
|
|
197
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
198
|
+
checksum = "bdaa4fffe9ff3ca2c353fa9729792805b9b3e324695ff5a081f860612e81b330"
|
|
199
|
+
dependencies = [
|
|
200
|
+
"bytemuck",
|
|
201
|
+
"foldhash",
|
|
202
|
+
"font-types",
|
|
203
|
+
"once_cell",
|
|
204
|
+
"smallvec",
|
|
205
|
+
"yoke",
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
[[package]]
|
|
209
|
+
name = "sha2"
|
|
210
|
+
version = "0.10.9"
|
|
211
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
212
|
+
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
|
213
|
+
dependencies = [
|
|
214
|
+
"cfg-if",
|
|
215
|
+
"cpufeatures",
|
|
216
|
+
"digest",
|
|
217
|
+
]
|
|
218
|
+
|
|
219
|
+
[[package]]
|
|
220
|
+
name = "smallvec"
|
|
221
|
+
version = "1.16.4"
|
|
222
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
223
|
+
checksum = "d0d5d4b1981b8bbbb7aed204cae5726d683d5d6ac7e74ec54122ea28f315e7c8"
|
|
224
|
+
|
|
225
|
+
[[package]]
|
|
226
|
+
name = "stable_deref_trait"
|
|
227
|
+
version = "1.2.1"
|
|
228
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
229
|
+
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
|
230
|
+
|
|
231
|
+
[[package]]
|
|
232
|
+
name = "syn"
|
|
233
|
+
version = "3.0.9"
|
|
234
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
235
|
+
checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b"
|
|
236
|
+
dependencies = [
|
|
237
|
+
"proc-macro2",
|
|
238
|
+
"quote",
|
|
239
|
+
"unicode-ident",
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
[[package]]
|
|
243
|
+
name = "synstructure"
|
|
244
|
+
version = "0.14.0"
|
|
245
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
246
|
+
checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02"
|
|
247
|
+
dependencies = [
|
|
248
|
+
"proc-macro2",
|
|
249
|
+
"quote",
|
|
250
|
+
"syn",
|
|
251
|
+
]
|
|
252
|
+
|
|
253
|
+
[[package]]
|
|
254
|
+
name = "typenum"
|
|
255
|
+
version = "1.20.1"
|
|
256
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
257
|
+
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
|
258
|
+
|
|
259
|
+
[[package]]
|
|
260
|
+
name = "unicode-ident"
|
|
261
|
+
version = "1.0.27"
|
|
262
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
263
|
+
checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
|
|
264
|
+
|
|
265
|
+
[[package]]
|
|
266
|
+
name = "version_check"
|
|
267
|
+
version = "0.9.5"
|
|
268
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
269
|
+
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
|
270
|
+
|
|
271
|
+
[[package]]
|
|
272
|
+
name = "yoke"
|
|
273
|
+
version = "0.8.4"
|
|
274
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
275
|
+
checksum = "417ef3fcf6c300b7dbd25c85531a746931c02ad536f3cf4786ed1e88223340b3"
|
|
276
|
+
dependencies = [
|
|
277
|
+
"stable_deref_trait",
|
|
278
|
+
"yoke-derive",
|
|
279
|
+
"zerofrom",
|
|
280
|
+
]
|
|
281
|
+
|
|
282
|
+
[[package]]
|
|
283
|
+
name = "yoke-derive"
|
|
284
|
+
version = "0.8.4"
|
|
285
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
286
|
+
checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71"
|
|
287
|
+
dependencies = [
|
|
288
|
+
"proc-macro2",
|
|
289
|
+
"quote",
|
|
290
|
+
"syn",
|
|
291
|
+
"synstructure",
|
|
292
|
+
]
|
|
293
|
+
|
|
294
|
+
[[package]]
|
|
295
|
+
name = "zerofrom"
|
|
296
|
+
version = "0.1.8"
|
|
297
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
298
|
+
checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
|
|
299
|
+
dependencies = [
|
|
300
|
+
"zerofrom-derive",
|
|
301
|
+
]
|
|
302
|
+
|
|
303
|
+
[[package]]
|
|
304
|
+
name = "zerofrom-derive"
|
|
305
|
+
version = "0.1.8"
|
|
306
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
307
|
+
checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a"
|
|
308
|
+
dependencies = [
|
|
309
|
+
"proc-macro2",
|
|
310
|
+
"quote",
|
|
311
|
+
"syn",
|
|
312
|
+
"synstructure",
|
|
313
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "fontisan_cdylib"
|
|
3
|
+
version = "0.0.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
publish = false
|
|
6
|
+
description = "C ABI of the fontisan engine as a shared library for the Ruby `ffi` tier (no magnus)"
|
|
7
|
+
|
|
8
|
+
[lib]
|
|
9
|
+
name = "fontisan_cdylib"
|
|
10
|
+
crate-type = ["cdylib"]
|
|
11
|
+
|
|
12
|
+
# Standalone: not a member of any enclosing workspace.
|
|
13
|
+
[workspace]
|
|
14
|
+
|
|
15
|
+
[dependencies]
|
|
16
|
+
# TEMPORARY (decision D3: the crate is not on crates.io yet). Replace with
|
|
17
|
+
# `fontisan = { version = "=<release>", features = ["ffi"] }` once published.
|
|
18
|
+
fontisan = { git = "https://github.com/fontist/fontisan-rs", rev = "daffb3f45b67517e924a3e5d0e113a2ecbde9959", features = ["ffi"] }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//! Embeds the engine rev this binary is compiled against, read from the
|
|
2
|
+
//! `fontisan` dependency's `rev = "..."` in this crate's own Cargo.toml (the
|
|
3
|
+
//! one place a repin edits), as `FONTISAN_ENGINE_REV`. The Ruby side compares
|
|
4
|
+
//! it with `Fontisan::Native::ENGINE_REV`, so a binary built from an older pin
|
|
5
|
+
//! counts as unavailable instead of serving old behaviour.
|
|
6
|
+
use std::{env, fs, path::PathBuf};
|
|
7
|
+
|
|
8
|
+
fn main() {
|
|
9
|
+
let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"))
|
|
10
|
+
.join("Cargo.toml");
|
|
11
|
+
println!("cargo:rerun-if-changed={}", manifest.display());
|
|
12
|
+
let text = fs::read_to_string(&manifest).expect("read Cargo.toml");
|
|
13
|
+
let rev = text
|
|
14
|
+
.lines()
|
|
15
|
+
.filter(|line| line.trim_start().starts_with("fontisan") && line.contains("git"))
|
|
16
|
+
.find_map(|line| {
|
|
17
|
+
let tail = line.split("rev").nth(1)?;
|
|
18
|
+
tail.split('"').nth(1).map(str::to_owned)
|
|
19
|
+
})
|
|
20
|
+
.expect("the fontisan dependency in Cargo.toml must carry `rev = \"<sha>\"`");
|
|
21
|
+
println!("cargo:rustc-env=FONTISAN_ENGINE_REV={rev}");
|
|
22
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Builds the :ffi tier's shared library with cargo and installs it next to
|
|
4
|
+
# lib/fontisan/ffi.rb. With no cargo, or FONTISAN_SKIP_CDYLIB=1, it writes a
|
|
5
|
+
# Makefile that does nothing, so the gem installs and the :ruby tier serves.
|
|
6
|
+
require "mkmf"
|
|
7
|
+
require "rbconfig"
|
|
8
|
+
|
|
9
|
+
here = __dir__
|
|
10
|
+
dest = File.expand_path("../../lib/fontisan/ffi", here)
|
|
11
|
+
cargo = ENV["FONTISAN_SKIP_CDYLIB"] == "1" ? nil : find_executable("cargo")
|
|
12
|
+
extension = case RbConfig::CONFIG["host_os"]
|
|
13
|
+
when /darwin/ then "dylib"
|
|
14
|
+
when /mswin|mingw|cygwin/ then "dll"
|
|
15
|
+
else "so"
|
|
16
|
+
end
|
|
17
|
+
prefix = extension == "dll" ? "" : "lib"
|
|
18
|
+
built = "target/release/#{prefix}fontisan_cdylib.#{extension}"
|
|
19
|
+
|
|
20
|
+
makefile =
|
|
21
|
+
if cargo
|
|
22
|
+
<<~MAKE
|
|
23
|
+
all:
|
|
24
|
+
\tcd "#{here}" && "#{cargo}" build --release
|
|
25
|
+
\tmkdir -p "#{dest}"
|
|
26
|
+
\tcp "#{File.join(here, built)}" "#{dest}/"
|
|
27
|
+
install:
|
|
28
|
+
\t@true
|
|
29
|
+
clean:
|
|
30
|
+
\t@true
|
|
31
|
+
MAKE
|
|
32
|
+
else
|
|
33
|
+
warn "fontisan: cargo not found; skipping the :ffi cdylib (the :ruby tier serves)"
|
|
34
|
+
"all:\n\t@true\ninstall:\n\t@true\nclean:\n\t@true\n"
|
|
35
|
+
end
|
|
36
|
+
File.write("Makefile", makefile)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//! The engine's C ABI (`fontisan_call`, `fontisan_result_free`,
|
|
2
|
+
//! `fontisan_abi_version`) re-exported so this cdylib exports the symbols.
|
|
3
|
+
//! Without the glob re-export the library links empty; CI checks the exports
|
|
4
|
+
//! with `nm -gU` / `dumpbin /exports`.
|
|
5
|
+
pub use fontisan::ffi::*;
|
|
6
|
+
|
|
7
|
+
/// The engine rev this library was compiled against (see `build.rs`), as a
|
|
8
|
+
/// NUL-terminated static string. The Ruby `:ffi` tier refuses a library that
|
|
9
|
+
/// lacks this symbol or reports another rev than `Fontisan::Native::ENGINE_REV`.
|
|
10
|
+
#[no_mangle]
|
|
11
|
+
pub extern "C" fn fontisan_cdylib_engine_rev() -> *const std::ffi::c_char {
|
|
12
|
+
concat!(env!("FONTISAN_ENGINE_REV"), "\0").as_ptr().cast()
|
|
13
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "fontisan_native"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
rust-version = "1.85"
|
|
6
|
+
publish = false
|
|
7
|
+
description = "The :native tier of the fontisan gem: the fontisan-rs engine through magnus."
|
|
8
|
+
|
|
9
|
+
[lib]
|
|
10
|
+
crate-type = ["cdylib"]
|
|
11
|
+
|
|
12
|
+
[dependencies]
|
|
13
|
+
# TEMPORARY (decision D3: the crate is not on crates.io yet). Replace with
|
|
14
|
+
# `fontisan = "=<version>"` once published. The rev must be a commit on
|
|
15
|
+
# fontist/fontisan-rs; keep it equal to the rev in ext/fontisan_cdylib/Cargo.toml.
|
|
16
|
+
fontisan = { git = "https://github.com/fontist/fontisan-rs", rev = "daffb3f45b67517e924a3e5d0e113a2ecbde9959" }
|
|
17
|
+
magnus = "=0.8.4"
|
|
18
|
+
rb-sys = { version = "=0.9.130", default-features = false }
|
|
19
|
+
|
|
20
|
+
[lints.rust]
|
|
21
|
+
unsafe_op_in_unsafe_fn = "deny"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//! Embeds the engine rev this binary is compiled against, read from the
|
|
2
|
+
//! `fontisan` dependency's `rev = "..."` in this crate's own Cargo.toml (the
|
|
3
|
+
//! one place a repin edits), as `FONTISAN_ENGINE_REV`. The Ruby side compares
|
|
4
|
+
//! it with `Fontisan::Native::ENGINE_REV`, so a binary built from an older pin
|
|
5
|
+
//! counts as unavailable instead of serving old behaviour.
|
|
6
|
+
use std::{env, fs, path::PathBuf};
|
|
7
|
+
|
|
8
|
+
fn main() {
|
|
9
|
+
let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"))
|
|
10
|
+
.join("Cargo.toml");
|
|
11
|
+
println!("cargo:rerun-if-changed={}", manifest.display());
|
|
12
|
+
let text = fs::read_to_string(&manifest).expect("read Cargo.toml");
|
|
13
|
+
let rev = text
|
|
14
|
+
.lines()
|
|
15
|
+
.filter(|line| line.trim_start().starts_with("fontisan") && line.contains("git"))
|
|
16
|
+
.find_map(|line| {
|
|
17
|
+
let tail = line.split("rev").nth(1)?;
|
|
18
|
+
tail.split('"').nth(1).map(str::to_owned)
|
|
19
|
+
})
|
|
20
|
+
.expect("the fontisan dependency in Cargo.toml must carry `rev = \"<sha>\"`");
|
|
21
|
+
println!("cargo:rustc-env=FONTISAN_ENGINE_REV={rev}");
|
|
22
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# The engine never spawns processes (index rule "No C, no forks"). xtask is its
|
|
2
|
+
# own workspace and is exempt.
|
|
3
|
+
disallowed-methods = [
|
|
4
|
+
{ path = "std::process::Command::new", reason = "the engine must not spawn processes" },
|
|
5
|
+
{ path = "libc::fork", reason = "the engine must not fork" },
|
|
6
|
+
]
|
|
7
|
+
disallowed-types = [
|
|
8
|
+
{ path = "std::process::Command", reason = "the engine must not spawn processes" },
|
|
9
|
+
]
|
|
10
|
+
msrv = "1.85"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Builds the :native tier. Degrades cleanly: without a Rust toolchain (or the
|
|
4
|
+
# rb_sys gem) it writes a no-op Makefile, the gem installs without the
|
|
5
|
+
# extension, and Fontisan::Native.available? is false, so only the :ruby tier
|
|
6
|
+
# serves. Set FONTISAN_NATIVE_REQUIRED=1 to turn that degradation into a failure.
|
|
7
|
+
#
|
|
8
|
+
# A failure at `make` time (a Cargo/Ruby target mismatch on Windows, a missing
|
|
9
|
+
# linker, an old rustc) degrades the same way: rb_sys's Makefile is kept as
|
|
10
|
+
# Makefile.rb_sys and a wrapper Makefile runs it, turning its failure into a
|
|
11
|
+
# warning. Only POSIX-sh-compatible recipe syntax is used (`cmd || echo`), so it
|
|
12
|
+
# works under GNU make on Linux/macOS and the RubyInstaller devkit (msys sh).
|
|
13
|
+
require "mkmf"
|
|
14
|
+
|
|
15
|
+
RB_SYS_MAKEFILE = "Makefile.rb_sys"
|
|
16
|
+
|
|
17
|
+
def cargo_present?
|
|
18
|
+
system("cargo", "--version", out: File::NULL, err: File::NULL)
|
|
19
|
+
rescue SystemCallError
|
|
20
|
+
false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def skip_native(reason)
|
|
24
|
+
abort "fontisan: cannot build the native extension: #{reason}" if ENV["FONTISAN_NATIVE_REQUIRED"] == "1"
|
|
25
|
+
|
|
26
|
+
warn "fontisan: skipping the native extension (#{reason}); the :ruby engine tier serves."
|
|
27
|
+
File.write("Makefile", <<~MAKEFILE)
|
|
28
|
+
all:
|
|
29
|
+
install:
|
|
30
|
+
clean:
|
|
31
|
+
distclean:
|
|
32
|
+
.PHONY: all install clean distclean
|
|
33
|
+
MAKEFILE
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Wraps the rb_sys Makefile so that a failing build/install/clean leaves the gem
|
|
37
|
+
# installed without the extension (unless FONTISAN_NATIVE_REQUIRED=1).
|
|
38
|
+
def wrap_rust_makefile
|
|
39
|
+
return if ENV["FONTISAN_NATIVE_REQUIRED"] == "1"
|
|
40
|
+
|
|
41
|
+
File.rename("Makefile", RB_SYS_MAKEFILE)
|
|
42
|
+
warning = %(echo "fontisan: the native extension did not build; the :ruby engine tier serves.")
|
|
43
|
+
targets = %w[all install clean distclean].map do |target|
|
|
44
|
+
"#{target}:\n\t$(MAKE) -f #{RB_SYS_MAKEFILE} #{target} || #{warning}\n"
|
|
45
|
+
end
|
|
46
|
+
File.write("Makefile", "#{targets.join}\n.PHONY: all install clean distclean\n")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if cargo_present?
|
|
50
|
+
begin
|
|
51
|
+
require "rb_sys/mkmf"
|
|
52
|
+
create_rust_makefile("fontisan/native/fontisan_native")
|
|
53
|
+
wrap_rust_makefile
|
|
54
|
+
rescue LoadError
|
|
55
|
+
skip_native("the rb_sys gem is not installed")
|
|
56
|
+
end
|
|
57
|
+
else
|
|
58
|
+
skip_native("cargo not found")
|
|
59
|
+
end
|