From 82d4bfb8f3ac30fecce41f8abe59f58ad64ba98a Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Fri, 14 Jun 2019 10:49:42 -0700 Subject: [PATCH 001/138] enable cff subset tests add Unicode UCS-4 cmap fix Unicode bits in OS/2 add Unicode cmap sub-table in SourceHanSans-Regular_subset.otf regenerate cff subset test expected results --- src/hb-ot-cmap-table.hh | 75 ++++++++++++++---- src/hb-ot-os2-table.hh | 10 ++- test/subset/data/Makefile.am | 2 + test/subset/data/Makefile.sources | 2 + ...utinize-retain-gids.1FC,21,41,20,62,63.otf | Bin 32124 -> 20000 bytes ...ar.desubroutinize-retain-gids.61,62,63.otf | Bin 29688 -> 2196 bytes ...ubroutinize-retain-gids.D7,D8,D9,DA,DE.otf | Bin 33316 -> 30412 bytes ...utinize-retain-gids.1FC,21,41,20,62,63.otf | Bin 31960 -> 19840 bytes ...ts-desubroutinize-retain-gids.61,62,63.otf | Bin 29564 -> 2072 bytes ...ubroutinize-retain-gids.D7,D8,D9,DA,DE.otf | Bin 33168 -> 30264 bytes ...p-hints-retain-gids.1FC,21,41,20,62,63.otf | Bin 32052 -> 19932 bytes ...egular.drop-hints-retain-gids.61,62,63.otf | Bin 29632 -> 2108 bytes ....drop-hints-retain-gids.D7,D8,D9,DA,DE.otf | Bin 33180 -> 30276 bytes ...Regular.retain-gids.1FC,21,41,20,62,63.otf | Bin 32276 -> 20152 bytes ...ceSansPro-Regular.retain-gids.61,62,63.otf | Bin 29788 -> 2264 bytes ...Pro-Regular.retain-gids.D7,D8,D9,DA,DE.otf | Bin 33332 -> 30428 bytes ....default.3042,3044,3046,3048,304A,304B.otf | Bin 3028 -> 3036 bytes ....default.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 3240 -> 3248 bytes ...ans-Regular_subset.default.61,63,65,6B.otf | Bin 2200 -> 2208 bytes ....default.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 3460 -> 3468 bytes ...rceHanSans-Regular_subset.default.660E.otf | Bin 1920 -> 1928 bytes ...ain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 90956 -> 8932 bytes ...ain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 125820 -> 116080 bytes ...desubroutinize-retain-gids.61,63,65,6B.otf | Bin 88392 -> 3016 bytes ...ain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 126004 -> 116264 bytes ...subset.desubroutinize-retain-gids.660E.otf | Bin 103780 -> 50224 bytes ...outinize.3042,3044,3046,3048,304A,304B.otf | Bin 2952 -> 2960 bytes ...outinize.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 3136 -> 3144 bytes ...ular_subset.desubroutinize.61,63,65,6B.otf | Bin 2132 -> 2140 bytes ...outinize.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 3256 -> 3264 bytes ...ans-Regular_subset.desubroutinize.660E.otf | Bin 1896 -> 1904 bytes ...ain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 90656 -> 8672 bytes ...ain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 125468 -> 115768 bytes ...desubroutinize-retain-gids.61,63,65,6B.otf | Bin 88156 -> 2892 bytes ...ain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 125584 -> 115884 bytes ...-hints-desubroutinize-retain-gids.660E.otf | Bin 103556 -> 50040 bytes ...outinize.3042,3044,3046,3048,304A,304B.otf | Bin 2792 -> 2800 bytes ...outinize.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 2896 -> 2904 bytes ....drop-hints-desubroutinize.61,63,65,6B.otf | Bin 2028 -> 2036 bytes ...outinize.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 2964 -> 2972 bytes ..._subset.drop-hints-desubroutinize.660E.otf | Bin 1804 -> 1812 bytes ...ain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 90724 -> 8740 bytes ...ain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 125560 -> 115864 bytes ...set.drop-hints-retain-gids.61,63,65,6B.otf | Bin 88196 -> 2852 bytes ...ain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 125780 -> 116084 bytes ...lar_subset.drop-hints-retain-gids.660E.otf | Bin 103572 -> 50060 bytes ...op-hints.3042,3044,3046,3048,304A,304B.otf | Bin 2848 -> 2856 bytes ...op-hints.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 2988 -> 2996 bytes ...-Regular_subset.drop-hints.61,63,65,6B.otf | Bin 2060 -> 2068 bytes ...op-hints.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 3164 -> 3172 bytes ...HanSans-Regular_subset.drop-hints.660E.otf | Bin 1824 -> 1832 bytes ...ain-gids.3042,3044,3046,3048,304A,304B.otf | Bin 91040 -> 9016 bytes ...ain-gids.3042,3044,3046,73E0,5EA6,8F38.otf | Bin 125924 -> 116184 bytes ...Regular_subset.retain-gids.61,63,65,6B.otf | Bin 88468 -> 3012 bytes ...ain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf | Bin 126208 -> 116468 bytes ...anSans-Regular_subset.retain-gids.660E.otf | Bin 103800 -> 50244 bytes .../fonts/SourceHanSans-Regular_subset.otf | Bin 2707728 -> 2707736 bytes 57 files changed, 71 insertions(+), 18 deletions(-) diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index 9e9679f8b..724da6e82 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -848,11 +848,16 @@ struct cmap size_t final_size () const { return 4 // header - + 8 * 3 // 3 EncodingRecord + + 8 * num_enc_records + CmapSubtableFormat4::get_sub_table_size (this->format4_segments) + CmapSubtableFormat12::get_sub_table_size (this->format12_groups); } + unsigned int num_enc_records; + bool has_unicode_bmp; + bool has_unicode_ucs4; + bool has_ms_bmp; + bool has_ms_ucs4; hb_sorted_vector_t format4_segments; hb_sorted_vector_t format12_groups; }; @@ -860,6 +865,12 @@ struct cmap bool _create_plan (const hb_subset_plan_t *plan, subset_plan *cmap_plan) const { + cmap_plan->has_unicode_bmp = find_subtable (0, 3); + cmap_plan->has_unicode_ucs4 = find_subtable (0, 4); + cmap_plan->has_ms_bmp = find_subtable (3, 1); + cmap_plan->has_ms_ucs4 = find_subtable (3, 10); + cmap_plan->num_enc_records = cmap_plan->has_unicode_bmp + cmap_plan->has_unicode_ucs4 + cmap_plan->has_ms_bmp + cmap_plan->has_ms_ucs4; + if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments))) return false; @@ -882,32 +893,60 @@ struct cmap table->version = 0; - if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ cmap_subset_plan.format12_groups ? 3 : 2))) return false; + if (unlikely (!table->encodingRecord.serialize (&c, cmap_subset_plan.num_enc_records))) return false; // TODO(grieger): Convert the below to a for loop + int enc_index = 0; + int unicode_bmp_index = 0; + int unicode_ucs4_index = 0; + int ms_bmp_index = 0; + int ms_ucs4_index = 0; // Format 4, Plat 0 Encoding Record - EncodingRecord &format4_plat0_rec = table->encodingRecord[0]; - format4_plat0_rec.platformID = 0; // Unicode - format4_plat0_rec.encodingID = 3; + if (cmap_subset_plan.has_unicode_bmp) + { + unicode_bmp_index = enc_index; + EncodingRecord &format4_plat0_rec = table->encodingRecord[enc_index++]; + format4_plat0_rec.platformID = 0; // Unicode + format4_plat0_rec.encodingID = 3; + } + + // Format 12, Plat 0 Encoding Record + if (cmap_subset_plan.has_unicode_ucs4) + { + unicode_ucs4_index = enc_index; + EncodingRecord &format12_rec = table->encodingRecord[enc_index++]; + format12_rec.platformID = 0; // Unicode + format12_rec.encodingID = 4; // Unicode UCS-4 + } // Format 4, Plat 3 Encoding Record - EncodingRecord &format4_plat3_rec = table->encodingRecord[1]; - format4_plat3_rec.platformID = 3; // Windows - format4_plat3_rec.encodingID = 1; // Unicode BMP - - // Format 12 Encoding Record - if (cmap_subset_plan.format12_groups) + if (cmap_subset_plan.has_ms_bmp) { - EncodingRecord &format12_rec = table->encodingRecord[2]; + ms_bmp_index = enc_index; + EncodingRecord &format4_plat3_rec = table->encodingRecord[enc_index++]; + format4_plat3_rec.platformID = 3; // Windows + format4_plat3_rec.encodingID = 1; // Unicode BMP + } + + // Format 12, Plat 3 Encoding Record + if (cmap_subset_plan.has_ms_ucs4) + { + ms_ucs4_index = enc_index; + EncodingRecord &format12_rec = table->encodingRecord[enc_index++]; format12_rec.platformID = 3; // Windows format12_rec.encodingID = 10; // Unicode UCS-4 } // Write out format 4 sub table { - CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table); - format4_plat3_rec.subtable = (unsigned int) format4_plat0_rec.subtable; + if (unlikely (!cmap_subset_plan.has_unicode_bmp && !cmap_subset_plan.has_ms_bmp)) return false; + EncodingRecord &format4_rec = cmap_subset_plan.has_unicode_bmp? + table->encodingRecord[unicode_bmp_index]: + table->encodingRecord[ms_bmp_index]; + CmapSubtable &subtable = format4_rec.subtable.serialize (&c, table); + if (cmap_subset_plan.has_unicode_bmp && cmap_subset_plan.has_ms_bmp) + table->encodingRecord[ms_bmp_index].subtable = (unsigned int) format4_rec.subtable; subtable.u.format = 4; CmapSubtableFormat4 &format4 = subtable.u.format4; @@ -918,8 +957,14 @@ struct cmap // Write out format 12 sub table. if (cmap_subset_plan.format12_groups) { - EncodingRecord &format12_rec = table->encodingRecord[2]; + if (unlikely (!cmap_subset_plan.has_unicode_ucs4 && !cmap_subset_plan.has_ms_ucs4)) return false; + EncodingRecord &format12_rec = cmap_subset_plan.has_unicode_ucs4? + table->encodingRecord[unicode_ucs4_index]: + table->encodingRecord[ms_ucs4_index]; + CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table); + if (cmap_subset_plan.has_unicode_ucs4 && cmap_subset_plan.has_ms_ucs4) + table->encodingRecord[ms_ucs4_index].subtable = (unsigned int) format12_rec.subtable; subtable.u.format = 12; CmapSubtableFormat12 &format12 = subtable.u.format12; diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh index 33fbb643c..16e29caf3 100644 --- a/src/hb-ot-os2-table.hh +++ b/src/hb-ot-os2-table.hh @@ -164,8 +164,9 @@ struct OS2 void _update_unicode_ranges (const hb_set_t *codepoints, HBUINT32 ulUnicodeRange[4]) const { + HBUINT32 newBits[4]; for (unsigned int i = 0; i < 4; i++) - ulUnicodeRange[i] = 0; + newBits[i] = 0; hb_codepoint_t cp = HB_SET_VALUE_INVALID; while (codepoints->next (&cp)) { @@ -175,16 +176,19 @@ struct OS2 unsigned int block = bit / 32; unsigned int bit_in_block = bit % 32; unsigned int mask = 1 << bit_in_block; - ulUnicodeRange[block] = ulUnicodeRange[block] | mask; + newBits[block] = newBits[block] | mask; } if (cp >= 0x10000 && cp <= 0x110000) { /* the spec says that bit 57 ("Non Plane 0") implies that there's at least one codepoint beyond the BMP; so I also include all the non-BMP codepoints here */ - ulUnicodeRange[1] = ulUnicodeRange[1] | (1 << 25); + newBits[1] = newBits[1] | (1 << 25); } } + + for (unsigned int i = 0; i < 4; i++) + ulUnicodeRange[i] = ulUnicodeRange[i] & newBits[i]; // set bits only if set in the original } static void find_min_and_max_codepoint (const hb_set_t *codepoints, diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am index 3439588ae..618e663c0 100644 --- a/test/subset/data/Makefile.am +++ b/test/subset/data/Makefile.am @@ -9,7 +9,9 @@ EXTRA_DIST += \ $(TESTS) \ expected/basics \ expected/full-font \ + expected/cff-full-font \ expected/japanese \ + expected/cff-japanese \ expected/layout \ fonts \ profiles \ diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources index 75913fd9f..f065e8327 100644 --- a/test/subset/data/Makefile.sources +++ b/test/subset/data/Makefile.sources @@ -1,7 +1,9 @@ TESTS = \ tests/basics.tests \ tests/full-font.tests \ + tests/cff-full-font.tests \ tests/japanese.tests \ + tests/cff-japanese.tests \ tests/layout.tests \ $(NULL) diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf index 8ce5fdbf532694d3fd3cb55e3de34ff63c0dccc9..2811017ca78f4a1a57bf62a814f9f9391f4b2729 100644 GIT binary patch delta 320 zcmezKi*dmm#(Mvd5Pt?vh6V;^1_5U`Hw7)}+D!}$3`-ao%ticz^^KyQmM>&r@B#`k zBqZl17O+I~|72kB4FU4kWTYmhi2B6G1J&*T^35`U0$eRzwhRoOcYu7AjNFn6-o1>L zK=}_041#ZR6DtZ>ssn&h40C{(EiW-wFZCktqbQ&S2@DKO9}Dt}Oa5PEFk)cv11VBq zUI7oh$TBdn7Bhgz5=IbN$^+((fQ delta 10142 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 a<1=N4?6*-XAIH{ySd*V~%6&(BhW!svS&ec4 diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf index a1487ff65c143e1363207a5d4892f3a1d799cf79..98bbf38d6f64d31d3ba0536eb84db6648c5a2ad4 100644 GIT binary patch delta 278 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 diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf index 9168bc869d211df24b7599ddb46004a17d6a6452..2d88e570bbbd65529ea1498062d16b45531f64a7 100644 GIT binary patch delta 313 zcmZ3|!gS^>W4(V!h(7}-LjwadgMhP}n}StH#}x(!h9wLPVX6MX`bN=n%bFP&ijDxq z5|VQh3pi^;fbwM$K>n1B)Wj4~pZItNhHxGr-z)_^8X@(5zvA)Km`g6 z3;_&m*BKZX8CaMY7#SJGCfnDGI)PX=vJ4FDy$m3-j}b)n^ME-Mm>qbS|3v-X2^8bV z{}sauq;1adp9WH4szN~0eyboG*Jc(*0Uq{J{i_D91|gfX`3m$m?{hxK%*1wm^Eda6 lyqi_S_i{{LnBdJaM^Sp^<_`&-(vyGIDluN)EK|q90ssr;Qbzy) delta 2687 zcmY*beQ;FO6~CJVa*kajic}=1;X_5#y!-Lq+k}FUU06|pq!L8~0*}p-Y@6(^`vFmd zD~h5+?I>w+WMBjbNB(fejyqGTGl){OM%030)q<8%TWT#-TLnL%_v0lm{BigEe&^$! zbI(0*-+S|TX#3iVQgdr-GeL4MsU$VAc)V`?MVXffA=?RAHobX)#TRW^c|RfdjFY-$ ziEb~8y%!uLWKCA`Uv(zE_R({fE|sQFBzHTd;+(bNO@yreTJlMq-G!cWJ3_A#;>q}N zhr7L=Z1u(#X(F5D8lLvLCngV!INBx?^b%6>MK+T!oH;-^A@@~DhdM%9NcG0Yo|-%r z9C9%s;D*$1B&?k|VzGP=O@R58hAJ4Dmf=}ZyK9?`x zZQSFXJi}M=)qE{q&o}TV_*VW5{|(>C_wasxkRRel`KSDIeu|$K!$eq&5@W@9Fl6w>Q{Z z>}Tzr_G|V5`-uISebNazVdp|;f^(%qovBXTndh`Rw>rObC%chy?TD;ZDyCDMv&ODu zKA*g!=yi4El3pR1(>R?eXz69MxlE6Ssq~6eI#sw+hEW=IvR>M{7#jU-e6dx%G)bFi?lo z4b~Jf)=03IKBAxvfkvNJ(8fTc4=!j^pwT@LG%7VE|G2t=g2n=;SiNV`>23-dA2jL9 zqJjl2VWty|`<>DEC_TggH+3>o95WR$RYpmAncPgxhh+K=1v6Q>xfpKx%1tx5=^!^< zuAwrPSL zjDu|ob^Q@)P-A3zs-bGAKYxb%W2K0xLH?PZHI#-9ar5U*>HR^|aPX@12L9bD%aHq( z50m`!) zD{@{Uy*$A3zB$#C6`viC^LkDfWQw^&vM!ac^Xdxa&C_;OmdKNYR6io$+n2~CU%%v1 z$$v>g`ei>u;zy-Uek@c!CgtN&ZXj2XUQ$6GlK4eZMM_dHKQ`pYNQkVJ@9f#1VkcoklQKfvqI z4{yLecoW`&x8aYl9}d7f@GcyL_ux(n z!{JzsfQaYdk1&iQ@LU{;HFzGLkE8Gc9F0H53vmoygk!N5$Kl0z30{hII36e9M4W_| z;pKP*PR1*73SNa*<26{17E)x$QJ{?ux){L*Y{aSf6P$+AOL#5Lz?s;DQH{m`KE>UhWfVUCWJmH@6AEg{{eii6I}oR diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf index 7cca4891a15287f9774fb72d1b9dafb1d753006c..e5775fd8d2656d9a827af24d7d5eb6eb9e19cbd8 100644 GIT binary patch delta 302 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 Pq@g(Pl(i=`c*pz?^t6li diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf index 06f0c1f2799b86fe9b7e0e3c3888eeb5ddac109e..572ea742b737823bbd8213db7b1a290cb40d4cff 100644 GIT binary patch delta 279 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 Ly#_`9hoAok;UtZ8 diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf index 556861c9521ce08a8f40182fe13d41c34b23405a..376f658ca16a54917414e946df33e4a37a9f483d 100644 GIT binary patch delta 303 zcmbQx%(UYTW4(V!h(7}-LjwadgMhP}o5G1Fn}rz|7?vVi4_HG*8_l340C{(EiW-wIrSp%qbQ(;2@DKO9}Dt}Oa5PEFk)aRlK?7E zU|2>m!D3bc=b e5r~;sX%|Fz^nD}b!i;gpwnVU2B zUhe}&122z3d_l-4DuQD9z@jj32~vnnYLS_ss2Eg44>Xaq6if};k27)i5)G4pJMyg3EB{Fc z`~3cF%{pyLHmEfw?e{e%_tqZnP!4YpQt@s!lP{dwO9UZHv&x`>klCbW9U&1?RY4+= z$b`X7`3WtGnRy-|@Q8lKBKp}BHK4ij;%Mc^9UncZWtk7ZQLSkF)Y#RE%zJp8dVYEK zSz{hAS4HZgrG96rv&y;C+2m|?wmLhUA!oO<$9c^;NJHn2!_c`H| z*YSEjjenlU_?P&lyp4Bozr=fao-g7n`5<4Mch>Tbu7K;IKt5_@U5u3y#;xVyJ42j)hpEw{6i#NqP;)FOU zt7TN4Ehow;a=LV6Ot#2NWt;4fDf#sUa;aP+H_FYjEQjO^@}N8-kGm1K&aHPZbUpVH zx6S>gn{xZzvdtdXm$EL@c z%JsEbr&LU*gy1uJllgq|+M?gvolE+KWX|yEOuy#T~tzOp8 z6;gh0S8Bcz7n0pMzc=T1r8@myvoDKj!bL1!?CbLjsZ3gJ)K%;(7%`X0e5sI9ie#4& z%wT>lmswcMS|kkW$}CK4?6ojM;$}}TK0~7>PZV+~zuUTatB}YjF$|IaRZyU@sGt?dNbE2)7?pJ!=$jp=$P~rVxm=tSESXFxFxeJNf;7uw!~V- zTP(5;aqS?ycwE~+1ATdc8jgc;65$wqQ&vf8F_FLOl6nnQ^>tzb_dmW10%a1m6-^if&JVQll{HaTuH;yR6zva+$co)3jg z4<)xzg>8(mbrrUl!d6h&s)<;TsIcV`VR?iNE5h;!n}M(yhDA=4#G1r-FNaY*+hC+G6 z%$=1baz7z8tJJT2vRdl*OU_q#wfdjy|NljbU!$nHKh)f==v|7gC7&gWNCi>%g_<3t zij(`u*CK~J3MgU$7NQ^5;d*=ri?A3spoAq@ie*@i0j$7{Sc#i( zGj74HxDBhY8sEhl+>W&v#2vU3>u?wD#ywb%d$9oHcj ziXY&I*n%J7$JmO;@Dn_aGJcAm;R$TRc07q4_&I)oop=hn@HBpjA^Zx@;8{F}U*k8} zjo;#V{0=YR_jnO|uoo}kW$eQ%conZI7JDK&j-Exw(X;6}bUd9v&!wNFpQ00KJ)K0)qm$|Rw1G~cQ|SeC8vQhl ze5M?|Vm=0Qvv-aAU}(H*oNAT2?Nv{HH8Fi_d0_6%_2r?tOCp1{xv7!;WtKzL{{iyx BDVqQQ diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf index 5177c149e79c43b446771f526ba12488b972136b..e23e37f4b3fe3ed38f7a10d589ae282a51204b81 100644 GIT binary patch delta 302 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 Q*VK4(&RG9sjeF4l03wEir~m)} diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf index c70b82a1becab94c1f1de7e9d8f2b597205b1cd8..b5a565e3ae16fe3d262687f9b46625193480e178 100644 GIT binary patch delta 323 zcmX@`oNai%*m6&XG~rg-@*gZ#K6QVC*r2dG1(wt<>Zt3N{sTG-{fCm1^`Z) BQ^WuO literal 29632 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 delta 2686 zcmY*bZE#f889o~V_d$b16s-g`AXY@X_k7%YH=(hRU07)ghC)OQ)Ogt}$!fB@?gvC0 z+#p|Cz(#^t5h}J)QBlyH5p||@hOy2toz6(d8SUr~hCkS8>*$DJ)k4q5O>X#c@B2LO z$9doLp7(yd_wUHwjWw0F_VzY1kqnY?q&|^MHqz9c8wnvV5YqWp+j5()+_zTp^}D3* zzEq!|pEz*khlC7%Ci$+OwBI##ac8GAt&-g9k%~(;)$Nh~dC6z>^p*NA>yG?I+GYIo zPy77-ytR9&G?BgXnvnJTqUjTpPIbtDGlbN9na>qV7fujP$c6#w&`8KqV(lg*LTYPB zBoeu5xU)Dlu29Rhguo^0?nTr+R;NkRxcPPCzVG<%ZKcb7yK20Y3)&|SNzu7wioD-` z;PMG?RBI#kb(Ma5gT2Fk%HD4uv=7_w*vIVS_6PPy_DTD+{keV4K2OKfIy#k3r#H|! zl+h+Sk0$97+D=!})igu%bRB(!Zl>GmFx^9+rw8d_`X>DoeUJW?{+<4Vo}{Pg=k#kv z*hE&(8rUp$3-j1*Y!Pc?9n7z=URGoSY%3dPd)NVXh#h5rX2;nF>=Sm1{fC`l7dZH2 zK8?@dw{pQ-c!DqH%XtU)c@NL=wR}C_#JBOC{29KVzsQg9qx={@&OhXz@KgMs{0n}L zpBLjrow!0w6EnnYVGB>RibbMLbcl?&XRX*EhQvN`P*lY+@i+0QI4#aP5vSg1aOOC! zv%qO{?sYOwzq8TV>Fje3IY*uMofFPU=U>iQH{#a0SGzOan_cS8b(8KAx81$leaoBe z#i|XH@^+=1&2Y||d(*{Y`oXf_+g(WerF22#Y_6oGpU)R^{TgPnYcknP=^+_LY23~G zg;K`v?aHi?>QcJ9;P)2%u1w1B)$3AE3C6u*xv$SJWpY`$P**us(rPBs#Y!n74e2he zXr_LlkXu*I8^$&3%B{;P?zU1b5_(NH(X3d^<)uQ#?=~TBTxgfLaf!#Yt;>YR7nty1 z6{eWSDw=vs(-_n7p4Zx&dpMo#PAeZOxDnb$g)155ag|<*xDg2>78;S%BGF`o@l3QD zW&#o_fV+u=>OU1!RiQ*Q<>yCWw*jg$X=0&?MFW#6OqzITQZ-7A2sMt;IH5*wKu}j} zD%xN5ONM#T)F>FKL+VCriWzGxTuX0J(56tMcPnUfsL>l2v^CV|9tawjno6);-9SMT zp;IF2n{>LHf+j~z`mm^AVN00l1mi(x^f^ioF~Uuq%oN8=MNE}ZkzOV@Q}ZF2K10Dw zR&EZ4o4#_>Ol~^JP1m>=6v|C|c-S6p((8XC->;lWrbVrq~t(~E}E&@pboyeWM! zXc~?lm0ln?TV)w@zVgA6)tLFyI1ExWC_uxDEy08-%a|!sG^j?yFvin~%z!I+k)<+{ zNO_HU{1gomX?Ri4NFrq!^Qfu3!IPw67~@Dw(0L679bHrKQ`yxamgmi>o~-1;WRgcYU7jl!Qt8G_vC(fVRrj_`slA^( zM~JmUe#@_um;C&a>m`3ee$dqqz&weEq?A7p){{~`E#*#f6B!^iq#$o$tQRjjY9GuGGES?iqjjrCvaTkAXPd+UGJ zdFuiQBB;SQ)M7j)zydH4m*7&=VG=IGWYptwOu-en5>s&%uEq~=4W^+1({U}X!}Vyy z49vt0n1vhhL)?VfxEXVB3vR`a5QPm2h6;y(0~a1*XhJjQ;>T#gZTJc1VLn98t$l5C^!@74ipLwO$5sqRhOa5ijC@>eDWLZM DW32*G diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf index 02529e3aca16ffd12755f87e1586fbd7fc453634..e1613ac5f0082e160fb1b7d7fd48857f9f3855b3 100644 GIT binary patch delta 300 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 K)?GEuJ?MY?IErBa diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf index 76e5cc59265761ea96c72468e404581d68b148a8..479c5e0164f1d9cc094168c48a3168cfc2e8dcdc 100644 GIT binary patch delta 307 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 diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.default.3042,3044,3046,3048,304A,304B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.default.3042,3044,3046,3048,304A,304B.otf index 4dadbfeeae8d2ad5cfc6ba4e36b7ade65405f5de..6065be461a6986053d875c9d1a3c1f5fc77e0ec3 100644 GIT binary patch delta 148 zcmca2en)(Qx$FW41_qAg+{A)}-KAL!3|tq0{0$kYi7C8YJr5>^1S>WG1r*AFA{^UA z?HCxicL4b+Ww|94EI$|vf&3L4PrPN5mM@wR&u{aUftmRQP@du95`jJteN)~%ZSw_o fW@beeAdeY{Re%`8P66^5!F*;0E)ak68?F}sXnQ2q delta 140 zcmca3enotOx$F!E1_qAg+{A)}-6by>7`QF~`71I~6H|CCdaEaf1S?hm1r*AFA{^UA z?HCxiHvsu6Ww|94EI$|vf&2vL^KpqIo07*tD%>|@mCV%020RUssB-Q`` diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.default.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.default.3042,3044,3046,73E0,5EA6,8F38.otf index b2a46c66d59db79f050049e743faf8941ffbca4d..cee758499234d6bb48435298050c8d53286ea4ea 100644 GIT binary patch delta 148 zcmZ1>xj}M*xoimo0|Q5LZel@(aN$`72JQ(!{*jE-#1!7Ho(B^{f)zu60t#h75svMm zb_@(WJwU!nS#C)M%LPVWAirkgiM8y~Vrf(3`E9;3Ff+dZ$}?PCBG3n-Z_1meZJxlv f%&f=)1>#R$!~F*UZAcJ=VlBJ$uC$r){5D@1n3-Py^1S@&~1r*AFA{^UA z?SN`)fP9s*+>#2mJjUrje!<2QN0?diF6c>5p1>l)a#P+sZSx8ic4kEuph9MlVju>w TV}LwHFrS%$3&fv%g8c#jJZ&Dc delta 126 zcmZ1=I74uPxoiRh0|Q5LZejt$e^yBb2KF^T{*;W=#1vkO-s*`V!HNz*0fjQ42*-9& zJD}PUAYY{{x1@qCk8wJXpRw`85oVVB65aokC$NaH+&F8&xOoK&JF_G+P$3A*07*tD N%>|@GCSPE`008$&9kc)d diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.default.660E,6975,73E0,5EA6,8F38,6E05.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.default.660E,6975,73E0,5EA6,8F38,6E05.otf index e9679cf9a42804331d499fad39b81c1aab6c3676..6db56f42d89970332ff16b2bf5db136f66412589 100644 GIT binary patch delta 148 zcmZpX?vb8gE*rqWz`&85n^@3wCDe(5fhPyZKa!D}n8MrD^I&2~u%ZD_K%opM!m(Y{ zj)8$U1ISk?%Ppy3$!1ssi0C_-u%*GQxnWT9NMdJBwzA`W~zW|9|Tq4j1qHoHZr)|E&{F_OU c1;}FtVih0;v0Z>XMlhe5feXZ+{DEx(07$MM=>Px# delta 140 zcmeC+Z{VL`F6+ai0C_-u$i@>tnWQ%qoQUVQ`O3h|`~oC;afv`5h`w>wf^qX5=HE<` W%s?Ip%K%A6D9r_=Z6^O`AEK>)!NAfkQ# zjMy8}XyDOSce|>^)Q(KG^4l!wZ1*&wo{zyo18Vq#U23J1bcsszggyp2s*vAnSiWbt z(TIUP+LlZ-h5TGshe3jZA6+3cSi8SP!OgqF<~dkIGM+qqyiX;h`&wU)C{1{N@a*uNoidSUb=?7BrTdc^H|6Z*`O+RQ}e{d(p-t=TGLT@zOZQ VOq)3zBbry1C6!rsdBGjgx_{iFfY$&3 literal 90956 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 z zjb{_sL^g>{W>eTyHjPbZX>105s5OhtW^>qFHjm9`3)n)oh%IJI*iyEPEoUp(O16rv zW^345wvMf58`ws+iEU^M8Y zPO?+%G&{r2vUBV_yTC58OYAbc!mhGw>^i%_Zn9hKHoL?AW_Q^=cAq_957{I3m_5PI z$DXoh>^XbEUb0v0HG9L}vUlt~`@lZ3Pb{5fuuS%uePLhOH+L3yR(Fbfko%SUwP%fI zt#=XEmTSkg=R&y-Tt}`G*O}|Wg>hZEZd^DQ!9{Z2xhSp&*OQCpdT}vaEEmVcbG^9) zE|E*(`fz=@eq4VpnH#_j)44Qm1~-$N#m(mCaC5nN+xgXq5?icqj z_nZ5}6VG@T@8&(cm*;q%7kH7Ec$rstmDhNkH+Yk`c$;_lzxXVCRz4e_ozKDNA8`=C|-$`EC4meh0sk-^K6d_wal9ef)m@0Dq7_#2@C5@JIP${BiyS zf094NpXSf-XZdsddHw=_k-x-W=CANq`D^@j{sw=Ozs29?@9=-~clmq#ef|OekblHK z=AZEY@K5jzvkcYZ~1rpd;SCek^jV}^BH_5|C#^7f91dN-}xW>PyQGG zFaMkWBapxZm*5sWf>+=KUJwLPkOWy!1Xa)kT`&YwumoFhgujF=LRKN0kX^_j

rV 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 diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf index 07adc1ada898edf29cc09dce8de44a7e911670a6..f1f0cb1bebbe5dab35197f961c919b611277137b 100644 GIT binary patch delta 541 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 S+kc>hW#QcabTl}d-tm7A!yAYI diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize-retain-gids.61,63,65,6B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize-retain-gids.61,63,65,6B.otf index 28fc250ea6464db50d7b81b47e94d9cc54c250d9..b353d43466e48e5fd93cc019d0aea85f0fdf7641 100644 GIT binary patch delta 487 zcmWkrO-NKx6#mY;Z=R#w9N*Lwkv}ujn*rTKCb=kTC>R}N7|B5lM145QK#h$kGDMIN z{a{+eh1?iuxCs;n2bx8zR=EgDsD-Uuwh>%pJ!hlmF3vsQcYeO_z}?>RZJ&RV$!0T< zn1?{(PBIxz{F4H}Pr!VW8Mxdz_~BC#u>NvwY%p`TM@%z9L!KZ1c)=~w)4C3zeuMc+ ze!|V2URc}%d^zUV@?7v=H@@-y59Ut3Fk6!MX^i_T0Cg4I(nt~Me(r&XU`@G&i7V}? zEKtW`3>6>F%pN~SCmZ&1KRl-etDyzp)H-u#js?%WG+VgOM^YEST4_cw4G_^eHE)D` z8YSQU@4n=f0^Va8t8GfhTe9Kj8CYn*t#>YdS|0z#@IBdQX@x}X)Q zPrzhTR)cNeBC%0g{l5BM*)MKazCOD}Q3#@XyV(oN_{ZA!pcj$xjoNPx)@kcxCtT(;ZdAF^5vT{&P(Q-;ql+x7)f<7A& ceTDubheP9GW?ISN+@N_iVbL#Ij@{EsC!gAF&;S4c literal 88392 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 XnWO@wxj_8wI|3P}PM9wE2BZl9k;snt delta 4052 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 ZYxb;ccGuh|F|2}VX~h4uIi1gL`#%92KUV+% diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize-retain-gids.660E.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize-retain-gids.660E.otf index 76fd881ce262138c194216802ebb468c484af20d..afd9c3363acfc6cdf7663ce0365b3cd7a53ec687 100644 GIT binary patch delta 529 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 ZotasZ8OQ@+86e3BrMZA~%;XhZF94CRB3b|d diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf index 7846eedd8c916e32afbf290a71f2611c1e6783bb..b69448b5e6822a63467077a4f93a3674a587bf0d 100644 GIT binary patch delta 134 zcmX>gaYAB(xhxL@0|Q5LZel@(aN$`725t=?|42q^VhV3p&x45}!HREy0t#h75svMm zb_@(WDnPzUS#C)M%LPVWAYWwT2^V&jdHv!yCkt?hu-ue4Pur})!OX140#wKhQVhf( Ub`Fro2<9_0aDn)fUAX@M005O8H~;_u delta 126 zcmX>haX?~%xhx9<0|Q5LZel@(aG?tW1Gff{zb7L#F@@Knw|Zhou;LS-fI=Bigk!s? z9RmZ843MuzOne-$pRcAEH})`MF8~1VV<2Pz delta 141 zcmca3a7AE(xvUHW0|Q5LZejt$e^yBb2KEdfe@aGbVhXQCZ}r5GASL!cKoNy9pb*D) zQ9Gbw10Y|eEVrbBEst?Jkgu}wL?g5Gg~|o-{5D@1n3-PypF diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf index 872859bfad812f0143f6af5d06b309b36e78f3b2..6f98c8fb5204f883de03024e0c17eaa9fc94feea 100644 GIT binary patch delta 148 zcmdlXc|dZ4xoisq0|Q5LZel^#l~5-J2JQtw{*jE-#1!7Ho(B^{f)!JM0t#h75svMm zb_@(WbAWu6vfPpimTZPKKz`506MNaE{T<%M^V@u7U}k;+lxMiOM4%5u-;_5`+q{5- fnOTtq$YTa#6(9z&bAUWXFrS%$3&fwihx-oz_N^nc delta 140 zcmX>gxkGY-xoiys0|Q5LZel^#m5`kb4BQKV{5=_|i7C7mz10&#f)!(c0t#h75svMm zb_@(WQ-FMxvfPpimTZPKKz_@{6MNaEKRbMk=ePOFz|8ytD9>_`2|Sy;u3*A5PehLJZ zib`k=*oz0z{sF}mA}9*tp@<#?FX_b|q83kuVms}j?Hh=P_vZV)nfJXnGcP^|)-u&> zKA(k+Sx5|JhKJ+7(j!j+`~d9D?4>jPbN7DdfUXm)-MpO5jmSwx=w9Yz-70zIiC6dg zfun28my6?GA@t}8FZ@dV@&Xs!@TX4 z#`{i==DFY@Ag+|}+^y`-fg5zs^L~6v8#ZDWfy8^}?vytCCS2Zss||rM2m%O(01v(Y9ouGf*$2`y>hSSJMH*pM1Pc{>+1QS%pbt$9hkn%c!`Wn%8Ys9hGRqpN{Ia zQ#Gx&9Cf@6|2WFEQwv)C>!@T~-EekiB3se_iC485*$GG0$B3SSgUqd^FV>Cl;6F&Y z&I-NV|B0FF6{2^LQoNr5CauaKoAK50~5O&ySrPr-Q8W=cH1pryY*bp z`<_qd_nvb;{Jq8)bFP{(=3MKRfRK;?QYf9A)TpVCk5}wu)`p0#6K#DJ5L~g!=;6lzvmDWiz&_Vuh2a{A}M#+`<8!#Qt(>=_N}1fTOsGS+^(Nx6ld_SJwFB&Aaa*=Pn=bN zCXHCB70gQkN+HDl{85U0FRH_;GEylH+1gzx2C3>YNyYVuBaQCRNBYAGusW9FNomQkJz`S5s#L06t=xb9t?u<-HN1k;Qc|PhQ@mOv zbWco9N=%MOjf(Ut6_c8pRHtIae*OAYi1^QmDs)ebuUNXASHIZQ7_XqHl&IvssOFQH zkm}VM4d_+!zn{8f1+V`$ykb+lBD_+QBO;^XBa-915~KfLmy1pCN{xx~YMT)IpNj{l z;vR5#LS)6nWUoY&BztvF?30k192=EV;eVeW?d$cQ2FA_&R|Eea;s193k4`A>9h=aj zTSRKg|6J-Dl@OI2+x>qoL`x?2NRCK~`M(_O7m*P0KOfm9IT6j88k?99(d++TqiIXO z|9>U#*dDR}x2FjG&z)c(W5mTd;wjACl9)RXqbmf&Qz7?4a=X`%!@ZIA^9@Pox05DR zBCYfYa+aPzj?zx`vb`jfJ_$WbeCdbKe-O{YaX*MFBa)+x z2NWbKQh;>C-9Q^(u9rjdmmDvf75MSmj%5Nk72=V8z-^0#^eua;j zSC)~ptOB)(l`RMg!!8CbPp+~JVf%pQ@bRo=L&#CK1MF@9bFXY)#L}RHp}20@anOli z9%3870dO4WIY(02+r*cBg0iQGy@X~$KNBnG1~O^o3K5knM(%PIq1DJyt`@W|${Itx zfiGfyC=W&~6oezzgIwj}p-G4jCb`^V;>xW<*=Fb|=tUCB-Ge>>FHr9_6whDoGdaus zBzJiivGO8Od4*i%ZTNX%qm9d>4a%1yNBPPquM2GoS|EltFCR)$`CjmmJIklym{EvL z1k=ELoM$E2LVWrCsB;c6`%lhIEX56@R7yM$N9Q^8_4(xi+ zMo?V00@}Vp0B8q440It^g&sIA8D)JD9|$nMD$Ip0hOPh@R~5Fv--G%G!71V@Tt@5; zVh^F8$Wc)xv0`E3DwZLtSdN?(D?_V;+K4qFR?!D_{NSVCE27UUqP;8jKv^QWEA~bG z(TI&l4Ey(m|9TLF_#2OW+~=4YoRvM$Jj5y^+gC0MEr~j1VV4KEc4Z&b2|z3qguxGoAA_<4a#!vH zdjRaA&>7H0sDo#(yaxUjup9M{!#@qKfm=A{73zG1or$#ubF4~EXdZG@DGDmWuL|lB zR|WZ`N&w0*$EtKBSCwe^J>gG>&I0qnQpDFFhG(yGhTK&y6JG^wTjd#vRsM7SY;sh^ zl36tuIjdqESFHvc^QWpe6z8uRgz|o1D!@6bZh+#xt74p1y@`5%!+!uUR;wcSR1=6* zLmO4Yd8%P9R%<}cY8VgI+QSY*c`|&=^=b>jGH?`}MEo-J4$5$@>TaUy0y(Q2P&|Ki z%(3capyfdolq1JfZvrshs{2Fn{M9=_yP-T9$6*Xq9|T6ho(#o2tB$s)z8I{AzZQyd zSN$*OLE@_4LhLTM5B~|V8tC^LGC6AGfaU_opEYWNI^?e53%@nMGu4Peoj%YsfL%z9 zQP8OX?NkHLSYr=30#2YFa%v5X?HZWdHSnA@kgIEag8c>hlUPkBKwhcoAxF*pQjc2Th_N&>A#F|N{+ZW)PHAjN!h~s)S(VjIof%D)R_!~S#8S+;xMpO%Z zQwz^k%Yx&;>!|nv4VfQ4i7IJs3{^YEM++Aw~n27jX zl&>aNtxd$&!dR|#9I^A@GRm)!SnDD5Iga@V{fhEm!$WglzvD($3 zxPI;Wup0x6zuNxfu8n7|jdrfxo8;Ofq4U5}uofHwXxrKsz%}p>$Ob>iQO5ytfC2#X zrcOn2*Qo`tCe&#Ky20)VMQ*Ay1-cNd0viCvMxDI?&r#<-zQ80KvQT(iMhoa-|DyCgQiIBW2m91W2>8}d+%oDDI58|EUtVJUJqL_aq~UT9bw zU=BCL{B770iaFe{0|-aF7ikTLLNTrzj>YlF-3@1=-dvO~Kn!!Y;ReKafaBmS{F~%x zb0c5ac%DW<#5F>0Y=qp<2+!0AbEVNj)WP^^v=M9vdr%+eX>BJgi9dEn|V5~I87-{?-d?ja-yyR$7 z0$@BhsR!DFPULEm2F4I;G6~>$nqYi1!B}px680K$H`xl^fwDa~$6?qfVV{A08Fg;J ze*oTqPlzFJG<6a+Re%QDB1hBQ&;sOcS`u0g@oE6~+!S-FX(P~_TuqU?nufs+N4;Uh zH62f8Q{=^_%gEVu4bFk*X}Sv>LfIMU1#ll_FQ9M150bnsa(fphr#JGkcTIrvdI!Tt zJA22I!+QWUojC7tsE6F^odM<%d9NVedn4*?C)xWL>LE{g-$uR1u;0PP{?7Xw_(jfU zZeq zL~=BnhWhis3e?$x_;%=FayL5*ZlN6a&zNPMT_5zP zPb1(1I{?HI`NY9bhK=0l(;vs-P1Zy|E{V%_tt1jSnF+X!)Qlw%L?i)Z%jgm^dDNjPpW z?2)iDi1WpI@4F2)^0DuJ*hk3ai|hJcK%Lu&-$(p0eB@={Oq6{m)||-Q9P_n#Uf4yU z<;c+-&)d8;=mI|h@jm2gJ_PkJ?wd~lQ@~7=A^$huPF(XN@Q=gCTxx!agyv6i?0aG@ zT!1HM3k{l^s6{DI7B-%%MK#2c4_Y*a-2#dn+M)x9AyspIFh#kOjM-e*> zJx5B5Cph*6{C6nBTG}ETVEnZBP1KT+qb24>OXQ!HdCAq%3tAk0DRQ=~47(2TEnAb= zG7M!s5budtA~XeHZEZOOItu5Q3^0CME`Yxn_IezT@zZiUV*6ktzqdrYw!8xSHe%RE zw0sRe8#Z#T9})RsE%K9z`57eo<%3{CXmmh*&@P z$Tfb$Q8ob}XZS4v>k!)p{R@g5?1$_7-G~1KirnRgeVre!@AofJE19@fX!BMW$F0z> zt;&+CRRh?_kFAh*TeTraD_pl#XV4WyBi4)fR{aqlL`o~{SzFBn3juO}s}<1IOIoQ?6)w%&u zYvj4s-mqIjTZ8t9bw-^S*u6n27zA*w*5d*4LF*0VZoLmNjNjJi&(_$xw7!RPJca*( zD8NH3z>6FK704M-4|v0GMXmtkynqfU$N2-$ZUM1~BliU08Ug*mU=jnSqYm;wz*5v% z4P6J20|T}Z7jO#az@9MR2Ea20U|t41LhL=x^$GSD@RJ;Eh*%qrTy0b+a#9D=}q^Q!v^jxD|YKVsJ3Z+LJT5D`Ii*u|@@_5f?ljIt_jXbUt(` zxr5iD9_D!P4uF0NK8$0J!#)kgJqDwVg0JD&ySUCv*zZs$n_M9RIYM-Dh7^Dn162Xm ztdM4)72+7PAzffc5(|lerohKs55YJI83o4S9GHV4vtgrOLJojKu+cUl4*=$O2SBzB{2{KbLXNfux!UH2;+s(0BG8i1%Fyc2diX+%Jzv`<@G&pj2BB^Ta<&ae zEDAQ(mA06VZD)ZM@He6CFVs6gV%sy&n<#&Ry10JZ*YLB!4`QKia)e@Dgqi?jGPELb zq4i+nnL~YGqrF41*9q+fyAQzn9E$6N&O)7q068sm6=FNc6^ii}iX0yL5BLKAH?ejO zasX%L z9dZ7S$VVN0iSO7IKHi5qW&o_69aoanaVw75MXrv=aGs0Md+;B_eg!_F4%W;tMij;o z3(HB)umaE`0J$wJ6m%q4SOm&bP;UyroC%u^AM+**`}#1nLD){jF=oS#!bV$!og+T% zI_&%4Iec6z>>CvO%uWtsoj9US8t}l*2Q3JS0_3+&)d0R>bn-!2OVAqeP?9@!hepGX zM|p4PV1WGAX(Si}CIIByPIJiBX%Xz@U=@zpNPMSV(ChG#Ydbv!$T6KTraNJ6>+}sa z#$9KO>CPUa&ba~Zr?VG1JC`I!=klN_xjOryJOp6<>5Tc@xf>L7x^p~8CU@u2(D49y zr8C~2I-_4ZF9GYoM)+u#&X`x7FT+Nz?R*zD#(ih3cbz{2jF~Q&TU}&wb;(bxODRyE zxGpuI4G_l~*ahE0y0n0eoZqDl=n6X$b&?TJ1p{#G7%-WHF6f^wi(q4Hb-}#uvKOF# zx?pT|!P?j56+oWtl8Nj7APVQn5svW{j`y1IQsfH9Iul+8V80ZOeh3dmJPaBEqQGFp z(eB|G!{KP}@Z~sWBkE(mg&#m&taIUb=J2bihjAAE88*g1_#a|jk;l8@I$iTXF_ycQ zhL#7F$=$UDv=uZQ@t&};C+j)__GIXCa(3Ma-G*|^yRIjQx?-Q*6?3NRHRv7a3-A#( zuGbZP8^Pn(D|}Omz%?Q&fLi2;@P+z8F()H1CnI`+6x6{UB?8|OBIc4a0{gy*^{{t< zJ*a;X+y^h=BX30D{1HEib;Ee>rV-c8i`?DH6Lo71Kb9QbhC!!;#pLX^nq1wmpYDeD zf^PRv?>TI|yJAQ?x);IkdiBZKy&ddmqVC8K-EnMpte4$!O!v#sr{E2_BT+w6A{JQ| zT7xJO*NSWlI>5&o9GMJz0=XhF1|w&}o(~qm#(5%7!oCK@GeqM0kyz&=G47)*P=Xv$ z4M8h_Hi<(2M&TKv5}?WCiW)!^H39xi;-gj}hJA3Fc-xAu6xadgOn7h#<;A4LsJqb4QX*BXxH1_+^i@_Rzyd8~pkKPY3 zj-t`8(U>PaT*P_^Py-YqcaM_LDgZg7M{Sffh3x~H1AlV$XpdND5J%1)si-p!_B^nJ zxE^bv+rd86!@F@0^ly)Au%7{p*BJC`4A!2Qa-afiJWotr#Ic^n;2TOzEBM$~#2_cd zpzULNfiy4@{w(Nn)Y}Z*36Otc4gx$&%t>;_AP2`hg#R97kt5bc6srQ{!`R&LF(+b? z(_@>1NRngwB98rB>{76bgxD=m+bs8eFb_K{v+@j{(sJivDwoNkjr~wuin!K zinYIIDirTHJx76Qu(AI4Tm`m*>*R>TIumDt`~d5F9Qre^EU~ysu&YDS&T;i&H-VyG z;{su~C088AZXEXfafwj$aUAYBE)5I;qX525#LYn2EZB2VAKyRX& zorL{Zl1T2PoJ2{5KuN@^fu@Kfk0!N64DZlMDX{y(9t_a_N#mi&6-j%^nS^yG34NP{ zbuS5ff~04#-{PFv(60dNPtq@P^k&3*>rmwD-uPDCyCSp(VpxZIH-`Em7L4+6a`ldZ zV$JJ44l#`5-WbQdm%-l-cEdjm&H(gR?_1FC#3kn;cQX1vxi~qKtHQ<@PWB~7ax0XD z!tO+TGWsGJeUY35`okUrorU;P9J3bwR@8k6eTDcZ@EKsPr8tRC(Md`{`=nGNM@kJ) z4>s~q3cl&21cCOjBM^%MDe#e3Q_xN+lgXJf8?hybts*XEGjs>JQ*iGo=KkA%*L?t@-{-T`09 z(Ff~RAMCOF;GX+b1Ze9%nBRS{=J)XdekAw7e!fpP#IPRpiHF@E_7K?PpfkZ-*qFzC zurBw(`0Rsr?{f~Z8>ovtc3%eY+e6=c0Bzs51Sm^FU$jr(y0Du8jM2WBgMHE7eP^NG z64={dW8d2MAnXg^3b={bQ|K#bCKThdpGuB?$eaCgle?c6v^;2uSR2q0b`OBQ?1!A! z?=-kd)DPpYAD+KI*1rCQNa$Y@VOCInvzZO49+p`KKX&rd5GmnCo`!_iTy2&{Z{W-80aRbrb1FM5N@EgL%clUvqn*$Tz4}_+p413an zlc3la55zSFu7SM?_FvGw0R1u${X6g`c!KgwatuP=86=WxkOh#}1{H^oYYnPG&OxA(0IhA!`}cO>)IeZ%OI=)gDw&`=r(N3-$C!-BmWHg zMy|nF^9C!#1|x3_#@=;sHgSXTt}?_RHpGiuLoh#vlmXb^4Z%7%qzXBP)P#?5Hl#Jm zLtwWD;qbA~7=nHH5cK5`^yLt|j|^D?T@CQeLw4c#gV2-kui_e53E;us=Yt{tw0Y zPA77vV_c+TZ<<~jKK3!`RbV$JF1BvXvVW@+4OGo}r$J&{Wbs~Kv>P&)WKrs%} z@%=G<6Lde$aTawh!@dVF{?b2!@8lka-`j@C#D?LU#IR!I7>4#5Rt409?Srx)*zHLe z)*b$E)L9DMjMxsMVY{G*;hzUj!5i=qb-s}>ydXJ;<6OfllVf;Iat}wY9^M|>6@C)v zgR*q!cxVPddk@FChpz$X`{9QXI|Y!FhCd*A_&X@tW;o{Q2mx5cM&tyAi5r3Mdn1su zM>GP+OCzvWkMKtwyaSJjfsghdkq$<{#~ynGt~X*1$`?Xcl6%Bvup3+>VZ;N(UZCt9 z?C<0lDFN(ZMm8d0WDpc%Wn?74{2z(u7}=kkBk@i(aul(V!bX3O-At~rn7d<7f$NB6f}i9V=O#7| zdx~-B<8cL`MSu^$J&o%~?r~V}$6+lVmkve)+|RhR0OMucWq`Rf?q70@F9FID8($TQ zb!$AzR&=GZx@p~k#kZK>=9rQ>aK#WMI5S-VZ$lPJy%VFGA6tQ=S0a|CB%Enu@*U)EY!n(JoV4L(!L0BS9R> zQs5(}OicqAXH$m({J)l|SRaniKE< zYs)m;`!tN_X~jWllBQuiPYWd1H1y##jOl5;Kwp5ha@s8DVscO007VX)whQcseH?lk zJcj)dig7tTAHbNNUW3^5rT}ZL~28!H~(Gj4(GopykK(5a~Uu2-2GBE!$kjpZVCo{I7&MxRtfP9&89&zM?jK?@H zuAT7~d_$ez#AYIQ&J>^uFk$B>ekR@vW@3$;Sraq>O%QJm{E3^1@iwzPxn@Q{qsToo z0r5fbF?VNTT+f_B!c5%D%+0Vdj%Q+@HWSZ2^A_qLr_Fo?@cn)kkz*Ft$yqs|=(}0v zVOJ;jtQN3a!w!Otyf6#%dKSLD%o<3}S;G)Vj+uoyGix>234bs281y9ST!!8t*KCZ} z+31tmi-~5VPiCX;Y}B277>ay0`yT3Kl5-CFcTP@n)NKAGb~@*IqtIbrbe9z7?L zTyx?`oP!)a2l;Ide&?Qp>(7}Adm(f=(VUgA*TUWi8`qe#7hJ+|4*=%v9Q(L9XTd3m77NArq_vz#1=#1#+m6_I z*f$Y>0Q)Dg`64;yo6x*O^9#T(3M~b#1Zt3LeiM{o?U)};?)gc?&7TAx=bXO^Wt&m= zAnfA+``P)=;NyLI{zuqZu)o8`y)VEu7I;8zaxExKv;bpZK~-`tXb8o)U(g0+p@^eD z7DOQ)2R|A90N5FbA%8Adh+|j4et_6h@SfO0Hwg=EaxTO>%|fg-3$fNLtWEBPK~T(} zg^^$!m`eP@dC+A5ZLkn|We?t+_n=Ro;r}>4J5KZr?f(q9_!-uNXIIGm>^92q?*8mG z<$CTU^|=L#5k1GeeUAHoUKKPX`HeyB;{>9QQ^6vD@2H=0lk-ynVxPQV7lD?5mI7sn z`-C?Agzto(8pHPnzMusa`qY!ePkl)FG=g$}T1YiN-9+6#M42`@GOs^G8|9g;mlf=x&R4L0QmX(uSSp`VQ!ZT%+ zAx9Q+NLFPio-L~$8CiHo$in|c%fh_Q>IyrWoLRkKC!s$2H7k|4EX>`kbds|sp;{Jfv!S1*5|DC@Hc_2q+}g}9>eiiKALn{bQWoZU)>p)^ z_ssfDj%+7UHb*QQV=r4JSGI@T+4(>b#4%s8OOl$6H6*(>?7Gkf&_?9UZiYJkq-A#@ zE*tHbodEihl06#bm`~XgaK0%}?1!^6z-;)~S7hV+UiNC7XB~7q;+WIfdvV>P&=cSc z;%Lk4DYs~bI|&;QM$APfNBLY7jZeTXLId}95xTvvi)JAyy67*WT`u}U^wY)8IM@YZ zU!0CsA*f{v(tgree5W<)>Uj16+7rC_QYB2qod?`cgcrT@)cjIA(d*( zm-41k&G=G>ou$t5rLLE{?!e_8QsYjQZ1@Y zb*L`Yqx#f<8d4)_OiidMc~dj;Azx}vEvO~=Q7iJN))auh)d{2^3Z@WhOQF<`+EWMW zNMY28I#U-4r>+!1-KaZ7QWRRR2gOh<^`toJMe&qCiD=8-luRj`fp`nyc!)Q2-ppi6+M$;G?OXFxfO`wT1i6+w&no84XI?bRAnu)%cO>?j&%%l0V zfELmsT1-o5DJ`Srw1QUBDq2lzXf3Uy^|XOD(k9wWTWBk7qwTbVcA^(|(Qev9dubo- zrvr454$)ycLPzNs9j6m?l1|ZSIzwma9RAel0$rp_beXQuRl0^hwYot!=@#9lJM=f* zrF(Rr9?(O2M33nS{XL^palDYkEU(=^eeN5A=~fQ6^@K^>Yd0KCqAM6U$^-ESr61U)Wdn&GFsw!`a^1!MV@5-__F<=WgJBCSRzyFa_XxWBr;xxc%AxPQ8Tx&L+lcK_js zW1NF?axTuzaU9PHoXAO>%qg78X`Id(oXJ_7&3U*STuv?*mz&GO<>m5m`MCmIL9P(z z#TDj?a7DRdTyd@hSCT8mmFCKDWw~-(d9DIik*ma2=BjX2xoTW>t_D|=tHssk>Tq?r zdR%?30oRag#5Lxca7{UHt{LaU`Et#<7FH+1#!V#2-lVi<=S!W zxei=ME{yBMb>_No;apcPg6qb0=OVc%E}HAX#c;7)PcDw@#l>?8Tq2jm_2!bf6fTwP z!}aC*as9b8ZU8rs8^jIfhHyiWZX7qBo4`%vCUKLwDcn?U z8aJJr!DVnWxmnz7ZVoq>o5#)P7H|u>MciU;3AdD6#x3Voa4Wf0+-hzOx0YMSt>-py z8@Wx~W^N0&mD|Q`=XP*Axxctw+-`0Ux0l<;?dJ|~2f0JsVeSZblsm>9=T2}Zxl`O} z?hJR9JI9^pE^rsQOWbAd3U`&e#$D%ba5uSI+->d-_cwQ!yT{$<9&iu2N8DrX3HJ~8 zlzYZK=U#9xxmVn4?hW^rd&j-!K5!qoPh2LK#btA!xi8#T?i=@=`@#L>esTYDzqvm= z@r-xyPTs}4d5-6Kffsp+mwAO(d5zb3gEx7Lw|NhrgU`w5;&bzP_`G~RK0jZ8FUS|- zz4*d>5xyv2j4#fY;7jtQ_|kkCzARskFV9!tEAo~2%6t{RDqoGS&ez~;^0oNdd>y_n zUyrZPH{cucjrhiV6TT_$%{SwHcwfFb--2(+`|+)Kf4(&zz_;N8`5-=+58>PLp?o{O zJ>P-v$cOQr_|AM6KAi8$NATVF?tCO4#Ygi!_!vHx@5#sUz4&-OfluU<_}+XnpTei| zefYk7KfXVo#t+~J@`L!n{1AR9pUw~Chw~%&k^CrrG(UzP%a7y7^Aq@q{3L!dKZT#l zPvfWaGx!XCCO?ax&ClWI^7Hul`~rRFgKjHu3 zpYqT6=ll!)CI5cm zAZ!#i37ds2!d79MuwB?8>=gbIb_u(MJ;GjLpRivzARH7935SIv!cpOva9lVcoD@z8 zr-d`ZS>c>;UbrA!6fOyug)72U;hJz=xFOsWZV9)AJHp?>UE!W^Uw9xq6dnnWg(t#4 z!c*ay@LYHyycAvuuZ1_lTj8DXUict<6g~-=LY9y%d=|b4UxjbNcj1TdQ}`wPEBqGz zh$J%6Av#5u=oUGV7X?uiB~ca?Q57{&7Y)%AEzuS|Vh%B#IkCK0L98fN5-W>U#HwO7vAS48tSQzKYm0Tn zx?(-CzSux)C^ixsi%rC)qPN&g^bvi<=3)!6rRXQN68**2Vu0923>1UJU@=5&D~5{g z#P(tbv7;C!b`m>_UBqy)s~9166T6F%Vw4yy_7G#lSh1%VC-xHK#RM@?OcHyG$zqC_ zD)tfkiv7g?VwyNW94HPF2a7|*p<=o?OdKwb5J!rm#L?myajZB_94}4~CyJBA$>J1o zsyI!YF3u1$#F^qOake-|oGZ=~=Zg!(h2kP{vA9HBDlQY3iz~#H;wo{qxJFznt`pab z8^n#`CULX4McgWG6Ss>y#GT?_;x2KwxJTS8?i2Tm2gHNoA@Q(yL_8`U6OW50#FOGF z@w9kGJS(0P&x;qti{d5mvUo+jDqa(>i#NoZ;w|yEct`wOyer-l?~4z_hvFmgvG_#% zM|>(i6Q7GO#FyeL@wNCyd@H^a--{o_kK!jWQ_K>x#n0jw@vHbv{4V|we~Q1vf5qS8 zABiL;IV7j#lH3v}@sc2kk|fEJBB_!l>5?Itk|o)aN6I1PlyXVAr94tzDW8;IDj*e< z3Q1m4VX25zR4OJFmr6(_rBYI9sf<)sDkqhfDo7QjN>XL1id0pqCRLYeNHwKeQf;Y@ zR9C7e)t4Gb4W&j>W2uSMRPvUZNj{RV)Ld#IwUqp%R+7KeS_+WbNP$w26fA{EZKY7D zoz!0HAa#_&q)t+2sf!dYb(JEdZc=wCQi_tIr5;j@6f540=lIwT#Ijz~wPW72Wygmh9m zC7qVeNN1&U(s}8EbWyq_U6!s$SEXyxb?Jt5Q@SPHmhMP@OLwJv(tYWH^iX;vJ(iwG z|42`zXVP=&h4fN-CB2s3NN=Tg(tGKH^ildGWlC96w)9#0B7K#m7B{g`H%A4fP@)mikyiMLN?~r%Of62S#-SQrJue?v*FCUN(%7^5`@)7x{d`vzrpO8<= zr{vS}8TqVyPChSRkT1%YzmQ+bujJSA8~LsLPJSl2gg0QblQd}valvGM7rIj*DS*4s(Ua6o|R4OTzl`2YArJ7P*siD+VYALmq zI!axoo>E_Fpfpq(DUFpTN>jyKX{PunzDjeYh0;>-Q(7thN^2!RX`=)xK}xU^qO?^) zm3B&drGwH@2~#>Los}+1xYAXLP`WAIl}IH@iB@_jF-ok`Q;Ac0De+2zlBgspy_IAo zMM+iqD1DWFN`ECy8K4YQ1}TG;A<9rCT^XhfS4Jo!l~KxQWsEXb8K;a_CMXk?Ny=np ziZWH1rc766C>hF3WtK8qnWM~A<|*@)1qAXRGDa(}=%1ULGvRYZAtX0-2 z>y-`4MrD(-S=pj&RkkVHl^x1X{a$D`;`OALFJHgSUI8`RgNjgl@rQI z<&<(-Iis9a&MD`W3(7_1l5$zOqFhz3Dc6-7%1z~#a$C8h{H@$o?kV?`2g*a`k@8r1 zqWq&gRh}u&l^4oO<(2YUd852l-YM^u56Va7lai@qDcQG@N4b+BeBek*GL~W{itIbp&)mLqL7KnIz%0+rmMr$;pzx=q&i9+t&UO0s^ir0>I8M7I!T?Z zPEn_-)70te3^hZYsm@Yot8>)3>O6J6xah(OVp+6GIhDSLS3n@Qdg^M)V1n5 zb-lVl-KcI-H>+FJt?D*)yShW&ss5$zQg^F+)V=CHb-#K*J*Xa1535Jiqv|pBxOzf8 zsh(0#t7p`+>N)kidO^LYUQ#csSJbQOHTAlBL%pfqQg5qw)W6lc>OJ+o`apfCK2jg6 zPtO1wl`a%7ueo`~lEHzvGtbS3ys^8S_>JRm&`b+&+ z{jL7dNMo8qb80Tlt#KN!37V)$nye|Bs%e_88JekCnyq=X99m8-mzG=0qvh4|Y5BDR zT0yOl=A{+ZifBc(Vp?&ngjP~3rIpsoXl1o>T6wL4R#B^@Ro1F#Rkdnbb*+Y0Q>&%b z*6L_=wR&28t%251Yos;SnrKZmZ>^c;qxovhwH8`S%};Bk`D?AU0IiJ{s0C@kT8P$G z3)R|b?X?bCM=eb2q;=N1XyIB{Ekf(2b=M-bC@os+p~YyiT2C!b>!rnO30k6-r1jR4 zwG=H?>!bD6`f2^OG;M%3P#dHT)`n<9wRCNmHe4H_jnqbIqqQ;GSZ$m(UYnpz)Fx?@ zwJF+EZJIV+o1tZBGqqXTY;BG zr>)mEXdAUn+GcHwwpH7vZP#{aJGH;GUD|GKkG5Car|s7cXa}`J+F|X8c2qm29oJ51 zC$&@BY3+=5Ry(Ji*Dh!mwM*J%?TU6)yQW>&ZfG~PTiR{yj`p{9SG%X(*B)pOwMW`x z?TPk}_EdYOJ=b1nFSS?NYweBpR(q$t*FI<;wNF~6mZfEDpS3UASM8hjUHhT^)P8CI zYQMEVI_XSz=uX|GyLC?IbwL+(Ntbm+S9ML-bwf9GOSg58oW%cqdK0~=?yWb|eRN;Fx!yu=sr%`zbbr0I9-z0;1N9(1SP#+L z>Y;i&y}jN+@2H3Ao%GIn7d>3>sz>PE^zM439;HX?J@gnoR`03D>Am!LJwZ>@ll0zt zvYw)+>V5RSdOy9to~94b2kL|L!TJz=sGhD5(}(LL^pW}~eY8GCAFGek$LkaHiTWgc zvOYzhs!!9W>ofEWeWpH3pRLc)=j!wH`T7EVp}t68tS`}*>dW-y`U-uezDi%MuhG}) z>-6>d27RNxN#Cq*(YNZ`^zHf%eW(7HzDwV&@6q?_`}F<#0sWwUNI$F}(U0oK^yB&o z{iJ?MKdqn9&+6y&^ZEt-qJBxgtY6Wu>euw^`VIZ2eoMct-_ifp@9OvT`}za@q5epJ ztUuBJ(Vyzi^ym5u{iXg&f33gK-|Fx5_xcC@qy9f>|Ehn}zw1BrpZYKT zU;VfK#~_0l4#R1<47b4)9=ja)`TH`0s&#z13`G1wSl3^me?Va9M{gfY?>WsEk)7-Nlb#&~0bG0~W0 zOg5$%Q;liHbYq5*VazmU8MBQ!#$02bG2d8VEHoAwi;X45Qe&C1+*o0(G*%g_jWxzv zW1X?y*kEilHW{0ZEyh-3o3Y*4VeB;iGIklejXlO*W1q3#IA9z!4jG4yBgRqVm~q@V zVVpEh8K;di##!T>ao)IKTr@5jmyIjNRpXj*-MC@gG;SHUjXTEQ#$Dr{ao>1gJTx8| zkBukBKgLtznep6sVZ1b68Ly2u##`f^@!t4gd^A28nMRh8ZG1Mq7+;NV#&_d~@zeNa z{A>I+{+MJk(_uPIm+3Y+lQ#uZG$m6u6;m}eQ#TFMG%eFMJ!TFwrno6 zGHaW4%(`Yhv%cBDY-lzz8=Fncrlz;q%=9sR&E{qcv!&^0wle+A)@Fd&#tbxr%wRLb zY-@&^?acOO2eYFYW_B_=n_bLsv#S|lb~C%1k!F+`ZT2u@%viIh8E5t~qs-Cf7;~&S&Kz$}FejRm z%*o~ybE-MboNmrAGt8OhEOWLw$DC`emzyihmF6mQwYkPz zYpyfbn;XoH<|cEqxy9USZZo%=JItNtU*;}zx4FmMYwk1mn+ME;<{|U2dBi+w9y5=d zC(M)PDf6^>#yo4DGtZkB%!}qF^RjuxylP%EubVf_o8~R^wt2_=+q`SuGw+)Z%!lS9 z^RfBF{KtH1J~N-2FU*(bEAzGa#(ZnOGvAvZ%#Y?LGtR@%W!mLhKXRC`9ZgsUHtZr6!E7FRxqOBfQj1_D3wBoE@R=ky9C0a>V zZ!6hKu~Mx*R$r^1)!$0923P~FLDpbvh&9wow}x56tr6BpYm_zG8e@&M##!U73D!hw zk~P_yVokNCS<|ftJYlpSd`pep7?Y8zx6aEI%S=<&RA!ybJlt5f_2flWL>tdSXZrU)^+QKbxK2wdS$(~-dJy~ch-CBgZ0t+WMx`eR<`xo`eJ>xzFFU`AJ$Ln zm-Vmp+xlaZ&1{G5v|YB_=4{>;Y|)l%*;Z`T)@%Pwpev5VTp?BaF_yQE#pE^U{w%i87a@^%HgqFu?ZY*(?X+STmpb`86x zUCXX**Rku`_3Zj~1G}N!$Zl*mv76f7b~D?@_O+YaE$o)IpWVv#w_Do*b{jj;4zh#o z5WB4%YPYl7+a2tVc9`AC?re9l!|kqigx$^VZb#ZtcC_8Yj_j`s z?rkUADR!#e$L?$Qv-{g=_5gdJJ;)wx53z^Z>Gm*txIMxiX^*l;+hgpp_BeaIJ;9!6 zPqHW5Q|zhsG<&)|!_Kg0+OzE0_8fbzJn zZlADE+NbQ(_8I%Eea=2_U$8IQm+Z^-75l1v&Ax8muy5M8?A!Jo`)~WMeb2scKd>L# zkL<_x6Z;?gsr}4;ZojZ!+OO=__8a@H{my=Gf3QE=pX^LK%g(kx+h6Rj_BZ>x{lorg z|FZwJf7^dN9IVv$K%Q2$?3`E$?eJG z$?M7I$?qxPDd;KW@$wY*6!8@G6!R4Kl<<`Fl=77Jl<}1Hl=GDLRPa>vRPt2zRPj{x zRP$8#)bP~w)biB!)bZ5y)brH$H1IU^H1ag|H1Ra`czc?8d_2CM=AIUwmL5M(E04dY zwI{&S#uMlX@&tQAJZ(Lpo_3!0o(`Ulo-j`*PiIdTPq?S6C&JUs)7=y4iSk5ydU#?y zv7VluI8QH6yeGkv=t=VQ_9S~!JgJ`l)!to3$E~xA0-mIlGFi4P*^-&d%*@Qp%*@Pf znlve=%*@Qp%*@OTlQxAj-FtuMeD|#LklwM44rVrDX>BsbE z1~3DeLCj!g2s4x!#tdghFe8~!%xGo|GnN_0L^9)HapnYbk~zhkX3j8Y znRCo}<^pq(xx`#%t}s`bYs_`#26L0S#oT7@Fn5`I%zfqo^N@MOJZ7FSPnl=TbLIu} zl6l3vX5KJwnRm>4<^%JQ`NVu?zA#^zAQR7gW4<#9%n#-#^NaZn0w4^8gG3-PNCJ|A zWFP`02Pr^GkP4&*X+T<#4x|SeKt{j-09e2Q2zY=11_BTP0Tf6;1`1Gt26SKm6Ij3o z4sd}7GJ(t>3&;wxf$Sg$$O&?R+#nCg3-W>dpa3Wc3W36)2q+4Qf#RS9C<#h|(x40| z3(A4=paQ4}DuK$N3aARIf$E?Js0nI;+Mo`o3+jRTpaEzI8iB^331|wMf##qEXbD<@ z)}Re&3)+G9pabX#I)Toh3+M{Ef$pFO=m~m(-k=ZY3;KcnU;r2h27$p~2p9^6f#F~T z7zsv!(O?W13&w#+FdjsKXfOf9fLJgQOaha^6fhM`1Jgkqm;q*jSztDp1LlHxU_Mv? z7J@}!F<1hYf@NSiSOHdoRbVw(1J;6dU_ICXHiAuHGuQ&Qf^A?s*a3EeU0^rZ1NMS_ zU_Uqj4uV7AFgOB^f@9z~H~~(AQ{Xf>1I~hT;5@hhE`m$oGPnY+f@|P9xB+g0Ti`ah z1MY%*;68W&9)d^UF?a%=f@k14cmZC5SKu{x1Kxsn;63;NK7vo+Gx!3&f*^PZ z&Bx|v3$O**LTq8S2wRjb#ujHwuqD}2Y-zR(Tb3=ymS-!l71>H`Wwr`im955BXKS!E z*;;IEwhmjDt;g198?X)8Mr>oY3EPxy#x`eLur1kEY-_d++m>y|wr4xA9obH7XSNI5 zmF>oMXM3}YljJC+^CMzZ7C zC^nj%z{aq#>_m1FJDHurPGzUD)7dz720N3T#m;8uuyfgY?0j|syO3SPE@qdoOW9@Y za&`r~l3m5FX4kN5*>&uCb_2VS-NbHYx3F8;ZR~b-2fLHq#qMVJuzT5k?0)tDdyqZE z9%hfQN7-ZSarOjzl0C(qX3wx^*>mi9_5yp6y~JK-udr9yYwUIQ278me#olJ`uy@&e z?0xnD`;dLaK4zb=PuXYebM^)Ml6}R#X5X-H*>~)F_5=Ho{ltD|zp!7~AREtqW52Tr z><{)Q`-}a}1-LLSoJ+(d=8|wpxnx`fmz+z%rQ}j^skt; z<2l4(PT)k2aFmlcnNv8G(>R?oIFqwDn{zmq^SDf0W-betmCMFu=W=j4xm;XsE)SQN z%g5#C3UCFvLR?|42v?LV#uevEa3#4?TxqThSC%WsmFFsO6}d`WWv&WWm8-^8=W1{@ zxmsLpt`1k1tH;&n8gLD{MqFdA3D=Zs#x>_!a4or3Tx+fk*OqI?wdXo;9l1_iXRZs^ zmFvcJ=X!8Gxn5jvt`FCj>&Nxy25)44cq1~-$N#m(mCaC5nN+!fWt4ya8{*Tktl#1Mk9n@IHJ1AHqlQF?<4_!e{U~d;wp=SMW7_1K+}T z@ICwhKf+J&GyDR-!XS)?-{5zc0Dr)r@E82e2ly~PoKM6j=9BPA`DAxy`Cfc)z7OA*@5lG&2k-;=LHuBT2tSk` z#t-L5@FV$A{Ahj*Kb9ZINAlzOC_b8>z{l{h{6u~dKbfDxPvxia)A=}l20xRZ#n0yF z@N@Zj{Cs`^zmQ+VFXor@KALftnNBLv?asC8{15&o|BL^P0w@fHqeLh%N`jK2WGDh9M=4NBlnSLr zX;4~}4y8vKP)5WcfLO#Kh?yMha4qhIC{g6IsYc4swx)GNH^U3(AVJ zq3kFJ%87EJ+$ayqi}IoTr~oR63ZcTN2r7z-q2j0nDv3&=(x?n7i^`$$r~;~pDxu1# z3aW~#q3Wmxs)=f$+Nchyi|V2Jr~zt-8llFh32KU(q2{OsYKdB*)~F3?i`t>~r~~SV zI-$;}3+jrxq3);$>WO-x-lz}ii~6DdXaE|B2BE=d2pWopq2Xu*8i_`s(P#`Bi^icy zG#*8vXfy%Epjb2!O+u5=6f_l0L(@?lnt^7bS!gzzgXW@nXg*qi7NSLHFF+ zF?xcYqG#widVyY|SLii*gWjTd=so&?KB7GLX>eMc4yVT%a7N5vfLY98hFBi`(J$xC8EpJK@f_3+{@$;qJHx?umQh-nb9$i~HgJcmN)V2jRhZ z2p)=u;o*1$9*IZc(Rd6Vi^t(eJRV2kXgmSO;8;8nPr{S&6g(AA!_#pbo`GlLS$H;{ zgXiLTcs^c$7ve>DF+Sx^L3&;(sD1XHjCTW|zd@Ptf4W+97^Rmdh}7jg(W zglou)p6@^MdWub~t zRj4LZ7itJKg<3*wp^i{js3+7H8VC)AMnYquiO^JNCNvjX2rY$HLTjOo&{k+Cv==%E z9feLpXQ7MGRp=&k7kUUigl@CCnD)2y=yb!hB(Yuuxbe zEEbjsONC{^a$$wAQdlLd7S;%Bg>}MuVS}(y*d%Ngwg_8=ZNhe8hp%Ar;ev2cxFlQ_t_W9!Yr=KmhHz83 zCEOP72zP~h!hPX^@KAUpJQkh^Plac~bK!;XQg|i27TySNg?GYx;e+r|_#}K5z6f81 zpb#&76TS-x!Vlr6@JskD2E;HiTudY;7L$lc#bjcHm|RRDrW8|&sl_y6S}~oNUd$k7 z6d4hStjLK_)47juX? z#av=;F^`y6%qQj-3y1~9LSkXDh*(rCCKeYJiP%(ZCN>vah%LodVr#LD*j8*Owii2y z9mP&!XR(XeRqQ5q7kh|3#a?1>v5(kS>?igY2Z#g3LE>O>h&WUnCJq-zh$F>O;%IS< zI941dMvCLbC^1@`AjXKX;zV(hI9Z$`P8Fw#)5SP(hB#B4CC(P-h;zkx;(T#|xKLaq zE*6)FOT}g4a&d*YQd}jj7T1Vt#dYF(af7%~+$3%mw}@NCZQ^!uhqzPRCGHmYhNNO*z>CIS%&A(Ti&CJIrBMs#8jlUT$i4snS`GLg(A3&~2dk?bS~$w_jN+$0al zOY)KYqyQ;M3X#I32q{X6k>aETDM?C^(xeP2OUjY*qyni(Dv`>h3aLt}k?N!dsYz;) z+N2JtOX`vOqycG28j;4N32922k>;cYX-Qg<)}#$-OWKk4qyyO+n8A(Qw(PRu6OU98%GM+?{XflDskXSO2 zOd^xX6f%`eBhyJ7nL%cfS!6buL*|lsWIkCy7Lr9|F+GPy#ol56BTxj}A{TjVymL++A$WHf>% zrzvPknu?~TX=qxSj;5y>XhzCVKv~LBNO_7VrUDfyp_EEgrV3T5Ms;dXlUmfK4t1$V zGtta63(ZQi(d;w_%}I07+%yl(OY_nEv;Zwg3(>-~2rWvB(c-iOElEq!(zFaMOUu#n zv;wV2E78id3av`3(dx7Ytx0Rq+O!U>OY714v;l2M8_~wJ32jQ7(dM)TZAn|v*0c?6 zOWV=*v;*x(JJHUx3++m~(eAVd?MZvl-n0+xOZ(CObO0Sl2hqWF2pvj?(cyFi9Z5&g z(R2(QOUKbjI-W++XgYz$&{#T=PNI|P6grhoqtj^|ok3^PS#&m?L+8?YbUs}`7t%#^ zF>Q}i@FL(kH4^gO*lFVai&GQC2t(rffOy+Lo%Tl6-)L+{di z^gew+AJRwkF?~Xx(r5HJeL-K+SM)V~L*LSO^gaDRKhjV1GyOup(jbke-{^OmK!4Dm z^cVdt1*9-3TuLM*mXb(GrDRfslw3+7rIb=hsiibhS}C2BUdkY4lo$y}ti(xB;w2iEXQ_+SRq7^n zmwHG&rCw5RsgKlG>L>M=21o;?LDFDph%{6hCJmQHNF$|D(r9UnG*%iXMM~qPC@ET+ zAjL?r(nM*JG+CM=O_ioe)1^3RhBQ-}CC!%RNOPrm(tK%wv`|_kEtZx@OQmJfa%qLM zQd%XgmexpXrFGJJX@j&;+9Yk3wn$s0ZPIpWhqP1LCGD2>NPDGy(thcHbWl1Z9hQzr zN2O!Zap{C~QaUA_md;3LrE}7G>4J1ox+Gneu1Hs4Wr9`XqgpzDQrCpcF5ClfFv{(hupU z^h^3J2jnn0Tuvk>mXpXy-ZIggxI&L`)W z3&;iKLULibh+I@ICKs1W$R*`ca%s7YTvje8mzOKZ73E5DWx0x6Rjwvimutv1nC^=f5 zAjinD@~vzsO(Zpd2rMlfTOe@(=l^ z{7e3=1e7o(TuG!PR+1=5m1IhUl3Yolq*PKVsg*QJS|y#5UdfK(G*=V6jQMjTX7Uu@svzTW+jV~RmrAgS8^yhm0U`0C6AI<$*1I3 z3Md7YLP}w!h*DH3rW997C?%CrN@=BxQdTLalvgS!6_rX#Wu=NzRjH;_S86CVm0C(| zrH)cpsi)Le8Ym5wMoMF)iPBVQrZiVtC@qy%N^7N!(pG7wv{yPP9hFW>XQhkMRq3X5 zS9&Ntm0n73rH|5A>8JEp1}FoSLCRodh%!_erVLj`C?l0o%4lVbGFBO99E7f zN0npBapi<^QaPoZR?aAAm2=8@<$`iixujfHt|(WPYsz)yhH_K6rQBBTD0h{6%6;X5 z@=$rCJXW44PnBoNbLEBdQhBAkR^BLYm3PW}<%9B3`J{YSz9?Unpc1cqQ@$$+$`9qI z@=N)x2GlS$Tur1VR+Fen)nsafnp{nxrc_g@sns-US~Z=TUd^CpR2dbhtjeiSYH78MT2?KmmRBpN71c^=WwnZ0RjsC0S8J#>)mmz8 zwT@a>t*6#k8>kJ{MrvcViP}_crZ!hws4dl2YHPKP+E#6+wpTl-9o0^1XSIvkRqdvB zS9_>E)n00EwU63Y?Wguv2dD$pLF!<2h&ogqrVdv}s3X-;>S%S0I#wO0Myli0C^cH0 zpvI`N>O^&tI$52fPF1I=)73b2hB{N7rOsC8sB_hM>U?#9x=>xDE>@SQOVwrSa&?8e zQeCC4R@bO&)phE6b%VN5-K1_-x2RjyZR&P)hq_bUrS4YusC(6Y>VEZrdQd&29#)U2 zN7ZBMarK0HQaz=fR?nzs)pP23^@4g)y`)}Nuc%kmYwC6NhI&)IrQTNWsCU(S>V5Tr z`cQqOK31QoPt|AYbM=M#QhlYqR^O;^)pzQ9^@I9R{iJ?Yzo=i;pc=1!Q@^VT>JRm& z`b+(-1+*|NTuY=S){dn$wbwdm9kotcXRV9YRqLj8 z*Lr9@wO(3pt&i4M>! zpv7ph+C*)VHd&jZP1UAp)3rElhBi~1rOnpnXmhoB+I($+woqH7E!LK3OSNU%a&3jS zQd_01*4AiiwRPHhZG*N^+oWyQwrE?mZQ6EihqhDOrR~=CXnVDN+J5bTc2GN{9oCL$ zN3~ypcb!v)4pp7+7Iog z_DlP%2lOyKTu-DY)|2Q-^<;X4o?K6%r_@vFsr58^T0NbfUeBOs)EOP3H=v0?eDdTYIn-d1m?x7R!99raFnXT6KwRqv*E z*L&za^gnOZ8>?a(#uq zQeUO7*4OB3^>zAseS^MH-=uHWx9D5-ZTfb7hrUzarSI1F=zH~j`hNX@eo#N8AJ&iP zNA+X+as7mTQa`1i*3al?^>g}p{epf`zocK*ujp6xYx;HlhJI7OrQg=?=y&yd`hER@ z{!o9UKh~eQh%kt*5BxF^>_Mv{e%8d|D=D`zvy4}pdPP()4%Hp`Val5 z{!9OD1dK2v+(=|3Hj)@gjbuiIk=#gOq%=|)sf{#7S|gp2-pF8NG#CRItic)3;0l9bC?ndK zV8j@)#zbS1G1-`6Of{w%(~US|hB4EaWz06_7;}wz#(ZOevCvp#EH;)HOO0j5a$|+D z(pY7zHr5zxjdjL)V}r5L*ko)rwisKDZN_$Ehq2SxW$ZTg7<-L<#(v{~anLwq95#*^ zM~!2~apQz>(l}+DHqIDljdR9%~ z@z8i=JT{&fPmO2BbK`~a(s*UOHr^O-jd#X-9;Grk)M#t-AC z@yqya2Fx%s+)QL9Hj|i1&17bTncPfarZiKTsm(NIS~H!Q-ppWTG#L|^tjU?s}U2j2bcrRLFQm{h&j|8W)3$;m?OE;g5#OU-5Ga&v{b z(p+V(HrJSI&2{E_bA!3j++=Pxx0qYaZRU1!hq=?-W$rfjn0w8A=6>^ldC)v$9yX7d zN6lmAar1Sy)023P~FLDpbvh&9w2W(~JSSR<`b)@W;tHP#wuMOx#nC@b2U zV8vLm)chqcq%W$m{1SbME~)_&`Nbw(>56sLx@KLsZdf<1Th?vsj&;|%XWh3R zSP!j7)?@35_0)Q1J-1$1FRfSBYwL~m)_P~Xw?0@Otxwix>x=c(3R>~jH|x8VVEwRu zTEDE{cEAp^!|gFo@5Mw_vL&Dxv|ZQe#U zwgp?XiA`%6gk91uWtX8D8XV^3CS@vvujy>0&XV146*bD7N_F{X9z0_W2FSl3N zEA3VGYI}{n)?R0?w>Q`u?M?P(dyBo*-ezyNci21aUG{E!kG75KtMu%~L!#bP;9o|6> zb_7Rsh(jI8ksZZR9nH}l!!aGpu^q>89nZ<+WOlMRS)FW7b|;6E)5+!JcJerRoqSGy zr+`z?DdZG(ia14`Voq_Vgj3Qf<&<{HIAxu3PI;$-Q_-p9RCcO3Rh?>1b*F|?)2Zdu zcIr5FoqA4vr-9SZY2-9^nmA3JW=?abh11e$<+OI%IBlJFPJ5?=)6wbVbauKpU7c=D zcc+Kb)9K~(cKSGdoqkS#XMi)%8RQIhhB!l=Va{-8gfr3^<&1X5IAfi0PNXy5iE^Ty z2~La?>r8YeIg_0!&QxcbGu?@EW;ipQS-GQcQ!a1olVYWXN$Ad+2(9_b~rnoUCwT2kF(d==j?Y5I0v0W&SB?> zbJRKJ9CuDQC!JHyY3Gb{);Z^#cP=;=olDMT=ZbUHx#nDVZa6ocTh49gj&s+!=iGN5 zI1imi&SU3^^VE6fJa=9=FP&G;Yv+yg)_Lc=cRn~DolnkZ=Zo{z2|Dr4H|M*P;QVlY zI=`IXZomz5!`(z~VmFDK)J^6_xXIlVZb~D>%&MwfAc%etHkUEW15 zb_G{-iA!C{m0iVEUCq^9!!=#YwOz+`UC+(rW_Gi0@Ib~lHc)6M1PcJsJ--F$9- zw}4yFE#ww=r<(78KxMkgPZh5zYThXoLR(7knRo!ZCb+?9F)2-#! zcI&ux-Fj|)w}IQxZR9p~o48HgW^Qx0h1=3?<+gU)xNY5bZhNrQkhxs%-~?o@Z0JKc?QXSg%nS?+9ijyu<#=gxN*xC`Ay?qYX|yVPCgE_YYB zE8SJ@YIlvh)?MeWcQ?2j-A(RhcZ<8#-R5q0cep#>Om)c9?rS;Nz>AehIMvw7;$9kLxJ>Eke z_5@G#h(|rilRd>#JD*U{_bb@sY=UA=Bz zcdv)n)9dB+_WF2zy?$PQZ-6(@8{`f4hIm80Vcu|Wgg4R~<&E~ncw@bBUZgkPi}Iqq z30{mB>rM0~d6T^<-c)azH{FZ#W_UBbS>9}KjyKnv=gs#PcniHn-ePZwx71taE%#P< zE4@|TYHy9V)?4ST_cnMNy-lINrS{AJe**Er_==!uLRi%T^iQC&m?+2O|fJ?lxxN z*x@j0$dK_vaJ|aI``4rswoKR(vmuyzVi3lCnjLu+>OB)u4NgcuDrR}i;+Xjp;$r5+ z#^s5ILn8Z*8$ibO9@}kf=ZMH&y~g*#&2mnPZAYVvCK%ksJyEr&gj7>= zk%XyBpJaZH&mBJ;EO?Ywyp+W3)=005OEn0F1@jM}BX37OjXDvvWWtV^MG^6FT|uF) zFA^e-CDfgrP@2EJYEZC1$zYT0!DM`zG~b#9AAy9@357EyjO;{q7D*DEx*=F2m?qc( z1!d)Cf}9ZA>#)OsQl#^!cB8tEU7Q6jnzDTQipdePkG@_LOo~68t(uqq$Pr&13@#E( z+$Y$uPcVEWKmEEBmC#{cLfGQaErMsiEd_&%2UGV77VGtPI6v)5rilsF7A6E1^6^;` z)`12GhL7nzy8k%7=-qXhc12%CSJcTV!^_NGnV3|^ZT`%PN#I9S#3(^h;j?|^t*}oKb zWJseT!^`8kJ!h>SN{6l*yl43GL7RInX&EzoLcgeCk?S`G!#`|TGi}=9`E%kTLd)HG z7_=<2ar^e8hi+}4Q6-|wwm}_-^zTVN1;2q!Q9Gk{l1r1X#T|)@ya{XcFFL5i@ThH3 z8>1FQEsS0oJtrb((wP3y?fam9kxe7(ka1nRMfSvP+C)vNMWc%(8M9$)G1yx^coHd~)-EYzcvZ2~5Ybv}y0oBUE^q$gIR+qLcb?jd`*rX&Bu;yM5gVZawK+n%-opyF>@k<^AbdGA@7ZZ z;>-0L>tVZRxr5~^-3qDu#TW1ed;wp;7w`pq0bjru@CAGUU%(ge1$+Ttz!&fZd;wp; z7w`pq0bjru@CAGUU%(ge1$+Ttz!&fZd;wp;7x+IzAP^B2mWop{d%oluYhNkhkEf%>8S zW5W_B54Ep{>fi0KK<3cd-|g@~ny{q*v=ap?hB5!N6aU+sB!Qk`P5w<1)t2eJmT1#$+w|7_<9wTgxIt?d$M9%vP6*9cwJBQ(EN zpi?MHfpUS)ffk|B?xB2tj?MlWYZ)4`{>s}k)So|)CG_g^*DG^q#=o*<{_Dz4p)vcf zJN5~!rf29XDYQ>st5EhHgo&vW2eC8hYgn6bL}{zbrb3p7&p4nFD!4 zKaT>TXKfbf5X$#wPU}#fj-jm0LnE03xk5E}AV+A$Swr!Ef2DukM}Jr0&$}Yj{u5J# zV#7ej<+`QN`UZ28ygzkM!Jg{}?+D*km0 z{P}ETE&g{63x;CJziZgHP%Qm-4NC~cvVYgGpP^VjR4arwSpNOjDnp5Wj|e^O|5QRN zPt-M3|Jr@|f12R;`2xOxFW?LK0=~fijRK+X_IiKT9g183i7oz#jsJ-?Lt~BpwEf}> z_yWFwFW?LK0=|GR;0yQyzJM>_3-|)QfG^++_yWFwFW?LK0=|GR;0yQyzJM>_3-|)Q zfG^++_yWFwFW?LK0=|GR;0yQyzJM>_3-|)QfG^++_yWFwFW?LK0=|GR;0yQyzJM>_ z3-|)QfG^++_yWFwFW?LK0=|GR;0yQyzJM?AZvtWI0%4zjg?5QecK&zn-_4SZ3yuBR Lf%ZR3c=&$+wcj~v diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf index 010a824b72c0641c69845b8443db29cce772da85..9a0e72600fdc2690bda1549d74027c4d66c3fc2b 100644 GIT binary patch delta 543 zcmbPpg?&c{d%b^1h(7}lLjwadgM+i1o5KCcSC=s`FkE3^n7_h5Sl_6v+1H+d(O?Ns zEFsK4$epZCszDh=JNriL-Q!P+_3j;&{ncT#RxB}(R0YEv1GeFFimzbMssOcHPz-Y+Az`zty zkY8N#zm35NXrTg7UZD(R;C4#`2F4>IK)y;D*g(dwKzR?4feZ`*49cH@?qgtKVqj!s z6r0?@Bs%evjnR+${IU!T`T{(vKx)1-j|zyFCdj}IRK~!@z{hZt;RC~eMp;HH#wf-T z#%YZEHm5LdXPoT7%(gj^`IrtbFnFXv<}$J{2(nI2G4^0l{;d3Y^DX0-?wcJuzcX&G zY5%QS&%nmW$Rn<#YvKGufk$lu$gX~&ABs@s6rmqVJZgO)(V0R&l%dQyLO)b^)Fy&N z=L`K%g^Df}`c)(HO%z4|=^vj(e)5a{*e?Qf1<)moY!&7S-SPZ3Um2L0UjRiIE-v8` z=mRls%A2QcX4(9(fBH%vMkU72+t2tg?q*U1hA7Y%z)%BX5IYCR0~w_Pq`5%+?F;-F Mr%ssu^Cd_V0M3e$v;Y7A delta 3974 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 diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize-retain-gids.61,63,65,6B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize-retain-gids.61,63,65,6B.otf index 6ca195572a101f2b4d6494ab66b288ce74258253..513d47ee92217931165df3dfe662fc118831619a 100644 GIT binary patch delta 486 zcmcb!f%S}7y?;oEKLZa#0|PUIgR`5P!v55&Nem1OR~Q&rg#3f`jlvdfD_~$?s{o26 zg!u=#GZz9`44iL(1V?giVgX|_yB3gd0OZffNKH)P?do{|)cXR+H_HGDa9A^)0qPF{ z@>Mc&ODcG>850;7SQQu;7)^2$E8+?md;@@T3_wK;YfsfL=KK*ek~7#Nr$3i69f z{aR*3l^?x=3>-i;3~UU13^y4*F#KnfVYFjR+nmBE!Z>*v zlk8-EW}eAEnUp3wFtbU5Ol0(CW?%tY3N(#DkcmN>5onR`+|8s2as)FFs{k>G a9RuWnOi}^TTp<4T5LU*kjMFV6K$-xa#&Hh- literal 88156 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 ZcdU$m{&&{j4dRao-|^2bnE$hs{U3t+McM!W diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize-retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize-retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf index c6ba9b4947d5329eec48fd217da08ae887810234..b10526d713f8ed3db5f1bedd395c29b9966ee15a 100644 GIT binary patch delta 510 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 r7H3?JqLxF}oaT+*{GnDVkGZDLN!JWUJH diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize-retain-gids.660E.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize-retain-gids.660E.otf index 996dfc7fc4cf98f740fbc57ef671d02486cbc20e..2684381c9bc70e07c1f08c8218f3f197520c6afe 100644 GIT binary patch delta 508 zcmXX@F-#L-6#icCJR3PUI6ww%ILft&gE5u_jgqEm2_g)K(h%bSUT961(;5q56ZIg* z7-MrHP7ZGBP?HNelM)Hhk%0jQTy$`AF^1va@cp5~```Dz@4fdW@Ap4wVpVzM6pIdY zEJH!AFg9krPk2oLdqDoXGkqbm>Db-C6P39;GtSLx$^%AN8Q~{B@3~duU49?%H>F-F zyQTK$FMa`qw_Fcbn229B72q**uq$3|>EtdV)^~wyr{^xsRt;FbF z;-`@S%tJlJDL<#%oVq8v(8g`h(18Q|#Staw3f-m}y`isRi6RPeiWa)c$If;>&l$Ow zRCJvPN<-tS;TwMVW2mh^tgk&ag816XBs3zuFM0lQL0EeFm9+X~ih&mVY>K3weks`v zQw+A?7gN}Jx-QwKDN-$VJIFQq46)V2mTXJf@80lFP;K<62mP1shR+(Q?D`FhlH^A< ii<+?k`9FMT*c=j%awSJ?&ZlG@jStd7cHMm~hyDYej(Jl6 delta 21756 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 Kdc)mu_5T6sNg^1S?Jf3MiBTML4#L z+A%P2odNPy%5qC8Sbi`T0{MFuo?w$fIMa(RsmuVI|ayN1oN30xIp|#TrU8Vh9t}Y delta 140 zcmew$`a*Pqx$GJS1_qAg+{A)}-6by>7&xB*`71I~6H|CCdaEaf1S|Fc1r*AFA{^UA z?HCxijsW>8Ww|94EI$|vf&48CPq4`_R&BZx&u{aUftmRQP@du95`jJtedDYJL^KpqIo07*tD%>|@mCUbDT003>_BhCN- diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize.3042,3044,3046,73E0,5EA6,8F38.otf index d2012df6bc68c17e0f7dc12fd07b533182b899d7..b900d92a84f8792705a49110108ee2b2085d91e0 100644 GIT binary patch delta 134 zcmca0c0+7}xvUHW0|Q5LZel@(aN$`71}+OA|42q^VhV3p&x45}!HR!?0t#h75svMm zb_@*MCP2PQS#C)M%LPVWAYWzUi4ZoH(1WVplNH!SSZ>Ojr){=iXJ%Gp0V-q$DF$K? TI|s;P1oN30xIp~LAzXg|6%-vt delta 126 zcmca1c0p`{xvU5S0|Q5LZel@(aG?tW1D6Gmzb7L#F@@Knw|Zhou;Le>fI=Bigk!s? z9RmZm4v?=>mRnN6a)FT-$d}o8B7}`4ELGKivI4sZ%Z;-ZjGHaknVBV-feJxb21qhO NX)Yk0GC79p4*;tF8%O{E diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize.61,63,65,6B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize.61,63,65,6B.otf index 6a35208fad7547860fae9169989bbb60538326d6..6b7cc2efe0d29ed902e084606e3976d0f612b03b 100644 GIT binary patch delta 149 zcmaFE|Al{ox$GVW1_qAg+{6Ng|E!Z37}$YahB+Cji7C8YJr5>^1S`$~3MiBTML4#L z+5r_@0PmJ843NhN<})*Jf%ubU*e?J85hWus delta 141 zcmeyu|Av2px$G7O1_qAg+{6Ng|E!V>4D3KI!<3BF#1vkO-s*`V!HQFW0t#h75svMm zc0dIufP9s*+>#2mJjUrj{+^8|B$#EcOlo=)&u{aUftmRQ$cT$e1o}Yqjk6YvoBuGg YGfOf9c_1tUBpIPJ7myB_tipZ)0G5d&GXMYp diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize.660E,6975,73E0,5EA6,8F38,6E05.otf index 39b88d5df0f1ad74ccfed805c4aad6c3ae817fbe..69b6b2e7492b052af1d95543c5eb4df66bad1001 100644 GIT binary patch delta 149 zcmbOtK1Y0lxoiRh0|Q5LZel^#l~5-J2Cf<)|42q^VhV3p&x45}!HNz*0fjQ42*-9& zI|c^s3LsylEVrbBC7WRlke{*f#0)l>s4bFw@%%Pl8JL-002MG?Tq4j1qHoHZr){ob gXJ%Gp0rHrESOthd>>MDE5zJ?1-~#a{&*1t40C77Z`Tzg` delta 141 zcmbOuK1F=m<%ncz&C&49v_gfC?BcE)nPh(KpUoFmA44 ZXJ(dU2J%2y21qhOX)Yk0GI;^l9{@ubAo~CS diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize.660E.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-desubroutinize.660E.otf index 754e35ea2cffc8d2c03538550e8ff946618bcf9a..460baced3ba1c226da4896e9ad915ec087fe5515 100644 GIT binary patch delta 133 zcmeC-o5DB2T=oG20|Q5LZejt0jBzjn16u-+pOBH7n8MrD^I&2~u;KxrfI=Bigk!s? z9Z2+K`*^R&$w%)glwS%8wvAhkdYV!Hr& Qj9@-90~d%txrS{50MMu%XaE2J delta 125 zcmbQj*TXl#T=oV70|Q5LZejt0jL|0s2DStsKO!SFF@@Knw|Zhou;LD&fI=Bigk!s? z9Z!A}lw~S}<PY diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-retain-gids.3042,3044,3046,3048,304A,304B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-retain-gids.3042,3044,3046,3048,304A,304B.otf index 92ba11f6b6c19cc1f65b82e697c6285f161f1ad3..ecdd5d64a95004a2a762732b255a55b023a1ef47 100644 GIT binary patch delta 514 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 diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-retain-gids.3042,3044,3046,73E0,5EA6,8F38.otf index 201557e74643d74eff42cc768992d19d57877898..77b1f95a3cdd050ce33375034b50d66cc62091f4 100644 GIT binary patch delta 526 zcmexyg?&aRd%b^1h(7}lLjwadgM+i1o5GF-C2R}~3|AN!7O?pT>l?K-``R-w8nOVz z62kn0+?fl3EJl+BK$0UlH?g28{_Q~qM&ms|{*jE-#1!7Ho(Dj^cYu7e44?pqwOSDa zqXAHiK_w%%q(VA^sg{9Zp$G#*|C!vxins#h&jCO=hBH9SmY0~DYN+WM0<42(xgfP9rQuz`$Uf$}Rr1~M=NFerZpx{rZ{iGh)k zQEYMpljy`xwuTb?vJ4FRo;<2RYF-163WzsfkbxVhih+%RkKrc62ZsNQvW!-YQH&*w z(-`+{PGQ{6IN5=jZF3^?e;r<6=tzT%Wn^IxWSus+v-0Q7!X_`>H!tk?&bWDN z`+pU01~x`U9&sgI3+EpSJZcj_cAXLWp$KJO6#AhAWnL5dp$uWp=Mws%!lO13sCNEe zp&zO|YJEWF0_M#>Hd-)h{@4!;C!n=J%*b|3PJV4Xzs*+$X66?_5r&IP1o}YqO?mUQ z%?X>MBuWRePy<^u7z|M6#>I$?U~E087t D{pN=W delta 3952 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 J2F3sG_#b;-_U-@x diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-retain-gids.61,63,65,6B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints-retain-gids.61,63,65,6B.otf index e6bc2aef4defbf5fc50410898edc49309604e1d9..8a1bc968a936955b32960f6d453ab0200c8addad 100644 GIT binary patch delta 560 zcmWkpQAkr^6h7zw@2+=xb#87m)8#g=OKoMY>8hzMg^Adh)mkf}yrg3gt5qUC3>uUY zQqs7fFTEst@GV1V4?WaFkG%x-AVl;OK@h%FcM{n7AI|@O-#O>|&N+`>St{-a$y6!{ zDwKdjY&;(K4t|YJ0Kg{z{xf;8Ka}2hT>y}$DL0c&UYOu_34!%JJ<83zUciTSeZ&>w z&vSG7Y~#w4ZvfIe;zKz~C{gx-^g-fUEx#UJBVFcGn^{)7Yxh*m+^~Z}Js?99?7%MUV+W36c6%0`Xsj`hVdJV%V}2vXWkct! zSp=NoAc?t%U}w;dG%A6}xMY#*6l;Bh+Sp`kwmVv!E_dsJwu9{*o4sK22`VvDwCaRkZ-!PvzhEr%10$(F0oM<@I3tlZ+@H4LK86o-)kH>s? literal 88196 zcmagFWq4Le5T;!%#}#)7?(XivErH+?NU%T>lHeBHJ-EBOySwYaU;~5O013{(KC}D% z+H3dQA2&}`bsuY~?sLN1sA|%c)Dcd;CiHzOLyo!{bre1Io68Bu~}?C`A3R z@W`;jQ858gD2WN^6xBO2E~Z;}Y@z?}{Ak~R{~8!K^FJH-e+&OF_kZhzf;GBDcIg-z z7yExMtrZ>_9@DMU|G5w?8Pz2wG`j2m<=}duk)i+RBOAv=p;_a)MMZ}8_o+9MGJ0ZcC<|KRYCE1r`){jbG?xnK6WLK^K251EDNv)N-7~V}V zlto!cin4~dvXKsGmC4h#ldBgYH}41%c_$FhJC!K!3}Sf~fF)oBSckHm&^;*IM|$2< z&~v2aeF*&<@kAW=oz#2=@q8&kW}VbwN^0h^*1Ii-c_XF{;r;^OK6C5Qi z-#L`uM*J_tpTT|y8`Co17x+Jk@-q_oZDks zH1rbb1@1u~gXgIC3X111@QFl$AEXqN#0nZj1#OZAQ@~FT8*N+=ZBQ@|@q$HBULIN< z)IkhwUND5rf<53Pp%#q8F{2Qh2&RGgIL}J3g|vbPQ0F{iNNffFB(>l(*dK@$;zWg1 z;)N{ODM=|506zyP0KX(C2fG5a3KZ8Zgtjl#2sDS^8nh!>s0)sZL0KQf2Lg<*LUW;u zp(_B!RiQ2L_oDtGaGKOYR}i~{*hA z2Os@j7=2zC?OnJF%A!aq+z0hXBQ_o}^mpM^U=94OIA#yZ4g$1);j7>l_zS#7>=W5V zutXFwi5GE+6-fq73o?;fBoFyTDv&IKYZt-u7HLLKk!aM7h1~~nEJa1eqV6QrT}`6M z2E_1uMGm3-C}J02Uj`51{{s?X|4Y0m+PkO(xNcF0MA4Mcbi|5c2`HK!nj3ZU!!8JL z?V^FG(+IH;&>DVw_+3#JNlMY)um`{%3Y`I6ggSWkqHEx90eevY1pG7LI`{*}yhNS% zus>n}!W=7>8k&xHvFxBQ{NkVjsl|{_iZwzR=2)>-B#U*1-yQyR=qxZFEJb_`VtDpq zXGtk`g|uR5+hR}2DE8m^lZY3`I$AspiQ*W?#Y@1({3%`oit`r_LU~^>72ur3H$ZXU z#W7Bc-$K1V;XeQvtHqIfO6bH&pp8o4JS8v}OH?9J0^^}X3)rnu9s?h9y~IMW3>*We z5WfPwgEE|}q(W3uCsERe;`vKrj+M*@EeMLC966?BHGuI}vH=v&U$PCfBg#ADIE;ak zgTN@*lcAVrCD9fo7lYOC*FrJwO74OlBDLfnh}{ME;Xfu;3jJQnB3>#LGz~!hEL9qm zBc)U=_zeM`sZ>|g=?(1QWzI ze}?`bR$2h$mC`ARm(EB^>739)@Jo^?T?00ru{7GRbVo8uW1CjG55P4`j|9^Z$Ms61 zJxgx_7r=G!CwPc5 zC&{uZ8D&$ED4QM>AYQfzv9cwgxPIA+u&V-$zp@QTDT`+=i*_#Ci>$IEq4U5}uofH! zXxp+E!FBLANCMx9m*XH6$OJHN$`vN1Tp55hp_Q@dflfK)Y8&n^ZE0Rq{Xz*l9_vl$Df9dEsLXsZ^G{O7)

^3D*Yl}8M(8v26ahP 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 AkpKVy delta 3959 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 delta 21755 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 M+52C;{o%;^f7$Cf;{X5v diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints.3042,3044,3046,3048,304A,304B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints.3042,3044,3046,3048,304A,304B.otf index 9756068614a84d0ec013f815dcaec6d76f81eae4..19c8ed86e97c6fa313d2feb5a35565915547ec4d 100644 GIT binary patch delta 148 zcmZ1=wnA)zx$GMT1_qAg+{A)}-KAL!3|ulm{)UXy#1!7Ho(B^{f)&pI1r*AFA{^UA z?HCxiS%7?%vfPpimLH6TKn-6up0H$-wmp~{&u{aUftmRQP@du95`jJteN)~%ZLwm@uxx$F}L1_qAg+{A)}-6by>7`SAB{1q9gi7C7mz10&#f)$Sd1r*AFA{^UA z?SKmY0Qo9qxg`}WKNt&v{5KmLy0N8#bUjP6A delta 141 zcmdlYzD9h4xoiOg0|Q5LZel@(aG?tW1J@KFe@{kgVhXQCZ}r5GV8sBSfI=Bigk!s? z9RmY*2avB)mRnN6a)FT-$gkLVVgs8D-<+qG@%%Pl8JL-002MG?Tq4j1qHmnFVB9=~ ZotasZ8OQ@+86e3BrMZA~%H$nfe*h+KAz=Uj diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints.61,63,65,6B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints.61,63,65,6B.otf index d6cad34dc6c76a25871334703088e9acb0f856c1..abac3dd75a073de79bab2eec652ee00cc496f215 100644 GIT binary patch delta 149 zcmeAXm?AL2T=otF0|Q5LZejt$f7VG14D1R({+x`|#1!7Ho(B^{f))1w1r*AFA{^UA z?SKkC0Qo9qxg`~Bd5qJ6{3jbvSTM_+nX__tJipCX24?0LKm`mJmk9KM=$rE9X`5wO f*qIesfIMa(RsmuVI|j&O1oN30xIp~LHtZJw?h+#P delta 141 zcmbOt&?7LxT=ohB0|Q5LZejt$e^yBb26hD?e@aGbVhXQCZ}r5GV8ty!0fjQ42*-9& zJD`FWK)y;@Zb=1O9^-T%|IWq}7R)kd9ahed=ePOFz|0I%z;JPiKp%*{an^!yvkVJ6 Xvm`T+2f{Kyk`YRC0qKy*F6>MDE5zJ?1-~#a{Cvg7(0Br3cp#T5? delta 141 zcmaDNaYtf;xvT;M0|Q5LZel^#m5`kb4BRe2{+^7~#1vkO-s*`V!HPgWgF+clgk!s? z9RmZ81(2^&mRnN6lFhIN$k*6-B7t3Ik-YfTcz&C&49v_gKsqii5$FTaH_loxZg$~d YW|m|I@<3PyNHRicE+CyUIfMHT06*Fwq5uE@ diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints.660E.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.drop-hints.660E.otf index 9a83a106dc43bfe6b5fee4e60563225f99a9d644..e586904fea43f1fce612abb9db9d33050a0b3304 100644 GIT binary patch delta 148 zcmZ3$w}Nkix$GAP1_qAg+{6L~8RK9E2DTC)KOrMEF@?9Q=fT8~V8tsy0fjQ42*-9& zI|c@J79d}xEVrbB1;_(x__OiEOeSfy)$`){ZN4%vGrs_dUR)y32cmDvo2PBAVgAje c2-3z3#411xV!Hr&j9@-90~d%tc>>!60QBP_1ONa4 delta 140 zcmZ3%w}5Ygx$GMT1_qAg+{6L~8KX}O3~VJpenduUVhXQCZ}r5GV8t^)0fjQ42*-9& zJD`F;K)y;@Zb=0TkO$;{*?3|mlk}<8LGk=HUm2L0Uw}j}E)nPh(KpUoFmA44{>>!G V4CH~Z43K1m(p*5=X7UWS2>@M#A_D*b diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.retain-gids.3042,3044,3046,3048,304A,304B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.retain-gids.3042,3044,3046,3048,304A,304B.otf index b2d477467c9185db3f6bed5e2717d57d649153fe..75f16131097863825a54b2b4d9bbc1924d3408ec 100644 GIT binary patch delta 547 zcmXX?O=uHQ5dLO&vxdz}(yplsYB5bW3xZPGLR+drr5G(eq{L8)_!pX%99&H?l;FVx zixowLvc>AHq8HIaVGAjU3VQIOhkyrrC=@N?(TjF-s`J3Zd-HuW@B7}&tbPh@WNO)b zJ_~_5RE&&fGD+*>&MyF8f!KKVd{5uvou4_ts&nq@WHxtJonwSUVZOrCZlOH;e4!6G zIK+IdG*c)>A3WR!;z{NMB~FA-Xf@VfWNw$-O4a(H>~MXG<%(OVUM?#%!8Ls5qhBw$ zGrdR0@+{Z}l&SKKo0Yvq$PZ*w$$4qmuucKp3Fh{^H2k92+)$e|1SX&mK+qHr(E+cn zbc7@tTiP8w7JQGl_K9>SU|bV+>r6W${0ur`*u-z_Q6~-41**_vdgm9ZLEea}dj+*8 zYN*&RZAn9W$aDL9RZ__R(I3+M)Ax7DzkBa3jYB6AR_gfBXpj`nEBVca8FUHfrG($i zAoU;qHG^*9JmYL6VFtEvUNek!m_b@Ns}c_Q)wP;BeEUgj?y251wj#}CA+|gb4c_zI zJRpyxFD=xUuf$LOfvU>op!uThk&K&1250@^dV<%HTS*y|CN$0&^hW8@xT^BueL>

%D}Q9!`J#O}uK?(XjH*2ng-TfnY!J?Ffi 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 GND}}dwu!0$ delta 4013 zcmYLMby!qg_dUbV3<&=uPVDY36kBYu6_`P>;M@Fu z-}8Kbth?4;JI>s5=gxEHVYtVe2Ojn&Em|~DHZ?(6Rn;1`YX|sy6q%)zid8B)wn_7% zA=4%|s-i577mL@WRg=&<)FK*yq5Boc9x-*rIurs*Ot`iE|xc(mxn;;j-LsazvA zh<+yC8^Kp)iF8w*k^agWnP1o_m&lTWa>^|-RJfg>yI`hZzVe7%DZEY)EjX`Sj;vGa z$VO#(dsKP8J#Sa)?Pb9=!3{x-a(nwwl5wIxs_gMrX)R+jh@f-1`A zQzm6e2v;gW_9$VsAWEsk9Lk!QS6LDRLU)aUU*chsA0ZeeJ!2)FD3~t!aAiwcDPE-HqLhz4X{VTbC5V>BW0E*2 zh36!`APe4d31+9dcI=QZ9}n;uRN`yK_`jnH-IUTPQb2 z2l2Xy?y0PfzM=<8y*ygSQ049zD?JmGk7JIqyEzt1QG^&#!keUEt6;mty99fc&2dWj zoD8@mzC0$!4H4wE>*cWtx7rFmBr~L+E=+cvnV%bZb6{< zg#=ppI!jBwoIHPL1re2nt17FrmJ~Ho8JwMzyHmE(*Z4K9$8kDIaHw@<^`XqHM{TMC4Q| zIk!OGs_*{F@4I}uRN1D~Ny;sCu4 z3EJu!v`Yn@bP0N84N7p)*WL7Ur9XH;6$RBipr(Ra9&p+US3MvWVxxx@`%uTOC+jJC zs-C8&>lu2co~6U}Y&}QM)${axy+AM2i}Yf>L@(9L^m4sIuhgq_gpSm!^%@P>pH-lDhaZF;-jp?B(Cdbi%A_v(E*TJP5f^g(?{AJ#|oQGHAw*C+HzeM+C! zXSDsSKBv#?3;LqIq%Z3$`l`OBuj?E7roN?b>ll4U-_^1Dp1!Xi=!g1|eypG9r#enQ z)6ew_{ZhZuuk{=KR>$ji`n~?3Kk85Vv;LyL>TfzhC+Z~a&`zDKzv~}5MgP>l^l$w~ z|JA8F4HQ`H-~v`~1vhX95AXyp@CF~SfiGl$jF1U3gCF=q7RUz zDzu;rTG18V&>cO{6TQ$Ieb9!!m;p0lCd`a}=#N=2D`vy&m;-ZSF3gR2FfZoA{1|`* zFc1r35EjB<)Ch=3$Y`)I7Qv!e42xq3mcWu&3QJ=dEQ{r^JXXMpSP3hmy$V*vYFHg> zU`?!rwXqJ?#d=sD8(>3hgpIKYHpONbip{YFw!~K08rxu7Y=`Z!19rqt*crQE7O z*d2RdPy7da;lJ1$`(R(}hy8H?4#Yt?7>D3c9EQVj1dhZ}I2y;`SR9Ar?P$jdI1wk| zWSoLiaT-p?88{PXVK~mlIXD;R;e1?x3vm%H#wEBEm*H|;fh%zpMqnha#x)p)YjGW} z#|^j9bZFXI)wir4Tu-oTr93vXi#-od*Vi}&z8KEQ|g2p{7Ue2Q`S44>l*e2K5{ zHNL^O7?1DpJ$}HC_z6Gb7yOFfFaZ-W2_5LfWc-dlFa>|&FZ_*v@UIi$c3!r zN^ay%9^^@0b9QFh8fIVl(AraY9F@=<;YpaK*~1u2LM zQ7~x&LLy=^RG5lTQ7T5oDTGQ;Nh(F9sSK5+a#WrwP(`v=qRLc-s!}zoPBo||)uP%| zhw4&2s!t85AvL1L)P$N+GYX~V)Ph=4D{4(`s4cal_SAtoQYY$6T_}vYQa9>OJ*X%B zL%rx<>P>y9FZHATG=K)uAR0_VXebS%;WUCq(kL2DV`!|M#?g4P(*&AGlV~zcp{X>D zrqc|XNwX-NX44#+OY>+xEue+8h!)clT1v}kIjx|Tw2C4ql2+3iilVi&j@Hu#+DMyd zGi{-*w2ijY4%$h(XgBSly|j;_X+IsHgLH@v(-AsK$H;!1PS8m@MW^WuouzYho-WWu zx@%{SM-|R&|8Y9 zcl4e<&`0`2pXm#IrEio#iIhYRa#AvVryrC;Kj|0!w$mT_OR1E`iY@HIR(54Kc4rUv zWH0t+AGWbCXW)#Si8Hew`*Rk~%Go$O=ir>2i*s`x&dd2YKL>CD4&;Iy#DzGRH3K6P zGaD|{0cO}v@6@K)Z& z+j$4?5AZ=g#E1C^+mG@wKF%ljB%k8be1^~RIX=%9_#$88%Y22e z@-@EBH~1#s;@cdY}ipK=^OU-Bz{&2RWE$MZXW&mZ_B zf8x*lg}?GQPT)jNVh1}pnZNT7PT`++{>8uf5C7#l;G&RjksA+Cmn3krMX>Hn=wx*qFZ#tNcrjzMxx|lH2)pUz)Hs*&V zy5;Cug`z{pymalRJS`Sm_Q1krYcy_~5?~A7E+@>rd;C%g*n+pF%iDe_f&X>C`lS@K z1+Nu%UnRekAY1Sbk>$&6o zz-P8C^RKa4*O$^8HCIB+4o<3B6sAx;1Q diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.retain-gids.61,63,65,6B.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.retain-gids.61,63,65,6B.otf index c0a3c3427fea7d9de24c2eaab47692285d9cb913..7c5f648c399b45c0a34087320f9b0d47244f0a0a 100644 GIT binary patch delta 580 zcmWkpUuaTc6hG&F*XzH}Ii1c*-PGN=Tz{6fW^1|u-^3ZfB020he6PZ5Do4}%6h_PCem`n1k{IN$gCo!>dXbIwX#_r>)fl}@LC z!y+(W7)FF|)K39&p*Xj|Zz5^B8UPL!GYeNrkUU2kXa&;kOfeS@ zO{M|#loV!4cka&ZEJzKF%zIlEE~^_hFi;Ih&<0zu1H0(KQOwt~=s@MU;8m=QD=i_Q#F?aI zm@AKfXBmhzmi)jbfE#I45>a5HPSP8UCNsCRS=(*)4u`YTwP)`>x5wMn?ehnE(NvI7^2bU zQGGo4y7k7c`g!ne>#JQ2@ZdV#E8ep!vCXb}b#n}d@7G%87gE!-ZEmh`zO8VJ`pH4J zX`4#ra$o4GHTD-6`=c%2eA)g~`?tEI`FiZ#B(6SV7{FxX1H+GkUptUd$P^mBOiXi< S={IS-QI+r~u9h!pP5%KZHG)q7 literal 88468 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 diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.retain-gids.660E,6975,73E0,5EA6,8F38,6E05.otf index 589cfdaf1d5979bd2041e45748a81406f97cc296..2dcd75b77f479c85e1b72a02328c65ce8bc3cb18 100644 GIT binary patch delta 528 zcmZp;#r~z2z1}}0#GiqOp@D&!!NJ+hP2n1|-ysGDhARvVi<13=^^LYX_qAnUG)@4D zC4~70xic36S&U|XfFwt9ZeqdSEn-K3d0|ti07C^pP22g;*TCE7E z-v-E6$;d6Kkd9!i1IiaLF!Z0vO{|D3Q2rbMlw&vp#B6zqxv7Slo*_UD2N)QbA`0@0 zOa8Yp7y&J~1C&=N0~xs8(tv^S*aaY8r3_-AJ_DmU3&=nQh5!cT&p`JvurM(&GBS!y zZeS9f_{r8#j9-?4LEoK66-X`M;86kb<_a=!1647wG4L_mWca}FpHY_4iZP0@gmD_< zzRf9&+ZiW2Ftcq=Wd5te3k)4;kg<#`41%naXB&I4D1TP|yjjrXrTgZI^S^R!-Z-IK z)|-Kik&#DSN!P;phXRk`Z9 zuvLWRro4ID<`-KZ_D}EiXH;VRynTZ|<8CHJV2}Xa4GbnA2C;L1JdjouAk78hZ*K`= MoH}9p-8Udj00Sb7>i_@% delta 3999 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 bQ?6-q(%471%f7P3t@*S5TM~aJZOQ)tCn6!2 diff --git a/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.retain-gids.660E.otf b/test/subset/data/expected/cff-japanese/SourceHanSans-Regular_subset.retain-gids.660E.otf index e7be927a2bda60f7623250c76bdf18fa06901e63..a5d40d0004db94a2083960a20987b43b3e6af4a7 100644 GIT binary patch delta 543 zcmXX@OK1~O6g@W+$I!eu>D13cOOrSma3N|6Dkg-|#QIxI(O60abug7Ij3yXs1<_*1 zT0{ymja3kJA&9Y{FpDe{MW{Q$2I`_h(4|Z910yc#edyx8d(J)Yp8Gz2LtU6wu3CkH z1%U}D=*tZZ#M+HxvjCQW+>CW(Tk4f%bOF~Exps2MI=oM*GQw1dm(Z!QUC|!&e*~^i zOT9E|7b7=seF5@C<~vJV2&Hv}`{$V(rE+b2^&*ZrVd5RHHle+AC6%+&)G1Y^4#6 z@bhexz7#~~D!16XKd3pH<9+H4_juL%q~?a|_93W5VnbrM4+a+;+$y$r;IEb&*s;E*`a VOgb5yJ0x#r47!k=J6e}be*uvOgkJyv delta 21801 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 RlwBn*W@w*x_OSRA`+tXoKv)0( diff --git a/test/subset/data/fonts/SourceHanSans-Regular_subset.otf b/test/subset/data/fonts/SourceHanSans-Regular_subset.otf index 7b3cb1cea1ed302ac39e6b1aa4f9278303ddd34f..06af9b320ae4a797fbd78b755ce8f2f7c8656e9a 100644 GIT binary patch delta 368 zcmWm5J4-@g7{Kx8^_nq1_ukZ&8fyrG8tftzh)YX|76u9pB2i;eU=j)q&SIay z!L9F5wA9ql(9qygi%b7A{CM8~!}B)UPpXB6KiZM_W;=CwklB{EfFue#BK5sgCcCwN zU;2>KI64X`@ltpe1O;)c! z$XC%2L_}jWG&Hny0hhl2;d2hZ!#Sr`zf)J5CwwijnRHHAYqOZ&`?-1h6)_#6Li^iW`GPBTaab)yZ0mp3+SI}kYoRi8N7FMY ziPi==S}v9j8nM7T`9vgpCW@(2_Tt3KbIv{eEry}r%j2zesr$=AN;NFivUv@X=A-H( z-JK#k_s2=|G-)c>U_j?K*wGFLI^aYny5K@L+_2DtUi6_K0~mw{L-1l4Bk;kG0D=f1 Tj0i>%#Ta6UBhgHn Date: Sat, 15 Jun 2019 21:38:27 -0400 Subject: [PATCH 002/138] Canonically reorder U+0C55 and U+0C56 --- src/hb-unicode.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh index 80624c0ec..021fa461d 100644 --- a/src/hb-unicode.hh +++ b/src/hb-unicode.hh @@ -326,11 +326,11 @@ DECLARE_NULL_INSTANCE (hb_unicode_funcs_t); * * Modify Telugu length marks (ccc=84, ccc=91). * These are the only matras in the main Indic scripts range that have - * a non-zero ccc. That makes them reorder with the Halant that is - * ccc=9. Just zero them, we don't need them in our Indic shaper. + * a non-zero ccc. That makes them reorder with the Halant (ccc=9). + * Assign 5 and 6, which are otherwise unassigned. */ -#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */ -#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */ +#define HB_MODIFIED_COMBINING_CLASS_CCC84 5 /* length mark */ +#define HB_MODIFIED_COMBINING_CLASS_CCC91 6 /* ai length mark */ /* Thai * From 2682efb02df72fb254c819cb76fc23592c30fc45 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 13:38:08 -0700 Subject: [PATCH 003/138] Revert "Deprecate font kern API" This reverts commit d219f899f4b2fb4b39ebc1dff9fb648fc5d6d112. API change: Un-deprecate font kern API. Part of https://github.com/harfbuzz/harfbuzz/issues/1682 We should document that this API is only necessary to hook up non-OpenType kerning. hb-ot-font will continue to NOT implement them. --- docs/harfbuzz-sections.txt | 16 +++++------ src/hb-deprecated.h | 54 -------------------------------------- src/hb-font.cc | 3 --- src/hb-font.h | 51 +++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 65 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index f97902f7f..2f34b6a85 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -195,14 +195,6 @@ HB_UNICODE_MAX_DECOMPOSITION_LEN hb_unicode_decompose_compatibility_func_t hb_unicode_decompose_compatibility hb_unicode_funcs_set_decompose_compatibility_func -hb_font_funcs_set_glyph_h_kerning_func -hb_font_funcs_set_glyph_v_kerning_func -hb_font_get_glyph_h_kerning -hb_font_get_glyph_h_kerning_func_t -hb_font_get_glyph_kerning_for_direction -hb_font_get_glyph_kerning_func_t -hb_font_get_glyph_v_kerning -hb_font_get_glyph_v_kerning_func_t

@@ -271,10 +263,12 @@ hb_font_funcs_set_glyph_extents_func hb_font_funcs_set_glyph_from_name_func hb_font_funcs_set_glyph_h_advance_func hb_font_funcs_set_glyph_h_advances_func +hb_font_funcs_set_glyph_h_kerning_func hb_font_funcs_set_glyph_h_origin_func hb_font_funcs_set_glyph_name_func hb_font_funcs_set_glyph_v_advance_func hb_font_funcs_set_glyph_v_advances_func +hb_font_funcs_set_glyph_v_kerning_func hb_font_funcs_set_glyph_v_origin_func hb_font_funcs_set_nominal_glyph_func hb_font_funcs_set_nominal_glyphs_func @@ -300,8 +294,12 @@ hb_font_get_glyph_h_advance hb_font_get_glyph_h_advance_func_t hb_font_get_glyph_h_advances hb_font_get_glyph_h_advances_func_t +hb_font_get_glyph_h_kerning +hb_font_get_glyph_h_kerning_func_t hb_font_get_glyph_h_origin hb_font_get_glyph_h_origin_func_t +hb_font_get_glyph_kerning_for_direction +hb_font_get_glyph_kerning_func_t hb_font_get_glyph_name hb_font_get_glyph_name_func_t hb_font_get_glyph_origin_for_direction @@ -310,6 +308,8 @@ hb_font_get_glyph_v_advance hb_font_get_glyph_v_advance_func_t hb_font_get_glyph_v_advances hb_font_get_glyph_v_advances_func_t +hb_font_get_glyph_v_kerning +hb_font_get_glyph_v_kerning_func_t hb_font_get_glyph_v_origin hb_font_get_glyph_v_origin_func_t hb_font_get_nominal_glyph diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h index 026a62c74..47de70a2b 100644 --- a/src/hb-deprecated.h +++ b/src/hb-deprecated.h @@ -165,60 +165,6 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, hb_codepoint_t *decomposed); -typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data, - hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, - void *user_data); -typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t; -typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t; - -/** - * hb_font_funcs_set_glyph_h_kerning_func: - * @ffuncs: font functions. - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: - * - * - * - * Since: 0.9.2 - * Deprecated: 2.0.0 - **/ -HB_EXTERN void -hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_h_kerning_func_t func, - void *user_data, hb_destroy_func_t destroy); - -/** - * hb_font_funcs_set_glyph_v_kerning_func: - * @ffuncs: font functions. - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: - * - * - * - * Since: 0.9.2 - * Deprecated: 2.0.0 - **/ -HB_EXTERN void -hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_v_kerning_func_t func, - void *user_data, hb_destroy_func_t destroy); - -HB_EXTERN hb_position_t -hb_font_get_glyph_h_kerning (hb_font_t *font, - hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); -HB_EXTERN hb_position_t -hb_font_get_glyph_v_kerning (hb_font_t *font, - hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); - -HB_EXTERN void -hb_font_get_glyph_kerning_for_direction (hb_font_t *font, - hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, - hb_direction_t direction, - hb_position_t *x, hb_position_t *y); - - #endif HB_END_DECLS diff --git a/src/hb-font.cc b/src/hb-font.cc index 19ee353eb..d7b2a7ae6 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -939,7 +939,6 @@ hb_font_get_glyph_v_origin (hb_font_t *font, * Return value: * * Since: 0.9.2 - * Deprecated: 2.0.0 **/ hb_position_t hb_font_get_glyph_h_kerning (hb_font_t *font, @@ -959,7 +958,6 @@ hb_font_get_glyph_h_kerning (hb_font_t *font, * Return value: * * Since: 0.9.2 - * Deprecated: 2.0.0 **/ hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, @@ -1190,7 +1188,6 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, * * * Since: 0.9.2 - * Deprecated: 2.0.0 **/ void hb_font_get_glyph_kerning_for_direction (hb_font_t *font, diff --git a/src/hb-font.h b/src/hb-font.h index e2086d818..40dfc41d2 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -157,6 +157,12 @@ typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *fon typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t; typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t; +typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, + void *user_data); +typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t; +typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t; + typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t glyph, @@ -356,6 +362,38 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_origin_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_glyph_h_kerning_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +HB_EXTERN void +hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_h_kerning_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_glyph_v_kerning_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + **/ +HB_EXTERN void +hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_kerning_func_t func, + void *user_data, hb_destroy_func_t destroy); + /** * hb_font_funcs_set_glyph_extents_func: * @ffuncs: font functions. @@ -469,6 +507,13 @@ hb_font_get_glyph_v_origin (hb_font_t *font, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y); +HB_EXTERN hb_position_t +hb_font_get_glyph_h_kerning (hb_font_t *font, + hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); +HB_EXTERN hb_position_t +hb_font_get_glyph_v_kerning (hb_font_t *font, + hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); + HB_EXTERN hb_bool_t hb_font_get_glyph_extents (hb_font_t *font, hb_codepoint_t glyph, @@ -531,6 +576,12 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, hb_direction_t direction, hb_position_t *x, hb_position_t *y); +HB_EXTERN void +hb_font_get_glyph_kerning_for_direction (hb_font_t *font, + hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, + hb_direction_t direction, + hb_position_t *x, hb_position_t *y); + HB_EXTERN hb_bool_t hb_font_get_glyph_extents_for_origin (hb_font_t *font, hb_codepoint_t glyph, From 896416bd4c6ac486eb4e1926eaa09d5a9b693763 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 13:39:49 -0700 Subject: [PATCH 004/138] Partially revert "[ft/ot] Remove implementation of deprecated kerning funcs" This reverts commit 47030b1855f04c0d75899ffb6f5021fea3c19b90. Reverts only the hb-ft part, to reinstate non-OpenType kerning with FreeType. Fixes https://github.com/harfbuzz/harfbuzz/issues/1682 --- src/hb-ft.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index d70c38a7a..c24a0e268 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -346,6 +346,23 @@ hb_ft_get_glyph_v_origin (hb_font_t *font, return true; } +static hb_position_t +hb_ft_get_glyph_h_kerning (hb_font_t *font, + void *font_data, + hb_codepoint_t left_glyph, + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) +{ + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Vector kerningv; + + FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED; + if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv)) + return 0; + + return kerningv.x; +} + static hb_bool_t hb_ft_get_glyph_extents (hb_font_t *font, void *font_data, @@ -497,6 +514,8 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t Date: Mon, 17 Jun 2019 13:42:53 -0700 Subject: [PATCH 005/138] Minor --- src/hb-ot-font.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 3344c4b6b..af9a9a2dc 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -37,7 +37,6 @@ #include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" #include "hb-ot-hmtx-table.hh" -#include "hb-ot-kern-table.hh" #include "hb-ot-os2-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise. From 0819f3ca863af520fe546e6ef0596300e9e28b01 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 14:02:47 -0700 Subject: [PATCH 006/138] Deprecate v_kerning callback again Part of https://github.com/harfbuzz/harfbuzz/issues/1682 --- docs/harfbuzz-sections.txt | 6 +++--- src/hb-deprecated.h | 23 +++++++++++++++++++++++ src/hb-font.cc | 7 +++---- src/hb-font.h | 20 -------------------- src/hb-font.hh | 2 +- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 2f34b6a85..4be248d30 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -195,6 +195,9 @@ HB_UNICODE_MAX_DECOMPOSITION_LEN hb_unicode_decompose_compatibility_func_t hb_unicode_decompose_compatibility hb_unicode_funcs_set_decompose_compatibility_func +hb_font_funcs_set_glyph_v_kerning_func +hb_font_get_glyph_v_kerning +hb_font_get_glyph_v_kerning_func_t
@@ -268,7 +271,6 @@ hb_font_funcs_set_glyph_h_origin_func hb_font_funcs_set_glyph_name_func hb_font_funcs_set_glyph_v_advance_func hb_font_funcs_set_glyph_v_advances_func -hb_font_funcs_set_glyph_v_kerning_func hb_font_funcs_set_glyph_v_origin_func hb_font_funcs_set_nominal_glyph_func hb_font_funcs_set_nominal_glyphs_func @@ -308,8 +310,6 @@ hb_font_get_glyph_v_advance hb_font_get_glyph_v_advance_func_t hb_font_get_glyph_v_advances hb_font_get_glyph_v_advances_func_t -hb_font_get_glyph_v_kerning -hb_font_get_glyph_v_kerning_func_t hb_font_get_glyph_v_origin hb_font_get_glyph_v_origin_func_t hb_font_get_nominal_glyph diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h index 47de70a2b..43f89a4c4 100644 --- a/src/hb-deprecated.h +++ b/src/hb-deprecated.h @@ -165,6 +165,29 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, hb_codepoint_t *decomposed); +typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t; + +/** + * hb_font_funcs_set_glyph_v_kerning_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 0.9.2 + * Deprecated: 2.0.0 + **/ +HB_EXTERN void +hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_v_kerning_func_t func, + void *user_data, hb_destroy_func_t destroy); + +HB_EXTERN hb_position_t +hb_font_get_glyph_v_kerning (hb_font_t *font, + hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); + #endif HB_END_DECLS diff --git a/src/hb-font.cc b/src/hb-font.cc index d7b2a7ae6..7eee284e6 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -336,7 +336,6 @@ hb_font_get_glyph_v_origin_default (hb_font_t *font, return ret; } -#ifndef HB_DISABLE_DEPRECATED static hb_position_t hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, @@ -356,6 +355,7 @@ hb_font_get_glyph_h_kerning_default (hb_font_t *font, return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); } +#ifndef HB_DISABLE_DEPRECATED static hb_position_t hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, @@ -927,7 +927,6 @@ hb_font_get_glyph_v_origin (hb_font_t *font, return font->get_glyph_v_origin (glyph, x, y); } -#ifndef HB_DISABLE_DEPRECATED /** * hb_font_get_glyph_h_kerning: * @font: a font. @@ -947,6 +946,7 @@ hb_font_get_glyph_h_kerning (hb_font_t *font, return font->get_glyph_h_kerning (left_glyph, right_glyph); } +#ifndef HB_DISABLE_DEPRECATED /** * hb_font_get_glyph_v_kerning: * @font: a font. @@ -958,6 +958,7 @@ hb_font_get_glyph_h_kerning (hb_font_t *font, * Return value: * * Since: 0.9.2 + * Deprecated: 2.0.0 **/ hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, @@ -1175,7 +1176,6 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, return font->subtract_glyph_origin_for_direction (glyph, direction, x, y); } -#ifndef HB_DISABLE_DEPRECATED /** * hb_font_get_glyph_kerning_for_direction: * @font: a font. @@ -1197,7 +1197,6 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font, { return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y); } -#endif /** * hb_font_get_glyph_extents_for_origin: diff --git a/src/hb-font.h b/src/hb-font.h index 40dfc41d2..5bd8cbbcf 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -161,7 +161,6 @@ typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, void *user_data); typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t; -typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t; typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data, @@ -378,22 +377,6 @@ hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_kerning_func_t func, void *user_data, hb_destroy_func_t destroy); -/** - * hb_font_funcs_set_glyph_v_kerning_func: - * @ffuncs: font functions. - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: - * - * - * - * Since: 0.9.2 - **/ -HB_EXTERN void -hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_v_kerning_func_t func, - void *user_data, hb_destroy_func_t destroy); - /** * hb_font_funcs_set_glyph_extents_func: * @ffuncs: font functions. @@ -510,9 +493,6 @@ hb_font_get_glyph_v_origin (hb_font_t *font, HB_EXTERN hb_position_t hb_font_get_glyph_h_kerning (hb_font_t *font, hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); -HB_EXTERN hb_position_t -hb_font_get_glyph_v_kerning (hb_font_t *font, - hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); HB_EXTERN hb_bool_t hb_font_get_glyph_extents (hb_font_t *font, diff --git a/src/hb-font.hh b/src/hb-font.hh index 95551bfd2..3b917d129 100644 --- a/src/hb-font.hh +++ b/src/hb-font.hh @@ -51,7 +51,7 @@ HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \ HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ - HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning)) \ + HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \ HB_FONT_FUNC_IMPLEMENT (glyph_extents) \ HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ From bfb5569d530a2b65dafd0d9be45d594af9e742ce Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 14:06:04 -0700 Subject: [PATCH 007/138] Disable non-OpenType kerning with hb-ft in HB_TINY --- src/hb-ft.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index c24a0e268..d40e8fad7 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -346,6 +346,7 @@ hb_ft_get_glyph_v_origin (hb_font_t *font, return true; } +#ifndef HB_NO_OT_SHAPE_FALLBACK static hb_position_t hb_ft_get_glyph_h_kerning (hb_font_t *font, void *font_data, @@ -362,6 +363,7 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font, return kerningv.x; } +#endif static hb_bool_t hb_ft_get_glyph_extents (hb_font_t *font, @@ -514,7 +516,9 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t Date: Mon, 17 Jun 2019 14:12:11 -0700 Subject: [PATCH 008/138] Use injected class name --- src/hb-open-type.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index de2d25638..2991d8e75 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -59,11 +59,11 @@ struct IntType typedef Type type; typedef hb_conditional wide_type; - IntType& operator = (wide_type i) { v = i; return *this; } + IntType& operator = (wide_type i) { v = i; return *this; } operator wide_type () const { return v; } - bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } - bool operator != (const IntType &o) const { return !(*this == o); } - HB_INTERNAL static int cmp (const IntType *a, const IntType *b) + bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } + bool operator != (const IntType &o) const { return !(*this == o); } + HB_INTERNAL static int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } template int cmp (Type2 a) const From 6492b2345cd913223b0eb931e9e11f7e5ad33049 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 14:19:13 -0700 Subject: [PATCH 009/138] Minor --- src/hb-open-type.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 2991d8e75..e235a97c3 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -146,7 +146,7 @@ struct LONGDATETIME * system, feature, or baseline */ struct Tag : HBUINT32 { - Tag& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; } + Tag& operator = (hb_tag_t i) { HBUINT32::operator= (i); return *this; } /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ operator const char* () const { return reinterpret_cast (&this->v); } operator char* () { return reinterpret_cast (&this->v); } From 1c56b5d1d8307efd12519556e41fc50c5371f136 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 14:23:04 -0700 Subject: [PATCH 010/138] [serialize] Fix copy() calling operator= https://github.com/googlefonts/harfbuzz/commit/9f610ae239a11e86f94621e26bc15849b65ce41b#commitcomment-33944686 --- src/hb-serialize.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 76f701608..5764a90f6 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -375,7 +375,7 @@ struct hb_serialize_context_t (Type *, src.copy (this, hb_forward (ds)...)) template auto - _copy (const Type &src, hb_priority<0>) -> decltype (&(src = src)) + _copy (const Type &src, hb_priority<0>) -> decltype (&(hb_declval () = src)) { Type *ret = this->allocate_size (sizeof (Type)); if (unlikely (!ret)) return nullptr; From 3a9394635ffd663d8acd0715236dd01d9f22f3b8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 20:10:36 -0700 Subject: [PATCH 011/138] Add CONFIG.md https://github.com/harfbuzz/harfbuzz/issues/1652 --- CONFIG.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile.am | 1 + README.md | 2 ++ 3 files changed, 54 insertions(+) create mode 100644 CONFIG.md diff --git a/CONFIG.md b/CONFIG.md new file mode 100644 index 000000000..b6b54f187 --- /dev/null +++ b/CONFIG.md @@ -0,0 +1,51 @@ +# Configuring HarfBuzz + +Most of the time you will not need any custom configuration. The configuration +options provided by `configure` or `cmake` should be enough. In particular, +if you just want HarfBuzz library plus hb-shape / hb-view utilities, make sure +FreeType and Cairo are available and found during configuration. + +If you are building for distribution, you should more carefully consider whether +you need Glib, ICU, Graphite2, as well as CoreText / Uniscribe / DWrite. Make +sure the relevant ones are enabled. + +If you are building for custom environment (embedded, downloadable app, etc) +where you mostly just want to call `hb_shape()` and the binary size of the +resulting library is very important to you, the rest of this file guides you +through your options to disable features you may not need, in exchange for +binary size savings. + +## Compiler Options + +Make sure you build with your compiler's "optimize for size" option. On `gcc` +this is `-Os`, and can be enabled by passing `CXXFLAGS=-Os` either to `configure` +(sticky) or to `make` (non-sticky). On clang there is an even more extreme flag, +`-Oz`. + +HarfBuzz heavily uses inline functions and the optimize-size flag can make the +library smaller by 20% or more. Moreover, sometimes, based on the target CPU, +the optimize-size builds perform *faster* as well, thanks to lower code +footprint and caching effects. So, definitely try that even if size is not +extremely tight but you have a huge application. For example, Chrome does +that. Note that this configuration also automatically enables certain internal +optimizations. Search for `HB_OPTIMIZE_SIZE` for details, if you are using +other compilers, or continue reading. + +Another compiler option to consider is "link-time optimization", also known as +'lto'. To enable that, with `gcc` or `clang`, add `-flto` to both `CXXFLAGS` +and `LDFLAGS`, either on `configure` invocation (sticky) or on `make` (non-sticky). +This, also, can have a huge impact on the final size, 20% or more. + +Finally, if you are making a static library build or otherwise linking the +library into your app, make sure your linker removes unused functions. This +can be tricky and differ from environment to environment, but you definitely +want to make sure this happens. Otherwise, every unused public function will +be adding unneeded bytes to your binary. + +Combining the above three build options should already shrink your library a lot. +The rest of this file shows you ways to shrink the library even further at the +expense of removing functionality (that may not be needed). + +## Custom configuration + +TODO diff --git a/Makefile.am b/Makefile.am index 26ebdc6e7..2bbd3c55d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,6 +13,7 @@ EXTRA_DIST = \ README.mingw.md \ README.python.md \ BUILD.md \ + CONFIG.md \ RELEASING.md \ TESTING.md \ CMakeLists.txt \ diff --git a/README.md b/README.md index ce0a04d1f..ce3e84dde 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ For license information, see [COPYING](COPYING). For build information, see [BUILD.md](BUILD.md). +For custom configurations, see [CONFIG.md](CONFIG.md). + For test execution, see [TESTING.md](TESTING.md). Documentation: https://harfbuzz.github.io From 23768a99e08cbe691772b7514c023d3184989ff8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 20:29:29 -0700 Subject: [PATCH 012/138] [config] Replace HAVE_FALLBACK with HB_NO_FALLBACK_SHAPE This disables fallback shaper in tiny builds. Projects that don't use our build system and want to disable fallback shaper (eg. Firefox) should define HB_NO_FALLBACK_SHAPE now. Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- CMakeLists.txt | 2 -- configure.ac | 8 -------- src/Makefile.am | 4 ---- src/Makefile.sources | 5 +---- src/hb-config.hh | 1 + src/hb-fallback-shape.cc | 3 +++ src/hb-shaper-list.hh | 2 +- 7 files changed, 6 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cbff81e95..f2b2268a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,8 +88,6 @@ include_directories(AFTER ${PROJECT_BINARY_DIR}/src ) -add_definitions(-DHAVE_FALLBACK) - # We need PYTHON_EXECUTABLE to be set for running the tests... include (FindPythonInterp) diff --git a/configure.ac b/configure.ac index d48823d25..ade6840e8 100644 --- a/configure.ac +++ b/configure.ac @@ -136,14 +136,6 @@ AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread) dnl ========================================================================== -have_fallback=true -if $have_fallback; then - AC_DEFINE(HAVE_FALLBACK, 1, [Have simple TrueType Layout backend]) -fi -AM_CONDITIONAL(HAVE_FALLBACK, $have_fallback) - -dnl =========================================================================== - AC_ARG_WITH(glib, [AS_HELP_STRING([--with-glib=@<:@yes/no/auto@:>@], [Use glib @<:@default=auto@:>@])],, diff --git a/src/Makefile.am b/src/Makefile.am index d126c4017..016229b34 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,10 +28,6 @@ HBSOURCES = $(HB_BASE_sources) HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources) HBHEADERS = $(HB_BASE_headers) -if HAVE_FALLBACK -HBSOURCES += $(HB_FALLBACK_sources) -endif - if HAVE_PTHREAD HBCFLAGS += $(PTHREAD_CFLAGS) HBNONPCLIBS += $(PTHREAD_LIBS) diff --git a/src/Makefile.sources b/src/Makefile.sources index 70983f135..af0296b67 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -36,6 +36,7 @@ HB_BASE_sources = \ hb-dispatch.hh \ hb-face.cc \ hb-face.hh \ + hb-fallback-shape.cc \ hb-font.cc \ hb-font.hh \ hb-iter.hh \ @@ -200,10 +201,6 @@ HB_BASE_headers = \ hb.h \ $(NULL) -HB_FALLBACK_sources = \ - hb-fallback-shape.cc \ - $(NULL) - # Optional Sources and Headers with external deps HB_FT_sources = hb-ft.cc diff --git a/src/hb-config.hh b/src/hb-config.hh index 56c85a042..491979653 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -99,6 +99,7 @@ #endif #ifdef HB_NO_LEGACY +#define HB_NO_FALLBACK_SHAPE #define HB_NO_OT_LAYOUT_BLACKLIST #define HB_NO_OT_SHAPE_FALLBACK #endif diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc index 09f02900f..c5b7c2c23 100644 --- a/src/hb-fallback-shape.cc +++ b/src/hb-fallback-shape.cc @@ -26,6 +26,7 @@ #include "hb-shaper-impl.hh" +#ifndef HB_NO_FALLBACK_SHAPE /* * shaper face data @@ -120,3 +121,5 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, return true; } + +#endif diff --git a/src/hb-shaper-list.hh b/src/hb-shaper-list.hh index 25c584bc0..4108e7aab 100644 --- a/src/hb-shaper-list.hh +++ b/src/hb-shaper-list.hh @@ -47,6 +47,6 @@ HB_SHAPER_IMPLEMENT (directwrite) HB_SHAPER_IMPLEMENT (coretext) #endif -#ifdef HAVE_FALLBACK +#ifndef HB_NO_FALLBACK_SHAPE HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */ #endif From 23ccd00a3d5033b812f2bebcc5b793a4415b252b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 20:35:04 -0700 Subject: [PATCH 013/138] Minor --- src/hb-config.hh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hb-config.hh b/src/hb-config.hh index 491979653..c1a15f86e 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -72,7 +72,8 @@ #define HB_NO_LEGACY #endif -/* Closure. */ + +/* Closure of options. */ #ifdef HB_DISABLE_DEPRECATED #define HB_IF_NOT_DEPRECATED(x) From 33d8b76e74579a27b06fa788d0bf696a9dd44cc4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 21:54:20 -0700 Subject: [PATCH 014/138] [config] Flesh out CONFIG.md Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- CONFIG.md | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/CONFIG.md b/CONFIG.md index b6b54f187..393553c0a 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -44,8 +44,89 @@ be adding unneeded bytes to your binary. Combining the above three build options should already shrink your library a lot. The rest of this file shows you ways to shrink the library even further at the -expense of removing functionality (that may not be needed). +expense of removing functionality (that may not be needed). The remaining +options are all enabled by defining pre-processor macros, which can be done +via `CXXFLAGS` or `CPPFLAGS` similarly. -## Custom configuration -TODO +## Unicode-functions + +Access to Unicode data can be configured at compile time as well as run-time. +By default, HarfBuzz ships with its own compact subset of properties from +Unicode Character Database that it needs. This is a highly-optimized +implementation that depending on compile settings (optimize-size or not) +takes around ~40kb or ~60kb. Using this implementation (default) is highly +recommended, as HarfBuzz always ships with data from latest version of Unicode. +This implementation can be disabled by defining `HB_NO_UCD`. + +For example, if you are enabling ICU as a built-in option, or GLib, those +can provide Unicode data as well, so defining `HB_NO_UCD` might save you +space without reducing functionality (to the extent that the Unicode version +of those implementations is recent.) + +If, however, you provide your own Unicode data to HarfBuzz at run-time by +calling `hb_buffer_set_unicode_funcs` on every buffer you create, and you do +not rely on `hb_unicode_funcs_get_default()` results, you can disable the +internal implementation by defining both `HB_NO_UCD` and `HB_NO_UNICODE_FUNCS`. +The latter is needed to guard against accidentally building a library without +any default Unicode implementations. + + +## Font-functions + +Access to certain font functionalities can also be configured at run-time. By +default, HarfBuzz uses an efficient internal implementation of OpenType +functionality for this. This internal implementation is called `hb-ot-font`. +All newly-created `hb_font_t` objects by default use `hb-ot-font`. Using this +is highly recommended, and is what fonts use by default when they are created. + +Most embedded uses will probably use HarfBuzz with FreeType using `hb-ft.h`. +In that case, or if you otherwise provide those functions by calling +`hb_font_set_funcs()` on every font you create, you can disable `hb-ot-font` +without loss of functionality by defining `HB_NO_OT_FONT`. + + +## Thread-safety + +By default HarfBuzz builds as a thread-safe library. The exception is that +the `HB_TINY` predefined configuring (more below) disables thread-safety. + +If you do /not/ need thread-safety in the library (eg. you always call into +HarfBuzz from the same thread), you can disable thread-safety by defining +`HB_NO_MT`. As noted already, this is enabled by `HB_TINY`. + + +## Pre-defined configurations + +The [`hb-config.hh`](src/hb-config.hh) internal header supports three +pre-defined configurations as well grouping of various configuration options. +The pre-defined configurations are: + + * `HB_MINI`: Disables shaping of AAT as well as legacy fonts. Ie. it produces + a capable OpenType shaper only. + + * `HB_LEAN`: Disables various non-shaping functionality in the library. See + the definition for details. + + * `HB_TINY`: Enables both `HB_MINI` and `HB_LEAN` configurations, as well as + disabling thread-safety and debugging, and use size-optimized data tables. + + +## Tailoring configuration + +Most of the time, one of the pre-defined configuration is exactly what one needs. +Sometimes, however, the pre-defined configuration cuts out features that might +be desired in the library. Unfortunately there is no quick way to undo those +configurations from the command-line. But one can add a header file called +`config-override.h` to undefine certain `HB_NO_*` symbols as desired. Then +define `HAVE_CONFIG_OVERRIDE_H` to make `hb-config.hh` include your configuration +overrides at the end. + + +## Notes + +Note that the config option `HB_NO_CFF`, which is enabled by `HB_LEAN` and +`HB_TINY` does /not/ mean that the resulting library won't work with CFF fonts. +The library can shape valid CFF fonts just fine, with or without this option. +This option disables (among other things) the code to calculate glyph exntents +for CFF fonts. From aa3450cac148280f747fb88864b6fcc4ec70cc51 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 22:41:49 -0700 Subject: [PATCH 015/138] [config] Don't compile disabled features This makes it possible to include all .cc files into build, even if not building CoreText, Uniscribe, etc. This was mostly to help custom builders. But also means that we can include all files in our own build system. Not sure if we should. Definitely simplifies things, but slightly only. --- src/Makefile.am | 1 + src/hb-coretext.cc | 6 ++++++ src/hb-directwrite.cc | 6 ++++++ src/hb-ft.cc | 5 +++++ src/hb-glib.cc | 5 +++++ src/hb-gobject-enums.cc.tmpl | 7 +++++++ src/hb-gobject-structs.cc | 5 +++++ src/hb-graphite2.cc | 7 +++++++ src/hb-icu.cc | 5 +++++ src/hb-uniscribe.cc | 4 ++++ 10 files changed, 51 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 016229b34..14cafb833 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -424,6 +424,7 @@ HarfBuzz_0_0_gir_CFLAGS = \ -DHB_AAT_H_IN \ -DHB_GOBJECT_H \ -DHB_GOBJECT_H_IN \ + -DHAVE_GOBJECT \ -DHB_EXTERN= \ $(NULL) HarfBuzz_0_0_gir_LIBS = \ diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 85993d196..20cfe4a60 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -27,6 +27,9 @@ */ #include "hb.hh" + +#ifdef HAVE_CORETEXT + #include "hb-shaper-impl.hh" #include "hb-coretext.h" @@ -1148,3 +1151,6 @@ fail: return ret; } + + +#endif diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index b135c49e9..85ba8b627 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -23,6 +23,9 @@ */ #include "hb.hh" + +#ifdef HAVE_DIRECTWRITE + #include "hb-shaper-impl.hh" #include @@ -958,3 +961,6 @@ hb_directwrite_face_get_font_face (hb_face_t *face) { return face->data.directwrite->fontFace; } + + +#endif diff --git a/src/hb-ft.cc b/src/hb-ft.cc index d40e8fad7..c01f02991 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -29,6 +29,8 @@ #include "hb.hh" +#ifdef HAVE_FREETYPE + #include "hb-ft.h" #include "hb-font.hh" @@ -877,3 +879,6 @@ hb_ft_font_set_funcs (hb_font_t *font) _hb_ft_font_set_funcs (font, ft_face, true); hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); } + + +#endif diff --git a/src/hb-glib.cc b/src/hb-glib.cc index 576375460..db02b6760 100644 --- a/src/hb-glib.cc +++ b/src/hb-glib.cc @@ -28,6 +28,8 @@ #include "hb.hh" +#ifdef HAVE_GLIB + #include "hb-glib.h" #include "hb-machinery.hh" @@ -404,3 +406,6 @@ hb_glib_blob_create (GBytes *gbytes) _hb_g_bytes_unref); } #endif + + +#endif diff --git a/src/hb-gobject-enums.cc.tmpl b/src/hb-gobject-enums.cc.tmpl index e3a9a6b3f..17f1adeb1 100644 --- a/src/hb-gobject-enums.cc.tmpl +++ b/src/hb-gobject-enums.cc.tmpl @@ -27,6 +27,8 @@ #include "hb.hh" +#ifdef HAVE_GOBJECT + /* g++ didn't like older gtype.h gcc-only code path. */ #include #if !GLIB_CHECK_VERSION(2,29,16) @@ -44,6 +46,11 @@ /* enumerations from "@filename@" */ /*** END file-production ***/ +/*** BEGIN file-tail ***/ + +#endif +/*** END file-tail ***/ + /*** BEGIN value-header ***/ GType @enum_name@_get_type () diff --git a/src/hb-gobject-structs.cc b/src/hb-gobject-structs.cc index 3cff880aa..7f4922ef1 100644 --- a/src/hb-gobject-structs.cc +++ b/src/hb-gobject-structs.cc @@ -26,6 +26,8 @@ #include "hb.hh" +#ifdef HAVE_GOBJECT + /** * SECTION:hb-gobject @@ -94,3 +96,6 @@ HB_DEFINE_VALUE_TYPE (user_data_key) HB_DEFINE_VALUE_TYPE (ot_math_glyph_variant) HB_DEFINE_VALUE_TYPE (ot_math_glyph_part) + + +#endif diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc index f799f8b22..9588fa4d6 100644 --- a/src/hb-graphite2.cc +++ b/src/hb-graphite2.cc @@ -26,6 +26,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifdef HAVE_GRAPHITE2 + #include "hb-shaper-impl.hh" #include "hb-graphite2.h" @@ -447,3 +451,6 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, return true; } + + +#endif diff --git a/src/hb-icu.cc b/src/hb-icu.cc index 399829a81..e98908de7 100644 --- a/src/hb-icu.cc +++ b/src/hb-icu.cc @@ -29,6 +29,8 @@ #include "hb.hh" +#ifdef HAVE_ICU + #include "hb-icu.h" #include "hb-machinery.hh" @@ -351,3 +353,6 @@ hb_icu_get_unicode_funcs () { return static_icu_funcs.get_unconst (); } + + +#endif diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index 69a1ae7e4..fceda5244 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -25,6 +25,9 @@ */ #include "hb.hh" + +#ifdef HAVE_UNISCRIBE + #include "hb-shaper-impl.hh" #include @@ -1023,3 +1026,4 @@ retry: } +#endif From efef672911dd6c3b80e53294f3fcd59dbb64597a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 17 Jun 2019 22:57:51 -0700 Subject: [PATCH 016/138] Fix cmake build Hopefullly. --- CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2b2268a2..c9ba0160c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,8 +161,6 @@ extract_make_variable(HB_BASE_sources ${SRCSOURCES}) add_prefix_to_list(HB_BASE_sources "${PROJECT_SOURCE_DIR}/src/") extract_make_variable(HB_BASE_headers ${SRCSOURCES}) add_prefix_to_list(HB_BASE_headers "${PROJECT_SOURCE_DIR}/src/") -extract_make_variable(HB_FALLBACK_sources ${SRCSOURCES}) -add_prefix_to_list(HB_FALLBACK_sources "${PROJECT_SOURCE_DIR}/src/") extract_make_variable(HB_SUBSET_sources ${SRCSOURCES}) add_prefix_to_list(HB_SUBSET_sources "${PROJECT_SOURCE_DIR}/src/") @@ -229,8 +227,6 @@ set (HB_VERSION_MICRO ${CMAKE_MATCH_4}) set (project_sources ${HB_BASE_sources} ${HB_BASE_RAGEL_GENERATED_sources} - - ${HB_FALLBACK_sources} ) set (subset_project_sources From eb28d6e48b02a8c49875cfcd084a16c1c66c367e Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 18 Jun 2019 12:14:10 +0430 Subject: [PATCH 017/138] [ci] Test no build system builds Introduced in aa3450c, let's preserve it --- .circleci/config.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c1741a804..2ce6a8e22 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -82,7 +82,7 @@ jobs: # - run: xbps-install -Suy freetype gettext gcc glib graphite pkg-config ragel libtool autoconf automake make # - run: ./autogen.sh && make -j32 && make check - clang-O3-O0: + clang-O3-O0-and-nobuildsystem: docker: - image: ubuntu:18.10 steps: @@ -97,6 +97,7 @@ jobs: - run: CFLAGS="-O0" CXXFLAGS="-O0" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-fontconfig --with-glib --with-cairo --with-icu --with-graphite2 - run: make -j32 - run: LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs" make check || .ci/fail.sh + - run: make clean && cd src && clang++ -c hb-*.cc gcc-valgrind: docker: @@ -315,7 +316,7 @@ workflows: - archlinux-py3-all #- void-notest - gcc-valgrind - - clang-O3-O0 + - clang-O3-O0-and-nobuildsystem - clang-everything - clang-asan - clang-msan From 6172ec5d879653c536d7cb3d3b3760fbb6d0f3f3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 12:41:56 -0700 Subject: [PATCH 018/138] Remove (unused) posix_memalign fallback Was wrong. The returned pointer couldn't be passed to free(). Ouch! --- configure.ac | 2 +- src/hb.hh | 34 ---------------------------------- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/configure.ac b/configure.ac index ade6840e8..958bd2dd2 100644 --- a/configure.ac +++ b/configure.ac @@ -77,7 +77,7 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl]) ]) # Functions and headers -AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l posix_memalign) +AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l) AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h stdbool.h) # Compiler flags diff --git a/src/hb.hh b/src/hb.hh index a2baa31d2..a63d629bd 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -211,14 +211,6 @@ extern "C" void hb_free_impl(void *ptr); #define calloc hb_calloc_impl #define realloc hb_realloc_impl #define free hb_free_impl - -#ifdef hb_memalign_impl -extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size); -#define posix_memalign hb_memalign_impl -#else -#undef HAVE_POSIX_MEMALIGN -#endif - #endif @@ -515,32 +507,6 @@ typedef uint64_t hb_vector_size_impl_t; #define VAR 1 -/* fallback for posix_memalign() */ -static inline int -_hb_memalign(void **memptr, size_t alignment, size_t size) -{ - if (unlikely (0 != (alignment & (alignment - 1)) || - !alignment || - 0 != (alignment & (sizeof (void *) - 1)))) - return EINVAL; - - char *p = (char *) malloc (size + alignment - 1); - if (unlikely (!p)) - return ENOMEM; - - size_t off = (size_t) p & (alignment - 1); - if (off) - p += alignment - off; - - *memptr = (void *) p; - - return 0; -} -#if !defined(posix_memalign) && !defined(HAVE_POSIX_MEMALIGN) -#define posix_memalign _hb_memalign -#endif - - /* * Big-endian integers. Here because fundamental. */ From 7cf9169078f35299ec0633a7b212256acdd71661 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 12:44:03 -0700 Subject: [PATCH 019/138] Remove accidentally left cruft --- src/hb-algs.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index 59eead4eb..9a8abe686 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -1021,7 +1021,7 @@ struct hb_vector_size_t hb_vector_size_t operator ~ () const { hb_vector_size_t r; -#if HB_VECTOR_SIZE && 0 +#if HB_VECTOR_SIZE if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) r.u.vec[i] = ~u.vec[i]; From 24060d3aa77f1e1a18960cc61c3d1ac241875507 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 12:50:42 -0700 Subject: [PATCH 020/138] Add hb_bitwise_neg --- src/hb-algs.hh | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index 9a8abe686..fe78d94c9 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -940,6 +940,12 @@ struct hb_bitwise_sub operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b) } HB_FUNCOBJ (hb_bitwise_sub); +struct +{ + template auto + operator () (const T &a) const HB_AUTO_RETURN (~a) +} +HB_FUNCOBJ (hb_bitwise_neg); struct { HB_PARTIALIZE(2); @@ -998,6 +1004,20 @@ struct hb_vector_size_t void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); } + template + hb_vector_size_t process (const Op& op) const + { + hb_vector_size_t r; +#if HB_VECTOR_SIZE + if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) + for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) + r.u.vec[i] = op (u.vec[i]); + else +#endif + for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++) + r.u.v[i] = op (u.v[i]); + return r; + } template hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const { @@ -1019,18 +1039,7 @@ struct hb_vector_size_t hb_vector_size_t operator ^ (const hb_vector_size_t &o) const { return process (hb_bitwise_xor, o); } hb_vector_size_t operator ~ () const - { - hb_vector_size_t r; -#if HB_VECTOR_SIZE - if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) - for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) - r.u.vec[i] = ~u.vec[i]; - else -#endif - for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++) - r.u.v[i] = ~u.v[i]; - return r; - } + { return process (hb_bitwise_neg); } private: static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, ""); From 60653a7adbbd8143d187b3edf33cb7a2dddadf74 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 13:01:11 -0700 Subject: [PATCH 021/138] Remove HB_VECTOR_SIZE It was cumbersome to get it to work reliably, for dubious performance gain, mostly in the subsetter maybe... Life is easier without. It was disabled forever anyway. --- src/hb-algs.hh | 36 +++++++++--------------------------- src/hb-null.hh | 4 ++-- src/hb-static.cc | 4 ++-- src/hb.hh | 32 -------------------------------- 4 files changed, 13 insertions(+), 63 deletions(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index fe78d94c9..4a537baf3 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -994,13 +994,12 @@ HB_FUNCOBJ (hb_neg); /* Compiler-assisted vectorization. */ /* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))), - * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128). - * Define that to 0 to disable. */ + * basically a fixed-size bitset. */ template struct hb_vector_size_t { - elt_t& operator [] (unsigned int i) { return u.v[i]; } - const elt_t& operator [] (unsigned int i) const { return u.v[i]; } + elt_t& operator [] (unsigned int i) { return v[i]; } + const elt_t& operator [] (unsigned int i) const { return v[i]; } void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); } @@ -1008,28 +1007,16 @@ struct hb_vector_size_t hb_vector_size_t process (const Op& op) const { hb_vector_size_t r; -#if HB_VECTOR_SIZE - if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) - for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) - r.u.vec[i] = op (u.vec[i]); - else -#endif - for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++) - r.u.v[i] = op (u.v[i]); + for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) + r.v[i] = op (v[i]); return r; } template hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const { hb_vector_size_t r; -#if HB_VECTOR_SIZE - if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) - for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) - r.u.vec[i] = op (u.vec[i], o.u.vec[i]); - else -#endif - for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++) - r.u.v[i] = op (u.v[i], o.u.v[i]); + for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) + r.v[i] = op (v[i], o.v[i]); return r; } hb_vector_size_t operator | (const hb_vector_size_t &o) const @@ -1042,13 +1029,8 @@ struct hb_vector_size_t { return process (hb_bitwise_neg); } private: - static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, ""); - union { - elt_t v[byte_size / sizeof (elt_t)]; -#if HB_VECTOR_SIZE - hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)]; -#endif - } u; + static_assert (0 == byte_size % sizeof (elt_t), ""); + elt_t v[byte_size / sizeof (elt_t)]; }; diff --git a/src/hb-null.hh b/src/hb-null.hh index 674b4dffc..d4578205e 100644 --- a/src/hb-null.hh +++ b/src/hb-null.hh @@ -74,7 +74,7 @@ using hb_static_size = _hb_static_size; */ extern HB_INTERNAL -hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)]; +uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)]; /* Generic nul-content Null objects. */ template @@ -128,7 +128,7 @@ struct NullHelper * causing bad memory access. So, races there are not actually introducing incorrectness * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */ extern HB_INTERNAL -/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)]; +/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)]; /* CRAP pool: Common Region for Access Protection. */ template diff --git a/src/hb-static.cc b/src/hb-static.cc index 6b89183ca..08a2f2136 100644 --- a/src/hb-static.cc +++ b/src/hb-static.cc @@ -39,8 +39,8 @@ #ifndef HB_NO_VISIBILITY #include "hb-ot-name-language-static.hh" -hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; -/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; +uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {}; +/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {}; DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00}; diff --git a/src/hb.hh b/src/hb.hh index a63d629bd..3145574d9 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -435,38 +435,6 @@ static_assert ((sizeof (hb_var_int_t) == 4), ""); void operator=(const TypeName&) = delete -/* - * Compiler-assisted vectorization parameters. - */ - -/* - * Disable vectorization for now. To correctly use them, we should - * use posix_memalign() to allocate in hb_vector_t. Otherwise, can - * cause misaligned access. - * - * https://bugs.chromium.org/p/chromium/issues/detail?id=860184 - */ -#ifndef HB_VECTOR_SIZE -# define HB_VECTOR_SIZE 0 -#endif - -/* The `vector_size' attribute was introduced in gcc 3.1. */ -#ifndef HB_VECTOR_SIZE -# if defined( __GNUC__ ) && ( __GNUC__ >= 4 ) -# define HB_VECTOR_SIZE 128 -# else -# define HB_VECTOR_SIZE 0 -# endif -#endif -static_assert (0 == (HB_VECTOR_SIZE & (HB_VECTOR_SIZE - 1)), "HB_VECTOR_SIZE is not power of 2."); -static_assert (0 == (HB_VECTOR_SIZE % 64), "HB_VECTOR_SIZE is not multiple of 64."); -#if HB_VECTOR_SIZE -typedef uint64_t hb_vector_size_impl_t __attribute__((vector_size (HB_VECTOR_SIZE / 8))); -#else -typedef uint64_t hb_vector_size_impl_t; -#endif - - /* Flags */ /* Enable bitwise ops on enums marked as flags_t */ From 737436d3f8aacfd0bd586cd54d7034bae3afc4e1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 13:07:44 -0700 Subject: [PATCH 022/138] Streamline HB_NO_CFF --- src/hb-ot-cff1-table.cc | 7 +++++-- src/hb-ot-cff2-table.cc | 7 +++++-- src/hb-subset-cff-common.cc | 7 +++++++ src/hb-subset-cff1.cc | 7 +++++-- src/hb-subset-cff2.cc | 7 +++++-- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-cff1-table.cc b/src/hb-ot-cff1-table.cc index e6dd6a7b8..3238ad73a 100644 --- a/src/hb-ot-cff1-table.cc +++ b/src/hb-ot-cff1-table.cc @@ -24,11 +24,13 @@ * Adobe Author(s): Michiharu Ariza */ -#include "hb-ot-cff1-table.hh" -#include "hb-cff1-interp-cs.hh" +#include "hb.hh" #ifndef HB_NO_CFF +#include "hb-ot-cff1-table.hh" +#include "hb-cff1-interp-cs.hh" + using namespace CFF; /* SID to code */ @@ -391,4 +393,5 @@ bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_code return false; } + #endif diff --git a/src/hb-ot-cff2-table.cc b/src/hb-ot-cff2-table.cc index f1fa6ec30..9c9e37bd0 100644 --- a/src/hb-ot-cff2-table.cc +++ b/src/hb-ot-cff2-table.cc @@ -24,11 +24,13 @@ * Adobe Author(s): Michiharu Ariza */ -#include "hb-ot-cff2-table.hh" -#include "hb-cff2-interp-cs.hh" +#include "hb.hh" #ifndef HB_NO_OT_FONT_CFF +#include "hb-ot-cff2-table.hh" +#include "hb-cff2-interp-cs.hh" + using namespace CFF; struct extents_param_t @@ -142,4 +144,5 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, return true; } + #endif diff --git a/src/hb-subset-cff-common.cc b/src/hb-subset-cff-common.cc index 2aa55b985..54f6dc2a7 100644 --- a/src/hb-subset-cff-common.cc +++ b/src/hb-subset-cff-common.cc @@ -24,6 +24,10 @@ * Adobe Author(s): Michiharu Ariza */ +#include "hb.hh" + +#ifndef HB_NO_SUBSET_CFF + #include "hb-ot-cff-common.hh" #include "hb-ot-cff2-table.hh" #include "hb-subset-cff-common.hh" @@ -223,3 +227,6 @@ hb_serialize_cff_fdselect (hb_serialize_context_t *c, return_trace (false); } } + + +#endif diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc index 688f3f377..ab46808d2 100644 --- a/src/hb-subset-cff1.cc +++ b/src/hb-subset-cff1.cc @@ -24,6 +24,10 @@ * Adobe Author(s): Michiharu Ariza */ +#include "hb.hh" + +#ifndef HB_NO_SUBSET_CFF + #include "hb-open-type.hh" #include "hb-ot-cff1-table.hh" #include "hb-set.h" @@ -32,8 +36,6 @@ #include "hb-subset-cff-common.hh" #include "hb-cff1-interp-cs.hh" -#ifndef HB_NO_SUBSET_CFF - using namespace CFF; struct remap_sid_t : remap_t @@ -1121,4 +1123,5 @@ hb_subset_cff1 (hb_subset_plan_t *plan, return result; } + #endif diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc index 78b8c05d4..afb23ae3c 100644 --- a/src/hb-subset-cff2.cc +++ b/src/hb-subset-cff2.cc @@ -24,6 +24,10 @@ * Adobe Author(s): Michiharu Ariza */ +#include "hb.hh" + +#ifndef HB_NO_SUBSET_CFF + #include "hb-open-type.hh" #include "hb-ot-cff2-table.hh" #include "hb-set.h" @@ -32,8 +36,6 @@ #include "hb-subset-cff-common.hh" #include "hb-cff2-interp-cs.hh" -#ifndef HB_NO_SUBSET_CFF - using namespace CFF; struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t @@ -629,4 +631,5 @@ hb_subset_cff2 (hb_subset_plan_t *plan, return result; } + #endif From da51a2cb0efae664d4ee83c6036f29a21621e993 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 13:09:22 -0700 Subject: [PATCH 023/138] [config] Don't compile math API if HB_NO_MATH Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-math.cc | 47 +++++++---------------------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index 7f2792327..a0bc357e6 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -24,6 +24,10 @@ * Igalia Author(s): Frédéric Wang */ +#include "hb.hh" + +#ifndef HB_NO_MATH + #include "hb-open-type.hh" #include "hb-ot-face.hh" @@ -62,10 +66,6 @@ hb_bool_t hb_ot_math_has_data (hb_face_t *face) { -#ifdef HB_NO_MATH - return false; -#endif - return face->table.MATH->has_data (); } @@ -90,10 +90,6 @@ hb_position_t hb_ot_math_get_constant (hb_font_t *font, hb_ot_math_constant_t constant) { -#ifdef HB_NO_MATH - return 0; -#endif - return font->face->table.MATH->get_constant(constant, font); } @@ -113,10 +109,6 @@ hb_position_t hb_ot_math_get_glyph_italics_correction (hb_font_t *font, hb_codepoint_t glyph) { -#ifdef HB_NO_MATH - return 0; -#endif - return font->face->table.MATH->get_glyph_info().get_italics_correction (glyph, font); } @@ -143,10 +135,6 @@ hb_position_t hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, hb_codepoint_t glyph) { -#ifdef HB_NO_MATH - return 0; -#endif - return font->face->table.MATH->get_glyph_info().get_top_accent_attachment (glyph, font); } @@ -165,10 +153,6 @@ hb_bool_t hb_ot_math_is_glyph_extended_shape (hb_face_t *face, hb_codepoint_t glyph) { -#ifdef HB_NO_MATH - return false; -#endif - return face->table.MATH->get_glyph_info().is_extended_shape (glyph); } @@ -197,10 +181,6 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, hb_ot_math_kern_t kern, hb_position_t correction_height) { -#ifdef HB_NO_MATH - return 0; -#endif - return font->face->table.MATH->get_glyph_info().get_kerning (glyph, kern, correction_height, @@ -238,12 +218,6 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, unsigned int *variants_count, /* IN/OUT */ hb_ot_math_glyph_variant_t *variants /* OUT */) { -#ifdef HB_NO_MATH - if (variants_count) - *variants_count = 0; - return 0; -#endif - return font->face->table.MATH->get_variants().get_glyph_variants (glyph, direction, font, start_offset, variants_count, @@ -272,10 +246,6 @@ hb_position_t hb_ot_math_get_min_connector_overlap (hb_font_t *font, hb_direction_t direction) { -#ifdef HB_NO_MATH - return 0; -#endif - return font->face->table.MATH->get_variants().get_min_connector_overlap (direction, font); } @@ -313,12 +283,6 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font, hb_ot_math_glyph_part_t *parts, /* OUT */ hb_position_t *italics_correction /* OUT */) { -#ifdef HB_NO_MATH - if (parts_count) - *parts_count = 0; - return 0; -#endif - return font->face->table.MATH->get_variants().get_glyph_parts (glyph, direction, font, @@ -327,3 +291,6 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font, parts, italics_correction); } + + +#endif From 350f98ea47aaf0fe008065b92c8b6fe2bc519fa7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 13:11:41 -0700 Subject: [PATCH 024/138] [config] Don't compile name table API if HB_NO_NAME Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-name.cc | 25 +++++-------------------- src/test-ot-name.cc | 5 ++++- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc index 5cd1cc118..2f37c6768 100644 --- a/src/hb-ot-name.cc +++ b/src/hb-ot-name.cc @@ -26,6 +26,8 @@ #include "hb.hh" +#ifndef HB_NO_NAME + #include "hb-ot-name-table.hh" #include "hb-ot-face.hh" @@ -58,11 +60,6 @@ const hb_ot_name_entry_t * hb_ot_name_list_names (hb_face_t *face, unsigned int *num_entries /* OUT */) { -#ifdef HB_NO_NAME - if (num_entries) - *num_entries = 0; - return 0; -#endif const OT::name_accelerator_t &name = *face->table.name; if (num_entries) *num_entries = name.names.length; return (const hb_ot_name_entry_t *) name.names; @@ -172,11 +169,6 @@ hb_ot_name_get_utf8 (hb_face_t *face, unsigned int *text_size /* IN/OUT */, char *text /* OUT */) { -#ifdef HB_NO_NAME - if (text_size) - *text_size = 0; - return 0; -#endif return hb_ot_name_get_utf (face, name_id, language, text_size, (hb_utf8_t::codepoint_t *) text); } @@ -204,11 +196,6 @@ hb_ot_name_get_utf16 (hb_face_t *face, unsigned int *text_size /* IN/OUT */, uint16_t *text /* OUT */) { -#ifdef HB_NO_NAME - if (text_size) - *text_size = 0; - return 0; -#endif return hb_ot_name_get_utf (face, name_id, language, text_size, text); } @@ -235,10 +222,8 @@ hb_ot_name_get_utf32 (hb_face_t *face, unsigned int *text_size /* IN/OUT */, uint32_t *text /* OUT */) { -#ifdef HB_NO_NAME - if (text_size) - *text_size = 0; - return 0; -#endif return hb_ot_name_get_utf (face, name_id, language, text_size, text); } + + +#endif diff --git a/src/test-ot-name.cc b/src/test-ot-name.cc index 518e4eb6e..44c2c179c 100644 --- a/src/test-ot-name.cc +++ b/src/test-ot-name.cc @@ -43,7 +43,9 @@ main (int argc, char **argv) hb_blob_destroy (blob); blob = nullptr; - unsigned int count; + unsigned int count = 0; + +#ifndef HB_NO_NAME const hb_ot_name_entry_t *entries = hb_ot_name_list_names (face, &count); for (unsigned int i = 0; i < count; i++) @@ -62,6 +64,7 @@ main (int argc, char **argv) printf ("%s\n", buf); } +#endif hb_face_destroy (face); From 83de3a60ab7383cf3ee25c1f8c33a45a7778d003 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 13:18:15 -0700 Subject: [PATCH 025/138] [config] Don't compile color API if HB_NO_COLOR Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-color.cc | 55 ++++++++------------------------------------ src/test-ot-color.cc | 9 +++++++- 2 files changed, 17 insertions(+), 47 deletions(-) diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 20c602cdc..0e7203a88 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -25,20 +25,21 @@ * Google Author(s): Sascha Brawer, Behdad Esfahbod */ -#include "hb-open-type.hh" +#include "hb.hh" + +#ifndef HB_NO_COLOR + +#include "hb-ot.h" + #include "hb-ot-color-cbdt-table.hh" #include "hb-ot-color-colr-table.hh" #include "hb-ot-color-cpal-table.hh" #include "hb-ot-color-sbix-table.hh" #include "hb-ot-color-svg-table.hh" -#include "hb-ot-face.hh" -#include "hb-ot.h" #include #include -#include "hb-ot-layout.hh" - /** * SECTION:hb-ot-color @@ -70,9 +71,6 @@ hb_bool_t hb_ot_color_has_palettes (hb_face_t *face) { -#ifdef HB_NO_COLOR - return false; -#endif return face->table.CPAL->has_data (); } @@ -89,9 +87,6 @@ hb_ot_color_has_palettes (hb_face_t *face) unsigned int hb_ot_color_palette_get_count (hb_face_t *face) { -#ifdef HB_NO_COLOR - return 0; -#endif return face->table.CPAL->get_palette_count (); } @@ -115,9 +110,6 @@ hb_ot_name_id_t hb_ot_color_palette_get_name_id (hb_face_t *face, unsigned int palette_index) { -#ifdef HB_NO_COLOR - return HB_OT_NAME_ID_INVALID; -#endif return face->table.CPAL->get_palette_name_id (palette_index); } @@ -140,9 +132,6 @@ hb_ot_name_id_t hb_ot_color_palette_color_get_name_id (hb_face_t *face, unsigned int color_index) { -#ifdef HB_NO_COLOR - return HB_OT_NAME_ID_INVALID; -#endif return face->table.CPAL->get_color_name_id (color_index); } @@ -161,9 +150,6 @@ hb_ot_color_palette_flags_t hb_ot_color_palette_get_flags (hb_face_t *face, unsigned int palette_index) { -#ifdef HB_NO_COLOR - return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; -#endif return face->table.CPAL->get_palette_flags (palette_index); } @@ -195,11 +181,6 @@ hb_ot_color_palette_get_colors (hb_face_t *face, unsigned int *colors_count /* IN/OUT. May be NULL. */, hb_color_t *colors /* OUT. May be NULL. */) { -#ifdef HB_NO_COLOR - if (colors_count) - *colors_count = 0; - return 0; -#endif return face->table.CPAL->get_palette_colors (palette_index, start_offset, colors_count, colors); } @@ -221,9 +202,6 @@ hb_ot_color_palette_get_colors (hb_face_t *face, hb_bool_t hb_ot_color_has_layers (hb_face_t *face) { -#ifdef HB_NO_COLOR - return false; -#endif return face->table.COLR->has_data (); } @@ -250,11 +228,6 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, unsigned int *layer_count, /* IN/OUT. May be NULL. */ hb_ot_color_layer_t *layers /* OUT. May be NULL. */) { -#ifdef HB_NO_COLOR - if (layer_count) - *layer_count = 0; - return 0; -#endif return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers); } @@ -276,9 +249,6 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, hb_bool_t hb_ot_color_has_svg (hb_face_t *face) { -#ifdef HB_NO_COLOR - return false; -#endif return face->table.SVG->has_data (); } @@ -296,9 +266,6 @@ hb_ot_color_has_svg (hb_face_t *face) hb_blob_t * hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph) { -#ifdef HB_NO_COLOR - return hb_blob_get_empty (); -#endif return face->table.SVG->reference_blob_for_glyph (glyph); } @@ -320,9 +287,6 @@ hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph) hb_bool_t hb_ot_color_has_png (hb_face_t *face) { -#ifdef HB_NO_COLOR - return false; -#endif return face->table.CBDT->has_data () || face->table.sbix->has_data (); } @@ -342,10 +306,6 @@ hb_ot_color_has_png (hb_face_t *face) hb_blob_t * hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t glyph) { -#ifdef HB_NO_COLOR - return hb_blob_get_empty (); -#endif - hb_blob_t *blob = hb_blob_get_empty (); if (font->face->table.sbix->has_data ()) @@ -356,3 +316,6 @@ hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t glyph) return blob; } + + +#endif diff --git a/src/test-ot-color.cc b/src/test-ot-color.cc index 26931fed3..44bd2eb69 100644 --- a/src/test-ot-color.cc +++ b/src/test-ot-color.cc @@ -23,7 +23,10 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#include "hb.h" +#include "hb.hh" + +#ifndef HB_NO_COLOR + #include "hb-ot.h" #include "hb-ft.h" @@ -334,3 +337,7 @@ main (int argc, char **argv) return 0; } + +#else +int main (int argc, char **argv) { return 0; } +#endif From bdbabd110cfdb4c59cf24bd500ce63073a5213e4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 13:21:25 -0700 Subject: [PATCH 026/138] Minor header include cleanup --- src/hb-aat-layout.cc | 1 - src/hb-ot-math.cc | 3 --- src/hb-ot-name.cc | 1 - src/hb-ot-var.cc | 4 ++-- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index 35ba611a9..0efc2c432 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -27,7 +27,6 @@ #include "hb-open-type.hh" -#include "hb-ot-face.hh" #include "hb-aat-layout.hh" #include "hb-aat-fdsc-table.hh" // Just so we compile it; unused otherwise. #include "hb-aat-layout-ankr-table.hh" diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index a0bc357e6..9d8c6e735 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -28,9 +28,6 @@ #ifndef HB_NO_MATH -#include "hb-open-type.hh" - -#include "hb-ot-face.hh" #include "hb-ot-math-table.hh" diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc index 2f37c6768..0b5ce810e 100644 --- a/src/hb-ot-name.cc +++ b/src/hb-ot-name.cc @@ -30,7 +30,6 @@ #include "hb-ot-name-table.hh" -#include "hb-ot-face.hh" #include "hb-utf.hh" diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index 25a246a21..5eea90d25 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -26,11 +26,11 @@ #include "hb-open-type.hh" -#include "hb-ot-face.hh" +#include "hb-ot-var.h" + #include "hb-ot-var-avar-table.hh" #include "hb-ot-var-fvar-table.hh" #include "hb-ot-var-mvar-table.hh" -#include "hb-ot-var.h" /** From be1c0ab2186a728eabdf6666632a9f759474f901 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 13:26:03 -0700 Subject: [PATCH 027/138] [config] Don't compile buffer serialize API if HB_NO_BUFFER_SERIALIZE Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-buffer-serialize.cc | 19 +++++++------------ src/test-buffer-serialize.cc | 7 ++++++- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hb-buffer-serialize.cc b/src/hb-buffer-serialize.cc index d3732fd02..77d997c90 100644 --- a/src/hb-buffer-serialize.cc +++ b/src/hb-buffer-serialize.cc @@ -24,14 +24,16 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_BUFFER_SERIALIZE + #include "hb-buffer.hh" static const char *serialize_formats[] = { -#ifndef HB_NO_BUFFER_SERIALIZE "text", "json", -#endif nullptr }; @@ -89,10 +91,8 @@ hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) { switch ((unsigned) format) { -#ifndef HB_NO_BUFFER_SERIALIZE case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; -#endif default: case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr; } @@ -348,10 +348,6 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, if (buf_size) *buf = '\0'; -#ifdef HB_NO_BUFFER_SERIALIZE - return 0; -#endif - assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); @@ -457,10 +453,6 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, end_ptr = &end; *end_ptr = buf; -#ifdef HB_NO_BUFFER_SERIALIZE - return false; -#endif - assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); @@ -496,3 +488,6 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, } } + + +#endif diff --git a/src/test-buffer-serialize.cc b/src/test-buffer-serialize.cc index a91f4f7e9..28826be8d 100644 --- a/src/test-buffer-serialize.cc +++ b/src/test-buffer-serialize.cc @@ -37,6 +37,10 @@ int main (int argc, char **argv) { + bool ret = true; + +#ifndef HB_NO_BUFFER_SERIALIZE + if (argc != 2) { fprintf (stderr, "usage: %s font-file\n", argv[0]); exit (1); @@ -59,7 +63,6 @@ main (int argc, char **argv) hb_buffer_t *buf; buf = hb_buffer_create (); - bool ret = true; char line[BUFSIZ], out[BUFSIZ]; while (fgets (line, sizeof(line), stdin) != nullptr) { @@ -85,5 +88,7 @@ main (int argc, char **argv) hb_font_destroy (font); +#endif + return !ret; } From eb9798ef733da53e69966054b67752cd8937eb7b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 13:29:55 -0700 Subject: [PATCH 028/138] [config] Dont' compile buffer message API if HB_NO_BUFFER_MESSAGE Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-buffer.cc | 2 ++ src/hb-buffer.hh | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 5dd83fc2c..d1dbd0788 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -1993,6 +1993,7 @@ hb_buffer_diff (hb_buffer_t *buffer, * Debugging. */ +#ifndef HB_NO_BUFFER_MESSAGE /** * hb_buffer_set_message_func: * @buffer: an #hb_buffer_t. @@ -2030,3 +2031,4 @@ hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) vsnprintf (buf, sizeof (buf), fmt, ap); return (bool) this->message_func (this, font, buf, this->message_data); } +#endif diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh index 9aae38dbb..bc0c7eddc 100644 --- a/src/hb-buffer.hh +++ b/src/hb-buffer.hh @@ -124,7 +124,9 @@ struct hb_buffer_t unsigned int context_len[2]; /* Debugging API */ +#ifndef HB_NO_BUFFER_MESSAGE hb_buffer_message_func_t message_func; +#endif void *message_data; hb_destroy_func_t message_destroy; @@ -351,8 +353,9 @@ struct hb_buffer_t { #ifdef HB_NO_BUFFER_MESSAGE return false; -#endif +#else return unlikely (message_func); +#endif } bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4) { From bf9424a9a198b99d49c005536a10f27387630064 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 13:31:35 -0700 Subject: [PATCH 029/138] [config] Don't compile unused layout API if HB_NO_LAYOUT_UNUSED Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-layout.cc | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 1945df4fe..9f3332281 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -311,6 +311,7 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face, } +#ifndef HB_NO_LAYOUT_UNUSED /** * hb_ot_layout_get_attach_points: * @face: The #hb_face_t to work on @@ -333,19 +334,11 @@ hb_ot_layout_get_attach_points (hb_face_t *face, unsigned int *point_count /* IN/OUT */, unsigned int *point_array /* OUT */) { -#ifdef HB_NO_LAYOUT_UNUSED - if (point_count) - *point_count = 0; - return 0; -#endif - return face->table.GDEF->table->get_attach_points (glyph, start_offset, point_count, point_array); } - - /** * hb_ot_layout_get_ligature_carets: * @font: The #hb_font_t to work on @@ -368,12 +361,6 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) { -#ifdef HB_NO_LAYOUT_UNUSED - if (caret_count) - *caret_count = 0; - return 0; -#endif - unsigned int result_caret_count = 0; unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array); if (result) @@ -384,6 +371,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array); return result; } +#endif /* From 231d0257883ec9e8904afae1adfd73f3c225f177 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 14:25:52 -0700 Subject: [PATCH 030/138] [config] Don't compile AAT API if HB_NO_AAT Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-aat-layout.cc | 131 ++++++++++++++----------------------------- src/hb-ot-shape.cc | 19 +++++-- 2 files changed, 56 insertions(+), 94 deletions(-) diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index 0efc2c432..e106c7623 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -25,7 +25,7 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-open-type.hh" +#include "hb.hh" #include "hb-aat-layout.hh" #include "hb-aat-fdsc-table.hh" // Just so we compile it; unused otherwise. @@ -39,6 +39,43 @@ #include "hb-aat-ltag-table.hh" +/* + * hb_aat_apply_context_t + */ + +/* Note: This context is used for kerning, even without AAT, hence the code location + * before HB_NO_AAT conditional below. */ + +AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_, + hb_font_t *font_, + hb_buffer_t *buffer_, + hb_blob_t *blob) : + plan (plan_), + font (font_), + face (font->face), + buffer (buffer_), + sanitizer (), + ankr_table (&Null(AAT::ankr)), + lookup_index (0), + debug_depth (0) +{ + sanitizer.init (blob); + sanitizer.set_num_glyphs (face->get_num_glyphs ()); + sanitizer.start_processing (); + sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX); +} + +AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t () +{ sanitizer.end_processing (); } + +void +AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_) +{ ankr_table = ankr_table_; } + + +#ifndef HB_NO_AAT + + /** * SECTION:hb-aat-layout * @title: hb-aat-layout @@ -134,10 +171,6 @@ static const hb_aat_feature_mapping_t feature_mappings[] = const hb_aat_feature_mapping_t * hb_aat_layout_find_feature_mapping (hb_tag_t tag) { -#ifdef HB_NO_SHAPE_AAT - return nullptr; -#endif - return (const hb_aat_feature_mapping_t *) hb_bsearch (&tag, feature_mappings, ARRAY_LENGTH (feature_mappings), @@ -146,39 +179,6 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag) } -/* - * hb_aat_apply_context_t - */ - -/* Note: This context is used for kerning, even without AAT. */ - -AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_, - hb_font_t *font_, - hb_buffer_t *buffer_, - hb_blob_t *blob) : - plan (plan_), - font (font_), - face (font->face), - buffer (buffer_), - sanitizer (), - ankr_table (&Null(AAT::ankr)), - lookup_index (0), - debug_depth (0) -{ - sanitizer.init (blob); - sanitizer.set_num_glyphs (face->get_num_glyphs ()); - sanitizer.start_processing (); - sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX); -} - -AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t () -{ sanitizer.end_processing (); } - -void -AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_) -{ ankr_table = ankr_table_; } - - /* * mort/morx/kerx/trak */ @@ -188,10 +188,6 @@ void hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, hb_aat_map_t *map) { -#ifdef HB_NO_SHAPE_AAT - return; -#endif - const AAT::morx& morx = *mapper->face->table.morx; if (morx.has_data ()) { @@ -218,10 +214,6 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, hb_bool_t hb_aat_layout_has_substitution (hb_face_t *face) { -#ifdef HB_NO_SHAPE_AAT - return false; -#endif - return face->table.morx->has_data () || face->table.mort->has_data (); } @@ -231,10 +223,6 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { -#ifdef HB_NO_SHAPE_AAT - return; -#endif - hb_blob_t *morx_blob = font->face->table.morx.get_blob (); const AAT::morx& morx = *morx_blob->as (); if (morx.has_data ()) @@ -257,10 +245,6 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, void hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer) { -#ifdef HB_NO_SHAPE_AAT - return; -#endif - unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; hb_glyph_position_t *pos = buffer->pos; @@ -278,10 +262,6 @@ is_deleted_glyph (const hb_glyph_info_t *info) void hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) { -#ifdef HB_NO_SHAPE_AAT - return; -#endif - hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph); } @@ -295,10 +275,6 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) hb_bool_t hb_aat_layout_has_positioning (hb_face_t *face) { -#ifdef HB_NO_SHAPE_AAT - return false; -#endif - return face->table.kerx->has_data (); } @@ -307,10 +283,6 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { -#ifdef HB_NO_SHAPE_AAT - return; -#endif - hb_blob_t *kerx_blob = font->face->table.kerx.get_blob (); const AAT::kerx& kerx = *kerx_blob->as (); @@ -330,10 +302,6 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan, hb_bool_t hb_aat_layout_has_tracking (hb_face_t *face) { -#ifdef HB_NO_SHAPE_AAT - return false; -#endif - return face->table.trak->has_data (); } @@ -342,10 +310,6 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { -#ifdef HB_NO_SHAPE_AAT - return; -#endif - const AAT::trak& trak = *font->face->table.trak; AAT::hb_aat_apply_context_t c (plan, font, buffer); @@ -369,12 +333,6 @@ hb_aat_layout_get_feature_types (hb_face_t *face, unsigned int *feature_count, /* IN/OUT. May be NULL. */ hb_aat_layout_feature_type_t *features /* OUT. May be NULL. */) { -#ifdef HB_NO_SHAPE_AAT - if (feature_count) - *feature_count = 0; - return 0; -#endif - return face->table.feat->get_feature_types (start_offset, feature_count, features); } @@ -391,10 +349,6 @@ hb_ot_name_id_t hb_aat_layout_feature_type_get_name_id (hb_face_t *face, hb_aat_layout_feature_type_t feature_type) { -#ifdef HB_NO_SHAPE_AAT - return HB_OT_NAME_ID_INVALID; -#endif - return face->table.feat->get_feature_name_id (feature_type); } @@ -423,11 +377,8 @@ hb_aat_layout_feature_type_get_selector_infos (hb_face_t hb_aat_layout_feature_selector_info_t *selectors, /* OUT. May be NULL. */ unsigned int *default_index /* OUT. May be NULL. */) { -#ifdef HB_NO_SHAPE_AAT - if (selector_count) - *selector_count = 0; - return 0; -#endif - return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index); } + + +#endif diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index c63c3adee..635fa9403 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -152,13 +152,12 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, if (!plan.apply_kerx && !has_gpos_kern) { /* Apparently Apple applies kerx if GPOS kern was not applied. */ - if (0) - ; #ifndef HB_NO_SHAPE_AAT - else if (hb_aat_layout_has_positioning (face)) + if (hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; + else #endif - else if (hb_ot_layout_has_kerning (face)) + if (hb_ot_layout_has_kerning (face)) plan.apply_kern = true; } @@ -220,9 +219,11 @@ void hb_ot_shape_plan_t::substitute (hb_font_t *font, hb_buffer_t *buffer) const { +#ifndef HB_NO_SHAPE_AAT if (unlikely (apply_morx)) hb_aat_layout_substitute (this, font, buffer); else +#endif map.substitute (this, font, buffer); } @@ -232,15 +233,19 @@ hb_ot_shape_plan_t::position (hb_font_t *font, { if (this->apply_gpos) map.position (this, font, buffer); +#ifndef HB_NO_SHAPE_AAT else if (this->apply_kerx) hb_aat_layout_position (this, font, buffer); +#endif else if (this->apply_kern) hb_ot_layout_kern (this, font, buffer); else _hb_ot_shape_fallback_kern (this, font, buffer); +#ifndef HB_NO_SHAPE_AAT if (this->apply_trak) hb_aat_layout_track (this, font, buffer); +#endif } @@ -336,6 +341,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, feature->value); } +#ifndef HB_NO_SHAPE_AAT if (planner->apply_morx) { hb_aat_map_builder_t *aat_map = &planner->aat_map; @@ -345,6 +351,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, aat_map->add_feature (feature->tag, feature->value); } } +#endif if (planner->shaper->override_features) planner->shaper->override_features (planner); @@ -779,8 +786,10 @@ static inline void hb_ot_substitute_post (const hb_ot_shape_context_t *c) { hb_ot_hide_default_ignorables (c->buffer, c->font); +#ifndef HB_NO_SHAPE_AAT if (c->plan->apply_morx) hb_aat_layout_remove_deleted_glyphs (c->buffer); +#endif if (c->plan->shaper->postprocess_glyphs) c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); @@ -914,8 +923,10 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) /* Finish off. Has to follow a certain order. */ hb_ot_layout_position_finish_advances (c->font, c->buffer); hb_ot_zero_width_default_ignorables (c->buffer); +#ifndef HB_NO_SHAPE_AAT if (c->plan->apply_morx) hb_aat_layout_zero_width_deleted_glyphs (c->buffer); +#endif hb_ot_layout_position_finish_offsets (c->font, c->buffer); /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ From f08066ce9a41469e2a7396f0accd61e1c02e5649 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 14:29:27 -0700 Subject: [PATCH 031/138] [config] One more morx disabling Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-layout.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 9f3332281..1c69e253f 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -385,6 +385,8 @@ OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED, #ifdef HB_NO_OT_LAYOUT_BLACKLIST return false; #endif + +#ifndef HB_NO_SHAPE_AAT /* Mac OS X prefers morx over GSUB. It also ships with various Indic fonts, * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken * GSUB/GPOS tables. Some have GSUB with zero scripts, those are ignored by @@ -402,6 +404,7 @@ OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED, if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') && face->table.morx->has_data ())) return true; +#endif return false; } From 37f8ebff5f1973423c7e4ed9dea88881d0642b61 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 14:33:49 -0700 Subject: [PATCH 032/138] [config] Fixup for AAT ltag table access Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-aat-layout.hh | 8 -------- src/hb-ot-name-table.hh | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/hb-aat-layout.hh b/src/hb-aat-layout.hh index 9a0e4468f..8310bfcc2 100644 --- a/src/hb-aat-layout.hh +++ b/src/hb-aat-layout.hh @@ -78,12 +78,4 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer); -inline hb_language_t -_hb_aat_language_get (hb_face_t *face, - unsigned int i) -{ - return face->table.ltag->get_language (i); -} - - #endif /* HB_AAT_LAYOUT_HH */ diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh index 68d7b3a65..59bf4387f 100644 --- a/src/hb-ot-name-table.hh +++ b/src/hb-ot-name-table.hh @@ -63,7 +63,7 @@ struct NameRecord #ifndef HB_NO_OT_NAME_LANGUAGE_AAT if (p == 0) - return _hb_aat_language_get (face, l); + return face->table.ltag->get_language (l); #endif #endif From d7e27cd65a085a76c85cddd93cea48ce4b7be03f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 14:38:05 -0700 Subject: [PATCH 033/138] [config] Don't use VORG table if HB_NO_OT_FONT_CFF Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-font.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index af9a9a2dc..0707a2ff8 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -148,12 +148,14 @@ hb_ot_get_glyph_v_origin (hb_font_t *font, *x = font->get_glyph_h_advance (glyph) / 2; +#ifndef HB_NO_OT_FONT_CFF const OT::VORG &VORG = *ot_face->VORG; if (VORG.has_data ()) { *y = font->em_scale_y (VORG.get_y_origin (glyph)); return true; } +#endif hb_glyph_extents_t extents = {0}; if (ot_face->glyf->get_extents (glyph, &extents)) From f0b0fd4e78e94315c9d01b9232ebfb09bbfef556 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 14:40:24 -0700 Subject: [PATCH 034/138] Remove dead code --- src/hb-ot-layout.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 1c69e253f..16b2c28f2 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1932,11 +1932,6 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, } #if 0 -static const OT::BASE& _get_base (hb_face_t *face) -{ - return *face->table.BASE; -} - hb_bool_t hb_ot_layout_get_baseline (hb_font_t *font, hb_ot_layout_baseline_t baseline, @@ -1945,9 +1940,8 @@ hb_ot_layout_get_baseline (hb_font_t *font, hb_tag_t language_tag, hb_position_t *coord /* OUT. May be NULL. */) { - const OT::BASE &base = _get_base (font->face); - bool result = base.get_baseline (font, baseline, direction, script_tag, - language_tag, coord); + bool result = font->face->table.BASE->get_baseline (font, baseline, direction, script_tag, + language_tag, coord); /* TODO: Simulate https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags#ideographic-em-box */ if (!result && coord) *coord = 0; From 10bac21bb5b25cf20c2198934e99e444625dfd97 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 18 Jun 2019 15:15:06 -0700 Subject: [PATCH 035/138] [coretext/uniscribe/directwrite] Remove extra semicolons Fixes https://github.com/harfbuzz/harfbuzz/pull/1783 --- src/hb-coretext.cc | 2 +- src/hb-directwrite.cc | 2 +- src/hb-uniscribe.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 20cfe4a60..4a299a6ee 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -652,7 +652,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, DEBUG_MSG (CORETEXT, nullptr, __VA_ARGS__); \ ret = false; \ goto fail; \ - } HB_STMT_END; + } HB_STMT_END bool ret = true; CFStringRef string_ref = nullptr; diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 85ba8b627..9b851148b 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -176,7 +176,7 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) HB_STMT_START { \ DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \ return nullptr; \ - } HB_STMT_END; + } HB_STMT_END if (FAILED (hr)) FAIL ("Failed to load font file from data!"); diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index fceda5244..88f429401 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -724,7 +724,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, HB_STMT_START { \ DEBUG_MSG (UNISCRIBE, nullptr, __VA_ARGS__); \ return false; \ - } HB_STMT_END; + } HB_STMT_END HRESULT hr; From e710888188ff3285a162c25c89d886d9535d9f02 Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Tue, 18 Jun 2019 15:20:38 -0700 Subject: [PATCH 036/138] coretext: remove trailing macro from SCRATCH_RESTORE --- src/hb-coretext.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 4a299a6ee..a57b97026 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -980,7 +980,7 @@ resize_and_retry: #define SCRATCH_RESTORE() \ scratch_size = scratch_size_saved; \ - scratch = scratch_saved; + scratch = scratch_saved { /* Setup glyphs */ SCRATCH_SAVE(); From 631da9d816da381c5fd4b3cc640c41fda736a96f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 15:36:14 -0700 Subject: [PATCH 037/138] [config] Remove tables from hb_face_t for disabled features Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/Makefile.sources | 1 + src/hb-ot-face-table-list.hh | 112 +++++++++++++++++++++++++++++++++++ src/hb-ot-face.cc | 8 +-- src/hb-ot-face.hh | 52 +--------------- src/hb-ot-layout.cc | 2 + 5 files changed, 120 insertions(+), 55 deletions(-) create mode 100644 src/hb-ot-face-table-list.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index af0296b67..ab228ce7e 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -64,6 +64,7 @@ HB_BASE_sources = \ hb-ot-color.cc \ hb-ot-face.cc \ hb-ot-face.hh \ + hb-ot-face-table-list.hh \ hb-ot-font.cc \ hb-ot-gasp-table.hh \ hb-ot-glyf-table.hh \ diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh new file mode 100644 index 000000000..75ce59309 --- /dev/null +++ b/src/hb-ot-face-table-list.hh @@ -0,0 +1,112 @@ +/* + * Copyright © 2007,2008,2009 Red Hat, Inc. + * Copyright © 2012,2013 Google, Inc. + * Copyright © 2019, Facebook 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. + * + * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod + * Facebook Author(s): Behdad Esfahbod + */ + +#ifndef HB_FACE_TABLE_LIST_HH +#define HB_FACE_TABLE_LIST_HH +#endif /* HB_FACE_TABLE_LIST_HH */ /* Dummy header guards */ + +#ifndef HB_OT_ACCELERATOR +#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type) +#define _HB_OT_ACCELERATOR_UNDEF +#endif + + +/* This lists font tables that the hb_face_t will contain and lazily + * load. Don't add a table unless it's used though. This is not + * exactly free. */ + +/* v--- Add new tables in the right place here. */ + + +/* OpenType fundamentals. */ +HB_OT_TABLE (OT, head) +HB_OT_ACCELERATOR (OT, cmap) +HB_OT_ACCELERATOR (OT, hmtx) +HB_OT_ACCELERATOR (OT, post) +HB_OT_TABLE (OT, kern) +HB_OT_ACCELERATOR (OT, name) +HB_OT_TABLE (OT, OS2) +HB_OT_TABLE (OT, STAT) + +/* Vertical layout. */ +HB_OT_ACCELERATOR (OT, vmtx) + +/* TrueType outlines. */ +HB_OT_ACCELERATOR (OT, glyf) + +/* CFF outlines. */ +#ifndef HB_NO_CFF +HB_OT_ACCELERATOR (OT, cff1) +HB_OT_ACCELERATOR (OT, cff2) +HB_OT_TABLE (OT, VORG) +#endif + +/* OpenType variations. */ +HB_OT_TABLE (OT, fvar) +HB_OT_TABLE (OT, avar) +HB_OT_TABLE (OT, MVAR) + +/* OpenType shaping. */ +HB_OT_ACCELERATOR (OT, GDEF) +HB_OT_ACCELERATOR (OT, GSUB) +HB_OT_ACCELERATOR (OT, GPOS) +//HB_OT_TABLE (OT, BASE) +//HB_OT_TABLE (OT, JSTF) + +/* AAT shaping. */ +#ifndef HB_NO_AAT +HB_OT_TABLE (AAT, morx) +HB_OT_TABLE (AAT, mort) +HB_OT_TABLE (AAT, kerx) +HB_OT_TABLE (AAT, ankr) +HB_OT_TABLE (AAT, trak) +HB_OT_TABLE (AAT, lcar) +HB_OT_TABLE (AAT, ltag) +HB_OT_TABLE (AAT, feat) +#endif + +/* OpenType color fonts. */ +#ifndef HB_NO_COLOR +HB_OT_TABLE (OT, COLR) +HB_OT_TABLE (OT, CPAL) +HB_OT_ACCELERATOR (OT, CBDT) +HB_OT_ACCELERATOR (OT, sbix) +HB_OT_ACCELERATOR (OT, SVG) +#endif + +/* OpenType math. */ +#ifndef HB_NO_MATH +HB_OT_TABLE (OT, MATH) +#endif + + +#ifdef _HB_OT_ACCELERATOR_UNDEF +#undef HB_OT_ACCELERATOR +#endif diff --git a/src/hb-ot-face.cc b/src/hb-ot-face.cc index 9b17526b7..f54d0b639 100644 --- a/src/hb-ot-face.cc +++ b/src/hb-ot-face.cc @@ -46,16 +46,12 @@ void hb_ot_face_t::init0 (hb_face_t *face) { this->face = face; #define HB_OT_TABLE(Namespace, Type) Type.init0 (); -#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type) - HB_OT_TABLES -#undef HB_OT_ACCELERATOR +#include "hb-ot-face-table-list.hh" #undef HB_OT_TABLE } void hb_ot_face_t::fini () { #define HB_OT_TABLE(Namespace, Type) Type.fini (); -#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type) - HB_OT_TABLES -#undef HB_OT_ACCELERATOR +#include "hb-ot-face-table-list.hh" #undef HB_OT_TABLE } diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh index 7f47ba6cb..e24d380bc 100644 --- a/src/hb-ot-face.hh +++ b/src/hb-ot-face.hh @@ -38,54 +38,10 @@ * hb_ot_face_t */ -#define HB_OT_TABLES \ - /* OpenType fundamentals. */ \ - HB_OT_TABLE(OT, head) \ - HB_OT_ACCELERATOR(OT, cmap) \ - HB_OT_ACCELERATOR(OT, hmtx) \ - HB_OT_ACCELERATOR(OT, vmtx) \ - HB_OT_ACCELERATOR(OT, post) \ - HB_OT_TABLE(OT, kern) \ - HB_OT_ACCELERATOR(OT, glyf) \ - HB_OT_ACCELERATOR(OT, cff1) \ - HB_OT_ACCELERATOR(OT, cff2) \ - HB_OT_TABLE(OT, VORG) \ - HB_OT_ACCELERATOR(OT, name) \ - HB_OT_TABLE(OT, OS2) \ - HB_OT_TABLE(OT, STAT) \ - /* OpenType shaping. */ \ - HB_OT_ACCELERATOR(OT, GDEF) \ - HB_OT_ACCELERATOR(OT, GSUB) \ - HB_OT_ACCELERATOR(OT, GPOS) \ - HB_OT_TABLE(OT, BASE) \ - HB_OT_TABLE(OT, JSTF) \ - /* AAT shaping. */ \ - HB_OT_TABLE(AAT, mort) \ - HB_OT_TABLE(AAT, morx) \ - HB_OT_TABLE(AAT, kerx) \ - HB_OT_TABLE(AAT, ankr) \ - HB_OT_TABLE(AAT, trak) \ - HB_OT_TABLE(AAT, lcar) \ - HB_OT_TABLE(AAT, ltag) \ - HB_OT_TABLE(AAT, feat) \ - /* OpenType variations. */ \ - HB_OT_TABLE(OT, fvar) \ - HB_OT_TABLE(OT, avar) \ - HB_OT_TABLE(OT, MVAR) \ - /* OpenType math. */ \ - HB_OT_TABLE(OT, MATH) \ - /* OpenType color fonts. */ \ - HB_OT_TABLE(OT, COLR) \ - HB_OT_TABLE(OT, CPAL) \ - HB_OT_ACCELERATOR(OT, CBDT) \ - HB_OT_ACCELERATOR(OT, sbix) \ - HB_OT_ACCELERATOR(OT, SVG) \ - /* */ - /* Declare tables. */ #define HB_OT_TABLE(Namespace, Type) namespace Namespace { struct Type; } #define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type##_accelerator_t) -HB_OT_TABLES +#include "hb-ot-face-table-list.hh" #undef HB_OT_ACCELERATOR #undef HB_OT_TABLE @@ -100,9 +56,7 @@ struct hb_ot_face_t { ORDER_ZERO, #define HB_OT_TABLE(Namespace, Type) HB_OT_TABLE_ORDER (Namespace, Type), -#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type) - HB_OT_TABLES -#undef HB_OT_ACCELERATOR +#include "hb-ot-face-table-list.hh" #undef HB_OT_TABLE }; @@ -111,7 +65,7 @@ struct hb_ot_face_t hb_table_lazy_loader_t Type; #define HB_OT_ACCELERATOR(Namespace, Type) \ hb_face_lazy_loader_t Type; - HB_OT_TABLES +#include "hb-ot-face-table-list.hh" #undef HB_OT_ACCELERATOR #undef HB_OT_TABLE }; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 16b2c28f2..0e75049c8 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -367,8 +367,10 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, { if (caret_count) *caret_count = result_caret_count; } +#ifndef HB_NO_AAT else result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array); +#endif return result; } #endif From 2e3e929d2b0fa6026c55eb92f91de0498fb22646 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 15:50:13 -0700 Subject: [PATCH 038/138] Fix build --- src/hb-ot-face-table-list.hh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index 75ce59309..74ee1985e 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -28,9 +28,9 @@ * Facebook Author(s): Behdad Esfahbod */ -#ifndef HB_FACE_TABLE_LIST_HH -#define HB_FACE_TABLE_LIST_HH -#endif /* HB_FACE_TABLE_LIST_HH */ /* Dummy header guards */ +#ifndef HB_OT_FACE_TABLE_LIST_HH +#define HB_OT_FACE_TABLE_LIST_HH +#endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */ #ifndef HB_OT_ACCELERATOR #define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type) From 588697afd0ddf411e8201866ade1f593ccb61aab Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 16:24:51 -0700 Subject: [PATCH 039/138] [config] Add HB_NO_OT_KERN, enabled by HB_MINI / HB_NO_LEGACY Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-ot-face-table-list.hh | 6 +++++- src/hb-ot-layout.cc | 4 ++-- src/hb-ot-shape.cc | 16 ++++++++++++++-- src/hb-ot-shape.hh | 4 ++++ 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/hb-config.hh b/src/hb-config.hh index c1a15f86e..e02694bef 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -101,6 +101,7 @@ #ifdef HB_NO_LEGACY #define HB_NO_FALLBACK_SHAPE +#define HB_NO_OT_KERN #define HB_NO_OT_LAYOUT_BLACKLIST #define HB_NO_OT_SHAPE_FALLBACK #endif diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index 74ee1985e..1dcfad4c9 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -50,7 +50,6 @@ HB_OT_TABLE (OT, head) HB_OT_ACCELERATOR (OT, cmap) HB_OT_ACCELERATOR (OT, hmtx) HB_OT_ACCELERATOR (OT, post) -HB_OT_TABLE (OT, kern) HB_OT_ACCELERATOR (OT, name) HB_OT_TABLE (OT, OS2) HB_OT_TABLE (OT, STAT) @@ -73,6 +72,11 @@ HB_OT_TABLE (OT, fvar) HB_OT_TABLE (OT, avar) HB_OT_TABLE (OT, MVAR) +/* Legacy kern. */ +#ifndef HB_NO_OT_KERN +HB_OT_TABLE (OT, kern) +#endif + /* OpenType shaping. */ HB_OT_ACCELERATOR (OT, GDEF) HB_OT_ACCELERATOR (OT, GSUB) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 0e75049c8..0761b8e53 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -62,6 +62,7 @@ * kern */ +#ifndef HB_NO_OT_KERN /** * hb_ot_layout_has_kerning: * @face: The #hb_face_t to work on @@ -78,7 +79,6 @@ hb_ot_layout_has_kerning (hb_face_t *face) return face->table.kern->has_data (); } - /** * hb_ot_layout_has_machine_kerning: * @face: The #hb_face_t to work on @@ -95,7 +95,6 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face) return face->table.kern->has_state_machine (); } - /** * hb_ot_layout_has_cross_kerning: * @face: The #hb_face_t to work on @@ -128,6 +127,7 @@ hb_ot_layout_kern (const hb_ot_shape_plan_t *plan, kern.apply (&c); } +#endif /* diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 635fa9403..f5f1ae6cc 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -157,18 +157,28 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.apply_kerx = true; else #endif +#ifndef HB_NO_OT_KERN if (hb_ot_layout_has_kerning (face)) plan.apply_kern = true; +#endif } plan.zero_marks = script_zero_marks && !plan.apply_kerx && - (!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face)); + (!plan.apply_kern +#ifndef HB_NO_OT_KERN + || !hb_ot_layout_has_machine_kerning (face) +#endif + ); plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k')); plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos && !plan.apply_kerx && - (!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face)); + (!plan.apply_kern +#ifndef HB_NO_OT_KERN + || !hb_ot_layout_has_cross_kerning (face) +#endif + ); plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing && script_fallback_mark_positioning; @@ -237,8 +247,10 @@ hb_ot_shape_plan_t::position (hb_font_t *font, else if (this->apply_kerx) hb_aat_layout_position (this, font, buffer); #endif +#ifndef HB_NO_OT_KERN else if (this->apply_kern) hb_ot_layout_kern (this, font, buffer); +#endif else _hb_ot_shape_fallback_kern (this, font, buffer); diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index b7c0f1065..09164427e 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -80,7 +80,11 @@ struct hb_ot_shape_plan_t bool adjust_mark_positioning_when_zeroing : 1; bool apply_gpos : 1; +#ifndef HB_NO_OT_KERN bool apply_kern : 1; +#else + static constexpr bool apply_kern = false; +#endif #ifndef HB_NO_SHAPE_AAT bool apply_kerx : 1; bool apply_morx : 1; From d2ff73b256599a655e4ddedbe1ca75abdf837d23 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 16:28:08 -0700 Subject: [PATCH 040/138] [config] Remove remaining AAT context bits if HB_NO_OT_KERN Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-aat-layout.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index e106c7623..c08bb11f4 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -43,8 +43,8 @@ * hb_aat_apply_context_t */ -/* Note: This context is used for kerning, even without AAT, hence the code location - * before HB_NO_AAT conditional below. */ +/* Note: This context is used for kerning, even without AAT, hence the condition. */ +#if !defined(HB_NO_AAT) || !defined(HB_NO_OT_KERN) AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_, hb_font_t *font_, @@ -72,6 +72,8 @@ void AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_) { ankr_table = ankr_table_; } +#endif + #ifndef HB_NO_AAT From f642a5fa6c42b145574593a0e18815dc74d3c617 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 16:36:09 -0700 Subject: [PATCH 041/138] Restructure code --- src/hb-ot-tag.cc | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index 61b609d5e..e3d1aa732 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -305,28 +305,24 @@ parse_private_use_subtag (const char *private_use_subtag, const char *prefix, unsigned char (*normalize) (unsigned char)) { - if (private_use_subtag && count && tags && *count) - { - const char *s = strstr (private_use_subtag, prefix); - if (s) - { - char tag[4]; - int i; - s += strlen (prefix); - for (i = 0; i < 4 && ISALNUM (s[i]); i++) - tag[i] = normalize (s[i]); - if (i) - { - for (; i < 4; i++) - tag[i] = ' '; - tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]); - if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT) - tags[0] ^= ~0xDFDFDFDF; - *count = 1; - return false; - } - } - } + if (!(private_use_subtag && count && tags && *count)) return false; + + const char *s = strstr (private_use_subtag, prefix); + if (!s) return false; + + char tag[4]; + int i; + s += strlen (prefix); + for (i = 0; i < 4 && ISALNUM (s[i]); i++) + tag[i] = normalize (s[i]); + if (!i) return false; + + for (; i < 4; i++) + tag[i] = ' '; + tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]); + if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT) + tags[0] ^= ~0xDFDFDFDF; + *count = 1; return true; } @@ -394,8 +390,8 @@ hb_ot_tags_from_script_and_language (hb_script_t script, limit = s; } - needs_script = parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER); - needs_language = parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER); + needs_script = !parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER); + needs_language = !parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER); if (needs_language && language_count && language_tags && *language_count) hb_ot_tags_from_language (lang_str, limit, language_count, language_tags); From 971330c0588307bcd73934e44c6343db55b1f5b6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 16:37:35 -0700 Subject: [PATCH 042/138] [config] Add HB_NO_LANGUAGE_PRIVATE_SUBTAG Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-ot-tag.cc | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/hb-config.hh b/src/hb-config.hh index e02694bef..381146c55 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -58,6 +58,7 @@ #define HB_NO_CFF #define HB_NO_COLOR #define HB_NO_GETENV +#define HB_NO_LANGUAGE_PRIVATE_SUBTAG #define HB_NO_LAYOUT_UNUSED #define HB_NO_MATH #define HB_NO_MMAP diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index e3d1aa732..e63045894 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -305,6 +305,10 @@ parse_private_use_subtag (const char *private_use_subtag, const char *prefix, unsigned char (*normalize) (unsigned char)) { +#ifdef HB_NO_LANGUAGE_PRIVATE_SUBTAG + return false; +#endif + if (!(private_use_subtag && count && tags && *count)) return false; const char *s = strstr (private_use_subtag, prefix); From eaf4a7364c28663720a9da57bf4d576b6009e17d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 16:51:13 -0700 Subject: [PATCH 043/138] [config] Minor trak disable Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-shape.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index f5f1ae6cc..e11dc15ce 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -317,10 +317,12 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, /* Random! */ map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE); +#ifndef HB_NO_SHAPE_AAT /* Tracking. We enable dummy feature here just to allow disabling * AAT 'trak' table using features. * https://github.com/harfbuzz/harfbuzz/issues/1303 */ map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK); +#endif map->enable_feature (HB_TAG ('H','A','R','F')); From d84932ba50482b3b47e393714eb77b19173d1f14 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 16:57:48 -0700 Subject: [PATCH 044/138] [config] add HB_NO_OT_SHAPE_FRACTIONS, enabled in HB_LEAN Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-ot-shape.cc | 9 +++++++++ src/hb-ot-shape.hh | 10 ++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/hb-config.hh b/src/hb-config.hh index 381146c55..2ff92ced3 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -65,6 +65,7 @@ #define HB_NO_NAME #define HB_NO_OPEN #define HB_NO_SETLOCALE +#define HB_NO_OT_SHAPE_FRACTIONS #define HB_NO_SUBSET_LAYOUT #endif diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index e11dc15ce..4bc91c2ef 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -101,10 +101,13 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, if (apply_morx) aat_map.compile (plan.aat_map); +#ifndef HB_NO_OT_SHAPE_FRACTIONS plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r')); plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m')); plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask); +#endif + plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ? HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'); @@ -309,10 +312,12 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, break; } +#ifndef HB_NO_OT_SHAPE_FRACTIONS /* Automatic fractions. */ map->add_feature (HB_TAG ('f','r','a','c')); map->add_feature (HB_TAG ('n','u','m','r')); map->add_feature (HB_TAG ('d','n','o','m')); +#endif /* Random! */ map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE); @@ -590,6 +595,10 @@ hb_ot_mirror_chars (const hb_ot_shape_context_t *c) static inline void hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c) { +#ifdef HB_NO_OT_SHAPE_FRACTIONS + return; +#endif + if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) || !c->plan->has_frac) return; diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index 09164427e..452da635d 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -65,14 +65,24 @@ struct hb_ot_shape_plan_t hb_ot_map_t map; hb_aat_map_t aat_map; const void *data; +#ifndef HB_NO_OT_SHAPE_FRACTIONS hb_mask_t frac_mask, numr_mask, dnom_mask; +#else + static constexpr hb_mask_t frac_mask = 0; + static constexpr hb_mask_t numr_mask = 0; + static constexpr hb_mask_t dnom_mask = 0; +#endif hb_mask_t rtlm_mask; hb_mask_t kern_mask; hb_mask_t trak_mask; bool requested_kerning : 1; bool requested_tracking : 1; +#ifndef HB_NO_OT_SHAPE_FRACTIONS bool has_frac : 1; +#else + static constexpr bool has_frac = false; +#endif bool has_gpos_mark : 1; bool zero_marks : 1; bool fallback_glyph_classes : 1; From 43d7048d59b1a0af62b80bd914805bdec74a29d2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 17:02:32 -0700 Subject: [PATCH 045/138] [config] More trak disabling Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-shape.cc | 4 +++- src/hb-ot-shape.hh | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 4bc91c2ef..d397dded1 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -112,10 +112,12 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ? HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'); plan.kern_mask = plan.map.get_mask (kern_tag); +#ifndef HB_NO_SHAPE_AAT plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k')); + plan.requested_tracking = !!plan.trak_mask; +#endif plan.requested_kerning = !!plan.kern_mask; - plan.requested_tracking = !!plan.trak_mask; bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX; bool disable_gpos = plan.shaper->gpos_tag && plan.shaper->gpos_tag != plan.map.chosen_script[1]; diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index 452da635d..01f6afa3d 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -74,10 +74,18 @@ struct hb_ot_shape_plan_t #endif hb_mask_t rtlm_mask; hb_mask_t kern_mask; +#ifndef HB_NO_SHAPE_AAT hb_mask_t trak_mask; +#else + static constexpr hb_mask_t trak_mask = 0; +#endif bool requested_kerning : 1; +#ifndef HB_NO_SHAPE_AAT bool requested_tracking : 1; +#else + static constexpr bool requested_tracking = false; +#endif #ifndef HB_NO_OT_SHAPE_FRACTIONS bool has_frac : 1; #else From d8bf6723a1176ca26e97e8015044c8829ec77c36 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 17:04:16 -0700 Subject: [PATCH 046/138] [config] Disable more legacy kerning Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-shape.cc | 4 +++- src/hb-ot-shape.hh | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index d397dded1..20dbac2be 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -111,13 +111,15 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ? HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'); +#ifndef HB_NO_OT_KERN plan.kern_mask = plan.map.get_mask (kern_tag); + plan.requested_kerning = !!plan.kern_mask; +#endif #ifndef HB_NO_SHAPE_AAT plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k')); plan.requested_tracking = !!plan.trak_mask; #endif - plan.requested_kerning = !!plan.kern_mask; bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX; bool disable_gpos = plan.shaper->gpos_tag && plan.shaper->gpos_tag != plan.map.chosen_script[1]; diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index 01f6afa3d..fec8983c6 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -73,14 +73,22 @@ struct hb_ot_shape_plan_t static constexpr hb_mask_t dnom_mask = 0; #endif hb_mask_t rtlm_mask; +#ifndef HB_NO_OT_KERN hb_mask_t kern_mask; +#else + static constexpr hb_mask_t kern_mask = 0; +#endif #ifndef HB_NO_SHAPE_AAT hb_mask_t trak_mask; #else static constexpr hb_mask_t trak_mask = 0; #endif +#ifndef HB_NO_OT_KERN bool requested_kerning : 1; +#else + static constexpr bool requested_kerning = false; +#endif #ifndef HB_NO_SHAPE_AAT bool requested_tracking : 1; #else From f4de0c775408e34474a688361fa319251e1a9c18 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 17:08:26 -0700 Subject: [PATCH 047/138] [config] Disable AAT map Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-aat-map.cc | 15 +++++++-------- src/hb-ot-shape.cc | 6 ++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/hb-aat-map.cc b/src/hb-aat-map.cc index d57ee849d..e16ecfe04 100644 --- a/src/hb-aat-map.cc +++ b/src/hb-aat-map.cc @@ -26,6 +26,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_SHAPE_AAT + #include "hb-aat-map.hh" #include "hb-aat-layout.hh" @@ -34,10 +38,6 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned int value) { -#ifdef HB_NO_SHAPE_AAT - return; -#endif - if (tag == HB_TAG ('a','a','l','t')) { feature_info_t *info = features.push(); @@ -57,10 +57,6 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag, void hb_aat_map_builder_t::compile (hb_aat_map_t &m) { -#ifdef HB_NO_SHAPE_AAT - return; -#endif - /* Sort features and merge duplicates */ if (features.length) { @@ -74,3 +70,6 @@ hb_aat_map_builder_t::compile (hb_aat_map_t &m) hb_aat_layout_compile_map (this, &m); } + + +#endif diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 20dbac2be..7690c2229 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -98,8 +98,10 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.props = props; plan.shaper = shaper; map.compile (plan.map, key); +#ifndef HB_NO_SHAPE_AAT if (apply_morx) aat_map.compile (plan.aat_map); +#endif #ifndef HB_NO_OT_SHAPE_FRACTIONS plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); @@ -201,7 +203,9 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face, const hb_shape_plan_key_t *key) { map.init (); +#ifndef HB_NO_SHAPE_AAT aat_map.init (); +#endif hb_ot_shape_planner_t planner (face, &key->props); @@ -229,7 +233,9 @@ hb_ot_shape_plan_t::fini () shaper->data_destroy (const_cast (data)); map.fini (); +#ifndef HB_NO_SHAPE_AAT aat_map.fini (); +#endif } void From b1a2384a5244ea3ea63ca94eb095c4add2cd451d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 17:34:12 -0700 Subject: [PATCH 048/138] [ucd] Print out table sizes --- src/gen-ucd-table.py | 27 +++++++++++++++++++-------- src/hb-ucd-table.hh | 1 - 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py index 967e000d4..c98c715e1 100755 --- a/src/gen-ucd-table.py +++ b/src/gen-ucd-table.py @@ -3,19 +3,22 @@ from __future__ import print_function, division, absolute_import import io, os.path, sys, re +import logging +logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) if len (sys.argv) != 2: print("usage: ./gen-ucd-table ucd.nonunihan.grouped.xml", file=sys.stderr) sys.exit(1) - # https://github.com/harfbuzz/packtab import packTab import packTab.ucdxml +logging.info('Loading UCDXML...') ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1]) ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml) +logging.info('Preparing data tables...') gc = [u['gc'] for u in ucd] ccc = [int(u['ccc']) for u in ucd] @@ -71,6 +74,7 @@ DEFAULT = 1 COMPACT = 3 +logging.info('Generating output...') print("/* == Start of generated table == */") print("/*") print(" * The following table is generated by running:") @@ -82,8 +86,6 @@ print(" */") print() print("#ifndef HB_UCD_TABLE_HH") print("#define HB_UCD_TABLE_HH") -print() - print() print('#include "hb.hh"') print() @@ -95,7 +97,16 @@ dm1_32_array, _ = code.addArray('uint32_t', 'dm1_u32_map', dm1_u32_array) dm2_array, _ = code.addArray('uint64_t', 'dm2_map', dm2_array) code.print_c(linkage='static inline') +datasets = [ + ('gc', gc, 'Cn', gc_order), + ('ccc', ccc, 0, None), + ('bmg', bmg, 0, None), + ('sc', sc, 'Zzzz', sc_order), + ('dm', dm, None, dm_order), +] + for compression in (DEFAULT, COMPACT): + logging.info(' Compression=%d:' % compression) print() if compression == DEFAULT: print('#ifndef HB_OPTIMIZE_SIZE') @@ -105,11 +116,10 @@ for compression in (DEFAULT, COMPACT): code = packTab.Code('_hb_ucd') - packTab.pack_table(gc, 'Cn', mapping=gc_order, compression=compression).genCode(code, 'gc') - packTab.pack_table(ccc, 0, compression=compression).genCode(code, 'ccc') - packTab.pack_table(bmg, 0, compression=compression).genCode(code, 'bmg') - packTab.pack_table(sc, 'Zzzz', mapping=sc_order, compression=compression).genCode(code, 'sc') - packTab.pack_table(dm, None, mapping=dm_order, compression=compression).genCode(code, 'dm') + for name,data,default,mapping in datasets: + sol = packTab.pack_table(data, default, mapping=mapping, compression=compression) + logging.info(' Dataset=%-8s FullCost=%d' % (name, sol.fullCost)) + sol.genCode(code, name) code.print_c(linkage='static inline') @@ -123,3 +133,4 @@ print() print("#endif /* HB_UCD_TABLE_HH */") print() print("/* == End of generated table == */") +logging.info('Done.') diff --git a/src/hb-ucd-table.hh b/src/hb-ucd-table.hh index ae339ec0c..e9d097542 100644 --- a/src/hb-ucd-table.hh +++ b/src/hb-ucd-table.hh @@ -10,7 +10,6 @@ #ifndef HB_UCD_TABLE_HH #define HB_UCD_TABLE_HH - #include "hb.hh" static const hb_script_t From 1432df102ebf206592f92677f48bb950871675b3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 18:32:40 -0700 Subject: [PATCH 049/138] [config] Disable hb-ot-font code if HB_NO_OT_FONT Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-font.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 0707a2ff8..5895c7b6b 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -26,6 +26,8 @@ #include "hb.hh" +#ifndef HB_NO_OT_FONT + #include "hb-ot.h" #include "hb-font.hh" @@ -317,3 +319,6 @@ hb_ot_font_set_funcs (hb_font_t *font) &font->face->table, nullptr); } + + +#endif From ffc2b8d56e5d35b4dc19499c830d8fc4b643213a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 18:33:29 -0700 Subject: [PATCH 050/138] [config] Don't include name table in face if HB_NO_NAME Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-ot-face-table-list.hh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index 1dcfad4c9..6185b67cc 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -50,8 +50,10 @@ HB_OT_TABLE (OT, head) HB_OT_ACCELERATOR (OT, cmap) HB_OT_ACCELERATOR (OT, hmtx) HB_OT_ACCELERATOR (OT, post) -HB_OT_ACCELERATOR (OT, name) HB_OT_TABLE (OT, OS2) +#ifndef HB_NO_NAME +HB_OT_ACCELERATOR (OT, name) +#endif HB_OT_TABLE (OT, STAT) /* Vertical layout. */ From a5897463d4d0b83cb1bfe4ae1477dac4e3851252 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 18:36:35 -0700 Subject: [PATCH 051/138] [config] Add HB_NO_STAT Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-ot-face-table-list.hh | 2 ++ src/hb-subset-plan.cc | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/hb-config.hh b/src/hb-config.hh index 2ff92ced3..3aa48b4b0 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -66,6 +66,7 @@ #define HB_NO_OPEN #define HB_NO_SETLOCALE #define HB_NO_OT_SHAPE_FRACTIONS +#define HB_NO_STAT #define HB_NO_SUBSET_LAYOUT #endif diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index 6185b67cc..4e73db566 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -54,7 +54,9 @@ HB_OT_TABLE (OT, OS2) #ifndef HB_NO_NAME HB_OT_ACCELERATOR (OT, name) #endif +#ifndef HB_NO_STAT HB_OT_TABLE (OT, STAT) +#endif /* Vertical layout. */ HB_OT_ACCELERATOR (OT, vmtx) diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 7c1ed872c..baf6a19e9 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -201,9 +201,11 @@ _nameid_closure (hb_face_t *face, { hb_tag_t tag = table_tags[i]; switch (tag) { +#ifndef HB_NO_STAT case HB_OT_TAG_STAT: face->table.STAT->collect_name_ids (nameids); break; +#endif case HB_OT_TAG_fvar: face->table.fvar->collect_name_ids (nameids); break; From b0debc32f6cedfa76a4851aa391f88ed1860955d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 18:42:39 -0700 Subject: [PATCH 052/138] [subset] Simplify collect_name_ids --- src/hb-subset-plan.cc | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index baf6a19e9..f4877332b 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -194,25 +194,10 @@ static void _nameid_closure (hb_face_t *face, hb_set_t *nameids) { - hb_tag_t table_tags[32]; - unsigned count = ARRAY_LENGTH (table_tags); - hb_face_get_table_tags (face, 0, &count, table_tags); - for (unsigned int i = 0; i < count; i++) - { - hb_tag_t tag = table_tags[i]; - switch (tag) { #ifndef HB_NO_STAT - case HB_OT_TAG_STAT: - face->table.STAT->collect_name_ids (nameids); - break; + face->table.STAT->collect_name_ids (nameids); #endif - case HB_OT_TAG_fvar: - face->table.fvar->collect_name_ids (nameids); - break; - default: - break; - } - } + face->table.fvar->collect_name_ids (nameids); } /** From 230adf2c417bbb6b5f367eb857dd6f98bea3ef26 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 18:49:52 -0700 Subject: [PATCH 053/138] [config] Add HB_NO_OT_FONT_GLYPH_NAMES Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-ot-face-table-list.hh | 4 +++- src/hb-ot-font.cc | 5 ++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hb-config.hh b/src/hb-config.hh index 3aa48b4b0..3f9a9ca6f 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -58,6 +58,7 @@ #define HB_NO_CFF #define HB_NO_COLOR #define HB_NO_GETENV +#define HB_NO_OT_FONT_GLYPH_NAMES #define HB_NO_LANGUAGE_PRIVATE_SUBTAG #define HB_NO_LAYOUT_UNUSED #define HB_NO_MATH diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index 4e73db566..348c3b299 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -49,8 +49,10 @@ HB_OT_TABLE (OT, head) HB_OT_ACCELERATOR (OT, cmap) HB_OT_ACCELERATOR (OT, hmtx) -HB_OT_ACCELERATOR (OT, post) HB_OT_TABLE (OT, OS2) +#ifndef HB_NO_OT_FONT_GLYPH_NAMES +HB_OT_ACCELERATOR (OT, post) +#endif #ifndef HB_NO_NAME HB_OT_ACCELERATOR (OT, name) #endif diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 5895c7b6b..999bfac29 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -205,6 +205,7 @@ hb_ot_get_glyph_extents (hb_font_t *font, return ret; } +#ifndef HB_NO_OT_FONT_GLYPH_NAMES static hb_bool_t hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, void *font_data, @@ -215,7 +216,6 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; return ot_face->post->get_glyph_name (glyph, name, size); } - static hb_bool_t hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, void *font_data, @@ -226,6 +226,7 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; return ot_face->post->get_glyph_from_name (name, len, glyph); } +#endif static hb_bool_t hb_ot_get_font_h_extents (hb_font_t *font, @@ -278,8 +279,10 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t Date: Wed, 19 Jun 2019 19:26:22 -0700 Subject: [PATCH 054/138] [config] Add HB_NO_VAR to disable variations support, enabled by HB_TINY Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-font.cc | 3 ++- src/hb-ot-face-table-list.hh | 2 ++ src/hb-ot-layout-common.hh | 34 ++++++++++++++++++++++++++++------ src/hb-ot-layout-gsubgpos.hh | 18 +++++++++++++++--- src/hb-ot-var.cc | 7 ++++++- src/hb-subset-plan.cc | 2 ++ 7 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/hb-config.hh b/src/hb-config.hh index 3f9a9ca6f..8f78ede21 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -69,6 +69,7 @@ #define HB_NO_OT_SHAPE_FRACTIONS #define HB_NO_STAT #define HB_NO_SUBSET_LAYOUT +#define HB_NO_VAR #endif #ifdef HB_MINI diff --git a/src/hb-font.cc b/src/hb-font.cc index 7eee284e6..f450d8889 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1824,6 +1824,7 @@ _hb_font_adopt_var_coords_normalized (hb_font_t *font, font->num_coords = coords_length; } +#ifndef HB_NO_VAR /** * hb_font_set_variations: * @@ -1854,7 +1855,6 @@ hb_font_set_variations (hb_font_t *font, normalized, coords_length); _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); } - /** * hb_font_set_var_coords_design: * @@ -1875,6 +1875,7 @@ hb_font_set_var_coords_design (hb_font_t *font, hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized); _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); } +#endif /** * hb_font_set_var_coords_normalized: diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index 348c3b299..e4ed6b07d 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -74,9 +74,11 @@ HB_OT_TABLE (OT, VORG) #endif /* OpenType variations. */ +#ifndef HB_NO_VAR HB_OT_TABLE (OT, fvar) HB_OT_TABLE (OT, avar) HB_OT_TABLE (OT, MVAR) +#endif /* Legacy kern. */ #ifndef HB_NO_OT_KERN diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index f801f5af8..c332e2815 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -1747,11 +1747,11 @@ struct VarData float *scalars /*OUT */, unsigned int num_scalars) const { - assert (num_scalars == regionIndices.len); - for (unsigned int i = 0; i < num_scalars; i++) - { - scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count); - } + unsigned count = hb_min (num_scalars, regionIndices.len); + for (unsigned int i = 0; i < count; i++) + scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count); + for (unsigned int i = count; i < num_scalars; i++) + scalars[i] = 0.f; } bool sanitize (hb_sanitize_context_t *c) const @@ -1779,8 +1779,12 @@ struct VariationStore float get_delta (unsigned int outer, unsigned int inner, const int *coords, unsigned int coord_count) const { +#ifdef HB_NO_VAR + return 0.f; +#endif + if (unlikely (outer >= dataSets.len)) - return 0.; + return 0.f; return (this+dataSets[outer]).get_delta (inner, coords, coord_count, @@ -1797,6 +1801,10 @@ struct VariationStore bool sanitize (hb_sanitize_context_t *c) const { +#ifdef HB_NO_VAR + return true; +#endif + TRACE_SANITIZE (this); return_trace (c->check_struct (this) && format == 1 && @@ -1812,6 +1820,12 @@ struct VariationStore float *scalars /*OUT*/, unsigned int num_scalars) const { +#ifdef HB_NO_VAR + for (unsigned i = 0; i < num_scalars; i++) + scalars[i] = 0.f; + return; +#endif + (this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions, &scalars[0], num_scalars); } @@ -2154,8 +2168,10 @@ struct Device { case 1: case 2: case 3: return u.hinting.get_x_delta (font); +#ifndef HB_NO_VAR case 0x8000: return u.variation.get_x_delta (font, store); +#endif default: return 0; } @@ -2166,8 +2182,10 @@ struct Device { case 1: case 2: case 3: return u.hinting.get_y_delta (font); +#ifndef HB_NO_VAR case 0x8000: return u.variation.get_y_delta (font, store); +#endif default: return 0; } @@ -2180,8 +2198,10 @@ struct Device switch (u.b.format) { case 1: case 2: case 3: return_trace (u.hinting.sanitize (c)); +#ifndef HB_NO_VAR case 0x8000: return_trace (u.variation.sanitize (c)); +#endif default: return_trace (true); } @@ -2191,7 +2211,9 @@ struct Device union { DeviceHeader b; HintingDevice hinting; +#ifndef HB_NO_VAR VariationDevice variation; +#endif } u; public: DEFINE_SIZE_UNION (6, b); diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 4bc3d7e15..dd54c9b34 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -2661,11 +2661,17 @@ struct GSUBGPOS bool find_variations_index (const int *coords, unsigned int num_coords, unsigned int *index) const - { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations)) - .find_index (coords, num_coords, index); } + { +#ifdef HB_NOVAR + return false; +#endif + return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations)) + .find_index (coords, num_coords, index); + } const Feature& get_feature_variation (unsigned int feature_index, unsigned int variations_index) const { +#ifndef HB_NO_VAR if (FeatureVariations::NOT_FOUND_INDEX != variations_index && version.to_int () >= 0x00010001u) { @@ -2674,6 +2680,7 @@ struct GSUBGPOS if (feature) return *feature; } +#endif return get_feature (feature_index); } @@ -2695,8 +2702,10 @@ struct GSUBGPOS this, out); +#ifndef HB_NO_VAR if (version.to_int () >= 0x00010001u) out->featureVars.serialize_copy (c->serializer, featureVars, this, out); +#endif return_trace (true); } @@ -2717,7 +2726,10 @@ struct GSUBGPOS scriptList.sanitize (c, this) && featureList.sanitize (c, this) && CastR> (lookupList).sanitize (c, this) && - (version.to_int () < 0x00010001u || featureVars.sanitize (c, this))); +#ifndef HB_NO_VAR + (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)) && +#endif + true); } template diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index 5eea90d25..6b8b09b6b 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -24,7 +24,9 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-open-type.hh" +#include "hb.hh" + +#ifndef HB_NO_VAR #include "hb-ot-var.h" @@ -213,3 +215,6 @@ hb_ot_var_normalize_coords (hb_face_t *face, face->table.avar->map_coords (normalized_coords, coords_length); } + + +#endif diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index f4877332b..6b33c17b6 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -197,7 +197,9 @@ _nameid_closure (hb_face_t *face, #ifndef HB_NO_STAT face->table.STAT->collect_name_ids (nameids); #endif +#ifndef HB_NO_VAR face->table.fvar->collect_name_ids (nameids); +#endif } /** From c8f529a07eca06acf2216935921377e7cad8436f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 19:33:15 -0700 Subject: [PATCH 055/138] [config] Add HB_NO_HINTING, enabled by HB_TINY Disables HintingDevice tables and Anchors addressing contour points. Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 3 ++- src/hb-ot-layout-common.hh | 6 ++++++ src/hb-ot-layout-gpos-table.hh | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/hb-config.hh b/src/hb-config.hh index 8f78ede21..5fac4f424 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -58,7 +58,7 @@ #define HB_NO_CFF #define HB_NO_COLOR #define HB_NO_GETENV -#define HB_NO_OT_FONT_GLYPH_NAMES +#define HB_NO_HINTING #define HB_NO_LANGUAGE_PRIVATE_SUBTAG #define HB_NO_LAYOUT_UNUSED #define HB_NO_MATH @@ -66,6 +66,7 @@ #define HB_NO_NAME #define HB_NO_OPEN #define HB_NO_SETLOCALE +#define HB_NO_OT_FONT_GLYPH_NAMES #define HB_NO_OT_SHAPE_FRACTIONS #define HB_NO_STAT #define HB_NO_SUBSET_LAYOUT diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index c332e2815..a903bcd87 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -2166,8 +2166,10 @@ struct Device { switch (u.b.format) { +#ifndef HB_NO_HINTING case 1: case 2: case 3: return u.hinting.get_x_delta (font); +#endif #ifndef HB_NO_VAR case 0x8000: return u.variation.get_x_delta (font, store); @@ -2181,7 +2183,9 @@ struct Device switch (u.b.format) { case 1: case 2: case 3: +#ifndef HB_NO_HINTING return u.hinting.get_y_delta (font); +#endif #ifndef HB_NO_VAR case 0x8000: return u.variation.get_y_delta (font, store); @@ -2196,8 +2200,10 @@ struct Device TRACE_SANITIZE (this); if (!u.b.format.sanitize (c)) return_trace (false); switch (u.b.format) { +#ifndef HB_NO_HINTING case 1: case 2: case 3: return_trace (u.hinting.sanitize (c)); +#endif #ifndef HB_NO_VAR case 0x8000: return_trace (u.variation.sanitize (c)); diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 86c45be29..d371c4b5f 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -267,6 +267,13 @@ struct AnchorFormat2 float *x, float *y) const { hb_font_t *font = c->font; + +#ifdef HB_NO_HINTING + *x = font->em_fscale_x (xCoordinate); + *y = font->em_fscale_y (yCoordinate); + return; +#endif + unsigned int x_ppem = font->x_ppem; unsigned int y_ppem = font->y_ppem; hb_position_t cx = 0, cy = 0; From 8e3cde67dfa4aa17c0f1156b4a4acd0c95bdbe6f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 19:58:24 -0700 Subject: [PATCH 056/138] Fix MSVC build MSVC warning: c:\projects\harfbuzz\src\hb-ot-layout-gsubgpos.hh(2732): error C2121: '#': invalid character: possibly the result of a macro expansion [C:\projects\harfbuzz\build\harfbuzz.vcxproj] Clang warning for it: ./hb-ot-layout-gsubgpos.hh:2729:2: error: embedding a directive within macro arguments has undefined behavior [-Werror,-Wembedded-directive] --- src/hb-ot-layout-gsubgpos.hh | 18 +++++++++++------- src/hb.hh | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index dd54c9b34..9a82a4d67 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -2721,15 +2721,19 @@ struct GSUBGPOS { TRACE_SANITIZE (this); typedef OffsetListOf TLookupList; - return_trace (version.sanitize (c) && - likely (version.major == 1) && - scriptList.sanitize (c, this) && - featureList.sanitize (c, this) && - CastR> (lookupList).sanitize (c, this) && + if (unlikely (!(version.sanitize (c) && + likely (version.major == 1) && + scriptList.sanitize (c, this) && + featureList.sanitize (c, this) && + CastR> (lookupList).sanitize (c, this)))) + return_trace (false); + #ifndef HB_NO_VAR - (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)) && + if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this)))) + return_trace (false); #endif - true); + + return_trace (true); } template diff --git a/src/hb.hh b/src/hb.hh index 3145574d9..bee39cd46 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -66,6 +66,7 @@ #pragma GCC diagnostic error "-Wcast-align" #pragma GCC diagnostic error "-Wcast-function-type" #pragma GCC diagnostic error "-Wdelete-non-virtual-dtor" +#pragma GCC diagnostic error "-Wembedded-directive" #pragma GCC diagnostic error "-Wextra-semi-stmt" #pragma GCC diagnostic error "-Wformat-security" #pragma GCC diagnostic error "-Wimplicit-function-declaration" From 3caa32d737e7c2b4fe6ccd10950760998524f573 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 19:50:54 -0700 Subject: [PATCH 057/138] [config] Add HB_NO_CMAP_LEGACY_SUBTABLES Part of https://vimeo.com/331852453/06eec89c65 --- src/hb-config.hh | 1 + src/hb-ot-cmap-table.hh | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/hb-config.hh b/src/hb-config.hh index 5fac4f424..d7ecf7d4c 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -106,6 +106,7 @@ #endif #ifdef HB_NO_LEGACY +#define HB_NO_CMAP_LEGACY_SUBTABLES #define HB_NO_FALLBACK_SHAPE #define HB_NO_OT_KERN #define HB_NO_OT_LAYOUT_BLACKLIST diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index 724da6e82..ac75bd96a 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -756,10 +756,12 @@ struct CmapSubtable hb_codepoint_t *glyph) const { switch (u.format) { +#ifndef HB_NO_CMAP_LEGACY_SUBTABLES case 0: return u.format0 .get_glyph (codepoint, glyph); - case 4: return u.format4 .get_glyph (codepoint, glyph); case 6: return u.format6 .get_glyph (codepoint, glyph); case 10: return u.format10.get_glyph (codepoint, glyph); +#endif + case 4: return u.format4 .get_glyph (codepoint, glyph); case 12: return u.format12.get_glyph (codepoint, glyph); case 13: return u.format13.get_glyph (codepoint, glyph); case 14: @@ -769,10 +771,12 @@ struct CmapSubtable void collect_unicodes (hb_set_t *out) const { switch (u.format) { +#ifndef HB_NO_CMAP_LEGACY_SUBTABLES case 0: u.format0 .collect_unicodes (out); return; - case 4: u.format4 .collect_unicodes (out); return; case 6: u.format6 .collect_unicodes (out); return; case 10: u.format10.collect_unicodes (out); return; +#endif + case 4: u.format4 .collect_unicodes (out); return; case 12: u.format12.collect_unicodes (out); return; case 13: u.format13.collect_unicodes (out); return; case 14: @@ -785,10 +789,12 @@ struct CmapSubtable TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return_trace (false); switch (u.format) { +#ifndef HB_NO_CMAP_LEGACY_SUBTABLES case 0: return_trace (u.format0 .sanitize (c)); - case 4: return_trace (u.format4 .sanitize (c)); case 6: return_trace (u.format6 .sanitize (c)); case 10: return_trace (u.format10.sanitize (c)); +#endif + case 4: return_trace (u.format4 .sanitize (c)); case 12: return_trace (u.format12.sanitize (c)); case 13: return_trace (u.format13.sanitize (c)); case 14: return_trace (u.format14.sanitize (c)); @@ -799,10 +805,12 @@ struct CmapSubtable public: union { HBUINT16 format; /* Format identifier */ +#ifndef HB_NO_CMAP_LEGACY_SUBTABLES CmapSubtableFormat0 format0; - CmapSubtableFormat4 format4; CmapSubtableFormat6 format6; CmapSubtableFormat10 format10; +#endif + CmapSubtableFormat4 format4; CmapSubtableFormat12 format12; CmapSubtableFormat13 format13; CmapSubtableFormat14 format14; From 27de7c44fe80e69c527578c99c26280ba9f26c15 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 20:07:02 -0700 Subject: [PATCH 058/138] [config] Add HB_NO_FACE_COLLECT_UNICODES Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-face.cc | 5 ++--- src/hb-ot-face-table-list.hh | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hb-config.hh b/src/hb-config.hh index d7ecf7d4c..92f0d5594 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -57,6 +57,7 @@ #define HB_NO_BITMAP #define HB_NO_CFF #define HB_NO_COLOR +#define HB_NO_FACE_COLLECT_UNICODES #define HB_NO_GETENV #define HB_NO_HINTING #define HB_NO_LANGUAGE_PRIVATE_SUBTAG diff --git a/src/hb-face.cc b/src/hb-face.cc index 375ef9293..1098adb33 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -531,6 +531,7 @@ hb_face_get_table_tags (const hb_face_t *face, */ +#ifndef HB_NO_FACE_COLLECT_UNICODES /** * hb_face_collect_unicodes: * @face: font face. @@ -544,7 +545,6 @@ hb_face_collect_unicodes (hb_face_t *face, { face->table.cmap->collect_unicodes (out); } - /** * hb_face_collect_variation_selectors: * @face: font face. @@ -560,7 +560,6 @@ hb_face_collect_variation_selectors (hb_face_t *face, { face->table.cmap->collect_variation_selectors (out); } - /** * hb_face_collect_variation_unicodes: * @face: font face. @@ -577,7 +576,7 @@ hb_face_collect_variation_unicodes (hb_face_t *face, { face->table.cmap->collect_variation_unicodes (variation_selector, out); } - +#endif /* diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index e4ed6b07d..d07f53c2b 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -47,7 +47,9 @@ /* OpenType fundamentals. */ HB_OT_TABLE (OT, head) +#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT) HB_OT_ACCELERATOR (OT, cmap) +#endif HB_OT_ACCELERATOR (OT, hmtx) HB_OT_TABLE (OT, OS2) #ifndef HB_NO_OT_FONT_GLYPH_NAMES From 6c725c7799bf4870fb8b4f896a537a2c0f7a1ccc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 20:12:25 -0700 Subject: [PATCH 059/138] [config] Add HB_NO_LAYOUT_FEATURE_PARAMS Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-ot-layout-common.hh | 7 +++++-- src/hb-ot-layout.cc | 6 ++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/hb-config.hh b/src/hb-config.hh index 92f0d5594..74e4ef5bd 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -61,6 +61,7 @@ #define HB_NO_GETENV #define HB_NO_HINTING #define HB_NO_LANGUAGE_PRIVATE_SUBTAG +#define HB_NO_LAYOUT_FEATURE_PARAMS #define HB_NO_LAYOUT_UNUSED #define HB_NO_MATH #define HB_NO_MMAP diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index a903bcd87..0866760bd 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -499,6 +499,9 @@ struct FeatureParams { bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const { +#ifdef HB_NO_LAYOUT_FEATURE_PARAMS + return true; +#endif TRACE_SANITIZE (this); if (tag == HB_TAG ('s','i','z','e')) return_trace (u.size.sanitize (c)); @@ -509,26 +512,26 @@ struct FeatureParams return_trace (true); } +#ifndef HB_NO_LAYOUT_FEATURE_PARAMS const FeatureParamsSize& get_size_params (hb_tag_t tag) const { if (tag == HB_TAG ('s','i','z','e')) return u.size; return Null (FeatureParamsSize); } - const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const { if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */ return u.stylisticSet; return Null (FeatureParamsStylisticSet); } - const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const { if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */ return u.characterVariants; return Null (FeatureParamsCharacterVariants); } +#endif private: union { diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 0761b8e53..0b897d5ac 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1557,6 +1557,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) } +#ifndef HB_NO_LAYOUT_FEATURE_PARAMS /** * hb_ot_layout_get_size_params: * @face: #hb_face_t to work upon @@ -1619,8 +1620,6 @@ hb_ot_layout_get_size_params (hb_face_t *face, return false; } - - /** * hb_ot_layout_feature_get_name_ids: * @face: #hb_face_t to work upon @@ -1695,8 +1694,6 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face, if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID; return false; } - - /** * hb_ot_layout_feature_get_characters: * @face: #hb_face_t to work upon @@ -1750,6 +1747,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face, if (char_count) *char_count = len; return cv_params.characters.len; } +#endif /* From fce3bf8127321bb53b14eb8a5528a2347cd9be8a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 19 Jun 2019 20:34:29 -0700 Subject: [PATCH 060/138] [config] Add HB_NO_LAYOUT_COLLECT_GLYPHS Part of --- src/hb-config.hh | 1 + src/hb-ot-layout.cc | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/hb-config.hh b/src/hb-config.hh index 74e4ef5bd..66af29aaa 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -62,6 +62,7 @@ #define HB_NO_HINTING #define HB_NO_LANGUAGE_PRIVATE_SUBTAG #define HB_NO_LAYOUT_FEATURE_PARAMS +#define HB_NO_LAYOUT_COLLECT_GLYPHS #define HB_NO_LAYOUT_UNUSED #define HB_NO_MATH #define HB_NO_MMAP diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 0b897d5ac..10b9ba092 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1203,6 +1203,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face, } +#ifndef HB_NO_LAYOUT_COLLECT_GLYPHS /** * hb_ot_layout_lookup_collect_glyphs: * @face: #hb_face_t to work upon @@ -1249,6 +1250,7 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, } } } +#endif /* Variations support */ From e9f7b338ef599b9cbffa125fe594a9939b8517cb Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 20 Jun 2019 11:48:44 -0700 Subject: [PATCH 061/138] [config] Adjust description of HB_LEAN https://github.com/harfbuzz/harfbuzz/commit/d84932ba50482b3b47e393714eb77b19173d1f14 --- CONFIG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONFIG.md b/CONFIG.md index 393553c0a..98be0363e 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -105,8 +105,8 @@ The pre-defined configurations are: * `HB_MINI`: Disables shaping of AAT as well as legacy fonts. Ie. it produces a capable OpenType shaper only. - * `HB_LEAN`: Disables various non-shaping functionality in the library. See - the definition for details. + * `HB_LEAN`: Disables various non-shaping functionality in the library, as well + as esoteric or rarely-used shaping features. See the definition for details. * `HB_TINY`: Enables both `HB_MINI` and `HB_LEAN` configurations, as well as disabling thread-safety and debugging, and use size-optimized data tables. From 6b44bf85382146b355a5a3cbbfde48166721ce52 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 20 Jun 2019 11:57:19 -0700 Subject: [PATCH 062/138] 2.5.2 --- NEWS | 12 ++++++++++++ configure.ac | 2 +- src/hb-version.h | 4 ++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 51929738a..0835378a1 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,15 @@ +Overview of changes leading to 2.5.2 +Thursday, June 20, 2019 +==================================== +- More hb-config.hh facilities to shrink library size, namely when built as + HB_TINY. +- New documentation of custom configurations in CONFIG.md. +- Fix build on gcc 4.8. That's supported again. +- Universal Shaping Engine improvements thanks to David Corbett. +- API Changes: Undeprecate some horizontal-kerning API and re-enable in hb-ft, + such that Type1 fonts will continue kerning. + + Overview of changes leading to 2.5.1 Friday, May 31, 2019 ==================================== diff --git a/configure.ac b/configure.ac index 958bd2dd2..426b85038 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [2.5.1], + [2.5.2], [https://github.com/harfbuzz/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) diff --git a/src/hb-version.h b/src/hb-version.h index 1eca37a58..10b826ffb 100644 --- a/src/hb-version.h +++ b/src/hb-version.h @@ -38,9 +38,9 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 2 #define HB_VERSION_MINOR 5 -#define HB_VERSION_MICRO 1 +#define HB_VERSION_MICRO 2 -#define HB_VERSION_STRING "2.5.1" +#define HB_VERSION_STRING "2.5.2" #define HB_VERSION_ATLEAST(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) <= \ From 7f3b409e85897ff267f1b6a5ce1b5cdafbfe7afe Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 20 Jun 2019 14:24:43 -0700 Subject: [PATCH 063/138] Fix build with -O0 message_impl was not defined. That causes trouble if compiler didn't optimize the unreachable call out... --- src/hb-buffer.cc | 1 - src/hb-buffer.hh | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index d1dbd0788..db1978e6d 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -2023,7 +2023,6 @@ hb_buffer_set_message_func (hb_buffer_t *buffer, buffer->message_destroy = nullptr; } } - bool hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) { diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh index bc0c7eddc..de0655de3 100644 --- a/src/hb-buffer.hh +++ b/src/hb-buffer.hh @@ -359,6 +359,9 @@ struct hb_buffer_t } bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4) { +#ifdef HB_NO_BUFFER_MESSAGE + return true; +#else if (!messaging ()) return true; va_list ap; @@ -366,6 +369,7 @@ struct hb_buffer_t bool ret = message_impl (font, fmt, ap); va_end (ap); return ret; +#endif } HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0); From 12cec6c12ec1856e483097e702126214dd25a34a Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 21 Jun 2019 22:39:42 +0430 Subject: [PATCH 064/138] Don't define hb_blob_create_from_file if HB_NO_OPEN is defined --- src/hb-blob.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/hb-blob.cc b/src/hb-blob.cc index 497df65fd..9ed26bd2f 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -487,6 +487,7 @@ hb_blob_t::try_make_writable () * Mmap */ +#ifndef HB_NO_OPEN #ifdef HAVE_MMAP # include # include @@ -543,10 +544,6 @@ _hb_mapped_file_destroy (void *file_) hb_blob_t * hb_blob_create_from_file (const char *file_name) { -#ifdef HB_NO_OPEN - return hb_blob_get_empty (); -#endif - /* Adopted from glib's gmappedfile.c with Matthias Clasen and Allison Lortie permission but changed a lot to suit our need. */ #if defined(HAVE_MMAP) && !defined(HB_NO_MMAP) @@ -680,3 +677,4 @@ fread_fail_without_close: free (data); return hb_blob_get_empty (); } +#endif /* !HB_NO_OPEN */ From ccea7fa119d139b6a3a429b3b81fac8448f3bab1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 21 Jun 2019 00:42:06 -0700 Subject: [PATCH 065/138] [config] Make test build under HB_TINY --- src/test-gpos-size-params.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test-gpos-size-params.cc b/src/test-gpos-size-params.cc index 12eec6188..acd1c4fc5 100644 --- a/src/test-gpos-size-params.cc +++ b/src/test-gpos-size-params.cc @@ -45,10 +45,15 @@ main (int argc, char **argv) hb_blob_destroy (blob); blob = nullptr; - unsigned int p[5]; - bool ret = hb_ot_layout_get_size_params (face, p, p+1, (p+2), p+3, p+4); + bool ret = true; +#ifndef HB_NO_LAYOUT_FEATURE_PARAMS + unsigned int p[5]; + ret = hb_ot_layout_get_size_params (face, p, p+1, (p+2), p+3, p+4); printf ("%g %u %u %g %g\n", p[0]/10., p[1], p[2], p[3]/10., p[4]/10.); +#endif + + hb_face_destroy (face); return !ret; } From ad97ec95019b1e5170d00953d4dfe392cfb4abb0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 21 Jun 2019 00:44:29 -0700 Subject: [PATCH 066/138] [config/ucd] Add HB_NO_UNICODE_UNASSIGNED and activate in HB_TINY Saves another 12kb: $ python ./gen-ucd-table.py ucd.nounihan.grouped.zip > hb-ucd-table.hh && make -j5 CPPFLAGS='-Os -DHB_TINY' -C ~/hb/build/src/ && size ~/hb/build/src/.libs/libharfbuzz_la-hb-ucd.o INFO: Loading UCDXML... INFO: Preparing data tables... INFO: Generating output... INFO: Compression=1: INFO: Dataset=gc FullCost=18612 INFO: Dataset=ccc FullCost=3550 INFO: Dataset=bmg FullCost=1548 INFO: Dataset=sc FullCost=17765 INFO: Dataset=dm FullCost=13325 INFO: Compression=3: INFO: Dataset=gc FullCost=10726 INFO: Dataset=ccc FullCost=2389 INFO: Dataset=bmg FullCost=1052 INFO: Dataset=sc FullCost=13669 INFO: Dataset=dm FullCost=7780 INFO: Compression=5: INFO: Dataset=gc FullCost=8274 INFO: Dataset=ccc FullCost=2055 INFO: Dataset=bmg FullCost=908 INFO: Dataset=sc FullCost=4073 INFO: Dataset=dm FullCost=7780 INFO: Done. Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- CONFIG.md | 3 +- src/gen-ucd-table.py | 27 +- src/hb-config.hh | 1 + src/hb-ucd-table.hh | 1161 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 1185 insertions(+), 7 deletions(-) diff --git a/CONFIG.md b/CONFIG.md index 98be0363e..5fb3e7cb4 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -109,7 +109,8 @@ The pre-defined configurations are: as esoteric or rarely-used shaping features. See the definition for details. * `HB_TINY`: Enables both `HB_MINI` and `HB_LEAN` configurations, as well as - disabling thread-safety and debugging, and use size-optimized data tables. + disabling thread-safety and debugging, and use even more size-optimized data + tables. ## Tailoring configuration diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py index c98c715e1..dd3a54626 100755 --- a/src/gen-ucd-table.py +++ b/src/gen-ucd-table.py @@ -72,6 +72,7 @@ for line in open('hb-common.h'): DEFAULT = 1 COMPACT = 3 +SLOPPY = 5 logging.info('Generating output...') @@ -105,15 +106,32 @@ datasets = [ ('dm', dm, None, dm_order), ] -for compression in (DEFAULT, COMPACT): +for compression in (DEFAULT, COMPACT, SLOPPY): logging.info(' Compression=%d:' % compression) print() if compression == DEFAULT: print('#ifndef HB_OPTIMIZE_SIZE') + elif compression == COMPACT: + print('#elif !defined(HB_NO_UCD_UNASSIGNED)') else: print('#else') print() + if compression == SLOPPY: + for i in range(len(gc)): + if (i % 128) and gc[i] == 'Cn': + gc[i] = gc[i - 1] + for i in range(len(gc) - 2, -1, -1): + if ((i + 1) % 128) and gc[i] == 'Cn': + gc[i] = gc[i + 1] + for i in range(len(sc)): + if (i % 128) and sc[i] == 'Zzzz': + sc[i] = sc[i - 1] + for i in range(len(sc) - 2, -1, -1): + if ((i + 1) % 128) and sc[i] == 'Zzzz': + sc[i] = sc[i + 1] + + code = packTab.Code('_hb_ucd') for name,data,default,mapping in datasets: @@ -123,12 +141,11 @@ for compression in (DEFAULT, COMPACT): code.print_c(linkage='static inline') - - if compression != DEFAULT: - print() - print('#endif') print() +print('#endif') +print() + print() print("#endif /* HB_UCD_TABLE_HH */") print() diff --git a/src/hb-config.hh b/src/hb-config.hh index 66af29aaa..f9e4699fc 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -40,6 +40,7 @@ #define HB_LEAN #define HB_MINI #define HB_NO_MT +#define HB_NO_UCD_UNASSIGNED #ifndef NDEBUG #define NDEBUG #endif diff --git a/src/hb-ucd-table.hh b/src/hb-ucd-table.hh index e9d097542..014508003 100644 --- a/src/hb-ucd-table.hh +++ b/src/hb-ucd-table.hh @@ -3476,7 +3476,7 @@ _hb_ucd_dm (unsigned u) } -#else +#elif !defined(HB_NO_UCD_UNASSIGNED) static const uint8_t _hb_ucd_u8[16998] = @@ -5156,6 +5156,1165 @@ _hb_ucd_dm (unsigned u) return u<195102u?_hb_ucd_u16[5632+(((_hb_ucd_u8[15974+(((_hb_ucd_b4(15878+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0; } + +#else + +static const uint8_t +_hb_ucd_u8[12888] = +{ + 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 5, 5, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 5, 17, 15, 15, 18, 15, 19, 20, 21, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 23, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 24, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 34, 34, 34, 35, 36, 37, 34, 34, 34, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 67, 68, 69, 67, 70, 71, + 67, 67, 62, 72, 62, 62, 73, 67, 74, 75, 76, 77, 78, 67, 67, 67, + 79, 80, 34, 81, 82, 83, 67, 67, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 84, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 85, 34, 34, 34, 34, 34, 34, 34, 34, 86, 34, 34, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, + 100,100, 34, 34, 34, 34,101,102, 34, 34,103,104,105,106,107,108, + 34, 34,109,110,111,112,113,114,115,116,117,111, 34, 34, 34,111, + 118,119,120,121,122,123,124,125, 34,126,127,111,128,111,129, 34, + 130,131,132,133,134,135,136,111,137,138,111,139,140,141,142,111, + 143,144,111,145,146,147,111,111,148,149,150,151,111,152,111,153, + 34, 34, 34, 34, 34, 34, 34, 34,154, 34, 34,111,111,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 34, 34, 34, 34, 34, 34, 34, 34,155,111,111,111,111,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 111,111,111,111,111,111,111,111, 34, 34, 34, 34, 34,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 34, 34, 34, 34,156,157,158, 34,111,111,111,111,159,160,161,162, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111, + 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111, + 111,111,111,111,111,111,111,111, 34,163,111,111,111,111,111,111, + 67, 67,164,165,166,128, 65,111,167,168,169,170,171,172,173,174, + 67, 67, 67, 67,175,176,111,111,111,111,111,111,111,111,111,111, + 177,111,178,111,111,179,111,111,111,111,111,111,111,111,111,111, + 34,180,181,111,111,111,111,111,128,182,183,111, 34,184,111,111, + 67, 67,185, 67, 67,111, 67,186, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67,111,111,111,111,111,111,111,111,111,111, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,111, + 187,111,177,177,111,111,111,111,111,111,111,111,111,111,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2, + 7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 17, 18, 19, 1, 20, 20, 21, 22, 23, 24, 25, + 26, 27, 15, 2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32, + 32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11, + 11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11, + 34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34, + 34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32, + 32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32, + 16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, + 40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, + 43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 16, 44, 16, 10, + 41, 41, 41, 45, 11, 11, 11, 11, 34, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34, + 16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 46, 34, 32, 34, 11, + 32, 47, 43, 43, 48, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16, + 11, 11, 11, 11, 49, 2, 2, 2, 16, 16, 16, 16, 50, 51, 52, 53, + 54, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 55, + 56, 57, 43, 56, 43, 43, 43, 43, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 58, 2, 2, 2, 2, 2, 2, 59, 59, 59, 8, 9, 60, 2, 61, + 43, 43, 43, 43, 43, 57, 59, 2, 62, 36, 36, 36, 36, 63, 43, 43, + 7, 7, 7, 7, 7, 2, 2, 36, 64, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 65, 43, 43, 43, 66, 47, 43, 43, 67, 68, 69, 43, 43, 36, + 7, 7, 7, 7, 7, 36, 70, 71, 2, 2, 2, 2, 2, 2, 2, 72, + 63, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 64, 36, + 36, 36, 36, 43, 43, 43, 43, 43, 7, 7, 7, 7, 7, 36, 36, 36, + 36, 36, 36, 36, 36, 63, 43, 43, 43, 43, 40, 21, 2, 40, 68, 20, + 36, 36, 36, 43, 43, 68, 43, 43, 43, 43, 68, 43, 68, 43, 43, 43, + 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 36, 36, 63, 43, 43, 2, + 36, 63, 43, 43, 43, 43, 43, 43, 43, 73, 43, 43, 43, 43, 43, 43, + 43, 74, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 74, 64, 75, + 76, 43, 43, 43, 74, 75, 76, 75, 63, 43, 43, 43, 36, 36, 36, 36, + 36, 43, 2, 7, 7, 7, 7, 7, 77, 36, 36, 36, 36, 36, 36, 36, + 63, 75, 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64, 75, + 76, 43, 43, 74, 75, 75, 76, 36, 36, 36, 36, 79, 75, 75, 36, 36, + 36, 43, 43, 7, 7, 7, 7, 7, 36, 20, 27, 27, 27, 53, 58, 43, + 43, 74, 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 75, + 76, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 64, 36, 36, 36, + 36, 36, 36, 7, 7, 7, 7, 7, 43, 36, 63, 2, 2, 2, 2, 2, + 76, 43, 43, 43, 74, 75, 76, 43, 60, 20, 20, 20, 80, 43, 43, 43, + 43, 75, 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64, 76, + 76, 43, 43, 74, 75, 75, 76, 43, 43, 43, 43, 74, 75, 75, 36, 36, + 71, 27, 27, 27, 27, 27, 27, 27, 43, 64, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 75, 74, 75, 75, 75, 75, 75, 76, 43, + 36, 36, 36, 79, 75, 75, 75, 75, 75, 75, 75, 7, 7, 7, 7, 7, + 27, 81, 61, 61, 53, 61, 61, 61, 74, 75, 64, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 43, 74, 75, 75, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 36, 36, 36, 36, 7, 7, 7, 82, 27, 27, 27, 81, + 63, 75, 65, 36, 36, 36, 36, 36, 75, 75, 75, 74, 75, 75, 43, 43, + 43, 43, 74, 75, 75, 75, 75, 36, 83, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 63, 64, 75, 76, 43, 43, 75, 75, 75, 76, 70, + 61, 61, 36, 79, 27, 27, 27, 84, 27, 27, 27, 27, 81, 36, 36, 36, + 75, 75, 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 74, + 75, 43, 43, 43, 75, 75, 75, 75, 7, 75, 2, 2, 2, 2, 2, 2, + 63, 36, 43, 43, 43, 43, 43, 85, 36, 36, 36, 68, 43, 43, 43, 57, + 7, 7, 7, 7, 7, 2, 2, 2, 63, 36, 43, 43, 43, 43, 64, 36, + 36, 36, 36, 40, 43, 43, 43, 43, 7, 7, 7, 7, 7, 7, 36, 36, + 70, 61, 2, 2, 2, 2, 2, 2, 2, 86, 86, 61, 43, 61, 61, 61, + 7, 7, 7, 7, 7, 27, 27, 27, 27, 27, 47, 47, 47, 4, 4, 75, + 63, 43, 43, 43, 43, 43, 43, 74, 43, 43, 57, 43, 36, 36, 63, 43, + 43, 43, 43, 43, 43, 43, 43, 61, 61, 61, 61, 69, 61, 61, 61, 61, + 2, 2, 86, 61, 21, 2, 2, 2, 36, 36, 36, 36, 36, 79, 76, 43, + 74, 43, 43, 43, 76, 74, 76, 64, 36, 36, 36, 75, 43, 36, 36, 43, + 64, 75, 78, 79, 75, 75, 75, 36, 63, 43, 64, 36, 36, 36, 36, 36, + 36, 74, 76, 74, 75, 75, 76, 79, 7, 7, 7, 7, 7, 75, 76, 61, + 16, 16, 16, 16, 16, 50, 44, 16, 36, 36, 36, 36, 36, 36, 63, 43, + 2, 2, 2, 2, 87, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 61, 61, 61, 61, 61, 61, 61, 61, 11, 11, 11, 11, 16, 16, 16, 16, + 88, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70, 65, + 89, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 90, 91, 91, + 36, 36, 36, 36, 36, 58, 2, 92, 93, 36, 36, 36, 36, 36, 36, 36, + 36, 43, 43, 43, 43, 43, 43, 43, 36, 43, 57, 2, 2, 2, 2, 2, + 36, 36, 43, 76, 43, 43, 43, 75, 75, 75, 75, 74, 76, 43, 43, 43, + 43, 43, 2, 77, 2, 60, 63, 43, 7, 7, 7, 7, 7, 7, 7, 7, + 2, 2, 2, 94, 2, 56, 43, 59, 36, 95, 36, 36, 36, 36, 36, 36, + 36, 36, 63, 64, 36, 36, 36, 36, 36, 36, 36, 36, 63, 36, 36, 36, + 43, 74, 75, 76, 74, 75, 75, 75, 75, 74, 75, 75, 76, 43, 43, 43, + 61, 61, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 27, 27, 61, + 36, 36, 36, 63, 74, 76, 43, 2, 36, 36, 79, 74, 43, 43, 43, 43, + 74, 74, 76, 43, 43, 43, 74, 75, 75, 76, 43, 43, 43, 43, 43, 43, + 2, 2, 2, 77, 2, 2, 2, 2, 43, 43, 43, 43, 43, 43, 43, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 43, 43, 78, 36, 36, 36, 36, 36, + 36, 36, 74, 43, 43, 74, 74, 75, 75, 74, 78, 36, 36, 36, 36, 36, + 86, 61, 61, 61, 61, 47, 43, 43, 43, 43, 61, 61, 61, 61, 61, 61, + 43, 78, 36, 36, 36, 36, 36, 36, 79, 43, 43, 75, 43, 76, 43, 36, + 36, 36, 36, 74, 43, 75, 76, 76, 43, 75, 75, 75, 75, 75, 2, 2, + 36, 36, 75, 75, 75, 75, 43, 43, 43, 43, 75, 43, 43, 57, 2, 2, + 7, 7, 7, 7, 7, 7, 83, 36, 36, 36, 36, 36, 40, 40, 40, 2, + 43, 57, 43, 43, 43, 43, 43, 43, 74, 43, 43, 43, 64, 36, 63, 36, + 36, 36, 64, 79, 43, 36, 36, 36, 16, 16, 16, 16, 16, 16, 40, 40, + 40, 40, 40, 40, 40, 44, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16, + 16, 16, 16, 16, 16, 96, 40, 40, 32, 32, 32, 16, 16, 16, 16, 32, + 16, 16, 16, 16, 11, 11, 11, 11, 16, 16, 16, 16, 34, 11, 11, 11, + 16, 16, 16, 16, 97, 97, 97, 97, 16, 16, 16, 16, 11, 11, 98, 99, + 41, 16, 16, 16, 11, 11, 98, 41, 16, 16, 16, 16, 11, 11,100, 41, + 101,101,101,101,101,102, 59, 59, 51, 51, 51, 2,103,104,103,104, + 2, 2, 2, 2,105, 59, 59,106, 2, 2, 2, 2,107,108, 2,109, + 110, 2,111,112, 2, 2, 2, 2, 2, 9,110, 2, 2, 2, 2,113, + 59, 59, 59, 59, 59, 59, 59, 59,114, 40, 27, 27, 27, 8,111,115, + 27, 27, 27, 27, 27, 8,111, 91, 20, 20, 20, 20, 20, 20, 20, 20, + 43, 43, 43, 43, 43, 43,116, 48,117, 48,117, 43, 43, 43, 43, 43, + 61,118, 61,119, 61, 34, 11, 16, 11, 32,119, 61, 46, 11, 11, 61, + 61, 61,118,118,118, 11, 11,120, 11, 11, 35, 36, 39, 61, 16, 11, + 8, 8, 46, 16, 16, 26, 61,121, 92, 92, 92, 92, 92, 92, 92, 92, + 92,122,123, 92,124, 61, 61, 61, 8, 8,125, 61, 61, 8, 61, 61, + 125, 26, 61,125, 61, 61, 61,125, 61, 61, 61, 61, 61, 61, 61, 8, + 61,125,125, 61, 61, 61, 61, 61, 61, 61, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 61, 61, 61, 61, 4, 4, 61, 61, + 8, 61, 61, 61,126,127, 61, 61, 61, 61, 61, 61, 61, 61,125, 61, + 61, 61, 61, 61, 61, 26, 8, 8, 8, 8, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 8, 8, 8, 61, 61, 61, 61, 61, 61, 61, + 27, 27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27, + 61, 61, 61, 26, 61, 61, 61, 61, 26, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 8, 8, 8, 8, 61, 61, 61, 61, 61, 61, 61, 26, + 61, 61, 61, 61, 4, 4, 4, 4, 4, 4, 4, 27, 27, 27, 27, 27, + 27, 27, 61, 61, 61, 61, 61, 61, 8, 8,111,128, 8, 8, 8, 8, + 8, 8, 8, 4, 4, 4, 4, 4, 8,111,129,129,129,129,129,129, + 129,129,129,129,128, 8, 8, 8, 8, 8, 8, 8, 4, 4, 8, 8, + 8, 8, 8, 8, 8, 8, 4, 8, 8, 8,125, 26, 8, 8,125, 61, + 32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11, + 32, 32,121, 61, 61,119, 34,130, 43, 32, 16, 16, 50, 2, 87, 2, + 36, 36, 36, 36, 36, 36, 36, 95, 2, 2, 2, 2, 2, 2, 2, 56, + 2,103,103, 2,107,108,103, 2, 2, 2, 2, 6, 2, 94,103, 2, + 103, 4, 4, 4, 4, 2, 2, 77, 2, 2, 2, 2, 2, 51, 2, 2, + 94,131, 2, 2, 2, 2, 2, 2, 1, 2,132,133, 4, 4, 4, 4, + 4, 61, 4, 4, 4, 4,134, 91,135, 92, 92, 92, 92, 43, 43, 75, + 136, 40, 40, 61, 92,137, 58, 61, 71, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 63,138,139, 62, 36, 36, 36, 36, 36, 58, 40, 62, + 61, 27, 27, 61, 61, 61, 61, 61, 27, 27, 27, 27, 27, 61, 61, 61, + 61, 61, 61, 61, 27, 27, 27, 27,140, 27, 27, 27, 27, 27, 27, 27, + 36, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,141, 2, + 32, 32, 32, 32, 32, 32, 32, 63, 48,142, 43, 43, 43, 43, 43, 77, + 32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36, 92, 92, 92, 92, 92, + 43, 2, 2, 2, 2, 2, 2, 2, 41, 41, 41,139, 40, 40, 40, 40, + 41, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32, + 44, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,143, 34, 35, + 32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32, + 11, 11, 32, 32, 32, 32, 32, 32, 16, 32, 11, 11, 11, 11, 11, 11, + 11, 11, 11,144, 40, 35, 36, 36, 36, 64, 36, 64, 36, 63, 36, 36, + 36, 79, 76, 74, 61, 61, 61, 61, 27, 27, 27, 61,145, 61, 61, 61, + 36, 36, 2, 2, 2, 2, 2, 2, 75, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 75, 75, 75, 75, 75, 75, 75, 75, 43, 43, 43, 43, 43, 2, + 43, 36, 36, 36, 2, 65, 65, 63, 36, 36, 36, 43, 43, 43, 43, 2, + 36, 36, 36, 63, 43, 43, 43, 43, 43, 75, 75, 75, 75, 75, 75,146, + 36, 63, 75, 43, 43, 75, 43, 75,146, 2, 2, 2, 2, 2, 2, 77, + 7, 7, 7, 7, 7, 7, 7, 2, 36, 36, 63, 62, 36, 36, 36, 36, + 36, 36, 36, 36, 63, 43, 43, 74, 76, 74, 76, 43, 43, 43, 43, 43, + 36, 63, 36, 36, 36, 36, 74, 75, 7, 7, 7, 7, 7, 7, 2, 2, + 62, 36, 36, 70, 61, 79, 74, 36, 64, 43, 64, 63, 64, 36, 36, 43, + 36, 36, 36, 36, 36, 36, 95, 2, 36, 36, 36, 36, 36, 79, 43, 75, + 2, 95,147, 43, 43, 43, 43, 43, 16, 16, 16, 16, 16, 99, 40, 40, + 36, 79, 76, 75, 74,146, 76, 43,148,148,148,148,148,148,148,148, + 149,149,149,149,149,149,149,149, 16, 16, 16, 16, 16, 16, 35, 64, + 36, 36, 36, 36,150, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41, + 41,151, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,129, + 152,152,152,152,152,152,152,152, 36, 36, 36, 36, 36, 36,145, 61, + 2, 2, 2,153,112, 2, 2, 2, 6,154,155,129,129,129,129,129, + 129,129,112,153,112, 2,109,156, 2, 2, 2, 2,134,129,129,112, + 2,157, 8, 8, 60, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36,158, + 2, 2, 3, 2, 4, 5, 6, 2, 16, 16, 16, 16, 16, 17, 18,111, + 112, 4, 2, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 40, 20,159, 53, 20, 26, 8,125, 61, + 61, 61, 61, 61,160, 59, 61, 61, 2, 2, 2, 87, 27, 27, 27, 27, + 27, 27, 27, 81, 61, 61, 61, 61, 92, 92,124, 27, 81, 61, 61, 61, + 61, 61, 61, 61, 61, 27, 61, 61, 61, 61, 61, 61, 61, 61, 47, 43, + 161,161,161,161,161,161,161,161,162, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 84, 36,133, 36, 36, 36, 36, 92, 92, 92, + 36, 36, 36, 36, 36, 36, 36, 58,163, 92, 92, 92, 92, 92, 92, 92, + 36, 36, 36, 58, 27, 27, 27, 27, 36, 36, 36, 70,140, 27, 27, 27, + 36, 36, 36,164, 27, 27, 27, 27, 36, 36, 36, 36, 36,164, 27, 27, + 36, 36, 36, 27, 27, 27, 27, 30, 36, 36, 36, 36, 36, 36, 27, 36, + 63, 43, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 43, 43, 43, 43, + 36, 36, 36, 36, 36, 36,164, 30, 36, 36, 36, 36, 36, 36,164, 27, + 36, 36, 36, 36, 71, 36, 36, 36, 36, 36, 63, 43, 43,162, 27, 27, + 36, 36, 36, 36, 58, 2, 2, 2, 36, 36, 36, 36, 27, 27, 27, 27, + 16, 16, 16, 16, 16, 27, 27, 27, 36, 36, 43, 43, 43, 43, 43, 43, + 27, 27, 27, 84, 36, 36, 36, 36,162, 27, 30, 2, 2, 2, 2, 2, + 76, 78, 36, 36, 36, 36, 36, 36, 43, 43, 43, 57, 2, 2, 2, 2, + 2, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7,165, 75, 76, 43, 74, 76, 57, 72, 2, + 2, 2, 2, 2, 2, 2, 72, 59, 36, 36, 36, 63, 43, 43, 76, 43, + 43, 43, 43, 7, 7, 7, 7, 7, 2, 2, 79, 75, 75, 75, 75, 75, + 36, 63, 2, 36, 36, 36, 36, 36, 36, 79, 75, 43, 43, 43, 43, 74, + 78, 36, 58, 2, 56, 43, 57, 2, 7, 7, 7, 7, 7, 58, 58, 2, + 87, 27, 27, 27, 27, 27, 27, 27, 36, 36, 36, 36, 36, 36, 75, 76, + 43, 75, 74, 43, 2, 2, 2, 43, 36, 36, 36, 36, 36, 36, 36, 63, + 74, 75, 75, 75, 75, 75, 75, 75, 36, 36, 36, 79, 75, 75, 78, 36, + 36, 75, 75, 43, 43, 43, 43, 43, 36, 36, 79, 75, 43, 43, 43, 43, + 75, 43, 74, 64, 36, 58, 2, 2, 7, 7, 7, 7, 7, 82, 2, 64, + 75, 76, 43, 43, 74, 74, 75, 76, 74, 43, 36, 65, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 79, 75, 43, 43, 43, 75, 75, 43, 76, + 57, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 43, 43, + 75, 76, 43, 43, 43, 74, 76, 76, 57, 2, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 63, 76, 75, 43, 43, 43, 76, 36, 36, 36, 36, + 75, 43, 43, 76, 43, 43, 43, 43, 7, 7, 7, 7, 7, 27, 2, 86, + 43, 43, 43, 43, 76, 57, 2, 2, 27, 27, 27, 27, 27, 27, 27, 84, + 79, 75, 43, 43, 43, 43, 75, 75, 64, 65, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 63, 43, 43, 43, 43, 64, 36, 36, + 36, 63, 43, 43, 74, 63, 43, 57, 2, 2, 2, 56, 43, 43, 43, 43, + 63, 43, 43, 74, 76, 43, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, + 43, 43, 43, 74, 43, 2, 65, 2, 43, 43, 43, 43, 43, 43, 43, 76, + 58, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, + 43, 43, 43, 43, 74, 43, 43, 43, 74, 43, 76, 43, 43, 43, 43, 43, + 43, 43, 43, 63, 43, 43, 43, 43, 36, 36, 36, 36, 36, 75, 75, 75, + 43, 74, 76, 76, 36, 36, 36, 36, 36, 63, 74,146, 2, 2, 2, 2, + 27, 27, 81, 61, 61, 61, 53, 20,145, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 21, 43, 43, 57, 2, 2, 2, 2, 2, + 43, 43, 43, 57, 2, 2, 61, 61, 40, 40, 86, 61, 61, 61, 61, 61, + 7, 7, 7, 7, 7,166, 27, 27, 27, 84, 36, 36, 36, 36, 36, 36, + 27, 27, 27, 30, 2, 2, 2, 2, 79, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 76, 43, 67, 40, 40, 40, 40, 40, 40, + 40, 77, 40, 40, 40, 40, 40, 40, 36, 36, 36, 36, 36, 36, 47, 57, + 61, 61,167, 76, 43, 61,167, 75, 75,168, 59, 59, 59, 73, 43, 43, + 43, 69, 47, 43, 43, 43, 61, 61, 61, 61, 61, 61, 61, 43, 43, 61, + 61, 43, 69, 61, 61, 61, 61, 61, 11, 11, 11, 11, 11, 16, 16, 16, + 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11, + 11, 11, 11, 16, 16, 16, 16, 16, 31, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, + 11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, + 16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, + 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, + 16, 33, 16, 16, 16, 32, 16, 7, 43, 43, 43, 69, 61, 47, 43, 43, + 43, 43, 43, 43, 43, 43, 69, 61, 61, 61, 47, 61, 61, 61, 61, 61, + 61, 61, 69, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 56, 43, 43, + 43, 43, 43, 67, 40, 40, 40, 40, 7, 7, 7, 7, 7, 7, 7, 70, + 36, 36, 36, 36, 36, 36, 43, 43, 7, 7, 7, 7, 7, 7, 7,169, + 16, 16, 43, 43, 43, 67, 40, 40, 27, 27, 27, 27, 27, 27,140, 27, + 170, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,140, + 61, 61, 61, 61, 61, 25, 41, 41, 0, 0, 29, 21, 21, 21, 23, 21, + 22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21, 9, 9, 9, + 9, 22, 21, 18, 24, 16, 24, 5, 5, 5, 5, 22, 25, 18, 25, 0, + 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24, 26, 25, 15, 15, + 24, 15, 7, 19, 15, 21, 9, 25, 9, 5, 5, 25, 5, 9, 5, 7, + 7, 7, 9, 8, 8, 5, 7, 5, 6, 6, 24, 24, 6, 24, 12, 12, + 6, 5, 9, 21, 25, 9, 26, 12, 11, 11, 9, 6, 5, 21, 17, 17, + 17, 26, 26, 23, 23, 12, 17, 12, 21, 12, 12, 21, 7, 21, 1, 1, + 21, 23, 26, 26, 6, 7, 7, 12, 12, 7, 21, 7, 12, 1, 12, 6, + 6, 12, 12, 26, 7, 26, 26, 7, 21, 1, 1, 12, 12, 10, 10, 10, + 10, 12, 21, 6, 10, 7, 7, 10, 23, 7, 15, 26, 13, 21, 13, 7, + 15, 7, 12, 23, 21, 26, 21, 15, 17, 7, 29, 7, 7, 22, 18, 18, + 14, 14, 14, 7, 17, 21, 7, 6, 5, 6, 8, 8, 8, 24, 5, 24, + 9, 24, 29, 29, 29, 1, 20, 19, 22, 20, 27, 28, 1, 29, 21, 20, + 19, 21, 21, 16, 16, 21, 25, 22, 18, 21, 21, 29, 15, 6, 18, 6, + 12, 11, 11, 12, 9, 26, 26, 9, 26, 5, 5, 26, 14, 9, 5, 14, + 14, 15, 25, 26, 26, 22, 18, 26, 18, 25, 18, 22, 5, 12, 22, 21, + 26, 6, 7, 14, 17, 22, 26, 14, 17, 6, 14, 6, 12, 24, 24, 6, + 26, 15, 6, 21, 11, 21, 24, 9, 9, 7, 23, 26, 10, 21, 6, 10, + 4, 4, 3, 3, 7, 25, 24, 7, 22, 22, 21, 22, 17, 16, 16, 22, + 16, 16, 25, 17, 7, 1, 25, 24, 26, 1, 2, 2, 12, 15, 21, 14, + 7, 15, 13, 12, 13, 15, 26, 10, 10, 1, 13, 23, 23, 15, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 12, 13, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, 16, 9, + 17, 18, 19, 20, 21, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 23, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 24, 9, 9, + 9, 9, 25, 9, 9, 9, 26, 9, 27, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, + 4, 5, 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 0, 14, 15, 16, + 15, 17, 15, 18, 15, 18, 15, 18, 0, 18, 0, 19, 15, 18, 20, 18, + 0, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 33, 0, 0, 34, 0, 0, 35, 0, 36, 0, + 0, 0, 37, 38, 39, 0, 40, 41, 42, 43, 44, 0, 0, 45, 0, 0, + 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, + 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 52, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 53, 54, 55, 0, 0, 0, 0, 56, 0, 0, 57, 58, 59, + 60, 61, 0, 0, 62, 63, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 67, 0, 0, 0, 68, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 70, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, + 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 74, 75, 0, 76, 60, + 0, 77, 78, 0, 0, 79, 80, 81, 0, 0, 0, 82, 0, 83, 0, 0, + 49, 84, 49, 0, 85, 0, 86, 0, 0, 0, 75, 0, 0, 0, 0, 0, + 0, 87, 88, 89, 90, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 91, + 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 93, 94, 0, 0, 0, 0, 0, 95, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, + 97, 0, 0, 98, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 94, 0, + 0, 0, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0,101, 0,102, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, + 3, 4, 5, 6, 7, 0, 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, + 0, 0, 0, 13, 0, 0, 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, + 0, 20, 21, 0, 0, 0, 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, + 0, 0, 0, 27, 28, 29, 0, 0, 0, 30, 31, 32, 0, 0, 31, 0, + 0, 33, 31, 0, 0, 0, 31, 34, 0, 0, 0, 0, 0, 35, 36, 0, + 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0, 0, 0, 39, 40, 0, + 0, 0, 0, 41, 0, 42, 0, 0, 0, 43, 44, 0, 0, 0, 45, 0, + 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 48, 0, 0, 0, 49, + 0, 49, 0, 50, 0, 0, 0, 0, 51, 0, 0, 0, 0, 52, 0, 53, + 0, 0, 0, 0, 54, 55, 0, 0, 0, 56, 0, 0, 0, 57, 49, 0, + 58, 59, 0, 0, 60, 0, 0, 0, 61, 62, 0, 0, 0, 63, 0, 64, + 65, 66, 67, 68, 1, 69, 0, 70, 71, 72, 0, 0, 73, 74, 0, 0, + 0, 75, 0, 0, 1, 1, 0, 0, 76, 0, 0, 77, 0, 0, 0, 0, + 73, 78, 0, 79, 0, 0, 0, 0, 0, 74, 80, 0, 0, 0, 49, 0, + 1, 74, 0, 0, 81, 0, 0, 82, 0, 0, 0, 0, 0, 83, 54, 0, + 0, 0, 0, 0, 0, 84, 85, 0, 0, 80, 0, 0, 31, 0, 0, 86, + 0, 0, 0, 0, 87, 0, 0, 0, 0, 47, 0, 0, 88, 0, 0, 0, + 0, 89, 90, 0, 0, 91, 0, 0, 92, 0, 0, 0, 93, 0, 94, 88, + 0, 0, 80, 0, 0, 75, 0, 0, 0, 95, 96, 0, 0, 97, 98, 0, + 0, 0, 0, 0, 0, 99, 0, 0,100, 0, 0, 0, 0,101, 31, 0, + 102,103,104, 33, 0, 0,105, 0, 0, 0,106, 0, 0, 0, 0, 0, + 0,107, 0, 0,108, 0, 0, 0, 54, 0, 0, 0, 0, 49,109, 0, + 0, 0, 0,110, 0, 0,111, 0, 0, 0, 0,109, 0, 0, 0, 0, + 0,112, 0, 0, 0,113, 0,114, 0, 0, 0, 0,115,116,117, 0, + 118, 0,119, 0, 0, 0,120,121,122, 0, 0, 0,123, 0, 0,124, + 0, 0,125, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, + 3, 4, 5, 6, 7, 4, 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, + 16, 17, 18, 1, 1, 1, 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, + 21, 24, 25, 26, 27, 28, 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, + 32, 33, 34, 35, 1, 36, 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, + 40, 41, 42, 0, 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, + 19, 1, 21, 0, 0, 47, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, + 51, 0, 52, 1, 1, 1, 53, 21, 43, 54, 55, 21, 35, 1, 0, 0, + 0, 56, 0, 0, 0, 57, 58, 59, 0, 0, 0, 0, 0, 60, 0, 61, + 0, 0, 0, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, + 66, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 69, 0, 0, 70, + 71, 0, 72, 73, 74, 75, 76, 77, 0, 0, 0, 78, 0, 0, 0, 79, + 80, 0, 0, 0, 0, 47, 0, 0, 0, 49, 0, 63, 0, 0, 64, 0, + 0, 81, 0, 0, 82, 0, 0, 0, 83, 0, 0, 19, 84, 0, 63, 0, + 0, 0, 0, 49, 1, 85, 1, 54, 15, 41, 0, 56, 0, 0, 0, 0, + 19, 10, 1, 0, 0, 0, 0, 0, 86, 0, 0, 87, 0, 0, 86, 0, + 0, 0, 0, 79, 0, 0, 88, 9, 12, 4, 89, 8, 90, 47, 0, 59, + 50, 0, 21, 1, 21, 91, 92, 1, 1, 1, 1, 93, 94, 95, 96, 1, + 97, 59, 81, 98, 99, 4, 59, 0, 0, 0, 0, 0, 0, 19, 50, 0, + 0, 0, 0, 0, 0, 62, 0, 0,100,101, 0, 0,102, 0, 0, 1, + 1, 50, 0, 0, 0, 38, 0, 64, 0, 0, 0, 0, 52, 69, 62, 0, + 0, 0, 79, 0, 0, 0,103,104, 59, 38, 81, 0, 0, 0, 0, 0, + 0,105, 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 88, 0, 0, 0, + 0,106, 0, 0,107, 62, 0,108, 0, 0, 0, 1, 0, 0, 0,109, + 14, 54, 0, 0,110, 0, 88, 0, 0, 0, 62, 63, 0, 0, 63, 0, + 87, 0, 0,110, 0, 0, 0, 0,111, 0, 0, 0, 79, 56, 0, 38, + 1, 59, 1, 59, 0, 0, 64, 87, 0, 0,112, 0, 0, 0, 56, 0, + 0, 0, 0,112, 0, 0, 0, 0, 62, 0, 0, 62, 0, 0, 0, 0, + 57, 0, 87,113, 0, 0, 8, 90, 0, 0, 1, 88, 0, 0, 0, 0, + 0,114, 0,115,116,117,118, 0, 52, 4,119, 49, 23, 0, 0, 0, + 38, 50, 38, 59, 0, 0, 1, 88, 1, 1, 1, 1, 39, 1, 48,103, + 88, 0, 0, 0, 0, 1, 4,119, 0, 0, 0, 1,120, 0, 0, 0, + 0, 0,230,230,230,230,230,232,220,220,220,220,232,216,220,220, + 220,220,220,202,202,220,220,220,220,202,202,220,220,220, 1, 1, + 1, 1, 1,220,220,220,220,230,230,230,230,240,230,220,220,220, + 230,230,230,220,220, 0,230,230,230,220,220,220,220,230,232,220, + 220,230,233,234,234,233,234,234,233,230, 0, 0, 0,230, 0,220, + 230,230,230,230,220,230,230,230,222,220,230,230,220,220,230,222, + 228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, + 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0, 0, 0, + 0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,220,230, + 230,220, 35, 0, 0, 0, 0, 0,230,230,230, 0, 0,230,230, 0, + 220,230,230,220, 0, 0, 0, 36, 0, 0,230,220,230,230,220,220, + 230,220,220,230,220,230,220,230,230, 0, 0,220, 0, 0,230,230, + 0,230, 0,230,230,230,230,230, 0, 0, 0,220,220,220, 0, 0, + 0,220,230,230, 0,220,230,220,220,220, 27, 28, 29,230, 7, 0, + 0, 0, 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0, + 230, 0, 0, 84, 91, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, + 9, 0,103,103, 9, 0,107,107,107,107,118,118, 9, 0,122,122, + 122,122,220,220, 0, 0, 0,220, 0,220, 0,216, 0, 0, 0,129, + 130, 0,132, 0, 0, 0, 0, 0,130,130,130,130, 0, 0,130, 0, + 230,230, 9, 0,230,230, 0, 0,220, 0, 0, 0, 0, 7, 0, 9, + 9, 0, 0,230, 0, 0, 0,228, 0, 0, 0,222,230,220,220, 0, + 0, 0,230, 0, 0,220, 0, 0, 9, 9, 0, 0, 7, 0,230,230, + 230, 0,230, 0, 1, 1, 1, 0, 0, 0,230,234,214,220,202,230, + 230,230,230,230,232,228,228,220, 0,230,233,220,230,220,230,230, + 1, 1, 1, 1, 1,230, 0, 1, 1,230,220,230, 1, 1, 0, 0, + 218,228,232,222,224,224, 0, 8, 8, 0,230, 0,230,230,220, 0, + 0,230, 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0, 0,230, + 220, 0, 0, 0,220,220, 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, + 9, 7, 9, 9, 0, 0, 0, 0, 1, 0, 0,216,216, 1, 1, 1, + 0, 0, 0,226,216,216,216,216,216, 0,220,220,220, 0,230,230, + 7, 0, 16, 17, 17, 33, 17, 49, 17, 17, 84, 97,135,145, 26, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17,177, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 5, 3, 3, 3, + 3, 3, 6, 7, 8, 3, 3, 3, 3, 3, 9, 10, 11, 12, 13, 3, + 3, 3, 3, 3, 3, 3, 3, 14, 3, 15, 3, 3, 3, 3, 3, 3, + 16, 17, 18, 19, 20, 21, 3, 3, 3, 22, 23, 3, 3, 3, 3, 3, + 3, 3, 24, 3, 3, 3, 3, 3, 3, 3, 3, 25, 3, 3, 26, 27, + 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, + 0, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 0, + 0, 14, 15, 16, 6, 0, 17, 18, 19, 19, 19, 20, 21, 22, 23, 24, + 19, 25, 0, 26, 27, 19, 19, 28, 29, 30, 0, 31, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 19, 28, 0, 32, 33, 9, 34, 35, 19, + 0, 0, 36, 37, 38, 39, 40, 19, 0, 41, 42, 43, 44, 31, 0, 1, + 45, 42, 0, 0, 0, 0, 0, 32, 14, 14, 0, 0, 0, 0, 14, 0, + 0, 46, 47, 47, 47, 47, 48, 49, 47, 47, 47, 47, 50, 51, 52, 53, + 43, 21, 0, 0, 0, 0, 0, 0, 0, 54, 6, 55, 0, 14, 19, 1, + 0, 0, 0, 19, 56, 31, 0, 0, 0, 0, 0, 0, 0, 57, 14, 0, + 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 58, 59, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3, 0, 4, + 5, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 1, 1, 0, 0, 8, + 9, 0, 8, 9, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0, 0, 0, + 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 1, 0, 0, 18, + 19, 0, 0, 0, 20, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 8, 21, 9, 0, 0, 22, 0, 0, 0, 0, 1, + 0, 23, 24, 25, 0, 0, 26, 0, 0, 0, 8, 21, 27, 0, 1, 0, + 0, 1, 1, 1, 1, 0, 1, 28, 29, 30, 0, 31, 32, 20, 1, 1, + 0, 0, 0, 8, 21, 9, 1, 4, 5, 0, 0, 0, 33, 9, 0, 1, + 1, 1, 0, 8, 21, 21, 21, 21, 34, 1, 35, 21, 21, 21, 9, 36, + 0, 0, 37, 38, 1, 0, 39, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 0, 8, 21, 9, 1, 0, 0, 0, 40, 0, 8, 21, 21, 21, 21, 21, + 21, 21, 21, 9, 0, 1, 1, 1, 1, 8, 21, 21, 21, 9, 0, 0, + 0, 41, 0, 42, 43, 0, 0, 0, 1, 44, 0, 0, 0, 45, 8, 9, + 1, 0, 1, 0, 1, 1, 8, 21, 21, 9, 0, 4, 5, 8, 9, 1, + 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 11, 12, 12, 12, + 12, 13, 14, 15, 16, 17, 18, 12, 19, 12, 20, 12, 12, 12, 12, 21, + 22, 22, 22, 23, 12, 12, 12, 12, 24, 25, 12, 12, 26, 27, 28, 29, + 30, 31, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 32, + 12, 33, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 34, 0, 0, 1, 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 32, 33, 33, 33, 34, 35, 35, 35, 35, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 2, 2, 51, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 57, 57, 56, 56, 56, 56, 56, 56, 58, 59, 60, 61, + 56, 62, 62, 63, 64, 65, 66, 67, 68, 69, 70, 56, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 71, + 62, 62, 62, 62, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 74, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 62, 62, 62, 62, 88, 89, 89, 89, 90, 89, + 91, 92, 93, 94, 95, 95, 96, 97, 87, 98, 99,100,101,102,103, 87, + 104,104,104, 87,105,106,107,108,109,110,111,112,113,114, 56, 87, + 89, 87,115, 89,116,117,118,119,120,121,122, 87,123,124, 87,125, + 126,127,128, 87,129,130, 87, 17,131,132, 87, 87,133,134,135, 51, + 87, 19, 87, 21,136,136,136,136,136,136,136,136,136,136,136, 87, + 87, 87, 87, 87,137,137,137,137,137,137,137,137,137, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,138,138,138,138, + 138, 87, 87, 87,139,139,139,139,140,141,142,142, 87, 87, 87, 87, + 18, 18,143,144,145,145,145,145,145,145,145,145,145,145,145,145, + 145,145,145,145,145,145,145,145,145,145, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87,146,147,148, 32, 32, 32, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,149,150, 87, 87, + 87, 87, 87, 87, 56, 56,151,152, 51, 56, 56, 87, 56, 56, 56, 56, + 56, 56, 56, 56,153,153,153,153,153,153, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87,154, 87, 62, 87, 87,155, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87,156,156,157, 87, 87, 87, 87, 87, 56, 56, 56, 87, + 89, 89, 87, 87, 56, 56, 56, 56,158, 87, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87, + 87, 87, 87, 87, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 56, 87,159,159, 0, 1, 2, 2, 0, 1, 2, 2, + 2, 3, 4, 5, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, + 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, + 11, 11, 12, 11, 13, 13, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 15, 16, 16, 16, 16, 17, 18, 19, 19, + 19, 19, 19, 19, 20, 21, 22, 22, 23, 24, 22, 25, 22, 22, 22, 22, + 22, 26, 22, 22, 27, 27, 27, 27, 27, 22, 22, 22, 28, 28, 28, 28, + 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 27, 27, 22, 22, 22, 22, + 22, 22, 32, 22, 33, 33, 33, 33, 33, 34, 35, 33, 36, 36, 36, 36, + 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, + 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, + 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, + 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, + 44, 44, 44, 44, 45, 45, 45, 46, 45, 45, 45, 45, 47, 47, 47, 47, + 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 49, 48, 48, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, + 51, 51, 51, 52, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, + 56, 56, 56, 56, 57, 57, 58, 58, 58, 58, 59, 58, 60, 60, 61, 62, + 63, 63, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 66, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 56, 56, 56, 56, 56, 68, 68, 68, 68, + 68, 69, 69, 69, 70, 70, 70, 70, 70, 70, 65, 65, 71, 71, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 8, 8, 8, 8, 8, 73, 73, 73, 73, + 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 76, 76, 76, 76, + 76, 77, 77, 77, 13, 51, 51, 51, 74, 78, 79, 80, 4, 4, 81, 4, + 4, 82, 83, 84, 4, 4, 4, 85, 8, 8, 8, 8, 11, 11, 11, 11, + 11, 11, 11, 11, 86, 0, 0, 0, 0, 0, 0, 87, 0, 4, 0, 0, + 0, 8, 8, 8, 0, 0, 88, 89, 90, 0, 4, 4, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 91, 91, 91, + 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, 4, 4, 93, 93, 93, 93, + 93, 93, 93, 93, 51, 51, 51, 94, 94, 94, 94, 94, 54, 54, 54, 54, + 54, 54, 13, 13, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 0, 96, 0, 97, 98, 99,100,100,100,100,101,102,103, + 103,103,103,104,105,105,105,106, 53, 53, 53, 53, 53, 0,105,105, + 0, 0, 0,103, 53, 53, 0, 0, 0, 0, 53,107, 0, 0, 0, 0, + 0,103,103,108,103,103,103,103,103,109, 0, 0, 95, 95, 95, 95, + 0, 0, 0, 0,110,110,110,110,110,110,110,110,110,110,110,110, + 110,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112, + 13, 13, 13, 13, 13, 13,113,113,113,113,113,113, 0, 0,114, 4, + 4, 4, 4, 4,115, 4, 4, 4, 4, 4, 4, 4,116,116,116, 0, + 117,117,117,117,118,118,118,118,118,118, 33, 33,119,119,120,121, + 121,121, 53, 53,122,122,122,122,123,122, 50, 50,124,124,124,124, + 124,124, 50, 50,125,125,125,125,125,125,126,126, 54, 54, 54, 4, + 4,127,128, 55, 55, 55, 55, 55,126,126,126,126,129,129,129,129, + 129,129,129,129, 4,130, 19, 19, 19, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22,131, 0, 22, 22, 22, 8, 0,132, 0, + 0, 0, 0, 22, 22, 22, 22, 22, 22, 22, 22,133, 0, 0, 1, 2, + 1, 2,134,102,103,135, 53, 53, 53, 53, 0, 0,136,136,136,136, + 136,136,136,136, 0, 0, 0, 0, 11, 11, 11, 11, 11, 0, 11, 11, + 11, 0, 0,137,138,138,139,139,139,139,140, 0,141,141,141,142, + 142,143,143,143,144,144,145,145,145,145,145,145,146,146,146,146, + 146,147,147,147,148,148,148,149,149,149,149,149,150,150,150,151, + 151,151,151,151,152,152,152,152,152,152,152,152,153,153,153,153, + 154,154,155,155,156,156,156,156,156,156,157,157,158,158,159,159, + 159,159,159,159,160,160,161,161,161,161,161,161,162,162,162,162, + 162,162,163,163,164,164,164,164,165,165,165,165,166,166,166,166, + 167,167,168,168,169,169,169,169,169,169,169,169,170,170,170,170, + 170,170,170,170,171,171,171,171,171,171,171,171, 8, 8, 8,129, + 129,129,129,129,172,172,172,172,172,172,172,172,173,173,173,173, + 173,174,174,174,175,175,175,175,175,176,176,176,177,177,177,177, + 177,177,178, 44,179,179,179,179,179,179,179,179,180,180,180,181, + 181,181,181,181,182,182,182,183,182,182,182,182,184,184,184,184, + 184,184,184,184,185,185,185,185,185,185,185,185,186,186,186,186, + 186,186,186,186,187,187,187,187,187,187, 67, 67,188,188,188,188, + 188,188,188,188,189,189,189,189,189,189,189,189, 16, 16, 16, 16, + 16, 16, 16, 16,190,190,190,190,190,190,190,190, 13, 13, 13, 13, + 13, 33, 33, 33, 33, 33, 33, 33,191,191,191,191,192,192,192,192, + 192,192,192,193,193,193,193,193,193,193,193,193, 51, 51, 51, 51, + 51, 51, 11, 11,194,194,194,194,194,194,194,194,195,195,195,195, + 195,195,195,195,196,196,196,196,196,196,196,196,113,113,113,113, + 113,113,113,113,113,113,113,113,197,197,197,197,198,198,198,198, + 198,198,198,198,199,199,199,199,199,199,199,199,200,200,200,200, + 200,200,200,200,200,200,200,200,200,200,201, 0,202,202,202,202, + 202,202,202,202,203,100,100,100,100,100,100,100,100,100,100,100, + 100,100,100,100,100,100,100,100,100,100,204, 53,205,205,205,205, + 205,205,205,205,205,205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,206,207,208, 0,209, 0, 0, 0, 0, 0,210,210,210,210, + 210,210,210,210, 92, 92, 92, 92, 92, 92, 92, 92, 19, 19, 19, 19, + 19, 19, 19, 19,211,211,211,211,211,211,211,211,212,212,212,212, + 212,212,212,212,213, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, + 8, 8, 8, 8, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, + 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0, + 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8, + 8, 8, 8, 8, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 14, 14, + 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 17, 19, 20, 20, 20, + 20, 20, 20, 20, 21, 22, 21, 23, 21, 21, 24, 24, 21, 21, 21, 21, + 23, 21, 25, 7, 7, 26, 21, 21, 27, 21, 21, 21, 21, 21, 21, 22, + 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, + 32, 32, 32, 32, 33, 21, 21, 21, 34, 34, 34, 34, 35, 36, 34, 34, + 34, 37, 34, 34, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, + 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, + 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 48, + 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 52, 50, 53, 53, 53, 53, + 54, 54, 54, 54, 54, 54, 55, 54, 56, 56, 56, 56, 57, 57, 57, 57, + 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 61, + 61, 61, 62, 63, 64, 64, 64, 64, 65, 65, 65, 65, 65, 66, 0, 0, + 67, 67, 67, 67, 68, 68, 68, 68, 69, 69, 69, 69, 70, 71, 72, 72, + 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, + 76, 76, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79, + 80, 80, 80, 80, 81, 81, 81, 81, 82, 82, 82, 82, 83, 7, 7, 7, + 84, 7, 85, 86, 0, 85, 87, 0, 2, 88, 89, 2, 2, 2, 2, 90, + 91, 88, 92, 2, 2, 2, 93, 2, 2, 2, 2, 94, 0, 0, 0, 87, + 1, 0, 0, 95, 0, 96, 97, 0, 4, 0, 0, 0, 0, 0, 0, 4, + 98, 98, 98, 98, 99, 99, 99, 99, 13, 13, 13, 13,100,100,100,100, + 101,101,101,101, 0,102, 0, 0,103,101,104,105, 0, 0,101, 0, + 106,107,107,107,107,107,107,107,107,107,108,106,109,110,110,110, + 110,110,110,110,110,110,111,109,112,112,112,112,113, 56, 56, 56, + 56, 56, 56,114,110,110,110,111,110,110, 0, 0,115,115,115,115, + 116,116,116,116,117,117,117,117,118,118,118,118, 97, 2, 2, 2, + 2, 2, 95, 2,119,119,119,119,120,120,120,120,121,121,121,121, + 122,122,122,122,122,122,122,123,124,124,124,124,125,125,125,125, + 125,125,125,126,127,127,127,127,128,128,128,128,129,129,129,129, + 2, 2, 3, 2, 2,130, 2, 2,131,131,131,131,132, 17, 17, 19, + 21, 21, 21,133, 7, 7, 7,134, 21, 21, 21, 24, 0,135,110,110, + 110,110,110,136,137,137,137,137, 0, 0, 0,138,139,139,139,139, + 140,140,140,140, 85, 0, 0, 0,141,141,141,141,142,142,142,142, + 143,143,143,143,144,144,144,144,145,145,145,145,146,146,146,146, + 147,147,147,147,148,148,148,148,149,149,149,149,150,150,150,150, + 151,151,151,151,152,152,152,152,153,153,153,153,154,154,154,154, + 155,155,155,155,156,156,156,156,157,157,157,157,158,158,158,158, + 159,159,159,159,160,160,160,160,161,161,161,161,162,162,162,162, + 163,163,163,163,164,164,164,164,165,165,165,165,166,166,166,166, + 167,167,167,167,168,168,168,168,169,169,169,169,170,170,170,170, + 171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,174, + 175,175,175,175,176,176,176,176,177,177,177,177,178, 46, 46, 46, + 179,179,179,179,180,180,180,180,181,181,181,181,182,182,182,182, + 182,182,183,182,184,184,184,184,185,185,185,185,186,186,186,186, + 187,187,187,187,188,188,188,188,189,189,189,189,190,190,190,190, + 191,191,191,191,192,192,192,192,193,193,193,193,194,194,194,194, + 195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198, + 199,199,199,199,200,200,200,200,201, 0, 0, 0,202,202,202,202, + 203,107,107,107,107,110,110,110,204,204,204,204, 0,205, 87, 0, + 0, 0,205, 7, 83,138, 7, 0, 0, 0,206, 87,207,207,207,207, + 208,208,208,208,209,209,209,209,210, 0, 0, 0, 0, 0, 0, 0, + 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, + 19, 0, 0, 0, 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, + 0, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55, + 55, 55, 55, 55, 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4, + 4, 4, 4, 4, 4, 0, 4, 4, 4, 14, 14, 14, 14, 14, 14, 14, + 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, + 3, 3, 3, 1, 1, 1, 3, 3, 1, 3, 3, 3, 37, 37, 37, 37, + 38, 38, 38, 38, 64, 64, 64, 64, 90, 90, 90, 90, 95, 95, 95, 95, + 3, 3, 0, 3, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, + 0, 0, 7, 7, 5, 5, 5, 5, 11, 11, 11, 11, 10, 10, 10, 10, + 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 16, 16, 16, 16, + 20, 20, 20, 20, 36, 36, 36, 36, 24, 24, 24, 24, 24, 24, 24, 0, + 18, 18, 18, 18, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, 25, 25, + 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 0, 12, 12, 12, 12, + 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28, 34, 34, 34, 34, + 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 45, 45, 45, 45, + 44, 44, 44, 44, 44, 0, 0, 0, 43, 43, 43, 43, 46, 46, 46, 46, + 31, 31, 31, 31, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, + 48, 48, 48, 48, 52, 52, 52, 52, 58, 58, 58, 58, 54, 54, 54, 54, + 91, 91, 91, 91, 62, 62, 62, 62, 76, 76, 76, 76, 93, 93, 93, 93, + 70, 70, 70, 70, 73, 73, 73, 73, 1, 1, 1, 0, 1, 0, 1, 1, + 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 19, 19, 9, 9, + 9, 9, 9, 6, 19, 9, 9, 9, 9, 9, 19, 19, 9, 9, 9, 19, + 6, 19, 19, 19, 19, 19, 19, 9, 0, 0, 0, 19, 0, 0, 9, 0, + 0, 0, 19, 19, 27, 27, 27, 27, 56, 56, 56, 56, 61, 61, 61, 61, + 13, 13, 13, 13, 0, 13, 0, 13, 0, 13, 13, 13, 13, 13, 1, 1, + 1, 1, 12, 12, 0, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, + 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 26, 26, 26, 26, + 26, 12, 12, 12, 12, 12, 12, 0, 39, 39, 39, 39, 86, 86, 86, 86, + 77, 77, 77, 77, 79, 79, 79, 79, 60, 60, 60, 60, 65, 65, 65, 65, + 75, 75, 75, 75, 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, + 84, 84, 84, 84, 84, 84, 84, 0, 68, 68, 68, 68, 92, 92, 92, 92, + 87, 87, 87, 87, 19, 9, 19, 19, 2, 2, 2, 2, 19, 19, 19, 4, + 3, 3, 0, 0, 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0, + 49, 49, 49, 49, 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67, + 42, 42, 42, 42, 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, + 59, 59, 59, 59, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50, + 135,135,135,135,106,106,106,106,104,104,104,104,110,110,110,110, + 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120,116,116,116,116, + 128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98, + 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117, + 112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82, + 122,122,122,122, 89, 89, 89, 89,130,130,130,130, 94, 94, 94, 94, + 85, 85, 85, 85,101,101,101,101, 96, 96, 96, 96,111,111,111,111, + 100,100,100,100,100, 36, 36, 36,108,108,108,108,129,129,129,129, + 109,109,109,109,107,107,107,107,107,107,107, 1,137,137,137,137, + 124,124,124,124,123,123,123,123,114,114,114,114,102,102,102,102, + 126,126,126,126,125,125,125,125,121,121,121,121,133,133,133,133, + 134,134,134,134, 63, 63, 63, 63, 80, 80, 80, 80,127,127,127,127, + 115,115,115,115,103,103,103,103,119,119,119,119, 99, 99, 99, 99, + 136, 12, 0, 0,136,136,136,136, 17, 15, 15, 15,105,105,105,105, + 0, 0, 0, 1, 0, 0, 1, 1,131,131,131,131,113,113,113,113, + 132,132,132,132, 15, 0, 0, 0, 16, 50, 84,118, 88, 89, 90, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 91, 85, 85,220, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, + 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, + 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, + 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, + 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, + 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, + 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, + 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0,110, 0,111,112, + 113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118,119,120,121, + 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131,132,133,134,135, + 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, + 152,153,154,155,156,157, 0, 0, 0,158,159,160,161, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,165, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,169, 0, + 0, 0, 0,170,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,172,173,174,175,176,177,178,179, + 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195, + 196,197,198,199,200,201,202,203,204,205, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 3, 4, +}; +static const uint16_t +_hb_ucd_u16[4800] = +{ + 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, + 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, + 13, 13, 13, 24, 25, 11, 11, 11, 11, 26, 11, 27, 28, 29, 30, 31, + 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 11, 37, 38, 13, 39, + 9, 9, 9, 11, 11, 11, 13, 13, 40, 13, 13, 13, 41, 13, 13, 13, + 13, 13, 13, 35, 9, 42, 11, 11, 43, 44, 32, 45, 46, 47, 47, 48, + 49, 50, 47, 47, 51, 32, 52, 53, 47, 47, 47, 47, 47, 54, 55, 56, + 57, 58, 47, 32, 59, 47, 47, 47, 47, 47, 60, 53, 61, 47, 62, 63, + 47, 64, 65, 66, 47, 67, 47, 47, 47, 47, 47, 47, 47, 68, 69, 32, + 70, 47, 47, 71, 72, 73, 74, 75, 76, 47, 47, 77, 78, 79, 80, 81, + 82, 47, 47, 83, 84, 85, 86, 87, 82, 47, 47, 77, 88, 47, 80, 89, + 90, 47, 47, 91, 92, 93, 80, 94, 95, 47, 47, 96, 97, 98, 99, 100, + 101, 47, 47, 102, 103, 104, 80, 105, 106, 47, 47, 91, 107, 108, 80, 109, + 90, 47, 47, 110, 111, 112, 80, 113, 114, 47, 47, 47, 115, 116, 99, 117, + 47, 47, 47, 118, 119, 120, 66, 66, 47, 47, 47, 121, 122, 123, 47, 47, + 124, 125, 126, 127, 47, 47, 47, 128, 129, 32, 32, 130, 131, 132, 66, 66, + 47, 47, 133, 134, 120, 135, 136, 137, 138, 139, 9, 9, 9, 11, 11, 140, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 141, 142, 143, + 47, 144, 9, 9, 9, 9, 9, 145, 146, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 147, 47, 148, 149, 47, 47, 47, 47, 150, 151, + 47, 152, 47, 153, 47, 152, 47, 152, 47, 47, 47, 154, 155, 156, 157, 143, + 158, 157, 47, 47, 159, 47, 47, 47, 160, 47, 161, 47, 47, 47, 47, 47, + 47, 47, 162, 163, 164, 47, 47, 47, 47, 47, 47, 47, 47, 165, 144, 144, + 47, 166, 47, 47, 47, 167, 168, 169, 157, 157, 170, 171, 172, 172, 172, 172, + 173, 47, 47, 174, 175, 120, 176, 177, 178, 47, 179, 61, 47, 47, 180, 181, + 47, 47, 182, 183, 184, 61, 47, 185, 11, 9, 9, 9, 66, 186, 187, 188, + 11, 11, 189, 27, 27, 27, 190, 191, 11, 192, 27, 27, 32, 32, 32, 32, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 193, 13, 13, 13, 13, 13, 13, + 194, 194, 194, 194, 194, 195, 194, 11, 196, 196, 196, 197, 198, 199, 199, 198, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 27, 209, 209, 209, 210, 211, 32, + 212, 213, 214, 215, 216, 143, 217, 217, 218, 219, 220, 144, 221, 222, 144, 223, + 224, 224, 224, 224, 224, 224, 224, 224, 225, 144, 226, 144, 144, 144, 144, 227, + 144, 228, 224, 229, 144, 230, 231, 144, 144, 144, 144, 144, 144, 144, 143, 143, + 143, 232, 144, 144, 144, 144, 233, 143, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 234, 235, 144, 144, 236, 144, 144, 144, 144, 144, 144, 237, 144, + 144, 144, 144, 144, 144, 144, 238, 239, 143, 240, 144, 144, 241, 224, 242, 224, + 243, 244, 224, 224, 224, 245, 224, 246, 144, 144, 144, 224, 247, 144, 144, 144, + 9, 9, 9, 11, 11, 11, 248, 249, 13, 13, 13, 13, 13, 13, 250, 251, + 11, 11, 11, 47, 47, 47, 252, 253, 47, 47, 47, 47, 47, 47, 32, 32, + 254, 255, 256, 257, 258, 66, 66, 66, 259, 260, 261, 262, 263, 47, 47, 47, + 47, 264, 146, 47, 47, 47, 47, 265, 47, 266, 47, 47, 144, 144, 144, 47, + 144, 144, 267, 144, 268, 269, 144, 144, 267, 144, 144, 269, 144, 144, 144, 144, + 47, 47, 47, 47, 144, 144, 144, 144, 47, 270, 47, 47, 47, 47, 47, 47, + 47, 144, 144, 144, 144, 47, 47, 185, 271, 47, 61, 47, 13, 13, 272, 273, + 13, 274, 47, 47, 47, 47, 275, 276, 31, 277, 278, 279, 13, 13, 13, 280, + 281, 282, 283, 284, 285, 9, 9, 286, 287, 47, 288, 289, 47, 47, 47, 290, + 291, 47, 47, 292, 293, 157, 32, 294, 61, 47, 295, 47, 296, 297, 47, 47, + 70, 47, 47, 298, 299, 300, 301, 61, 47, 47, 302, 303, 304, 305, 47, 306, + 47, 47, 47, 307, 58, 308, 309, 310, 47, 47, 47, 11, 11, 311, 11, 11, + 11, 11, 11, 11, 47, 47, 312, 157, 313, 313, 313, 313, 313, 313, 313, 313, + 314, 314, 314, 314, 314, 314, 314, 314, 11, 315, 316, 47, 47, 47, 47, 47, + 47, 47, 47, 317, 31, 318, 47, 47, 47, 47, 47, 319, 320, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 321, 32, 322, 32, 323, 324, 325, 326, 47, + 47, 47, 47, 47, 47, 47, 47, 327, 328, 2, 3, 4, 5, 329, 330, 331, + 47, 332, 47, 47, 47, 47, 333, 334, 335, 143, 143, 336, 217, 217, 217, 337, + 338, 144, 144, 144, 144, 144, 144, 339, 340, 340, 340, 340, 340, 340, 340, 340, + 47, 47, 47, 47, 47, 47, 341, 143, 47, 47, 342, 47, 343, 47, 47, 60, + 47, 344, 47, 47, 47, 345, 217, 217, 9, 9, 145, 11, 11, 47, 47, 47, + 47, 47, 157, 9, 9, 145, 11, 11, 47, 47, 47, 47, 47, 47, 344, 66, + 47, 47, 47, 47, 47, 346, 47, 347, 47, 47, 348, 143, 143, 143, 47, 349, + 47, 350, 47, 344, 66, 66, 66, 66, 47, 47, 47, 351, 143, 143, 143, 143, + 352, 47, 47, 353, 143, 66, 47, 354, 47, 355, 143, 143, 356, 47, 357, 66, + 47, 47, 47, 358, 47, 359, 47, 359, 47, 358, 142, 143, 143, 143, 143, 143, + 9, 9, 9, 9, 11, 11, 11, 360, 47, 47, 361, 157, 157, 157, 157, 157, + 143, 143, 143, 143, 143, 143, 143, 143, 47, 355, 362, 47, 60, 363, 66, 66, + 364, 47, 47, 353, 365, 366, 367, 368, 178, 47, 47, 369, 370, 47, 47, 157, + 95, 47, 371, 372, 373, 47, 47, 374, 178, 47, 47, 375, 376, 377, 378, 143, + 47, 47, 379, 380, 32, 32, 32, 32, 47, 47, 358, 47, 47, 381, 169, 157, + 90, 47, 47, 110, 382, 383, 384, 32, 47, 47, 47, 385, 386, 387, 47, 47, + 47, 47, 47, 388, 389, 157, 157, 157, 47, 47, 390, 391, 392, 393, 32, 32, + 47, 47, 47, 394, 395, 157, 66, 66, 47, 47, 396, 397, 157, 157, 157, 157, + 47, 141, 398, 399, 144, 144, 144, 144, 47, 47, 379, 400, 66, 66, 66, 66, + 9, 9, 9, 9, 11, 11, 126, 401, 47, 47, 47, 47, 47, 402, 403, 404, + 405, 47, 47, 406, 407, 408, 47, 47, 409, 410, 66, 66, 47, 47, 47, 47, + 47, 47, 390, 411, 412, 126, 143, 413, 47, 152, 414, 415, 32, 32, 32, 32, + 47, 47, 47, 352, 416, 157, 47, 47, 417, 418, 157, 157, 157, 157, 157, 157, + 47, 47, 47, 47, 47, 47, 47, 419, 143, 143, 143, 143, 143, 420, 421, 422, + 217, 217, 217, 217, 217, 217, 217, 66, 47, 47, 47, 206, 206, 206, 206, 206, + 47, 47, 47, 47, 47, 47, 300, 66, 47, 47, 47, 47, 47, 47, 47, 423, + 47, 47, 47, 424, 425, 426, 427, 47, 9, 9, 9, 9, 9, 9, 11, 11, + 143, 428, 66, 66, 66, 66, 66, 66, 47, 47, 47, 47, 381, 429, 404, 404, + 430, 431, 27, 27, 27, 27, 432, 27, 47, 433, 206, 206, 206, 206, 206, 206, + 144, 144, 144, 144, 144, 144, 434, 435, 436, 144, 437, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 438, 144, 144, 144, 9, 439, 11, 440, 441, 11, 194, 9, + 442, 443, 9, 444, 11, 9, 439, 11, 440, 441, 11, 194, 9, 442, 443, 9, + 444, 11, 9, 439, 11, 440, 441, 11, 194, 9, 442, 443, 9, 444, 11, 9, + 439, 11, 194, 9, 445, 446, 447, 448, 11, 449, 9, 450, 451, 452, 453, 11, + 454, 9, 455, 11, 456, 157, 157, 157, 32, 32, 32, 457, 32, 32, 458, 459, + 460, 461, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 47, 47, 47, 462, 463, 144, 144, 144, 47, 47, 47, 47, 47, 47, 464, 465, + 47, 47, 47, 47, 348, 32, 32, 32, 9, 9, 442, 11, 466, 300, 66, 66, + 143, 143, 467, 468, 143, 143, 143, 143, 143, 143, 469, 143, 143, 143, 143, 143, + 47, 47, 47, 47, 47, 47, 47, 224, 143, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 470, 206, 206, 206, 206, 206, 206, 206, 206, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008, + 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0, + 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193, + 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303, + 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149, + 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175, + 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199, + 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0, + 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231, + 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258, + 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275, + 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0, + 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093, + 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010, + 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347, + 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424, + 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365, + 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238, + 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182, + 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232, + 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461, + 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486, + 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0, + 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0, + 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0, + 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553, + 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560, + 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0, + 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0, + 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627, + 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0, + 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0, + 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0, + 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0, + 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0, + 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0, + 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0, + 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0, + 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153, + 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171, + 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356, + 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214, + 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363, + 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251, + 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266, + 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287, + 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302, + 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0, + 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375, + 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353, + 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234, + 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403, + 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412, + 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0, + 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721, + 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0, + 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757, + 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776, + 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0, + 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793, + 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814, + 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0, + 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728, + 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764, + 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821, + 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0, + 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828, + 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833, + 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3, + 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838, + 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0, + 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0, + 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938, + 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0, + 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870, + 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0, + 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0, + 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0, + 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0, + 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0, + 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0, + 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0, + 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0, + 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0, + 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601, + 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662, + 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168, + 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758, + 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585, + 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259, + 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697, + 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170, + 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330, + 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473, + 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603, + 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411, + 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583, + 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269, + 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510, + 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156, + 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0, + 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0, + 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773, + 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329, + 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548, + 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651, + 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0, + 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243, + 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362, + 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490, + 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586, + 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706, + 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848, + 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575, + 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0, + 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1948,1949, + 1950,1951,1952,1953,1954, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1955,1956,1957,1959,1958, + 1960, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131, + 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37, + 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179, + 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195, + 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216, + 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244, + 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259, + 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276, + 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934, + 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312, + 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334, + 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361, + 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381, + 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399, + 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417, + 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433, + 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460, + 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870, + 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505, + 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64, + 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538, + 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567, + 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592, + 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611, + 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627, + 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651, + 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83, + 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85, + 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696, + 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728, + 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90, + 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787, + 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807, + 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0, +}; +static const int16_t +_hb_ucd_i16[92] = +{ + 0, 0, 1, -1, 2, 0, -2, 0, 0, 2, 0, -2, 0, 16, 0, -16, + 0, 1, -1, 0, 3, 3, 3, -3, -3, -3, 0, 2016, 0, 2527, 1923, 1914, + 1918, 0, 2250, 0, 0, 138, 0, 7, -7, 0, -1, 1, 1824, 0, 2104, 0, + 2108, 2106, 0, 2106, 1316, 0, -1, -138, 8, 8, 8, 0, 7, 7, -8, -8, + -8, -7,-1316, 1, -1, 3, -3, 1, 0,-1914,-1918, 0, 0,-1923,-1824, 0, + 0,-2016,-2104, 0, 0,-2106,-2108,-2106,-2250, 0,-2527, 0, +}; + +static inline uint_fast8_t +_hb_ucd_gc (unsigned u) +{ + return u<1114112u?_hb_ucd_u8[4840+(((_hb_ucd_u8[1072+(((_hb_ucd_u16[((_hb_ucd_u8[272+(((_hb_ucd_u8[u>>1>>3>>3>>5])<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2; +} +static inline uint_fast8_t +_hb_ucd_ccc (unsigned u) +{ + return u<125259u?_hb_ucd_u8[6670+(((_hb_ucd_u8[6166+(((_hb_ucd_u8[5754+(((_hb_ucd_u8[5306+(((_hb_ucd_u8[5182+(u>>2>>2>>2>>4)])<<4)+((u>>2>>2>>2)&15u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0; +} +static inline unsigned +_hb_ucd_b4 (const uint8_t* a, unsigned i) +{ + return (a[i>>1]>>((i&1u)<<2))&15u; +} +static inline int_fast16_t +_hb_ucd_bmg (unsigned u) +{ + return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7538+(((_hb_ucd_u8[7314+(((_hb_ucd_u8[7218+(((_hb_ucd_b4(7154+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0; +} +static inline uint_fast8_t +_hb_ucd_sc (unsigned u) +{ + return u<918016u?_hb_ucd_u8[10924+(((_hb_ucd_u8[10068+(((_hb_ucd_u8[8788+(((_hb_ucd_u8[8228+(((_hb_ucd_u8[7778+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2; +} +static inline uint_fast16_t +_hb_ucd_dm (unsigned u) +{ + return u<195102u?_hb_ucd_u16[1504+(((_hb_ucd_u8[11864+(((_hb_ucd_b4(11768+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0; +} + #endif From c2d7dfc68ffcb389c9f73b5ef94da7b270bdcf9e Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Sat, 22 Jun 2019 19:38:48 -0600 Subject: [PATCH 067/138] Add missing cairo-svg dependency to test-ot-color --- src/test-ot-color.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test-ot-color.cc b/src/test-ot-color.cc index 44bd2eb69..e9126c064 100644 --- a/src/test-ot-color.cc +++ b/src/test-ot-color.cc @@ -25,7 +25,9 @@ #include "hb.hh" -#ifndef HB_NO_COLOR +#include + +#if !defined(HB_NO_COLOR) && defined(CAIRO_HAS_SVG_SURFACE) #include "hb-ot.h" @@ -35,7 +37,6 @@ #include FT_FREETYPE_H #include FT_GLYPH_H -#include #include #include From 9bd8d66c2ba97aec57597ff85e059a7618260a1c Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Wed, 12 Jun 2019 11:02:48 -0700 Subject: [PATCH 068/138] [subset] VORG table to use _subset2 method and new iterator frameworks --- src/hb-ot-vorg-table.hh | 116 +++++++++++----------------------------- src/hb-subset.cc | 2 +- 2 files changed, 33 insertions(+), 85 deletions(-) diff --git a/src/hb-ot-vorg-table.hh b/src/hb-ot-vorg-table.hh index b2059e86e..19e08ebb5 100644 --- a/src/hb-ot-vorg-table.hh +++ b/src/hb-ot-vorg-table.hh @@ -69,102 +69,50 @@ struct VORG return vertYOrigins[i].vertOriginY; } - bool _subset (const hb_subset_plan_t *plan HB_UNUSED, - const VORG *vorg_table, - const hb_vector_t &subset_metrics, - unsigned int dest_sz, - void *dest) const + template + void serialize (hb_serialize_context_t *c, + Iterator it, + FWORD defaultVertOriginY) { - hb_serialize_context_t c (dest, dest_sz); - VORG *subset_table = c.start_serialize (); - if (unlikely (!c.extend_min (*subset_table))) - return false; + if (unlikely (!c->extend_min ((*this)))) return; - subset_table->version.major = 1; - subset_table->version.minor = 0; + this->version.major = 1; + this->version.minor = 0; - subset_table->defaultVertOriginY = vorg_table->defaultVertOriginY; - subset_table->vertYOrigins.len = subset_metrics.length; + this->defaultVertOriginY = defaultVertOriginY; + this->vertYOrigins.len = it.len (); - bool success = true; - if (subset_metrics.length > 0) - { - unsigned int size = VertOriginMetric::static_size * subset_metrics.length; - VertOriginMetric *metrics = c.allocate_size (size); - if (likely (metrics != nullptr)) - memcpy (metrics, &subset_metrics[0], size); - else - success = false; - } - c.end_serialize (); - - return success; + + it + | hb_apply ([c] (const VertOriginMetric& _) { c->copy (_);}) + ; } - bool subset (hb_subset_plan_t *plan) const + bool subset (hb_subset_context_t *c) const { - hb_blob_t *vorg_blob = hb_sanitize_context_t().reference_table (plan->source); - const VORG *vorg_table = vorg_blob->as (); + TRACE_SUBSET (this); + VORG *vorg_prime = c->serializer->start_embed (); + if (unlikely (!c->serializer->check_success (vorg_prime))) return_trace (false); - /* count the number of glyphs to be included in the subset table */ - hb_vector_t subset_metrics; - subset_metrics.init (); + auto it = + + vertYOrigins.as_array () + | hb_filter (c->plan->glyphset (), &VertOriginMetric::glyph) + | hb_map ([&] (const VertOriginMetric& _) + { + hb_codepoint_t new_glyph = HB_SET_VALUE_INVALID; + c->plan->new_gid_for_old_gid (_.glyph, &new_glyph); - - hb_codepoint_t old_glyph = HB_SET_VALUE_INVALID; - unsigned int i = 0; - while (i < vertYOrigins.len - && plan->glyphset ()->next (&old_glyph)) - { - while (old_glyph > vertYOrigins[i].glyph) - { - i++; - if (i >= vertYOrigins.len) - break; - } - - if (old_glyph == vertYOrigins[i].glyph) - { - hb_codepoint_t new_glyph; - if (plan->new_gid_for_old_gid (old_glyph, &new_glyph)) - { - VertOriginMetric *metrics = subset_metrics.push (); - metrics->glyph = new_glyph; - metrics->vertOriginY = vertYOrigins[i].vertOriginY; - } - } - } - - /* alloc the new table */ - unsigned int dest_sz = VORG::min_size + VertOriginMetric::static_size * subset_metrics.length; - void *dest = (void *) malloc (dest_sz); - if (unlikely (!dest)) - { - subset_metrics.fini (); - hb_blob_destroy (vorg_blob); - return false; - } + VertOriginMetric metric; + metric.glyph = new_glyph; + metric.vertOriginY = _.vertOriginY; + return metric; + }) + ; /* serialize the new table */ - if (!_subset (plan, vorg_table, subset_metrics, dest_sz, dest)) - { - subset_metrics.fini (); - free (dest); - hb_blob_destroy (vorg_blob); - return false; - } - - hb_blob_t *result = hb_blob_create ((const char *)dest, - dest_sz, - HB_MEMORY_MODE_READONLY, - dest, - free); - bool success = plan->add_table (HB_OT_TAG_VORG, result); - hb_blob_destroy (result); - subset_metrics.fini (); - hb_blob_destroy (vorg_blob); - return success; + vorg_prime->serialize (c->serializer, it, defaultVertOriginY); + return_trace (true); } bool sanitize (hb_sanitize_context_t *c) const diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 3f4c2e40b..b117870c8 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -204,7 +204,7 @@ _subset_table (hb_subset_plan_t *plan, result = _subset (plan); break; case HB_OT_TAG_VORG: - result = _subset (plan); + result = _subset2 (plan); break; #endif From 9c933acaa443889bc2484dbe3ef3e990b299cd52 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 23 Jun 2019 17:14:27 -0700 Subject: [PATCH 069/138] [ucd] Save a few more bytes Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/gen-ucd-table.py | 11 ++++++----- src/hb-ucd-table.hh | 34 +++++++++++++++++----------------- src/hb-ucd.cc | 12 ++++++------ 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py index dd3a54626..7410dd3f0 100755 --- a/src/gen-ucd-table.py +++ b/src/gen-ucd-table.py @@ -34,15 +34,16 @@ ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'} assert not any(v for v in dm.values() if len(v) not in (1,2)) dm1 = sorted(set(v for v in dm.values() if len(v) == 1)) -dm1_u16_array = ['0x%04Xu' % v for v in dm1 if v[0] <= 0xFFFF] -dm1_u32_array = ['0x%04Xu' % v for v in dm1 if v[0] > 0xFFFF] +assert all((v[0] >> 16) in (0,2) for v in dm1) +dm1_p0_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 0] +dm1_p2_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 2] dm1_order = {v:i+1 for i,v in enumerate(dm1)} dm2 = sorted((v, i) for i,v in dm.items() if len(v) == 2) dm2 = [("HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % (v+(i if i not in ce and not ccc[i] else 0,)), v) for v,i in dm2] dm2_array = [s for s,v in dm2] -l = 1 + len(dm1_u16_array) + len(dm1_u32_array) +l = 1 + len(dm1_p0_array) + len(dm1_p2_array) dm2_order = {v[1]:i+l for i,v in enumerate(dm2)} dm_order = {None: 0} dm_order.update(dm1_order) @@ -93,8 +94,8 @@ print() code = packTab.Code('_hb_ucd') sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array) -dm1_16_array, _ = code.addArray('uint16_t', 'dm1_u16_map', dm1_u16_array) -dm1_32_array, _ = code.addArray('uint32_t', 'dm1_u32_map', dm1_u32_array) +dm1_p0_array, _ = code.addArray('uint16_t', 'dm1_p0_map', dm1_p0_array) +dm1_p2_array, _ = code.addArray('uint16_t', 'dm1_p2_map', dm1_p2_array) dm2_array, _ = code.addArray('uint64_t', 'dm2_map', dm2_array) code.print_c(linkage='static inline') diff --git a/src/hb-ucd-table.hh b/src/hb-ucd-table.hh index 014508003..5cd503bf5 100644 --- a/src/hb-ucd-table.hh +++ b/src/hb-ucd-table.hh @@ -86,7 +86,7 @@ _hb_ucd_sc_map[138] = HB_SCRIPT_TANGUT, HB_SCRIPT_NEWA, }; static const uint16_t -_hb_ucd_dm1_u16_map[825] = +_hb_ucd_dm1_p0_map[825] = { 0x003Bu, 0x004Bu, 0x0060u, 0x00B4u, 0x00B7u, 0x00C5u, 0x02B9u, 0x0300u, 0x0301u, 0x0313u, 0x0385u, 0x0386u, 0x0388u, 0x0389u, 0x038Au, 0x038Cu, @@ -193,23 +193,23 @@ _hb_ucd_dm1_u16_map[825] = 0x9EFEu, 0x9F05u, 0x9F0Fu, 0x9F16u, 0x9F3Bu, 0x9F43u, 0x9F8Du, 0x9F8Eu, 0x9F9Cu, }; -static const uint32_t -_hb_ucd_dm1_u32_map[110] = +static const uint16_t +_hb_ucd_dm1_p2_map[110] = { - 0x20122u,0x2051Cu,0x20525u,0x2054Bu,0x2063Au,0x20804u,0x208DEu,0x20A2Cu, - 0x20B63u,0x214E4u,0x216A8u,0x216EAu,0x219C8u,0x21B18u,0x21D0Bu,0x21DE4u, - 0x21DE6u,0x22183u,0x2219Fu,0x22331u,0x226D4u,0x22844u,0x2284Au,0x22B0Cu, - 0x22BF1u,0x2300Au,0x232B8u,0x2335Fu,0x23393u,0x2339Cu,0x233C3u,0x233D5u, - 0x2346Du,0x236A3u,0x238A7u,0x23A8Du,0x23AFAu,0x23CBCu,0x23D1Eu,0x23ED1u, - 0x23F5Eu,0x23F8Eu,0x24263u,0x242EEu,0x243ABu,0x24608u,0x24735u,0x24814u, - 0x24C36u,0x24C92u,0x24FA1u,0x24FB8u,0x25044u,0x250F2u,0x250F3u,0x25119u, - 0x25133u,0x25249u,0x2541Du,0x25626u,0x2569Au,0x256C5u,0x2597Cu,0x25AA7u, - 0x25BABu,0x25C80u,0x25CD0u,0x25F86u,0x261DAu,0x26228u,0x26247u,0x262D9u, - 0x2633Eu,0x264DAu,0x26523u,0x265A8u,0x267A7u,0x267B5u,0x26B3Cu,0x26C36u, - 0x26CD5u,0x26D6Bu,0x26F2Cu,0x26FB1u,0x270D2u,0x273CAu,0x27667u,0x278AEu, - 0x27966u,0x27CA8u,0x27ED3u,0x27F2Fu,0x285D2u,0x285EDu,0x2872Eu,0x28BFAu, - 0x28D77u,0x29145u,0x291DFu,0x2921Au,0x2940Au,0x29496u,0x295B6u,0x29B30u, - 0x2A0CEu,0x2A105u,0x2A20Eu,0x2A291u,0x2A392u,0x2A600u, + 0x0122u, 0x051Cu, 0x0525u, 0x054Bu, 0x063Au, 0x0804u, 0x08DEu, 0x0A2Cu, + 0x0B63u, 0x14E4u, 0x16A8u, 0x16EAu, 0x19C8u, 0x1B18u, 0x1D0Bu, 0x1DE4u, + 0x1DE6u, 0x2183u, 0x219Fu, 0x2331u, 0x26D4u, 0x2844u, 0x284Au, 0x2B0Cu, + 0x2BF1u, 0x300Au, 0x32B8u, 0x335Fu, 0x3393u, 0x339Cu, 0x33C3u, 0x33D5u, + 0x346Du, 0x36A3u, 0x38A7u, 0x3A8Du, 0x3AFAu, 0x3CBCu, 0x3D1Eu, 0x3ED1u, + 0x3F5Eu, 0x3F8Eu, 0x4263u, 0x42EEu, 0x43ABu, 0x4608u, 0x4735u, 0x4814u, + 0x4C36u, 0x4C92u, 0x4FA1u, 0x4FB8u, 0x5044u, 0x50F2u, 0x50F3u, 0x5119u, + 0x5133u, 0x5249u, 0x541Du, 0x5626u, 0x569Au, 0x56C5u, 0x597Cu, 0x5AA7u, + 0x5BABu, 0x5C80u, 0x5CD0u, 0x5F86u, 0x61DAu, 0x6228u, 0x6247u, 0x62D9u, + 0x633Eu, 0x64DAu, 0x6523u, 0x65A8u, 0x67A7u, 0x67B5u, 0x6B3Cu, 0x6C36u, + 0x6CD5u, 0x6D6Bu, 0x6F2Cu, 0x6FB1u, 0x70D2u, 0x73CAu, 0x7667u, 0x78AEu, + 0x7966u, 0x7CA8u, 0x7ED3u, 0x7F2Fu, 0x85D2u, 0x85EDu, 0x872Eu, 0x8BFAu, + 0x8D77u, 0x9145u, 0x91DFu, 0x921Au, 0x940Au, 0x9496u, 0x95B6u, 0x9B30u, + 0xA0CEu, 0xA105u, 0xA20Eu, 0xA291u, 0xA392u, 0xA600u, }; static const uint64_t _hb_ucd_dm2_map[1025] = diff --git a/src/hb-ucd.cc b/src/hb-ucd.cc index 4d35017a6..4bdd4f463 100644 --- a/src/hb-ucd.cc +++ b/src/hb-ucd.cc @@ -148,19 +148,19 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, if (likely (!i)) return false; i--; - if (i < ARRAY_LENGTH (_hb_ucd_dm1_u16_map) + ARRAY_LENGTH (_hb_ucd_dm1_u32_map)) + if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map)) { - if (i < ARRAY_LENGTH (_hb_ucd_dm1_u16_map)) - *a = _hb_ucd_dm1_u16_map[i]; + if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map)) + *a = _hb_ucd_dm1_p0_map[i]; else { - i -= ARRAY_LENGTH (_hb_ucd_dm1_u16_map); - *a = _hb_ucd_dm1_u32_map[i]; + i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map); + *a = 0x20000 | _hb_ucd_dm1_p2_map[i]; } *b = 0; return true; } - i -= ARRAY_LENGTH (_hb_ucd_dm1_u16_map) + ARRAY_LENGTH (_hb_ucd_dm1_u32_map); + i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map); uint64_t v = _hb_ucd_dm2_map[i]; *a = HB_CODEPOINT_DECODE3_1 (v); From ec8e635e0c1a8e5c631a90820be68cf07c52c1a0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 24 Jun 2019 12:37:23 -0700 Subject: [PATCH 070/138] [ucd] Use custom encoding to shrink composition data Saves another 2.5kb. Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/gen-ucd-table.py | 22 +- src/hb-algs.hh | 5 + src/hb-ucd-table.hh | 965 +++++++++++++++++++++++++++++-------------- src/hb-ucd.cc | 49 ++- 4 files changed, 705 insertions(+), 336 deletions(-) diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py index 7410dd3f0..053953a97 100755 --- a/src/gen-ucd-table.py +++ b/src/gen-ucd-table.py @@ -38,13 +38,22 @@ assert all((v[0] >> 16) in (0,2) for v in dm1) dm1_p0_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 0] dm1_p2_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 2] dm1_order = {v:i+1 for i,v in enumerate(dm1)} -dm2 = sorted((v, i) for i,v in dm.items() if len(v) == 2) -dm2 = [("HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % - (v+(i if i not in ce and not ccc[i] else 0,)), v) - for v,i in dm2] -dm2_array = [s for s,v in dm2] + +dm2 = sorted((v+(i if i not in ce and not ccc[i] else 0,), v) + for i,v in dm.items() if len(v) == 2) + +filt = lambda v: ((v[0] & 0xFFFFF800) == 0x0000 and + (v[1] & 0xFFFFFF80) == 0x0300 and + (v[2] & 0xFFF0C000) == 0x0000) +dm2_u32_array = [v for v in dm2 if filt(v[0])] +dm2_u64_array = [v for v in dm2 if not filt(v[0])] +assert dm2_u32_array + dm2_u64_array == dm2 +dm2_u32_array = ["HB_CODEPOINT_ENCODE3_11_7_14 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % v[0] for v in dm2_u32_array] +dm2_u64_array = ["HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % v[0] for v in dm2_u64_array] + l = 1 + len(dm1_p0_array) + len(dm1_p2_array) dm2_order = {v[1]:i+l for i,v in enumerate(dm2)} + dm_order = {None: 0} dm_order.update(dm1_order) dm_order.update(dm2_order) @@ -96,7 +105,8 @@ code = packTab.Code('_hb_ucd') sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array) dm1_p0_array, _ = code.addArray('uint16_t', 'dm1_p0_map', dm1_p0_array) dm1_p2_array, _ = code.addArray('uint16_t', 'dm1_p2_map', dm1_p2_array) -dm2_array, _ = code.addArray('uint64_t', 'dm2_map', dm2_array) +dm2_u32_array, _ = code.addArray('uint32_t', 'dm2_u32_map', dm2_u32_array) +dm2_u64_array, _ = code.addArray('uint64_t', 'dm2_u64_map', dm2_u64_array) code.print_c(linkage='static inline') datasets = [ diff --git a/src/hb-algs.hh b/src/hb-algs.hh index 4a537baf3..c8d83c828 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -41,6 +41,11 @@ #define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu) #define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu) +/* Custom encoding used by hb-ucd. */ +#define HB_CODEPOINT_ENCODE3_11_7_14(x,y,z) (((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu)) +#define HB_CODEPOINT_DECODE3_11_7_14_1(v) ((hb_codepoint_t) ((v) >> 21)) +#define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300) +#define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu) struct { diff --git a/src/hb-ucd-table.hh b/src/hb-ucd-table.hh index 5cd503bf5..ae9ce3e2f 100644 --- a/src/hb-ucd-table.hh +++ b/src/hb-ucd-table.hh @@ -211,328 +211,651 @@ _hb_ucd_dm1_p2_map[110] = 0x8D77u, 0x9145u, 0x91DFu, 0x921Au, 0x940Au, 0x9496u, 0x95B6u, 0x9B30u, 0xA0CEu, 0xA105u, 0xA20Eu, 0xA291u, 0xA392u, 0xA600u, }; -static const uint64_t -_hb_ucd_dm2_map[1025] = +static const uint32_t +_hb_ucd_dm2_u32_map[638] = +{ + HB_CODEPOINT_ENCODE3_11_7_14 (0x003Cu, 0x0338u, 0x226Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x003Du, 0x0338u, 0x2260u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x003Eu, 0x0338u, 0x226Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0300u, 0x00C0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0301u, 0x00C1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0302u, 0x00C2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0303u, 0x00C3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0304u, 0x0100u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0306u, 0x0102u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0307u, 0x0226u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0308u, 0x00C4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0309u, 0x1EA2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x030Au, 0x00C5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x030Cu, 0x01CDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x030Fu, 0x0200u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0311u, 0x0202u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0323u, 0x1EA0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0325u, 0x1E00u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0328u, 0x0104u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0042u, 0x0307u, 0x1E02u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0042u, 0x0323u, 0x1E04u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0042u, 0x0331u, 0x1E06u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0301u, 0x0106u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0302u, 0x0108u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0307u, 0x010Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x030Cu, 0x010Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0327u, 0x00C7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0307u, 0x1E0Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x030Cu, 0x010Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0323u, 0x1E0Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0327u, 0x1E10u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x032Du, 0x1E12u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0331u, 0x1E0Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0300u, 0x00C8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0301u, 0x00C9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0302u, 0x00CAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0303u, 0x1EBCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0304u, 0x0112u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0306u, 0x0114u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0307u, 0x0116u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0308u, 0x00CBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0309u, 0x1EBAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x030Cu, 0x011Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x030Fu, 0x0204u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0311u, 0x0206u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0323u, 0x1EB8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0327u, 0x0228u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0328u, 0x0118u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x032Du, 0x1E18u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0330u, 0x1E1Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0046u, 0x0307u, 0x1E1Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0301u, 0x01F4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0302u, 0x011Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0304u, 0x1E20u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0306u, 0x011Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0307u, 0x0120u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x030Cu, 0x01E6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0327u, 0x0122u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0302u, 0x0124u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0307u, 0x1E22u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0308u, 0x1E26u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x030Cu, 0x021Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0323u, 0x1E24u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0327u, 0x1E28u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x032Eu, 0x1E2Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0300u, 0x00CCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0301u, 0x00CDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0302u, 0x00CEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0303u, 0x0128u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0304u, 0x012Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0306u, 0x012Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0307u, 0x0130u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0308u, 0x00CFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0309u, 0x1EC8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x030Cu, 0x01CFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x030Fu, 0x0208u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0311u, 0x020Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0323u, 0x1ECAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0328u, 0x012Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0330u, 0x1E2Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Au, 0x0302u, 0x0134u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0301u, 0x1E30u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x030Cu, 0x01E8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0323u, 0x1E32u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0327u, 0x0136u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0331u, 0x1E34u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0301u, 0x0139u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x030Cu, 0x013Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0323u, 0x1E36u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0327u, 0x013Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x032Du, 0x1E3Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0331u, 0x1E3Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Du, 0x0301u, 0x1E3Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Du, 0x0307u, 0x1E40u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Du, 0x0323u, 0x1E42u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0300u, 0x01F8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0301u, 0x0143u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0303u, 0x00D1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0307u, 0x1E44u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x030Cu, 0x0147u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0323u, 0x1E46u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0327u, 0x0145u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x032Du, 0x1E4Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0331u, 0x1E48u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0300u, 0x00D2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0301u, 0x00D3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0302u, 0x00D4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0303u, 0x00D5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0304u, 0x014Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0306u, 0x014Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0307u, 0x022Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0308u, 0x00D6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0309u, 0x1ECEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x030Bu, 0x0150u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x030Cu, 0x01D1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x030Fu, 0x020Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0311u, 0x020Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x031Bu, 0x01A0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0323u, 0x1ECCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0328u, 0x01EAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0050u, 0x0301u, 0x1E54u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0050u, 0x0307u, 0x1E56u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0301u, 0x0154u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0307u, 0x1E58u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x030Cu, 0x0158u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x030Fu, 0x0210u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0311u, 0x0212u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0323u, 0x1E5Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0327u, 0x0156u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0331u, 0x1E5Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0301u, 0x015Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0302u, 0x015Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0307u, 0x1E60u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x030Cu, 0x0160u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0323u, 0x1E62u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0326u, 0x0218u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0327u, 0x015Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0307u, 0x1E6Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x030Cu, 0x0164u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0323u, 0x1E6Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0326u, 0x021Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0327u, 0x0162u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x032Du, 0x1E70u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0331u, 0x1E6Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0300u, 0x00D9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0301u, 0x00DAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0302u, 0x00DBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0303u, 0x0168u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0304u, 0x016Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0306u, 0x016Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0308u, 0x00DCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0309u, 0x1EE6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Au, 0x016Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Bu, 0x0170u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Cu, 0x01D3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Fu, 0x0214u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0311u, 0x0216u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x031Bu, 0x01AFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0323u, 0x1EE4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0324u, 0x1E72u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0328u, 0x0172u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x032Du, 0x1E76u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0330u, 0x1E74u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0056u, 0x0303u, 0x1E7Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0056u, 0x0323u, 0x1E7Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0300u, 0x1E80u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0301u, 0x1E82u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0302u, 0x0174u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0307u, 0x1E86u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0308u, 0x1E84u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0323u, 0x1E88u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0058u, 0x0307u, 0x1E8Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0058u, 0x0308u, 0x1E8Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0300u, 0x1EF2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0301u, 0x00DDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0302u, 0x0176u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0303u, 0x1EF8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0304u, 0x0232u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0307u, 0x1E8Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0308u, 0x0178u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0309u, 0x1EF6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0323u, 0x1EF4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0301u, 0x0179u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0302u, 0x1E90u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0307u, 0x017Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x030Cu, 0x017Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0323u, 0x1E92u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0331u, 0x1E94u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0300u, 0x00E0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0301u, 0x00E1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0302u, 0x00E2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0303u, 0x00E3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0304u, 0x0101u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0306u, 0x0103u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0307u, 0x0227u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0308u, 0x00E4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0309u, 0x1EA3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x030Au, 0x00E5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x030Cu, 0x01CEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x030Fu, 0x0201u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0311u, 0x0203u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0323u, 0x1EA1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0325u, 0x1E01u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0328u, 0x0105u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0062u, 0x0307u, 0x1E03u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0062u, 0x0323u, 0x1E05u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0062u, 0x0331u, 0x1E07u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0301u, 0x0107u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0302u, 0x0109u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0307u, 0x010Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x030Cu, 0x010Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0327u, 0x00E7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0307u, 0x1E0Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x030Cu, 0x010Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0323u, 0x1E0Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0327u, 0x1E11u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x032Du, 0x1E13u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0331u, 0x1E0Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0300u, 0x00E8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0301u, 0x00E9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0302u, 0x00EAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0303u, 0x1EBDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0304u, 0x0113u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0306u, 0x0115u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0307u, 0x0117u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0308u, 0x00EBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0309u, 0x1EBBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x030Cu, 0x011Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x030Fu, 0x0205u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0311u, 0x0207u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0323u, 0x1EB9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0327u, 0x0229u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0328u, 0x0119u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x032Du, 0x1E19u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0330u, 0x1E1Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0066u, 0x0307u, 0x1E1Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0301u, 0x01F5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0302u, 0x011Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0304u, 0x1E21u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0306u, 0x011Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0307u, 0x0121u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x030Cu, 0x01E7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0327u, 0x0123u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0302u, 0x0125u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0307u, 0x1E23u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0308u, 0x1E27u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x030Cu, 0x021Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0323u, 0x1E25u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0327u, 0x1E29u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x032Eu, 0x1E2Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0331u, 0x1E96u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0300u, 0x00ECu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0301u, 0x00EDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0302u, 0x00EEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0303u, 0x0129u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0304u, 0x012Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0306u, 0x012Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0308u, 0x00EFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0309u, 0x1EC9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x030Cu, 0x01D0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x030Fu, 0x0209u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0311u, 0x020Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0323u, 0x1ECBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0328u, 0x012Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0330u, 0x1E2Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Au, 0x0302u, 0x0135u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Au, 0x030Cu, 0x01F0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0301u, 0x1E31u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x030Cu, 0x01E9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0323u, 0x1E33u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0327u, 0x0137u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0331u, 0x1E35u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0301u, 0x013Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x030Cu, 0x013Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0323u, 0x1E37u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0327u, 0x013Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x032Du, 0x1E3Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0331u, 0x1E3Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Du, 0x0301u, 0x1E3Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Du, 0x0307u, 0x1E41u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Du, 0x0323u, 0x1E43u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0300u, 0x01F9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0301u, 0x0144u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0303u, 0x00F1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0307u, 0x1E45u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x030Cu, 0x0148u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0323u, 0x1E47u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0327u, 0x0146u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x032Du, 0x1E4Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0331u, 0x1E49u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0300u, 0x00F2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0301u, 0x00F3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0302u, 0x00F4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0303u, 0x00F5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0304u, 0x014Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0306u, 0x014Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0307u, 0x022Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0308u, 0x00F6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0309u, 0x1ECFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x030Bu, 0x0151u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x030Cu, 0x01D2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x030Fu, 0x020Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0311u, 0x020Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x031Bu, 0x01A1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0323u, 0x1ECDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0328u, 0x01EBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0070u, 0x0301u, 0x1E55u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0070u, 0x0307u, 0x1E57u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0301u, 0x0155u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0307u, 0x1E59u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x030Cu, 0x0159u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x030Fu, 0x0211u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0311u, 0x0213u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0323u, 0x1E5Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0327u, 0x0157u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0331u, 0x1E5Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0301u, 0x015Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0302u, 0x015Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0307u, 0x1E61u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x030Cu, 0x0161u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0323u, 0x1E63u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0326u, 0x0219u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0327u, 0x015Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0307u, 0x1E6Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0308u, 0x1E97u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x030Cu, 0x0165u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0323u, 0x1E6Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0326u, 0x021Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0327u, 0x0163u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x032Du, 0x1E71u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0331u, 0x1E6Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0300u, 0x00F9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0301u, 0x00FAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0302u, 0x00FBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0303u, 0x0169u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0304u, 0x016Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0306u, 0x016Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0308u, 0x00FCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0309u, 0x1EE7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Au, 0x016Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Bu, 0x0171u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Cu, 0x01D4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Fu, 0x0215u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0311u, 0x0217u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x031Bu, 0x01B0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0323u, 0x1EE5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0324u, 0x1E73u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0328u, 0x0173u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x032Du, 0x1E77u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0330u, 0x1E75u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0076u, 0x0303u, 0x1E7Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0076u, 0x0323u, 0x1E7Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0300u, 0x1E81u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0301u, 0x1E83u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0302u, 0x0175u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0307u, 0x1E87u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0308u, 0x1E85u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x030Au, 0x1E98u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0323u, 0x1E89u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0078u, 0x0307u, 0x1E8Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0078u, 0x0308u, 0x1E8Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0300u, 0x1EF3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0301u, 0x00FDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0302u, 0x0177u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0303u, 0x1EF9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0304u, 0x0233u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0307u, 0x1E8Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0308u, 0x00FFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0309u, 0x1EF7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x030Au, 0x1E99u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0323u, 0x1EF5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0301u, 0x017Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0302u, 0x1E91u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0307u, 0x017Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x030Cu, 0x017Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0323u, 0x1E93u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0331u, 0x1E95u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00A8u, 0x0300u, 0x1FEDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00A8u, 0x0301u, 0x0385u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00A8u, 0x0342u, 0x1FC1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0300u, 0x1EA6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0301u, 0x1EA4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0303u, 0x1EAAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0309u, 0x1EA8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00C4u, 0x0304u, 0x01DEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00C5u, 0x0301u, 0x01FAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00C6u, 0x0301u, 0x01FCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00C6u, 0x0304u, 0x01E2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00C7u, 0x0301u, 0x1E08u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0300u, 0x1EC0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0301u, 0x1EBEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0303u, 0x1EC4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0309u, 0x1EC2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00CFu, 0x0301u, 0x1E2Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0300u, 0x1ED2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0301u, 0x1ED0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0303u, 0x1ED6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0309u, 0x1ED4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00D5u, 0x0301u, 0x1E4Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00D5u, 0x0304u, 0x022Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00D5u, 0x0308u, 0x1E4Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00D6u, 0x0304u, 0x022Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00D8u, 0x0301u, 0x01FEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x0300u, 0x01DBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x0301u, 0x01D7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x0304u, 0x01D5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x030Cu, 0x01D9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0300u, 0x1EA7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0301u, 0x1EA5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0303u, 0x1EABu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0309u, 0x1EA9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00E4u, 0x0304u, 0x01DFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00E5u, 0x0301u, 0x01FBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00E6u, 0x0301u, 0x01FDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00E6u, 0x0304u, 0x01E3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00E7u, 0x0301u, 0x1E09u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0300u, 0x1EC1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0301u, 0x1EBFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0303u, 0x1EC5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0309u, 0x1EC3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00EFu, 0x0301u, 0x1E2Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0300u, 0x1ED3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0301u, 0x1ED1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0303u, 0x1ED7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0309u, 0x1ED5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00F5u, 0x0301u, 0x1E4Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00F5u, 0x0304u, 0x022Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00F5u, 0x0308u, 0x1E4Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00F6u, 0x0304u, 0x022Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00F8u, 0x0301u, 0x01FFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x0300u, 0x01DCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x0301u, 0x01D8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x0304u, 0x01D6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x030Cu, 0x01DAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0300u, 0x1EB0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0301u, 0x1EAEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0303u, 0x1EB4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0309u, 0x1EB2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0300u, 0x1EB1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0301u, 0x1EAFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0303u, 0x1EB5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0309u, 0x1EB3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0112u, 0x0300u, 0x1E14u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0112u, 0x0301u, 0x1E16u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0113u, 0x0300u, 0x1E15u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0113u, 0x0301u, 0x1E17u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x014Cu, 0x0300u, 0x1E50u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x014Cu, 0x0301u, 0x1E52u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x014Du, 0x0300u, 0x1E51u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x014Du, 0x0301u, 0x1E53u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x015Au, 0x0307u, 0x1E64u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x015Bu, 0x0307u, 0x1E65u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0160u, 0x0307u, 0x1E66u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0161u, 0x0307u, 0x1E67u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0168u, 0x0301u, 0x1E78u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0169u, 0x0301u, 0x1E79u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x016Au, 0x0308u, 0x1E7Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x016Bu, 0x0308u, 0x1E7Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x017Fu, 0x0307u, 0x1E9Bu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0300u, 0x1EDCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0301u, 0x1EDAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0303u, 0x1EE0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0309u, 0x1EDEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0323u, 0x1EE2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0300u, 0x1EDDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0301u, 0x1EDBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0303u, 0x1EE1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0309u, 0x1EDFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0323u, 0x1EE3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0300u, 0x1EEAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0301u, 0x1EE8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0303u, 0x1EEEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0309u, 0x1EECu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0323u, 0x1EF0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0300u, 0x1EEBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0301u, 0x1EE9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0303u, 0x1EEFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0309u, 0x1EEDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0323u, 0x1EF1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01B7u, 0x030Cu, 0x01EEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01EAu, 0x0304u, 0x01ECu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x01EBu, 0x0304u, 0x01EDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0226u, 0x0304u, 0x01E0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0227u, 0x0304u, 0x01E1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0228u, 0x0306u, 0x1E1Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0229u, 0x0306u, 0x1E1Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x022Eu, 0x0304u, 0x0230u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x022Fu, 0x0304u, 0x0231u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0292u, 0x030Cu, 0x01EFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0308u, 0x0301u, 0x0000u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0300u, 0x1FBAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0301u, 0x0386u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0304u, 0x1FB9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0306u, 0x1FB8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0313u, 0x1F08u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0314u, 0x1F09u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0345u, 0x1FBCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0300u, 0x1FC8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0301u, 0x0388u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0313u, 0x1F18u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0314u, 0x1F19u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0300u, 0x1FCAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0301u, 0x0389u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0313u, 0x1F28u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0314u, 0x1F29u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0345u, 0x1FCCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0300u, 0x1FDAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0301u, 0x038Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0304u, 0x1FD9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0306u, 0x1FD8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0308u, 0x03AAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0313u, 0x1F38u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0314u, 0x1F39u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0300u, 0x1FF8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0301u, 0x038Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0313u, 0x1F48u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0314u, 0x1F49u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A1u, 0x0314u, 0x1FECu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0300u, 0x1FEAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0301u, 0x038Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0304u, 0x1FE9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0306u, 0x1FE8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0308u, 0x03ABu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0314u, 0x1F59u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0300u, 0x1FFAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0301u, 0x038Fu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0313u, 0x1F68u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0314u, 0x1F69u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0345u, 0x1FFCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03ACu, 0x0345u, 0x1FB4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03AEu, 0x0345u, 0x1FC4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0300u, 0x1F70u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0301u, 0x03ACu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0304u, 0x1FB1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0306u, 0x1FB0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0313u, 0x1F00u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0314u, 0x1F01u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0342u, 0x1FB6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0345u, 0x1FB3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0300u, 0x1F72u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0301u, 0x03ADu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0313u, 0x1F10u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0314u, 0x1F11u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0300u, 0x1F74u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0301u, 0x03AEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0313u, 0x1F20u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0314u, 0x1F21u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0342u, 0x1FC6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0345u, 0x1FC3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0300u, 0x1F76u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0301u, 0x03AFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0304u, 0x1FD1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0306u, 0x1FD0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0308u, 0x03CAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0313u, 0x1F30u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0314u, 0x1F31u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0342u, 0x1FD6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0300u, 0x1F78u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0301u, 0x03CCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0313u, 0x1F40u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0314u, 0x1F41u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C1u, 0x0313u, 0x1FE4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C1u, 0x0314u, 0x1FE5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0300u, 0x1F7Au), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0301u, 0x03CDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0304u, 0x1FE1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0306u, 0x1FE0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0308u, 0x03CBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0313u, 0x1F50u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0314u, 0x1F51u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0342u, 0x1FE6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0300u, 0x1F7Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0301u, 0x03CEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0313u, 0x1F60u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0314u, 0x1F61u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0342u, 0x1FF6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0345u, 0x1FF3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03CAu, 0x0300u, 0x1FD2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03CAu, 0x0301u, 0x0390u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03CAu, 0x0342u, 0x1FD7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03CBu, 0x0300u, 0x1FE2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03CBu, 0x0301u, 0x03B0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03CBu, 0x0342u, 0x1FE7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03CEu, 0x0345u, 0x1FF4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03D2u, 0x0301u, 0x03D3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x03D2u, 0x0308u, 0x03D4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0406u, 0x0308u, 0x0407u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0410u, 0x0306u, 0x04D0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0410u, 0x0308u, 0x04D2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0413u, 0x0301u, 0x0403u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0415u, 0x0300u, 0x0400u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0415u, 0x0306u, 0x04D6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0415u, 0x0308u, 0x0401u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0416u, 0x0306u, 0x04C1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0416u, 0x0308u, 0x04DCu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0417u, 0x0308u, 0x04DEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0300u, 0x040Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0304u, 0x04E2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0306u, 0x0419u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0308u, 0x04E4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x041Au, 0x0301u, 0x040Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x041Eu, 0x0308u, 0x04E6u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x0304u, 0x04EEu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x0306u, 0x040Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x0308u, 0x04F0u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x030Bu, 0x04F2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0427u, 0x0308u, 0x04F4u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x042Bu, 0x0308u, 0x04F8u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x042Du, 0x0308u, 0x04ECu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0430u, 0x0306u, 0x04D1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0430u, 0x0308u, 0x04D3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0433u, 0x0301u, 0x0453u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0435u, 0x0300u, 0x0450u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0435u, 0x0306u, 0x04D7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0435u, 0x0308u, 0x0451u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0436u, 0x0306u, 0x04C2u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0436u, 0x0308u, 0x04DDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0437u, 0x0308u, 0x04DFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0300u, 0x045Du), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0304u, 0x04E3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0306u, 0x0439u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0308u, 0x04E5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x043Au, 0x0301u, 0x045Cu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x043Eu, 0x0308u, 0x04E7u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x0304u, 0x04EFu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x0306u, 0x045Eu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x0308u, 0x04F1u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x030Bu, 0x04F3u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0447u, 0x0308u, 0x04F5u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x044Bu, 0x0308u, 0x04F9u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x044Du, 0x0308u, 0x04EDu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0456u, 0x0308u, 0x0457u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0474u, 0x030Fu, 0x0476u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x0475u, 0x030Fu, 0x0477u), + HB_CODEPOINT_ENCODE3_11_7_14 (0x04D8u, 0x0308u, 0x04DAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x04D9u, 0x0308u, 0x04DBu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x04E8u, 0x0308u, 0x04EAu), + HB_CODEPOINT_ENCODE3_11_7_14 (0x04E9u, 0x0308u, 0x04EBu), +}; +static const uint64_t +_hb_ucd_dm2_u64_map[387] = { - HB_CODEPOINT_ENCODE3 (0x003Cu, 0x0338u, 0x226Eu), HB_CODEPOINT_ENCODE3 (0x003Du, 0x0338u, 0x2260u), - HB_CODEPOINT_ENCODE3 (0x003Eu, 0x0338u, 0x226Fu), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0300u, 0x00C0u), - HB_CODEPOINT_ENCODE3 (0x0041u, 0x0301u, 0x00C1u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0302u, 0x00C2u), - HB_CODEPOINT_ENCODE3 (0x0041u, 0x0303u, 0x00C3u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0304u, 0x0100u), - HB_CODEPOINT_ENCODE3 (0x0041u, 0x0306u, 0x0102u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0307u, 0x0226u), - HB_CODEPOINT_ENCODE3 (0x0041u, 0x0308u, 0x00C4u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0309u, 0x1EA2u), - HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Au, 0x00C5u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Cu, 0x01CDu), - HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Fu, 0x0200u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0311u, 0x0202u), - HB_CODEPOINT_ENCODE3 (0x0041u, 0x0323u, 0x1EA0u), HB_CODEPOINT_ENCODE3 (0x0041u, 0x0325u, 0x1E00u), - HB_CODEPOINT_ENCODE3 (0x0041u, 0x0328u, 0x0104u), HB_CODEPOINT_ENCODE3 (0x0042u, 0x0307u, 0x1E02u), - HB_CODEPOINT_ENCODE3 (0x0042u, 0x0323u, 0x1E04u), HB_CODEPOINT_ENCODE3 (0x0042u, 0x0331u, 0x1E06u), - HB_CODEPOINT_ENCODE3 (0x0043u, 0x0301u, 0x0106u), HB_CODEPOINT_ENCODE3 (0x0043u, 0x0302u, 0x0108u), - HB_CODEPOINT_ENCODE3 (0x0043u, 0x0307u, 0x010Au), HB_CODEPOINT_ENCODE3 (0x0043u, 0x030Cu, 0x010Cu), - HB_CODEPOINT_ENCODE3 (0x0043u, 0x0327u, 0x00C7u), HB_CODEPOINT_ENCODE3 (0x0044u, 0x0307u, 0x1E0Au), - HB_CODEPOINT_ENCODE3 (0x0044u, 0x030Cu, 0x010Eu), HB_CODEPOINT_ENCODE3 (0x0044u, 0x0323u, 0x1E0Cu), - HB_CODEPOINT_ENCODE3 (0x0044u, 0x0327u, 0x1E10u), HB_CODEPOINT_ENCODE3 (0x0044u, 0x032Du, 0x1E12u), - HB_CODEPOINT_ENCODE3 (0x0044u, 0x0331u, 0x1E0Eu), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0300u, 0x00C8u), - HB_CODEPOINT_ENCODE3 (0x0045u, 0x0301u, 0x00C9u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0302u, 0x00CAu), - HB_CODEPOINT_ENCODE3 (0x0045u, 0x0303u, 0x1EBCu), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0304u, 0x0112u), - HB_CODEPOINT_ENCODE3 (0x0045u, 0x0306u, 0x0114u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0307u, 0x0116u), - HB_CODEPOINT_ENCODE3 (0x0045u, 0x0308u, 0x00CBu), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0309u, 0x1EBAu), - HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Cu, 0x011Au), HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Fu, 0x0204u), - HB_CODEPOINT_ENCODE3 (0x0045u, 0x0311u, 0x0206u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0323u, 0x1EB8u), - HB_CODEPOINT_ENCODE3 (0x0045u, 0x0327u, 0x0228u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0328u, 0x0118u), - HB_CODEPOINT_ENCODE3 (0x0045u, 0x032Du, 0x1E18u), HB_CODEPOINT_ENCODE3 (0x0045u, 0x0330u, 0x1E1Au), - HB_CODEPOINT_ENCODE3 (0x0046u, 0x0307u, 0x1E1Eu), HB_CODEPOINT_ENCODE3 (0x0047u, 0x0301u, 0x01F4u), - HB_CODEPOINT_ENCODE3 (0x0047u, 0x0302u, 0x011Cu), HB_CODEPOINT_ENCODE3 (0x0047u, 0x0304u, 0x1E20u), - HB_CODEPOINT_ENCODE3 (0x0047u, 0x0306u, 0x011Eu), HB_CODEPOINT_ENCODE3 (0x0047u, 0x0307u, 0x0120u), - HB_CODEPOINT_ENCODE3 (0x0047u, 0x030Cu, 0x01E6u), HB_CODEPOINT_ENCODE3 (0x0047u, 0x0327u, 0x0122u), - HB_CODEPOINT_ENCODE3 (0x0048u, 0x0302u, 0x0124u), HB_CODEPOINT_ENCODE3 (0x0048u, 0x0307u, 0x1E22u), - HB_CODEPOINT_ENCODE3 (0x0048u, 0x0308u, 0x1E26u), HB_CODEPOINT_ENCODE3 (0x0048u, 0x030Cu, 0x021Eu), - HB_CODEPOINT_ENCODE3 (0x0048u, 0x0323u, 0x1E24u), HB_CODEPOINT_ENCODE3 (0x0048u, 0x0327u, 0x1E28u), - HB_CODEPOINT_ENCODE3 (0x0048u, 0x032Eu, 0x1E2Au), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0300u, 0x00CCu), - HB_CODEPOINT_ENCODE3 (0x0049u, 0x0301u, 0x00CDu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0302u, 0x00CEu), - HB_CODEPOINT_ENCODE3 (0x0049u, 0x0303u, 0x0128u), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0304u, 0x012Au), - HB_CODEPOINT_ENCODE3 (0x0049u, 0x0306u, 0x012Cu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0307u, 0x0130u), - HB_CODEPOINT_ENCODE3 (0x0049u, 0x0308u, 0x00CFu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0309u, 0x1EC8u), - HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Cu, 0x01CFu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Fu, 0x0208u), - HB_CODEPOINT_ENCODE3 (0x0049u, 0x0311u, 0x020Au), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0323u, 0x1ECAu), - HB_CODEPOINT_ENCODE3 (0x0049u, 0x0328u, 0x012Eu), HB_CODEPOINT_ENCODE3 (0x0049u, 0x0330u, 0x1E2Cu), - HB_CODEPOINT_ENCODE3 (0x004Au, 0x0302u, 0x0134u), HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0301u, 0x1E30u), - HB_CODEPOINT_ENCODE3 (0x004Bu, 0x030Cu, 0x01E8u), HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0323u, 0x1E32u), - HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0327u, 0x0136u), HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0331u, 0x1E34u), - HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0301u, 0x0139u), HB_CODEPOINT_ENCODE3 (0x004Cu, 0x030Cu, 0x013Du), - HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0323u, 0x1E36u), HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0327u, 0x013Bu), - HB_CODEPOINT_ENCODE3 (0x004Cu, 0x032Du, 0x1E3Cu), HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0331u, 0x1E3Au), - HB_CODEPOINT_ENCODE3 (0x004Du, 0x0301u, 0x1E3Eu), HB_CODEPOINT_ENCODE3 (0x004Du, 0x0307u, 0x1E40u), - HB_CODEPOINT_ENCODE3 (0x004Du, 0x0323u, 0x1E42u), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0300u, 0x01F8u), - HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0301u, 0x0143u), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0303u, 0x00D1u), - HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0307u, 0x1E44u), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x030Cu, 0x0147u), - HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0323u, 0x1E46u), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0327u, 0x0145u), - HB_CODEPOINT_ENCODE3 (0x004Eu, 0x032Du, 0x1E4Au), HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0331u, 0x1E48u), - HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0300u, 0x00D2u), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0301u, 0x00D3u), - HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0302u, 0x00D4u), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0303u, 0x00D5u), - HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0304u, 0x014Cu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0306u, 0x014Eu), - HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0307u, 0x022Eu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0308u, 0x00D6u), - HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0309u, 0x1ECEu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Bu, 0x0150u), - HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Cu, 0x01D1u), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Fu, 0x020Cu), - HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0311u, 0x020Eu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x031Bu, 0x01A0u), - HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0323u, 0x1ECCu), HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0328u, 0x01EAu), - HB_CODEPOINT_ENCODE3 (0x0050u, 0x0301u, 0x1E54u), HB_CODEPOINT_ENCODE3 (0x0050u, 0x0307u, 0x1E56u), - HB_CODEPOINT_ENCODE3 (0x0052u, 0x0301u, 0x0154u), HB_CODEPOINT_ENCODE3 (0x0052u, 0x0307u, 0x1E58u), - HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Cu, 0x0158u), HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Fu, 0x0210u), - HB_CODEPOINT_ENCODE3 (0x0052u, 0x0311u, 0x0212u), HB_CODEPOINT_ENCODE3 (0x0052u, 0x0323u, 0x1E5Au), - HB_CODEPOINT_ENCODE3 (0x0052u, 0x0327u, 0x0156u), HB_CODEPOINT_ENCODE3 (0x0052u, 0x0331u, 0x1E5Eu), - HB_CODEPOINT_ENCODE3 (0x0053u, 0x0301u, 0x015Au), HB_CODEPOINT_ENCODE3 (0x0053u, 0x0302u, 0x015Cu), - HB_CODEPOINT_ENCODE3 (0x0053u, 0x0307u, 0x1E60u), HB_CODEPOINT_ENCODE3 (0x0053u, 0x030Cu, 0x0160u), - HB_CODEPOINT_ENCODE3 (0x0053u, 0x0323u, 0x1E62u), HB_CODEPOINT_ENCODE3 (0x0053u, 0x0326u, 0x0218u), - HB_CODEPOINT_ENCODE3 (0x0053u, 0x0327u, 0x015Eu), HB_CODEPOINT_ENCODE3 (0x0054u, 0x0307u, 0x1E6Au), - HB_CODEPOINT_ENCODE3 (0x0054u, 0x030Cu, 0x0164u), HB_CODEPOINT_ENCODE3 (0x0054u, 0x0323u, 0x1E6Cu), - HB_CODEPOINT_ENCODE3 (0x0054u, 0x0326u, 0x021Au), HB_CODEPOINT_ENCODE3 (0x0054u, 0x0327u, 0x0162u), - HB_CODEPOINT_ENCODE3 (0x0054u, 0x032Du, 0x1E70u), HB_CODEPOINT_ENCODE3 (0x0054u, 0x0331u, 0x1E6Eu), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x0300u, 0x00D9u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0301u, 0x00DAu), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x0302u, 0x00DBu), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0303u, 0x0168u), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x0304u, 0x016Au), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0306u, 0x016Cu), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x0308u, 0x00DCu), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0309u, 0x1EE6u), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Au, 0x016Eu), HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Bu, 0x0170u), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Cu, 0x01D3u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Fu, 0x0214u), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x0311u, 0x0216u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x031Bu, 0x01AFu), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x0323u, 0x1EE4u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x0324u, 0x1E72u), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x0328u, 0x0172u), HB_CODEPOINT_ENCODE3 (0x0055u, 0x032Du, 0x1E76u), - HB_CODEPOINT_ENCODE3 (0x0055u, 0x0330u, 0x1E74u), HB_CODEPOINT_ENCODE3 (0x0056u, 0x0303u, 0x1E7Cu), - HB_CODEPOINT_ENCODE3 (0x0056u, 0x0323u, 0x1E7Eu), HB_CODEPOINT_ENCODE3 (0x0057u, 0x0300u, 0x1E80u), - HB_CODEPOINT_ENCODE3 (0x0057u, 0x0301u, 0x1E82u), HB_CODEPOINT_ENCODE3 (0x0057u, 0x0302u, 0x0174u), - HB_CODEPOINT_ENCODE3 (0x0057u, 0x0307u, 0x1E86u), HB_CODEPOINT_ENCODE3 (0x0057u, 0x0308u, 0x1E84u), - HB_CODEPOINT_ENCODE3 (0x0057u, 0x0323u, 0x1E88u), HB_CODEPOINT_ENCODE3 (0x0058u, 0x0307u, 0x1E8Au), - HB_CODEPOINT_ENCODE3 (0x0058u, 0x0308u, 0x1E8Cu), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0300u, 0x1EF2u), - HB_CODEPOINT_ENCODE3 (0x0059u, 0x0301u, 0x00DDu), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0302u, 0x0176u), - HB_CODEPOINT_ENCODE3 (0x0059u, 0x0303u, 0x1EF8u), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0304u, 0x0232u), - HB_CODEPOINT_ENCODE3 (0x0059u, 0x0307u, 0x1E8Eu), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0308u, 0x0178u), - HB_CODEPOINT_ENCODE3 (0x0059u, 0x0309u, 0x1EF6u), HB_CODEPOINT_ENCODE3 (0x0059u, 0x0323u, 0x1EF4u), - HB_CODEPOINT_ENCODE3 (0x005Au, 0x0301u, 0x0179u), HB_CODEPOINT_ENCODE3 (0x005Au, 0x0302u, 0x1E90u), - HB_CODEPOINT_ENCODE3 (0x005Au, 0x0307u, 0x017Bu), HB_CODEPOINT_ENCODE3 (0x005Au, 0x030Cu, 0x017Du), - HB_CODEPOINT_ENCODE3 (0x005Au, 0x0323u, 0x1E92u), HB_CODEPOINT_ENCODE3 (0x005Au, 0x0331u, 0x1E94u), - HB_CODEPOINT_ENCODE3 (0x0061u, 0x0300u, 0x00E0u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0301u, 0x00E1u), - HB_CODEPOINT_ENCODE3 (0x0061u, 0x0302u, 0x00E2u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0303u, 0x00E3u), - HB_CODEPOINT_ENCODE3 (0x0061u, 0x0304u, 0x0101u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0306u, 0x0103u), - HB_CODEPOINT_ENCODE3 (0x0061u, 0x0307u, 0x0227u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0308u, 0x00E4u), - HB_CODEPOINT_ENCODE3 (0x0061u, 0x0309u, 0x1EA3u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Au, 0x00E5u), - HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Cu, 0x01CEu), HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Fu, 0x0201u), - HB_CODEPOINT_ENCODE3 (0x0061u, 0x0311u, 0x0203u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0323u, 0x1EA1u), - HB_CODEPOINT_ENCODE3 (0x0061u, 0x0325u, 0x1E01u), HB_CODEPOINT_ENCODE3 (0x0061u, 0x0328u, 0x0105u), - HB_CODEPOINT_ENCODE3 (0x0062u, 0x0307u, 0x1E03u), HB_CODEPOINT_ENCODE3 (0x0062u, 0x0323u, 0x1E05u), - HB_CODEPOINT_ENCODE3 (0x0062u, 0x0331u, 0x1E07u), HB_CODEPOINT_ENCODE3 (0x0063u, 0x0301u, 0x0107u), - HB_CODEPOINT_ENCODE3 (0x0063u, 0x0302u, 0x0109u), HB_CODEPOINT_ENCODE3 (0x0063u, 0x0307u, 0x010Bu), - HB_CODEPOINT_ENCODE3 (0x0063u, 0x030Cu, 0x010Du), HB_CODEPOINT_ENCODE3 (0x0063u, 0x0327u, 0x00E7u), - HB_CODEPOINT_ENCODE3 (0x0064u, 0x0307u, 0x1E0Bu), HB_CODEPOINT_ENCODE3 (0x0064u, 0x030Cu, 0x010Fu), - HB_CODEPOINT_ENCODE3 (0x0064u, 0x0323u, 0x1E0Du), HB_CODEPOINT_ENCODE3 (0x0064u, 0x0327u, 0x1E11u), - HB_CODEPOINT_ENCODE3 (0x0064u, 0x032Du, 0x1E13u), HB_CODEPOINT_ENCODE3 (0x0064u, 0x0331u, 0x1E0Fu), - HB_CODEPOINT_ENCODE3 (0x0065u, 0x0300u, 0x00E8u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0301u, 0x00E9u), - HB_CODEPOINT_ENCODE3 (0x0065u, 0x0302u, 0x00EAu), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0303u, 0x1EBDu), - HB_CODEPOINT_ENCODE3 (0x0065u, 0x0304u, 0x0113u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0306u, 0x0115u), - HB_CODEPOINT_ENCODE3 (0x0065u, 0x0307u, 0x0117u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0308u, 0x00EBu), - HB_CODEPOINT_ENCODE3 (0x0065u, 0x0309u, 0x1EBBu), HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Cu, 0x011Bu), - HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Fu, 0x0205u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0311u, 0x0207u), - HB_CODEPOINT_ENCODE3 (0x0065u, 0x0323u, 0x1EB9u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x0327u, 0x0229u), - HB_CODEPOINT_ENCODE3 (0x0065u, 0x0328u, 0x0119u), HB_CODEPOINT_ENCODE3 (0x0065u, 0x032Du, 0x1E19u), - HB_CODEPOINT_ENCODE3 (0x0065u, 0x0330u, 0x1E1Bu), HB_CODEPOINT_ENCODE3 (0x0066u, 0x0307u, 0x1E1Fu), - HB_CODEPOINT_ENCODE3 (0x0067u, 0x0301u, 0x01F5u), HB_CODEPOINT_ENCODE3 (0x0067u, 0x0302u, 0x011Du), - HB_CODEPOINT_ENCODE3 (0x0067u, 0x0304u, 0x1E21u), HB_CODEPOINT_ENCODE3 (0x0067u, 0x0306u, 0x011Fu), - HB_CODEPOINT_ENCODE3 (0x0067u, 0x0307u, 0x0121u), HB_CODEPOINT_ENCODE3 (0x0067u, 0x030Cu, 0x01E7u), - HB_CODEPOINT_ENCODE3 (0x0067u, 0x0327u, 0x0123u), HB_CODEPOINT_ENCODE3 (0x0068u, 0x0302u, 0x0125u), - HB_CODEPOINT_ENCODE3 (0x0068u, 0x0307u, 0x1E23u), HB_CODEPOINT_ENCODE3 (0x0068u, 0x0308u, 0x1E27u), - HB_CODEPOINT_ENCODE3 (0x0068u, 0x030Cu, 0x021Fu), HB_CODEPOINT_ENCODE3 (0x0068u, 0x0323u, 0x1E25u), - HB_CODEPOINT_ENCODE3 (0x0068u, 0x0327u, 0x1E29u), HB_CODEPOINT_ENCODE3 (0x0068u, 0x032Eu, 0x1E2Bu), - HB_CODEPOINT_ENCODE3 (0x0068u, 0x0331u, 0x1E96u), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0300u, 0x00ECu), - HB_CODEPOINT_ENCODE3 (0x0069u, 0x0301u, 0x00EDu), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0302u, 0x00EEu), - HB_CODEPOINT_ENCODE3 (0x0069u, 0x0303u, 0x0129u), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0304u, 0x012Bu), - HB_CODEPOINT_ENCODE3 (0x0069u, 0x0306u, 0x012Du), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0308u, 0x00EFu), - HB_CODEPOINT_ENCODE3 (0x0069u, 0x0309u, 0x1EC9u), HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Cu, 0x01D0u), - HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Fu, 0x0209u), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0311u, 0x020Bu), - HB_CODEPOINT_ENCODE3 (0x0069u, 0x0323u, 0x1ECBu), HB_CODEPOINT_ENCODE3 (0x0069u, 0x0328u, 0x012Fu), - HB_CODEPOINT_ENCODE3 (0x0069u, 0x0330u, 0x1E2Du), HB_CODEPOINT_ENCODE3 (0x006Au, 0x0302u, 0x0135u), - HB_CODEPOINT_ENCODE3 (0x006Au, 0x030Cu, 0x01F0u), HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0301u, 0x1E31u), - HB_CODEPOINT_ENCODE3 (0x006Bu, 0x030Cu, 0x01E9u), HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0323u, 0x1E33u), - HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0327u, 0x0137u), HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0331u, 0x1E35u), - HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0301u, 0x013Au), HB_CODEPOINT_ENCODE3 (0x006Cu, 0x030Cu, 0x013Eu), - HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0323u, 0x1E37u), HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0327u, 0x013Cu), - HB_CODEPOINT_ENCODE3 (0x006Cu, 0x032Du, 0x1E3Du), HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0331u, 0x1E3Bu), - HB_CODEPOINT_ENCODE3 (0x006Du, 0x0301u, 0x1E3Fu), HB_CODEPOINT_ENCODE3 (0x006Du, 0x0307u, 0x1E41u), - HB_CODEPOINT_ENCODE3 (0x006Du, 0x0323u, 0x1E43u), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0300u, 0x01F9u), - HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0301u, 0x0144u), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0303u, 0x00F1u), - HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0307u, 0x1E45u), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x030Cu, 0x0148u), - HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0323u, 0x1E47u), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0327u, 0x0146u), - HB_CODEPOINT_ENCODE3 (0x006Eu, 0x032Du, 0x1E4Bu), HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0331u, 0x1E49u), - HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0300u, 0x00F2u), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0301u, 0x00F3u), - HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0302u, 0x00F4u), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0303u, 0x00F5u), - HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0304u, 0x014Du), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0306u, 0x014Fu), - HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0307u, 0x022Fu), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0308u, 0x00F6u), - HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0309u, 0x1ECFu), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Bu, 0x0151u), - HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Cu, 0x01D2u), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Fu, 0x020Du), - HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0311u, 0x020Fu), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x031Bu, 0x01A1u), - HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0323u, 0x1ECDu), HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0328u, 0x01EBu), - HB_CODEPOINT_ENCODE3 (0x0070u, 0x0301u, 0x1E55u), HB_CODEPOINT_ENCODE3 (0x0070u, 0x0307u, 0x1E57u), - HB_CODEPOINT_ENCODE3 (0x0072u, 0x0301u, 0x0155u), HB_CODEPOINT_ENCODE3 (0x0072u, 0x0307u, 0x1E59u), - HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Cu, 0x0159u), HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Fu, 0x0211u), - HB_CODEPOINT_ENCODE3 (0x0072u, 0x0311u, 0x0213u), HB_CODEPOINT_ENCODE3 (0x0072u, 0x0323u, 0x1E5Bu), - HB_CODEPOINT_ENCODE3 (0x0072u, 0x0327u, 0x0157u), HB_CODEPOINT_ENCODE3 (0x0072u, 0x0331u, 0x1E5Fu), - HB_CODEPOINT_ENCODE3 (0x0073u, 0x0301u, 0x015Bu), HB_CODEPOINT_ENCODE3 (0x0073u, 0x0302u, 0x015Du), - HB_CODEPOINT_ENCODE3 (0x0073u, 0x0307u, 0x1E61u), HB_CODEPOINT_ENCODE3 (0x0073u, 0x030Cu, 0x0161u), - HB_CODEPOINT_ENCODE3 (0x0073u, 0x0323u, 0x1E63u), HB_CODEPOINT_ENCODE3 (0x0073u, 0x0326u, 0x0219u), - HB_CODEPOINT_ENCODE3 (0x0073u, 0x0327u, 0x015Fu), HB_CODEPOINT_ENCODE3 (0x0074u, 0x0307u, 0x1E6Bu), - HB_CODEPOINT_ENCODE3 (0x0074u, 0x0308u, 0x1E97u), HB_CODEPOINT_ENCODE3 (0x0074u, 0x030Cu, 0x0165u), - HB_CODEPOINT_ENCODE3 (0x0074u, 0x0323u, 0x1E6Du), HB_CODEPOINT_ENCODE3 (0x0074u, 0x0326u, 0x021Bu), - HB_CODEPOINT_ENCODE3 (0x0074u, 0x0327u, 0x0163u), HB_CODEPOINT_ENCODE3 (0x0074u, 0x032Du, 0x1E71u), - HB_CODEPOINT_ENCODE3 (0x0074u, 0x0331u, 0x1E6Fu), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0300u, 0x00F9u), - HB_CODEPOINT_ENCODE3 (0x0075u, 0x0301u, 0x00FAu), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0302u, 0x00FBu), - HB_CODEPOINT_ENCODE3 (0x0075u, 0x0303u, 0x0169u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0304u, 0x016Bu), - HB_CODEPOINT_ENCODE3 (0x0075u, 0x0306u, 0x016Du), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0308u, 0x00FCu), - HB_CODEPOINT_ENCODE3 (0x0075u, 0x0309u, 0x1EE7u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Au, 0x016Fu), - HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Bu, 0x0171u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Cu, 0x01D4u), - HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Fu, 0x0215u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0311u, 0x0217u), - HB_CODEPOINT_ENCODE3 (0x0075u, 0x031Bu, 0x01B0u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0323u, 0x1EE5u), - HB_CODEPOINT_ENCODE3 (0x0075u, 0x0324u, 0x1E73u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0328u, 0x0173u), - HB_CODEPOINT_ENCODE3 (0x0075u, 0x032Du, 0x1E77u), HB_CODEPOINT_ENCODE3 (0x0075u, 0x0330u, 0x1E75u), - HB_CODEPOINT_ENCODE3 (0x0076u, 0x0303u, 0x1E7Du), HB_CODEPOINT_ENCODE3 (0x0076u, 0x0323u, 0x1E7Fu), - HB_CODEPOINT_ENCODE3 (0x0077u, 0x0300u, 0x1E81u), HB_CODEPOINT_ENCODE3 (0x0077u, 0x0301u, 0x1E83u), - HB_CODEPOINT_ENCODE3 (0x0077u, 0x0302u, 0x0175u), HB_CODEPOINT_ENCODE3 (0x0077u, 0x0307u, 0x1E87u), - HB_CODEPOINT_ENCODE3 (0x0077u, 0x0308u, 0x1E85u), HB_CODEPOINT_ENCODE3 (0x0077u, 0x030Au, 0x1E98u), - HB_CODEPOINT_ENCODE3 (0x0077u, 0x0323u, 0x1E89u), HB_CODEPOINT_ENCODE3 (0x0078u, 0x0307u, 0x1E8Bu), - HB_CODEPOINT_ENCODE3 (0x0078u, 0x0308u, 0x1E8Du), HB_CODEPOINT_ENCODE3 (0x0079u, 0x0300u, 0x1EF3u), - HB_CODEPOINT_ENCODE3 (0x0079u, 0x0301u, 0x00FDu), HB_CODEPOINT_ENCODE3 (0x0079u, 0x0302u, 0x0177u), - HB_CODEPOINT_ENCODE3 (0x0079u, 0x0303u, 0x1EF9u), HB_CODEPOINT_ENCODE3 (0x0079u, 0x0304u, 0x0233u), - HB_CODEPOINT_ENCODE3 (0x0079u, 0x0307u, 0x1E8Fu), HB_CODEPOINT_ENCODE3 (0x0079u, 0x0308u, 0x00FFu), - HB_CODEPOINT_ENCODE3 (0x0079u, 0x0309u, 0x1EF7u), HB_CODEPOINT_ENCODE3 (0x0079u, 0x030Au, 0x1E99u), - HB_CODEPOINT_ENCODE3 (0x0079u, 0x0323u, 0x1EF5u), HB_CODEPOINT_ENCODE3 (0x007Au, 0x0301u, 0x017Au), - HB_CODEPOINT_ENCODE3 (0x007Au, 0x0302u, 0x1E91u), HB_CODEPOINT_ENCODE3 (0x007Au, 0x0307u, 0x017Cu), - HB_CODEPOINT_ENCODE3 (0x007Au, 0x030Cu, 0x017Eu), HB_CODEPOINT_ENCODE3 (0x007Au, 0x0323u, 0x1E93u), - HB_CODEPOINT_ENCODE3 (0x007Au, 0x0331u, 0x1E95u), HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0300u, 0x1FEDu), - HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0301u, 0x0385u), HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0342u, 0x1FC1u), - HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0300u, 0x1EA6u), HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0301u, 0x1EA4u), - HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0303u, 0x1EAAu), HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0309u, 0x1EA8u), - HB_CODEPOINT_ENCODE3 (0x00C4u, 0x0304u, 0x01DEu), HB_CODEPOINT_ENCODE3 (0x00C5u, 0x0301u, 0x01FAu), - HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0301u, 0x01FCu), HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0304u, 0x01E2u), - HB_CODEPOINT_ENCODE3 (0x00C7u, 0x0301u, 0x1E08u), HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0300u, 0x1EC0u), - HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0301u, 0x1EBEu), HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0303u, 0x1EC4u), - HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0309u, 0x1EC2u), HB_CODEPOINT_ENCODE3 (0x00CFu, 0x0301u, 0x1E2Eu), - HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0300u, 0x1ED2u), HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0301u, 0x1ED0u), - HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0303u, 0x1ED6u), HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0309u, 0x1ED4u), - HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0301u, 0x1E4Cu), HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0304u, 0x022Cu), - HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0308u, 0x1E4Eu), HB_CODEPOINT_ENCODE3 (0x00D6u, 0x0304u, 0x022Au), - HB_CODEPOINT_ENCODE3 (0x00D8u, 0x0301u, 0x01FEu), HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0300u, 0x01DBu), - HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0301u, 0x01D7u), HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0304u, 0x01D5u), - HB_CODEPOINT_ENCODE3 (0x00DCu, 0x030Cu, 0x01D9u), HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0300u, 0x1EA7u), - HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0301u, 0x1EA5u), HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0303u, 0x1EABu), - HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0309u, 0x1EA9u), HB_CODEPOINT_ENCODE3 (0x00E4u, 0x0304u, 0x01DFu), - HB_CODEPOINT_ENCODE3 (0x00E5u, 0x0301u, 0x01FBu), HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0301u, 0x01FDu), - HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0304u, 0x01E3u), HB_CODEPOINT_ENCODE3 (0x00E7u, 0x0301u, 0x1E09u), - HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0300u, 0x1EC1u), HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0301u, 0x1EBFu), - HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0303u, 0x1EC5u), HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0309u, 0x1EC3u), - HB_CODEPOINT_ENCODE3 (0x00EFu, 0x0301u, 0x1E2Fu), HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0300u, 0x1ED3u), - HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0301u, 0x1ED1u), HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0303u, 0x1ED7u), - HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0309u, 0x1ED5u), HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0301u, 0x1E4Du), - HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0304u, 0x022Du), HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0308u, 0x1E4Fu), - HB_CODEPOINT_ENCODE3 (0x00F6u, 0x0304u, 0x022Bu), HB_CODEPOINT_ENCODE3 (0x00F8u, 0x0301u, 0x01FFu), - HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0300u, 0x01DCu), HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0301u, 0x01D8u), - HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0304u, 0x01D6u), HB_CODEPOINT_ENCODE3 (0x00FCu, 0x030Cu, 0x01DAu), - HB_CODEPOINT_ENCODE3 (0x0102u, 0x0300u, 0x1EB0u), HB_CODEPOINT_ENCODE3 (0x0102u, 0x0301u, 0x1EAEu), - HB_CODEPOINT_ENCODE3 (0x0102u, 0x0303u, 0x1EB4u), HB_CODEPOINT_ENCODE3 (0x0102u, 0x0309u, 0x1EB2u), - HB_CODEPOINT_ENCODE3 (0x0103u, 0x0300u, 0x1EB1u), HB_CODEPOINT_ENCODE3 (0x0103u, 0x0301u, 0x1EAFu), - HB_CODEPOINT_ENCODE3 (0x0103u, 0x0303u, 0x1EB5u), HB_CODEPOINT_ENCODE3 (0x0103u, 0x0309u, 0x1EB3u), - HB_CODEPOINT_ENCODE3 (0x0112u, 0x0300u, 0x1E14u), HB_CODEPOINT_ENCODE3 (0x0112u, 0x0301u, 0x1E16u), - HB_CODEPOINT_ENCODE3 (0x0113u, 0x0300u, 0x1E15u), HB_CODEPOINT_ENCODE3 (0x0113u, 0x0301u, 0x1E17u), - HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0300u, 0x1E50u), HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0301u, 0x1E52u), - HB_CODEPOINT_ENCODE3 (0x014Du, 0x0300u, 0x1E51u), HB_CODEPOINT_ENCODE3 (0x014Du, 0x0301u, 0x1E53u), - HB_CODEPOINT_ENCODE3 (0x015Au, 0x0307u, 0x1E64u), HB_CODEPOINT_ENCODE3 (0x015Bu, 0x0307u, 0x1E65u), - HB_CODEPOINT_ENCODE3 (0x0160u, 0x0307u, 0x1E66u), HB_CODEPOINT_ENCODE3 (0x0161u, 0x0307u, 0x1E67u), - HB_CODEPOINT_ENCODE3 (0x0168u, 0x0301u, 0x1E78u), HB_CODEPOINT_ENCODE3 (0x0169u, 0x0301u, 0x1E79u), - HB_CODEPOINT_ENCODE3 (0x016Au, 0x0308u, 0x1E7Au), HB_CODEPOINT_ENCODE3 (0x016Bu, 0x0308u, 0x1E7Bu), - HB_CODEPOINT_ENCODE3 (0x017Fu, 0x0307u, 0x1E9Bu), HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0300u, 0x1EDCu), - HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0301u, 0x1EDAu), HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0303u, 0x1EE0u), - HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0309u, 0x1EDEu), HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0323u, 0x1EE2u), - HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0300u, 0x1EDDu), HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0301u, 0x1EDBu), - HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0303u, 0x1EE1u), HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0309u, 0x1EDFu), - HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0323u, 0x1EE3u), HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0300u, 0x1EEAu), - HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0301u, 0x1EE8u), HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0303u, 0x1EEEu), - HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0309u, 0x1EECu), HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0323u, 0x1EF0u), - HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0300u, 0x1EEBu), HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0301u, 0x1EE9u), - HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0303u, 0x1EEFu), HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0309u, 0x1EEDu), - HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0323u, 0x1EF1u), HB_CODEPOINT_ENCODE3 (0x01B7u, 0x030Cu, 0x01EEu), - HB_CODEPOINT_ENCODE3 (0x01EAu, 0x0304u, 0x01ECu), HB_CODEPOINT_ENCODE3 (0x01EBu, 0x0304u, 0x01EDu), - HB_CODEPOINT_ENCODE3 (0x0226u, 0x0304u, 0x01E0u), HB_CODEPOINT_ENCODE3 (0x0227u, 0x0304u, 0x01E1u), - HB_CODEPOINT_ENCODE3 (0x0228u, 0x0306u, 0x1E1Cu), HB_CODEPOINT_ENCODE3 (0x0229u, 0x0306u, 0x1E1Du), - HB_CODEPOINT_ENCODE3 (0x022Eu, 0x0304u, 0x0230u), HB_CODEPOINT_ENCODE3 (0x022Fu, 0x0304u, 0x0231u), - HB_CODEPOINT_ENCODE3 (0x0292u, 0x030Cu, 0x01EFu), HB_CODEPOINT_ENCODE3 (0x0308u, 0x0301u, 0x0000u), - HB_CODEPOINT_ENCODE3 (0x0391u, 0x0300u, 0x1FBAu), HB_CODEPOINT_ENCODE3 (0x0391u, 0x0301u, 0x0386u), - HB_CODEPOINT_ENCODE3 (0x0391u, 0x0304u, 0x1FB9u), HB_CODEPOINT_ENCODE3 (0x0391u, 0x0306u, 0x1FB8u), - HB_CODEPOINT_ENCODE3 (0x0391u, 0x0313u, 0x1F08u), HB_CODEPOINT_ENCODE3 (0x0391u, 0x0314u, 0x1F09u), - HB_CODEPOINT_ENCODE3 (0x0391u, 0x0345u, 0x1FBCu), HB_CODEPOINT_ENCODE3 (0x0395u, 0x0300u, 0x1FC8u), - HB_CODEPOINT_ENCODE3 (0x0395u, 0x0301u, 0x0388u), HB_CODEPOINT_ENCODE3 (0x0395u, 0x0313u, 0x1F18u), - HB_CODEPOINT_ENCODE3 (0x0395u, 0x0314u, 0x1F19u), HB_CODEPOINT_ENCODE3 (0x0397u, 0x0300u, 0x1FCAu), - HB_CODEPOINT_ENCODE3 (0x0397u, 0x0301u, 0x0389u), HB_CODEPOINT_ENCODE3 (0x0397u, 0x0313u, 0x1F28u), - HB_CODEPOINT_ENCODE3 (0x0397u, 0x0314u, 0x1F29u), HB_CODEPOINT_ENCODE3 (0x0397u, 0x0345u, 0x1FCCu), - HB_CODEPOINT_ENCODE3 (0x0399u, 0x0300u, 0x1FDAu), HB_CODEPOINT_ENCODE3 (0x0399u, 0x0301u, 0x038Au), - HB_CODEPOINT_ENCODE3 (0x0399u, 0x0304u, 0x1FD9u), HB_CODEPOINT_ENCODE3 (0x0399u, 0x0306u, 0x1FD8u), - HB_CODEPOINT_ENCODE3 (0x0399u, 0x0308u, 0x03AAu), HB_CODEPOINT_ENCODE3 (0x0399u, 0x0313u, 0x1F38u), - HB_CODEPOINT_ENCODE3 (0x0399u, 0x0314u, 0x1F39u), HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0300u, 0x1FF8u), - HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0301u, 0x038Cu), HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0313u, 0x1F48u), - HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0314u, 0x1F49u), HB_CODEPOINT_ENCODE3 (0x03A1u, 0x0314u, 0x1FECu), - HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0300u, 0x1FEAu), HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0301u, 0x038Eu), - HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0304u, 0x1FE9u), HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0306u, 0x1FE8u), - HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0308u, 0x03ABu), HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0314u, 0x1F59u), - HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0300u, 0x1FFAu), HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0301u, 0x038Fu), - HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0313u, 0x1F68u), HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0314u, 0x1F69u), - HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0345u, 0x1FFCu), HB_CODEPOINT_ENCODE3 (0x03ACu, 0x0345u, 0x1FB4u), - HB_CODEPOINT_ENCODE3 (0x03AEu, 0x0345u, 0x1FC4u), HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0300u, 0x1F70u), - HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0301u, 0x03ACu), HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0304u, 0x1FB1u), - HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0306u, 0x1FB0u), HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0313u, 0x1F00u), - HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0314u, 0x1F01u), HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0342u, 0x1FB6u), - HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0345u, 0x1FB3u), HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0300u, 0x1F72u), - HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0301u, 0x03ADu), HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0313u, 0x1F10u), - HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0314u, 0x1F11u), HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0300u, 0x1F74u), - HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0301u, 0x03AEu), HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0313u, 0x1F20u), - HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0314u, 0x1F21u), HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0342u, 0x1FC6u), - HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0345u, 0x1FC3u), HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0300u, 0x1F76u), - HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0301u, 0x03AFu), HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0304u, 0x1FD1u), - HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0306u, 0x1FD0u), HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0308u, 0x03CAu), - HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0313u, 0x1F30u), HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0314u, 0x1F31u), - HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0342u, 0x1FD6u), HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0300u, 0x1F78u), - HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0301u, 0x03CCu), HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0313u, 0x1F40u), - HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0314u, 0x1F41u), HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0313u, 0x1FE4u), - HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0314u, 0x1FE5u), HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0300u, 0x1F7Au), - HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0301u, 0x03CDu), HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0304u, 0x1FE1u), - HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0306u, 0x1FE0u), HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0308u, 0x03CBu), - HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0313u, 0x1F50u), HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0314u, 0x1F51u), - HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0342u, 0x1FE6u), HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0300u, 0x1F7Cu), - HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0301u, 0x03CEu), HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0313u, 0x1F60u), - HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0314u, 0x1F61u), HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0342u, 0x1FF6u), - HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0345u, 0x1FF3u), HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0300u, 0x1FD2u), - HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0301u, 0x0390u), HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0342u, 0x1FD7u), - HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0300u, 0x1FE2u), HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0301u, 0x03B0u), - HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0342u, 0x1FE7u), HB_CODEPOINT_ENCODE3 (0x03CEu, 0x0345u, 0x1FF4u), - HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0301u, 0x03D3u), HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0308u, 0x03D4u), - HB_CODEPOINT_ENCODE3 (0x0406u, 0x0308u, 0x0407u), HB_CODEPOINT_ENCODE3 (0x0410u, 0x0306u, 0x04D0u), - HB_CODEPOINT_ENCODE3 (0x0410u, 0x0308u, 0x04D2u), HB_CODEPOINT_ENCODE3 (0x0413u, 0x0301u, 0x0403u), - HB_CODEPOINT_ENCODE3 (0x0415u, 0x0300u, 0x0400u), HB_CODEPOINT_ENCODE3 (0x0415u, 0x0306u, 0x04D6u), - HB_CODEPOINT_ENCODE3 (0x0415u, 0x0308u, 0x0401u), HB_CODEPOINT_ENCODE3 (0x0416u, 0x0306u, 0x04C1u), - HB_CODEPOINT_ENCODE3 (0x0416u, 0x0308u, 0x04DCu), HB_CODEPOINT_ENCODE3 (0x0417u, 0x0308u, 0x04DEu), - HB_CODEPOINT_ENCODE3 (0x0418u, 0x0300u, 0x040Du), HB_CODEPOINT_ENCODE3 (0x0418u, 0x0304u, 0x04E2u), - HB_CODEPOINT_ENCODE3 (0x0418u, 0x0306u, 0x0419u), HB_CODEPOINT_ENCODE3 (0x0418u, 0x0308u, 0x04E4u), - HB_CODEPOINT_ENCODE3 (0x041Au, 0x0301u, 0x040Cu), HB_CODEPOINT_ENCODE3 (0x041Eu, 0x0308u, 0x04E6u), - HB_CODEPOINT_ENCODE3 (0x0423u, 0x0304u, 0x04EEu), HB_CODEPOINT_ENCODE3 (0x0423u, 0x0306u, 0x040Eu), - HB_CODEPOINT_ENCODE3 (0x0423u, 0x0308u, 0x04F0u), HB_CODEPOINT_ENCODE3 (0x0423u, 0x030Bu, 0x04F2u), - HB_CODEPOINT_ENCODE3 (0x0427u, 0x0308u, 0x04F4u), HB_CODEPOINT_ENCODE3 (0x042Bu, 0x0308u, 0x04F8u), - HB_CODEPOINT_ENCODE3 (0x042Du, 0x0308u, 0x04ECu), HB_CODEPOINT_ENCODE3 (0x0430u, 0x0306u, 0x04D1u), - HB_CODEPOINT_ENCODE3 (0x0430u, 0x0308u, 0x04D3u), HB_CODEPOINT_ENCODE3 (0x0433u, 0x0301u, 0x0453u), - HB_CODEPOINT_ENCODE3 (0x0435u, 0x0300u, 0x0450u), HB_CODEPOINT_ENCODE3 (0x0435u, 0x0306u, 0x04D7u), - HB_CODEPOINT_ENCODE3 (0x0435u, 0x0308u, 0x0451u), HB_CODEPOINT_ENCODE3 (0x0436u, 0x0306u, 0x04C2u), - HB_CODEPOINT_ENCODE3 (0x0436u, 0x0308u, 0x04DDu), HB_CODEPOINT_ENCODE3 (0x0437u, 0x0308u, 0x04DFu), - HB_CODEPOINT_ENCODE3 (0x0438u, 0x0300u, 0x045Du), HB_CODEPOINT_ENCODE3 (0x0438u, 0x0304u, 0x04E3u), - HB_CODEPOINT_ENCODE3 (0x0438u, 0x0306u, 0x0439u), HB_CODEPOINT_ENCODE3 (0x0438u, 0x0308u, 0x04E5u), - HB_CODEPOINT_ENCODE3 (0x043Au, 0x0301u, 0x045Cu), HB_CODEPOINT_ENCODE3 (0x043Eu, 0x0308u, 0x04E7u), - HB_CODEPOINT_ENCODE3 (0x0443u, 0x0304u, 0x04EFu), HB_CODEPOINT_ENCODE3 (0x0443u, 0x0306u, 0x045Eu), - HB_CODEPOINT_ENCODE3 (0x0443u, 0x0308u, 0x04F1u), HB_CODEPOINT_ENCODE3 (0x0443u, 0x030Bu, 0x04F3u), - HB_CODEPOINT_ENCODE3 (0x0447u, 0x0308u, 0x04F5u), HB_CODEPOINT_ENCODE3 (0x044Bu, 0x0308u, 0x04F9u), - HB_CODEPOINT_ENCODE3 (0x044Du, 0x0308u, 0x04EDu), HB_CODEPOINT_ENCODE3 (0x0456u, 0x0308u, 0x0457u), - HB_CODEPOINT_ENCODE3 (0x0474u, 0x030Fu, 0x0476u), HB_CODEPOINT_ENCODE3 (0x0475u, 0x030Fu, 0x0477u), - HB_CODEPOINT_ENCODE3 (0x04D8u, 0x0308u, 0x04DAu), HB_CODEPOINT_ENCODE3 (0x04D9u, 0x0308u, 0x04DBu), - HB_CODEPOINT_ENCODE3 (0x04E8u, 0x0308u, 0x04EAu), HB_CODEPOINT_ENCODE3 (0x04E9u, 0x0308u, 0x04EBu), HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B7u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B8u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BCu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BFu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x05D2u, 0x05BCu, 0x0000u), diff --git a/src/hb-ucd.cc b/src/hb-ucd.cc index 4bdd4f463..69949a288 100644 --- a/src/hb-ucd.cc +++ b/src/hb-ucd.cc @@ -114,6 +114,14 @@ _cmp_pair (const void *_key, const void *_item) return a < b ? -1 : a > b ? +1 : 0; } +static int +_cmp_pair_11_7_14 (const void *_key, const void *_item) +{ + uint32_t& a = * (uint32_t*) _key; + uint32_t b = (* (uint32_t*) _item) & HB_CODEPOINT_ENCODE3_11_7_14(0x1FFFFFu, 0x1FFFFFu, 0); + + return a < b ? -1 : a > b ? +1 : 0; +} static hb_bool_t hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED, @@ -122,16 +130,30 @@ hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED, { if (_hb_ucd_compose_hangul (a, b, ab)) return true; - uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0); - uint64_t *v = (uint64_t*) hb_bsearch (&k, _hb_ucd_dm2_map, - ARRAY_LENGTH (_hb_ucd_dm2_map), - sizeof (*_hb_ucd_dm2_map), - _cmp_pair); - if (likely (!v)) return false; + hb_codepoint_t u = 0; + + if ((a & 0xFFFFF800u) == 0x0000u && (b & 0xFFFFFF80) == 0x0300u) + { + uint32_t k = HB_CODEPOINT_ENCODE3_11_7_14 (a, b, 0); + uint32_t *v = (uint32_t*) hb_bsearch (&k, _hb_ucd_dm2_u32_map, + ARRAY_LENGTH (_hb_ucd_dm2_u32_map), + sizeof (*_hb_ucd_dm2_u32_map), + _cmp_pair_11_7_14); + if (likely (!v)) return false; + u = HB_CODEPOINT_DECODE3_11_7_14_3 (*v); + } + else + { + uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0); + uint64_t *v = (uint64_t*) hb_bsearch (&k, _hb_ucd_dm2_u64_map, + ARRAY_LENGTH (_hb_ucd_dm2_u64_map), + sizeof (*_hb_ucd_dm2_u64_map), + _cmp_pair); + if (likely (!v)) return false; + u = HB_CODEPOINT_DECODE3_3 (*v); + } - hb_codepoint_t u = HB_CODEPOINT_DECODE3_3 (*v); if (unlikely (!u)) return false; - *ab = u; return true; } @@ -162,7 +184,16 @@ hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, } i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map); - uint64_t v = _hb_ucd_dm2_map[i]; + if (i < ARRAY_LENGTH (_hb_ucd_dm2_u32_map)) + { + uint32_t v = _hb_ucd_dm2_u32_map[i]; + *a = HB_CODEPOINT_DECODE3_11_7_14_1 (v); + *b = HB_CODEPOINT_DECODE3_11_7_14_2 (v); + return true; + } + i -= ARRAY_LENGTH (_hb_ucd_dm2_u32_map); + + uint64_t v = _hb_ucd_dm2_u64_map[i]; *a = HB_CODEPOINT_DECODE3_1 (v); *b = HB_CODEPOINT_DECODE3_2 (v); return true; From ccf1448238c91da3cba8370ee527229013f6d362 Mon Sep 17 00:00:00 2001 From: GaryQian Date: Mon, 24 Jun 2019 12:57:13 -0700 Subject: [PATCH 071/138] Cast long->size_t to ensure comparison of similar types --- src/hb-common.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-common.cc b/src/hb-common.cc index fb6377e39..9035755a4 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -70,7 +70,7 @@ _hb_options_init () p = c + strlen (c); #define OPTION(name, symbol) \ - if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) do { u.opts.symbol = true; } while (0) + if (0 == strncmp (c, name, p - c) && strlen (name) == static_cast(p - c)) do { u.opts.symbol = true; } while (0) OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible); OPTION ("aat", aat); From bb4cdf8e0bcc98a036c22cfd44242502b107fb32 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 25 Jun 2019 01:42:42 +0430 Subject: [PATCH 072/138] Replace create_from_file with empty blob if HB_NO_OPEN is defined --- src/main.cc | 4 ++++ src/test-buffer-serialize.cc | 4 ++++ src/test-gpos-size-params.cc | 4 ++++ src/test-gsub-would-substitute.cc | 4 ++++ src/test-ot-color.cc | 4 ++++ src/test-ot-name.cc | 4 ++++ src/test.cc | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/src/main.cc b/src/main.cc index 490b76e5b..0aa4a5b20 100644 --- a/src/main.cc +++ b/src/main.cc @@ -38,6 +38,10 @@ using namespace OT; +#ifdef HB_NO_OPEN +#define hb_blob_create_from_file(x) hb_blob_get_empty () +#endif + int main (int argc, char **argv) { diff --git a/src/test-buffer-serialize.cc b/src/test-buffer-serialize.cc index 28826be8d..6393f0b7f 100644 --- a/src/test-buffer-serialize.cc +++ b/src/test-buffer-serialize.cc @@ -34,6 +34,10 @@ #include +#ifdef HB_NO_OPEN +#define hb_blob_create_from_file(x) hb_blob_get_empty () +#endif + int main (int argc, char **argv) { diff --git a/src/test-gpos-size-params.cc b/src/test-gpos-size-params.cc index acd1c4fc5..ad10ed40d 100644 --- a/src/test-gpos-size-params.cc +++ b/src/test-gpos-size-params.cc @@ -31,6 +31,10 @@ #include +#ifdef HB_NO_OPEN +#define hb_blob_create_from_file(x) hb_blob_get_empty () +#endif + int main (int argc, char **argv) { diff --git a/src/test-gsub-would-substitute.cc b/src/test-gsub-would-substitute.cc index 268f7db98..7ad9e084c 100644 --- a/src/test-gsub-would-substitute.cc +++ b/src/test-gsub-would-substitute.cc @@ -35,6 +35,10 @@ #include "hb-ft.h" #endif +#ifdef HB_NO_OPEN +#define hb_blob_create_from_file(x) hb_blob_get_empty () +#endif + int main (int argc, char **argv) { diff --git a/src/test-ot-color.cc b/src/test-ot-color.cc index e9126c064..3b4c8b6c2 100644 --- a/src/test-ot-color.cc +++ b/src/test-ot-color.cc @@ -27,6 +27,10 @@ #include +#ifdef HB_NO_OPEN +#define hb_blob_create_from_file(x) hb_blob_get_empty () +#endif + #if !defined(HB_NO_COLOR) && defined(CAIRO_HAS_SVG_SURFACE) #include "hb-ot.h" diff --git a/src/test-ot-name.cc b/src/test-ot-name.cc index 44c2c179c..4a484c6d6 100644 --- a/src/test-ot-name.cc +++ b/src/test-ot-name.cc @@ -30,6 +30,10 @@ #include #include +#ifdef HB_NO_OPEN +#define hb_blob_create_from_file(x) hb_blob_get_empty () +#endif + int main (int argc, char **argv) { diff --git a/src/test.cc b/src/test.cc index f0eace8c4..65b469feb 100644 --- a/src/test.cc +++ b/src/test.cc @@ -34,6 +34,10 @@ #include "hb-ft.h" #endif +#ifdef HB_NO_OPEN +#define hb_blob_create_from_file(x) hb_blob_get_empty () +#endif + int main (int argc, char **argv) { From fb0df17b2701c1c5623198440aa88a676985bd4f Mon Sep 17 00:00:00 2001 From: David Corbett Date: Mon, 24 Jun 2019 21:54:26 -0400 Subject: [PATCH 073/138] Correct "nonunihan" to "nounihan" --- src/gen-ucd-table.py | 4 ++-- src/hb-ucd-table.hh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py index 053953a97..f443ac1cf 100755 --- a/src/gen-ucd-table.py +++ b/src/gen-ucd-table.py @@ -7,7 +7,7 @@ import logging logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) if len (sys.argv) != 2: - print("usage: ./gen-ucd-table ucd.nonunihan.grouped.xml", file=sys.stderr) + print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml", file=sys.stderr) sys.exit(1) # https://github.com/harfbuzz/packtab @@ -90,7 +90,7 @@ print("/* == Start of generated table == */") print("/*") print(" * The following table is generated by running:") print(" *") -print(" * ./gen-ucd-table.py ucd.nonunihan.grouped.xml") +print(" * ./gen-ucd-table.py ucd.nounihan.grouped.xml") print(" *") print(" * on file with this description:", ucdxml.description) print(" */") diff --git a/src/hb-ucd-table.hh b/src/hb-ucd-table.hh index ae9ce3e2f..4a5e30c64 100644 --- a/src/hb-ucd-table.hh +++ b/src/hb-ucd-table.hh @@ -2,7 +2,7 @@ /* * The following table is generated by running: * - * ./gen-ucd-table.py ucd.nonunihan.grouped.xml + * ./gen-ucd-table.py ucd.nounihan.grouped.xml * * on file with this description: Unicode 12.1.0 */ From 0660175dc82d82bbb38c45b9cb53190e06f55750 Mon Sep 17 00:00:00 2001 From: David Corbett Date: Tue, 25 Jun 2019 10:14:03 -0400 Subject: [PATCH 074/138] Categorize U+1133B for use in Tamil --- src/hb-ot-shape-complex-indic.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-shape-complex-indic.hh b/src/hb-ot-shape-complex-indic.hh index dc8f8c7ce..d207728c4 100644 --- a/src/hb-ot-shape-complex-indic.hh +++ b/src/hb-ot-shape-complex-indic.hh @@ -359,7 +359,7 @@ set_indic_properties (hb_glyph_info_t &info) /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil, * so the Indic shaper needs to know their categories. */ else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM; - else if (unlikely (u == 0x1133cu)) cat = OT_N; + else if (unlikely (u == 0x1133Bu || u == 0x1133Cu)) cat = OT_N; else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */ From 094966959f96d9a41fb612fd0b870f5ae8f5a954 Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Mon, 17 Jun 2019 22:12:40 -0700 Subject: [PATCH 075/138] add hb_bimap_t, subclass hb_inc_bimap_t replacing CFF::remap_t --- src/Makefile.sources | 1 + src/hb-bimap.hh | 129 ++++++++++++++++++++++++++++++++++++ src/hb-ot-cff-common.hh | 64 ++---------------- src/hb-ot-cff1-table.hh | 16 ++--- src/hb-subset-cff-common.cc | 12 ++-- src/hb-subset-cff-common.hh | 40 +++++------ src/hb-subset-cff1.cc | 26 ++++---- src/hb-subset-cff2.cc | 29 ++++---- 8 files changed, 190 insertions(+), 127 deletions(-) create mode 100644 src/hb-bimap.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index ab228ce7e..6f42ba3dc 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -44,6 +44,7 @@ HB_BASE_sources = \ hb-machinery.hh \ hb-map.cc \ hb-map.hh \ + hb-bimap.hh \ hb-meta.hh \ hb-mutex.hh \ hb-null.hh \ diff --git a/src/hb-bimap.hh b/src/hb-bimap.hh new file mode 100644 index 000000000..9dbe0dfb5 --- /dev/null +++ b/src/hb-bimap.hh @@ -0,0 +1,129 @@ +/* + * Copyright © 2019 Adobe 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. + * + * Adobe Author(s): Michiharu Ariza + */ + +#ifndef HB_BIMAP_HH +#define HB_BIMAP_HH + +#include "hb.hh" + +/* Bi-directional map */ +struct hb_bimap_t +{ + hb_bimap_t () { init (); } + ~hb_bimap_t () { fini (); } + + void init () + { + forw_map.init (); + back_map.init (); + } + + void fini () + { + forw_map.fini (); + back_map.fini (); + } + + /* returns HB_MAP_VALUE_INVALID if unmapped */ + hb_codepoint_t forward (hb_codepoint_t lhs) const { return forw_map[lhs]; } + hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; } + + void set (hb_codepoint_t lhs, hb_codepoint_t rhs) + { + forw_map.set (lhs, rhs); + back_map.set (rhs, lhs); + } + + /* Create an identity map. */ + bool identity (unsigned int size) + { + clear (); + for (hb_codepoint_t i = 0; i < size; i++) set (i, i); + return forw_map.successful && back_map.successful; + } + + void clear () + { + forw_map.clear (); + back_map.clear (); + } + + void reset () + { + forw_map.reset (); + back_map.reset (); + } + + unsigned int get_population () const { return forw_map.get_population (); } + + protected: + hb_map_t forw_map; + hb_map_t back_map; +}; + +/* Inremental bimap: only lhs is given, rhs is incrementally assigned */ +struct hb_inc_bimap_t : hb_bimap_t +{ + /* Add a mapping from lhs to rhs with a unique value if lhs is unknown. + * Return the rhs value as the result. + */ + hb_codepoint_t add (hb_codepoint_t lhs) + { + hb_codepoint_t rhs = forw_map[lhs]; + if (rhs == HB_MAP_VALUE_INVALID) + { + rhs = get_population (); + set (lhs, rhs); + } + return rhs; + } + + bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); } + + protected: + static int cmp_id (const void* a, const void* b) + { return (int)*(const hb_codepoint_t *)a - (int)*(const hb_codepoint_t *)b; } + + public: + /* Optional: after finished adding all mappings in a random order, + * reassign rhs to lhs so that they are in the same order. */ + void sort () + { + hb_codepoint_t count = get_population (); + hb_vector_t work; + work.resize (count); + + for (hb_codepoint_t rhs = 0; rhs < count; rhs++) + work[rhs] = back_map[rhs]; + + work.qsort (cmp_id); + + for (hb_codepoint_t rhs = 0; rhs < count; rhs++) + set (work[rhs], rhs); + } +}; + +#endif /* HB_BIMAP_HH */ diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh index 919cb8150..2de5a2995 100644 --- a/src/hb-ot-cff-common.hh +++ b/src/hb-ot-cff-common.hh @@ -27,6 +27,7 @@ #define HB_OT_CFF_COMMON_HH #include "hb-open-type.hh" +#include "hb-bimap.hh" #include "hb-ot-layout-common.hh" #include "hb-cff-interp-dict-common.hh" #include "hb-subset-plan.hh" @@ -410,57 +411,6 @@ struct table_info_t unsigned int offSize; }; -/* used to remap font index or SID from fullset to subset. - * set to CFF_UNDEF_CODE if excluded from subset */ -struct remap_t : hb_vector_t -{ - void init () { SUPER::init (); } - - void fini () { SUPER::fini (); } - - bool reset (unsigned int size) - { - if (unlikely (!SUPER::resize (size))) - return false; - for (unsigned int i = 0; i < length; i++) - (*this)[i] = CFF_UNDEF_CODE; - count = 0; - return true; - } - - bool identity (unsigned int size) - { - if (unlikely (!SUPER::resize (size))) - return false; - unsigned int i; - for (i = 0; i < length; i++) - (*this)[i] = i; - count = i; - return true; - } - - bool excludes (hb_codepoint_t id) const - { return (id < length) && ((*this)[id] == CFF_UNDEF_CODE); } - - bool includes (hb_codepoint_t id) const - { return !excludes (id); } - - unsigned int add (unsigned int i) - { - if ((*this)[i] == CFF_UNDEF_CODE) - (*this)[i] = count++; - return (*this)[i]; - } - - hb_codepoint_t get_count () const { return count; } - - protected: - hb_codepoint_t count; - - private: - typedef hb_vector_t SUPER; -}; - template struct FDArray : CFFIndexOf { @@ -504,7 +454,7 @@ struct FDArray : CFFIndexOf unsigned int offSize_, const hb_vector_t &fontDicts, unsigned int fdCount, - const remap_t &fdmap, + const hb_inc_bimap_t &fdmap, OP_SERIALIZER& opszr, const hb_vector_t &privateInfos) { @@ -519,7 +469,7 @@ struct FDArray : CFFIndexOf unsigned int offset = 1; unsigned int fid = 0; for (unsigned i = 0; i < fontDicts.length; i++) - if (fdmap.includes (i)) + if (fdmap.has (i)) { if (unlikely (fid >= fdCount)) return_trace (false); CFFIndexOf::set_offset_at (fid++, offset); @@ -529,10 +479,10 @@ struct FDArray : CFFIndexOf /* serialize font dicts */ for (unsigned int i = 0; i < fontDicts.length; i++) - if (fdmap.includes (i)) + if (fdmap.has (i)) { FontDict *dict = c->start_embed (); - if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]]))) + if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap.forward (i)]))) return_trace (false); } return_trace (true); @@ -543,12 +493,12 @@ struct FDArray : CFFIndexOf static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */, const hb_vector_t &fontDicts, unsigned int fdCount, - const remap_t &fdmap, + const hb_inc_bimap_t &fdmap, OP_SERIALIZER& opszr) { unsigned int dictsSize = 0; for (unsigned int i = 0; i < fontDicts.len; i++) - if (fdmap.includes (i)) + if (fdmap.has (i)) dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr); offSize_ = calcOffSize (dictsSize); diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index 31d9d879d..0dbd0bae2 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -594,10 +594,10 @@ struct Charset struct CFF1StringIndex : CFF1Index { bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, - unsigned int offSize_, const remap_t &sidmap) + unsigned int offSize_, const hb_inc_bimap_t &sidmap) { TRACE_SERIALIZE (this); - if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0))) + if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0))) { if (unlikely (!c->extend_min (this->count))) return_trace (false); @@ -607,11 +607,11 @@ struct CFF1StringIndex : CFF1Index byte_str_array_t bytesArray; bytesArray.init (); - if (!bytesArray.resize (sidmap.get_count ())) + if (!bytesArray.resize (sidmap.get_population ())) return_trace (false); for (unsigned int i = 0; i < strings.count; i++) { - hb_codepoint_t j = sidmap[i]; + hb_codepoint_t j = sidmap.forward (i); if (j != CFF_UNDEF_CODE) bytesArray[j] = strings[i]; } @@ -622,19 +622,19 @@ struct CFF1StringIndex : CFF1Index } /* in parallel to above */ - unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const remap_t &sidmap) const + unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_inc_bimap_t &sidmap) const { offSize_ = 0; - if ((count == 0) || (sidmap.get_count () == 0)) + if ((count == 0) || (sidmap.get_population () == 0)) return count.static_size; unsigned int dataSize = 0; for (unsigned int i = 0; i < count; i++) - if (sidmap[i] != CFF_UNDEF_CODE) + if (sidmap.forward (i) != CFF_UNDEF_CODE) dataSize += length_at (i); offSize_ = calcOffSize(dataSize); - return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_count (), dataSize); + return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_population (), dataSize); } }; diff --git a/src/hb-subset-cff-common.cc b/src/hb-subset-cff-common.cc index 54f6dc2a7..1da5c4a14 100644 --- a/src/hb-subset-cff-common.cc +++ b/src/hb-subset-cff-common.cc @@ -54,7 +54,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, unsigned int &subset_fdselect_size /* OUT */, unsigned int &subset_fdselect_format /* OUT */, hb_vector_t &fdselect_ranges /* OUT */, - remap_t &fdmap /* OUT */) + hb_inc_bimap_t &fdmap /* OUT */) { subset_fd_count = 0; subset_fdselect_size = 0; @@ -102,23 +102,19 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, else { /* create a fdmap */ - if (!fdmap.reset (fdCount)) - { - hb_set_destroy (set); - return false; - } + fdmap.reset (); hb_codepoint_t fd = CFF_UNDEF_CODE; while (set->next (&fd)) fdmap.add (fd); hb_set_destroy (set); - if (unlikely (fdmap.get_count () != subset_fd_count)) + if (unlikely (fdmap.get_population () != subset_fd_count)) return false; } /* update each font dict index stored as "code" in fdselect_ranges */ for (unsigned int i = 0; i < fdselect_ranges.length; i++) - fdselect_ranges[i].code = fdmap[fdselect_ranges[i].code]; + fdselect_ranges[i].code = fdmap.forward (fdselect_ranges[i].code); } /* determine which FDSelect format is most compact */ diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index 921b0253d..5c9584107 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -541,39 +541,29 @@ struct subr_subset_param_t bool drop_hints; }; -struct subr_remap_t : remap_t +struct subr_remap_t : hb_inc_bimap_t { void create (hb_set_t *closure) { /* create a remapping of subroutine numbers from old to new. * no optimization based on usage counts. fonttools doesn't appear doing that either. */ - reset (closure->get_max () + 1); - for (hb_codepoint_t old_num = 0; old_num < length; old_num++) - { - if (hb_set_has (closure, old_num)) - add (old_num); - } + + hb_codepoint_t old_num = HB_SET_VALUE_INVALID; + while (hb_set_next (closure, &old_num)) + add (old_num); - if (get_count () < 1240) + if (get_population () < 1240) bias = 107; - else if (get_count () < 33900) + else if (get_population () < 33900) bias = 1131; else bias = 32768; } - hb_codepoint_t operator[] (unsigned int old_num) const - { - if (old_num >= length) - return CFF_UNDEF_CODE; - else - return remap_t::operator[] (old_num); - } - int biased_num (unsigned int old_num) const { - hb_codepoint_t new_num = (*this)[old_num]; + hb_codepoint_t new_num = forward (old_num); return (int)new_num - bias; } @@ -581,15 +571,15 @@ struct subr_remap_t : remap_t int bias; }; -struct subr_remap_ts +struct subr_remaps_t { - subr_remap_ts () + subr_remaps_t () { global_remap.init (); local_remaps.init (); } - ~subr_remap_ts () { fini (); } + ~subr_remaps_t () { fini (); } void init (unsigned int fdCount) { @@ -765,13 +755,13 @@ struct subr_subsetter_t bool encode_subrs (const parsed_cs_str_vec_t &subrs, const subr_remap_t& remap, unsigned int fd, str_buff_vec_t &buffArray) const { - unsigned int count = remap.get_count (); + unsigned int count = remap.get_population (); if (unlikely (!buffArray.resize (count))) return false; for (unsigned int old_num = 0; old_num < subrs.length; old_num++) { - hb_codepoint_t new_num = remap[old_num]; + hb_codepoint_t new_num = remap.forward (old_num); if (new_num != CFF_UNDEF_CODE) { if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num]))) @@ -1005,7 +995,7 @@ struct subr_subsetter_t parsed_cs_str_vec_t parsed_global_subrs; hb_vector_t parsed_local_subrs; - subr_remap_ts remaps; + subr_remaps_t remaps; private: typedef typename SUBRS::count_type subr_count_type; @@ -1021,7 +1011,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, unsigned int &subset_fdselect_size /* OUT */, unsigned int &subset_fdselect_format /* OUT */, hb_vector_t &fdselect_ranges /* OUT */, - CFF::remap_t &fdmap /* OUT */); + hb_inc_bimap_t &fdmap /* OUT */); HB_INTERNAL bool hb_serialize_cff_fdselect (hb_serialize_context_t *c, diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc index ab46808d2..8c0447d2b 100644 --- a/src/hb-subset-cff1.cc +++ b/src/hb-subset-cff1.cc @@ -31,6 +31,7 @@ #include "hb-open-type.hh" #include "hb-ot-cff1-table.hh" #include "hb-set.h" +#include "hb-bimap.hh" #include "hb-subset-cff1.hh" #include "hb-subset-plan.hh" #include "hb-subset-cff-common.hh" @@ -38,12 +39,12 @@ using namespace CFF; -struct remap_sid_t : remap_t +struct remap_sid_t : hb_inc_bimap_t { unsigned int add (unsigned int sid) { if ((sid != CFF_UNDEF_SID) && !is_std_std (sid)) - return offset_sid (remap_t::add (unoffset_sid (sid))); + return offset_sid (hb_inc_bimap_t::add (unoffset_sid (sid))); else return sid; } @@ -53,7 +54,7 @@ struct remap_sid_t : remap_t if (is_std_std (sid) || (sid == CFF_UNDEF_SID)) return sid; else - return offset_sid (remap_t::operator [] (unoffset_sid (sid))); + return offset_sid (forward (unoffset_sid (sid))); } static const unsigned int num_std_strings = 391; @@ -581,8 +582,7 @@ struct cff_subset_plan { bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc) { - if (unlikely (!sidmap.reset (acc.stringIndex->count))) - return false; + sidmap.reset (); for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++) { @@ -596,7 +596,7 @@ struct cff_subset_plan { if (acc.fdArray != &Null(CFF1FDArray)) for (unsigned int i = 0; i < orig_fdcount; i++) - if (fdmap.includes (i)) + if (fdmap.has (i)) (void)sidmap.add (acc.fontDicts[i].fontName); return true; @@ -682,7 +682,7 @@ struct cff_subset_plan { /* SIDs for name strings in dicts are added before glyph names so they fit in 16-bit int range */ if (unlikely (!collect_sids_in_dicts (acc))) return false; - if (unlikely (sidmap.get_count () > 0x8000)) /* assumption: a dict won't reference that many strings */ + if (unlikely (sidmap.get_population () > 0x8000)) /* assumption: a dict won't reference that many strings */ return false; if (subset_charset) offsets.charsetInfo.size = plan_subset_charset (acc, plan); @@ -739,7 +739,7 @@ struct cff_subset_plan { { subset_localsubrs[fd].init (); offsets.localSubrsInfos[fd].init (); - if (fdmap.includes (fd)) + if (fdmap.has (fd)) { if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd])) return false; @@ -790,7 +790,7 @@ struct cff_subset_plan { cff1_font_dict_op_serializer_t fontSzr; unsigned int dictsSize = 0; for (unsigned int i = 0; i < acc.fontDicts.length; i++) - if (fdmap.includes (i)) + if (fdmap.has (i)) dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr); offsets.FDArrayInfo.offSize = calcOffSize (dictsSize); @@ -813,7 +813,7 @@ struct cff_subset_plan { offsets.privateDictInfo.offset = final_size; for (unsigned int i = 0; i < orig_fdcount; i++) { - if (fdmap.includes (i)) + if (fdmap.has (i)) { bool has_localsubrs = offsets.localSubrsInfos[i].size > 0; cff_private_dict_op_serializer_t privSzr (desubroutinize, plan->drop_hints); @@ -857,7 +857,7 @@ struct cff_subset_plan { /* font dict index remap table from fullset FDArray to subset FDArray. * set to CFF_UNDEF_CODE if excluded from subset */ - remap_t fdmap; + hb_inc_bimap_t fdmap; str_buff_vec_t subset_charstrings; str_buff_vec_t subset_globalsubrs; @@ -1034,11 +1034,11 @@ static inline bool _write_cff1 (const cff_subset_plan &plan, assert (plan.offsets.privateDictInfo.offset == (unsigned) (c.head - c.start)); for (unsigned int i = 0; i < acc.privateDicts.length; i++) { - if (plan.fdmap.includes (i)) + if (plan.fdmap.has (i)) { PrivateDict *pd = c.start_embed (); if (unlikely (pd == nullptr)) return false; - unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size; + unsigned int priv_size = plan.fontdicts_mod[plan.fdmap.forward (i)].privateDictInfo.size; bool result; cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc index afb23ae3c..5e36c7fd3 100644 --- a/src/hb-subset-cff2.cc +++ b/src/hb-subset-cff2.cc @@ -330,18 +330,15 @@ struct cff2_subset_plan { { subset_localsubrs[fd].init (); offsets.localSubrsInfos[fd].init (); - if (fdmap.includes (fd)) - { - if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd])) - return false; + if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd])) + return false; - unsigned int dataSize = subset_localsubrs[fd].total_size (); - if (dataSize > 0) - { - offsets.localSubrsInfos[fd].offset = final_size; - offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize); - offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize); - } + unsigned int dataSize = subset_localsubrs[fd].total_size (); + if (dataSize > 0) + { + offsets.localSubrsInfos[fd].offset = final_size; + offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize); + offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize); } } } @@ -382,7 +379,7 @@ struct cff2_subset_plan { cff_font_dict_op_serializer_t fontSzr; unsigned int dictsSize = 0; for (unsigned int i = 0; i < acc.fontDicts.length; i++) - if (fdmap.includes (i)) + if (fdmap.has (i)) dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr); offsets.FDArrayInfo.offSize = calcOffSize (dictsSize); @@ -401,7 +398,7 @@ struct cff2_subset_plan { offsets.privateDictsOffset = final_size; for (unsigned int i = 0; i < orig_fdcount; i++) { - if (fdmap.includes (i)) + if (fdmap.has (i)) { bool has_localsubrs = offsets.localSubrsInfos[i].size > 0; cff_private_dict_op_serializer_t privSzr (desubroutinize, drop_hints); @@ -431,7 +428,7 @@ struct cff2_subset_plan { unsigned int subset_fdselect_format; hb_vector_t subset_fdselect_ranges; - remap_t fdmap; + hb_inc_bimap_t fdmap; str_buff_vec_t subset_charstrings; str_buff_vec_t subset_globalsubrs; @@ -541,11 +538,11 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan, assert (plan.offsets.privateDictsOffset == (unsigned) (c.head - c.start)); for (unsigned int i = 0; i < acc.privateDicts.length; i++) { - if (plan.fdmap.includes (i)) + if (plan.fdmap.has (i)) { PrivateDict *pd = c.start_embed (); if (unlikely (pd == nullptr)) return false; - unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size; + unsigned int priv_size = plan.privateDictInfos[plan.fdmap.forward (i)].size; bool result; cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ From f3ee2bd020f8ca313fae783cc49a374f1377e877 Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Thu, 20 Jun 2019 14:33:09 -0700 Subject: [PATCH 076/138] add ops & methods to hb_bimap_t making it more like hb_map_t moved has () to hb_bimap_t from hb_inc_bimap_t moved identity () to hb_inc_bimap_t removed forward() --- src/hb-bimap.hh | 38 +++++++++++++++++++++++-------------- src/hb-ot-cff-common.hh | 2 +- src/hb-ot-cff1-table.hh | 4 ++-- src/hb-subset-cff-common.cc | 2 +- src/hb-subset-cff-common.hh | 4 ++-- src/hb-subset-cff1.cc | 4 ++-- src/hb-subset-cff2.cc | 2 +- 7 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/hb-bimap.hh b/src/hb-bimap.hh index 9dbe0dfb5..cd7729c2a 100644 --- a/src/hb-bimap.hh +++ b/src/hb-bimap.hh @@ -47,9 +47,13 @@ struct hb_bimap_t back_map.fini (); } - /* returns HB_MAP_VALUE_INVALID if unmapped */ - hb_codepoint_t forward (hb_codepoint_t lhs) const { return forw_map[lhs]; } - hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; } + void reset () + { + forw_map.reset (); + back_map.reset (); + } + + bool in_error () const { return forw_map.in_error () || back_map.in_error (); } void set (hb_codepoint_t lhs, hb_codepoint_t rhs) { @@ -57,12 +61,16 @@ struct hb_bimap_t back_map.set (rhs, lhs); } - /* Create an identity map. */ - bool identity (unsigned int size) + hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); } + hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; } + + hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); } + bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); } + + void del (hb_codepoint_t lhs) { - clear (); - for (hb_codepoint_t i = 0; i < size; i++) set (i, i); - return forw_map.successful && back_map.successful; + back_map.del (get (lhs)); + forw_map.del (lhs); } void clear () @@ -71,11 +79,7 @@ struct hb_bimap_t back_map.clear (); } - void reset () - { - forw_map.reset (); - back_map.reset (); - } + bool is_empty () const { return get_population () == 0; } unsigned int get_population () const { return forw_map.get_population (); } @@ -101,7 +105,13 @@ struct hb_inc_bimap_t : hb_bimap_t return rhs; } - bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); } + /* Create an identity map. */ + bool identity (unsigned int size) + { + clear (); + for (hb_codepoint_t i = 0; i < size; i++) set (i, i); + return !in_error (); + } protected: static int cmp_id (const void* a, const void* b) diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh index 2de5a2995..8b8e59201 100644 --- a/src/hb-ot-cff-common.hh +++ b/src/hb-ot-cff-common.hh @@ -482,7 +482,7 @@ struct FDArray : CFFIndexOf if (fdmap.has (i)) { FontDict *dict = c->start_embed (); - if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap.forward (i)]))) + if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]]))) return_trace (false); } return_trace (true); diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index 0dbd0bae2..4050b7d6f 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -611,7 +611,7 @@ struct CFF1StringIndex : CFF1Index return_trace (false); for (unsigned int i = 0; i < strings.count; i++) { - hb_codepoint_t j = sidmap.forward (i); + hb_codepoint_t j = sidmap[i]; if (j != CFF_UNDEF_CODE) bytesArray[j] = strings[i]; } @@ -630,7 +630,7 @@ struct CFF1StringIndex : CFF1Index unsigned int dataSize = 0; for (unsigned int i = 0; i < count; i++) - if (sidmap.forward (i) != CFF_UNDEF_CODE) + if (sidmap[i] != CFF_UNDEF_CODE) dataSize += length_at (i); offSize_ = calcOffSize(dataSize); diff --git a/src/hb-subset-cff-common.cc b/src/hb-subset-cff-common.cc index 1da5c4a14..b71ac57cc 100644 --- a/src/hb-subset-cff-common.cc +++ b/src/hb-subset-cff-common.cc @@ -114,7 +114,7 @@ hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, /* update each font dict index stored as "code" in fdselect_ranges */ for (unsigned int i = 0; i < fdselect_ranges.length; i++) - fdselect_ranges[i].code = fdmap.forward (fdselect_ranges[i].code); + fdselect_ranges[i].code = fdmap[fdselect_ranges[i].code]; } /* determine which FDSelect format is most compact */ diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index 5c9584107..6c36e458f 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -563,7 +563,7 @@ struct subr_remap_t : hb_inc_bimap_t int biased_num (unsigned int old_num) const { - hb_codepoint_t new_num = forward (old_num); + hb_codepoint_t new_num = get (old_num); return (int)new_num - bias; } @@ -761,7 +761,7 @@ struct subr_subsetter_t return false; for (unsigned int old_num = 0; old_num < subrs.length; old_num++) { - hb_codepoint_t new_num = remap.forward (old_num); + hb_codepoint_t new_num = remap[old_num]; if (new_num != CFF_UNDEF_CODE) { if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num]))) diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc index 8c0447d2b..21bd97fbb 100644 --- a/src/hb-subset-cff1.cc +++ b/src/hb-subset-cff1.cc @@ -54,7 +54,7 @@ struct remap_sid_t : hb_inc_bimap_t if (is_std_std (sid) || (sid == CFF_UNDEF_SID)) return sid; else - return offset_sid (forward (unoffset_sid (sid))); + return offset_sid (get (unoffset_sid (sid))); } static const unsigned int num_std_strings = 391; @@ -1038,7 +1038,7 @@ static inline bool _write_cff1 (const cff_subset_plan &plan, { PrivateDict *pd = c.start_embed (); if (unlikely (pd == nullptr)) return false; - unsigned int priv_size = plan.fontdicts_mod[plan.fdmap.forward (i)].privateDictInfo.size; + unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size; bool result; cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc index 5e36c7fd3..e89ca6951 100644 --- a/src/hb-subset-cff2.cc +++ b/src/hb-subset-cff2.cc @@ -542,7 +542,7 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan, { PrivateDict *pd = c.start_embed (); if (unlikely (pd == nullptr)) return false; - unsigned int priv_size = plan.privateDictInfos[plan.fdmap.forward (i)].size; + unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size; bool result; cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ From 10bd6b8d913a57260b35c1ef830db37c06eebd18 Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Thu, 20 Jun 2019 16:22:08 -0700 Subject: [PATCH 077/138] minor --- src/hb-bimap.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-bimap.hh b/src/hb-bimap.hh index cd7729c2a..29291506a 100644 --- a/src/hb-bimap.hh +++ b/src/hb-bimap.hh @@ -62,7 +62,7 @@ struct hb_bimap_t } hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); } - hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; } + hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); } hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); } bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); } From f4ea1a9afb4849e7cfb7a5eb9e81e4f656c3f89e Mon Sep 17 00:00:00 2001 From: David Corbett Date: Tue, 25 Jun 2019 21:08:14 -0400 Subject: [PATCH 078/138] [ucd] Include scripts added in Unicode 10 or later --- src/gen-ucd-table.py | 2 +- src/hb-ucd-table.hh | 988 +++++++++++++++++++++++-------------------- 2 files changed, 520 insertions(+), 470 deletions(-) diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py index f443ac1cf..1afde3bdf 100755 --- a/src/gen-ucd-table.py +++ b/src/gen-ucd-table.py @@ -66,7 +66,7 @@ for _ in ('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu', sc_order = packTab.AutoMapping() sc_array = [] -sc_re = re.compile(" (HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]") +sc_re = re.compile(r"\b(HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]") for line in open('hb-common.h'): m = sc_re.search (line) if not m: continue diff --git a/src/hb-ucd-table.hh b/src/hb-ucd-table.hh index 4a5e30c64..8b7d648a9 100644 --- a/src/hb-ucd-table.hh +++ b/src/hb-ucd-table.hh @@ -13,7 +13,7 @@ #include "hb.hh" static const hb_script_t -_hb_ucd_sc_map[138] = +_hb_ucd_sc_map[153] = { HB_SCRIPT_COMMON, HB_SCRIPT_INHERITED, HB_SCRIPT_UNKNOWN, HB_SCRIPT_ARABIC, @@ -84,6 +84,14 @@ _hb_ucd_sc_map[138] = HB_SCRIPT_ADLAM, HB_SCRIPT_BHAIKSUKI, HB_SCRIPT_MARCHEN, HB_SCRIPT_OSAGE, HB_SCRIPT_TANGUT, HB_SCRIPT_NEWA, + HB_SCRIPT_MASARAM_GONDI, HB_SCRIPT_NUSHU, + HB_SCRIPT_SOYOMBO, HB_SCRIPT_ZANABAZAR_SQUARE, + HB_SCRIPT_DOGRA, HB_SCRIPT_GUNJALA_GONDI, + HB_SCRIPT_HANIFI_ROHINGYA, HB_SCRIPT_MAKASAR, + HB_SCRIPT_MEDEFAIDRIN, HB_SCRIPT_OLD_SOGDIAN, + HB_SCRIPT_SOGDIAN, HB_SCRIPT_ELYMAIC, + HB_SCRIPT_NANDINAGARI, HB_SCRIPT_NYIAKENG_PUACHUE_HMONG, + HB_SCRIPT_WANCHO, }; static const uint16_t _hb_ucd_dm1_p0_map[825] = @@ -1055,7 +1063,7 @@ _hb_ucd_dm2_u64_map[387] = #ifndef HB_OPTIMIZE_SIZE static const uint8_t -_hb_ucd_u8[31814] = +_hb_ucd_u8[32102] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26, @@ -2666,11 +2674,17 @@ _hb_ucd_u8[31814] = 89, 89, 89, 89, 89, 2, 2, 2, 2, 2, 2, 2,130,130,130,130, 130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,130,130,130, 2, - 2, 2, 2, 2, 2, 2,130,130,130,130,130,130, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, - 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 94, 94, 94, 94, + 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,144,144,144,144, + 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144, + 144,144,144,144, 2, 2, 2, 2, 2, 2, 2, 2,144,144,144,144, + 144,144,144,144,144,144, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2,147,147,147,147, + 147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147, + 147,147,147,147, 2, 2, 2, 2, 2, 2, 2, 2,148,148,148,148, + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148, + 148,148,148,148,148,148, 2, 2, 2, 2, 2, 2,149,149,149,149, + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149, + 149,149,149, 2, 2, 2, 2, 2, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, @@ -2723,14 +2737,17 @@ _hb_ucd_u8[31814] = 102,102,102,102,102,102, 2, 2, 2, 2, 2, 2,126,126,126,126, 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, 126,126,126,126,126,126,126, 2, 2,126,126,126,126,126,126,126, - 126,126,126,126,126,126,126,126, 2, 2, 2, 2, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2,125,125,125,125, + 126,126,126,126,126,126,126,126, 2, 2, 2, 2,142,142,142,142, + 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, + 142,142,142,142,142,142,142,142, 2, 2, 2, 2,125,125,125,125, 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,125, 5, 5, 5, 5, - 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, - 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,125,150,150,150,150, + 150,150,150,150, 2, 2,150,150,150,150,150,150,150,150,150,150, + 150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, + 150, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,141,141,141,141, + 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, + 141,141,141,141, 2, 2, 2, 2, 2, 2, 2, 2,140,140,140,140, + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,121,121,121,121, 121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, 121,121,121,121,121, 2, 2, 2, 2, 2, 2, 2,133,133,133,133, @@ -2742,16 +2759,19 @@ _hb_ucd_u8[31814] = 134,134,134,134,134,134,134,134,134,134,134,134, 2, 2,134,134, 134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, 134,134,134,134, 2,134,134,134,134,134,134,134,134,134,134,134, - 134,134,134, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, - 8, 8, 8, 2, 8, 8, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 2, 2, 2, 8, 2, 8, 8, 2, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, - 9, 9, 2, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, - 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, + 134,134,134, 2, 2, 2, 2, 2, 2, 2, 2, 2,138,138,138,138, + 138,138,138, 2,138,138, 2,138,138,138,138,138,138,138,138,138, + 138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138, + 138,138,138, 2, 2, 2,138, 2,138,138, 2,138,138,138,138,138, + 138,138,138,138, 2, 2, 2, 2, 2, 2, 2, 2,138,138,138,138, + 138,138,138,138,138,138, 2, 2, 2, 2, 2, 2,143,143,143,143, + 143,143, 2,143,143, 2,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143,143,143,143,143,143,143, 2,143,143, 2,143, + 143,143,143,143,143, 2, 2, 2, 2, 2, 2, 2,143,143,143,143, + 143,143,143,143,143,143, 2, 2, 2, 2, 2, 2,145,145,145,145, + 145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, + 145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, @@ -2775,12 +2795,12 @@ _hb_ucd_u8[31814] = 119,119, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,119,119,119,119, 119,119,119,119,119,119, 2,119,119,119,119,119,119,119, 2,119, 119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119, - 119,119,119,119, 2, 2, 2, 2, 2,119,119,119, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 2, 99, 99, 99, 99, + 119,119,119,119, 2, 2, 2, 2, 2,119,119,119,146,146,146,146, + 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, + 146,146,146,146,146,146,146, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 2, 2, 2, 2, 2, 2, 2, 99,136, 12, 0, 0, + 99, 99, 99, 99, 2, 2, 2, 2, 2, 2, 2, 99,136,139, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,136,136,136,136, 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, 136,136,136,136, 2, 2, 2, 2, 2, 2, 2, 2,136,136,136, 2, @@ -2788,7 +2808,9 @@ _hb_ucd_u8[31814] = 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 17, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2, 2,105,105,105,105, + 17, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2, 2,139,139,139,139, + 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, + 139,139,139,139,139,139,139,139, 2, 2, 2, 2,105,105,105,105, 105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, 105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105,105,105, 105,105,105,105,105,105,105,105,105, 2, 2, 2,105,105,105,105, @@ -2818,10 +2840,13 @@ _hb_ucd_u8[31814] = 131,131,131,131,131,131,131,131,131,131,131,131, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 2, 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, - 56, 2, 56, 56, 56, 56, 56, 2, 2, 2, 2, 2, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 13, 13, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 14,113,113,113,113, + 56, 2, 56, 56, 56, 56, 56, 2, 2, 2, 2, 2,151,151,151,151, + 151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151, + 151,151,151,151,151,151,151,151,151, 2, 2, 2,151,151,151,151, + 151,151,151,151,151,151,151,151,151,151, 2, 2,151,151,151,151, + 151,151,151,151,151,151, 2, 2, 2, 2,151,151,152,152,152,152, + 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152, + 152,152,152,152,152,152, 2, 2, 2, 2, 2,152,113,113,113,113, 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, 113, 2, 2,113,113,113,113,113,113,113,113,113,113,113,113,113, 113,113,113, 2, 2, 2, 2, 2, 2, 2, 2, 2,132,132,132,132, @@ -2844,6 +2869,7 @@ _hb_ucd_u8[31814] = 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, @@ -3331,102 +3357,102 @@ _hb_ucd_u16[11168] = 403, 404, 405, 406, 407, 407, 408, 408, 409, 409, 45, 45, 410, 410, 411, 412, 413, 413, 413, 414, 415, 416, 417, 418, 419, 420, 421, 45, 45, 45, 45, 45, 422, 422, 422, 422, 423, 45, 45, 45, 424, 424, 424, 425, 424, 424, 424, 426, - 0, 0, 427, 285, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 27, 428, 45, 45, 45, 45, 45, 45, 45, 45, - 8, 8, 429, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 27, 430, - 431, 431, 431, 431, 432, 433, 431, 434, 435, 435, 435, 435, 436, 437, 438, 439, - 440, 440, 440, 441, 442, 443, 443, 444, 445, 445, 445, 445, 446, 445, 447, 448, - 449, 450, 449, 451, 45, 45, 45, 45, 452, 453, 454, 455, 455, 455, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 45, 45, 45, 45, 45, 45, 45, 45, - 466, 466, 466, 466, 466, 467, 45, 45, 468, 468, 468, 468, 469, 470, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 471, 471, 471, 472, 471, 473, 45, 45, - 474, 474, 474, 474, 475, 476, 477, 45, 478, 478, 478, 479, 480, 45, 45, 45, - 481, 482, 483, 481, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 17, 17, 17, 484, 45, 45, 45, 45, 45, 45, 485, 485, 485, 485, 485, 486, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 487, 488, 488, 487, 489, 45, - 14, 14, 14, 14, 490, 49, 49, 49, 49, 49, 491, 45, 492, 492, 492, 493, + 427, 427, 428, 429, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 27, 430, 45, 45, 45, 45, 45, 45, 45, 45, + 431, 431, 432, 433, 433, 434, 45, 45, 45, 45, 45, 45, 45, 45, 435, 436, + 437, 437, 437, 437, 438, 439, 437, 440, 441, 441, 441, 441, 442, 443, 444, 445, + 446, 446, 446, 447, 448, 449, 449, 450, 451, 451, 451, 451, 452, 451, 453, 454, + 455, 456, 455, 457, 45, 45, 45, 45, 458, 459, 460, 461, 461, 461, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 45, 45, 45, 45, 45, 45, 45, 45, + 472, 472, 472, 472, 472, 473, 45, 45, 474, 474, 474, 474, 475, 476, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 477, 477, 477, 478, 477, 479, 45, 45, + 480, 480, 480, 480, 481, 482, 483, 45, 484, 484, 484, 485, 486, 45, 45, 45, + 487, 488, 489, 487, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 490, 490, 490, 491, 45, 45, 45, 45, 45, 45, 492, 492, 492, 492, 492, 493, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 494, 495, 495, 494, 496, 45, + 497, 497, 497, 497, 498, 499, 499, 499, 499, 499, 500, 45, 501, 501, 501, 502, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 494, 495, 495, 496, 497, 495, 498, 499, 499, 500, 501, 502, 45, 45, 45, 45, - 503, 139, 139, 504, 505, 506, 507, 11, 349, 508, 509, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 510, 511, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 512, 512, 512, 513, - 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, - 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, - 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, - 514, 514, 514, 514, 514, 514, 514, 514, 514, 515, 45, 45, 45, 45, 45, 45, - 514, 514, 514, 514, 514, 514, 516, 517, 514, 514, 514, 514, 514, 514, 514, 514, - 514, 514, 514, 514, 518, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, - 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, - 519, 519, 520, 521, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 503, 504, 504, 505, 506, 504, 507, 508, 508, 509, 510, 511, 45, 45, 45, 45, + 512, 513, 513, 514, 515, 516, 517, 518, 519, 520, 521, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 522, 523, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 524, 524, 524, 525, + 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, + 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, + 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, + 526, 526, 526, 526, 526, 526, 526, 526, 526, 527, 45, 45, 45, 45, 45, 45, + 526, 526, 526, 526, 526, 526, 528, 529, 526, 526, 526, 526, 526, 526, 526, 526, + 526, 526, 526, 526, 530, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, + 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, + 531, 531, 532, 533, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, - 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, - 522, 522, 522, 522, 523, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, + 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, + 534, 534, 534, 534, 535, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 524, 525, 526, 527, 45, 45, 45, 45, 45, 45, 528, 529, 530, - 531, 531, 531, 531, 532, 533, 534, 535, 531, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 536, 536, 536, 536, 536, 537, 45, 45, 45, 45, 45, 45, - 538, 538, 538, 538, 539, 538, 538, 538, 540, 538, 45, 45, 45, 45, 541, 45, - 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, - 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, - 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, - 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 543, - 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 544, + 277, 277, 277, 536, 537, 538, 539, 45, 45, 45, 45, 45, 45, 540, 541, 542, + 543, 543, 543, 543, 544, 545, 546, 547, 543, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 548, 548, 548, 548, 548, 549, 45, 45, 45, 45, 45, 45, + 550, 550, 550, 550, 551, 550, 550, 550, 552, 550, 45, 45, 45, 45, 553, 45, + 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, + 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, + 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, + 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 555, + 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 556, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 545, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, - 257, 546, 45, 45, 45, 547, 548, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 317, + 557, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, + 257, 558, 45, 45, 45, 559, 560, 561, 561, 561, 561, 561, 561, 561, 561, 561, + 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 562, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 549, 549, 549, 549, 549, 549, 550, 551, 552, 553, 267, 45, 45, 45, 45, 45, + 563, 563, 563, 563, 563, 563, 564, 565, 566, 567, 267, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 554, - 0, 0, 555, 0, 0, 0, 556, 557, 558, 0, 559, 0, 0, 0, 560, 45, - 11, 11, 11, 11, 561, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 267, - 0, 0, 0, 0, 0, 234, 0, 560, 45, 45, 45, 45, 45, 45, 45, 45, - 0, 0, 0, 0, 0, 225, 0, 0, 0, 562, 563, 564, 565, 0, 0, 0, - 566, 567, 0, 568, 569, 570, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 568, + 0, 0, 569, 0, 0, 0, 570, 571, 572, 0, 573, 0, 0, 0, 574, 45, + 11, 11, 11, 11, 575, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 267, + 0, 0, 0, 0, 0, 234, 0, 574, 45, 45, 45, 45, 45, 45, 45, 45, + 0, 0, 0, 0, 0, 225, 0, 0, 0, 576, 577, 578, 579, 0, 0, 0, + 580, 581, 0, 582, 583, 584, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 571, 0, 0, 0, - 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 572, 572, 572, 572, 573, 574, 575, 45, 45, 45, 45, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 585, 0, 0, 0, + 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, + 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, + 586, 586, 586, 586, 586, 586, 586, 586, 587, 588, 589, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 576, 577, 578, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 248, 248, 579, 318, 580, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 21, 21, 21, 581, + 590, 591, 592, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 593, 593, 594, 595, 596, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 597, 597, 597, 598, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, 584, 45, 45, - 585, 585, 585, 585, 586, 587, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 334, 0, 0, 0, 588, 45, 45, 45, 45, - 334, 0, 0, 589, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 590, 27, 591, 592, 593, 594, 595, 596, 597, 598, 599, 598, 45, 45, 45, 324, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 600, 601, 45, 45, + 602, 602, 602, 602, 603, 604, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 334, 0, 0, 0, 605, 45, 45, 45, 45, + 334, 0, 0, 606, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 607, 27, 608, 609, 610, 611, 612, 613, 614, 615, 616, 615, 45, 45, 45, 324, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 0, 0, 252, 0, 0, 0, 0, 0, 0, 267, 227, 334, 334, 334, 0, 554, - 600, 0, 0, 0, 0, 0, 600, 0, 0, 0, 600, 45, 45, 45, 601, 0, - 602, 0, 0, 252, 560, 603, 554, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 0, 0, 252, 0, 0, 0, 0, 0, 0, 267, 227, 334, 334, 334, 0, 568, + 617, 0, 0, 0, 0, 0, 617, 0, 0, 0, 617, 45, 45, 45, 618, 0, + 619, 0, 0, 252, 574, 620, 568, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 554, 600, 235, - 0, 0, 0, 0, 0, 0, 0, 267, 0, 0, 0, 0, 0, 560, 252, 45, - 252, 0, 0, 0, 427, 285, 0, 0, 427, 0, 589, 45, 45, 45, 45, 45, - 604, 0, 0, 0, 0, 0, 0, 605, 0, 0, 606, 0, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 267, 589, 608, 609, 554, 45, 45, 45, 45, 45, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 568, 617, 235, + 0, 0, 0, 0, 0, 0, 0, 267, 0, 0, 0, 0, 0, 574, 252, 45, + 252, 0, 0, 0, 621, 285, 0, 0, 621, 0, 606, 45, 45, 45, 45, 45, + 622, 0, 0, 0, 0, 0, 0, 623, 0, 0, 624, 0, 625, 0, 0, 0, + 0, 0, 0, 0, 0, 267, 606, 626, 627, 568, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 610, 45, 45, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 628, 45, 45, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 611, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 629, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 612, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 630, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, - 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 613, 45, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 631, 45, 248, 318, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 614, 45, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, + 632, 45, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3795,14 +3821,14 @@ _hb_ucd_sc (unsigned u) static inline uint_fast16_t _hb_ucd_dm (unsigned u) { - return u<195102u?_hb_ucd_u16[6048+(((_hb_ucd_u8[28764+(u>>6)])<<6)+((u)&63u))]:0; + return u<195102u?_hb_ucd_u16[6048+(((_hb_ucd_u8[29052+(u>>6)])<<6)+((u)&63u))]:0; } #elif !defined(HB_NO_UCD_UNASSIGNED) static const uint8_t -_hb_ucd_u8[16998] = +_hb_ucd_u8[17198] = { 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 10, 11, 7, 7, 7, 7, 12, 13, 14, 14, 14, 15, @@ -4465,21 +4491,21 @@ _hb_ucd_u8[16998] = 97, 97,172,173,174,175,176,176,176,176,176,176,176,176,176,176, 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176, 176,176,176,176,176,177,176,176,176,176,176,178, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97,179,180,181, 32, 32,182, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,183,184, - 97, 97, 97, 97, 97, 97, 59,185,186,187,188,189,190, 97,191,192, - 193, 59, 59,194, 59,195,196,196,196,196,196,197, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97,198, 97,199, 97, 97,200, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97,201,202,203, 97, 97, 97, 97, 97,204,205, - 206, 97,207,208, 97, 97,209,210,211,212,213, 97, 59, 59, 59, 59, - 59, 59, 59,214,215,216,217,218,219,220,221,222, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97,179,180,181,182,182,183, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,184,185, + 97, 97, 97, 97, 97, 97, 59,186,187,188,189,190,191, 97,192,193, + 194, 59, 59,195, 59,196,197,197,197,197,197,198, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97,199, 97,200, 97, 97,201, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97,202,203,204, 97, 97, 97, 97, 97,205,206, + 207, 97,208,209, 97, 97,210,211,212,213,214, 97, 59, 59, 59, 59, + 59, 59, 59,215,216,217,218,219,220,221,222,223, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70,223, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 70,224, 70,225, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70,224, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70,225, 70,226, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70,226, 70, 70, 70, 70, 70, 70, 70, 70, 70,227, 97, 97, - 97, 97, 97, 97, 97, 97, 70, 70, 70, 70,228, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97,229, 97,230,231, 0, 1, 2, 2, 0, 1, + 70, 70, 70,227, 70, 70, 70, 70, 70, 70, 70, 70, 70,228, 97, 97, + 97, 97, 97, 97, 97, 97, 70, 70, 70, 70,229, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97,230, 97,231,232, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 19, 19, @@ -4709,49 +4735,58 @@ _hb_ucd_u8[16998] = 2, 2, 2, 2, 2, 2, 2,122,122,122,122, 2, 2, 2, 2,122, 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130, - 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130, 3, 3, - 3, 3, 3, 3, 3, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 2, 2, - 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 2, 2,101,101, - 101,101,101,101,101,101,101, 2, 2, 2, 2, 2, 2, 2,101,101, - 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2,111,111, - 111,111,111,111,111,111,111,111,111,111,111,111,111, 2,100,100, - 100,100,100,100,100,100,100,100,100,100,100,100, 2, 2, 2, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,108,108, - 108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108, - 108,108,108,108,108, 2,129,129,129,129,129,129,129, 2,129, 2, - 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129, - 129,129,129,129, 2,129,129,129, 2, 2, 2, 2, 2, 2,109,109, - 109,109,109,109,109,109,109,109,109, 2, 2, 2, 2, 2,109,109, - 2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107, - 107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107, - 107,107,107,107,107,107,107, 2,107,107,107,107,107,107,107, 2, - 107,107, 2,107,107,107,107,107, 2, 1,107,107,107,107,107, 2, - 2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2, - 2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107, - 107,107,107, 2, 2, 2,137,137,137,137,137,137,137,137,137,137, - 2,137, 2,137,137,137,124,124,124,124,124,124,124,124,124,124, - 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123, - 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114, - 114,114,114, 2, 2, 2,114,114, 2, 2, 2, 2, 2, 2, 32, 32, - 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102, 2, - 2, 2, 2, 2, 2, 2,102,102, 2, 2, 2, 2, 2, 2,126,126, - 126,126,126,126,126,126,126,126,126, 2, 2,126,126,126,126,126, - 126,126, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2,125,125, + 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,144,144, + 144,144,144,144,144,144,144,144, 2, 2, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 2,147,147,147,147,147,147,147,147,148,148, + 148,148,148,148,148,148,148,148, 2, 2, 2, 2, 2, 2,149,149, + 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, + 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 2, 2, 2, 94, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101, 2, + 2, 2, 2, 2, 2, 2,101,101, 2, 2, 2, 2, 2, 2, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 2,111,111,111,111,111,111,111,111,111,111, + 111,111,111,111,111, 2,100,100,100,100,100,100,100,100,100,100, + 100,100,100,100, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 2, 2, 2,108,108,108,108,108,108,108,108,108,108, + 2,108,108,108,108,108,108,108,108,108,108,108,108, 2,129,129, + 129,129,129,129,129, 2,129, 2,129,129,129,129, 2,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129, 2,129,129,129, + 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109, + 109, 2, 2, 2, 2, 2,109,109, 2, 2, 2, 2, 2, 2,107,107, + 107,107, 2,107,107,107,107,107,107,107,107, 2, 2,107,107, 2, + 2,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2, + 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107, + 2, 1,107,107,107,107,107, 2, 2,107,107,107, 2, 2,107, 2, + 2, 2, 2, 2, 2,107, 2, 2, 2, 2, 2,107,107,107,107,107, + 107,107, 2, 2,107,107,107,107,107,107,107, 2, 2, 2,137,137, + 137,137,137,137,137,137,137,137, 2,137, 2,137,137,137,124,124, + 124,124,124,124,124,124,124,124, 2, 2, 2, 2, 2, 2,123,123, + 123,123,123,123,123,123,123,123,123,123,123,123, 2, 2,114,114, + 114,114,114,114,114,114,114,114,114,114,114, 2, 2, 2,114,114, + 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 2, 2, 2,102,102, + 102,102,102,102,102,102,102, 2, 2, 2, 2, 2, 2, 2,102,102, + 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126, + 126, 2, 2,126,126,126,126,126,126,126, 2, 2, 2, 2,142,142, + 142,142,142,142,142,142,142,142,142,142, 2, 2, 2, 2,125,125, 125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2,125, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 2, 2, 2, 7, 7, 7, 2, 2, 2, 2, 2,121,121, - 121,121,121,121,121,121,121, 2, 2, 2, 2, 2, 2, 2,133,133, - 133,133,133,133,133,133,133, 2,133,133,133,133,133,133,133,133, - 133,133,133,133,133, 2,133,133,133,133,133,133, 2, 2,133,133, - 133,133,133, 2, 2, 2,134,134,134,134,134,134,134,134, 2, 2, - 134,134,134,134,134,134, 2,134,134,134,134,134,134,134,134,134, - 134,134,134,134,134, 2, 8, 8, 8, 8, 8, 8, 8, 2, 8, 8, - 2, 8, 8, 8, 8, 8, 2, 2, 8, 2, 8, 8, 2, 8, 8, 8, - 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 2, 9, 9, 2, - 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 22, 22, + 2, 2, 2, 2, 2,125,150,150,150,150,150,150,150,150, 2, 2, + 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2,141,141, + 141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140, + 140, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121, 2, + 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2, + 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133, + 133,133,133,133, 2, 2,133,133,133,133,133, 2, 2, 2,134,134, + 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134, 2,134, + 134,134,134,134,134,134,134,134,134,134,134,134,134, 2,138,138, + 138,138,138,138,138, 2,138,138, 2,138,138,138,138,138,138,138, + 138,138,138,138,138,138, 2, 2,138, 2,138,138, 2,138,138,138, + 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2, + 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, + 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2, + 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2, 2, 2,145,145, + 145,145,145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63, 63, 63, 63, 2, 2, 2, 63, 63, @@ -4762,28 +4797,31 @@ _hb_ucd_u8[16998] = 115,115,115,115,115, 2,115,115, 2, 2, 2, 2,115,115,103,103, 103,103,103,103,103,103,103,103,103,103,103,103, 2, 2,119,119, 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,119,119, - 2,119,119,119,119,119, 2, 2, 2, 2, 2,119,119,119, 11, 11, - 11, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 2, 2, 2, 2, 99, 2, 2, 2, 2, 2, 2, 2, 99,136, 12, - 0, 0, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136,136, - 136, 2, 2, 2, 2, 2, 17, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,105,105, - 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105, - 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105, - 2, 2,105,105,105,105, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, - 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, - 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,131,131, - 131,131,131,131,131,131,131,131,131,131, 2, 2, 2, 2, 2, 2, - 2,131,131,131,131,131, 2,131,131,131,131,131,131,131, 56, 2, - 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56, - 56, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 2, 2, 2, 13, 13, - 2, 2, 2, 2, 13, 13, 14, 14, 2, 2, 2, 2, 2, 14,113,113, + 2,119,119,119,119,119, 2, 2, 2, 2, 2,119,119,119,146,146, + 146,146,146,146,146,146,146,146,146, 2, 2, 2, 2, 2, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99, 2, 2, + 2, 2, 2, 2, 2, 99,136,139, 0, 0, 2, 2, 2, 2,136,136, + 136,136,136,136,136,136,136,136,136, 2, 2, 2, 2, 2, 17, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 17, 17, 17, 17,139,139,139,139,139,139,139,139,139,139, + 139,139, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105, + 105, 2, 2, 2, 2, 2,105,105,105,105,105, 2, 2, 2,105, 2, + 2, 2, 2, 2, 2, 2,105,105, 2, 2,105,105,105,105, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 0, 2, 2, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,131,131,131,131, + 131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131, + 131,131,131,131,131,131, 56, 2, 2, 56, 56, 56, 56, 56, 56, 56, + 2, 56, 56, 2, 56, 56, 56, 56, 56, 2, 2, 2, 2, 2,151,151, + 151,151,151,151,151,151,151,151,151,151,151, 2, 2, 2,151,151, + 151,151,151,151, 2, 2,151,151, 2, 2, 2, 2,151,151,152,152, + 152,152,152,152,152,152,152,152, 2, 2, 2, 2, 2,152,113,113, 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113, 113,113,113,113,113, 2,132,132,132,132,132,132,132,132,132,132, 132,132, 2, 2, 2, 2,132,132, 2, 2, 2, 2,132,132, 0, 0, @@ -4795,30 +4833,31 @@ _hb_ucd_u8[16998] = 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 13, 13, - 13, 13, 13, 13, 13, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 0, - 2, 2, 2, 2, 2, 2, 16, 50, 84,118, 88, 89, 90, 85, 85, 85, + 13, 13, 13, 13, 13, 2, 13, 13, 13, 13, 13, 2, 2, 2, 13, 2, + 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 16, 50, + 84,118, 88, 89, 90, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 91, 85, 85, + 220, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 91, 85, 85,220, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, - 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, - 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, + 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, - 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, - 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, - 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, - 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, - 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, + 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, + 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4828,48 +4867,47 @@ _hb_ucd_u8[16998] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, + 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0, + 109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0, + 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99,100,101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0,105, - 106, 0,107, 0, 0, 0,108, 0,109, 0,110, 0,111,112,113, 0, - 114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118,119,120,121, 0,122, - 123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,129, + 130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145, + 146,147,148,149,150,151,152,153,154,155,156,157, 0, 0, 0,158, + 159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0, + 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128,129,130,131,132,133,134,135,136,137, - 138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153, - 154,155,156,157, 0, 0, 0,158,159,160,161, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162, - 163, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,168,169, 0, 0, 0, 0,170,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,172,173, + 174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189, + 190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,169, 0, 0, 0, - 0,170,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,172,173,174,175,176,177,178,179,180,181, - 182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, - 198,199,200,201,202,203,204,205, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, }; static const uint16_t -_hb_ucd_u16[8928] = +_hb_ucd_u16[8944] = { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23, @@ -5122,105 +5160,106 @@ _hb_ucd_u16[8928] = 450, 450, 451, 452, 26, 453, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 454, 454, 454, 454, 454, 454, 454, 454, 454, 455, 26, 26, 26, 26, 26, 26, 456, 456, 456, 456, 456, 456, 457, 26, 456, 456, 456, 456, 456, 456, 457, 458, - 0, 0, 0, 0, 0, 26, 0, 316, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 459, - 9, 9, 9, 9, 9, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 459, 26, - 460, 460, 460, 460, 460, 460, 460, 460, 460, 461, 462, 460, 460, 460, 26, 463, - 464, 464, 464, 464, 464, 464, 464, 464, 465, 466, 467, 467, 467, 468, 467, 469, - 470, 470, 470, 470, 470, 470, 471, 470, 472, 26, 473, 473, 473, 473, 474, 26, - 475, 475, 475, 475, 475, 475, 475, 475, 475, 476, 475, 475, 477, 140, 478, 26, - 479, 479, 480, 479, 479, 479, 479, 481, 26, 26, 26, 26, 26, 26, 26, 26, - 482, 483, 484, 485, 484, 486, 487, 487, 487, 487, 487, 487, 487, 488, 487, 489, - 490, 491, 492, 493, 493, 494, 495, 496, 491, 497, 498, 499, 500, 501, 501, 26, - 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 503, 26, 26, 26, 26, - 504, 504, 504, 504, 504, 504, 504, 504, 504, 26, 504, 505, 26, 26, 26, 26, - 506, 506, 506, 506, 506, 506, 507, 506, 506, 506, 506, 507, 26, 26, 26, 26, - 508, 508, 508, 508, 508, 508, 508, 508, 509, 26, 508, 510, 201, 511, 26, 26, - 512, 512, 512, 512, 512, 512, 512, 513, 512, 514, 26, 26, 26, 26, 26, 26, - 515, 515, 515, 516, 515, 517, 515, 515, 26, 26, 26, 26, 26, 26, 26, 26, - 21, 21, 21, 21, 21, 21, 21, 518, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 520, 521, - 26, 26, 26, 26, 60, 522, 60, 60, 60, 60, 60, 522, 523, 26, 26, 26, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 26, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 524, 26, 26, 26, 525, 525, 525, 525, 525, 525, 525, 526, - 527, 528, 527, 527, 527, 527, 529, 527, 530, 26, 527, 527, 527, 531, 532, 532, - 532, 532, 533, 532, 532, 534, 535, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 536, 537, 167, 167, 167, 167, 536, 538, 167, 26, 167, 539, 540, 541, 14, 14, - 14, 257, 15, 375, 14, 542, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 84, 84, 84, 89, - 26, 26, 26, 26, 26, 26, 26, 26, 109, 109, 109, 109, 109, 109, 543, 544, - 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, - 545, 545, 545, 546, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 547, 548, 26, - 545, 545, 545, 545, 545, 545, 545, 545, 549, 26, 26, 26, 26, 26, 26, 26, - 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, - 550, 550, 550, 550, 550, 551, 550, 552, 26, 26, 26, 26, 26, 26, 26, 26, - 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, - 553, 553, 553, 553, 553, 553, 553, 553, 554, 26, 26, 26, 26, 26, 26, 26, + 459, 459, 459, 459, 459, 26, 459, 460, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 461, + 462, 462, 462, 462, 462, 26, 463, 463, 463, 463, 463, 464, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 465, 465, 466, 26, + 467, 467, 467, 467, 467, 467, 467, 467, 467, 468, 469, 467, 467, 467, 26, 470, + 471, 471, 471, 471, 471, 471, 471, 471, 472, 473, 474, 474, 474, 475, 474, 476, + 477, 477, 477, 477, 477, 477, 478, 477, 479, 26, 480, 480, 480, 480, 481, 26, + 482, 482, 482, 482, 482, 482, 482, 482, 482, 483, 482, 482, 484, 140, 485, 26, + 486, 486, 487, 486, 486, 486, 486, 488, 26, 26, 26, 26, 26, 26, 26, 26, + 489, 490, 491, 492, 491, 493, 494, 494, 494, 494, 494, 494, 494, 495, 494, 496, + 497, 498, 499, 500, 500, 501, 502, 503, 498, 504, 505, 506, 507, 508, 508, 26, + 509, 509, 509, 509, 509, 509, 509, 509, 509, 509, 509, 510, 26, 26, 26, 26, + 511, 511, 511, 511, 511, 511, 511, 511, 511, 26, 511, 512, 26, 26, 26, 26, + 513, 513, 513, 513, 513, 513, 514, 513, 513, 513, 513, 514, 26, 26, 26, 26, + 515, 515, 515, 515, 515, 515, 515, 515, 516, 26, 515, 517, 201, 518, 26, 26, + 519, 519, 519, 519, 519, 519, 519, 520, 519, 521, 26, 26, 26, 26, 26, 26, + 522, 522, 522, 523, 522, 524, 522, 522, 26, 26, 26, 26, 26, 26, 26, 26, + 525, 525, 525, 525, 525, 525, 525, 526, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 528, 529, + 26, 26, 26, 26, 530, 531, 530, 530, 530, 530, 530, 531, 532, 26, 26, 26, + 533, 533, 533, 533, 533, 533, 533, 533, 533, 26, 534, 534, 534, 534, 534, 534, + 534, 534, 534, 534, 535, 26, 26, 26, 536, 536, 536, 536, 536, 536, 536, 537, + 538, 539, 538, 538, 538, 538, 540, 538, 541, 26, 538, 538, 538, 542, 543, 543, + 543, 543, 544, 543, 543, 545, 546, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 547, 548, 549, 549, 549, 549, 547, 550, 549, 26, 549, 551, 552, 553, 554, 554, + 554, 555, 556, 557, 554, 558, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 559, 559, 559, 560, + 26, 26, 26, 26, 26, 26, 26, 26, 109, 109, 109, 109, 109, 109, 561, 562, + 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, + 563, 563, 563, 564, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 565, 566, 26, + 563, 563, 563, 563, 563, 563, 563, 563, 567, 26, 26, 26, 26, 26, 26, 26, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 569, 568, 570, 26, 26, 26, 26, 26, 26, 26, 26, + 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, + 571, 571, 571, 571, 571, 571, 571, 571, 572, 26, 26, 26, 26, 26, 26, 26, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, - 309, 309, 309, 309, 309, 309, 309, 555, 556, 556, 556, 557, 556, 558, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 559, 559, 559, 560, 560, 26, - 561, 561, 561, 561, 561, 561, 561, 561, 562, 26, 561, 563, 563, 561, 561, 564, - 561, 561, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 72, 72, 72, 72, 72, 72, 72, 72, - 72, 72, 72, 565, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 566, 566, 566, 566, 566, 566, 566, 566, 566, 567, 566, 566, 566, 566, 566, 566, - 566, 568, 566, 566, 26, 26, 26, 26, 26, 26, 26, 26, 569, 26, 26, 26, - 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, - 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 26, - 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 571, 26, - 572, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 309, 309, 309, 309, 309, 309, 309, 573, 574, 574, 574, 575, 574, 576, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 577, 577, 577, 578, 578, 26, + 579, 579, 579, 579, 579, 579, 579, 579, 580, 26, 579, 581, 581, 579, 579, 582, + 579, 579, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 583, 583, 583, 583, 583, 583, 583, 583, + 583, 583, 583, 584, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 585, 585, 585, 585, 585, 585, 585, 585, 585, 586, 585, 585, 585, 585, 585, 585, + 585, 587, 585, 585, 26, 26, 26, 26, 26, 26, 26, 26, 588, 26, 26, 26, + 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, + 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 26, + 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 590, 26, + 591, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, - 290, 290, 290, 291, 26, 26, 26, 26, 26, 26, 573, 26, 574, 26, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 346, - 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 576, 575, 577, - 575, 578, 575, 579, 284, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 290, 290, 290, 291, 26, 26, 26, 26, 26, 26, 592, 26, 593, 26, 594, 594, + 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, + 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 595, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 597, 596, 598, + 596, 599, 596, 600, 284, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 26, - 0, 0, 0, 0, 262, 361, 0, 0, 0, 0, 0, 0, 580, 581, 0, 582, - 583, 584, 0, 0, 0, 585, 0, 0, 0, 0, 0, 0, 0, 586, 26, 26, + 0, 0, 0, 0, 262, 361, 0, 0, 0, 0, 0, 0, 601, 602, 0, 603, + 604, 605, 0, 0, 0, 606, 0, 0, 0, 0, 0, 0, 0, 607, 26, 26, 14, 14, 14, 14, 14, 14, 14, 14, 251, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 284, 26, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 262, 26, 0, 0, 0, 586, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 262, 26, 0, 0, 0, 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259, 0, 0, 0, 0, 0, - 0, 0, 0, 259, 587, 588, 0, 589, 590, 0, 0, 0, 0, 0, 0, 0, - 591, 592, 259, 259, 0, 0, 0, 593, 594, 595, 596, 0, 0, 0, 0, 0, + 0, 0, 0, 259, 608, 609, 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, + 612, 613, 259, 259, 0, 0, 0, 614, 615, 616, 617, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 271, 0, 0, 0, 0, 0, 0, - 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, - 597, 598, 26, 599, 600, 597, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 274, 273, 273, 601, 602, 603, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 280, 280, 280, 280, 280, 604, 280, 283, 280, 605, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 606, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 608, 607, 609, 26, 26, 26, 26, 26, - 610, 610, 610, 610, 610, 610, 610, 610, 610, 611, 610, 612, 26, 26, 26, 26, + 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, + 618, 619, 26, 620, 621, 618, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 274, 273, 273, 622, 623, 624, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 625, 625, 625, 625, 625, 626, 625, 627, 625, 628, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 629, 629, 629, 629, 629, 629, 629, 630, + 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, + 631, 631, 631, 631, 631, 631, 631, 631, 632, 631, 633, 26, 26, 26, 26, 26, + 634, 634, 634, 634, 634, 634, 634, 634, 634, 635, 634, 636, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 361, 0, - 0, 0, 0, 0, 0, 0, 613, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 0, 0, 0, 0, 0, 0, 637, 26, 26, 26, 26, 26, 26, 26, 26, 26, 361, 0, 0, 0, 0, 0, 0, 272, 26, 26, 26, 26, 26, 26, 26, 26, - 614, 31, 31, 31, 615, 616, 617, 618, 619, 620, 615, 621, 615, 617, 617, 622, - 31, 623, 31, 624, 625, 623, 31, 624, 26, 26, 26, 26, 26, 26, 355, 26, + 638, 31, 31, 31, 639, 640, 641, 642, 643, 644, 639, 645, 639, 641, 641, 646, + 31, 647, 31, 648, 649, 647, 31, 648, 26, 26, 26, 26, 26, 26, 355, 26, 0, 0, 0, 0, 0, 284, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 284, 26, 0, 262, 361, 0, 361, 0, 361, 0, 0, 0, 272, 26, - 0, 613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 613, 0, 0, - 0, 0, 0, 0, 0, 613, 26, 26, 26, 26, 26, 26, 626, 0, 0, 0, - 627, 26, 0, 0, 0, 0, 0, 284, 0, 586, 316, 26, 272, 26, 26, 26, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 26, 0, 613, 0, 269, + 0, 637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 637, 0, 0, + 0, 0, 0, 0, 0, 637, 26, 26, 26, 26, 26, 26, 650, 0, 0, 0, + 651, 26, 0, 0, 0, 0, 0, 284, 0, 607, 316, 26, 272, 26, 26, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 26, 0, 637, 0, 269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 284, 26, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 586, 0, 284, 26, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 607, 0, 284, 26, 26, 0, 284, 0, 0, 0, 0, 0, 0, 0, 26, 0, 316, 0, 0, 0, 0, 0, 26, 0, 0, 0, 272, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 0, 590, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 593, 595, - 0, 0, 0, 0, 592, 628, 0, 0, 0, 592, 0, 0, 0, 0, 0, 0, + 0, 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 614, 616, + 0, 0, 0, 0, 613, 652, 0, 0, 0, 613, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 284, 26, 0, 272, 284, 269, 269, 26, 272, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 629, 26, 26, 26, 26, 26, - 280, 280, 280, 280, 280, 280, 604, 26, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 653, 26, 26, 26, 26, 26, + 280, 280, 280, 280, 280, 280, 654, 26, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 283, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 348, 26, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 630, 26, 26, 26, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 655, 26, 26, 26, 280, 280, 280, 283, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 631, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 656, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5476,14 +5515,14 @@ _hb_ucd_sc (unsigned u) static inline uint_fast16_t _hb_ucd_dm (unsigned u) { - return u<195102u?_hb_ucd_u16[5632+(((_hb_ucd_u8[15974+(((_hb_ucd_b4(15878+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0; + return u<195102u?_hb_ucd_u16[5648+(((_hb_ucd_u8[16174+(((_hb_ucd_b4(16078+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0; } #else static const uint8_t -_hb_ucd_u8[12888] = +_hb_ucd_u8[13072] = { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 6, 5, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 5, 17, 15, 15, 18, 15, 19, 20, 21, @@ -6014,26 +6053,26 @@ _hb_ucd_u8[12888] = 32, 32, 32, 32, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 62, 62, 62, 62, 88, 89, 89, 89, 90, 89, 91, 92, 93, 94, 95, 95, 96, 97, 87, 98, 99,100,101,102,103, 87, - 104,104,104, 87,105,106,107,108,109,110,111,112,113,114, 56, 87, - 89, 87,115, 89,116,117,118,119,120,121,122, 87,123,124, 87,125, - 126,127,128, 87,129,130, 87, 17,131,132, 87, 87,133,134,135, 51, - 87, 19, 87, 21,136,136,136,136,136,136,136,136,136,136,136, 87, - 87, 87, 87, 87,137,137,137,137,137,137,137,137,137, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,138,138,138,138, - 138, 87, 87, 87,139,139,139,139,140,141,142,142, 87, 87, 87, 87, - 18, 18,143,144,145,145,145,145,145,145,145,145,145,145,145,145, - 145,145,145,145,145,145,145,145,145,145, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87,146,147,148, 32, 32, 32, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,149,150, 87, 87, - 87, 87, 87, 87, 56, 56,151,152, 51, 56, 56, 87, 56, 56, 56, 56, - 56, 56, 56, 56,153,153,153,153,153,153, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87,154, 87, 62, 87, 87,155, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87,156,156,157, 87, 87, 87, 87, 87, 56, 56, 56, 87, - 89, 89, 87, 87, 56, 56, 56, 56,158, 87, 56, 56, 56, 56, 56, 56, + 104,104,104, 87,105,106,107,108,109,110,111,112,113,114,115, 87, + 89, 87,116,117,118,119,120,121,122,123,124, 87,125,126, 87,127, + 128,129,130, 87,131,132, 87,133,134,135, 87, 87,136,137,138,139, + 87,140, 87, 21,141,141,141,141,141,141,141,141,141,141,141, 87, + 87, 87, 87, 87,142,142,142,142,142,142,142,142,142, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,143,143,143,143, + 143, 87, 87, 87,144,144,144,144,145,146,147,147, 87, 87, 87, 87, + 148,148,149,150,151,151,151,151,151,151,151,151,151,151,151,151, + 151,151,151,151,151,151,151,151,151,151, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87,152,153,154,155,155,155, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,156,157, 87, 87, + 87, 87, 87, 87, 56, 56,158,159, 51, 56, 56, 87, 56, 56, 56, 56, + 56, 56, 56, 56,160,160,160,160,160,160, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87,161, 87,162, 87, 87,163, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87,164,164,165, 87, 87, 87, 87, 87, 56, 56, 56, 87, + 89, 89, 87, 87, 56, 56, 56, 56,166, 87, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87, 87, 87, 87, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 56, 87,159,159, 0, 1, 2, 2, 0, 1, 2, 2, + 87, 87, 87, 87, 56, 87,167,167, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, @@ -6091,29 +6130,33 @@ _hb_ucd_u8[12888] = 159,159,159,159,160,160,161,161,161,161,161,161,162,162,162,162, 162,162,163,163,164,164,164,164,165,165,165,165,166,166,166,166, 167,167,168,168,169,169,169,169,169,169,169,169,170,170,170,170, - 170,170,170,170,171,171,171,171,171,171,171,171, 8, 8, 8,129, - 129,129,129,129,172,172,172,172,172,172,172,172,173,173,173,173, - 173,174,174,174,175,175,175,175,175,176,176,176,177,177,177,177, - 177,177,178, 44,179,179,179,179,179,179,179,179,180,180,180,181, - 181,181,181,181,182,182,182,183,182,182,182,182,184,184,184,184, - 184,184,184,184,185,185,185,185,185,185,185,185,186,186,186,186, - 186,186,186,186,187,187,187,187,187,187, 67, 67,188,188,188,188, - 188,188,188,188,189,189,189,189,189,189,189,189, 16, 16, 16, 16, - 16, 16, 16, 16,190,190,190,190,190,190,190,190, 13, 13, 13, 13, - 13, 33, 33, 33, 33, 33, 33, 33,191,191,191,191,192,192,192,192, - 192,192,192,193,193,193,193,193,193,193,193,193, 51, 51, 51, 51, - 51, 51, 11, 11,194,194,194,194,194,194,194,194,195,195,195,195, - 195,195,195,195,196,196,196,196,196,196,196,196,113,113,113,113, - 113,113,113,113,113,113,113,113,197,197,197,197,198,198,198,198, - 198,198,198,198,199,199,199,199,199,199,199,199,200,200,200,200, - 200,200,200,200,200,200,200,200,200,200,201, 0,202,202,202,202, - 202,202,202,202,203,100,100,100,100,100,100,100,100,100,100,100, - 100,100,100,100,100,100,100,100,100,100,204, 53,205,205,205,205, - 205,205,205,205,205,205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,206,207,208, 0,209, 0, 0, 0, 0, 0,210,210,210,210, - 210,210,210,210, 92, 92, 92, 92, 92, 92, 92, 92, 19, 19, 19, 19, - 19, 19, 19, 19,211,211,211,211,211,211,211,211,212,212,212,212, - 212,212,212,212,213, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, + 170,170,170,170,171,171,171,171,171,171,171,171,172,172,172,172, + 172,172,172,172,173,173,173,174,174,174,174,174,175,175,175,175, + 175,175,175,175,176,176,176,176,176,176,176,176,177,177,177,177, + 177,178,178,178,179,179,179,179,179,180,180,180,181,181,181,181, + 181,181,182, 44,183,183,183,183,183,183,183,183,184,184,184,185, + 185,185,185,185,186,186,186,187,186,186,186,186,188,188,188,188, + 188,188,188,188,189,189,189,189,189,189,189,189,190,190,190,190, + 190,190,190,190,191,191,191,191,191,191, 67, 67,192,192,192,192, + 192,192,192,192,193,193,193,193,193,193,193,193,194,194,194,194, + 194,194,194,194,195,195,195,195,195,195,195,195,196,196,196,196, + 196,196,196,196,197,197,197,197,197,198,198,198,198,198,198,198, + 199,199,199,199,200,200,200,200,200,200,200,201,201,201,201,201, + 201,201,201,201,202,202,202,202,202,202,203,203,203,203,203,203, + 203,203,203,203,204,204,204,204,204,204,204,204,205,205,205,205, + 205,205,205,205,206,206,206,206,206,206,206,206,207,207,207,207, + 207,207,207,207,113,113,113,113,113,113,113,113,113,113,113,113, + 208,208,208,208,209,209,209,209,209,209,209,209,210,210,210,210, + 210,210,210,210,211,211,211,211,211,211,211,211,212,212,212,212, + 212,212,212,212,212,212,212,212,212,212,213, 0,214,214,214,214, + 214,214,214,214,215,100,100,100,100,100,100,100,100,100,100,100, + 100,100,100,100,100,100,100,100,100,100,216,217,217,217,217,217, + 217,217,217,217,218,218,218,218,218,218,218,218,218,218, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,219,220,221, 0,222, 0, + 0, 0, 0, 0,223,223,223,223,223,223,223,223, 92, 92, 92, 92, + 92, 92, 92, 92,224,224,224,224,224,224,224,224,225,225,225,225, + 225,225,225,225,226,226,226,226,226,226,226,226,227,227,227,227, + 227,227,227,227,228, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0, 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8, @@ -6158,91 +6201,99 @@ _hb_ucd_u8[12888] = 163,163,163,163,164,164,164,164,165,165,165,165,166,166,166,166, 167,167,167,167,168,168,168,168,169,169,169,169,170,170,170,170, 171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,174, - 175,175,175,175,176,176,176,176,177,177,177,177,178, 46, 46, 46, - 179,179,179,179,180,180,180,180,181,181,181,181,182,182,182,182, - 182,182,183,182,184,184,184,184,185,185,185,185,186,186,186,186, - 187,187,187,187,188,188,188,188,189,189,189,189,190,190,190,190, + 175,175,175,175,176,176,176,176,177,177,177,177,178,178,178,178, + 179,179,179,179,180,180,180,180,181,181,181,181,182, 46, 46, 46, + 183,183,183,183,184,184,184,184,185,185,185,185,186,186,186,186, + 186,186,187,186,188,188,188,188,189,189,189,189,190,190,190,190, 191,191,191,191,192,192,192,192,193,193,193,193,194,194,194,194, 195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198, - 199,199,199,199,200,200,200,200,201, 0, 0, 0,202,202,202,202, - 203,107,107,107,107,110,110,110,204,204,204,204, 0,205, 87, 0, - 0, 0,205, 7, 83,138, 7, 0, 0, 0,206, 87,207,207,207,207, - 208,208,208,208,209,209,209,209,210, 0, 0, 0, 0, 0, 0, 0, - 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, - 19, 0, 0, 0, 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55, - 55, 55, 55, 55, 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4, - 4, 4, 4, 4, 4, 0, 4, 4, 4, 14, 14, 14, 14, 14, 14, 14, - 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, - 3, 3, 3, 1, 1, 1, 3, 3, 1, 3, 3, 3, 37, 37, 37, 37, - 38, 38, 38, 38, 64, 64, 64, 64, 90, 90, 90, 90, 95, 95, 95, 95, - 3, 3, 0, 3, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, - 0, 0, 7, 7, 5, 5, 5, 5, 11, 11, 11, 11, 10, 10, 10, 10, - 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 16, 16, 16, 16, - 20, 20, 20, 20, 36, 36, 36, 36, 24, 24, 24, 24, 24, 24, 24, 0, - 18, 18, 18, 18, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, 25, 25, - 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 0, 12, 12, 12, 12, - 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28, 34, 34, 34, 34, - 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 45, 45, 45, 45, - 44, 44, 44, 44, 44, 0, 0, 0, 43, 43, 43, 43, 46, 46, 46, 46, - 31, 31, 31, 31, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, - 48, 48, 48, 48, 52, 52, 52, 52, 58, 58, 58, 58, 54, 54, 54, 54, - 91, 91, 91, 91, 62, 62, 62, 62, 76, 76, 76, 76, 93, 93, 93, 93, - 70, 70, 70, 70, 73, 73, 73, 73, 1, 1, 1, 0, 1, 0, 1, 1, - 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 19, 19, 9, 9, - 9, 9, 9, 6, 19, 9, 9, 9, 9, 9, 19, 19, 9, 9, 9, 19, - 6, 19, 19, 19, 19, 19, 19, 9, 0, 0, 0, 19, 0, 0, 9, 0, - 0, 0, 19, 19, 27, 27, 27, 27, 56, 56, 56, 56, 61, 61, 61, 61, - 13, 13, 13, 13, 0, 13, 0, 13, 0, 13, 13, 13, 13, 13, 1, 1, - 1, 1, 12, 12, 0, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, - 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 26, 26, 26, 26, - 26, 12, 12, 12, 12, 12, 12, 0, 39, 39, 39, 39, 86, 86, 86, 86, - 77, 77, 77, 77, 79, 79, 79, 79, 60, 60, 60, 60, 65, 65, 65, 65, - 75, 75, 75, 75, 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, - 84, 84, 84, 84, 84, 84, 84, 0, 68, 68, 68, 68, 92, 92, 92, 92, - 87, 87, 87, 87, 19, 9, 19, 19, 2, 2, 2, 2, 19, 19, 19, 4, - 3, 3, 0, 0, 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0, - 49, 49, 49, 49, 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67, - 42, 42, 42, 42, 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, - 59, 59, 59, 59, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50, - 135,135,135,135,106,106,106,106,104,104,104,104,110,110,110,110, - 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120,116,116,116,116, - 128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98, - 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117, - 112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82, - 122,122,122,122, 89, 89, 89, 89,130,130,130,130, 94, 94, 94, 94, - 85, 85, 85, 85,101,101,101,101, 96, 96, 96, 96,111,111,111,111, - 100,100,100,100,100, 36, 36, 36,108,108,108,108,129,129,129,129, - 109,109,109,109,107,107,107,107,107,107,107, 1,137,137,137,137, - 124,124,124,124,123,123,123,123,114,114,114,114,102,102,102,102, - 126,126,126,126,125,125,125,125,121,121,121,121,133,133,133,133, - 134,134,134,134, 63, 63, 63, 63, 80, 80, 80, 80,127,127,127,127, - 115,115,115,115,103,103,103,103,119,119,119,119, 99, 99, 99, 99, - 136, 12, 0, 0,136,136,136,136, 17, 15, 15, 15,105,105,105,105, - 0, 0, 0, 1, 0, 0, 1, 1,131,131,131,131,113,113,113,113, - 132,132,132,132, 15, 0, 0, 0, 16, 50, 84,118, 88, 89, 90, 85, + 199,199,199,199,200,200,200,200,201,201,201,201,202,202,202,202, + 203,203,203,203,204,204,204,204,205,205,205,205,206,206,206,206, + 207,207,207,207,208,208,208,208,209,209,209,209,210,210,210,210, + 211,211,211,211,212,212,212,212,213, 0, 0, 0,214,214,214,214, + 215,107,107,107,107,110,110,110,216,216,216,216,217,217,217,217, + 0,218, 87, 0, 0, 0,218, 7, 83,138, 7, 0, 0, 0,219, 87, + 220,220,220,220,221,221,221,221,222,222,222,222,223,223,223,223, + 224,224,224,224,225, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0, + 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, + 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55, 55, 55, 55, 55, + 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4, 4, 4, 4, 4, + 4, 0, 4, 4, 4, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, + 3, 0, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 1, + 1, 1, 3, 3, 1, 3, 3, 3, 37, 37, 37, 37, 38, 38, 38, 38, + 64, 64, 64, 64, 90, 90, 90, 90, 95, 95, 95, 95, 3, 3, 0, 3, + 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 0, 0, 7, 7, + 5, 5, 5, 5, 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21, + 22, 22, 22, 22, 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20, + 36, 36, 36, 36, 24, 24, 24, 24, 24, 24, 24, 0, 18, 18, 18, 18, + 25, 25, 25, 25, 25, 0, 0, 0, 0, 25, 25, 25, 33, 33, 33, 33, + 8, 8, 8, 8, 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, + 29, 29, 29, 29, 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35, + 35, 35, 35, 0, 0, 0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44, + 44, 0, 0, 0, 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31, + 32, 32, 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, + 52, 52, 52, 52, 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91, + 62, 62, 62, 62, 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, + 73, 73, 73, 73, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 0, 0, 19, 19, 9, 9, 9, 9, 9, 6, + 19, 9, 9, 9, 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19, + 19, 19, 19, 9, 0, 0, 0, 19, 0, 0, 9, 0, 0, 0, 19, 19, + 27, 27, 27, 27, 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13, + 0, 13, 0, 13, 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, + 0, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, 0, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 0, 26, 26, 26, 26, 26, 12, 12, 12, + 12, 12, 12, 0, 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77, + 79, 79, 79, 79, 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75, + 69, 69, 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 84, 84, 84, 84, + 84, 84, 84, 0, 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87, + 19, 9, 19, 19, 2, 2, 2, 2, 19, 19, 19, 4, 3, 3, 0, 0, + 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0, 49, 49, 49, 49, + 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42, + 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59, + 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135, + 106,106,106,106,104,104,104,104,110,110,110,110, 47, 47, 47, 47, + 81, 81, 81, 81,120,120,120,120,116,116,116,116,128,128,128,128, + 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98, 97, 97, 97, 97, + 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117,112,112,112,112, + 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82,122,122,122,122, + 89, 89, 89, 89,130,130,130,130,144,144,144,144,147,147,147,147, + 148,148,148,148,149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85, + 101,101,101,101, 96, 96, 96, 96,111,111,111,111,100,100,100,100, + 100, 36, 36, 36,108,108,108,108,129,129,129,129,109,109,109,109, + 107,107,107,107,107,107,107, 1,137,137,137,137,124,124,124,124, + 123,123,123,123,114,114,114,114,102,102,102,102,126,126,126,126, + 142,142,142,142,125,125,125,125,150,150,150,150,141,141,141,141, + 140,140,140,140,121,121,121,121,133,133,133,133,134,134,134,134, + 138,138,138,138,143,143,143,143,145,145,145,145, 63, 63, 63, 63, + 80, 80, 80, 80,127,127,127,127,115,115,115,115,103,103,103,103, + 119,119,119,119,146,146,146,146, 99, 99, 99, 99,136,139, 0, 0, + 136,136,136,136, 17, 15, 15, 15,139,139,139,139,105,105,105,105, + 0, 0, 0, 1, 0, 0, 1, 1,131,131,131,131,151,151,151,151, + 152,152,152,152,113,113,113,113,132,132,132,132, 15, 0, 0, 0, + 16, 50, 84,118, 88, 89, 90, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 91, + 85, 85,220, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 91, 85, 85,220, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 15, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, - 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, - 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, + 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, - 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, - 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, - 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, - 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, - 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, + 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, + 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, + 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, + 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, + 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6253,44 +6304,43 @@ _hb_ucd_u8[12888] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, + 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99,100,101,102,103, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, - 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0,110, 0,111,112, - 113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0, 0, 0, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102, + 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0, + 108, 0,109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, + 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,118,119,120,121, - 0,122,123,124,125,126, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157, 0, 0, + 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, + 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,128,129,130,131,132,133,134,135, - 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, - 152,153,154,155,156,157, 0, 0, 0,158,159,160,161, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,165, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,168,169, 0, 0, 0, 0,170,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,169, 0, - 0, 0, 0,170,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,172,173,174,175,176,177,178,179, - 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195, - 196,197,198,199,200,201,202,203,204,205, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 2, 3, 4, + 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187, + 188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203, + 204,205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, }; static const uint16_t _hb_ucd_u16[4800] = @@ -6630,12 +6680,12 @@ _hb_ucd_bmg (unsigned u) static inline uint_fast8_t _hb_ucd_sc (unsigned u) { - return u<918016u?_hb_ucd_u8[10924+(((_hb_ucd_u8[10068+(((_hb_ucd_u8[8788+(((_hb_ucd_u8[8228+(((_hb_ucd_u8[7778+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2; + return u<918016u?_hb_ucd_u8[11048+(((_hb_ucd_u8[10132+(((_hb_ucd_u8[8788+(((_hb_ucd_u8[8228+(((_hb_ucd_u8[7778+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2; } static inline uint_fast16_t _hb_ucd_dm (unsigned u) { - return u<195102u?_hb_ucd_u16[1504+(((_hb_ucd_u8[11864+(((_hb_ucd_b4(11768+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0; + return u<195102u?_hb_ucd_u16[1504+(((_hb_ucd_u8[12048+(((_hb_ucd_b4(11952+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0; } #endif From 3bfa878c98cceeaae074d81c14329e358bea8912 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 25 Jun 2019 19:07:07 -0700 Subject: [PATCH 079/138] [gen-ucd] Protect against accidents like previous commit https://github.com/harfbuzz/harfbuzz/pull/1796 --- src/gen-ucd-table.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py index 1afde3bdf..a152375dd 100755 --- a/src/gen-ucd-table.py +++ b/src/gen-ucd-table.py @@ -58,13 +58,14 @@ dm_order = {None: 0} dm_order.update(dm1_order) dm_order.update(dm2_order) -gc_order = packTab.AutoMapping() -for _ in ('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu', - 'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf', - 'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',): - gc_order[_] +gc_order = dict() +for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu', + 'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf', + 'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',)): + gc_order[i] = v + gc_order[v] = i -sc_order = packTab.AutoMapping() +sc_order = dict() sc_array = [] sc_re = re.compile(r"\b(HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]") for line in open('hb-common.h'): @@ -72,14 +73,11 @@ for line in open('hb-common.h'): if not m: continue name = m.group(1) tag = ''.join(m.group(i) for i in range(2, 6)) - i = sc_order[tag] - assert i == len(sc_array) + i = len(sc_array) + sc_order[tag] = i + sc_order[i] = tag sc_array.append(name) -# TODO Currently if gc_order or sc_order do not capture all values, we get in -# trouble because they silently add new values. We should be able to "freeze" -# them, or just do the mapping ourselves. - DEFAULT = 1 COMPACT = 3 SLOPPY = 5 From b14e413fae8f14b75c5956e9b38e413c878ded0c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 10:44:10 -0700 Subject: [PATCH 080/138] 2.5.3 --- NEWS | 7 +++++++ configure.ac | 2 +- src/hb-version.h | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 0835378a1..20bb21ba2 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +Overview of changes leading to 2.5.3 +Wednesday, June 26, 2019 +==================================== +- Fix UCD script data for Unicode 10+ scripts. This was broken since 2.5.0. +- More optimizations for HB_TINY. + + Overview of changes leading to 2.5.2 Thursday, June 20, 2019 ==================================== diff --git a/configure.ac b/configure.ac index 426b85038..0dc672a81 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [2.5.2], + [2.5.3], [https://github.com/harfbuzz/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) diff --git a/src/hb-version.h b/src/hb-version.h index 10b826ffb..251cc6399 100644 --- a/src/hb-version.h +++ b/src/hb-version.h @@ -38,9 +38,9 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 2 #define HB_VERSION_MINOR 5 -#define HB_VERSION_MICRO 2 +#define HB_VERSION_MICRO 3 -#define HB_VERSION_STRING "2.5.2" +#define HB_VERSION_STRING "2.5.3" #define HB_VERSION_ATLEAST(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) <= \ From 8786820a5a7406be95bc4a6b6e2aca736126420c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 12:53:57 -0700 Subject: [PATCH 081/138] [src] Add make targets "tiny" and "tinyz" --- src/Makefile.am | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 14cafb833..51f9aac88 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,6 +15,10 @@ check_PROGRAMS = # Convenience targets: lib: $(BUILT_SOURCES) libharfbuzz.la libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES) +tiny: + $(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Os -DHB_TINY $(CPPFLAGS)" libs +tinyz: + $(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Oz -DHB_TINY $(CPPFLAGS)" libs lib_LTLIBRARIES = libharfbuzz.la From cee9f6e044278b590694f4dff6f22eaad9371385 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:01:58 -0700 Subject: [PATCH 082/138] Fail compile if no shapers enabled --- src/hb-shaper.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hb-shaper.cc b/src/hb-shaper.cc index 575ab1f7d..4858a6a9c 100644 --- a/src/hb-shaper.cc +++ b/src/hb-shaper.cc @@ -34,6 +34,7 @@ static const hb_shaper_entry_t all_shapers[] = { #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT }; +static_assert (0 != ARRAY_LENGTH_CONST (all_shapers), "No shaper enabled."); #if HB_USE_ATEXIT static void free_static_shapers (); From 7aad53657eb23264f658711a71da3e50f2264455 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:21:03 -0700 Subject: [PATCH 083/138] [config] Add HB_NO_OT_SHAPE / HB_NO_OT Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- CONFIG.md | 14 ++++++++++++++ src/gen-indic-table.py | 6 ++++++ src/gen-use-table.py | 6 ++++++ src/gen-vowel-constraints.py | 7 +++++++ src/hb-config.hh | 4 ++++ src/hb-ot-shape-complex-arabic.cc | 6 ++++++ src/hb-ot-shape-complex-default.cc | 7 +++++++ src/hb-ot-shape-complex-hangul.cc | 7 +++++++ src/hb-ot-shape-complex-hebrew.cc | 7 +++++++ src/hb-ot-shape-complex-indic-table.cc | 6 ++++++ src/hb-ot-shape-complex-indic.cc | 7 +++++++ src/hb-ot-shape-complex-khmer.cc | 7 +++++++ src/hb-ot-shape-complex-myanmar.cc | 7 +++++++ src/hb-ot-shape-complex-thai.cc | 7 +++++++ src/hb-ot-shape-complex-use-table.cc | 6 ++++++ src/hb-ot-shape-complex-use.cc | 7 +++++++ src/hb-ot-shape-complex-vowel-constraints.cc | 6 ++++++ src/hb-ot-shape-fallback.cc | 7 +++++++ src/hb-ot-shape-normalize.cc | 7 +++++++ src/hb-ot-shape.cc | 7 +++++++ src/hb-shape-plan.cc | 10 ++++++++++ src/hb-shape-plan.hh | 4 ++++ src/hb-shaper-list.hh | 2 ++ 23 files changed, 154 insertions(+) diff --git a/CONFIG.md b/CONFIG.md index 5fb3e7cb4..ff55154ad 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -86,6 +86,20 @@ In that case, or if you otherwise provide those functions by calling without loss of functionality by defining `HB_NO_OT_FONT`. +## Shapers + +Most HarfBuzz clients use it for the main shaper, called "ot". However, it +is legitimate to want to compile HarfBuzz with only another backend, eg. +CoreText, for example for an iOS app. For that, you want `HB_NO_OT_SHAPE`, +or more generally `HB_NO_OT`. + +This is very rarely what you need. Make sure you understand exactly what you +are doing. + +Defining `HB_NO_FALLBACK_SHAPE` however is pretty harmless. That removes the +(unused) "fallback" shaper. + + ## Thread-safety By default HarfBuzz builds as a thread-safe library. The exception is that diff --git a/src/gen-indic-table.py b/src/gen-indic-table.py index eedf420b7..cdf81fe75 100755 --- a/src/gen-indic-table.py +++ b/src/gen-indic-table.py @@ -98,6 +98,10 @@ for h in headers: print (" * %s" % (l.strip())) print (" */") print () +print ('#include "hb.hh"') +print () +print ('#ifndef HB_NO_OT_SHAPE') +print () print ('#include "hb-ot-shape-complex-indic.hh"') print () @@ -251,6 +255,8 @@ for i in range (2): print ("#undef %s_%s" % (what_short[i], short[i][v])) print () +print () +print ('#endif') print ("/* == End of generated table == */") # Maintain at least 30% occupancy in the table */ diff --git a/src/gen-use-table.py b/src/gen-use-table.py index 820838cf8..a8a03a77b 100755 --- a/src/gen-use-table.py +++ b/src/gen-use-table.py @@ -419,6 +419,10 @@ for h in headers: print (" * %s" % (l.strip())) print (" */") print () +print ('#include "hb.hh"') +print () +print ('#ifndef HB_NO_OT_SHAPE') +print () print ('#include "hb-ot-shape-complex-use.hh"') print () @@ -533,6 +537,8 @@ for k,v in sorted(use_positions.items()): tag = k + suf print ("#undef %s" % tag) print () +print () +print ('#endif') print ("/* == End of generated table == */") # Maintain at least 50% occupancy in the table */ diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py index 1340d97dc..8ca90c819 100755 --- a/src/gen-vowel-constraints.py +++ b/src/gen-vowel-constraints.py @@ -157,6 +157,11 @@ print (' *') for line in scripts_header: print (' * %s' % line.strip ()) print (' */') + +print () +print ('#include "hb.hh"') +print () +print ('#ifndef HB_NO_OT_SHAPE') print () print ('#include "hb-ot-shape-complex-vowel-constraints.hh"') print () @@ -223,4 +228,6 @@ print (' }') print ('}') print () +print () +print ('#endif') print ('/* == End of generated functions == */') diff --git a/src/hb-config.hh b/src/hb-config.hh index f9e4699fc..c6a408053 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -121,6 +121,10 @@ #define HB_NO_OT_NAME_LANGUAGE #endif +#ifdef HB_NO_OT +#define HB_NO_OT_SHAPE +#endif + #ifdef HB_NO_OT_SHAPE_FALLBACK #define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK #define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 3212e0c96..b24833b71 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -25,6 +25,9 @@ */ #include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex-arabic.hh" #include "hb-ot-shape.hh" @@ -710,3 +713,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; + + +#endif diff --git a/src/hb-ot-shape-complex-default.cc b/src/hb-ot-shape-complex-default.cc index 97923ecf6..a921f16fa 100644 --- a/src/hb-ot-shape-complex-default.cc +++ b/src/hb-ot-shape-complex-default.cc @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex.hh" @@ -44,3 +48,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; + + +#endif diff --git a/src/hb-ot-shape-complex-hangul.cc b/src/hb-ot-shape-complex-hangul.cc index f084f6ad6..32e0e6612 100644 --- a/src/hb-ot-shape-complex-hangul.cc +++ b/src/hb-ot-shape-complex-hangul.cc @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex.hh" @@ -430,3 +434,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul = HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; + + +#endif diff --git a/src/hb-ot-shape-complex-hebrew.cc b/src/hb-ot-shape-complex-hebrew.cc index 14989730f..334d3ded8 100644 --- a/src/hb-ot-shape-complex-hebrew.cc +++ b/src/hb-ot-shape-complex-hebrew.cc @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex.hh" @@ -176,3 +180,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; + + +#endif diff --git a/src/hb-ot-shape-complex-indic-table.cc b/src/hb-ot-shape-complex-indic-table.cc index d26bbb8f3..419aae11e 100644 --- a/src/hb-ot-shape-complex-indic-table.cc +++ b/src/hb-ot-shape-complex-indic-table.cc @@ -14,6 +14,10 @@ * # Date: 2018-07-30, 19:40:00 GMT [KW] */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex-indic.hh" #pragma GCC diagnostic push @@ -487,4 +491,6 @@ hb_indic_get_categories (hb_codepoint_t u) #undef IMC_TR #undef IMC_VOL + +#endif /* == End of generated table == */ diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index f8cb5741b..6405d9c2d 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex-indic.hh" #include "hb-ot-shape-complex-vowel-constraints.hh" #include "hb-ot-layout.hh" @@ -1648,3 +1652,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; + + +#endif diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc index 4c8847762..eba7d86ea 100644 --- a/src/hb-ot-shape-complex-khmer.cc +++ b/src/hb-ot-shape-complex-khmer.cc @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex-khmer.hh" #include "hb-ot-layout.hh" @@ -502,3 +506,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_khmer = HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; + + +#endif diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index b1f6b65ef..5b819cf47 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex-myanmar.hh" @@ -415,3 +419,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi = HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; + + +#endif diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc index 22d4aa3ab..347ea2e7a 100644 --- a/src/hb-ot-shape-complex-thai.cc +++ b/src/hb-ot-shape-complex-thai.cc @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex.hh" @@ -385,3 +389,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, false,/* fallback_position */ }; + + +#endif diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc index 024746989..4c5d687c7 100644 --- a/src/hb-ot-shape-complex-use-table.cc +++ b/src/hb-ot-shape-complex-use-table.cc @@ -15,6 +15,10 @@ * UnicodeData.txt does not have a header. */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex-use.hh" #pragma GCC diagnostic push @@ -851,4 +855,6 @@ hb_use_get_category (hb_codepoint_t u) #undef VMPst #undef VMAbv + +#endif /* == End of generated table == */ diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 2cc5ea278..91c0b8c04 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -26,6 +26,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex-use.hh" #include "hb-ot-shape-complex-arabic.hh" #include "hb-ot-shape-complex-vowel-constraints.hh" @@ -643,3 +647,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; + + +#endif diff --git a/src/hb-ot-shape-complex-vowel-constraints.cc b/src/hb-ot-shape-complex-vowel-constraints.cc index 912ee35b4..2f8041323 100644 --- a/src/hb-ot-shape-complex-vowel-constraints.cc +++ b/src/hb-ot-shape-complex-vowel-constraints.cc @@ -13,6 +13,10 @@ * # Date: 2019-01-28, 22:16:47 GMT */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-complex-vowel-constraints.hh" static void @@ -440,4 +444,6 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, } } + +#endif /* == End of generated functions == */ diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc index 573af8ec6..03a42df6f 100644 --- a/src/hb-ot-shape-fallback.cc +++ b/src/hb-ot-shape-fallback.cc @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-fallback.hh" #include "hb-kern.hh" @@ -587,3 +591,6 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED, } } } + + +#endif diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 82bb24b7d..14c5bd4ac 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-shape-normalize.hh" #include "hb-ot-shape-complex.hh" #include "hb-ot-shape.hh" @@ -469,3 +473,6 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, buffer->swap_buffers (); } } + + +#endif diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 7690c2229..499b1be4b 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -26,6 +26,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-shaper-impl.hh" #include "hb-ot-shape.hh" @@ -1146,3 +1150,6 @@ hb_ot_shape_glyphs_closure (hb_font_t *font, hb_shape_plan_destroy (shape_plan); } + + +#endif diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index 61ea8d0e5..2b23dee62 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -79,7 +79,9 @@ hb_shape_plan_key_t::init (bool copy, } this->shaper_func = nullptr; this->shaper_name = nullptr; +#ifndef HB_NO_OT_SHAPE this->ot.init (face, coords, num_coords); +#endif /* * Choose shaper. @@ -148,7 +150,9 @@ hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other) { return hb_segment_properties_equal (&this->props, &other->props) && this->user_features_match (other) && +#ifndef HB_NO_OT_SHAPE this->ot.equal (&other->ot) && +#endif this->shaper_func == other->shaper_func; } @@ -224,12 +228,16 @@ hb_shape_plan_create2 (hb_face_t *face, num_coords, shaper_list))) goto bail2; +#ifndef HB_NO_OT_SHAPE if (unlikely (!shape_plan->ot.init0 (face, &shape_plan->key))) goto bail3; +#endif return shape_plan; +#ifndef HB_NO_OT_SHAPE bail3: +#endif shape_plan->key.free (); bail2: free (shape_plan); @@ -281,7 +289,9 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) { if (!hb_object_destroy (shape_plan)) return; +#ifndef HB_NO_OT_SHAPE shape_plan->ot.fini (); +#endif shape_plan->key.free (); free (shape_plan); } diff --git a/src/hb-shape-plan.hh b/src/hb-shape-plan.hh index 3a057fd22..8e8d7632b 100644 --- a/src/hb-shape-plan.hh +++ b/src/hb-shape-plan.hh @@ -39,7 +39,9 @@ struct hb_shape_plan_key_t const hb_feature_t *user_features; unsigned int num_user_features; +#ifndef HB_NO_OT_SHAPE hb_ot_shape_plan_key_t ot; +#endif hb_shape_func_t *shaper_func; const char *shaper_name; @@ -65,7 +67,9 @@ struct hb_shape_plan_t hb_object_header_t header; hb_face_t *face_unsafe; /* We don't carry a reference to face. */ hb_shape_plan_key_t key; +#ifndef HB_NO_OT_SHAPE hb_ot_shape_plan_t ot; +#endif }; diff --git a/src/hb-shaper-list.hh b/src/hb-shaper-list.hh index 4108e7aab..c864af6ec 100644 --- a/src/hb-shaper-list.hh +++ b/src/hb-shaper-list.hh @@ -35,7 +35,9 @@ HB_SHAPER_IMPLEMENT (graphite2) #endif +#ifndef HB_NO_OT_SHAPE HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */ +#endif #ifdef HAVE_UNISCRIBE HB_SHAPER_IMPLEMENT (uniscribe) From ab40a2feecf53d2ef787b7785132bf57e5bdcff9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:25:02 -0700 Subject: [PATCH 084/138] [config] Enable HB_NO_OT_FONT in HB_NO_OT --- CONFIG.md | 4 ++-- src/hb-config.hh | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CONFIG.md b/CONFIG.md index ff55154ad..bf14a6df4 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -90,8 +90,8 @@ without loss of functionality by defining `HB_NO_OT_FONT`. Most HarfBuzz clients use it for the main shaper, called "ot". However, it is legitimate to want to compile HarfBuzz with only another backend, eg. -CoreText, for example for an iOS app. For that, you want `HB_NO_OT_SHAPE`, -or more generally `HB_NO_OT`. +CoreText, for example for an iOS app. For that, you want `HB_NO_OT_SHAPE`. +If you are going down that route, check if you want `HB_NO_OT`. This is very rarely what you need. Make sure you understand exactly what you are doing. diff --git a/src/hb-config.hh b/src/hb-config.hh index c6a408053..e364a6a90 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -122,6 +122,7 @@ #endif #ifdef HB_NO_OT +#define HB_NO_OT_FONT #define HB_NO_OT_SHAPE #endif From bb4bbe617d3878ca7e5e359ada493c68ec7f0a90 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:29:58 -0700 Subject: [PATCH 085/138] [config] Add HB_NO_OT_LAYOUT Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-ot-layout.cc | 7 +++++++ src/hb-ot-map.cc | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/src/hb-config.hh b/src/hb-config.hh index e364a6a90..1faeca240 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -123,6 +123,7 @@ #ifdef HB_NO_OT #define HB_NO_OT_FONT +#define HB_NO_OT_LAYOUT #define HB_NO_OT_SHAPE #endif diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 10b9ba092..846c2b00a 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -28,6 +28,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_LAYOUT + #include "hb-open-type.hh" #include "hb-ot-layout.hh" #include "hb-ot-face.hh" @@ -2000,3 +2004,6 @@ hb_ot_layout_get_baseline (hb_font_t *font, hb_position_t *coord /* OUT. May be NULL. */); #endif + + +#endif diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 92d70bb41..b0bc4726b 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -26,6 +26,10 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + #include "hb-ot-map.hh" #include "hb-ot-shape.hh" #include "hb-ot-layout.hh" @@ -332,3 +336,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, } } } + + +#endif From 12092a46d8826eec5dcf69e7817921380e4bc507 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:31:01 -0700 Subject: [PATCH 086/138] [config] Rename HB_NO_SHAPE_AAT to HB_NO_AAT_SHAPE --- src/hb-aat-map.cc | 2 +- src/hb-config.hh | 2 +- src/hb-ot-kern-table.hh | 14 +++++++------- src/hb-ot-layout.cc | 2 +- src/hb-ot-shape.cc | 36 ++++++++++++++++++------------------ src/hb-ot-shape.hh | 8 ++++---- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/hb-aat-map.cc b/src/hb-aat-map.cc index e16ecfe04..bc879359a 100644 --- a/src/hb-aat-map.cc +++ b/src/hb-aat-map.cc @@ -28,7 +28,7 @@ #include "hb.hh" -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE #include "hb-aat-map.hh" diff --git a/src/hb-config.hh b/src/hb-config.hh index 1faeca240..fc663d878 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -93,7 +93,7 @@ #ifdef HB_NO_AAT #define HB_NO_OT_NAME_LANGUAGE_AAT -#define HB_NO_SHAPE_AAT +#define HB_NO_AAT_SHAPE #endif #ifdef HB_NO_BITMAP diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh index ae2bcc92d..7dfb207b2 100644 --- a/src/hb-ot-kern-table.hh +++ b/src/hb-ot-kern-table.hh @@ -128,11 +128,11 @@ struct KernSubTable TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { case 0: return_trace (c->dispatch (u.format0)); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE case 1: return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward (ds)...) : c->default_return_value ()); #endif case 2: return_trace (c->dispatch (u.format2)); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE case 3: return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward (ds)...) : c->default_return_value ()); #endif default: return_trace (c->default_return_value ()); @@ -282,7 +282,7 @@ struct kern { switch (get_type ()) { case 0: return u.ot.has_state_machine (); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE case 1: return u.aat.has_state_machine (); #endif default:return false; @@ -293,7 +293,7 @@ struct kern { switch (get_type ()) { case 0: return u.ot.has_cross_stream (); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE case 1: return u.aat.has_cross_stream (); #endif default:return false; @@ -304,7 +304,7 @@ struct kern { switch (get_type ()) { case 0: return u.ot.get_h_kerning (left, right); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE case 1: return u.aat.get_h_kerning (left, right); #endif default:return 0; @@ -321,7 +321,7 @@ struct kern TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { case 0: return_trace (c->dispatch (u.ot, hb_forward (ds)...)); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE case 1: return_trace (c->dispatch (u.aat, hb_forward (ds)...)); #endif default: return_trace (c->default_return_value ()); @@ -340,7 +340,7 @@ struct kern HBUINT32 version32; HBUINT16 major; KernOT ot; -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE KernAAT aat; #endif } u; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 846c2b00a..63ccab885 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -392,7 +392,7 @@ OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED, return false; #endif -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE /* Mac OS X prefers morx over GSUB. It also ships with various Indic fonts, * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken * GSUB/GPOS tables. Some have GSUB with zero scripts, those are ignored by diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 499b1be4b..007fae8fa 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -59,7 +59,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, const hb_feature_t *user_features, unsigned int num_user_features); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE static inline bool _hb_apply_morx (hb_face_t *face) { @@ -82,7 +82,7 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac props (*props), map (face, props), aat_map (face, props) -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE , apply_morx (_hb_apply_morx (face)) #endif { @@ -102,7 +102,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.props = props; plan.shaper = shaper; map.compile (plan.map, key); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE if (apply_morx) aat_map.compile (plan.aat_map); #endif @@ -121,7 +121,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.kern_mask = plan.map.get_mask (kern_tag); plan.requested_kerning = !!plan.kern_mask; #endif -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k')); plan.requested_tracking = !!plan.trak_mask; #endif @@ -141,7 +141,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, * Decide who does substitutions. GSUB, morx, or fallback. */ -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE plan.apply_morx = apply_morx; #endif @@ -151,13 +151,13 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, if (0) ; -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE else if (hb_options ().aat && hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; #endif else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face)) plan.apply_gpos = true; -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE else if (hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; #endif @@ -165,7 +165,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, if (!plan.apply_kerx && !has_gpos_kern) { /* Apparently Apple applies kerx if GPOS kern was not applied. */ -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE if (hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; else @@ -196,7 +196,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing && script_fallback_mark_positioning; -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE /* Currently we always apply trak. */ plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face); #endif @@ -207,7 +207,7 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face, const hb_shape_plan_key_t *key) { map.init (); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE aat_map.init (); #endif @@ -237,7 +237,7 @@ hb_ot_shape_plan_t::fini () shaper->data_destroy (const_cast (data)); map.fini (); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE aat_map.fini (); #endif } @@ -246,7 +246,7 @@ void hb_ot_shape_plan_t::substitute (hb_font_t *font, hb_buffer_t *buffer) const { -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE if (unlikely (apply_morx)) hb_aat_layout_substitute (this, font, buffer); else @@ -260,7 +260,7 @@ hb_ot_shape_plan_t::position (hb_font_t *font, { if (this->apply_gpos) map.position (this, font, buffer); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE else if (this->apply_kerx) hb_aat_layout_position (this, font, buffer); #endif @@ -271,7 +271,7 @@ hb_ot_shape_plan_t::position (hb_font_t *font, else _hb_ot_shape_fallback_kern (this, font, buffer); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE if (this->apply_trak) hb_aat_layout_track (this, font, buffer); #endif @@ -336,7 +336,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, /* Random! */ map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE /* Tracking. We enable dummy feature here just to allow disabling * AAT 'trak' table using features. * https://github.com/harfbuzz/harfbuzz/issues/1303 */ @@ -374,7 +374,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, feature->value); } -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE if (planner->apply_morx) { hb_aat_map_builder_t *aat_map = &planner->aat_map; @@ -823,7 +823,7 @@ static inline void hb_ot_substitute_post (const hb_ot_shape_context_t *c) { hb_ot_hide_default_ignorables (c->buffer, c->font); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE if (c->plan->apply_morx) hb_aat_layout_remove_deleted_glyphs (c->buffer); #endif @@ -960,7 +960,7 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) /* Finish off. Has to follow a certain order. */ hb_ot_layout_position_finish_advances (c->font, c->buffer); hb_ot_zero_width_default_ignorables (c->buffer); -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE if (c->plan->apply_morx) hb_aat_layout_zero_width_deleted_glyphs (c->buffer); #endif diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index fec8983c6..2cde73d85 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -78,7 +78,7 @@ struct hb_ot_shape_plan_t #else static constexpr hb_mask_t kern_mask = 0; #endif -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE hb_mask_t trak_mask; #else static constexpr hb_mask_t trak_mask = 0; @@ -89,7 +89,7 @@ struct hb_ot_shape_plan_t #else static constexpr bool requested_kerning = false; #endif -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE bool requested_tracking : 1; #else static constexpr bool requested_tracking = false; @@ -111,7 +111,7 @@ struct hb_ot_shape_plan_t #else static constexpr bool apply_kern = false; #endif -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE bool apply_kerx : 1; bool apply_morx : 1; bool apply_trak : 1; @@ -149,7 +149,7 @@ struct hb_ot_shape_planner_t hb_segment_properties_t props; hb_ot_map_builder_t map; hb_aat_map_builder_t aat_map; -#ifndef HB_NO_SHAPE_AAT +#ifndef HB_NO_AAT_SHAPE bool apply_morx : 1; #else static constexpr bool apply_morx = false; From b0fd16eec62dea29d984bab879064ae9d91afdfc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:31:51 -0700 Subject: [PATCH 087/138] [config] Add dependency --- src/hb-config.hh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hb-config.hh b/src/hb-config.hh index fc663d878..38a685e43 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -127,6 +127,10 @@ #define HB_NO_OT_SHAPE #endif +#ifdef HB_NO_OT_SHAPE +#define HB_NO_AAT_SHAPE +#endif + #ifdef HB_NO_OT_SHAPE_FALLBACK #define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK #define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK From 2804790bceb9398cc9b668ca63f5aa9ffe29beeb Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:38:14 -0700 Subject: [PATCH 088/138] [config] Add dependency --- src/hb-ot-shape.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 007fae8fa..c659f28ca 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -30,6 +30,10 @@ #ifndef HB_NO_OT_SHAPE +#ifdef HB_NO_OT_LAYOUT +#error "Cannot compile 'ot' shaper with HB_NO_OT_LAYOUT." +#endif + #include "hb-shaper-impl.hh" #include "hb-ot-shape.hh" From 7dcf8e126ecf52c67f59745e04d21df68b1a6992 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:44:10 -0700 Subject: [PATCH 089/138] [config] Fix build with HB_NO_OT_LAYOUT --- src/hb-ot-face-table-list.hh | 2 ++ src/hb-ot-layout-gpos-table.hh | 3 ++- src/hb-ot-layout-gsub-table.hh | 5 +++-- src/hb-ot-layout-gsubgpos.hh | 8 +++++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/hb-ot-face-table-list.hh b/src/hb-ot-face-table-list.hh index d07f53c2b..ac7052751 100644 --- a/src/hb-ot-face-table-list.hh +++ b/src/hb-ot-face-table-list.hh @@ -88,11 +88,13 @@ HB_OT_TABLE (OT, kern) #endif /* OpenType shaping. */ +#ifndef HB_NO_OT_LAYOUT HB_OT_ACCELERATOR (OT, GDEF) HB_OT_ACCELERATOR (OT, GSUB) HB_OT_ACCELERATOR (OT, GPOS) //HB_OT_TABLE (OT, BASE) //HB_OT_TABLE (OT, JSTF) +#endif /* AAT shaping. */ #ifndef HB_NO_AAT diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index d371c4b5f..f4be42c1d 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1737,13 +1737,13 @@ struct GPOS_accelerator_t : GPOS::accelerator_t {}; /* Out-of-class implementation for methods recursing */ +#ifndef HB_NO_OT_LAYOUT template /*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) { const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index); return l.dispatch (c); } - /*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index) { const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index); @@ -1756,6 +1756,7 @@ template c->set_lookup_props (saved_lookup_props); return ret; } +#endif } /* namespace OT */ diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index f532f9dff..a6cc1a230 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -1409,6 +1409,7 @@ struct GSUB_accelerator_t : GSUB::accelerator_t {}; /* Out-of-class implementation for methods recursing */ +#ifndef HB_NO_OT_LAYOUT /*static*/ inline bool ExtensionSubst::is_reverse () const { unsigned int type = get_type (); @@ -1416,14 +1417,12 @@ struct GSUB_accelerator_t : GSUB::accelerator_t {}; return CastR (get_subtable()).is_reverse (); return SubstLookup::lookup_type_is_reverse (type); } - template /*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) { const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); return l.dispatch (c); } - /*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index) { const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); @@ -1436,6 +1435,8 @@ template c->set_lookup_props (saved_lookup_props); return ret; } +#endif + } /* namespace OT */ diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 9a82a4d67..c6e6ac9cb 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -483,7 +483,13 @@ struct hb_ot_apply_context_t : iter_input (), iter_context (), font (font_), face (font->face), buffer (buffer_), recurse_func (nullptr), - gdef (*face->table.GDEF->table), + gdef ( +#ifndef HB_NO_OT_LAYOUT + *face->table.GDEF->table +#else + Null(GDEF) +#endif + ), var_store (gdef.get_var_store ()), direction (buffer_->props.direction), lookup_mask (1), From 8fe15485cbc2f56adb29d4d5f0c3957869bd0e1a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:49:42 -0700 Subject: [PATCH 090/138] [config] Add HB_NO_OT_TAG Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-ot-layout.cc | 4 ++++ src/hb-ot-tag.cc | 5 +++++ src/hb-uniscribe.cc | 4 ++++ 4 files changed, 14 insertions(+) diff --git a/src/hb-config.hh b/src/hb-config.hh index 38a685e43..adf2b3348 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -124,6 +124,7 @@ #ifdef HB_NO_OT #define HB_NO_OT_FONT #define HB_NO_OT_LAYOUT +#define HB_NO_OT_TAG #define HB_NO_OT_SHAPE #endif diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 63ccab885..98cd10923 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -32,6 +32,10 @@ #ifndef HB_NO_OT_LAYOUT +#ifdef HB_NO_OT_TAG +#error "Cannot compile hb-ot-layout.cc with HB_NO_OT_TAG." +#endif + #include "hb-open-type.hh" #include "hb-ot-layout.hh" #include "hb-ot-face.hh" diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index e63045894..8ad917ae7 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -28,6 +28,8 @@ #include "hb.hh" +#ifndef HB_NO_OT_TAG + /* hb_script_t */ @@ -548,3 +550,6 @@ main () } #endif + + +#endif diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index 88f429401..5c7ff8744 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -28,6 +28,10 @@ #ifdef HAVE_UNISCRIBE +#ifdef HB_NO_OT_TAG +#error "Cannot compile 'uniscribe' shaper with HB_NO_OT_TAG." +#endif + #include "hb-shaper-impl.hh" #include From 9d5b5348c7ca1e39faa9e197fdebfb8f5d3aeece Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 13:58:40 -0700 Subject: [PATCH 091/138] [config] Add HB_NO_SHAPER Don't know who would want when why. But makes sense to have. --- src/hb-shaper-list.hh | 6 ++++++ src/hb-shaper.cc | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/hb-shaper-list.hh b/src/hb-shaper-list.hh index c864af6ec..0d63933a7 100644 --- a/src/hb-shaper-list.hh +++ b/src/hb-shaper-list.hh @@ -28,6 +28,9 @@ #define HB_SHAPER_LIST_HH #endif /* HB_SHAPER_LIST_HH */ /* Dummy header guards */ +#ifndef HB_NO_SHAPER + + /* v--- Add new shapers in the right place here. */ #ifdef HAVE_GRAPHITE2 @@ -52,3 +55,6 @@ HB_SHAPER_IMPLEMENT (coretext) #ifndef HB_NO_FALLBACK_SHAPE HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */ #endif + + +#endif diff --git a/src/hb-shaper.cc b/src/hb-shaper.cc index 4858a6a9c..0ea68ad1f 100644 --- a/src/hb-shaper.cc +++ b/src/hb-shaper.cc @@ -34,7 +34,9 @@ static const hb_shaper_entry_t all_shapers[] = { #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT }; +#ifndef HB_NO_SHAPER static_assert (0 != ARRAY_LENGTH_CONST (all_shapers), "No shaper enabled."); +#endif #if HB_USE_ATEXIT static void free_static_shapers (); From 5130c90ac0173c542b550049c93738ab5de84bb9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 14:29:39 -0700 Subject: [PATCH 092/138] [config] Add HB_NO_EMOJI Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-config.hh | 1 + src/hb-ot-shape.cc | 2 ++ src/hb-unicode.cc | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/hb-config.hh b/src/hb-config.hh index adf2b3348..6a95501d7 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -58,6 +58,7 @@ #define HB_NO_BITMAP #define HB_NO_CFF #define HB_NO_COLOR +#define HB_NO_EMOJI #define HB_NO_FACE_COLLECT_UNICODES #define HB_NO_GETENV #define HB_NO_HINTING diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index c659f28ca..7ae0925a0 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -479,6 +479,7 @@ hb_set_unicode_props (hb_buffer_t *buffer) { _hb_glyph_info_set_continuation (&info[i]); } +#ifndef HB_NO_EMOJI else if (unlikely (_hb_glyph_info_is_zwj (&info[i]))) { _hb_glyph_info_set_continuation (&info[i]); @@ -490,6 +491,7 @@ hb_set_unicode_props (hb_buffer_t *buffer) _hb_glyph_info_set_continuation (&info[i]); } } +#endif /* Or part of the Other_Grapheme_Extend that is not marks. * As of Unicode 11 that is just: * diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index 9ec2d8563..eb9451c60 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -570,6 +570,7 @@ _hb_modified_combining_class[256] = /* * Emoji */ +#ifndef HB_NO_EMOJI #include "hb-unicode-emoji-table.hh" @@ -581,3 +582,4 @@ _hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp) sizeof (hb_unicode_range_t), hb_unicode_range_t::cmp); } +#endif From 1cdd0fa60d9a6aaddc20e646d294d642e2db9be4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 14:49:15 -0700 Subject: [PATCH 093/138] [emoji] Port generator to packtab --- src/gen-emoji-table.py | 18 +++-- src/hb-unicode-emoji-table.hh | 126 +++++++++++++--------------------- src/hb-unicode.cc | 5 +- 3 files changed, 60 insertions(+), 89 deletions(-) diff --git a/src/gen-emoji-table.py b/src/gen-emoji-table.py index 9afe747dd..22da22811 100755 --- a/src/gen-emoji-table.py +++ b/src/gen-emoji-table.py @@ -4,6 +4,7 @@ from __future__ import print_function, division, absolute_import import sys import os.path from collections import OrderedDict +import packTab if len (sys.argv) != 2: print("usage: ./gen-emoji-table.py emoji-data.txt", file=sys.stderr) @@ -54,12 +55,17 @@ print () for typ,s in ranges.items(): if typ != "Extended_Pictographic": continue - print() - print("static const struct hb_unicode_range_t _hb_unicode_emoji_%s_table[] =" % typ) - print("{") - for pair in sorted(s): - print(" {0x%04X, 0x%04X}," % pair) - print("};") + + arr = dict() + for start,end in s: + for i in range(start,end): + arr[i] = 1 + + sol = packTab.pack_table(arr, 0, compression=3) + code = packTab.Code('_hb_emoji') + sol.genCode(code, 'is_'+typ) + code.print_c(linkage='static inline') + print() print () print ("#endif /* HB_UNICODE_EMOJI_TABLE_HH */") diff --git a/src/hb-unicode-emoji-table.hh b/src/hb-unicode-emoji-table.hh index aa297fcf9..1ff79c977 100644 --- a/src/hb-unicode-emoji-table.hh +++ b/src/hb-unicode-emoji-table.hh @@ -23,88 +23,56 @@ #include "hb-unicode.hh" - -static const struct hb_unicode_range_t _hb_unicode_emoji_Extended_Pictographic_table[] = +static const uint8_t +_hb_emoji_u8[448] = { - {0x00A9, 0x00A9}, - {0x00AE, 0x00AE}, - {0x203C, 0x203C}, - {0x2049, 0x2049}, - {0x2122, 0x2122}, - {0x2139, 0x2139}, - {0x2194, 0x2199}, - {0x21A9, 0x21AA}, - {0x231A, 0x231B}, - {0x2328, 0x2328}, - {0x2388, 0x2388}, - {0x23CF, 0x23CF}, - {0x23E9, 0x23F3}, - {0x23F8, 0x23FA}, - {0x24C2, 0x24C2}, - {0x25AA, 0x25AB}, - {0x25B6, 0x25B6}, - {0x25C0, 0x25C0}, - {0x25FB, 0x25FE}, - {0x2600, 0x2605}, - {0x2607, 0x2612}, - {0x2614, 0x2685}, - {0x2690, 0x2705}, - {0x2708, 0x2712}, - {0x2714, 0x2714}, - {0x2716, 0x2716}, - {0x271D, 0x271D}, - {0x2721, 0x2721}, - {0x2728, 0x2728}, - {0x2733, 0x2734}, - {0x2744, 0x2744}, - {0x2747, 0x2747}, - {0x274C, 0x274C}, - {0x274E, 0x274E}, - {0x2753, 0x2755}, - {0x2757, 0x2757}, - {0x2763, 0x2767}, - {0x2795, 0x2797}, - {0x27A1, 0x27A1}, - {0x27B0, 0x27B0}, - {0x27BF, 0x27BF}, - {0x2934, 0x2935}, - {0x2B05, 0x2B07}, - {0x2B1B, 0x2B1C}, - {0x2B50, 0x2B50}, - {0x2B55, 0x2B55}, - {0x3030, 0x3030}, - {0x303D, 0x303D}, - {0x3297, 0x3297}, - {0x3299, 0x3299}, - {0x1F000, 0x1F0FF}, - {0x1F10D, 0x1F10F}, - {0x1F12F, 0x1F12F}, - {0x1F16C, 0x1F171}, - {0x1F17E, 0x1F17F}, - {0x1F18E, 0x1F18E}, - {0x1F191, 0x1F19A}, - {0x1F1AD, 0x1F1E5}, - {0x1F201, 0x1F20F}, - {0x1F21A, 0x1F21A}, - {0x1F22F, 0x1F22F}, - {0x1F232, 0x1F23A}, - {0x1F23C, 0x1F23F}, - {0x1F249, 0x1F3FA}, - {0x1F400, 0x1F53D}, - {0x1F546, 0x1F64F}, - {0x1F680, 0x1F6FF}, - {0x1F774, 0x1F77F}, - {0x1F7D5, 0x1F7FF}, - {0x1F80C, 0x1F80F}, - {0x1F848, 0x1F84F}, - {0x1F85A, 0x1F85F}, - {0x1F888, 0x1F88F}, - {0x1F8AE, 0x1F8FF}, - {0x1F90C, 0x1F93A}, - {0x1F93C, 0x1F945}, - {0x1F947, 0x1FFFD}, + 0, 0, 0, 0, 33, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,118, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 7, 9, 10, 11, 0, + 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, + 7, 7, 7, 14, 15, 16, 17, 18, 19, 20, 7, 7, 7, 7, 7, 21, + 7, 7, 7, 7, 22, 23, 7, 7, 7, 24, 7, 14, 0, 25, 0, 26, + 27, 28, 29, 14, 30, 31, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 22, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 1, 0, 2, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 7, 3, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, + 159,255,243,255,255,255,255,255,255,255,255,255,255,255,255,255, + 31, 0,255,255,255,255,255,255, 31,255, 3, 0, 0, 0, 8, 0, + 0, 0, 24, 0,120, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16, 0, 96, 0, 0, 8, 0, 0, 0, 0, + 255,255,255,255,255,255,255,127, 0, 96, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,240, 1, 64, 0, 0,254, 3, 0,224,255,255, + 255,255,255,255, 31, 0, 0, 0,254,127, 0, 0, 0, 0,252,115, + 0,254,255,255,255,255,255,255,255,255,255,255,255,255,255, 3, + 255,255,255,255,255,255,255, 31,192,255,255,255,255,255,255,255, + 255,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,127, + 0, 0,224,255,255,255,255,127, 0,112, 0, 0, 0, 0, 0, 0, + 0,127, 0,124, 0, 0, 0, 0, 0,127, 0, 0, 0,192,255,255, + 0,240,255,255,255,255,255,243,159,255,255,255,255,255,255,255, }; +static inline unsigned +_hb_emoji_b4 (const uint8_t* a, unsigned i) +{ + return (a[i>>1]>>((i&1u)<<2))&15u; +} +static inline unsigned +_hb_emoji_b1 (const uint8_t* a, unsigned i) +{ + return (a[i>>3]>>((i&7u)<<0))&1u; +} +static inline uint_fast8_t +_hb_emoji_is_Extended_Pictographic (unsigned u) +{ + return u<131069u?_hb_emoji_b1(192+_hb_emoji_u8,((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>6>>4))<<4)+((u>>6)&15u))])<<6)+((u)&63u)):0; +} + + #endif /* HB_UNICODE_EMOJI_TABLE_HH */ /* == End of generated table == */ diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index eb9451c60..56f1c62c8 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -577,9 +577,6 @@ _hb_modified_combining_class[256] = bool _hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp) { - return hb_bsearch (&cp, _hb_unicode_emoji_Extended_Pictographic_table, - ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table), - sizeof (hb_unicode_range_t), - hb_unicode_range_t::cmp); + return _hb_emoji_is_Extended_Pictographic (cp); } #endif From 7298716a3cfbdabedd15960404623317a64db3ae Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 14:51:17 -0700 Subject: [PATCH 094/138] [config] Compile out modified combining-class if HB_NO_OT_SHAPE Part of https://github.com/harfbuzz/harfbuzz/issues/1652 --- src/hb-unicode.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index 56f1c62c8..be87759a9 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -453,6 +453,7 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, #endif +#ifndef HB_NO_OT_SHAPE /* See hb-unicode.hh for details. */ const uint8_t _hb_modified_combining_class[256] = @@ -565,6 +566,7 @@ _hb_modified_combining_class[256] = 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, /* HB_UNICODE_COMBINING_CLASS_INVALID */ }; +#endif /* From cd65305b059e7495f4f993d25cfda4d88781589b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Jun 2019 14:57:48 -0700 Subject: [PATCH 095/138] [config] Don't disable emoji sequences in HB_TINY It makes sense to disable this code these if editing is not needed. However, this is also necessary to correctly display emoji sequences in right-to-left direction. For that reason, don't auto-disable it. --- src/hb-config.hh | 1 - src/hb-ot-shape.cc | 2 +- src/hb-unicode.cc | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hb-config.hh b/src/hb-config.hh index 6a95501d7..adf2b3348 100644 --- a/src/hb-config.hh +++ b/src/hb-config.hh @@ -58,7 +58,6 @@ #define HB_NO_BITMAP #define HB_NO_CFF #define HB_NO_COLOR -#define HB_NO_EMOJI #define HB_NO_FACE_COLLECT_UNICODES #define HB_NO_GETENV #define HB_NO_HINTING diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 7ae0925a0..c8bda2aad 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -479,7 +479,7 @@ hb_set_unicode_props (hb_buffer_t *buffer) { _hb_glyph_info_set_continuation (&info[i]); } -#ifndef HB_NO_EMOJI +#ifndef HB_NO_EMOJI_SEQUENCES else if (unlikely (_hb_glyph_info_is_zwj (&info[i]))) { _hb_glyph_info_set_continuation (&info[i]); diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index be87759a9..ed4fb7782 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -572,7 +572,7 @@ _hb_modified_combining_class[256] = /* * Emoji */ -#ifndef HB_NO_EMOJI +#ifndef HB_NO_EMOJI_SEQUENCES #include "hb-unicode-emoji-table.hh" From 01832fd16b605971466fc3b174cb932787ef4bfb Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Wed, 26 Jun 2019 15:58:38 -0700 Subject: [PATCH 096/138] alternate fix for https://crbug.com/971933 --- src/hb-cff-interp-cs-common.hh | 6 +++--- src/hb-cff1-interp-cs.hh | 2 +- src/hb-cff2-interp-cs.hh | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hb-cff-interp-cs-common.hh b/src/hb-cff-interp-cs-common.hh index 1cfbba603..cf9ce4dc3 100644 --- a/src/hb-cff-interp-cs-common.hh +++ b/src/hb-cff-interp-cs-common.hh @@ -62,9 +62,9 @@ struct call_stack_t : stack_t {}; template struct biased_subrs_t { - void init (const SUBRS &subrs_) + void init (const SUBRS *subrs_) { - subrs = &subrs_; + subrs = subrs_; unsigned int nSubrs = get_count (); if (nSubrs < 1240) bias = 107; @@ -118,7 +118,7 @@ struct point_t template struct cs_interp_env_t : interp_env_t { - void init (const byte_str_t &str, const SUBRS &globalSubrs_, const SUBRS &localSubrs_) + void init (const byte_str_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_) { interp_env_t::init (str); diff --git a/src/hb-cff1-interp-cs.hh b/src/hb-cff1-interp-cs.hh index cc528564c..1c8762c17 100644 --- a/src/hb-cff1-interp-cs.hh +++ b/src/hb-cff1-interp-cs.hh @@ -40,7 +40,7 @@ struct cff1_cs_interp_env_t : cs_interp_env_t template void init (const byte_str_t &str, ACC &acc, unsigned int fd) { - SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs); + SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs); processed_width = false; has_width = false; arg_start = 0; diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh index 1faf20831..a72100e1a 100644 --- a/src/hb-cff2-interp-cs.hh +++ b/src/hb-cff2-interp-cs.hh @@ -82,7 +82,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t void init (const byte_str_t &str, ACC &acc, unsigned int fd, const int *coords_=nullptr, unsigned int num_coords_=0) { - SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs); + SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs); coords = coords_; num_coords = num_coords_; From 8341c0b304ee3bb0b7d150bcfb42a8b9e6448687 Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Thu, 27 Jun 2019 08:43:31 -0700 Subject: [PATCH 097/138] add test case file --- ...se-minimized-harfbuzz_fuzzer-5093685255077888 | Bin 0 -> 1160 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5093685255077888 diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5093685255077888 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5093685255077888 new file mode 100644 index 0000000000000000000000000000000000000000..e65025e1655b04232a11c80171bf9ed351030984 GIT binary patch literal 1160 zcmZuxU1%It6h3!mchY31n{JZ^rTMv)6(lw>hN7Yco5ptAre@1-EqyY3yK}QU>F&&Q zX0kLdA{0bxgbE@)i3F?=Ldi?PN2w)N5C!qk(o$dYVEdra9Zbyn-P!g*?S(VveCM3| zoipd&nf&R~c}mmUq*H0~=u!U5wfBaJv{gtWcPd|`J=8^%e1?e3T=9*=-+Esgzz2xf zr}^S@;~!1;bi%d}FP+I3a{2{WWc-B3j&faiyN$CRxcY&^suY&-%J5m(8;}>OaG3Xv zFR=d*aJE_xFQ!+w{{-F-+*=nHJxZQ}Nxwo2N7QBV*v=~AH-XQ1ZVgnE0p<IddlnA z1+0^%yfD^jWY%>Y;fa3z6Xp54p}2If^)A~;eTh9H<;CnO_-G|5p?|}!pz;pwvZmgC zs;$|ZG{%mg`;=-*tuc^2d*`64+NbcuYln}puM)7@H4-ngvC=5(P%&*tyA8z&=Yb9f z(I-oEqB_p+p{?O$hiRHz3L%_|B*>uv)+C*vDd+-8s?a>u5b^(mKtpk9=CqF3&0$mDertPW zfGFkR(XlJJ`0)UJaOqZh(Hw%K)iR%os5|O3pN{6tY}A{f4#te-&#vFN-JG!8bMm+) zozM;!CS7mAw=30cnfX6XjTnIv05BPDX?E0STi%?ple4-E(y@@CW$^XigO) literal 0 HcmV?d00001 From d42264f151a61a4a77e5d5712e535fc6e2daf338 Mon Sep 17 00:00:00 2001 From: David Corbett Date: Wed, 26 Jun 2019 21:10:11 -0400 Subject: [PATCH 098/138] Test at least one character per Unicode version --- test/api/test-unicode.c | 142 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 4 deletions(-) diff --git a/test/api/test-unicode.c b/test/api/test-unicode.c index 0587c6e7f..ac34fcbb5 100644 --- a/test/api/test-unicode.c +++ b/test/api/test-unicode.c @@ -157,6 +157,27 @@ static const test_pair_t combining_class_tests_more[] = /* Unicode-6.0 character additions */ { 0x135D, 230 }, + /* Unicode-6.1 character additions */ + { 0xA674, 230 }, + + /* Unicode-7.0 character additions */ + { 0x1AB0, 230 }, + + /* Unicode-8.0 character additions */ + { 0xA69E, 230 }, + + /* Unicode-9.0 character additions */ + { 0x1E000, 230 }, + + /* Unicode-10.0 character additions */ + { 0x1DF6, 232 }, + + /* Unicode-11.0 character additions */ + { 0x07FD, 220 }, + + /* Unicode-12.0 character additions */ + { 0x0EBA, 9 }, + { 0x111111, 0 } }; @@ -204,6 +225,36 @@ static const test_pair_t general_category_tests_more[] = /* Unicode-6.0 character additions */ { 0x0620, HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER }, + /* Unicode-6.1 character additions */ + { 0x058F, HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL }, + + /* Unicode-6.2 character additions */ + { 0x20BA, HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL }, + + /* Unicode-6.3 character additions */ + { 0x061C, HB_UNICODE_GENERAL_CATEGORY_FORMAT }, + + /* Unicode-7.0 character additions */ + { 0x058D, HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL }, + + /* Unicode-8.0 character additions */ + { 0x08E3, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK }, + + /* Unicode-9.0 character additions */ + { 0x08D4, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK }, + + /* Unicode-10.0 character additions */ + { 0x09FD, HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION }, + + /* Unicode-11.0 character additions */ + { 0x0560, HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER }, + + /* Unicode-12.0 character additions */ + { 0x0C77, HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION }, + + /* Unicode-12.1 character additions */ + { 0x32FF, HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL }, + { 0x111111, HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED } }; @@ -242,7 +293,12 @@ static const test_pair_t mirroring_tests[] = }; static const test_pair_t mirroring_tests_more[] = { - /* No new mirroring characters have been encoded in recent Unicode versions. */ + /* Unicode-6.1 character additions */ + { 0x27CB, 0x27CD }, + + /* Unicode-11.0 character additions */ + { 0x2BFE, 0x221F }, + { 0x111111, 0x111111 } }; @@ -342,8 +398,10 @@ static const test_pair_t script_tests_more[] = /* Unicode-5.2 additions */ { 0x10B00, HB_SCRIPT_AVESTAN }, { 0xA6A0, HB_SCRIPT_BAMUM }, + { 0x1400, HB_SCRIPT_CANADIAN_ABORIGINAL }, { 0x13000, HB_SCRIPT_EGYPTIAN_HIEROGLYPHS }, { 0x10840, HB_SCRIPT_IMPERIAL_ARAMAIC }, + { 0x1CED, HB_SCRIPT_INHERITED }, { 0x10B60, HB_SCRIPT_INSCRIPTIONAL_PAHLAVI }, { 0x10B40, HB_SCRIPT_INSCRIPTIONAL_PARTHIAN }, { 0xA980, HB_SCRIPT_JAVANESE }, @@ -361,9 +419,85 @@ static const test_pair_t script_tests_more[] = { 0x11000, HB_SCRIPT_BRAHMI }, { 0x0840, HB_SCRIPT_MANDAIC }, - /* Unicode-5.2 character additions */ - { 0x1CED, HB_SCRIPT_INHERITED }, - { 0x1400, HB_SCRIPT_CANADIAN_ABORIGINAL }, + /* Unicode-6.1 additions */ + { 0x10980, HB_SCRIPT_MEROITIC_HIEROGLYPHS }, + { 0x109A0, HB_SCRIPT_MEROITIC_CURSIVE }, + { 0x110D0, HB_SCRIPT_SORA_SOMPENG }, + { 0x11100, HB_SCRIPT_CHAKMA }, + { 0x11180, HB_SCRIPT_SHARADA }, + { 0x11680, HB_SCRIPT_TAKRI }, + { 0x16F00, HB_SCRIPT_MIAO }, + + /* Unicode-6.2 additions */ + { 0x20BA, HB_SCRIPT_COMMON }, + + /* Unicode-6.3 additions */ + { 0x2066, HB_SCRIPT_COMMON }, + + /* Unicode-7.0 additions */ + { 0x10350, HB_SCRIPT_OLD_PERMIC }, + { 0x10500, HB_SCRIPT_ELBASAN }, + { 0x10530, HB_SCRIPT_CAUCASIAN_ALBANIAN }, + { 0x10600, HB_SCRIPT_LINEAR_A }, + { 0x10860, HB_SCRIPT_PALMYRENE }, + { 0x10880, HB_SCRIPT_NABATAEAN }, + { 0x10A80, HB_SCRIPT_OLD_NORTH_ARABIAN }, + { 0x10AC0, HB_SCRIPT_MANICHAEAN }, + { 0x10B80, HB_SCRIPT_PSALTER_PAHLAVI }, + { 0x11150, HB_SCRIPT_MAHAJANI }, + { 0x11200, HB_SCRIPT_KHOJKI }, + { 0x112B0, HB_SCRIPT_KHUDAWADI }, + { 0x11300, HB_SCRIPT_GRANTHA }, + { 0x11480, HB_SCRIPT_TIRHUTA }, + { 0x11580, HB_SCRIPT_SIDDHAM }, + { 0x11600, HB_SCRIPT_MODI }, + { 0x118A0, HB_SCRIPT_WARANG_CITI }, + { 0x11AC0, HB_SCRIPT_PAU_CIN_HAU }, + { 0x16A40, HB_SCRIPT_MRO }, + { 0x16AD0, HB_SCRIPT_BASSA_VAH }, + { 0x16B00, HB_SCRIPT_PAHAWH_HMONG }, + { 0x1BC00, HB_SCRIPT_DUPLOYAN }, + { 0x1E800, HB_SCRIPT_MENDE_KIKAKUI }, + + /* Unicode-8.0 additions */ + { 0x108E0, HB_SCRIPT_HATRAN }, + { 0x10C80, HB_SCRIPT_OLD_HUNGARIAN }, + { 0x11280, HB_SCRIPT_MULTANI }, + { 0x11700, HB_SCRIPT_AHOM }, + { 0x14400, HB_SCRIPT_ANATOLIAN_HIEROGLYPHS }, + { 0x1D800, HB_SCRIPT_SIGNWRITING }, + + /* Unicode-9.0 additions */ + { 0x104B0, HB_SCRIPT_OSAGE }, + { 0x11400, HB_SCRIPT_NEWA }, + { 0x11C00, HB_SCRIPT_BHAIKSUKI }, + { 0x11C70, HB_SCRIPT_MARCHEN }, + { 0x17000, HB_SCRIPT_TANGUT }, + { 0x1E900, HB_SCRIPT_ADLAM }, + + /* Unicode-10.0 additions */ + { 0x11A00, HB_SCRIPT_ZANABAZAR_SQUARE }, + { 0x11A50, HB_SCRIPT_SOYOMBO }, + { 0x11D00, HB_SCRIPT_MASARAM_GONDI }, + { 0x1B170, HB_SCRIPT_NUSHU }, + + /* Unicode-11.0 additions */ + { 0x10D00, HB_SCRIPT_HANIFI_ROHINGYA }, + { 0x10F00, HB_SCRIPT_OLD_SOGDIAN }, + { 0x10F30, HB_SCRIPT_SOGDIAN }, + { 0x11800, HB_SCRIPT_DOGRA }, + { 0x11D60, HB_SCRIPT_GUNJALA_GONDI }, + { 0x11EE0, HB_SCRIPT_MAKASAR }, + { 0x16E40, HB_SCRIPT_MEDEFAIDRIN }, + + /* Unicode-12.0 additions */ + { 0x10FE0, HB_SCRIPT_ELYMAIC }, + { 0x119A0, HB_SCRIPT_NANDINAGARI }, + { 0x1E100, HB_SCRIPT_NYIAKENG_PUACHUE_HMONG }, + { 0x1E2C0, HB_SCRIPT_WANCHO }, + + /* Unicode-12.1 additions */ + { 0x32FF, HB_SCRIPT_COMMON }, { 0x111111, HB_SCRIPT_UNKNOWN } }; From f53590971c5326dd15f4296764bfd1255ec0506a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 27 Jun 2019 13:42:51 -0700 Subject: [PATCH 099/138] [test] Make Unicode tests strict against internal UCD https://github.com/harfbuzz/harfbuzz/pull/1799 --- test/api/test-unicode.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/test/api/test-unicode.c b/test/api/test-unicode.c index ac34fcbb5..4376fd05f 100644 --- a/test/api/test-unicode.c +++ b/test/api/test-unicode.c @@ -547,7 +547,7 @@ static const property_t properties[] = #undef PROPERTY static void -test_unicode_properties (gconstpointer user_data) +test_unicode_properties (gconstpointer user_data, hb_bool_t lenient) { hb_unicode_funcs_t *uf = (hb_unicode_funcs_t *) user_data; unsigned int i, j; @@ -571,16 +571,30 @@ test_unicode_properties (gconstpointer user_data) tests = p->tests_more; for (j = 0; j < p->num_tests_more; j++) { g_test_message ("Test %s more #%d: U+%04X", p->name, j, tests[j].unicode); - if (p->getter (uf, tests[j].unicode) != tests[j].value) { - g_test_message ("Soft fail: Received %x, expected %x", p->getter (uf, tests[j].unicode), tests[j].value); - failed = TRUE; + if (lenient) { + if (p->getter (uf, tests[j].unicode) != tests[j].value) { + g_test_message ("Soft fail: Received %x, expected %x", p->getter (uf, tests[j].unicode), tests[j].value); + failed = TRUE; + } } + else + g_assert_cmphex (p->getter (uf, tests[j].unicode), ==, tests[j].value); } } if (failed) g_test_message ("Some property tests failed. You probably have an old version of one of the libraries used."); } +static void +test_unicode_properties_lenient (gconstpointer user_data) +{ + test_unicode_properties (user_data, TRUE); +} +static void +test_unicode_properties_strict (gconstpointer user_data) +{ + test_unicode_properties (user_data, FALSE); +} static hb_codepoint_t default_value (hb_codepoint_t _default_value, hb_codepoint_t unicode) @@ -663,7 +677,7 @@ test_unicode_chainup (void) g_assert (!hb_unicode_funcs_is_immutable (uf2)); hb_unicode_funcs_make_immutable (uf2); - test_unicode_properties (uf2); + test_unicode_properties_strict (uf2); hb_unicode_funcs_destroy (uf2); @@ -934,16 +948,16 @@ main (int argc, char **argv) hb_test_add (test_unicode_properties_nil); hb_test_add (test_unicode_properties_empty); - hb_test_add_data_flavor (hb_unicode_funcs_get_default (), "default", test_unicode_properties); + hb_test_add_data_flavor (hb_unicode_funcs_get_default (), "default", test_unicode_properties_strict); hb_test_add_data_flavor (hb_unicode_funcs_get_default (), "default", test_unicode_normalization); hb_test_add_data_flavor ((gconstpointer) script_roundtrip_default, "default", test_unicode_script_roundtrip); #ifdef HAVE_GLIB - hb_test_add_data_flavor (hb_glib_get_unicode_funcs (), "glib", test_unicode_properties); + hb_test_add_data_flavor (hb_glib_get_unicode_funcs (), "glib", test_unicode_properties_lenient); hb_test_add_data_flavor (hb_glib_get_unicode_funcs (), "glib", test_unicode_normalization); hb_test_add_data_flavor ((gconstpointer) script_roundtrip_glib, "glib", test_unicode_script_roundtrip); #endif #ifdef HAVE_ICU - hb_test_add_data_flavor (hb_icu_get_unicode_funcs (), "icu", test_unicode_properties); + hb_test_add_data_flavor (hb_icu_get_unicode_funcs (), "icu", test_unicode_properties_lenient); hb_test_add_data_flavor (hb_icu_get_unicode_funcs (), "icu", test_unicode_normalization); hb_test_add_data_flavor ((gconstpointer) script_roundtrip_icu, "icu", test_unicode_script_roundtrip); #endif From 8d36ef50c8712be476572514d73b7bddf43e5951 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 27 Jun 2019 14:48:10 -0700 Subject: [PATCH 100/138] [config] Add links --- CONFIG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CONFIG.md b/CONFIG.md index bf14a6df4..46971b0f2 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -40,7 +40,11 @@ Finally, if you are making a static library build or otherwise linking the library into your app, make sure your linker removes unused functions. This can be tricky and differ from environment to environment, but you definitely want to make sure this happens. Otherwise, every unused public function will -be adding unneeded bytes to your binary. +be adding unneeded bytes to your binary. The following pointers might come +handy: + + * https://lwn.net/Articles/741494/ (all of the four-part series) + * https://elinux.org/images/2/2d/ELC2010-gc-sections_Denys_Vlasenko.pdf Combining the above three build options should already shrink your library a lot. The rest of this file shows you ways to shrink the library even further at the From 9a7b7bd9fc5bde7796ffdd997ee65cb33cbf6b29 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 28 Jun 2019 22:53:51 +0430 Subject: [PATCH 101/138] style fix for pylint complain --- src/gen-emoji-table.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/gen-emoji-table.py b/src/gen-emoji-table.py index 22da22811..49770d4fd 100755 --- a/src/gen-emoji-table.py +++ b/src/gen-emoji-table.py @@ -53,19 +53,19 @@ print () print ('#include "hb-unicode.hh"') print () -for typ,s in ranges.items(): +for typ, s in ranges.items(): if typ != "Extended_Pictographic": continue - arr = dict() - for start,end in s: - for i in range(start,end): - arr[i] = 1 + arr = dict() + for start,end in s: + for i in range(start,end): + arr[i] = 1 - sol = packTab.pack_table(arr, 0, compression=3) - code = packTab.Code('_hb_emoji') - sol.genCode(code, 'is_'+typ) - code.print_c(linkage='static inline') - print() + sol = packTab.pack_table(arr, 0, compression=3) + code = packTab.Code('_hb_emoji') + sol.genCode(code, 'is_'+typ) + code.print_c(linkage='static inline') + print() print () print ("#endif /* HB_UNICODE_EMOJI_TABLE_HH */") From 9db7ce73d7ac6566837cdd70d38c45f3aefd7769 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 28 Jun 2019 23:11:52 +0430 Subject: [PATCH 102/138] minor style improve in hb-cff-interp-common.hh --- src/hb-cff-interp-common.hh | 91 ++++++++++++------------------------- 1 file changed, 30 insertions(+), 61 deletions(-) diff --git a/src/hb-cff-interp-common.hh b/src/hb-cff-interp-common.hh index c5157c783..948772b0e 100644 --- a/src/hb-cff-interp-common.hh +++ b/src/hb-cff-interp-common.hh @@ -226,7 +226,7 @@ struct number_t void set_fixed (int32_t v) { value = v / 65536.0; } int32_t to_fixed () const { return (int32_t) (value * 65536.0); } - void set_real (double v) { value = v; } + void set_real (double v) { value = v; } double to_real () const { return value; } int ceil () const { return (int) ::ceil (value); } @@ -235,17 +235,10 @@ struct number_t bool in_int_range () const { return ((double) (int16_t) to_int () == value); } - bool operator > (const number_t &n) const - { return value > n.to_real (); } - - bool operator < (const number_t &n) const - { return n > *this; } - - bool operator >= (const number_t &n) const - { return !(*this < n); } - - bool operator <= (const number_t &n) const - { return !(*this > n); } + bool operator > (const number_t &n) const { return value > n.to_real (); } + bool operator < (const number_t &n) const { return n > *this; } + bool operator >= (const number_t &n) const { return !(*this < n); } + bool operator <= (const number_t &n) const { return !(*this > n); } const number_t &operator += (const number_t &n) { @@ -255,7 +248,7 @@ struct number_t } protected: - double value; + double value; }; /* byte string */ @@ -308,7 +301,7 @@ struct byte_str_t : hb_ubytes_t : hb_ubytes_t (s, l) {} byte_str_t (const hb_ubytes_t &ub) /* conversion from hb_ubytes_t */ : hb_ubytes_t (ub) {} - + /* sub-string */ byte_str_t sub_str (unsigned int offset, unsigned int len_) const { return byte_str_t (hb_ubytes_t::sub_array (offset, len_)); } @@ -320,8 +313,7 @@ struct byte_str_t : hb_ubytes_t /* A byte string associated with the current offset and an error condition */ struct byte_str_ref_t { - byte_str_ref_t () - { init (); } + byte_str_ref_t () { init (); } void init () { @@ -343,13 +335,12 @@ struct byte_str_ref_t } const unsigned char& operator [] (int i) { - if (unlikely ((unsigned int)(offset + i) >= str.length)) + if (unlikely ((unsigned int) (offset + i) >= str.length)) { set_error (); - return Null(unsigned char); + return Null (unsigned char); } - else - return str[offset + i]; + return str[offset + i]; } /* Conversion to byte_str_t */ @@ -359,9 +350,7 @@ struct byte_str_ref_t { return str.sub_str (offset_, len_); } bool avail (unsigned int count=1) const - { - return (!in_error () && str.check_limit (offset, count)); - } + { return (!in_error () && str.check_limit (offset, count)); } void inc (unsigned int count=1) { if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length))) @@ -400,11 +389,7 @@ struct stack_t for (unsigned int i = 0; i < elements.length; i++) elements[i].init (); } - - void fini () - { - elements.fini_deep (); - } + void fini () { elements.fini_deep (); } ELEM& operator [] (unsigned int i) { @@ -419,7 +404,6 @@ struct stack_t else set_error (); } - ELEM &push () { if (likely (count < elements.length)) @@ -441,7 +425,6 @@ struct stack_t return Crap(ELEM); } } - void pop (unsigned int n) { if (likely (count >= n)) @@ -452,13 +435,12 @@ struct stack_t const ELEM& peek () { - if (likely (count > 0)) - return elements[count-1]; - else + if (unlikely (count < 0)) { set_error (); return Null(ELEM); } + return elements[count - 1]; } void unpop () @@ -475,7 +457,7 @@ struct stack_t void set_error () { error = true; } unsigned int get_count () const { return count; } - bool is_empty () const { return count == 0; } + bool is_empty () const { return !count; } static constexpr unsigned kSizeLimit = LIMIT; @@ -519,7 +501,7 @@ struct arg_stack_t : stack_t i = 0; S::set_error (); } - return (unsigned)i; + return (unsigned) i; } void push_longint_from_substr (byte_str_ref_t& str_ref) @@ -538,9 +520,7 @@ struct arg_stack_t : stack_t } hb_array_t get_subarray (unsigned int start) const - { - return S::elements.sub_array (start); - } + { return S::elements.sub_array (start); } private: typedef stack_t S; @@ -605,7 +585,7 @@ struct parsed_values_t } unsigned get_count () const { return values.length; } - const VAL &get_value (unsigned int i) const { return values[i]; } + const VAL &get_value (unsigned int i) const { return values[i]; } const VAL &operator [] (unsigned int i) const { return get_value (i); } unsigned int opStart; @@ -644,30 +624,19 @@ struct interp_env_t return op; } - const ARG& eval_arg (unsigned int i) - { - return argStack[i]; - } + const ARG& eval_arg (unsigned int i) { return argStack[i]; } - ARG& pop_arg () - { - return argStack.pop (); - } + ARG& pop_arg () { return argStack.pop (); } + void pop_n_args (unsigned int n) { argStack.pop (n); } - void pop_n_args (unsigned int n) - { - argStack.pop (n); - } + void clear_args () { pop_n_args (argStack.get_count ()); } - void clear_args () - { - pop_n_args (argStack.get_count ()); - } - - byte_str_ref_t str_ref; - arg_stack_t argStack; + byte_str_ref_t + str_ref; + arg_stack_t + argStack; protected: - bool error; + bool error; }; typedef interp_env_t<> num_interp_env_t; @@ -711,8 +680,8 @@ struct opset_t }; template -struct interpreter_t { - +struct interpreter_t +{ ~interpreter_t() { fini (); } void fini () { env.fini (); } From ddd29e5594ccc9d0281e6da7373a1f115f6f6f3a Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 28 Jun 2019 23:44:14 +0430 Subject: [PATCH 103/138] minor, reuse StructAtOffset logic in StructAtOffsetOrNull --- src/hb-ot-cff-common.hh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh index 8b8e59201..e89fd1e0d 100644 --- a/src/hb-ot-cff-common.hh +++ b/src/hb-ot-cff-common.hh @@ -40,14 +40,14 @@ using namespace OT; /* utility macro */ template -static inline const Type& StructAtOffsetOrNull(const void *P, unsigned int offset) -{ return offset? (* reinterpret_cast ((const char *) P + offset)): Null(Type); } +static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset) +{ return offset ? StructAtOffset (P, offset) : Null (Type); } -inline unsigned int calcOffSize(unsigned int dataSize) +inline unsigned int calcOffSize (unsigned int dataSize) { unsigned int size = 1; unsigned int offset = dataSize + 1; - while ((offset & ~0xFF) != 0) + while (offset & ~0xFF) { size++; offset >>= 8; @@ -58,8 +58,8 @@ inline unsigned int calcOffSize(unsigned int dataSize) struct code_pair_t { - hb_codepoint_t code; - hb_codepoint_t glyph; + hb_codepoint_t code; + hb_codepoint_t glyph; }; typedef hb_vector_t str_buff_t; From 3f806673fbeacdbe1b31399394ccc26c773a794b Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 29 Jun 2019 00:00:00 +0430 Subject: [PATCH 104/138] Apply some minor improves on CFFIndex --- src/hb-ot-cff-common.hh | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh index e89fd1e0d..aced77c83 100644 --- a/src/hb-ot-cff-common.hh +++ b/src/hb-ot-cff-common.hh @@ -92,10 +92,8 @@ struct CFFIndex static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count, unsigned int dataSize) { - if (count == 0) - return COUNT::static_size; - else - return min_size + calculate_offset_array_size (offSize_, count) + dataSize; + if (count == 0) return COUNT::static_size; + return min_size + calculate_offset_array_size (offSize_, count) + dataSize; } bool serialize (hb_serialize_context_t *c, const CFFIndex &src) @@ -159,9 +157,7 @@ struct CFFIndex byteArray.init (); byteArray.resize (buffArray.length); for (unsigned int i = 0; i < byteArray.length; i++) - { byteArray[i] = byte_str_t (buffArray[i].arrayZ, buffArray[i].length); - } bool result = this->serialize (c, offSize_, byteArray); byteArray.fini (); return result; @@ -192,43 +188,35 @@ struct CFFIndex unsigned int length_at (unsigned int index) const { - if (likely ((offset_at (index + 1) >= offset_at (index)) && - (offset_at (index + 1) <= offset_at (count)))) - return offset_at (index + 1) - offset_at (index); - else + if (unlikely ((offset_at (index + 1) < offset_at (index)) || + (offset_at (index + 1) > offset_at (count)))) return 0; + return offset_at (index + 1) - offset_at (index); } const unsigned char *data_base () const - { return (const unsigned char *)this + min_size + offset_array_size (); } + { return (const unsigned char *) this + min_size + offset_array_size (); } unsigned int data_size () const { return HBINT8::static_size; } byte_str_t operator [] (unsigned int index) const { - if (likely (index < count)) - return byte_str_t (data_base () + offset_at (index) - 1, length_at (index)); - else - return Null (byte_str_t); + if (unlikely (index >= count)) return Null (byte_str_t); + return byte_str_t (data_base () + offset_at (index) - 1, length_at (index)); } unsigned int get_size () const { - if (this != &Null (CFFIndex)) - { - if (count > 0) - return min_size + offset_array_size () + (offset_at (count) - 1); - else - return count.static_size; /* empty CFFIndex contains count only */ - } - else - return 0; + if (this == &Null (CFFIndex)) return 0; + if (count > 0) + return min_size + offset_array_size () + (offset_at (count) - 1); + return count.static_size; /* empty CFFIndex contains count only */ } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */ + return_trace (likely ((c->check_struct (this) && count == 0) || /* empty INDEX */ (c->check_struct (this) && offSize >= 1 && offSize <= 4 && c->check_array (offsets, offSize, count + 1) && c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1)))); From ad341d5f1624f4e30b2d0eb2a171054a973053b5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 28 Jun 2019 16:00:37 -0700 Subject: [PATCH 105/138] [config] Fix CoreText build with NO_AAT --- src/hb-aat-layout.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index c08bb11f4..4e506de16 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -75,9 +75,6 @@ AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_) #endif -#ifndef HB_NO_AAT - - /** * SECTION:hb-aat-layout * @title: hb-aat-layout @@ -88,6 +85,8 @@ AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_) **/ +#if !defined(HB_NO_AAT) || defined(HAVE_CORETEXT) + /* Table data courtesy of Apple. Converted from mnemonics to integers * when moving to this file. */ static const hb_aat_feature_mapping_t feature_mappings[] = @@ -179,8 +178,11 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag) sizeof (feature_mappings[0]), hb_aat_feature_mapping_t::cmp); } +#endif +#ifndef HB_NO_AAT + /* * mort/morx/kerx/trak */ From 601b6825b05f67354b48dd3629b95e0d8bf68a14 Mon Sep 17 00:00:00 2001 From: Carlo Bramini <30959007+carlo-bramini@users.noreply.github.com> Date: Sun, 30 Jun 2019 15:03:44 +0200 Subject: [PATCH 106/138] Dynamically load DWRITE Also checks if DWriteCreateFactory() has been executed successfully. --- src/hb-directwrite.cc | 45 +++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 9b851148b..1f00aa478 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -33,6 +33,13 @@ #include "hb-directwrite.h" +/* Declare object creator for dynamic support of DWRITE */ +typedef HRESULT (* WINAPI t_DWriteCreateFactory)( + DWRITE_FACTORY_TYPE factoryType, + REFIID iid, + IUnknown **factory +); + /* * hb-directwrite uses new/delete syntatically but as we let users * to override malloc/free, we will redefine new/delete so users @@ -138,6 +145,7 @@ public: struct hb_directwrite_face_data_t { + HMODULE dwrite_dll; IDWriteFactory *dwriteFactory; IDWriteFontFile *fontFile; DWriteFontFileStream *fontFileStream; @@ -153,12 +161,33 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) if (unlikely (!data)) return nullptr; - // TODO: factory and fontFileLoader should be cached separately - IDWriteFactory* dwriteFactory; - DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), - (IUnknown**) &dwriteFactory); +#define FAIL(...) \ + HB_STMT_START { \ + DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \ + return nullptr; \ + } HB_STMT_END + + data->dwrite_dll = LoadLibrary(TEXT("DWRITE")); + if (data->dwrite_dll == NULL) + FAIL ("Cannot find DWrite.DLL"); + + t_DWriteCreateFactory p_DWriteCreateFactory; + + p_DWriteCreateFactory = (t_DWriteCreateFactory) + GetProcAddress(data->dwrite_dll, "DWriteCreateFactory"); + if (p_DWriteCreateFactory == NULL) + FAIL ("Cannot find DWriteCreateFactory()."); HRESULT hr; + + // TODO: factory and fontFileLoader should be cached separately + IDWriteFactory* dwriteFactory; + hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), + (IUnknown**) &dwriteFactory); + + if (hr != S_OK) + FAIL ("Failed to run DWriteCreateFactory()."); + hb_blob_t *blob = hb_face_reference_blob (face); DWriteFontFileStream *fontFileStream; fontFileStream = new DWriteFontFileStream ((uint8_t *) hb_blob_get_data (blob, nullptr), @@ -172,12 +201,6 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey), fontFileLoader, &fontFile); -#define FAIL(...) \ - HB_STMT_START { \ - DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \ - return nullptr; \ - } HB_STMT_END - if (FAILED (hr)) FAIL ("Failed to load font file from data!"); @@ -224,6 +247,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data) delete data->fontFileStream; if (data->faceBlob) hb_blob_destroy (data->faceBlob); + if (data->dwrite_dll != NULL) + FreeLibrary(data->dwrite_dll); if (data) delete data; } From a4543d408b31376c38bab878b2f72d4323abc564 Mon Sep 17 00:00:00 2001 From: Carlo Bramini <30959007+carlo-bramini@users.noreply.github.com> Date: Sun, 30 Jun 2019 15:06:30 +0200 Subject: [PATCH 107/138] Empty DIRECTWRITE_LIBS Not used anymore since DWRITE is loaded dynamically. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 0dc672a81..09ce4e6ec 100644 --- a/configure.ac +++ b/configure.ac @@ -376,7 +376,7 @@ if test "x$with_directwrite" = "xyes" -a "x$have_directwrite" != "xtrue"; then fi if $have_directwrite; then DIRECTWRITE_CXXFLAGS= - DIRECTWRITE_LIBS="-ldwrite" + DIRECTWRITE_LIBS= AC_SUBST(DIRECTWRITE_CXXFLAGS) AC_SUBST(DIRECTWRITE_LIBS) AC_DEFINE(HAVE_DIRECTWRITE, 1, [Have DirectWrite library]) From 693dacbb1c0bc805e3e6aedaca5a57f04eb6ec9c Mon Sep 17 00:00:00 2001 From: Carlo Bramini <30959007+carlo-bramini@users.noreply.github.com> Date: Mon, 1 Jul 2019 13:31:26 +0200 Subject: [PATCH 108/138] Use lower case file name with #include I tried to cross compile harfbuzz for Windows and an error was generated because `DWrite_1.h` was not found. This happened because the filesystem is case sensitive and for this reason that include file was not found. The right name of the file to be used is `dwrite_1.h`, with all letters not capitalized: https://docs.microsoft.com/en-us/windows/desktop/api/dwrite_1/ I also verified in the installation of VS2017 with Windows Kit v10 and in that place it was also lower case. So, in my opinion it should be better to change this. --- src/hb-directwrite.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 1f00aa478..1b2bd1964 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -28,7 +28,7 @@ #include "hb-shaper-impl.hh" -#include +#include #include "hb-directwrite.h" From 5ebd265e66cbcd167469837dcf8647484310dfb5 Mon Sep 17 00:00:00 2001 From: Carlo Bramini <30959007+carlo-bramini@users.noreply.github.com> Date: Mon, 1 Jul 2019 16:06:43 +0200 Subject: [PATCH 109/138] Fix error rised by GCC8+ --- src/hb-directwrite.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 1b2bd1964..865100aa2 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -173,8 +173,18 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) t_DWriteCreateFactory p_DWriteCreateFactory; +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif + p_DWriteCreateFactory = (t_DWriteCreateFactory) GetProcAddress(data->dwrite_dll, "DWriteCreateFactory"); + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + if (p_DWriteCreateFactory == NULL) FAIL ("Cannot find DWriteCreateFactory()."); From 4ab2d1d6767568c45495be515e016805cce0c69a Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Mon, 1 Jul 2019 19:30:21 +0430 Subject: [PATCH 110/138] [dwrite] Apply minor style improves --- src/hb-directwrite.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 865100aa2..a625763da 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -167,8 +167,8 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) return nullptr; \ } HB_STMT_END - data->dwrite_dll = LoadLibrary(TEXT("DWRITE")); - if (data->dwrite_dll == NULL) + data->dwrite_dll = LoadLibrary (TEXT ("DWRITE")); + if (unlikely (!data->dwrite_dll)) FAIL ("Cannot find DWrite.DLL"); t_DWriteCreateFactory p_DWriteCreateFactory; @@ -179,13 +179,13 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) #endif p_DWriteCreateFactory = (t_DWriteCreateFactory) - GetProcAddress(data->dwrite_dll, "DWriteCreateFactory"); + GetProcAddress (data->dwrite_dll, "DWriteCreateFactory"); #if defined(__GNUC__) #pragma GCC diagnostic pop #endif - if (p_DWriteCreateFactory == NULL) + if (unlikely (!p_DWriteCreateFactory)) FAIL ("Cannot find DWriteCreateFactory()."); HRESULT hr; @@ -193,9 +193,9 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) // TODO: factory and fontFileLoader should be cached separately IDWriteFactory* dwriteFactory; hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), - (IUnknown**) &dwriteFactory); + (IUnknown**) &dwriteFactory); - if (hr != S_OK) + if (unlikely (hr != S_OK)) FAIL ("Failed to run DWriteCreateFactory()."); hb_blob_t *blob = hb_face_reference_blob (face); @@ -257,8 +257,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data) delete data->fontFileStream; if (data->faceBlob) hb_blob_destroy (data->faceBlob); - if (data->dwrite_dll != NULL) - FreeLibrary(data->dwrite_dll); + if (data->dwrite_dll) + FreeLibrary (data->dwrite_dll); if (data) delete data; } From 040b261deeed8924edcb087e27a61392d1f85023 Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Sun, 30 Jun 2019 16:13:07 -0700 Subject: [PATCH 111/138] add bimap test along with bug fix/tweaks --- src/Makefile.am | 6 +++- src/hb-bimap.hh | 4 +++ src/test-bimap.cc | 76 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/test-bimap.cc diff --git a/src/Makefile.am b/src/Makefile.am index 51f9aac88..d4ba39afc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -374,7 +374,7 @@ dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc dump_use_data_CPPFLAGS = $(HBCFLAGS) dump_use_data_LDADD = libharfbuzz.la $(HBLIBS) -COMPILED_TESTS = test-algs test-iter test-meta test-ot-tag test-unicode-ranges +COMPILED_TESTS = test-algs test-iter test-meta test-ot-tag test-unicode-ranges test-bimap COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS) check_PROGRAMS += $(COMPILED_TESTS) @@ -400,6 +400,10 @@ test_unicode_ranges_SOURCES = test-unicode-ranges.cc test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD) +test_bimap_SOURCES = test-bimap.cc hb-static.cc +test_bimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) +test_bimap_LDADD = $(COMPILED_TESTS_LDADD) + TESTS_ENVIRONMENT = \ srcdir="$(srcdir)" \ MAKE="$(MAKE) $(AM_MAKEFLAGS)" \ diff --git a/src/hb-bimap.hh b/src/hb-bimap.hh index 29291506a..a773951ab 100644 --- a/src/hb-bimap.hh +++ b/src/hb-bimap.hh @@ -28,6 +28,7 @@ #define HB_BIMAP_HH #include "hb.hh" +#include "hb-map.hh" /* Bi-directional map */ struct hb_bimap_t @@ -57,6 +58,8 @@ struct hb_bimap_t void set (hb_codepoint_t lhs, hb_codepoint_t rhs) { + if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return; + if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; } forw_map.set (lhs, rhs); back_map.set (rhs, lhs); } @@ -131,6 +134,7 @@ struct hb_inc_bimap_t : hb_bimap_t work.qsort (cmp_id); + clear (); for (hb_codepoint_t rhs = 0; rhs < count; rhs++) set (work[rhs], rhs); } diff --git a/src/test-bimap.cc b/src/test-bimap.cc new file mode 100644 index 000000000..1253d0c1d --- /dev/null +++ b/src/test-bimap.cc @@ -0,0 +1,76 @@ +/* + * Copyright © 2019 Adobe, 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. + * + * Adobe Author(s): Michiharu Ariza + */ + +#include "hb.hh" +#include "hb-bimap.hh" + +int +main (int argc, char **argv) +{ + hb_bimap_t bm; + + assert (bm.is_empty () == true); + bm.set (1, 4); + bm.set (2, 5); + bm.set (3, 6); + assert (bm.get_population () == 3); + assert (bm.has (1) == true); + assert (bm.has (4) == false); + assert (bm[2] == 5); + assert (bm.backward (6) == 3); + bm.del (1); + assert (bm.has (1) == false); + assert (bm.has (3) == true); + bm.clear (); + assert (bm.get_population () == 0); + + hb_inc_bimap_t ibm; + + assert (ibm.add (13) == 0); + assert (ibm.add (8) == 1); + assert (ibm.add (10) == 2); + assert (ibm.add (8) == 1); + assert (ibm.add (7) == 3); + assert (ibm.get_population () == 4); + assert (ibm[7] == 3); + + ibm.sort (); + assert (ibm.get_population () == 4); + assert (ibm[7] == 0); + assert (ibm[13] == 3); + + ibm.identity (3); + assert (ibm.get_population () == 3); + assert (ibm[0] == 0); + assert (ibm[1] == 1); + assert (ibm[2] == 2); + assert (ibm.backward (0) == 0); + assert (ibm.backward (1) == 1); + assert (ibm.backward (2) == 2); + assert (ibm.has (4) == false); + + return 0; +} From f1d20d9b4dcbeead3757650b9286393918b4be8a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 14:18:38 -0700 Subject: [PATCH 112/138] Add ucd-table make target --- src/Makefile.am | 23 +++++++++++++++-------- src/gen-ucd-table.py | 8 +++++--- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index d4ba39afc..e7b279ddc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -253,31 +253,38 @@ GENERATORS = \ $(NULL) EXTRA_DIST += $(GENERATORS) -unicode-tables: arabic-table indic-table tag-table use-table emoji-table +unicode-tables: \ + arabic-table \ + emoji-table \ + indic-table \ + tag-table \ + ucd-table \ + use-table \ + emoji-table \ + $(NULL) arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-arabic-table.hh \ || ($(RM) $(srcdir)/hb-ot-shape-complex-arabic-table.hh; false) - +emoji-table: gen-emoji-table.py emoji-data.txt + $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \ + || ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false) indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-indic-table.cc \ || ($(RM) $(srcdir)/hb-ot-shape-complex-indic-table.cc; false) - tag-table: gen-tag-table.py languagetags language-subtag-registry $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-tag-table.hh \ || ($(RM) $(srcdir)/hb-ot-tag-table.hh; false) - +ucd-table: gen-ucd-table.py ucd.nounihan.grouped.zip hb-common.h + $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ucd-table.hh \ + || ($(RM) $(srcdir)/hb-ucd-table.hh; false) use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \ || ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false) - vowel-constraints: gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \ || ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false) -emoji-table: gen-emoji-table.py emoji-data.txt - $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \ - || ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false) built-sources: $(BUILT_SOURCES) diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py index a152375dd..552c3c675 100755 --- a/src/gen-ucd-table.py +++ b/src/gen-ucd-table.py @@ -6,8 +6,8 @@ import io, os.path, sys, re import logging logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) -if len (sys.argv) != 2: - print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml", file=sys.stderr) +if len (sys.argv) not in (2, 3): + print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml [/path/to/hb-common.h]", file=sys.stderr) sys.exit(1) # https://github.com/harfbuzz/packtab @@ -18,6 +18,8 @@ logging.info('Loading UCDXML...') ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1]) ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml) +hb_common_h = 'hb-common.h' if len (sys.argv) < 3 else sys.argv[2] + logging.info('Preparing data tables...') gc = [u['gc'] for u in ucd] @@ -68,7 +70,7 @@ for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu' sc_order = dict() sc_array = [] sc_re = re.compile(r"\b(HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]") -for line in open('hb-common.h'): +for line in open(hb_common_h): m = sc_re.search (line) if not m: continue name = m.group(1) From c073233f45da6ad8131dd38cb43b125f48c17432 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 14:26:45 -0700 Subject: [PATCH 113/138] Add make rule to build hb.cc Part of https://github.com/harfbuzz/harfbuzz/issues/1809 --- src/Makefile.am | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index e7b279ddc..c276118e8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -303,6 +303,12 @@ $(srcdir)/%.hh: $(srcdir)/%.rl $(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \ || ($(RM) "$@"; false) +hb.cc: Makefile.sources + $(AM_V_GEN) \ + for f in $(HB_BASE_sources); do echo '#include "'$$f'"'; done | \ + grep '[.]cc"' > $(srcdir)/hb.cc \ + || ($(RM) $(srcdir)/hb.cc; false) + noinst_PROGRAMS = \ main \ test \ From d115a9e022c0b687fb402cfd2b90d516beded5c0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 14:42:45 -0700 Subject: [PATCH 114/138] [amalgam] Fix most duplicate-id instances in Indic-like shapers Part of https://github.com/harfbuzz/harfbuzz/issues/1809 --- src/hb-ot-layout.hh | 22 +++ src/hb-ot-shape-complex-indic-machine.hh | 6 +- src/hb-ot-shape-complex-indic-machine.rl | 6 +- src/hb-ot-shape-complex-indic.cc | 130 ++++++------------ src/hb-ot-shape-complex-indic.hh | 26 ++++ src/hb-ot-shape-complex-khmer-machine.hh | 6 +- src/hb-ot-shape-complex-khmer-machine.rl | 6 +- src/hb-ot-shape-complex-khmer.cc | 97 ++++--------- src/hb-ot-shape-complex-myanmar-machine.hh | 4 +- src/hb-ot-shape-complex-myanmar-machine.rl | 4 +- src/hb-ot-shape-complex-myanmar.cc | 69 ++++------ src/hb-ot-shape-complex-use-machine.hh | 4 +- src/hb-ot-shape-complex-use-machine.rl | 4 +- src/hb-ot-shape-complex-use.cc | 150 +++++++++------------ 14 files changed, 231 insertions(+), 303 deletions(-) diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh index be7ef0263..f3bb15581 100644 --- a/src/hb-ot-layout.hh +++ b/src/hb-ot-layout.hh @@ -168,6 +168,17 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start) return start; } +static inline void +_hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + info[i].syllable() = 0; +} + /* unicode_props */ @@ -551,6 +562,17 @@ _hb_glyph_info_clear_substituted (hb_glyph_info_t *info) info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED); } +static inline void +_hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + _hb_glyph_info_clear_substituted (&info[i]); +} + /* Allocation / deallocation. */ diff --git a/src/hb-ot-shape-complex-indic-machine.hh b/src/hb-ot-shape-complex-indic-machine.hh index ca26ecbae..670b6bf48 100644 --- a/src/hb-ot-shape-complex-indic-machine.hh +++ b/src/hb-ot-shape-complex-indic-machine.hh @@ -395,13 +395,13 @@ static const int indic_syllable_machine_en_main = 39; HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | indic_##syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (hb_buffer_t *buffer) +find_syllables_indic (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act; int cs; @@ -569,4 +569,6 @@ _again: } +#undef found_syllable + #endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */ diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl index a2a88af0d..5f819bd29 100644 --- a/src/hb-ot-shape-complex-indic-machine.rl +++ b/src/hb-ot-shape-complex-indic-machine.rl @@ -96,13 +96,13 @@ main := |* HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | indic_##syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (hb_buffer_t *buffer) +find_syllables_indic (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act; int cs; @@ -121,4 +121,6 @@ find_syllables (hb_buffer_t *buffer) }%% } +#undef found_syllable + #endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */ diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 6405d9c2d..23a1be2da 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -172,21 +172,17 @@ enum { }; static void -setup_syllables (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +setup_syllables_indic (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void -initial_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +initial_reordering_indic (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void -final_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); -static void -clear_syllables (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +final_reordering_indic (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void collect_features_indic (hb_ot_shape_planner_t *plan) @@ -194,7 +190,7 @@ collect_features_indic (hb_ot_shape_planner_t *plan) hb_ot_map_builder_t *map = &plan->map; /* Do this before any lookups have been applied. */ - map->add_gsub_pause (setup_syllables); + map->add_gsub_pause (setup_syllables_indic); map->enable_feature (HB_TAG('l','o','c','l')); /* The Indic specs do not require ccmp, but we apply it here since if @@ -203,14 +199,14 @@ collect_features_indic (hb_ot_shape_planner_t *plan) unsigned int i = 0; - map->add_gsub_pause (initial_reordering); + map->add_gsub_pause (initial_reordering_indic); for (; i < INDIC_BASIC_FEATURES; i++) { map->add_feature (indic_features[i]); map->add_gsub_pause (nullptr); } - map->add_gsub_pause (final_reordering); + map->add_gsub_pause (final_reordering_indic); for (; i < INDIC_NUM_FEATURES; i++) map->add_feature (indic_features[i]); @@ -218,7 +214,7 @@ collect_features_indic (hb_ot_shape_planner_t *plan) map->enable_feature (HB_TAG('c','a','l','t')); map->enable_feature (HB_TAG('c','l','i','g')); - map->add_gsub_pause (clear_syllables); + map->add_gsub_pause (_hb_clear_syllables); } static void @@ -228,32 +224,6 @@ override_features_indic (hb_ot_shape_planner_t *plan) } -struct would_substitute_feature_t -{ - void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) - { - zero_context = zero_context_; - map->get_stage_lookups (0/*GSUB*/, - map->get_feature_stage (0/*GSUB*/, feature_tag), - &lookups, &count); - } - - bool would_substitute (const hb_codepoint_t *glyphs, - unsigned int glyphs_count, - hb_face_t *face) const - { - for (unsigned int i = 0; i < count; i++) - if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context)) - return true; - return false; - } - - private: - const hb_ot_map_t::lookup_map_t *lookups; - unsigned int count; - bool zero_context; -}; - struct indic_shape_plan_t { bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const @@ -285,10 +255,10 @@ struct indic_shape_plan_t #endif mutable hb_atomic_int_t virama_glyph; - would_substitute_feature_t rphf; - would_substitute_feature_t pref; - would_substitute_feature_t blwf; - would_substitute_feature_t pstf; + hb_indic_would_substitute_feature_t rphf; + hb_indic_would_substitute_feature_t pref; + hb_indic_would_substitute_feature_t blwf; + hb_indic_would_substitute_feature_t pstf; hb_mask_t mask_array[INDIC_NUM_FEATURES]; }; @@ -371,13 +341,13 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan, } -enum syllable_type_t { - consonant_syllable, - vowel_syllable, - standalone_cluster, - symbol_cluster, - broken_cluster, - non_indic_cluster, +enum indic_syllable_type_t { + indic_consonant_syllable, + indic_vowel_syllable, + indic_standalone_cluster, + indic_symbol_cluster, + indic_broken_cluster, + indic_non_indic_cluster, }; #include "hb-ot-shape-complex-indic-machine.hh" @@ -401,11 +371,11 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, } static void -setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { - find_syllables (buffer); + find_syllables_indic (buffer); foreach_syllable (buffer, start, end) buffer->unsafe_to_break (start, end); } @@ -950,21 +920,21 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, unsigned int start, unsigned int end) { - syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); + indic_syllable_type_t syllable_type = (indic_syllable_type_t) (buffer->info[start].syllable() & 0x0F); switch (syllable_type) { - case vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */ - case consonant_syllable: + case indic_vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */ + case indic_consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); break; - case broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */ - case standalone_cluster: + case indic_broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */ + case indic_standalone_cluster: initial_reordering_standalone_cluster (plan, face, buffer, start, end); break; - case symbol_cluster: - case non_indic_cluster: + case indic_symbol_cluster: + case indic_non_indic_cluster: break; } } @@ -983,7 +953,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if ((info[i].syllable() & 0x0F) == broken_cluster) + if ((info[i].syllable() & 0x0F) == indic_broken_cluster) { has_broken_syllables = true; break; @@ -1008,8 +978,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, while (buffer->idx < buffer->len && buffer->successful) { unsigned int syllable = buffer->cur().syllable(); - syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); - if (unlikely (last_syllable != syllable && syllable_type == broken_cluster)) + indic_syllable_type_t syllable_type = (indic_syllable_type_t) (syllable & 0x0F); + if (unlikely (last_syllable != syllable && syllable_type == indic_broken_cluster)) { last_syllable = syllable; @@ -1033,9 +1003,9 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, } static void -initial_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) +initial_reordering_indic (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { update_consonant_positions (plan, font, buffer); insert_dotted_circles (plan, font, buffer); @@ -1508,9 +1478,9 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, static void -final_reordering (const hb_ot_shape_plan_t *plan, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +final_reordering_indic (const hb_ot_shape_plan_t *plan, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { unsigned int count = buffer->len; if (unlikely (!count)) return; @@ -1523,18 +1493,6 @@ final_reordering (const hb_ot_shape_plan_t *plan, } -static void -clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - info[i].syllable() = 0; -} - - static void preprocess_text_indic (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, diff --git a/src/hb-ot-shape-complex-indic.hh b/src/hb-ot-shape-complex-indic.hh index d207728c4..f3f195806 100644 --- a/src/hb-ot-shape-complex-indic.hh +++ b/src/hb-ot-shape-complex-indic.hh @@ -398,5 +398,31 @@ set_indic_properties (hb_glyph_info_t &info) info.indic_position() = pos; } +struct hb_indic_would_substitute_feature_t +{ + void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) + { + zero_context = zero_context_; + map->get_stage_lookups (0/*GSUB*/, + map->get_feature_stage (0/*GSUB*/, feature_tag), + &lookups, &count); + } + + bool would_substitute (const hb_codepoint_t *glyphs, + unsigned int glyphs_count, + hb_face_t *face) const + { + for (unsigned int i = 0; i < count; i++) + if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context)) + return true; + return false; + } + + private: + const hb_ot_map_t::lookup_map_t *lookups; + unsigned int count; + bool zero_context; +}; + #endif /* HB_OT_SHAPE_COMPLEX_INDIC_HH */ diff --git a/src/hb-ot-shape-complex-khmer-machine.hh b/src/hb-ot-shape-complex-khmer-machine.hh index 65e0ffc85..a040318d3 100644 --- a/src/hb-ot-shape-complex-khmer-machine.hh +++ b/src/hb-ot-shape-complex-khmer-machine.hh @@ -226,13 +226,13 @@ static const int khmer_syllable_machine_en_main = 20; HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (hb_buffer_t *buffer) +find_syllables_khmer (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act HB_UNUSED; int cs; @@ -367,4 +367,6 @@ _again: } +#undef found_syllable + #endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */ diff --git a/src/hb-ot-shape-complex-khmer-machine.rl b/src/hb-ot-shape-complex-khmer-machine.rl index 1076a08e8..e7f14533d 100644 --- a/src/hb-ot-shape-complex-khmer-machine.rl +++ b/src/hb-ot-shape-complex-khmer-machine.rl @@ -83,13 +83,13 @@ main := |* HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (hb_buffer_t *buffer) +find_syllables_khmer (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act HB_UNUSED; int cs; @@ -108,4 +108,6 @@ find_syllables (hb_buffer_t *buffer) }%% } +#undef found_syllable + #endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */ diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc index eba7d86ea..2bc62bb56 100644 --- a/src/hb-ot-shape-complex-khmer.cc +++ b/src/hb-ot-shape-complex-khmer.cc @@ -89,17 +89,13 @@ enum { }; static void -setup_syllables (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +setup_syllables_khmer (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void -reorder (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); -static void -clear_syllables (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +reorder_khmer (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void collect_features_khmer (hb_ot_shape_planner_t *plan) @@ -107,8 +103,8 @@ collect_features_khmer (hb_ot_shape_planner_t *plan) hb_ot_map_builder_t *map = &plan->map; /* Do this before any lookups have been applied. */ - map->add_gsub_pause (setup_syllables); - map->add_gsub_pause (reorder); + map->add_gsub_pause (setup_syllables_khmer); + map->add_gsub_pause (reorder_khmer); /* Testing suggests that Uniscribe does NOT pause between basic * features. Test with KhmerUI.ttf and the following three @@ -127,7 +123,7 @@ collect_features_khmer (hb_ot_shape_planner_t *plan) for (; i < KHMER_BASIC_FEATURES; i++) map->add_feature (khmer_features[i]); - map->add_gsub_pause (clear_syllables); + map->add_gsub_pause (_hb_clear_syllables); for (; i < KHMER_NUM_FEATURES; i++) map->add_feature (khmer_features[i]); @@ -153,32 +149,6 @@ override_features_khmer (hb_ot_shape_planner_t *plan) } -struct would_substitute_feature_t -{ - void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) - { - zero_context = zero_context_; - map->get_stage_lookups (0/*GSUB*/, - map->get_feature_stage (0/*GSUB*/, feature_tag), - &lookups, &count); - } - - bool would_substitute (const hb_codepoint_t *glyphs, - unsigned int glyphs_count, - hb_face_t *face) const - { - for (unsigned int i = 0; i < count; i++) - if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context)) - return true; - return false; - } - - private: - const hb_ot_map_t::lookup_map_t *lookups; - unsigned int count; - bool zero_context; -}; - struct khmer_shape_plan_t { bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const @@ -202,7 +172,7 @@ struct khmer_shape_plan_t mutable hb_codepoint_t virama_glyph; - would_substitute_feature_t pref; + hb_indic_would_substitute_feature_t pref; hb_mask_t mask_array[KHMER_NUM_FEATURES]; }; @@ -232,10 +202,10 @@ data_destroy_khmer (void *data) } -enum syllable_type_t { - consonant_syllable, - broken_cluster, - non_khmer_cluster, +enum khmer_syllable_type_t { + khmer_consonant_syllable, + khmer_broken_cluster, + khmer_non_khmer_cluster, }; #include "hb-ot-shape-complex-khmer-machine.hh" @@ -257,11 +227,11 @@ setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED, } static void -setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { - find_syllables (buffer); + find_syllables_khmer (buffer); foreach_syllable (buffer, start, end) buffer->unsafe_to_break (start, end); } @@ -351,15 +321,15 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, unsigned int start, unsigned int end) { - syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); + khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (buffer->info[start].syllable() & 0x0F); switch (syllable_type) { - case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */ - case consonant_syllable: + case khmer_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */ + case khmer_consonant_syllable: reorder_consonant_syllable (plan, face, buffer, start, end); break; - case non_khmer_cluster: + case khmer_non_khmer_cluster: break; } } @@ -378,7 +348,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if ((info[i].syllable() & 0x0F) == broken_cluster) + if ((info[i].syllable() & 0x0F) == khmer_broken_cluster) { has_broken_syllables = true; break; @@ -403,8 +373,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, while (buffer->idx < buffer->len && buffer->successful) { unsigned int syllable = buffer->cur().syllable(); - syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); - if (unlikely (last_syllable != syllable && syllable_type == broken_cluster)) + khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (syllable & 0x0F); + if (unlikely (last_syllable != syllable && syllable_type == khmer_broken_cluster)) { last_syllable = syllable; @@ -428,9 +398,9 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, } static void -reorder (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) +reorder_khmer (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { insert_dotted_circles (plan, font, buffer); @@ -440,17 +410,6 @@ reorder (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category); } -static void -clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - info[i].syllable() = 0; -} - static bool decompose_khmer (const hb_ot_shape_normalize_context_t *c, diff --git a/src/hb-ot-shape-complex-myanmar-machine.hh b/src/hb-ot-shape-complex-myanmar-machine.hh index b7b04cb6d..c2f4c0045 100644 --- a/src/hb-ot-shape-complex-myanmar-machine.hh +++ b/src/hb-ot-shape-complex-myanmar-machine.hh @@ -304,13 +304,13 @@ static const int myanmar_syllable_machine_en_main = 0; HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | myanmar_##syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (hb_buffer_t *buffer) +find_syllables_myanmar (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act HB_UNUSED; int cs; diff --git a/src/hb-ot-shape-complex-myanmar-machine.rl b/src/hb-ot-shape-complex-myanmar-machine.rl index 665998938..67133cd73 100644 --- a/src/hb-ot-shape-complex-myanmar-machine.rl +++ b/src/hb-ot-shape-complex-myanmar-machine.rl @@ -97,13 +97,13 @@ main := |* HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | myanmar_##syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (hb_buffer_t *buffer) +find_syllables_myanmar (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act HB_UNUSED; int cs; diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index 5b819cf47..d1aabf46e 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -80,15 +80,11 @@ positioning_features[] = }; static void -setup_syllables (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); +setup_syllables_myanmar (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void -reorder (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); -static void -clear_syllables (const hb_ot_shape_plan_t *plan, +reorder_myanmar (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); @@ -98,7 +94,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan) hb_ot_map_builder_t *map = &plan->map; /* Do this before any lookups have been applied. */ - map->add_gsub_pause (setup_syllables); + map->add_gsub_pause (setup_syllables_myanmar); map->enable_feature (HB_TAG('l','o','c','l')); /* The Indic specs do not require ccmp, but we apply it here since if @@ -106,7 +102,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan) map->enable_feature (HB_TAG('c','c','m','p')); - map->add_gsub_pause (reorder); + map->add_gsub_pause (reorder_myanmar); for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) { @@ -114,7 +110,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan) map->add_gsub_pause (nullptr); } - map->add_gsub_pause (clear_syllables); + map->add_gsub_pause (_hb_clear_syllables); for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) map->enable_feature (other_features[i], F_MANUAL_ZWJ); @@ -130,11 +126,11 @@ override_features_myanmar (hb_ot_shape_planner_t *plan) } -enum syllable_type_t { - consonant_syllable, - punctuation_cluster, - broken_cluster, - non_myanmar_cluster, +enum myanmar_syllable_type_t { + myanmar_consonant_syllable, + myanmar_punctuation_cluster, + myanmar_broken_cluster, + myanmar_non_myanmar_cluster, }; #include "hb-ot-shape-complex-myanmar-machine.hh" @@ -158,11 +154,11 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, } static void -setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { - find_syllables (buffer); + find_syllables_myanmar (buffer); foreach_syllable (buffer, start, end) buffer->unsafe_to_break (start, end); } @@ -283,16 +279,16 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, unsigned int start, unsigned int end) { - syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); + myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (buffer->info[start].syllable() & 0x0F); switch (syllable_type) { - case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */ - case consonant_syllable: + case myanmar_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */ + case myanmar_consonant_syllable: initial_reordering_consonant_syllable (buffer, start, end); break; - case punctuation_cluster: - case non_myanmar_cluster: + case myanmar_punctuation_cluster: + case myanmar_non_myanmar_cluster: break; } } @@ -311,7 +307,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if ((info[i].syllable() & 0x0F) == broken_cluster) + if ((info[i].syllable() & 0x0F) == myanmar_broken_cluster) { has_broken_syllables = true; break; @@ -336,8 +332,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, while (buffer->idx < buffer->len && buffer->successful) { unsigned int syllable = buffer->cur().syllable(); - syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); - if (unlikely (last_syllable != syllable && syllable_type == broken_cluster)) + myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (syllable & 0x0F); + if (unlikely (last_syllable != syllable && syllable_type == myanmar_broken_cluster)) { last_syllable = syllable; @@ -355,9 +351,9 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, } static void -reorder (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) +reorder_myanmar (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { insert_dotted_circles (plan, font, buffer); @@ -368,17 +364,6 @@ reorder (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position); } -static void -clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - info[i].syllable() = 0; -} - const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = { diff --git a/src/hb-ot-shape-complex-use-machine.hh b/src/hb-ot-shape-complex-use-machine.hh index 01fe3d788..462342c61 100644 --- a/src/hb-ot-shape-complex-use-machine.hh +++ b/src/hb-ot-shape-complex-use-machine.hh @@ -380,13 +380,13 @@ static const int use_syllable_machine_en_main = 5; HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | use_##syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (hb_buffer_t *buffer) +find_syllables_use (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act; int cs; diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl index aca7ea683..9b75b5c6e 100644 --- a/src/hb-ot-shape-complex-use-machine.rl +++ b/src/hb-ot-shape-complex-use-machine.rl @@ -165,13 +165,13 @@ main := |* HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | use_##syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END static void -find_syllables (hb_buffer_t *buffer) +find_syllables_use (hb_buffer_t *buffer) { unsigned int p, pe, eof, ts, te, act; int cs; diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 91c0b8c04..716ffd376 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -106,29 +106,21 @@ positioning_features[] = }; static void -setup_syllables (const hb_ot_shape_plan_t *plan, +setup_syllables_use (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); +static void +record_rphf_use (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); static void -clear_substitution_flags (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); -static void -record_rphf (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); -static void -record_pref (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); -static void -reorder (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer); -static void -clear_syllables (const hb_ot_shape_plan_t *plan, +record_pref_use (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); +static void +reorder_use (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void collect_features_use (hb_ot_shape_planner_t *plan) @@ -136,7 +128,7 @@ collect_features_use (hb_ot_shape_planner_t *plan) hb_ot_map_builder_t *map = &plan->map; /* Do this before any lookups have been applied. */ - map->add_gsub_pause (setup_syllables); + map->add_gsub_pause (setup_syllables_use); /* "Default glyph pre-processing group" */ map->enable_feature (HB_TAG('l','o','c','l')); @@ -145,19 +137,19 @@ collect_features_use (hb_ot_shape_planner_t *plan) map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ); /* "Reordering group" */ - map->add_gsub_pause (clear_substitution_flags); + map->add_gsub_pause (_hb_clear_substitution_flags); map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ); - map->add_gsub_pause (record_rphf); - map->add_gsub_pause (clear_substitution_flags); + map->add_gsub_pause (record_rphf_use); + map->add_gsub_pause (_hb_clear_substitution_flags); map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ); - map->add_gsub_pause (record_pref); + map->add_gsub_pause (record_pref_use); /* "Orthographic unit shaping group" */ for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) map->enable_feature (basic_features[i], F_MANUAL_ZWJ); - map->add_gsub_pause (reorder); - map->add_gsub_pause (clear_syllables); + map->add_gsub_pause (reorder_use); + map->add_gsub_pause (_hb_clear_syllables); /* "Topographical features" */ for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++) @@ -247,16 +239,16 @@ data_destroy_use (void *data) free (data); } -enum syllable_type_t { - independent_cluster, - virama_terminated_cluster, - sakot_terminated_cluster, - standard_cluster, - number_joiner_terminated_cluster, - numeral_cluster, - symbol_cluster, - broken_cluster, - non_cluster, +enum use_syllable_type_t { + use_independent_cluster, + use_virama_terminated_cluster, + use_sakot_terminated_cluster, + use_standard_cluster, + use_number_joiner_terminated_cluster, + use_numeral_cluster, + use_symbol_cluster, + use_broken_cluster, + use_non_cluster, }; #include "hb-ot-shape-complex-use-machine.hh" @@ -331,22 +323,22 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, hb_glyph_info_t *info = buffer->info; foreach_syllable (buffer, start, end) { - syllable_type_t syllable_type = (syllable_type_t) (info[start].syllable() & 0x0F); + use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F); switch (syllable_type) { - case independent_cluster: - case symbol_cluster: - case non_cluster: + case use_independent_cluster: + case use_symbol_cluster: + case use_non_cluster: /* These don't join. Nothing to do. */ last_form = _NONE; break; - case virama_terminated_cluster: - case sakot_terminated_cluster: - case standard_cluster: - case number_joiner_terminated_cluster: - case numeral_cluster: - case broken_cluster: + case use_virama_terminated_cluster: + case use_sakot_terminated_cluster: + case use_standard_cluster: + case use_number_joiner_terminated_cluster: + case use_numeral_cluster: + case use_broken_cluster: bool join = last_form == FINA || last_form == ISOL; @@ -371,11 +363,11 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, } static void -setup_syllables (const hb_ot_shape_plan_t *plan, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +setup_syllables_use (const hb_ot_shape_plan_t *plan, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { - find_syllables (buffer); + find_syllables_use (buffer); foreach_syllable (buffer, start, end) buffer->unsafe_to_break (start, end); setup_rphf_mask (plan, buffer); @@ -383,20 +375,9 @@ setup_syllables (const hb_ot_shape_plan_t *plan, } static void -clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - _hb_glyph_info_clear_substituted (&info[i]); -} - -static void -record_rphf (const hb_ot_shape_plan_t *plan, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +record_rphf_use (const hb_ot_shape_plan_t *plan, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data; @@ -417,9 +398,9 @@ record_rphf (const hb_ot_shape_plan_t *plan, } static void -record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) +record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) { hb_glyph_info_t *info = buffer->info; @@ -443,15 +424,15 @@ is_halant (const hb_glyph_info_t &info) } static void -reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end) +reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) { - syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); + use_syllable_type_t syllable_type = (use_syllable_type_t) (buffer->info[start].syllable() & 0x0F); /* Only a few syllable types need reordering. */ if (unlikely (!(FLAG_UNSAFE (syllable_type) & - (FLAG (virama_terminated_cluster) | - FLAG (sakot_terminated_cluster) | - FLAG (standard_cluster) | - FLAG (broken_cluster) | + (FLAG (use_virama_terminated_cluster) | + FLAG (use_sakot_terminated_cluster) | + FLAG (use_standard_cluster) | + FLAG (use_broken_cluster) | 0)))) return; @@ -539,7 +520,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if ((info[i].syllable() & 0x0F) == broken_cluster) + if ((info[i].syllable() & 0x0F) == use_broken_cluster) { has_broken_syllables = true; break; @@ -559,8 +540,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, while (buffer->idx < buffer->len && buffer->successful) { unsigned int syllable = buffer->cur().syllable(); - syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F); - if (unlikely (last_syllable != syllable && syllable_type == broken_cluster)) + use_syllable_type_t syllable_type = (use_syllable_type_t) (syllable & 0x0F); + if (unlikely (last_syllable != syllable && syllable_type == use_broken_cluster)) { last_syllable = syllable; @@ -584,29 +565,18 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, } static void -reorder (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) +reorder_use (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { insert_dotted_circles (plan, font, buffer); foreach_syllable (buffer, start, end) - reorder_syllable (buffer, start, end); + reorder_syllable_use (buffer, start, end); HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); } -static void -clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - info[i].syllable() = 0; -} - static void preprocess_text_use (const hb_ot_shape_plan_t *plan, From d8b5353e07650cf243ba182dbf52e7f198719762 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 15:09:26 -0700 Subject: [PATCH 115/138] [amalgam] More Part of https://github.com/harfbuzz/harfbuzz/issues/1809 --- src/hb-ot-shape-complex-myanmar.cc | 28 ++++++++++++++-------------- src/hb-ot-shape-complex-use.cc | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index d1aabf46e..21793b4c4 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -36,7 +36,7 @@ */ static const hb_tag_t -basic_features[] = +myanmar_basic_features[] = { /* * Basic features. @@ -48,7 +48,7 @@ basic_features[] = HB_TAG('p','s','t','f'), }; static const hb_tag_t -other_features[] = +myanmar_other_features[] = { /* * Other features. @@ -60,7 +60,7 @@ other_features[] = HB_TAG('p','s','t','s'), }; static const hb_tag_t -positioning_features[] = +myanmar_positioning_features[] = { /* * Positioning features. @@ -104,19 +104,19 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan) map->add_gsub_pause (reorder_myanmar); - for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) + for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_basic_features); i++) { - map->enable_feature (basic_features[i], F_MANUAL_ZWJ); + map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ); map->add_gsub_pause (nullptr); } map->add_gsub_pause (_hb_clear_syllables); - for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) - map->enable_feature (other_features[i], F_MANUAL_ZWJ); + for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++) + map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ); - for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++) - map->enable_feature (positioning_features[i]); + for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_positioning_features); i++) + map->enable_feature (myanmar_positioning_features[i]); } static void @@ -274,10 +274,10 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer, } static void -initial_reordering_syllable (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_face_t *face HB_UNUSED, - hb_buffer_t *buffer, - unsigned int start, unsigned int end) +reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_face_t *face HB_UNUSED, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) { myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (buffer->info[start].syllable() & 0x0F); switch (syllable_type) { @@ -358,7 +358,7 @@ reorder_myanmar (const hb_ot_shape_plan_t *plan, insert_dotted_circles (plan, font, buffer); foreach_syllable (buffer, start, end) - initial_reordering_syllable (plan, font->face, buffer, start, end); + reorder_syllable_myanmar (plan, font->face, buffer, start, end); HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category); HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position); diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 716ffd376..f3b150d1c 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -44,7 +44,7 @@ */ static const hb_tag_t -basic_features[] = +use_basic_features[] = { /* * Basic features. @@ -59,7 +59,7 @@ basic_features[] = HB_TAG('c','j','c','t'), }; static const hb_tag_t -arabic_features[] = +use_arabic_features[] = { HB_TAG('i','s','o','l'), HB_TAG('i','n','i','t'), @@ -71,7 +71,7 @@ arabic_features[] = HB_TAG('f','i','n','2'), HB_TAG('f','i','n','3'), }; -/* Same order as arabic_features. Don't need Syriac stuff.*/ +/* Same order as use_arabic_features. Don't need Syriac stuff.*/ enum joining_form_t { ISOL, INIT, @@ -80,7 +80,7 @@ enum joining_form_t { _NONE }; static const hb_tag_t -other_features[] = +use_other_features[] = { /* * Other features. @@ -94,7 +94,7 @@ other_features[] = HB_TAG('p','s','t','s'), }; static const hb_tag_t -positioning_features[] = +use_positioning_features[] = { /* * Positioning features. @@ -145,24 +145,24 @@ collect_features_use (hb_ot_shape_planner_t *plan) map->add_gsub_pause (record_pref_use); /* "Orthographic unit shaping group" */ - for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) - map->enable_feature (basic_features[i], F_MANUAL_ZWJ); + for (unsigned int i = 0; i < ARRAY_LENGTH (use_basic_features); i++) + map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ); map->add_gsub_pause (reorder_use); map->add_gsub_pause (_hb_clear_syllables); /* "Topographical features" */ - for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++) - map->add_feature (arabic_features[i]); + for (unsigned int i = 0; i < ARRAY_LENGTH (use_arabic_features); i++) + map->add_feature (use_arabic_features[i]); map->add_gsub_pause (nullptr); /* "Standard typographic presentation" */ - for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) - map->enable_feature (other_features[i], F_MANUAL_ZWJ); + for (unsigned int i = 0; i < ARRAY_LENGTH (use_other_features); i++) + map->enable_feature (use_other_features[i], F_MANUAL_ZWJ); /* "Positional feature application" */ - for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++) - map->enable_feature (positioning_features[i]); + for (unsigned int i = 0; i < ARRAY_LENGTH (use_positioning_features); i++) + map->enable_feature (use_positioning_features[i]); } struct use_shape_plan_t @@ -309,7 +309,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, hb_mask_t masks[4], all_masks = 0; for (unsigned int i = 0; i < 4; i++) { - masks[i] = plan->map.get_1_mask (arabic_features[i]); + masks[i] = plan->map.get_1_mask (use_arabic_features[i]); if (masks[i] == plan->map.get_global_mask ()) masks[i] = 0; all_masks |= masks[i]; From dc480fc4717937d53cf38860a5c5d48211e8cbc8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 15:17:56 -0700 Subject: [PATCH 116/138] [amalgam] More Indic-like issues Part of https://github.com/harfbuzz/harfbuzz/issues/1809 --- src/hb-ot-shape-complex-indic.cc | 72 ++++++++++++++++---------------- src/hb-ot-shape-complex-khmer.cc | 36 ++++++++-------- src/hb-ot-shape-complex-use.cc | 32 +++++++------- 3 files changed, 72 insertions(+), 68 deletions(-) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 23a1be2da..43f377b66 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -144,31 +144,31 @@ indic_features[] = * Must be in the same order as the indic_features array. */ enum { - _NUKT, - _AKHN, - RPHF, - _RKRF, - PREF, - BLWF, - ABVF, - HALF, - PSTF, - _VATU, - _CJCT, + _INDIC_NUKT, + _INDIC_AKHN, + INDIC_RPHF, + _INDIC_RKRF, + INDIC_PREF, + INDIC_BLWF, + INDIC_ABVF, + INDIC_HALF, + INDIC_PSTF, + _INDIC_VATU, + _INDIC_CJCT, - INIT, - _PRES, - _ABVS, - _BLWS, - _PSTS, - _HALN, + INDIC_INIT, + _INDIC_PRES, + _INDIC_ABVS, + _INDIC_BLWS, + _INDIC_PSTS, + _INDIC_HALN, - _DIST, - _ABVM, - _BLWM, + _INDIC_DIST, + _INDIC_ABVM, + _INDIC_BLWM, INDIC_NUM_FEATURES, - INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */ + INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */ }; static void @@ -467,7 +467,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * and has more than one consonant, Ra is excluded from candidates for * base consonants. */ unsigned int limit = start; - if (indic_plan->mask_array[RPHF] && + if (indic_plan->mask_array[INDIC_RPHF] && start + 3 <= end && ( (indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) || @@ -803,13 +803,13 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Reph */ for (unsigned int i = start; i < end && info[i].indic_position() == POS_RA_TO_BECOME_REPH; i++) - info[i].mask |= indic_plan->mask_array[RPHF]; + info[i].mask |= indic_plan->mask_array[INDIC_RPHF]; /* Pre-base */ - mask = indic_plan->mask_array[HALF]; + mask = indic_plan->mask_array[INDIC_HALF]; if (!indic_plan->is_old_spec && indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST) - mask |= indic_plan->mask_array[BLWF]; + mask |= indic_plan->mask_array[INDIC_BLWF]; for (unsigned int i = start; i < base; i++) info[i].mask |= mask; /* Base */ @@ -817,7 +817,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, if (base < end) info[base].mask |= mask; /* Post-base */ - mask = indic_plan->mask_array[BLWF] | indic_plan->mask_array[ABVF] | indic_plan->mask_array[PSTF]; + mask = indic_plan->mask_array[INDIC_BLWF] | + indic_plan->mask_array[INDIC_ABVF] | + indic_plan->mask_array[INDIC_PSTF]; for (unsigned int i = base + 1; i < end; i++) info[i].mask |= mask; } @@ -849,13 +851,13 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, (i + 2 == base || info[i+2].indic_category() != OT_ZWJ)) { - info[i ].mask |= indic_plan->mask_array[BLWF]; - info[i+1].mask |= indic_plan->mask_array[BLWF]; + info[i ].mask |= indic_plan->mask_array[INDIC_BLWF]; + info[i+1].mask |= indic_plan->mask_array[INDIC_BLWF]; } } unsigned int pref_len = 2; - if (indic_plan->mask_array[PREF] && base + pref_len < end) + if (indic_plan->mask_array[INDIC_PREF] && base + pref_len < end) { /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */ for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) { @@ -865,7 +867,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, if (indic_plan->pref.would_substitute (glyphs, pref_len, face)) { for (unsigned int j = 0; j < pref_len; j++) - info[i++].mask |= indic_plan->mask_array[PREF]; + info[i++].mask |= indic_plan->mask_array[INDIC_PREF]; break; } } @@ -886,7 +888,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* A ZWNJ disables HALF. */ if (non_joiner) - info[j].mask &= ~indic_plan->mask_array[HALF]; + info[j].mask &= ~indic_plan->mask_array[INDIC_HALF]; } while (j > start && !is_consonant (info[j])); } @@ -1053,7 +1055,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * syllable. */ - bool try_pref = !!indic_plan->mask_array[PREF]; + bool try_pref = !!indic_plan->mask_array[INDIC_PREF]; /* Find base again */ unsigned int base; @@ -1063,7 +1065,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (try_pref && base + 1 < end) { for (unsigned int i = base + 1; i < end; i++) - if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) + if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0) { if (!(_hb_glyph_info_substituted (&info[i]) && _hb_glyph_info_ligated_and_didnt_multiply (&info[i]))) @@ -1385,7 +1387,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */ { for (unsigned int i = base + 1; i < end; i++) - if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) + if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0) { /* 1. Only reorder a glyph produced by substitution during application * of the feature. (Note that a font may shape a Ra consonant with @@ -1448,7 +1450,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (!start || !(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) & FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) - info[start].mask |= indic_plan->mask_array[INIT]; + info[start].mask |= indic_plan->mask_array[INDIC_INIT]; else buffer->unsafe_to_break (start - 1, start + 1); } diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc index 2bc62bb56..6eec2438d 100644 --- a/src/hb-ot-shape-complex-khmer.cc +++ b/src/hb-ot-shape-complex-khmer.cc @@ -69,23 +69,23 @@ khmer_features[] = * Must be in the same order as the khmer_features array. */ enum { - PREF, - BLWF, - ABVF, - PSTF, - CFAR, + KHMER_PREF, + KHMER_BLWF, + KHMER_ABVF, + KHMER_PSTF, + KHMER_CFAR, - _PRES, - _ABVS, - _BLWS, - _PSTS, + _KHMER_PRES, + _KHMER_ABVS, + _KHMER_BLWS, + _KHMER_PSTS, - _DIST, - _ABVM, - _BLWM, + _KHMER_DIST, + _KHMER_ABVM, + _KHMER_BLWM, KHMER_NUM_FEATURES, - KHMER_BASIC_FEATURES = _PRES, /* Don't forget to update this! */ + KHMER_BASIC_FEATURES = _KHMER_PRES, /* Don't forget to update this! */ }; static void @@ -252,7 +252,9 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Setup masks. */ { /* Post-base */ - hb_mask_t mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF]; + hb_mask_t mask = khmer_plan->mask_array[KHMER_BLWF] | + khmer_plan->mask_array[KHMER_ABVF] | + khmer_plan->mask_array[KHMER_PSTF]; for (unsigned int i = start + 1; i < end; i++) info[i].mask |= mask; } @@ -279,7 +281,7 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan, if (info[i + 1].khmer_category() == OT_Ra) { for (unsigned int j = 0; j < 2; j++) - info[i + j].mask |= khmer_plan->mask_array[PREF]; + info[i + j].mask |= khmer_plan->mask_array[KHMER_PREF]; /* Move the Coeng,Ro sequence to the start. */ buffer->merge_clusters (start, i + 2); @@ -295,9 +297,9 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan, * U+1784,U+17D2,U+179A,U+17D2,U+1782 * U+1784,U+17D2,U+1782,U+17D2,U+179A */ - if (khmer_plan->mask_array[CFAR]) + if (khmer_plan->mask_array[KHMER_CFAR]) for (unsigned int j = i + 2; j < end; j++) - info[j].mask |= khmer_plan->mask_array[CFAR]; + info[j].mask |= khmer_plan->mask_array[KHMER_CFAR]; num_coengs = 2; /* Done. */ } diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index f3b150d1c..003d897b2 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -59,7 +59,7 @@ use_basic_features[] = HB_TAG('c','j','c','t'), }; static const hb_tag_t -use_arabic_features[] = +use_topographical_features[] = { HB_TAG('i','s','o','l'), HB_TAG('i','n','i','t'), @@ -71,13 +71,13 @@ use_arabic_features[] = HB_TAG('f','i','n','2'), HB_TAG('f','i','n','3'), }; -/* Same order as use_arabic_features. Don't need Syriac stuff.*/ +/* Same order as use_topographical_features. Don't need Syriac stuff.*/ enum joining_form_t { - ISOL, - INIT, - MEDI, - FINA, - _NONE + USE_ISOL, + USE_INIT, + USE_MEDI, + USE_FINA, + _USE_NONE }; static const hb_tag_t use_other_features[] = @@ -152,8 +152,8 @@ collect_features_use (hb_ot_shape_planner_t *plan) map->add_gsub_pause (_hb_clear_syllables); /* "Topographical features" */ - for (unsigned int i = 0; i < ARRAY_LENGTH (use_arabic_features); i++) - map->add_feature (use_arabic_features[i]); + for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++) + map->add_feature (use_topographical_features[i]); map->add_gsub_pause (nullptr); /* "Standard typographic presentation" */ @@ -305,11 +305,11 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, if (use_plan->arabic_plan) return; - static_assert ((INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4), ""); + static_assert ((USE_INIT < 4 && USE_ISOL < 4 && USE_MEDI < 4 && USE_FINA < 4), ""); hb_mask_t masks[4], all_masks = 0; for (unsigned int i = 0; i < 4; i++) { - masks[i] = plan->map.get_1_mask (use_arabic_features[i]); + masks[i] = plan->map.get_1_mask (use_topographical_features[i]); if (masks[i] == plan->map.get_global_mask ()) masks[i] = 0; all_masks |= masks[i]; @@ -319,7 +319,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, hb_mask_t other_masks = ~all_masks; unsigned int last_start = 0; - joining_form_t last_form = _NONE; + joining_form_t last_form = _USE_NONE; hb_glyph_info_t *info = buffer->info; foreach_syllable (buffer, start, end) { @@ -330,7 +330,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, case use_symbol_cluster: case use_non_cluster: /* These don't join. Nothing to do. */ - last_form = _NONE; + last_form = _USE_NONE; break; case use_virama_terminated_cluster: @@ -340,18 +340,18 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, case use_numeral_cluster: case use_broken_cluster: - bool join = last_form == FINA || last_form == ISOL; + bool join = last_form == USE_FINA || last_form == USE_ISOL; if (join) { /* Fixup previous syllable's form. */ - last_form = last_form == FINA ? MEDI : INIT; + last_form = last_form == USE_FINA ? USE_MEDI : USE_INIT; for (unsigned int i = last_start; i < start; i++) info[i].mask = (info[i].mask & other_masks) | masks[last_form]; } /* Form for this syllable. */ - last_form = join ? FINA : ISOL; + last_form = join ? USE_FINA : USE_ISOL; for (unsigned int i = start; i < end; i++) info[i].mask = (info[i].mask & other_masks) | masks[last_form]; From eb37bc9d93b3abebee24390708940510fe37477a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 15:19:39 -0700 Subject: [PATCH 117/138] [use] Remove Syriac features This was non-standard, and unused anyway. --- src/hb-ot-shape-complex-use.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 003d897b2..0a8c4e5d0 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -65,13 +65,8 @@ use_topographical_features[] = HB_TAG('i','n','i','t'), HB_TAG('m','e','d','i'), HB_TAG('f','i','n','a'), - /* The spec doesn't specify these but we apply anyway, since our Arabic shaper - * does. These are only used in Syriac spec. */ - HB_TAG('m','e','d','2'), - HB_TAG('f','i','n','2'), - HB_TAG('f','i','n','3'), }; -/* Same order as use_topographical_features. Don't need Syriac stuff.*/ +/* Same order as use_topographical_features. */ enum joining_form_t { USE_ISOL, USE_INIT, From 3724f13ba0292055197efdbfcacfe3d7b067175c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 15:23:00 -0700 Subject: [PATCH 118/138] [amalgam] Finish fixing Indic-like shapers Part of https://github.com/harfbuzz/harfbuzz/issues/1809 --- src/hb-ot-shape-complex-indic.cc | 34 +++++++++++++++--------------- src/hb-ot-shape-complex-indic.hh | 9 +++++++- src/hb-ot-shape-complex-khmer.cc | 18 ++++++++-------- src/hb-ot-shape-complex-khmer.hh | 17 +++++++-------- src/hb-ot-shape-complex-myanmar.cc | 8 +++---- src/hb-ot-shape-complex-myanmar.hh | 16 +++++++------- src/hb-ot-shape-complex-use.cc | 14 ++++++------ 7 files changed, 61 insertions(+), 55 deletions(-) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 43f377b66..fd099cac7 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -392,9 +392,9 @@ compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) static void -update_consonant_positions (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) +update_consonant_positions_indic (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; @@ -917,10 +917,10 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan, } static void -initial_reordering_syllable (const hb_ot_shape_plan_t *plan, - hb_face_t *face, - hb_buffer_t *buffer, - unsigned int start, unsigned int end) +initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan, + hb_face_t *face, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) { indic_syllable_type_t syllable_type = (indic_syllable_type_t) (buffer->info[start].syllable() & 0x0F); switch (syllable_type) @@ -942,9 +942,9 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, } static inline void -insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font, - hb_buffer_t *buffer) +insert_dotted_circles_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font, + hb_buffer_t *buffer) { if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) return; @@ -1009,17 +1009,17 @@ initial_reordering_indic (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - update_consonant_positions (plan, font, buffer); - insert_dotted_circles (plan, font, buffer); + update_consonant_positions_indic (plan, font, buffer); + insert_dotted_circles_indic (plan, font, buffer); foreach_syllable (buffer, start, end) - initial_reordering_syllable (plan, font->face, buffer, start, end); + initial_reordering_syllable_indic (plan, font->face, buffer, start, end); } static void -final_reordering_syllable (const hb_ot_shape_plan_t *plan, - hb_buffer_t *buffer, - unsigned int start, unsigned int end) +final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) { const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; hb_glyph_info_t *info = buffer->info; @@ -1488,7 +1488,7 @@ final_reordering_indic (const hb_ot_shape_plan_t *plan, if (unlikely (!count)) return; foreach_syllable (buffer, start, end) - final_reordering_syllable (plan, buffer, start, end); + final_reordering_syllable_indic (plan, buffer, start, end); HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category); HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position); diff --git a/src/hb-ot-shape-complex-indic.hh b/src/hb-ot-shape-complex-indic.hh index f3f195806..1eeed68c5 100644 --- a/src/hb-ot-shape-complex-indic.hh +++ b/src/hb-ot-shape-complex-indic.hh @@ -64,7 +64,14 @@ enum indic_category_t { OT_Ra = 16, OT_CM = 17, /* Consonant-Medial. */ OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */ - OT_CS = 19 + OT_CS = 19, + + /* The following are used by Khmer & Myanmar shapers. Defined + * here for them to share. */ + OT_VAbv = 26, + OT_VBlw = 27, + OT_VPre = 28, + OT_VPst = 29, }; #define MEDIAL_FLAGS (FLAG (OT_CM)) diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc index 6eec2438d..b1fa0156a 100644 --- a/src/hb-ot-shape-complex-khmer.cc +++ b/src/hb-ot-shape-complex-khmer.cc @@ -318,10 +318,10 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan, } static void -initial_reordering_syllable (const hb_ot_shape_plan_t *plan, - hb_face_t *face, - hb_buffer_t *buffer, - unsigned int start, unsigned int end) +reorder_syllable_khmer (const hb_ot_shape_plan_t *plan, + hb_face_t *face, + hb_buffer_t *buffer, + unsigned int start, unsigned int end) { khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (buffer->info[start].syllable() & 0x0F); switch (syllable_type) @@ -337,9 +337,9 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, } static inline void -insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font, - hb_buffer_t *buffer) +insert_dotted_circles_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font, + hb_buffer_t *buffer) { if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) return; @@ -404,10 +404,10 @@ reorder_khmer (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - insert_dotted_circles (plan, font, buffer); + insert_dotted_circles_khmer (plan, font, buffer); foreach_syllable (buffer, start, end) - initial_reordering_syllable (plan, font->face, buffer, start, end); + reorder_syllable_khmer (plan, font->face, buffer, start, end); HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category); } diff --git a/src/hb-ot-shape-complex-khmer.hh b/src/hb-ot-shape-complex-khmer.hh index 21015c730..11a77bfd4 100644 --- a/src/hb-ot-shape-complex-khmer.hh +++ b/src/hb-ot-shape-complex-khmer.hh @@ -43,11 +43,10 @@ enum khmer_category_t OT_Robatic = 20, OT_Xgroup = 21, OT_Ygroup = 22, - - OT_VAbv = 26, - OT_VBlw = 27, - OT_VPre = 28, - OT_VPst = 29, + //OT_VAbv = 26, + //OT_VBlw = 27, + //OT_VPre = 28, + //OT_VPst = 29, }; static inline void @@ -100,10 +99,10 @@ set_khmer_properties (hb_glyph_info_t &info) if (cat == (khmer_category_t) OT_M) switch ((int) pos) { - case POS_PRE_C: cat = OT_VPre; break; - case POS_BELOW_C: cat = OT_VBlw; break; - case POS_ABOVE_C: cat = OT_VAbv; break; - case POS_POST_C: cat = OT_VPst; break; + case POS_PRE_C: cat = (khmer_category_t) OT_VPre; break; + case POS_BELOW_C: cat = (khmer_category_t) OT_VBlw; break; + case POS_ABOVE_C: cat = (khmer_category_t) OT_VAbv; break; + case POS_POST_C: cat = (khmer_category_t) OT_VPst; break; default: assert (0); } diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index 21793b4c4..14d215eac 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -294,9 +294,9 @@ reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, } static inline void -insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font, - hb_buffer_t *buffer) +insert_dotted_circles_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font, + hb_buffer_t *buffer) { if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) return; @@ -355,7 +355,7 @@ reorder_myanmar (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - insert_dotted_circles (plan, font, buffer); + insert_dotted_circles_myanmar (plan, font, buffer); foreach_syllable (buffer, start, end) reorder_syllable_myanmar (plan, font->face, buffer, start, end); diff --git a/src/hb-ot-shape-complex-myanmar.hh b/src/hb-ot-shape-complex-myanmar.hh index 9ec78ef89..7b9821e6b 100644 --- a/src/hb-ot-shape-complex-myanmar.hh +++ b/src/hb-ot-shape-complex-myanmar.hh @@ -49,10 +49,10 @@ enum myanmar_category_t { OT_MW = 23, /* Various consonant medial types */ OT_MY = 24, /* Various consonant medial types */ OT_PT = 25, /* Pwo and other tones */ - OT_VAbv = 26, - OT_VBlw = 27, - OT_VPre = 28, - OT_VPst = 29, + //OT_VAbv = 26, + //OT_VBlw = 27, + //OT_VPre = 28, + //OT_VPst = 29, OT_VS = 30, /* Variation selectors */ OT_P = 31, /* Punctuation */ OT_D = 32, /* Digits except zero */ @@ -155,11 +155,11 @@ set_myanmar_properties (hb_glyph_info_t &info) { switch ((int) pos) { - case POS_PRE_C: cat = OT_VPre; + case POS_PRE_C: cat = (myanmar_category_t) OT_VPre; pos = POS_PRE_M; break; - case POS_ABOVE_C: cat = OT_VAbv; break; - case POS_BELOW_C: cat = OT_VBlw; break; - case POS_POST_C: cat = OT_VPst; break; + case POS_ABOVE_C: cat = (myanmar_category_t) OT_VAbv; break; + case POS_BELOW_C: cat = (myanmar_category_t) OT_VBlw; break; + case POS_POST_C: cat = (myanmar_category_t) OT_VPst; break; } } diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 0a8c4e5d0..1ea2957f2 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -412,7 +412,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED, } static inline bool -is_halant (const hb_glyph_info_t &info) +is_halant_use (const hb_glyph_info_t &info) { return (info.use_category() == USE_H || info.use_category() == USE_HVM) && !_hb_glyph_info_ligated (&info); @@ -458,7 +458,7 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) for (unsigned int i = start + 1; i < end; i++) { bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) || - is_halant (info[i]); + is_halant_use (info[i]); if (is_post_base_glyph || i == end - 1) { /* If we hit a post-base glyph, move before it; otherwise move to the @@ -482,7 +482,7 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) for (unsigned int i = start; i < end; i++) { uint32_t flag = FLAG_UNSAFE (info[i].use_category()); - if (is_halant (info[i])) + if (is_halant_use (info[i])) { /* If we hit a halant, move after it; otherwise move to the beginning, and * shift things in between forward. */ @@ -502,9 +502,9 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) } static inline void -insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font, - hb_buffer_t *buffer) +insert_dotted_circles_use (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font, + hb_buffer_t *buffer) { if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) return; @@ -564,7 +564,7 @@ reorder_use (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - insert_dotted_circles (plan, font, buffer); + insert_dotted_circles_use (plan, font, buffer); foreach_syllable (buffer, start, end) reorder_syllable_use (buffer, start, end); From 7ca54811f471a28163de6b3c561990c85aa39880 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 16:00:58 -0700 Subject: [PATCH 119/138] [amalgam] Fix CFF Part of https://github.com/harfbuzz/harfbuzz/issues/1809 --- src/hb-ot-cff1-table.cc | 18 +++++++++--------- src/hb-ot-cff2-table.cc | 16 ++++++++-------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/hb-ot-cff1-table.cc b/src/hb-ot-cff1-table.cc index 3238ad73a..3e4fc204f 100644 --- a/src/hb-ot-cff1-table.cc +++ b/src/hb-ot-cff1-table.cc @@ -210,7 +210,7 @@ struct bounds_t point_t max; }; -struct extents_param_t +struct cff1_extents_param_t { void init (const OT::cff1::accelerator_t *_cff) { @@ -229,15 +229,15 @@ struct extents_param_t const OT::cff1::accelerator_t *cff; }; -struct cff1_path_procs_extents_t : path_procs_t +struct cff1_path_procs_extents_t : path_procs_t { - static void moveto (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt) + static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt) { param.end_path (); env.moveto (pt); } - static void line (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1) + static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1) { if (!param.is_path_open ()) { @@ -248,7 +248,7 @@ struct cff1_path_procs_extents_t : path_procs_t +struct cff1_cs_opset_extents_t : cff1_cs_opset_t { - static void process_seac (cff1_cs_interp_env_t &env, extents_param_t& param) + static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param) { unsigned int n = env.argStack.get_count (); point_t delta; @@ -296,11 +296,11 @@ bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, boun if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; unsigned int fd = cff->fdSelect->get_fd (glyph); - cff1_cs_interpreter_t interp; + cff1_cs_interpreter_t interp; const byte_str_t str = (*cff->charStrings)[glyph]; interp.env.init (str, *cff, fd); interp.env.set_in_seac (in_seac); - extents_param_t param; + cff1_extents_param_t param; param.init (cff); if (unlikely (!interp.interpret (param))) return false; bounds = param.bounds; diff --git a/src/hb-ot-cff2-table.cc b/src/hb-ot-cff2-table.cc index 9c9e37bd0..33b51fea4 100644 --- a/src/hb-ot-cff2-table.cc +++ b/src/hb-ot-cff2-table.cc @@ -33,7 +33,7 @@ using namespace CFF; -struct extents_param_t +struct cff2_extents_param_t { void init () { @@ -63,15 +63,15 @@ struct extents_param_t number_t max_y; }; -struct cff2_path_procs_extents_t : path_procs_t +struct cff2_path_procs_extents_t : path_procs_t { - static void moveto (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt) + static void moveto (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt) { param.end_path (); env.moveto (pt); } - static void line (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1) + static void line (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1) { if (!param.is_path_open ()) { @@ -82,7 +82,7 @@ struct cff2_path_procs_extents_t : path_procs_t {}; +struct cff2_cs_opset_extents_t : cff2_cs_opset_t {}; bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, @@ -113,10 +113,10 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, unsigned int num_coords; const int *coords = hb_font_get_var_coords_normalized (font, &num_coords); unsigned int fd = fdSelect->get_fd (glyph); - cff2_cs_interpreter_t interp; + cff2_cs_interpreter_t interp; const byte_str_t str = (*charStrings)[glyph]; interp.env.init (str, *this, fd, coords, num_coords); - extents_param_t param; + cff2_extents_param_t param; param.init (); if (unlikely (!interp.interpret (param))) return false; From ceb4c212dc91a277f646c4a5354e4362f548a9f6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 16:02:13 -0700 Subject: [PATCH 120/138] [amalgam] Fix UCD issue This actually makes it build now! Part https://github.com/harfbuzz/harfbuzz/issues/1809 Keeping open to add tests, CI, etc. --- src/hb-ucd.cc | 5 +---- src/hb-unicode.cc | 2 -- src/hb-unicode.hh | 3 +++ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/hb-ucd.cc b/src/hb-ucd.cc index 69949a288..b29f2a9c7 100644 --- a/src/hb-ucd.cc +++ b/src/hb-ucd.cc @@ -15,6 +15,7 @@ */ #include "hb.hh" +#include "hb-unicode.hh" #include "hb-machinery.hh" #include "hb-ucd-table.hh" @@ -235,10 +236,6 @@ void free_static_ucd_funcs () } #endif -extern "C" HB_INTERNAL -hb_unicode_funcs_t * -hb_ucd_get_unicode_funcs (); - hb_unicode_funcs_t * hb_ucd_get_unicode_funcs () { diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index ed4fb7782..e2deaa240 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -126,8 +126,6 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED } #endif - -extern "C" hb_unicode_funcs_t *hb_ucd_get_unicode_funcs (); extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs (); extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs (); diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh index 021fa461d..9b181c11c 100644 --- a/src/hb-unicode.hh +++ b/src/hb-unicode.hh @@ -395,4 +395,7 @@ HB_INTERNAL bool _hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp); +extern "C" HB_INTERNAL hb_unicode_funcs_t *hb_ucd_get_unicode_funcs (); + + #endif /* HB_UNICODE_HH */ From 62e60322cb9e18b3ee75f1b4a2a6d3069f587407 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 16:07:03 -0700 Subject: [PATCH 121/138] Minor --- src/hb-unicode.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index e2deaa240..663415b26 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -126,17 +126,16 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED } #endif -extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs (); -extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs (); - hb_unicode_funcs_t * hb_unicode_funcs_get_default () { #if !defined(HB_NO_UNICODE_FUNCS) && !defined(HB_NO_UCD) return hb_ucd_get_unicode_funcs (); #elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_GLIB) + extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs (); return hb_glib_get_unicode_funcs (); #elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN) + extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs (); return hb_icu_get_unicode_funcs (); #else #define HB_UNICODE_FUNCS_NIL 1 From 04a4957040380bba58880ff51d529c5cccf1d2c7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 16:19:18 -0700 Subject: [PATCH 122/138] [amalgam] Add hb.cc to git Part of https://github.com/harfbuzz/harfbuzz/issues/1809 --- src/Makefile.am | 1 + src/hb.cc | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/hb.cc diff --git a/src/Makefile.am b/src/Makefile.am index c276118e8..0d85dd757 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -308,6 +308,7 @@ hb.cc: Makefile.sources for f in $(HB_BASE_sources); do echo '#include "'$$f'"'; done | \ grep '[.]cc"' > $(srcdir)/hb.cc \ || ($(RM) $(srcdir)/hb.cc; false) +EXTRA_DIST += hb.cc noinst_PROGRAMS = \ main \ diff --git a/src/hb.cc b/src/hb.cc new file mode 100644 index 000000000..a9581d246 --- /dev/null +++ b/src/hb.cc @@ -0,0 +1,44 @@ +#include "hb-aat-layout.cc" +#include "hb-aat-map.cc" +#include "hb-blob.cc" +#include "hb-buffer-serialize.cc" +#include "hb-buffer.cc" +#include "hb-common.cc" +#include "hb-face.cc" +#include "hb-fallback-shape.cc" +#include "hb-font.cc" +#include "hb-map.cc" +#include "hb-ot-cff1-table.cc" +#include "hb-ot-cff2-table.cc" +#include "hb-ot-color.cc" +#include "hb-ot-face.cc" +#include "hb-ot-font.cc" +#include "hb-ot-layout.cc" +#include "hb-ot-map.cc" +#include "hb-ot-math.cc" +#include "hb-ot-name.cc" +#include "hb-ot-shape-complex-arabic.cc" +#include "hb-ot-shape-complex-default.cc" +#include "hb-ot-shape-complex-hangul.cc" +#include "hb-ot-shape-complex-hebrew.cc" +#include "hb-ot-shape-complex-indic-table.cc" +#include "hb-ot-shape-complex-indic.cc" +#include "hb-ot-shape-complex-khmer.cc" +#include "hb-ot-shape-complex-myanmar.cc" +#include "hb-ot-shape-complex-thai.cc" +#include "hb-ot-shape-complex-use-table.cc" +#include "hb-ot-shape-complex-use.cc" +#include "hb-ot-shape-complex-vowel-constraints.cc" +#include "hb-ot-shape-fallback.cc" +#include "hb-ot-shape-normalize.cc" +#include "hb-ot-shape.cc" +#include "hb-ot-tag.cc" +#include "hb-ot-var.cc" +#include "hb-set.cc" +#include "hb-shape-plan.cc" +#include "hb-shape.cc" +#include "hb-shaper.cc" +#include "hb-static.cc" +#include "hb-ucd.cc" +#include "hb-unicode.cc" +#include "hb-warning.cc" From df4448064e370a410404708a15ce819daf1d9386 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 17:11:09 -0700 Subject: [PATCH 123/138] Remove unused 'inline' specifier --- src/hb-ot-map.hh | 4 ++-- src/hb-shape-plan.hh | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh index dd6778638..0a4827d74 100644 --- a/src/hb-ot-map.hh +++ b/src/hb-ot-map.hh @@ -154,8 +154,8 @@ struct hb_ot_map_t HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const; template - HB_INTERNAL inline void apply (const Proxy &proxy, - const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const; + HB_INTERNAL void apply (const Proxy &proxy, + const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const; HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const; HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const; diff --git a/src/hb-shape-plan.hh b/src/hb-shape-plan.hh index 8e8d7632b..6da7edb2f 100644 --- a/src/hb-shape-plan.hh +++ b/src/hb-shape-plan.hh @@ -46,16 +46,16 @@ struct hb_shape_plan_key_t hb_shape_func_t *shaper_func; const char *shaper_name; - HB_INTERNAL inline bool init (bool copy, - hb_face_t *face, - const hb_segment_properties_t *props, - const hb_feature_t *user_features, - unsigned int num_user_features, - const int *coords, - unsigned int num_coords, - const char * const *shaper_list); + HB_INTERNAL bool init (bool copy, + hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list); - HB_INTERNAL inline void free () { ::free ((void *) user_features); } + HB_INTERNAL void free () { ::free ((void *) user_features); } HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other); From 2e48fd077954410f59156b3100c16bf56a507948 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 17:55:58 -0700 Subject: [PATCH 124/138] Sprinkle constexpr around Being conservative. Also not sure it makes any real difference in our codebase. --- src/hb-algs.hh | 48 ++++++++++++++++++++++++------------------------ src/hb-meta.hh | 18 +++++++++--------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index c8d83c828..788689478 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -50,31 +50,31 @@ struct { /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */ - template auto + template constexpr auto operator () (T&& v) const HB_AUTO_RETURN ( hb_forward (v) ) } HB_FUNCOBJ (hb_identity); struct { /* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */ - template T& + template constexpr T& operator () (T& v) const { return v; } - template hb_remove_reference + template constexpr hb_remove_reference operator () (T&& v) const { return v; } } HB_FUNCOBJ (hb_lidentity); struct { /* Like identity(), but always returns rvalue. */ - template hb_remove_reference + template constexpr hb_remove_reference operator () (T&& v) const { return v; } } HB_FUNCOBJ (hb_ridentity); struct { - template bool + template constexpr bool operator () (T&& v) const { return bool (hb_forward (v)); } } HB_FUNCOBJ (hb_bool); @@ -82,11 +82,11 @@ HB_FUNCOBJ (hb_bool); struct { private: - template auto + template constexpr auto impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) template auto + hb_enable_if (hb_is_integral (T))> constexpr auto impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN ( /* Knuth's multiplicative method: */ @@ -95,7 +95,7 @@ struct public: - template auto + template constexpr auto operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize)) } HB_FUNCOBJ (hb_hash); @@ -328,14 +328,14 @@ hb_pair (T1&& a, T2&& b) { return hb_pair_t (a, b); } struct { - template typename Pair::first_t + template constexpr typename Pair::first_t operator () (const Pair& pair) const { return pair.first; } } HB_FUNCOBJ (hb_first); struct { - template typename Pair::second_t + template constexpr typename Pair::second_t operator () (const Pair& pair) const { return pair.second; } } HB_FUNCOBJ (hb_second); @@ -346,14 +346,14 @@ HB_FUNCOBJ (hb_second); * comparing integers of different signedness. */ struct { - template auto + template constexpr auto operator () (T&& a, T2&& b) const HB_AUTO_RETURN (hb_forward (a) <= hb_forward (b) ? hb_forward (a) : hb_forward (b)) } HB_FUNCOBJ (hb_min); struct { - template auto + template constexpr auto operator () (T&& a, T2&& b) const HB_AUTO_RETURN (hb_forward (a) >= hb_forward (b) ? hb_forward (a) : hb_forward (b)) } @@ -917,7 +917,7 @@ struct hb_bitwise_and { HB_PARTIALIZE(2); static constexpr bool passthru_left = false; static constexpr bool passthru_right = false; - template auto + template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b) } HB_FUNCOBJ (hb_bitwise_and); @@ -925,7 +925,7 @@ struct hb_bitwise_or { HB_PARTIALIZE(2); static constexpr bool passthru_left = true; static constexpr bool passthru_right = true; - template auto + template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b) } HB_FUNCOBJ (hb_bitwise_or); @@ -933,7 +933,7 @@ struct hb_bitwise_xor { HB_PARTIALIZE(2); static constexpr bool passthru_left = true; static constexpr bool passthru_right = true; - template auto + template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b) } HB_FUNCOBJ (hb_bitwise_xor); @@ -941,56 +941,56 @@ struct hb_bitwise_sub { HB_PARTIALIZE(2); static constexpr bool passthru_left = true; static constexpr bool passthru_right = false; - template auto + template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b) } HB_FUNCOBJ (hb_bitwise_sub); struct { - template auto + template constexpr auto operator () (const T &a) const HB_AUTO_RETURN (~a) } HB_FUNCOBJ (hb_bitwise_neg); struct { HB_PARTIALIZE(2); - template auto + template constexpr auto operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b) } HB_FUNCOBJ (hb_add); struct { HB_PARTIALIZE(2); - template auto + template constexpr auto operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b) } HB_FUNCOBJ (hb_sub); struct { HB_PARTIALIZE(2); - template auto + template constexpr auto operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b) } HB_FUNCOBJ (hb_mul); struct { HB_PARTIALIZE(2); - template auto + template constexpr auto operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b) } HB_FUNCOBJ (hb_div); struct { HB_PARTIALIZE(2); - template auto + template constexpr auto operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b) } HB_FUNCOBJ (hb_mod); struct { - template auto + template constexpr auto operator () (const T &a) const HB_AUTO_RETURN (+a) } HB_FUNCOBJ (hb_pos); struct { - template auto + template constexpr auto operator () (const T &a) const HB_AUTO_RETURN (-a) } HB_FUNCOBJ (hb_neg); diff --git a/src/hb-meta.hh b/src/hb-meta.hh index df8ebd175..2dfaeb7b4 100644 --- a/src/hb-meta.hh +++ b/src/hb-meta.hh @@ -80,8 +80,8 @@ template using hb_type_identity = typename hb_type_identity_t::t struct { - template - T* operator () (T& arg) const + template constexpr T* + operator () (T& arg) const { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" @@ -171,29 +171,29 @@ using hb_is_cr_convertible = hb_bool_constant< /* std::move and std::forward */ template -static hb_remove_reference&& hb_move (T&& t) { return (hb_remove_reference&&) (t); } +static constexpr hb_remove_reference&& hb_move (T&& t) { return (hb_remove_reference&&) (t); } template -static T&& hb_forward (hb_remove_reference& t) { return (T&&) t; } +static constexpr T&& hb_forward (hb_remove_reference& t) { return (T&&) t; } template -static T&& hb_forward (hb_remove_reference&& t) { return (T&&) t; } +static constexpr T&& hb_forward (hb_remove_reference&& t) { return (T&&) t; } struct { - template auto + template constexpr auto operator () (T&& v) const HB_AUTO_RETURN (hb_forward (v)) - template auto + template constexpr auto operator () (T *v) const HB_AUTO_RETURN (*v) } HB_FUNCOBJ (hb_deref); struct { - template auto + template constexpr auto operator () (T&& v) const HB_AUTO_RETURN (hb_forward (v)) - template auto + template constexpr auto operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v)) } HB_FUNCOBJ (hb_ref); From c4aa10ebc8dc28b1f9c90af2ca2092a7535f8395 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 19:15:03 -0700 Subject: [PATCH 125/138] Use constexpr to replace passthru_ bools --- src/hb-algs.hh | 8 -------- src/hb-set.hh | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index 788689478..5d8c8dd82 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -915,32 +915,24 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o struct hb_bitwise_and { HB_PARTIALIZE(2); - static constexpr bool passthru_left = false; - static constexpr bool passthru_right = false; template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b) } HB_FUNCOBJ (hb_bitwise_and); struct hb_bitwise_or { HB_PARTIALIZE(2); - static constexpr bool passthru_left = true; - static constexpr bool passthru_right = true; template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b) } HB_FUNCOBJ (hb_bitwise_or); struct hb_bitwise_xor { HB_PARTIALIZE(2); - static constexpr bool passthru_left = true; - static constexpr bool passthru_right = true; template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b) } HB_FUNCOBJ (hb_bitwise_xor); struct hb_bitwise_sub { HB_PARTIALIZE(2); - static constexpr bool passthru_left = true; - static constexpr bool passthru_right = false; template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b) } diff --git a/src/hb-set.hh b/src/hb-set.hh index ad449d0ce..11034af4b 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -448,6 +448,8 @@ struct hb_set_t dirty (); + constexpr bool passthru_left = op (0, 0) || op (1, 0); + constexpr bool passthru_right = op (0, 0) || op (0, 1); unsigned int na = pages.length; unsigned int nb = other->pages.length; unsigned int next_page = na; @@ -464,20 +466,20 @@ struct hb_set_t } else if (page_map[a].major < other->page_map[b].major) { - if (Op::passthru_left) + if (passthru_left) count++; a++; } else { - if (Op::passthru_right) + if (passthru_right) count++; b++; } } - if (Op::passthru_left) + if (passthru_left) count += na - a; - if (Op::passthru_right) + if (passthru_right) count += nb - b; if (count > pages.length) @@ -501,7 +503,7 @@ struct hb_set_t else if (page_map[a - 1].major > other->page_map[b - 1].major) { a--; - if (Op::passthru_left) + if (passthru_left) { count--; page_map[count] = page_map[a]; @@ -510,7 +512,7 @@ struct hb_set_t else { b--; - if (Op::passthru_right) + if (passthru_right) { count--; page_map[count].major = other->page_map[b].major; @@ -519,14 +521,14 @@ struct hb_set_t } } } - if (Op::passthru_left) + if (passthru_left) while (a) { a--; count--; page_map[count] = page_map [a]; } - if (Op::passthru_right) + if (passthru_right) while (b) { b--; From 4cb180d227c1adc32e921c241a93cd1f50a98d33 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 2 Jul 2019 19:44:18 -0700 Subject: [PATCH 126/138] Revert "Use constexpr to replace passthru_ bools" This reverts commit c4aa10ebc8dc28b1f9c90af2ca2092a7535f8395. Broke several compilers... Sigh. The version without constexpr didn't fully optimize out the unreachable code on clang. So, revert it is... --- src/hb-algs.hh | 8 ++++++++ src/hb-set.hh | 18 ++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index 5d8c8dd82..788689478 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -915,24 +915,32 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o struct hb_bitwise_and { HB_PARTIALIZE(2); + static constexpr bool passthru_left = false; + static constexpr bool passthru_right = false; template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b) } HB_FUNCOBJ (hb_bitwise_and); struct hb_bitwise_or { HB_PARTIALIZE(2); + static constexpr bool passthru_left = true; + static constexpr bool passthru_right = true; template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b) } HB_FUNCOBJ (hb_bitwise_or); struct hb_bitwise_xor { HB_PARTIALIZE(2); + static constexpr bool passthru_left = true; + static constexpr bool passthru_right = true; template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b) } HB_FUNCOBJ (hb_bitwise_xor); struct hb_bitwise_sub { HB_PARTIALIZE(2); + static constexpr bool passthru_left = true; + static constexpr bool passthru_right = false; template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b) } diff --git a/src/hb-set.hh b/src/hb-set.hh index 11034af4b..ad449d0ce 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -448,8 +448,6 @@ struct hb_set_t dirty (); - constexpr bool passthru_left = op (0, 0) || op (1, 0); - constexpr bool passthru_right = op (0, 0) || op (0, 1); unsigned int na = pages.length; unsigned int nb = other->pages.length; unsigned int next_page = na; @@ -466,20 +464,20 @@ struct hb_set_t } else if (page_map[a].major < other->page_map[b].major) { - if (passthru_left) + if (Op::passthru_left) count++; a++; } else { - if (passthru_right) + if (Op::passthru_right) count++; b++; } } - if (passthru_left) + if (Op::passthru_left) count += na - a; - if (passthru_right) + if (Op::passthru_right) count += nb - b; if (count > pages.length) @@ -503,7 +501,7 @@ struct hb_set_t else if (page_map[a - 1].major > other->page_map[b - 1].major) { a--; - if (passthru_left) + if (Op::passthru_left) { count--; page_map[count] = page_map[a]; @@ -512,7 +510,7 @@ struct hb_set_t else { b--; - if (passthru_right) + if (Op::passthru_right) { count--; page_map[count].major = other->page_map[b].major; @@ -521,14 +519,14 @@ struct hb_set_t } } } - if (passthru_left) + if (Op::passthru_left) while (a) { a--; count--; page_map[count] = page_map [a]; } - if (passthru_right) + if (Op::passthru_right) while (b) { b--; From d51524204528b36907ab0f48bf2a48ec124c93d9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 3 Jul 2019 12:10:03 -0700 Subject: [PATCH 127/138] [amalgam] Rename hb.cc to harfbuzz.cc Part of https://github.com/harfbuzz/harfbuzz/issues/1809 --- src/Makefile.am | 8 ++++---- src/{hb.cc => harfbuzz.cc} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename src/{hb.cc => harfbuzz.cc} (100%) diff --git a/src/Makefile.am b/src/Makefile.am index 0d85dd757..746b8f022 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -303,12 +303,12 @@ $(srcdir)/%.hh: $(srcdir)/%.rl $(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \ || ($(RM) "$@"; false) -hb.cc: Makefile.sources +harfbuzz.cc: Makefile.sources $(AM_V_GEN) \ for f in $(HB_BASE_sources); do echo '#include "'$$f'"'; done | \ - grep '[.]cc"' > $(srcdir)/hb.cc \ - || ($(RM) $(srcdir)/hb.cc; false) -EXTRA_DIST += hb.cc + grep '[.]cc"' > $(srcdir)/harfbuzz.cc \ + || ($(RM) $(srcdir)/harfbuzz.cc; false) +EXTRA_DIST += harfbuzz.cc noinst_PROGRAMS = \ main \ diff --git a/src/hb.cc b/src/harfbuzz.cc similarity index 100% rename from src/hb.cc rename to src/harfbuzz.cc From b240d701fd98efa59a7f772ff39654fc95b8fc8f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 3 Jul 2019 12:17:57 -0700 Subject: [PATCH 128/138] [amalgam] Include integration source files as well Just for those that are normally built into libharfbuzz itself. Part of https://github.com/harfbuzz/harfbuzz/issues/1809 --- src/Makefile.am | 12 ++++++++++-- src/harfbuzz.cc | 6 ++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 746b8f022..5c15a3d3d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -305,10 +305,18 @@ $(srcdir)/%.hh: $(srcdir)/%.rl harfbuzz.cc: Makefile.sources $(AM_V_GEN) \ - for f in $(HB_BASE_sources); do echo '#include "'$$f'"'; done | \ + for f in \ + $(HB_BASE_sources) \ + $(HB_GLIB_sources) \ + $(HB_FT_sources) \ + $(HB_GRAPHITE2_sources) \ + $(HB_UNISCRIBE_sources) \ + $(HB_DIRECTWRITE_sources) \ + $(HB_CORETEXT_sources) \ + ; do echo '#include "'$$f'"'; done | \ grep '[.]cc"' > $(srcdir)/harfbuzz.cc \ || ($(RM) $(srcdir)/harfbuzz.cc; false) -EXTRA_DIST += harfbuzz.cc +BUILT_SOURCES += harfbuzz.cc noinst_PROGRAMS = \ main \ diff --git a/src/harfbuzz.cc b/src/harfbuzz.cc index a9581d246..8f5bb79a1 100644 --- a/src/harfbuzz.cc +++ b/src/harfbuzz.cc @@ -42,3 +42,9 @@ #include "hb-ucd.cc" #include "hb-unicode.cc" #include "hb-warning.cc" +#include "hb-glib.cc" +#include "hb-ft.cc" +#include "hb-graphite2.cc" +#include "hb-uniscribe.cc" +#include "hb-directwrite.cc" +#include "hb-coretext.cc" From 9fea6b4dd41bfe2b85f788523162658a7ab9bd49 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 5 Jul 2019 18:46:41 +0430 Subject: [PATCH 129/138] [amalgam] Use it in cmake port and fix conflicts (#1812) --- .circleci/config.yml | 8 ++-- CMakeLists.txt | 74 +++------------------------------- src/Makefile.am | 2 + src/hb-cff-interp-common.hh | 6 +-- src/hb-cff-interp-cs-common.hh | 2 +- src/hb-coretext.cc | 4 +- src/hb-directwrite.cc | 14 +++---- src/hb-ft.cc | 4 +- 8 files changed, 27 insertions(+), 87 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2ce6a8e22..6ad98d237 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -264,7 +264,7 @@ jobs: - image: dockcross/android-arm steps: - checkout - - run: cmake -Bbuild -H. -GNinja + - run: cmake -Bbuild -H. -GNinja -DHB_BUILD_TESTS=OFF - run: ninja -Cbuild crosscompile-cmake-notest-browser-asmjs-hb_tiny: @@ -272,7 +272,7 @@ jobs: - image: dockcross/browser-asmjs steps: - checkout - - run: cmake -Bbuild -H. -GNinja -DCMAKE_CXX_FLAGS="-DHB_TINY" + - run: cmake -Bbuild -H. -GNinja -DCMAKE_CXX_FLAGS="-DHB_TINY" -DHB_BUILD_TESTS=OFF - run: ninja -Cbuild crosscompile-cmake-notest-linux-arm64: @@ -280,7 +280,7 @@ jobs: - image: dockcross/linux-arm64 steps: - checkout - - run: cmake -Bbuild -H. -GNinja + - run: cmake -Bbuild -H. -GNinja -DHB_BUILD_TESTS=OFF - run: ninja -Cbuild crosscompile-cmake-notest-linux-mips: @@ -288,7 +288,7 @@ jobs: - image: dockcross/linux-mips steps: - checkout - - run: cmake -Bbuild -H. -GNinja + - run: cmake -Bbuild -H. -GNinja -DHB_BUILD_TESTS=OFF - run: ninja -Cbuild #crosscompile-cmake-notest-windows-x64: diff --git a/CMakeLists.txt b/CMakeLists.txt index c9ba0160c..c41579c1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,8 +157,6 @@ endfunction () file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES) file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES) -extract_make_variable(HB_BASE_sources ${SRCSOURCES}) -add_prefix_to_list(HB_BASE_sources "${PROJECT_SOURCE_DIR}/src/") extract_make_variable(HB_BASE_headers ${SRCSOURCES}) add_prefix_to_list(HB_BASE_headers "${PROJECT_SOURCE_DIR}/src/") @@ -192,59 +190,12 @@ set (HB_VERSION_MAJOR ${CMAKE_MATCH_2}) set (HB_VERSION_MINOR ${CMAKE_MATCH_3}) set (HB_VERSION_MICRO ${CMAKE_MATCH_4}) - -## Define ragel tasks -# if (NOT IN_HB_DIST) -# foreach (ragel_output IN ITEMS ${HB_BASE_RAGEL_GENERATED_sources}) -# string(REGEX MATCH "([^/]+)\\.hh" temp ${ragel_output}) -# set (target_name ${CMAKE_MATCH_1}) -# add_custom_command(OUTPUT ${ragel_output} -# COMMAND ${RAGEL} -G2 -o ${ragel_output} ${PROJECT_SOURCE_DIR}/src/${target_name}.rl -I ${PROJECT_SOURCE_DIR} ${ARGN} -# DEPENDS ${PROJECT_SOURCE_DIR}/src/${target_name}.rl -# ) -# add_custom_target(harfbuzz_${target_name} DEPENDS ${PROJECT_BINARY_DIR}/src/${target_name}) -# endforeach () - -# mark_as_advanced(RAGEL) -# endif () - - -## Generate hb-version.h -# if (NOT IN_HB_DIST) -# set (HB_VERSION_H_IN "${PROJECT_SOURCE_DIR}/src/hb-version.h.in") -# set (HB_VERSION_H "${PROJECT_BINARY_DIR}/src/hb-version.h") -# set_source_files_properties("${HB_VERSION_H}" PROPERTIES GENERATED true) -# configure_file("${HB_VERSION_H_IN}" "${HB_VERSION_H}.tmp" @ONLY) -# execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different -# "${HB_VERSION_H}.tmp" -# "${HB_VERSION_H}" -# ) -# file(REMOVE "${HB_VERSION_H}.tmp") -# endif () - - ## Define sources and headers of the project -set (project_sources - ${HB_BASE_sources} - ${HB_BASE_RAGEL_GENERATED_sources} -) - -set (subset_project_sources - ${HB_SUBSET_sources} -) - +set (project_sources ${PROJECT_SOURCE_DIR}/src/harfbuzz.cc) # use amalgam source +set (subset_project_sources ${HB_SUBSET_sources}) set (project_extra_sources) - -set (project_headers - #${HB_VERSION_H} - - ${HB_BASE_headers} -) - -set (subset_project_headers - ${HB_SUBSET_headers} -) - +set (project_headers ${HB_BASE_headers}) +set (subset_project_headers ${HB_SUBSET_headers}) ## Find and include needed header folders and libraries if (HB_HAVE_FREETYPE) @@ -257,7 +208,6 @@ if (HB_HAVE_FREETYPE) include_directories(AFTER ${FREETYPE_INCLUDE_DIRS}) add_definitions(-DHAVE_FREETYPE=1) - list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ft.cc) list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-ft.h) # So check_funcs can find its headers @@ -275,7 +225,6 @@ if (HB_HAVE_GRAPHITE2) include_directories(${GRAPHITE2_INCLUDE_DIR}) - list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-graphite2.cc) list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-graphite2.h) list(APPEND THIRD_PARTY_LIBS ${GRAPHITE2_LIBRARY}) @@ -296,7 +245,6 @@ if (HB_HAVE_GLIB) include_directories(${GLIBCONFIG_INCLUDE_DIR} ${GLIB_INCLUDE_DIR}) - list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-glib.cc) list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-glib.h) list(APPEND THIRD_PARTY_LIBS ${GLIB_LIBRARIES}) @@ -316,7 +264,6 @@ if (HB_HAVE_ICU) include_directories(${ICU_INCLUDE_DIR}) - list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-icu.cc) list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-icu.h) list(APPEND THIRD_PARTY_LIBS ${ICU_LIBRARY}) @@ -328,7 +275,6 @@ if (APPLE AND HB_HAVE_CORETEXT) # Apple Advanced Typography add_definitions(-DHAVE_CORETEXT) - list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-coretext.cc) list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-coretext.h) if (HB_IOS) @@ -361,19 +307,13 @@ endif () if (WIN32 AND HB_HAVE_UNISCRIBE) add_definitions(-DHAVE_UNISCRIBE) - - list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.cc) list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h) - list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4) endif () if (WIN32 AND HB_HAVE_DIRECTWRITE) add_definitions(-DHAVE_DIRECTWRITE) - - list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-directwrite.cc) list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-directwrite.h) - list(APPEND THIRD_PARTY_LIBS dwrite rpcrt4) endif () @@ -481,7 +421,6 @@ if (HB_HAVE_GOBJECT) ) endif () - ## Atomic ops availability detection file(WRITE "${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c" " void memory_barrier (void) { __sync_synchronize (); } @@ -590,7 +529,6 @@ if (WIN32) endif () if (HB_HAVE_INTROSPECTION) - find_package(PkgConfig) pkg_check_modules(PC_GI QUIET gobject-introspection-1.0) @@ -824,7 +762,7 @@ endif () if (HB_BUILD_TESTS) ## src/ executables - foreach (prog main test test-gsub-would-substitute test-gpos-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges) + foreach (prog main test test-gsub-would-substitute test-gpos-size-params test-buffer-serialize test-unicode-ranges) # hb-ot-tag set (prog_name ${prog}) if (${prog_name} STREQUAL "test") # test can not be used as a valid executable name on cmake, lets special case it @@ -833,7 +771,7 @@ if (HB_BUILD_TESTS) add_executable(${prog_name} ${PROJECT_SOURCE_DIR}/src/${prog}.cc) target_link_libraries(${prog_name} harfbuzz ${THIRD_PARTY_LIBS}) endforeach () - set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN") + # set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN") ## Tests if (UNIX OR MINGW) diff --git a/src/Makefile.am b/src/Makefile.am index 5c15a3d3d..1e79483c9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,6 +12,8 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-introspection TESTS = check_PROGRAMS = +EXTRA_DIST += harfbuzz.cc + # Convenience targets: lib: $(BUILT_SOURCES) libharfbuzz.la libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES) diff --git a/src/hb-cff-interp-common.hh b/src/hb-cff-interp-common.hh index 948772b0e..fdc5c683a 100644 --- a/src/hb-cff-interp-common.hh +++ b/src/hb-cff-interp-common.hh @@ -378,7 +378,7 @@ typedef hb_vector_t byte_str_array_t; /* stack */ template -struct stack_t +struct cff_stack_t { void init () { @@ -469,7 +469,7 @@ struct stack_t /* argument stack */ template -struct arg_stack_t : stack_t +struct arg_stack_t : cff_stack_t { void push_int (int v) { @@ -523,7 +523,7 @@ struct arg_stack_t : stack_t { return S::elements.sub_array (start); } private: - typedef stack_t S; + typedef cff_stack_t S; }; /* an operator prefixed by its operands in a byte string */ diff --git a/src/hb-cff-interp-cs-common.hh b/src/hb-cff-interp-cs-common.hh index cf9ce4dc3..d9ad4d0d6 100644 --- a/src/hb-cff-interp-cs-common.hh +++ b/src/hb-cff-interp-cs-common.hh @@ -57,7 +57,7 @@ struct call_context_t /* call stack */ const unsigned int kMaxCallLimit = 10; -struct call_stack_t : stack_t {}; +struct call_stack_t : cff_stack_t {}; template struct biased_subrs_t diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index a57b97026..e8a4fd51e 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -75,7 +75,7 @@ release_table_data (void *user_data) } static hb_blob_t * -reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) +_hb_cg_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) { CGFontRef cg_font = reinterpret_cast (user_data); CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag); @@ -299,7 +299,7 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data) hb_face_t * hb_coretext_face_create (CGFontRef cg_font) { - return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release); + return hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release); } /* diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index a625763da..810c5e553 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -539,10 +539,10 @@ protected: Run mRunHead; }; -static inline uint16_t hb_uint16_swap (const uint16_t v) +static inline uint16_t hb_dw_uint16_swap (const uint16_t v) { return (v >> 8) | (v << 8); } -static inline uint32_t hb_uint32_swap (const uint32_t v) -{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } +static inline uint32_t hb_dw_uint32_swap (const uint32_t v) +{ return (hb_dw_uint16_swap (v) << 16) | hb_dw_uint16_swap (v >> 16); } /* * shaper @@ -653,7 +653,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan, for (unsigned int i = 0; i < num_features; ++i) { typographic_features.features[i].nameTag = (DWRITE_FONT_FEATURE_TAG) - hb_uint32_swap (features[i].tag); + hb_dw_uint32_swap (features[i].tag); typographic_features.features[i].parameter = features[i].value; } } @@ -934,14 +934,14 @@ _hb_directwrite_table_data_release (void *data) } static hb_blob_t * -reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) +_hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) { IDWriteFontFace *dw_face = ((IDWriteFontFace *) user_data); const void *data; uint32_t length; void *table_context; BOOL exists; - if (!dw_face || FAILED (dw_face->TryGetFontTable (hb_uint32_swap (tag), &data, + if (!dw_face || FAILED (dw_face->TryGetFontTable (hb_dw_uint32_swap (tag), &data, &length, &table_context, &exists))) return nullptr; @@ -979,7 +979,7 @@ hb_directwrite_face_create (IDWriteFontFace *font_face) { if (font_face) font_face->AddRef (); - return hb_face_create_for_tables (reference_table, font_face, + return hb_face_create_for_tables (_hb_directwrite_reference_table, font_face, _hb_directwrite_font_release); } diff --git a/src/hb-ft.cc b/src/hb-ft.cc index c01f02991..2d7f2b959 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -564,7 +564,7 @@ _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) static hb_blob_t * -reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) +_hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) { FT_Face ft_face = (FT_Face) user_data; FT_Byte *buffer; @@ -619,7 +619,7 @@ hb_ft_face_create (FT_Face ft_face, face = hb_face_create (blob, ft_face->face_index); hb_blob_destroy (blob); } else { - face = hb_face_create_for_tables (reference_table, ft_face, destroy); + face = hb_face_create_for_tables (_hb_ft_reference_table, ft_face, destroy); } hb_face_set_index (face, ft_face->face_index); From 641f33738089ef7ccbedce09886309edcd2e1718 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 4 Jul 2019 23:03:45 +0200 Subject: [PATCH 130/138] =?UTF-8?q?Docs=20typo=20fix:=20slower=20=E2=86=92?= =?UTF-8?q?=20lower?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hb-set.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-set.cc b/src/hb-set.cc index fa9868809..8e6790760 100644 --- a/src/hb-set.cc +++ b/src/hb-set.cc @@ -479,7 +479,7 @@ hb_set_next (const hb_set_t *set, * @set: a set. * @codepoint: (inout): * - * Gets the previous number in @set that is slower than current value of @codepoint. + * Gets the previous number in @set that is lower than current value of @codepoint. * * Set @codepoint to %HB_SET_VALUE_INVALID to get started. * From ffa736f151f27adb76fb0bf91e18e1ec5cb8fe8d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 4 Jul 2019 23:05:50 +0200 Subject: [PATCH 131/138] hb_set_previous_range docs: fix presumed copy/paste error --- src/hb-set.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-set.cc b/src/hb-set.cc index 8e6790760..10638a7e6 100644 --- a/src/hb-set.cc +++ b/src/hb-set.cc @@ -524,7 +524,7 @@ hb_set_next_range (const hb_set_t *set, * @last: (out): output last codepoint in the range. * * Gets the previous consecutive range of numbers in @set that - * are greater than current value of @last. + * are less than current value of @first. * * Set @first to %HB_SET_VALUE_INVALID to get started. * From cf1a782a5ca82a880906cae3d4cb76b10ec2aad2 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 4 Jul 2019 21:06:59 +0200 Subject: [PATCH 132/138] Docs: fix a typo in function name --- docs/usermanual-fonts-and-faces.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usermanual-fonts-and-faces.xml b/docs/usermanual-fonts-and-faces.xml index b87f0e5e8..1258bec8c 100644 --- a/docs/usermanual-fonts-and-faces.xml +++ b/docs/usermanual-fonts-and-faces.xml @@ -86,7 +86,7 @@ objects. hb_font_set_ppem(font, x_ppem, y_ppem) sets the pixels-per-EM value of the font. You can also set the point size of the font with - hb_font_set_ppem(font, ptem). HarfBuzz uses the + hb_font_set_ptem(font, ptem). HarfBuzz uses the industry standard 72 points per inch. From 144326e215671a42fb3ac9f00ddef779ba354345 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 5 Jul 2019 19:05:11 +0200 Subject: [PATCH 133/138] Clusters are reversed based on the direction, not script Fixes https://github.com/harfbuzz/harfbuzz/issues/1818 --- docs/usermanual-clusters.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/usermanual-clusters.xml b/docs/usermanual-clusters.xml index a7b16580a..9147ff0a5 100644 --- a/docs/usermanual-clusters.xml +++ b/docs/usermanual-clusters.xml @@ -156,14 +156,16 @@ order. - For left-to-right scripts (LTR) and top-to-bottom scripts (TTB), + For buffers in the left-to-right (LTR) + or top-to-bottom (TTB) text flow direction, HarfBuzz will preserve the monotonic property: client programs are guaranteed that monotonically increasing initial cluster values will be returned as monotonically increasing final cluster values. - For right-to-left scripts (RTL) and bottom-to-top scripts (BTT), + For buffers in the right-to-left (RTL) + or bottom-to-top (BTT) text flow direction, the directionality of the buffer itself is reversed for final output as a matter of design. Therefore, HarfBuzz inverts the monotonic property: client programs are guaranteed that From 0d425e1eeaea97bf5e4fc9ce40e549332bc0cea1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 5 Jul 2019 13:18:05 -0700 Subject: [PATCH 134/138] [ot-font] Optimize rounding Part of https://github.com/harfbuzz/harfbuzz/issues/1801 The assumption that compiler optimizes "upem/2" to a shift only works if upem is unsigned... Anyway, spoon-feed the compiler. --- src/hb-font.hh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hb-font.hh b/src/hb-font.hh index 3b917d129..d807874f6 100644 --- a/src/hb-font.hh +++ b/src/hb-font.hh @@ -609,9 +609,11 @@ struct hb_font_t hb_position_t em_scale (int16_t v, int scale) { - int upem = face->get_upem (); + signed upem = face->get_upem (); + signed upem2 = upem >> 1; int64_t scaled = v * (int64_t) scale; - scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */ + + scaled += scaled >= 0 ? upem2 : -upem2; /* Round. */ return (hb_position_t) (scaled / upem); } hb_position_t em_scalef (float v, int scale) From df6edcd44ceb63d01d9c0d6d2aa06b6c6cbb914d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 5 Jul 2019 13:45:15 -0700 Subject: [PATCH 135/138] Make face immutable in hb_font_set_face() --- src/hb-font.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hb-font.cc b/src/hb-font.cc index f450d8889..5727247af 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1601,6 +1601,7 @@ hb_font_set_face (hb_font_t *font, hb_face_t *old = font->face; + hb_face_make_immutable (face); font->face = hb_face_reference (face); hb_face_destroy (old); From b847769292aca13345fd1facae35aaf999198ad4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 5 Jul 2019 13:52:09 -0700 Subject: [PATCH 136/138] [font] Keep font-space to user-space multiplier Part of https://github.com/harfbuzz/harfbuzz/issues/1801 --- src/hb-font.cc | 5 +++++ src/hb-font.hh | 13 +++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index 5727247af..9cd501170 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1300,6 +1300,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) = 1000, /* x_scale */ 1000, /* y_scale */ + 1<<16, /* x_mult */ + 1<<16, /* y_mult */ 0, /* x_ppem */ 0, /* y_ppem */ @@ -1330,6 +1332,7 @@ _hb_font_create (hb_face_t *face) font->klass = hb_font_funcs_get_empty (); font->data.init0 (font); font->x_scale = font->y_scale = hb_face_get_upem (face); + font->x_mult = font->y_mult = 1 << 16; return font; } @@ -1603,6 +1606,7 @@ hb_font_set_face (hb_font_t *font, hb_face_make_immutable (face); font->face = hb_face_reference (face); + font->mults_changed (); hb_face_destroy (old); } @@ -1712,6 +1716,7 @@ hb_font_set_scale (hb_font_t *font, font->x_scale = x_scale; font->y_scale = y_scale; + font->mults_changed (); } /** diff --git a/src/hb-font.hh b/src/hb-font.hh index d807874f6..e379f125c 100644 --- a/src/hb-font.hh +++ b/src/hb-font.hh @@ -107,8 +107,10 @@ struct hb_font_t hb_font_t *parent; hb_face_t *face; - int x_scale; - int y_scale; + int32_t x_scale; + int32_t y_scale; + int64_t x_mult; + int64_t y_mult; unsigned int x_ppem; unsigned int y_ppem; @@ -607,6 +609,13 @@ struct hb_font_t return false; } + void mults_changed () + { + signed upem = face->get_upem (); + x_mult = ((int64_t) x_scale << 16) / upem; + y_mult = ((int64_t) y_scale << 16) / upem; + } + hb_position_t em_scale (int16_t v, int scale) { signed upem = face->get_upem (); From f18ea1dd3a9961661a383b2966de57ea68a267e7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 5 Jul 2019 13:56:45 -0700 Subject: [PATCH 137/138] [font] Remove division when scaling Yoohoo. This seems to be precise enough! Let's see if it sticks. I'm asking Dominik to run this in Chrome test suite and report. Fixes https://github.com/harfbuzz/harfbuzz/issues/1801 --- src/hb-font.hh | 23 +++++++++-------------- src/hb-ot-math-table.hh | 16 ++++++++-------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/hb-font.hh b/src/hb-font.hh index e379f125c..4adf6ae99 100644 --- a/src/hb-font.hh +++ b/src/hb-font.hh @@ -129,16 +129,16 @@ struct hb_font_t /* Convert from font-space to user-space */ - int dir_scale (hb_direction_t direction) - { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; } - hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); } - hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); } - hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); } - hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); } + int64_t dir_mult (hb_direction_t direction) + { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; } + hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); } + hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); } + hb_position_t em_scalef_x (float v) { return em_scalef (v, x_scale); } + hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); } float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); } float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); } hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) - { return em_scale (v, dir_scale (direction)); } + { return em_mult (v, dir_mult (direction)); } /* Convert from parent-font user-space to our user-space */ hb_position_t parent_scale_x_distance (hb_position_t v) @@ -616,14 +616,9 @@ struct hb_font_t y_mult = ((int64_t) y_scale << 16) / upem; } - hb_position_t em_scale (int16_t v, int scale) + hb_position_t em_mult (int16_t v, int64_t mult) { - signed upem = face->get_upem (); - signed upem2 = upem >> 1; - int64_t scaled = v * (int64_t) scale; - - scaled += scaled >= 0 ? upem2 : -upem2; /* Round. */ - return (hb_position_t) (scaled / upem); + return (hb_position_t) ((v * mult) >> 16); } hb_position_t em_scalef (float v, int scale) { return (hb_position_t) roundf (v * scale / face->get_upem ()); } diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh index 0b16e0b9b..b4592ccde 100644 --- a/src/hb-ot-math-table.hh +++ b/src/hb-ot-math-table.hh @@ -453,14 +453,14 @@ struct MathGlyphPartRecord } void extract (hb_ot_math_glyph_part_t &out, - int scale, + int64_t mult, hb_font_t *font) const { out.glyph = glyph; - out.start_connector_length = font->em_scale (startConnectorLength, scale); - out.end_connector_length = font->em_scale (endConnectorLength, scale); - out.full_advance = font->em_scale (fullAdvance, scale); + out.start_connector_length = font->em_mult (startConnectorLength, mult); + out.end_connector_length = font->em_mult (endConnectorLength, mult); + out.full_advance = font->em_mult (fullAdvance, mult); static_assert ((unsigned int) HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER == (unsigned int) PartFlags::Extender, ""); @@ -508,11 +508,11 @@ struct MathGlyphAssembly { if (parts_count) { - int scale = font->dir_scale (direction); + int64_t mult = font->dir_mult (direction); hb_array_t arr = partRecords.sub_array (start_offset, parts_count); unsigned int count = arr.length; for (unsigned int i = 0; i < count; i++) - arr[i].extract (parts[i], scale, font); + arr[i].extract (parts[i], mult, font); } if (italics_correction) @@ -553,13 +553,13 @@ struct MathGlyphConstruction { if (variants_count) { - int scale = font->dir_scale (direction); + int64_t mult = font->dir_mult (direction); hb_array_t arr = mathGlyphVariantRecord.sub_array (start_offset, variants_count); unsigned int count = arr.length; for (unsigned int i = 0; i < count; i++) { variants[i].glyph = arr[i].variantGlyph; - variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale); + variants[i].advance = font->em_mult (arr[i].advanceMeasurement, mult); } } return mathGlyphVariantRecord.len; From 2e7021da7d1726a37822e6a001b9218f82255bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Mon, 8 Jul 2019 10:19:49 +0300 Subject: [PATCH 138/138] Revert "Minor" - revert moving extern "C" definitions in-function This reverts commit 62e60322cb9e18b3ee75f1b4a2a6d3069f587407 since it breaks building HarfBuzz as part of Chromium. Fixes https://github.com/harfbuzz/harfbuzz/issues/1821. --- src/hb-unicode.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index 663415b26..e2deaa240 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -126,16 +126,17 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED } #endif +extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs (); +extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs (); + hb_unicode_funcs_t * hb_unicode_funcs_get_default () { #if !defined(HB_NO_UNICODE_FUNCS) && !defined(HB_NO_UCD) return hb_ucd_get_unicode_funcs (); #elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_GLIB) - extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs (); return hb_glib_get_unicode_funcs (); #elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN) - extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs (); return hb_icu_get_unicode_funcs (); #else #define HB_UNICODE_FUNCS_NIL 1