mirror of
https://github.com/harfbuzz/harfbuzz.git
synced 2025-04-19 19:53:48 +00:00
Compare commits
1103 commits
Author | SHA1 | Date | |
---|---|---|---|
|
4e7b178f3c | ||
|
2602f7292c | ||
|
416e6b6921 | ||
|
32b36fa84c | ||
|
bc15ebdea1 | ||
|
8f413a533c | ||
|
21516f74d2 | ||
|
7bb3000a31 | ||
|
4da8671b50 | ||
|
e192a584a8 | ||
|
cf7bffb690 | ||
|
9def626d4a | ||
|
e2a865f024 | ||
|
efcb7d3de1 | ||
|
5afbd187b6 | ||
|
e6b5dba369 | ||
|
d3ccdcdd80 | ||
|
b33f2e26ee | ||
|
ab3235150d | ||
|
5f80cc1600 | ||
|
6b0124284b | ||
|
caa9cf2e85 | ||
|
c7f980907f | ||
|
b1a0a4c228 | ||
|
6dff699f3f | ||
|
6697cd833a | ||
|
2c4bc83244 | ||
|
e31721b5cf | ||
|
a9e2c8f3aa | ||
|
a3d626b4b9 | ||
|
b99382e292 | ||
|
ba4a92c53b | ||
|
8a1ba4d151 | ||
|
fb04a306fc | ||
|
b43901151f | ||
|
b106a9ef58 | ||
|
59771e5613 | ||
|
fd9903fc4e | ||
|
f09c4d6dd8 | ||
|
1f0559392d | ||
|
d8f00171d7 | ||
|
cc065cf2e5 | ||
|
c60067c675 | ||
|
8456c33ac3 | ||
|
1f1cbb64ee | ||
|
aa6a37de61 | ||
|
ba309a1826 | ||
|
58d7ab2d59 | ||
|
328509ef66 | ||
|
03f4230188 | ||
|
5a46872853 | ||
|
9718681c99 | ||
|
2b5ae9dec3 | ||
|
155e1e633b | ||
|
f73039422e | ||
|
5efdb884a5 | ||
|
8132a6607f | ||
|
b2179dcfcd | ||
|
a777a9c535 | ||
|
e332777763 | ||
|
740a103ba1 | ||
|
a530672f04 | ||
|
628a9ee28a | ||
|
fbda749bdb | ||
|
da5a9fb860 | ||
|
b01cea95e1 | ||
|
1db93d2f6d | ||
|
ee50fad676 | ||
|
db953a43d0 | ||
|
69fd949014 | ||
|
2834900d92 | ||
|
e4e4d66523 | ||
|
c523f9ac13 | ||
|
f69ecc9438 | ||
|
6acb2942e8 | ||
|
bee08cf290 | ||
|
a46b93208a | ||
|
3cf48234b9 | ||
|
112b599826 | ||
|
6c98519c7e | ||
|
0a5cc89e00 | ||
|
d9304b69e0 | ||
|
58170206a1 | ||
|
a24c40dfb4 | ||
|
d74606bbff | ||
|
2d8e5255f3 | ||
|
f57b43c980 | ||
|
52a4bea109 | ||
|
b53000403e | ||
|
7dcd69544b | ||
|
c42b6ea829 | ||
|
e5541a0b63 | ||
|
d65fa93440 | ||
|
00b4f86e5f | ||
|
267de2bb90 | ||
|
5194ec4758 | ||
|
fa737da022 | ||
|
54295ccf45 | ||
|
0fecd2ecc3 | ||
|
a637c08d5a | ||
|
866096d04a | ||
|
b6cbd6a0fc | ||
|
2f86ab8d47 | ||
|
9971d84ea7 | ||
|
bf3ce2cb6b | ||
|
90331b41ef | ||
|
3207575979 | ||
|
0457d3d734 | ||
|
9ddf3da71e | ||
|
43a7784922 | ||
|
13752124d7 | ||
|
623a7a4198 | ||
|
c44f1e71d7 | ||
|
1337912680 | ||
|
cc782b5427 | ||
|
7ba4e87934 | ||
|
089a9961ad | ||
|
a55305038c | ||
|
8994e91487 | ||
|
d515630f6b | ||
|
d30d7f6b2b | ||
|
9cae040bb4 | ||
|
810fbedf27 | ||
|
6cc9c01aaa | ||
|
e10d647a73 | ||
|
e404cf0860 | ||
|
e480d9de96 | ||
|
60fc8b4cbc | ||
|
062c3b4d80 | ||
|
2152ff779c | ||
|
18ab0f5522 | ||
|
c6c8dcdeca | ||
|
6f5b8d59c7 | ||
|
7da049ed42 | ||
|
da0c459dd4 | ||
|
37989fb4cd | ||
|
d3e4977c70 | ||
|
ef8c25ad9f | ||
|
bbf0c6e781 | ||
|
321c14c920 | ||
|
7f5fafec0d | ||
|
8864c264b9 | ||
|
3d0816c7c4 | ||
|
591f00a281 | ||
|
7ebe6b48b6 | ||
|
4d5348d660 | ||
|
bed2d3dd2b | ||
|
89ab5f2b21 | ||
|
48e7e5a008 | ||
|
9f83bbbe64 | ||
|
91fd40ac7c | ||
|
ca66c64655 | ||
|
a1e587b75a | ||
|
a5b00faaf8 | ||
|
d53cbeee41 | ||
|
7c368dabae | ||
|
674ce63021 | ||
|
4f5b31b7ea | ||
|
4cf4099f07 | ||
|
4954edb2b1 | ||
|
afa0549dff | ||
|
67314b205a | ||
|
c260550ae5 | ||
|
18ced8dbb1 | ||
|
17c875c309 | ||
|
ea08b04752 | ||
|
cb44134cbf | ||
|
ef95dc0e7f | ||
|
c39ac0e171 | ||
|
1358e38154 | ||
|
1dac21c177 | ||
|
22f81f70cb | ||
|
aad5780f53 | ||
|
83481d65d0 | ||
|
a588761198 | ||
|
1f6da390e0 | ||
|
449752c57c | ||
|
b808d1746d | ||
|
9d584c4d3d | ||
|
82d664519c | ||
|
7ba0368200 | ||
|
283ab21841 | ||
|
0752e5852b | ||
|
ae8b288db7 | ||
|
c50c0a39e5 | ||
|
b4fd777c23 | ||
|
5ebe36e1ac | ||
|
208ffb3f1f | ||
|
dda1d95af2 | ||
|
0d4053b11d | ||
|
7c90f446c2 | ||
|
d47a47e20b | ||
|
7ab42f9af3 | ||
|
9609f50bad | ||
|
9a80c0da84 | ||
|
ba6869848f | ||
|
7f10c0edfd | ||
|
bd5b8a1feb | ||
|
e4410a85fa | ||
|
a6f563247e | ||
|
93288a1ced | ||
|
a410a042c7 | ||
|
4d83b238ea | ||
|
59001aa952 | ||
|
3d3f241941 | ||
|
75643768de | ||
|
29c800bd8d | ||
|
192d264ae7 | ||
|
4d2a362f84 | ||
|
bed29d1cd3 | ||
|
e16a985798 | ||
|
851d3e33b5 | ||
|
2b5f244639 | ||
|
eec9108416 | ||
|
fea0c0df33 | ||
|
fe51e23738 | ||
|
188531b3ba | ||
|
d81d4dfbd3 | ||
|
614013940d | ||
|
190ad35f71 | ||
|
6cf308c857 | ||
|
1402ecfecf | ||
|
46a30fe390 | ||
|
bb3a55a61a | ||
|
0affe12785 | ||
|
83d3ffc5d1 | ||
|
0ae4b8f48e | ||
|
aa450db1f7 | ||
|
10256a9fc7 | ||
|
6c337ddc24 | ||
|
59c0deba8f | ||
|
7876aac4eb | ||
|
4901ecd66e | ||
|
589e78cec5 | ||
|
5c3f23c09c | ||
|
b114518310 | ||
|
eda33efc88 | ||
|
c141541159 | ||
|
2fd2f8e711 | ||
|
b690de572c | ||
|
9c63dcb3fe | ||
|
ba709a385e | ||
|
0849d3d8b6 | ||
|
8e1502cce8 | ||
|
2ed9c2826a | ||
|
48ce9c397e | ||
|
ea6a172f84 | ||
|
7599d097c9 | ||
|
7612ec44dc | ||
|
391cbed883 | ||
|
4cc66435f9 | ||
|
74c82b3a29 | ||
|
f0e260ad73 | ||
|
af6b6b4828 | ||
|
4f12035e5d | ||
|
e4b633deb8 | ||
|
8d62ad3b35 | ||
|
c226da8c35 | ||
|
f48d641483 | ||
|
018858b2ce | ||
|
2421efc17b | ||
|
3259f9f89a | ||
|
55743b239f | ||
|
9afdc7e1d2 | ||
|
1c7a1c7b04 | ||
|
ed558e5da4 | ||
|
45a724b90c | ||
|
f53befb6a0 | ||
|
b159f5c74e | ||
|
298a367ad3 | ||
|
24a23aca69 | ||
|
91bd6bf0df | ||
|
40ef946ec5 | ||
|
b205a7fbe8 | ||
|
c274ee7b3e | ||
|
f0b0d92ab5 | ||
|
201a0fe361 | ||
|
6e17bd374f | ||
|
7153e7814b | ||
|
8db34adc37 | ||
|
e0aee5815a | ||
|
c3bc5e4c68 | ||
|
6509414227 | ||
|
977e4f94e0 | ||
|
8ae92d0d83 | ||
|
51a5618c54 | ||
|
a388989af4 | ||
|
f7f9cd1296 | ||
|
e320109e5d | ||
|
f9ad7c37b1 | ||
|
0b139a81fe | ||
|
4fd4dbb896 | ||
|
475afee0b8 | ||
|
0eeb6ccb42 | ||
|
cfb962d73c | ||
|
9fa31d1ed2 | ||
|
852f66a418 | ||
|
c867bc976a | ||
|
a551736532 | ||
|
6a82561f00 | ||
|
cc0451c949 | ||
|
e2a24ce13a | ||
|
be90974de8 | ||
|
1d25de8316 | ||
|
e3dc86bb0f | ||
|
a189b0f772 | ||
|
ca14981262 | ||
|
12e31ab7e8 | ||
|
14c07dcfa7 | ||
|
b2f7f6db1a | ||
|
64dcece342 | ||
|
4107cceea1 | ||
|
c84b9dca24 | ||
|
e57e728532 | ||
|
686503e2e0 | ||
|
24ad0dd46b | ||
|
b3d48c2c1b | ||
|
4822cb7672 | ||
|
60ce16f221 | ||
|
34b9100c67 | ||
|
82e0ff6da0 | ||
|
1a8352cfdb | ||
|
59aee7f3e8 | ||
|
0349359ce6 | ||
|
38889c3ad6 | ||
|
472e65dd0f | ||
|
0ebcc66506 | ||
|
696b4a26a8 | ||
|
ad9c473759 | ||
|
630bc9b45d | ||
|
719dafdaad | ||
|
27bb37c5d0 | ||
|
b24a93c68e | ||
|
9a0802dbe5 | ||
|
ee34711d64 | ||
|
220a8b9496 | ||
|
7c248cccb5 | ||
|
3e137c8e8a | ||
|
cf1772a492 | ||
|
a37fb2fbf7 | ||
|
24f9fd46ce | ||
|
5b3bf25bb8 | ||
|
f16196a00e | ||
|
0d5795c0a5 | ||
|
aacc667e51 | ||
|
cdfbb7efb9 | ||
|
ee15f723fd | ||
|
9298b31046 | ||
|
286e832854 | ||
|
a520ee9503 | ||
|
d65fd65608 | ||
|
1a7b31f260 | ||
|
7272abc35e | ||
|
6a50badb57 | ||
|
4dc25e7066 | ||
|
f9aabf7062 | ||
|
38db0f4c12 | ||
|
6ccfadb911 | ||
|
422ffff15c | ||
|
bd2bf3536c | ||
|
a9a3fd33a2 | ||
|
0a991cc543 | ||
|
14e5a046c8 | ||
|
a95a500d3d | ||
|
8d8fe19099 | ||
|
08781f6f7d | ||
|
93f8cbf4fa | ||
|
6958064c7f | ||
|
000a0ad7a6 | ||
|
e6519fcb2b | ||
|
e1d395f4b5 | ||
|
db8d099d4d | ||
|
13849d4205 | ||
|
e9d5ecca1d | ||
|
d2b722803f | ||
|
41d722c3d2 | ||
|
9d6e24a1d2 | ||
|
c1ed463195 | ||
|
bd05b260af | ||
|
da4758e791 | ||
|
b3a293813a | ||
|
bda5b832b0 | ||
|
09d983258b | ||
|
d441b4cbc7 | ||
|
e92cd9f769 | ||
|
1e9d101ed7 | ||
|
c73b54bcca | ||
|
db93dbb286 | ||
|
9e5a767855 | ||
|
64716226d2 | ||
|
27fc376fe9 | ||
|
aacaa8bba3 | ||
|
2502d0b698 | ||
|
d0fef9a1fc | ||
|
ad3225c648 | ||
|
00360049e3 | ||
|
f6744c2c73 | ||
|
379688c566 | ||
|
344915c9ea | ||
|
b0a5920d1a | ||
|
7e4698abe2 | ||
|
471ac1cdc0 | ||
|
5f61ccf07d | ||
|
a0fbd25e10 | ||
|
c2f8066b2f | ||
|
b57d2a2050 | ||
|
d6f5cbdd8c | ||
|
64240602b4 | ||
|
7b8ae3d067 | ||
|
0f18838c69 | ||
|
a115228329 | ||
|
e5a01efd07 | ||
|
7b48aa37a7 | ||
|
792b9b9337 | ||
|
43d421d388 | ||
|
aa233ecedc | ||
|
402876d489 | ||
|
c38d518718 | ||
|
2449eb0882 | ||
|
6388ce2224 | ||
|
b861b54178 | ||
|
7146e5818f | ||
|
41b396c64b | ||
|
83e0944f0f | ||
|
02733deded | ||
|
45b2d28d04 | ||
|
d76a23a3f1 | ||
|
b1a9219ac5 | ||
|
54962b3fce | ||
|
4807a021a1 | ||
|
829d1eda16 | ||
|
a0d76c5b37 | ||
|
bdee8658c6 | ||
|
469502c99b | ||
|
fbb81e344b | ||
|
8d300049f5 | ||
|
05cfdb9105 | ||
|
0b2a0bac47 | ||
|
5bf81c3758 | ||
|
a2c7dc0669 | ||
|
f0a67e9948 | ||
|
d014efd03d | ||
|
759e1881e8 | ||
|
15fcfcb606 | ||
|
5e6da54166 | ||
|
8687f5c38e | ||
|
8e8a9f6f40 | ||
|
cbc205c2f0 | ||
|
b1c50eb938 | ||
|
f98c203e7a | ||
|
8ca9fe7617 | ||
|
e4fe8bf95e | ||
|
3c30562dc7 | ||
|
756668d35c | ||
|
6b2f859232 | ||
|
8ca892b0e2 | ||
|
d247c116fb | ||
|
d2ccf595bd | ||
|
41dcc493e5 | ||
|
57deae5fd4 | ||
|
dbad6cdfec | ||
|
3c02fcd0e8 | ||
|
4323c6643b | ||
|
7a912c4746 | ||
|
c2e92b6f7b | ||
|
5a03844914 | ||
|
2edab536bd | ||
|
18e9550579 | ||
|
9c0ac9aec4 | ||
|
8ee8e0a213 | ||
|
885eef8ea5 | ||
|
d8a774c011 | ||
|
f88fe4d403 | ||
|
1531be8a1d | ||
|
9305aae476 | ||
|
7518718671 | ||
|
62c320a2d6 | ||
|
0b62666ece | ||
|
bcbd1df3dd | ||
|
e77fb46335 | ||
|
780809fb0c | ||
|
9f8e7ebf24 | ||
|
ff76244ea6 | ||
|
dc048b7c88 | ||
|
4ec560dd02 | ||
|
c6972ac6dd | ||
|
ec4d4b01e8 | ||
|
c88e819965 | ||
|
d067f2b224 | ||
|
0a01fc558b | ||
|
ec6f99c5ea | ||
|
9e639e676a | ||
|
1e812e43b3 | ||
|
7791f50e3a | ||
|
aa268fc8ef | ||
|
6ae7ef0659 | ||
|
a83faa061c | ||
|
402f89cb79 | ||
|
5cf1fa3add | ||
|
2ecc68c12f | ||
|
6b9d9f7259 | ||
|
9d05b03f83 | ||
|
39ade99d47 | ||
|
79c991e143 | ||
|
50ea460b93 | ||
|
43ff0f73cc | ||
|
437ce95059 | ||
|
68b07475a7 | ||
|
5a12bf417b | ||
|
712a403bec | ||
|
fae9d2ab27 | ||
|
e8ddb4325b | ||
|
c3eac5c0f3 | ||
|
2a878b1b76 | ||
|
e9348cd76d | ||
|
27fa1c4229 | ||
|
080bd09db3 | ||
|
3f6da0a367 | ||
|
4bb7f61050 | ||
|
aabf8aadf8 | ||
|
52852c6cb6 | ||
|
77314a3be7 | ||
|
5c01d8298c | ||
|
bd66336d45 | ||
|
8fd718c9eb | ||
|
a68f458612 | ||
|
f7cb3a3c8e | ||
|
6c1f27faab | ||
|
514b28af3c | ||
|
55ca000b0e | ||
|
73f1c2ba43 | ||
|
ecb9e393f2 | ||
|
493bf07596 | ||
|
78b3234396 | ||
|
52ad51382a | ||
|
4e5358a288 | ||
|
e27e7f1c7d | ||
|
460a8225ba | ||
|
575e70b063 | ||
|
41e14f7029 | ||
|
b8b56c4a67 | ||
|
a356603061 | ||
|
9abaf193d3 | ||
|
fe8a3972dd | ||
|
abc468275b | ||
|
6506bd7e82 | ||
|
9fbc2d23b5 | ||
|
0ce90f60ab | ||
|
bf55e33287 | ||
|
8685653cc7 | ||
|
ad9fa13d23 | ||
|
cd45a7f531 | ||
|
44705c1acb | ||
|
cda4b56bfe | ||
|
e8bed99b16 | ||
|
1147c0e1ca | ||
|
ad0bcec378 | ||
|
0d70cfacb2 | ||
|
77a319daa6 | ||
|
fc8334d96b | ||
|
a20138dcfc | ||
|
f379505d4d | ||
|
123a0d68a1 | ||
|
462a54895b | ||
|
3985939842 | ||
|
597a934368 | ||
|
4a3329dafb | ||
|
4b035ae611 | ||
|
34a919b980 | ||
|
547027837e | ||
|
d9b1101de6 | ||
|
b5d2ec4f83 | ||
|
92af2e47fc | ||
|
3ce6b720ac | ||
|
aecc9110a3 | ||
|
a6d295fa1e | ||
|
6b035cd7b7 | ||
|
83e58980a6 | ||
|
91f4a67d5d | ||
|
43e82682c5 | ||
|
2c11c9db52 | ||
|
dedc05c220 | ||
|
9b4eaff867 | ||
|
3a699c3764 | ||
|
b5ad6de8d6 | ||
|
a2d9c29b08 | ||
|
b5a04a9600 | ||
|
e10e5c3764 | ||
|
865d75ef30 | ||
|
d72968efac | ||
|
4b1f655a83 | ||
|
1a39f8935e | ||
|
5b27f32876 | ||
|
d069e79016 | ||
|
dbc04d1c7d | ||
|
6e472748d7 | ||
|
024e9356eb | ||
|
3f57f76e99 | ||
|
c4932fa57a | ||
|
e054db4ae2 | ||
|
ea5a14f7bc | ||
|
87c62f4ebb | ||
|
bc2851b407 | ||
|
b9a4d148c9 | ||
|
f2e5955e1e | ||
|
166e630768 | ||
|
83e85d2ac1 | ||
|
156b77327e | ||
|
74bd99e40e | ||
|
7a65fdcabf | ||
|
c969c2dec0 | ||
|
d19e45a1f5 | ||
|
51c68eb29d | ||
|
f400d8b30c | ||
|
1705723d7e | ||
|
7871ee5b6c | ||
|
c6d2e9e855 | ||
|
afe1af8fa9 | ||
|
e801e484f1 | ||
|
1390da5d12 | ||
|
94a6cfba89 | ||
|
77b20cf7b9 | ||
|
0113c86a2f | ||
|
71accd5e14 | ||
|
9d754188c6 | ||
|
9439e1fdad | ||
|
6cac2a1ae0 | ||
|
395270e494 | ||
|
2a06b85d4e | ||
|
f28daba53c | ||
|
161b20f333 | ||
|
e806c9ae2a | ||
|
e1c934421a | ||
|
db6431f140 | ||
|
bed809bc6b | ||
|
26da19f6ea | ||
|
3ba4266daa | ||
|
f9b4706151 | ||
|
2abe54fc9c | ||
|
ad8e4a29b9 | ||
|
ca3cd48fa3 | ||
|
718542ef7a | ||
|
c544028700 | ||
|
958e2c5331 | ||
|
c4b572a24c | ||
|
50fe45f43c | ||
|
628b868f44 | ||
|
9c6b6998ef | ||
|
2a471ed125 | ||
|
e9134c8ce3 | ||
|
9efd17e225 | ||
|
17ddc84406 | ||
|
a62058eee8 | ||
|
3199d1c1f5 | ||
|
e0c6c98025 | ||
|
d1826ca626 | ||
|
d9628a5643 | ||
|
c81b1c43b1 | ||
|
ad0a5c93b5 | ||
|
7e3c96582f | ||
|
3ef8709829 | ||
|
75ce774bc3 | ||
|
532ed228e7 | ||
|
69e1c3c352 | ||
|
484e8d4997 | ||
|
8226f597ac | ||
|
64dbeaf0f4 | ||
|
d59d435ec6 | ||
|
cb781f53aa | ||
|
1a759886d9 | ||
|
527a209674 | ||
|
4be765c083 | ||
|
4a43373aec | ||
|
00541f1952 | ||
|
a0543453de | ||
|
7504c67fb7 | ||
|
9d149c5284 | ||
|
753093d60e | ||
|
6fe1441782 | ||
|
17a83b748e | ||
|
44b7ba51a3 | ||
|
13900ce40d | ||
|
ffe955b9f9 | ||
|
894fee6db3 | ||
|
4d3642c188 | ||
|
6fbd6bb34e | ||
|
6a7b4dcae6 | ||
|
84ffb7e477 | ||
|
54db2b2ed6 | ||
|
bb4d37b052 | ||
|
51d3489ca1 | ||
|
a037d3815f | ||
|
59e6a1c477 | ||
|
3c4cb472d1 | ||
|
fcbf14a0e5 | ||
|
6ca8852eff | ||
|
0cd98ebbf7 | ||
|
41626401b0 | ||
|
aaf5c06d62 | ||
|
40c77a1c5a | ||
|
81339256da | ||
|
87830b62c6 | ||
|
7614320a13 | ||
|
882d328839 | ||
|
ffee85d67f | ||
|
dcb80ecbd9 | ||
|
23937e8cd5 | ||
|
9b451f2055 | ||
|
7222c1e50f | ||
|
e450552d07 | ||
|
b12612f525 | ||
|
8280ef7d93 | ||
|
ea1434b897 | ||
|
aaecaa4c0e | ||
|
f71faf5fec | ||
|
e76b689fe1 | ||
|
827be1b23c | ||
|
13d98f1ded | ||
|
9a0cf8d641 | ||
|
084fb3ab4f | ||
|
51d8ef48d9 | ||
|
47124e6337 | ||
|
d5d199fbc7 | ||
|
2c5ab14aaa | ||
|
a058a1f223 | ||
|
13ee8edf06 | ||
|
46485124ea | ||
|
6fe550306c | ||
|
97a5c52af4 | ||
|
6938ee0342 | ||
|
74bb7c52f3 | ||
|
081fcbdf5a | ||
|
0a1b26b862 | ||
|
76c3beaf36 | ||
|
2099db378a | ||
|
043980a60e | ||
|
474c6e43a6 | ||
|
22e5469cec | ||
|
5f23b9767a | ||
|
1ba907209f | ||
|
e41dc20c1c | ||
|
694ffa8747 | ||
|
03cf1565f5 | ||
|
f012442f98 | ||
|
a8fd29718a | ||
|
7cf634290f | ||
|
e28bcf58b1 | ||
|
a2ea5d28cb | ||
|
2032da0117 | ||
|
01f02f55a1 | ||
|
4c263ecd00 | ||
|
f26d9514b1 | ||
|
0bb72eeed0 | ||
|
c84e9b95be | ||
|
1c18646dd6 | ||
|
fb0e181a3e | ||
|
646da80c41 | ||
|
5aea89b5c4 | ||
|
c7fc03a33a | ||
|
bedc8d9373 | ||
|
2bdf985022 | ||
|
3cb4971729 | ||
|
0667ceae87 | ||
|
4335e49a02 | ||
|
a0f83e783f | ||
|
d5faabe7ea | ||
|
0aa400b1d8 | ||
|
ed76c8559e | ||
|
016e78b683 | ||
|
e6eec3cc14 | ||
|
b97ef6c702 | ||
|
215c8de3cd | ||
|
ff3aaece6d | ||
|
cf336f17b2 | ||
|
a7d7715f10 | ||
|
bcd5aa368d | ||
|
d2a88fbd7b | ||
|
94584d14d3 | ||
|
1bc87dfed2 | ||
|
8c561733b6 | ||
|
c07b22335f | ||
|
778acfc606 | ||
|
27a25f2d3d | ||
|
33b3177157 | ||
|
d46c0ca223 | ||
|
467b08ba36 | ||
|
a69842a839 | ||
|
e9c2d78dae | ||
|
6d95c12871 | ||
|
3446465750 | ||
|
8f1c31c09c | ||
|
11b714187b | ||
|
63cee529c2 | ||
|
39fec7b11d | ||
|
abdd60acef | ||
|
b540c37c89 | ||
|
7ba3efa5c6 | ||
|
57c9bdd0bd | ||
|
c404d8fc70 | ||
|
4c43fdcd07 | ||
|
c29b1de39f | ||
|
1e3f59a79f | ||
|
86329643fd | ||
|
be22e43d7d | ||
|
b5e07e7546 | ||
|
6738ee3d1b | ||
|
fc4d507770 | ||
|
4b54ee1148 | ||
|
f858def14b | ||
|
f68193a00a | ||
|
19a152b47e | ||
|
3c975a857f | ||
|
cb6779f9e5 | ||
|
134eef550d | ||
|
c55738fa77 | ||
|
b13017e651 | ||
|
ee19666c39 | ||
|
5cab741929 | ||
|
922a56f43a | ||
|
17c11ec523 | ||
|
ffae5b040d | ||
|
f840480fde | ||
|
be287eab02 | ||
|
1150d4bf12 | ||
|
4c06c3d606 | ||
|
fb22295311 | ||
|
f6bf9f697e | ||
|
c5e6c885c1 | ||
|
b9675d6d40 | ||
|
a70a30ddfd | ||
|
1bf0a5bc17 | ||
|
b1677e76aa | ||
|
691cc93976 | ||
|
b8327fe605 | ||
|
f394206b7c | ||
|
6e0dd8110e | ||
|
ef00ac8c84 | ||
|
6a37a65276 | ||
|
8efd2d85c7 | ||
|
b5327faf99 | ||
|
24fe2be9c1 | ||
|
97db7bb2a0 | ||
|
f0d6a36612 | ||
|
7bdc6c9a5a | ||
|
6091abcc9b | ||
|
e5e3bc4080 | ||
|
403f12f766 | ||
|
4818ba9ece | ||
|
c737829449 | ||
|
3577992a5b | ||
|
d0d256bb66 | ||
|
a4cd11dea9 | ||
|
0a678a9233 | ||
|
cad264b2c9 | ||
|
63c92d5a0d | ||
|
d712a02845 | ||
|
f5fe66cf5f | ||
|
4e75dfae84 | ||
|
99043f204d | ||
|
69057e6ec0 | ||
|
3975e220ce | ||
|
e535c6835b | ||
|
7a746c3295 | ||
|
9a15e0e69a | ||
|
5be62a9f66 | ||
|
f22943a2a2 | ||
|
726af2e4e5 | ||
|
acd122d030 | ||
|
3f40edbfa0 | ||
|
7392f32e47 | ||
|
515b6a58d9 | ||
|
601dd1a748 | ||
|
c05002afb8 | ||
|
ad7f428be4 | ||
|
900db7b1bd | ||
|
942a30b7df | ||
|
44281b2856 | ||
|
dc8da6129f | ||
|
b857b21a45 | ||
|
491c8c4e10 | ||
|
624d6edfe4 | ||
|
a26cf0f409 | ||
|
cec5c57130 | ||
|
cd5dfc6dbe | ||
|
d40c079fed | ||
|
7b9277486f | ||
|
b44f6ff5fe | ||
|
f738534042 | ||
|
fc825168d0 | ||
|
849b17351e | ||
|
b4787838e4 | ||
|
7d14eb5eb3 | ||
|
6215d68b69 | ||
|
dc4ff7012c | ||
|
37bfdf79c6 | ||
|
d9e99baa9a | ||
|
5ade5bab01 | ||
|
9f38690e8e | ||
|
d9058c64e0 | ||
|
1a2780735c | ||
|
c87bfe410b | ||
|
e99e6538d9 | ||
|
3e27038fca | ||
|
7f5fac7c87 | ||
|
f0ead85283 | ||
|
e5bdba0b3c | ||
|
cb09fe7995 | ||
|
749dc1eee0 | ||
|
b30c65e271 | ||
|
22a21e81a0 | ||
|
275fb565bb | ||
|
255dadc152 | ||
|
a617328005 | ||
|
7862c7c5e1 | ||
|
474bef1cfd | ||
|
95eefa38f6 | ||
|
80bbb0b2e9 | ||
|
7d17ea4996 | ||
|
a315d43b04 | ||
|
5b49ac21fe | ||
|
722ab54868 | ||
|
449c7f2a0d | ||
|
3a1d7ee7e8 | ||
|
e1cb3b155a | ||
|
359d163d25 | ||
|
7d23e642a2 | ||
|
d109947672 | ||
|
2ddcccd26e | ||
|
1ff462354b | ||
|
4825e5e2b4 | ||
|
9cf2ea3e8f | ||
|
bf36f5c3a4 | ||
|
7642366593 | ||
|
9a4601b06b | ||
|
3e50a8dfec | ||
|
cafbdf4217 | ||
|
267ebeeccd | ||
|
ee4ca63b6d | ||
|
ed37725e00 | ||
|
be022b3550 | ||
|
4291114246 | ||
|
91572945bb | ||
|
556eb02977 | ||
|
d9a25bc4ee | ||
|
7b44a94a55 | ||
|
b89ab7d0fb | ||
|
4fb0ac7728 | ||
|
832f199607 | ||
|
0e13e78153 | ||
|
3839e5fd59 | ||
|
04b2006fc9 | ||
|
bbb9e56365 | ||
|
d8d0987feb | ||
|
138448487e | ||
|
f5e50890d0 | ||
|
c68df817a6 | ||
|
9bd75952e5 | ||
|
66bb94fe46 | ||
|
9fd855ed55 | ||
|
880b92ed6e | ||
|
92f13bbdd7 | ||
|
c4c8eb4f8c | ||
|
b394ab39e9 | ||
|
9ba286de08 | ||
|
6d8035a99c | ||
|
adc5ef1e09 | ||
|
c2fa380391 | ||
|
721470f564 | ||
|
9ef009f597 | ||
|
6be66b0ef2 | ||
|
4df11621ce | ||
|
2fa9ccee61 | ||
|
2d2418ebac | ||
|
fe9398e9a9 | ||
|
22fbc75688 | ||
|
a888761a78 | ||
|
a40d6921dc | ||
|
3414b2dc6a | ||
|
6e518c3f55 | ||
|
66cc1e7da9 | ||
|
3a7ebc320d | ||
|
1e629c3511 | ||
|
7b27c8edd4 | ||
|
ba31fc95a9 | ||
|
021b443886 | ||
|
fc42cdd68d | ||
|
1ce8191289 | ||
|
e943a0098b | ||
|
9d5beeafa1 | ||
|
bdb50f1c6e | ||
|
056504168c | ||
|
3a63e174d8 | ||
|
503553c3d2 | ||
|
fca062eb4c | ||
|
c1f5b780f3 | ||
|
379e3c989a | ||
|
5a6f5922dd | ||
|
1abc8d2f37 | ||
|
23358ec279 | ||
|
57569baa65 | ||
|
b5a65e0f20 | ||
|
3258b1f248 | ||
|
524e0f0ad5 | ||
|
e451e91ec3 | ||
|
ce00135e37 | ||
|
edb3b20895 | ||
|
f887096ab1 | ||
|
c8050b3872 | ||
|
c6609bed68 | ||
|
8364839f5c | ||
|
30099ee188 | ||
|
40ef6c0577 | ||
|
1c249be96e | ||
|
10cf348a67 | ||
|
780aaca89b | ||
|
3bb89eebd6 | ||
|
26a737ac15 | ||
|
1dc8ff050f | ||
|
7d6729de29 | ||
|
056cc56044 | ||
|
5e584ee7d9 | ||
|
0b7beefd0b | ||
|
773fe85018 | ||
|
5002153e3a | ||
|
b14def8bb3 | ||
|
baf374e378 | ||
|
b608892658 | ||
|
2ddae77179 | ||
|
392463267f | ||
|
d759ee5a8d | ||
|
965790764a | ||
|
21cba9e5bc | ||
|
de7f97b7f7 | ||
|
b0d52abe97 | ||
|
1767f99e2e | ||
|
6898a6048c | ||
|
b5ed7846d6 | ||
|
622e9c33c3 | ||
|
9ef44a2d67 | ||
|
a9b76edca6 | ||
|
c85a6c2a22 | ||
|
5e32b5ca8f | ||
|
4148c8d4e1 | ||
|
f8e0ba5eff | ||
|
9974a66169 | ||
|
392581be01 | ||
|
e5139c51aa | ||
|
825bc19643 | ||
|
35f67618e8 | ||
|
de1a1e27d4 | ||
|
786097029e | ||
|
e1026a2252 | ||
|
d44cc8a1fc | ||
|
0ce67f56dd | ||
|
e31ea830c8 | ||
|
52becf1c6d | ||
|
a8360b7e95 | ||
|
c224178a09 | ||
|
2dc6334133 | ||
|
734ba5ab48 | ||
|
67591f8511 | ||
|
75d168cbf4 | ||
|
aa933abb76 | ||
|
12fc715dd6 | ||
|
89c83b5b08 | ||
|
5f8b77d195 | ||
|
bb5a8284e0 | ||
|
ea3b6c60ba | ||
|
b12acba494 | ||
|
2437fd883a | ||
|
2166a46ad3 | ||
|
62ae9fbd6a | ||
|
b5e9f2cb2b | ||
|
8db2997e4e | ||
|
8a805271a1 | ||
|
064b24177b | ||
|
e1269215f9 | ||
|
755929c48d | ||
|
377e3c67a4 | ||
|
ab36089924 | ||
|
1a4bdd699a | ||
|
9c00255b4a | ||
|
6a25df24b0 | ||
|
5462978c90 | ||
|
008505e1c4 | ||
|
cec95a2d26 | ||
|
4d1f6e049c | ||
|
4587e08a46 | ||
|
e8de8d88df | ||
|
50d67b202a | ||
|
d9c029755c | ||
|
e157205499 | ||
|
8de0d91166 | ||
|
b6196986d7 | ||
|
31b22016a2 | ||
|
5772f4ffce | ||
|
18f1d9121e | ||
|
c1c0e82e3f | ||
|
4aad43c826 | ||
|
a891445449 | ||
|
a87fa89b4e | ||
|
fa79b51d13 | ||
|
c7ef6a2ed5 |
1138 changed files with 64495 additions and 13206 deletions
48
.ci/build-win.sh
Executable file
48
.ci/build-win.sh
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
if [ "$#" -lt 1 ]
|
||||
then
|
||||
echo "Usage $0 ARCH (ARCH can be 32 or 64)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ARCH=$1
|
||||
shift
|
||||
|
||||
BUILD=build-win${ARCH}
|
||||
INSTALL=install-win${ARCH}
|
||||
DIST=harfbuzz-win${ARCH}
|
||||
|
||||
meson setup \
|
||||
--buildtype=release \
|
||||
--prefix="${PWD}/${BUILD}/${INSTALL}" \
|
||||
--cross-file=.ci/win${ARCH}-cross-file.txt \
|
||||
--wrap-mode=default \
|
||||
--strip \
|
||||
-Dtests=enabled \
|
||||
-Dcairo=enabled \
|
||||
-Dcairo:fontconfig=disabled \
|
||||
-Dcairo:freetype=disabled \
|
||||
-Dcairo:dwrite=disabled \
|
||||
-Dcairo:tests=disabled \
|
||||
-Dglib=enabled \
|
||||
-Dlibffi:tests=false \
|
||||
-Dfreetype=disabled \
|
||||
-Dicu=disabled \
|
||||
-Dchafa=disabled \
|
||||
-Dgdi=enabled \
|
||||
-Ddirectwrite=enabled \
|
||||
${BUILD} \
|
||||
"$@"
|
||||
|
||||
# building with all the cores won't work fine with CricleCI for some reason
|
||||
meson compile -C ${BUILD} -j3
|
||||
meson install -C ${BUILD}
|
||||
|
||||
mkdir ${BUILD}/${DIST}
|
||||
cp ${BUILD}/${INSTALL}/bin/hb-*.exe ${BUILD}/${DIST}
|
||||
cp ${BUILD}/${INSTALL}/bin/*.dll ${BUILD}/${DIST}
|
||||
rm -f ${DIST}.zip
|
||||
(cd ${BUILD} && zip -r ../${DIST}.zip ${DIST})
|
||||
echo "${DIST}.zip is ready."
|
|
@ -1,28 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
meson --cross-file=.ci/win32-cross-file.txt \
|
||||
--wrap-mode=default \
|
||||
-Dtests=disabled \
|
||||
-Dcairo=enabled \
|
||||
-Dcairo:fontconfig=disabled \
|
||||
-Dcairo:freetype=disabled \
|
||||
-Dcairo:dwrite=disabled \
|
||||
-Dcairo:tests=disabled \
|
||||
-Dglib=enabled \
|
||||
-Dfreetype=disabled \
|
||||
-Dgdi=enabled \
|
||||
-Ddirectwrite=enabled \
|
||||
win32build \
|
||||
$@
|
||||
|
||||
ninja -Cwin32build -j3 # building with all the cores won't work fine with CricleCI for some reason
|
||||
|
||||
rm -rf win32build/harfbuzz-win32
|
||||
mkdir win32build/harfbuzz-win32
|
||||
cp win32build/util/hb-*.exe win32build/harfbuzz-win32
|
||||
find win32build -name '*.dll' -exec cp {} win32build/harfbuzz-win32 \;
|
||||
i686-w64-mingw32-strip win32build/harfbuzz-win32/*.{dll,exe}
|
||||
rm -f harfbuzz-win32.zip
|
||||
(cd win32build && zip -r ../harfbuzz-win32.zip harfbuzz-win32)
|
||||
echo "harfbuzz-win32.zip is ready."
|
|
@ -1,28 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
meson --cross-file=.ci/win64-cross-file.txt \
|
||||
--wrap-mode=default \
|
||||
-Dtests=disabled \
|
||||
-Dcairo=enabled \
|
||||
-Dcairo:fontconfig=disabled \
|
||||
-Dcairo:freetype=disabled \
|
||||
-Dcairo:dwrite=disabled \
|
||||
-Dcairo:tests=disabled \
|
||||
-Dglib=enabled \
|
||||
-Dfreetype=disabled \
|
||||
-Dgdi=enabled \
|
||||
-Ddirectwrite=enabled \
|
||||
win64build \
|
||||
$@
|
||||
|
||||
ninja -Cwin64build -j3 # building with all the cores won't work fine with CricleCI for some reason
|
||||
|
||||
rm -rf win64build/harfbuzz-win64
|
||||
mkdir win64build/harfbuzz-win64
|
||||
cp win64build/util/hb-*.exe win64build/harfbuzz-win64
|
||||
find win64build -name '*.dll' -exec cp {} win64build/harfbuzz-win64 \;
|
||||
x86_64-w64-mingw32-strip win64build/harfbuzz-win64/*.{dll,exe}
|
||||
rm -f harfbuzz-win64.zip
|
||||
(cd win64build && zip -r ../harfbuzz-win64.zip harfbuzz-win64)
|
||||
echo "harfbuzz-win64.zip is ready."
|
|
@ -11,12 +11,11 @@ fi
|
|||
if ! hash ghr 2> /dev/null; then
|
||||
_GHR_VER=v0.14.0
|
||||
_GHR=ghr_${_GHR_VER}_linux_amd64
|
||||
mkdir -p $HOME/.local/bin
|
||||
curl -sfL https://github.com/tcnksm/ghr/releases/download/$_GHR_VER/$_GHR.tar.gz |
|
||||
tar xz -C $HOME/.local/bin --strip-components=1 $_GHR/ghr
|
||||
tar xz -C . --strip-components=1 $_GHR/ghr
|
||||
fi
|
||||
|
||||
ghr -replace \
|
||||
./ghr -replace \
|
||||
-u $CIRCLE_PROJECT_USERNAME \
|
||||
-r $CIRCLE_PROJECT_REPONAME \
|
||||
$CIRCLE_TAG \
|
||||
|
|
|
@ -4,47 +4,55 @@
|
|||
#
|
||||
# pip-compile --generate-hashes .ci/requirements-fonttools.in
|
||||
#
|
||||
fonttools==4.53.1 \
|
||||
--hash=sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122 \
|
||||
--hash=sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397 \
|
||||
--hash=sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f \
|
||||
--hash=sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d \
|
||||
--hash=sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60 \
|
||||
--hash=sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169 \
|
||||
--hash=sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8 \
|
||||
--hash=sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31 \
|
||||
--hash=sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923 \
|
||||
--hash=sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2 \
|
||||
--hash=sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb \
|
||||
--hash=sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab \
|
||||
--hash=sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb \
|
||||
--hash=sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a \
|
||||
--hash=sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670 \
|
||||
--hash=sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8 \
|
||||
--hash=sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407 \
|
||||
--hash=sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671 \
|
||||
--hash=sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88 \
|
||||
--hash=sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f \
|
||||
--hash=sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f \
|
||||
--hash=sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0 \
|
||||
--hash=sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb \
|
||||
--hash=sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2 \
|
||||
--hash=sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d \
|
||||
--hash=sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c \
|
||||
--hash=sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3 \
|
||||
--hash=sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719 \
|
||||
--hash=sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749 \
|
||||
--hash=sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4 \
|
||||
--hash=sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f \
|
||||
--hash=sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02 \
|
||||
--hash=sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58 \
|
||||
--hash=sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1 \
|
||||
--hash=sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41 \
|
||||
--hash=sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4 \
|
||||
--hash=sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb \
|
||||
--hash=sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb \
|
||||
--hash=sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3 \
|
||||
--hash=sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d \
|
||||
--hash=sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d \
|
||||
--hash=sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2
|
||||
fonttools==4.57.0 \
|
||||
--hash=sha256:03290e818782e7edb159474144fca11e36a8ed6663d1fcbd5268eb550594fd8e \
|
||||
--hash=sha256:0425c2e052a5f1516c94e5855dbda706ae5a768631e9fcc34e57d074d1b65b92 \
|
||||
--hash=sha256:05efceb2cb5f6ec92a4180fcb7a64aa8d3385fd49cfbbe459350229d1974f0b1 \
|
||||
--hash=sha256:17168a4670bbe3775f3f3f72d23ee786bd965395381dfbb70111e25e81505b9d \
|
||||
--hash=sha256:3122c604a675513c68bd24c6a8f9091f1c2376d18e8f5fe5a101746c81b3e98f \
|
||||
--hash=sha256:34687a5d21f1d688d7d8d416cb4c5b9c87fca8a1797ec0d74b9fdebfa55c09ab \
|
||||
--hash=sha256:3871349303bdec958360eedb619169a779956503ffb4543bb3e6211e09b647c4 \
|
||||
--hash=sha256:39acf68abdfc74e19de7485f8f7396fa4d2418efea239b7061d6ed6a2510c746 \
|
||||
--hash=sha256:3cf97236b192a50a4bf200dc5ba405aa78d4f537a2c6e4c624bb60466d5b03bd \
|
||||
--hash=sha256:408ce299696012d503b714778d89aa476f032414ae57e57b42e4b92363e0b8ef \
|
||||
--hash=sha256:44c26a311be2ac130f40a96769264809d3b0cb297518669db437d1cc82974888 \
|
||||
--hash=sha256:46370ac47a1e91895d40e9ad48effbe8e9d9db1a4b80888095bc00e7beaa042f \
|
||||
--hash=sha256:4dea5893b58d4637ffa925536462ba626f8a1b9ffbe2f5c272cdf2c6ebadb817 \
|
||||
--hash=sha256:51d8482e96b28fb28aa8e50b5706f3cee06de85cbe2dce80dbd1917ae22ec5a6 \
|
||||
--hash=sha256:541cb48191a19ceb1a2a4b90c1fcebd22a1ff7491010d3cf840dd3a68aebd654 \
|
||||
--hash=sha256:579ba873d7f2a96f78b2e11028f7472146ae181cae0e4d814a37a09e93d5c5cc \
|
||||
--hash=sha256:57e30241524879ea10cdf79c737037221f77cc126a8cdc8ff2c94d4a522504b9 \
|
||||
--hash=sha256:69ab81b66ebaa8d430ba56c7a5f9abe0183afefd3a2d6e483060343398b13fb1 \
|
||||
--hash=sha256:6e3e1ec10c29bae0ea826b61f265ec5c858c5ba2ce2e69a71a62f285cf8e4595 \
|
||||
--hash=sha256:727ece10e065be2f9dd239d15dd5d60a66e17eac11aea47d447f9f03fdbc42de \
|
||||
--hash=sha256:7339e6a3283e4b0ade99cade51e97cde3d54cd6d1c3744459e886b66d630c8b3 \
|
||||
--hash=sha256:767604f244dc17c68d3e2dbf98e038d11a18abc078f2d0f84b6c24571d9c0b13 \
|
||||
--hash=sha256:7a64edd3ff6a7f711a15bd70b4458611fb240176ec11ad8845ccbab4fe6745db \
|
||||
--hash=sha256:81aa97669cd726349eb7bd43ca540cf418b279ee3caba5e2e295fb4e8f841c02 \
|
||||
--hash=sha256:84c41ba992df5b8d680b89fd84c6a1f2aca2b9f1ae8a67400c8930cd4ea115f6 \
|
||||
--hash=sha256:84fd56c78d431606332a0627c16e2a63d243d0d8b05521257d77c6529abe14d8 \
|
||||
--hash=sha256:889e45e976c74abc7256d3064aa7c1295aa283c6bb19810b9f8b604dfe5c7f31 \
|
||||
--hash=sha256:8e2e12d0d862f43d51e5afb8b9751c77e6bec7d2dc00aad80641364e9df5b199 \
|
||||
--hash=sha256:967b65232e104f4b0f6370a62eb33089e00024f2ce143aecbf9755649421c683 \
|
||||
--hash=sha256:9d077f909f2343daf4495ba22bb0e23b62886e8ec7c109ee8234bdbd678cf344 \
|
||||
--hash=sha256:9d57b4e23ebbe985125d3f0cabbf286efa191ab60bbadb9326091050d88e8213 \
|
||||
--hash=sha256:a1968f2a2003c97c4ce6308dc2498d5fd4364ad309900930aa5a503c9851aec8 \
|
||||
--hash=sha256:a2a722c0e4bfd9966a11ff55c895c817158fcce1b2b6700205a376403b546ad9 \
|
||||
--hash=sha256:a97bb05eb24637714a04dee85bdf0ad1941df64fe3b802ee4ac1c284a5f97b7c \
|
||||
--hash=sha256:aff40f8ac6763d05c2c8f6d240c6dac4bb92640a86d9b0c3f3fff4404f34095c \
|
||||
--hash=sha256:babe8d1eb059a53e560e7bf29f8e8f4accc8b6cfb9b5fd10e485bde77e71ef41 \
|
||||
--hash=sha256:bbceffc80aa02d9e8b99f2a7491ed8c4a783b2fc4020119dc405ca14fb5c758c \
|
||||
--hash=sha256:c59375e85126b15a90fcba3443eaac58f3073ba091f02410eaa286da9ad80ed8 \
|
||||
--hash=sha256:ca2aed95855506b7ae94e8f1f6217b7673c929e4f4f1217bcaa236253055cb36 \
|
||||
--hash=sha256:cc066cb98b912f525ae901a24cd381a656f024f76203bc85f78fcc9e66ae5aec \
|
||||
--hash=sha256:cdef9a056c222d0479a1fdb721430f9efd68268014c54e8166133d2643cb05d9 \
|
||||
--hash=sha256:d07f1b64008e39fceae7aa99e38df8385d7d24a474a8c9872645c4397b674481 \
|
||||
--hash=sha256:d639397de852f2ccfb3134b152c741406752640a266d9c1365b0f23d7b88077f \
|
||||
--hash=sha256:dff02c5c8423a657c550b48231d0a48d7e2b2e131088e55983cfe74ccc2c7cc9 \
|
||||
--hash=sha256:e952c684274a7714b3160f57ec1d78309f955c6335c04433f07d36c5eb27b1f9 \
|
||||
--hash=sha256:ea1e9e43ca56b0c12440a7c689b1350066595bebcaa83baad05b8b2675129d98 \
|
||||
--hash=sha256:f022601f3ee9e1f6658ed6d184ce27fa5216cee5b82d279e0f0bde5deebece72 \
|
||||
--hash=sha256:f0e9618630edd1910ad4f07f60d77c184b2f572c8ee43305ea3265675cbbfe7e \
|
||||
--hash=sha256:f1d6bc9c23356908db712d282acb3eebd4ae5ec6d8b696aa40342b1d84f8e9e3 \
|
||||
--hash=sha256:f4376819c1c778d59e0a31db5dc6ede854e9edf28bbfa5b756604727f7f800ac
|
||||
# via -r requirements-fonttools.in
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
-r requirements-fonttools.in
|
||||
meson==1.5.2
|
||||
gcovr==5.0
|
||||
meson==1.7.0
|
||||
ninja
|
||||
setuptools # https://github.com/harfbuzz/harfbuzz/issues/4475
|
||||
|
|
|
@ -4,242 +4,84 @@
|
|||
#
|
||||
# pip-compile --allow-unsafe --generate-hashes --output-file=.ci/requirements.txt .ci/requirements.in
|
||||
#
|
||||
fonttools==4.53.1 \
|
||||
--hash=sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122 \
|
||||
--hash=sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397 \
|
||||
--hash=sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f \
|
||||
--hash=sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d \
|
||||
--hash=sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60 \
|
||||
--hash=sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169 \
|
||||
--hash=sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8 \
|
||||
--hash=sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31 \
|
||||
--hash=sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923 \
|
||||
--hash=sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2 \
|
||||
--hash=sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb \
|
||||
--hash=sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab \
|
||||
--hash=sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb \
|
||||
--hash=sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a \
|
||||
--hash=sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670 \
|
||||
--hash=sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8 \
|
||||
--hash=sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407 \
|
||||
--hash=sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671 \
|
||||
--hash=sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88 \
|
||||
--hash=sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f \
|
||||
--hash=sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f \
|
||||
--hash=sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0 \
|
||||
--hash=sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb \
|
||||
--hash=sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2 \
|
||||
--hash=sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d \
|
||||
--hash=sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c \
|
||||
--hash=sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3 \
|
||||
--hash=sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719 \
|
||||
--hash=sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749 \
|
||||
--hash=sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4 \
|
||||
--hash=sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f \
|
||||
--hash=sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02 \
|
||||
--hash=sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58 \
|
||||
--hash=sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1 \
|
||||
--hash=sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41 \
|
||||
--hash=sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4 \
|
||||
--hash=sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb \
|
||||
--hash=sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb \
|
||||
--hash=sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3 \
|
||||
--hash=sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d \
|
||||
--hash=sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d \
|
||||
--hash=sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2
|
||||
fonttools==4.57.0 \
|
||||
--hash=sha256:03290e818782e7edb159474144fca11e36a8ed6663d1fcbd5268eb550594fd8e \
|
||||
--hash=sha256:0425c2e052a5f1516c94e5855dbda706ae5a768631e9fcc34e57d074d1b65b92 \
|
||||
--hash=sha256:05efceb2cb5f6ec92a4180fcb7a64aa8d3385fd49cfbbe459350229d1974f0b1 \
|
||||
--hash=sha256:17168a4670bbe3775f3f3f72d23ee786bd965395381dfbb70111e25e81505b9d \
|
||||
--hash=sha256:3122c604a675513c68bd24c6a8f9091f1c2376d18e8f5fe5a101746c81b3e98f \
|
||||
--hash=sha256:34687a5d21f1d688d7d8d416cb4c5b9c87fca8a1797ec0d74b9fdebfa55c09ab \
|
||||
--hash=sha256:3871349303bdec958360eedb619169a779956503ffb4543bb3e6211e09b647c4 \
|
||||
--hash=sha256:39acf68abdfc74e19de7485f8f7396fa4d2418efea239b7061d6ed6a2510c746 \
|
||||
--hash=sha256:3cf97236b192a50a4bf200dc5ba405aa78d4f537a2c6e4c624bb60466d5b03bd \
|
||||
--hash=sha256:408ce299696012d503b714778d89aa476f032414ae57e57b42e4b92363e0b8ef \
|
||||
--hash=sha256:44c26a311be2ac130f40a96769264809d3b0cb297518669db437d1cc82974888 \
|
||||
--hash=sha256:46370ac47a1e91895d40e9ad48effbe8e9d9db1a4b80888095bc00e7beaa042f \
|
||||
--hash=sha256:4dea5893b58d4637ffa925536462ba626f8a1b9ffbe2f5c272cdf2c6ebadb817 \
|
||||
--hash=sha256:51d8482e96b28fb28aa8e50b5706f3cee06de85cbe2dce80dbd1917ae22ec5a6 \
|
||||
--hash=sha256:541cb48191a19ceb1a2a4b90c1fcebd22a1ff7491010d3cf840dd3a68aebd654 \
|
||||
--hash=sha256:579ba873d7f2a96f78b2e11028f7472146ae181cae0e4d814a37a09e93d5c5cc \
|
||||
--hash=sha256:57e30241524879ea10cdf79c737037221f77cc126a8cdc8ff2c94d4a522504b9 \
|
||||
--hash=sha256:69ab81b66ebaa8d430ba56c7a5f9abe0183afefd3a2d6e483060343398b13fb1 \
|
||||
--hash=sha256:6e3e1ec10c29bae0ea826b61f265ec5c858c5ba2ce2e69a71a62f285cf8e4595 \
|
||||
--hash=sha256:727ece10e065be2f9dd239d15dd5d60a66e17eac11aea47d447f9f03fdbc42de \
|
||||
--hash=sha256:7339e6a3283e4b0ade99cade51e97cde3d54cd6d1c3744459e886b66d630c8b3 \
|
||||
--hash=sha256:767604f244dc17c68d3e2dbf98e038d11a18abc078f2d0f84b6c24571d9c0b13 \
|
||||
--hash=sha256:7a64edd3ff6a7f711a15bd70b4458611fb240176ec11ad8845ccbab4fe6745db \
|
||||
--hash=sha256:81aa97669cd726349eb7bd43ca540cf418b279ee3caba5e2e295fb4e8f841c02 \
|
||||
--hash=sha256:84c41ba992df5b8d680b89fd84c6a1f2aca2b9f1ae8a67400c8930cd4ea115f6 \
|
||||
--hash=sha256:84fd56c78d431606332a0627c16e2a63d243d0d8b05521257d77c6529abe14d8 \
|
||||
--hash=sha256:889e45e976c74abc7256d3064aa7c1295aa283c6bb19810b9f8b604dfe5c7f31 \
|
||||
--hash=sha256:8e2e12d0d862f43d51e5afb8b9751c77e6bec7d2dc00aad80641364e9df5b199 \
|
||||
--hash=sha256:967b65232e104f4b0f6370a62eb33089e00024f2ce143aecbf9755649421c683 \
|
||||
--hash=sha256:9d077f909f2343daf4495ba22bb0e23b62886e8ec7c109ee8234bdbd678cf344 \
|
||||
--hash=sha256:9d57b4e23ebbe985125d3f0cabbf286efa191ab60bbadb9326091050d88e8213 \
|
||||
--hash=sha256:a1968f2a2003c97c4ce6308dc2498d5fd4364ad309900930aa5a503c9851aec8 \
|
||||
--hash=sha256:a2a722c0e4bfd9966a11ff55c895c817158fcce1b2b6700205a376403b546ad9 \
|
||||
--hash=sha256:a97bb05eb24637714a04dee85bdf0ad1941df64fe3b802ee4ac1c284a5f97b7c \
|
||||
--hash=sha256:aff40f8ac6763d05c2c8f6d240c6dac4bb92640a86d9b0c3f3fff4404f34095c \
|
||||
--hash=sha256:babe8d1eb059a53e560e7bf29f8e8f4accc8b6cfb9b5fd10e485bde77e71ef41 \
|
||||
--hash=sha256:bbceffc80aa02d9e8b99f2a7491ed8c4a783b2fc4020119dc405ca14fb5c758c \
|
||||
--hash=sha256:c59375e85126b15a90fcba3443eaac58f3073ba091f02410eaa286da9ad80ed8 \
|
||||
--hash=sha256:ca2aed95855506b7ae94e8f1f6217b7673c929e4f4f1217bcaa236253055cb36 \
|
||||
--hash=sha256:cc066cb98b912f525ae901a24cd381a656f024f76203bc85f78fcc9e66ae5aec \
|
||||
--hash=sha256:cdef9a056c222d0479a1fdb721430f9efd68268014c54e8166133d2643cb05d9 \
|
||||
--hash=sha256:d07f1b64008e39fceae7aa99e38df8385d7d24a474a8c9872645c4397b674481 \
|
||||
--hash=sha256:d639397de852f2ccfb3134b152c741406752640a266d9c1365b0f23d7b88077f \
|
||||
--hash=sha256:dff02c5c8423a657c550b48231d0a48d7e2b2e131088e55983cfe74ccc2c7cc9 \
|
||||
--hash=sha256:e952c684274a7714b3160f57ec1d78309f955c6335c04433f07d36c5eb27b1f9 \
|
||||
--hash=sha256:ea1e9e43ca56b0c12440a7c689b1350066595bebcaa83baad05b8b2675129d98 \
|
||||
--hash=sha256:f022601f3ee9e1f6658ed6d184ce27fa5216cee5b82d279e0f0bde5deebece72 \
|
||||
--hash=sha256:f0e9618630edd1910ad4f07f60d77c184b2f572c8ee43305ea3265675cbbfe7e \
|
||||
--hash=sha256:f1d6bc9c23356908db712d282acb3eebd4ae5ec6d8b696aa40342b1d84f8e9e3 \
|
||||
--hash=sha256:f4376819c1c778d59e0a31db5dc6ede854e9edf28bbfa5b756604727f7f800ac
|
||||
# via -r requirements-fonttools.in
|
||||
gcovr==5.0 \
|
||||
--hash=sha256:1d80264cbaadff356b3dda71b8c62b3aa803e5b3eb6d526a24932cd6660a2576 \
|
||||
--hash=sha256:8c49ebcfc5a98b56dd900c687aad0258ac86093d2f81a1417905193ab45fe69f
|
||||
meson==1.7.0 \
|
||||
--hash=sha256:08efbe84803eed07f863b05092d653a9d348f7038761d900412fddf56deb0284 \
|
||||
--hash=sha256:ae3f12953045f3c7c60e27f2af1ad862f14dee125b4ed9bcb8a842a5080dbf85
|
||||
# via -r requirements.in
|
||||
jinja2==3.1.4 \
|
||||
--hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \
|
||||
--hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d
|
||||
# via gcovr
|
||||
lxml==4.9.3 \
|
||||
--hash=sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3 \
|
||||
--hash=sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d \
|
||||
--hash=sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a \
|
||||
--hash=sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120 \
|
||||
--hash=sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305 \
|
||||
--hash=sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287 \
|
||||
--hash=sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23 \
|
||||
--hash=sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52 \
|
||||
--hash=sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f \
|
||||
--hash=sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4 \
|
||||
--hash=sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584 \
|
||||
--hash=sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f \
|
||||
--hash=sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693 \
|
||||
--hash=sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef \
|
||||
--hash=sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5 \
|
||||
--hash=sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02 \
|
||||
--hash=sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc \
|
||||
--hash=sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7 \
|
||||
--hash=sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da \
|
||||
--hash=sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a \
|
||||
--hash=sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40 \
|
||||
--hash=sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8 \
|
||||
--hash=sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd \
|
||||
--hash=sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601 \
|
||||
--hash=sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c \
|
||||
--hash=sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be \
|
||||
--hash=sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2 \
|
||||
--hash=sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c \
|
||||
--hash=sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129 \
|
||||
--hash=sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc \
|
||||
--hash=sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2 \
|
||||
--hash=sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1 \
|
||||
--hash=sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7 \
|
||||
--hash=sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d \
|
||||
--hash=sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477 \
|
||||
--hash=sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d \
|
||||
--hash=sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e \
|
||||
--hash=sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7 \
|
||||
--hash=sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2 \
|
||||
--hash=sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574 \
|
||||
--hash=sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf \
|
||||
--hash=sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b \
|
||||
--hash=sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98 \
|
||||
--hash=sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12 \
|
||||
--hash=sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42 \
|
||||
--hash=sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35 \
|
||||
--hash=sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d \
|
||||
--hash=sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce \
|
||||
--hash=sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d \
|
||||
--hash=sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f \
|
||||
--hash=sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db \
|
||||
--hash=sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4 \
|
||||
--hash=sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694 \
|
||||
--hash=sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac \
|
||||
--hash=sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2 \
|
||||
--hash=sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7 \
|
||||
--hash=sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96 \
|
||||
--hash=sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d \
|
||||
--hash=sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b \
|
||||
--hash=sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a \
|
||||
--hash=sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13 \
|
||||
--hash=sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340 \
|
||||
--hash=sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6 \
|
||||
--hash=sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458 \
|
||||
--hash=sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c \
|
||||
--hash=sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c \
|
||||
--hash=sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9 \
|
||||
--hash=sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432 \
|
||||
--hash=sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991 \
|
||||
--hash=sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69 \
|
||||
--hash=sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf \
|
||||
--hash=sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb \
|
||||
--hash=sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b \
|
||||
--hash=sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833 \
|
||||
--hash=sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76 \
|
||||
--hash=sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85 \
|
||||
--hash=sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e \
|
||||
--hash=sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50 \
|
||||
--hash=sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8 \
|
||||
--hash=sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4 \
|
||||
--hash=sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b \
|
||||
--hash=sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5 \
|
||||
--hash=sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190 \
|
||||
--hash=sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7 \
|
||||
--hash=sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa \
|
||||
--hash=sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0 \
|
||||
--hash=sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9 \
|
||||
--hash=sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0 \
|
||||
--hash=sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b \
|
||||
--hash=sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5 \
|
||||
--hash=sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7 \
|
||||
--hash=sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4
|
||||
# via gcovr
|
||||
markupsafe==2.1.3 \
|
||||
--hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \
|
||||
--hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \
|
||||
--hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \
|
||||
--hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \
|
||||
--hash=sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c \
|
||||
--hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \
|
||||
--hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \
|
||||
--hash=sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb \
|
||||
--hash=sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939 \
|
||||
--hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \
|
||||
--hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \
|
||||
--hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \
|
||||
--hash=sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9 \
|
||||
--hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \
|
||||
--hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \
|
||||
--hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \
|
||||
--hash=sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd \
|
||||
--hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \
|
||||
--hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \
|
||||
--hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \
|
||||
--hash=sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac \
|
||||
--hash=sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52 \
|
||||
--hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \
|
||||
--hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \
|
||||
--hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \
|
||||
--hash=sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007 \
|
||||
--hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \
|
||||
--hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \
|
||||
--hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \
|
||||
--hash=sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0 \
|
||||
--hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \
|
||||
--hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \
|
||||
--hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \
|
||||
--hash=sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1 \
|
||||
--hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \
|
||||
--hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \
|
||||
--hash=sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c \
|
||||
--hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \
|
||||
--hash=sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823 \
|
||||
--hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \
|
||||
--hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \
|
||||
--hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \
|
||||
--hash=sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad \
|
||||
--hash=sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee \
|
||||
--hash=sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc \
|
||||
--hash=sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2 \
|
||||
--hash=sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48 \
|
||||
--hash=sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7 \
|
||||
--hash=sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e \
|
||||
--hash=sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b \
|
||||
--hash=sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa \
|
||||
--hash=sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5 \
|
||||
--hash=sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e \
|
||||
--hash=sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb \
|
||||
--hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \
|
||||
--hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \
|
||||
--hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \
|
||||
--hash=sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc \
|
||||
--hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \
|
||||
--hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11
|
||||
# via jinja2
|
||||
meson==1.5.2 \
|
||||
--hash=sha256:77706e2368a00d789c097632ccf4fc39251fba56d03e1e1b262559a3c7a08f5b \
|
||||
--hash=sha256:f955e09ab0d71ef180ae85df65991d58ed8430323de7d77a37e11c9ea630910b
|
||||
ninja==1.11.1.4 \
|
||||
--hash=sha256:055f386fb550c2c9d6157e45e20a84d29c47968876b9c5794ae2aec46f952306 \
|
||||
--hash=sha256:096487995473320de7f65d622c3f1d16c3ad174797602218ca8c967f51ec38a0 \
|
||||
--hash=sha256:2ab67a41c90bea5ec4b795bab084bc0b3b3bb69d3cd21ca0294fc0fc15a111eb \
|
||||
--hash=sha256:4617b3c12ff64b611a7d93fd9e378275512bb36eff8babff7c83f5116b4f8d66 \
|
||||
--hash=sha256:5713cf50c5be50084a8693308a63ecf9e55c3132a78a41ab1363a28b6caaaee1 \
|
||||
--hash=sha256:6aa39f6e894e0452e5b297327db00019383ae55d5d9c57c73b04f13bf79d438a \
|
||||
--hash=sha256:9c29bb66d2aa46a2409ab369ea804c730faec7652e8c22c1e428cc09216543e5 \
|
||||
--hash=sha256:b33923c8da88e8da20b6053e38deb433f53656441614207e01d283ad02c5e8e7 \
|
||||
--hash=sha256:c3b96bd875f3ef1db782470e9e41d7508905a0986571f219d20ffed238befa15 \
|
||||
--hash=sha256:cede0af00b58e27b31f2482ba83292a8e9171cdb9acc2c867a3b6e40b3353e43 \
|
||||
--hash=sha256:cf4453679d15babc04ba023d68d091bb613091b67101c88f85d2171c6621c6eb \
|
||||
--hash=sha256:cf554e73f72c04deb04d0cf51f5fdb1903d9c9ca3d2344249c8ce3bd616ebc02 \
|
||||
--hash=sha256:cfdd09776436a1ff3c4a2558d3fc50a689fb9d7f1bdbc3e6f7b8c2991341ddb3 \
|
||||
--hash=sha256:d3090d4488fadf6047d0d7a1db0c9643a8d391f0d94729554dbb89b5bdc769d7 \
|
||||
--hash=sha256:d4a6f159b08b0ac4aca5ee1572e3e402f969139e71d85d37c0e2872129098749 \
|
||||
--hash=sha256:ecce44a00325a93631792974659cf253a815cc6da4ec96f89742925dfc295a0d \
|
||||
--hash=sha256:f6186d7607bb090c3be1e10c8a56b690be238f953616626f5032238c66e56867
|
||||
# via -r requirements.in
|
||||
ninja==1.11.1.1 \
|
||||
--hash=sha256:18302d96a5467ea98b68e1cae1ae4b4fb2b2a56a82b955193c637557c7273dbd \
|
||||
--hash=sha256:185e0641bde601e53841525c4196278e9aaf4463758da6dd1e752c0a0f54136a \
|
||||
--hash=sha256:376889c76d87b95b5719fdd61dd7db193aa7fd4432e5d52d2e44e4c497bdbbee \
|
||||
--hash=sha256:3e0f9be5bb20d74d58c66cc1c414c3e6aeb45c35b0d0e41e8d739c2c0d57784f \
|
||||
--hash=sha256:73b93c14046447c7c5cc892433d4fae65d6364bec6685411cb97a8bcf815f93a \
|
||||
--hash=sha256:7563ce1d9fe6ed5af0b8dd9ab4a214bf4ff1f2f6fd6dc29f480981f0f8b8b249 \
|
||||
--hash=sha256:76482ba746a2618eecf89d5253c0d1e4f1da1270d41e9f54dfbd91831b0f6885 \
|
||||
--hash=sha256:84502ec98f02a037a169c4b0d5d86075eaf6afc55e1879003d6cab51ced2ea4b \
|
||||
--hash=sha256:95da904130bfa02ea74ff9c0116b4ad266174fafb1c707aa50212bc7859aebf1 \
|
||||
--hash=sha256:9d793b08dd857e38d0b6ffe9e6b7145d7c485a42dcfea04905ca0cdb6017cc3c \
|
||||
--hash=sha256:9df724344202b83018abb45cb1efc22efd337a1496514e7e6b3b59655be85205 \
|
||||
--hash=sha256:aad34a70ef15b12519946c5633344bc775a7656d789d9ed5fdb0d456383716ef \
|
||||
--hash=sha256:d491fc8d89cdcb416107c349ad1e3a735d4c4af5e1cb8f5f727baca6350fdaea \
|
||||
--hash=sha256:ecf80cf5afd09f14dcceff28cb3f11dc90fb97c999c89307aea435889cb66877 \
|
||||
--hash=sha256:fa2ba9d74acfdfbfbcf06fad1b8282de8a7a8c481d9dee45c859a8c93fcc1082
|
||||
# via -r requirements.in
|
||||
pygments==2.16.1 \
|
||||
--hash=sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692 \
|
||||
--hash=sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29
|
||||
# via gcovr
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
setuptools==73.0.1 \
|
||||
--hash=sha256:b208925fcb9f7af924ed2dc04708ea89791e24bde0d3020b27df0e116088b34e \
|
||||
--hash=sha256:d59a3e788ab7e012ab2c4baed1b376da6366883ee20d7a5fc426816e3d7b1193
|
||||
setuptools==78.1.0 \
|
||||
--hash=sha256:18fd474d4a82a5f83dac888df697af65afa82dec7323d09c3e37d1f14288da54 \
|
||||
--hash=sha256:3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8
|
||||
# via -r requirements.in
|
||||
|
|
|
@ -4,7 +4,7 @@ cpu_family = 'x86'
|
|||
cpu = 'i686'
|
||||
endian = 'little'
|
||||
|
||||
[properties]
|
||||
[built-in options]
|
||||
c_args = []
|
||||
c_link_args = ['-static-libgcc', '-Wl,-Bstatic', '-lpthread']
|
||||
cpp_args = []
|
||||
|
@ -18,3 +18,5 @@ ld = 'i686-w64-mingw32-ld'
|
|||
objcopy = 'i686-w64-mingw32-objcopy'
|
||||
strip = 'i686-w64-mingw32-strip'
|
||||
windres = 'i686-w64-mingw32-windres'
|
||||
pkg-config = 'i686-w64-mingw32-pkg-config'
|
||||
exe_wrapper = 'wine'
|
||||
|
|
|
@ -4,7 +4,7 @@ cpu_family = 'x86_64'
|
|||
cpu = 'x86_64'
|
||||
endian = 'little'
|
||||
|
||||
[properties]
|
||||
[built-in options]
|
||||
c_args = []
|
||||
c_link_args = ['-static-libgcc', '-Wl,-Bstatic', '-lpthread']
|
||||
cpp_args = []
|
||||
|
@ -18,3 +18,5 @@ ld = 'x86_64-w64-mingw32-ld'
|
|||
objcopy = 'x86_64-w64-mingw32-objcopy'
|
||||
strip = 'x86_64-w64-mingw32-strip'
|
||||
windres = 'x86_64-w64-mingw32-windres'
|
||||
pkg-config = 'x86_64-w64-mingw32-pkg-config'
|
||||
exe_wrapper = 'wine'
|
||||
|
|
|
@ -3,10 +3,10 @@ version: 2.1
|
|||
executors:
|
||||
win32-executor:
|
||||
docker:
|
||||
- image: cimg/base:2023.10
|
||||
- image: ubuntu:24.04
|
||||
win64-executor:
|
||||
docker:
|
||||
- image: cimg/base:2023.10
|
||||
- image: ubuntu:24.04
|
||||
dist-executor:
|
||||
docker:
|
||||
- image: cimg/base:2023.10
|
||||
|
@ -37,7 +37,7 @@ jobs:
|
|||
- run: meson dist --no-tests -Cbuild
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: build/meson-dist/harfbuzz-*.tar.xz
|
||||
paths: [build/meson-dist/harfbuzz-*.tar.xz]
|
||||
|
||||
publish-dist:
|
||||
executor: dist-executor
|
||||
|
@ -56,22 +56,7 @@ jobs:
|
|||
- run: dnf install -y pkg-config ragel valgrind gcc gcc-c++ meson git glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python python-pip || true
|
||||
- run: meson setup build --buildtype=debugoptimized
|
||||
- run: meson compile -Cbuild -j9
|
||||
# TOOD: increase timeouts and remove --no-suite=slow
|
||||
- run: RUN_VALGRIND=1 meson test -Cbuild --no-suite=slow --wrap='valgrind --leak-check=full --error-exitcode=1' --print-errorlogs --num-processes=$(($(nproc)/2 + 1))
|
||||
|
||||
alpine:
|
||||
docker:
|
||||
- image: alpine
|
||||
steps:
|
||||
- checkout
|
||||
- run: apk update && apk add ragel gcc g++ glib-dev freetype-dev cairo-dev git py3-pip ninja
|
||||
- run: |
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip3 install meson==0.56.0
|
||||
meson setup build --buildtype=minsize
|
||||
meson compile -Cbuild -j9
|
||||
meson test -Cbuild --print-errorlogs
|
||||
- run: RUN_VALGRIND=1 meson test -Cbuild -t 10 --no-suite=slow --wrap='valgrind --leak-check=full --error-exitcode=1' --print-errorlogs --num-processes=$(($(nproc)/2 + 1))
|
||||
|
||||
asan-ubsan:
|
||||
docker:
|
||||
|
@ -81,43 +66,47 @@ jobs:
|
|||
- run: apt update || true
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip python3-venv ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
|
||||
- run: |
|
||||
export ASAN_OPTIONS=log_path=stderr:halt_on_error=1:abort_on_error=1
|
||||
export UBSAN_OPTIONS=log_path=stderr:halt_on_error=1:abort_on_error=1:print_stacktrace=1
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip3 install meson==0.56.0
|
||||
pip3 install meson==0.60.0
|
||||
CC=clang CXX=clang++ meson setup build --default-library=static -Db_sanitize=address,undefined --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
|
||||
meson compile -Cbuild -j9
|
||||
meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||
meson test -Cbuild -t 10 --print-errorlogs | asan_symbolize | c++filt
|
||||
|
||||
tsan:
|
||||
docker:
|
||||
- image: ubuntu:20.04
|
||||
- image: ubuntu:24.04
|
||||
steps:
|
||||
- checkout
|
||||
- run: apt update || true
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip python3-venv ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
|
||||
- run: |
|
||||
export TSAN_OPTIONS=log_path=stderr:halt_on_error=1:abort_on_error=1
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip3 install meson==0.56.0
|
||||
pip3 install meson==0.60.0
|
||||
CC=clang CXX=clang++ meson setup build --default-library=static -Db_sanitize=thread --buildtype=debugoptimized --wrap-mode=nodownload -Dexperimental_api=true
|
||||
meson compile -Cbuild -j9
|
||||
meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||
meson test -Cbuild -t 10 --print-errorlogs | asan_symbolize | c++filt
|
||||
|
||||
msan:
|
||||
docker:
|
||||
- image: ubuntu:20.04
|
||||
- image: ubuntu:24.04
|
||||
steps:
|
||||
- checkout
|
||||
- run: apt update || true
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip python3-venv ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
|
||||
- run: |
|
||||
export MSAN_OPTIONS=log_path=stderr:halt_on_error=1:abort_on_error=1:print_stacktrace=1
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip3 install meson==0.56.0
|
||||
pip3 install meson==0.60.0
|
||||
# msan, needs --force-fallback-for=glib,freetype2 also which doesn't work yet but runs fuzzer cases at least
|
||||
CC=clang CXX=clang++ meson setup build --default-library=static -Db_sanitize=memory --buildtype=debugoptimized --wrap-mode=nodownload -Dauto_features=disabled -Dtests=enabled -Dexperimental_api=true
|
||||
meson compile -Cbuild -j9
|
||||
meson test -Cbuild --print-errorlogs | asan_symbolize | c++filt
|
||||
meson test -Cbuild -t 10 --print-errorlogs | asan_symbolize | c++filt
|
||||
|
||||
clang-cxx2a:
|
||||
docker:
|
||||
|
@ -132,17 +121,21 @@ jobs:
|
|||
executor: win32-executor
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build python3 python3-pip python3-venv git g++-mingw-w64-i686 zip
|
||||
- run: dpkg --add-architecture i386
|
||||
- run: apt update
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt install -y ninja-build python3 python3-pip python3-venv git g++-mingw-w64-i686 zip wine wine32
|
||||
- run: |
|
||||
export LANG=en_US.UTF-8
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip3 install meson==0.60.0
|
||||
bash .ci/build-win32.sh
|
||||
pip3 install meson==1.6.0
|
||||
bash .ci/build-win.sh 32
|
||||
meson devenv -Cbuild-win32 meson test -t 10 --print-errorlogs --suite=harfbuzz
|
||||
- store_artifacts:
|
||||
path: harfbuzz-win32.zip
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: harfbuzz-win32.zip
|
||||
paths: [harfbuzz-win32.zip]
|
||||
|
||||
publish-win32:
|
||||
executor: win32-executor
|
||||
|
@ -150,6 +143,8 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: apt update
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt install -y curl
|
||||
- run: |
|
||||
mv harfbuzz-win32{,-$CIRCLE_TAG}.zip
|
||||
.ci/publish_release_artifact.sh harfbuzz-win32-$CIRCLE_TAG.zip
|
||||
|
@ -158,17 +153,21 @@ jobs:
|
|||
executor: win64-executor
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build python3 python3-pip python3-venv git g++-mingw-w64-x86-64 zip
|
||||
- run: dpkg --add-architecture i386
|
||||
- run: apt update
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt install -y ninja-build python3 python3-pip python3-venv git g++-mingw-w64-x86-64 zip wine wine64 wine32:i386
|
||||
- run: |
|
||||
export LANG=en_US.UTF-8
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip3 install meson==0.60.0
|
||||
bash .ci/build-win64.sh
|
||||
pip3 install meson==1.6.0
|
||||
bash .ci/build-win.sh 64
|
||||
meson devenv -Cbuild-win64 meson test -t 10 --print-errorlogs --suite=harfbuzz
|
||||
- store_artifacts:
|
||||
path: harfbuzz-win64.zip
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: harfbuzz-win64.zip
|
||||
paths: [harfbuzz-win64.zip]
|
||||
|
||||
publish-win64:
|
||||
executor: win64-executor
|
||||
|
@ -176,6 +175,8 @@ jobs:
|
|||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run: apt update
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt install -y curl
|
||||
- run: |
|
||||
mv harfbuzz-win64{,-$CIRCLE_TAG}.zip
|
||||
.ci/publish_release_artifact.sh harfbuzz-win64-$CIRCLE_TAG.zip
|
||||
|
@ -200,7 +201,6 @@ workflows:
|
|||
branches:
|
||||
ignore: /.*/
|
||||
- fedora-valgrind
|
||||
- alpine
|
||||
- asan-ubsan
|
||||
- tsan
|
||||
- msan
|
||||
|
|
2
.github/workflows/arm-ci.yml
vendored
2
.github/workflows/arm-ci.yml
vendored
|
@ -15,7 +15,7 @@ jobs:
|
|||
container:
|
||||
image: devkitpro/devkitarm:latest
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
cmake -S . -B build \
|
||||
|
|
2
.github/workflows/cifuzz.yml
vendored
2
.github/workflows/cifuzz.yml
vendored
|
@ -21,7 +21,7 @@ jobs:
|
|||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
|
|
4
.github/workflows/configs-build.yml
vendored
4
.github/workflows/configs-build.yml
vendored
|
@ -11,10 +11,10 @@ permissions:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: install dependencies
|
||||
run: sudo apt-get install gcc
|
||||
- name: HB_DISABLE_DEPRECATED
|
||||
|
|
2
.github/workflows/coverity-scan.yml
vendored
2
.github/workflows/coverity-scan.yml
vendored
|
@ -11,7 +11,7 @@ jobs:
|
|||
latest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- run: sudo apt-get install gcc clang wget git curl pkg-config libfreetype6-dev libglib2.0-dev libicu-dev libgraphite2-dev
|
||||
|
||||
|
|
63
.github/workflows/fontations.yml
vendored
Normal file
63
.github/workflows/fontations.yml
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
name: fontations
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
tags: ["*.*.*"]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Ccache
|
||||
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
|
||||
with:
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ runner.arch }}
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
rustup component add \
|
||||
rust-src \
|
||||
rustfmt \
|
||||
clippy \
|
||||
--toolchain nightly-x86_64-unknown-linux-gnu
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
gcc \
|
||||
gobject-introspection \
|
||||
gtk-doc-tools \
|
||||
libcairo2-dev \
|
||||
libfreetype6-dev \
|
||||
libgirepository1.0-dev \
|
||||
libglib2.0-dev \
|
||||
libgraphite2-dev \
|
||||
libicu-dev \
|
||||
pkg-config \
|
||||
bindgen
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
|
||||
with:
|
||||
python-version: '3.12'
|
||||
- name: Install Python Dependencies
|
||||
run: pip3 install -r .ci/requirements.txt --require-hashes
|
||||
- name: Setup Meson
|
||||
run: |
|
||||
ccache --version
|
||||
meson setup build \
|
||||
-Dauto_features=enabled \
|
||||
-Dchafa=disabled \
|
||||
-Dgraphite=enabled \
|
||||
-Doptimization=2 \
|
||||
-Dfontations=enabled
|
||||
- name: Build
|
||||
run: meson compile -Cbuild
|
||||
- name: Test
|
||||
run: RUST_BACKTRACE=1 meson test --print-errorlogs -Cbuild
|
23
.github/workflows/linux-ci.yml
vendored
23
.github/workflows/linux-ci.yml
vendored
|
@ -12,13 +12,13 @@ permissions:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Ccache
|
||||
uses: hendrikmuhs/ccache-action@ed74d11c0b343532753ecead8a951bb09bb34bc9 # v1.2.14
|
||||
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
|
||||
with:
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ runner.arch }}
|
||||
- name: Install Dependencies
|
||||
|
@ -34,16 +34,14 @@ jobs:
|
|||
libglib2.0-dev \
|
||||
libgraphite2-dev \
|
||||
libicu-dev \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
python3 \
|
||||
python3-setuptools
|
||||
help2man
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
|
||||
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
python-version: '3.12'
|
||||
- name: Install Python Dependencies
|
||||
run: sudo pip3 install -r .ci/requirements.txt --require-hashes
|
||||
run: pip3 install -r .ci/requirements.txt --require-hashes
|
||||
- name: Setup Meson
|
||||
run: |
|
||||
ccache --version
|
||||
|
@ -52,7 +50,6 @@ jobs:
|
|||
-Dchafa=disabled \
|
||||
-Dgraphite=enabled \
|
||||
-Doptimization=2 \
|
||||
-Db_coverage=true \
|
||||
-Ddoc_tests=true \
|
||||
-Dragel_subproject=true
|
||||
- name: Build
|
||||
|
@ -67,9 +64,3 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
REVISION: ${{ github.sha }}
|
||||
- name: Generate Coverage
|
||||
run: ninja -Cbuild coverage-xml
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
||||
with:
|
||||
file: build/meson-logs/coverage.xml
|
||||
|
|
18
.github/workflows/macos-ci.yml
vendored
18
.github/workflows/macos-ci.yml
vendored
|
@ -15,15 +15,16 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Ccache
|
||||
uses: hendrikmuhs/ccache-action@ed74d11c0b343532753ecead8a951bb09bb34bc9 # v1.2.14
|
||||
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
|
||||
with:
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ runner.arch }}
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
export HOMEBREW_NO_AUTO_UPDATE=1
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew rm -f pkg-config@0.29.2
|
||||
brew install \
|
||||
cairo \
|
||||
freetype \
|
||||
|
@ -33,11 +34,11 @@ jobs:
|
|||
icu4c \
|
||||
meson \
|
||||
ninja \
|
||||
pkg-config
|
||||
pkgconf
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
|
||||
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
python-version: '3.12'
|
||||
- name: Install Python Dependencies
|
||||
run: pip3 install -r .ci/requirements.txt --require-hashes
|
||||
- name: Setup Meson
|
||||
|
@ -53,14 +54,7 @@ jobs:
|
|||
-Dcoretext=enabled \
|
||||
-Dgraphite=enabled \
|
||||
-Doptimization=2 \
|
||||
-Db_coverage=true \
|
||||
- name: Build
|
||||
run: meson compile -Cbuild
|
||||
- name: Test
|
||||
run: meson test --print-errorlogs -Cbuild
|
||||
- name: Generate Coverage
|
||||
run: ninja -Cbuild coverage-xml
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
||||
with:
|
||||
file: build/meson-logs/coverage.xml
|
||||
|
|
8
.github/workflows/msvc-ci.yml
vendored
8
.github/workflows/msvc-ci.yml
vendored
|
@ -28,16 +28,16 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Ccache
|
||||
uses: hendrikmuhs/ccache-action@ed74d11c0b343532753ecead8a951bb09bb34bc9 # v1.2.14
|
||||
uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-${{ matrix.os }}-${{ matrix.ARCH }}
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
|
||||
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
python-version: '3.12'
|
||||
- name: Setup MSVC
|
||||
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
|
||||
with:
|
||||
|
|
19
.github/workflows/msys2-ci.yml
vendored
19
.github/workflows/msys2-ci.yml
vendored
|
@ -21,19 +21,16 @@ jobs:
|
|||
MSYS2_ARCH: i686
|
||||
- MSYSTEM: MINGW64
|
||||
MSYS2_ARCH: x86_64
|
||||
- MSYSTEM: CLANG64
|
||||
MSYS2_ARCH: clang-x86_64
|
||||
name: ${{ matrix.MSYSTEM }}
|
||||
|
||||
env:
|
||||
# XXX: For some reason enabling jit debugging "fixes" random python crashes
|
||||
# see https://github.com/msys2/MINGW-packages/issues/11864
|
||||
MSYS: "winjitdebug"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@cf96e00c0aab3788743aaf63b64146f0d383cee9 # v2
|
||||
with:
|
||||
|
@ -42,8 +39,7 @@ jobs:
|
|||
install: >-
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-cairo
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-freetype
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gcc-libs
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-cc
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gettext
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-glib2
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-gobject-introspection
|
||||
|
@ -51,12 +47,9 @@ jobs:
|
|||
mingw-w64-${{ matrix.MSYS2_ARCH }}-icu
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-meson
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-ninja
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-pkg-config
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-pkgconf
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-python
|
||||
mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip
|
||||
- name: Remove installed HarfBuzz DLLs
|
||||
run: |
|
||||
rm -f -v /ming*/bin/libharfbuzz-*.dll
|
||||
- name: Install Python Dependencies
|
||||
run: |
|
||||
pip3 install -r .ci/requirements-fonttools.txt --require-hashes
|
||||
|
@ -76,7 +69,7 @@ jobs:
|
|||
run: meson test --print-errorlogs --suite=harfbuzz -Cbuild
|
||||
- name: Upload DLLs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: libharfbuzz-${{ matrix.MSYS2_ARCH }}
|
||||
path: ./build/src/libharfbuzz-*.dll
|
||||
|
|
8
.github/workflows/scorecard.yml
vendored
8
.github/workflows/scorecard.yml
vendored
|
@ -29,12 +29,12 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
|
@ -51,7 +51,7 @@ jobs:
|
|||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
|
@ -59,6 +59,6 @@ jobs:
|
|||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@294a9d92911152fe08befb9ec03e240add280cb3 # v3.26.8
|
||||
uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 # v3.28.15
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
124
CMakeLists.txt
124
CMakeLists.txt
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(harfbuzz)
|
||||
|
||||
message(WARN "HarfBuzz has a Meson port and tries to migrate all the other build systems to it, please consider using it as we might remove our cmake port soon.")
|
||||
|
@ -6,20 +6,6 @@ message(WARN "HarfBuzz has a Meson port and tries to migrate all the other build
|
|||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
## Limit framework build to Xcode generator
|
||||
if (BUILD_FRAMEWORK)
|
||||
# for a framework build on macOS, use:
|
||||
# cmake -DBUILD_FRAMEWORK=ON -Bbuild -H. -GXcode && cmake --build build
|
||||
if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode")
|
||||
message(FATAL_ERROR
|
||||
"You should use Xcode generator with BUILD_FRAMEWORK enabled")
|
||||
endif ()
|
||||
set (CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)")
|
||||
set (CMAKE_MACOSX_RPATH ON)
|
||||
set (BUILD_SHARED_LIBS ON)
|
||||
endif ()
|
||||
|
||||
|
||||
## Disallow in-source builds, as CMake generated make files can collide with autotools ones
|
||||
if (NOT MSVC AND "${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}")
|
||||
message(FATAL_ERROR
|
||||
|
@ -73,6 +59,14 @@ if (HB_HAVE_INTROSPECTION)
|
|||
set (HB_HAVE_GLIB ON)
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
option(BUILD_FRAMEWORK "Build as Apple Frameworks" OFF)
|
||||
endif ()
|
||||
if (BUILD_FRAMEWORK)
|
||||
set (CMAKE_MACOSX_RPATH ON)
|
||||
set (BUILD_SHARED_LIBS OFF)
|
||||
endif ()
|
||||
|
||||
include_directories(AFTER
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_BINARY_DIR}/src
|
||||
|
@ -168,7 +162,7 @@ set (subset_project_sources
|
|||
${PROJECT_SOURCE_DIR}/src/hb-subset-plan.cc
|
||||
${PROJECT_SOURCE_DIR}/src/hb-subset-plan.hh
|
||||
${PROJECT_SOURCE_DIR}/src/hb-subset-plan-member-list.hh
|
||||
${PROJECT_SOURCE_DIR}/src/hb-subset-repacker.cc
|
||||
${PROJECT_SOURCE_DIR}/src/hb-subset-serialize.cc
|
||||
${PROJECT_SOURCE_DIR}/src/hb-subset.cc
|
||||
${PROJECT_SOURCE_DIR}/src/hb-subset.hh
|
||||
${PROJECT_SOURCE_DIR}/src/hb-repacker.hh
|
||||
|
@ -210,6 +204,7 @@ set (project_headers
|
|||
${PROJECT_SOURCE_DIR}/src/hb-ot.h
|
||||
${PROJECT_SOURCE_DIR}/src/hb-paint.h
|
||||
${PROJECT_SOURCE_DIR}/src/hb-set.h
|
||||
${PROJECT_SOURCE_DIR}/src/hb-script-list.h
|
||||
${PROJECT_SOURCE_DIR}/src/hb-shape-plan.h
|
||||
${PROJECT_SOURCE_DIR}/src/hb-shape.h
|
||||
${PROJECT_SOURCE_DIR}/src/hb-style.h
|
||||
|
@ -219,7 +214,7 @@ set (project_headers
|
|||
)
|
||||
set (subset_project_headers
|
||||
${PROJECT_SOURCE_DIR}/src/hb-subset.h
|
||||
${PROJECT_SOURCE_DIR}/src/hb-subset-repacker.h
|
||||
${PROJECT_SOURCE_DIR}/src/hb-subset-serialize.h
|
||||
)
|
||||
|
||||
## Find and include needed header folders and libraries
|
||||
|
@ -239,7 +234,7 @@ if (HB_HAVE_FREETYPE AND NOT TARGET freetype)
|
|||
set (CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${FREETYPE_INCLUDE_DIRS})
|
||||
set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${FREETYPE_LIBRARIES})
|
||||
|
||||
check_funcs(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var)
|
||||
check_funcs(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var FT_Get_Transform)
|
||||
endif ()
|
||||
|
||||
if (HB_HAVE_FREETYPE)
|
||||
|
@ -340,15 +335,15 @@ endif ()
|
|||
if (WIN32 AND HB_HAVE_GDI)
|
||||
add_definitions(-DHAVE_GDI)
|
||||
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-gdi.h)
|
||||
list(APPEND THIRD_PARTY_LIBS gdi32)
|
||||
list(APPEND PC_LIBS_PRIV -lgdi32)
|
||||
list(APPEND THIRD_PARTY_LIBS gdi32 user32)
|
||||
list(APPEND PC_LIBS_PRIV -lgdi32 -luser32)
|
||||
endif ()
|
||||
|
||||
if (WIN32 AND HB_HAVE_UNISCRIBE)
|
||||
add_definitions(-DHAVE_UNISCRIBE)
|
||||
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h)
|
||||
list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4)
|
||||
list(APPEND PC_LIBS_PRIV -lusp10 -lgdi32 -lrpcrt4)
|
||||
list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4 user32)
|
||||
list(APPEND PC_LIBS_PRIV -lusp10 -lgdi32 -lrpcrt4 -luser32)
|
||||
endif ()
|
||||
|
||||
if (WIN32 AND HB_HAVE_DIRECTWRITE)
|
||||
|
@ -506,6 +501,21 @@ if (HB_HAVE_ICU)
|
|||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set_target_properties(harfbuzz harfbuzz-icu PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
|
||||
|
||||
if (BUILD_FRAMEWORK)
|
||||
set_target_properties(harfbuzz harfbuzz-icu PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
FRAMEWORK_VERSION "${HB_VERSION}"
|
||||
PUBLIC_HEADER "${project_headers}"
|
||||
PRODUCT_BUNDLE_IDENTIFIER "harfbuzz.harfbuzz-icu"
|
||||
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
|
||||
OUTPUT_NAME "harfbuzz-icu"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
|
||||
MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz-icu"
|
||||
MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}"
|
||||
MACOSX_FRAMEWORK_BUNDLE_VERSION "${HB_VERSION}"
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
@ -513,12 +523,27 @@ endif ()
|
|||
## Define harfbuzz-subset library
|
||||
if (HB_BUILD_SUBSET)
|
||||
add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
|
||||
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-subset.h ${PROJECT_SOURCE_DIR}/src/hb-subset-repacker.h)
|
||||
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-subset.h ${PROJECT_SOURCE_DIR}/src/hb-subset-serialize.h)
|
||||
add_dependencies(harfbuzz-subset harfbuzz)
|
||||
target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set_target_properties(harfbuzz harfbuzz-subset PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
|
||||
|
||||
if (BUILD_FRAMEWORK)
|
||||
set_target_properties(harfbuzz harfbuzz-subset PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
FRAMEWORK_VERSION "${HB_VERSION}"
|
||||
PUBLIC_HEADER "${project_headers}"
|
||||
PRODUCT_BUNDLE_IDENTIFIER "harfbuzz.harfbuzz-subset"
|
||||
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
|
||||
OUTPUT_NAME "harfbuzz-subset"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
|
||||
MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz-subset"
|
||||
MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}"
|
||||
MACOSX_FRAMEWORK_BUNDLE_VERSION "${HB_VERSION}"
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
@ -568,7 +593,22 @@ if (HB_HAVE_GOBJECT)
|
|||
target_link_libraries(harfbuzz-gobject harfbuzz ${GOBJECT_LIBRARIES} ${THIRD_PARTY_LIBS})
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set_target_properties(harfbuzz-gobject PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
|
||||
set_target_properties(harfbuzz harfbuzz-gobject PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
|
||||
|
||||
if (BUILD_FRAMEWORK)
|
||||
set_target_properties(harfbuzz-gobject PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
FRAMEWORK_VERSION "${HB_VERSION}"
|
||||
PUBLIC_HEADER "${project_headers}"
|
||||
PRODUCT_BUNDLE_IDENTIFIER "harfbuzz.harfbuzz-gobject"
|
||||
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
|
||||
OUTPUT_NAME "harfbuzz-gobject"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
|
||||
MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz-gobject"
|
||||
MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}"
|
||||
MACOSX_FRAMEWORK_BUNDLE_VERSION "${HB_VERSION}"
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
@ -581,6 +621,21 @@ if (HB_HAVE_CAIRO)
|
|||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set_target_properties(harfbuzz-cairo PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
|
||||
|
||||
if (BUILD_FRAMEWORK)
|
||||
set_target_properties(harfbuzz-cairo PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
FRAMEWORK_VERSION "${HB_VERSION}"
|
||||
PUBLIC_HEADER "${project_headers}"
|
||||
PRODUCT_BUNDLE_IDENTIFIER "harfbuzz.harbuzz-cairo"
|
||||
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
|
||||
OUTPUT_NAME "harfbuzz-cairo"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
|
||||
MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz-cairo"
|
||||
MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}"
|
||||
MACOSX_FRAMEWORK_BUNDLE_VERSION "${HB_VERSION}"
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
|
@ -719,8 +774,12 @@ if (BUILD_FRAMEWORK)
|
|||
set (CMAKE_MACOSX_RPATH ON)
|
||||
set_target_properties(harfbuzz PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
FRAMEWORK_VERSION "${HB_VERSION}"
|
||||
PUBLIC_HEADER "${project_headers}"
|
||||
PRODUCT_BUNDLE_IDENTIFIER "harfbuzz"
|
||||
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
|
||||
OUTPUT_NAME "harfbuzz"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
|
||||
)
|
||||
set (MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz")
|
||||
set (MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}")
|
||||
|
@ -881,7 +940,8 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
|||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
FRAMEWORK DESTINATION Library/Frameworks
|
||||
FRAMEWORK DESTINATION Library/Frameworks
|
||||
COMPONENT runtime OPTIONAL
|
||||
)
|
||||
make_pkgconfig_pc_file("harfbuzz")
|
||||
install(EXPORT harfbuzzConfig
|
||||
|
@ -893,7 +953,8 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
|||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
FRAMEWORK DESTINATION Library/Frameworks
|
||||
FRAMEWORK DESTINATION Library/Frameworks
|
||||
COMPONENT runtime OPTIONAL
|
||||
)
|
||||
make_pkgconfig_pc_file("harfbuzz-icu")
|
||||
endif ()
|
||||
|
@ -902,13 +963,19 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
|||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
FRAMEWORK DESTINATION Library/Frameworks
|
||||
FRAMEWORK DESTINATION Library/Frameworks
|
||||
COMPONENT runtime OPTIONAL
|
||||
)
|
||||
make_pkgconfig_pc_file("harfbuzz-cairo")
|
||||
endif ()
|
||||
if (HB_BUILD_SUBSET)
|
||||
install(TARGETS harfbuzz-subset
|
||||
EXPORT harfbuzz-subset
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
FRAMEWORK DESTINATION Library/Frameworks
|
||||
COMPONENT runtime OPTIONAL
|
||||
)
|
||||
make_pkgconfig_pc_file("harfbuzz-subset")
|
||||
endif ()
|
||||
|
@ -943,9 +1010,12 @@ if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
|||
endif ()
|
||||
if (HB_HAVE_GOBJECT)
|
||||
install(TARGETS harfbuzz-gobject
|
||||
EXPORT harfbuzz-gobject
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT runtime OPTIONAL
|
||||
)
|
||||
make_pkgconfig_pc_file("harfbuzz-gobject")
|
||||
if (HB_HAVE_INTROSPECTION)
|
||||
|
|
228
NEWS
228
NEWS
|
@ -1,12 +1,232 @@
|
|||
Overview of changes leading to 11.1.0
|
||||
Wednesdat, April 16, 2025
|
||||
====================================
|
||||
- Include bidi mirroring variants of the requested codepoints when subsetting.
|
||||
The new HB_SUBSET_FLAGS_NO_BIDI_CLOSURE can be used to disable this
|
||||
behaviour.
|
||||
- Various bug fixes.
|
||||
- Various build fixes and improvements.
|
||||
- Various test suite improvements.
|
||||
|
||||
New API:
|
||||
+HB_SUBSET_FLAGS_NO_BIDI_CLOSURE
|
||||
|
||||
|
||||
Overview of changes leading to 11.0.1
|
||||
Friday, April 4, 2025
|
||||
====================================
|
||||
- The change in version 10.3.0 to apply “trak” table tracking values to glyph
|
||||
advances directly has been reverted as it required every font functions
|
||||
implementation to handle it, which breaks existing custom font functions.
|
||||
Tracking is instead back to being applied during shaping.
|
||||
- When `directwrite` integration is enabled, we now link to `dwrite.dll`
|
||||
instead of dynamically loading it.
|
||||
- A new experimental APIs for getting raw “CFF” and “CFF2” CharStrings.
|
||||
- We now provide manpages for the various command line utilities. Building
|
||||
manpages requires “help2man” and will be skipped if it is not present.
|
||||
- The command line utilities now set different return value for different kinds
|
||||
of failures. Details are provided in the manpages.
|
||||
- Various fixes and improvements to `fontations` font functions.
|
||||
- All shaping operations using the `ot` shaper have become memory
|
||||
allocation-free.
|
||||
- Glyph extents returned by `hb-ot` and `hb-ft` font functions are now rounded
|
||||
in stead of flooring/ceiling them, which also matches what other font
|
||||
libraries do.
|
||||
- Fix “AAT” deleted glyph marks interfering with fallback mark positioning.
|
||||
- Glyph outlines emboldening have been moved out of `hb-ot` and `hb-ft` font
|
||||
functions to the HarfBuzz font layer, so that it works with any font
|
||||
functions implementation.
|
||||
- Fix our fallback C++11 atomics integration, which seems to not be widely
|
||||
used.
|
||||
- Various testing fixes and improvements.
|
||||
- Various subsetting fixes and improvements.
|
||||
- Various other fixes and improvements.
|
||||
|
||||
|
||||
Overview of changes leading to 11.0.0
|
||||
Monday, March 24, 2025
|
||||
====================================
|
||||
- There are three new font-functions implementations (integrations) in this
|
||||
release:
|
||||
* `hb-coretext` has gained one, calling into the CoreText library,
|
||||
* `hb-directwrite` has gained one, calling into the DirectWrite library.
|
||||
* `hb-fontations` has gained one, calling into the Skrifa Rust library.
|
||||
All three are mostly useful for performance and correctness testing, but some
|
||||
clients might find them useful.
|
||||
An API is added to use them from a single API by providing a backend name
|
||||
string:
|
||||
* `hb_font_set_funcs_using()`
|
||||
- Several new APIs are added, to load a font-face using different
|
||||
"face-loaders", and a single entry point to them all using a loader name
|
||||
string:
|
||||
* `hb_ft_face_create_from_file_or_fail()` and
|
||||
`hb_ft_face_create_from_blob_or_fail()`
|
||||
* `hb_coretext_face_create_from_file_or_fail()` and
|
||||
`hb_coretext_face_create_from_blob_or_fail()`
|
||||
* `hb_directwrite_face_create_from_file_or_fail()` and
|
||||
`hb_directwrite_face_create_from_blob_or_fail()`
|
||||
* `hb_face_create_from_file_or_fail_using()`
|
||||
- All drawing and painting operations using the default, `hb-ot` functions have
|
||||
become memory allocation-free.
|
||||
- Several performance optimizations have been implemented.
|
||||
- Application of the `trak` table during shaping has been improved.
|
||||
- The `directwrite` shaper now supports font variations, and correctly applies
|
||||
user features.
|
||||
- The `hb-directwrite` API and shaper has graduated from experimental.
|
||||
- Various bug fixes and other improvements.
|
||||
|
||||
- New API:
|
||||
+hb_malloc
|
||||
+hb_calloc
|
||||
+hb_realloc
|
||||
+hb_free
|
||||
+hb_face_list_loaders
|
||||
+hb_face_create_or_fail_using
|
||||
+hb_face_create_from_file_or_fail_using
|
||||
+hb_font_list_funcs
|
||||
+hb_font_set_funcs_using
|
||||
+hb_coretext_face_create_from_blob_or_fail
|
||||
+hb_directwrite_face_create_from_file_or_fail
|
||||
+hb_directwrite_face_create_from_blob_or_fail
|
||||
+hb_directwrite_font_create
|
||||
+hb_directwrite_font_get_dw_font_face
|
||||
+hb_directwrite_font_set_funcs
|
||||
+hb_fontations_font_set_funcs
|
||||
+hb_ft_face_create_from_blob_or_fail
|
||||
+hb_paint_push_font_transform
|
||||
+hb_paint_push_inverse_font_transform
|
||||
+HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES
|
||||
+HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE
|
||||
+HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES
|
||||
+HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS
|
||||
|
||||
- Deprecated API:
|
||||
+hb_directwrite_font_get_dw_font
|
||||
|
||||
|
||||
Overview of changes leading to 10.4.0
|
||||
Saturday, March 1, 2025
|
||||
====================================
|
||||
- Drawing glyphs using hb-draw API now avoids any “malloc” calls, which
|
||||
improves drawing performance by 10+%.
|
||||
- Add support new “GVAR” table fonts with more than 65535 glyphs. Support is
|
||||
currently behind a compilation flag and is disabled by default.
|
||||
- Some hb-directwrite and hb-ft APIs got renamed with more clear names and the
|
||||
old names are deprecated.
|
||||
- Various build and fuzzing fixes.
|
||||
|
||||
- New API:
|
||||
+hb_directwrite_face_get_dw_font_face()
|
||||
+hb_ft_font_get_ft_face()
|
||||
|
||||
- Deprecated API:
|
||||
+hb_directwrite_face_get_font_face()
|
||||
+hb_ft_font_get_face()
|
||||
|
||||
|
||||
Overview of changes leading to 10.3.0
|
||||
Thursday, February 11, 2025
|
||||
====================================
|
||||
- Vastly improved “AAT” shaping performance. LucidaGrande benchmark-shape
|
||||
before: 14.6ms after: 5.9ms.
|
||||
- Improved OpenType shaping performance (kerning / ligature), at the expense of
|
||||
~1kb per face allocated cache memory. Roboto-Regular benchmark-shape before:
|
||||
10.3ms after: 9.4ms.
|
||||
- Improved “COLRv1” benchmark-font paint performance. Before: 7.85ms after
|
||||
4.85ms.
|
||||
- Don’t apply glyph substitutions in “morx” table of a font with known broken
|
||||
“morx” table (AALMAGHRIBI.ttf font).
|
||||
- Update IANA and OT language registries.
|
||||
- Various documentation updates.
|
||||
- Various build improvements, and test speed-ups.
|
||||
- The “hb_face_reference_blob()” API now works for faces created with
|
||||
“hb_face_create_for_tables()” if the face sets “get_table_tags” callback.
|
||||
This constructs a new face blob from individual table blobs.
|
||||
- Various fixes to how “trak” table is handled to bring it closer to Core Text
|
||||
behaviour. Particularly, the tracking values for sizes not explicitly set in
|
||||
the table are now properly interpolated, and the tracking is applied to glyph
|
||||
advances when they are returned by ot-font functions, instead of applying
|
||||
them during shaping. The “trak” pseudo OpenType feature that could be used to
|
||||
disable “trak” table application have been dropped.
|
||||
- Core Text font functions now support non-BMP code points.
|
||||
- The drawing algorithm used by hb-draw for “glyf” table now match the
|
||||
algorithm used by FreeType and Core Text.
|
||||
- The “hb_coretext_font_create()” API now copy font variations from Core Text
|
||||
font to the created HarfBuzz font.
|
||||
- Add an API to get the feature tags enabled on a given shape-plan after
|
||||
executing it, which can be used to applications to show in the UI what
|
||||
features are applied by default (which can vary based on the font, the
|
||||
script, the language, and the direction set on the buffer).
|
||||
- Add APIs to created HarfBuzz font from DirectWrite font, and copy the font
|
||||
variations.
|
||||
|
||||
- New API:
|
||||
+hb_directwrite_font_create()
|
||||
+hb_directwrite_font_get_dw_font()
|
||||
+hb_ot_shape_plan_get_feature_tags()
|
||||
|
||||
|
||||
Overview of changes leading to 10.2.0
|
||||
Saturday, January 11, 2025
|
||||
====================================
|
||||
- Consider Unicode Variation Selectors when subsetting “cmap” table.
|
||||
- Guard hb_cairo_glyphs_from_buffer() against malformed UTF-8 strings.
|
||||
- Fix incorrect “COLR” v1 glyph scaling in hb-cairo.
|
||||
- Use locale-independent parsing of double numbers is “hb-subset” command line
|
||||
tool.
|
||||
- Fix incorrect zeroing of advance width of base glyphs in various “Courier New”
|
||||
font versions due to incorrect “GDEF” glyph classes.
|
||||
- Fix handling of long language codes with “HB_LEAN” configuration.
|
||||
- Update OpenType language system registry.
|
||||
- Allow all Myanmar tone marks (including visarga) in any order
|
||||
- Don’t insert U+25CC DOTTED CIRCLE before superscript/subscript digits
|
||||
- Handle Garay script as right to left script.
|
||||
- New API for serializing font tables and potentially repacking them in optimal
|
||||
way. This was a previously experimental-only API.
|
||||
- New API for converting font variation setting from and to strings.
|
||||
- Various build fixes
|
||||
- Various subsetter and instancer fixes.
|
||||
|
||||
- New API:
|
||||
+hb_subset_serialize_link_t
|
||||
+hb_subset_serialize_object_t
|
||||
+hb_subset_serialize_or_fail()
|
||||
+hb_subset_axis_range_from_string()
|
||||
+hb_subset_axis_range_to_string()
|
||||
|
||||
|
||||
Overview of changes leading to 10.1.0
|
||||
Tuesday, November 5, 2024
|
||||
====================================
|
||||
- Fix the sign of fallback vertical glyph advance (used when font has no
|
||||
vertical advance data).
|
||||
- Increase maximum “CFF” operands limit 20 times to support more complex fonts.
|
||||
- Add “--face-loader” option to command line utilities.
|
||||
- Support “COLR” v0 table in hb_font_get_glyph_extents().
|
||||
- Add support for font functions that use Core Text APIs, similar to FreeType
|
||||
font functions. This allows, for example, using drawing fonts that use the new
|
||||
(and undocumented) “hvgl” table.
|
||||
- Update IANA and OT language registries, as well ase USE data files.
|
||||
- Fix build with ICU 76.
|
||||
- Various compiler warnings and build fixes.
|
||||
- Various subsetter fixes.
|
||||
|
||||
- New API:
|
||||
+hb_face_create_or_fail()
|
||||
+hb_face_create_from_file_or_fail()
|
||||
+hb_coretext_face_create_from_file_or_fail()
|
||||
+hb_coretext_font_set_funcs()
|
||||
+hb_ft_face_create_from_file_or_fail()
|
||||
|
||||
Overview of changes leading to 10.0.1
|
||||
Tuesday, Sep 24, 2024
|
||||
Tuesday, September 24, 2024
|
||||
====================================
|
||||
- Relax sanitization checks for “morx” subtables to fix broken AAT shaping of
|
||||
macOS 15.0 version of GeezaPro.
|
||||
|
||||
|
||||
Overview of changes leading to 10.0.0
|
||||
Monday, Sep 23, 2024
|
||||
Monday, September 23, 2024
|
||||
====================================
|
||||
- Unicode 16.0.0 support.
|
||||
- Various documentation fixes.
|
||||
|
@ -131,10 +351,10 @@ Saturday, November 11, 2023
|
|||
tools. Old option is kept as an alias.
|
||||
|
||||
- New API:
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION
|
||||
+HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION
|
||||
|
||||
- Deprecated API:
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION
|
||||
+HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION
|
||||
|
||||
Overview of changes leading to 8.2.2
|
||||
Wednesday, October 18, 2023
|
||||
|
|
73
README.md
73
README.md
|
@ -1,9 +1,9 @@
|
|||
[](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)
|
||||
[](https://github.com/harfbuzz/harfbuzz/actions/workflows/linux-ci.yml)
|
||||
[](https://github.com/harfbuzz/harfbuzz/actions/workflows/macos-ci.yml)
|
||||
[](https://github.com/harfbuzz/harfbuzz/actions/workflows/msvc-ci.yml)
|
||||
[](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main)
|
||||
[](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
|
||||
[](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#harfbuzz)
|
||||
[](https://scan.coverity.com/projects/harfbuzz)
|
||||
[](https://app.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
||||
[](https://codecov.io/gh/harfbuzz/harfbuzz)
|
||||
[](https://repology.org/project/harfbuzz/versions)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz)
|
||||
|
||||
|
@ -35,13 +35,20 @@ will also find Win32/Win64 binary bundles that include `libharfbuzz` DLL,
|
|||
`hb-view.exe`, `hb-shape.exe`, and all dependencies.
|
||||
|
||||
The canonical source tree is available on [github][4].
|
||||
Both development and user support discussion around HarfBuzz happens on
|
||||
[github][4] as well.
|
||||
|
||||
The API that comes with `hb.h` will not change incompatibly. Other, peripheral,
|
||||
headers are more likely to go through minor modifications, but again, we do our
|
||||
best to never change API in an incompatible way. We will never break the ABI.
|
||||
|
||||
If you are not sure whether Pango or HarfBuzz is right for you, read [Pango vs
|
||||
HarfBuzz][5].
|
||||
The API and ABI are stable even across major version number jumps. In fact,
|
||||
current HarfBuzz is API/ABI compatible all the way back to the 0.9.x series.
|
||||
If one day we need to break the API/ABI, that would be called a new a library.
|
||||
|
||||
As such, we bump the major version number only when we add major new features,
|
||||
the minor version when there is new API, and the micro version when there
|
||||
are bug fixes.
|
||||
|
||||
## Development
|
||||
|
||||
|
@ -51,24 +58,38 @@ For custom configurations, see [CONFIG.md](CONFIG.md).
|
|||
|
||||
For testing and profiling, see [TESTING.md](TESTING.md).
|
||||
|
||||
For using with Python, see [README.python.md](README.python.md). There is also [uharfbuzz](https://github.com/harfbuzz/uharfbuzz).
|
||||
|
||||
For cross-compiling to Windows from Linux or macOS, see [README.mingw.md](README.mingw.md).
|
||||
|
||||
To report bugs or submit patches please use [github][4] issues and pull-requests.
|
||||
|
||||
### Developer documents
|
||||
|
||||
To get a better idea of where HarfBuzz stands in the text rendering stack you
|
||||
may want to read [State of Text Rendering 2024][6].
|
||||
Here are a few presentation slides about HarfBuzz at the
|
||||
Internationalization and Unicode Conference over the years:
|
||||
|
||||
* November 2014, [Unicode, OpenType, and HarfBuzz: Closing the Circle][7],
|
||||
* October 2012, [HarfBuzz, The Free and Open Text Shaping Engine][8],
|
||||
* October 2009, [HarfBuzz: the Free and Open Shaping Engine][9].
|
||||
- 2014 – [Unicode, OpenType, and HarfBuzz: Closing the Circle][7]
|
||||
- 2012 – [HarfBuzz, The Free and Open Text Shaping Engine][8]
|
||||
- 2016 – [Ten Years of HarfBuzz][20]
|
||||
- 2009 – [HarfBuzz: the Free and Open Shaping Engine][9]
|
||||
|
||||
Both development and user support discussion around HarfBuzz happens on the
|
||||
[github][4].
|
||||
More presentations and papers are available on [behdad][11]'s website.
|
||||
In particular, the following _studies_ are relevant to HarfBuzz development:
|
||||
|
||||
To report bugs or submit patches please use [github][4] issues and
|
||||
pull-requests.
|
||||
- 2025 – [Subsetting][21]
|
||||
- 2025 – [Caching][12]
|
||||
- 2025 – [`hb-decycler`][13]
|
||||
- 2022 – [`hb-iter`][14]
|
||||
- 2022 – [A C library written in C++][15]
|
||||
- 2022 – [The case of the slow `hb-ft` `>h_advance` function][18]
|
||||
- 2022 – [PackTab: A static integer table packer][16]
|
||||
- 2020 – [HarfBuzz OT+AAT "Unishaper"][19]
|
||||
- 2014 – [Building the Indic Shaper][17]
|
||||
- 2012 – [Memory Consumption][10]
|
||||
|
||||
For a comparison of old vs new HarfBuzz memory consumption see [this][10].
|
||||
|
||||
<!--See past and upcoming [HarfBuzz Hackfests](https://freedesktop.org/wiki/Software/HarfBuzz/Hackfests/)!-->
|
||||
|
||||
## Name
|
||||
|
||||
|
@ -85,6 +106,8 @@ transliterated using the Latin script. It also means "talkative" or
|
|||
> TrueType that adds support for complex script rendering, and HarfBuzz is an
|
||||
> implementation of OpenType complex text shaping.
|
||||
|
||||
## Distribution
|
||||
|
||||
<details>
|
||||
<summary>Packaging status of HarfBuzz</summary>
|
||||
|
||||
|
@ -96,9 +119,19 @@ transliterated using the Latin script. It also means "talkative" or
|
|||
[2]: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html
|
||||
[3]: https://github.com/harfbuzz/harfbuzz/releases
|
||||
[4]: https://github.com/harfbuzz/harfbuzz
|
||||
[5]: http://mces.blogspot.com/2009/11/pango-vs-harfbuzz.html
|
||||
[6]: http://behdad.org/text2024
|
||||
[7]: https://goo.gl/FSIQuC
|
||||
[8]: https://goo.gl/2wSRu
|
||||
[7]: https://docs.google.com/presentation/d/1x97pfbB1gbD53Yhz6-_yBUozQMVJ_5yMqqR_D-R7b7I/preview
|
||||
[8]: https://docs.google.com/presentation/d/1ySTZaXP5XKFg0OpmHZM00v5b17GSr3ojnzJekl4U8qI/preview
|
||||
[9]: http://behdad.org/download/Presentations/slippy/harfbuzz_slides.pdf
|
||||
[10]: https://goo.gl/woyty
|
||||
[10]: https://docs.google.com/document/d/12jfNpQJzeVIAxoUSpk7KziyINAa1msbGliyXqguS86M/preview
|
||||
[11]: https://behdad.org/
|
||||
[12]: https://docs.google.com/document/d/1_VgObf6Je0J8byMLsi7HCQHnKo2emGnx_ib_sHo-bt4/preview
|
||||
[13]: https://docs.google.com/document/d/1Y-u08l9YhObRVObETZt1k8f_5lQdOix9TRH3zEXaoAw/preview
|
||||
[14]: https://docs.google.com/document/d/1o-xvxCbgMe9JYFHLVnPjk01ZY_8Cj0vB9-KTI1d0nyk/preview
|
||||
[15]: https://docs.google.com/document/d/18hI56KJpvXtwWbc9QSaz9zzhJwIMnrJ-zkAaKS-W-8k/preview
|
||||
[16]: https://docs.google.com/document/d/1Xq3owVt61HVkJqbLFHl73il6pcTy6PdPJJ7bSouQiQw/preview
|
||||
[17]: https://docs.google.com/document/d/1wMPwVNBvsIriamcyBO5aNs7Cdr8lmbwLJ8GmZBAswF4/preview
|
||||
[18]: https://docs.google.com/document/d/1wskYbA-czBt57oH9gEuGf3sWbTx7bfOiEIcDs36-heo/preview
|
||||
[19]: https://prezi.com/view/THNPJGFVDUCWoM20syev/
|
||||
[20]: https://behdad.org/doc/harfbuzz10years-slides.pdf
|
||||
[21]: https://docs.google.com/document/d/1_vZrt97OorJ0jA1YzJ29LRcGr3YGrNJANdOABjVZGEs/preview
|
||||
|
|
216
README.mingw.md
Normal file
216
README.mingw.md
Normal file
|
@ -0,0 +1,216 @@
|
|||
Most HarfBuzz developers do so on Linux or macOS. However, HarfBuzz is a
|
||||
cross-platform library and it is important to ensure that it works on Windows
|
||||
as well. In particular, we use this workflow to develop and test the HarfBuzz
|
||||
Uniscribe shaper and DirectWrite shaper and font backend, all from Linux or
|
||||
macOS.
|
||||
|
||||
This document provides instructions for cross-compiling HarfBuzz on Linux or
|
||||
macOS, for Windows, using the MinGW toolchain, and running tests and utilties
|
||||
under Wine.
|
||||
|
||||
We then discuss using native Windows Uniscribe or DirectWrite DLLs, which
|
||||
allows you to test HarfBuzz's shaping against the Microsoft shaping engines
|
||||
instead of those provided by Wine.
|
||||
|
||||
This document assumes that you are familiar with building HarfBuzz on Linux or
|
||||
macOS.
|
||||
|
||||
You can build for 32bit or 64bit Windows. If your intention is to use a native
|
||||
Uniscribe usp10.dll from Windows 7 or before, you would need to build for 32bit.
|
||||
If you want to use a native DirectWrite DLL from Windows 10 or later, you would
|
||||
need to build for 64bit.
|
||||
|
||||
We suggest you read to the end of this document before starting, as it provides
|
||||
a few different ways to build and test HarfBuzz for Windows.
|
||||
|
||||
1. Install Wine.
|
||||
|
||||
- Fedora: `dnf install wine`.
|
||||
- Ubuntu, 32bit: `apt install wine wine32`.
|
||||
- Ubuntu, 64bit: `apt install wine wine64`.
|
||||
- Mac: `brew install wine-stable`.
|
||||
|
||||
Note that to run Wine on Apple silicon systems, you need the Apple Rosetta translator.
|
||||
Follow the instructions you got from brew. This should do it:
|
||||
|
||||
- `softwareupdate --install-rosetta --agree-to-license`
|
||||
|
||||
2. Install the `mingw-w64` cross-compiler.
|
||||
|
||||
- Fedora, 32bit: `dnf install mingw32-gcc-c++`
|
||||
- Fedora, 64bit: `dnf install mingw64-gcc-c++`
|
||||
- Ubuntu, 32bit: `apt install g++-mingw-w64-i686`
|
||||
- Ubuntu, 64bit: `apt install g++-mingw-w64-x86-64`
|
||||
- Mac: `brew install mingw-w64`
|
||||
|
||||
3. Install dependencies.
|
||||
|
||||
First, make sure you do not have the mingw32 harfbuzz package, as that will
|
||||
override our own build with older `meson`:
|
||||
|
||||
- Fedora, 32bit: `dnf remove mingw32-harfbuzz`
|
||||
- Fedora, 64bit: `dnf remove mingw64-harfbuzz`
|
||||
|
||||
Then install the actual dependencies:
|
||||
|
||||
- Fedora, 32bit: `dnf install mingw32-glib2 mingw32-cairo mingw32-freetype`
|
||||
- Fedora, 64bit: `dnf install mingw64-glib2 mingw64-cairo mingw64-freetype`
|
||||
|
||||
If you cannot find these packages for your distribution, or you are on macOS,
|
||||
you can skip to the next step, as meson will automatically download and build
|
||||
the dependencies for you.
|
||||
|
||||
4. If you are familiar with `meson`, you can use the cross-compile files we
|
||||
provide to find your way around. But we do not recommend this way. Read until
|
||||
the end of this section before deciding which one to use.
|
||||
|
||||
- 32bit: `meson --cross-file=.ci/win32-cross-file.txt build-win -Dglib-enabled -Dcairo=enabled -Dgdi=enabled -Ddirectwrite=enabled`
|
||||
- 64bit: `meson --cross-file=.ci/win64-cross-file.txt build-win -Dglib-enabled -Dcairo=enabled -Dgdi=enabled -Ddirectwrite=enabled`
|
||||
|
||||
In which case, you will proceed to run `ninja` as usual to build:
|
||||
|
||||
- `ninja -C build-win`
|
||||
|
||||
Or you can simply invoke the scripts we provide for our Continuous Integration
|
||||
system, to configure and build HarfBuzz for you. This is the easiest way to
|
||||
build HarfBuzz for Windows and how we build our Windows binaries:
|
||||
|
||||
- 32bit: `./.ci/build-win.sh 32 && ln -s build-win32 build-win`
|
||||
- 64bit: `./.ci/build-win.sh 64 && ln -s build-win64 build-win`
|
||||
|
||||
This might take a while, since, if you do not have the dependencies installed,
|
||||
meson will download and build them for you.
|
||||
|
||||
5. If everything succeeds, you should have the `hb-shape.exe`, `hb-view.exe`,
|
||||
`hb-subset.exe`, and `hb-info.exe` executables in `build-win/util`.
|
||||
|
||||
6. Configure your wine to find system mingw libraries. While there, set it also
|
||||
to find the built HarfBuzz DLLs:
|
||||
|
||||
- Fedora, 32bit: `export WINEPATH="$HOME/harfbuzz/build-win/src;/usr/i686-w64-mingw32/sys-root/mingw/bin"`
|
||||
- Fedora, 64bit: `export WINEPATH="$HOME/harfbuzz/build-win/src;/usr/x86_64-w64-mingw32/sys-root/mingw/bin"`
|
||||
- Other systems: `export WINEPATH="$HOME/harfbuzz/build-win/src"`
|
||||
|
||||
Adjust for the path where you have built HarfBuzz. You might want to add this
|
||||
to your `.bashrc` or `.zshrc` file.
|
||||
|
||||
Alternatively, can skip this step if commands are run through the `meson devenv`
|
||||
command, which we will introduce in the next step. I personally find it more
|
||||
convenient to set the `WINEPATH` variable, as it allows me to run the executables
|
||||
directly from the shell.
|
||||
|
||||
7. Run the `hb-shape` executable under Wine:
|
||||
|
||||
- `wine build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test`
|
||||
|
||||
Or using `meson devenv to do the same:
|
||||
|
||||
- `meson devenv -C build-win util/hb-shape.exe $PWD/perf/fonts/Roboto-Regular.ttf Test`
|
||||
|
||||
You probably will get lots of Wine warnings, but if all works fine, you
|
||||
should see:
|
||||
```
|
||||
[gid57=0+1123|gid74=1+1086|gid88=2+1057|gid89=3+670]
|
||||
```
|
||||
|
||||
You can make Wine less verbose, without hiding all errors, by setting:
|
||||
|
||||
- `export WINEDEBUG=fixme-all,warn-all,err-plugplay,err-seh,err-rpc,err-ntoskrnl,err-winediag,err-systray,err-hid`
|
||||
|
||||
Add this to your `.bashrc` or `.zshrc` file as well.
|
||||
|
||||
Next, let's try some non-Latin text. Unfortunately, the command-line parsing of
|
||||
our cross-compiled glib is not quite Unicode-aware, at least when run under
|
||||
Wine. So you will need to find some other way to feed Unicode text to the
|
||||
shaper. There are three different ways you can try:
|
||||
|
||||
- `echo حرف | wine build-win/util/hb-shape.exe perf/fonts/Amiri-Regular.ttf`
|
||||
- `wine build-win/util/hb-shape.exe perf/fonts/Amiri-Regular.ttf -u 062D,0631,0641`
|
||||
- `wine build-win/util/hb-shape.exe perf/fonts/Amiri-Regular.ttf --text-file harf.txt`
|
||||
|
||||
To get the Unicode codepoints for a string, you can use the `hb-unicode-decode`
|
||||
utility:
|
||||
```
|
||||
$ test/shape/hb-unicode-decode حرف
|
||||
U+062D,U+0631,U+0641
|
||||
```
|
||||
|
||||
8. Next, let's try the `hb-view` utility. By default, `hb-view` outputs ANSI text,
|
||||
which Wine will not display correctly. You can use the `-o` option to redirect the
|
||||
output to a file, or just redirect the output using the shell, which will produce
|
||||
a PNG file.
|
||||
|
||||
- `wine build-win/util/hb-view.exe perf/fonts/Roboto-Regular.ttf Test > test.png`
|
||||
|
||||
7. As noted, if your Linux has `binfmt_misc` enabled, you can run the executables
|
||||
directly. If not, you can modify the cross-file to use the `exe_wrapper` option as
|
||||
specified before.
|
||||
|
||||
- `build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test`
|
||||
|
||||
If that does not work, you can use the `wine` command as shown above.
|
||||
|
||||
10. You can try running the test suite. If on Linux with `binfmt_misc` enabled, you
|
||||
can run the tests directly:
|
||||
|
||||
- `ninja -C build-win test`
|
||||
|
||||
For other situations, use `meson devenv`:
|
||||
|
||||
- `meson devenv -C build-win ninja test`
|
||||
|
||||
This might take a couple of minutes to run. Running under Wine is expensive, so
|
||||
be patient.
|
||||
|
||||
If all goes well, tests should run. If all is well, you should probably see about
|
||||
400 tests pass, some skipped, but none failing.
|
||||
|
||||
11. In the above testing situation, the `directwrite` test will be disabled
|
||||
automatically upon detection of running under Wine. The reason the `directwrite`
|
||||
test would otherwise fails is that we are running against the Wine-provided
|
||||
DirectWrite DLL, which is an incomplete reimplementation of the DirectWrite API
|
||||
by Wine, and not the real thing.
|
||||
|
||||
If you want to test the Uniscribe or DirectWrite shapers against the real
|
||||
Uniscribe / DirectWrite, you can follow the instructions below.
|
||||
|
||||
11. Old Uniscribe: Assuming a 32bit build for now.
|
||||
|
||||
Bring a 32bit version of `usp10.dll` for yourself from
|
||||
`C:\Windows\SysWOW64\usp10.dll` of your 64bit Windows installation,
|
||||
or `C:\Windows\System32\usp10.dll` for 32bit Windows installation.
|
||||
|
||||
You want one from Windows 7 or earlier. One that is not just a proxy for
|
||||
`TextShaping.dll`. Rule of thumb, your `usp10.dll` should have a size more
|
||||
than 500kb.
|
||||
|
||||
Put the file in `~/.wine/drive_c/windows/syswow64/` so wine can find it.
|
||||
|
||||
You can now tell wine to use the native `usp10.dll`:
|
||||
|
||||
- `export WINEDLLOVERRIDES="usp10=n"`
|
||||
- `wine build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test --shaper=uniscribe`
|
||||
|
||||
12. DirectWrite and new Uniscribe: You can use the same method to test the
|
||||
DirectWrite shaper against the native DirectWrite DLL. Try with a 64bit build
|
||||
this time.
|
||||
|
||||
Bring `TextShaping.dll`, `DWrite.dll`, and `usp10.dll` from your 64bit Windows
|
||||
installation (`C:\Windows\System32`) to `~/.wine/drive_c/windows/system32/`.
|
||||
|
||||
You want the ones from Windows 10 or later. You might have some luck downloading
|
||||
them from the internet, but be careful with the source. I had success with the
|
||||
DLLs from [https://dllme.com](dllme.com), but I cannot vouch for the site.
|
||||
|
||||
You can now tell wine to use the native DirectWrite:
|
||||
|
||||
- `export WINEDLLOVERRIDES="textshaping,dwrite,usp10=n"`
|
||||
- `wine build-win/util/hb-shape.exe perf/fonts/Roboto-Regular.ttf Test --shaper=directwrite`
|
||||
|
||||
If all works well, you should be able to rerun the tests and see all pass this time.
|
||||
|
||||
13. For some old instructions on how to test HarfBuzz's native Indic shaper against
|
||||
Uniscribe, see: https://github.com/harfbuzz/harfbuzz/issues/3671
|
||||
|
||||
14. That's it! If you made it this far, you are now able to develop and test
|
||||
HarfBuzz on Windows, from Linux or macOS. Enjoy!
|
22
RELEASING.md
22
RELEASING.md
|
@ -3,21 +3,21 @@
|
|||
- [ ] Open gitk and review changes since last release.
|
||||
|
||||
- [ ] Print all public API changes:
|
||||
`git diff $(git describe | sed 's/-.*//').. src/*.h`
|
||||
`git diff $(git describe | sed 's/-.*//').. src/*.h`
|
||||
|
||||
- [ ] Document them in NEWS.
|
||||
All API and API semantic changes should be clearly marked as API additions, API changes, or API deletions.
|
||||
All API and API semantic changes should be clearly marked as API additions, API changes, or API deletions.
|
||||
|
||||
- [ ] Document deprecations.
|
||||
Ensure all new API / deprecations are in listed correctly in docs/harfbuzz-sections.txt.
|
||||
If release added new API, add entry for new API index at the end of docs/harfbuzz-docs.xml.
|
||||
Ensure all new API / deprecations are listed correctly in docs/harfbuzz-sections.txt.
|
||||
If release added new API, add entry for new API index at the end of docs/harfbuzz-docs.xml.
|
||||
|
||||
If there's a backward-incompatible API change (including deletions for API used anywhere), that's a release blocker.
|
||||
Do NOT release.
|
||||
If there's a backward-incompatible API change (including deletions for API used anywhere), that's a release blocker.
|
||||
Do NOT release.
|
||||
|
||||
- [ ] Based on severity of changes, decide whether it's a minor or micro release number bump.
|
||||
|
||||
- [ ] Search for 'XSince: REPLACEME' on the repository and replace it with the chosen version for the release, e.g. 'Since: 1.4.7'.
|
||||
- [ ] Search for 'REPLACEME' on the repository and replace it with the chosen version for the release, e.g. 'Since: 1.4.7'.
|
||||
|
||||
- [ ] Make sure you have correct date and new version at the top of NEWS file.
|
||||
|
||||
|
@ -26,12 +26,16 @@
|
|||
- [ ] Do a `meson test -Cbuild` so it both checks the tests and updates hb-version.h (use `git diff` to see if is really updated).
|
||||
|
||||
- [ ] Commit NEWS, meson.build, and src/hb-version.h, as well as any REPLACEME changes you made.
|
||||
The commit message is simply the release number, e. g. "1.4.7"
|
||||
The commit message is simply the release number, e. g. "1.4.7"
|
||||
|
||||
- [ ] Do a `meson dist -Cbuild` that runs the tests against the latest committed changes.
|
||||
If doesn't pass, something fishy is going on, reset the repo and start over.
|
||||
If it does not pass, something fishy is going on, reset the repo and start over.
|
||||
|
||||
- [ ] Tag the release and sign it: e.g. `git tag -s 1.4.7 -m 1.4.7`.
|
||||
Enter your GPG password.
|
||||
|
||||
- [ ] Push the commit and tag out: `git push --follow-tags`.
|
||||
|
||||
- [ ] There should be a GitHub release automatically created.
|
||||
When it does, go to that release page and add description.
|
||||
The description should be the NEWS file additions.
|
||||
|
|
|
@ -90,15 +90,16 @@
|
|||
|
||||
<chapter id="integration-api">
|
||||
<title>Integration API</title>
|
||||
<xi:include href="xml/hb-cairo.xml"/>
|
||||
<xi:include href="xml/hb-coretext.xml"/>
|
||||
<xi:include href="xml/hb-directwrite.xml"/>
|
||||
<xi:include href="xml/hb-ft.xml"/>
|
||||
<xi:include href="xml/hb-fontations.xml"/>
|
||||
<xi:include href="xml/hb-gdi.xml"/>
|
||||
<xi:include href="xml/hb-glib.xml"/>
|
||||
<xi:include href="xml/hb-graphite2.xml"/>
|
||||
<xi:include href="xml/hb-icu.xml"/>
|
||||
<xi:include href="xml/hb-uniscribe.xml"/>
|
||||
<xi:include href="xml/hb-gdi.xml"/>
|
||||
<xi:include href="xml/hb-directwrite.xml"/>
|
||||
<xi:include href="xml/hb-cairo.xml"/>
|
||||
</chapter>
|
||||
|
||||
<chapter id="style-api">
|
||||
|
@ -120,6 +121,11 @@
|
|||
<index id="api-index-full"><title>API Index</title><xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="deprecated-api-index"><title>Index of deprecated API</title><xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include></index>
|
||||
|
||||
<index id="api-index-11-0-0"><title>Index of new symbols in 11.0.0</title><xi:include href="xml/api-index-11.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-10-4-0"><title>Index of new symbols in 10.4.0</title><xi:include href="xml/api-index-10.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-10-3-0"><title>Index of new symbols in 10.3.0</title><xi:include href="xml/api-index-10.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-10-2-0"><title>Index of new symbols in 10.2.0</title><xi:include href="xml/api-index-10.2.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-10-1-0"><title>Index of new symbols in 10.1.0</title><xi:include href="xml/api-index-10.1.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-10-0-0"><title>Index of new symbols in 10.0.0</title><xi:include href="xml/api-index-10.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-8-5-0"><title>Index of new symbols in 8.5.0</title><xi:include href="xml/api-index-8.5.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-8-4-0"><title>Index of new symbols in 8.4.0</title><xi:include href="xml/api-index-8.4.0.xml"><xi:fallback /></xi:include></index>
|
||||
|
|
|
@ -114,6 +114,9 @@ hb_glyph_position_t
|
|||
hb_buffer_content_type_t
|
||||
hb_buffer_flags_t
|
||||
hb_buffer_cluster_level_t
|
||||
HB_BUFFER_CLUSTER_LEVEL_IS_CHARACTERS
|
||||
HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES
|
||||
HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE
|
||||
hb_segment_properties_t
|
||||
hb_buffer_serialize_format_t
|
||||
hb_buffer_serialize_flags_t
|
||||
|
@ -181,6 +184,10 @@ uint8_t
|
|||
HB_EXTERN
|
||||
HB_DEPRECATED
|
||||
HB_DEPRECATED_FOR
|
||||
hb_malloc
|
||||
hb_calloc
|
||||
hb_realloc
|
||||
hb_free
|
||||
<SUBSECTION Private>
|
||||
HB_H_IN
|
||||
HB_OT_H_IN
|
||||
|
@ -285,6 +292,8 @@ hb_paint_custom_palette_color_func_t
|
|||
hb_paint_funcs_set_custom_palette_color_func
|
||||
|
||||
hb_paint_push_transform
|
||||
hb_paint_push_font_transform
|
||||
hb_paint_push_inverse_font_transform
|
||||
hb_paint_pop_transform
|
||||
hb_paint_color_glyph
|
||||
hb_paint_push_clip_glyph
|
||||
|
@ -332,6 +341,10 @@ hb_font_funcs_set_glyph_shape_func
|
|||
hb_font_get_glyph_v_kerning
|
||||
hb_font_get_glyph_v_kerning_func_t
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION
|
||||
hb_directwrite_face_get_font_face
|
||||
hb_directwrite_font_get_dw_font
|
||||
hb_ft_font_get_face
|
||||
hb_graphite2_font_get_gr_font
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -340,15 +353,23 @@ HB_CORETEXT_TAG_KERX
|
|||
HB_CORETEXT_TAG_MORT
|
||||
HB_CORETEXT_TAG_MORX
|
||||
hb_coretext_face_create
|
||||
hb_coretext_face_create_from_file_or_fail
|
||||
hb_coretext_face_create_from_blob_or_fail
|
||||
hb_coretext_font_create
|
||||
hb_coretext_face_get_cg_font
|
||||
hb_coretext_font_get_ct_font
|
||||
hb_coretext_font_set_funcs
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-directwrite</FILE>
|
||||
hb_directwrite_face_create
|
||||
hb_directwrite_face_get_font_face
|
||||
hb_directwrite_face_create_from_file_or_fail
|
||||
hb_directwrite_face_create_from_blob_or_fail
|
||||
hb_directwrite_face_get_dw_font_face
|
||||
hb_directwrite_font_create
|
||||
hb_directwrite_font_get_dw_font_face
|
||||
hb_directwrite_font_set_funcs
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -356,6 +377,11 @@ hb_directwrite_face_get_font_face
|
|||
hb_face_count
|
||||
hb_face_t
|
||||
hb_face_create
|
||||
hb_face_create_or_fail
|
||||
hb_face_create_or_fail_using
|
||||
hb_face_create_from_file_or_fail
|
||||
hb_face_create_from_file_or_fail_using
|
||||
hb_face_list_loaders
|
||||
hb_reference_table_func_t
|
||||
hb_face_create_for_tables
|
||||
hb_face_get_empty
|
||||
|
@ -449,6 +475,8 @@ hb_font_get_serial
|
|||
hb_font_changed
|
||||
hb_font_set_funcs
|
||||
hb_font_set_funcs_data
|
||||
hb_font_set_funcs_using
|
||||
hb_font_list_funcs
|
||||
hb_font_subtract_glyph_origin_for_direction
|
||||
hb_font_funcs_create
|
||||
hb_font_funcs_get_empty
|
||||
|
@ -508,15 +536,23 @@ hb_font_extents_t
|
|||
hb_glyph_extents_t
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-fontations</FILE>
|
||||
hb_fontations_font_set_funcs
|
||||
</SECTION>
|
||||
|
||||
|
||||
<SECTION>
|
||||
<FILE>hb-ft</FILE>
|
||||
hb_ft_face_create
|
||||
hb_ft_face_create_cached
|
||||
hb_ft_face_create_referenced
|
||||
hb_ft_face_create_from_file_or_fail
|
||||
hb_ft_face_create_from_blob_or_fail
|
||||
hb_ft_font_create
|
||||
hb_ft_font_create_referenced
|
||||
hb_ft_font_changed
|
||||
hb_ft_font_get_face
|
||||
hb_ft_font_get_ft_face
|
||||
hb_ft_font_lock_face
|
||||
hb_ft_font_unlock_face
|
||||
hb_ft_font_set_load_flags
|
||||
|
@ -542,7 +578,6 @@ hb_glib_blob_create
|
|||
<FILE>hb-graphite2</FILE>
|
||||
HB_GRAPHITE2_TAG_SILF
|
||||
hb_graphite2_face_get_gr_face
|
||||
hb_graphite2_font_get_gr_font
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -669,6 +704,7 @@ hb_ot_layout_table_get_script_tags
|
|||
hb_ot_layout_table_get_lookup_count
|
||||
hb_ot_layout_table_select_script
|
||||
hb_ot_shape_plan_collect_lookups
|
||||
hb_ot_shape_plan_get_feature_tags
|
||||
hb_ot_layout_language_get_required_feature_index
|
||||
HB_OT_MAX_TAGS_PER_LANGUAGE
|
||||
HB_OT_MAX_TAGS_PER_SCRIPT
|
||||
|
@ -796,8 +832,10 @@ hb_set_t
|
|||
<FILE>hb-shape</FILE>
|
||||
hb_shape
|
||||
hb_shape_full
|
||||
hb_shape_justify
|
||||
hb_shape_list_shapers
|
||||
<SUBSECTION Private>
|
||||
hb_shape_justify
|
||||
</SUBSECTION>
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -895,6 +933,8 @@ hb_subset_input_pin_axis_location
|
|||
hb_subset_input_pin_axis_to_default
|
||||
hb_subset_input_get_axis_range
|
||||
hb_subset_input_set_axis_range
|
||||
hb_subset_axis_range_from_string
|
||||
hb_subset_axis_range_to_string
|
||||
hb_subset_or_fail
|
||||
hb_subset_plan_create_or_fail
|
||||
hb_subset_plan_reference
|
||||
|
@ -910,11 +950,15 @@ hb_subset_flags_t
|
|||
hb_subset_input_t
|
||||
hb_subset_sets_t
|
||||
hb_subset_plan_t
|
||||
hb_subset_serialize_link_t
|
||||
hb_subset_serialize_object_t
|
||||
hb_subset_serialize_or_fail
|
||||
<SUBSECTION Private>
|
||||
hb_link_t
|
||||
hb_object_t
|
||||
hb_subset_repack_or_fail
|
||||
hb_subset_input_override_name_table
|
||||
hb_subset_cff_get_charstring_data
|
||||
hb_subset_cff_get_charstrings_index
|
||||
hb_subset_cff2_get_charstring_data
|
||||
hb_subset_cff2_get_charstrings_index
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
|
|
@ -518,18 +518,6 @@
|
|||
<type>hb_font_t</type> font object. Core Text uses this value to
|
||||
implement optical scaling.
|
||||
</para>
|
||||
<para>
|
||||
When integrating your client code with Core Text, it is
|
||||
important to recognize that Core Text <literal>points</literal>
|
||||
are not typographic points (standardized at 72 per inch) as the
|
||||
term is used elsewhere in OpenType. Instead, Core Text points
|
||||
are CSS points, which are standardized at 96 per inch.
|
||||
</para>
|
||||
<para>
|
||||
HarfBuzz's font functions take this distinction into account,
|
||||
but it can be an easy detail to miss in cross-platform
|
||||
code.
|
||||
</para>
|
||||
<para>
|
||||
As a final note, you may notice a reference to an optional
|
||||
<literal>coretext</literal> shaper back-end in the <xref
|
||||
|
|
132
meson.build
132
meson.build
|
@ -1,11 +1,12 @@
|
|||
project('harfbuzz', 'c', 'cpp',
|
||||
meson_version: '>= 0.55.0',
|
||||
version: '10.0.1',
|
||||
project('harfbuzz', ['c', 'cpp'],
|
||||
meson_version: '>= 0.60.0',
|
||||
version: '11.1.0',
|
||||
default_options: [
|
||||
'cpp_eh=none', # Just to support msvc, we are passing -fno-exceptions also anyway
|
||||
# 'cpp_rtti=false', # Do NOT enable, wraps inherit it and ICU needs RTTI
|
||||
'cpp_std=c++11',
|
||||
'wrap_mode=nofallback', # Use --wrap-mode=default to revert, https://github.com/harfbuzz/harfbuzz/pull/2548
|
||||
'buildtype=debugoptimized',
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -31,11 +32,16 @@ pkgmod = import('pkgconfig')
|
|||
cpp = meson.get_compiler('cpp')
|
||||
null_dep = dependency('', required: false)
|
||||
|
||||
|
||||
# Includes Microsoft Clang compiler with GNU arguments, see
|
||||
# https://github.com/harfbuzz/harfbuzz/pull/4394
|
||||
cpp_is_microsoft_compiler = host_machine.system() == 'windows' and cpp.get_define('_MSC_FULL_VER') != ''
|
||||
|
||||
# Only perform these checks if cpp_std is c++11 as setting -std directly
|
||||
# produces a warning from meson.
|
||||
if get_option('cpp_std') == 'c++11'
|
||||
# Enforce C++14 requirement for MSVC STL
|
||||
if cpp.get_id() == 'clang' and cpp.get_define('_MSC_FULL_VER') != ''
|
||||
if cpp.get_id() == 'clang' and cpp_is_microsoft_compiler
|
||||
add_project_arguments('-std=c++14', language: 'cpp')
|
||||
elif cpp.get_id() == 'clang-cl'
|
||||
# Clang-cl produces a warning when using -std=c++14, but not when using /std:c++14
|
||||
|
@ -102,44 +108,36 @@ check_funcs = [
|
|||
|
||||
m_dep = cpp.find_library('m', required: false)
|
||||
|
||||
if meson.version().version_compare('>=0.60.0')
|
||||
# Painful hack to handle multiple dependencies but also respect options
|
||||
if get_option('freetype').disabled()
|
||||
freetype_dep = dependency('', required: false)
|
||||
else
|
||||
# Sadly, FreeType's versioning schemes are different between pkg-config and CMake
|
||||
# pkg-config: freetype2, cmake: Freetype
|
||||
|
||||
# Try pkg-config name
|
||||
freetype_dep = dependency('freetype2',
|
||||
version: freetype_min_version,
|
||||
method: 'pkg-config',
|
||||
required: false,
|
||||
allow_fallback: false)
|
||||
if not freetype_dep.found()
|
||||
freetype_dep = dependency('FreeType',
|
||||
# Try cmake name
|
||||
freetype_dep = dependency('Freetype',
|
||||
version: freetype_min_version_actual,
|
||||
method: 'cmake',
|
||||
required: get_option('freetype'),
|
||||
default_options: ['harfbuzz=disabled'],
|
||||
allow_fallback: true)
|
||||
endif
|
||||
else
|
||||
# painful hack to handle multiple dependencies but also respect options
|
||||
freetype_opt = get_option('freetype')
|
||||
# we want to handle enabled manually after fallbacks, but also handle disabled normally
|
||||
if freetype_opt.enabled()
|
||||
freetype_opt = false
|
||||
endif
|
||||
# try pkg-config name
|
||||
freetype_dep = dependency('freetype2', version: freetype_min_version, method: 'pkg-config', required: freetype_opt)
|
||||
# when disabled, leave it not-found
|
||||
if not freetype_dep.found() and not get_option('freetype').disabled()
|
||||
# Try cmake name
|
||||
freetype_dep = dependency('Freetype', version: freetype_min_version_actual, method: 'cmake', required: false)
|
||||
# Subproject fallback, `allow_fallback: true` means the fallback will be
|
||||
# tried even if the freetype option is set to `auto`.
|
||||
required: false,
|
||||
allow_fallback: false)
|
||||
# Subproject fallback
|
||||
if not freetype_dep.found()
|
||||
freetype_dep = dependency('freetype2',
|
||||
version: freetype_min_version,
|
||||
method: 'pkg-config',
|
||||
freetype_proj = subproject('freetype2',
|
||||
version: freetype_min_version_actual,
|
||||
required: get_option('freetype'),
|
||||
default_options: ['harfbuzz=disabled'],
|
||||
allow_fallback: true)
|
||||
default_options: ['harfbuzz=disabled'])
|
||||
if freetype_proj.found()
|
||||
freetype_dep = freetype_proj.get_variable('freetype_dep')
|
||||
else
|
||||
freetype_dep = dependency('', required: false)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -152,38 +150,12 @@ wasm_dep = cpp.find_library('iwasm', required: get_option('wasm'))
|
|||
# How to check whether iwasm was built, and hence requires, LLVM?
|
||||
#llvm_dep = cpp.find_library('LLVM-15', required: get_option('wasm'))
|
||||
|
||||
if meson.version().version_compare('>=0.60.0')
|
||||
# pkg-config: icu-uc, cmake: ICU but with components
|
||||
icu_dep = dependency('icu-uc', 'ICU',
|
||||
version: icu_min_version,
|
||||
components: 'uc',
|
||||
required: get_option('icu'),
|
||||
allow_fallback: true)
|
||||
else
|
||||
# painful hack to handle multiple dependencies but also respect options
|
||||
icu_opt = get_option('icu')
|
||||
# we want to handle enabled manually after fallbacks, but also handle disabled normally
|
||||
if icu_opt.enabled()
|
||||
icu_opt = false
|
||||
endif
|
||||
# try pkg-config name
|
||||
icu_dep = dependency('icu-uc', version: icu_min_version, method: 'pkg-config', required: icu_opt)
|
||||
# when disabled, leave it not-found
|
||||
if not icu_dep.found() and not get_option('icu').disabled()
|
||||
# Try cmake name
|
||||
icu_dep = dependency('ICU', version: icu_min_version, method: 'cmake', components: 'uc', required: false)
|
||||
# Try again with subproject fallback. `allow_fallback: true` means the
|
||||
# fallback will be tried even if the icu option is set to `auto`, but
|
||||
# we cannot pass this option until Meson 0.59.0, because no wrap file
|
||||
# is checked into git.
|
||||
if not icu_dep.found()
|
||||
icu_dep = dependency('icu-uc',
|
||||
version: icu_min_version,
|
||||
method: 'pkg-config',
|
||||
required: get_option('icu'))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
# pkg-config: icu-uc, cmake: ICU but with components
|
||||
icu_dep = dependency('icu-uc', 'ICU',
|
||||
version: icu_min_version,
|
||||
components: 'uc',
|
||||
required: get_option('icu'),
|
||||
allow_fallback: true)
|
||||
|
||||
if icu_dep.found() and icu_dep.version().version_compare('>=75.1') and (get_option('cpp_std') == 'c++11' or get_option('cpp_std') == 'c++14')
|
||||
cpp17_arg = cpp.get_argument_syntax() == 'msvc' ? '/std:c++17' : '-std=c++17'
|
||||
|
@ -227,16 +199,18 @@ endif
|
|||
|
||||
chafa_dep = dependency('chafa', version: chafa_min_version, required: get_option('chafa'))
|
||||
|
||||
fontations_dep_found = false
|
||||
if get_option('fontations').enabled()
|
||||
add_languages(['rust'], native: false, required : true)
|
||||
fontations_dep_found = true
|
||||
endif
|
||||
|
||||
conf = configuration_data()
|
||||
incconfig = include_directories('.')
|
||||
|
||||
add_project_arguments('-DHAVE_CONFIG_H', language: ['c', 'cpp'])
|
||||
|
||||
warn_cflags = [
|
||||
'-Wno-non-virtual-dtor',
|
||||
]
|
||||
|
||||
cpp_args = cpp.get_supported_arguments(warn_cflags)
|
||||
cpp_args = []
|
||||
|
||||
if glib_dep.found()
|
||||
conf.set('HAVE_GLIB', 1)
|
||||
|
@ -272,6 +246,10 @@ if chafa_dep.found()
|
|||
conf.set('HAVE_CHAFA', 1)
|
||||
endif
|
||||
|
||||
if fontations_dep_found
|
||||
conf.set('HAVE_FONTATIONS', 1)
|
||||
endif
|
||||
|
||||
if wasm_dep.found()
|
||||
conf.set('HAVE_WASM', 1)
|
||||
conf.set('HB_WASM_MODULE_DIR', '"'+get_option('prefix')+'/'+get_option('libdir')+'/harfbuzz/wasm"')
|
||||
|
@ -315,13 +293,13 @@ endif
|
|||
gdi_uniscribe_deps = []
|
||||
# GDI (Uniscribe) (Windows)
|
||||
if host_machine.system() == 'windows' and not get_option('gdi').disabled()
|
||||
if (get_option('directwrite').enabled() and
|
||||
if (get_option('gdi').enabled() and
|
||||
not (cpp.has_header('usp10.h') and cpp.has_header('windows.h')))
|
||||
error('GDI/Uniscribe was enabled explicitly, but required headers are missing.')
|
||||
endif
|
||||
|
||||
gdi_deps_found = true
|
||||
foreach usplib : ['usp10', 'gdi32', 'rpcrt4']
|
||||
foreach usplib : ['usp10', 'gdi32', 'rpcrt4', 'user32']
|
||||
dep = cpp.find_library(usplib, required: get_option('gdi'))
|
||||
gdi_deps_found = gdi_deps_found and dep.found()
|
||||
gdi_uniscribe_deps += dep
|
||||
|
@ -333,13 +311,16 @@ if host_machine.system() == 'windows' and not get_option('gdi').disabled()
|
|||
endif
|
||||
endif
|
||||
|
||||
directwrite_dep = []
|
||||
# DirectWrite (Windows)
|
||||
if host_machine.system() == 'windows' and not get_option('directwrite').disabled()
|
||||
if get_option('directwrite').enabled() and not cpp.has_header('dwrite_1.h')
|
||||
if get_option('directwrite').enabled() and not cpp.has_header('dwrite_3.h')
|
||||
error('DirectWrite was enabled explicitly, but required header is missing.')
|
||||
endif
|
||||
|
||||
conf.set('HAVE_DIRECTWRITE', 1)
|
||||
directwrite_dep = cpp.find_library('dwrite', required: get_option('directwrite'))
|
||||
if directwrite_dep.found()
|
||||
conf.set('HAVE_DIRECTWRITE', 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
# CoreText (macOS)
|
||||
|
@ -464,6 +445,11 @@ configure_file(output: 'config.h', configuration: conf)
|
|||
alias_target('lib', libharfbuzz)
|
||||
alias_target('libs', libharfbuzz, libharfbuzz_subset)
|
||||
|
||||
# Re glib, see https://github.com/harfbuzz/harfbuzz/issues/4153#issuecomment-2646347531
|
||||
add_test_setup('default',
|
||||
exclude_suites: ['google-benchmark'],
|
||||
is_default: glib_dep.type_name() != 'internal' and not meson.is_subproject())
|
||||
|
||||
build_summary = {
|
||||
'Directories':
|
||||
{'prefix': get_option('prefix'),
|
||||
|
|
|
@ -15,10 +15,12 @@ option('graphite2', type: 'feature', value: 'disabled',
|
|||
description: 'Enable Graphite2 complementary shaper')
|
||||
option('freetype', type: 'feature', value: 'auto',
|
||||
description: 'Enable freetype interop helpers')
|
||||
option('fontations', type: 'feature', value: 'disabled',
|
||||
description: 'Enabled fontations font functions')
|
||||
option('gdi', type: 'feature', value: 'disabled',
|
||||
description: 'Enable GDI helpers and Uniscribe shaper backend (Windows only)')
|
||||
option('directwrite', type: 'feature', value: 'disabled',
|
||||
description: 'Enable DirectWrite shaper backend on Windows (experimental)')
|
||||
description: 'Enable DirectWrite shaper backend on Windows')
|
||||
option('coretext', type: 'feature', value: 'disabled',
|
||||
description: 'Enable CoreText shaper backend on macOS')
|
||||
option('wasm', type: 'feature', value: 'disabled',
|
||||
|
|
|
@ -4,17 +4,21 @@ Benchmarks are implemented using [Google Benchmark](https://github.com/google/be
|
|||
|
||||
To build the benchmarks in this directory you need to set the benchmark
|
||||
option while configuring the build with meson:
|
||||
|
||||
```
|
||||
meson build -Dbenchmark=enabled --buildtype=release
|
||||
```
|
||||
or:
|
||||
```
|
||||
meson build -Dbenchmark=enabled --buildtype=debugoptimized
|
||||
```
|
||||
|
||||
The default build type is `debugoptimized`, which is good enough for
|
||||
benchmarking, but you can also get the fastest mode with `release`
|
||||
build type:
|
||||
```
|
||||
meson build -Dbenchmark=enabled --buildtype=release
|
||||
```
|
||||
|
||||
Then build a specific benchmark binaries with ninja:
|
||||
You should, of course, enable features you want to benchmark, like
|
||||
`-Dfreetype`, `-Dfontations`, `-Dcoretext`, etc.
|
||||
|
||||
Then build a specific benchmark binaries with ninja, eg.:
|
||||
```
|
||||
ninja -Cbuild perf/benchmark-set
|
||||
```
|
||||
|
@ -33,22 +37,47 @@ It's possible to filter the benchmarks being run and customize the output
|
|||
via flags to the benchmark binary. See the
|
||||
[Google Benchmark User Guide](https://github.com/google/benchmark/blob/main/docs/user_guide.md#user-guide) for more details.
|
||||
|
||||
The most useful benchmark is `benchmark-font`. You can provide custom fonts to it too.
|
||||
For example, to run only the "paint" benchmarks, against a given font, you can do:
|
||||
```
|
||||
./build/perf/benchmark-font NotoColorEmoji-Regular.ttf --benchmark_filter="paint"
|
||||
```
|
||||
|
||||
Some useful options are: `--benchmark_repetitions=5` to run the benchmark 5 times,
|
||||
`--benchmark_min_time=.1s` to run the benchmark for at least .1 seconds (defaults
|
||||
to .5s), and `--benchmark_filter=...` to filter the benchmarks by regular expression.
|
||||
|
||||
To compare before/after benchmarks, you need to save the benchmark results in files
|
||||
for both runs. Use `--benchmark_out=results.json` to output the results in JSON format.
|
||||
Then you can use:
|
||||
```
|
||||
./subprojects/benchmark-1.8.4/tools/compare.py benchmarks before.json after.json
|
||||
```
|
||||
Substitute your version of benchmark instead of 1.8.4.
|
||||
|
||||
# Profiling
|
||||
|
||||
Configure the build to include debug information for profiling:
|
||||
|
||||
If you like to disable optimizations and enable frame pointers for better profiling output,
|
||||
you can do so with the following meson command:
|
||||
```
|
||||
CXXFLAGS="-fno-omit-frame-pointer" meson --reconfigure build -Dbenchmark=enabled --buildtype=debug
|
||||
ninja -Cbuild
|
||||
```
|
||||
However, this will slow down the benchmarks significantly and might give you inaccurate
|
||||
information as to where to optimize. It's better to profile the `debugoptimized` build (the default).
|
||||
|
||||
Then run the benchmark with perf:
|
||||
|
||||
```
|
||||
perf record -g build/perf/benchmark-subset --benchmark_filter="BM_subset_codepoints/subset_notocjk/100000" --benchmark_repetitions=5
|
||||
```
|
||||
You probably want to filter to a specific benchmark of interest and set the number of repititions high enough to get a good sampling of profile data.
|
||||
You probably want to filter to a specific benchmark of interest and set the number of
|
||||
repititions high enough to get a good sampling of profile data.
|
||||
|
||||
Finally view the profile with:
|
||||
|
||||
```
|
||||
perf report
|
||||
```
|
||||
|
||||
Another useful `perf` tool is the `perf stat` command, which can give you a quick overview
|
||||
of the performance of a benchmark, as well as stalled cycles, cache misses, and mispredicted branches.
|
||||
|
|
|
@ -1,17 +1,4 @@
|
|||
#include "benchmark/benchmark.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "hb.h"
|
||||
#include "hb-ot.h"
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "hb-ft.h"
|
||||
#endif
|
||||
|
||||
#include "hb-benchmark.hh"
|
||||
|
||||
#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
|
||||
|
||||
|
@ -34,8 +21,6 @@ struct test_input_t
|
|||
static test_input_t *tests = default_tests;
|
||||
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
|
||||
|
||||
enum backend_t { HARFBUZZ, FREETYPE };
|
||||
|
||||
enum operation_t
|
||||
{
|
||||
nominal_glyphs,
|
||||
|
@ -94,16 +79,15 @@ _draw_funcs_create (void)
|
|||
}
|
||||
|
||||
static void BM_Font (benchmark::State &state,
|
||||
bool is_var, backend_t backend, operation_t operation,
|
||||
bool is_var, const char * backend,
|
||||
operation_t operation,
|
||||
const test_input_t &test_input)
|
||||
{
|
||||
hb_font_t *font;
|
||||
unsigned num_glyphs;
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
hb_face_t *face = hb_benchmark_face_create_from_file_or_fail (test_input.font_path, 0);
|
||||
assert (face);
|
||||
num_glyphs = hb_face_get_glyph_count (face);
|
||||
font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
|
@ -115,17 +99,12 @@ static void BM_Font (benchmark::State &state,
|
|||
hb_font_set_variations (font, &wght, 1);
|
||||
}
|
||||
|
||||
switch (backend)
|
||||
bool ret = hb_font_set_funcs_using (font, backend);
|
||||
if (!ret)
|
||||
{
|
||||
case HARFBUZZ:
|
||||
hb_ot_font_set_funcs (font);
|
||||
break;
|
||||
|
||||
case FREETYPE:
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
state.SkipWithError("Backend failed to initialize for font.");
|
||||
hb_font_destroy (font);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (operation)
|
||||
|
@ -208,24 +187,17 @@ static void BM_Font (benchmark::State &state,
|
|||
{
|
||||
for (auto _ : state)
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
hb_face_t *face = hb_benchmark_face_create_from_file_or_fail (test_input.font_path, 0);
|
||||
assert (face);
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
|
||||
switch (backend)
|
||||
bool ret = hb_font_set_funcs_using (font, backend);
|
||||
if (!ret)
|
||||
{
|
||||
case HARFBUZZ:
|
||||
hb_ot_font_set_funcs (font);
|
||||
break;
|
||||
|
||||
case FREETYPE:
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
state.SkipWithError("Backend failed to initialize for font.");
|
||||
hb_font_destroy (font);
|
||||
return;
|
||||
}
|
||||
|
||||
hb_buffer_t *buffer = hb_buffer_create ();
|
||||
|
@ -245,8 +217,7 @@ static void BM_Font (benchmark::State &state,
|
|||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
static void test_backend (backend_t backend,
|
||||
const char *backend_name,
|
||||
static void test_backend (const char *backend,
|
||||
bool variable,
|
||||
operation_t op,
|
||||
const char *op_name,
|
||||
|
@ -260,7 +231,7 @@ static void test_backend (backend_t backend,
|
|||
strcat (name, p ? p + 1 : test_input.font_path);
|
||||
strcat (name, variable ? "/var" : "");
|
||||
strcat (name, "/");
|
||||
strcat (name, backend_name);
|
||||
strcat (name, backend);
|
||||
|
||||
benchmark::RegisterBenchmark (name, BM_Font, variable, backend, op, test_input)
|
||||
->Unit(time_unit);
|
||||
|
@ -270,6 +241,7 @@ static void test_operation (operation_t op,
|
|||
const char *op_name,
|
||||
benchmark::TimeUnit time_unit)
|
||||
{
|
||||
const char **supported_backends = hb_font_list_funcs ();
|
||||
for (unsigned i = 0; i < num_tests; i++)
|
||||
{
|
||||
auto& test_input = tests[i];
|
||||
|
@ -277,10 +249,8 @@ static void test_operation (operation_t op,
|
|||
{
|
||||
bool is_var = (bool) variable;
|
||||
|
||||
test_backend (HARFBUZZ, "hb", is_var, op, op_name, time_unit, test_input);
|
||||
#ifdef HAVE_FREETYPE
|
||||
test_backend (FREETYPE, "ft", is_var, op, op_name, time_unit, test_input);
|
||||
#endif
|
||||
for (const char **backend = supported_backends; *backend; backend++)
|
||||
test_backend (*backend, is_var, op, op_name, time_unit, test_input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +275,7 @@ int main(int argc, char** argv)
|
|||
TEST_OPERATION (nominal_glyphs, benchmark::kMicrosecond);
|
||||
TEST_OPERATION (glyph_h_advances, benchmark::kMicrosecond);
|
||||
TEST_OPERATION (glyph_extents, benchmark::kMicrosecond);
|
||||
TEST_OPERATION (draw_glyph, benchmark::kMicrosecond);
|
||||
TEST_OPERATION (draw_glyph, benchmark::kMillisecond);
|
||||
TEST_OPERATION (paint_glyph, benchmark::kMillisecond);
|
||||
TEST_OPERATION (load_face_and_shape, benchmark::kMicrosecond);
|
||||
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
/*
|
||||
* Benchmarks for hb_map_t operations.
|
||||
*/
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include "hb.h"
|
||||
#include "hb-benchmark.hh"
|
||||
|
||||
void RandomMap(unsigned size, hb_map_t* out, hb_set_t* key_sample) {
|
||||
hb_map_clear(out);
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
/*
|
||||
* Benchmarks for hb_set_t operations.
|
||||
*/
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "hb-ot.h"
|
||||
#include "hb-benchmark.hh"
|
||||
|
||||
static void BM_hb_ot_tags_from_script_and_language (benchmark::State& state,
|
||||
hb_script_t script,
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
/*
|
||||
* Benchmarks for hb_set_t operations.
|
||||
*/
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include "hb.h"
|
||||
#include "hb-benchmark.hh"
|
||||
|
||||
void RandomSet(unsigned size, unsigned max_value, hb_set_t* out) {
|
||||
hb_set_clear(out);
|
||||
|
|
|
@ -1,17 +1,4 @@
|
|||
#include "benchmark/benchmark.h"
|
||||
#include <cstring>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "hb.h"
|
||||
#include "hb-ot.h"
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "hb-ft.h"
|
||||
#endif
|
||||
#include "hb-benchmark.hh"
|
||||
|
||||
#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
|
||||
|
||||
|
@ -19,76 +6,52 @@ struct test_input_t
|
|||
{
|
||||
const char *font_path;
|
||||
const char *text_path;
|
||||
bool is_variable;
|
||||
} default_tests[] =
|
||||
{
|
||||
|
||||
{"perf/fonts/NotoNastaliqUrdu-Regular.ttf",
|
||||
"perf/texts/fa-thelittleprince.txt",
|
||||
false},
|
||||
"perf/texts/fa-thelittleprince.txt"},
|
||||
|
||||
{"perf/fonts/NotoNastaliqUrdu-Regular.ttf",
|
||||
"perf/texts/fa-words.txt",
|
||||
false},
|
||||
"perf/texts/fa-words.txt"},
|
||||
|
||||
{"perf/fonts/Amiri-Regular.ttf",
|
||||
"perf/texts/fa-thelittleprince.txt",
|
||||
false},
|
||||
"perf/texts/fa-thelittleprince.txt"},
|
||||
|
||||
{SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf",
|
||||
"perf/texts/hi-words.txt",
|
||||
false},
|
||||
"perf/texts/hi-words.txt"},
|
||||
|
||||
{"perf/fonts/Roboto-Regular.ttf",
|
||||
"perf/texts/en-thelittleprince.txt",
|
||||
false},
|
||||
"perf/texts/en-thelittleprince.txt"},
|
||||
|
||||
{"perf/fonts/Roboto-Regular.ttf",
|
||||
"perf/texts/en-words.txt",
|
||||
false},
|
||||
"perf/texts/en-words.txt"},
|
||||
|
||||
{SUBSET_FONT_BASE_PATH "SourceSerifVariable-Roman.ttf",
|
||||
"perf/texts/en-thelittleprince.txt",
|
||||
true},
|
||||
"perf/texts/react-dom.txt"},
|
||||
};
|
||||
|
||||
static test_input_t *tests = default_tests;
|
||||
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
|
||||
|
||||
enum backend_t { HARFBUZZ, FREETYPE };
|
||||
const char *variation = nullptr;
|
||||
|
||||
static void BM_Shape (benchmark::State &state,
|
||||
bool is_var,
|
||||
backend_t backend,
|
||||
const char *shaper,
|
||||
const test_input_t &input)
|
||||
{
|
||||
hb_font_t *font;
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (input.font_path);
|
||||
assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
hb_face_t *face = hb_benchmark_face_create_from_file_or_fail (input.font_path, 0);
|
||||
assert (face);
|
||||
font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
if (is_var)
|
||||
if (variation)
|
||||
{
|
||||
hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
|
||||
hb_font_set_variations (font, &wght, 1);
|
||||
}
|
||||
|
||||
switch (backend)
|
||||
{
|
||||
case HARFBUZZ:
|
||||
hb_ot_font_set_funcs (font);
|
||||
break;
|
||||
|
||||
case FREETYPE:
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
hb_variation_t var;
|
||||
hb_variation_from_string (variation, -1, &var);
|
||||
hb_font_set_variations (font, &var, 1);
|
||||
}
|
||||
|
||||
hb_blob_t *text_blob = hb_blob_create_from_file_or_fail (input.text_path);
|
||||
|
@ -108,7 +71,8 @@ static void BM_Shape (benchmark::State &state,
|
|||
hb_buffer_clear_contents (buf);
|
||||
hb_buffer_add_utf8 (buf, text, text_length, 0, end - text);
|
||||
hb_buffer_guess_segment_properties (buf);
|
||||
hb_shape (font, buf, nullptr, 0);
|
||||
const char *shaper_list[] = {shaper, nullptr};
|
||||
hb_shape_full (font, buf, nullptr, 0, shaper_list);
|
||||
|
||||
unsigned skip = end - text + 1;
|
||||
text_length -= skip;
|
||||
|
@ -121,10 +85,8 @@ static void BM_Shape (benchmark::State &state,
|
|||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
static void test_backend (backend_t backend,
|
||||
const char *backend_name,
|
||||
bool variable,
|
||||
const test_input_t &test_input)
|
||||
static void test_shaper (const char *shaper,
|
||||
const test_input_t &test_input)
|
||||
{
|
||||
char name[1024] = "BM_Shape";
|
||||
const char *p;
|
||||
|
@ -134,11 +96,10 @@ static void test_backend (backend_t backend,
|
|||
strcat (name, "/");
|
||||
p = strrchr (test_input.text_path, '/');
|
||||
strcat (name, p ? p + 1 : test_input.text_path);
|
||||
strcat (name, variable ? "/var" : "");
|
||||
strcat (name, "/");
|
||||
strcat (name, backend_name);
|
||||
strcat (name, shaper);
|
||||
|
||||
benchmark::RegisterBenchmark (name, BM_Shape, variable, backend, test_input)
|
||||
benchmark::RegisterBenchmark (name, BM_Shape, shaper, test_input)
|
||||
->Unit(benchmark::kMillisecond);
|
||||
}
|
||||
|
||||
|
@ -146,35 +107,25 @@ int main(int argc, char** argv)
|
|||
{
|
||||
benchmark::Initialize(&argc, argv);
|
||||
|
||||
test_input_t static_test = {};
|
||||
if (argc > 2)
|
||||
{
|
||||
num_tests = (argc - 1) / 2;
|
||||
tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
|
||||
for (unsigned i = 0; i < num_tests; i++)
|
||||
{
|
||||
tests[i].is_variable = true;
|
||||
tests[i].font_path = argv[1 + i * 2];
|
||||
tests[i].text_path = argv[2 + i * 2];
|
||||
}
|
||||
static_test.font_path = argv[1];
|
||||
static_test.text_path = argv[2];
|
||||
tests = &static_test;
|
||||
num_tests = 1;
|
||||
}
|
||||
if (argc > 3)
|
||||
variation = argv[3];
|
||||
|
||||
for (unsigned i = 0; i < num_tests; i++)
|
||||
{
|
||||
auto& test_input = tests[i];
|
||||
for (int variable = 0; variable < int (test_input.is_variable) + 1; variable++)
|
||||
{
|
||||
bool is_var = (bool) variable;
|
||||
|
||||
test_backend (HARFBUZZ, "hb", is_var, test_input);
|
||||
#ifdef HAVE_FREETYPE
|
||||
test_backend (FREETYPE, "ft", is_var, test_input);
|
||||
#endif
|
||||
}
|
||||
const char **shapers = hb_shape_list_shapers ();
|
||||
for (const char **shaper = shapers; *shaper; shaper++)
|
||||
test_shaper (*shaper, test_input);
|
||||
}
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
benchmark::Shutdown();
|
||||
|
||||
if (tests != default_tests)
|
||||
free (tests);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
#include "benchmark/benchmark.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "hb-subset.h"
|
||||
|
||||
#include "hb-benchmark.hh"
|
||||
|
||||
enum operation_t
|
||||
{
|
||||
|
@ -148,10 +139,8 @@ static void BM_subset (benchmark::State &state,
|
|||
|
||||
if (!cached_font_path || strcmp (cached_font_path, test_input.font_path))
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
|
||||
assert (blob);
|
||||
face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
face = hb_benchmark_face_create_from_file_or_fail (test_input.font_path, 0);
|
||||
assert (face);
|
||||
|
||||
face = preprocess_face (face);
|
||||
|
||||
|
|
64
perf/hb-benchmark.hh
Normal file
64
perf/hb-benchmark.hh
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright © 2024 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_BENCHMARK_HH
|
||||
#define HB_BENCHMARK_HH
|
||||
|
||||
#include <hb-config.hh>
|
||||
|
||||
#include <hb.h>
|
||||
#include <hb-subset.h>
|
||||
|
||||
#include <hb-ot.h>
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include <hb-ft.h>
|
||||
#endif
|
||||
#ifdef HAVE_FONTATIONS
|
||||
#include <hb-fontations.h>
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
#include <hb-coretext.h>
|
||||
#endif
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
static inline hb_face_t *
|
||||
hb_benchmark_face_create_from_file_or_fail (const char *font_path,
|
||||
unsigned face_index)
|
||||
{
|
||||
return hb_face_create_from_file_or_fail_using (font_path, face_index, nullptr);
|
||||
}
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_BENCHMARK_HH */
|
45
perf/hb-draw-all.c
Normal file
45
perf/hb-draw-all.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include <hb.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s font-file [font-funcs] [wght]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
hb_face_t *face = hb_face_create_from_file_or_fail (argv[1], 0);
|
||||
|
||||
if (!face)
|
||||
{
|
||||
fprintf (stderr, "Failed to create face\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
|
||||
if (argc > 2)
|
||||
hb_font_set_funcs_using (font, argv[2]);
|
||||
|
||||
if (argc > 3)
|
||||
{
|
||||
hb_variation_t variations[] = {
|
||||
{ HB_TAG ('w', 'g', 'h', 't'), atoi (argv[3]) },
|
||||
};
|
||||
hb_font_set_variations (font, variations, 1);
|
||||
}
|
||||
|
||||
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
||||
|
||||
unsigned glyph_count = hb_face_get_glyph_count (face);
|
||||
for (unsigned gid = 0; gid < glyph_count; gid++)
|
||||
hb_font_draw_glyph (font, gid, funcs, NULL);
|
||||
|
||||
hb_draw_funcs_destroy (funcs);
|
||||
hb_font_destroy (font);
|
||||
hb_face_destroy (face);
|
||||
return 0;
|
||||
}
|
45
perf/hb-paint-all.c
Normal file
45
perf/hb-paint-all.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include <hb.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s font-file [font-funcs] [wght]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
hb_face_t *face = hb_face_create_from_file_or_fail (argv[1], 0);
|
||||
|
||||
if (!face)
|
||||
{
|
||||
fprintf (stderr, "Failed to create face\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
|
||||
if (argc > 2)
|
||||
hb_font_set_funcs_using (font, argv[2]);
|
||||
|
||||
if (argc > 3)
|
||||
{
|
||||
hb_variation_t variations[] = {
|
||||
{ HB_TAG ('w', 'g', 'h', 't'), atoi (argv[3]) },
|
||||
};
|
||||
hb_font_set_variations (font, variations, 1);
|
||||
}
|
||||
|
||||
hb_paint_funcs_t *funcs = hb_paint_funcs_create ();
|
||||
|
||||
unsigned glyph_count = hb_face_get_glyph_count (face);
|
||||
for (unsigned gid = 0; gid < glyph_count; gid++)
|
||||
hb_font_paint_glyph (font, gid, funcs, NULL, 0, 0);
|
||||
|
||||
hb_paint_funcs_destroy (funcs);
|
||||
hb_font_destroy (font);
|
||||
hb_face_destroy (face);
|
||||
return 0;
|
||||
}
|
100
perf/meson.build
100
perf/meson.build
|
@ -1,62 +1,54 @@
|
|||
google_benchmark = subproject('google-benchmark')
|
||||
google_benchmark_dep = google_benchmark.get_variable('google_benchmark_dep')
|
||||
|
||||
benchmark('benchmark-font', executable('benchmark-font', 'benchmark-font.cc',
|
||||
dependencies: [
|
||||
google_benchmark_dep, freetype_dep,
|
||||
],
|
||||
cpp_args: [],
|
||||
benchmarks = [
|
||||
'benchmark-font.cc',
|
||||
'benchmark-map.cc',
|
||||
'benchmark-ot.cc',
|
||||
'benchmark-set.cc',
|
||||
'benchmark-shape.cc',
|
||||
]
|
||||
|
||||
foreach source : benchmarks
|
||||
benchmark_name = source.split('.')[0]
|
||||
benchmark(benchmark_name, executable(benchmark_name, source,
|
||||
dependencies: [
|
||||
google_benchmark_dep, freetype_dep, coretext_deps,
|
||||
],
|
||||
cpp_args: [],
|
||||
include_directories: [incconfig, incsrc],
|
||||
link_with: [libharfbuzz],
|
||||
install: false,
|
||||
), workdir: meson.current_source_dir() / '..', timeout: 100)
|
||||
endforeach
|
||||
|
||||
benchmarks_subset = [
|
||||
'benchmark-subset.cc',
|
||||
]
|
||||
|
||||
foreach source : benchmarks_subset
|
||||
benchmark_name = source.split('.')[0]
|
||||
benchmark(benchmark_name, executable(benchmark_name, source,
|
||||
dependencies: [
|
||||
google_benchmark_dep, freetype_dep, coretext_deps,
|
||||
],
|
||||
cpp_args: [],
|
||||
include_directories: [incconfig, incsrc],
|
||||
link_with: [libharfbuzz, libharfbuzz_subset],
|
||||
install: false,
|
||||
), workdir: meson.current_source_dir() / '..', timeout: 100)
|
||||
endforeach
|
||||
|
||||
hb_draw_all = executable('hb-draw-all', ['hb-draw-all.c'],
|
||||
cpp_args: cpp_args,
|
||||
include_directories: [incconfig, incsrc],
|
||||
link_with: [libharfbuzz],
|
||||
install: false,
|
||||
), workdir: meson.current_source_dir() / '..', timeout: 100)
|
||||
)
|
||||
meson.override_find_program('hb-draw-all', hb_draw_all)
|
||||
|
||||
benchmark('benchmark-map', executable('benchmark-map', 'benchmark-map.cc',
|
||||
dependencies: [
|
||||
google_benchmark_dep,
|
||||
],
|
||||
cpp_args: [],
|
||||
hb_paint_all = executable('hb-paint-all', ['hb-paint-all.c'],
|
||||
cpp_args: cpp_args,
|
||||
include_directories: [incconfig, incsrc],
|
||||
link_with: [libharfbuzz],
|
||||
install: false,
|
||||
), workdir: meson.current_source_dir() / '..', timeout: 100)
|
||||
|
||||
benchmark('benchmark-ot', executable('benchmark-ot', 'benchmark-ot.cc',
|
||||
dependencies: [
|
||||
google_benchmark_dep,
|
||||
],
|
||||
cpp_args: [],
|
||||
include_directories: [incconfig, incsrc],
|
||||
link_with: [libharfbuzz],
|
||||
install: false,
|
||||
), workdir: meson.current_source_dir() / '..', timeout: 100)
|
||||
|
||||
benchmark('benchmark-set', executable('benchmark-set', 'benchmark-set.cc',
|
||||
dependencies: [
|
||||
google_benchmark_dep,
|
||||
],
|
||||
cpp_args: [],
|
||||
include_directories: [incconfig, incsrc],
|
||||
link_with: [libharfbuzz],
|
||||
install: false,
|
||||
), workdir: meson.current_source_dir() / '..', timeout: 100)
|
||||
|
||||
benchmark('benchmark-shape', executable('benchmark-shape', 'benchmark-shape.cc',
|
||||
dependencies: [
|
||||
google_benchmark_dep, freetype_dep,
|
||||
],
|
||||
cpp_args: [],
|
||||
include_directories: [incconfig, incsrc],
|
||||
link_with: [libharfbuzz],
|
||||
install: false,
|
||||
), workdir: meson.current_source_dir() / '..', timeout: 100)
|
||||
|
||||
benchmark('benchmark-subset', executable('benchmark-subset', 'benchmark-subset.cc',
|
||||
dependencies: [
|
||||
google_benchmark_dep,
|
||||
],
|
||||
cpp_args: [],
|
||||
include_directories: [incconfig, incsrc],
|
||||
link_with: [libharfbuzz, libharfbuzz_subset],
|
||||
install: false,
|
||||
), workdir: meson.current_source_dir() / '..', timeout: 100)
|
||||
)
|
||||
meson.override_find_program('hb-paint-all', hb_paint_all)
|
||||
|
|
12391
perf/texts/en-2letters.txt
Normal file
12391
perf/texts/en-2letters.txt
Normal file
File diff suppressed because it is too large
Load diff
29869
perf/texts/react-dom.txt
Normal file
29869
perf/texts/react-dom.txt
Normal file
File diff suppressed because it is too large
Load diff
|
@ -941,10 +941,12 @@ struct CBDT
|
|||
}
|
||||
}
|
||||
|
||||
bool has_data () const { return cbdt.get_length (); }
|
||||
bool has_data () const { return cbdt->version.major; }
|
||||
|
||||
bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
|
||||
{
|
||||
if (!has_data ()) return false;
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_glyph_extents_t pixel_extents;
|
||||
hb_blob_t *blob = reference_png (font, glyph);
|
||||
|
|
|
@ -29,11 +29,14 @@
|
|||
#define OT_COLOR_COLR_COLR_HH
|
||||
|
||||
#include "../../../hb.hh"
|
||||
#include "../../../hb-decycler.hh"
|
||||
#include "../../../hb-open-type.hh"
|
||||
#include "../../../hb-ot-var-common.hh"
|
||||
#include "../../../hb-paint.hh"
|
||||
#include "../../../hb-paint-extents.hh"
|
||||
|
||||
#include "../CPAL/CPAL.hh"
|
||||
|
||||
/*
|
||||
* COLR -- Color
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/colr
|
||||
|
@ -44,6 +47,11 @@ namespace OT {
|
|||
struct hb_paint_context_t;
|
||||
}
|
||||
|
||||
struct hb_colr_scratch_t
|
||||
{
|
||||
hb_paint_extents_context_t paint_extents;
|
||||
};
|
||||
|
||||
namespace OT {
|
||||
|
||||
struct COLR;
|
||||
|
@ -66,11 +74,11 @@ public:
|
|||
hb_paint_funcs_t *funcs;
|
||||
void *data;
|
||||
hb_font_t *font;
|
||||
unsigned int palette_index;
|
||||
hb_array_t<const BGRAColor> palette;
|
||||
hb_color_t foreground;
|
||||
ItemVarStoreInstancer &instancer;
|
||||
hb_map_t current_glyphs;
|
||||
hb_map_t current_layers;
|
||||
hb_decycler_t glyphs_decycler;
|
||||
hb_decycler_t layers_decycler;
|
||||
int depth_left = HB_MAX_NESTING_LEVEL;
|
||||
int edge_count = HB_MAX_GRAPH_EDGE_COUNT;
|
||||
|
||||
|
@ -85,7 +93,12 @@ public:
|
|||
funcs (funcs_),
|
||||
data (data_),
|
||||
font (font_),
|
||||
palette_index (palette_),
|
||||
palette (
|
||||
#ifndef HB_NO_COLOR
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5116
|
||||
font->face->table.CPAL->get_palette_colors (palette_ < font->face->table.CPAL->get_palette_count () ? palette_ : 0)
|
||||
#endif
|
||||
),
|
||||
foreground (foreground_),
|
||||
instancer (instancer_)
|
||||
{ }
|
||||
|
@ -99,12 +112,7 @@ public:
|
|||
if (color_index != 0xffff)
|
||||
{
|
||||
if (!funcs->custom_palette_color (data, color_index, &color))
|
||||
{
|
||||
unsigned int clen = 1;
|
||||
hb_face_t *face = hb_font_get_face (font);
|
||||
|
||||
hb_ot_color_palette_get_colors (face, palette_index, color_index, &clen, &color);
|
||||
}
|
||||
color = palette[color_index];
|
||||
|
||||
*is_foreground = false;
|
||||
}
|
||||
|
@ -930,9 +938,9 @@ struct PaintGlyph
|
|||
void paint_glyph (hb_paint_context_t *c) const
|
||||
{
|
||||
TRACE_PAINT (this);
|
||||
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||
c->funcs->push_inverse_font_transform (c->data, c->font);
|
||||
c->funcs->push_clip_glyph (c->data, gid, c->font);
|
||||
c->funcs->push_root_transform (c->data, c->font);
|
||||
c->funcs->push_font_transform (c->data, c->font);
|
||||
c->recurse (this+paint);
|
||||
c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_clip (c->data);
|
||||
|
@ -1003,7 +1011,7 @@ struct PaintTransform
|
|||
void paint_glyph (hb_paint_context_t *c) const
|
||||
{
|
||||
TRACE_PAINT (this);
|
||||
(this+transform).paint_glyph (c);
|
||||
(this+transform).paint_glyph (c); // This does a push_transform()
|
||||
c->recurse (this+src);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
@ -1509,10 +1517,12 @@ struct PaintComposite
|
|||
void paint_glyph (hb_paint_context_t *c) const
|
||||
{
|
||||
TRACE_PAINT (this);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (this+backdrop);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (this+src);
|
||||
c->funcs->pop_group (c->data, (hb_paint_composite_mode_t) (int) mode);
|
||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 32 */
|
||||
|
@ -1610,7 +1620,7 @@ struct ClipBox
|
|||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 2: u.format2.closurev1 (c);
|
||||
case 2: u.format2.closurev1 (c); return;
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
|
@ -2058,7 +2068,7 @@ struct delta_set_index_map_subset_plan_t
|
|||
unsigned outer = (*var_idx) >> 16;
|
||||
unsigned bit_count = (outer == 0) ? 1 : hb_bit_storage (outer);
|
||||
outer_bit_count = hb_max (bit_count, outer_bit_count);
|
||||
|
||||
|
||||
unsigned inner = (*var_idx) & 0xFFFF;
|
||||
bit_count = (inner == 0) ? 1 : hb_bit_storage (inner);
|
||||
inner_bit_count = hb_max (bit_count, inner_bit_count);
|
||||
|
@ -2077,10 +2087,12 @@ struct COLR
|
|||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
|
||||
|
||||
bool has_data () const { return has_v0_data () || version; }
|
||||
|
||||
bool has_v0_data () const { return numBaseGlyphs; }
|
||||
bool has_v1_data () const
|
||||
{
|
||||
if (version != 1)
|
||||
if (version < 1)
|
||||
return false;
|
||||
hb_barrier ();
|
||||
|
||||
|
@ -2110,7 +2122,53 @@ struct COLR
|
|||
{
|
||||
accelerator_t (hb_face_t *face)
|
||||
{ colr = hb_sanitize_context_t ().reference_table<COLR> (face); }
|
||||
~accelerator_t () { this->colr.destroy (); }
|
||||
|
||||
~accelerator_t ()
|
||||
{
|
||||
auto *scratch = cached_scratch.get_relaxed ();
|
||||
if (scratch)
|
||||
{
|
||||
scratch->~hb_colr_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
|
||||
colr.destroy ();
|
||||
}
|
||||
|
||||
|
||||
bool has_data () const { return colr->has_data (); }
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
bool
|
||||
get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
if (unlikely (!has_data ())) return false;
|
||||
|
||||
hb_colr_scratch_t *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch)) return true;
|
||||
bool ret = colr->get_extents (font, glyph, extents, *scratch);
|
||||
release_scratch (scratch);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool paint_glyph (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *funcs, void *data,
|
||||
unsigned int palette_index,
|
||||
hb_color_t foreground,
|
||||
bool clip = true) const
|
||||
{
|
||||
if (unlikely (!has_data ())) return false;
|
||||
|
||||
hb_colr_scratch_t *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch)) return true;
|
||||
bool ret = colr->paint_glyph (font, glyph, funcs, data, palette_index, foreground, clip, *scratch);
|
||||
release_scratch (scratch);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool is_valid () { return colr.get_blob ()->length; }
|
||||
|
||||
|
@ -2134,15 +2192,45 @@ struct COLR
|
|||
|
||||
const ItemVariationStore &get_var_store () const
|
||||
{ return colr->get_var_store (); }
|
||||
const ItemVariationStore *get_var_store_ptr () const
|
||||
{ return colr->get_var_store_ptr (); }
|
||||
|
||||
bool has_delta_set_index_map () const
|
||||
{ return colr->has_delta_set_index_map (); }
|
||||
|
||||
const DeltaSetIndexMap &get_delta_set_index_map () const
|
||||
{ return colr->get_delta_set_index_map (); }
|
||||
const DeltaSetIndexMap *get_delta_set_index_map_ptr () const
|
||||
{ return colr->get_delta_set_index_map_ptr (); }
|
||||
|
||||
private:
|
||||
|
||||
hb_colr_scratch_t *acquire_scratch () const
|
||||
{
|
||||
hb_colr_scratch_t *scratch = cached_scratch.get_acquire ();
|
||||
|
||||
if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
|
||||
{
|
||||
scratch = (hb_colr_scratch_t *) hb_calloc (1, sizeof (hb_colr_scratch_t));
|
||||
if (unlikely (!scratch))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return scratch;
|
||||
}
|
||||
void release_scratch (hb_colr_scratch_t *scratch) const
|
||||
{
|
||||
if (!cached_scratch.cmpexch (nullptr, scratch))
|
||||
{
|
||||
scratch->~hb_colr_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
hb_blob_ptr_t<COLR> colr;
|
||||
private:
|
||||
hb_atomic_t<hb_colr_scratch_t *> cached_scratch;
|
||||
};
|
||||
|
||||
void closure_glyphs (hb_codepoint_t glyph,
|
||||
|
@ -2180,7 +2268,7 @@ struct COLR
|
|||
hb_set_t *variation_indices,
|
||||
hb_set_t *delta_set_indices) const
|
||||
{
|
||||
if (version != 1) return;
|
||||
if (version < 1) return;
|
||||
hb_barrier ();
|
||||
|
||||
hb_set_t visited_glyphs;
|
||||
|
@ -2222,16 +2310,26 @@ struct COLR
|
|||
{ return (this+baseGlyphList); }
|
||||
|
||||
bool has_var_store () const
|
||||
{ return version >= 1 && varStore != 0; }
|
||||
{ return version >= 1 && hb_barrier () && varStore != 0; }
|
||||
|
||||
bool has_delta_set_index_map () const
|
||||
{ return version >= 1 && varIdxMap != 0; }
|
||||
{ return version >= 1 && hb_barrier () && varIdxMap != 0; }
|
||||
|
||||
bool has_clip_list () const
|
||||
{ return version >= 1 && hb_barrier () && clipList != 0; }
|
||||
|
||||
const DeltaSetIndexMap &get_delta_set_index_map () const
|
||||
{ return (version == 0 || varIdxMap == 0) ? Null (DeltaSetIndexMap) : this+varIdxMap; }
|
||||
{ return has_delta_set_index_map () && hb_barrier () ? this+varIdxMap : Null (DeltaSetIndexMap); }
|
||||
const DeltaSetIndexMap *get_delta_set_index_map_ptr () const
|
||||
{ return has_delta_set_index_map () && hb_barrier () ? &(this+varIdxMap) : nullptr; }
|
||||
|
||||
const ItemVariationStore &get_var_store () const
|
||||
{ return (version == 0 || varStore == 0) ? Null (ItemVariationStore) : this+varStore; }
|
||||
{ return has_var_store () && hb_barrier () ? this+varStore : Null (ItemVariationStore); }
|
||||
const ItemVariationStore *get_var_store_ptr () const
|
||||
{ return has_var_store () && hb_barrier () ? &(this+varStore) : nullptr; }
|
||||
|
||||
const ClipList &get_clip_list () const
|
||||
{ return has_clip_list () && hb_barrier () ? this+clipList : Null (ClipList); }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -2242,7 +2340,6 @@ struct COLR
|
|||
(this+layersZ).sanitize (c, numLayers) &&
|
||||
(version == 0 ||
|
||||
(hb_barrier () &&
|
||||
version == 1 &&
|
||||
baseGlyphList.sanitize (c, this) &&
|
||||
layerList.sanitize (c, this) &&
|
||||
clipList.sanitize (c, this) &&
|
||||
|
@ -2465,7 +2562,9 @@ struct COLR
|
|||
if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false);
|
||||
|
||||
if (version == 0 || downgrade_to_V0 (glyphset))
|
||||
return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
|
||||
return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
|
||||
|
||||
hb_barrier ();
|
||||
|
||||
//start version 1
|
||||
if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false);
|
||||
|
@ -2475,9 +2574,9 @@ struct COLR
|
|||
* after instancing */
|
||||
if (!subset_varstore (c, colr_prime)) return_trace (false);
|
||||
|
||||
ItemVarStoreInstancer instancer (varStore ? &(this+varStore) : nullptr,
|
||||
varIdxMap ? &(this+varIdxMap) : nullptr,
|
||||
c->plan->normalized_coords.as_array ());
|
||||
ItemVarStoreInstancer instancer (get_var_store_ptr (),
|
||||
get_delta_set_index_map_ptr (),
|
||||
c->plan->normalized_coords.as_array ());
|
||||
|
||||
if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this, instancer))
|
||||
return_trace (false);
|
||||
|
@ -2503,14 +2602,15 @@ struct COLR
|
|||
|
||||
#ifndef HB_NO_PAINT
|
||||
bool
|
||||
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
|
||||
get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
hb_colr_scratch_t &scratch) const
|
||||
{
|
||||
if (version != 1)
|
||||
return false;
|
||||
|
||||
ItemVarStoreInstancer instancer (&(this+varStore),
|
||||
&(this+varIdxMap),
|
||||
hb_array (font->coords, font->num_coords));
|
||||
ItemVarStoreInstancer instancer (get_var_store_ptr (),
|
||||
get_delta_set_index_map_ptr (),
|
||||
hb_array (font->coords, font->num_coords));
|
||||
|
||||
if (get_clip (glyph, extents, instancer))
|
||||
{
|
||||
|
@ -2519,10 +2619,10 @@ struct COLR
|
|||
}
|
||||
|
||||
auto *extents_funcs = hb_paint_extents_get_funcs ();
|
||||
hb_paint_extents_context_t extents_data;
|
||||
bool ret = paint_glyph (font, glyph, extents_funcs, &extents_data, 0, HB_COLOR(0,0,0,0));
|
||||
scratch.paint_extents.clear ();
|
||||
bool ret = paint_glyph (font, glyph, extents_funcs, &scratch.paint_extents, 0, HB_COLOR(0,0,0,0), true, scratch);
|
||||
|
||||
hb_extents_t e = extents_data.get_extents ();
|
||||
auto e = scratch.paint_extents.get_extents ();
|
||||
if (e.is_void ())
|
||||
{
|
||||
extents->x_bearing = 0;
|
||||
|
@ -2532,6 +2632,7 @@ struct COLR
|
|||
}
|
||||
else
|
||||
{
|
||||
// Ugh. We need to undo the synthetic slant here. Leave it for now. :-(.
|
||||
extents->x_bearing = e.xmin;
|
||||
extents->y_bearing = e.ymax;
|
||||
extents->width = e.xmax - e.xmin;
|
||||
|
@ -2545,7 +2646,7 @@ struct COLR
|
|||
bool
|
||||
has_paint_for_glyph (hb_codepoint_t glyph) const
|
||||
{
|
||||
if (version == 1)
|
||||
if (version >= 1)
|
||||
{
|
||||
hb_barrier ();
|
||||
|
||||
|
@ -2561,22 +2662,29 @@ struct COLR
|
|||
hb_glyph_extents_t *extents,
|
||||
const ItemVarStoreInstancer instancer) const
|
||||
{
|
||||
return (this+clipList).get_extents (glyph,
|
||||
return get_clip_list ().get_extents (glyph,
|
||||
extents,
|
||||
instancer);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
bool
|
||||
paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const
|
||||
paint_glyph (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_paint_funcs_t *funcs, void *data,
|
||||
unsigned int palette_index, hb_color_t foreground,
|
||||
bool clip,
|
||||
hb_colr_scratch_t &scratch) const
|
||||
{
|
||||
ItemVarStoreInstancer instancer (&(this+varStore),
|
||||
&(this+varIdxMap),
|
||||
hb_array (font->coords, font->num_coords));
|
||||
ItemVarStoreInstancer instancer (get_var_store_ptr (),
|
||||
get_delta_set_index_map_ptr (),
|
||||
hb_array (font->coords, font->num_coords));
|
||||
hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
|
||||
c.current_glyphs.add (glyph);
|
||||
|
||||
if (version == 1)
|
||||
hb_decycler_node_t node (c.glyphs_decycler);
|
||||
node.visit (glyph);
|
||||
|
||||
if (version >= 1)
|
||||
{
|
||||
hb_barrier ();
|
||||
|
||||
|
@ -2592,6 +2700,7 @@ struct COLR
|
|||
if (get_clip (glyph, &extents, instancer))
|
||||
{
|
||||
font->scale_glyph_extents (&extents);
|
||||
font->synthetic_glyph_extents (&extents);
|
||||
c.funcs->push_clip_rectangle (c.data,
|
||||
extents.x_bearing,
|
||||
extents.y_bearing + extents.height,
|
||||
|
@ -2601,15 +2710,16 @@ struct COLR
|
|||
else
|
||||
{
|
||||
auto *extents_funcs = hb_paint_extents_get_funcs ();
|
||||
hb_paint_extents_context_t extents_data;
|
||||
scratch.paint_extents.clear ();
|
||||
|
||||
paint_glyph (font, glyph,
|
||||
extents_funcs, &extents_data,
|
||||
extents_funcs, &scratch.paint_extents,
|
||||
palette_index, foreground,
|
||||
false);
|
||||
false,
|
||||
scratch);
|
||||
|
||||
hb_extents_t extents = extents_data.get_extents ();
|
||||
is_bounded = extents_data.is_bounded ();
|
||||
auto extents = scratch.paint_extents.get_extents ();
|
||||
is_bounded = scratch.paint_extents.is_bounded ();
|
||||
|
||||
c.funcs->push_clip_rectangle (c.data,
|
||||
extents.xmin,
|
||||
|
@ -2619,7 +2729,7 @@ struct COLR
|
|||
}
|
||||
}
|
||||
|
||||
c.funcs->push_root_transform (c.data, font);
|
||||
c.funcs->push_font_transform (c.data, font);
|
||||
|
||||
if (is_bounded)
|
||||
c.recurse (*paint);
|
||||
|
@ -2690,19 +2800,14 @@ void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const
|
|||
{
|
||||
TRACE_PAINT (this);
|
||||
const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
|
||||
hb_decycler_node_t node (c->layers_decycler);
|
||||
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
|
||||
{
|
||||
if (unlikely (c->current_layers.has (i)))
|
||||
continue;
|
||||
|
||||
c->current_layers.add (i);
|
||||
if (unlikely (!node.visit (i)))
|
||||
return;
|
||||
|
||||
const Paint &paint = paint_offset_lists.get_paint (i);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (paint);
|
||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
|
||||
c->current_layers.del (i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2710,16 +2815,14 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
|
|||
{
|
||||
TRACE_PAINT (this);
|
||||
|
||||
if (unlikely (c->current_glyphs.has (gid)))
|
||||
hb_decycler_node_t node (c->glyphs_decycler);
|
||||
if (unlikely (!node.visit (gid)))
|
||||
return;
|
||||
|
||||
c->current_glyphs.add (gid);
|
||||
|
||||
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||
c->funcs->push_inverse_font_transform (c->data, c->font);
|
||||
if (c->funcs->color_glyph (c->data, gid, c->font))
|
||||
{
|
||||
c->funcs->pop_transform (c->data);
|
||||
c->current_glyphs.del (gid);
|
||||
return;
|
||||
}
|
||||
c->funcs->pop_transform (c->data);
|
||||
|
@ -2742,8 +2845,6 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
|
|||
|
||||
if (has_clip_box)
|
||||
c->funcs->pop_clip (c->data);
|
||||
|
||||
c->current_glyphs.del (gid);
|
||||
}
|
||||
|
||||
} /* namespace OT */
|
||||
|
|
|
@ -187,6 +187,14 @@ struct CPAL
|
|||
hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
|
||||
{ return v1 ().get_color_name_id (this, color_index, numColors); }
|
||||
|
||||
hb_array_t<const BGRAColor> get_palette_colors (unsigned int palette_index) const
|
||||
{
|
||||
if (unlikely (palette_index >= numPalettes))
|
||||
return hb_array_t<const BGRAColor> ();
|
||||
unsigned int start_index = colorRecordIndicesZ[palette_index];
|
||||
hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
|
||||
return all_colors.sub_array (start_index, numColors);
|
||||
}
|
||||
unsigned int get_palette_colors (unsigned int palette_index,
|
||||
unsigned int start_offset,
|
||||
unsigned int *color_count, /* IN/OUT. May be NULL. */
|
||||
|
|
|
@ -96,6 +96,15 @@ struct Coverage
|
|||
default:return NOT_COVERED;
|
||||
}
|
||||
}
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id,
|
||||
hb_ot_lookup_cache_t *cache) const
|
||||
{
|
||||
unsigned coverage;
|
||||
if (cache && cache->get (glyph_id, &coverage)) return coverage;
|
||||
coverage = get_coverage (glyph_id);
|
||||
if (cache) cache->set (glyph_id, coverage);
|
||||
return coverage;
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
|
@ -201,6 +210,19 @@ struct Coverage
|
|||
}
|
||||
}
|
||||
|
||||
unsigned cost () const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1: hb_barrier (); return u.format1.cost ();
|
||||
case 2: hb_barrier (); return u.format2.cost ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: hb_barrier (); return u.format3.cost ();
|
||||
case 4: hb_barrier (); return u.format4.cost ();
|
||||
#endif
|
||||
default:return 0u;
|
||||
}
|
||||
}
|
||||
|
||||
/* Might return false if array looks unsorted.
|
||||
* Used for faster rejection of corrupt data. */
|
||||
template <typename set_t>
|
||||
|
|
|
@ -77,7 +77,7 @@ struct CoverageFormat1_3
|
|||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
|
||||
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len))
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
|
@ -103,6 +103,8 @@ struct CoverageFormat1_3
|
|||
intersect_glyphs << glyphArray[i];
|
||||
}
|
||||
|
||||
unsigned cost () const { return hb_bit_storage ((unsigned) glyphArray.len); /* bsearch cost */ }
|
||||
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{ return glyphs->add_sorted_array (glyphArray.as_array ()); }
|
||||
|
|
|
@ -120,7 +120,7 @@ struct CoverageFormat2_4
|
|||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
|
||||
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len))
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
|
@ -157,6 +157,8 @@ struct CoverageFormat2_4
|
|||
}
|
||||
}
|
||||
|
||||
unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
|
||||
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{
|
||||
|
|
|
@ -205,20 +205,19 @@ struct CaretValueFormat3
|
|||
|
||||
unsigned varidx = (this+deviceTable).get_variation_index ();
|
||||
hb_pair_t<unsigned, int> *new_varidx_delta;
|
||||
if (!c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta))
|
||||
return_trace (false);
|
||||
if (c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) {
|
||||
uint32_t new_varidx = hb_first (*new_varidx_delta);
|
||||
int delta = hb_second (*new_varidx_delta);
|
||||
if (delta != 0)
|
||||
{
|
||||
if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
uint32_t new_varidx = hb_first (*new_varidx_delta);
|
||||
int delta = hb_second (*new_varidx_delta);
|
||||
if (delta != 0)
|
||||
{
|
||||
if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
|
||||
if (!c->serializer->embed (deviceTable))
|
||||
return_trace (false);
|
||||
|
||||
|
@ -1015,7 +1014,8 @@ struct GDEF
|
|||
hb_blob_ptr_t<GDEF> table;
|
||||
#ifndef HB_NO_GDEF_CACHE
|
||||
hb_vector_t<hb_set_digest_t> mark_glyph_set_digests;
|
||||
mutable hb_cache_t<21, 3, 8> glyph_props_cache;
|
||||
mutable hb_cache_t<21, 3> glyph_props_cache;
|
||||
static_assert (sizeof (glyph_props_cache) == 512, "");
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ struct PairPosFormat1_3
|
|||
{
|
||||
auto &cov = this+coverage;
|
||||
|
||||
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
|
||||
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len))
|
||||
{
|
||||
for (hb_codepoint_t g : glyphs->iter())
|
||||
{
|
||||
|
@ -103,12 +103,50 @@ struct PairPosFormat1_3
|
|||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
unsigned cache_cost () const
|
||||
{
|
||||
return (this+coverage).cost ();
|
||||
}
|
||||
static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case hb_ot_lookup_cache_op_t::CREATE:
|
||||
{
|
||||
hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
|
||||
if (likely (cache))
|
||||
cache->clear ();
|
||||
return cache;
|
||||
}
|
||||
case hb_ot_lookup_cache_op_t::ENTER:
|
||||
return (void *) true;
|
||||
case hb_ot_lookup_cache_op_t::LEAVE:
|
||||
return nullptr;
|
||||
case hb_ot_lookup_cache_op_t::DESTROY:
|
||||
{
|
||||
hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
|
||||
hb_free (cache);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
|
||||
bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache);
|
||||
#else
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
#endif
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
|
@ -156,7 +194,7 @@ struct PairPosFormat1_3
|
|||
strip = true;
|
||||
newFormats = compute_effective_value_formats (glyphset, strip, true);
|
||||
}
|
||||
|
||||
|
||||
out->valueFormat[0] = newFormats.first;
|
||||
out->valueFormat[1] = newFormats.second;
|
||||
|
||||
|
|
|
@ -123,12 +123,61 @@ struct PairPosFormat2_4 : ValueBase
|
|||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
struct pair_pos_cache_t
|
||||
{
|
||||
hb_ot_lookup_cache_t coverage;
|
||||
hb_ot_lookup_cache_t first;
|
||||
hb_ot_lookup_cache_t second;
|
||||
};
|
||||
|
||||
unsigned cache_cost () const
|
||||
{
|
||||
return (this+coverage).cost () + (this+classDef1).cost () + (this+classDef2).cost ();
|
||||
}
|
||||
static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case hb_ot_lookup_cache_op_t::CREATE:
|
||||
{
|
||||
pair_pos_cache_t *cache = (pair_pos_cache_t *) hb_malloc (sizeof (pair_pos_cache_t));
|
||||
if (likely (cache))
|
||||
{
|
||||
cache->coverage.clear ();
|
||||
cache->first.clear ();
|
||||
cache->second.clear ();
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
case hb_ot_lookup_cache_op_t::ENTER:
|
||||
return (void *) true;
|
||||
case hb_ot_lookup_cache_op_t::LEAVE:
|
||||
return nullptr;
|
||||
case hb_ot_lookup_cache_op_t::DESTROY:
|
||||
{
|
||||
pair_pos_cache_t *cache = (pair_pos_cache_t *) p;
|
||||
hb_free (cache);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
|
||||
bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
pair_pos_cache_t *cache = cached ? (pair_pos_cache_t *) c->lookup_accel->cache : nullptr;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
#else
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
#endif
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
|
@ -139,8 +188,13 @@ struct PairPosFormat2_4 : ValueBase
|
|||
return_trace (false);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint, cache ? &cache->first : nullptr);
|
||||
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint, cache ? &cache->second : nullptr);
|
||||
#else
|
||||
unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
|
||||
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
|
||||
#endif
|
||||
if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
|
||||
{
|
||||
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
|
||||
|
|
|
@ -67,7 +67,7 @@ struct SinglePosFormat1 : ValueBase
|
|||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
|
|
|
@ -66,7 +66,7 @@ struct SinglePosFormat2 : ValueBase
|
|||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
if (unlikely (index >= valueCount)) return_trace (false);
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ struct AlternateSubstFormat1_2
|
|||
TRACE_APPLY (this);
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
return_trace ((this+alternateSet[index]).apply (c));
|
||||
}
|
||||
|
|
|
@ -78,12 +78,49 @@ struct LigatureSubstFormat1_2
|
|||
return lig_set.would_apply (c);
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
unsigned cache_cost () const
|
||||
{
|
||||
return (this+coverage).cost ();
|
||||
}
|
||||
static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case hb_ot_lookup_cache_op_t::CREATE:
|
||||
{
|
||||
hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
|
||||
if (likely (cache))
|
||||
cache->clear ();
|
||||
return cache;
|
||||
}
|
||||
case hb_ot_lookup_cache_op_t::ENTER:
|
||||
return (void *) true;
|
||||
case hb_ot_lookup_cache_op_t::LEAVE:
|
||||
return nullptr;
|
||||
case hb_ot_lookup_cache_op_t::DESTROY:
|
||||
{
|
||||
hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
|
||||
hb_free (cache);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
|
||||
bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache);
|
||||
#else
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
#endif
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
const auto &lig_set = this+ligatureSet[index];
|
||||
return_trace (lig_set.apply (c));
|
||||
|
|
|
@ -66,7 +66,7 @@ struct MultipleSubstFormat1_2
|
|||
TRACE_APPLY (this);
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
return_trace ((this+sequence[index]).apply (c));
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
{
|
||||
TRACE_APPLY (this);
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
|
||||
return_trace (false); /* No chaining to this type */
|
||||
|
|
|
@ -128,7 +128,7 @@ struct SingleSubstFormat1_3
|
|||
TRACE_APPLY (this);
|
||||
hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
|
||||
unsigned int index = (this+coverage).get_coverage (glyph_id);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
hb_codepoint_t d = deltaGlyphID;
|
||||
hb_codepoint_t mask = get_mask ();
|
||||
|
|
|
@ -104,7 +104,7 @@ struct SingleSubstFormat2_4
|
|||
{
|
||||
TRACE_APPLY (this);
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
if (unlikely (index >= substitute.len)) return_trace (false);
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#ifndef OT_LAYOUT_TYPES_HH
|
||||
#define OT_LAYOUT_TYPES_HH
|
||||
|
||||
using hb_ot_lookup_cache_t = hb_cache_t<15, 8, 7>;
|
||||
static_assert (sizeof (hb_ot_lookup_cache_t) == 256, "");
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
|
||||
#include "../../../hb-draw.hh"
|
||||
#include "../../../hb-geometry.hh"
|
||||
#include "../../../hb-ot-layout-common.hh"
|
||||
#include "../../../hb-ot-layout-gdef-table.hh"
|
||||
|
||||
|
@ -127,24 +126,19 @@ hb_transforming_pen_get_funcs ()
|
|||
return static_transforming_pen_funcs.get_unconst ();
|
||||
}
|
||||
|
||||
|
||||
hb_ubytes_t
|
||||
VarComponent::get_path_at (hb_font_t *font,
|
||||
VarComponent::get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t parent_gid,
|
||||
hb_draw_session_t &draw_session,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t total_transform,
|
||||
hb_ubytes_t total_record,
|
||||
hb_set_t *visited,
|
||||
signed *edges_left,
|
||||
signed depth_left,
|
||||
VarRegionList::cache_t *cache) const
|
||||
{
|
||||
const unsigned char *end = total_record.arrayZ + total_record.length;
|
||||
const unsigned char *record = total_record.arrayZ;
|
||||
|
||||
auto &VARC = *font->face->table.VARC;
|
||||
auto &VARC = *c.font->face->table.VARC->table;
|
||||
auto &varStore = &VARC+VARC.varStore;
|
||||
auto instancer = MultiItemVarStoreInstancer(&varStore, nullptr, coords, cache);
|
||||
|
||||
#define READ_UINT32VAR(name) \
|
||||
HB_STMT_START { \
|
||||
|
@ -187,22 +181,25 @@ VarComponent::get_path_at (hb_font_t *font,
|
|||
unsigned conditionIndex;
|
||||
READ_UINT32VAR (conditionIndex);
|
||||
const auto &condition = (&VARC+VARC.conditionList)[conditionIndex];
|
||||
auto instancer = MultiItemVarStoreInstancer(&varStore, nullptr, coords, cache);
|
||||
show = condition.evaluate (coords.arrayZ, coords.length, &instancer);
|
||||
}
|
||||
|
||||
// Axis values
|
||||
|
||||
hb_vector_t<unsigned> axisIndices;
|
||||
hb_vector_t<float> axisValues;
|
||||
auto &axisIndices = c.scratch.axisIndices;
|
||||
axisIndices.clear ();
|
||||
auto &axisValues = c.scratch.axisValues;
|
||||
axisValues.clear ();
|
||||
if (flags & (unsigned) flags_t::HAVE_AXES)
|
||||
{
|
||||
unsigned axisIndicesIndex;
|
||||
READ_UINT32VAR (axisIndicesIndex);
|
||||
axisIndices = (&VARC+VARC.axisIndicesList)[axisIndicesIndex];
|
||||
axisIndices.extend ((&VARC+VARC.axisIndicesList)[axisIndicesIndex]);
|
||||
axisValues.resize (axisIndices.length);
|
||||
const HBUINT8 *p = (const HBUINT8 *) record;
|
||||
TupleValues::decompile (p, axisValues, (const HBUINT8 *) end);
|
||||
record += (const unsigned char *) p - record;
|
||||
record = (const unsigned char *) p;
|
||||
}
|
||||
|
||||
// Apply variations if any
|
||||
|
@ -219,7 +216,7 @@ VarComponent::get_path_at (hb_font_t *font,
|
|||
* limit on the max number of coords for now. */
|
||||
if ((flags & (unsigned) flags_t::RESET_UNSPECIFIED_AXES) ||
|
||||
coords.length > HB_VAR_COMPOSITE_MAX_AXES)
|
||||
component_coords = hb_array<int> (font->coords, font->num_coords);
|
||||
component_coords = hb_array<int> (c.font->coords, c.font->num_coords);
|
||||
|
||||
// Transform
|
||||
|
||||
|
@ -312,26 +309,19 @@ VarComponent::get_path_at (hb_font_t *font,
|
|||
if (!(flags & (unsigned) flags_t::HAVE_SCALE_Y))
|
||||
transform.scaleY = transform.scaleX;
|
||||
|
||||
// Scale the transform by the font's scale
|
||||
float x_scale = font->x_multf;
|
||||
float y_scale = font->y_multf;
|
||||
transform.translateX *= x_scale;
|
||||
transform.translateY *= y_scale;
|
||||
transform.tCenterX *= x_scale;
|
||||
transform.tCenterY *= y_scale;
|
||||
total_transform.transform (transform.to_transform ());
|
||||
total_transform.scale (c.font->x_mult ? 1.f / c.font->x_multf : 0.f,
|
||||
c.font->y_mult ? 1.f / c.font->y_multf : 0.f);
|
||||
|
||||
// Build a transforming pen to apply the transform.
|
||||
hb_draw_funcs_t *transformer_funcs = hb_transforming_pen_get_funcs ();
|
||||
hb_transforming_pen_context_t context {transform.to_transform (),
|
||||
draw_session.funcs,
|
||||
draw_session.draw_data,
|
||||
&draw_session.st};
|
||||
hb_draw_session_t transformer_session {transformer_funcs, &context};
|
||||
bool same_coords = component_coords.length == coords.length &&
|
||||
component_coords.arrayZ == coords.arrayZ;
|
||||
|
||||
VARC.get_path_at (font, gid,
|
||||
transformer_session, component_coords,
|
||||
c.depth_left--;
|
||||
VARC.get_path_at (c, gid,
|
||||
component_coords, total_transform,
|
||||
parent_gid,
|
||||
visited, edges_left, depth_left - 1);
|
||||
same_coords ? cache : nullptr);
|
||||
c.depth_left++;
|
||||
}
|
||||
|
||||
#undef PROCESS_TRANSFORM_COMPONENTS
|
||||
|
@ -340,6 +330,87 @@ VarComponent::get_path_at (hb_font_t *font,
|
|||
return hb_ubytes_t (record, end - record);
|
||||
}
|
||||
|
||||
bool
|
||||
VARC::get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t glyph,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_codepoint_t parent_glyph,
|
||||
VarRegionList::cache_t *parent_cache) const
|
||||
{
|
||||
// Don't recurse on the same glyph.
|
||||
unsigned idx = glyph == parent_glyph ?
|
||||
NOT_COVERED :
|
||||
(this+coverage).get_coverage (glyph);
|
||||
if (idx == NOT_COVERED)
|
||||
{
|
||||
if (c.draw_session)
|
||||
{
|
||||
// Build a transforming pen to apply the transform.
|
||||
hb_draw_funcs_t *transformer_funcs = hb_transforming_pen_get_funcs ();
|
||||
hb_transforming_pen_context_t context {transform,
|
||||
c.draw_session->funcs,
|
||||
c.draw_session->draw_data,
|
||||
&c.draw_session->st};
|
||||
hb_draw_session_t transformer_session {transformer_funcs, &context};
|
||||
hb_draw_session_t &shape_draw_session = transform.is_identity () ? *c.draw_session : transformer_session;
|
||||
|
||||
if (!c.font->face->table.glyf->get_path_at (c.font, glyph, shape_draw_session, coords, c.scratch.glyf_scratch))
|
||||
#ifndef HB_NO_CFF
|
||||
if (!c.font->face->table.cff2->get_path_at (c.font, glyph, shape_draw_session, coords))
|
||||
if (!c.font->face->table.cff1->get_path (c.font, glyph, shape_draw_session)) // Doesn't have variations
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
else if (c.extents)
|
||||
{
|
||||
hb_glyph_extents_t glyph_extents;
|
||||
if (!c.font->face->table.glyf->get_extents_at (c.font, glyph, &glyph_extents, coords))
|
||||
#ifndef HB_NO_CFF
|
||||
if (!c.font->face->table.cff2->get_extents_at (c.font, glyph, &glyph_extents, coords))
|
||||
if (!c.font->face->table.cff1->get_extents (c.font, glyph, &glyph_extents)) // Doesn't have variations
|
||||
#endif
|
||||
return false;
|
||||
|
||||
hb_extents_t comp_extents (glyph_extents);
|
||||
transform.transform_extents (comp_extents);
|
||||
c.extents->union_ (comp_extents);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c.depth_left <= 0)
|
||||
return true;
|
||||
|
||||
if (c.edges_left <= 0)
|
||||
return true;
|
||||
(c.edges_left)--;
|
||||
|
||||
hb_decycler_node_t node (c.decycler);
|
||||
if (unlikely (!node.visit (glyph)))
|
||||
return true;
|
||||
|
||||
hb_ubytes_t record = (this+glyphRecords)[idx];
|
||||
|
||||
VarRegionList::cache_t static_cache[sizeof (void *) * 16];
|
||||
VarRegionList::cache_t *cache = parent_cache ?
|
||||
parent_cache :
|
||||
(this+varStore).create_cache (hb_array (static_cache));
|
||||
|
||||
transform.scale (c.font->x_multf, c.font->y_multf);
|
||||
|
||||
VarCompositeGlyph::get_path_at (c,
|
||||
glyph,
|
||||
coords, transform,
|
||||
record,
|
||||
cache);
|
||||
|
||||
if (cache != parent_cache)
|
||||
(this+varStore).destroy_cache (cache, hb_array (static_cache));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//} // namespace Var
|
||||
} // namespace OT
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef OT_VAR_VARC_VARC_HH
|
||||
#define OT_VAR_VARC_VARC_HH
|
||||
|
||||
#include "../../../hb-decycler.hh"
|
||||
#include "../../../hb-geometry.hh"
|
||||
#include "../../../hb-ot-layout-common.hh"
|
||||
#include "../../../hb-ot-glyf-table.hh"
|
||||
#include "../../../hb-ot-cff2-table.hh"
|
||||
|
@ -19,6 +21,24 @@ namespace OT {
|
|||
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
|
||||
struct hb_varc_scratch_t
|
||||
{
|
||||
hb_vector_t<unsigned> axisIndices;
|
||||
hb_vector_t<float> axisValues;
|
||||
hb_glyf_scratch_t glyf_scratch;
|
||||
};
|
||||
|
||||
struct hb_varc_context_t
|
||||
{
|
||||
hb_font_t *font;
|
||||
hb_draw_session_t *draw_session;
|
||||
hb_extents_t *extents;
|
||||
mutable hb_decycler_t decycler;
|
||||
mutable signed edges_left;
|
||||
mutable signed depth_left;
|
||||
hb_varc_scratch_t &scratch;
|
||||
};
|
||||
|
||||
struct VarComponent
|
||||
{
|
||||
enum class flags_t : uint32_t
|
||||
|
@ -42,37 +62,32 @@ struct VarComponent
|
|||
};
|
||||
|
||||
HB_INTERNAL hb_ubytes_t
|
||||
get_path_at (hb_font_t *font,
|
||||
get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t parent_gid,
|
||||
hb_draw_session_t &draw_session,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_ubytes_t record,
|
||||
hb_set_t *visited,
|
||||
signed *edges_left,
|
||||
signed depth_left,
|
||||
VarRegionList::cache_t *cache = nullptr) const;
|
||||
};
|
||||
|
||||
struct VarCompositeGlyph
|
||||
{
|
||||
static void
|
||||
get_path_at (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_session_t &draw_session,
|
||||
get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t gid,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_ubytes_t record,
|
||||
hb_set_t *visited,
|
||||
signed *edges_left,
|
||||
signed depth_left,
|
||||
VarRegionList::cache_t *cache = nullptr)
|
||||
VarRegionList::cache_t *cache)
|
||||
{
|
||||
while (record)
|
||||
{
|
||||
const VarComponent &comp = * (const VarComponent *) (record.arrayZ);
|
||||
record = comp.get_path_at (font, glyph,
|
||||
draw_session, coords,
|
||||
record = comp.get_path_at (c,
|
||||
gid,
|
||||
coords, transform,
|
||||
record,
|
||||
visited, edges_left, depth_left, cache);
|
||||
cache);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -85,79 +100,48 @@ struct VARC
|
|||
|
||||
static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C');
|
||||
|
||||
bool
|
||||
get_path_at (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_session_t &draw_session,
|
||||
HB_INTERNAL bool
|
||||
get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t gid,
|
||||
hb_array_t<const int> coords,
|
||||
hb_codepoint_t parent_glyph = HB_CODEPOINT_INVALID,
|
||||
hb_set_t *visited = nullptr,
|
||||
signed *edges_left = nullptr,
|
||||
signed depth_left = HB_MAX_NESTING_LEVEL) const
|
||||
hb_transform_t transform = HB_TRANSFORM_IDENTITY,
|
||||
hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID,
|
||||
VarRegionList::cache_t *parent_cache = nullptr) const;
|
||||
|
||||
bool
|
||||
get_path (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_draw_session_t &draw_session,
|
||||
hb_varc_scratch_t &scratch) const
|
||||
{
|
||||
hb_set_t stack_set;
|
||||
if (visited == nullptr)
|
||||
visited = &stack_set;
|
||||
signed stack_edges = HB_MAX_GRAPH_EDGE_COUNT;
|
||||
if (edges_left == nullptr)
|
||||
edges_left = &stack_edges;
|
||||
hb_varc_context_t c {font,
|
||||
&draw_session,
|
||||
nullptr,
|
||||
hb_decycler_t {},
|
||||
HB_MAX_GRAPH_EDGE_COUNT,
|
||||
HB_MAX_NESTING_LEVEL,
|
||||
scratch};
|
||||
|
||||
// Don't recurse on the same glyph.
|
||||
unsigned idx = glyph == parent_glyph ?
|
||||
NOT_COVERED :
|
||||
(this+coverage).get_coverage (glyph);
|
||||
if (idx == NOT_COVERED)
|
||||
{
|
||||
if (!font->face->table.glyf->get_path_at (font, glyph, draw_session, coords))
|
||||
#ifndef HB_NO_CFF
|
||||
if (!font->face->table.cff2->get_path_at (font, glyph, draw_session, coords))
|
||||
if (!font->face->table.cff1->get_path (font, glyph, draw_session)) // Doesn't have variations
|
||||
#endif
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (depth_left <= 0)
|
||||
return true;
|
||||
|
||||
if (*edges_left <= 0)
|
||||
return true;
|
||||
(*edges_left)--;
|
||||
|
||||
if (visited->has (glyph) || visited->in_error ())
|
||||
return true;
|
||||
visited->add (glyph);
|
||||
|
||||
hb_ubytes_t record = (this+glyphRecords)[idx];
|
||||
|
||||
VarRegionList::cache_t *cache = record.length >= 64 ? // Heuristic
|
||||
(this+varStore).create_cache ()
|
||||
: nullptr;
|
||||
|
||||
VarCompositeGlyph::get_path_at (font, glyph,
|
||||
draw_session, coords,
|
||||
record,
|
||||
visited, edges_left, depth_left,
|
||||
cache);
|
||||
|
||||
(this+varStore).destroy_cache (cache);
|
||||
|
||||
visited->del (glyph);
|
||||
|
||||
return true;
|
||||
return get_path_at (c, gid,
|
||||
hb_array (font->coords, font->num_coords));
|
||||
}
|
||||
|
||||
bool
|
||||
get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
|
||||
{ return get_path_at (font, gid, draw_session, hb_array (font->coords, font->num_coords)); }
|
||||
|
||||
bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
|
||||
get_extents (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_extents_t *extents,
|
||||
hb_varc_scratch_t &scratch) const
|
||||
{
|
||||
funcs->push_clip_glyph (data, gid, font);
|
||||
funcs->color (data, true, foreground);
|
||||
funcs->pop_clip (data);
|
||||
hb_varc_context_t c {font,
|
||||
nullptr,
|
||||
extents,
|
||||
hb_decycler_t {},
|
||||
HB_MAX_GRAPH_EDGE_COUNT,
|
||||
HB_MAX_NESTING_LEVEL,
|
||||
scratch};
|
||||
|
||||
return true;
|
||||
return get_path_at (c, gid,
|
||||
hb_array (font->coords, font->num_coords));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -173,6 +157,89 @@ struct VARC
|
|||
glyphRecords.sanitize (c, this));
|
||||
}
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
friend struct VarComponent;
|
||||
|
||||
accelerator_t (hb_face_t *face)
|
||||
{
|
||||
table = hb_sanitize_context_t ().reference_table<VARC> (face);
|
||||
}
|
||||
~accelerator_t ()
|
||||
{
|
||||
auto *scratch = cached_scratch.get_relaxed ();
|
||||
if (scratch)
|
||||
{
|
||||
scratch->~hb_varc_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
|
||||
table.destroy ();
|
||||
}
|
||||
|
||||
bool
|
||||
get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
|
||||
{
|
||||
if (!table->has_data ()) return false;
|
||||
|
||||
auto *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch)) return true;
|
||||
bool ret = table->get_path (font, gid, draw_session, *scratch);
|
||||
release_scratch (scratch);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
get_extents (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
if (!table->has_data ()) return false;
|
||||
|
||||
hb_extents_t f_extents;
|
||||
|
||||
auto *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch)) return true;
|
||||
bool ret = table->get_extents (font, gid, &f_extents, *scratch);
|
||||
release_scratch (scratch);
|
||||
|
||||
if (ret)
|
||||
*extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
hb_varc_scratch_t *acquire_scratch () const
|
||||
{
|
||||
hb_varc_scratch_t *scratch = cached_scratch.get_acquire ();
|
||||
|
||||
if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
|
||||
{
|
||||
scratch = (hb_varc_scratch_t *) hb_calloc (1, sizeof (hb_varc_scratch_t));
|
||||
if (unlikely (!scratch))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return scratch;
|
||||
}
|
||||
void release_scratch (hb_varc_scratch_t *scratch) const
|
||||
{
|
||||
if (!cached_scratch.cmpexch (nullptr, scratch))
|
||||
{
|
||||
scratch->~hb_varc_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
hb_blob_ptr_t<VARC> table;
|
||||
hb_atomic_t<hb_varc_scratch_t *> cached_scratch;
|
||||
};
|
||||
|
||||
bool has_data () const { return version.major != 0; }
|
||||
|
||||
protected:
|
||||
FixedVersion<> version; /* Version identifier */
|
||||
Offset32To<Coverage> coverage;
|
||||
|
@ -184,6 +251,10 @@ struct VARC
|
|||
DEFINE_SIZE_STATIC (24);
|
||||
};
|
||||
|
||||
struct VARC_accelerator_t : VARC::accelerator_t {
|
||||
VARC_accelerator_t (hb_face_t *face) : VARC::accelerator_t (face) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//}
|
||||
|
|
|
@ -11,22 +11,48 @@ namespace OT {
|
|||
|
||||
struct coord_setter_t
|
||||
{
|
||||
coord_setter_t (hb_array_t<const int> coords) :
|
||||
coords (coords) {}
|
||||
coord_setter_t (hb_array_t<const int> coords_)
|
||||
{
|
||||
length = coords_.length;
|
||||
if (length <= ARRAY_LENGTH (static_coords))
|
||||
hb_memcpy (static_coords, coords_.arrayZ, length * sizeof (int));
|
||||
else
|
||||
dynamic_coords.extend (coords_);
|
||||
}
|
||||
|
||||
int& operator [] (unsigned idx)
|
||||
{
|
||||
if (unlikely (idx >= HB_VAR_COMPOSITE_MAX_AXES))
|
||||
return Crap(int);
|
||||
if (coords.length < idx + 1)
|
||||
coords.resize (idx + 1);
|
||||
return coords[idx];
|
||||
|
||||
if (length <= ARRAY_LENGTH (static_coords))
|
||||
{
|
||||
if (idx < ARRAY_LENGTH (static_coords))
|
||||
{
|
||||
while (length <= idx)
|
||||
static_coords[length++] = 0;
|
||||
return static_coords[idx];
|
||||
}
|
||||
else
|
||||
dynamic_coords.extend (hb_array (static_coords, length));
|
||||
}
|
||||
|
||||
if (dynamic_coords.length <= idx)
|
||||
{
|
||||
if (unlikely (!dynamic_coords.resize (idx + 1)))
|
||||
return Crap(int);
|
||||
length = idx + 1;
|
||||
}
|
||||
return dynamic_coords.arrayZ[idx];
|
||||
}
|
||||
|
||||
hb_array_t<int> get_coords ()
|
||||
{ return coords.as_array (); }
|
||||
{ return length <= ARRAY_LENGTH (static_coords) ? hb_array (static_coords, length) : dynamic_coords.as_array (); }
|
||||
|
||||
hb_vector_t<int> coords;
|
||||
private:
|
||||
hb_vector_t<int> dynamic_coords;
|
||||
unsigned length;
|
||||
int static_coords[sizeof (void *) * 8];
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ struct CompositeGlyphRecord
|
|||
float matrix[4];
|
||||
contour_point_t trans;
|
||||
get_transformation (matrix, trans);
|
||||
if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points
|
||||
if (unlikely (!points.alloc (points.length + 1 + 4))) return false; // For phantom points
|
||||
points.push (trans);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -251,7 +251,8 @@ struct Glyph
|
|||
composite_contours_p = nullptr;
|
||||
}
|
||||
|
||||
if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
|
||||
hb_glyf_scratch_t scratch;
|
||||
if (!get_points (font, glyf, all_points, scratch, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
|
||||
return false;
|
||||
|
||||
// .notdef, set type to empty so we only update metrics and don't compile bytes for
|
||||
|
@ -305,6 +306,7 @@ struct Glyph
|
|||
template <typename accelerator_t>
|
||||
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
||||
contour_point_vector_t &all_points /* OUT */,
|
||||
hb_glyf_scratch_t &scratch,
|
||||
contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
|
||||
head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
|
||||
unsigned *composite_contours = nullptr, /* OUT */
|
||||
|
@ -312,7 +314,6 @@ struct Glyph
|
|||
bool use_my_metrics = true,
|
||||
bool phantom_only = false,
|
||||
hb_array_t<const int> coords = hb_array_t<const int> (),
|
||||
hb_map_t *current_glyphs = nullptr,
|
||||
unsigned int depth = 0,
|
||||
unsigned *edge_count = nullptr) const
|
||||
{
|
||||
|
@ -322,10 +323,6 @@ struct Glyph
|
|||
if (unlikely (*edge_count > HB_MAX_GRAPH_EDGE_COUNT)) return false;
|
||||
(*edge_count)++;
|
||||
|
||||
hb_map_t current_glyphs_stack;
|
||||
if (current_glyphs == nullptr)
|
||||
current_glyphs = ¤t_glyphs_stack;
|
||||
|
||||
if (head_maxp_info)
|
||||
{
|
||||
head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
|
||||
|
@ -334,8 +331,7 @@ struct Glyph
|
|||
if (!coords)
|
||||
coords = hb_array (font->coords, font->num_coords);
|
||||
|
||||
contour_point_vector_t stack_points;
|
||||
contour_point_vector_t &points = type == SIMPLE ? all_points : stack_points;
|
||||
contour_point_vector_t &points = type == SIMPLE ? all_points : scratch.comp_points;
|
||||
unsigned old_length = points.length;
|
||||
|
||||
switch (type) {
|
||||
|
@ -388,36 +384,53 @@ struct Glyph
|
|||
|
||||
#ifndef HB_NO_VAR
|
||||
if (coords)
|
||||
glyf_accelerator.gvar->apply_deltas_to_points (gid,
|
||||
coords,
|
||||
points.as_array ().sub_array (old_length),
|
||||
phantom_only && type == SIMPLE);
|
||||
{
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (glyf_accelerator.GVAR->has_data ())
|
||||
glyf_accelerator.GVAR->apply_deltas_to_points (gid,
|
||||
coords,
|
||||
points.as_array ().sub_array (old_length),
|
||||
scratch,
|
||||
phantom_only && type == SIMPLE);
|
||||
else
|
||||
#endif
|
||||
glyf_accelerator.gvar->apply_deltas_to_points (gid,
|
||||
coords,
|
||||
points.as_array ().sub_array (old_length),
|
||||
scratch,
|
||||
phantom_only && type == SIMPLE);
|
||||
}
|
||||
#endif
|
||||
|
||||
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
|
||||
// with child glyphs' points
|
||||
if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||
{
|
||||
if (unlikely (!points_with_deltas->resize (points.length))) return false;
|
||||
assert (old_length == 0);
|
||||
*points_with_deltas = points;
|
||||
}
|
||||
|
||||
float shift = 0;
|
||||
switch (type) {
|
||||
case SIMPLE:
|
||||
if (depth == 0 && head_maxp_info)
|
||||
head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, all_points.length - old_length - 4);
|
||||
shift = phantoms[PHANTOM_LEFT].x;
|
||||
break;
|
||||
case COMPOSITE:
|
||||
{
|
||||
hb_decycler_node_t decycler_node (scratch.decycler);
|
||||
|
||||
unsigned int comp_index = 0;
|
||||
for (auto &item : get_composite_iterator ())
|
||||
{
|
||||
hb_codepoint_t item_gid = item.get_gid ();
|
||||
|
||||
if (unlikely (current_glyphs->has (item_gid)))
|
||||
if (unlikely (!decycler_node.visit (item_gid)))
|
||||
{
|
||||
comp_index++;
|
||||
continue;
|
||||
|
||||
current_glyphs->add (item_gid);
|
||||
}
|
||||
|
||||
unsigned old_count = all_points.length;
|
||||
|
||||
|
@ -426,6 +439,7 @@ struct Glyph
|
|||
.get_points (font,
|
||||
glyf_accelerator,
|
||||
all_points,
|
||||
scratch,
|
||||
points_with_deltas,
|
||||
head_maxp_info,
|
||||
composite_contours,
|
||||
|
@ -433,14 +447,16 @@ struct Glyph
|
|||
use_my_metrics,
|
||||
phantom_only,
|
||||
coords,
|
||||
current_glyphs,
|
||||
depth + 1,
|
||||
edge_count)))
|
||||
{
|
||||
current_glyphs->del (item_gid);
|
||||
points.resize (old_length);
|
||||
return false;
|
||||
}
|
||||
|
||||
// points might have been reallocated. Relocate phantoms.
|
||||
phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
||||
|
||||
auto comp_points = all_points.as_array ().sub_array (old_count);
|
||||
|
||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||
|
@ -455,7 +471,7 @@ struct Glyph
|
|||
item.get_transformation (matrix, default_trans);
|
||||
|
||||
/* Apply component transformation & translation (with deltas applied) */
|
||||
item.transform_points (comp_points, matrix, points[comp_index]);
|
||||
item.transform_points (comp_points, matrix, points[old_length + comp_index]);
|
||||
}
|
||||
|
||||
if (item.is_anchored () && !phantom_only)
|
||||
|
@ -476,12 +492,11 @@ struct Glyph
|
|||
|
||||
if (all_points.length > HB_GLYF_MAX_POINTS)
|
||||
{
|
||||
current_glyphs->del (item_gid);
|
||||
points.resize (old_length);
|
||||
return false;
|
||||
}
|
||||
|
||||
comp_index++;
|
||||
current_glyphs->del (item_gid);
|
||||
}
|
||||
|
||||
if (head_maxp_info && depth == 0)
|
||||
|
@ -492,9 +507,13 @@ struct Glyph
|
|||
head_maxp_info->maxComponentElements = hb_max (head_maxp_info->maxComponentElements, comp_index);
|
||||
}
|
||||
all_points.extend (phantoms);
|
||||
shift = phantoms[PHANTOM_LEFT].x;
|
||||
points.resize (old_length);
|
||||
} break;
|
||||
case EMPTY:
|
||||
all_points.extend (phantoms);
|
||||
shift = phantoms[PHANTOM_LEFT].x;
|
||||
points.resize (old_length);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -503,10 +522,9 @@ struct Glyph
|
|||
/* Undocumented rasterizer behavior:
|
||||
* Shift points horizontally by the updated left side bearing
|
||||
*/
|
||||
float v = -phantoms[PHANTOM_LEFT].x;
|
||||
if (v)
|
||||
if (shift)
|
||||
for (auto &point : all_points)
|
||||
point.x += v;
|
||||
point.x -= shift;
|
||||
}
|
||||
|
||||
return !all_points.in_error ();
|
||||
|
|
|
@ -127,19 +127,20 @@ struct SimpleGlyph
|
|||
hb_array_t<contour_point_t> points_ /* IN/OUT */,
|
||||
const HBUINT8 *end)
|
||||
{
|
||||
auto *points = points_.arrayZ;
|
||||
unsigned count = points_.length;
|
||||
for (unsigned int i = 0; i < count;)
|
||||
{
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
uint8_t flag = *p++;
|
||||
points_.arrayZ[i++].flag = flag;
|
||||
points[i++].flag = flag;
|
||||
if (flag & FLAG_REPEAT)
|
||||
{
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
unsigned int repeat_count = *p++;
|
||||
unsigned stop = hb_min (i + repeat_count, count);
|
||||
for (; i < stop; i++)
|
||||
points_.arrayZ[i].flag = flag;
|
||||
points[i].flag = flag;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -160,10 +161,7 @@ struct SimpleGlyph
|
|||
if (flag & short_flag)
|
||||
{
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
if (flag & same_flag)
|
||||
v += *p++;
|
||||
else
|
||||
v -= *p++;
|
||||
v += (bool(flag & same_flag) * 2 - 1) * *p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -190,7 +188,7 @@ struct SimpleGlyph
|
|||
unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
|
||||
|
||||
unsigned old_length = points.length;
|
||||
points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy
|
||||
points.alloc (points.length + num_points + 4); // Allocate for phantom points, to avoid a possible copy
|
||||
if (unlikely (!points.resize (points.length + num_points, false))) return false;
|
||||
auto points_ = points.as_array ().sub_array (old_length);
|
||||
if (!phantom_only)
|
||||
|
@ -281,9 +279,9 @@ struct SimpleGlyph
|
|||
unsigned num_points = all_points.length - 4;
|
||||
|
||||
hb_vector_t<uint8_t> flags, x_coords, y_coords;
|
||||
if (unlikely (!flags.alloc (num_points, true))) return false;
|
||||
if (unlikely (!x_coords.alloc (2*num_points, true))) return false;
|
||||
if (unlikely (!y_coords.alloc (2*num_points, true))) return false;
|
||||
if (unlikely (!flags.alloc_exact (num_points))) return false;
|
||||
if (unlikely (!x_coords.alloc_exact (2*num_points))) return false;
|
||||
if (unlikely (!y_coords.alloc_exact (2*num_points))) return false;
|
||||
|
||||
unsigned lastflag = 255, repeat = 0;
|
||||
int prev_x = 0, prev_y = 0;
|
||||
|
|
|
@ -94,7 +94,7 @@ struct glyf
|
|||
}
|
||||
|
||||
hb_vector_t<unsigned> padded_offsets;
|
||||
if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true)))
|
||||
if (unlikely (!padded_offsets.alloc_exact (c->plan->new_to_old_gid_list.length)))
|
||||
return_trace (false);
|
||||
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
|
||||
|
@ -172,6 +172,9 @@ struct glyf_accelerator_t
|
|||
glyf_table = nullptr;
|
||||
#ifndef HB_NO_VAR
|
||||
gvar = nullptr;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
GVAR = nullptr;
|
||||
#endif
|
||||
#endif
|
||||
hmtx = nullptr;
|
||||
#ifndef HB_NO_VERTICAL
|
||||
|
@ -187,6 +190,9 @@ struct glyf_accelerator_t
|
|||
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
|
||||
#ifndef HB_NO_VAR
|
||||
gvar = face->table.gvar;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
GVAR = face->table.GVAR;
|
||||
#endif
|
||||
#endif
|
||||
hmtx = face->table.hmtx;
|
||||
#ifndef HB_NO_VERTICAL
|
||||
|
@ -198,6 +204,13 @@ struct glyf_accelerator_t
|
|||
}
|
||||
~glyf_accelerator_t ()
|
||||
{
|
||||
auto *scratch = cached_scratch.get_relaxed ();
|
||||
if (scratch)
|
||||
{
|
||||
scratch->~hb_glyf_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
|
||||
glyf_table.destroy ();
|
||||
}
|
||||
|
||||
|
@ -206,21 +219,16 @@ struct glyf_accelerator_t
|
|||
protected:
|
||||
template<typename T>
|
||||
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer,
|
||||
hb_array_t<const int> coords = hb_array_t<const int> ()) const
|
||||
hb_array_t<const int> coords,
|
||||
hb_glyf_scratch_t &scratch) const
|
||||
{
|
||||
if (!coords)
|
||||
coords = hb_array (font->coords, font->num_coords);
|
||||
|
||||
if (gid >= num_glyphs) return false;
|
||||
|
||||
/* Making this allocfree is not that easy
|
||||
https://github.com/harfbuzz/harfbuzz/issues/2095
|
||||
mostly because of gvar handling in VF fonts,
|
||||
perhaps a separate path for non-VF fonts can be considered */
|
||||
contour_point_vector_t all_points;
|
||||
auto &all_points = scratch.all_points;
|
||||
all_points.resize (0);
|
||||
|
||||
bool phantom_only = !consumer.is_consuming_contour_points ();
|
||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only, coords)))
|
||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, scratch, nullptr, nullptr, nullptr, true, true, phantom_only, coords)))
|
||||
return false;
|
||||
|
||||
unsigned count = all_points.length;
|
||||
|
@ -229,8 +237,61 @@ struct glyf_accelerator_t
|
|||
|
||||
if (consumer.is_consuming_contour_points ())
|
||||
{
|
||||
for (auto &point : all_points.as_array ().sub_array (0, count))
|
||||
consumer.consume_point (point);
|
||||
auto *points = all_points.arrayZ;
|
||||
|
||||
if (false)
|
||||
{
|
||||
/* Our path-builder was designed to work with this simple loop.
|
||||
* But FreeType and CoreText do it differently, so we match those
|
||||
* with the other, more complicated, code branch below. */
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
consumer.consume_point (points[i]);
|
||||
if (points[i].is_end_point)
|
||||
consumer.contour_end ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
// Start of a contour.
|
||||
if (points[i].flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE)
|
||||
{
|
||||
// First point is on-curve. Draw the contour.
|
||||
for (; i < count; i++)
|
||||
{
|
||||
consumer.consume_point (points[i]);
|
||||
if (points[i].is_end_point)
|
||||
{
|
||||
consumer.contour_end ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned start = i;
|
||||
|
||||
// Find end of the contour.
|
||||
for (; i < count; i++)
|
||||
if (points[i].is_end_point)
|
||||
break;
|
||||
|
||||
unsigned end = i;
|
||||
|
||||
// Enough to start from the end. Our path-builder takes care of the rest.
|
||||
if (likely (end < count)) // Can only fail in case of alloc failure *maybe*.
|
||||
consumer.consume_point (points[end]);
|
||||
|
||||
for (i = start; i < end; i++)
|
||||
consumer.consume_point (points[i]);
|
||||
|
||||
consumer.contour_end ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
consumer.points_end ();
|
||||
}
|
||||
|
||||
|
@ -303,6 +364,7 @@ struct glyf_accelerator_t
|
|||
|
||||
HB_ALWAYS_INLINE
|
||||
void consume_point (const contour_point_t &point) { bounds.add (point); }
|
||||
void contour_end () {}
|
||||
void points_end () { bounds.get_extents (font, extents, scaled); }
|
||||
|
||||
bool is_consuming_contour_points () { return extents; }
|
||||
|
@ -318,7 +380,12 @@ struct glyf_accelerator_t
|
|||
|
||||
contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
|
||||
if (font->num_coords)
|
||||
success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false));
|
||||
{
|
||||
hb_glyf_scratch_t scratch;
|
||||
success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false),
|
||||
hb_array (font->coords, font->num_coords),
|
||||
scratch);
|
||||
}
|
||||
|
||||
if (unlikely (!success))
|
||||
return
|
||||
|
@ -338,9 +405,11 @@ struct glyf_accelerator_t
|
|||
if (unlikely (gid >= num_glyphs)) return false;
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
|
||||
hb_glyf_scratch_t scratch;
|
||||
contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
|
||||
if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false))))
|
||||
if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false),
|
||||
hb_array (font->coords, font->num_coords),
|
||||
scratch)))
|
||||
return false;
|
||||
|
||||
*lsb = is_vertical
|
||||
|
@ -360,26 +429,33 @@ struct glyf_accelerator_t
|
|||
}
|
||||
|
||||
public:
|
||||
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
||||
|
||||
bool get_extents (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{ return get_extents_at (font, gid, extents, hb_array (font->coords, font->num_coords)); }
|
||||
|
||||
bool get_extents_at (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents,
|
||||
hb_array_t<const int> coords) const
|
||||
{
|
||||
if (unlikely (gid >= num_glyphs)) return false;
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (font->num_coords)
|
||||
return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true));
|
||||
if (coords)
|
||||
{
|
||||
hb_glyf_scratch_t scratch;
|
||||
return get_points (font,
|
||||
gid,
|
||||
points_aggregator_t (font, extents, nullptr, true),
|
||||
coords,
|
||||
scratch);
|
||||
}
|
||||
#endif
|
||||
return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
|
||||
}
|
||||
|
||||
bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
|
||||
{
|
||||
funcs->push_clip_glyph (data, gid, font);
|
||||
funcs->color (data, true, foreground);
|
||||
funcs->pop_clip (data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const glyf_impl::Glyph
|
||||
glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
|
||||
{
|
||||
|
@ -410,15 +486,52 @@ struct glyf_accelerator_t
|
|||
|
||||
bool
|
||||
get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
|
||||
{ return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); }
|
||||
{
|
||||
if (!has_data ()) return false;
|
||||
|
||||
hb_glyf_scratch_t *scratch;
|
||||
|
||||
// Borrow the cached strach buffer.
|
||||
{
|
||||
scratch = cached_scratch.get_acquire ();
|
||||
if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
|
||||
{
|
||||
scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t));
|
||||
if (unlikely (!scratch))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
|
||||
hb_array (font->coords, font->num_coords),
|
||||
*scratch);
|
||||
|
||||
// Put it back.
|
||||
if (!cached_scratch.cmpexch (nullptr, scratch))
|
||||
{
|
||||
scratch->~hb_glyf_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
get_path_at (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session,
|
||||
hb_array_t<const int> coords) const
|
||||
{ return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session), coords); }
|
||||
hb_array_t<const int> coords,
|
||||
hb_glyf_scratch_t &scratch) const
|
||||
{
|
||||
if (!has_data ()) return false;
|
||||
return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
|
||||
coords,
|
||||
scratch);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
const gvar_accelerator_t *gvar;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
const GVAR_accelerator_t *GVAR;
|
||||
#endif
|
||||
#endif
|
||||
const hmtx_accelerator_t *hmtx;
|
||||
#ifndef HB_NO_VERTICAL
|
||||
|
@ -430,6 +543,7 @@ struct glyf_accelerator_t
|
|||
unsigned int num_glyphs;
|
||||
hb_blob_ptr_t<loca> loca_table;
|
||||
hb_blob_ptr_t<glyf> glyf_table;
|
||||
hb_atomic_t<hb_glyf_scratch_t *> cached_scratch;
|
||||
};
|
||||
|
||||
|
||||
|
@ -439,7 +553,7 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
|||
hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
|
||||
{
|
||||
OT::glyf_accelerator_t glyf (plan->source);
|
||||
if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false;
|
||||
if (!glyphs.alloc_exact (plan->new_to_old_gid_list.length)) return false;
|
||||
|
||||
for (const auto &pair : plan->new_to_old_gid_list)
|
||||
{
|
||||
|
|
|
@ -42,7 +42,7 @@ struct path_builder_t
|
|||
{
|
||||
bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
|
||||
#ifdef HB_NO_CUBIC_GLYF
|
||||
bool is_cubic = false;
|
||||
constexpr bool is_cubic = false;
|
||||
#else
|
||||
bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
|
||||
#endif
|
||||
|
@ -124,58 +124,60 @@ struct path_builder_t
|
|||
}
|
||||
}
|
||||
|
||||
if (unlikely (point.is_end_point))
|
||||
{
|
||||
if (first_offcurve && last_offcurve)
|
||||
{
|
||||
optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
|
||||
first_offcurve2 :
|
||||
first_offcurve);
|
||||
if (last_offcurve2)
|
||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
||||
last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
else
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
last_offcurve = optional_point_t ();
|
||||
}
|
||||
/* now check the rest */
|
||||
|
||||
if (first_offcurve && first_oncurve)
|
||||
{
|
||||
if (first_offcurve2)
|
||||
draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
|
||||
first_offcurve.x, first_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else
|
||||
draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
}
|
||||
else if (last_offcurve && first_oncurve)
|
||||
{
|
||||
if (last_offcurve2)
|
||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
||||
last_offcurve.x, last_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
}
|
||||
else if (first_oncurve)
|
||||
draw_session->line_to (first_oncurve.x, first_oncurve.y);
|
||||
else if (first_offcurve)
|
||||
{
|
||||
float x = first_offcurve.x, y = first_offcurve.y;
|
||||
draw_session->move_to (x, y);
|
||||
draw_session->quadratic_to (x, y, x, y);
|
||||
}
|
||||
|
||||
/* Getting ready for the next contour */
|
||||
first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
|
||||
draw_session->close_path ();
|
||||
}
|
||||
}
|
||||
|
||||
void contour_end ()
|
||||
{
|
||||
if (first_offcurve && last_offcurve)
|
||||
{
|
||||
optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
|
||||
first_offcurve2 :
|
||||
first_offcurve);
|
||||
if (last_offcurve2)
|
||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
||||
last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
else
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
last_offcurve = optional_point_t ();
|
||||
}
|
||||
/* now check the rest */
|
||||
|
||||
if (first_offcurve && first_oncurve)
|
||||
{
|
||||
if (first_offcurve2)
|
||||
draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
|
||||
first_offcurve.x, first_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else
|
||||
draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
}
|
||||
else if (last_offcurve && first_oncurve)
|
||||
{
|
||||
if (last_offcurve2)
|
||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
||||
last_offcurve.x, last_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
}
|
||||
else if (first_oncurve)
|
||||
draw_session->line_to (first_oncurve.x, first_oncurve.y);
|
||||
else if (first_offcurve)
|
||||
{
|
||||
float x = first_offcurve.x, y = first_offcurve.y;
|
||||
draw_session->move_to (x, y);
|
||||
draw_session->quadratic_to (x, y, x, y);
|
||||
}
|
||||
|
||||
/* Getting ready for the next contour */
|
||||
first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
|
||||
draw_session->close_path ();
|
||||
}
|
||||
|
||||
void points_end () {}
|
||||
|
||||
bool is_consuming_contour_points () { return true; }
|
||||
|
|
|
@ -163,7 +163,7 @@ struct NameRecord
|
|||
if (platformID != 1)
|
||||
{
|
||||
unsigned text_size = hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, nullptr, nullptr);
|
||||
|
||||
|
||||
text_size++; // needs to consider NULL terminator for use in hb_ot_name_convert_utf()
|
||||
unsigned byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
|
||||
name_str_utf16_be = (char *) hb_calloc (byte_len, 1);
|
||||
|
@ -174,14 +174,14 @@ struct NameRecord
|
|||
}
|
||||
hb_ot_name_convert_utf<hb_utf8_t, hb_utf16_be_t> (*name_bytes, &text_size,
|
||||
(hb_utf16_be_t::codepoint_t *) name_str_utf16_be);
|
||||
|
||||
|
||||
unsigned encoded_byte_len = text_size * hb_utf16_be_t::codepoint_t::static_size;
|
||||
if (!encoded_byte_len || !c->check_assign (out->length, encoded_byte_len, HB_SERIALIZE_ERROR_INT_OVERFLOW)) {
|
||||
c->revert (snap);
|
||||
hb_free (name_str_utf16_be);
|
||||
return_trace (nullptr);
|
||||
}
|
||||
|
||||
|
||||
encoded_bytes = hb_bytes_t (name_str_utf16_be, encoded_byte_len);
|
||||
}
|
||||
else
|
||||
|
@ -392,7 +392,7 @@ struct name
|
|||
const hb_hashmap_t<hb_ot_name_record_ids_t, hb_bytes_t> *name_table_overrides =
|
||||
&c->plan->name_table_overrides;
|
||||
#endif
|
||||
|
||||
|
||||
auto it =
|
||||
+ nameRecordZ.as_array (count)
|
||||
| hb_filter (c->plan->name_ids, &NameRecord::nameID)
|
||||
|
@ -485,7 +485,7 @@ struct name
|
|||
const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
|
||||
this->table->count);
|
||||
|
||||
this->names.alloc (all_names.length, true);
|
||||
this->names.alloc_exact (all_names.length);
|
||||
|
||||
for (unsigned int i = 0; i < all_names.length; i++)
|
||||
{
|
||||
|
|
2
src/addTable.py
Normal file → Executable file
2
src/addTable.py
Normal file → Executable file
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from fontTools.ttLib import TTFont
|
||||
from fontTools.ttLib.tables.DefaultTable import DefaultTable
|
||||
|
|
|
@ -22,30 +22,30 @@ if not OBJS:
|
|||
stat = 0
|
||||
tested = 0
|
||||
|
||||
for obj in OBJS:
|
||||
result = subprocess.run(objdump.split () + ['-t', obj], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(objdump.split () + ['-t'] + OBJS, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
if result.returncode:
|
||||
if result.stderr.find (b'not recognized') != -1:
|
||||
# https://github.com/harfbuzz/harfbuzz/issues/3019
|
||||
print ('objdump %s returned "not recognized", skipping' % obj)
|
||||
continue
|
||||
print ('objdump %s returned error:\n%s' % (obj, result.stderr.decode ('utf-8')))
|
||||
stat = 2
|
||||
if result.returncode:
|
||||
if result.stderr.find (b'not recognized') != -1:
|
||||
# https://github.com/harfbuzz/harfbuzz/issues/3019
|
||||
print ('objdump %s returned "not recognized", skipping')
|
||||
else:
|
||||
print ('objdump returned error:\n%s' % (result.stderr.decode ('utf-8')))
|
||||
stat = 2
|
||||
else:
|
||||
tested = 1
|
||||
|
||||
result = result.stdout.decode ('utf-8')
|
||||
result = result.stdout.decode ('utf-8')
|
||||
|
||||
# Checking that no object file has static initializers
|
||||
for l in re.findall (r'^.*\.[cd]tors.*$', result, re.MULTILINE):
|
||||
if not re.match (r'.*\b0+\b', l):
|
||||
print ('Ouch, %s has static initializers/finalizers' % obj)
|
||||
stat = 1
|
||||
# Checking that no object file has static initializers
|
||||
for l in re.findall (r'^.*\.[cd]tors.*$', result, re.MULTILINE):
|
||||
if not re.match (r'.*\b0+\b', l):
|
||||
print ('Ouch, library has static initializers/finalizers')
|
||||
stat = 1
|
||||
|
||||
# Checking that no object file has lazy static C++ constructors/destructors or other such stuff
|
||||
if ('__cxa_' in result) and ('__ubsan_handle' not in result):
|
||||
print ('Ouch, %s has lazy static C++ constructors/destructors or other such stuff' % obj)
|
||||
stat = 1
|
||||
# Checking that no object file has lazy static C++ constructors/destructors or other such stuff
|
||||
if ('__cxa_' in result) and ('__ubsan_handle' not in result):
|
||||
print ('Ouch, library has lazy static C++ constructors/destructors or other such stuff')
|
||||
stat = 1
|
||||
|
||||
tested += 1
|
||||
|
||||
sys.exit (stat if tested else 77)
|
||||
|
|
|
@ -7,18 +7,27 @@ os.environ['LC_ALL'] = 'C' # otherwise 'nm' prints in wrong order
|
|||
builddir = os.getenv ('builddir', os.path.dirname (__file__))
|
||||
libs = os.getenv ('libs', '.libs')
|
||||
|
||||
IGNORED_SYMBOLS = '|'.join(['_fini', '_init', '_fdata', '_ftext', '_fbss',
|
||||
IGNORED_SYMBOLS = ['_fini', '_init', '_fdata', '_ftext', '_fbss',
|
||||
'__bss_start', '__bss_start__', '__bss_end__', '_edata', '_end', '_bss_end__',
|
||||
'__end__', '__gcov_.*', 'llvm_.*', 'flush_fn_list', 'writeout_fn_list', 'mangle_path',
|
||||
'lprofDirMode', 'reset_fn_list'])
|
||||
'lprofDirMode', 'reset_fn_list']
|
||||
|
||||
# Rust
|
||||
IGNORED_SYMBOLS += [
|
||||
'rust_eh_personality',
|
||||
'_ZN3std9panicking11EMPTY_PANIC.*', # 'std::panicking::EMPTY_PANIC::.*'
|
||||
'_ZN3std3sys3pal4unix4args3imp15ARGV_INIT_ARRAY.*', # 'std::sys::pal::unix::args::imp::ARGV_INIT_ARRAY::.*'
|
||||
'_ZN3std3sys4args4unix3imp15ARGV_INIT_ARRAY.*', # std::sys::args::unix::imp::ARGV_INIT_ARRAY::.*
|
||||
'_ZN17compiler_builtins4math4libm7generic4sqrt9RSQRT_TAB.*', # 'compiler_builtins::math::libm::generic::sqrt::RSQRT_TAB::.*'
|
||||
]
|
||||
|
||||
IGNORED_SYMBOLS = '|'.join (IGNORED_SYMBOLS)
|
||||
|
||||
nm = os.getenv ('NM', shutil.which ('nm'))
|
||||
if not nm:
|
||||
print ('check-symbols.py: \'nm\' not found; skipping test')
|
||||
sys.exit (77)
|
||||
|
||||
cxxfilt = shutil.which ('c++filt')
|
||||
|
||||
tested = False
|
||||
stat = 0
|
||||
|
||||
|
@ -34,12 +43,6 @@ for soname in ['harfbuzz', 'harfbuzz-subset', 'harfbuzz-icu', 'harfbuzz-gobject'
|
|||
for s in re.findall (r'^.+ [BCDGIRSTu] .+$', subprocess.check_output (nm.split() + [so]).decode ('utf-8'), re.MULTILINE)
|
||||
if not re.match (r'.* %s(%s)\b' % (symprefix, IGNORED_SYMBOLS), s)]
|
||||
|
||||
# run again c++filt also if is available
|
||||
if cxxfilt:
|
||||
EXPORTED_SYMBOLS = subprocess.check_output (
|
||||
[cxxfilt], input='\n'.join (EXPORTED_SYMBOLS).encode ()
|
||||
).decode ('utf-8').splitlines ()
|
||||
|
||||
prefix = (symprefix + os.path.basename (so)).replace ('libharfbuzz', 'hb').replace ('-', '_').split ('.')[0]
|
||||
|
||||
print ('Checking that %s does not expose internal symbols' % so)
|
||||
|
|
95
src/fontations/Cargo.lock
generated
Normal file
95
src/fontations/Cargo.lock
generated
Normal file
|
@ -0,0 +1,95 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck_derive"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "font-types"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d868ec188a98bb014c606072edd47e52e7ab7297db943b0b28503121e1d037bd"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "harfbuzz_fontations"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"read-fonts",
|
||||
"skrifa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "read-fonts"
|
||||
version = "0.27.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f14974c88fb4fd0a7203719f98020209248c9dbebaf9d10d860337797a905097"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"font-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "skrifa"
|
||||
version = "0.29.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c0ca53de9bb9bee1720c727606275148463cd938eb6bde249dcedeec4967747"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"read-fonts",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
28
src/fontations/Cargo.toml
Normal file
28
src/fontations/Cargo.toml
Normal file
|
@ -0,0 +1,28 @@
|
|||
[package]
|
||||
name = "harfbuzz_fontations"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
read-fonts = "0.27"
|
||||
skrifa = "0.29.2"
|
||||
|
||||
[lib]
|
||||
name = "harfbuzz_fontations"
|
||||
path = "lib.rs"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[profile.release]
|
||||
strip = true
|
||||
lto = "fat"
|
||||
panic = "abort"
|
||||
overflow-checks = false
|
||||
codegen-units = 1
|
||||
|
||||
[profile.debugoptimized]
|
||||
inherits = "release"
|
||||
debug = true
|
||||
codegen-units = 16
|
||||
strip = false
|
||||
|
||||
[profile.dev]
|
||||
lto = "fat"
|
1132
src/fontations/lib.rs
Normal file
1132
src/fontations/lib.rs
Normal file
File diff suppressed because it is too large
Load diff
105
src/fontations/meson.build
Normal file
105
src/fontations/meson.build
Normal file
|
@ -0,0 +1,105 @@
|
|||
rust = import('unstable-rust')
|
||||
|
||||
hb_rs = rust.bindgen(
|
||||
input : '../hb.h',
|
||||
output : 'hb.rs',
|
||||
include_directories: incsrc,
|
||||
args : ['--allowlist-function=hb_.*',
|
||||
'--allowlist-type=hb_.*',
|
||||
'--no-copy=hb_.*',
|
||||
],
|
||||
)
|
||||
|
||||
cargo = find_program('cargo')
|
||||
rustfmt = find_program('rustfmt')
|
||||
|
||||
rust_flags = ''
|
||||
cargo_args = [
|
||||
'--package', 'harfbuzz_fontations',
|
||||
'--lib',
|
||||
'--target-dir', meson.current_build_dir(),
|
||||
'--manifest-path', meson.current_source_dir() / 'Cargo.toml',
|
||||
'-Z', 'build-std=std,panic_abort',
|
||||
'-Z', 'build-std-features=panic_immediate_abort',
|
||||
]
|
||||
|
||||
buildtype = get_option('buildtype')
|
||||
if buildtype == 'release' or buildtype == 'debugoptimized'
|
||||
cargo_args += ['--profile', buildtype]
|
||||
endif
|
||||
|
||||
opt_level = get_option('optimization')
|
||||
rust_flags += ' -C opt-level=' + opt_level
|
||||
|
||||
harfbuzz_fontations = custom_target(
|
||||
'harfbuzz_fontations',
|
||||
input: ['lib.rs', 'Cargo.toml', 'Cargo.lock'],
|
||||
output: ['libharfbuzz_fontations.a'],
|
||||
depends: [hb_rs],
|
||||
env: ['OUT_DIR=' + meson.current_build_dir(),
|
||||
'RUSTFLAGS=' + rust_flags,
|
||||
],
|
||||
command: [
|
||||
cargo, 'build',
|
||||
] + cargo_args + [
|
||||
'-Z', 'unstable-options',
|
||||
'--artifact-dir', meson.current_build_dir(),
|
||||
],
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('prefix'), 'lib'),
|
||||
)
|
||||
|
||||
harfbuzz_fontations_dep = declare_dependency(
|
||||
link_with: harfbuzz_fontations,
|
||||
)
|
||||
|
||||
clippy_fix = run_target(
|
||||
'clippy-fix',
|
||||
env: ['OUT_DIR=' + meson.current_build_dir()],
|
||||
depends: [hb_rs, harfbuzz_fontations],
|
||||
command: [
|
||||
cargo, 'clippy',
|
||||
] + cargo_args + [
|
||||
'--allow-dirty', '--fix',
|
||||
],
|
||||
)
|
||||
if get_option('tests').enabled() and cargo.found()
|
||||
test(
|
||||
'clippy',
|
||||
cargo,
|
||||
env: ['OUT_DIR=' + meson.current_build_dir()],
|
||||
depends: [hb_rs, harfbuzz_fontations],
|
||||
args: [
|
||||
'clippy',
|
||||
] + cargo_args + [
|
||||
'--', '-D', 'warnings',
|
||||
],
|
||||
timeout: 120,
|
||||
)
|
||||
endif
|
||||
|
||||
rustfmt_fix = run_target(
|
||||
'rustfmt-fix',
|
||||
env: ['OUT_DIR=' + meson.current_build_dir()],
|
||||
depends: [hb_rs],
|
||||
command: [
|
||||
rustfmt,
|
||||
'--edition', '2021',
|
||||
'--',
|
||||
meson.current_source_dir() / 'lib.rs',
|
||||
],
|
||||
)
|
||||
if get_option('tests').enabled() and rustfmt.found()
|
||||
test(
|
||||
'rustfmt',
|
||||
rustfmt,
|
||||
env: ['OUT_DIR=' + meson.current_build_dir()],
|
||||
depends: [hb_rs],
|
||||
args: [
|
||||
'--check',
|
||||
'--edition', '2021',
|
||||
'--',
|
||||
meson.current_source_dir() / 'lib.rs',
|
||||
],
|
||||
)
|
||||
endif
|
|
@ -20,8 +20,11 @@ if '--experimental-api' not in sys.argv:
|
|||
# Move these to harfbuzz-sections.txt when got stable
|
||||
experimental_symbols = \
|
||||
"""hb_shape_justify
|
||||
hb_subset_repack_or_fail
|
||||
hb_subset_input_override_name_table
|
||||
hb_subset_cff_get_charstring_data
|
||||
hb_subset_cff_get_charstrings_index
|
||||
hb_subset_cff2_get_charstring_data
|
||||
hb_subset_cff2_get_charstrings_index
|
||||
""".splitlines ()
|
||||
symbols = [x for x in symbols if x not in experimental_symbols]
|
||||
symbols = "\n".join (symbols)
|
||||
|
|
|
@ -102,6 +102,7 @@ categories = {
|
|||
'CM',
|
||||
'Symbol',
|
||||
'CS',
|
||||
'SMPst',
|
||||
],
|
||||
'khmer' : [
|
||||
'VAbv',
|
||||
|
@ -435,6 +436,8 @@ defaults = (category_map[defaults[0]], position_map[defaults[1]], defaults[2])
|
|||
indic_data = {}
|
||||
for k, (cat, pos, block) in combined.items():
|
||||
cat = category_map[cat]
|
||||
if cat == 'SM' and pos == 'Not_Applicable':
|
||||
cat = 'SMPst'
|
||||
pos = position_map[pos]
|
||||
indic_data[k] = (cat, pos, block)
|
||||
|
||||
|
@ -454,7 +457,7 @@ for k, (cat, pos, block) in indic_data.items():
|
|||
# Keep in sync with CONSONANT_FLAGS in the shaper
|
||||
consonant_categories = ('C', 'CS', 'Ra','CM', 'V', 'PLACEHOLDER', 'DOTTEDCIRCLE')
|
||||
matra_categories = ('M', 'MPst')
|
||||
smvd_categories = ('SM', 'VD', 'A', 'Symbol')
|
||||
smvd_categories = ('SM', 'SMPst', 'VD', 'A', 'Symbol')
|
||||
for k, (cat, pos, block) in indic_data.items():
|
||||
if cat in consonant_categories:
|
||||
pos = 'BASE_C'
|
||||
|
@ -530,6 +533,7 @@ short = [{
|
|||
"Repha": 'Rf',
|
||||
"PLACEHOLDER": 'GB',
|
||||
"DOTTEDCIRCLE": 'DC',
|
||||
"SMPst": 'SP',
|
||||
"VPst": 'VR',
|
||||
"VPre": 'VL',
|
||||
"Robatic": 'Rt',
|
||||
|
|
|
@ -19,7 +19,9 @@ outdir = os.path.dirname (OUTPUT)
|
|||
shutil.copy (INPUT, outdir)
|
||||
rl = os.path.basename (INPUT)
|
||||
hh = rl.replace ('.rl', '.hh')
|
||||
subprocess.Popen (ragel.split() + ['-e', '-F1', '-o', hh, rl], cwd=outdir).wait ()
|
||||
ret = subprocess.Popen (ragel.split() + ['-e', '-F1', '-o', hh, rl], cwd=outdir).wait ()
|
||||
if ret:
|
||||
sys.exit (ret)
|
||||
|
||||
# copy it also to src/
|
||||
shutil.copyfile (os.path.join (outdir, hh), os.path.join (CURRENT_SOURCE_DIR, hh))
|
||||
|
|
|
@ -345,14 +345,18 @@ class OpenTypeRegistryParser (HTMLParser):
|
|||
self.from_bcp_47_uninherited = None
|
||||
# Whether the parser is in a <td> element
|
||||
self._td = False
|
||||
# Whether the parser is after a <br> element within the current <tr> element
|
||||
self._br = False
|
||||
# Whether the parser ignores the rest of the current <td> element
|
||||
self._disengaged = False
|
||||
# The text of the <td> elements of the current <tr> element.
|
||||
self._current_tr = []
|
||||
|
||||
def handle_starttag (self, tag, attrs):
|
||||
if tag == 'br':
|
||||
self._br = True
|
||||
if tag == 'a':
|
||||
if self._current_tr and not self._disengaged:
|
||||
self._current_tr[-1] = ''
|
||||
self._disengaged = True
|
||||
elif tag == 'br':
|
||||
self._disengaged = True
|
||||
elif tag == 'meta':
|
||||
for attr, value in attrs:
|
||||
if attr == 'name' and value == 'updated_at':
|
||||
|
@ -362,12 +366,13 @@ class OpenTypeRegistryParser (HTMLParser):
|
|||
self._td = True
|
||||
self._current_tr.append ('')
|
||||
elif tag == 'tr':
|
||||
self._br = False
|
||||
self._disengaged = False
|
||||
self._current_tr = []
|
||||
|
||||
def handle_endtag (self, tag):
|
||||
if tag == 'td':
|
||||
self._td = False
|
||||
self._disengaged = False
|
||||
elif tag == 'tr' and self._current_tr:
|
||||
expect (2 <= len (self._current_tr) <= 3)
|
||||
name = self._current_tr[0].strip ()
|
||||
|
@ -387,7 +392,7 @@ class OpenTypeRegistryParser (HTMLParser):
|
|||
self.ranks[tag] = rank
|
||||
|
||||
def handle_data (self, data):
|
||||
if self._td and not self._br:
|
||||
if self._td and not self._disengaged:
|
||||
self._current_tr[-1] += data
|
||||
|
||||
def handle_charref (self, name):
|
||||
|
|
|
@ -109,6 +109,7 @@ property_names = [
|
|||
'Nukta',
|
||||
'Virama',
|
||||
'Pure_Killer',
|
||||
'Reordering_Killer',
|
||||
'Invisible_Stacker',
|
||||
'Vowel_Independent',
|
||||
'Vowel_Dependent',
|
||||
|
@ -263,6 +264,8 @@ def is_OTHER(U, UISC, UDI, UGC, AJT):
|
|||
and not is_SYM_MOD(U, UISC, UDI, UGC, AJT)
|
||||
and not is_Word_Joiner(U, UISC, UDI, UGC, AJT)
|
||||
)
|
||||
def is_REORDERING_KILLER(U, UISC, UDI, UGC, AJT):
|
||||
return UISC == Reordering_Killer
|
||||
def is_REPHA(U, UISC, UDI, UGC, AJT):
|
||||
return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed]
|
||||
def is_SAKOT(U, UISC, UDI, UGC, AJT):
|
||||
|
@ -306,6 +309,7 @@ use_mapping = {
|
|||
'SE': is_HIEROGLYPH_SEGMENT_END,
|
||||
'ZWNJ': is_ZWNJ,
|
||||
'O': is_OTHER,
|
||||
'RK': is_REORDERING_KILLER,
|
||||
'R': is_REPHA,
|
||||
'Sk': is_SAKOT,
|
||||
'SM': is_SYM_MOD,
|
||||
|
@ -358,6 +362,7 @@ use_positions = {
|
|||
'Pst': [Not_Applicable],
|
||||
},
|
||||
'R': None,
|
||||
'RK': None,
|
||||
'SUB': None,
|
||||
}
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ print ('static void')
|
|||
print ('_output_dotted_circle (hb_buffer_t *buffer)')
|
||||
print ('{')
|
||||
print (' (void) buffer->output_glyph (0x25CCu);')
|
||||
print (' _hb_glyph_info_reset_continuation (&buffer->prev());')
|
||||
print (' _hb_glyph_info_clear_continuation (&buffer->prev());')
|
||||
print ('}')
|
||||
print ()
|
||||
print ('static void')
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
set_and_check(HARFBUZZ_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
|
||||
|
||||
set(HARFBUZZ_VERSION "@HARFBUZZ_VERSION@")
|
||||
|
||||
# Add the libraries.
|
||||
add_library(harfbuzz::harfbuzz @HB_LIBRARY_TYPE@ IMPORTED)
|
||||
set_target_properties(harfbuzz::harfbuzz PROPERTIES
|
||||
|
|
|
@ -57,8 +57,10 @@
|
|||
#include "hb-subset-input.cc"
|
||||
#include "hb-subset-instancer-iup.cc"
|
||||
#include "hb-subset-instancer-solver.cc"
|
||||
#include "hb-subset-plan-layout.cc"
|
||||
#include "hb-subset-plan-var.cc"
|
||||
#include "hb-subset-plan.cc"
|
||||
#include "hb-subset-repacker.cc"
|
||||
#include "hb-subset-serialize.cc"
|
||||
#include "hb-subset.cc"
|
||||
#include "hb-ucd.cc"
|
||||
#include "hb-unicode.cc"
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
#include "hb-buffer-verify.cc"
|
||||
#include "hb-buffer.cc"
|
||||
#include "hb-common.cc"
|
||||
#include "hb-coretext-font.cc"
|
||||
#include "hb-coretext-shape.cc"
|
||||
#include "hb-coretext.cc"
|
||||
#include "hb-directwrite-font.cc"
|
||||
#include "hb-directwrite-shape.cc"
|
||||
#include "hb-directwrite.cc"
|
||||
#include "hb-draw.cc"
|
||||
#include "hb-face-builder.cc"
|
||||
|
|
|
@ -29,7 +29,13 @@
|
|||
|
||||
#include "hb-aat-layout.hh"
|
||||
#include "hb-aat-map.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-cache.hh"
|
||||
#include "hb-bit-set.hh"
|
||||
#include "hb-bit-page.hh"
|
||||
|
||||
|
||||
namespace OT {
|
||||
struct GDEF;
|
||||
|
@ -39,10 +45,66 @@ namespace AAT {
|
|||
|
||||
using namespace OT;
|
||||
|
||||
#define HB_AAT_BUFFER_DIGEST_THRESHOLD 32
|
||||
|
||||
struct ankr;
|
||||
|
||||
using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>;
|
||||
static_assert (sizeof (hb_aat_class_cache_t) == 256, "");
|
||||
|
||||
struct hb_aat_scratch_t
|
||||
{
|
||||
hb_aat_scratch_t () = default;
|
||||
hb_aat_scratch_t (const hb_aat_scratch_t &) = delete;
|
||||
|
||||
hb_aat_scratch_t (hb_aat_scratch_t &&o)
|
||||
{
|
||||
buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ());
|
||||
o.buffer_glyph_set.set_relaxed (nullptr);
|
||||
}
|
||||
hb_aat_scratch_t & operator = (hb_aat_scratch_t &&o)
|
||||
{
|
||||
buffer_glyph_set.set_relaxed (o.buffer_glyph_set.get_relaxed ());
|
||||
o.buffer_glyph_set.set_relaxed (nullptr);
|
||||
return *this;
|
||||
}
|
||||
~hb_aat_scratch_t ()
|
||||
{
|
||||
auto *s = buffer_glyph_set.get_relaxed ();
|
||||
if (unlikely (!s))
|
||||
return;
|
||||
s->fini ();
|
||||
hb_free (s);
|
||||
}
|
||||
|
||||
hb_bit_set_t *create_buffer_glyph_set () const
|
||||
{
|
||||
hb_bit_set_t *s = buffer_glyph_set.get_acquire ();
|
||||
if (s && buffer_glyph_set.cmpexch (s, nullptr))
|
||||
return s;
|
||||
|
||||
s = (hb_bit_set_t *) hb_calloc (1, sizeof (hb_bit_set_t));
|
||||
if (unlikely (!s))
|
||||
return nullptr;
|
||||
s->init ();
|
||||
|
||||
return s;
|
||||
}
|
||||
void destroy_buffer_glyph_set (hb_bit_set_t *s) const
|
||||
{
|
||||
if (unlikely (!s))
|
||||
return;
|
||||
if (buffer_glyph_set.cmpexch (nullptr, s))
|
||||
return;
|
||||
s->fini ();
|
||||
hb_free (s);
|
||||
}
|
||||
|
||||
mutable hb_atomic_t<hb_bit_set_t *> buffer_glyph_set;
|
||||
};
|
||||
|
||||
enum { DELETED_GLYPH = 0xFFFF };
|
||||
|
||||
#define HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED HB_BUFFER_SCRATCH_FLAG_SHAPER0
|
||||
|
||||
struct hb_aat_apply_context_t :
|
||||
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
|
||||
{
|
||||
|
@ -59,12 +121,15 @@ struct hb_aat_apply_context_t :
|
|||
hb_buffer_t *buffer;
|
||||
hb_sanitize_context_t sanitizer;
|
||||
const ankr *ankr_table;
|
||||
const OT::GDEF *gdef_table;
|
||||
const OT::GDEF &gdef;
|
||||
bool has_glyph_classes;
|
||||
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
|
||||
hb_set_digest_t buffer_digest = hb_set_digest_t::full ();
|
||||
hb_set_digest_t machine_glyph_set = hb_set_digest_t::full ();
|
||||
hb_set_digest_t left_set = hb_set_digest_t::full ();
|
||||
hb_set_digest_t right_set = hb_set_digest_t::full ();
|
||||
bool using_buffer_glyph_set = false;
|
||||
hb_bit_set_t *buffer_glyph_set = nullptr;
|
||||
const hb_bit_set_t *left_set = nullptr;
|
||||
const hb_bit_set_t *right_set = nullptr;
|
||||
const hb_bit_set_t *machine_glyph_set = nullptr;
|
||||
hb_aat_class_cache_t *machine_class_cache = nullptr;
|
||||
hb_mask_t subtable_flags = 0;
|
||||
|
||||
/* Unused. For debug tracing only. */
|
||||
|
@ -80,6 +145,88 @@ struct hb_aat_apply_context_t :
|
|||
HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
|
||||
|
||||
void set_lookup_index (unsigned int i) { lookup_index = i; }
|
||||
|
||||
void setup_buffer_glyph_set ()
|
||||
{
|
||||
using_buffer_glyph_set = buffer->len >= 4 && buffer_glyph_set;
|
||||
|
||||
if (likely (using_buffer_glyph_set))
|
||||
buffer->collect_codepoints (*buffer_glyph_set);
|
||||
}
|
||||
bool buffer_intersects_machine () const
|
||||
{
|
||||
if (likely (using_buffer_glyph_set))
|
||||
return buffer_glyph_set->intersects (*machine_glyph_set);
|
||||
|
||||
// Faster for shorter buffers.
|
||||
for (unsigned i = 0; i < buffer->len; i++)
|
||||
if (machine_glyph_set->has (buffer->info[i].codepoint))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HB_NODISCARD bool output_glyphs (unsigned int count,
|
||||
const T *glyphs)
|
||||
{
|
||||
if (likely (using_buffer_glyph_set))
|
||||
buffer_glyph_set->add_array (glyphs, count);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (glyphs[i] == DELETED_GLYPH)
|
||||
{
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
|
||||
_hb_glyph_info_set_aat_deleted (&buffer->cur());
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->cur(),
|
||||
gdef.get_glyph_props (glyphs[i]));
|
||||
#endif
|
||||
}
|
||||
if (unlikely (!buffer->output_glyph (glyphs[i]))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph)
|
||||
{
|
||||
if (glyph == DELETED_GLYPH)
|
||||
{
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
|
||||
_hb_glyph_info_set_aat_deleted (&buffer->cur());
|
||||
}
|
||||
|
||||
if (likely (using_buffer_glyph_set))
|
||||
buffer_glyph_set->add (glyph);
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->cur(),
|
||||
gdef.get_glyph_props (glyph));
|
||||
#endif
|
||||
return buffer->replace_glyph (glyph);
|
||||
}
|
||||
|
||||
HB_NODISCARD bool delete_glyph ()
|
||||
{
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED;
|
||||
_hb_glyph_info_set_aat_deleted (&buffer->cur());
|
||||
return buffer->replace_glyph (DELETED_GLYPH);
|
||||
}
|
||||
|
||||
void replace_glyph_inplace (unsigned i, hb_codepoint_t glyph)
|
||||
{
|
||||
buffer->info[i].codepoint = glyph;
|
||||
if (likely (using_buffer_glyph_set))
|
||||
buffer_glyph_set->add (glyph);
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->info[i],
|
||||
gdef.get_glyph_props (glyph));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -87,8 +234,6 @@ struct hb_aat_apply_context_t :
|
|||
* Lookup Table
|
||||
*/
|
||||
|
||||
enum { DELETED_GLYPH = 0xFFFF };
|
||||
|
||||
template <typename T> struct Lookup;
|
||||
|
||||
template <typename T>
|
||||
|
@ -108,6 +253,13 @@ struct LookupFormat0
|
|||
{
|
||||
glyphs.add_range (0, num_glyphs - 1);
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
|
||||
{
|
||||
for (unsigned i = 0; i < num_glyphs; i++)
|
||||
if (filter (arrayZ[i]))
|
||||
glyphs.add (i);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -140,8 +292,14 @@ struct LookupSegmentSingle
|
|||
template <typename set_t>
|
||||
void collect_glyphs (set_t &glyphs) const
|
||||
{
|
||||
if (first == DELETED_GLYPH)
|
||||
return;
|
||||
if (first == DELETED_GLYPH) return;
|
||||
glyphs.add_range (first, last);
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
|
||||
{
|
||||
if (first == DELETED_GLYPH) return;
|
||||
if (!filter (value)) return;
|
||||
glyphs.add_range (first, last);
|
||||
}
|
||||
|
||||
|
@ -182,6 +340,13 @@ struct LookupFormat2
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
segments[i].collect_glyphs (glyphs);
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
|
||||
{
|
||||
unsigned count = segments.get_length ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
segments[i].collect_glyphs_filtered (glyphs, filter);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -217,10 +382,18 @@ struct LookupSegmentArray
|
|||
template <typename set_t>
|
||||
void collect_glyphs (set_t &glyphs) const
|
||||
{
|
||||
if (first == DELETED_GLYPH)
|
||||
return;
|
||||
if (first == DELETED_GLYPH) return;
|
||||
glyphs.add_range (first, last);
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const
|
||||
{
|
||||
if (first == DELETED_GLYPH) return;
|
||||
const auto &values = base+valuesZ;
|
||||
for (hb_codepoint_t i = first; i <= last; i++)
|
||||
if (filter (values[i - first]))
|
||||
glyphs.add (i);
|
||||
}
|
||||
|
||||
int cmp (hb_codepoint_t g) const
|
||||
{ return g < first ? -1 : g <= last ? 0 : +1; }
|
||||
|
@ -271,6 +444,13 @@ struct LookupFormat4
|
|||
for (unsigned i = 0; i < count; i++)
|
||||
segments[i].collect_glyphs (glyphs);
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
|
||||
{
|
||||
unsigned count = segments.get_length ();
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
segments[i].collect_glyphs_filtered (glyphs, this, filter);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -303,8 +483,14 @@ struct LookupSingle
|
|||
template <typename set_t>
|
||||
void collect_glyphs (set_t &glyphs) const
|
||||
{
|
||||
if (glyph == DELETED_GLYPH)
|
||||
return;
|
||||
if (glyph == DELETED_GLYPH) return;
|
||||
glyphs.add (glyph);
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
|
||||
{
|
||||
if (glyph == DELETED_GLYPH) return;
|
||||
if (!filter (value)) return;
|
||||
glyphs.add (glyph);
|
||||
}
|
||||
|
||||
|
@ -344,6 +530,13 @@ struct LookupFormat6
|
|||
for (unsigned i = 0; i < count; i++)
|
||||
entries[i].collect_glyphs (glyphs);
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
|
||||
{
|
||||
unsigned count = entries.get_length ();
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
entries[i].collect_glyphs_filtered (glyphs, filter);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -379,12 +572,20 @@ struct LookupFormat8
|
|||
template <typename set_t>
|
||||
void collect_glyphs (set_t &glyphs) const
|
||||
{
|
||||
if (unlikely (!glyphCount))
|
||||
return;
|
||||
if (firstGlyph == DELETED_GLYPH)
|
||||
return;
|
||||
if (unlikely (!glyphCount)) return;
|
||||
if (firstGlyph == DELETED_GLYPH) return;
|
||||
glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
|
||||
{
|
||||
if (unlikely (!glyphCount)) return;
|
||||
if (firstGlyph == DELETED_GLYPH) return;
|
||||
const T *p = valueArrayZ.arrayZ;
|
||||
for (unsigned i = 0; i < glyphCount; i++)
|
||||
if (filter (p[i]))
|
||||
glyphs.add (firstGlyph + i);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -433,10 +634,8 @@ struct LookupFormat10
|
|||
template <typename set_t>
|
||||
void collect_glyphs (set_t &glyphs) const
|
||||
{
|
||||
if (unlikely (!glyphCount))
|
||||
return;
|
||||
if (firstGlyph == DELETED_GLYPH)
|
||||
return;
|
||||
if (unlikely (!glyphCount)) return;
|
||||
if (firstGlyph == DELETED_GLYPH) return;
|
||||
glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
|
||||
}
|
||||
|
||||
|
@ -501,6 +700,18 @@ struct Lookup
|
|||
default:return;
|
||||
}
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 0: hb_barrier (); u.format0.collect_glyphs_filtered (glyphs, num_glyphs, filter); return;
|
||||
case 2: hb_barrier (); u.format2.collect_glyphs_filtered (glyphs, filter); return;
|
||||
case 4: hb_barrier (); u.format4.collect_glyphs_filtered (glyphs, filter); return;
|
||||
case 6: hb_barrier (); u.format6.collect_glyphs_filtered (glyphs, filter); return;
|
||||
case 8: hb_barrier (); u.format8.collect_glyphs_filtered (glyphs, filter); return;
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
|
||||
typename T::type get_class (hb_codepoint_t glyph_id,
|
||||
unsigned int num_glyphs,
|
||||
|
@ -563,7 +774,7 @@ DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
|
|||
template <typename T>
|
||||
struct Entry
|
||||
{
|
||||
// This does seem like it's ever called.
|
||||
// This doesn't seem like it's ever called.
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -632,18 +843,51 @@ struct StateTable
|
|||
{
|
||||
(this+classTable).collect_glyphs (glyphs, num_glyphs);
|
||||
}
|
||||
template <typename set_t, typename table_t>
|
||||
void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs, const table_t &table) const
|
||||
{
|
||||
unsigned num_classes = nClasses;
|
||||
|
||||
if (unlikely (num_classes > hb_bit_page_t::BITS))
|
||||
{
|
||||
(this+classTable).collect_glyphs (glyphs, num_glyphs);
|
||||
return;
|
||||
}
|
||||
|
||||
// Collect all classes going out from the start state.
|
||||
hb_bit_page_t filter;
|
||||
|
||||
for (unsigned i = 0; i < num_classes; i++)
|
||||
{
|
||||
const auto &entry = get_entry (STATE_START_OF_TEXT, i);
|
||||
if (new_state (entry.newState) == STATE_START_OF_TEXT &&
|
||||
!table.is_action_initiable (entry) && !table.is_actionable (entry))
|
||||
continue;
|
||||
|
||||
filter.add (i);
|
||||
}
|
||||
|
||||
// And glyphs in those classes.
|
||||
|
||||
if (filter (CLASS_DELETED_GLYPH))
|
||||
glyphs.add (DELETED_GLYPH);
|
||||
|
||||
(this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter);
|
||||
}
|
||||
|
||||
int new_state (unsigned int newState) const
|
||||
{ return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
|
||||
|
||||
template <typename set_t>
|
||||
unsigned int get_class (hb_codepoint_t glyph_id,
|
||||
unsigned int num_glyphs,
|
||||
const set_t &glyphs) const
|
||||
hb_aat_class_cache_t *cache = nullptr) const
|
||||
{
|
||||
unsigned klass;
|
||||
if (cache && cache->get (glyph_id, &klass)) return klass;
|
||||
if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
|
||||
if (!glyphs[glyph_id]) return CLASS_OUT_OF_BOUNDS;
|
||||
return (this+classTable).get_class (glyph_id, num_glyphs, CLASS_OUT_OF_BOUNDS);
|
||||
klass = (this+classTable).get_class (glyph_id, num_glyphs, CLASS_OUT_OF_BOUNDS);
|
||||
if (cache) cache->set (glyph_id, klass);
|
||||
return klass;
|
||||
}
|
||||
|
||||
const Entry<Extra> *get_entries () const
|
||||
|
@ -651,13 +895,14 @@ struct StateTable
|
|||
|
||||
const Entry<Extra> &get_entry (int state, unsigned int klass) const
|
||||
{
|
||||
if (unlikely (klass >= nClasses))
|
||||
unsigned n_classes = nClasses;
|
||||
if (unlikely (klass >= n_classes))
|
||||
klass = CLASS_OUT_OF_BOUNDS;
|
||||
|
||||
const HBUSHORT *states = (this+stateArrayTable).arrayZ;
|
||||
const Entry<Extra> *entries = (this+entryTable).arrayZ;
|
||||
|
||||
unsigned int entry = states[state * nClasses + klass];
|
||||
unsigned int entry = states[state * n_classes + klass];
|
||||
DEBUG_MSG (APPLY, nullptr, "e%u", entry);
|
||||
|
||||
return entries[entry];
|
||||
|
@ -803,6 +1048,13 @@ struct ClassTable
|
|||
if (classArray.arrayZ[i] != CLASS_OUT_OF_BOUNDS)
|
||||
glyphs.add (firstGlyph + i);
|
||||
}
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
|
||||
{
|
||||
for (unsigned i = 0; i < classArray.len; i++)
|
||||
if (filter (classArray.arrayZ[i]))
|
||||
glyphs.add (firstGlyph + i);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -918,7 +1170,7 @@ struct ExtendedTypes
|
|||
}
|
||||
};
|
||||
|
||||
template <typename Types, typename EntryData>
|
||||
template <typename Types, typename EntryData, typename Flags>
|
||||
struct StateTableDriver
|
||||
{
|
||||
using StateTableT = StateTable<Types, EntryData>;
|
||||
|
@ -929,14 +1181,6 @@ struct StateTableDriver
|
|||
machine (machine_),
|
||||
num_glyphs (face_->get_num_glyphs ()) {}
|
||||
|
||||
template <typename context_t>
|
||||
bool is_idempotent_on_all_out_of_bounds (context_t *c, hb_aat_apply_context_t *ac)
|
||||
{
|
||||
const auto entry = machine.get_entry (StateTableT::STATE_START_OF_TEXT, CLASS_OUT_OF_BOUNDS);
|
||||
return !c->is_actionable (ac->buffer, this, entry) &&
|
||||
machine.new_state (entry.newState) == StateTableT::STATE_START_OF_TEXT;
|
||||
}
|
||||
|
||||
template <typename context_t>
|
||||
void drive (context_t *c, hb_aat_apply_context_t *ac)
|
||||
{
|
||||
|
@ -977,7 +1221,7 @@ struct StateTableDriver
|
|||
}
|
||||
|
||||
unsigned int klass = likely (buffer->idx < buffer->len) ?
|
||||
machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_glyph_set) :
|
||||
machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_class_cache) :
|
||||
(unsigned) CLASS_END_OF_TEXT;
|
||||
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
|
||||
const EntryT &entry = machine.get_entry (state, klass);
|
||||
|
@ -1011,41 +1255,36 @@ struct StateTableDriver
|
|||
*
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/2860
|
||||
*/
|
||||
|
||||
const auto is_safe_to_break_extra = [&]()
|
||||
{
|
||||
/* 2c. */
|
||||
const auto &wouldbe_entry = machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass);
|
||||
|
||||
/* 2c'. */
|
||||
if (c->is_actionable (buffer, this, wouldbe_entry))
|
||||
return false;
|
||||
|
||||
/* 2c". */
|
||||
return next_state == machine.new_state(wouldbe_entry.newState)
|
||||
&& (entry.flags & context_t::DontAdvance) == (wouldbe_entry.flags & context_t::DontAdvance);
|
||||
};
|
||||
|
||||
const auto is_safe_to_break = [&]()
|
||||
{
|
||||
const EntryT *wouldbe_entry;
|
||||
bool is_safe_to_break =
|
||||
(
|
||||
/* 1. */
|
||||
if (c->is_actionable (buffer, this, entry))
|
||||
return false;
|
||||
!c->table->is_actionable (entry) &&
|
||||
|
||||
/* 2. */
|
||||
// This one is meh, I know...
|
||||
const auto ok =
|
||||
(
|
||||
state == StateTableT::STATE_START_OF_TEXT
|
||||
|| ((entry.flags & context_t::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT)
|
||||
|| is_safe_to_break_extra();
|
||||
if (!ok)
|
||||
return false;
|
||||
|| ((entry.flags & Flags::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT)
|
||||
|| (
|
||||
/* 2c. */
|
||||
wouldbe_entry = &machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass)
|
||||
,
|
||||
/* 2c'. */
|
||||
!c->table->is_actionable (*wouldbe_entry) &&
|
||||
/* 2c". */
|
||||
(
|
||||
next_state == machine.new_state(wouldbe_entry->newState) &&
|
||||
(entry.flags & Flags::DontAdvance) == (wouldbe_entry->flags & Flags::DontAdvance)
|
||||
)
|
||||
)
|
||||
) &&
|
||||
|
||||
/* 3. */
|
||||
return !c->is_actionable (buffer, this, machine.get_entry (state, CLASS_END_OF_TEXT));
|
||||
};
|
||||
!c->table->is_actionable (machine.get_entry (state, CLASS_END_OF_TEXT))
|
||||
);
|
||||
|
||||
if (!is_safe_to_break () && buffer->backtrack_len () && buffer->idx < buffer->len)
|
||||
if (!is_safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
|
||||
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
|
||||
|
||||
c->transition (buffer, this, entry);
|
||||
|
@ -1056,7 +1295,7 @@ struct StateTableDriver
|
|||
if (buffer->idx == buffer->len || unlikely (!buffer->successful))
|
||||
break;
|
||||
|
||||
if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
|
||||
if (!(entry.flags & Flags::DontAdvance) || buffer->max_ops-- <= 0)
|
||||
(void) buffer->next_glyph ();
|
||||
}
|
||||
|
||||
|
|
|
@ -112,10 +112,6 @@ struct KerxSubTableFormat0
|
|||
if (header.coverage & header.Backwards)
|
||||
return_trace (false);
|
||||
|
||||
if (!(c->buffer_digest.may_have (c->left_set) &&
|
||||
c->buffer_digest.may_have (c->right_set)))
|
||||
return_trace (false);
|
||||
|
||||
accelerator_t accel (*this, c);
|
||||
hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
|
||||
machine.kern (c->font, c->buffer, c->plan->kern_mask);
|
||||
|
@ -144,7 +140,7 @@ struct KerxSubTableFormat0
|
|||
|
||||
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||
{
|
||||
if (!c->left_set[left] || !c->right_set[right]) return 0;
|
||||
if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
|
||||
return table.get_kerning (left, right, c);
|
||||
}
|
||||
};
|
||||
|
@ -189,6 +185,9 @@ struct Format1Entry<true>
|
|||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
static bool initiateAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & Push; }
|
||||
|
||||
static bool performAction (const Entry<EntryData> &entry)
|
||||
{ return entry.data.kernActionIndex != 0xFFFF; }
|
||||
|
||||
|
@ -211,6 +210,9 @@ struct Format1Entry<false>
|
|||
|
||||
typedef void EntryData;
|
||||
|
||||
static bool initiateAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & Push; }
|
||||
|
||||
static bool performAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & Offset; }
|
||||
|
||||
|
@ -227,13 +229,23 @@ struct KerxSubTableFormat1
|
|||
typedef Format1Entry<Types::extended> Format1EntryT;
|
||||
typedef typename Format1EntryT::EntryData EntryData;
|
||||
|
||||
enum Flags
|
||||
{
|
||||
DontAdvance = Format1EntryT::DontAdvance,
|
||||
};
|
||||
|
||||
bool is_action_initiable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return Format1EntryT::initiateAction (entry);
|
||||
}
|
||||
bool is_actionable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return Format1EntryT::performAction (entry);
|
||||
}
|
||||
|
||||
struct driver_context_t
|
||||
{
|
||||
static constexpr bool in_place = true;
|
||||
enum
|
||||
{
|
||||
DontAdvance = Format1EntryT::DontAdvance,
|
||||
};
|
||||
|
||||
driver_context_t (const KerxSubTableFormat1 *table_,
|
||||
hb_aat_apply_context_t *c_) :
|
||||
|
@ -246,12 +258,8 @@ struct KerxSubTableFormat1
|
|||
depth (0),
|
||||
crossStream (table->header.coverage & table->header.CrossStream) {}
|
||||
|
||||
bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
|
||||
StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> &entry)
|
||||
{ return Format1EntryT::performAction (entry); }
|
||||
void transition (hb_buffer_t *buffer,
|
||||
StateTableDriver<Types, EntryData> *driver,
|
||||
StateTableDriver<Types, EntryData, Flags> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
unsigned int flags = entry.flags;
|
||||
|
@ -320,8 +328,9 @@ struct KerxSubTableFormat1
|
|||
}
|
||||
else if (buffer->info[idx].mask & kern_mask)
|
||||
{
|
||||
o.x_advance += c->font->em_scale_x (v);
|
||||
o.x_offset += c->font->em_scale_x (v);
|
||||
auto scaled = c->font->em_scale_x (v);
|
||||
o.x_advance += scaled;
|
||||
o.x_offset += scaled;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -351,9 +360,10 @@ struct KerxSubTableFormat1
|
|||
}
|
||||
}
|
||||
|
||||
private:
|
||||
public:
|
||||
hb_aat_apply_context_t *c;
|
||||
const KerxSubTableFormat1 *table;
|
||||
private:
|
||||
const UnsizedArrayOf<FWORD> &kernAction;
|
||||
unsigned int stack[8];
|
||||
unsigned int depth;
|
||||
|
@ -370,12 +380,7 @@ struct KerxSubTableFormat1
|
|||
|
||||
driver_context_t dc (this, c);
|
||||
|
||||
StateTableDriver<Types, EntryData> driver (machine, c->font->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!(c->buffer_digest.may_have (c->left_set) &&
|
||||
c->buffer_digest.may_have (c->right_set)))
|
||||
return_trace (false);
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->font->face);
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
|
@ -393,10 +398,8 @@ struct KerxSubTableFormat1
|
|||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
{
|
||||
set_t set;
|
||||
machine.collect_glyphs (set, num_glyphs);
|
||||
left_set.union_ (set);
|
||||
right_set.union_ (set);
|
||||
machine.collect_initial_glyphs (left_set, num_glyphs, *this);
|
||||
//machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -440,10 +443,6 @@ struct KerxSubTableFormat2
|
|||
if (header.coverage & header.Backwards)
|
||||
return_trace (false);
|
||||
|
||||
if (!(c->buffer_digest.may_have (c->left_set) &&
|
||||
c->buffer_digest.may_have (c->right_set)))
|
||||
return_trace (false);
|
||||
|
||||
accelerator_t accel (*this, c);
|
||||
hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
|
||||
machine.kern (c->font, c->buffer, c->plan->kern_mask);
|
||||
|
@ -469,7 +468,7 @@ struct KerxSubTableFormat2
|
|||
|
||||
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||
{
|
||||
if (!c->left_set[left] || !c->right_set[right]) return 0;
|
||||
if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
|
||||
return table.get_kerning (left, right, c);
|
||||
}
|
||||
};
|
||||
|
@ -513,17 +512,26 @@ struct KerxSubTableFormat4
|
|||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
enum Flags
|
||||
{
|
||||
Mark = 0x8000, /* If set, remember this glyph as the marked glyph. */
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
||||
* going to the new state. */
|
||||
Reserved = 0x3FFF, /* Not used; set to 0. */
|
||||
};
|
||||
|
||||
bool is_action_initiable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return (entry.flags & Mark);
|
||||
}
|
||||
bool is_actionable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return entry.data.ankrActionIndex != 0xFFFF;
|
||||
}
|
||||
|
||||
struct driver_context_t
|
||||
{
|
||||
static constexpr bool in_place = true;
|
||||
enum Flags
|
||||
{
|
||||
Mark = 0x8000, /* If set, remember this glyph as the marked glyph. */
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
||||
* going to the new state. */
|
||||
Reserved = 0x3FFF, /* Not used; set to 0. */
|
||||
};
|
||||
|
||||
enum SubTableFlags
|
||||
{
|
||||
ActionType = 0xC0000000, /* A two-bit field containing the action type. */
|
||||
|
@ -533,20 +541,17 @@ struct KerxSubTableFormat4
|
|||
* point table. */
|
||||
};
|
||||
|
||||
driver_context_t (const KerxSubTableFormat4 *table,
|
||||
driver_context_t (const KerxSubTableFormat4 *table_,
|
||||
hb_aat_apply_context_t *c_) :
|
||||
c (c_),
|
||||
table (table_),
|
||||
action_type ((table->flags & ActionType) >> 30),
|
||||
ankrData ((HBUINT16 *) ((const char *) &table->machine + (table->flags & Offset))),
|
||||
mark_set (false),
|
||||
mark (0) {}
|
||||
|
||||
bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
|
||||
StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> &entry)
|
||||
{ return entry.data.ankrActionIndex != 0xFFFF; }
|
||||
void transition (hb_buffer_t *buffer,
|
||||
StateTableDriver<Types, EntryData> *driver,
|
||||
StateTableDriver<Types, EntryData, Flags> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
|
||||
|
@ -634,8 +639,10 @@ struct KerxSubTableFormat4
|
|||
}
|
||||
}
|
||||
|
||||
private:
|
||||
public:
|
||||
hb_aat_apply_context_t *c;
|
||||
const KerxSubTableFormat4 *table;
|
||||
private:
|
||||
unsigned int action_type;
|
||||
const HBUINT16 *ankrData;
|
||||
bool mark_set;
|
||||
|
@ -648,12 +655,7 @@ struct KerxSubTableFormat4
|
|||
|
||||
driver_context_t dc (this, c);
|
||||
|
||||
StateTableDriver<Types, EntryData> driver (machine, c->font->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!(c->buffer_digest.may_have (c->left_set) &&
|
||||
c->buffer_digest.may_have (c->right_set)))
|
||||
return_trace (false);
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->font->face);
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
|
@ -671,10 +673,8 @@ struct KerxSubTableFormat4
|
|||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
{
|
||||
set_t set;
|
||||
machine.collect_glyphs (set, num_glyphs);
|
||||
left_set.union_ (set);
|
||||
right_set.union_ (set);
|
||||
machine.collect_initial_glyphs (left_set, num_glyphs, *this);
|
||||
//machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -735,10 +735,6 @@ struct KerxSubTableFormat6
|
|||
if (header.coverage & header.Backwards)
|
||||
return_trace (false);
|
||||
|
||||
if (!(c->buffer_digest.may_have (c->left_set) &&
|
||||
c->buffer_digest.may_have (c->right_set)))
|
||||
return_trace (false);
|
||||
|
||||
accelerator_t accel (*this, c);
|
||||
hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
|
||||
machine.kern (c->font, c->buffer, c->plan->kern_mask);
|
||||
|
@ -793,7 +789,7 @@ struct KerxSubTableFormat6
|
|||
|
||||
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||
{
|
||||
if (!c->left_set[left] || !c->right_set[right]) return 0;
|
||||
if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
|
||||
return table.get_kerning (left, right, c);
|
||||
}
|
||||
};
|
||||
|
@ -925,7 +921,18 @@ struct KerxSubTable
|
|||
* The 'kerx' Table
|
||||
*/
|
||||
|
||||
using kern_accelerator_data_t = hb_vector_t<hb_pair_t<hb_set_digest_t, hb_set_digest_t>>;
|
||||
struct kern_subtable_accelerator_data_t
|
||||
{
|
||||
hb_bit_set_t left_set;
|
||||
hb_bit_set_t right_set;
|
||||
mutable hb_aat_class_cache_t class_cache;
|
||||
};
|
||||
|
||||
struct kern_accelerator_data_t
|
||||
{
|
||||
hb_vector_t<kern_subtable_accelerator_data_t> subtable_accels;
|
||||
hb_aat_scratch_t scratch;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct KerxTable
|
||||
|
@ -985,14 +992,11 @@ struct KerxTable
|
|||
}
|
||||
|
||||
bool apply (AAT::hb_aat_apply_context_t *c,
|
||||
const kern_accelerator_data_t *accel_data = nullptr) const
|
||||
const kern_accelerator_data_t &accel_data) const
|
||||
{
|
||||
c->buffer->unsafe_to_concat ();
|
||||
|
||||
if (c->buffer->len < HB_AAT_BUFFER_DIGEST_THRESHOLD)
|
||||
c->buffer_digest = c->buffer->digest ();
|
||||
else
|
||||
c->buffer_digest = hb_set_digest_t::full ();
|
||||
c->setup_buffer_glyph_set ();
|
||||
|
||||
typedef typename T::SubTable SubTable;
|
||||
|
||||
|
@ -1005,12 +1009,25 @@ struct KerxTable
|
|||
{
|
||||
bool reverse;
|
||||
|
||||
auto &subtable_accel = accel_data.subtable_accels[i];
|
||||
|
||||
if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation))
|
||||
goto skip;
|
||||
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ())
|
||||
goto skip;
|
||||
|
||||
c->left_set = &subtable_accel.left_set;
|
||||
c->right_set = &subtable_accel.right_set;
|
||||
c->machine_glyph_set = &subtable_accel.left_set;
|
||||
c->machine_class_cache = &subtable_accel.class_cache;
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped subtable %u because no glyph matches", c->lookup_index);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
reverse = bool (st->u.header.coverage & st->u.header.Backwards) !=
|
||||
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
|
||||
|
||||
|
@ -1037,16 +1054,6 @@ struct KerxTable
|
|||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
|
||||
if (accel_data)
|
||||
{
|
||||
c->left_set = (*accel_data)[i].first;
|
||||
c->right_set = (*accel_data)[i].second;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->left_set = c->right_set = hb_set_digest_t::full ();
|
||||
}
|
||||
|
||||
{
|
||||
/* See comment in sanitize() for conditional here. */
|
||||
hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
|
||||
|
@ -1122,9 +1129,13 @@ struct KerxTable
|
|||
unsigned int count = thiz()->tableCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
hb_set_digest_t left_set, right_set;
|
||||
st->collect_glyphs (left_set, right_set, num_glyphs);
|
||||
accel_data.push (hb_pair (left_set, right_set));
|
||||
auto &subtable_accel = *accel_data.subtable_accels.push ();
|
||||
if (unlikely (accel_data.subtable_accels.in_error ()))
|
||||
return accel_data;
|
||||
|
||||
st->collect_glyphs (subtable_accel.left_set, subtable_accel.right_set, num_glyphs);
|
||||
subtable_accel.class_cache.clear ();
|
||||
|
||||
st = &StructAfter<SubTable> (*st);
|
||||
}
|
||||
|
||||
|
@ -1148,11 +1159,12 @@ struct KerxTable
|
|||
|
||||
bool apply (AAT::hb_aat_apply_context_t *c) const
|
||||
{
|
||||
return table->apply (c, &accel_data);
|
||||
return table->apply (c, accel_data);
|
||||
}
|
||||
|
||||
hb_blob_ptr_t<T> table;
|
||||
kern_accelerator_data_t accel_data;
|
||||
hb_aat_scratch_t scratch;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -29,8 +29,7 @@
|
|||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-aat-layout-common.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-ot-layout.hh"
|
||||
#include "hb-aat-map.hh"
|
||||
|
||||
/*
|
||||
|
@ -53,35 +52,40 @@ struct RearrangementSubtable
|
|||
|
||||
typedef void EntryData;
|
||||
|
||||
struct driver_context_t
|
||||
enum Flags
|
||||
{
|
||||
static constexpr bool in_place = true;
|
||||
enum Flags
|
||||
{
|
||||
MarkFirst = 0x8000, /* If set, make the current glyph the first
|
||||
MarkFirst = 0x8000, /* If set, make the current glyph the first
|
||||
* glyph to be rearranged. */
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph
|
||||
* before going to the new state. This means
|
||||
* that the glyph index doesn't change, even
|
||||
* if the glyph at that index has changed. */
|
||||
MarkLast = 0x2000, /* If set, make the current glyph the last
|
||||
MarkLast = 0x2000, /* If set, make the current glyph the last
|
||||
* glyph to be rearranged. */
|
||||
Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */
|
||||
Verb = 0x000F, /* The type of rearrangement specified. */
|
||||
};
|
||||
Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */
|
||||
Verb = 0x000F, /* The type of rearrangement specified. */
|
||||
};
|
||||
|
||||
driver_context_t (const RearrangementSubtable *table HB_UNUSED) :
|
||||
bool is_action_initiable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return (entry.flags & MarkFirst);
|
||||
}
|
||||
bool is_actionable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return (entry.flags & Verb);
|
||||
}
|
||||
|
||||
struct driver_context_t
|
||||
{
|
||||
static constexpr bool in_place = true;
|
||||
|
||||
driver_context_t (const RearrangementSubtable *table_) :
|
||||
ret (false),
|
||||
table (table_),
|
||||
start (0), end (0) {}
|
||||
|
||||
bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
|
||||
StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> &entry) const
|
||||
{
|
||||
return (entry.flags & Verb) && start < end;
|
||||
}
|
||||
void transition (hb_buffer_t *buffer,
|
||||
StateTableDriver<Types, EntryData> *driver,
|
||||
StateTableDriver<Types, EntryData, Flags> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
unsigned int flags = entry.flags;
|
||||
|
@ -158,6 +162,7 @@ struct RearrangementSubtable
|
|||
|
||||
public:
|
||||
bool ret;
|
||||
const RearrangementSubtable *table;
|
||||
private:
|
||||
unsigned int start;
|
||||
unsigned int end;
|
||||
|
@ -169,11 +174,7 @@ struct RearrangementSubtable
|
|||
|
||||
driver_context_t dc (this);
|
||||
|
||||
StateTableDriver<Types, EntryData> driver (machine, c->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!c->buffer_digest.may_have (c->machine_glyph_set))
|
||||
return_trace (false);
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
|
@ -207,39 +208,38 @@ struct ContextualSubtable
|
|||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
enum Flags
|
||||
{
|
||||
SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
||||
* going to the new state. */
|
||||
Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */
|
||||
};
|
||||
|
||||
bool is_action_initiable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return (entry.flags & SetMark);
|
||||
}
|
||||
bool is_actionable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
|
||||
}
|
||||
|
||||
struct driver_context_t
|
||||
{
|
||||
static constexpr bool in_place = true;
|
||||
enum Flags
|
||||
{
|
||||
SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
||||
* going to the new state. */
|
||||
Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */
|
||||
};
|
||||
|
||||
driver_context_t (const ContextualSubtable *table_,
|
||||
hb_aat_apply_context_t *c_) :
|
||||
ret (false),
|
||||
c (c_),
|
||||
gdef (*c->gdef_table),
|
||||
mark_set (false),
|
||||
has_glyph_classes (gdef.has_glyph_classes ()),
|
||||
mark (0),
|
||||
table (table_),
|
||||
mark_set (false),
|
||||
mark (0),
|
||||
subs (table+table->substitutionTables) {}
|
||||
|
||||
bool is_actionable (hb_buffer_t *buffer,
|
||||
StateTableDriver<Types, EntryData> *driver,
|
||||
const Entry<EntryData> &entry) const
|
||||
{
|
||||
if (buffer->idx == buffer->len && !mark_set)
|
||||
return false;
|
||||
|
||||
return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
|
||||
}
|
||||
void transition (hb_buffer_t *buffer,
|
||||
StateTableDriver<Types, EntryData> *driver,
|
||||
StateTableDriver<Types, EntryData, Flags> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
/* Looks like CoreText applies neither mark nor current substitution for
|
||||
|
@ -271,11 +271,7 @@ struct ContextualSubtable
|
|||
if (replacement)
|
||||
{
|
||||
buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
|
||||
buffer->info[mark].codepoint = *replacement;
|
||||
c->buffer_digest.add (*replacement);
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->info[mark],
|
||||
gdef.get_glyph_props (*replacement));
|
||||
c->replace_glyph_inplace (mark, *replacement);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
@ -301,11 +297,7 @@ struct ContextualSubtable
|
|||
}
|
||||
if (replacement)
|
||||
{
|
||||
buffer->info[idx].codepoint = *replacement;
|
||||
c->buffer_digest.add (*replacement);
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&buffer->info[idx],
|
||||
gdef.get_glyph_props (*replacement));
|
||||
c->replace_glyph_inplace (idx, *replacement);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
@ -318,13 +310,11 @@ struct ContextualSubtable
|
|||
|
||||
public:
|
||||
bool ret;
|
||||
private:
|
||||
hb_aat_apply_context_t *c;
|
||||
const OT::GDEF &gdef;
|
||||
bool mark_set;
|
||||
bool has_glyph_classes;
|
||||
unsigned int mark;
|
||||
const ContextualSubtable *table;
|
||||
private:
|
||||
bool mark_set;
|
||||
unsigned int mark;
|
||||
const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false> &subs;
|
||||
};
|
||||
|
||||
|
@ -334,11 +324,7 @@ struct ContextualSubtable
|
|||
|
||||
driver_context_t dc (this, c);
|
||||
|
||||
StateTableDriver<Types, EntryData> driver (machine, c->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!c->buffer_digest.may_have (c->machine_glyph_set))
|
||||
return_trace (false);
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
|
@ -389,6 +375,16 @@ struct LigatureEntry;
|
|||
template <>
|
||||
struct LigatureEntry<true>
|
||||
{
|
||||
|
||||
struct EntryData
|
||||
{
|
||||
HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry
|
||||
* for processing this group, if indicated
|
||||
* by the flags. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
enum Flags
|
||||
{
|
||||
SetComponent = 0x8000, /* Push this glyph onto the component stack for
|
||||
|
@ -400,14 +396,8 @@ struct LigatureEntry<true>
|
|||
Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */
|
||||
};
|
||||
|
||||
struct EntryData
|
||||
{
|
||||
HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry
|
||||
* for processing this group, if indicated
|
||||
* by the flags. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
static bool initiateAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & SetComponent; }
|
||||
|
||||
static bool performAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & PerformAction; }
|
||||
|
@ -418,6 +408,8 @@ struct LigatureEntry<true>
|
|||
template <>
|
||||
struct LigatureEntry<false>
|
||||
{
|
||||
typedef void EntryData;
|
||||
|
||||
enum Flags
|
||||
{
|
||||
SetComponent = 0x8000, /* Push this glyph onto the component stack for
|
||||
|
@ -429,7 +421,8 @@ struct LigatureEntry<false>
|
|||
* multiple of 4. */
|
||||
};
|
||||
|
||||
typedef void EntryData;
|
||||
static bool initiateAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & SetComponent; }
|
||||
|
||||
static bool performAction (const Entry<EntryData> &entry)
|
||||
{ return entry.flags & Offset; }
|
||||
|
@ -447,13 +440,23 @@ struct LigatureSubtable
|
|||
typedef LigatureEntry<Types::extended> LigatureEntryT;
|
||||
typedef typename LigatureEntryT::EntryData EntryData;
|
||||
|
||||
enum Flags
|
||||
{
|
||||
DontAdvance = LigatureEntryT::DontAdvance,
|
||||
};
|
||||
|
||||
bool is_action_initiable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return LigatureEntryT::initiateAction (entry);
|
||||
}
|
||||
bool is_actionable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return LigatureEntryT::performAction (entry);
|
||||
}
|
||||
|
||||
struct driver_context_t
|
||||
{
|
||||
static constexpr bool in_place = false;
|
||||
enum
|
||||
{
|
||||
DontAdvance = LigatureEntryT::DontAdvance,
|
||||
};
|
||||
enum LigActionFlags
|
||||
{
|
||||
LigActionLast = 0x80000000, /* This is the last action in the list. This also
|
||||
|
@ -476,14 +479,8 @@ struct LigatureSubtable
|
|||
ligature (table+table->ligature),
|
||||
match_length (0) {}
|
||||
|
||||
bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
|
||||
StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> &entry) const
|
||||
{
|
||||
return LigatureEntryT::performAction (entry);
|
||||
}
|
||||
void transition (hb_buffer_t *buffer,
|
||||
StateTableDriver<Types, EntryData> *driver,
|
||||
StateTableDriver<Types, EntryData, Flags> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
|
||||
|
@ -556,7 +553,7 @@ struct LigatureSubtable
|
|||
hb_codepoint_t lig = ligatureData;
|
||||
|
||||
DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
|
||||
if (unlikely (!buffer->replace_glyph (lig))) return;
|
||||
if (unlikely (!c->replace_glyph (lig))) return;
|
||||
|
||||
unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
|
||||
/* Now go and delete all subsequent components. */
|
||||
|
@ -564,8 +561,7 @@ struct LigatureSubtable
|
|||
{
|
||||
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
|
||||
if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return;
|
||||
buffer->cur().unicode_props() |= UPROPS_MASK_IGNORABLE;
|
||||
if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return;
|
||||
if (!c->delete_glyph ()) return;
|
||||
}
|
||||
|
||||
if (unlikely (!buffer->move_to (lig_end))) return;
|
||||
|
@ -581,9 +577,9 @@ struct LigatureSubtable
|
|||
|
||||
public:
|
||||
bool ret;
|
||||
private:
|
||||
hb_aat_apply_context_t *c;
|
||||
const LigatureSubtable *table;
|
||||
private:
|
||||
const UnsizedArrayOf<HBUINT32> &ligAction;
|
||||
const UnsizedArrayOf<HBUINT16> &component;
|
||||
const UnsizedArrayOf<HBGlyphID16> &ligature;
|
||||
|
@ -597,11 +593,7 @@ struct LigatureSubtable
|
|||
|
||||
driver_context_t dc (this, c);
|
||||
|
||||
StateTableDriver<Types, EntryData> driver (machine, c->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!c->buffer_digest.may_have (c->machine_glyph_set))
|
||||
return_trace (false);
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
|
@ -638,9 +630,6 @@ struct NoncontextualSubtable
|
|||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
const OT::GDEF &gdef (*c->gdef_table);
|
||||
bool has_glyph_classes = gdef.has_glyph_classes ();
|
||||
|
||||
bool ret = false;
|
||||
unsigned int num_glyphs = c->face->get_num_glyphs ();
|
||||
|
||||
|
@ -670,11 +659,7 @@ struct NoncontextualSubtable
|
|||
const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
|
||||
if (replacement)
|
||||
{
|
||||
info[i].codepoint = *replacement;
|
||||
c->buffer_digest.add (*replacement);
|
||||
if (has_glyph_classes)
|
||||
_hb_glyph_info_set_glyph_props (&info[i],
|
||||
gdef.get_glyph_props (*replacement));
|
||||
c->replace_glyph_inplace (i, *replacement);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
@ -682,6 +667,12 @@ struct NoncontextualSubtable
|
|||
return_trace (ret);
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs) const
|
||||
{
|
||||
substitute.collect_glyphs (glyphs, num_glyphs);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -715,73 +706,78 @@ struct InsertionSubtable
|
|||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
enum Flags
|
||||
{
|
||||
SetMark = 0x8000, /* If set, mark the current glyph. */
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
||||
* going to the new state. This does not mean
|
||||
* that the glyph pointed to is the same one as
|
||||
* before. If you've made insertions immediately
|
||||
* downstream of the current glyph, the next glyph
|
||||
* processed would in fact be the first one
|
||||
* inserted. */
|
||||
CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero,
|
||||
* then the specified glyph list will be inserted
|
||||
* as a kashida-like insertion, either before or
|
||||
* after the current glyph (depending on the state
|
||||
* of the currentInsertBefore flag). If clear, and
|
||||
* the currentInsertList is nonzero, then the
|
||||
* specified glyph list will be inserted as a
|
||||
* split-vowel-like insertion, either before or
|
||||
* after the current glyph (depending on the state
|
||||
* of the currentInsertBefore flag). */
|
||||
MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero,
|
||||
* then the specified glyph list will be inserted
|
||||
* as a kashida-like insertion, either before or
|
||||
* after the marked glyph (depending on the state
|
||||
* of the markedInsertBefore flag). If clear, and
|
||||
* the markedInsertList is nonzero, then the
|
||||
* specified glyph list will be inserted as a
|
||||
* split-vowel-like insertion, either before or
|
||||
* after the marked glyph (depending on the state
|
||||
* of the markedInsertBefore flag). */
|
||||
CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made
|
||||
* to the left of the current glyph. If clear,
|
||||
* they're made to the right of the current glyph. */
|
||||
MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be
|
||||
* made to the left of the marked glyph. If clear,
|
||||
* they're made to the right of the marked glyph. */
|
||||
CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the
|
||||
* number of glyphs to insert at the current
|
||||
* position. Since zero means no insertions, the
|
||||
* largest number of insertions at any given
|
||||
* current location is 31 glyphs. */
|
||||
MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the
|
||||
* number of glyphs to insert at the marked
|
||||
* position. Since zero means no insertions, the
|
||||
* largest number of insertions at any given
|
||||
* marked location is 31 glyphs. */
|
||||
};
|
||||
|
||||
bool is_action_initiable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return (entry.flags & SetMark);
|
||||
}
|
||||
bool is_actionable (const Entry<EntryData> &entry) const
|
||||
{
|
||||
return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
|
||||
(entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
|
||||
}
|
||||
|
||||
struct driver_context_t
|
||||
{
|
||||
static constexpr bool in_place = false;
|
||||
enum Flags
|
||||
{
|
||||
SetMark = 0x8000, /* If set, mark the current glyph. */
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
||||
* going to the new state. This does not mean
|
||||
* that the glyph pointed to is the same one as
|
||||
* before. If you've made insertions immediately
|
||||
* downstream of the current glyph, the next glyph
|
||||
* processed would in fact be the first one
|
||||
* inserted. */
|
||||
CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero,
|
||||
* then the specified glyph list will be inserted
|
||||
* as a kashida-like insertion, either before or
|
||||
* after the current glyph (depending on the state
|
||||
* of the currentInsertBefore flag). If clear, and
|
||||
* the currentInsertList is nonzero, then the
|
||||
* specified glyph list will be inserted as a
|
||||
* split-vowel-like insertion, either before or
|
||||
* after the current glyph (depending on the state
|
||||
* of the currentInsertBefore flag). */
|
||||
MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero,
|
||||
* then the specified glyph list will be inserted
|
||||
* as a kashida-like insertion, either before or
|
||||
* after the marked glyph (depending on the state
|
||||
* of the markedInsertBefore flag). If clear, and
|
||||
* the markedInsertList is nonzero, then the
|
||||
* specified glyph list will be inserted as a
|
||||
* split-vowel-like insertion, either before or
|
||||
* after the marked glyph (depending on the state
|
||||
* of the markedInsertBefore flag). */
|
||||
CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made
|
||||
* to the left of the current glyph. If clear,
|
||||
* they're made to the right of the current glyph. */
|
||||
MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be
|
||||
* made to the left of the marked glyph. If clear,
|
||||
* they're made to the right of the marked glyph. */
|
||||
CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the
|
||||
* number of glyphs to insert at the current
|
||||
* position. Since zero means no insertions, the
|
||||
* largest number of insertions at any given
|
||||
* current location is 31 glyphs. */
|
||||
MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the
|
||||
* number of glyphs to insert at the marked
|
||||
* position. Since zero means no insertions, the
|
||||
* largest number of insertions at any given
|
||||
* marked location is 31 glyphs. */
|
||||
};
|
||||
|
||||
driver_context_t (const InsertionSubtable *table,
|
||||
driver_context_t (const InsertionSubtable *table_,
|
||||
hb_aat_apply_context_t *c_) :
|
||||
ret (false),
|
||||
c (c_),
|
||||
table (table_),
|
||||
mark (0),
|
||||
insertionAction (table+table->insertionAction) {}
|
||||
|
||||
bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
|
||||
StateTableDriver<Types, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> &entry) const
|
||||
{
|
||||
return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
|
||||
(entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
|
||||
}
|
||||
void transition (hb_buffer_t *buffer,
|
||||
StateTableDriver<Types, EntryData> *driver,
|
||||
StateTableDriver<Types, EntryData, Flags> *driver,
|
||||
const Entry<EntryData> &entry)
|
||||
{
|
||||
unsigned int flags = entry.flags;
|
||||
|
@ -805,9 +801,7 @@ struct InsertionSubtable
|
|||
if (buffer->idx < buffer->len && !before)
|
||||
if (unlikely (!buffer->copy_glyph ())) return;
|
||||
/* TODO We ignore KashidaLike setting. */
|
||||
if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->buffer_digest.add (glyphs[i]);
|
||||
if (unlikely (!c->output_glyphs (count, glyphs))) return;
|
||||
ret = true;
|
||||
if (buffer->idx < buffer->len && !before)
|
||||
buffer->skip_glyph ();
|
||||
|
@ -836,7 +830,8 @@ struct InsertionSubtable
|
|||
if (buffer->idx < buffer->len && !before)
|
||||
if (unlikely (!buffer->copy_glyph ())) return;
|
||||
/* TODO We ignore KashidaLike setting. */
|
||||
if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
|
||||
if (unlikely (!c->output_glyphs (count, glyphs))) return;
|
||||
ret = true;
|
||||
if (buffer->idx < buffer->len && !before)
|
||||
buffer->skip_glyph ();
|
||||
|
||||
|
@ -861,8 +856,9 @@ struct InsertionSubtable
|
|||
|
||||
public:
|
||||
bool ret;
|
||||
private:
|
||||
hb_aat_apply_context_t *c;
|
||||
const InsertionSubtable *table;
|
||||
private:
|
||||
unsigned int mark;
|
||||
const UnsizedArrayOf<HBGlyphID16> &insertionAction;
|
||||
};
|
||||
|
@ -873,11 +869,7 @@ struct InsertionSubtable
|
|||
|
||||
driver_context_t dc (this, c);
|
||||
|
||||
StateTableDriver<Types, EntryData> driver (machine, c->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!c->buffer_digest.may_have (c->machine_glyph_set))
|
||||
return_trace (false);
|
||||
StateTableDriver<Types, EntryData, Flags> driver (machine, c->face);
|
||||
|
||||
driver.drive (&dc, c);
|
||||
|
||||
|
@ -935,24 +927,33 @@ struct hb_accelerate_subtables_context_t :
|
|||
friend struct hb_aat_layout_lookup_accelerator_t;
|
||||
|
||||
public:
|
||||
hb_set_digest_t digest;
|
||||
hb_bit_set_t glyph_set;
|
||||
mutable hb_aat_class_cache_t class_cache;
|
||||
|
||||
template <typename T>
|
||||
auto init_ (const T &obj_, unsigned num_glyphs, hb_priority<1>) HB_AUTO_RETURN
|
||||
(
|
||||
obj_.machine.collect_glyphs (this->digest, num_glyphs)
|
||||
obj_.machine.collect_initial_glyphs (glyph_set, num_glyphs, obj_)
|
||||
)
|
||||
|
||||
template <typename T>
|
||||
void init_ (const T &obj_, unsigned num_glyphs, hb_priority<0>)
|
||||
{
|
||||
digest = digest.full ();
|
||||
obj_.collect_initial_glyphs (glyph_set, num_glyphs);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void init (const T &obj_, unsigned num_glyphs)
|
||||
{
|
||||
glyph_set.init ();
|
||||
init_ (obj_, num_glyphs, hb_prioritize);
|
||||
class_cache.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
fini ()
|
||||
{
|
||||
glyph_set.fini ();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -999,12 +1000,21 @@ struct hb_aat_layout_chain_accelerator_t
|
|||
if (unlikely (!thiz))
|
||||
return nullptr;
|
||||
|
||||
thiz->count = count;
|
||||
|
||||
hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables, num_glyphs);
|
||||
chain.dispatch (&c_accelerate_subtables);
|
||||
|
||||
return thiz;
|
||||
}
|
||||
|
||||
void destroy ()
|
||||
{
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
subtables[i].fini ();
|
||||
}
|
||||
|
||||
unsigned count;
|
||||
hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
|
||||
};
|
||||
|
||||
|
@ -1152,17 +1162,28 @@ struct Chain
|
|||
{
|
||||
bool reverse;
|
||||
|
||||
if (hb_none (hb_iter (c->range_flags) |
|
||||
hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); })))
|
||||
goto skip;
|
||||
c->subtable_flags = subtable->subFeatureFlags;
|
||||
c->machine_glyph_set = accel ? accel->subtables[i].digest : hb_set_digest_t::full ();
|
||||
auto coverage = subtable->get_coverage ();
|
||||
|
||||
if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
|
||||
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
|
||||
bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical))
|
||||
hb_mask_t subtable_flags = subtable->subFeatureFlags;
|
||||
if (hb_none (hb_iter (c->range_flags) |
|
||||
hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); })))
|
||||
goto skip;
|
||||
|
||||
c->subtable_flags = subtable_flags;
|
||||
c->machine_glyph_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_bit_set_t);
|
||||
c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr;
|
||||
|
||||
if (!(coverage & ChainSubtable<Types>::AllDirections) &&
|
||||
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
|
||||
bool (coverage & ChainSubtable<Types>::Vertical))
|
||||
goto skip;
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable %u because no glyph matches", c->lookup_index);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
/* Buffer contents is always in logical direction. Determine if
|
||||
* we need to reverse before applying this subtable. We reverse
|
||||
* back after if we did reverse indeed.
|
||||
|
@ -1190,9 +1211,9 @@ struct Chain
|
|||
(the order opposite that of the characters, which
|
||||
may be right-to-left or left-to-right).
|
||||
*/
|
||||
reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ?
|
||||
bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) :
|
||||
bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) !=
|
||||
reverse = coverage & ChainSubtable<Types>::Logical ?
|
||||
bool (coverage & ChainSubtable<Types>::Backwards) :
|
||||
bool (coverage & ChainSubtable<Types>::Backwards) !=
|
||||
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
|
||||
|
||||
if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index))
|
||||
|
@ -1298,9 +1319,15 @@ struct mortmorx
|
|||
hb_sanitize_context_t sc;
|
||||
this->table = sc.reference_table<T> (face);
|
||||
|
||||
if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
|
||||
{
|
||||
hb_blob_destroy (this->table.get_blob ());
|
||||
this->table = hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
this->chain_count = table->get_chain_count ();
|
||||
|
||||
this->accels = (hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *) hb_calloc (this->chain_count, sizeof (*accels));
|
||||
this->accels = (hb_atomic_t<hb_aat_layout_chain_accelerator_t *> *) hb_calloc (this->chain_count, sizeof (*accels));
|
||||
if (unlikely (!this->accels))
|
||||
{
|
||||
this->chain_count = 0;
|
||||
|
@ -1311,7 +1338,11 @@ struct mortmorx
|
|||
~accelerator_t ()
|
||||
{
|
||||
for (unsigned int i = 0; i < this->chain_count; i++)
|
||||
{
|
||||
if (this->accels[i])
|
||||
this->accels[i]->destroy ();
|
||||
hb_free (this->accels[i]);
|
||||
}
|
||||
hb_free (this->accels);
|
||||
this->table.destroy ();
|
||||
}
|
||||
|
@ -1343,7 +1374,8 @@ struct mortmorx
|
|||
|
||||
hb_blob_ptr_t<T> table;
|
||||
unsigned int chain_count;
|
||||
hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *accels;
|
||||
hb_atomic_t<hb_aat_layout_chain_accelerator_t *> *accels;
|
||||
hb_aat_scratch_t scratch;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1365,9 +1397,8 @@ struct mortmorx
|
|||
|
||||
unsigned get_chain_count () const
|
||||
{
|
||||
return chainCount;
|
||||
return chainCount;
|
||||
}
|
||||
|
||||
void apply (hb_aat_apply_context_t *c,
|
||||
const hb_aat_map_t &map,
|
||||
const accelerator_t &accel) const
|
||||
|
@ -1376,10 +1407,7 @@ struct mortmorx
|
|||
|
||||
c->buffer->unsafe_to_concat ();
|
||||
|
||||
if (c->buffer->len < HB_AAT_BUFFER_DIGEST_THRESHOLD)
|
||||
c->buffer_digest = c->buffer->digest ();
|
||||
else
|
||||
c->buffer_digest = hb_set_digest_t::full ();
|
||||
c->setup_buffer_glyph_set ();
|
||||
|
||||
c->set_lookup_index (0);
|
||||
const Chain<Types> *chain = &firstChain;
|
||||
|
@ -1428,8 +1456,17 @@ struct mortmorx
|
|||
DEFINE_SIZE_MIN (8);
|
||||
};
|
||||
|
||||
struct morx : mortmorx<morx, ExtendedTypes, HB_AAT_TAG_morx> {};
|
||||
struct mort : mortmorx<mort, ObsoleteTypes, HB_AAT_TAG_mort> {};
|
||||
struct morx : mortmorx<morx, ExtendedTypes, HB_AAT_TAG_morx>
|
||||
{
|
||||
HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const;
|
||||
};
|
||||
|
||||
struct mort : mortmorx<mort, ObsoleteTypes, HB_AAT_TAG_mort>
|
||||
{
|
||||
HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const;
|
||||
};
|
||||
|
||||
struct morx_accelerator_t : morx::accelerator_t {
|
||||
morx_accelerator_t (hb_face_t *face) : morx::accelerator_t (face) {}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "hb-aat-layout-common.hh"
|
||||
#include "hb-ot-layout.hh"
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-stat-table.hh"
|
||||
|
||||
/*
|
||||
* trak -- Tracking
|
||||
|
@ -48,22 +49,74 @@ struct TrackTableEntry
|
|||
|
||||
float get_track_value () const { return track.to_float (); }
|
||||
|
||||
int get_value (const void *base, unsigned int index,
|
||||
unsigned int table_size) const
|
||||
{ return (base+valuesZ).as_array (table_size)[index]; }
|
||||
float interpolate_at (unsigned int idx,
|
||||
float ptem,
|
||||
const void *base,
|
||||
hb_array_t<const F16DOT16> size_table) const
|
||||
{
|
||||
const FWORD *values = (base+valuesZ).arrayZ;
|
||||
|
||||
float s0 = size_table[idx].to_float ();
|
||||
float s1 = size_table[idx + 1].to_float ();
|
||||
int v0 = values[idx];
|
||||
int v1 = values[idx + 1];
|
||||
|
||||
// Deal with font bugs.
|
||||
if (unlikely (s1 < s0))
|
||||
{ hb_swap (s0, s1); hb_swap (v0, v1); }
|
||||
if (unlikely (ptem < s0)) return v0;
|
||||
if (unlikely (ptem > s1)) return v1;
|
||||
if (unlikely (s0 == s1)) return (v0 + v1) * 0.5f;
|
||||
|
||||
float t = (ptem - s0) / (s1 - s0);
|
||||
return v0 + t * (v1 - v0);
|
||||
}
|
||||
|
||||
float get_value (float ptem,
|
||||
const void *base,
|
||||
hb_array_t<const F16DOT16> size_table) const
|
||||
{
|
||||
const FWORD *values = (base+valuesZ).arrayZ;
|
||||
|
||||
unsigned int n_sizes = size_table.length;
|
||||
|
||||
/*
|
||||
* Choose size.
|
||||
*/
|
||||
if (!n_sizes) return 0.f;
|
||||
if (n_sizes == 1) return values[0];
|
||||
|
||||
// At least two entries.
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < n_sizes; i++)
|
||||
if (size_table[i].to_float () >= ptem)
|
||||
break;
|
||||
|
||||
// Boundary conditions.
|
||||
if (i == 0) return values[0];
|
||||
if (i == n_sizes) return values[n_sizes - 1];
|
||||
|
||||
// Exact match.
|
||||
if (size_table[i].to_float () == ptem) return values[i];
|
||||
|
||||
// Interpolate.
|
||||
return interpolate_at (i - 1, ptem, base, size_table);
|
||||
}
|
||||
|
||||
public:
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base,
|
||||
unsigned int table_size) const
|
||||
bool sanitize (hb_sanitize_context_t *c,
|
||||
const void *base,
|
||||
unsigned int n_sizes) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
(valuesZ.sanitize (c, base, table_size))));
|
||||
(valuesZ.sanitize (c, base, n_sizes))));
|
||||
}
|
||||
|
||||
protected:
|
||||
F16DOT16 track; /* Track value for this record. */
|
||||
NameID trackNameID; /* The 'name' table index for this track.
|
||||
OT::NameID trackNameID; /* The 'name' table index for this track.
|
||||
* (a short word or phrase like "loose"
|
||||
* or "very tight") */
|
||||
NNOffset16To<UnsizedArrayOf<FWORD>>
|
||||
|
@ -76,58 +129,38 @@ struct TrackTableEntry
|
|||
|
||||
struct TrackData
|
||||
{
|
||||
float interpolate_at (unsigned int idx,
|
||||
float target_size,
|
||||
const TrackTableEntry &trackTableEntry,
|
||||
const void *base) const
|
||||
float get_tracking (const void *base, float ptem, float track = 0.f) const
|
||||
{
|
||||
unsigned int sizes = nSizes;
|
||||
hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
unsigned count = nTracks;
|
||||
hb_array_t<const F16DOT16> size_table = (base+sizeTable).as_array (nSizes);
|
||||
|
||||
float s0 = size_table[idx].to_float ();
|
||||
float s1 = size_table[idx + 1].to_float ();
|
||||
float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0);
|
||||
return t * trackTableEntry.get_value (base, idx + 1, sizes) +
|
||||
(1.f - t) * trackTableEntry.get_value (base, idx, sizes);
|
||||
}
|
||||
if (!count) return 0.f;
|
||||
if (count == 1) return trackTable[0].get_value (ptem, base, size_table);
|
||||
|
||||
int get_tracking (const void *base, float ptem) const
|
||||
{
|
||||
/*
|
||||
* Choose track.
|
||||
*/
|
||||
const TrackTableEntry *trackTableEntry = nullptr;
|
||||
unsigned int count = nTracks;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
/* Note: Seems like the track entries are sorted by values. But the
|
||||
* spec doesn't explicitly say that. It just mentions it in the example. */
|
||||
// At least two entries.
|
||||
|
||||
/* For now we only seek for track entries with zero tracking value */
|
||||
unsigned i = 0;
|
||||
unsigned j = count - 1;
|
||||
|
||||
if (trackTable[i].get_track_value () == 0.f)
|
||||
{
|
||||
trackTableEntry = &trackTable[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!trackTableEntry) return 0;
|
||||
// Find the two entries that track is between.
|
||||
while (i + 1 < count && trackTable[i + 1].get_track_value () <= track)
|
||||
i++;
|
||||
while (j > 0 && trackTable[j - 1].get_track_value () >= track)
|
||||
j--;
|
||||
|
||||
/*
|
||||
* Choose size.
|
||||
*/
|
||||
unsigned int sizes = nSizes;
|
||||
if (!sizes) return 0;
|
||||
if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
|
||||
// Exact match.
|
||||
if (i == j) return trackTable[i].get_value (ptem, base, size_table);
|
||||
|
||||
hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
unsigned int size_index;
|
||||
for (size_index = 0; size_index < sizes - 1; size_index++)
|
||||
if (size_table[size_index].to_float () >= ptem)
|
||||
break;
|
||||
// Interpolate.
|
||||
|
||||
return roundf (interpolate_at (size_index ? size_index - 1 : 0, ptem,
|
||||
*trackTableEntry, base));
|
||||
float t0 = trackTable[i].get_track_value ();
|
||||
float t1 = trackTable[j].get_track_value ();
|
||||
|
||||
float t = (track - t0) / (t1 - t0);
|
||||
|
||||
float a = trackTable[i].get_value (ptem, base, size_table);
|
||||
float b = trackTable[j].get_value (ptem, base, size_table);
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
|
@ -158,42 +191,52 @@ struct trak
|
|||
|
||||
bool has_data () const { return version.to_int (); }
|
||||
|
||||
bool apply (hb_aat_apply_context_t *c) const
|
||||
hb_position_t get_h_tracking (hb_font_t *font, float track = 0.f) const
|
||||
{
|
||||
float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE;
|
||||
return font->em_scalef_x ((this+horizData).get_tracking (this, ptem, track));
|
||||
}
|
||||
hb_position_t get_v_tracking (hb_font_t *font, float track = 0.f) const
|
||||
{
|
||||
float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE;
|
||||
return font->em_scalef_y ((this+vertData).get_tracking (this, ptem, track));
|
||||
}
|
||||
hb_position_t get_tracking (hb_font_t *font, hb_direction_t dir, float track = 0.f) const
|
||||
{
|
||||
#ifndef HB_NO_STYLE
|
||||
if (!font->face->table.STAT->has_data ())
|
||||
return 0;
|
||||
return HB_DIRECTION_IS_HORIZONTAL (dir) ?
|
||||
get_h_tracking (font, track) :
|
||||
get_v_tracking (font, track);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool apply (hb_aat_apply_context_t *c, float track = 0.f) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
hb_mask_t trak_mask = c->plan->trak_mask;
|
||||
|
||||
const float ptem = c->font->ptem;
|
||||
float ptem = c->font->ptem;
|
||||
if (unlikely (ptem <= 0.f))
|
||||
return_trace (false);
|
||||
{
|
||||
/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
|
||||
ptem = HB_CORETEXT_DEFAULT_FONT_SIZE;
|
||||
}
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||
{
|
||||
const TrackData &trackData = this+horizData;
|
||||
int tracking = trackData.get_tracking (this, ptem);
|
||||
hb_position_t offset_to_add = c->font->em_scalef_x (tracking / 2);
|
||||
hb_position_t advance_to_add = c->font->em_scalef_x (tracking);
|
||||
hb_position_t advance_to_add = get_h_tracking (c->font, track);
|
||||
foreach_grapheme (buffer, start, end)
|
||||
{
|
||||
if (!(buffer->info[start].mask & trak_mask)) continue;
|
||||
buffer->pos[start].x_advance += advance_to_add;
|
||||
buffer->pos[start].x_offset += offset_to_add;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const TrackData &trackData = this+vertData;
|
||||
int tracking = trackData.get_tracking (this, ptem);
|
||||
hb_position_t offset_to_add = c->font->em_scalef_y (tracking / 2);
|
||||
hb_position_t advance_to_add = c->font->em_scalef_y (tracking);
|
||||
hb_position_t advance_to_add = get_v_tracking (c->font, track);
|
||||
foreach_grapheme (buffer, start, end)
|
||||
{
|
||||
if (!(buffer->info[start].mask & trak_mask)) continue;
|
||||
buffer->pos[start].y_advance += advance_to_add;
|
||||
buffer->pos[start].y_offset += offset_to_add;
|
||||
}
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
#include "hb-aat-layout-trak-table.hh"
|
||||
#include "hb-aat-ltag-table.hh"
|
||||
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
|
||||
|
||||
/*
|
||||
* hb_aat_apply_context_t
|
||||
|
@ -55,13 +58,14 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p
|
|||
buffer (buffer_),
|
||||
sanitizer (),
|
||||
ankr_table (&Null (AAT::ankr)),
|
||||
gdef_table (
|
||||
gdef (
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
face->table.GDEF->table
|
||||
*face->table.GDEF->table
|
||||
#else
|
||||
&Null (GDEF)
|
||||
Null (GDEF)
|
||||
#endif
|
||||
),
|
||||
has_glyph_classes (gdef.has_glyph_classes ()),
|
||||
lookup_index (0)
|
||||
{
|
||||
sanitizer.init (blob);
|
||||
|
@ -200,13 +204,43 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag)
|
|||
#endif
|
||||
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
|
||||
/*
|
||||
* mort/morx/kerx/trak
|
||||
*/
|
||||
|
||||
|
||||
bool
|
||||
AAT::morx::is_blocklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const
|
||||
{
|
||||
#ifdef HB_NO_AAT_LAYOUT_BLOCKLIST
|
||||
return false;
|
||||
#endif
|
||||
|
||||
switch HB_CODEPOINT_ENCODE3 (blob->length,
|
||||
face->table.GSUB->table.get_length (),
|
||||
face->table.GDEF->table.get_length ())
|
||||
{
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/4108
|
||||
sha1sum:a71ca6813b7e56a772cffff7c24a5166b087197c AALMAGHRIBI.ttf */
|
||||
case HB_CODEPOINT_ENCODE3 (19892, 2794, 340):
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
AAT::mort::is_blocklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const
|
||||
{
|
||||
#ifdef HB_NO_AAT_LAYOUT_BLOCKLIST
|
||||
return false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
|
||||
hb_aat_map_t *map)
|
||||
|
@ -254,11 +288,14 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
|||
const hb_feature_t *features,
|
||||
unsigned num_features)
|
||||
{
|
||||
hb_aat_map_builder_t builder (font->face, plan->props);
|
||||
for (unsigned i = 0; i < num_features; i++)
|
||||
builder.add_feature (features[i]);
|
||||
hb_aat_map_t map;
|
||||
builder.compile (map);
|
||||
if (num_features)
|
||||
{
|
||||
hb_aat_map_builder_t builder (font->face, plan->props);
|
||||
for (unsigned i = 0; i < num_features; i++)
|
||||
builder.add_feature (features[i]);
|
||||
builder.compile (map);
|
||||
}
|
||||
|
||||
{
|
||||
auto &accel = *font->face->table.morx;
|
||||
|
@ -267,7 +304,10 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
|||
{
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
|
||||
if (!buffer->message (font, "start table morx")) return;
|
||||
morx.apply (&c, map, accel);
|
||||
c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
|
||||
morx.apply (&c, num_features ? map : plan->aat_map, accel);
|
||||
accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
|
||||
c.buffer_glyph_set = nullptr;
|
||||
(void) buffer->message (font, "end table morx");
|
||||
return;
|
||||
}
|
||||
|
@ -280,34 +320,24 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
|||
{
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
|
||||
if (!buffer->message (font, "start table mort")) return;
|
||||
mort.apply (&c, map, accel);
|
||||
mort.apply (&c, num_features ? map : plan->aat_map, accel);
|
||||
(void) buffer->message (font, "end table mort");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pos = buffer->pos;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
|
||||
pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_deleted_glyph (const hb_glyph_info_t *info)
|
||||
{
|
||||
return info->codepoint == AAT::DELETED_GLYPH;
|
||||
return _hb_glyph_info_is_aat_deleted (info);
|
||||
}
|
||||
|
||||
void
|
||||
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
|
||||
{
|
||||
buffer->delete_glyphs_inplace (is_deleted_glyph);
|
||||
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED)
|
||||
buffer->delete_glyphs_inplace (is_deleted_glyph);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -338,8 +368,11 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
|
|||
|
||||
AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
|
||||
if (!buffer->message (font, "start table kerx")) return;
|
||||
c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set ();
|
||||
c.set_ankr_table (font->face->table.ankr.get ());
|
||||
accel.apply (&c);
|
||||
accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set);
|
||||
c.buffer_glyph_set = nullptr;
|
||||
(void) buffer->message (font, "end table kerx");
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
#include "hb-ot-shape.hh"
|
||||
#include "hb-aat-ltag-table.hh"
|
||||
|
||||
/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
|
||||
#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
|
||||
|
||||
struct hb_aat_feature_mapping_t
|
||||
{
|
||||
hb_tag_t otFeatureTag;
|
||||
|
@ -57,9 +60,6 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
|
|||
const hb_feature_t *features,
|
||||
unsigned num_features);
|
||||
|
||||
HB_INTERNAL void
|
||||
hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);
|
||||
|
||||
HB_INTERNAL void
|
||||
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer);
|
||||
|
||||
|
|
|
@ -85,25 +85,31 @@ void
|
|||
hb_aat_map_builder_t::compile (hb_aat_map_t &m)
|
||||
{
|
||||
/* Compute active features per range, and compile each. */
|
||||
if (!features.length)
|
||||
{
|
||||
hb_aat_layout_compile_map (this, &m);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sort features by start/end events. */
|
||||
hb_vector_t<feature_event_t> feature_events;
|
||||
feature_events.alloc_exact (features.length * 2 + 1);
|
||||
for (unsigned int i = 0; i < features.length; i++)
|
||||
{
|
||||
auto &feature = features[i];
|
||||
auto &feature = features.arrayZ[i];
|
||||
|
||||
if (features[i].start == features[i].end)
|
||||
if (feature.start == feature.end)
|
||||
continue;
|
||||
|
||||
feature_event_t *event;
|
||||
|
||||
event = feature_events.push ();
|
||||
event->index = features[i].start;
|
||||
event->index = feature.start;
|
||||
event->start = true;
|
||||
event->feature = feature.info;
|
||||
|
||||
event = feature_events.push ();
|
||||
event->index = features[i].end;
|
||||
event->index = feature.end;
|
||||
event->start = false;
|
||||
event->feature = feature.info;
|
||||
}
|
||||
|
@ -139,12 +145,12 @@ hb_aat_map_builder_t::compile (hb_aat_map_t &m)
|
|||
current_features.qsort ();
|
||||
unsigned int j = 0;
|
||||
for (unsigned int i = 1; i < current_features.length; i++)
|
||||
if (current_features[i].type != current_features[j].type ||
|
||||
if (current_features.arrayZ[i].type != current_features.arrayZ[j].type ||
|
||||
/* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
|
||||
* respectively, so we mask out the low-order bit when checking for "duplicates"
|
||||
* (selectors referring to the same feature setting) here. */
|
||||
(!current_features[i].is_exclusive && ((current_features[i].setting & ~1) != (current_features[j].setting & ~1))))
|
||||
current_features[++j] = current_features[i];
|
||||
(!current_features.arrayZ[i].is_exclusive && ((current_features.arrayZ[i].setting & ~1) != (current_features.arrayZ[j].setting & ~1))))
|
||||
current_features.arrayZ[++j] = current_features.arrayZ[i];
|
||||
current_features.shrink (j + 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -286,7 +286,7 @@ HB_FUNCOBJ (hb_bool);
|
|||
|
||||
// Compression function for Merkle-Damgard construction.
|
||||
// This function is generated using the framework provided.
|
||||
#define mix(h) ( \
|
||||
#define fasthash_mix(h) ( \
|
||||
(void) ((h) ^= (h) >> 23), \
|
||||
(void) ((h) *= 0x2127599bf4325c37ULL), \
|
||||
(h) ^= (h) >> 47)
|
||||
|
@ -310,7 +310,7 @@ static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
|
|||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
v = * (const uint64_t *) (pos++);
|
||||
#pragma GCC diagnostic pop
|
||||
h ^= mix(v);
|
||||
h ^= fasthash_mix(v);
|
||||
h *= m;
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
|
|||
while (pos != end)
|
||||
{
|
||||
v = pos++->v;
|
||||
h ^= mix(v);
|
||||
h ^= fasthash_mix(v);
|
||||
h *= m;
|
||||
}
|
||||
}
|
||||
|
@ -336,11 +336,11 @@ static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
|
|||
case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH;
|
||||
case 2: v ^= (uint64_t)pos2[1] << 8; HB_FALLTHROUGH;
|
||||
case 1: v ^= (uint64_t)pos2[0];
|
||||
h ^= mix(v);
|
||||
h ^= fasthash_mix(v);
|
||||
h *= m;
|
||||
}
|
||||
|
||||
return mix(h);
|
||||
return fasthash_mix(h);
|
||||
}
|
||||
|
||||
static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
|
||||
|
|
|
@ -251,7 +251,8 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
if (end < start + 2)
|
||||
return;
|
||||
|
||||
for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--)
|
||||
unsigned stop = start + (end - start) / 2;
|
||||
for (unsigned lhs = start, rhs = end - 1; lhs < stop; lhs++, rhs--)
|
||||
hb_swap (arrayZ[rhs], arrayZ[lhs]);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,15 +80,14 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
|||
|
||||
#include <atomic>
|
||||
|
||||
#define _hb_memory_barrier() std::atomic_thread_fence(std::memory_order_ack_rel)
|
||||
#define _hb_memory_r_barrier() std::atomic_thread_fence(std::memory_order_acquire)
|
||||
#define _hb_memory_w_barrier() std::atomic_thread_fence(std::memory_order_release)
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
|
||||
#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_release))
|
||||
#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_get(AI) (reinterpret_cast<std::atomic<std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_acquire))
|
||||
#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
|
||||
#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_release))
|
||||
#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_get(AI) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_acquire))
|
||||
|
||||
#define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast<std::atomic<void*> *> (P)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast<std::atomic<void*> const *> (P)->load (std::memory_order_relaxed))
|
||||
|
@ -149,62 +148,47 @@ static inline void _hb_compiler_memory_r_barrier () {}
|
|||
#define hb_atomic_ptr_impl_get_relaxed(P) (*(P))
|
||||
#endif
|
||||
#ifndef hb_atomic_int_impl_set
|
||||
inline void hb_atomic_int_impl_set (int *AI, int v) { _hb_memory_w_barrier (); *AI = v; }
|
||||
inline void hb_atomic_int_impl_set (short *AI, short v) { _hb_memory_w_barrier (); *AI = v; }
|
||||
template <typename T>
|
||||
inline void hb_atomic_int_impl_set (T *AI, T v) { _hb_memory_w_barrier (); *AI = v; }
|
||||
#endif
|
||||
#ifndef hb_atomic_int_impl_get
|
||||
inline int hb_atomic_int_impl_get (const int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; }
|
||||
inline short hb_atomic_int_impl_get (const short *AI) { short v = *AI; _hb_memory_r_barrier (); return v; }
|
||||
template <typename T>
|
||||
inline T hb_atomic_int_impl_get (const T *AI) { T v = *AI; _hb_memory_r_barrier (); return v; }
|
||||
#endif
|
||||
#ifndef hb_atomic_ptr_impl_get
|
||||
inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; }
|
||||
#endif
|
||||
|
||||
|
||||
struct hb_atomic_short_t
|
||||
template <typename T>
|
||||
struct hb_atomic_t
|
||||
{
|
||||
hb_atomic_short_t () = default;
|
||||
constexpr hb_atomic_short_t (short v) : v (v) {}
|
||||
hb_atomic_t () = default;
|
||||
constexpr hb_atomic_t (T v) : v (v) {}
|
||||
|
||||
hb_atomic_short_t& operator = (short v_) { set_relaxed (v_); return *this; }
|
||||
operator short () const { return get_relaxed (); }
|
||||
hb_atomic_t& operator = (T v_) { set_relaxed (v_); return *this; }
|
||||
operator T () const { return get_relaxed (); }
|
||||
|
||||
void set_relaxed (short v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
|
||||
void set_release (short v_) { hb_atomic_int_impl_set (&v, v_); }
|
||||
short get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
|
||||
short get_acquire () const { return hb_atomic_int_impl_get (&v); }
|
||||
short inc () { return hb_atomic_int_impl_add (&v, 1); }
|
||||
short dec () { return hb_atomic_int_impl_add (&v, -1); }
|
||||
void set_relaxed (T v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
|
||||
void set_release (T v_) { hb_atomic_int_impl_set (&v, v_); }
|
||||
T get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
|
||||
T get_acquire () const { return hb_atomic_int_impl_get (&v); }
|
||||
T inc () { return hb_atomic_int_impl_add (&v, 1); }
|
||||
T dec () { return hb_atomic_int_impl_add (&v, -1); }
|
||||
|
||||
short v = 0;
|
||||
int operator ++ (int) { return inc (); }
|
||||
int operator -- (int) { return dec (); }
|
||||
long operator |= (long v_) { set_relaxed (get_relaxed () | v_); return *this; }
|
||||
|
||||
T v = 0;
|
||||
};
|
||||
|
||||
struct hb_atomic_int_t
|
||||
template <typename T>
|
||||
struct hb_atomic_t<T*>
|
||||
{
|
||||
hb_atomic_int_t () = default;
|
||||
constexpr hb_atomic_int_t (int v) : v (v) {}
|
||||
|
||||
hb_atomic_int_t& operator = (int v_) { set_relaxed (v_); return *this; }
|
||||
operator int () const { return get_relaxed (); }
|
||||
|
||||
void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
|
||||
void set_release (int v_) { hb_atomic_int_impl_set (&v, v_); }
|
||||
int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
|
||||
int get_acquire () const { return hb_atomic_int_impl_get (&v); }
|
||||
int inc () { return hb_atomic_int_impl_add (&v, 1); }
|
||||
int dec () { return hb_atomic_int_impl_add (&v, -1); }
|
||||
|
||||
int v = 0;
|
||||
};
|
||||
|
||||
template <typename P>
|
||||
struct hb_atomic_ptr_t
|
||||
{
|
||||
typedef hb_remove_pointer<P> T;
|
||||
|
||||
hb_atomic_ptr_t () = default;
|
||||
constexpr hb_atomic_ptr_t (T* v) : v (v) {}
|
||||
hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete;
|
||||
hb_atomic_t () = default;
|
||||
constexpr hb_atomic_t (T* v) : v (v) {}
|
||||
hb_atomic_t (const hb_atomic_t &other) = delete;
|
||||
|
||||
void init (T* v_ = nullptr) { set_relaxed (v_); }
|
||||
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
|
||||
|
@ -212,6 +196,7 @@ struct hb_atomic_ptr_t
|
|||
T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
|
||||
bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
|
||||
|
||||
operator bool () const { return get_acquire () != nullptr; }
|
||||
T * operator -> () const { return get_acquire (); }
|
||||
template <typename C> operator C * () const { return get_acquire (); }
|
||||
|
||||
|
|
|
@ -78,6 +78,28 @@ struct hb_vector_size_t
|
|||
hb_vector_size_t operator ~ () const
|
||||
{ return process (hb_bitwise_neg); }
|
||||
|
||||
operator bool () const
|
||||
{
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
|
||||
if (v[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
operator unsigned int () const
|
||||
{
|
||||
unsigned int r = 0;
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
|
||||
r += hb_popcount (v[i]);
|
||||
return r;
|
||||
}
|
||||
bool operator == (const hb_vector_size_t &o) const
|
||||
{
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
|
||||
if (v[i] != o.v[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
hb_array_t<const elt_t> iter () const
|
||||
{ return hb_array (v); }
|
||||
|
||||
|
@ -89,6 +111,8 @@ struct hb_vector_size_t
|
|||
|
||||
struct hb_bit_page_t
|
||||
{
|
||||
hb_bit_page_t () { init0 (); }
|
||||
|
||||
void init0 () { v.init0 (); population = 0; }
|
||||
void init1 () { v.init1 (); population = PAGE_BITS; }
|
||||
|
||||
|
@ -101,10 +125,9 @@ struct hb_bit_page_t
|
|||
bool is_empty () const
|
||||
{
|
||||
if (has_population ()) return !population;
|
||||
return
|
||||
+ hb_iter (v)
|
||||
| hb_none
|
||||
;
|
||||
bool empty = !v;
|
||||
if (empty) population = 0;
|
||||
return empty;
|
||||
}
|
||||
uint32_t hash () const
|
||||
{
|
||||
|
@ -115,6 +138,10 @@ struct hb_bit_page_t
|
|||
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); dirty (); }
|
||||
void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
|
||||
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
|
||||
bool may_have (hb_codepoint_t g) const { return get (g); }
|
||||
|
||||
bool operator [] (hb_codepoint_t g) const { return get (g); }
|
||||
bool operator () (hb_codepoint_t g) const { return get (g); }
|
||||
|
||||
void add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
|
@ -220,13 +247,17 @@ struct hb_bit_page_t
|
|||
}
|
||||
|
||||
bool operator == (const hb_bit_page_t &other) const { return is_equal (other); }
|
||||
bool is_equal (const hb_bit_page_t &other) const
|
||||
bool is_equal (const hb_bit_page_t &other) const { return v == other.v; }
|
||||
bool intersects (const hb_bit_page_t &other) const
|
||||
{
|
||||
for (unsigned i = 0; i < len (); i++)
|
||||
if (v[i] != other.v[i])
|
||||
return false;
|
||||
return true;
|
||||
if (v[i] & other.v[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool may_intersect (const hb_bit_page_t &other) const
|
||||
{ return intersects (other); }
|
||||
|
||||
bool operator <= (const hb_bit_page_t &larger_page) const { return is_subset (larger_page); }
|
||||
bool is_subset (const hb_bit_page_t &larger_page) const
|
||||
{
|
||||
|
@ -241,14 +272,10 @@ struct hb_bit_page_t
|
|||
}
|
||||
|
||||
bool has_population () const { return population != UINT_MAX; }
|
||||
unsigned int get_population () const
|
||||
unsigned get_population () const
|
||||
{
|
||||
if (has_population ()) return population;
|
||||
population =
|
||||
+ hb_iter (v)
|
||||
| hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u)
|
||||
;
|
||||
return population;
|
||||
return population = v;
|
||||
}
|
||||
|
||||
bool next (hb_codepoint_t *codepoint) const
|
||||
|
|
|
@ -126,6 +126,7 @@ struct hb_bit_set_invertible_t
|
|||
{ unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); }
|
||||
|
||||
bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
|
||||
bool may_have (hb_codepoint_t g) const { return get (g); }
|
||||
|
||||
/* Has interface. */
|
||||
bool operator [] (hb_codepoint_t k) const { return get (k); }
|
||||
|
@ -139,6 +140,9 @@ struct hb_bit_set_invertible_t
|
|||
hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool may_intersect (const hb_bit_set_invertible_t &other) const
|
||||
{ return inverted || other.inverted || s.intersects (other.s); }
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{
|
||||
hb_codepoint_t c = first - 1;
|
||||
|
|
|
@ -77,7 +77,7 @@ struct hb_bit_set_t
|
|||
|
||||
bool successful = true; /* Allocations successful */
|
||||
mutable unsigned int population = 0;
|
||||
mutable hb_atomic_int_t last_page_lookup = 0;
|
||||
mutable hb_atomic_t<unsigned> last_page_lookup = 0;
|
||||
hb_sorted_vector_t<page_map_t> page_map;
|
||||
hb_vector_t<page_t> pages;
|
||||
|
||||
|
@ -88,10 +88,11 @@ struct hb_bit_set_t
|
|||
{
|
||||
if (unlikely (!successful)) return false;
|
||||
|
||||
if (pages.length == 0 && count == 1)
|
||||
if (pages.length < count && (unsigned) pages.allocated < count && count <= 2)
|
||||
exact_size = true; // Most sets are small and local
|
||||
|
||||
if (unlikely (!pages.resize (count, clear, exact_size) || !page_map.resize (count, clear, exact_size)))
|
||||
if (unlikely (!pages.resize (count, clear, exact_size) ||
|
||||
!page_map.resize (count, clear)))
|
||||
{
|
||||
pages.resize (page_map.length, clear, exact_size);
|
||||
successful = false;
|
||||
|
@ -297,9 +298,9 @@ struct hb_bit_set_t
|
|||
unsigned int write_index = 0;
|
||||
for (unsigned int i = 0; i < page_map.length; i++)
|
||||
{
|
||||
int m = (int) page_map[i].major;
|
||||
int m = (int) page_map.arrayZ[i].major;
|
||||
if (m < ds || de < m)
|
||||
page_map[write_index++] = page_map[i];
|
||||
page_map.arrayZ[write_index++] = page_map.arrayZ[i];
|
||||
}
|
||||
compact (compact_workspace, write_index);
|
||||
resize (write_index);
|
||||
|
@ -345,6 +346,7 @@ struct hb_bit_set_t
|
|||
return false;
|
||||
return page->get (g);
|
||||
}
|
||||
bool may_have (hb_codepoint_t g) const { return get (g); }
|
||||
|
||||
/* Has interface. */
|
||||
bool operator [] (hb_codepoint_t k) const { return get (k); }
|
||||
|
@ -358,6 +360,31 @@ struct hb_bit_set_t
|
|||
hb_bit_set_t& operator << (const hb_codepoint_pair_t& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool intersects (const hb_bit_set_t &other) const
|
||||
{
|
||||
unsigned int na = pages.length;
|
||||
unsigned int nb = other.pages.length;
|
||||
|
||||
unsigned int a = 0, b = 0;
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major)
|
||||
{
|
||||
if (page_at (a).intersects (other.page_at (b)))
|
||||
return true;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
else if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
|
||||
a++;
|
||||
else
|
||||
b++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool may_intersect (const hb_bit_set_t &other) const
|
||||
{ return intersects (other); }
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{
|
||||
hb_codepoint_t c = first - 1;
|
||||
|
@ -389,7 +416,7 @@ struct hb_bit_set_t
|
|||
{
|
||||
if (page_at (a).is_empty ()) { a++; continue; }
|
||||
if (other.page_at (b).is_empty ()) { b++; continue; }
|
||||
if (page_map[a].major != other.page_map[b].major ||
|
||||
if (page_map.arrayZ[a].major != other.page_map.arrayZ[b].major ||
|
||||
!page_at (a).is_equal (other.page_at (b)))
|
||||
return false;
|
||||
a++;
|
||||
|
@ -412,8 +439,8 @@ struct hb_bit_set_t
|
|||
uint32_t spi = 0;
|
||||
for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++)
|
||||
{
|
||||
uint32_t spm = page_map[spi].major;
|
||||
uint32_t lpm = larger_set.page_map[lpi].major;
|
||||
uint32_t spm = page_map.arrayZ[spi].major;
|
||||
uint32_t lpm = larger_set.page_map.arrayZ[lpi].major;
|
||||
auto sp = page_at (spi);
|
||||
|
||||
if (spm < lpm && !sp.is_empty ())
|
||||
|
@ -503,7 +530,7 @@ struct hb_bit_set_t
|
|||
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_map[a].major == other.page_map[b].major)
|
||||
if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major)
|
||||
{
|
||||
if (!passthru_left)
|
||||
{
|
||||
|
@ -512,7 +539,7 @@ struct hb_bit_set_t
|
|||
// passthru_left is set since no left side pages will be removed
|
||||
// in that case.
|
||||
if (write_index < a)
|
||||
page_map[write_index] = page_map[a];
|
||||
page_map.arrayZ[write_index] = page_map.arrayZ[a];
|
||||
write_index++;
|
||||
}
|
||||
|
||||
|
@ -520,7 +547,7 @@ struct hb_bit_set_t
|
|||
a++;
|
||||
b++;
|
||||
}
|
||||
else if (page_map[a].major < other.page_map[b].major)
|
||||
else if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
|
||||
{
|
||||
if (passthru_left)
|
||||
count++;
|
||||
|
@ -765,8 +792,8 @@ struct hb_bit_set_t
|
|||
unsigned int initial_size = size;
|
||||
for (unsigned int i = start_page; i < page_map.length && size; i++)
|
||||
{
|
||||
uint32_t base = major_start (page_map[i].major);
|
||||
unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size);
|
||||
uint32_t base = major_start (page_map.arrayZ[i].major);
|
||||
unsigned int n = pages[page_map.arrayZ[i].index].write (base, start_page_value, out, size);
|
||||
out += n;
|
||||
size -= n;
|
||||
start_page_value = 0;
|
||||
|
@ -814,8 +841,8 @@ struct hb_bit_set_t
|
|||
hb_codepoint_t next_value = codepoint + 1;
|
||||
for (unsigned int i=start_page; i<page_map.length && size; i++)
|
||||
{
|
||||
uint32_t base = major_start (page_map[i].major);
|
||||
unsigned int n = pages[page_map[i].index].write_inverted (base, start_page_value, out, size, &next_value);
|
||||
uint32_t base = major_start (page_map.arrayZ[i].major);
|
||||
unsigned int n = pages[page_map.arrayZ[i].index].write_inverted (base, start_page_value, out, size, &next_value);
|
||||
out += n;
|
||||
size -= n;
|
||||
start_page_value = 0;
|
||||
|
@ -846,8 +873,8 @@ struct hb_bit_set_t
|
|||
unsigned count = pages.length;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
const auto& map = page_map[i];
|
||||
const auto& page = pages[map.index];
|
||||
const auto& map = page_map.arrayZ[i];
|
||||
const auto& page = pages.arrayZ[map.index];
|
||||
|
||||
if (!page.is_empty ())
|
||||
return map.major * page_t::PAGE_BITS + page.get_min ();
|
||||
|
@ -859,8 +886,8 @@ struct hb_bit_set_t
|
|||
unsigned count = pages.length;
|
||||
for (signed i = count - 1; i >= 0; i--)
|
||||
{
|
||||
const auto& map = page_map[(unsigned) i];
|
||||
const auto& page = pages[map.index];
|
||||
const auto& map = page_map.arrayZ[(unsigned) i];
|
||||
const auto& page = pages.arrayZ[map.index];
|
||||
|
||||
if (!page.is_empty ())
|
||||
return map.major * page_t::PAGE_BITS + page.get_max ();
|
||||
|
@ -961,7 +988,7 @@ struct hb_bit_set_t
|
|||
return nullptr;
|
||||
|
||||
last_page_lookup = i;
|
||||
return &pages.arrayZ[page_map[i].index];
|
||||
return &pages.arrayZ[page_map.arrayZ[i].index];
|
||||
}
|
||||
page_t &page_at (unsigned int i)
|
||||
{
|
||||
|
|
195
src/hb-bit-vector.hh
Normal file
195
src/hb-bit-vector.hh
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_BIT_VECTOR_HH
|
||||
#define HB_BIT_VECTOR_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-atomic.hh"
|
||||
|
||||
struct hb_min_max_t
|
||||
{
|
||||
void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); }
|
||||
void add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
min_v = hb_min (min_v, a);
|
||||
max_v = hb_max (max_v, b);
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
void union_ (const set_t &set)
|
||||
{
|
||||
hb_codepoint_t set_min = set.get_min ();
|
||||
if (unlikely (set_min == HB_CODEPOINT_INVALID))
|
||||
return;
|
||||
hb_codepoint_t set_max = set.get_max ();
|
||||
min_v = hb_min (min_v, set_min);
|
||||
max_v = hb_max (max_v, set_max);
|
||||
}
|
||||
|
||||
hb_codepoint_t get_min () const { return min_v; }
|
||||
hb_codepoint_t get_max () const { return max_v; }
|
||||
|
||||
private:
|
||||
hb_codepoint_t min_v = HB_CODEPOINT_INVALID;
|
||||
hb_codepoint_t max_v = 0;
|
||||
};
|
||||
|
||||
template <bool atomic = false>
|
||||
struct hb_bit_vector_t
|
||||
{
|
||||
using int_t = uint64_t;
|
||||
using elt_t = typename std::conditional<atomic, hb_atomic_t<int_t>, int_t>::type;
|
||||
|
||||
hb_bit_vector_t () = delete;
|
||||
hb_bit_vector_t (const hb_bit_vector_t &other) = delete;
|
||||
hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete;
|
||||
|
||||
// Move
|
||||
hb_bit_vector_t (hb_bit_vector_t &&other)
|
||||
: min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts)
|
||||
{
|
||||
other.min_v = other.max_v = other.count = 0;
|
||||
other.elts = nullptr;
|
||||
}
|
||||
hb_bit_vector_t &operator= (hb_bit_vector_t &&other)
|
||||
{
|
||||
hb_swap (min_v, other.min_v);
|
||||
hb_swap (max_v, other.max_v);
|
||||
hb_swap (count, other.count);
|
||||
hb_swap (elts, other.elts);
|
||||
return *this;
|
||||
}
|
||||
|
||||
hb_bit_vector_t (unsigned min_v, unsigned max_v)
|
||||
: min_v (min_v), max_v (max_v)
|
||||
{
|
||||
if (unlikely (min_v >= max_v))
|
||||
{
|
||||
min_v = max_v = count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned num = (max_v - min_v + sizeof (int_t) * 8) / (sizeof (int_t) * 8);
|
||||
elts = (elt_t *) hb_calloc (num, sizeof (int_t));
|
||||
if (unlikely (!elts))
|
||||
{
|
||||
min_v = max_v = count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
count = max_v - min_v + 1;
|
||||
}
|
||||
~hb_bit_vector_t ()
|
||||
{
|
||||
hb_free (elts);
|
||||
}
|
||||
|
||||
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
|
||||
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
|
||||
void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
|
||||
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
|
||||
bool has (hb_codepoint_t g) const { return get (g); }
|
||||
bool may_have (hb_codepoint_t g) const { return get (g); }
|
||||
|
||||
bool operator [] (hb_codepoint_t g) const { return get (g); }
|
||||
bool operator () (hb_codepoint_t g) const { return get (g); }
|
||||
|
||||
void add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
if (unlikely (!count || a > b || a < min_v || b > max_v))
|
||||
return;
|
||||
|
||||
elt_t *la = &elt (a);
|
||||
elt_t *lb = &elt (b);
|
||||
if (la == lb)
|
||||
*la |= (mask (b) << 1) - mask(a);
|
||||
else
|
||||
{
|
||||
*la |= ~(mask (a) - 1llu);
|
||||
la++;
|
||||
|
||||
hb_memset (la, 0xff, (char *) lb - (char *) la);
|
||||
|
||||
*lb |= ((mask (b) << 1) - 1llu);
|
||||
}
|
||||
}
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
if (unlikely (!count || a > b || a < min_v || b > max_v))
|
||||
return;
|
||||
|
||||
elt_t *la = &elt (a);
|
||||
elt_t *lb = &elt (b);
|
||||
if (la == lb)
|
||||
*la &= ~((mask (b) << 1llu) - mask(a));
|
||||
else
|
||||
{
|
||||
*la &= mask (a) - 1;
|
||||
la++;
|
||||
|
||||
hb_memset (la, 0, (char *) lb - (char *) la);
|
||||
|
||||
*lb &= ~((mask (b) << 1) - 1llu);
|
||||
}
|
||||
}
|
||||
void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
|
||||
{ if (v) add_range (a, b); else del_range (a, b); }
|
||||
|
||||
template <typename set_t>
|
||||
void union_ (const set_t &set)
|
||||
{
|
||||
for (hb_codepoint_t g : set)
|
||||
add (g);
|
||||
}
|
||||
|
||||
static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
|
||||
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
|
||||
|
||||
static constexpr elt_t zero = 0;
|
||||
|
||||
elt_t &elt (hb_codepoint_t g)
|
||||
{
|
||||
g -= min_v;
|
||||
if (unlikely (g >= count))
|
||||
return Crap(elt_t);
|
||||
return elts[g / ELT_BITS];
|
||||
}
|
||||
const elt_t& elt (hb_codepoint_t g) const
|
||||
{
|
||||
g -= min_v;
|
||||
if (unlikely (g >= count))
|
||||
return Null(elt_t);
|
||||
return elts[g / ELT_BITS];
|
||||
}
|
||||
|
||||
static constexpr int_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
|
||||
|
||||
hb_codepoint_t min_v = 0, max_v = 0, count = 0;
|
||||
elt_t *elts = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_BIT_VECTOR_HH */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue