├── .github └── workflows │ └── main.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── benches ├── Cargo.toml ├── README.md ├── fonts │ ├── Amiri-LICENSE-OFL.txt │ ├── Amiri-Regular.ttf │ ├── NotoSans-LICENSE-OFL.txt │ ├── NotoSans-Regular.ttf │ ├── NotoSans-VariableFont.ttf │ ├── NotoSansArabic-LICENSE-OFL.txt │ ├── NotoSansArabic-Regular.ttf │ ├── NotoSansDevanagari-LICENSE-OFL.txt │ ├── NotoSansDevanagari-Regular.ttf │ ├── NotoSansHebrew-LICENSE-OFL.txt │ ├── NotoSansHebrew-Regular.ttf │ ├── NotoSansKhmer-LICENSE-OFL.txt │ ├── NotoSansKhmer-Regular.ttf │ ├── NotoSansMyanmar-LICENSE-OFL.txt │ ├── NotoSansMyanmar-Regular.ttf │ ├── NotoSansThai-LICENSE-OFL.txt │ ├── NotoSansThai-Regular.ttf │ ├── Roboto-LICENSE-APACHE.txt │ └── RobotoMono-Regular.ttf ├── rustfmt.toml ├── src │ └── lib.rs └── texts │ ├── arabic │ ├── paragraph_long.txt │ ├── paragraph_medium.txt │ ├── paragraph_short.txt │ ├── sentence_1.txt │ ├── sentence_2.txt │ ├── word_1.txt │ ├── word_2.txt │ └── word_3.txt │ ├── english │ ├── long_zalgo.txt │ ├── paragraph_long.txt │ ├── paragraph_medium.txt │ ├── paragraph_short.txt │ ├── sentence_1.txt │ ├── sentence_2.txt │ ├── short_zalgo.txt │ ├── word_1.txt │ ├── word_2.txt │ ├── word_3.txt │ └── word_4.txt │ ├── hebrew │ ├── paragraph_long_1.txt │ ├── paragraph_long_2.txt │ ├── paragraph_medium.txt │ ├── sentence_1.txt │ ├── sentence_2.txt │ ├── word_1.txt │ └── word_2.txt │ ├── hindi │ ├── paragraph_long.txt │ ├── paragraph_medium.txt │ ├── paragraph_short.txt │ ├── sentence_1.txt │ ├── sentence_2.txt │ ├── word_1.txt │ └── word_2.txt │ ├── khmer │ ├── paragraph_long_1.txt │ ├── paragraph_long_2.txt │ ├── paragraph_medium.txt │ ├── sentence_1.txt │ ├── sentence_2.txt │ ├── word_1.txt │ ├── word_2.txt │ └── word_3.txt │ ├── myanmar │ ├── paragraph_long.txt │ ├── paragraph_medium.txt │ ├── paragraph_short.txt │ ├── sentence_1.txt │ ├── sentence_2.txt │ ├── word_1.txt │ └── word_2.txt │ └── thai │ ├── paragraph_long.txt │ ├── paragraph_medium.txt │ ├── paragraph_short.txt │ ├── sentence_1.txt │ ├── word_1.txt │ └── word_2.txt ├── docs ├── backporting.md └── ragel.md ├── examples └── shape.rs ├── scripts ├── .gitignore ├── README.md ├── gen-arabic-table.py ├── gen-indic-table.py ├── gen-shaping-tests.py ├── gen-tag-table.py ├── gen-unicode-is-emoji-ext-pict.py ├── gen-unicode-norm-table.py ├── gen-vowel-constraints.py └── ms-use │ ├── COPYING │ ├── IndicPositionalCategory-Additional.txt │ ├── IndicShapingInvalidCluster.txt │ └── IndicSyllabicCategory-Additional.txt ├── src ├── hb │ ├── aat_layout.rs │ ├── aat_layout_common.rs │ ├── aat_layout_kerx_table.rs │ ├── aat_layout_morx_table.rs │ ├── aat_layout_trak_table.rs │ ├── aat_map.rs │ ├── algs.rs │ ├── buffer.rs │ ├── common.rs │ ├── face.rs │ ├── kerning.rs │ ├── machine_cursor.rs │ ├── mod.rs │ ├── ot │ │ ├── layout │ │ │ ├── GPOS │ │ │ │ ├── cursive_pos.rs │ │ │ │ ├── mark_array.rs │ │ │ │ ├── mark_base_pos.rs │ │ │ │ ├── mark_lig_pos.rs │ │ │ │ ├── mark_mark_pos.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── pair_pos.rs │ │ │ │ ├── pos_lookup.rs │ │ │ │ └── single_pos.rs │ │ │ ├── GSUB │ │ │ │ ├── alternate_set.rs │ │ │ │ ├── alternate_subst.rs │ │ │ │ ├── ligature.rs │ │ │ │ ├── ligature_set.rs │ │ │ │ ├── ligature_subst.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── multi_subst.rs │ │ │ │ ├── reverse_chain_single_subst.rs │ │ │ │ ├── sequence.rs │ │ │ │ ├── single_subst.rs │ │ │ │ ├── subst_lookup.rs │ │ │ │ └── subst_lookup_subtable.rs │ │ │ └── mod.rs │ │ └── mod.rs │ ├── ot_layout.rs │ ├── ot_layout_common.rs │ ├── ot_layout_gpos_table.rs │ ├── ot_layout_gsub_table.rs │ ├── ot_layout_gsubgpos.rs │ ├── ot_map.rs │ ├── ot_shape.rs │ ├── ot_shape_fallback.rs │ ├── ot_shape_normalize.rs │ ├── ot_shape_plan.rs │ ├── ot_shaper.rs │ ├── ot_shaper_arabic.rs │ ├── ot_shaper_arabic_table.rs │ ├── ot_shaper_hangul.rs │ ├── ot_shaper_hebrew.rs │ ├── ot_shaper_indic.rs │ ├── ot_shaper_indic_machine.rl │ ├── ot_shaper_indic_machine.rs │ ├── ot_shaper_indic_table.rs │ ├── ot_shaper_khmer.rs │ ├── ot_shaper_khmer_machine.rl │ ├── ot_shaper_khmer_machine.rs │ ├── ot_shaper_myanmar.rs │ ├── ot_shaper_myanmar_machine.rl │ ├── ot_shaper_myanmar_machine.rs │ ├── ot_shaper_syllabic.rs │ ├── ot_shaper_thai.rs │ ├── ot_shaper_use.rs │ ├── ot_shaper_use_machine.rl │ ├── ot_shaper_use_machine.rs │ ├── ot_shaper_use_table.rs │ ├── ot_shaper_vowel_constraints.rs │ ├── paint_extents.rs │ ├── set_digest.rs │ ├── shape.rs │ ├── shape_wasm.rs │ ├── tag.rs │ ├── tag_table.rs │ ├── text_parser.rs │ ├── unicode.rs │ └── unicode_norm.rs └── lib.rs └── tests ├── custom ├── bugs.tests ├── colr.tests ├── fuzzer.tests ├── glyph-flags.tests └── macos.tests ├── fonts ├── aots │ ├── classdef1_font2.otf │ ├── classdef1_font3.otf │ ├── classdef1_font4.otf │ ├── classdef2_font1.otf │ ├── classdef2_font2.otf │ ├── classdef2_font3.otf │ ├── classdef2_font4.otf │ ├── cmap0_font1.otf │ ├── cmap10_font1.otf │ ├── cmap10_font2.otf │ ├── cmap12_font1.otf │ ├── cmap4_font1.otf │ ├── cmap4_font2.otf │ ├── cmap4_font3.otf │ ├── cmap4_font4.otf │ ├── cmap6_font1.otf │ ├── cmap6_font2.otf │ ├── gpos1_1_lookupflag_f1.otf │ ├── gpos1_1_simple_f1.otf │ ├── gpos1_1_simple_f2.otf │ ├── gpos1_1_simple_f3.otf │ ├── gpos1_2_font1.otf │ ├── gpos1_2_font2.otf │ ├── gpos2_1_font6.otf │ ├── gpos2_1_font7.otf │ ├── gpos2_1_lookupflag_f1.otf │ ├── gpos2_1_lookupflag_f2.otf │ ├── gpos2_1_next_glyph_f1.otf │ ├── gpos2_1_next_glyph_f2.otf │ ├── gpos2_1_simple_f1.otf │ ├── gpos2_2_font1.otf │ ├── gpos2_2_font2.otf │ ├── gpos2_2_font3.otf │ ├── gpos2_2_font4.otf │ ├── gpos2_2_font5.otf │ ├── gpos3_font1.otf │ ├── gpos3_font3.otf │ ├── gpos4_lookupflag_f1.otf │ ├── gpos4_lookupflag_f2.otf │ ├── gpos4_simple_1.otf │ ├── gpos5_font1.otf │ ├── gpos6_font1.otf │ ├── gpos7_1_font1.otf │ ├── gpos9_font1.otf │ ├── gpos9_font2.otf │ ├── gpos_chaining1_boundary_f1.otf │ ├── gpos_chaining1_boundary_f2.otf │ ├── gpos_chaining1_boundary_f3.otf │ ├── gpos_chaining1_boundary_f4.otf │ ├── gpos_chaining1_lookupflag_f1.otf │ ├── gpos_chaining1_multiple_subrules_f1.otf │ ├── gpos_chaining1_multiple_subrules_f2.otf │ ├── gpos_chaining1_next_glyph_f1.otf │ ├── gpos_chaining1_simple_f1.otf │ ├── gpos_chaining1_simple_f2.otf │ ├── gpos_chaining1_successive_f1.otf │ ├── gpos_chaining2_boundary_f1.otf │ ├── gpos_chaining2_boundary_f2.otf │ ├── gpos_chaining2_boundary_f3.otf │ ├── gpos_chaining2_boundary_f4.otf │ ├── gpos_chaining2_lookupflag_f1.otf │ ├── gpos_chaining2_multiple_subrules_f1.otf │ ├── gpos_chaining2_multiple_subrules_f2.otf │ ├── gpos_chaining2_next_glyph_f1.otf │ ├── gpos_chaining2_simple_f1.otf │ ├── gpos_chaining2_simple_f2.otf │ ├── gpos_chaining2_successive_f1.otf │ ├── gpos_chaining3_boundary_f1.otf │ ├── gpos_chaining3_boundary_f2.otf │ ├── gpos_chaining3_boundary_f3.otf │ ├── gpos_chaining3_boundary_f4.otf │ ├── gpos_chaining3_lookupflag_f1.otf │ ├── gpos_chaining3_next_glyph_f1.otf │ ├── gpos_chaining3_simple_f1.otf │ ├── gpos_chaining3_simple_f2.otf │ ├── gpos_chaining3_successive_f1.otf │ ├── gpos_context1_boundary_f1.otf │ ├── gpos_context1_boundary_f2.otf │ ├── gpos_context1_expansion_f1.otf │ ├── gpos_context1_lookupflag_f1.otf │ ├── gpos_context1_lookupflag_f2.otf │ ├── gpos_context1_multiple_subrules_f1.otf │ ├── gpos_context1_multiple_subrules_f2.otf │ ├── gpos_context1_next_glyph_f1.otf │ ├── gpos_context1_simple_f1.otf │ ├── gpos_context1_simple_f2.otf │ ├── gpos_context1_successive_f1.otf │ ├── gpos_context2_boundary_f1.otf │ ├── gpos_context2_boundary_f2.otf │ ├── gpos_context2_classes_f1.otf │ ├── gpos_context2_classes_f2.otf │ ├── gpos_context2_expansion_f1.otf │ ├── gpos_context2_lookupflag_f1.otf │ ├── gpos_context2_lookupflag_f2.otf │ ├── gpos_context2_multiple_subrules_f1.otf │ ├── gpos_context2_multiple_subrules_f2.otf │ ├── gpos_context2_next_glyph_f1.otf │ ├── gpos_context2_simple_f1.otf │ ├── gpos_context2_simple_f2.otf │ ├── gpos_context2_successive_f1.otf │ ├── gpos_context3_boundary_f1.otf │ ├── gpos_context3_boundary_f2.otf │ ├── gpos_context3_lookupflag_f1.otf │ ├── gpos_context3_lookupflag_f2.otf │ ├── gpos_context3_next_glyph_f1.otf │ ├── gpos_context3_simple_f1.otf │ ├── gpos_context3_successive_f1.otf │ ├── gsub1_1_lookupflag_f1.otf │ ├── gsub1_1_modulo_f1.otf │ ├── gsub1_1_simple_f1.otf │ ├── gsub1_2_lookupflag_f1.otf │ ├── gsub1_2_simple_f1.otf │ ├── gsub2_1_lookupflag_f1.otf │ ├── gsub2_1_multiple_sequences_f1.otf │ ├── gsub2_1_simple_f1.otf │ ├── gsub3_1_lookupflag_f1.otf │ ├── gsub3_1_multiple_f1.otf │ ├── gsub3_1_simple_f1.otf │ ├── gsub4_1_lookupflag_f1.otf │ ├── gsub4_1_multiple_ligatures_f1.otf │ ├── gsub4_1_multiple_ligatures_f2.otf │ ├── gsub4_1_multiple_ligsets_f1.otf │ ├── gsub4_1_simple_f1.otf │ ├── gsub7_font1.otf │ ├── gsub7_font2.otf │ ├── gsub_chaining1_boundary_f1.otf │ ├── gsub_chaining1_boundary_f2.otf │ ├── gsub_chaining1_boundary_f3.otf │ ├── gsub_chaining1_boundary_f4.otf │ ├── gsub_chaining1_lookupflag_f1.otf │ ├── gsub_chaining1_multiple_subrules_f1.otf │ ├── gsub_chaining1_multiple_subrules_f2.otf │ ├── gsub_chaining1_next_glyph_f1.otf │ ├── gsub_chaining1_simple_f1.otf │ ├── gsub_chaining1_simple_f2.otf │ ├── gsub_chaining1_successive_f1.otf │ ├── gsub_chaining2_boundary_f1.otf │ ├── gsub_chaining2_boundary_f2.otf │ ├── gsub_chaining2_boundary_f3.otf │ ├── gsub_chaining2_boundary_f4.otf │ ├── gsub_chaining2_lookupflag_f1.otf │ ├── gsub_chaining2_multiple_subrules_f1.otf │ ├── gsub_chaining2_multiple_subrules_f2.otf │ ├── gsub_chaining2_next_glyph_f1.otf │ ├── gsub_chaining2_simple_f1.otf │ ├── gsub_chaining2_simple_f2.otf │ ├── gsub_chaining2_successive_f1.otf │ ├── gsub_chaining3_boundary_f1.otf │ ├── gsub_chaining3_boundary_f2.otf │ ├── gsub_chaining3_boundary_f3.otf │ ├── gsub_chaining3_boundary_f4.otf │ ├── gsub_chaining3_lookupflag_f1.otf │ ├── gsub_chaining3_next_glyph_f1.otf │ ├── gsub_chaining3_simple_f1.otf │ ├── gsub_chaining3_simple_f2.otf │ ├── gsub_chaining3_successive_f1.otf │ ├── gsub_context1_boundary_f1.otf │ ├── gsub_context1_boundary_f2.otf │ ├── gsub_context1_expansion_f1.otf │ ├── gsub_context1_lookupflag_f1.otf │ ├── gsub_context1_lookupflag_f2.otf │ ├── gsub_context1_multiple_subrules_f1.otf │ ├── gsub_context1_multiple_subrules_f2.otf │ ├── gsub_context1_next_glyph_f1.otf │ ├── gsub_context1_simple_f1.otf │ ├── gsub_context1_simple_f2.otf │ ├── gsub_context1_successive_f1.otf │ ├── gsub_context2_boundary_f1.otf │ ├── gsub_context2_boundary_f2.otf │ ├── gsub_context2_classes_f1.otf │ ├── gsub_context2_classes_f2.otf │ ├── gsub_context2_expansion_f1.otf │ ├── gsub_context2_lookupflag_f1.otf │ ├── gsub_context2_lookupflag_f2.otf │ ├── gsub_context2_multiple_subrules_f1.otf │ ├── gsub_context2_multiple_subrules_f2.otf │ ├── gsub_context2_next_glyph_f1.otf │ ├── gsub_context2_simple_f1.otf │ ├── gsub_context2_simple_f2.otf │ ├── gsub_context2_successive_f1.otf │ ├── gsub_context3_boundary_f1.otf │ ├── gsub_context3_boundary_f2.otf │ ├── gsub_context3_lookupflag_f1.otf │ ├── gsub_context3_lookupflag_f2.otf │ ├── gsub_context3_next_glyph_f1.otf │ ├── gsub_context3_simple_f1.otf │ ├── gsub_context3_successive_f1.otf │ ├── lookupflag_ignore_attach_f1.otf │ ├── lookupflag_ignore_base_f1.otf │ ├── lookupflag_ignore_combination_f1.otf │ ├── lookupflag_ignore_ligatures_f1.otf │ └── lookupflag_ignore_marks_f1.otf ├── in-house │ ├── 03e3f463c3a985bc42096620cc415342818454fb.ttf │ ├── 051d92f8bc6ff724511b296c27623f824de256e9.ttf │ ├── 065b01e54f35f0d849fd43bd5b936212739a50cb.ttf │ ├── 074a5ae6b19de8f29772fdd5df2d3d833f81f5e6.ttf │ ├── 07f054357ff8638bac3711b422a1e31180bba863.ttf │ ├── 086d83239e8f958391ff6cdd8fda9376a4bd3673.ttf │ ├── 08b4b136f418add748dc641eb4a83033476f1170.ttf │ ├── 15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf │ ├── 1735326da89f0818cd8c51a0600e9789812c0f94.ttf │ ├── 190a621e48d4af1fffd8144bd41d2027e9a32fbf.ttf │ ├── 191826b9643e3f124d865d617ae609db6a2ce203.ttf │ ├── 1a3d8f381387dd29be1e897e4b5100ac8b4829e1.ttf │ ├── 1a5face3fcbd929d228235c2f72bbd6f8eb37424.ttf │ ├── 1b66a1f4b076b734caa6397b3e57231af1feaafb.ttf │ ├── 1c04a16f32a39c26c851b7fc014d2e8d298ba2b8.ttf │ ├── 1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf │ ├── 1c2fb74c1b2aa173262734c1f616148f1648cfd6.ttf │ ├── 1ed7e9064f008f62de6ff0207bb4dd29409597a5.ttf │ ├── 21b7fb9c1eeae260473809fbc1fe330f66a507cd.ttf │ ├── 226bc2deab3846f1a682085f70c67d0421014144.ttf │ ├── 23406a60ab081c4fb15e1596ea1cd4f27ae8443e.ttf │ ├── 24b8d24d00ae86f49791b746da4c9d3f717a51a8.ttf │ ├── 2681c1c72d6484ed3410417f521b1b819b4e2392.ttf │ ├── 270b89df543a7e48e206a2d830c0e10e5265c630.ttf │ ├── 28f497629c04ceb15546c9a70e0730125ed6698d.ttf │ ├── 298c9e1d955f10f6f72c6915c3c6ff9bf9695cec.ttf │ ├── 2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf │ ├── 2c25beb56d9c556622d56b0b5d02b4670c034f89.ttf │ ├── 2de1ab4907ab688c0cfc236b0bf51151db38bf2e.ttf │ ├── 3105b51976b879032c66aa93a634b3b3672cd344.ttf │ ├── 341421e629668b1a1242245d39238ca48432d35d.ttf │ ├── 3493e92eaded2661cadde752a39f9d58b11f0326.ttf │ ├── 34da9aab7bee86c4dfc3b85e423435822fdf4b62.ttf │ ├── 37033cc5cf37bb223d7355153016b6ccece93b28.ttf │ ├── 373e67bf41ca264e260a9716162b71a23549e885.ttf │ ├── 3998336402905b8be8301ef7f47cf7e050cbb1bd.ttf │ ├── 3b791518a9ba89675df02f1eefbc9026a50648a6.ttf │ ├── 3c96e7a303c58475a8c750bf4289bbe73784f37d.ttf │ ├── 3cae6bfe5b57c07ba81ddbd54c02fe4f3a1e3bf6.ttf │ ├── 3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf │ ├── 3cf6f8ac6d647473a43a3100e7494b202b2cfafe.ttf │ ├── 3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf │ ├── 3e46c3b84c1370a06594736c7f8acebf810bbb3b.ttf │ ├── 3f24aff8b768e586162e9b9d03b15c36508dd2ae.ttf │ ├── 41071178fbce4956d151f50967af458dbf555f7b.ttf │ ├── 43ef465752be9af900745f72fe29cb853a1401a5.ttf │ ├── 45855bc8d46332b39c4ab9e2ee1a26b1f896da6b.ttf │ ├── 46669c8860cbfea13562a6ca0d83130ee571137b.ttf │ ├── 49c9f7485c1392fa09a1b801bc2ffea79275f22e.ttf │ ├── 4afb0e8b9a86bb9bd73a1247de4e33fbe3c1fd93.ttf │ ├── 4cbbc461be066fccc611dcc634af6e8cb2705537.ttf │ ├── 4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf │ ├── 4d4206e30b2dbf1c1ef492a8eae1c9e7829ebad8.ttf │ ├── 4fac3929fc3332834e93673780ec0fe94342d193.ttf │ ├── 5028afb650b1bb718ed2131e872fbcce57828fff.ttf │ ├── 507637795ce4f2975593da54d12b46f76c7cc4cc.ttf │ ├── 53374c7ca3657be37efde7ed02ae34229a56ae1f.ttf │ ├── 53a91c20e33a596f2be17fb68b382d6b7eb85d5c.ttf │ ├── 54674a3111d209fb6be0ed31745314b7a8d2c244.ttf │ ├── 55c88ebbe938680b08f92c3de20713183e0c7481.ttf │ ├── 55e2910dbc9ef5dd89f4e146e7e0152169545b6a.ttf │ ├── 56cfd0e18d07f41c38e9598545a6d369127fc6f9.ttf │ ├── 573d3a3177c9a8646e94c8a0d7b224334340946a.ttf │ ├── 57a9d9f83020155cbb1d2be1f43d82388cbecc88.ttf │ ├── 59a585a63b3df608fbeef00956c8c108deec7de6.ttf │ ├── 5af5361ed4d1e8305780b100e1730cb09132f8d1.ttf │ ├── 5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf │ ├── 5bbf3712e6f79775c66a4407837a90e591efbef2.ttf │ ├── 5dfad7735c6a67085f1b90d4d497e32907db4c78.ttf │ ├── 5f73fff1ffc07b5a99a90c0909609f2b09fef274.ttf │ ├── 604026ae5aaca83c49cd8416909d71ba3e1c1194.ttf │ ├── 63a539a90a371ccf028dc2dcced9b63b07163be7.ttf │ ├── 63e224dcb3d559d590f80c83b832cfca789e5dcc.ttf │ ├── 65984dfce552a785f564422aadf4715fa07795ad.ttf │ ├── 663aef6b019dbf45ffd74089e2b5f2496ceceb18.ttf │ ├── 6677074106f94a2644da6aaaacd5bbd48cbdc7de.ttf │ ├── 6991b13ce889466be6de3f66e891de2bc0f117ee.ttf │ ├── 6f36d056bad6d478fc0bf7397bd52dc3bd197d5f.ttf │ ├── 6ff0fbead4462d9f229167b4e6839eceb8465058.ttf │ ├── 738d9f3b8c2dfd03875bf35a61d28fd78faf17c8.ttf │ ├── 73e84dac2fc6a2d1bc9250d1414353661088937d.ttf │ ├── 757ebd573617a24aa9dfbf0b885c54875c6fe06b.ttf │ ├── 7a37dc4d5bf018456aea291cee06daf004c0221c.ttf │ ├── 7c24183f26d60df414578a0a9f5e79ab9d32a22b.ttf │ ├── 7d18685e1529e4ceaad5b6095dfab2f9789e5bce.ttf │ ├── 7e14e7883ed152baa158b80e207b66114c823a8b.ttf │ ├── 8099955657a54e9ee38a6ba1d6f950ce58e3cc25.ttf │ ├── 8116e5d8fedfbec74e45dc350d2416d810bed8c4.ttf │ ├── 813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf │ ├── 81c368a33816fb20e9f647e8f24e2180f4720263.ttf │ ├── 8228d035fcd65d62ec9728fb34f42c63be93a5d3.ttf │ ├── 82f4f3b57bb55344e72e70231380202a52af5805.ttf │ ├── 8339c821814d9bad7c77169332327ad8b0f33c81.ttf │ ├── 8454d22037f892e76614e1645d066689a0200e61.ttf │ ├── 85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf │ ├── 856ff9562451293cbeff6f396d4e3877c4f0a436.ttf │ ├── 85fe0be440c64ac77699e21c2f1bd933a919167e.ttf │ ├── 86cdd983c4e4c4d7f27dd405d6ceb7d4b9ed3d35.ttf │ ├── 872d2955d326bd6676a06f66b8238ebbaabc212f.ttf │ ├── 87f85d17d26f1fe9ad28d7365101958edaefb967.ttf │ ├── 881642af1667ae30a54e58de8be904566d00508f.ttf │ ├── 8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf │ ├── 8d9c4b193808b8bde94389ba7831c1fc6f9e794e.ttf │ ├── 932ad5132c2761297c74e9976fe25b08e5ffa10b.ttf │ ├── 94a5d6fb15a27521fba9ea4aee9cb39b2d03322a.ttf │ ├── 96490dd2ff81233b335a650e7eb660e0e7b2eeea.ttf │ ├── 98b7887cff91f722b92a8ff800120954606354f9.ttf │ ├── 9d8c53cb64b8747abdd2b70755cce2ee0eb42ef7.ttf │ ├── 9fc3e6960b3520e5304033ef5fd540285f72f14d.ttf │ ├── DFONT.dfont │ ├── FallbackPlus-Javanese-no-GDEF.otf │ ├── HBTest-VF.ttf │ ├── MORXTwentyeight.ttf │ ├── NotoNastaliqUrdu-Regular.ttf │ ├── TRAK.ttf │ ├── TTC.ttc │ ├── a014549f766436cf55b2ceb40e462038938ee899.ttf │ ├── a02a7f0ad42c2922cb37ad1358c9df4eb81f1bca.ttf │ ├── a232bb734d4c6c898a44506547d19768f0eba6a6.ttf │ ├── a34a7b00f22ffb5fd7eef6933b81c7e71bc2cdfb.ttf │ ├── a56745bac8449d0ad94918b2bb5930716ba02fe3.ttf │ ├── a59fd13f1525a91cbe529c882e93d9d1fbb80463.ttf │ ├── a6b17da98b9f1565ba428719777bbf94a66403c1.ttf │ ├── a6c76d1bafde4a0b1026ebcc932d2e5c6fd02442.ttf │ ├── a706511c65fb278fda87eaf2180ca6684a80f423.ttf │ ├── a919b33197965846f21074b24e30250d67277bce.ttf │ ├── a98e908e2ed21b22228ea59ebcc0f05034c86f2e.ttf │ ├── ab14b4eb9d7a67e293f51d30d719add06c9d6e06.ttf │ ├── ab40c89624a6104e5d0a2308e448a989302f515b.ttf │ ├── ad01ab2ea1cb1a4d3a2783e2675112ef11ae6404.ttf │ ├── af3086380b743099c54a3b11b96766039ea62fcd.ttf │ ├── af85624080af5627fb050f570d148a62f04fda74.ttf │ ├── b082211be29a3e2cf91f0fd43497e40b2a27b344.ttf │ ├── b121d4306b2e3add5abbaad21d95fcf04aacbd64.ttf │ ├── b151cfcdaa77585d77f17a42158e0873fc8e2633.ttf │ ├── b3075ca42b27dde7341c2d0ae16703c5b6640df0.ttf │ ├── b31e6c52a31edadc16f1bec9efe6019e2d59824a.ttf │ ├── b6031119874ae9ff1dd65383a335e361c0962220.ttf │ ├── b722a7d09e60421f3efbc706ad348ab47b88567b.ttf │ ├── b895f8ff06493cc893ec44de380690ca0074edfa.ttf │ ├── bb0c53752e85c3d28973ebc913287b8987d3dfe8.ttf │ ├── bb9473d2403488714043bcfb946c9f78b86ad627.ttf │ ├── bbc24004e776f348a0f72287d24b0124867ee750.ttf │ ├── be10ea33f28a139f3305db2302af6220f2f9a583.ttf │ ├── bef923f4ccb474f961c43b63a9c74b7d9b7a023f.ttf │ ├── bf39b0e91ef9807f15a9e283a21a14a209fd2cfc.ttf │ ├── bf962d3202883a820aed019d9b5c1838c2ff69c6.ttf │ ├── c4e48b0886ef460f532fb49f00047ec92c432ec0.ttf │ ├── cc5f3d2d717fb6bd4dfae1c16d48a2cb8e12233b.ttf │ ├── cee442574141a0304e780b27dd872519f7d229db.ttf │ ├── d0430ea499348c420946f6abc2efc84fdf8f00e3.ttf │ ├── d23d76ea0909c14972796937ba072b5a40c1e257.ttf │ ├── d3129450fafe5e5c98cfc25a4e71809b1b4d2855.ttf │ ├── d629e7fedc0b350222d7987345fe61613fa3929a.ttf │ ├── d9b8bc10985f24796826c29f7ccba3d0ae11ec02.ttf │ ├── dcf774ca21062e7439f98658b18974ea8b956d0c.ttf │ ├── e207635780b42f898d58654b65098763e340f5c7.ttf │ ├── e2b17207c4b7ad78d843e1b0c4d00b09398a1137.ttf │ ├── e39391c77a6321c2ac7a2d644de0396470cd4bfe.ttf │ ├── e5ff44940364c2247abed50bdda30d2ef5aedfe4.ttf │ ├── e6185e88b04432fbf373594d5971686bb7dd698d.ttf │ ├── e68a88939e0f06e34d2bc911f09b70890289c8fd.ttf │ ├── e716f6bd00a108d186b7e9f47b4515565f784f36.ttf │ ├── e8691822f6a705e3e9fb48a0405c645b1a036590.ttf │ ├── ea3f63620511b2097200d23774ffef197e829e69.ttf │ ├── ec404b8524cd56efa5d25524cc8541a0b6604b4f.ttf │ ├── ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf │ ├── ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf │ ├── f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf │ ├── f443753e8ffe8e8aae606cfba158e00334b6efb1.ttf │ ├── f499fbc23865022234775c43503bba2e63978fe1.ttf │ ├── f518eb6f6b5eec2946c9fbbbde44e45d46f5e2ac.ttf │ ├── f70f345188472b93f565d1d7fae8c668dd6a3244.ttf │ ├── f75c4b05a0a4d67c1a808081ae3d74a9c66509e8.ttf │ ├── f79eb71df4e4c9c273b67b89a06e5ff9e3c1f834.ttf │ ├── f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf │ ├── fbb6c84c9e1fe0c39e152fbe845e51fd81f6748e.ttf │ ├── fcbaa518d3cce441ed37ae3b1fed6a19e9b54efd.ttf │ ├── fcdcffbdf1c4c97c05308d7600e4c283eb47dbca.ttf │ ├── fcea341ba6489536390384d8403ce5287ba71a4a.ttf │ ├── fd07ea46e4d8368ada1776208c07fd596f727852.ttf │ └── ffa0f5d2d9025486d8469d8b1fdd983e7632499b.ttf ├── rb_custom │ ├── AdobeBlank-Regular-OFL.txt │ ├── AdobeBlank-Regular.ttf │ ├── BungeeTint-Regular-OFL.txt │ ├── BungeeTint-Regular.ttf │ ├── LaBelleAurore-OFL.txt │ ├── LaBelleAurore.ttf │ ├── LineFont-OFL.txt │ ├── Linefont.ttf │ ├── NotoSans-OFL.txt │ ├── NotoSansCJK.subset1.otf │ ├── NotoSansMalayalam.subset1.ttf │ ├── NotoSansMyanmarUI-Regular.subset1.otf │ ├── NotoSansSinhala.subset1.otf │ ├── OpenSans-OFL.txt │ ├── OpenSans.subset1.ttf │ ├── PT_Sans-Caption-Web-Regular-OFL.txt │ ├── PT_Sans-Caption-Web-Regular.ttf │ ├── Rasa-OFL.txt │ ├── Rasa.subset1.otf │ └── test_glyphs-glyf_colr_1_no_cliplist.ttf └── text-rendering-tests │ ├── AdobeVFPrototype-Subset.otf │ ├── ArefRuqaa-Wasm.ttf │ ├── Calculator-Regular.ttf │ ├── FDArrayTest257.otf │ ├── FDArrayTest65535.otf │ ├── NotoSansBalinese-Regular.ttf │ ├── NotoSansKannada-Regular.ttf │ ├── NotoSerifKannada-Regular.ttf │ ├── TestAVAR.ttf │ ├── TestCMAP14.otf │ ├── TestCMAPMacTurkish.ttf │ ├── TestCVARGVAROne.ttf │ ├── TestCVARGVARTwo.ttf │ ├── TestGLYFOne.ttf │ ├── TestGPOSFour.ttf │ ├── TestGPOSOne.ttf │ ├── TestGPOSThree.ttf │ ├── TestGPOSTwo.otf │ ├── TestGSUBOne.otf │ ├── TestGSUBThree.ttf │ ├── TestGVAREight.ttf │ ├── TestGVARFour.ttf │ ├── TestGVARNine.ttf │ ├── TestGVAROne.ttf │ ├── TestGVARThree.ttf │ ├── TestGVARTwo.ttf │ ├── TestHVAROne.otf │ ├── TestHVARTwo.ttf │ ├── TestKERNOne.otf │ ├── TestMORXEight.ttf │ ├── TestMORXEighteen.ttf │ ├── TestMORXEleven.ttf │ ├── TestMORXForty.ttf │ ├── TestMORXFour.ttf │ ├── TestMORXFourteen.ttf │ ├── TestMORXFourtyone.ttf │ ├── TestMORXNine.ttf │ ├── TestMORXOne.ttf │ ├── TestMORXSeventeen.ttf │ ├── TestMORXSixteen.ttf │ ├── TestMORXTen.ttf │ ├── TestMORXThirteen.ttf │ ├── TestMORXThirtyeight.ttf │ ├── TestMORXThirtyfive.ttf │ ├── TestMORXThirtyfour.ttf │ ├── TestMORXThirtynine.ttf │ ├── TestMORXThirtyone.ttf │ ├── TestMORXThirtyseven.ttf │ ├── TestMORXThirtysix.ttf │ ├── TestMORXThirtythree.ttf │ ├── TestMORXThirtytwo.ttf │ ├── TestMORXThree.ttf │ ├── TestMORXTwelve.ttf │ ├── TestMORXTwenty.ttf │ ├── TestMORXTwentyeight.ttf │ ├── TestMORXTwentyfive.ttf │ ├── TestMORXTwentyfour.ttf │ ├── TestMORXTwentynine.ttf │ ├── TestMORXTwentyone.ttf │ ├── TestMORXTwentyseven.ttf │ ├── TestMORXTwentysix.ttf │ ├── TestMORXTwentythree.ttf │ ├── TestMORXTwentytwo.ttf │ ├── TestMORXTwo.ttf │ ├── TestSFNTOne.otf │ ├── TestSFNTTwo.ttf │ ├── TestShapeAran.ttf │ ├── TestShapeEthi.ttf │ ├── TestShapeLana.ttf │ └── Zycon.ttf └── shaping ├── aots.rs ├── custom.rs ├── in_house.rs ├── macos.rs ├── main.rs ├── text_rendering_tests.rs └── wasm.rs /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: [push, pull_request] 4 | 5 | env: 6 | CARGO_TERM_COLOR: always 7 | 8 | jobs: 9 | build: 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | matrix: 13 | os: [ubuntu-latest, macos-15] 14 | rust: [stable] 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | 19 | - name: Build without std 20 | run: cargo build --no-default-features 21 | 22 | - name: Build with std 23 | run: cargo build 24 | 25 | - name: Run tests 26 | run: cargo test --verbose 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .directory 3 | .DS_Store 4 | /src/complex/*.ri 5 | .vscode 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rustybuzz" 3 | version = "0.20.1" 4 | authors = [ 5 | "Caleb Maclennan ", 6 | "Laurenz Stampfl ", 7 | "Yevhenii Reizner ", 8 | "خالد حسني (Khaled Hosny) " 9 | ] 10 | edition = "2021" 11 | rust-version = "1.65.0" 12 | description = "A complete harfbuzz shaping algorithm port to Rust." 13 | documentation = "https://docs.rs/rustybuzz/" 14 | readme = "README.md" 15 | repository = "https://github.com/harfbuzz/rustybuzz" 16 | license = "MIT" 17 | keywords = ["text", "shaping", "opentype", "truetype"] 18 | categories = ["text-processing"] 19 | exclude = ["benches/", "tests/"] 20 | 21 | [dependencies] 22 | bitflags = "2.9" 23 | bytemuck = { version = "1.22", features = ["extern_crate_alloc"] } 24 | core_maths = "0.1" # only for no_std builds 25 | smallvec = "1.14" 26 | unicode-bidi-mirroring = "0.4" 27 | unicode-ccc = "0.4" 28 | unicode-properties = { version = "0.1", default-features = false, features = ["general-category"] } 29 | unicode-script = "0.5" 30 | wasmi = { version = "0.40", optional = true } 31 | log = "0.4" 32 | 33 | [dependencies.ttf-parser] 34 | version = "0.25" 35 | default-features = false 36 | features = [ 37 | "opentype-layout", 38 | "apple-layout", 39 | "variable-fonts", 40 | "glyph-names", 41 | "no-std-float", 42 | ] 43 | 44 | [features] 45 | default = ["std"] 46 | std = ["ttf-parser/std"] 47 | wasm-shaper = ["std", "dep:wasmi"] 48 | 49 | [dev-dependencies] 50 | pico-args = { version = "0.5", features = ["eq-separator"] } 51 | libc = "0.2" 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) HarfBuzz developers 4 | Copyright (c) 2020 Yevhenii Reizner 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /benches/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "benchmarks" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | [dependencies] 7 | harfbuzz_rs = { git = "https://github.com/harfbuzz/harfbuzz_rs/", rev = "43f0fb5" } 8 | rustybuzz = { path = "../" } 9 | 10 | [features] 11 | default = ["hb"] 12 | hb = [] 13 | -------------------------------------------------------------------------------- /benches/fonts/Amiri-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/Amiri-Regular.ttf -------------------------------------------------------------------------------- /benches/fonts/NotoSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/NotoSans-Regular.ttf -------------------------------------------------------------------------------- /benches/fonts/NotoSans-VariableFont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/NotoSans-VariableFont.ttf -------------------------------------------------------------------------------- /benches/fonts/NotoSansArabic-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/NotoSansArabic-Regular.ttf -------------------------------------------------------------------------------- /benches/fonts/NotoSansDevanagari-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/NotoSansDevanagari-Regular.ttf -------------------------------------------------------------------------------- /benches/fonts/NotoSansHebrew-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/NotoSansHebrew-Regular.ttf -------------------------------------------------------------------------------- /benches/fonts/NotoSansKhmer-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/NotoSansKhmer-Regular.ttf -------------------------------------------------------------------------------- /benches/fonts/NotoSansMyanmar-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/NotoSansMyanmar-Regular.ttf -------------------------------------------------------------------------------- /benches/fonts/NotoSansThai-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/NotoSansThai-Regular.ttf -------------------------------------------------------------------------------- /benches/fonts/RobotoMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harfbuzz/rustybuzz/77ea103f476199251c5c4e117362c76e35f3dd44/benches/fonts/RobotoMono-Regular.ttf -------------------------------------------------------------------------------- /benches/rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 200 -------------------------------------------------------------------------------- /benches/texts/arabic/paragraph_long.txt: -------------------------------------------------------------------------------- 1 | دفع ظهور النازية في الثلاثينيات من القرن الماضي العديد من العلماء الأوروبيين، بما فيهم ألبرت أينشتاين وإنريكو فيرمي، إلى الهجرة إلى الولايات المتحدة. خلال الحرب العالمية الثانية، طور مشروع مانهاتن الأسلحة النووية، فاتحاً المجال أمام عصر الذرة. أدى سباق الفضاء إلى تقدم سريع في إنتاج الصواريخ وعلوم المواد والكمبيوتر. كما طورت الولايات المتحدة أربانت وشبكة الإنترنت التي تلتها. يمول القطاع الخاص حالياً النسبة الأكبر من الأبحاث والتطويرات عند . تقود الولايات المتحدة العالم من حيث عدد أوراق البحث العلمي وعامل التأثير. يملك الأمريكيون مستويات عالية من السلع الاستهلاكية التكنولوجية، كما أن نصف الأسر الأمريكية لديها إمكانية الاتصال بالإنترنت عبر حزم الاتصال عريضة النطاق. تعد الولايات المتحدة البلد الرئيسي لتطوير مزارع الأغذية المعدلة وراثياً، حيث يقع في الولايات المتحدة أكثر من نصف أراضي العالم المزروعة بالمحاصيل المعدلة وراثياً. في عام ، كانت الولايات المتحدة ثاني أكبر دولة من حيث عدد الأوراق العلمية المنشورة. في ، احتلت الولايات المتحدة المركز الثاني من حيث عدد براءات الاختراع، والمركز الثالث من حيث طلبات العلامات التجارية والتصميمات الصناعية. عام ، احتلت الولايات المتحدة المركز الثالث في مؤشر الابتكار العالمي. -------------------------------------------------------------------------------- /benches/texts/arabic/paragraph_medium.txt: -------------------------------------------------------------------------------- 1 | تعد الولايات المتحدة أقدم فيدرالية حية في العالم. هي جمهورية دستورية وديمقراطية تمثيلية «تحكمها الأغلبية ويصون فيها القانون حقوق الأقليات.» هناك نظام للضوابط والتوازنات لتنظيم الحكومة حدده الدستور الأميركي، والذي يعد الوثيقة القانونية العليا للبلاد. في النظام الفيدرالي الأمريكي، يخضع المواطنون لثلاث مستويات من الحكومات: الحكومة الفيدرالية، وحكومة الولاية، والحكومة المحلية؛ تنقسم واجبات الحكومات المحلية بين حكومات المقاطعات وحكومات البلديات. يتم انتخاب مسؤولي الحكومات من قبل المواطنين عبر انتخابات فردية في تلك المقاطعات. لا يوجد نظام للتمثيل النسبي على المستوى الفيدرالي، ونادراً ما يلاحظ على المستويات الأقل من ذلك. -------------------------------------------------------------------------------- /benches/texts/arabic/paragraph_short.txt: -------------------------------------------------------------------------------- 1 | السلطة التشريعية: يتكون الكونغرس من مجلسين هما مجلس الشيوخ ومجلس النواب، من مهامه وضع القانون الفيدرالي وإعلان الحروب وتصديق المعاهدات ولديه نفوذ الملاحقة وسلطة الاتهام بحيث يمكنه إزالة أفراد من الحكومة. -------------------------------------------------------------------------------- /benches/texts/arabic/sentence_1.txt: -------------------------------------------------------------------------------- 1 | هذه جملة أطول تحتوي على المزيد من الكلمات وهي أطول قليلاً للتحقق من الوقت المستغرق لتشكيل جملة واحدة باستخدام كلا الشكلين. -------------------------------------------------------------------------------- /benches/texts/arabic/sentence_2.txt: -------------------------------------------------------------------------------- 1 | كان إنشائها مستوحى من الألعاب الأولمبية القديمة التي أقيمت في أولمبيا باليونان من القرن الثامن قبل الميلاد إلى القرن الرابع الميلادي. -------------------------------------------------------------------------------- /benches/texts/arabic/word_1.txt: -------------------------------------------------------------------------------- 1 | آلة -------------------------------------------------------------------------------- /benches/texts/arabic/word_2.txt: -------------------------------------------------------------------------------- 1 | التسريع -------------------------------------------------------------------------------- /benches/texts/arabic/word_3.txt: -------------------------------------------------------------------------------- 1 | ثعبان -------------------------------------------------------------------------------- /benches/texts/english/paragraph_long.txt: -------------------------------------------------------------------------------- 1 | The maple leaf slowly caught on as a national symbol. In 1868, it was included in the coat of arms of Ontario and the coat of arms of Quebec, and was added to the Canadian coat of arms in 1921. Historically, the golden maple leaf had represented Ontario, while the green maple leaf had represented Quebec.[4] In 1867, Alexander Muir composed the patriotic song "The Maple Leaf Forever", which became an unofficial anthem in English-speaking Canada.[5] From 1876 until 1901, the leaf appeared on all Canadian coins, and remained on the penny after 1901.[6] The use of the maple leaf as a regimental symbol extended from the 1890s, and Canadian soldiers in the Second Boer War were distinguished by a maple leaf on their sun helmets.[7] During the First World War, badges of the Canadian Expeditionary Force were often based on a maple leaf design.[8] In 1957, the maple leaf colour on the Canadian arms was changed from green to red[9] – some maple leaves are commonly red even in spring as they bud and no seasonal colouring has been assigned heraldically. -------------------------------------------------------------------------------- /benches/texts/english/paragraph_medium.txt: -------------------------------------------------------------------------------- 1 | The maple leaf became the central national symbol with the introduction of the Canadian flag (suggested by George F. G. Stanley and sponsored by MP John Matheson) in 1965, which uses a highly stylized eleven-pointed maple leaf, referring to no specific species of maple.[9] Earlier official uses of a maple leaf design often used more than 30 points and a short stem. The one chosen is a generic maple leaf representing the ten species of maple tree native to Canada – at least one of these species grows natively in every province.[10] The maple leaf is used on the Canadian flag and by the Federal Government as a personification and identifier on its websites, as part of the government's wordmark. -------------------------------------------------------------------------------- /benches/texts/english/paragraph_short.txt: -------------------------------------------------------------------------------- 1 | Its popularity with French Canadians continued and was reinforced when, at the inaugural meeting of the Saint-Jean-Baptiste Society in 1834,[3] the maple leaf was one of numerous emblems proposed to represent the society. Speaking in its favour, Jacques Viger, the first mayor of Montreal, described the maple as "the king of our forest; ... the symbol of the Canadian people." -------------------------------------------------------------------------------- /benches/texts/english/sentence_1.txt: -------------------------------------------------------------------------------- 1 | This is a longer sentence that contains some more words and is a bit more lengthy to check how long it takes to shape a single sentence with both shapers. -------------------------------------------------------------------------------- /benches/texts/english/sentence_2.txt: -------------------------------------------------------------------------------- 1 | Their creation was inspired by the ancient Olympic Games, held in Olympia, Greece from the 8th century BC to the 4th century AD. -------------------------------------------------------------------------------- /benches/texts/english/short_zalgo.txt: -------------------------------------------------------------------------------- 1 | r̶̨͔͖̜̾̅̑̆̌͊̆̚ǔ̶̮̯̳̣͕̺̲͖̊̍͑̇̈́̀ş̵̢͍̲̳̩̆̅̐̒̈́́̓̚͝t̶̜̯̆̂̎̂y̸̢̧̰͉̭̬̟̼̽͆̾͗̍̍̕͝b̶̧̥̻̭̩͙̳̂͐̆͆͊́͌̀̈́ư̵̞͌̐͛̌͑́̇̔̅ż̸̧̧̙͉̩̮͎͎̥̄͝ź̶͚̞̈́͂́ 2 | -------------------------------------------------------------------------------- /benches/texts/english/word_1.txt: -------------------------------------------------------------------------------- 1 | machine -------------------------------------------------------------------------------- /benches/texts/english/word_2.txt: -------------------------------------------------------------------------------- 1 | acceleration -------------------------------------------------------------------------------- /benches/texts/english/word_3.txt: -------------------------------------------------------------------------------- 1 | résumé -------------------------------------------------------------------------------- /benches/texts/english/word_4.txt: -------------------------------------------------------------------------------- 1 | serendipitous -------------------------------------------------------------------------------- /benches/texts/hebrew/paragraph_long_1.txt: -------------------------------------------------------------------------------- 1 | התפוח מוזכר ארבע פעמים בספר שיר השירים אך זהו אינו התפוח המוכר לנו שכן זה הגיע לעולם הקדום רק בתקופה ההלניסטית. נגה הראובני מזהה את התפוח המקראי עם העץ הנקרא כיום עוזרר זערור בפי הערבים, שם זה מוכר מהמשנה ופירושו קטן. נראה שעם הגעתו של הפרי הקרוי כיום תפוח נקרא זה תפוח גדול עקב דמיונו הרב לעוזרר הן בצורת הפרי והן בצורת העץ ואילו העוזרר נקרא תפוח קטן. עם הזמן נפלה המילה תפוח משמו של העוזרר ונפלה המילה גדול משמו של התפוח. כל פרשני ימי הביניים מסכימים עם זיהוי ה'תפוח' המקראי עם העץ הקרוי בימינו תפוח, מלבד תוספות, שפירשו שהתפוח המקראי הוא אתרוג תוספות שבת, פ"ח, א'. כך גם לדעת כמה חוקרים מודרניים, אין מדובר בתפוח, כי לדעתם קשה להניח שהתפוח, אשר אינו עץ פרי מקומי, גדל בארץ ישראל הקדומה ולפיכך הציעו פירות אחרים ממשפחת הוורדניים. אבל המחקרים האחרונים מורים שהתפוח כן גדל בארץ ישראל הקדומה. בתקופת המקרא גידולו היה מוגבל, והוא הפך לנרחב יותר בתרבות החקלאית באגן הים התיכון רק בתקופות הקלאסיות. בימי הביניים הייתה ארץ ישראל מפורסמת בתפוחיה המשובחים. ההצעה ש"תפוחי זהב" (משלי, כ"ה, י"א) הם פירות התפוז נתונה בספק, מאחר שהחלו לגדלו כגידול שכיח במזרח התיכון כנראה רק בימי הביניים. גם לזיהוי התפוח עם "פרי עץ הדעת" אין סימוכין, והוא כנראה בא על סמך פרשנות מוטעית מימי הביניים, שהחליפה אותו עם האתרוג שכונה "תפוח אדם הראשון". -------------------------------------------------------------------------------- /benches/texts/hebrew/paragraph_long_2.txt: -------------------------------------------------------------------------------- 1 | לשפה העברית יש מורפולוגיה טיפוסית של שפה שמית. המאפיינים העיקריים הם ריבוי נטיות לכל מילה (בפרט לפעלים), נטייה לא-רציפה (כלומר בסיס המילה משתנה בנטייה, ולא רק המוספיות), ושינויים רבים בתנועות לעומת יציבות של העיצורים. מקובל לתאר יצירה של מילים בשפות שמיות, בכלל זה בשפה העברית, כתהליך של הרכבת שורש ומשקל. השורש הוא מורפמה, שהיא סדרה של 3–4 (לעיתים נדירות: חמש או שש) אותיות; המשקל הוא סדרה דומה של תנועות ואלמנטים פרוזודיים (לפעמים נצמדות אליו גם מוספיות). באמצעות שילוב התנועות והאלמנטים הפרוזודיים בין עיצורי השורש נוצרת מילה. לדוגמה, הרכבת השורש כ-ת-ב על המשקל מִ-םְםָם יוצרת את המילה: מִכְתָב ("מִ" היא מוספית, לצורך תיאור המשקל מציינת כאן האות מ"ם סופית עיצור כלשהו). בדרך-כלל, למילים שנגזרות משורש אחד יש משמעות דומה, אולם יש לכך חריגים רבים. לשורשים ולמשקלים אין קיום בשפה כשלעצמם, אלא רק כמרכיב של מילים, ולעיתים קרובות בצירוף מורפמות אחרות. אין הסכמה בין הבלשנים בדבר הממשות של השורש בשפה. יש הטוענים שמדובר בחלק בלתי נפרד מאוצר המילים של השפה, גם אם הוא מופיע רק בצירוף מורפמות אחרות, ואחרים טוענים שמדובר בהפשטה מדעית, שהדוברים אינם מודעים לה בצורה אינטואיטיבית. רוב הבלשנים מסכימים כי בעבר היו שורשים של שתי אותיות כגון "ב-א" ו"ק-מ" (כיום מקובל להתייחס לשורשים האלה כשורשים תלת-עיצוריים: ב-ו-א, ק-ו-מ). כמו כן, העברית המודרנית יוצרת שורשים של יותר מ-4 אותיות (בעיקר ממילים שאולות), כגון פלרטט, טלגרף. בעברית מודרנית נוצרות מילים ששורשן אינו ברור. למשל, מילים כמו "רמזור" או "מדרחוב" נוצרו בדרך של הֶלְחם בסיסים, כך שקשה לקבוע את שורשן. עם זאת, המילה "רמזור" התפתחה לשורש רמז"ר, כמו בביטוי "צומת מרומזר". כמו כן, הקשר הסמנטי בין מילים שנגזרו משורש אחד הוא לפעמים מעורפל. כך למשל, הפעלים "פסל" (במובן של פסילה) ו"פיסל" נראים כאילו נגזרו משורש אחד, אולם אין ביניהם קשר סמנטי, כיוון שהאחרון נגזר משורש של העברית המקראית, ואילו הראשון נגזר ממילה ארמית שנכנסה אל העברית בתקופה מאוחרת יותר. -------------------------------------------------------------------------------- /benches/texts/hebrew/paragraph_medium.txt: -------------------------------------------------------------------------------- 1 | עצי התפוח גדלים במגוון רחב של קרקעות מבחינת רמת החומציות שלהן. העצים זקוקים להגנה מפני רוח ולאקלים קריר. בשנתגודלו בעולם מיליון טונות של תפוחים, כמחצית מהתוצרת מגיעה מסין, יצואניות בולטות אחרות של תפוחים הן – ארצות הברית, טורקיה, צרפת, איטליה, דרום אפריקה וצ'ילה. בישראל התפוחים גדלים בצפון הארץ ובאזור גוש עציון. -------------------------------------------------------------------------------- /benches/texts/hebrew/sentence_1.txt: -------------------------------------------------------------------------------- 1 | זהו משפט ארוך יותר שמכיל עוד כמה מילים והוא קצת יותר ארוך כדי לבדוק כמה זמן לוקח לעצב משפט בודד עם שני המעצבים. -------------------------------------------------------------------------------- /benches/texts/hebrew/sentence_2.txt: -------------------------------------------------------------------------------- 1 | המקור הקדום ביותר המזכיר את המונח עברית כשם השפה, הוא מקור יווני מן המאה ה לפנה"ס. -------------------------------------------------------------------------------- /benches/texts/hebrew/word_1.txt: -------------------------------------------------------------------------------- 1 | מְכוֹנָה -------------------------------------------------------------------------------- /benches/texts/hebrew/word_2.txt: -------------------------------------------------------------------------------- 1 | תְאוּצָה -------------------------------------------------------------------------------- /benches/texts/hindi/paragraph_long.txt: -------------------------------------------------------------------------------- 1 | क्षेत्रफल व उत्‍पन्‍न की दृष्‍टि से आम के बाद केले का क्रमांक आता है। केले के उत्‍पादन को देखे तो भारत का दूसरा क्रमांक है। भारत में अंदाजे दोन लाख बीस हजार हेक्‍टर क्षेत्रफल पर केले लगाए जाते हैं। केले का उत्‍पादन करनेवाले प्रांतो में क्षेत्रफल की दृष्‍टी से महाराष्‍ट्र का तिसरा क्रमांक है फिर भी व्‍यापारी दृष्‍टी से या परप्रांत में बिक्रीकी दृष्‍टी से होनेवाले उत्‍पादन में महाराष्‍ट्र पहिला है। उत्‍पादन के लगभग ५० प्रतिशत उत्‍पादन महाराष्‍ट्र में होता है। फिलहाल महाराष्‍ट्र में कुल चवालिस हजार हेक्‍टर क्षेत्र केले की फसल के लिए है उसमें से आधेसे अधिक क्षेत्र जलगांव जिले में है इसलिए जलगांव जिले को केलेका भंडार कहते है।मुख्‍यतः उत्‍तर भारत में जलगाव भाग के बसराई केले भेजे जाते हैं। इसी प्रकार सौदी अरेबिया इराण, कुवेत, दुबई, जपान और युरोप में बाजारपेठ में केले की निर्यात की जाती है। उससे बड़े पैमाने पर विदेशी चलन प्राप्‍त होता है। केले के ८६ प्रतिशत से अधिक उपयोग खाने के लिए होता है। पके केले उत्‍तम पौष्टिक खाद्य होकर केले के फूल, कच्‍चे फल व तने का भीतरी भाग सब्जी के लिए उपयोग में लाया जाता है।फल से पावडर, मुराब्‍बा, टॉफी, जेली आदि पदार्थ बनाते हैं। सूखे पत्तों का उपयोग आच्‍छन के लिए करते हैं। केले के तने और कंद के टुकडे करके वह जानवरो के लिए चारा के रुप में उपयोग में लाते है। केले के झाड का धार्मिक कार्य में मंगलचिन्‍ह के रुप में उपयोग में लाए जाते हैं। -------------------------------------------------------------------------------- /benches/texts/hindi/paragraph_medium.txt: -------------------------------------------------------------------------------- 1 | हिन्दी और उर्दू दोनों को मिलाकर हिन्दुस्तानी भाषा कहा जाता है। हिन्दुस्तानी मानकीकृत हिन्दी और मानकीकृत उर्दू के बोलचाल की भाषा है। इसमें शुद्ध संस्कृत और शुद्ध फ़ारसी-अरबी दोनों के शब्द कम होते हैं और तद्भव शब्द अधिक। उच्च हिन्दी भारतीय संघ की राजभाषा है (अनुच्छेद 343, भारतीय संविधान)। यह इन भारतीय राज्यों की भी राजभाषा है : उत्तर प्रदेश, बिहार, झारखण्ड, मध्य प्रदेश, उत्तरांचल, हिमाचल प्रदेश, छत्तीसगढ़, राजस्थान, हरियाणा और दिल्ली। इन राज्यों के अतिरिक्त महाराष्ट्र, गुजरात, पश्चिम बंगाल, पंजाब और हिन्दी भाषी राज्यों से लगते अन्य राज्यों में भी हिन्दी बोलने वालों की अच्छी संख्या है। उर्दू पाकिस्तान की और भारतीय राज्य जम्मू और कश्मीर की राजभाषा है, इसके अतिरिक्त उत्तर प्रदेश, बिहार, तेलंगाना और दिल्ली में द्वितीय राजभाषा है। यह लगभग सभी ऐसे राज्यों की सह-राजभाषा है; जिनकी मुख्य राजभाषा हिन्दी है। -------------------------------------------------------------------------------- /benches/texts/hindi/paragraph_short.txt: -------------------------------------------------------------------------------- 1 | अपभ्रंश की समाप्ति और आधुनिक भारतीय भाषाओं के जन्मकाल के समय को संक्रान्तिकाल कहा जा सकता है। हिन्दी का स्वरूप शौरसेनी और अर्धमागधी अपभ्रंशों से विकसित हुआ है। १००० ई॰ के आसपास इसकी स्वतन्त्र सत्ता का परिचय मिलने लगा था, जब अपभ्रंश भाषाएँ साहित्यिक सन्दर्भों में प्रयोग में आ रही थीं। यही भाषाएँ बाद में विकसित होकर आधुनिक भारतीय आर्य भाषाओं के रूप में अभिहित हुईं। अपभ्रंश का जो भी कथ्य रूप था - वही आधुनिक बोलियों में विकसित हुआ। -------------------------------------------------------------------------------- /benches/texts/hindi/sentence_1.txt: -------------------------------------------------------------------------------- 1 | यह एक लम्बा वाक्य है जिसमें कुछ और शब्द हैं तथा यह थोड़ा अधिक लम्बा है, जिससे यह पता लगाया जा सके कि दोनों शेपर्स के साथ एक वाक्य को आकार देने में कितना समय लगता है। -------------------------------------------------------------------------------- /benches/texts/hindi/sentence_2.txt: -------------------------------------------------------------------------------- 1 | सम्पूर्ण भारत के विभिन्न राज्यों में हिन्दी और इसकी बोलियाँ बोली जाती हैं। भारत और अन्य देशों में भी लोग हिन्दी बोलते, सोचते और सोचते हैं। -------------------------------------------------------------------------------- /benches/texts/hindi/word_1.txt: -------------------------------------------------------------------------------- 1 | मशीन -------------------------------------------------------------------------------- /benches/texts/hindi/word_2.txt: -------------------------------------------------------------------------------- 1 | त्वरण -------------------------------------------------------------------------------- /benches/texts/khmer/paragraph_long_1.txt: -------------------------------------------------------------------------------- 1 | នៅ​សតវត្ស​ទី​១៩ សហរដ្ឋអាមេរិក​បាន​ទទួល​ទឹកដី​ប្រទេស​បារាំង អេស្ប៉ាញ រាជាណាចក្ររួម មិកស៊ិក និង​រុស្ស៊ី ហើយ​ថែមទាំង​បាន​ធ្វើ​ការ​បង្រួបបង្រួម​ជាមួយ​សាធារណរដ្ឋ​តិចសាស និង​សាធារណរដ្ឋ​ហាវៃ​ទៀត​ផង ។ ជម្លោះ​រវាង​បណ្ដា​រដ្ឋ​កសិកម្ម​នៅ​ភាគ​ខាងត្បូង និង​បណ្ដា​រដ្ឋ​ឧស្សាហកម្ម​នៅ​ភាគ​ខាងជើង លើ​បញ្ហា​សិទ្ធិ និង​ច្បាប់​ស្ដីពី​ទាសភាព បាន​បង្ក​ឱ្យ​មាន​សង្គ្រាមស៊ីវិល ឬ សង្គ្រាម​បំបែក​ស្រុក​នៅ​អាមេរិក ក្នុង​ទសវត្ស​ឆ្នាំ ១៨៦០ ។ ទីបំផុត​ទៅ ពួក​ខាងជើង​បាន​ទទួល​ជ័យជម្នះ បាន​ធ្វើ​ឱ្យ​សហរដ្ឋអាមេរិក​រក្សា​បាន​នូវ​ឯកភាព និង​លុបបំបាត់​ចោល​ច្បាប់​ទាសភាព​នៅ​សហរដ្ឋអាមេរិក​ទាំងមូល​។ សង្គ្រាម​អេស្ប៉ាញ-អាមេរិក និង​សង្គ្រាមលោក​លើក​ទី​១ បាន​បង្ហាញ​ឱ្យ​ឃើញ​ថា​សហរដ្ឋអាមេរិក ជា​មហាអំណាច​យោធា​មួយ​លើ​ពិភពលោក​។ សង្គ្រាមលោក​លើក​ទី​២ នៅ​ឆ្នាំ ១៩៤៥ សហរដ្ឋអាមេរិក​ជា​ប្រទេស​ទី​១ ដែល​មាន​អាវុធ​នុយក្លេអ៊ែរ ជា​សមាជិក​អចិន្ត្រៃយ៍​នៃ​ក្រុមប្រឹក្សាសន្តិសុខ​អង្គការសហប្រជាជាតិ និង​ជា​សមាជិក​ស្ថាបនិក​មួយ​នៃ​អង្គការ​ណាតូ​។ ក្រោយ​សង្គ្រាមត្រជាក់ និង​ការ​ដួល​រលំ​នៃ​សហភាពសូវៀត បាន​ធ្វើ​ឱ្យ​សហរដ្ឋអាមេរិក​ក្លាយ​ជា​កំពូល​មហាអំណាច​តែមួយគត់​។ នៅ​វិស័យ​យោធា សហរដ្ឋអាមេរិក​បាន​ចំណាយ​ជាង ៥០% នៃ​វិស័យ​យោធា​ទាំងអស់​លើ​ពិភពលោក និង​ភាព​នាំមុខ​គេ​ទាំង​សេដ្ឋកិច្ច នយោបាយ និង​វប្បធម៌​។ -------------------------------------------------------------------------------- /benches/texts/khmer/paragraph_long_2.txt: -------------------------------------------------------------------------------- 1 | កម្ពុជា​បាន​ងើប​មុខ​ឡើង​វិញ​ប៉ុន្មានឆ្នាំ​ក្រោយ​មក​ក្នុង​មណ្ឌល​នៃ​ឥទ្ធិពល​សង្គមនិយម ជា​សាធារណរដ្ឋប្រជាមានិតកម្ពុជា​រហូត​ដល់​ឆ្នាំ​ ១៩៩៣។ បន្ទាប់​ពី​ប៉ុន្មាន​ឆ្នាំ​នៃ​គម្លាត​ឆ្ងាយ ប្រជាជាតិ​ដែល​ត្រូវ​បាន​បំផ្លិច​បំផ្លាញ​ដោយ​សារ​សង្គ្រាមមួយនេះ បាន​បង្រួប​បង្រួម​គ្នាឡើង​វិញ​ក្រោម​របប​រាជាធិបតេយ្យ​នៅ​ឆ្នាំ ១៩៩៣ និង​បាន​ស្គាល់នូវ​ការ​រីក​ចម្រើន​យ៉ាង​លឿន​ក្នុង​វិស័យ​សេដ្ឋកិច្ច និង​ធនធានមនុស្ស ដែល​ពេល​នោះកំពុង​តែ​រស់រានឡើង​វិញក្រោយ​ពី​ប៉ុន្មាន​ទសវត្ស​នៃ​សង្គ្រាមរដ្ឋប្បវេណី​មក។ កម្ពុជា​ធ្លាប់​មាន​កំណត់ត្រា​មួយ​ក្នុង​ចំណោម​កំណត់ត្រា​សេដ្ឋកិច្ច​ដ៏​ល្អ​បំផុត​នៅ​អាស៊ី ជាមួយ​នឹង​កំណើន​សេដ្ឋកិច្ច​ជា​មធ្យម ៦, ក្នុងរយៈ​ពេល​ ១០ ​ឆ្នាំ​ចុង​ក្រោយ​នេះ។ វិស័យ​វាយនភណ្ឌ កសិកម្ម សំណង់ សម្លៀកបំពាក់ និង ​ទេសចរណ៍​ដ៏​ខ្លាំងក្លា​បាន​នាំ​ឱ្យ​មាន​ការ​បណ្ដាក់​ទុន​បរទេស និង​ការ​ដោះដូរ​ពាណិជ្ជកម្ម​អន្តរជាតិ។[៨] នៅ​ឆ្នាំ​២០០៥ ស្រទាប់​រ៉ែប្រេង និង​ឧស្ម័ន​ធម្មជាតិ​ត្រូវ​បាន​រក​ឃើញ​ខាង​ក្រោម​ទឹក​ក្នុង​ទឹក​ដី​កម្ពុជា និង​គ្រានោះដែរ​និស្សារណកម្ម​ពាណិជ្ជកម្មនឹង​ចាប់ផ្ដើម​ក្នុង​ឆ្នាំ ​២០១៣ ចំណូល​ប្រេង​ទាំងមូល​អាច​ជះ​ឥទ្ធិពល​ដល់​សេដ្ឋកិច្ច​កម្ពុជា​យ៉ាង​ខ្លាំង។[៩] ទោះបីមានការរីកចម្រើនខាងសេដ្ឋកិច្ចយ៉ាងណាក្ដី ពេលតែមួយក្នុងឆ្នាំ ២០១៣ នោះដែរ លិបិក្រមអភិវឌ្ឍន៍មនុស្ស (លអម) ចាត់ថ្នាក់កម្ពុជាក្នុងចំណាត់ថ្នាក់ទី១៣៨ (រួមជាមួយ លាវ) ក្នុងលក្ខខណ្ឌនៃការអភិវឌ្ឍមនុស្សចង្អុលបង្ហាញថាកម្ពុជាមានការរីកចម្រើនពីមធ្យមមកទាបមកទល់​សព្វថ្ងៃនេះ។[១០] -------------------------------------------------------------------------------- /benches/texts/khmer/paragraph_medium.txt: -------------------------------------------------------------------------------- 1 | អ្នក​ប្រាជ្ញ​ជំនាន់​មុន​ចែង​ថា ស្រៈ​ពេញ​តួ​មាន ១៦ តួ ដោយ​រាប់​យក​ អ អា មក​បញ្ចូល​ផង ។ ប៉ុន្តែ​អ្នក​ប្រាជ្ញ​បច្ចុប្បន្ន​លោក​ដក​យក​ “៛អ” និង “អា” នេះ​ចេញ​ពី​ប្រព័ន្ធ​ស្រៈ​ពេញ​តួ ព្រោះ​លោក​យល់​ថា​​ “អ” គឺ​ជា​ព្យញ្ជនៈ ដែល​ត្រូប​រាប់​បញ្ចូល​ទៅ​ក្នុង​ក្រុម​ព្យញ្ជនៈ ទាំង​៣៣​ តួ​នោះ​វិញ ។ ឯ “អា” គឺ​តួ​ព្យញ្ជនៈ​បំបែក ​យក​តួ ​​​​​​​​​ “ អ” មក​ផ្សំ​ជា​មួយ​ស្រៈ “ ា ” ដូច្នេះ​ស្រៈ​ពេញ​តួ​បច្ចុប្បន្ន​នេះ មាន​តែ ១៤​តួ​ទេ គឺ ឥ​ ឦ​ ឧ ​ឩ ឪ ឱ្យឫ ឬ ឭ ឮ ឯ ឰ ឱ ឳ ។ ចំពោះ​អស់​លោក​អ្នក​ប្រាជ្ញ​ខ្លះ​ទៀត​យល់​ថា ​ក្នុង​ចំណោម​ស្រៈ​ពេញ​តួ​ទាំង​១៤ជាៗ​នេះ ស្រៈ ឩ គេ​មិន​សូវ​ប្រើ​ទេ ដូច្នេះ​ គួរ​រាប់​យក​ត្រឹម​តែ ១៣ តួវិញ ព្រោះ​គេ​ប្រើ​ស្រៈ​ពេញ​តួ ឩ នេះ​តែ​ពាក្យ “ព្រះ​ឩរូ” មួយម៉ាត់​គត់ ដែល​មាន​នៅ​ក្នុង​ពាក្យ “ រាជ​ស័ព្ទ ” មាន​ន័យ​ថា “​ ភ្លៅ​ស្ដេច ” ។ -------------------------------------------------------------------------------- /benches/texts/khmer/sentence_1.txt: -------------------------------------------------------------------------------- 1 | นี่เป็นประโยคที่ยาวกว่าซึ่งมีคำมากกว่าปกติ และยาวกว่าเล็กน้อยในการตรวจสอบว่าต้องใช้เวลานานเท่าใดในการกำหนดรูปแบบประโยคเดียวด้วยทั้งสองโปรแกรม -------------------------------------------------------------------------------- /benches/texts/khmer/sentence_2.txt: -------------------------------------------------------------------------------- 1 | ខ្មែរ គឺជាភាសាកំណើតរបស់ជនជាតិខ្មែរនិងជាភាសាផ្លូវការរបស់ប្រទេសកម្ពុជា។ -------------------------------------------------------------------------------- /benches/texts/khmer/word_1.txt: -------------------------------------------------------------------------------- 1 | ម៉ាស៊ីន -------------------------------------------------------------------------------- /benches/texts/khmer/word_2.txt: -------------------------------------------------------------------------------- 1 | ការបង្កើនល្បឿន -------------------------------------------------------------------------------- /benches/texts/khmer/word_3.txt: -------------------------------------------------------------------------------- 1 | ស្ងប់ស្ងាត់ -------------------------------------------------------------------------------- /benches/texts/myanmar/paragraph_long.txt: -------------------------------------------------------------------------------- 1 | ရှေးအခါက တောကြီးမျက်မည်းဖြစ်၍ ရောဂါဘယထူပြောသော အပူပိုင်း အရပ်ဒေသများသည် ယခုအခါတွင် ငှက်ပျောစိုက်ခင်းကြီးများ ဖြစ်လာကြသည်။ ယခင်က သမပိုင်းဇုန်၌ နေထိုင်သူတို့တွင် ငှက်ပျောသီးကို လူတိုင်းပင် မမြင်ဘူး။ မစားဘူးကြချေ။ မီးသင်္ဘောများ စတင်ပေါ်ပေါက်လာသည့်အခါမှ အလွန်အမှည့်လွယ်သော ငှက်ပျောသီးများကို လိုရာ အရပ်သို့ သယ်ယူရောင်းချနိုင်ကြသည်။ ငှက်ပျောစိုက်ခင်းများမှသင်္ဘောကမ်းသို့ ငှက်ပျောခိုင် အစိမ်းလိုက်ကို အထူးမီးရထားတွဲများဖြင့် တင်ပို့သည်။ ငှက်ပျောခိုင်များထားရာ အခန်းမှာ အပူချိန် ၅၆ ဒီဂရီ(56 °F) သာ ရှိရပေမည်။ အသီးများ အခိုင်မှ ကြွေမကျစေရန် အတင်အချတွင် အလွန်ဂရုစိုက်ရသည်။ လိုရာမြို့ကြီးများသို့ ငှက်ပျောခိုင်အစိမ်းများ ရောက်သောအခါ အမှည့်ခံအခန်းများတွင် ငှက်ပျောခိုင်များကို အပူဓာတ်ပေးခြင်းဖြင့် နာရီအနည်းငယ်အတွင်း အသီးများ ဝင်းထိန်၍ မှည့်လာကြသည်။ ငှက်ပျောပင်သည် ၁၂ ပေ မှ ၃ဝ ပေအထိမြင့်သော တစ်နှစ်ခံပင်မျိုးဖြစ်၍ ရှည်ဖားဖား အရွက်ကြီးများရှိသည်။ ငှက်ပျောပင်တစ်ပင်မှ ငှက်ပျောတစ်ခိုင်သာ ထွက်၍ အခိုင်ကို ခုတ်ယူပြီးနောက် အပင်မကြီးကို ခုတ်ပစ်ရသည်။ ပင်စည်ရင်းမှ အတက်ငယ်များ ဖြာလာ၍ ထိုသားတက်ခေါ် ငှက်ပျောခေါင်းများကိုပင်မမှ ခွဲထုတ်၍ စိုက်ပျိုးကြပြန်သည်။ သို့အားဖြင့် ငှက်ပျောပင်များကို မျိုးပွားယူကြ၏။ အပင် ၁၂ လမှ ၁၈ လအထိရှိမှအသီးများ ထွက်လာသည်။ ငှက်ပျောသီးတွင် ရေ ၇၅ ရာခိုင်နှုန်းပါသည်။ အသီးတွင် ပါရှိသော ကစီဓာတ်သည် အသီးမှည့်လာသောအခါ သကြားဓာတ်သို့ ပြောင်းလဲသွားသဖြင့် စားသုံးရာ၌ အလွန်အနှစ်အရသာနှင့် ပြည့်စုံသည်။ ငှက်ပျောသီးသည်လူတို့အတွက် အာဟာရဓာတ်ဖြည့်စွမ်းသော အစားအစာတစ်ရပ်ဖြစ်ပေသည်။ ကမ္ဘာပေါ်တွင် လူတို့သိနှင့်ပြီးသော ငှက်ပျောပင်မျိုးပေါင်း ၇ဝ နီးပါးရှိသည်။ သို့ရာတွင် မြန်မာနိုင်ငံ၌ထင်ရှားသောငှက်ပျောမျိုးမှာ ထောပတ်၊ ရခိုင်၊ နံ့သာပု၊ သီးမွှေး၊ ဖီးကြမ်း၊သူငယ်စာ၊ ပျားရည်ဆမ်း၊ ရသာရုံ၊ မယားမန်၊ ငှက်ပျောချဉ်၊ရွှေနီနှင့် ဝက်မလွတ်တို့ ဖြစ်သည်။ အလုံးအလွန်ကြီးထွားသော ငှက်ပျောမျိုးကို မြန်မာနိုင်ငံတွင် ဆင်အံ သို့မဟုတ်ဗျပ်ပြည့် သို့မဟုတ် မောင်ကြီးပင့်ပါဟု ခေါ်ကြသည်။ သမပိုင်းနိုင်ငံတို့တွင် ဂျုံနှင့် အာလူးကို အဓိကအာဟာရအဖြစ် မှီဝဲသကဲ့သို့ အပူပိုင်းဒေသရှိ တိုင်းပြည်အချို့တွင် ငှက်ပျောသီးအစိမ်းများကို အဓိကအာဟာရ အဖြစ်ဖြင့် စားသုံးကြသည်။ -------------------------------------------------------------------------------- /benches/texts/myanmar/paragraph_medium.txt: -------------------------------------------------------------------------------- 1 | အကျယ်အဝန်း စတုရန်းမိုင်ပေါင်း ၃.၇၉ သန်း (စတုရန်း ကီလိုမီတာ ၉.၈၃ သန်း) နှင့် လူဦးရေ သန်း ၃၀၀ ကျော်ရှိသည့်အတွက် အမေရိကန်ပြည်ထောင်စုတွင် ကမ္ဘာပေါ်တွင် စုစုပေါင်း အကျယ်အဝန်းအားဖြင့် စတုတ္တမြောက် အကြီးဆုံးနှင့် ကုန်းမြေအကျယ်အဝန်းနှင့် လူဦးရေအားဖြင့် တတိယမြောက် အကြီးမား အများပြားဆုံး ဖြစ်သည်။ နိုင်ငံအများအပြားမှ လူအများအပြား ရွှေ့ပြောင်းနေထိုင်ကြသဖြင့် အမေရိကန်ပြည်ထောင်စုသည် ကမ္ဘာပေါ်တွင် လူမျိုးစု အများဆုံး ရောထွေးနေထိုင်ပြီး ယဉ်ကျေးမှုအစုံလင်ဆုံး နိုင်ငံများတွင် တစ်နိုင်ငံ အပါအဝင်ဖြစ်သည်။ အမေရိကန်၏ စီးပွားရေးသည် ကမ္ဘာပေါ်တွင် အကြီးဆုံး စီးပွားရေးဖြစ်ပြီး စုစုပေါင်း ပြည်တွင်းထုတ်ကုန် အမေရိကန် ဒေါ်လာ ၁၄.၃ ထရီလီယံ မျှရှိသည်။အားဖြင့် တစ်ကမ္ဘာလုံး၏ ၂၃ ရာခိုင်နှုန်းဖြစ်ပြီး တစ်ကမ္ဘာလုံး ဝယ်ယူသည့်တန်ဖိုး၏ ၂၁ ရာခိုင်နှုန်းဖြစ်သည်။) -------------------------------------------------------------------------------- /benches/texts/myanmar/paragraph_short.txt: -------------------------------------------------------------------------------- 1 | ၂၀၁၇ ခုနှစ်တွင် ကမ္ဘာတစ်ဝန်း ပန်းသီးထုတ်လုပ်မှုသည် တန်ချိန် ၈၃.၁ သန်းရှိသည်။ တရုတ်နိုင်ငံ၏ ထုတ်လုပ်မှုသည် စုစုပေါင်းထုတ်လုပ်မှု၏ ၄၉.၈ ရာခိုင်နှုန်း ရှိသည်။[၃] -------------------------------------------------------------------------------- /benches/texts/myanmar/sentence_1.txt: -------------------------------------------------------------------------------- 1 | ဤသည်မှာ စကားလုံးအချို့ပါရှိသော ရှည်လျားသောဝါကျဖြစ်ပြီး ပုံသဏ္ဍာန်နှစ်ခုစလုံးဖြင့် ဝါကျတစ်ခုကိုပုံဖော်ရန် အချိန်မည်မျှကြာကြောင်း စစ်ဆေးရန် အနည်းငယ်ပိုရှည်သည်။ -------------------------------------------------------------------------------- /benches/texts/myanmar/sentence_2.txt: -------------------------------------------------------------------------------- 1 | မြန်မာနိုင်ငံ (အဂ္လိပ်: မြန်မာဘာသာ မြန်မာပြည်)၊ တရားဝင်အားဖြင့် ပြည်ထောင်စု သမ္မတ မြန်မာနိုင်ငံတော် (ပြည်ထောင်စု သမ္မတ မြန်မာနိုင်ငံတော်) သည် ดังရှိ နိုင်ငံတစ်နိုင်ငံทอด အနောက်နှင့် အနောက်မြောက်ဘက်တွင် နိုင်ငံ၊ -------------------------------------------------------------------------------- /benches/texts/myanmar/word_1.txt: -------------------------------------------------------------------------------- 1 | စက် -------------------------------------------------------------------------------- /benches/texts/myanmar/word_2.txt: -------------------------------------------------------------------------------- 1 | အရှိန် -------------------------------------------------------------------------------- /benches/texts/thai/paragraph_long.txt: -------------------------------------------------------------------------------- 1 | ช่วงต้นกรุงรัตนโกสินทร์อินเดียสามารถลงทะเบียนได้จากชาติใกล้เคียงแต่หลังรัชดาพระบาทหลวงจอมเกล้าเจ้าอยู่หัวเป็นต้นมาชาติตะวันตกเริ่มช้าลงเรื่อยๆเรื่อยๆเข้าเป็นภาคีแห่งสนธิสัญญาไม่ยุติธรรมหลายฉบับเริ่ม จากสนธิสัญญาเบา ๆ แหวนล่องเรือ สยามไม่ตกเป็นส่วนสำคัญของชาติใด ๆ มีให้สยามประจักษ์และรวมอำนาจอีกครั้งในรัชกาลพระบาทสมเด็จพระเจ้าจอมจิตเกล้าเจ้าอยู่หัว สยามกับเข้าร่วมฝ่ายสัมพันธมิตรในเส้นทางที่หนึ่งในปี ในปี พ.ศ. เป็นผลมาจากการปรับปรุงเซิร์ฟเวอร์สู่การพิสูจน์ประสิทธิภาพอันมีความน่าเชื่อถือ​ ทรงเป็นประมุขโดยไม่เสียเลือดเนื้อคณะราษฎรเป็นจุดนำที่โดดเด่นและในพุทธศาสนิกชนทฤษฎีจอมพลแปลกพิบูลสงคราม ดำเนินแนวทางปฏิบัติชาตินิยมเข้มข้นตามมาภายหลังไทยเข้า กับฝ่ายอักษะ แต่ฝ่ายพันธมิตรส่วนมากมักจะไม่ยอมรับสงคราม รัฐบาลสงครามเย็นเป็นพันธมิตรกับรัฐบาลซึ่งสนับสนุนรัฐบาลทหารรัฐประหารที่มีจอมพลสฤษดิ์ธนะรัชต์เป็นหัวหน้าคณะในปี พ.ศ. นำประเทศเข้าสู่ทั่วไป ยุคเผด็จการทหารอย่างเบ็ดเสร็จ รัฐบาลฟื้นฟูพระราชอำนาจและดำเนินการตามนโยบายคอมมิวนิสต์ในไดรฟ์ ตุ ระบบควบคุมการปกครองช่วงสั้น แต่หลังจากนั้น ตุลาและรัฐประหารปี สำหรับประเทศไทยกลับเข้าสู่เผด็จการทหาร และ "ประชาธิปไตยครึ่งใบ" ประเทศไทยมีตั้งแต่ครั้งแรกในปี หลังพุทธศาสนิกชน มีวิกฤตการณ์การเมืองระหว่างฝ่ายที่สนับสนุนและผลกระทบต่ออดีตกาลทักษิณ ชินวัตรมาจนปัจจุบันปัจจุบันเกิดรัฐประหารโดยโดยครั้งล่าสุด สำหรับในปี เอกสารฉบับปัจจุบันเป็นฉบับที่ ประกาศใช้ต่อไปเมษายน -------------------------------------------------------------------------------- /benches/texts/thai/paragraph_medium.txt: -------------------------------------------------------------------------------- 1 | จนกระทั่งคริสต์ศตวรรษที่ ชาวไร่เก็บแอปเปิลไว้ในห้องเก็บป้องกันความเย็นตลอดฤดูหนาวสำหรับใช้และสำหรับขาย ต่อมาการคมนาคมขนส่งแอปเปิลที่พัฒนาขึ้นได้เข้ามาแทนที่ ทำให้การเก็บรักษาไม่จำเป็นอีกต่อไป ในคริสต์ศตวรรษที่ การเก็บรักษาแอปเปิลในระยะยาวกลับมาได้รับความนิยมอีกครั้ง เนื่องจากมีสาธารณูปโภคที่ "ควบคุมบรรยากาศได้" สามารถเก็บแอปเปิลได้นานถึงปี สาธารณูปโภคดังกล่าวใช้ความชื้นสูง ออกซิเจนต่ำ และควบคุมระดับคาร์บอนไดออกไซด์เพื่อรักษาความสดของแอปเปิล -------------------------------------------------------------------------------- /benches/texts/thai/paragraph_short.txt: -------------------------------------------------------------------------------- 1 | ประเทศไทยเป็นหนึ่งในประเทศที่ได้รับผลกระทบจากปัญหาโลกเดือด มีอากาศร้อนในฤดูหนาว รวมถึงมีปัญหาฝุ่นละออง จากเอลนีโญ ปัญหาดังกล่าวส่งผลกระทบต่อประเทศไทยในวงกว้าง โดยเฉพาะสุขภาพของประชากรไทยโดยรวม -------------------------------------------------------------------------------- /benches/texts/thai/sentence_1.txt: -------------------------------------------------------------------------------- 1 | นี่เป็นประโยคที่ยาวกว่าซึ่งมีคำมากกว่าปกติ และยาวกว่าเล็กน้อยในการตรวจสอบว่าต้องใช้เวลานานเท่าใดในการสร้างประโยคเดียวด้วยทั้งสองโปรแกรม -------------------------------------------------------------------------------- /benches/texts/thai/word_1.txt: -------------------------------------------------------------------------------- 1 | เครื่องจักร -------------------------------------------------------------------------------- /benches/texts/thai/word_2.txt: -------------------------------------------------------------------------------- 1 | การเร่งความเร็ว -------------------------------------------------------------------------------- /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | ArabicShaping.txt 2 | Blocks.txt 3 | DerivedCoreProperties.txt 4 | IndicPositionalCategory.txt 5 | IndicSyllabicCategory.txt 6 | Scripts.txt 7 | UnicodeData.txt 8 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | ## Usage 2 | 3 | ```sh 4 | python3 gen-universal-table.py > ../src/hb/ot_shaper_use_table.rs 5 | 6 | python3 ./gen-vowel-constraints.py > ../src/complex/vowel_constraints.rs 7 | rustfmt ../src/complex/vowel_constraints.rs 8 | ``` 9 | -------------------------------------------------------------------------------- /scripts/gen-unicode-is-emoji-ext-pict.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import urllib.request 4 | import os 5 | 6 | URL = 'https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt' 7 | FILE_NAME = 'emoji-data.txt' 8 | 9 | if not os.path.exists(FILE_NAME): 10 | urllib.request.urlretrieve(URL, FILE_NAME) 11 | 12 | is_ext_pict_section = False 13 | ranges = [] 14 | with open(FILE_NAME) as f: 15 | for line in f: 16 | line = line.strip() 17 | 18 | if not is_ext_pict_section: 19 | if line == '# All omitted code points have Extended_Pictographic=No': 20 | is_ext_pict_section = True 21 | continue 22 | 23 | if not line: 24 | continue 25 | 26 | if line.startswith('#'): 27 | continue 28 | 29 | range, _ = line.split(' ; ') 30 | range = range.strip() 31 | 32 | if '..' in range: 33 | start, end = range.split('..') 34 | ranges.append([start, end]) 35 | else: 36 | ranges.append([range, range]) 37 | 38 | # Merge ranges. 39 | idx = 0 40 | while idx < len(ranges)-1: 41 | if int(ranges[idx][1], 16) + 1 == int(ranges[idx+1][0], 16): 42 | ranges[idx][1] = ranges[idx+1][1] 43 | del ranges[idx+1] 44 | else: 45 | idx += 1; 46 | 47 | for range in ranges: 48 | if range[0] == range[1]: 49 | print('0x{} => true,'.format(range[0], range[1])) 50 | else: 51 | print('0x{}..=0x{} => true,'.format(range[0], range[1])) 52 | -------------------------------------------------------------------------------- /scripts/ms-use/COPYING: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /src/hb/aat_layout_common.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::aat_map::range_flags_t; 2 | use crate::hb::buffer::hb_buffer_t; 3 | use crate::hb::face::hb_font_t; 4 | use crate::hb::hb_mask_t; 5 | 6 | pub struct hb_aat_apply_context_t<'a> { 7 | pub face: &'a hb_font_t<'a>, 8 | pub buffer: &'a mut hb_buffer_t, 9 | pub range_flags: Option<&'a mut [range_flags_t]>, 10 | pub subtable_flags: hb_mask_t, 11 | } 12 | 13 | impl<'a> hb_aat_apply_context_t<'a> { 14 | pub fn new(face: &'a hb_font_t<'a>, buffer: &'a mut hb_buffer_t) -> Self { 15 | Self { 16 | face, 17 | buffer, 18 | range_flags: None, 19 | subtable_flags: 0, 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/hb/algs.rs: -------------------------------------------------------------------------------- 1 | // FLAG macro in harfbuzz. 2 | #[inline] 3 | pub const fn rb_flag(x: u32) -> u32 { 4 | 1 << x 5 | } 6 | 7 | // FLAG_UNSAFE macro in harfbuzz. 8 | #[inline] 9 | pub fn rb_flag_unsafe(x: u32) -> u32 { 10 | if x < 32 { 11 | 1 << x 12 | } else { 13 | 0 14 | } 15 | } 16 | 17 | // FLAG_RANGE macro in harfbuzz. 18 | #[inline] 19 | pub fn rb_flag_range(x: u32, y: u32) -> u32 { 20 | (x < y) as u32 + rb_flag(y + 1) - rb_flag(x) 21 | } 22 | 23 | // FLAG64 macro in harfbuzz. 24 | #[inline] 25 | pub const fn rb_flag64(x: u32) -> u64 { 26 | 1 << x as u64 27 | } 28 | 29 | // FLAG64_UNSAFE macro in harfbuzz. 30 | #[inline] 31 | pub fn rb_flag64_unsafe(x: u32) -> u64 { 32 | if x < 64 { 33 | 1 << (x as u64) 34 | } else { 35 | 0 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/hb/mod.rs: -------------------------------------------------------------------------------- 1 | // Match harfbuzz code style. 2 | #![allow(non_camel_case_types)] 3 | #![allow(non_upper_case_globals)] 4 | #![allow(non_snake_case)] 5 | #![allow(clippy::collapsible_if)] 6 | #![allow(clippy::collapsible_else_if)] 7 | #![allow(clippy::comparison_chain)] 8 | #![allow(clippy::needless_range_loop)] 9 | #![allow(clippy::non_canonical_partial_ord_impl)] 10 | #![allow(clippy::upper_case_acronyms)] 11 | #![allow(clippy::too_many_arguments)] 12 | #![allow(clippy::wildcard_in_or_patterns)] 13 | #![allow(clippy::identity_op)] 14 | #![allow(clippy::mut_range_bound)] 15 | #![allow(clippy::enum_variant_names)] 16 | #![allow(clippy::manual_range_patterns)] 17 | #![allow(clippy::type_complexity)] 18 | #![allow(clippy::wrong_self_convention)] 19 | #![allow(clippy::match_like_matches_macro)] 20 | #![allow(clippy::manual_range_contains)] 21 | 22 | mod algs; 23 | #[macro_use] 24 | pub mod buffer; 25 | mod aat_layout; 26 | mod aat_layout_kerx_table; 27 | mod aat_layout_morx_table; 28 | mod aat_layout_trak_table; 29 | mod aat_map; 30 | pub mod common; 31 | pub mod face; 32 | mod kerning; 33 | mod machine_cursor; 34 | mod ot; 35 | mod ot_layout; 36 | mod ot_layout_common; 37 | mod ot_layout_gpos_table; 38 | mod ot_layout_gsub_table; 39 | mod ot_layout_gsubgpos; 40 | mod ot_map; 41 | mod ot_shape; 42 | mod ot_shape_fallback; 43 | mod ot_shape_normalize; 44 | pub mod ot_shape_plan; 45 | mod ot_shaper; 46 | mod ot_shaper_arabic; 47 | mod ot_shaper_arabic_table; 48 | mod ot_shaper_hangul; 49 | mod ot_shaper_hebrew; 50 | mod ot_shaper_indic; 51 | mod ot_shaper_indic_machine; 52 | #[rustfmt::skip] 53 | mod ot_shaper_indic_table; 54 | mod ot_shaper_khmer; 55 | mod ot_shaper_khmer_machine; 56 | mod ot_shaper_myanmar; 57 | mod ot_shaper_myanmar_machine; 58 | mod ot_shaper_syllabic; 59 | mod ot_shaper_thai; 60 | mod ot_shaper_use; 61 | mod ot_shaper_use_machine; 62 | #[rustfmt::skip] 63 | mod ot_shaper_use_table; 64 | mod aat_layout_common; 65 | mod ot_shaper_vowel_constraints; 66 | mod paint_extents; 67 | mod set_digest; 68 | pub mod shape; 69 | #[cfg(feature = "wasm-shaper")] 70 | mod shape_wasm; 71 | mod tag; 72 | mod tag_table; 73 | mod text_parser; 74 | mod unicode; 75 | mod unicode_norm; 76 | 77 | use ttf_parser::Tag as hb_tag_t; 78 | 79 | use self::buffer::hb_glyph_info_t; 80 | use self::face::hb_font_t; 81 | 82 | type hb_mask_t = u32; 83 | 84 | use self::common::{script, Direction, Feature, Language, Script}; 85 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GPOS/mark_array.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::buffer::HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; 2 | use crate::hb::ot_layout_gpos_table::{attach_type, AnchorExt}; 3 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 4 | use ttf_parser::gpos::{AnchorMatrix, MarkArray}; 5 | 6 | pub(crate) trait MarkArrayExt { 7 | fn apply( 8 | &self, 9 | ctx: &mut hb_ot_apply_context_t, 10 | anchors: AnchorMatrix, 11 | mark_index: u16, 12 | glyph_index: u16, 13 | glyph_pos: usize, 14 | ) -> Option<()>; 15 | } 16 | 17 | impl MarkArrayExt for MarkArray<'_> { 18 | fn apply( 19 | &self, 20 | ctx: &mut hb_ot_apply_context_t, 21 | anchors: AnchorMatrix, 22 | mark_index: u16, 23 | glyph_index: u16, 24 | glyph_pos: usize, 25 | ) -> Option<()> { 26 | // If this subtable doesn't have an anchor for this base and this class 27 | // return `None` such that the subsequent subtables have a chance at it. 28 | let (mark_class, mark_anchor) = self.get(mark_index)?; 29 | let base_anchor = anchors.get(glyph_index, mark_class)?; 30 | 31 | let (mark_x, mark_y) = mark_anchor.get(ctx.face); 32 | let (base_x, base_y) = base_anchor.get(ctx.face); 33 | 34 | ctx.buffer 35 | .unsafe_to_break(Some(glyph_pos), Some(ctx.buffer.idx + 1)); 36 | 37 | let idx = ctx.buffer.idx; 38 | let pos = ctx.buffer.cur_pos_mut(); 39 | pos.x_offset = base_x - mark_x; 40 | pos.y_offset = base_y - mark_y; 41 | pos.set_attach_type(attach_type::MARK); 42 | pos.set_attach_chain((glyph_pos as isize - idx as isize) as i16); 43 | 44 | ctx.buffer.scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; 45 | ctx.buffer.idx += 1; 46 | 47 | Some(()) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GPOS/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod cursive_pos; 2 | pub(crate) mod mark_array; 3 | pub(crate) mod mark_base_pos; 4 | pub(crate) mod mark_lig_pos; 5 | pub(crate) mod mark_mark_pos; 6 | pub(crate) mod pair_pos; 7 | pub(crate) mod pos_lookup; 8 | pub(crate) mod single_pos; 9 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GPOS/pos_lookup.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout::LayoutLookup; 2 | use crate::hb::ot_layout_common::PositioningLookup; 3 | use crate::hb::ot_layout_gsubgpos::Apply; 4 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 5 | use crate::hb::set_digest::{hb_set_digest_ext, hb_set_digest_t}; 6 | 7 | impl LayoutLookup for PositioningLookup<'_> { 8 | fn props(&self) -> u32 { 9 | self.props 10 | } 11 | 12 | fn is_reverse(&self) -> bool { 13 | false 14 | } 15 | 16 | fn digest(&self) -> &hb_set_digest_t { 17 | &self.set_digest 18 | } 19 | } 20 | 21 | impl Apply for PositioningLookup<'_> { 22 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 23 | if self.digest().may_have_glyph(ctx.buffer.cur(0).as_glyph()) { 24 | for subtable in &self.subtables { 25 | if subtable.apply(ctx).is_some() { 26 | return Some(()); 27 | } 28 | } 29 | } 30 | 31 | None 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GPOS/single_pos.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout_gpos_table::ValueRecordExt; 2 | use crate::hb::ot_layout_gsubgpos::Apply; 3 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 4 | use ttf_parser::gpos::SingleAdjustment; 5 | 6 | impl Apply for SingleAdjustment<'_> { 7 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 8 | let glyph = ctx.buffer.cur(0).as_glyph(); 9 | let record = match self { 10 | Self::Format1 { coverage, value } => { 11 | coverage.get(glyph)?; 12 | *value 13 | } 14 | Self::Format2 { coverage, values } => { 15 | let index = coverage.get(glyph)?; 16 | values.get(index)? 17 | } 18 | }; 19 | record.apply(ctx, ctx.buffer.idx); 20 | ctx.buffer.idx += 1; 21 | Some(()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/alternate_set.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout_gsubgpos::Apply; 2 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 3 | use crate::hb::ot_map::hb_ot_map_t; 4 | use core::convert::TryFrom; 5 | use ttf_parser::gsub::AlternateSet; 6 | 7 | impl Apply for AlternateSet<'_> { 8 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 9 | let len = self.alternates.len(); 10 | if len == 0 { 11 | return None; 12 | } 13 | 14 | let glyph_mask = ctx.buffer.cur(0).mask; 15 | 16 | // Note: This breaks badly if two features enabled this lookup together. 17 | let shift = ctx.lookup_mask().trailing_zeros(); 18 | let mut alt_index = (ctx.lookup_mask() & glyph_mask) >> shift; 19 | 20 | // If alt_index is MAX_VALUE, randomize feature if it is the rand feature. 21 | if alt_index == hb_ot_map_t::MAX_VALUE && ctx.random { 22 | // Maybe we can do better than unsafe-to-break all; but since we are 23 | // changing random state, it would be hard to track that. Good 'nough. 24 | ctx.buffer.unsafe_to_break(Some(0), Some(ctx.buffer.len)); 25 | alt_index = ctx.random_number() % u32::from(len) + 1; 26 | } 27 | 28 | let idx = u16::try_from(alt_index).ok()?.checked_sub(1)?; 29 | ctx.replace_glyph(self.alternates.get(idx)?); 30 | 31 | Some(()) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/alternate_subst.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 2 | use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext}; 3 | use ttf_parser::gsub::AlternateSubstitution; 4 | 5 | // AlternateSubstFormat1::would_apply 6 | impl WouldApply for AlternateSubstitution<'_> { 7 | fn would_apply(&self, ctx: &WouldApplyContext) -> bool { 8 | ctx.glyphs.len() == 1 && self.coverage.get(ctx.glyphs[0]).is_some() 9 | } 10 | } 11 | 12 | // AlternateSubstFormat1::apply 13 | impl Apply for AlternateSubstitution<'_> { 14 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 15 | let glyph = ctx.buffer.cur(0).as_glyph(); 16 | let index = self.coverage.get(glyph)?; 17 | let set = self.alternate_sets.get(index)?; 18 | set.apply(ctx) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/ligature.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 2 | use crate::hb::ot_layout_gsubgpos::{ 3 | ligate_input, match_glyph, match_input, Apply, WouldApply, WouldApplyContext, 4 | }; 5 | use ttf_parser::gsub::Ligature; 6 | 7 | impl WouldApply for Ligature<'_> { 8 | fn would_apply(&self, ctx: &WouldApplyContext) -> bool { 9 | ctx.glyphs.len() == usize::from(self.components.len()) + 1 10 | && self 11 | .components 12 | .into_iter() 13 | .enumerate() 14 | .all(|(i, comp)| ctx.glyphs[i + 1] == comp) 15 | } 16 | } 17 | 18 | impl Apply for Ligature<'_> { 19 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 20 | // Special-case to make it in-place and not consider this 21 | // as a "ligated" substitution. 22 | if self.components.is_empty() { 23 | ctx.replace_glyph(self.glyph); 24 | Some(()) 25 | } else { 26 | let f = |glyph, index| { 27 | let value = self.components.get(index).unwrap(); 28 | match_glyph(glyph, value.0) 29 | }; 30 | 31 | let mut match_end = 0; 32 | let mut match_positions = smallvec::SmallVec::from_elem(0, 4); 33 | let mut total_component_count = 0; 34 | 35 | if !match_input( 36 | ctx, 37 | self.components.len(), 38 | &f, 39 | &mut match_end, 40 | &mut match_positions, 41 | Some(&mut total_component_count), 42 | ) { 43 | ctx.buffer 44 | .unsafe_to_concat(Some(ctx.buffer.idx), Some(match_end)); 45 | return None; 46 | } 47 | 48 | let count = usize::from(self.components.len()) + 1; 49 | ligate_input( 50 | ctx, 51 | count, 52 | &match_positions, 53 | match_end, 54 | total_component_count, 55 | self.glyph, 56 | ); 57 | Some(()) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/ligature_set.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 2 | use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext}; 3 | use ttf_parser::gsub::LigatureSet; 4 | 5 | impl WouldApply for LigatureSet<'_> { 6 | fn would_apply(&self, ctx: &WouldApplyContext) -> bool { 7 | self.into_iter().any(|lig| lig.would_apply(ctx)) 8 | } 9 | } 10 | 11 | impl Apply for LigatureSet<'_> { 12 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 13 | for lig in self.into_iter() { 14 | if lig.apply(ctx).is_some() { 15 | return Some(()); 16 | } 17 | } 18 | None 19 | 20 | // TODO: port https://github.com/harfbuzz/harfbuzz/commit/7881eadff and 21 | // the following commits. Since it's behind a feature flag, we ignore it 22 | // for now and just use the simpler version. 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/ligature_subst.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 2 | use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext}; 3 | use ttf_parser::gsub::LigatureSubstitution; 4 | 5 | // LigatureSubstFormat1::would_apply 6 | impl WouldApply for LigatureSubstitution<'_> { 7 | fn would_apply(&self, ctx: &WouldApplyContext) -> bool { 8 | self.coverage 9 | .get(ctx.glyphs[0]) 10 | .and_then(|index| self.ligature_sets.get(index)) 11 | .map_or(false, |set| set.would_apply(ctx)) 12 | } 13 | } 14 | 15 | // LigatureSubstFormat1::apply 16 | impl Apply for LigatureSubstitution<'_> { 17 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 18 | let glyph = ctx.buffer.cur(0).as_glyph(); 19 | self.coverage 20 | .get(glyph) 21 | .and_then(|index| self.ligature_sets.get(index)) 22 | .and_then(|set| set.apply(ctx)) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/mod.rs: -------------------------------------------------------------------------------- 1 | mod alternate_set; 2 | mod alternate_subst; 3 | mod ligature; 4 | mod ligature_set; 5 | mod ligature_subst; 6 | mod multi_subst; 7 | mod reverse_chain_single_subst; 8 | mod sequence; 9 | mod single_subst; 10 | mod subst_lookup; 11 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/multi_subst.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 2 | use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext}; 3 | use ttf_parser::gsub::MultipleSubstitution; 4 | 5 | // MultipleSubstFormat1::would_apply 6 | impl WouldApply for MultipleSubstitution<'_> { 7 | fn would_apply(&self, ctx: &WouldApplyContext) -> bool { 8 | ctx.glyphs.len() == 1 && self.coverage.get(ctx.glyphs[0]).is_some() 9 | } 10 | } 11 | 12 | // MultipleSubstFormat1::apply 13 | impl Apply for MultipleSubstitution<'_> { 14 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 15 | let glyph = ctx.buffer.cur(0).as_glyph(); 16 | let index = self.coverage.get(glyph)?; 17 | let seq = self.sequences.get(index)?; 18 | seq.apply(ctx) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/sequence.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::buffer::GlyphPropsFlags; 2 | use crate::hb::ot_layout::{ 3 | _hb_glyph_info_get_lig_id, _hb_glyph_info_is_ligature, 4 | _hb_glyph_info_set_lig_props_for_component, 5 | }; 6 | use crate::hb::ot_layout_gsubgpos::Apply; 7 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 8 | use ttf_parser::gsub::Sequence; 9 | 10 | impl Apply for Sequence<'_> { 11 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 12 | match self.substitutes.len() { 13 | // Spec disallows this, but Uniscribe allows it. 14 | // https://github.com/harfbuzz/harfbuzz/issues/253 15 | 0 => ctx.buffer.delete_glyph(), 16 | 17 | // Special-case to make it in-place and not consider this 18 | // as a "multiplied" substitution. 19 | 1 => ctx.replace_glyph(self.substitutes.get(0)?), 20 | 21 | _ => { 22 | let class = if _hb_glyph_info_is_ligature(ctx.buffer.cur(0)) { 23 | GlyphPropsFlags::BASE_GLYPH 24 | } else { 25 | GlyphPropsFlags::empty() 26 | }; 27 | let lig_id = _hb_glyph_info_get_lig_id(ctx.buffer.cur(0)); 28 | 29 | for (i, subst) in self.substitutes.into_iter().enumerate() { 30 | // If is attached to a ligature, don't disturb that. 31 | // https://github.com/harfbuzz/harfbuzz/issues/3069 32 | if lig_id == 0 { 33 | // Index is truncated to 4 bits anway, so we can safely cast to u8. 34 | _hb_glyph_info_set_lig_props_for_component(ctx.buffer.cur_mut(0), i as u8); 35 | } 36 | ctx.output_glyph_for_component(subst, class); 37 | } 38 | 39 | ctx.buffer.skip_glyph(); 40 | } 41 | } 42 | Some(()) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/single_subst.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 2 | use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext}; 3 | use ttf_parser::gsub::SingleSubstitution; 4 | use ttf_parser::GlyphId; 5 | 6 | // SingleSubstFormat1::would_apply 7 | // SingleSubstFormat2::would_apply 8 | impl WouldApply for SingleSubstitution<'_> { 9 | fn would_apply(&self, ctx: &WouldApplyContext) -> bool { 10 | ctx.glyphs.len() == 1 && self.coverage().get(ctx.glyphs[0]).is_some() 11 | } 12 | } 13 | 14 | // SingleSubstFormat1::apply 15 | // SingleSubstFormat2::apply 16 | impl Apply for SingleSubstitution<'_> { 17 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 18 | let glyph = ctx.buffer.cur(0).as_glyph(); 19 | let subst = match *self { 20 | Self::Format1 { coverage, delta } => { 21 | coverage.get(glyph)?; 22 | // According to the Adobe Annotated OpenType Suite, result is always 23 | // limited to 16bit, so we explicitly want to truncate. 24 | GlyphId((i32::from(glyph.0) + i32::from(delta)) as u16) 25 | } 26 | Self::Format2 { 27 | coverage, 28 | substitutes, 29 | } => { 30 | let index = coverage.get(glyph)?; 31 | substitutes.get(index)? 32 | } 33 | }; 34 | 35 | ctx.replace_glyph(subst); 36 | Some(()) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/subst_lookup.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout::LayoutLookup; 2 | use crate::hb::ot_layout_common::SubstLookup; 3 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 4 | use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext}; 5 | use crate::hb::set_digest::{hb_set_digest_ext, hb_set_digest_t}; 6 | 7 | impl LayoutLookup for SubstLookup<'_> { 8 | fn props(&self) -> u32 { 9 | self.props 10 | } 11 | 12 | fn is_reverse(&self) -> bool { 13 | self.reverse 14 | } 15 | 16 | fn digest(&self) -> &hb_set_digest_t { 17 | &self.set_digest 18 | } 19 | } 20 | 21 | impl WouldApply for SubstLookup<'_> { 22 | fn would_apply(&self, ctx: &WouldApplyContext) -> bool { 23 | self.digest().may_have_glyph(ctx.glyphs[0]) 24 | && self 25 | .subtables 26 | .iter() 27 | .any(|subtable| subtable.would_apply(ctx)) 28 | } 29 | } 30 | 31 | impl Apply for SubstLookup<'_> { 32 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 33 | if self.digest().may_have_glyph(ctx.buffer.cur(0).as_glyph()) { 34 | for subtable in &self.subtables { 35 | if subtable.apply(ctx).is_some() { 36 | return Some(()); 37 | } 38 | } 39 | } 40 | 41 | None 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/hb/ot/layout/GSUB/subst_lookup_subtable.rs: -------------------------------------------------------------------------------- 1 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; 2 | use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext}; 3 | use ttf_parser::gsub::SubstitutionSubtable; 4 | 5 | impl WouldApply for SubstitutionSubtable<'_> { 6 | fn would_apply(&self, ctx: &WouldApplyContext) -> bool { 7 | match self { 8 | Self::Single(t) => t.would_apply(ctx), 9 | Self::Multiple(t) => t.would_apply(ctx), 10 | Self::Alternate(t) => t.would_apply(ctx), 11 | Self::Ligature(t) => t.would_apply(ctx), 12 | Self::Context(t) => t.would_apply(ctx), 13 | Self::ChainContext(t) => t.would_apply(ctx), 14 | Self::ReverseChainSingle(t) => t.would_apply(ctx), 15 | } 16 | } 17 | } 18 | 19 | impl Apply for SubstitutionSubtable<'_> { 20 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 21 | match self { 22 | Self::Single(t) => t.apply(ctx), 23 | Self::Multiple(t) => t.apply(ctx), 24 | Self::Alternate(t) => t.apply(ctx), 25 | Self::Ligature(t) => t.apply(ctx), 26 | Self::Context(t) => t.apply(ctx), 27 | Self::ChainContext(t) => t.apply(ctx), 28 | Self::ReverseChainSingle(t) => t.apply(ctx), 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/hb/ot/layout/mod.rs: -------------------------------------------------------------------------------- 1 | mod GPOS; 2 | mod GSUB; 3 | -------------------------------------------------------------------------------- /src/hb/ot/mod.rs: -------------------------------------------------------------------------------- 1 | mod layout; 2 | -------------------------------------------------------------------------------- /src/hb/ot_layout_gsub_table.rs: -------------------------------------------------------------------------------- 1 | use ttf_parser::gsub::*; 2 | use ttf_parser::opentype_layout::LookupIndex; 3 | 4 | use super::buffer::hb_buffer_t; 5 | use super::hb_font_t; 6 | use super::ot_layout::*; 7 | use super::ot_layout_common::{SubstLookup, SubstitutionTable}; 8 | use super::ot_layout_gsubgpos::*; 9 | use super::ot_shape_plan::hb_ot_shape_plan_t; 10 | use OT::hb_ot_apply_context_t; 11 | 12 | pub fn substitute(plan: &hb_ot_shape_plan_t, face: &hb_font_t, buffer: &mut hb_buffer_t) { 13 | apply_layout_table(plan, face, buffer, face.gsub.as_ref()); 14 | } 15 | 16 | impl<'a> LayoutTable for SubstitutionTable<'a> { 17 | const INDEX: TableIndex = TableIndex::GSUB; 18 | const IN_PLACE: bool = false; 19 | 20 | type Lookup = SubstLookup<'a>; 21 | 22 | fn get_lookup(&self, index: LookupIndex) -> Option<&Self::Lookup> { 23 | self.lookups.get(usize::from(index)) 24 | } 25 | } 26 | 27 | impl WouldApply for SubstitutionSubtable<'_> { 28 | fn would_apply(&self, ctx: &WouldApplyContext) -> bool { 29 | match self { 30 | Self::Single(t) => t.would_apply(ctx), 31 | Self::Multiple(t) => t.would_apply(ctx), 32 | Self::Alternate(t) => t.would_apply(ctx), 33 | Self::Ligature(t) => t.would_apply(ctx), 34 | Self::Context(t) => t.would_apply(ctx), 35 | Self::ChainContext(t) => t.would_apply(ctx), 36 | Self::ReverseChainSingle(t) => t.would_apply(ctx), 37 | } 38 | } 39 | } 40 | 41 | impl Apply for SubstitutionSubtable<'_> { 42 | fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> { 43 | match self { 44 | Self::Single(t) => t.apply(ctx), 45 | Self::Multiple(t) => t.apply(ctx), 46 | Self::Alternate(t) => t.apply(ctx), 47 | Self::Ligature(t) => t.apply(ctx), 48 | Self::Context(t) => t.apply(ctx), 49 | Self::ChainContext(t) => t.apply(ctx), 50 | Self::ReverseChainSingle(t) => t.apply(ctx), 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/hb/ot_shape_plan.rs: -------------------------------------------------------------------------------- 1 | use alloc::boxed::Box; 2 | use alloc::vec::Vec; 3 | use core::any::Any; 4 | 5 | use super::ot_map::*; 6 | use super::ot_shape::*; 7 | use super::ot_shaper::*; 8 | use super::{hb_font_t, hb_mask_t, Direction, Feature, Language, Script}; 9 | 10 | /// A reusable plan for shaping a text buffer. 11 | pub struct hb_ot_shape_plan_t { 12 | pub(crate) direction: Direction, 13 | pub(crate) script: Option