From d5d38cd3173d55eda0f04a8ec5d1c73c9b10cba3 Mon Sep 17 00:00:00 2001 From: Zachary Quinn Scheuren Date: Mon, 1 Jun 2020 12:55:09 -0700 Subject: [PATCH] Add new keywords to and fix bugs in OpenType feature file lexer (#1519) This commit updates the OpenType feature file lexer with new keywords and fixes to identifiers, include paths, strings and numbers. It also adds additional examples to the visual sample. --- lib/rouge/lexers/opentype_feature_file.rb | 69 ++++++------- spec/visual/samples/opentype_feature_file | 113 +++++++++++++++++++++- 2 files changed, 138 insertions(+), 44 deletions(-) diff --git a/lib/rouge/lexers/opentype_feature_file.rb b/lib/rouge/lexers/opentype_feature_file.rb index 1abb8817c9..4004e8a6a6 100644 --- a/lib/rouge/lexers/opentype_feature_file.rb +++ b/lib/rouge/lexers/opentype_feature_file.rb @@ -12,24 +12,30 @@ class OpenTypeFeatureFile < RegexLexer def self.keywords @keywords ||= %w( - Ascender Attach CapHeight CaretOffset CodePageRange Descender FontRevision FSType - GlyphClassDef HorizAxis.BaseScriptList HorizAxis.BaseTagList HorizAxis.MinMax - IgnoreBaseGlyphs IgnoreLigatures IgnoreMarks LigatureCaretByDev LigatureCaretByIndex - LigatureCaretByPos LineGap MarkAttachClass MarkAttachmentType NULL Panose RightToLeft - TypoAscender TypoDescender TypoLineGap UnicodeRange UseMarkFilteringSet Vendor - VertAdvanceY VertAxis.BaseScriptList VertAxis.BaseTagList VertAxis.MinMax VertOriginY - VertTypoAscender VertTypoDescender VertTypoLineGap WeightClass WidthClass XHeight - - anchorDef anchor anonymous anon by contour cursive device enumerate enum - exclude_dflt featureNames feature from ignore include_dflt include languagesystem - language lookupflag lookup markClass mark nameid name parameters position pos required - reversesub rsub script sizemenuname substitute subtable sub table useExtension + Ascender Attach AxisValue CapHeight CaretOffset CodePageRange + DesignAxis Descender ElidedFallbackName ElidedFallbackNameID + ElidableAxisValueName FeatUILabelNameID FeatUITooltipTextNameID + FontRevision FSType GlyphClassDef HorizAxis.BaseScriptList + HorizAxis.BaseTagList HorizAxis.MinMax IgnoreBaseGlyphs + IgnoreLigatures IgnoreMarks LigatureCaretByDev LigatureCaretByIndex + LigatureCaretByPos LineGap MarkAttachClass MarkAttachmentType NULL + OlderSiblingFontAttribute Panose ParamUILabelNameID RightToLeft + SampleTextNameID TypoAscender TypoDescender TypoLineGap UnicodeRange + UseMarkFilteringSet Vendor VertAdvanceY VertAxis.BaseScriptList + VertAxis.BaseTagList VertAxis.MinMax VertOriginY VertTypoAscender + VertTypoDescender VertTypoLineGap WeightClass WidthClass XHeight + + anchorDef anchor anonymous anon by contour cursive device enumerate + enum exclude_dflt featureNames feature flag from ignore include_dflt + include languagesystem language location lookupflag lookup markClass + mark nameid name parameters position pos required reversesub rsub + script sizemenuname substitute subtable sub table useExtension valueRecordDef winAscent winDescent ) end - identifier = %r/[a-z_][a-z0-9\/_]*/i + identifier = %r/[a-z_][a-z0-9\/_.-]*/i state :root do rule %r/\s+/m, Text::Whitespace @@ -41,17 +47,18 @@ def self.keywords push :featurename end # } ; - rule %r/(\})((?:\s)*)/ do + rule %r/(\})((?:\s))/ do groups Punctuation, Text push :featurename end # solve include( ../path) - rule %r/(include)/i, Keyword, :includepath + rule %r/include\b/i, Keyword, :includepath rule %r/[\-\[\]\/(){},.:;=%*<>']/, Punctuation rule %r/`.*?/, Str::Backtick - rule %r/\"/, Str, :dqs + rule %r/\"/, Str, :strings + rule %r/\\[^.*\s]+/i, Str::Escape # classes, start with @ rule %r/@#{identifier}/, Name::Class @@ -66,6 +73,7 @@ def self.keywords end rule identifier, Name + rule %r/(?:0x|\\)[0-9A-Fa-f]+/, Num::Hex rule %r/-?\d+/, Num::Integer end @@ -77,37 +85,14 @@ def self.keywords rule %r/\s+/, Text::Whitespace rule %r/\)/, Punctuation, :pop! rule %r/\(/, Punctuation - rule %r/[a-z0-9\/_.]*/i, Str + rule %r/[^\s()]+/, Str end state :strings do - rule %r/(\([a-z0-9_]+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?/i, Str - end - - state :strings_double do - rule %r/[^\\"%\n]+/, Str - mixin :strings - end - - state :escape do - rule %r(\\ - ( [\\abfnrtv"'] - | \n - | N{[a-zA-z][a-zA-Z ]+[a-zA-Z]} - | u[a-fA-F0-9]{4} - | U[a-fA-F0-9]{8} - | x[a-fA-F0-9]{2} - | [0-7]{1,3} - ) - )x, Str::Escape - end - - state :dqs do rule %r/"/, Str, :pop! - mixin :escape - mixin :strings_double + rule %r/[^"%\n]+/, Str + rule %r/(\([a-z0-9_]+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?/i, Str end - end end end diff --git a/spec/visual/samples/opentype_feature_file b/spec/visual/samples/opentype_feature_file index 58841a9358..9623625f7a 100644 --- a/spec/visual/samples/opentype_feature_file +++ b/spec/visual/samples/opentype_feature_file @@ -7,7 +7,7 @@ languagesystem grek dflt; table name { - nameid 0 "Copyright Enschede"; + nameid 0 "\00A9 2020 Enschede"; nameid 9 "Jan van Krimpen"; } name; @@ -15,6 +15,7 @@ table name { include (../../family.fea); include ( ../../family.fea ) ; +include (../../locl-IPPH-APPH.fea); # imports IPA lookups (which differ between upright and italic) languagesystem DFLT dflt; languagesystem latn dflt; @@ -57,6 +58,7 @@ table OS/2 { # Script and language coverage languagesystem DFLT dflt; languagesystem latn dflt; +language DEU include_dflt; # Ligature formation feature liga { @@ -88,6 +90,24 @@ feature test { substitute [ a e i o u] c' lookup CNTXT_LIGS t' s' lookup CNTXT_SUB; } test; +lookup ADD_ADVANCE_WIDTH { + pos ka-gran' lookup REPHA_SPACE lookup ANUSVARA_SPACE lookup ADD70 repha-gran anusvara-gran; + pos ka-gran' lookup REPHA_SPACE lookup ADD70 repha-gran; + pos ka-gran' lookup ANUSVARA_SPACE lookup ADD70 anusvara-gran; +} ADD_ADVANCE_WIDTH; + +lookup REMOVE_CAKRA { + sub ka ka.pas_cakra.ns by ka; +} REMOVE_CAKRA; + +lookup REORDER_CAKRA { + sub ka by ka.pas_cakra ka; +} REORDER_CAKRA; + +lookup REORDER_CHAIN { + sub ka' lookup REMOVE_CAKRA lookup REORDER_CAKRA ka.pas_cakra.ns' ; +} REORDER_CHAIN; + table OS/2 { FSType 4; Panose 2 15 0 0 2 2 8 2 9 4; @@ -113,4 +133,93 @@ table OS/2 { WeightClass 800; WidthClass 3; Vendor "ADBE"; -} OS/2; \ No newline at end of file +} OS/2; + +feature vpal { + position \1401 <0 26 0 -87>; + position \1414 <0 50 0 -140>; +} vpal; + +table vmtx { + VertOriginY \736 867; + VertOriginY \754 868; + VertOriginY \755 875; +} vmtx; + +feature cv18 { # Character Variant 18 — dotted zero + + cvParameters { + FeatUILabelNameID { + name 3 1 0x0409 "Dotted zero [ 0 ]"; # English US + name 3 1 0x0809 "Dotted zero [ 0 ]"; # English GB + name 1 0 0 "Dotted zero [ 0 ]"; # Mac English + name 3 1 0x0408 "\039C\03B7\03B4\03AD\03BD \03BC\03B5 \03BA\03B5\03BD\03C4\03C1\03B9\03BA\03AE \03C4\03B5\03BB\03B5\03AF\03B1 [ 0 ]"; # Greek: "Μηδέν με κεντρική τελεία [ 0 ]" + name 3 1 0x0419 "\041D\043E\043B\044C \0441 \043F\0443\043D\043A\0442\0438\0440\043E\043C [ 0 ]"; # Russian: "Ноль с пунктиром [ 0 ]" + }; + }; + + lookup ZERO { + sub zero by zero.0; + sub zero.pnum by zero.0p; + } ZERO; + +} cv18; + +table STAT { + + ElidedFallbackName { name "Regular"; }; + + DesignAxis wght 0 { name "Weight"; }; + DesignAxis opsz 1 { name "Optical"; }; + + AxisValue { + location wght 200 200 - 250; + name "ExtraLight"; + }; + + AxisValue { + location wght 300 250 - 350; + name "Light"; + }; + + AxisValue { + location wght 400 350 - 450; + name "Regular"; + flag ElidableAxisValueName; + }; + + AxisValue { + location wght 600 550 - 650; + name "Semibold"; + }; + + AxisValue { + location wght 700 650 - 750; + name "Bold"; + }; + + AxisValue { + location wght 900 800 - 900; + name "Black"; + }; + + AxisValue { + location + opsz 6 0 - 8; + name "Caption"; + }; + + AxisValue { + location + opsz 10 8 - 24; + name "Text"; + flag ElidableAxisValueName; + }; + + AxisValue { + location + opsz 60 24 - 100; + name "Display"; + }; + +} STAT;