├── .github └── workflows │ └── rust.yml ├── .gitignore ├── .gitmodules ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── fea-lsp ├── Cargo.toml ├── README.md ├── editors │ └── vscode │ │ ├── .eslintignore │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ │ ├── .vscodeignore │ │ ├── README.md │ │ ├── language-configuration.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ └── extension.ts │ │ └── tsconfig.json └── src │ ├── document.rs │ └── main.rs ├── fea-rs ├── Cargo.toml ├── benches │ └── parsing.rs ├── src │ ├── bin │ │ ├── compile.rs │ │ ├── highlight.rs │ │ ├── parse_test.rs │ │ └── ttx_test.rs │ ├── common.rs │ ├── common │ │ ├── glyph_class.rs │ │ └── glyph_map.rs │ ├── compile.rs │ ├── compile │ │ ├── compile_ctx.rs │ │ ├── compiler.rs │ │ ├── error.rs │ │ ├── features.rs │ │ ├── glyph_range.rs │ │ ├── language_system.rs │ │ ├── lookups.rs │ │ ├── lookups │ │ │ ├── contextual.rs │ │ │ ├── gpos.rs │ │ │ ├── gsub.rs │ │ │ └── helpers.rs │ │ ├── opts.rs │ │ ├── output.rs │ │ ├── tables.rs │ │ ├── tables │ │ │ ├── base.rs │ │ │ ├── gdef.rs │ │ │ ├── name.rs │ │ │ ├── os2.rs │ │ │ └── stat.rs │ │ ├── tags.rs │ │ ├── validate.rs │ │ ├── valuerecordext.rs │ │ └── variations.rs │ ├── diagnostic.rs │ ├── lib.rs │ ├── parse.rs │ ├── parse │ │ ├── context.rs │ │ ├── grammar │ │ │ ├── feature.rs │ │ │ ├── glyph.rs │ │ │ ├── gpos.rs │ │ │ ├── gsub.rs │ │ │ ├── metrics.rs │ │ │ ├── mod.rs │ │ │ ├── table.rs │ │ │ └── variations.rs │ │ ├── lexer.rs │ │ ├── lexer │ │ │ ├── lexeme.rs │ │ │ └── token_set.rs │ │ ├── parser.rs │ │ ├── source.rs │ │ └── tree.rs │ ├── tests.rs │ ├── tests │ │ ├── compile.rs │ │ └── parse.rs │ ├── token_tree.rs │ ├── token_tree │ │ ├── cursor.rs │ │ ├── edit.rs │ │ ├── rewrite.rs │ │ ├── stack.rs │ │ ├── token.rs │ │ └── typed.rs │ ├── util.rs │ └── util │ │ ├── highlighting.rs │ │ ├── paths.rs │ │ ├── pretty_diff.rs │ │ └── ttx.rs └── test-data │ ├── README.md │ ├── compile-tests │ ├── README.md │ └── mini-latin │ │ ├── bad │ │ ├── GDEF_conflicting_classes.ERR │ │ ├── GDEF_conflicting_classes.fea │ │ ├── GPOS_4_non_disjoint_mark_class.ERR │ │ ├── GPOS_4_non_disjoint_mark_class.fea │ │ ├── aalt_reference_missing_feature.ERR │ │ ├── aalt_reference_missing_feature.fea │ │ ├── aalt_script_statement.ERR │ │ ├── aalt_script_statement.fea │ │ ├── bad_size1.ERR │ │ ├── bad_size1.fea │ │ ├── bad_size2.ERR │ │ ├── bad_size2.fea │ │ ├── bad_size3.ERR │ │ ├── bad_size3.fea │ │ ├── bad_size4.ERR │ │ ├── bad_size4.fea │ │ ├── chain_pos_references_gsub_lookup.ERR │ │ ├── chain_pos_references_gsub_lookup.fea │ │ ├── chain_subst_references_gpos_lookup.ERR │ │ ├── chain_subst_references_gpos_lookup.fea │ │ ├── contextual_gsub2_class.ERR │ │ ├── contextual_gsub2_class.fea │ │ ├── duplicate_named_lookup.ERR │ │ ├── duplicate_named_lookup.fea │ │ ├── feature_ref_outside_aalt.ERR │ │ ├── feature_ref_outside_aalt.fea │ │ ├── gpos_8a.ERR │ │ ├── gpos_8a.fea │ │ ├── gsub_6_inline_class.ERR │ │ ├── gsub_6_inline_class.fea │ │ ├── gsub_6_inline_no_class.ERR │ │ ├── gsub_6_inline_no_class.fea │ │ ├── gsub_6_named_and_inline.ERR │ │ ├── gsub_6_named_and_inline.fea │ │ ├── languagesystem_order.ERR │ │ ├── languagesystem_order.fea │ │ ├── languagesystem_order2.ERR │ │ ├── languagesystem_order2.fea │ │ ├── lookup_mixed_rules.ERR │ │ ├── lookup_mixed_rules.fea │ │ ├── lookup_multiple_flags.ERR │ │ ├── lookup_multiple_flags.fea │ │ ├── name_table_encoding.ERR │ │ ├── name_table_encoding.fea │ │ ├── script_in_lookup.ERR │ │ ├── script_in_lookup.fea │ │ ├── size_script_statement.ERR │ │ ├── size_script_statement.fea │ │ ├── variable_condset_oob.ERR │ │ ├── variable_condset_oob.fea │ │ ├── variable_unknown_condset_tag.ERR │ │ ├── variable_unknown_condset_tag.fea │ │ ├── variable_value_record_oob.ERR │ │ ├── variable_value_record_oob.fea │ │ ├── variable_value_record_unknown_axis.ERR │ │ ├── variable_value_record_unknown_axis.fea │ │ ├── variation_undefined_condset.ERR │ │ └── variation_undefined_condset.fea │ │ ├── glyph_order.txt │ │ └── good │ │ ├── basic_kern.fea │ │ ├── basic_kern.ttx │ │ ├── basic_liga.fea │ │ ├── basic_liga.ttx │ │ ├── big_device.fea │ │ ├── big_device.ttx │ │ ├── duplicate_lookups.fea │ │ ├── duplicate_lookups.ttx │ │ ├── gpos8a.fea │ │ ├── gpos8a.ttx │ │ ├── gpos_mixed_single_multi_rules.fea │ │ ├── gpos_mixed_single_multi_rules.ttx │ │ ├── gsub1.fea │ │ ├── gsub1.ttx │ │ ├── gsub_1_omit_by.fea │ │ ├── gsub_1_omit_by.ttx │ │ ├── lookup_single_flag.fea │ │ ├── lookup_single_flag.ttx │ │ ├── mixed_lookups.fea │ │ ├── mixed_lookups.ttx │ │ ├── naked_semi.fea │ │ ├── naked_semi.ttx │ │ ├── rsub_many_by_one.fea │ │ ├── rsub_many_by_one.ttx │ │ ├── spec_6iii_3c.fea │ │ ├── spec_6iii_3c.ttx │ │ ├── value_record_def_simple.fea │ │ ├── value_record_def_simple.ttx │ │ ├── variable_condition_sort_order.fea │ │ ├── variable_condition_sort_order.ttx │ │ ├── variable_feature_include_base.fea │ │ ├── variable_feature_include_base.ttx │ │ ├── variable_feature_null_conditionset.fea │ │ └── variable_feature_null_conditionset.ttx │ ├── fonttools-tests │ ├── AlternateChained.fea │ ├── AlternateChained.ttx │ ├── AlternateSubtable.fea │ ├── AlternateSubtable.ttx │ ├── Attach.fea │ ├── Attach.ttx │ ├── ChainPosSubtable.fea │ ├── ChainPosSubtable.ttx │ ├── ChainSubstSubtable.fea │ ├── ChainSubstSubtable.ttx │ ├── GPOS_1.fea │ ├── GPOS_1.ttx │ ├── GPOS_1_zero.fea │ ├── GPOS_1_zero.ttx │ ├── GPOS_2.expected_diff │ ├── GPOS_2.fea │ ├── GPOS_2.ttx │ ├── GPOS_2b.fea │ ├── GPOS_2b.ttx │ ├── GPOS_3.fea │ ├── GPOS_3.ttx │ ├── GPOS_4.fea │ ├── GPOS_4.ttx │ ├── GPOS_5.fea │ ├── GPOS_5.ttx │ ├── GPOS_6.fea │ ├── GPOS_6.ttx │ ├── GPOS_8.fea │ ├── GPOS_8.ttx │ ├── GSUB_2.fea │ ├── GSUB_2.ttx │ ├── GSUB_3.fea │ ├── GSUB_3.ttx │ ├── GSUB_5_formats.expected_diff │ ├── GSUB_5_formats.fea │ ├── GSUB_5_formats.ttx │ ├── GSUB_6.fea │ ├── GSUB_6.ttx │ ├── GSUB_6_formats.expected_diff │ ├── GSUB_6_formats.fea │ ├── GSUB_6_formats.ttx │ ├── GSUB_8.fea │ ├── GSUB_8.ttx │ ├── GSUB_error.fea │ ├── GlyphClassDef.fea │ ├── GlyphClassDef.ttx │ ├── LigatureCaretByIndex.fea │ ├── LigatureCaretByIndex.ttx │ ├── LigatureCaretByPos.fea │ ├── LigatureCaretByPos.ttx │ ├── LigatureSubtable.fea │ ├── LigatureSubtable.ttx │ ├── MultipleLookupsPerGlyph.fea │ ├── MultipleLookupsPerGlyph.ttx │ ├── MultipleLookupsPerGlyph2.fea │ ├── MultipleLookupsPerGlyph2.ttx │ ├── MultipleSubstSubtable.fea │ ├── MultipleSubstSubtable.ttx │ ├── PairPosSubtable.fea │ ├── PairPosSubtable.ttx │ ├── README.md │ ├── STAT_bad.fea │ ├── STAT_test.fea │ ├── STAT_test.ttx │ ├── STAT_test_elidedFallbackNameID.fea │ ├── STAT_test_elidedFallbackNameID.ttx │ ├── SingleSubstSubtable.fea │ ├── SingleSubstSubtable.ttx │ ├── SubstSubtable.fea │ ├── SubstSubtable.ttx │ ├── ZeroValue_ChainSinglePos_horizontal.fea │ ├── ZeroValue_ChainSinglePos_horizontal.ttx │ ├── ZeroValue_ChainSinglePos_vertical.fea │ ├── ZeroValue_ChainSinglePos_vertical.ttx │ ├── ZeroValue_PairPos_horizontal.fea │ ├── ZeroValue_PairPos_horizontal.ttx │ ├── ZeroValue_PairPos_vertical.fea │ ├── ZeroValue_PairPos_vertical.ttx │ ├── ZeroValue_SinglePos_horizontal.fea │ ├── ZeroValue_SinglePos_horizontal.ttx │ ├── ZeroValue_SinglePos_vertical.fea │ ├── ZeroValue_SinglePos_vertical.ttx │ ├── aalt_chain_contextual_subst.fea │ ├── aalt_chain_contextual_subst.ttx │ ├── baseClass.fea │ ├── bug1307.fea │ ├── bug1307.ttx │ ├── bug1459.fea │ ├── bug1459.ttx │ ├── bug2276.fea │ ├── bug2276.ttx │ ├── bug2949.fea │ ├── bug2949.ttx │ ├── bug453.fea │ ├── bug453.ttx │ ├── bug457.fea │ ├── bug457.ttx │ ├── bug463.fea │ ├── bug463.ttx │ ├── bug501.fea │ ├── bug501.ttx │ ├── bug502.fea │ ├── bug502.ttx │ ├── bug504.fea │ ├── bug504.ttx │ ├── bug505.fea │ ├── bug505.ttx │ ├── bug506.fea │ ├── bug506.ttx │ ├── bug509.fea │ ├── bug509.ttx │ ├── bug512.fea │ ├── bug512.ttx │ ├── bug514.fea │ ├── bug514.ttx │ ├── bug568.fea │ ├── bug568.ttx │ ├── bug633.fea │ ├── bug633.ttx │ ├── cid_range.fea │ ├── cid_range.ttx │ ├── delete_glyph.fea │ ├── delete_glyph.ttx │ ├── enum.fea │ ├── enum.ttx │ ├── feature_aalt.expected_diff │ ├── feature_aalt.fea │ ├── feature_aalt.ttx │ ├── ignore_pos.fea │ ├── ignore_pos.ttx │ ├── include0.fea │ ├── language_required.fea │ ├── language_required.ttx │ ├── lookup-debug.ttx │ ├── lookup.fea │ ├── lookup.ttx │ ├── lookupflag.fea │ ├── lookupflag.ttx │ ├── markClass.fea │ ├── markClass.ttx │ ├── mini.fea │ ├── multiple_feature_blocks.fea │ ├── multiple_feature_blocks.ttx │ ├── name.fea │ ├── name.ttx │ ├── omitted_GlyphClassDef.fea │ ├── omitted_GlyphClassDef.ttx │ ├── size.fea │ ├── size.ttx │ ├── size2.fea │ ├── size2.ttx │ ├── spec10.fea │ ├── spec10.ttx │ ├── spec4h1.fea │ ├── spec4h1.ttx │ ├── spec4h2.fea │ ├── spec4h2.ttx │ ├── spec5d1.expected_diff │ ├── spec5d1.fea │ ├── spec5d1.ttx │ ├── spec5d2.fea │ ├── spec5d2.ttx │ ├── spec5f_ii_1.fea │ ├── spec5f_ii_1.ttx │ ├── spec5f_ii_2.fea │ ├── spec5f_ii_2.ttx │ ├── spec5f_ii_3.expected_diff │ ├── spec5f_ii_3.fea │ ├── spec5f_ii_3.ttx │ ├── spec5f_ii_4.expected_diff │ ├── spec5f_ii_4.fea │ ├── spec5f_ii_4.ttx │ ├── spec5fi1.fea │ ├── spec5fi1.ttx │ ├── spec5fi2.fea │ ├── spec5fi2.ttx │ ├── spec5fi3.fea │ ├── spec5fi3.ttx │ ├── spec5fi4.fea │ ├── spec5fi4.ttx │ ├── spec5h1.fea │ ├── spec5h1.ttx │ ├── spec6b_ii.fea │ ├── spec6b_ii.ttx │ ├── spec6d2.fea │ ├── spec6d2.ttx │ ├── spec6e.fea │ ├── spec6e.ttx │ ├── spec6f.fea │ ├── spec6f.ttx │ ├── spec6h_ii.fea │ ├── spec6h_ii.ttx │ ├── spec6h_iii_1.fea │ ├── spec6h_iii_1.ttx │ ├── spec6h_iii_3d.fea │ ├── spec6h_iii_3d.ttx │ ├── spec8a.expected_diff │ ├── spec8a.fea │ ├── spec8a.ttx │ ├── spec8b.fea │ ├── spec8b.ttx │ ├── spec8c.expected_diff │ ├── spec8c.fea │ ├── spec8c.ttx │ ├── spec8d.fea │ ├── spec8d.ttx │ ├── spec9a.fea │ ├── spec9a.ttx │ ├── spec9b.fea │ ├── spec9b.ttx │ ├── spec9c1.fea │ ├── spec9c1.ttx │ ├── spec9c2.fea │ ├── spec9c2.ttx │ ├── spec9c3.fea │ ├── spec9c3.ttx │ ├── spec9d.fea │ ├── spec9d.ttx │ ├── spec9e.fea │ ├── spec9e.ttx │ ├── spec9f.expected_diff │ ├── spec9f.fea │ ├── spec9f.ttx │ ├── spec9g.fea │ ├── spec9g.ttx │ ├── test.fea │ ├── variable_bug2772.fea │ ├── variable_bug2772.ttx │ ├── variable_conditionset.fea │ ├── variable_conditionset.ttx │ ├── variable_scalar_anchor.fea │ ├── variable_scalar_anchor.ttx │ ├── variable_scalar_valuerecord.fea │ └── variable_scalar_valuerecord.ttx │ ├── include-resolution-tests │ ├── _included1.fea │ ├── _included2.fea │ └── dir1 │ │ ├── _included3.fea │ │ ├── test1.PARSE_TREE │ │ ├── test1.fea │ │ └── test1.ttx │ ├── parse-tests │ ├── README.md │ ├── bad │ │ ├── bad_tag_keyword.ERR │ │ ├── bad_tag_keyword.fea │ │ ├── bad_tag_num.ERR │ │ ├── bad_tag_num.fea │ │ ├── contextual_from.ERR │ │ ├── contextual_from.fea │ │ ├── contextual_inline_pairpos.ERR │ │ ├── contextual_inline_pairpos.fea │ │ ├── include_missing_file.ERR │ │ ├── include_missing_file.fea │ │ ├── rsub_input_len.ERR │ │ ├── rsub_input_len.fea │ │ ├── rsub_multi.ERR │ │ ├── rsub_multi.fea │ │ ├── rsub_null.ERR │ │ ├── rsub_null.fea │ │ ├── suffix_metrics.ERR │ │ ├── suffix_metrics.fea │ │ ├── tag_mismatch.ERR │ │ ├── tag_mismatch.fea │ │ ├── value_record_def_outside_top_level.ERR │ │ ├── value_record_def_outside_top_level.fea │ │ ├── variation_missing_condset.ERR │ │ └── variation_missing_condset.fea │ └── good │ │ ├── GPOS_1.PARSE_TREE │ │ ├── GPOS_1.fea │ │ ├── GPOS_2a.PARSE_TREE │ │ ├── GPOS_2a.fea │ │ ├── GPOS_2b.PARSE_TREE │ │ ├── GPOS_2b.fea │ │ ├── GPOS_2c.PARSE_TREE │ │ ├── GPOS_2c.fea │ │ ├── GPOS_2d.PARSE_TREE │ │ ├── GPOS_2d.fea │ │ ├── GPOS_5.PARSE_TREE │ │ ├── GPOS_5.fea │ │ ├── GPOS_8a.PARSE_TREE │ │ ├── GPOS_8a.fea │ │ ├── GPOS_8b.PARSE_TREE │ │ ├── GPOS_8b.fea │ │ ├── GPOS_8c.PARSE_TREE │ │ ├── GPOS_8c.fea │ │ ├── GSUB_1a.PARSE_TREE │ │ ├── GSUB_1a.fea │ │ ├── GSUB_1b.PARSE_TREE │ │ ├── GSUB_1b.fea │ │ ├── GSUB_1c.PARSE_TREE │ │ ├── GSUB_1c.fea │ │ ├── GSUB_1d.PARSE_TREE │ │ ├── GSUB_1d.fea │ │ ├── GSUB_2.PARSE_TREE │ │ ├── GSUB_2.fea │ │ ├── GSUB_3.PARSE_TREE │ │ ├── GSUB_3.fea │ │ ├── GSUB_4.PARSE_TREE │ │ ├── GSUB_4.fea │ │ ├── GSUB_6.PARSE_TREE │ │ ├── GSUB_6.fea │ │ ├── anchor_formats.PARSE_TREE │ │ ├── anchor_formats.fea │ │ ├── contextual_gsub2.PARSE_TREE │ │ ├── contextual_gsub2.fea │ │ ├── escape_nonkeyword.PARSE_TREE │ │ ├── escape_nonkeyword.fea │ │ ├── glyph_name_formats.PARSE_TREE │ │ ├── glyph_name_formats.fea │ │ ├── glyph_name_tricks.PARSE_TREE │ │ ├── glyph_name_tricks.fea │ │ ├── glyph_or_range.PARSE_TREE │ │ ├── glyph_or_range.fea │ │ ├── ignore_pos.PARSE_TREE │ │ ├── ignore_pos.fea │ │ ├── ignore_sub.PARSE_TREE │ │ ├── ignore_sub.fea │ │ ├── ignore_sub_comma.PARSE_TREE │ │ ├── ignore_sub_comma.fea │ │ ├── include_in_feature.PARSE_TREE │ │ ├── include_in_feature.fea │ │ ├── include_without_semi.PARSE_TREE │ │ ├── include_without_semi.fea │ │ ├── language_system.PARSE_TREE │ │ ├── language_system.fea │ │ ├── lookup_def_group.PARSE_TREE │ │ ├── lookup_def_group.fea │ │ ├── mark-tag.PARSE_TREE │ │ ├── mark-tag.fea │ │ ├── mark_class.PARSE_TREE │ │ ├── mark_class.fea │ │ ├── naked_semi_in_lookup.PARSE_TREE │ │ ├── naked_semi_in_lookup.fea │ │ ├── name-tag.PARSE_TREE │ │ ├── name-tag.fea │ │ ├── named_value_record_reference.PARSE_TREE │ │ ├── named_value_record_reference.fea │ │ ├── rsub.PARSE_TREE │ │ ├── rsub.fea │ │ ├── short-tag.PARSE_TREE │ │ ├── short-tag.fea │ │ ├── simple_aalt.PARSE_TREE │ │ ├── simple_aalt.fea │ │ ├── size_zero.PARSE_TREE │ │ ├── size_zero.fea │ │ ├── spec6iii_3c.PARSE_TREE │ │ ├── spec6iii_3c.fea │ │ ├── spec8d.PARSE_TREE │ │ ├── spec8d.fea │ │ ├── spec9h.PARSE_TREE │ │ ├── spec9h.fea │ │ ├── suffix_metrics.PARSE_TREE │ │ ├── suffix_metrics.fea │ │ ├── value_record_def.PARSE_TREE │ │ ├── value_record_def.fea │ │ ├── valuerecord_formats.PARSE_TREE │ │ ├── valuerecord_formats.fea │ │ ├── variable_anchor.PARSE_TREE │ │ ├── variable_anchor.fea │ │ ├── variable_conditionset.PARSE_TREE │ │ ├── variable_conditionset.fea │ │ ├── variable_metrics.PARSE_TREE │ │ ├── variable_metrics.fea │ │ ├── variable_value_record.PARSE_TREE │ │ ├── variable_value_record.fea │ │ ├── variation_block.PARSE_TREE │ │ └── variation_block.fea │ ├── real-files │ ├── plex_devanagari.fea │ ├── roboto-regular.fea │ └── tajawal-regular.fea │ ├── scripts │ └── update_fonttools_tests.sh │ └── simple_glyph_order.txt └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | 4 | .venv 5 | venv 6 | 7 | # a directory colin uses to stash various wip diffs/test inputs 8 | _experiments 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmyr/fea-rs/17da167b89152859184430cf4ddc4b5310f05bb1/.gitmodules -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "fea-rs", 5 | "fea-lsp", 6 | ] 7 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Colin Rothfels 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fea-rs 2 | 3 | This project now lives at [googlefonts/fontc/fea-rs](https://github.com/googlefonts/fontc/tree/main/fea-rs). 4 | -------------------------------------------------------------------------------- /fea-lsp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fea-lsp" 3 | version = "0.1.0" 4 | edition = "2018" 5 | publish = false 6 | 7 | [dependencies] 8 | fea-rs = {version = "0", path = "../fea-rs"} 9 | lspower = "1.1.0" 10 | tokio = { version = "1.3", features = ["io-std", "io-util", "macros", "net", "rt-multi-thread", "sync", "time"] } 11 | serde_json = "1.0" 12 | anyhow = "1.0" 13 | env_logger = "0.10" 14 | 15 | # cargo-release settings 16 | [package.metadata.release] 17 | release = false 18 | -------------------------------------------------------------------------------- /fea-lsp/README.md: -------------------------------------------------------------------------------- 1 | # FEA Language Server 2 | 3 | This crate is an experimental [language server][] for Adobe OpenType Feature 4 | files. 5 | 6 | It is an experiment, and not supported or intended for use. 7 | 8 | [language server]: https://microsoft.github.io/language-server-protocol/ 9 | -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/** 2 | client/node_modules/** 3 | client/out/** 4 | server/node_modules/** 5 | server/out/** -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /**@type {import('eslint').Linter.Config} */ 2 | // eslint-disable-next-line no-undef 3 | module.exports = { 4 | root: true, 5 | parser: '@typescript-eslint/parser', 6 | plugins: [ 7 | '@typescript-eslint', 8 | ], 9 | extends: [ 10 | 'eslint:recommended', 11 | 'plugin:@typescript-eslint/recommended', 12 | ], 13 | rules: { 14 | 'semi': [2, "always"], 15 | '@typescript-eslint/no-unused-vars': 0, 16 | '@typescript-eslint/no-explicit-any': 0, 17 | '@typescript-eslint/explicit-module-boundary-types': 0, 18 | '@typescript-eslint/no-non-null-assertion': 0, 19 | } 20 | }; -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | client/server 4 | .vscode-test -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "dbaeumer.vscode-eslint" 8 | ] 9 | } -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "name": "Launch Client", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}"], 11 | "outFiles": ["${workspaceRoot}/client/out/**/*.js"], 12 | "preLaunchTask": { 13 | "type": "npm", 14 | "script": "watch" 15 | } 16 | }, 17 | { 18 | "type": "node", 19 | "request": "attach", 20 | "name": "Attach to Server", 21 | "port": 6009, 22 | "restart": true, 23 | "outFiles": ["${workspaceRoot}/server/out/**/*.js"] 24 | }, 25 | { 26 | "name": "Language Server E2E Test", 27 | "type": "extensionHost", 28 | "request": "launch", 29 | "runtimeExecutable": "${execPath}", 30 | "args": [ 31 | "--extensionDevelopmentPath=${workspaceRoot}", 32 | "--extensionTestsPath=${workspaceRoot}/client/out/test/index", 33 | "${workspaceRoot}/client/testFixture" 34 | ], 35 | "outFiles": ["${workspaceRoot}/client/out/test/**/*.js"] 36 | } 37 | ], 38 | "compounds": [ 39 | { 40 | "name": "Client + Server", 41 | "configurations": ["Launch Client", "Attach to Server"] 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.insertSpaces": false, 3 | "typescript.tsc.autoDetect": "off", 4 | "typescript.preferences.quoteStyle": "single", 5 | "editor.codeActionsOnSave": { 6 | "source.fixAll.eslint": true 7 | } 8 | } -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "compile", 7 | "group": "build", 8 | "presentation": { 9 | "panel": "dedicated", 10 | "reveal": "never" 11 | }, 12 | "problemMatcher": [ 13 | "$tsc" 14 | ] 15 | }, 16 | { 17 | "type": "npm", 18 | "script": "watch", 19 | "isBackground": true, 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | "presentation": { 25 | "panel": "dedicated", 26 | "reveal": "never" 27 | }, 28 | "problemMatcher": [ 29 | "$tsc-watch" 30 | ] 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | **/*.ts 3 | **/*.map 4 | .gitignore 5 | **/tsconfig.json 6 | **/tsconfig.base.json 7 | contributing.md 8 | .travis.yml 9 | client/node_modules/** 10 | !client/node_modules/vscode-jsonrpc/** 11 | !client/node_modules/vscode-languageclient/** 12 | !client/node_modules/vscode-languageserver-protocol/** 13 | !client/node_modules/vscode-languageserver-types/** 14 | !client/node_modules/{minimatch,brace-expansion,concat-map,balanced-match}/** 15 | !client/node_modules/{semver,lru-cache,yallist}/** -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/README.md: -------------------------------------------------------------------------------- 1 | # VSCode Extension 2 | 3 | This is very hacky and probably not a great experience right now; it was 4 | intended as a proof of concept. Use at your peril. 5 | 6 | 7 | Installation: 8 | 9 | this extension is not published, and has to be run manually. First, you will 10 | need to compile the `fea-lsp` crate in the parent directory, and move the 11 | binary somewhere where you can easily find it, such as `~/.fea-lsp/fea-lsp`. 12 | 13 | Then from from this directory, run: 14 | 15 | ```sh 16 | npm install 17 | npm run compile 18 | ``` 19 | 20 | Open this directory in VSCode. From the 'run and debug' sidebar, run the 'Launch 21 | Client' command. This will open a new VSCode window with the extenstion enabled. 22 | 23 | To actually make it work, you need to point it the location of the `fea-lsp` 24 | binary you compiled earlier. Open VSCode settings, and search for 'fea'. At the 25 | bottom you should find a setting "fea-lsp > Server: Path", where you can enter 26 | the path to the binary. 27 | -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | // symbol used for single line comment. Remove this entry if your language does not support line comments 4 | "lineComment": "#" 5 | }, 6 | // symbols used as brackets 7 | "brackets": [ 8 | ["{", "}"], 9 | ["[", "]"], 10 | ["(", ")"], 11 | ["<", ">"] 12 | ], 13 | // symbols that are auto closed when typing 14 | "autoClosingPairs": [ 15 | ["{", "}"], 16 | ["[", "]"], 17 | ["(", ")"], 18 | ["\"", "\""] 19 | ], 20 | // symbols that can be used to surround a selection 21 | "surroundingPairs": [ 22 | ["{", "}"], 23 | ["[", "]"], 24 | ["(", ")"], 25 | ["<", ">"], 26 | ["\"", "\""] 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /fea-lsp/editors/vscode/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2019", 5 | "lib": ["ES2019"], 6 | "outDir": "out", 7 | "rootDir": "src", 8 | "sourceMap": true 9 | }, 10 | "include": [ 11 | "src" 12 | ], 13 | "exclude": [ 14 | "node_modules", 15 | ".vscode-test" 16 | ] 17 | } -------------------------------------------------------------------------------- /fea-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fea-rs" 3 | version = "0.18.0" 4 | license = "MIT/Apache-2.0" 5 | authors = ["Colin Rofls "] 6 | description = "Tools for working with Adobe OpenType Feature files." 7 | repository = "https://github.com/cmyr/fea-rs" 8 | categories = ["parsing", "text-processing"] 9 | keywords = ["fonts", "opentype"] 10 | readme = "../README.md" 11 | edition = "2021" 12 | default-run = "fea-rs" 13 | exclude = ["test-data"] 14 | 15 | [dependencies] 16 | ansi_term = "0.12.1" 17 | smol_str = "0.2.0" 18 | norad = { version = "0.12", optional = true } # Used in the compile binary 19 | write-fonts = { version = "0.17.0", features = ["read"] } 20 | chrono = "0.4.3" 21 | diff = { version = "0.1.12", optional = true } 22 | rayon = { version = "1.6", optional = true } 23 | serde = { version = "1.0.147", features = ["derive"], optional = true } 24 | serde_json = {version = "1.0.87", optional = true } 25 | thiserror = "1.0.37" 26 | clap = { version = "4.0.32", features = ["derive"], optional = true } 27 | log = "0.4" 28 | env_logger = "0.10.0" 29 | indexmap = "2.0" 30 | ordered-float = "4.1.0" 31 | 32 | [features] 33 | test = ["diff", "rayon", "serde", "serde_json", "clap"] 34 | cli = ["norad", "clap"] 35 | 36 | [dev-dependencies] 37 | diff = "0.1.12" 38 | rayon = "1.5" 39 | criterion = "0.5" 40 | serde = { version = "1.0.147", features = ["derive"] } 41 | serde_json = "1.0.87" 42 | 43 | [[bench]] 44 | name = "parsing" 45 | harness = false 46 | 47 | [[bin]] 48 | name = "fea-rs" 49 | path = "src/bin/compile.rs" 50 | required-features = ["cli"] 51 | 52 | [[bin]] 53 | name = "ttx_test" 54 | required-features = ["test"] 55 | -------------------------------------------------------------------------------- /fea-rs/benches/parsing.rs: -------------------------------------------------------------------------------- 1 | //! A very simple benchmark for the parser 2 | 3 | use std::sync::Arc; 4 | 5 | use criterion::{black_box, criterion_group, criterion_main, Criterion}; 6 | 7 | const DEVA: &str = include_str!("../test-data/real-files/plex_devanagari.fea"); 8 | const LATN: &str = include_str!("../test-data/real-files/roboto-regular.fea"); 9 | const ARAB: &str = include_str!("../test-data/real-files/tajawal-regular.fea"); 10 | 11 | fn parse_source(source: Arc) -> fea_rs::Node { 12 | fea_rs::parse::parse_string(source).0 13 | } 14 | 15 | fn parsing(c: &mut Criterion) { 16 | let deva: Arc = DEVA.into(); 17 | let latn: Arc = LATN.into(); 18 | let arab: Arc = ARAB.into(); 19 | c.bench_function("parse plex-devenagari", |b| { 20 | b.iter(|| parse_source(black_box(deva.clone()))) 21 | }); 22 | c.bench_function("parse roboto-regular", |b| { 23 | b.iter(|| parse_source(black_box(latn.clone()))) 24 | }); 25 | c.bench_function("parse tajawal-regular", |b| { 26 | b.iter(|| parse_source(black_box(arab.clone()))) 27 | }); 28 | } 29 | 30 | criterion_group!(benches, parsing); 31 | criterion_main!(benches); 32 | -------------------------------------------------------------------------------- /fea-rs/src/compile/opts.rs: -------------------------------------------------------------------------------- 1 | //! Options used during compilation 2 | //! 3 | 4 | // NOTE: This was designed to originate from the command line, but that isn't 5 | // a very important part of our API, and a more natural place for us to specify 6 | // options is in the 'Compiler' struct itself. 7 | 8 | /// Options for configuring compilation behaviour. 9 | #[derive(Clone, Debug, Default)] 10 | pub struct Opts { 11 | pub(crate) make_post_table: bool, 12 | } 13 | 14 | impl Opts { 15 | /// Create a new empty set of options 16 | pub fn new() -> Self { 17 | Self::default() 18 | } 19 | 20 | /// If `true`, we will generate a post table from the glyph map. 21 | pub fn make_post_table(mut self, flag: bool) -> Self { 22 | self.make_post_table = flag; 23 | self 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fea-rs/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Parsing and compiling the Adobe OpenType Feature File format. 2 | //! 3 | //! The main entry point for this crate is the [`Compiler`] struct, which provides 4 | //! a builder-like interface for compiliing from source. 5 | 6 | #![deny(missing_docs, rustdoc::broken_intra_doc_links)] 7 | 8 | mod common; 9 | pub mod compile; 10 | mod diagnostic; 11 | pub mod parse; 12 | mod token_tree; 13 | pub mod util; 14 | 15 | #[cfg(test)] 16 | mod tests; 17 | 18 | pub use common::{GlyphIdent, GlyphMap, GlyphName}; 19 | pub use compile::Compiler; 20 | pub use diagnostic::{Diagnostic, Level}; 21 | pub use parse::{ParseTree, TokenSet}; 22 | pub use token_tree::{typed, Kind, Node, NodeOrToken, Token}; 23 | -------------------------------------------------------------------------------- /fea-rs/src/tests.rs: -------------------------------------------------------------------------------- 1 | //! integraton-style tests 2 | 3 | mod compile; 4 | mod parse; 5 | -------------------------------------------------------------------------------- /fea-rs/src/util.rs: -------------------------------------------------------------------------------- 1 | //! helpers and utilties (mostly for testing/debugging?) 2 | 3 | pub(crate) mod highlighting; 4 | pub mod paths; 5 | #[cfg(any(test, feature = "diff"))] 6 | pub mod pretty_diff; 7 | #[cfg(any(test, feature = "test"))] 8 | pub mod ttx; 9 | 10 | pub use highlighting::style_for_kind; 11 | #[cfg(any(test, feature = "diff"))] 12 | pub use pretty_diff::write_line_diff; 13 | 14 | #[doc(hidden)] 15 | pub static SPACES: &str = " "; 16 | #[cfg(any(test, feature = "test"))] 17 | pub(crate) static WRITE_RESULTS_VAR: &str = "FEA_WRITE_TEST_OUTPUT"; 18 | #[cfg(any(test, feature = "test"))] 19 | pub(crate) static VERBOSE: &str = "FEA_VERBOSE"; 20 | -------------------------------------------------------------------------------- /fea-rs/test-data/README.md: -------------------------------------------------------------------------------- 1 | # [fea-rs] test data 2 | 3 | This directory contains data files used for testing [fea-rs]. 4 | 5 | See the [main readme][fea-rs-readme] for an overview of the testing process, and 6 | the readmes in the individual subdirectories here describe in more detail what 7 | they contain. 8 | 9 | 10 | [fea-rs]: https://github.com/cmyr/fea-rs/ 11 | [fea-rs-readme]: ../../README.md 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/README.md: -------------------------------------------------------------------------------- 1 | # compile-tests 2 | 3 | Each subdirectory in this directory should contain a `glyph_order.txt` file and a 4 | pair of directores, 'good' and 'bad', each of which contains a number of `.fea` 5 | files. Each of these files is intended to be compiled using the provided glyph 6 | order. 7 | 8 | ## the good 9 | 10 | Files in the 'good' directory are expected to compile successfuly. The output is 11 | not currently checked, although this is something I would like to do later. 12 | 13 | ## the bad 14 | 15 | Files in the 'bad' directory are expected failures. Each of these has a 16 | corresponding `.ERR` file, which contains the expected diagnostic output. 17 | 18 | To update the diagnostics, pass `FEA_WRITE_TEST_OUTPUT=1` as an environment 19 | variable when running the tests. 20 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/GDEF_conflicting_classes.ERR: -------------------------------------------------------------------------------- 1 | error: class includes glyph 'X', already in class Ligature 2 | in ./test-data/compile-tests/mini-latin/bad/GDEF_conflicting_classes.fea at 4:18 3 | | 4 | 4 | GlyphClassDef [a b X], , , ; 5 | | ^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/GDEF_conflicting_classes.fea: -------------------------------------------------------------------------------- 1 | # adapted from a test on fonttools 2 | table GDEF { 3 | GlyphClassDef [a b], [X], , ; 4 | GlyphClassDef [a b X], , , ; 5 | } GDEF; 6 | 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/GPOS_4_non_disjoint_mark_class.ERR: -------------------------------------------------------------------------------- 1 | error: mark class includes glyph in class '@TOP_MARKS', already used in lookup. 2 | in ./test-data/compile-tests/mini-latin/bad/GPOS_4_non_disjoint_mark_class.fea at 10:28 3 | | 4 | 10 | mark @CUTE_TOP_MARKS; 5 | | ^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/GPOS_4_non_disjoint_mark_class.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | markClass [grave bar] @TOP_MARKS; 4 | markClass [grave] @CUTE_TOP_MARKS; 5 | 6 | feature test { 7 | pos base a 8 | mark @TOP_MARKS; 9 | pos base b 10 | mark @CUTE_TOP_MARKS; 11 | } test; 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/aalt_reference_missing_feature.ERR: -------------------------------------------------------------------------------- 1 | error: Referenced feature not found. 2 | in ./test-data/compile-tests/mini-latin/bad/aalt_reference_missing_feature.fea at 2:12 3 | | 4 | 2 | feature nope; 5 | | ^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/aalt_reference_missing_feature.fea: -------------------------------------------------------------------------------- 1 | feature aalt { 2 | feature nope; 3 | } aalt; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/aalt_script_statement.ERR: -------------------------------------------------------------------------------- 1 | error: aalt can only contain feature names and single or alternate sub rules. 2 | in ./test-data/compile-tests/mini-latin/bad/aalt_script_statement.fea at 3:4 3 | | 4 | 3 | script latn; 5 | | ^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/aalt_script_statement.fea: -------------------------------------------------------------------------------- 1 | feature aalt { 2 | # script statements are not allowed in aalt 3 | script latn; 4 | } aalt; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/bad_size1.ERR: -------------------------------------------------------------------------------- 1 | error: size feature can have only one 'parameters' statement 2 | in ./test-data/compile-tests/mini-latin/bad/bad_size1.fea at 3:4 3 | | 4 | 3 | parameters 6 6 6 0; # only one param statement allowed 5 | | ^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/bad_size1.fea: -------------------------------------------------------------------------------- 1 | feature size { 2 | parameters 10.0 3 80 139; 3 | parameters 6 6 6 0; # only one param statement allowed 4 | } size; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/bad_size2.ERR: -------------------------------------------------------------------------------- 1 | error: size feature must include a 'parameters' statement 2 | in ./test-data/compile-tests/mini-latin/bad/bad_size2.fea at 2:8 3 | | 4 | 2 | feature size { 5 | | ^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/bad_size2.fea: -------------------------------------------------------------------------------- 1 | # parameters statement is missing 2 | feature size { 3 | sizemenuname 1 0 5 "Mac MinionPro Size Name"; 4 | } size; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/bad_size3.ERR: -------------------------------------------------------------------------------- 1 | error: if subfamily is omitted, there must be no 'sizemenuname' statements 2 | in ./test-data/compile-tests/mini-latin/bad/bad_size3.fea at 2:4 3 | | 4 | 2 | parameters 6 0 0 0; 5 | | ^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/bad_size3.fea: -------------------------------------------------------------------------------- 1 | feature size { 2 | parameters 6 0 0 0; 3 | sizemenuname "statement not allowed if no subfamily/range present"; 4 | } size; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/bad_size4.ERR: -------------------------------------------------------------------------------- 1 | error: if subfamily is omitted, there must be no 'sizemenuname' statements 2 | in ./test-data/compile-tests/mini-latin/bad/bad_size4.fea at 2:4 3 | | 4 | 2 | parameters 6 0; 5 | | ^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/bad_size4.fea: -------------------------------------------------------------------------------- 1 | feature size { 2 | parameters 6 0; 3 | sizemenuname "statement not allowed if no subfamily/range present"; 4 | } size; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/chain_pos_references_gsub_lookup.ERR: -------------------------------------------------------------------------------- 1 | error: Invalid lookup type: expected GPOS, found GSUB 2 | in ./test-data/compile-tests/mini-latin/bad/chain_pos_references_gsub_lookup.fea at 6:18 3 | | 4 | 6 | pos a' lookup dummy b; 5 | | ^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/chain_pos_references_gsub_lookup.fea: -------------------------------------------------------------------------------- 1 | lookup dummy { 2 | sub a by A; 3 | } dummy; 4 | 5 | feature test { 6 | pos a' lookup dummy b; 7 | } test; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/chain_subst_references_gpos_lookup.ERR: -------------------------------------------------------------------------------- 1 | error: Invalid lookup: expected GSUB, found GPOS 2 | in ./test-data/compile-tests/mini-latin/bad/chain_subst_references_gpos_lookup.fea at 6:18 3 | | 4 | 6 | sub a' lookup dummy b; 5 | | ^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/chain_subst_references_gpos_lookup.fea: -------------------------------------------------------------------------------- 1 | lookup dummy { 2 | pos a 1; 3 | } dummy; 4 | 5 | feature test { 6 | sub a' lookup dummy b; 7 | } test; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/contextual_gsub2_class.ERR: -------------------------------------------------------------------------------- 1 | error: Inline multiple substitution must have a single glyph target 2 | in ./test-data/compile-tests/mini-latin/bad/contextual_gsub2_class.fea at 2:28 3 | | 4 | 2 | substitute [ a e i o u] [f_f f_f_i]' by f f; 5 | | ^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/contextual_gsub2_class.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | substitute [ a e i o u] [f_f f_f_i]' by f f; 3 | } hi; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/duplicate_named_lookup.ERR: -------------------------------------------------------------------------------- 1 | error: A lookup named 'foo' has already been defined 2 | in ./test-data/compile-tests/mini-latin/bad/duplicate_named_lookup.fea at 6:7 3 | | 4 | 6 | lookup foo { 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/duplicate_named_lookup.fea: -------------------------------------------------------------------------------- 1 | 2 | lookup foo { 3 | pos a b 3; 4 | } foo; 5 | 6 | lookup foo { 7 | sub x by y; 8 | } foo; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/feature_ref_outside_aalt.ERR: -------------------------------------------------------------------------------- 1 | error: feature reference only valid in 'aalt' feature 2 | in ./test-data/compile-tests/mini-latin/bad/feature_ref_outside_aalt.fea at 2:4 3 | | 4 | 2 | feature none; # this syntax is only allowed in the 'aalt' feature 5 | | ^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/feature_ref_outside_aalt.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | feature none; # this syntax is only allowed in the 'aalt' feature 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/gpos_8a.ERR: -------------------------------------------------------------------------------- 1 | error: rule cannot have both inline rules and explicit lookups 2 | in ./test-data/compile-tests/mini-latin/bad/gpos_8a.fea at 6:26 3 | | 4 | 6 | pos a b' lookup HI c' -20; 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/gpos_8a.fea: -------------------------------------------------------------------------------- 1 | lookup HI { 2 | pos b -30; 3 | } HI; 4 | 5 | feature test { 6 | pos a b' lookup HI c' -20; 7 | 8 | } test; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/gsub_6_inline_class.ERR: -------------------------------------------------------------------------------- 1 | error: if replacing by glyph class, input sequence must be a single glyph class 2 | in ./test-data/compile-tests/mini-latin/bad/gsub_6_inline_class.fea at 3:8 3 | | 4 | 3 | sub a' [b c]' d by [z x]; 5 | | ^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/gsub_6_inline_class.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | # replace by class only accepts single input 3 | sub a' [b c]' d by [z x]; 4 | } test; 5 | 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/gsub_6_inline_no_class.ERR: -------------------------------------------------------------------------------- 1 | error: if replacing by glyph class, input sequence must be a single glyph class 2 | in ./test-data/compile-tests/mini-latin/bad/gsub_6_inline_no_class.fea at 3:8 3 | | 4 | 3 | sub a' d by [z x]; 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/gsub_6_inline_no_class.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | # replace by class only accepts single input 3 | sub a' d by [z x]; 4 | } test; 5 | 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/gsub_6_named_and_inline.ERR: -------------------------------------------------------------------------------- 1 | error: named lookup not allowed in statement that includes inline rule 2 | in ./test-data/compile-tests/mini-latin/bad/gsub_6_named_and_inline.fea at 7:11 3 | | 4 | 7 | sub a' lookup HI b' c by d; 5 | | ^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/gsub_6_named_and_inline.fea: -------------------------------------------------------------------------------- 1 | lookup HI { 2 | sub a by b; 3 | } HI; 4 | 5 | feature test { 6 | # cannot have explicit lookup as well as inline rule: 7 | sub a' lookup HI b' c by d; 8 | } test; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/languagesystem_order.ERR: -------------------------------------------------------------------------------- 1 | error: 'DFLT dftl' must be first languagesystem statement 2 | in ./test-data/compile-tests/mini-latin/bad/languagesystem_order.fea at 2:0 3 | | 4 | 2 | languagesystem DFLT dflt; 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/languagesystem_order.fea: -------------------------------------------------------------------------------- 1 | languagesystem latn TRK; 2 | languagesystem DFLT dflt; 3 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/languagesystem_order2.ERR: -------------------------------------------------------------------------------- 1 | error: languagesystem with 'DFLT' script tag must precede non-'DFLT' languagesystems 2 | in ./test-data/compile-tests/mini-latin/bad/languagesystem_order2.fea at 3:15 3 | | 4 | 3 | languagesystem DFLT autr; 5 | | ^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/languagesystem_order2.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | languagesystem latn dflt; 3 | languagesystem DFLT autr; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/lookup_mixed_rules.ERR: -------------------------------------------------------------------------------- 1 | error: multiple rule types in lookup block (saw 'GsubType1' after 'GsubType4') 2 | in ./test-data/compile-tests/mini-latin/bad/lookup_mixed_rules.fea at 4:4 3 | | 4 | 4 | sub one by one.osf; 5 | | ^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/lookup_mixed_rules.fea: -------------------------------------------------------------------------------- 1 | # within a named lookup, all rules must have same lookuptype 2 | lookup foo { 3 | sub f f i by f_f_i; 4 | sub one by one.osf; 5 | } foo; 6 | 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/lookup_multiple_flags.ERR: -------------------------------------------------------------------------------- 1 | error: all rules in named lookup must have same lookup flags 2 | in ./test-data/compile-tests/mini-latin/bad/lookup_multiple_flags.fea at 5:4 3 | | 4 | 5 | lookupflag 2; 5 | | ^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/lookup_multiple_flags.fea: -------------------------------------------------------------------------------- 1 | # within a named lookup, all rules must have same lookupflag 2 | lookup foo { 3 | lookupflag 1; 4 | sub a by b; 5 | lookupflag 2; 6 | sub x by y; 7 | } foo; 8 | 9 | # this is fine, since no rules in the lookup use the second lookupflag 10 | lookup bar { 11 | lookupflag 1; 12 | sub g by h; 13 | lookupflag 0; 14 | } bar; 15 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/name_table_encoding.ERR: -------------------------------------------------------------------------------- 1 | error: windows escape sequences must be four hex digits long 2 | in ./test-data/compile-tests/mini-latin/bad/name_table_encoding.fea at 3:21 3 | | 4 | 3 | nameid 9 "Joachim\CF"; # windows escapes must be 4 digits 5 | | ^^^ 6 | 7 | error: mac escape sequences must be two hex digits long 8 | in ./test-data/compile-tests/mini-latin/bad/name_table_encoding.fea at 5:23 9 | | 10 | 5 | nameid 1001 1 "bad \d"; # mac escapes must be 2 digits 11 | | ^^ 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/name_table_encoding.fea: -------------------------------------------------------------------------------- 1 | # each of these entries contains an invalid escape sequence 2 | table name { 3 | nameid 9 "Joachim\CF"; # windows escapes must be 4 digits 4 | nameid 1001 "Null Mc\0000face"; # which cannot all be zero 5 | nameid 1001 1 "bad \d"; # mac escapes must be 2 digits 6 | } name; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/script_in_lookup.ERR: -------------------------------------------------------------------------------- 1 | error: script and language statements not allowed in standalone lookup blocks 2 | in ./test-data/compile-tests/mini-latin/bad/script_in_lookup.fea at 3:4 3 | | 4 | 3 | script latn; 5 | | ^^^^^^^^^^^^ 6 | 7 | error: script and language statements not allowed in standalone lookup blocks 8 | in ./test-data/compile-tests/mini-latin/bad/script_in_lookup.fea at 4:4 9 | | 10 | 4 | language lang; 11 | | ^^^^^^^^^^^^^^ 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/script_in_lookup.fea: -------------------------------------------------------------------------------- 1 | # script/language is not allowed in standalone lookups 2 | lookup test { 3 | script latn; 4 | language lang; 5 | } test; 6 | 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/size_script_statement.ERR: -------------------------------------------------------------------------------- 1 | error: size can only contain feature names and single or alternate sub rules. 2 | in ./test-data/compile-tests/mini-latin/bad/size_script_statement.fea at 3:4 3 | | 4 | 3 | script latn; 5 | | ^^^^^^^^^^^^ 6 | 7 | error: size can only contain feature names and single or alternate sub rules. 8 | in ./test-data/compile-tests/mini-latin/bad/size_script_statement.fea at 4:4 9 | | 10 | 4 | language lang; 11 | | ^^^^^^^^^^^^^^ 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/size_script_statement.fea: -------------------------------------------------------------------------------- 1 | # script & language re not allowed in 'size' feature 2 | feature size { 3 | script latn; 4 | language lang; 5 | parameters 1 2 3 4; 6 | } size; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variable_condset_oob.ERR: -------------------------------------------------------------------------------- 1 | error: value is less than axis minimum (200) 2 | in ./test-data/compile-tests/mini-latin/bad/variable_condset_oob.fea at 2:6 3 | | 4 | 2 | wght -100 4004; 5 | | ^^^^ 6 | 7 | error: value is more than axis maximum (1000) 8 | in ./test-data/compile-tests/mini-latin/bad/variable_condset_oob.fea at 2:11 9 | | 10 | 2 | wght -100 4004; 11 | | ^^^^ 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variable_condset_oob.fea: -------------------------------------------------------------------------------- 1 | conditionset inval { 2 | wght -100 4004; 3 | } inval; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variable_unknown_condset_tag.ERR: -------------------------------------------------------------------------------- 1 | error: unknown axis 2 | in ./test-data/compile-tests/mini-latin/bad/variable_unknown_condset_tag.fea at 2:1 3 | | 4 | 2 | grvy 101 404; 5 | | ^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variable_unknown_condset_tag.fea: -------------------------------------------------------------------------------- 1 | conditionset groovy { 2 | grvy 101 404; 3 | } groovy; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variable_value_record_oob.ERR: -------------------------------------------------------------------------------- 1 | error: value exceeds expected range (200, 1000) 2 | in ./test-data/compile-tests/mini-latin/bad/variable_value_record_oob.fea at 1:24 3 | | 4 | 1 | valueRecordDef <0 (wght=100:-100 wght=1100:-150) 0 0> foo; 5 | | ^^^ 6 | 7 | error: value exceeds expected range (200, 1000) 8 | in ./test-data/compile-tests/mini-latin/bad/variable_value_record_oob.fea at 1:38 9 | | 10 | 1 | valueRecordDef <0 (wght=100:-100 wght=1100:-150) 0 0> foo; 11 | | ^^^^ 12 | 13 | error: normalized value should be in range (-1.0, 1.0) 14 | in ./test-data/compile-tests/mini-latin/bad/variable_value_record_oob.fea at 2:24 15 | | 16 | 2 | valueRecordDef <0 (wght=-1.2n:-100 wght=5n:-150) 0 0> boo; 17 | | ^^^^^ 18 | 19 | error: normalized value should be in range (-1.0, 1.0) 20 | in ./test-data/compile-tests/mini-latin/bad/variable_value_record_oob.fea at 2:40 21 | | 22 | 2 | valueRecordDef <0 (wght=-1.2n:-100 wght=5n:-150) 0 0> boo; 23 | | ^^ 24 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variable_value_record_oob.fea: -------------------------------------------------------------------------------- 1 | valueRecordDef <0 (wght=100:-100 wght=1100:-150) 0 0> foo; 2 | valueRecordDef <0 (wght=-1.2n:-100 wght=5n:-150) 0 0> boo; 3 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variable_value_record_unknown_axis.ERR: -------------------------------------------------------------------------------- 1 | error: unknown axis 2 | in ./test-data/compile-tests/mini-latin/bad/variable_value_record_unknown_axis.fea at 1:33 3 | | 4 | 1 | valueRecordDef <0 (wght=200:-100 heft=150,wght=900:-120) 0 0> foo; 5 | | ^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variable_value_record_unknown_axis.fea: -------------------------------------------------------------------------------- 1 | valueRecordDef <0 (wght=200:-100 heft=150,wght=900:-120) 0 0> foo; 2 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variation_undefined_condset.ERR: -------------------------------------------------------------------------------- 1 | error: undefined conditionset 2 | in ./test-data/compile-tests/mini-latin/bad/variation_undefined_condset.fea at 1:15 3 | | 4 | 1 | variation oops my_conditions { 5 | | ^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/bad/variation_undefined_condset.fea: -------------------------------------------------------------------------------- 1 | variation oops my_conditions { 2 | pos a b 3; 3 | } oops; 4 | 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/glyph_order.txt: -------------------------------------------------------------------------------- 1 | .notdef 2 | NULL 3 | CR 4 | space 5 | exclam 6 | quotedbl 7 | numbersign 8 | dollar 9 | percent 10 | ampersand 11 | quotesingle 12 | parenleft 13 | parenright 14 | asterisk 15 | plus 16 | comma 17 | hyphen 18 | period 19 | slash 20 | zero 21 | one 22 | two 23 | three 24 | four 25 | five 26 | six 27 | seven 28 | eight 29 | nine 30 | colon 31 | semicolon 32 | less 33 | equal 34 | greater 35 | question 36 | at 37 | A 38 | B 39 | C 40 | D 41 | E 42 | F 43 | G 44 | H 45 | I 46 | J 47 | K 48 | L 49 | M 50 | N 51 | O 52 | P 53 | Q 54 | R 55 | S 56 | T 57 | U 58 | V 59 | W 60 | X 61 | Y 62 | Z 63 | bracketleft 64 | backslash 65 | bracketright 66 | asciicircum 67 | underscore 68 | grave 69 | a 70 | b 71 | c 72 | d 73 | e 74 | f 75 | g 76 | h 77 | i 78 | j 79 | k 80 | l 81 | m 82 | n 83 | o 84 | p 85 | q 86 | r 87 | s 88 | t 89 | u 90 | v 91 | w 92 | x 93 | y 94 | z 95 | braceleft 96 | bar 97 | braceright 98 | asciitilde 99 | f_f 100 | f_f_i 101 | g.salt 102 | zero.osf 103 | one.osf 104 | two.osf 105 | three.osf 106 | four.osf 107 | five.osf 108 | six.osf 109 | seven.osf 110 | eight.osf 111 | nine.osf 112 | zero.slash 113 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/basic_kern.fea: -------------------------------------------------------------------------------- 1 | feature kern { 2 | pos A B 5; 3 | pos a f -10; 4 | pos b one 15; 5 | } kern; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/basic_liga.fea: -------------------------------------------------------------------------------- 1 | feature liga { 2 | sub f f by f_f; 3 | sub f f i by f_f_i; 4 | } liga; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/basic_liga.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/big_device.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | 3 | pos A <-80 0 -160 0 4 | 5 | 6 | 7 | >; 8 | } test; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/big_device.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/duplicate_lookups.fea: -------------------------------------------------------------------------------- 1 | # It is possible to add the same lookup multiple times to a feature, but 2 | # it will be removed before compilation. 3 | languagesystem DFLT dflt; 4 | languagesystem latn dflt; 5 | languagesystem latn HMM; 6 | 7 | feature test { 8 | 9 | lookup alt1 { 10 | sub a by A; 11 | } alt1; 12 | lookup alt2 { 13 | sub b by B; 14 | } alt2; 15 | 16 | # latn dflt here includes both named lookups 17 | script latn; 18 | lookup alt1; # so this is redundant 19 | } test; 20 | 21 | 22 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/gpos8a.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos a b' -20 c' 30 g' <-10 10 22 23> e; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/gpos_mixed_single_multi_rules.fea: -------------------------------------------------------------------------------- 1 | # when a lookup block contains mixed single & multi-sub rules, we combine 2 | # them into a single multi-sub lookup. 3 | lookup mixed { 4 | # single sub rules: 5 | sub [c d] by E; 6 | sub b by B; 7 | # ligature decomposition/multi sub rules: 8 | sub F by f f; 9 | } mixed; 10 | 11 | # we also want to allow single rules to follow multi, and be promoted 12 | lookup also_mixed { 13 | sub F by f f; 14 | sub b by B; 15 | } also_mixed; 16 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/gpos_mixed_single_multi_rules.ttx: -------------------------------------------------------------------------------- 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 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/gsub1.fea: -------------------------------------------------------------------------------- 1 | @numbers = [one two three four]; 2 | @numbers_old_style = [one.osf two.osf three.osf four.osf]; 3 | 4 | # glyph -> glyph 5 | feature onum { 6 | sub one by one.osf; 7 | sub two by two.osf; 8 | sub three by three.osf; 9 | sub four by four.osf; 10 | } onum; 11 | 12 | # class -> class 13 | feature noos { 14 | sub @numbers_old_style by @numbers; 15 | } noos; 16 | 17 | # class -> glyph 18 | feature nono { 19 | # technically creates a type-2 lookup: multisub with an empty target sequence 20 | sub @numbers by NULL; 21 | # that means this will also be type-2, since we combine mixed single&multi rules. 22 | sub @numbers_old_style by question; 23 | } nono; 24 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/gsub_1_omit_by.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | # equivalent to 'sub a by NULL;' 3 | sub a; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/gsub_1_omit_by.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/lookup_single_flag.fea: -------------------------------------------------------------------------------- 1 | # ensure that we allow a single lookupflag before rules in named lookups 2 | lookup foo { 3 | lookupflag 3; 4 | sub a by b; 5 | } foo; 6 | 7 | feature test { 8 | lookup foo; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/lookup_single_flag.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/mixed_lookups.fea: -------------------------------------------------------------------------------- 1 | # a feature with both gpos & gsub lookups 2 | 3 | feature mixt { 4 | sub a by b; 5 | pos c d -10; 6 | } mixt; 7 | 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/naked_semi.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | lookup foo { 3 | lookupflag 3; 4 | # we should warn here but otherwise continue 5 | ; 6 | sub a c' by b; 7 | } foo; 8 | } test; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/rsub_many_by_one.fea: -------------------------------------------------------------------------------- 1 | # makeotf errors but fonttools replaces everything with the target, 2 | # which is now normal sub rules work, so that seems sane 3 | feature test { 4 | rsub a [b c]' d by X; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/spec_6iii_3c.fea: -------------------------------------------------------------------------------- 1 | # http://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html#example-3c 2 | # this is a special case, and should produce a pairpos lookup for f -> 10 3 | feature kern { 4 | pos s f' t period 10; 5 | pos a b' c 10; 6 | } kern; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/value_record_def_simple.fea: -------------------------------------------------------------------------------- 1 | valueRecordDef 123 foo; 2 | 3 | feature liga { 4 | # these should go in the same lookup 5 | pos a -20; 6 | pos b ; 7 | } liga; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/value_record_def_simple.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/variable_condition_sort_order.fea: -------------------------------------------------------------------------------- 1 | # the conditions in the FeatureVariations table should be ordered by 2 | # when they are used, not declared 3 | 4 | # index 0 0.0 - 0.625 5 | conditionset TWO { 6 | wght 200 700; 7 | } TWO; 8 | 9 | # index 1 0.0 - 0.2 10 | conditionset ZERO { 11 | wdth 100 120; 12 | } ZERO; 13 | 14 | # index 0 0.125 - 0.2525 15 | conditionset ONE { 16 | wght 300 402; 17 | } ONE; 18 | 19 | lookup blah { 20 | pos a 5; 21 | } blah; 22 | 23 | variation test NULL { 24 | lookup blah; 25 | } test; 26 | 27 | variation test ZERO { 28 | lookup blah; 29 | } test; 30 | 31 | variation test ONE { 32 | lookup blah; 33 | } test; 34 | 35 | variation test TWO { 36 | lookup blah; 37 | } test; 38 | 39 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/variable_feature_include_base.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | feature test { 4 | pos a b 5; 5 | } test; 6 | 7 | conditionset MAYBE { 8 | wght 200 202; 9 | } MAYBE; 10 | 11 | # this feature variation should include the lookup declared for the base feature. 12 | variation test MAYBE { 13 | pos d e 101; 14 | } test; 15 | -------------------------------------------------------------------------------- /fea-rs/test-data/compile-tests/mini-latin/good/variable_feature_null_conditionset.fea: -------------------------------------------------------------------------------- 1 | # null conditionset should be null offest in output font 2 | variation test NULL { 3 | pos a b -100; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/AlternateChained.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub A B a' [Y y] Z from [a.alt1 a.alt2 a.alt3]; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/AlternateSubtable.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub A from [A.alt1 A.alt2]; 3 | subtable; 4 | sub B from [B.alt1 B.alt2]; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/AlternateSubtable.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/Attach.fea: -------------------------------------------------------------------------------- 1 | table GDEF { 2 | Attach [a e] 7; 3 | Attach a 23; 4 | Attach a 23; 5 | } GDEF; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/Attach.ttx: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ChainPosSubtable.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos X [A - B]' -40 B' -40 A' -40 Y; 3 | subtable; 4 | pos X A' -111 Y; 5 | subtable; 6 | pos X B' -40 A' -111 [A - C]' -40 Y; 7 | } test; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ChainSubstSubtable.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub A G' by G.swash; 3 | subtable; 4 | sub A H' by H.swash; 5 | subtable; 6 | sub A G' by g; 7 | subtable; 8 | sub A H' by H.swash; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_1.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | @sevenEightNine = [seven eight nine]; 4 | 5 | feature kern { 6 | pos zero 0; 7 | 8 | pos [one two three] <-80 0 -160 0>; 9 | pos A <1 2 3 4 >; 10 | pos B <1 2 3 4 >; 11 | pos C <1 2 3 4 >; 12 | pos four 400; 13 | pos four.oldstyle 401; 14 | pos five <-80 0 -160 0>; 15 | pos six -200; 16 | pos @sevenEightNine -100; 17 | 18 | pos P <1 0 800 0>; 19 | pos Q <1 0 801 0>; 20 | pos R <1 0 802 0>; 21 | pos S <1 1 803 0>; 22 | pos T <1 1 804 0>; 23 | pos U <1 1 805 0>; 24 | 25 | # The AFDKO makeotf tool accepts re-definitions of previously defined 26 | # single adjustment positionings, provided the re-definition is using 27 | # the same value. We replicate this behavior. 28 | pos four 400; 29 | pos four <0 0 400 0>; 30 | pos nine -100; 31 | } kern; 32 | 33 | # According to the OpenType Feature File specification section 2.e.iv, 34 | # the following should be interpreted as vertical advance adjustment 35 | # because -100 (a value record format A) appears within a ‘vkrn’ feature. 36 | # However, the AFDKO makeotf tool v2.0.90 (built on Nov 19, 2015) still 37 | # makes it a horizontal advance adjustment. In our implementation, 38 | # we follow the specification, so we produce different output than makeotf. 39 | # https://github.com/adobe-type-tools/afdko/issues/85 40 | feature vkrn { 41 | pos A -100; 42 | } vkrn; 43 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_1_zero.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/471 2 | feature test { 3 | pos zero 0; 4 | pos four 500; 5 | } test; -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_1_zero.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_2.expected_diff: -------------------------------------------------------------------------------- 1 | # generated automatically by fea-rs 2 | # this file represents an acceptable difference between the output of 3 | # fonttools and the output of fea-rs for a given input. 4 | # 5 | # Note: the order of lookups within a feature doesn't matter, they are processed 6 | # in the order they appear in the lookup list 7 | L26 8 | > 9 | > 10 | L26 11 | < 12 | < 13 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_2.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | # Mixes kerning between single glyphs, and class-based kerning. 4 | # https://github.com/fonttools/fonttools/issues/456 5 | lookup MixedKerning { 6 | pos v v 14; 7 | pos [D O Q] [T V W] -26; 8 | } MixedKerning; 9 | 10 | lookup GlyphKerning { 11 | pos T one 100; 12 | pos T two 200; 13 | pos T two.oldstyle 200; 14 | pos T three 300; 15 | pos T four 400; 16 | pos X a 100; 17 | pos X b 200; 18 | pos Y a 100; 19 | pos Y b 200; 20 | pos Y c <3 3 3 3>; 21 | } GlyphKerning; 22 | 23 | feature kern { 24 | lookup GlyphKerning; 25 | lookup MixedKerning; 26 | } kern; 27 | 28 | feature vkrn { 29 | pos T one 100; 30 | } vkrn; 31 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_2b.fea: -------------------------------------------------------------------------------- 1 | @PUNC = [comma semicolon period]; 2 | 3 | feature kern { 4 | pos [A] @PUNC 1; 5 | pos [B C] [comma] 2; 6 | pos [D E F] [comma] 3; 7 | pos [D E F] [semicolon period] 4; 8 | pos [G] @PUNC <5 5 5 5>; 9 | } kern; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_3.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | anchorDef 3 4 contourpoint 2 ANCH342; 4 | 5 | feature kern { 6 | pos cursive zero ; 7 | pos cursive one ; 8 | pos cursive two ; 9 | pos cursive three ; 10 | pos cursive four ; 11 | pos cursive five > ; 12 | } kern; 13 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_4.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | markClass [acute grave] @TOP_MARKS; 4 | markClass macron @TOP_MARKS; 5 | markClass [cedilla] @BOTTOM_MARKS; 6 | markClass [ogonek] @SIDE_MARKS; 7 | 8 | feature test { 9 | pos base a 10 | mark @TOP_MARKS 11 | mark @BOTTOM_MARKS; 12 | pos base [b c] 13 | mark @BOTTOM_MARKS; 14 | pos base d 15 | mark @SIDE_MARKS; 16 | } test; 17 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_5.fea: -------------------------------------------------------------------------------- 1 | markClass [acute grave] @TOP_MARKS; 2 | markClass macron @TOP_MARKS; 3 | markClass [cedilla] @BOTTOM_MARKS; 4 | markClass [ogonek] @OGONEK; 5 | 6 | feature test { 7 | 8 | pos ligature [c_t s_t] 9 | mark @TOP_MARKS 10 | mark @BOTTOM_MARKS 11 | ligComponent 12 | mark @TOP_MARKS 13 | mark @BOTTOM_MARKS 14 | mark @OGONEK; 15 | 16 | pos ligature f_l 17 | mark @TOP_MARKS 18 | mark @BOTTOM_MARKS 19 | ligComponent 20 | mark @TOP_MARKS 21 | mark @BOTTOM_MARKS; 22 | 23 | pos ligature [f_f_l] 24 | mark @TOP_MARKS 25 | mark @BOTTOM_MARKS 26 | ligComponent 27 | mark @TOP_MARKS 28 | mark @BOTTOM_MARKS 29 | ligComponent 30 | mark @TOP_MARKS 31 | mark @BOTTOM_MARKS; 32 | 33 | } test; 34 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_6.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | markClass [acute grave] @TOP_MARKS; 4 | markClass macron @TOP_MARKS; 5 | markClass [cedilla] @BOTTOM_MARKS; 6 | 7 | feature test { 8 | pos mark [acute grave macron ogonek] 9 | mark @TOP_MARKS 10 | mark @BOTTOM_MARKS; 11 | pos mark [dieresis caron] 12 | mark @TOP_MARKS; 13 | } test; 14 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GPOS_8.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | lookup ChainedSinglePos { 4 | pos A one' 1 two' 2 one' -1 two' -2; 5 | } ChainedSinglePos; 6 | 7 | lookup L1 { 8 | pos one 100; 9 | } L1; 10 | 11 | lookup L2 { 12 | pos two 200; 13 | } L2; 14 | 15 | lookup ChainedContextualPos { 16 | pos [A a] [B b] I' lookup L1 N' lookup L2 P' [Y y] [Z z]; 17 | } ChainedContextualPos; 18 | 19 | feature test { 20 | lookup ChainedSinglePos; 21 | lookup ChainedContextualPos; 22 | } test; 23 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GSUB_2.fea: -------------------------------------------------------------------------------- 1 | feature f1 { 2 | sub c_t by c t; 3 | sub f_i by f i; 4 | sub f_f_i by f f i; 5 | } f1; 6 | 7 | 8 | # Even if it has exactly the same content as feature f1, 9 | # the lookup should not be shared. 10 | feature f2 { 11 | sub c_t by c t; 12 | sub f_i by f i; 13 | sub f_f_i by f f i; 14 | } f2; 15 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GSUB_3.fea: -------------------------------------------------------------------------------- 1 | feature f1 { 2 | sub A from [A.alt1 A.alt2]; 3 | sub B from [B.alt1 B.alt2 B.alt3]; 4 | sub C from [C.alt1]; 5 | } f1; 6 | 7 | 8 | # Even if it has exactly the same content as feature f1, 9 | # the lookup should not be shared. 10 | feature f2 { 11 | sub A from [A.alt1 A.alt2]; 12 | sub B from [B.alt1 B.alt2 B.alt3]; 13 | sub C from [C.alt1]; 14 | } f2; 15 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GSUB_5_formats.fea: -------------------------------------------------------------------------------- 1 | lookup GSUB5f1 { 2 | ignore sub three' four'; 3 | ignore sub four' five'; 4 | } GSUB5f1; 5 | 6 | lookup GSUB5f2 { 7 | ignore sub [a - z]' [A - H]' [I - Z]'; 8 | ignore sub [a - z]' [A - H]' [I - Z]'; 9 | ignore sub [a - z]' [I - Z]' [A - H]'; 10 | } GSUB5f2; 11 | 12 | lookup GSUB5f3 { 13 | ignore sub e'; 14 | } GSUB5f3; 15 | 16 | feature test { 17 | lookup GSUB5f1; 18 | lookup GSUB5f2; 19 | lookup GSUB5f3; 20 | } test; 21 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GSUB_6.fea: -------------------------------------------------------------------------------- 1 | lookup ChainedSingleSubst { 2 | sub [one two] three A' by A.sc; 3 | sub [B - D]' seven [eight nine] by [B.sc - D.sc]; 4 | } ChainedSingleSubst; 5 | 6 | lookup ChainedMultipleSubst { 7 | sub [A - C a - c] [D d] E c_t' V [W w] [X - Z x - z] by c t; 8 | } ChainedMultipleSubst; 9 | 10 | lookup ChainedAlternateSubst { 11 | sub [space comma semicolon] e' from [e e.begin]; 12 | } ChainedAlternateSubst; 13 | 14 | lookup ChainedLigatureSubst { 15 | sub A [C c]' [T t]' Z by c_t; 16 | } ChainedLigatureSubst; 17 | 18 | lookup ChainedContextualSubst { 19 | sub A D E c_t' lookup ChainedMultipleSubst V W X; 20 | } ChainedContextualSubst; 21 | 22 | feature test { 23 | lookup ChainedSingleSubst; 24 | lookup ChainedMultipleSubst; 25 | lookup ChainedAlternateSubst; 26 | lookup ChainedLigatureSubst; 27 | lookup ChainedContextualSubst; 28 | } test; 29 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GSUB_6_formats.fea: -------------------------------------------------------------------------------- 1 | lookup GSUB6f1 { 2 | ignore sub one two three' four' five six seven; 3 | ignore sub two one three' four' six five seven; 4 | } GSUB6f1; 5 | 6 | lookup GSUB6f2 { 7 | ignore sub [A - H] [I - Z] [a - z]' [A - H]' [I - Z]'; 8 | ignore sub [I - Z] [A - H] [a - z]' [A - H]' [I - Z]'; 9 | ignore sub [A - H] [I - Z] [a - z]' [I - Z]' [A - H]'; 10 | } GSUB6f2; 11 | 12 | lookup GSUB6f3 { 13 | ignore sub [space comma semicolon] e'; 14 | } GSUB6f3; 15 | 16 | feature test { 17 | lookup GSUB6f1; 18 | lookup GSUB6f2; 19 | lookup GSUB6f3; 20 | } test; 21 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GSUB_8.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | feature test { 4 | rsub [a A] [b B] [c C] q' [d D] [e E] [f F] by Q; 5 | rsub [a A] [b B] [c C] [s - z]' [d D] [e E] [f F] by [S - Z]; 6 | 7 | # Having no context for a reverse chaining substitution rule 8 | # is a little degenerate (we define a chain without linking it 9 | # to anything else), but makeotf accepts this. 10 | rsub p by P; 11 | } test; 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GSUB_error.fea: -------------------------------------------------------------------------------- 1 | # Trigger a parser error in the function parse_substitute_ in order to improve the error message. 2 | # Note that this is not a valid substitution, this test is made to trigger an error. 3 | 4 | languagesystem latn dflt; 5 | 6 | @base = [a e]; 7 | @accents = [acute grave]; 8 | 9 | feature abvs { 10 | lookup lookup1 { 11 | sub @base @accents by @base; 12 | } lookup1; 13 | } abvs; 14 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GlyphClassDef.fea: -------------------------------------------------------------------------------- 1 | table GDEF { 2 | GlyphClassDef [a], [b], [c], [d]; 3 | GlyphClassDef [e], [f], [g], [h]; 4 | GlyphClassDef [i], [j], [k], [l]; 5 | } GDEF; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/GlyphClassDef.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/LigatureCaretByIndex.fea: -------------------------------------------------------------------------------- 1 | table GDEF { 2 | LigatureCaretByIndex [c_t s_t] 11; 3 | 4 | LigatureCaretByIndex o_f_f_i 66 33; 5 | LigatureCaretByIndex o_f_f_i 55; 6 | } GDEF; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/LigatureCaretByIndex.ttx: -------------------------------------------------------------------------------- 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 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/LigatureCaretByPos.fea: -------------------------------------------------------------------------------- 1 | table GDEF { 2 | LigatureCaretByPos [c_h c_k] 500; 3 | 4 | LigatureCaretByPos o_f_f_i 700 300; 5 | LigatureCaretByPos o_f_f_i 900; 6 | } GDEF; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/LigatureCaretByPos.ttx: -------------------------------------------------------------------------------- 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 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/LigatureSubtable.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub f f by f_f; 3 | subtable; 4 | sub f i by f_i; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/LigatureSubtable.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/MultipleLookupsPerGlyph.fea: -------------------------------------------------------------------------------- 1 | lookup a_to_bc { 2 | sub a by b c; 3 | } a_to_bc; 4 | 5 | lookup b_to_d { 6 | sub b by d; 7 | } b_to_d; 8 | 9 | feature test { 10 | sub a' lookup a_to_bc lookup b_to_d b; 11 | } test; -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/MultipleLookupsPerGlyph2.fea: -------------------------------------------------------------------------------- 1 | lookup a_reduce_sb { 2 | pos a <-80 0 -160 0>; 3 | } a_reduce_sb; 4 | 5 | lookup a_raise { 6 | pos a <0 100 0 0>; 7 | } a_raise; 8 | 9 | feature test { 10 | pos a' lookup a_reduce_sb lookup a_raise b; 11 | } test; -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/MultipleSubstSubtable.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub c_t by c t; 3 | subtable; 4 | sub f_i by f i; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/MultipleSubstSubtable.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/PairPosSubtable.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | languagesystem latn dflt; 3 | 4 | @group1 = [b o]; 5 | @group2 = [c d]; 6 | @group3 = [v w]; 7 | 8 | lookup kernlookup { 9 | pos A V -34; 10 | subtable; 11 | pos @group1 @group2 -12; 12 | subtable; 13 | pos @group1 @group3 -10; 14 | pos @group3 @group2 -20; 15 | } kernlookup; 16 | 17 | feature kern { 18 | script DFLT; 19 | language dflt; 20 | lookup kernlookup; 21 | 22 | script latn; 23 | language dflt; 24 | lookup kernlookup; 25 | } kern; 26 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/README.md: -------------------------------------------------------------------------------- 1 | These tests are taken from the [fonttools] python project. 2 | 3 | [fonttools]: https://github.com/fonttools/fonttools 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/SingleSubstSubtable.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub a by b; 3 | subtable; 4 | sub c by d; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/SingleSubstSubtable.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/SubstSubtable.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub G' by G.swash; 3 | subtable; 4 | sub H' by H.swash; 5 | subtable; 6 | sub G' by g; 7 | subtable; 8 | sub H' by H.swash; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ZeroValue_ChainSinglePos_horizontal.fea: -------------------------------------------------------------------------------- 1 | # For contextual positioning statements with in-line single positioning rules, 2 | # zeroes should get compiled to ValueRecord format 0. 3 | # https://github.com/fonttools/fonttools/issues/633 4 | 5 | # Zero value in a horizontal context. 6 | feature kern { 7 | pos A G' 0 A; # value format A 8 | pos B G' <0 0 0 0> B; # value format B 9 | } kern; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ZeroValue_ChainSinglePos_vertical.fea: -------------------------------------------------------------------------------- 1 | # For contextual positioning statements with in-line single positioning rules, 2 | # zeroes should get compiled to ValueRecord format 0. 3 | # https://github.com/fonttools/fonttools/issues/633 4 | 5 | # Zero value in a vertical context. 6 | feature vkrn { 7 | pos A G' 0 A; # value format A 8 | pos B G' <0 0 0 0> B; # value format B 9 | } vkrn; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ZeroValue_PairPos_horizontal.fea: -------------------------------------------------------------------------------- 1 | # For PairPos statements in horizontal compilation contexts, 2 | # zero values should get compiled to ValueRecord format 4. 3 | # https://github.com/fonttools/fonttools/issues/633 4 | feature kern { 5 | pos A 0 A 0; 6 | pos A 0 B <0 0 0 0>; 7 | pos B <0 0 0 0> A 0; 8 | pos B <0 0 0 0> B <0 0 0 0>; 9 | } kern; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ZeroValue_PairPos_vertical.fea: -------------------------------------------------------------------------------- 1 | # For PairPos statements in vertical compilation contexts, 2 | # zero values should get compiled to ValueRecord format 8. 3 | # https://github.com/fonttools/fonttools/issues/633 4 | feature vkrn { 5 | pos A 0 A 0; 6 | pos A 0 B <0 0 0 0>; 7 | pos B <0 0 0 0> A 0; 8 | pos B <0 0 0 0> B <0 0 0 0>; 9 | } vkrn; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ZeroValue_SinglePos_horizontal.fea: -------------------------------------------------------------------------------- 1 | # For SinglePos statements, zeroes should get compiled to ValueRecord format 0. 2 | # https://github.com/fonttools/fonttools/issues/633 3 | 4 | # Zero value in a horizontal context. 5 | feature kern { 6 | pos A 0; # format A 7 | pos B <0 0 0 0>; # format B 8 | } kern; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ZeroValue_SinglePos_horizontal.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ZeroValue_SinglePos_vertical.fea: -------------------------------------------------------------------------------- 1 | # For SinglePos statements, zeroes should get compiled to ValueRecord format 0. 2 | # https://github.com/fonttools/fonttools/issues/633 3 | 4 | # Zero value in a vertical context. 5 | feature vkrn { 6 | pos A 0; # format A 7 | pos B <0 0 0 0>; # format B 8 | } vkrn; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ZeroValue_SinglePos_vertical.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/aalt_chain_contextual_subst.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/googlefonts/fontmake/issues/648 2 | 3 | lookup CNTXT_LIGS { 4 | sub f i by f_i; 5 | sub c t by c_t; 6 | } CNTXT_LIGS; 7 | 8 | lookup CNTXT_SUB { 9 | sub n by n.end; 10 | sub s by s.end; 11 | } CNTXT_SUB; 12 | 13 | feature calt { 14 | sub [a e i o u] f' lookup CNTXT_LIGS i' n' lookup CNTXT_SUB; 15 | sub [a e i o u] c' lookup CNTXT_LIGS t' s' lookup CNTXT_SUB; 16 | } calt; 17 | 18 | feature aalt { 19 | feature calt; 20 | } aalt; 21 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/baseClass.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | markClass [acute] @TOP_MARKS; 4 | 5 | feature test { 6 | pos base [a] mark @TOP_MARKS; 7 | pos base b mark @TOP_MARKS; 8 | } test; 9 | 10 | 11 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug1307.fea: -------------------------------------------------------------------------------- 1 | # Test of features and languagesystems 2 | 3 | lookup a { 4 | sub a by A; 5 | } a; 6 | 7 | lookup b { 8 | sub b by B; 9 | } b; 10 | 11 | lookup c { 12 | sub c by C; 13 | } c; 14 | 15 | lookup d { 16 | sub d by D; 17 | } d; 18 | 19 | lookup e { 20 | sub e by E; 21 | } e; 22 | 23 | lookup f { 24 | sub f by F; 25 | } f; 26 | 27 | lookup g { 28 | sub g by G; 29 | } g; 30 | 31 | lookup h { 32 | sub h by H; 33 | } h; 34 | 35 | lookup i { 36 | sub i by I; 37 | } i; 38 | 39 | languagesystem DFLT dflt; 40 | languagesystem DFLT FRE; 41 | languagesystem DFLT ABC; 42 | languagesystem latn dflt; 43 | languagesystem latn ABC; 44 | 45 | feature smcp { 46 | lookup a; 47 | } smcp; 48 | 49 | feature liga { 50 | lookup b; 51 | script DFLT; 52 | lookup c; 53 | language dflt; 54 | lookup d; 55 | language FRE; 56 | lookup e; 57 | script latn; 58 | lookup f; 59 | language dflt; 60 | lookup g; 61 | language FRE; 62 | lookup h; 63 | language DEF exclude_dflt; 64 | lookup i; 65 | } liga; 66 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug1459.fea: -------------------------------------------------------------------------------- 1 | # A pair position lookup where only the second glyph has a non-empty valuerecord 2 | # while the first glyph has a NULL valuerecord. The ValueFormat1 for the first 3 | # glyph is expected to be 0. 4 | # https://github.com/fonttools/fonttools/issues/1459 5 | feature kern { 6 | pos A V <-180 0 -90 0>; 7 | } kern; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug2276.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/2276 2 | lookup EMPTY { 3 | # pass 4 | } EMPTY; 5 | feature ss01 { 6 | sub a by a.alt1; 7 | lookup EMPTY; 8 | } ss01; 9 | feature aalt { 10 | feature ss01; 11 | } aalt; 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug2949.fea: -------------------------------------------------------------------------------- 1 | lookup lookup1 { 2 | #test-fea2fea: ignore sub three' four; 3 | ignore sub three four; 4 | } lookup1; 5 | 6 | lookup lookup2 { 7 | #test-fea2fea: ignore pos three' four; 8 | ignore pos three four; 9 | } lookup2; 10 | 11 | lookup lookup3 { 12 | #test-fea2fea: ignore sub one' two, three' four; 13 | ignore sub one two, three four; 14 | } lookup3; 15 | 16 | feature test { 17 | lookup lookup1; 18 | lookup lookup2; 19 | lookup lookup3; 20 | } test; 21 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug453.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/453 2 | feature mark { 3 | lookup mark1 { 4 | markClass [acute] @TOP_MARKS; 5 | pos base [e] 6 | mark @TOP_MARKS; 7 | } mark1; 8 | lookup mark2 { 9 | markClass [acute] @TOP_MARKS_2; 10 | pos base [e] 11 | mark @TOP_MARKS_2; 12 | } mark2; 13 | } mark; 14 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug457.fea: -------------------------------------------------------------------------------- 1 | @group = [A \sub \lookup \feature \by \table]; 2 | 3 | feature liga { 4 | sub @group by G; 5 | } liga; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug457.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug463.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/463 2 | feature ordn { 3 | @DIGIT = [zero one two three four five six seven eight nine]; 4 | sub @DIGIT [A a]' by ordfeminine; 5 | sub @DIGIT [O o]' by ordmasculine; 6 | } ordn; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug501.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/501 2 | languagesystem DFLT dflt; 3 | feature test { 4 | lookup L { 5 | script grek; 6 | pos T 100; 7 | } L; 8 | } test; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug501.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug502.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/502 2 | feature aalt { 3 | sub A by A.alt1; 4 | sub Eng by Eng.alt1; 5 | sub Eng by Eng.alt2; 6 | sub Eng by Eng.alt3; 7 | } aalt; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug504.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/504 2 | 3 | feature test { 4 | sub [a b c d] by [T E S T]; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug504.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug505.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/505 2 | 3 | languagesystem armn dflt; 4 | languagesystem avst dflt; 5 | languagesystem bali dflt; 6 | languagesystem bamu dflt; 7 | 8 | feature test { 9 | script linb; 10 | script vai; 11 | sub T by t; 12 | } test; 13 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug505.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug506.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/506 2 | feature test { 3 | sub f' i' by f_i; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug509.fea: -------------------------------------------------------------------------------- 1 | @LETTER_A = [A A.sc A.alt1]; 2 | feature test { 3 | ignore sub A'; 4 | sub @LETTER_A' by a; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug512.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub G' by G.swash; 3 | sub H' by H.swash; 4 | sub G' by g; 5 | sub H' by H.swash; 6 | } test; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug514.fea: -------------------------------------------------------------------------------- 1 | # The many chain targets for this feature should get combined into 2 | # two separate SinglePos lookups: {A:-40, B:-40, C:-40} and {A:-111}. 3 | # https://github.com/fonttools/fonttools/issues/514 4 | # 5 | # makeotf produces {A:-40, B:-40, C:-40} and {A:-111, B:-40} which 6 | # is redundant. https://github.com/adobe-type-tools/afdko/issues/169 7 | feature test { 8 | pos X [A - B]' -40 B' -40 A' -40 Y; 9 | pos X A' -111 Y; 10 | pos X B' -40 A' -111 [A - C]' -40 Y; 11 | } test; 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug568.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/568 2 | 3 | feature tst1 { 4 | script latn; 5 | pos T -20; 6 | } tst1; 7 | 8 | feature tst2 { 9 | script cyrl; 10 | pos T -80; 11 | } tst2; 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/bug633.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/fonttools/fonttools/issues/633 2 | 3 | @public.kern1.K = [K X]; 4 | @public.kern2.O = [C O]; 5 | @public.kern2.V = [V W]; 6 | 7 | feature kern { 8 | pos @public.kern1.K @public.kern2.O -20; 9 | pos @public.kern1.K @public.kern2.V 0; 10 | } kern; 11 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/cid_range.fea: -------------------------------------------------------------------------------- 1 | # A CID range can be valid even if it is invalid as a glyph name range. 2 | # For example, [cid00800 - cid01001] is invalid. 3 | 4 | feature zero { 5 | sub [\800 - \1001] by zero; 6 | } zero; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/delete_glyph.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub a by NULL; 3 | } test; 4 | 5 | feature test { 6 | sub [a b c] by NULL; 7 | } test; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/delete_glyph.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/enum.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | feature kern { 4 | @Y_LC = [y yacute ydieresis]; 5 | @SMALL_PUNC = [comma semicolon period]; 6 | enum pos @Y_LC @SMALL_PUNC -100; 7 | } kern; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/feature_aalt.expected_diff: -------------------------------------------------------------------------------- 1 | # generated automatically by fea-rs 2 | # this file represents an acceptable difference between the output of 3 | # fonttools and the output of fea-rs for a given input. 4 | # 5 | # Note: fonttools orders ligature components by glyph name, but we use glyph id. 6 | # this should have no practical impact on the user. 7 | L93 8 | > 9 | L95 10 | < 11 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/feature_aalt.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | feature aalt { 4 | feature sups; 5 | feature frac; 6 | feature ordn; 7 | } aalt; 8 | 9 | feature sups { 10 | sub one by onesuperior; 11 | sub two by twosuperior; 12 | sub three by threesuperior; 13 | } sups; 14 | 15 | feature frac { 16 | sub one slash four by onequarter; 17 | sub one slash two by onehalf; 18 | sub three slash four by threequarters; 19 | } frac; 20 | 21 | feature ordn { 22 | sub [zero one two three four five six seven eight nine] [A a]' by ordfeminine; 23 | sub [zero one two three four five six seven eight nine] [O o]' by ordmasculine; 24 | } ordn; 25 | 26 | feature liga { 27 | sub f i by f_i; 28 | sub f l by f_l; 29 | } liga; 30 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/ignore_pos.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | ignore pos f [a e] d'; 3 | ignore pos a d' d; 4 | pos [a e n] d' -20; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/include0.fea: -------------------------------------------------------------------------------- 1 | I0 2 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/language_required.fea: -------------------------------------------------------------------------------- 1 | languagesystem latn DEU; 2 | languagesystem latn FRA; 3 | languagesystem latn ITA; 4 | 5 | feature hlig { 6 | script latn; 7 | language DEU exclude_dflt required; 8 | sub D E U by D.sc; 9 | 10 | language FRA exclude_dflt; 11 | sub F R A by F.sc; 12 | } hlig; 13 | 14 | feature liga { 15 | script latn; 16 | language ITA exclude_dflt required; 17 | sub I T A by I.sc; 18 | } liga; 19 | 20 | feature scmp { 21 | sub [a - z] by [A.sc - Z.sc]; 22 | } scmp; 23 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/lookup.fea: -------------------------------------------------------------------------------- 1 | # Three features. In the output, they should all point to the same lookup. 2 | 3 | lookup SomeLookup { 4 | sub f f i by f_f_i; 5 | sub f i by f_i; 6 | } SomeLookup; 7 | 8 | feature tst1 { 9 | lookup SomeLookup; 10 | } tst1; 11 | 12 | feature tst2 { 13 | lookup SomeLookup; 14 | } tst2; 15 | 16 | feature tst3 { 17 | lookup EmbeddedLookup { 18 | sub A by A.sc; 19 | } EmbeddedLookup; 20 | } tst3; 21 | 22 | feature tst4 { 23 | lookup EmbeddedLookup; 24 | } tst4; 25 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/markClass.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | markClass [acute] @TOP_MARKS; 4 | 5 | feature foo { 6 | markClass [grave] @TOP_MARKS; 7 | markClass cedilla @BOTTOM_MARKS; 8 | } foo; 9 | 10 | feature bar { 11 | markClass [dieresis breve] @TOP_MARKS; 12 | } bar; 13 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/markClass.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/mini.fea: -------------------------------------------------------------------------------- 1 | # Example file from OpenType Feature File specification, section 1. 2 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 3 | 4 | # Script and language coverage 5 | languagesystem DFLT dflt; 6 | languagesystem latn dflt; 7 | 8 | # Ligature formation 9 | feature liga { 10 | substitute f i by f_i; 11 | substitute f l by f_l; 12 | } liga; 13 | 14 | # Kerning 15 | feature kern { 16 | position A Y -100; 17 | position a y -80; 18 | position s f' <0 0 10 0> t; 19 | } kern; 20 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/multiple_feature_blocks.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | languagesystem latn dflt; 3 | languagesystem latn TRK; 4 | 5 | feature liga { 6 | lookup liga_fl { 7 | sub f l by f_l; 8 | } liga_fl; 9 | } liga; 10 | 11 | feature liga { 12 | lookup liga_fi { 13 | sub f i by f_i; 14 | } liga_fi; 15 | 16 | script latn; 17 | language TRK exclude_dflt; 18 | } liga; 19 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/name.fea: -------------------------------------------------------------------------------- 1 | table name { 2 | #test-fea2fea: 3 | nameid 1 "Test1"; 4 | #test-fea2fea: 5 | nameid 2 "Test2"; 6 | #test-fea2fea: 7 | nameid 3 "Test3"; 8 | #test-fea2fea: 9 | nameid 4 "Test4"; 10 | #test-fea2fea: 11 | nameid 5 "Test5"; 12 | #test-fea2fea: 13 | nameid 6 "Test6"; 14 | #test-fea2fea: nameid 7 "Test7"; 15 | nameid 7 3 "Test7"; 16 | nameid 8 1 "Test8"; 17 | #test-fea2fea: nameid 9 "Test9"; 18 | nameid 9 3 1 0x0409 "Test9"; 19 | nameid 10 1 "Test10"; 20 | #test-fea2fea: nameid 11 1 "Test11"; 21 | nameid 11 1 0 0 "Test11"; 22 | } name; 23 | 24 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/name.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Test8 7 | 8 | 9 | Test10 10 | 11 | 12 | Test11 13 | 14 | 15 | Test1 16 | 17 | 18 | Test2 19 | 20 | 21 | Test3 22 | 23 | 24 | Test4 25 | 26 | 27 | Test5 28 | 29 | 30 | Test6 31 | 32 | 33 | Test7 34 | 35 | 36 | Test9 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/omitted_GlyphClassDef.fea: -------------------------------------------------------------------------------- 1 | @BASE = [f i]; 2 | @MARKS = [acute grave]; 3 | 4 | table GDEF { 5 | GlyphClassDef @BASE, , @MARKS, ; 6 | } GDEF; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/omitted_GlyphClassDef.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/size.fea: -------------------------------------------------------------------------------- 1 | feature size { 2 | #test-fea2fea: parameters 10.0 0; 3 | parameters 10.0 0 0 0; 4 | } size; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/size.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/size2.fea: -------------------------------------------------------------------------------- 1 | feature size { 2 | parameters 10.0 0; 3 | } size; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/size2.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec10.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 10. 2 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 3 | 4 | anon sbit { 5 | /* sbit table specifications */ 6 | 72 % dpi 7 | sizes { 8 | 10, 12, 14 source { 9 | all "Generic/JGeneric" 10 | } 11 | } 12 | } sbit; 13 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec10.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec4h2.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 4.h, example 2. 2 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 3 | 4 | languagesystem DFLT dflt; 5 | languagesystem latn dflt; 6 | languagesystem latn DEU; 7 | languagesystem cyrl dflt; 8 | languagesystem cyrl SRB; 9 | languagesystem grek dflt; 10 | 11 | feature liga { 12 | # start of default rules that are applied under all language systems. 13 | lookup HAS_I { 14 | sub f f i by f_f_i; 15 | sub f i by f_i; 16 | } HAS_I; 17 | 18 | lookup NO_I { 19 | sub f f l by f_f_l; 20 | sub f f by f_f; 21 | } NO_I; 22 | 23 | # end of default rules that are applied under all language systems. 24 | 25 | script latn; 26 | language dflt; 27 | # default lookup for latn included under all languages for the latn script 28 | sub f l by f_l; 29 | 30 | language DEU; 31 | # default lookups included under the DEU language 32 | sub s s by germandbls; # This is also included. 33 | 34 | language TRK exclude_dflt; # default lookups are excluded. 35 | lookup NO_I; # Only this lookup is included under the TRK language 36 | 37 | script cyrl; 38 | language SRB; 39 | sub c t by c_t; # this rule will apply only under script cyrl language SRB. 40 | } liga; 41 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5d1.expected_diff: -------------------------------------------------------------------------------- 1 | # generated automatically by fea-rs 2 | # this file represents an acceptable difference between the output of 3 | # fonttools and the output of fea-rs for a given input. 4 | # 5 | # Note: fonttools orders ligature components by glyph name, but we use glyph id. 6 | # this should have no practical impact on the user. 7 | L45 8 | > 9 | > 10 | L49 11 | > 12 | > 13 | L53 14 | < 15 | < 16 | L57 17 | < 18 | < 19 | L68 20 | > 21 | > 22 | L72 23 | > 24 | > 25 | L76 26 | < 27 | < 28 | L80 29 | < 30 | < 31 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5d1.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.d, example 1. 2 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 3 | 4 | feature F1 { 5 | sub [one one.oldstyle] [slash fraction] [two two.oldstyle] by onehalf; 6 | } F1; 7 | 8 | # Since the OpenType specification does not allow ligature substitutions 9 | # to be specified on target sequences that contain glyph classes, the 10 | # implementation software will enumerate all specific glyph sequences 11 | # if glyph classes are detected in . Thus, the above 12 | # example produces an identical representation in the font as if all 13 | # the sequences were manually enumerated by the font editor: 14 | feature F2 { 15 | sub one slash two by onehalf; 16 | sub one.oldstyle slash two by onehalf; 17 | sub one fraction two by onehalf; 18 | sub one.oldstyle fraction two by onehalf; 19 | sub one slash two.oldstyle by onehalf; 20 | sub one.oldstyle slash two.oldstyle by onehalf; 21 | sub one fraction two.oldstyle by onehalf; 22 | sub one.oldstyle fraction two.oldstyle by onehalf; 23 | } F2; 24 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5d2.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.d, example 2. 2 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 3 | 4 | # A contiguous set of ligature rules does not need to be ordered in 5 | # any particular way by the font editor; the implementation software 6 | # must do the appropriate sorting. 7 | 8 | # So: 9 | feature F1 { 10 | sub f f by f_f; 11 | sub f i by f_i; 12 | sub f f i by f_f_i; 13 | sub o f f i by o_f_f_i; 14 | } F1; 15 | 16 | # will produce an identical representation in the font as: 17 | feature F2 { 18 | sub o f f i by o_f_f_i; 19 | sub f f i by f_f_i; 20 | sub f f by f_f; 21 | sub f i by f_i; 22 | } F2; 23 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5f_ii_1.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.f.ii, example 1 2 | # "Specifying exceptions to the Chain Sub rule" 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | feature test { 6 | ignore sub f [a e] d'; 7 | ignore sub a d' d; 8 | sub [a e n] d' by d.alt; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5f_ii_2.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.f.ii, example 2 2 | # "Specifying exceptions to the Chain Sub rule" 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | feature test { 6 | @LETTER = [a - z]; 7 | ignore sub @LETTER f' i'; 8 | sub f' i' by f_i.begin; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5f_ii_3.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.f.ii, example 3 2 | # "Specifying exceptions to the Chain Sub rule" 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | feature test { 6 | @LETTER = [a - z]; 7 | ignore sub @LETTER a' n' d', a' n' d' @LETTER; 8 | sub a' n' d' by a_n_d; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5f_ii_4.expected_diff: -------------------------------------------------------------------------------- 1 | # generated automatically by fea-rs 2 | # this file represents an acceptable difference between the output of 3 | # fonttools and the output of fea-rs for a given input. 4 | # 5 | # # Note: we generate two different subtables here, which is a more efficient 6 | # representation than what fonttools does. 7 | L247 8 | > 9 | L247 10 | < 11 | L250 12 | < 13 | < 14 | < 15 | < 16 | < 17 | < 18 | < 19 | L276 20 | > 21 | L283 22 | > 23 | > 24 | > 25 | > 26 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5f_ii_4.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.f.ii, example 4 2 | # "Specifying exceptions to the Chain Sub rule" 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | @LETTER = [A - Z a - z]; 6 | 7 | feature cswh { 8 | 9 | # --- Glyph classes used in this feature: 10 | @BEGINNINGS = [A - N P - Z T_h m]; 11 | @BEGINNINGS_SWASH = [A.swash - N.swash P.swash - Z.swash T_h.swash m.begin]; 12 | @ENDINGS = [a e z]; 13 | @ENDINGS_SWASH = [a.end e.end z.end]; 14 | 15 | # --- Beginning-of-word swashes: 16 | ignore sub @LETTER @BEGINNINGS'; 17 | sub @BEGINNINGS' by @BEGINNINGS_SWASH; 18 | 19 | # --- End-of-word swashes: 20 | ignore sub @ENDINGS' @LETTER; 21 | sub @ENDINGS' by @ENDINGS_SWASH; 22 | 23 | } cswh; 24 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5fi1.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.f.i, example 1 2 | # "Specifying a Chain Sub rule and marking sub-runs" 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | languagesystem latn dflt; 6 | 7 | lookup CNTXT_LIGS { 8 | sub f i by f_i; 9 | sub c t by c_t; 10 | } CNTXT_LIGS; 11 | 12 | lookup CNTXT_SUB { 13 | sub n by n.end; 14 | sub s by s.end; 15 | } CNTXT_SUB; 16 | 17 | feature test { 18 | sub [a e i o u] f' lookup CNTXT_LIGS i' n' lookup CNTXT_SUB; 19 | sub [a e i o u] c' lookup CNTXT_LIGS t' s' lookup CNTXT_SUB; 20 | } test; 21 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5fi2.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.f.i, example 2 2 | # "Specifying a Chain Sub rule and marking sub-runs" 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | languagesystem latn dflt; 6 | 7 | feature test { 8 | #test-fea2fea: lookupflag RightToLeft IgnoreBaseGlyphs IgnoreLigatures; 9 | lookupflag 7; 10 | sub [a e n] d' by d.alt; 11 | } test; 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5fi3.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.f.i, example 3 2 | # "Specifying a Chain Sub rule and marking sub-runs" 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | languagesystem latn dflt; 6 | 7 | feature test { 8 | sub [A - Z] [A.sc - Z.sc]' by [a - z]; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5fi4.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.f.i, example 4 2 | # "Specifying a Chain Sub rule and marking sub-runs" 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | languagesystem latn dflt; 6 | 7 | feature test { 8 | sub [e e.begin]' t' c by ampersand; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec5h1.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 5.h, example 1. 2 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 3 | 4 | languagesystem DFLT dflt; 5 | 6 | feature test { 7 | #test-fea2fea: rsub [a e n] d' by d.alt; 8 | reversesub [a e n] d' by d.alt; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec6b_ii.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 6.b.ii: 2 | # [GPOS LookupType 2] Enumerating pairs 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | @Y_LC = [y yacute ydieresis]; 6 | @SMALL_PUNC = [comma semicolon period]; 7 | 8 | feature kern { 9 | enum pos @Y_LC semicolon -80; # specific pairs 10 | pos f quoteright 30; # specific pair 11 | pos @Y_LC @SMALL_PUNC -100; # class pair 12 | } kern; 13 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec6d2.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 6.d, example 1: 2 | # [GPOS LookupType 4] Mark-to-Base attachment positioning 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | languagesystem DFLT dflt; 6 | 7 | markClass [acute grave] @TOP_MARKS; 8 | markClass [dieresis umlaut] @TOP_MARKS; 9 | markClass [cedilla] @BOTTOM_MARKS; 10 | 11 | feature test { 12 | pos base [e o] 13 | mark @TOP_MARKS 14 | mark @BOTTOM_MARKS; 15 | #test-fea2fea: pos base [a u] 16 | position base [a u] 17 | mark @TOP_MARKS 18 | mark @BOTTOM_MARKS; 19 | } test; 20 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec6e.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | markClass sukun @TOP_MARKS; 4 | markClass kasratan @BOTTOM_MARKS; 5 | 6 | feature test { 7 | pos ligature lam_meem_jeem 8 | mark @TOP_MARKS # mark above lam 9 | ligComponent 10 | mark @BOTTOM_MARKS # mark below meem 11 | ligComponent 12 | ; # jeem has no marks 13 | } test; 14 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec6f.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | feature test { 4 | markClass damma @MARK_CLASS_1; 5 | pos mark hamza 6 | mark @MARK_CLASS_1; 7 | } test; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec6h_ii.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 6.h.ii: 2 | # Specifying Contextual Positioning with explicit lookup references 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | languagesystem DFLT dflt; 6 | 7 | markClass [acute grave] @ALL_MARKS; 8 | 9 | lookup CNTXT_PAIR_POS { 10 | pos T o -10; 11 | pos T c -12; 12 | } CNTXT_PAIR_POS; 13 | 14 | lookup CNTXT_MARK_TO_BASE { 15 | pos base o 16 | mark @ALL_MARKS; 17 | pos base c 18 | mark @ALL_MARKS; 19 | } CNTXT_MARK_TO_BASE; 20 | 21 | feature test { 22 | pos T' lookup CNTXT_PAIR_POS [o c]' @ALL_MARKS' lookup CNTXT_MARK_TO_BASE; 23 | } test; 24 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec6h_iii_1.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 6.h.iii, example 1: 2 | # Specifying Contextual Positioning with in-line single positioning rules 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | languagesystem DFLT dflt; 6 | 7 | feature test { 8 | pos [quoteleft quotedblleft] [Y T]' <0 0 20 0> [quoteright quotedblright]; 9 | } test; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec6h_iii_3d.fea: -------------------------------------------------------------------------------- 1 | # OpenType Feature File specification, section 6.h.iii, example 3d: 2 | # Specifying Contextual Positioning with in-line single positioning rules 3 | # http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html 4 | 5 | feature test { 6 | pos L' quoteright' -150; 7 | } test; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec8a.expected_diff: -------------------------------------------------------------------------------- 1 | # generated automatically by fea-rs 2 | # this file represents an acceptable difference between the output of 3 | # fonttools and the output of fea-rs for a given input. 4 | # 5 | # Note: fonttools currently generates the wrong ordering in aalt. 6 | # see 7 | L101 8 | > 9 | L105 10 | < 11 | L108 12 | > 13 | L110 14 | < 15 | L113 16 | > 17 | L115 18 | < 19 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec8a.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | languagesystem latn dflt; 3 | languagesystem latn TRK; 4 | languagesystem cyrl dflt; 5 | 6 | feature aalt { 7 | feature salt; 8 | feature smcp; 9 | sub d by d.alt; 10 | } aalt; 11 | 12 | feature smcp { 13 | sub [a - c] by [A.sc - C.sc]; 14 | sub f i by f_i; # not considered for aalt 15 | } smcp; 16 | 17 | feature salt { 18 | sub a from [a.alt1 a.alt2 a.alt3]; 19 | sub e [c d e]' f by [c.mid d.mid e.mid]; 20 | sub b by b.alt; 21 | } salt; 22 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec8b.fea: -------------------------------------------------------------------------------- 1 | feature size { 2 | parameters 10.0 3 80 139; 3 | # 10.0 - design size, 3 - subfamily identifier, 80 - range start (exclusive, decipoints) 4 | # 139 - range end (inclusive, decipoints) 5 | sizemenuname "Win MinionPro Size Name"; 6 | sizemenuname 1 "Mac MinionPro Size Name"; 7 | # The specification says: sizemenuname 1 21 0 "Mac MinionPro Size Name"; 8 | # which means Macintosh platform, MacOS Thai encoding, English language. 9 | # Since fonttools currently does not support the MacOS Thai encoding, 10 | # we use instead MacOS Roman encoding (0), Swedish language (5) for our test. 11 | sizemenuname 1 0 5 "Mac MinionPro Size Name"; 12 | } size; 13 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec8c.expected_diff: -------------------------------------------------------------------------------- 1 | # generated automatically by fea-rs 2 | # this file represents an acceptable difference between the output of 3 | # fonttools and the output of fea-rs for a given input. 4 | # 5 | # Note: we do not (yet) support this encoding 6 | L7 7 | > 8 | > Feature description for Apple Platform, script Japanese, language Japanese 9 | > 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec8c.fea: -------------------------------------------------------------------------------- 1 | feature ss01 { 2 | featureNames { 3 | name "Feature description for MS Platform, script Unicode, language English"; 4 | # With no platform ID, script ID, or language ID specified, the implementation assumes (3,1,0x409). 5 | #test-fea2fea: name 3 1 1041 "Feature description for MS Platform, script Unicode, language Japanese"; 6 | name 3 1 0x411 "Feature description for MS Platform, script Unicode, language Japanese"; 7 | name 1 "Feature description for Apple Platform, script Roman, language unspecified"; 8 | # With only the platform ID specified, the implementation assumes script and language = Latin. For Apple this is (1,0,0). 9 | name 1 1 12 "Feature description for Apple Platform, script Japanese, language Japanese"; 10 | }; 11 | # --- rules for this feature --- 12 | sub A by B; 13 | } ss01; 14 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9a.fea: -------------------------------------------------------------------------------- 1 | table BASE { 2 | HorizAxis.BaseTagList ideo romn; 3 | HorizAxis.BaseScriptList latn romn -120 0, cyrl romn -120 0, grek romn -120 0, hani ideo -120 0, kana ideo -120 0, hang ideo -120 0; 4 | } BASE; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9b.fea: -------------------------------------------------------------------------------- 1 | @BASE = [f i]; 2 | @LIGATURES = [c_s c_t f_i f_f_i s_t]; 3 | @MARKS = [acute grave]; 4 | @COMPONENT = [noon.final noon.initial]; 5 | 6 | table GDEF { 7 | GlyphClassDef @BASE, @LIGATURES, @MARKS, @COMPONENT; 8 | Attach noon.final 5; 9 | Attach noon.initial 4; 10 | LigatureCaretByPos f_i 400 380; 11 | LigatureCaretByPos [c_t s_t] 500; 12 | LigatureCaretByIndex f_f_i 23 46; 13 | } GDEF; 14 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9c1.fea: -------------------------------------------------------------------------------- 1 | table head { 2 | #test-fea2fea: FontRevision 1.100; 3 | FontRevision 1.1; 4 | } head; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9c1.ttx: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9c2.fea: -------------------------------------------------------------------------------- 1 | table head { 2 | FontRevision 1.001; 3 | } head; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9c2.ttx: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9c3.fea: -------------------------------------------------------------------------------- 1 | table head { 2 | FontRevision 1.500; 3 | } head; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9c3.ttx: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9d.fea: -------------------------------------------------------------------------------- 1 | table hhea { 2 | CaretOffset -50; 3 | Ascender 800; 4 | Descender 200; 5 | LineGap 200; 6 | } hhea; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9d.ttx: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9e.fea: -------------------------------------------------------------------------------- 1 | table name { 2 | nameid 9 "Joachim M\00fcller-Lanc\00e9"; # Windows (Unicode) 3 | nameid 9 1 "Joachim M\9fller-Lanc\8e"; # Macintosh (Mac Roman) 4 | } name; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9e.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Joachim Müller-Lancé 7 | 8 | 9 | Joachim Müller-Lancé 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9f.expected_diff: -------------------------------------------------------------------------------- 1 | # generated automatically by fea-rs 2 | # this file represents an acceptable difference between the output of 3 | # fonttools and the output of fea-rs for a given input. 4 | # 5 | # Note: write-fonts always prefers format 4, which is identical to 2 but with 6 | # updated names 7 | L6 8 | > 9 | L6 10 | < 11 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9f.fea: -------------------------------------------------------------------------------- 1 | table OS/2 { 2 | FSType 4; 3 | Panose 2 15 0 0 2 2 8 2 9 4; 4 | TypoAscender 800; 5 | TypoDescender -200; # Note that TypoDescender is negative for descent below the baseline. 6 | winAscent 832; 7 | winDescent 321; # Note that winDescent is positive for descent below the baseline. 8 | UnicodeRange 0 1 9 55 59 60; 9 | # 0 - Basic Latin, 1 - Latin-1 Supplement 10 | # 9 - Cyrillic, 55 - CJK Compatibility 11 | # 59 - CJK Unified Ideographs, 60 - Private Use Area 12 | CodePageRange 1252 1251 932; 13 | # 1252 - Latin 1, 1251 - Cyrllic, 932 - JIS/Japan 14 | XHeight 400; 15 | CapHeight 600; 16 | WeightClass 800; 17 | WidthClass 3; 18 | Vendor "ADBE"; 19 | } OS/2; 20 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9g.fea: -------------------------------------------------------------------------------- 1 | table vhea { 2 | VertTypoAscender 500; 3 | VertTypoDescender -500; 4 | VertTypoLineGap 1000; 5 | } vhea; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/spec9g.ttx: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/test.fea: -------------------------------------------------------------------------------- 1 | # Nothing 2 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/variable_bug2772.fea: -------------------------------------------------------------------------------- 1 | feature kern { 2 | pos [p] g -5; 3 | pos [p] y (wght=1000:-100 wght=200:0); 4 | } kern; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/variable_conditionset.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | lookup symbols_heavy { 4 | sub a by b; 5 | } symbols_heavy; 6 | 7 | conditionset heavy { 8 | wght 700 900; 9 | } heavy; 10 | 11 | variation rvrn heavy { 12 | lookup symbols_heavy; 13 | } rvrn; 14 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/variable_scalar_anchor.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | feature kern { 3 | pos cursive one ; 4 | } kern; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/fonttools-tests/variable_scalar_valuerecord.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | feature kern { 3 | pos one 1; 4 | pos two <0 (wght=200:12 wght=900:22 wdth=150,wght=900:42) 0 0>; 5 | } kern; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/include-resolution-tests/_included1.fea: -------------------------------------------------------------------------------- 1 | # this file is included from test1.fea, 2 | # but this include is relative to *this* file, not the parent. 3 | include(_included2.fea); 4 | # but this is relative to the parent 5 | include(_included3.fea); 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/include-resolution-tests/_included2.fea: -------------------------------------------------------------------------------- 1 | @items = [a b]; # defined here, used in _included3 2 | -------------------------------------------------------------------------------- /fea-rs/test-data/include-resolution-tests/dir1/_included3.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | sub @items by [c d]; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/include-resolution-tests/dir1/test1.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 276) 2 | #@0 "# this just includes another file" 3 | WS@33 "\n" 4 | #@34 "# this file is included from test1.fea," 5 | WS@73 "\n" 6 | #@74 "# but this include is relative to *this* file, not the parent." 7 | WS@136 "\n" 8 | GlyphClassDefNode@[137; 152) 9 | @GlyphClass@137 "@items" 10 | WS@143 " " 11 | =@144 "=" 12 | WS@145 " " 13 | GlyphClass@[146; 151) 14 | [@146 "[" 15 | GlyphName@147 "a" 16 | WS@148 " " 17 | GlyphName@149 "b" 18 | ]@150 "]" 19 | ;@151 ";" 20 | WS@152 " " 21 | #@153 "# defined here, used in _included3" 22 | WS@187 "\n" 23 | WS@188 "\n" 24 | #@189 "# but this is relative to the parent" 25 | WS@225 "\n" 26 | FeatureNode@[226; 273) 27 | FeatureKw@226 "feature" 28 | WS@233 " " 29 | Tag@234 "test" 30 | WS@238 " " 31 | {@239 "{" 32 | WS@240 "\n " 33 | GsubType1@[245; 265) 34 | SubKw@245 "sub" 35 | WS@248 " " 36 | @GlyphClass@249 "@items" 37 | WS@255 " " 38 | ByKw@256 "by" 39 | WS@258 " " 40 | GlyphClass@[259; 264) 41 | [@259 "[" 42 | GlyphName@260 "c" 43 | WS@261 " " 44 | GlyphName@262 "d" 45 | ]@263 "]" 46 | ;@264 ";" 47 | WS@265 "\n" 48 | }@266 "}" 49 | WS@267 " " 50 | Tag@268 "test" 51 | ;@272 ";" 52 | WS@273 "\n" 53 | WS@274 "\n" 54 | WS@275 "\n" 55 | -------------------------------------------------------------------------------- /fea-rs/test-data/include-resolution-tests/dir1/test1.fea: -------------------------------------------------------------------------------- 1 | # this just includes another file 2 | include(../_included1.fea); 3 | -------------------------------------------------------------------------------- /fea-rs/test-data/include-resolution-tests/dir1/test1.ttx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/README.md: -------------------------------------------------------------------------------- 1 | # parse tests 2 | 3 | The tests in this folder are intended to test the output of the parsing stage, 4 | before validation and compilation. 5 | 6 | Each `.fea` file in the `./good` has a cooresponding `.PARSE_TREE` file that 7 | represents the expected parse tree produced for this input. 8 | 9 | In the `./bad` folder, each `.fea` file has a corresponding `.ERR` file that 10 | represents the expected error output of the compiler. 11 | 12 | During testing, we check that the output of each `.fea` file matches the 13 | expected result. 14 | 15 | 16 | ## developement 17 | 18 | Pass `FEA_WRITE_TEST_OUTPUT=1` as an environment argument when running tests in 19 | order to write the generated output the the expected location. You can then 20 | manually verify that this is correct before commiting the changes. 21 | 22 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/bad_tag_keyword.ERR: -------------------------------------------------------------------------------- 1 | error: expected tag, found EnumKw 2 | in ./test-data/parse-tests/bad/bad_tag_keyword.fea at 1:8 3 | | 4 | 1 | feature enum { 5 | | ^^^^ 6 | 7 | error: expected tag, found EnumKw 8 | in ./test-data/parse-tests/bad/bad_tag_keyword.fea at 4:2 9 | | 10 | 4 | } enum; 11 | | ^^^^ 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/bad_tag_keyword.fea: -------------------------------------------------------------------------------- 1 | feature enum { 2 | #test-fea2fea: parameters 10.0 0; 3 | parameters 10.0 0 0 0; 4 | } enum; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/bad_tag_num.ERR: -------------------------------------------------------------------------------- 1 | error: expected tag, found NUM 2 | in ./test-data/parse-tests/bad/bad_tag_num.fea at 1:8 3 | | 4 | 1 | feature 1pos { 5 | | ^ 6 | 7 | error: Expected {, found PosKw 8 | in ./test-data/parse-tests/bad/bad_tag_num.fea at 1:9 9 | | 10 | 1 | feature 1pos { 11 | | ^^^ 12 | 13 | error: Expected glyph or glyph class 14 | in ./test-data/parse-tests/bad/bad_tag_num.fea at 1:13 15 | | 16 | 1 | feature 1pos { 17 | | ^ 18 | 19 | error: expected tag, found NUM 20 | in ./test-data/parse-tests/bad/bad_tag_num.fea at 3:2 21 | | 22 | 3 | } 1pos; 23 | | ^ 24 | 25 | error: Expected ';' 26 | in ./test-data/parse-tests/bad/bad_tag_num.fea at 3:3 27 | | 28 | 3 | } 1pos; 29 | | ^ 30 | 31 | error: Unexpected token 'pos', expected global keyword. 32 | in ./test-data/parse-tests/bad/bad_tag_num.fea at 3:3 33 | | 34 | 3 | } 1pos; 35 | | ^^^ 36 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/bad_tag_num.fea: -------------------------------------------------------------------------------- 1 | feature 1pos { 2 | pos A B 20; 3 | } 1pos; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/contextual_from.ERR: -------------------------------------------------------------------------------- 1 | error: alternate substition rules cannot be specified inline 2 | in ./test-data/parse-tests/bad/contextual_from.fea at 3:15 3 | | 4 | 3 | sub a b' c from [d e]; 5 | | ^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/contextual_from.fea: -------------------------------------------------------------------------------- 1 | feature nono { 2 | # 'from' is not supported in contextual rules 3 | sub a b' c from [d e]; 4 | } nono; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/contextual_inline_pairpos.ERR: -------------------------------------------------------------------------------- 1 | error: trailing value record only valid if there is a single marked glyph, no inline lookups, and at least one lookahead glyph. 2 | in ./test-data/parse-tests/bad/contextual_inline_pairpos.fea at 7:25 3 | | 4 | 7 | pos a b' lookup hi c 20; 5 | | ^^ 6 | 7 | error: trailing value record only valid if there is a single marked glyph, no inline lookups, and at least one lookahead glyph. 8 | in ./test-data/parse-tests/bad/contextual_inline_pairpos.fea at 9:18 9 | | 10 | 9 | pos a b' c' d <10 5 0 0>; 11 | | ^^^^^^^^^^ 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/contextual_inline_pairpos.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | pos b 5; 3 | } hi; 4 | 5 | feature kern { 6 | # can't have inline pairpos with other lookup 7 | pos a b' lookup hi c 20; 8 | # can't have inline pairpos with two marked glyphs 9 | pos a b' c' d <10 5 0 0>; 10 | 11 | } kern; 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/include_missing_file.ERR: -------------------------------------------------------------------------------- 1 | error: Failed to load source at 'i_am_quite_unlikely_to_exist.fea': 'No such file or directory (os error 2)' 2 | in ./test-data/parse-tests/bad/include_missing_file.fea at 7:8 3 | | 4 | 7 | include(i_am_quite_unlikely_to_exist.fea); 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/include_missing_file.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | feature hilo { 4 | pos a b 69; 5 | } hilo; 6 | 7 | include(i_am_quite_unlikely_to_exist.fea); 8 | 9 | feature tata { 10 | pos a b 0; 11 | } tata; 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/rsub_input_len.ERR: -------------------------------------------------------------------------------- 1 | error: Expected ';' 2 | in ./test-data/parse-tests/bad/rsub_input_len.fea at 3:18 3 | | 4 | 3 | rsub a b' by c d; 5 | | ^ 6 | 7 | error: 'd' Not valid in a feature block 8 | in ./test-data/parse-tests/bad/rsub_input_len.fea at 3:19 9 | | 10 | 3 | rsub a b' by c d; 11 | | ^ 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/rsub_input_len.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | # only a single item after 'by' 3 | rsub a b' by c d; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/rsub_multi.ERR: -------------------------------------------------------------------------------- 1 | error: reversesub rule can have only one marked glyph 2 | in ./test-data/parse-tests/bad/rsub_multi.fea at 3:15 3 | | 4 | 3 | rsub a b' d' f by g; 5 | | ^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/rsub_multi.fea: -------------------------------------------------------------------------------- 1 | # rsub rules can only have a single marked glyph 2 | feature test { 3 | rsub a b' d' f by g; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/rsub_null.ERR: -------------------------------------------------------------------------------- 1 | error: Although explicitly part of the FEA spec, 'by NULL' in rsub rules is meaningless. 2 | See https://github.com/fonttools/fonttools/issues/2952 for more information 3 | in ./test-data/parse-tests/bad/rsub_null.fea at 4:19 4 | | 5 | 4 | rsub a b' c by NULL; 6 | | ^^^^ 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/rsub_null.fea: -------------------------------------------------------------------------------- 1 | # the spec says this is cool but there's no way to make it work? 2 | # https://github.com/fonttools/fonttools/issues/2952 3 | feature test { 4 | rsub a b' c by NULL; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/suffix_metrics.ERR: -------------------------------------------------------------------------------- 1 | error: Expected : found ID 2 | in ./test-data/parse-tests/bad/suffix_metrics.fea at 2:20 3 | | 4 | 2 | pos p (wght=1000f:-100 wght=200D:0); 5 | | ^^^^^^ 6 | 7 | error: Expected : found ID 8 | in ./test-data/parse-tests/bad/suffix_metrics.fea at 2:35 9 | | 10 | 2 | pos p (wght=1000f:-100 wght=200D:0); 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/suffix_metrics.fea: -------------------------------------------------------------------------------- 1 | feature kern { 2 | pos p (wght=1000f:-100 wght=200D:0); 3 | } kern; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/tag_mismatch.ERR: -------------------------------------------------------------------------------- 1 | error: expected tag 'size' 2 | in ./test-data/parse-tests/bad/tag_mismatch.fea at 3:2 3 | | 4 | 3 | } Size; 5 | | ^^^^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/tag_mismatch.fea: -------------------------------------------------------------------------------- 1 | feature size { 2 | pos A B 20; 3 | } Size; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/value_record_def_outside_top_level.ERR: -------------------------------------------------------------------------------- 1 | error: 'valueRecordDef' Not valid in a feature block 2 | in ./test-data/parse-tests/bad/value_record_def_outside_top_level.fea at 5:4 3 | | 4 | 5 | valueRecordDef 123 BAD; 5 | | ^^^^^^^^^^^^^^ 6 | 7 | error: 'valueRecordDef' Not valid in a lookup block 8 | in ./test-data/parse-tests/bad/value_record_def_outside_top_level.fea at 9:4 9 | | 10 | 9 | valueRecordDef <4 3 2 1> ALSO_BAD; 11 | | ^^^^^^^^^^^^^^ 12 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/value_record_def_outside_top_level.fea: -------------------------------------------------------------------------------- 1 | # fonttools accepts both of these but they're disallowed by the spec, 2 | # and given that they do not seem to actually be used anywhere I would 3 | # prefer to skip handling them as well. 4 | feature test { 5 | valueRecordDef 123 BAD; 6 | } test; 7 | 8 | lookup shmookup { 9 | valueRecordDef <4 3 2 1> ALSO_BAD; 10 | } shmookup; 11 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/variation_missing_condset.ERR: -------------------------------------------------------------------------------- 1 | error: expected label or NULL 2 | in ./test-data/parse-tests/bad/variation_missing_condset.fea at 1:15 3 | | 4 | 1 | variation oops { 5 | | ^ 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/bad/variation_missing_condset.fea: -------------------------------------------------------------------------------- 1 | variation oops { 2 | lookup thing; 3 | } oops; 4 | 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_1.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 56) 2 | FeatureNode@[0; 55) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "test" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType1@[19; 47) 10 | PosKw@19 "position" 11 | WS@27 " " 12 | GlyphName@28 "one" 13 | WS@31 " " 14 | ValueRecordNode@[32; 46) 15 | <@32 "<" 16 | NUM@33 "-80" 17 | WS@36 " " 18 | NUM@37 "0" 19 | WS@38 " " 20 | NUM@39 "-160" 21 | WS@43 " " 22 | NUM@44 "0" 23 | >@45 ">" 24 | ;@46 ";" 25 | WS@47 "\n" 26 | }@48 "}" 27 | WS@49 " " 28 | Tag@50 "test" 29 | ;@54 ";" 30 | WS@55 "\n" 31 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_1.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | position one <-80 0 -160 0>; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_2a.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 41) 2 | FeatureNode@[0; 40) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "test" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType2@[19; 32) 10 | PosKw@19 "pos" 11 | WS@22 " " 12 | GlyphName@23 "T" 13 | WS@24 " " 14 | GlyphName@25 "a" 15 | WS@26 " " 16 | ValueRecordNode@[27; 31) 17 | NUM@27 "-100" 18 | ;@31 ";" 19 | WS@32 "\n" 20 | }@33 "}" 21 | WS@34 " " 22 | Tag@35 "test" 23 | ;@39 ";" 24 | WS@40 "\n" 25 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_2a.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos T a -100; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_2b.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 43) 2 | FeatureNode@[0; 42) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "test" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType2@[19; 34) 10 | PosKw@19 "pos" 11 | WS@22 " " 12 | GlyphClass@[23; 26) 13 | [@23 "[" 14 | GlyphName@24 "T" 15 | ]@25 "]" 16 | WS@26 " " 17 | GlyphName@27 "a" 18 | WS@28 " " 19 | ValueRecordNode@[29; 33) 20 | NUM@29 "-100" 21 | ;@33 ";" 22 | WS@34 "\n" 23 | }@35 "}" 24 | WS@36 " " 25 | Tag@37 "test" 26 | ;@41 ";" 27 | WS@42 "\n" 28 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_2b.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos [T] a -100; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_2c.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 44) 2 | FeatureNode@[0; 43) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "test" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType2@[19; 35) 10 | PosKw@19 "pos" 11 | WS@22 " " 12 | GlyphClass@[23; 26) 13 | [@23 "[" 14 | GlyphName@24 "T" 15 | ]@25 "]" 16 | WS@26 " " 17 | @GlyphClass@27 "@a" 18 | WS@29 " " 19 | ValueRecordNode@[30; 34) 20 | NUM@30 "-100" 21 | ;@34 ";" 22 | WS@35 "\n" 23 | }@36 "}" 24 | WS@37 " " 25 | Tag@38 "test" 26 | ;@42 ";" 27 | WS@43 "\n" 28 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_2c.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos [T] @a -100; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_2d.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 48) 2 | FeatureNode@[0; 47) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "test" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType2@[19; 39) 10 | PosKw@19 "pos" 11 | WS@22 " " 12 | @GlyphClass@23 "@T" 13 | WS@25 " " 14 | GlyphClass@[26; 33) 15 | [@26 "[" 16 | GlyphName@27 "a" 17 | WS@28 " " 18 | GlyphName@29 "o" 19 | WS@30 " " 20 | GlyphName@31 "u" 21 | ]@32 "]" 22 | WS@33 " " 23 | ValueRecordNode@[34; 38) 24 | NUM@34 "-100" 25 | ;@38 ";" 26 | WS@39 "\n" 27 | }@40 "}" 28 | WS@41 " " 29 | Tag@42 "test" 30 | ;@46 ";" 31 | WS@47 "\n" 32 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_2d.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos @T [a o u] -100; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_5.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | position ligature lam_meem_jeem 3 | mark @TOP_MARKS # mark above lam 4 | ligComponent # start specifying marks for meem 5 | mark @BOTTOM_MARKS 6 | ligComponent 7 | ; 8 | } test; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_8a.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 80) 2 | FeatureNode@[0; 79) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "test" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType8@[19; 71) 10 | PosKw@19 "pos" 11 | WS@22 " " 12 | BacktrackSequence@[23; 23) 13 | ContextSequence@[23; 70) 14 | ContextGlyphNode@[23; 41) 15 | GlyphName@23 "T" 16 | '@24 "'" 17 | WS@25 " " 18 | LookupRefNode@[26; 40) 19 | LookupKw@26 "lookup" 20 | WS@32 " " 21 | ID@33 "LOOKUP1" 22 | WS@40 " " 23 | ContextGlyphNode@[41; 48) 24 | GlyphClass@[41; 46) 25 | [@41 "[" 26 | GlyphName@42 "o" 27 | WS@43 " " 28 | GlyphName@44 "c" 29 | ]@45 "]" 30 | '@46 "'" 31 | WS@47 " " 32 | ContextGlyphNode@[48; 70) 33 | @GlyphClass@48 "@MARKS" 34 | '@54 "'" 35 | WS@55 " " 36 | LookupRefNode@[56; 70) 37 | LookupKw@56 "lookup" 38 | WS@62 " " 39 | ID@63 "LOOKUP2" 40 | LookaheadSequence@[70; 70) 41 | ;@70 ";" 42 | WS@71 "\n" 43 | }@72 "}" 44 | WS@73 " " 45 | Tag@74 "test" 46 | ;@78 ";" 47 | WS@79 "\n" 48 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_8a.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos T' lookup LOOKUP1 [o c]' @MARKS' lookup LOOKUP2; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_8b.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos [a b] [Y T]' <0 0 20 0 > [c d]; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GPOS_8c.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos s f' 10 t; 3 | pos s f' 10 t' -5 period; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_1a.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 37) 2 | LookupBlockNode@[0; 36) 3 | LookupKw@0 "lookup" 4 | WS@6 " " 5 | LABEL@7 "hi" 6 | WS@9 " " 7 | {@10 "{" 8 | WS@11 "\n " 9 | GsubType1@[16; 30) 10 | SubKw@16 "sub" 11 | WS@19 " " 12 | GlyphName@20 "a" 13 | WS@21 " " 14 | ByKw@22 "by" 15 | WS@24 " " 16 | GlyphName@25 "A.sc" 17 | ;@29 ";" 18 | WS@30 "\n" 19 | }@31 "}" 20 | WS@32 " " 21 | LABEL@33 "hi" 22 | ;@35 ";" 23 | WS@36 "\n" 24 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_1a.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | sub a by A.sc; 3 | } hi; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_1b.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 85) 2 | LookupBlockNode@[0; 83) 3 | LookupKw@0 "lookup" 4 | WS@6 " " 5 | LABEL@7 "hi" 6 | WS@9 " " 7 | {@10 "{" 8 | WS@11 "\n " 9 | GsubType1@[16; 77) 10 | SubKw@16 "substitute" 11 | WS@26 " " 12 | GlyphClass@[27; 69) 13 | [@27 "[" 14 | GlyphName@28 "one.fitted" 15 | WS@38 " " 16 | GlyphName@39 "one.oldstyle" 17 | WS@51 " " 18 | GlyphName@52 "one.tab.oldstyle" 19 | ]@68 "]" 20 | WS@69 " " 21 | ByKw@70 "by" 22 | WS@72 " " 23 | GlyphName@73 "one" 24 | ;@76 ";" 25 | WS@77 "\n" 26 | }@78 "}" 27 | WS@79 " " 28 | LABEL@80 "hi" 29 | ;@82 ";" 30 | WS@83 "\n\n" 31 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_1b.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | substitute [one.fitted one.oldstyle one.tab.oldstyle] by one; 3 | } hi; 4 | 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_1c.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 59) 2 | LookupBlockNode@[0; 58) 3 | LookupKw@0 "lookup" 4 | WS@6 " " 5 | LABEL@7 "hi" 6 | WS@9 " " 7 | {@10 "{" 8 | WS@11 "\n " 9 | GsubType1@[16; 52) 10 | SubKw@16 "substitute" 11 | WS@26 " " 12 | GlyphClass@[27; 34) 13 | [@27 "[" 14 | GlyphRange@[28; 33) 15 | GlyphName@28 "a" 16 | WS@29 " " 17 | -@30 "-" 18 | WS@31 " " 19 | GlyphName@32 "z" 20 | ]@33 "]" 21 | WS@34 " " 22 | ByKw@35 "by" 23 | WS@37 " " 24 | GlyphClass@[38; 51) 25 | [@38 "[" 26 | GlyphRange@[39; 50) 27 | GlyphName@39 "A.sc" 28 | WS@43 " " 29 | -@44 "-" 30 | WS@45 " " 31 | GlyphName@46 "Z.sc" 32 | ]@50 "]" 33 | ;@51 ";" 34 | WS@52 "\n" 35 | }@53 "}" 36 | WS@54 " " 37 | LABEL@55 "hi" 38 | ;@57 ";" 39 | WS@58 "\n" 40 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_1c.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | substitute [a - z] by [A.sc - Z.sc]; 3 | } hi; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_1d.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 84) 2 | LookupBlockNode@[0; 83) 3 | LookupKw@0 "lookup" 4 | WS@6 " " 5 | LABEL@7 "hi" 6 | WS@9 " " 7 | {@10 "{" 8 | WS@11 "\n " 9 | GsubType1@[16; 77) 10 | SubKw@16 "substitute" 11 | WS@26 " " 12 | GlyphClass@[27; 69) 13 | [@27 "[" 14 | GlyphName@28 "one.fitted" 15 | WS@38 " " 16 | GlyphName@39 "one.oldstyle" 17 | WS@51 " " 18 | GlyphName@52 "one.tab.oldstyle" 19 | ]@68 "]" 20 | WS@69 " " 21 | ByKw@70 "by" 22 | WS@72 " " 23 | GlyphName@73 "one" 24 | ;@76 ";" 25 | WS@77 "\n" 26 | }@78 "}" 27 | WS@79 " " 28 | LABEL@80 "hi" 29 | ;@82 ";" 30 | WS@83 "\n" 31 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_1d.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | substitute [one.fitted one.oldstyle one.tab.oldstyle] by one; 3 | } hi; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_2.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 50) 2 | LookupBlockNode@[0; 48) 3 | LookupKw@0 "lookup" 4 | WS@6 " " 5 | LABEL@7 "hi" 6 | WS@9 " " 7 | {@10 "{" 8 | WS@11 "\n " 9 | GsubType2@[16; 42) 10 | SubKw@16 "substitute" 11 | WS@26 " " 12 | GlyphName@27 "f_f_i" 13 | WS@32 " " 14 | ByKw@33 "by" 15 | WS@35 " " 16 | GlyphName@36 "f" 17 | WS@37 " " 18 | GlyphName@38 "f" 19 | WS@39 " " 20 | GlyphName@40 "i" 21 | ;@41 ";" 22 | WS@42 "\n" 23 | }@43 "}" 24 | WS@44 " " 25 | LABEL@45 "hi" 26 | ;@47 ";" 27 | WS@48 "\n\n" 28 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_2.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | substitute f_f_i by f f i; 3 | } hi; 4 | 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_3.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 87) 2 | LookupBlockNode@[0; 86) 3 | LookupKw@0 "lookup" 4 | WS@6 " " 5 | LABEL@7 "hi" 6 | WS@9 " " 7 | {@10 "{" 8 | WS@11 "\n " 9 | GsubType3@[16; 80) 10 | SubKw@16 "substitute" 11 | WS@26 " " 12 | GlyphName@27 "ampersand" 13 | WS@36 " " 14 | FromKw@37 "from" 15 | WS@41 " " 16 | GlyphClass@[42; 79) 17 | [@42 "[" 18 | GlyphName@43 "ampersand.1" 19 | WS@54 " " 20 | GlyphName@55 "ampersand.2" 21 | WS@66 " " 22 | GlyphName@67 "ampersand.3" 23 | ]@78 "]" 24 | ;@79 ";" 25 | WS@80 "\n" 26 | }@81 "}" 27 | WS@82 " " 28 | LABEL@83 "hi" 29 | ;@85 ";" 30 | WS@86 "\n" 31 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_3.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | substitute ampersand from [ampersand.1 ampersand.2 ampersand.3]; 3 | } hi; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_4.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 100) 2 | LookupBlockNode@[0; 99) 3 | LookupKw@0 "lookup" 4 | WS@6 " " 5 | LABEL@7 "hi" 6 | WS@9 " " 7 | {@10 "{" 8 | WS@11 "\n " 9 | GsubType4@[16; 93) 10 | SubKw@16 "substitute" 11 | WS@26 " " 12 | GlyphClass@[27; 45) 13 | [@27 "[" 14 | GlyphName@28 "one" 15 | WS@31 " " 16 | GlyphName@32 "one.oldstyle" 17 | ]@44 "]" 18 | WS@45 " " 19 | GlyphClass@[46; 62) 20 | [@46 "[" 21 | GlyphName@47 "slash" 22 | WS@52 " " 23 | GlyphName@53 "fraction" 24 | ]@61 "]" 25 | WS@62 " " 26 | GlyphClass@[63; 81) 27 | [@63 "[" 28 | GlyphName@64 "two" 29 | WS@67 " " 30 | GlyphName@68 "two.oldstyle" 31 | ]@80 "]" 32 | WS@81 " " 33 | ByKw@82 "by" 34 | WS@84 " " 35 | GlyphName@85 "onehalf" 36 | ;@92 ";" 37 | WS@93 "\n" 38 | }@94 "}" 39 | WS@95 " " 40 | LABEL@96 "hi" 41 | ;@98 ";" 42 | WS@99 "\n" 43 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_4.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | substitute [one one.oldstyle] [slash fraction] [two two.oldstyle] by onehalf; 3 | } hi; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/GSUB_6.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | substitute [ a e i o u] f' lookup CNTXT_LIGS i' n' lookup CNTXT_SUB; 3 | } hi; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/anchor_formats.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 117) 2 | FeatureNode@[0; 116) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "test" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType4@[19; 108) 10 | PosKw@19 "pos" 11 | WS@22 " " 12 | BaseKw@23 "base" 13 | WS@27 " " 14 | GlyphName@28 "a" 15 | WS@29 " " 16 | AnchorMarkNode@[30; 54) 17 | AnchorNode@[30; 46) 18 | <@30 "<" 19 | AnchorKw@31 "anchor" 20 | WS@37 " " 21 | NUM@38 "120" 22 | WS@41 " " 23 | NUM@42 "-30" 24 | >@45 ">" 25 | WS@46 " " 26 | MarkKw@47 "mark" 27 | WS@51 " " 28 | @GlyphClass@52 "@T" 29 | WS@54 "\n " 30 | AnchorMarkNode@[70; 107) 31 | AnchorNode@[70; 99) 32 | <@70 "<" 33 | AnchorKw@71 "anchor" 34 | WS@77 " " 35 | NUM@78 "5" 36 | WS@79 " " 37 | NUM@80 "-5" 38 | WS@82 " " 39 | ContourpointKw@83 "contourpoint" 40 | WS@95 " " 41 | NUM@96 "14" 42 | >@98 ">" 43 | WS@99 " " 44 | MarkKw@100 "mark" 45 | WS@104 " " 46 | @GlyphClass@105 "@B" 47 | ;@107 ";" 48 | WS@108 "\n" 49 | }@109 "}" 50 | WS@110 " " 51 | Tag@111 "test" 52 | ;@115 ";" 53 | WS@116 "\n" 54 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/anchor_formats.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos base a mark @T 3 | mark @B; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/contextual_gsub2.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 59) 2 | LookupBlockNode@[0; 58) 3 | LookupKw@0 "lookup" 4 | WS@6 " " 5 | LABEL@7 "hi" 6 | WS@9 " " 7 | {@10 "{" 8 | WS@11 "\n " 9 | GsubType6@[16; 52) 10 | SubKw@16 "substitute" 11 | WS@26 " " 12 | BacktrackSequence@[27; 39) 13 | GlyphClass@[27; 39) 14 | [@27 "[" 15 | WS@28 " " 16 | GlyphName@29 "a" 17 | WS@30 " " 18 | GlyphName@31 "e" 19 | WS@32 " " 20 | GlyphName@33 "i" 21 | WS@34 " " 22 | GlyphName@35 "o" 23 | WS@36 " " 24 | GlyphName@37 "u" 25 | ]@38 "]" 26 | WS@39 " " 27 | ContextSequence@[40; 45) 28 | ContextGlyphNode@[40; 45) 29 | GlyphName@40 "f_f" 30 | '@43 "'" 31 | WS@44 " " 32 | LookaheadSequence@[45; 45) 33 | InlineSubNode@[45; 51) 34 | ByKw@45 "by" 35 | WS@47 " " 36 | GlyphName@48 "f" 37 | WS@49 " " 38 | GlyphName@50 "f" 39 | ;@51 ";" 40 | WS@52 "\n" 41 | }@53 "}" 42 | WS@54 " " 43 | LABEL@55 "hi" 44 | ;@57 ";" 45 | WS@58 "\n" 46 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/contextual_gsub2.fea: -------------------------------------------------------------------------------- 1 | lookup hi { 2 | substitute [ a e i o u] f_f' by f f; 3 | } hi; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/escape_nonkeyword.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 71) 2 | LookupBlockNode@[0; 69) 3 | LookupKw@0 "lookup" 4 | WS@6 " " 5 | LABEL@7 "hkern" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GlyphClassDefNode@[19; 38) 10 | @GlyphClass@19 "@group" 11 | WS@25 " " 12 | =@26 "=" 13 | WS@27 " " 14 | GlyphClass@[28; 37) 15 | [@28 "[" 16 | \@29 "\\" 17 | GlyphName@30 "pos" 18 | WS@33 " " 19 | \@34 "\\" 20 | CID@35 "5" 21 | ]@36 "]" 22 | ;@37 ";" 23 | WS@38 "\n " 24 | GposType2@[43; 60) 25 | PosKw@43 "pos" 26 | WS@46 " " 27 | \@47 "\\" 28 | GlyphName@48 "sub" 29 | WS@51 " " 30 | \@52 "\\" 31 | GlyphName@53 "four" 32 | WS@57 " " 33 | ValueRecordNode@[58; 59) 34 | NUM@58 "1" 35 | ;@59 ";" 36 | WS@60 "\n" 37 | }@61 "}" 38 | WS@62 " " 39 | LABEL@63 "hkern" 40 | ;@68 ";" 41 | WS@69 "\n\n" 42 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/escape_nonkeyword.fea: -------------------------------------------------------------------------------- 1 | lookup hkern { 2 | @group = [\pos \5]; 3 | pos \sub \four 1; 4 | } hkern; 5 | 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/glyph_name_formats.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 31) 2 | GlyphClassDefNode@[0; 30) 3 | @GlyphClass@0 "@name" 4 | WS@5 " " 5 | =@6 "=" 6 | WS@7 " " 7 | GlyphClass@[8; 29) 8 | [@8 "[" 9 | GlyphName@9 "a" 10 | WS@10 " " 11 | GlyphName@11 "b" 12 | WS@12 " " 13 | GlyphRange@[13; 18) 14 | GlyphName@13 "d" 15 | WS@14 " " 16 | -@15 "-" 17 | WS@16 " " 18 | GlyphName@17 "z" 19 | WS@18 " " 20 | \@19 "\\" 21 | GlyphRange@[20; 24) 22 | CID@20 "1" 23 | -@21 "-" 24 | \@22 "\\" 25 | CID@23 "5" 26 | WS@24 " " 27 | @GlyphClass@25 "@hi" 28 | ]@28 "]" 29 | ;@29 ";" 30 | WS@30 "\n" 31 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/glyph_name_formats.fea: -------------------------------------------------------------------------------- 1 | @name = [a b d - z \1-\5 @hi]; 2 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/glyph_name_tricks.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 93) 2 | #@0 "# normal name, an escaped glyph name, and a contextual keyword" 3 | WS@62 "\n" 4 | GlyphClassDefNode@[63; 92) 5 | @GlyphClass@63 "@tricks" 6 | WS@70 " " 7 | =@71 "=" 8 | WS@72 " " 9 | GlyphClass@[73; 91) 10 | [@73 "[" 11 | GlyphName@74 "A" 12 | WS@75 " " 13 | \@76 "\\" 14 | GlyphName@77 "mark" 15 | WS@81 " " 16 | GlyphName@82 "Ascender" 17 | ]@90 "]" 18 | ;@91 ";" 19 | WS@92 "\n" 20 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/glyph_name_tricks.fea: -------------------------------------------------------------------------------- 1 | # normal name, an escaped glyph name, and a contextual keyword 2 | @tricks = [A \mark Ascender]; 3 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/glyph_or_range.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 99) 2 | FeatureNode@[0; 98) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "derp" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType1@[19; 30) 10 | PosKw@19 "pos" 11 | WS@22 " " 12 | GlyphRange@[23; 26) 13 | GlyphName@23 "a" 14 | -@24 "-" 15 | GlyphName@25 "z" 16 | WS@26 " " 17 | ValueRecordNode@[27; 29) 18 | NUM@27 "10" 19 | ;@29 ";" 20 | WS@30 " " 21 | #@31 "# this is range" 22 | WS@46 "\n " 23 | GposType1@[51; 67) 24 | PosKw@51 "pos" 25 | WS@54 " " 26 | GlyphName@55 "two-four" 27 | WS@63 " " 28 | ValueRecordNode@[64; 66) 29 | NUM@64 "15" 30 | ;@66 ";" 31 | WS@67 " " 32 | #@68 "# this is a glyph name" 33 | WS@90 "\n" 34 | }@91 "}" 35 | WS@92 " " 36 | Tag@93 "derp" 37 | ;@97 ";" 38 | WS@98 "\n" 39 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/glyph_or_range.fea: -------------------------------------------------------------------------------- 1 | feature derp { 2 | pos a-z 10; # this is range 3 | pos two-four 15; # this is a glyph name 4 | } derp; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/ignore_pos.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | ignore pos f [a e] d'; 3 | ignore pos a d' d; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/ignore_sub.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | ignore sub f [a e] d'; 3 | ignore sub a d' d; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/ignore_sub_comma.fea: -------------------------------------------------------------------------------- 1 | # you can have multiple ignore statements separated by commas 2 | feature test { 3 | ignore substitute @LETTER a' n' d', a' n' d' @LETTER; 4 | } test; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/include_in_feature.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 99) 2 | FeatureNode@[0; 98) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "ohno" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | LookupBlockNode@[19; 88) 10 | LookupKw@19 "lookup" 11 | WS@25 " " 12 | LABEL@26 "hkern" 13 | WS@31 " " 14 | {@32 "{" 15 | WS@33 "\n " 16 | GlyphClassDefNode@[38; 57) 17 | @GlyphClass@38 "@group" 18 | WS@44 " " 19 | =@45 "=" 20 | WS@46 " " 21 | GlyphClass@[47; 56) 22 | [@47 "[" 23 | \@48 "\\" 24 | GlyphName@49 "pos" 25 | WS@52 " " 26 | \@53 "\\" 27 | CID@54 "5" 28 | ]@55 "]" 29 | ;@56 ";" 30 | WS@57 "\n " 31 | GposType2@[62; 79) 32 | PosKw@62 "pos" 33 | WS@65 " " 34 | \@66 "\\" 35 | GlyphName@67 "sub" 36 | WS@70 " " 37 | \@71 "\\" 38 | GlyphName@72 "four" 39 | WS@76 " " 40 | ValueRecordNode@[77; 78) 41 | NUM@77 "1" 42 | ;@78 ";" 43 | WS@79 "\n" 44 | }@80 "}" 45 | WS@81 " " 46 | LABEL@82 "hkern" 47 | ;@87 ";" 48 | WS@88 "\n\n" 49 | WS@90 "\n" 50 | }@91 "}" 51 | WS@92 " " 52 | Tag@93 "ohno" 53 | ;@97 ";" 54 | WS@98 "\n" 55 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/include_in_feature.fea: -------------------------------------------------------------------------------- 1 | feature ohno { 2 | include(escape_nonkeyword.fea); 3 | } ohno; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/include_without_semi.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 233) 2 | #@0 "# semis after includes are required in the spec, but not required by all impls." 3 | WS@79 "\n" 4 | #@80 "# we print a warning here, but accept the syntax." 5 | WS@129 "\n" 6 | FeatureNode@[130; 231) 7 | FeatureKw@130 "feature" 8 | WS@137 " " 9 | Tag@138 "size" 10 | WS@142 " " 11 | {@143 "{" 12 | WS@144 "\n " 13 | #@147 "# we had a parse failure when this was exactly \'0.0\'" 14 | WS@199 "\n " 15 | ParametersNode@[202; 223) 16 | ParametersKw@202 "parameters" 17 | WS@212 " " 18 | FLOAT@213 "0.0" 19 | WS@216 " " 20 | NUM@217 "0" 21 | WS@218 " " 22 | NUM@219 "0" 23 | WS@220 " " 24 | NUM@221 "0" 25 | ;@222 ";" 26 | WS@223 "\n" 27 | }@224 "}" 28 | WS@225 " " 29 | Tag@226 "size" 30 | ;@230 ";" 31 | WS@231 "\n" 32 | WS@232 "\n" 33 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/include_without_semi.fea: -------------------------------------------------------------------------------- 1 | # semis after includes are required in the spec, but not required by all impls. 2 | # we print a warning here, but accept the syntax. 3 | include(size_zero.fea) 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/language_system.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 52) 2 | LanguageSystemNode@[0; 25) 3 | LanguagesystemKw@0 "languagesystem" 4 | WS@14 " " 5 | Tag@15 "dflt" 6 | WS@19 " " 7 | Tag@20 "DFLT" 8 | ;@24 ";" 9 | WS@25 "\n" 10 | LanguageSystemNode@[26; 51) 11 | LanguagesystemKw@26 "languagesystem" 12 | WS@40 " " 13 | Tag@41 "okay" 14 | WS@45 " " 15 | Tag@46 "cool" 16 | ;@50 ";" 17 | WS@51 "\n" 18 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/language_system.fea: -------------------------------------------------------------------------------- 1 | languagesystem dflt DFLT; 2 | languagesystem okay cool; 3 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/lookup_def_group.fea: -------------------------------------------------------------------------------- 1 | 2 | feature ccmp { 3 | # zero.slash alternate 4 | sub zero VS1 by zero.slash; 5 | lookup latnSoftDot { 6 | @CombiningTopAccents = [acomb acutecomb acutetonecomb almostequaltoabovecomb arrowheadrightabovecomb brevecomb breveinvertedcomb candraBinducomb caroncomb ccomb circumflexcomb commaabovecomb commareversedabovecomb commaturnedabovecomb dblgravecomb]; 7 | sub zero VS1 by zero.slash; 8 | } latnSoftDot; 9 | } ccmp; 10 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/mark-tag.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 37) 2 | FeatureNode@[0; 36) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "mark" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType2@[17; 28) 10 | PosKw@17 "pos" 11 | WS@20 " " 12 | GlyphName@21 "A" 13 | WS@22 " " 14 | GlyphName@23 "B" 15 | WS@24 " " 16 | ValueRecordNode@[25; 27) 17 | NUM@25 "20" 18 | ;@27 ";" 19 | WS@28 "\n" 20 | }@29 "}" 21 | WS@30 " " 22 | Tag@31 "mark" 23 | ;@35 ";" 24 | WS@36 "\n" 25 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/mark-tag.fea: -------------------------------------------------------------------------------- 1 | feature mark { 2 | pos A B 20; 3 | } mark; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/mark_class.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 45) 2 | MarkClassNode@[0; 44) 3 | MarkClassKw@0 "markClass" 4 | WS@9 " " 5 | GlyphClass@[10; 17) 6 | [@10 "[" 7 | GlyphName@11 "acute" 8 | ]@16 "]" 9 | WS@17 " " 10 | AnchorNode@[18; 32) 11 | <@18 "<" 12 | AnchorKw@19 "anchor" 13 | WS@25 " " 14 | NUM@26 "350" 15 | WS@29 " " 16 | NUM@30 "0" 17 | >@31 ">" 18 | WS@32 " " 19 | @GlyphClass@33 "@TOP_MARKS" 20 | ;@43 ";" 21 | WS@44 "\n" 22 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/mark_class.fea: -------------------------------------------------------------------------------- 1 | markClass [acute] @TOP_MARKS; 2 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/naked_semi_in_lookup.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 172) 2 | #@0 "# some generated sources (glyphs.app?) insert bare semis in places, which we" 3 | WS@76 "\n" 4 | #@77 "# should warn about but ignore?" 5 | WS@108 "\n" 6 | LookupBlockNode@[109; 171) 7 | LookupKw@109 "lookup" 8 | WS@115 " " 9 | LABEL@116 "ABC" 10 | WS@119 " " 11 | {@120 "{" 12 | WS@121 "\n " 13 | LookupFlagNode@[126; 139) 14 | LookupflagKw@126 "lookupflag" 15 | WS@136 " " 16 | NUM@137 "0" 17 | ;@138 ";" 18 | WS@139 "\n " 19 | ;@144 ";" 20 | WS@145 "\n " 21 | GsubType6@[150; 164) 22 | SubKw@150 "sub" 23 | WS@153 " " 24 | BacktrackSequence@[154; 155) 25 | GlyphName@154 "a" 26 | WS@155 " " 27 | ContextSequence@[156; 159) 28 | ContextGlyphNode@[156; 159) 29 | GlyphName@156 "b" 30 | '@157 "'" 31 | WS@158 " " 32 | LookaheadSequence@[159; 159) 33 | InlineSubNode@[159; 163) 34 | ByKw@159 "by" 35 | WS@161 " " 36 | GlyphName@162 "c" 37 | ;@163 ";" 38 | WS@164 "\n" 39 | }@165 "}" 40 | WS@166 " " 41 | LABEL@167 "ABC" 42 | ;@170 ";" 43 | WS@171 "\n" 44 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/naked_semi_in_lookup.fea: -------------------------------------------------------------------------------- 1 | # some generated sources (glyphs.app?) insert bare semis in places, which we 2 | # should warn about but ignore? 3 | lookup ABC { 4 | lookupflag 0; 5 | ; 6 | sub a b' by c; 7 | } ABC; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/name-tag.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 37) 2 | FeatureNode@[0; 36) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "name" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType2@[17; 28) 10 | PosKw@17 "pos" 11 | WS@20 " " 12 | GlyphName@21 "A" 13 | WS@22 " " 14 | GlyphName@23 "B" 15 | WS@24 " " 16 | ValueRecordNode@[25; 27) 17 | NUM@25 "20" 18 | ;@27 ";" 19 | WS@28 "\n" 20 | }@29 "}" 21 | WS@30 " " 22 | Tag@31 "name" 23 | ;@35 ";" 24 | WS@36 "\n" 25 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/name-tag.fea: -------------------------------------------------------------------------------- 1 | feature name { 2 | pos A B 20; 3 | } name; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/named_value_record_reference.fea: -------------------------------------------------------------------------------- 1 | valueRecordDef 42 FOURTWO; 2 | 3 | feature test { 4 | pos a ; 5 | pos b c ; 6 | pos [d e] f ; 7 | pos g h i' [j k]; 8 | } test; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/rsub.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 57) 2 | FeatureNode@[0; 56) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "test" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GsubType8@[19; 48) 10 | RsubKw@19 "reversesub" 11 | WS@29 " " 12 | BacktrackSequence@[30; 35) 13 | GlyphClass@[30; 35) 14 | [@30 "[" 15 | GlyphName@31 "a" 16 | WS@32 " " 17 | GlyphName@33 "e" 18 | ]@34 "]" 19 | WS@35 " " 20 | ContextSequence@[36; 39) 21 | ContextGlyphNode@[36; 39) 22 | GlyphName@36 "d" 23 | '@37 "'" 24 | WS@38 " " 25 | LookaheadSequence@[39; 39) 26 | InlineSubNode@[39; 47) 27 | ByKw@39 "by" 28 | WS@41 " " 29 | GlyphName@42 "d.alt" 30 | ;@47 ";" 31 | WS@48 "\n" 32 | }@49 "}" 33 | WS@50 " " 34 | Tag@51 "test" 35 | ;@55 ";" 36 | WS@56 "\n" 37 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/rsub.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | reversesub [a e] d' by d.alt; 3 | } test; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/short-tag.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 35) 2 | FeatureNode@[0; 34) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "nam" 6 | WS@11 " " 7 | {@12 "{" 8 | WS@13 "\n " 9 | GposType2@[16; 27) 10 | PosKw@16 "pos" 11 | WS@19 " " 12 | GlyphName@20 "A" 13 | WS@21 " " 14 | GlyphName@22 "B" 15 | WS@23 " " 16 | ValueRecordNode@[24; 26) 17 | NUM@24 "20" 18 | ;@26 ";" 19 | WS@27 "\n" 20 | }@28 "}" 21 | WS@29 " " 22 | Tag@30 "nam" 23 | ;@33 ";" 24 | WS@34 "\n" 25 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/short-tag.fea: -------------------------------------------------------------------------------- 1 | feature nam { 2 | pos A B 20; 3 | } nam; 4 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/simple_aalt.fea: -------------------------------------------------------------------------------- 1 | languagesystem DFLT dflt; 2 | 3 | feature aalt { 4 | feature sups; 5 | feature frac; 6 | 7 | sub g by g_very_cool; 8 | substitute ampersand from [ampersand.1 ampersand.2 ampersand.3]; 9 | } aalt; 10 | 11 | feature sups { 12 | sub one by onesuperior; 13 | } sups; 14 | 15 | feature frac { 16 | sub one slash four by onequarter; 17 | } frac; 18 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/size_zero.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 102) 2 | FeatureNode@[0; 101) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "size" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | #@17 "# we had a parse failure when this was exactly \'0.0\'" 10 | WS@69 "\n " 11 | ParametersNode@[72; 93) 12 | ParametersKw@72 "parameters" 13 | WS@82 " " 14 | FLOAT@83 "0.0" 15 | WS@86 " " 16 | NUM@87 "0" 17 | WS@88 " " 18 | NUM@89 "0" 19 | WS@90 " " 20 | NUM@91 "0" 21 | ;@92 ";" 22 | WS@93 "\n" 23 | }@94 "}" 24 | WS@95 " " 25 | Tag@96 "size" 26 | ;@100 ";" 27 | WS@101 "\n" 28 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/size_zero.fea: -------------------------------------------------------------------------------- 1 | feature size { 2 | # we had a parse failure when this was exactly '0.0' 3 | parameters 0.0 0 0 0; 4 | } size; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/spec6iii_3c.fea: -------------------------------------------------------------------------------- 1 | # http://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html#example-3c 2 | feature kern { 3 | pos a b' c 10; 4 | pos e f' g h <12 0 5 0>; 5 | } kern; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/spec9h.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 120) 2 | VmtxTableNode@[0; 119) 3 | TableKw@0 "table" 4 | WS@5 " " 5 | Tag@6 "vmtx" 6 | WS@10 " " 7 | {@11 "{" 8 | WS@12 "\n " 9 | #@17 "# these are cids" 10 | WS@33 "\n " 11 | VmtxEntryNode@[38; 59) 12 | VertOriginY@38 "VertOriginY" 13 | WS@49 " " 14 | \@50 "\\" 15 | CID@51 "711" 16 | WS@54 " " 17 | NUM@55 "864" 18 | ;@58 ";" 19 | WS@59 "\n " 20 | VmtxEntryNode@[64; 85) 21 | VertOriginY@64 "VertOriginY" 22 | WS@75 " " 23 | \@76 "\\" 24 | CID@77 "712" 25 | WS@80 " " 26 | NUM@81 "867" 27 | ;@84 ";" 28 | WS@85 "\n " 29 | VmtxEntryNode@[90; 111) 30 | VertOriginY@90 "VertOriginY" 31 | WS@101 " " 32 | \@102 "\\" 33 | CID@103 "713" 34 | WS@106 " " 35 | NUM@107 "866" 36 | ;@110 ";" 37 | WS@111 "\n" 38 | }@112 "}" 39 | WS@113 " " 40 | Tag@114 "vmtx" 41 | ;@118 ";" 42 | WS@119 "\n" 43 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/spec9h.fea: -------------------------------------------------------------------------------- 1 | table vmtx { 2 | # these are cids 3 | VertOriginY \711 864; 4 | VertOriginY \712 867; 5 | VertOriginY \713 866; 6 | } vmtx; 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/suffix_metrics.fea: -------------------------------------------------------------------------------- 1 | feature kern { 2 | pos p (wght=1000u:-100 wght=200d:0); 3 | pos d (blah=-1n:5 blah=0.5,rah=-0.3n: -9); 4 | } kern; 5 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/value_record_def.fea: -------------------------------------------------------------------------------- 1 | valueRecordDef 123 format_a; 2 | valueRecordDef <1 2 3 4> format_b; 3 | valueRecordDef < 4 | 1 2 3 4 5 | 6 | 7 | 8 | 9 | > format_c; 10 | valueRecordDef format_d; 11 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/valuerecord_formats.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 91) 2 | FeatureNode@[0; 90) 3 | FeatureKw@0 "feature" 4 | WS@7 " " 5 | Tag@8 "test" 6 | WS@12 " " 7 | {@13 "{" 8 | WS@14 "\n " 9 | GposType1@[19; 32) 10 | PosKw@19 "pos" 11 | WS@22 " " 12 | GlyphName@23 "fmt_a" 13 | WS@28 " " 14 | ValueRecordNode@[29; 31) 15 | NUM@29 "69" 16 | ;@31 ";" 17 | WS@32 "\n " 18 | GposType1@[37; 62) 19 | PosKw@37 "pos" 20 | WS@40 " " 21 | GlyphName@41 "fmt_b" 22 | WS@46 " " 23 | ValueRecordNode@[47; 61) 24 | <@47 "<" 25 | NUM@48 "-80" 26 | WS@51 " " 27 | NUM@52 "0" 28 | WS@53 " " 29 | NUM@54 "-160" 30 | WS@58 " " 31 | NUM@59 "0" 32 | >@60 ">" 33 | ;@61 ";" 34 | WS@62 "\n " 35 | GposType1@[67; 82) 36 | PosKw@67 "pos" 37 | WS@70 " " 38 | GlyphName@71 "fmt_e" 39 | WS@76 " " 40 | ValueRecordNode@[77; 81) 41 | <@77 "<" 42 | ID@78 "HI" 43 | >@80 ">" 44 | ;@81 ";" 45 | WS@82 "\n" 46 | }@83 "}" 47 | WS@84 " " 48 | Tag@85 "test" 49 | ;@89 ";" 50 | WS@90 "\n" 51 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/valuerecord_formats.fea: -------------------------------------------------------------------------------- 1 | feature test { 2 | pos fmt_a 69; 3 | pos fmt_b <-80 0 -160 0>; 4 | pos fmt_e ; 5 | } test; 6 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/variable_anchor.fea: -------------------------------------------------------------------------------- 1 | anchorDef 0 (wght=200:12 wght=900:22 wdth=150,wght=900:42) COOL; 2 | anchorDef (wght=100:0 wght=900:5) (wght=200:12 wght=900:22 wdth=150,wght=900:42) COOL; 3 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/variable_conditionset.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 116) 2 | #@0 "# https://github.com/adobe-type-tools/afdko/pull/1350" 3 | WS@53 "\n" 4 | ConditionSetNode@[54; 114) 5 | ConditionSetKw@54 "conditionset" 6 | WS@66 " " 7 | LABEL@67 "cool" 8 | WS@71 " " 9 | {@72 "{" 10 | WS@73 "\n\t" 11 | ConditionNode@[75; 88) 12 | Tag@75 "wght" 13 | WS@79 " " 14 | NUM@80 "700" 15 | WS@83 " " 16 | NUM@84 "900" 17 | ;@87 ";" 18 | WS@88 "\n " 19 | ConditionNode@[93; 106) 20 | Tag@93 "temp" 21 | WS@97 " " 22 | NUM@98 "100" 23 | WS@101 " " 24 | NUM@102 "300" 25 | ;@105 ";" 26 | WS@106 "\n" 27 | }@107 "}" 28 | WS@108 " " 29 | LABEL@109 "cool" 30 | ;@113 ";" 31 | WS@114 "\n\n" 32 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/variable_conditionset.fea: -------------------------------------------------------------------------------- 1 | # https://github.com/adobe-type-tools/afdko/pull/1350 2 | conditionset cool { 3 | wght 700 900; 4 | temp 100 300; 5 | } cool; 6 | 7 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/variable_metrics.fea: -------------------------------------------------------------------------------- 1 | feature kern { 2 | pos p y (wght=1000:-100 wght=200:0); 3 | pos x y (wght=200:-100 wght=900:-150 wdth=150,wght=900:-120); 4 | } kern; 5 | 6 | table OS/2 { 7 | TypoAscender (blah=100:5 blah=400,rah=300: -9); 8 | } OS/2; 9 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/variable_value_record.fea: -------------------------------------------------------------------------------- 1 | valueRecordDef <0 (wght=200:-100 wght=900:-150 wdth=150,wght=900:-120) 0 0> foo; 2 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/variation_block.PARSE_TREE: -------------------------------------------------------------------------------- 1 | FILE@[0; 101) 2 | VariationNode@[0; 48) 3 | VariationKw@0 "variation" 4 | WS@9 " " 5 | Tag@10 "test" 6 | WS@14 " " 7 | LABEL@15 "heavy" 8 | WS@20 " " 9 | {@21 "{" 10 | WS@22 "\n " 11 | LookupRefNode@[27; 40) 12 | LookupKw@27 "lookup" 13 | WS@33 " " 14 | ID@34 "thing" 15 | ;@39 ";" 16 | WS@40 "\n" 17 | }@41 "}" 18 | WS@42 " " 19 | Tag@43 "test" 20 | ;@47 ";" 21 | WS@48 "\n\n" 22 | VariationNode@[50; 100) 23 | VariationKw@50 "variation" 24 | WS@59 " " 25 | Tag@60 "hmm" 26 | WS@63 " " 27 | NullKw@64 "NULL" 28 | WS@68 " " 29 | {@69 "{" 30 | WS@70 "\n " 31 | #@75 "# accept me please" 32 | WS@93 "\n" 33 | }@94 "}" 34 | WS@95 " " 35 | Tag@96 "hmm" 36 | ;@99 ";" 37 | WS@100 "\n" 38 | -------------------------------------------------------------------------------- /fea-rs/test-data/parse-tests/good/variation_block.fea: -------------------------------------------------------------------------------- 1 | variation test heavy { 2 | lookup thing; 3 | } test; 4 | 5 | variation hmm NULL { 6 | # accept me please 7 | } hmm; 8 | -------------------------------------------------------------------------------- /fea-rs/test-data/scripts/update_fonttools_tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # run this script from the repo root 4 | # there are currently two files we don't want: 5 | # - includ0.fea (part of include tests, that we don't run) 6 | # - STAT_bad.fea (an 'expected failure', which we don't currently handle) 7 | 8 | TEMP_DIR=./temp 9 | REPO=https://github.com/fonttools/fonttools.git 10 | TEST_DATA=$TEMP_DIR/Tests/feaLib/data 11 | DEST_DIR=./fonttools-tests 12 | 13 | git clone $REPO $TEMP_DIR 14 | cp $TEST_DATA/*.fea $DEST_DIR 15 | cp $TEST_DATA/*.ttx $DEST_DIR 16 | rm -rf $TEMP_DIR 17 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # used in CI to install fonttools for ttx tests 2 | fonttools[unicode]==4.38 3 | --------------------------------------------------------------------------------