summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/font-imp-reorder.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/font-imp-reorder.lua')
-rw-r--r--tex/context/base/mkiv/font-imp-reorder.lua174
1 files changed, 174 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/font-imp-reorder.lua b/tex/context/base/mkiv/font-imp-reorder.lua
new file mode 100644
index 000000000..b2dec781c
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-reorder.lua
@@ -0,0 +1,174 @@
+if not modules then modules = { } end modules ['font-imp-reorder'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not context then return end
+
+local next = next
+local find = string.find
+local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local registerotffeature = otf.features.register
+
+-- This is a rather special test-only feature that I added for the sake of testing
+-- Idris's husayni. We wanted to know if uniscribe obeys the order of lookups in a
+-- font, in spite of what the description of handling arabic suggests. And indeed,
+-- mixed-in lookups of other features (like all these ss* in husayni) are handled
+-- the same in context as in uniscribe. If one sets reorderlookups=arab then we sort
+-- according to the "assumed" order so e.g. the ss* move to after the standard
+-- features. The observed difference in rendering is an indication that uniscribe is
+-- quite faithful to the font (while e.g. tests with the hb plugin demonstrate some
+-- interference, apart from some hard coded init etc expectations). Anyway, it means
+-- that we're okay with the (generic) node processor. A pitfall is that in context
+-- we can actually control more, so we can trigger an analyze pass with e.g.
+-- dflt/dflt while the libraries depend on the script settings for that. Uniscribe
+-- probably also parses the string and when seeing arabic will follow a different
+-- code path, although it seems to treat all features equal.
+
+local trace_reorder = trackers.register("fonts.reorderlookups",function(v) trace_reorder = v end)
+local report_reorder = logs.reporter("fonts","reorder")
+
+local vectors = { }
+
+vectors.arab = {
+ gsub = {
+ ccmp = 1,
+ isol = 2,
+ fina = 3,
+ medi = 4,
+ init = 5,
+ rlig = 6,
+ rclt = 7,
+ calt = 8,
+ liga = 9,
+ dlig = 10,
+ cswh = 11,
+ mset = 12,
+ },
+ gpos = {
+ curs = 1,
+ kern = 2,
+ mark = 3,
+ mkmk = 4,
+ },
+}
+
+local function compare(a,b)
+ local what_a = a.what
+ local what_b = b.what
+ if what_a ~= what_b then
+ return a.index < b.index
+ end
+ local when_a = a.when
+ local when_b = b.when
+ if when_a == when_b then
+ return a.index < b.index
+ else
+ return when_a < when_b
+ end
+end
+
+function otf.reorderlookups(tfmdata,vector)
+ local order = vectors[vector]
+ if not order then
+ return
+ end
+ local oldsequences = tfmdata.resources.sequences
+ if oldsequences then
+ local sequences = { }
+ for i=1,#oldsequences do
+ sequences[i] = oldsequences[i]
+ end
+ for i=1,#sequences do
+ local s = sequences[i]
+ local features = s.features
+ local kind = s.type
+ local index = s.index
+ if features then
+ local when
+ local what
+ for feature in sortedhash(features) do
+ if not what then
+ what = find(kind,"^gsub") and "gsub" or "gpos"
+ end
+ local newwhen = order[what][feature]
+ if not newwhen then
+ -- skip
+ elseif not when then
+ when = newwhen
+ elseif newwhen < when then
+ when = newwhen
+ end
+ end
+ s.ondex = s.index
+ s.index = i
+ s.what = what == "gsub" and 1 or 2
+ s.when = when or 99
+ else
+ s.ondex = s.index
+ s.index = i
+ s.what = 1
+ s.when = 99
+ end
+ end
+ sort(sequences,compare)
+ local swapped = 0
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local features = sequence.features
+ if features then
+ local index = sequence.index
+ if index ~= i then
+ swapped = swapped + 1
+ end
+ if trace_reorder then
+ if swapped == 1 then
+ report_reorder()
+ report_reorder("start swapping lookups in font %!font:name!",tfmdata)
+ report_reorder()
+ report_reorder("gsub order: % t",table.swapped(order.gsub))
+ report_reorder("gpos order: % t",table.swapped(order.gpos))
+ report_reorder()
+ end
+ report_reorder("%03i : lookup %03i, type %s, sorted %2i, moved %s, % t",
+ i,index,sequence.what == 1 and "gsub" or "gpos",sequence.when or 99,
+ (index > i and "-") or (index < i and "+") or "=",sortedkeys(features))
+ end
+ end
+ sequence.what = nil
+ sequence.when = nil
+ sequence.index = sequence.ondex
+ end
+ if swapped > 0 then
+ if trace_reorder then
+ report_reorder()
+ report_reorder("stop swapping lookups, %i lookups swapped",swapped)
+ report_reorder()
+ end
+ tfmdata.shared.reorderedsequences = sequences
+ end
+ end
+end
+
+-- maybe delay till ra is filled
+
+local function initialize(tfmdata,key,value)
+ if value then
+ otf.reorderlookups(tfmdata,value)
+ end
+end
+
+registerotffeature {
+ name = "reorderlookups",
+ description = "reorder lookups",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}