From d3991a85e57a8198b008a09ae863bae23c2d7845 Mon Sep 17 00:00:00 2001 From: be5invis Date: Tue, 20 Dec 2022 22:33:34 -0800 Subject: [PATCH] Optimize building speed of GPOS --- font-src/otl/gpos-mark-mkmk.ptl | 101 ++++++++++++++++++-------------- sample-text/tie-marks.txt | 1 + 2 files changed, 58 insertions(+), 44 deletions(-) create mode 100644 sample-text/tie-marks.txt diff --git a/font-src/otl/gpos-mark-mkmk.ptl b/font-src/otl/gpos-mark-mkmk.ptl index 7a7696d8c..92f227068 100644 --- a/font-src/otl/gpos-mark-mkmk.ptl +++ b/font-src/otl/gpos-mark-mkmk.ptl @@ -1,4 +1,6 @@ import [AddCommonFeature AddFeature AddLookup] from"./table-util.mjs" + +extern Map extern Set define MarkClasses { @@ -9,56 +11,67 @@ define MarkClasses { } export : define [buildMarkMkmk sink glyphStore] : begin - define mark : AddFeature sink 'mark' - define mkmk : AddFeature sink 'mkmk' - AddCommonFeature sink mark - AddCommonFeature sink mkmk + define validMarkClasses : new Set MarkClasses - local markLookupNames {} - local mkmkLookupNames {} + define mark : object + feature : AddFeature sink 'mark' + lookupMap : new Map + lookupNames : new Set + createLookup : function [] {.type 'gpos_mark_to_base' .marks {.} .bases {.}} + define mkmk : object + feature : AddFeature sink 'mkmk' + lookupMap : new Map + lookupNames : new Set + createLookup : function [] {.type 'gpos_mark_to_mark' .marks {.} .bases {.}} - foreach markCls [items-of MarkClasses] : begin - local [object markLookup mkmkLookup] : createMTLookups glyphStore { markCls } - if ([objectIsNotEmpty markLookup.marks] && [objectIsNotEmpty markLookup.bases]) : begin - local lidMark : AddLookup sink markLookup - mark.lookups.push lidMark - markLookupNames.push lidMark + AddCommonFeature sink mark.feature + AddCommonFeature sink mkmk.feature - if ([objectIsNotEmpty mkmkLookup.marks] && [objectIsNotEmpty mkmkLookup.bases]) : begin - local lidMkmk : AddLookup sink mkmkLookup - mkmk.lookups.push lidMkmk - mkmkLookupNames.push lidMkmk + foreach cls [items-of MarkClasses] : begin + local markLookup : ensureLookup sink mark cls + local mkmkLookup : ensureLookup sink mkmk cls - foreach lidMark [items-of markLookupNames] : foreach lidMkmk [items-of mkmkLookupNames] + foreach { gn glyph } [glyphStore.namedEntries] : begin + local glyphIsMark false + if glyph.markAnchors.(cls) : begin + set glyphIsMark true + addMarkAnchor markLookup gn cls glyph.markAnchors.(cls) + addMarkAnchor mkmkLookup gn cls glyph.markAnchors.(cls) + + if glyph.baseAnchors.(cls) : begin + local anchor : object + x glyph.baseAnchors.(cls).x + y glyph.baseAnchors.(cls).y + if glyphIsMark + : then : addBaseAnchor mkmkLookup gn cls glyph.baseAnchors.(cls) + : else : addBaseAnchor markLookup gn cls glyph.baseAnchors.(cls) + + foreach lidMark mark.lookupNames : foreach lidMkmk mkmk.lookupNames sink.lookupDep.push { lidMark lidMkmk } -define [createMTLookups glyphStore markClasses] : begin - local markLookup {.type 'gpos_mark_to_base' .marks {.} .bases {.}} - local mkmkLookup {.type 'gpos_mark_to_mark' .marks {.} .bases {.}} - local allowMarkClsSet : new Set markClasses - foreach { gn glyph } [glyphStore.namedEntries] : begin - createMarkInfo markLookup.marks gn glyph allowMarkClsSet - createMarkInfo mkmkLookup.marks gn glyph allowMarkClsSet - local isMark : objectIsNotEmpty glyph.markAnchors - if isMark - createBaseInfo mkmkLookup.bases gn glyph allowMarkClsSet - createBaseInfo markLookup.bases gn glyph allowMarkClsSet - return : object markLookup mkmkLookup -define [createBaseInfo sink gn glyph allowMarkClsSet] : begin - local res {.} - local pushed false - foreach { markCls anchor } [pairs-of glyph.baseAnchors] : if [allowMarkClsSet.has markCls] : begin - set pushed true - set res.(markCls) {.x anchor.x .y anchor.y} - if pushed : set sink.(gn) res - return pushed +define [ensureLookup sink feat cls] : begin + local existing : feat.lookupMap.get cls + if existing : return existing -define [createMarkInfo sink gn glyph allowMarkClsSet] : begin - local m null - foreach { markCls anchor } [pairs-of glyph.markAnchors] : if [allowMarkClsSet.has markCls] : begin - set m {.class markCls .x anchor.x .y anchor.y} - if m : set sink.(gn) m - return m + local novel : feat.createLookup + local lid : AddLookup sink novel + feat.feature.lookups.push lid + feat.lookupNames.add lid + feat.lookupMap.set cls novel -define [objectIsNotEmpty obj] : obj && [Object.keys obj].length \ No newline at end of file + return novel + +define [addMarkAnchor lookup gn cls anchor] : begin + local a : object + class cls + x anchor.x + y anchor.y + set lookup.marks.(gn) a + +define [addBaseAnchor lookup gn cls anchor] : begin + local a : object + x anchor.x + y anchor.y + if [not lookup.bases.(gn)] : set lookup.bases.(gn) {.} + set lookup.bases.(gn).(cls) a diff --git a/sample-text/tie-marks.txt b/sample-text/tie-marks.txt new file mode 100644 index 000000000..0a69cdf87 --- /dev/null +++ b/sample-text/tie-marks.txt @@ -0,0 +1 @@ +u\u0303\u0361\u034f\u030ei\u030a u\u030e u\u034f\u030e u\u0303\u035f\u034f\u0348i\u030a u\u0348 u\u034f\u0348 \ No newline at end of file