summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2017-07-14 21:22:10 +0200
committerContext Git Mirror Bot <phg42.2a@gmail.com>2017-07-14 21:22:10 +0200
commit23b495f46b4d2e9264d54095f43774ef47d3a656 (patch)
tree1b0131b93d92d4aa7e15b55c50ad1dfa3573a7e1 /tex
parent6ae40572e7643edcc29f8d5b071221dd1e04bdf3 (diff)
downloadcontext-23b495f46b4d2e9264d54095f43774ef47d3a656.tar.gz
2017-07-14 19:41:00
Diffstat (limited to 'tex')
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkii/mult-en.mkii1
-rw-r--r--tex/context/base/mkii/mult-pe.mkii1
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/cont-run.lua5
-rw-r--r--tex/context/base/mkiv/cont-run.mkiv1
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/font-con.lua16
-rw-r--r--tex/context/base/mkiv/font-ctx.lua8
-rw-r--r--tex/context/base/mkiv/font-dsp.lua35
-rw-r--r--tex/context/base/mkiv/font-ext.lua11
-rw-r--r--tex/context/base/mkiv/font-fbk.lua10
-rw-r--r--tex/context/base/mkiv/font-lib.mkvi2
-rw-r--r--tex/context/base/mkiv/font-mis.lua17
-rw-r--r--tex/context/base/mkiv/font-nod.lua34
-rw-r--r--tex/context/base/mkiv/font-otc.lua10
-rw-r--r--tex/context/base/mkiv/font-otd.lua2
-rw-r--r--tex/context/base/mkiv/font-otj.lua17
-rw-r--r--tex/context/base/mkiv/font-otl.lua2
-rw-r--r--tex/context/base/mkiv/font-oto.lua53
-rw-r--r--tex/context/base/mkiv/font-ots.lua1170
-rw-r--r--tex/context/base/mkiv/font-oup.lua291
-rw-r--r--tex/context/base/mkiv/font-shp.lua2
-rw-r--r--tex/context/base/mkiv/font-vir.lua (renamed from tex/context/base/mkiv/font-vf.lua)2
-rw-r--r--tex/context/base/mkiv/hand-ini.mkiv1
-rw-r--r--tex/context/base/mkiv/l-package.lua33
-rw-r--r--tex/context/base/mkiv/lpdf-col.lua34
-rw-r--r--tex/context/base/mkiv/lpdf-mis.lua5
-rw-r--r--tex/context/base/mkiv/lpdf-ren.lua7
-rw-r--r--tex/context/base/mkiv/lpdf-xmp.lua63
-rw-r--r--tex/context/base/mkiv/lxml-tex.lua23
-rw-r--r--tex/context/base/mkiv/m-fonts-plugins.mkiv23
-rw-r--r--tex/context/base/mkiv/meta-fnt.lua2
-rw-r--r--tex/context/base/mkiv/node-fin.lua115
-rw-r--r--tex/context/base/mkiv/node-fnt.lua193
-rw-r--r--tex/context/base/mkiv/node-ini.mkiv1
-rw-r--r--tex/context/base/mkiv/node-met.lua46
-rw-r--r--tex/context/base/mkiv/node-nut.lua79
-rw-r--r--tex/context/base/mkiv/node-ref.lua204
-rw-r--r--tex/context/base/mkiv/node-syn.lua62
-rw-r--r--tex/context/base/mkiv/spac-chr.lua81
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin25688 -> 25746 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin425247 -> 426034 bytes
-rw-r--r--tex/context/base/mkiv/strc-con.mkvi23
-rw-r--r--tex/context/base/mkiv/supp-box.lua1
-rw-r--r--tex/context/base/mkiv/trac-vis.lua457
-rw-r--r--tex/context/base/mkiv/trac-vis.mkiv3
-rw-r--r--tex/context/base/mkiv/typo-del.mkiv2
-rw-r--r--tex/context/base/mkiv/util-lib.lua7
-rw-r--r--tex/context/base/mkiv/util-sbx.lua15
-rw-r--r--tex/context/base/mkiv/util-seq.lua2
-rw-r--r--tex/context/base/mkiv/util-str.lua39
-rw-r--r--tex/context/base/mkiv/util-tab.lua4
-rw-r--r--tex/context/interface/mkii/keys-en.xml1
-rw-r--r--tex/context/interface/mkii/keys-pe.xml1
-rw-r--r--tex/context/interface/mkiv/context-en.xml18
-rw-r--r--tex/context/interface/mkiv/i-context.pdfbin848046 -> 848182 bytes
-rw-r--r--tex/context/interface/mkiv/i-description.xml6
-rw-r--r--tex/context/interface/mkiv/i-enumeration.xml6
-rw-r--r--tex/context/interface/mkiv/i-note.xml6
-rw-r--r--tex/context/interface/mkiv/i-readme.pdfbin60775 -> 60775 bytes
-rw-r--r--tex/context/test/mkiv/pdf-ua.mkiv7
-rw-r--r--tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua19
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua1153
65 files changed, 3067 insertions, 1373 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 4e4b70b10..e22f6c377 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2017.07.05 23:01}
+\newcontextversion{2017.07.14 19:35}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index b80487453..9b7f9c968 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2017.07.05 23:01}
+\edef\contextversion{2017.07.14 19:35}
%D For those who want to use this:
diff --git a/tex/context/base/mkii/mult-en.mkii b/tex/context/base/mkii/mult-en.mkii
index a4838128b..e1f59ed93 100644
--- a/tex/context/base/mkii/mult-en.mkii
+++ b/tex/context/base/mkii/mult-en.mkii
@@ -687,6 +687,7 @@
\setinterfaceconstant{bottomoffset}{bottomoffset}
\setinterfaceconstant{bottomspace}{bottomspace}
\setinterfaceconstant{bottomstate}{bottomstate}
+\setinterfaceconstant{break}{break}
\setinterfaceconstant{buffer}{buffer}
\setinterfaceconstant{cache}{cache}
\setinterfaceconstant{calculate}{calculate}
diff --git a/tex/context/base/mkii/mult-pe.mkii b/tex/context/base/mkii/mult-pe.mkii
index 8b300ae73..46a715d2e 100644
--- a/tex/context/base/mkii/mult-pe.mkii
+++ b/tex/context/base/mkii/mult-pe.mkii
@@ -687,6 +687,7 @@
\setinterfaceconstant{bottomoffset}{آفست‌پایین}
\setinterfaceconstant{bottomspace}{فضای‌پایین}
\setinterfaceconstant{bottomstate}{وضعیت‌پایین}
+\setinterfaceconstant{break}{break}
\setinterfaceconstant{buffer}{buffer}
\setinterfaceconstant{cache}{میانگیر}
\setinterfaceconstant{calculate}{محاسبه}
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index da2b24760..92d217d35 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2017.07.05 23:01}
+\newcontextversion{2017.07.14 19:35}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/mkiv/cont-run.lua b/tex/context/base/mkiv/cont-run.lua
index ee86c6a18..f18d06d66 100644
--- a/tex/context/base/mkiv/cont-run.lua
+++ b/tex/context/base/mkiv/cont-run.lua
@@ -181,7 +181,10 @@ local function processjob()
local filename = environment.filename -- hm, not inputfilename !
if arguments.synctex then
- directives.enable("system.synctex")
+ luatex.synctex.setup {
+ state = interfaces.variables.start,
+ method = interfaces.variables.max,
+ }
end
if not filename or filename == "" then
diff --git a/tex/context/base/mkiv/cont-run.mkiv b/tex/context/base/mkiv/cont-run.mkiv
index ef4992c69..8a6d49d7d 100644
--- a/tex/context/base/mkiv/cont-run.mkiv
+++ b/tex/context/base/mkiv/cont-run.mkiv
@@ -13,7 +13,6 @@
\writestatus{loading}{ConTeXt Core Macros / Runner}
-\registerctxluafile{node-syn}{1.001}
\registerctxluafile{cont-run}{1.001}
% \enabletrackers[system.synctex.visualize]
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index c142bbc64..056ba3d32 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -41,7 +41,7 @@
%D up and the dependencies are more consistent.
\edef\contextformat {\jobname}
-\edef\contextversion{2017.07.05 23:01}
+\edef\contextversion{2017.07.14 19:35}
\edef\contextkind {beta}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua
index fd3b28612..1b986b6a6 100644
--- a/tex/context/base/mkiv/font-con.lua
+++ b/tex/context/base/mkiv/font-con.lua
@@ -555,22 +555,6 @@ function constructors.scale(tfmdata,specification)
if changed then
local c = changed[unicode]
if c and c ~= unicode then
--- while true do
--- local cc = changed[c]
--- if not cc then
--- -- we're done, no (futher) chain
--- break
--- elseif cc == unicode then
--- -- we probably have a bidi swap
--- break
--- elseif cc == c then
--- -- we have a self reference, shouldn't happen
--- c = nil
--- break
--- else
--- c = cc
--- end
--- end
if c then
description = descriptions[c] or descriptions[unicode] or character
character = characters[c] or character
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 8f7eed4b9..eabd1d435 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -2543,7 +2543,7 @@ end
-- a fontkern plug:
-nodes.injections.installnewkern(nuts.pool.fontkern)
+-- nodes.injections.installnewkern(nuts.pool.fontkern)
do
@@ -2599,7 +2599,7 @@ do
local unsetvalue = attributes.unsetvalue
- local traverse_id = nuts.traverse_id
+ local traverse_char = nuts.traverse_char
local a_color = attributes.private('color')
local a_colormodel = attributes.private('colormodel')
@@ -2628,7 +2628,7 @@ do
if head then
head = tonut(head)
local model = getattr(head,a_colormodel) or 1
- for glyph in traverse_id(glyph_code,head) do
+ for glyph in traverse_char(head) do
local a = getprop(glyph,a_state)
if a then
local name = colornames[a]
@@ -2679,7 +2679,7 @@ do
function methods.nocolor(head,font,attr)
- for n in traverse_id(glyph_code,head) do
+ for n in traverse_char(head) do
if not font or getfont(n) == font then
setattr(n,a_color,unsetvalue)
end
diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua
index 2e85c2438..2d3dce2fb 100644
--- a/tex/context/base/mkiv/font-dsp.lua
+++ b/tex/context/base/mkiv/font-dsp.lua
@@ -690,13 +690,13 @@ end
local function readposition(f,format,mainoffset,getdelta)
if format == 0 then
- return
+ return false
end
-- a few happen often
if format == 0x04 then
local h = readshort(f)
if h == 0 then
- return
+ return true -- all zero
else
return { 0, 0, h, 0 }
end
@@ -705,7 +705,7 @@ local function readposition(f,format,mainoffset,getdelta)
local x = readshort(f)
local h = readshort(f)
if x == 0 and h == 0 then
- return
+ return true -- all zero
else
return { x, 0, h, 0 }
end
@@ -724,7 +724,7 @@ local function readposition(f,format,mainoffset,getdelta)
skipshort(f,1)
end
if h == 0 then
- return
+ return true -- all zero
else
return { 0, 0, h, 0 }
end
@@ -779,7 +779,7 @@ local function readposition(f,format,mainoffset,getdelta)
end
return { x, y, h, v }
elseif x == 0 and y == 0 and h == 0 and v == 0 then
- return
+ return true -- all zero
else
return { x, y, h, v }
end
@@ -1521,7 +1521,7 @@ function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofgly
local first = value[2]
local second = value[3]
if first or second then
- hash[other] = { first, second } -- needs checking
+ hash[other] = { first, second or nil } -- needs checking
else
hash[other] = nil
end
@@ -1557,7 +1557,7 @@ function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofgly
local first = offsets[1]
local second = offsets[2]
if first or second then
- hash[paired] = { first, second }
+ hash[paired] = { first, second or nil }
else
-- upto the next lookup for this combination
end
@@ -1591,18 +1591,27 @@ function gposhandlers.cursive(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local entry = readushort(f)
local exit = readushort(f)
records[i] = {
- entry = entry ~= 0 and (tableoffset + entry) or false,
- exit = exit ~= 0 and (tableoffset + exit ) or false,
+ -- entry = entry ~= 0 and (tableoffset + entry) or false,
+ -- exit = exit ~= 0 and (tableoffset + exit ) or nil,
+ entry ~= 0 and (tableoffset + entry) or false,
+ exit ~= 0 and (tableoffset + exit ) or nil,
}
end
+ -- slot 1 will become hash after loading an dit must be unique because we
+ -- pack the tables (packed we turn the cc-* into a zero)
+ local cc = (fontdata.temporary.cursivecount or 0) + 1
+ fontdata.temporary.cursivecount = cc
+ cc = "cc-" .. cc
coverage = readcoverage(f,coverage)
for i=1,nofrecords do
local r = records[i]
- -- slot 1 will become hash after loading (must be unique per lookup when packed)
records[i] = {
- 1,
- readanchor(f,r.entry,getdelta) or nil,
- readanchor(f,r.exit, getdelta) or nil,
+ -- 1,
+ cc,
+ -- readanchor(f,r.entry,getdelta) or false,
+ -- readanchor(f,r.exit, getdelta) or nil,
+ readanchor(f,r[1],getdelta) or false,
+ readanchor(f,r[2],getdelta) or nil,
}
end
for index, newindex in next, coverage do
diff --git a/tex/context/base/mkiv/font-ext.lua b/tex/context/base/mkiv/font-ext.lua
index cf77ac4eb..d541521fb 100644
--- a/tex/context/base/mkiv/font-ext.lua
+++ b/tex/context/base/mkiv/font-ext.lua
@@ -749,15 +749,15 @@ registerafmfeature(dimensions_specification)
--
-- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression
--
--- local gray = { "pdf", "/Tr1 gs .75 g" }
--- local black = { "pdf", "/Tr0 gs 0 g" }
+-- local gray = { "pdf", "origin", "/Tr1 gs .75 g" }
+-- local black = { "pdf", "origin", "/Tr0 gs 0 g" }
-- sort of obsolete as we now have \showglyphs
local push = { "push" }
local pop = { "pop" }
-local gray = { "pdf", ".75 g" }
-local black = { "pdf", "0 g" }
+local gray = { "pdf", "origin", ".75 g" }
+local black = { "pdf", "origin", "0 g" }
local downcache = { } -- handy for huge cjk fonts
local rulecache = { } -- handy for huge cjk fonts
@@ -1486,7 +1486,8 @@ do
report_reorder("stop swapping lookups, %i lookups swapped",swapped)
report_reorder()
end
- tfmdata.resources.sequences = sequences
+-- tfmdata.resources.sequences = sequences
+ tfmdata.shared.reorderedsequences = sequences
end
end
end
diff --git a/tex/context/base/mkiv/font-fbk.lua b/tex/context/base/mkiv/font-fbk.lua
index 8a5c1ebb7..5008887b8 100644
--- a/tex/context/base/mkiv/font-fbk.lua
+++ b/tex/context/base/mkiv/font-fbk.lua
@@ -300,11 +300,11 @@ end
-- vf builder
--- { "pdf", "q " .. s .. " 0 0 " .. s .. " 0 0 cm" },
--- { "pdf", "q 1 0 0 1 " .. -w .. " " .. -h .. " cm" },
--- { "pdf", "/Fm\XX\space Do" },
--- { "pdf", "Q" },
--- { "pdf", "Q" },
+-- { "pdf", "origin", "q " .. s .. " 0 0 " .. s .. " 0 0 cm" },
+-- { "pdf", "origin", "q 1 0 0 1 " .. -w .. " " .. -h .. " cm" },
+-- { "pdf", "origin", "/Fm\XX\space Do" },
+-- { "pdf", "origin", "Q" },
+-- { "pdf", "origin", "Q" },
-- new and experimental
diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi
index 4ba7a7de4..4dd15812f 100644
--- a/tex/context/base/mkiv/font-lib.mkvi
+++ b/tex/context/base/mkiv/font-lib.mkvi
@@ -81,7 +81,7 @@
\registerctxluafile{font-lua}{1.001}
-\registerctxluafile{font-vf} {1.001}
+\registerctxluafile{font-vir}{1.001}
\registerctxluafile{font-enh}{1.001}
\registerctxluafile{good-ini}{1.001}
diff --git a/tex/context/base/mkiv/font-mis.lua b/tex/context/base/mkiv/font-mis.lua
index 024e32831..3325264fc 100644
--- a/tex/context/base/mkiv/font-mis.lua
+++ b/tex/context/base/mkiv/font-mis.lua
@@ -21,7 +21,7 @@ local readers = otf.readers
if readers then
- otf.version = otf.version or 3.031
+ otf.version = otf.version or 3.032
otf.cache = otf.cache or containers.define("fonts", "otl", otf.version, true)
function fonts.helpers.getfeatures(name,save)
@@ -33,10 +33,17 @@ if readers then
if data then
readers.unpack(data)
else
- data = readers.loadfont(filename)
- if data and save then
- containers.write(otf.cache,cleanname,data)
- end
+ data = readers.loadfont(filename) -- we can do a more minimal load
+ -- if data and save then
+ -- -- keep this in sync with font-otl
+ -- readers.compact(data)
+ -- readers.rehash(data,"unicodes")
+ -- readers.addunicodetable(data)
+ -- readers.extend(data)
+ -- readers.pack(data)
+ -- -- till here
+ -- containers.write(otf.cache,cleanname,data)
+ -- end
end
return data and data.resources and data.resources.features
end
diff --git a/tex/context/base/mkiv/font-nod.lua b/tex/context/base/mkiv/font-nod.lua
index b629a51d1..c70763e6b 100644
--- a/tex/context/base/mkiv/font-nod.lua
+++ b/tex/context/base/mkiv/font-nod.lua
@@ -78,7 +78,7 @@ local copy_node_list = nuts.copy_list
local hpack_node_list = nuts.hpack
local flush_node_list = nuts.flush_list
local traverse_nodes = nuts.traverse
-local traverse_id = nuts.traverse_id
+----- traverse_id = nuts.traverse_id
local protect_glyphs = nuts.protect_glyphs
local nodepool = nuts.pool
@@ -135,22 +135,22 @@ function char_tracers.collect(head,list,tag,n)
l[#l+1] = { c, f }
elseif id == disc_code then
-- skip
--- local pre, post, replace = getdisc(head)
--- if replace then
--- for n in traverse_id(glyph_code,replace) do
--- l[#l+1] = { c, f }
--- end
--- end
--- if pre then
--- for n in traverse_id(glyph_code,pre) do
--- l[#l+1] = { c, f }
--- end
--- end
--- if post then
--- for n in traverse_id(glyph_code,post) do
--- l[#l+1] = { c, f }
--- end
--- end
+ -- local pre, post, replace = getdisc(head)
+ -- if replace then
+ -- for n in traverse_id(glyph_code,replace) do
+ -- l[#l+1] = { c, f }
+ -- end
+ -- end
+ -- if pre then
+ -- for n in traverse_id(glyph_code,pre) do
+ -- l[#l+1] = { c, f }
+ -- end
+ -- end
+ -- if post then
+ -- for n in traverse_id(glyph_code,post) do
+ -- l[#l+1] = { c, f }
+ -- end
+ -- end
else
ok = false
end
diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua
index 0af588b74..b7c296809 100644
--- a/tex/context/base/mkiv/font-otc.lua
+++ b/tex/context/base/mkiv/font-otc.lua
@@ -412,11 +412,9 @@ local function addfeature(data,feature,specifications)
local rules = list.rules
local coverage = { }
if rules then
- local rulehash = { }
- local rulesize = 0
- local sequence = { }
- local nofsequences = 0
- local lookuptype = types[featuretype]
+ local rulehash = { }
+ local rulesize = 0
+ local lookuptype = types[featuretype]
for nofrules=1,#rules do
local rule = rules[nofrules]
local current = rule.current
@@ -504,8 +502,10 @@ local function addfeature(data,feature,specifications)
coverage[unic] = rulehash -- can now be done cleaner i think
end
end
+ sequence.n = nofsequences
end
end
+ rulehash.n = rulesize
end
return coverage
end
diff --git a/tex/context/base/mkiv/font-otd.lua b/tex/context/base/mkiv/font-otd.lua
index c45278826..2633c6cae 100644
--- a/tex/context/base/mkiv/font-otd.lua
+++ b/tex/context/base/mkiv/font-otd.lua
@@ -268,7 +268,7 @@ function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in specia
-- indexed but we can also add specific data by key in:
}
rl[attr] = ra
- local sequences = tfmdata.resources.sequences
+ local sequences = tfmdata.shared.reorderedsequences or tfmdata.resources.sequences
if sequences then
local autoscript = (s_enabled and s_enabled.autoscript ) or (a_enabled and a_enabled.autoscript )
local autolanguage = (s_enabled and s_enabled.autolanguage) or (a_enabled and a_enabled.autolanguage)
diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua
index 6275f81b8..a6e60a3f5 100644
--- a/tex/context/base/mkiv/font-otj.lua
+++ b/tex/context/base/mkiv/font-otj.lua
@@ -515,7 +515,7 @@ end
local function showsub(n,what,where)
report_injections("begin subrun: %s",where)
- for n in traverse_id(glyph_code,n) do
+ for n in traverse_char(n) do
showchar(n,where)
show(n,what,where," ")
end
@@ -593,7 +593,7 @@ local function inject_kerns_only(head,where)
local prev = nil
local next = nil
local prevdisc = nil
- local prevglyph = nil
+ -- local prevglyph = nil
local pre = nil -- saves a lookup
local post = nil -- saves a lookup
local replace = nil -- saves a lookup
@@ -655,11 +655,11 @@ local function inject_kerns_only(head,where)
end
end
prevdisc = nil
- prevglyph = current
+ -- prevglyph = current
elseif char == false then
-- other font
prevdisc = nil
- prevglyph = current
+ -- prevglyph = current
elseif id == disc_code then
pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
local done = false
@@ -717,10 +717,10 @@ local function inject_kerns_only(head,where)
if done then
setdisc(current,pre,post,replace)
end
- prevglyph = nil
+ -- prevglyph = nil
prevdisc = current
else
- prevglyph = nil
+ -- prevglyph = nil
prevdisc = nil
end
prev = current
@@ -966,7 +966,7 @@ local function inject_pairs_only(head,where)
if keepregisteredcounts then
keepregisteredcounts = false
else
- nofregisteredkerns = 0
+ nofregisteredpairs = 0
end
if trace_injections then
show_result(head)
@@ -1548,7 +1548,8 @@ local function injectspaces(head)
factor = getthreshold(font)
end
- for n in traverse_id(glue_code,tonut(head)) do
+ -- for n in traverse_id(glue_code,tonut(head)) do
+ for n in traverse_char(tonut(head)) do
local prev, next = getspaceboth(n)
local prevchar = prev and ischar(prev)
local nextchar = next and ischar(next)
diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua
index 2661ac5c1..1cdbb450a 100644
--- a/tex/context/base/mkiv/font-otl.lua
+++ b/tex/context/base/mkiv/font-otl.lua
@@ -52,7 +52,7 @@ local report_otf = logs.reporter("fonts","otf loading")
local fonts = fonts
local otf = fonts.handlers.otf
-otf.version = 3.031 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.version = 3.032 -- beware: also sync font-mis.lua and in mtx-fonts
otf.cache = containers.define("fonts", "otl", otf.version, true)
otf.svgcache = containers.define("fonts", "svg", otf.version, true)
otf.sbixcache = containers.define("fonts", "sbix", otf.version, true)
diff --git a/tex/context/base/mkiv/font-oto.lua b/tex/context/base/mkiv/font-oto.lua
index 22bb1d74e..0009d7f5f 100644
--- a/tex/context/base/mkiv/font-oto.lua
+++ b/tex/context/base/mkiv/font-oto.lua
@@ -368,9 +368,13 @@ local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist
local character = characters[unicode]
local kerns = character.kerns
for otherunicode, kern in next, data do
- if not kern[2] and not (kerns and kerns[otherunicode]) then
+ -- kern[2] is true (all zero) or a table
+ local other = kern[2]
+ if other == true or (not other and not (kerns and kerns[otherunicode])) then
local kern = kern[1]
- if kern[1] ~= 0 or kern[2] ~= 0 or kern[4] ~= 0 then
+ if kern == true then
+ -- all zero
+ elseif kern[1] ~= 0 or kern[2] ~= 0 or kern[4] ~= 0 then
-- a complex pair not suitable for basemode
else
kern = kern[3]
@@ -400,6 +404,43 @@ local function initializehashes(tfmdata)
-- already done
end
+local function checkmathreplacements(tfmdata,fullname)
+ if tfmdata.mathparameters then
+ local characters = tfmdata.characters
+ local changed = tfmdata.changed
+ if next(changed) then
+ if trace_preparing or trace_baseinit then
+ report_prepare("checking math replacements for %a",fullname)
+ end
+ for unicode, replacement in next, changed do
+ local u = characters[unicode]
+ local r = characters[replacement]
+ local n = u.next
+ local v = u.vert_variants
+ local h = u.horiz_variants
+ if n and not r.next then
+ if trace_preparing then
+ report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement)
+ end
+ r.next = n
+ end
+ if v and not r.vert_variants then
+ if trace_preparing then
+ report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement)
+ end
+ r.vert_variants = v
+ end
+ if h and not r.horiz_variants then
+ if trace_preparing then
+ report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement)
+ end
+ r.horiz_variants = h
+ end
+ end
+ end
+ end
+end
+
local function featuresinitializer(tfmdata,value)
if true then -- value then
local starttime = trace_preparing and os.clock()
@@ -416,6 +457,8 @@ local function featuresinitializer(tfmdata,value)
local rawfeatures = rawresources and rawresources.features
local basesubstitutions = rawfeatures and rawfeatures.gsub
local basepositionings = rawfeatures and rawfeatures.gpos
+ local substitutionsdone = false
+ local positioningsdone = false
--
if basesubstitutions or basepositionings then
local sequences = tfmdata.resources.sequences
@@ -438,12 +481,14 @@ local function featuresinitializer(tfmdata,value)
end
preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
registerbasefeature(feature,value)
+ substitutionsdone = true
elseif basepositionings and basepositionings[feature] then
if trace_preparing then
report_prepare("filtering base %a feature %a for %a with value %a","pos",feature,fullname,value)
end
preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
registerbasefeature(feature,value)
+ positioningsdone = true
end
end
end
@@ -452,6 +497,10 @@ local function featuresinitializer(tfmdata,value)
end
end
--
+ if substitutionsdone then
+ checkmathreplacements(tfmdata,fullname)
+ end
+ --
registerbasehash(tfmdata)
end
if trace_preparing then
diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua
index a5a039525..26659721f 100644
--- a/tex/context/base/mkiv/font-ots.lua
+++ b/tex/context/base/mkiv/font-ots.lua
@@ -148,7 +148,6 @@ local trace_compruns = false registertracker("otf.compruns", function
local trace_testruns = false registertracker("otf.testruns", function(v) trace_testruns = v end)
local forcediscretionaries = false
-local optimizekerns = true
directives.register("otf.forcediscretionaries",function(v)
forcediscretionaries = v
@@ -207,7 +206,7 @@ local flush_node_list = nuts.flush_list
local flush_node = nuts.flush_node
local end_of_math = nuts.end_of_math
local traverse_nodes = nuts.traverse
-local traverse_id = nuts.traverse_id
+----- traverse_id = nuts.traverse_id
local set_components = nuts.set_components
local take_components = nuts.take_components
local count_components = nuts.count_components
@@ -271,6 +270,8 @@ local factor = 0
local threshold = 0
local checkmarks = false
+local discs = false
+
local sweepnode = nil
local sweephead = { } -- we don't nil entries but false them (no collection and such)
@@ -305,47 +306,56 @@ local function logwarning(...)
report_direct(...)
end
-local f_unicode = formatters["U+%X"] -- was ["%U"]
-local f_uniname = formatters["U+%X (%s)"] -- was ["%U (%s)"]
-local f_unilist = formatters["% t (% t)"]
+local gref do
-local function gref(n) -- currently the same as in font-otb
- if type(n) == "number" then
- local description = descriptions[n]
- local name = description and description.name
- if name then
- return f_uniname(n,name)
- else
- return f_unicode(n)
- end
- elseif n then
- local num, nam = { }, { }
- for i=1,#n do
- local ni = n[i]
- if tonumber(ni) then -- later we will start at 2
- local di = descriptions[ni]
- num[i] = f_unicode(ni)
- nam[i] = di and di.name or "-"
+ local f_unicode = formatters["U+%X"] -- was ["%U"]
+ local f_uniname = formatters["U+%X (%s)"] -- was ["%U (%s)"]
+ local f_unilist = formatters["% t (% t)"]
+
+ gref = function(n) -- currently the same as in font-otb
+ if type(n) == "number" then
+ local description = descriptions[n]
+ local name = description and description.name
+ if name then
+ return f_uniname(n,name)
+ else
+ return f_unicode(n)
end
+ elseif n then
+ local num, nam = { }, { }
+ for i=1,#n do
+ local ni = n[i]
+ if tonumber(ni) then -- later we will start at 2
+ local di = descriptions[ni]
+ num[i] = f_unicode(ni)
+ nam[i] = di and di.name or "-"
+ end
+ end
+ return f_unilist(num,nam)
+ else
+ return "<error in node mode tracing>"
end
- return f_unilist(num,nam)
- else
- return "<error in node mode tracing>"
end
+
end
local function cref(dataset,sequence,index)
if not dataset then
return "no valid dataset"
- elseif index then
- return formatters["feature %a, type %a, chain lookup %a, index %a"](dataset[4],sequence.type,sequence.name,index)
+ end
+ local merged = sequence.merged and "merged " or ""
+ if index then
+ return formatters["feature %a, type %a, %schain lookup %a, index %a"](
+ dataset[4],sequence.type,merged,sequence.name,index)
else
- return formatters["feature %a, type %a, chain lookup %a"](dataset[4],sequence.type,sequence.name)
+ return formatters["feature %a, type %a, %schain lookup %a"](
+ dataset[4],sequence.type,merged,sequence.name)
end
end
local function pref(dataset,sequence)
- return formatters["feature %a, type %a, lookup %a"](dataset[4],sequence.type,sequence.name)
+ return formatters["feature %a, type %a, %slookup %a"](
+ dataset[4],sequence.type,sequence.merged and "merged " or "",sequence.name)
end
local function mref(rlmode)
@@ -689,7 +699,7 @@ function handlers.gsub_alternate(head,start,dataset,sequence,alternative)
setchar(start,choice)
else
if trace_alternatives then
- logwarning("%s: no variant %a for %s, %s",pref(dataset,sequence),value,gref(getchar(start)),comment)
+ logwarning("%s: no variant %a for %s, %s",pref(dataset,sequence),value,gref(getchar(start)),comment)
end
end
return head, start, true
@@ -850,36 +860,32 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
if nextchar then
local krn = kerns[nextchar]
if not krn and marks[nextchar] then
+ -- hm, needs checking i guess
prev = snext
snext = getnext(snext)
elseif not krn then
break
elseif step.format == "pair" then
local a, b = krn[1], krn[2]
- if optimizekerns then
- -- this permits a mixed table, but we could also decide to optimize this
- -- in the loader and use format 'kern'
- if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then
- local k = setkern(snext,factor,rlmode,a[3],injection)
- if trace_kerns then
- logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
- end
- return head, start, true
- end
- end
- if a and #a > 0 then
+ if a == true then
+ -- zero
+ elseif a then -- #a > 0
local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection)
if trace_kerns then
local startchar = getchar(start)
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
end
end
- if b and #b > 0 then
+ if b == true then
+ -- zero
+ start = snext -- cf spec
+ elseif b then -- #b > 0
local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
if trace_kerns then
local startchar = getchar(snext)
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
end
+ start = snext -- cf spec
end
return head, start, true
elseif krn ~= 0 then
@@ -1073,8 +1079,7 @@ function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,st
if not nextchar then
break
elseif marks[nextchar] then
- -- should not happen (maybe warning)
- nxt = getnext(nxt)
+ nxt = getnext(nxt)
else
local exit = exitanchors[3]
if exit then
@@ -1458,30 +1463,25 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
break
elseif step.format == "pair" then
local a, b = krn[1], krn[2]
- if optimizekerns then
- -- this permits a mixed table, but we could also decide to optimize this
- -- in the loader and use format 'kern'
- if not b and a[1] == 0 and a[2] == 0 and a[4] == 0 then
- local k = setkern(snext,factor,rlmode,a[3],"injections")
- if trace_kerns then
- logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k)
- end
- return head, start, true
- end
- end
- if a and #a > 0 then
- local startchar = getchar(start)
+ if a then
+ -- zero
+ elseif a then
local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,"injections") -- currentlookups flags?
if trace_kerns then
+ local startchar = getchar(start)
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
end
end
- if b and #b > 0 then
- local startchar = getchar(start)
+ if b == true then
+ -- zero
+ start = snext -- cf spec
+ elseif b then -- #b > 0
local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,"injections")
if trace_kerns then
+ local startchar = getchar(start)
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
end
+ start = snext -- cf spec
end
return head, start, true
elseif krn ~= 0 then
@@ -1836,20 +1836,21 @@ local noflags = { false, false, false, false }
local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
local size = ck[5] - ck[4] + 1
- local flags = sequence.flags or noflags
- local done = false
- local skipmark = flags[1]
local chainlookups = ck[6]
+ local done = false
-- current match
if chainlookups then
- local nofchainlookups = #chainlookups
+
-- Lookups can be like { 1, false, 3 } or { false, 2 } or basically anything and
-- #lookups can be less than #current
+
if size == 1 then
+
-- if nofchainlookups > size then
-- -- bad rules
-- end
+
local chainlookup = chainlookups[1]
for j=1,#chainlookup do
local chainstep = chainlookup[j]
@@ -1865,7 +1866,9 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
end
end
+
else
+
-- See LookupType 5: Contextual Substitution Subtable. Now it becomes messy. The
-- easiest case is where #current maps on #lookups i.e. one-to-one. But what if
-- we have a ligature. Cf the spec we then need to advance one character but we
@@ -1876,10 +1879,27 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
--
-- Even worse are these family emoji shapes as they can have multiple lookups
-- per slot (probably only for gpos).
+
+ -- It's very unlikely that we will have skip classes here but still ... we seldom
+ -- enter this branch anyway.
+
+ local skipmark
+ local skipligature
+ local skipbase
+ local markclass
+ if skipped then
+ local flags = sequence.flags or noflags
+ skipmark = flags[1]
+ skipligature = flags[2]
+ skipbase = flags[3]
+ markclass = sequence.markclass
+ end
+
local i = 1
local laststart = start
+ local nofchainlookups = #chainlookups -- useful?
while start do
- if skipped then
+ if skipped then -- hm, so we know we skip some
while start do
local char, id = ischar(start,currentfont)
if char then
@@ -1932,6 +1952,7 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
if not start then
start = laststart
end
+
end
else
-- todo: needs checking for holes in the replacements
@@ -2762,11 +2783,12 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local checkdisc = sweeptype and getprev(head)
local flags = sequence.flags or noflags
local done = false
+ local markclass = sequence.markclass
local skipmark = flags[1]
local skipligature = flags[2]
local skipbase = flags[3]
- local markclass = sequence.markclass
- local skipsome = skipmark ~= false or skipligature ~= false or skipbase ~= false or markclass
+ -- local skipsome = skipmark ~= false or skipligature ~= false or skipbase ~= false or markclass
+ local skipsome = flags[5]
local skipped = false
local startprev,
startnext = getboth(start)
@@ -2778,7 +2800,6 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local ck = contexts[k]
local seq = ck[3]
local s = #seq
- local size = 1
-- f..l = mid string
if s == 1 then
-- this seldom happens as it makes no sense (bril, ebgaramond, husayni, minion)
@@ -2793,12 +2814,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local l = ck[5]
-- current match
-- seq[f][ischar(current,currentfont)] is not nil
- size = l - f + 1
- if size > 1 then
+ if l > f then
-- before/current/after | before/current | current/after
local discfound -- = nil
local n = f + 1
- -- last = getnext(last) -- the second in current (first already matched)
last = startnext -- the second in current (first already matched)
while n <= l do
if not last and (sweeptype == "post" or sweeptype == "replace") then
@@ -2923,13 +2942,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
-- before
if match and f > 1 then
- -- local prev = getprev(start)
- -- if prev then
if startprev then
local prev = startprev
if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then
- prev = getprev(sweepnode)
- -- sweeptype = nil
+ prev = getprev(sweepnode)
end
if prev then
local discfound -- = nil
@@ -3074,8 +3090,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if match and s > l then
local current = last and getnext(last)
if not current and (sweeptype == "post" or sweeptype == "replace") then
- current = getnext(sweepnode)
- -- sweeptype = nil
+ current = getnext(sweepnode)
end
if current then
local discfound -- = nil
@@ -3232,6 +3247,503 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
return head, start, done
end
+-- only a bit faster but probably also a bit cleaner ... so ...
+
+local function optimized_handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
+ -- optimizing for rlmode gains nothing
+ local sweepnode = sweepnode
+ local sweeptype = sweeptype
+ local postreplace
+ local prereplace
+ local checkdisc
+ local diskseen -- = false
+ if sweeptype then
+ if sweeptype == "replace" then
+ postreplace = true
+ prereplace = true
+ else
+ postreplace = sweeptype == "post"
+ prereplace = sweeptype == "pre"
+ end
+ checkdisc = getprev(head)
+ end
+ local currentfont = currentfont
+ local flags = sequence.flags or noflags
+ local skipsome = flags[5]
+ local skipmark
+ local skipligature
+ local skipbase
+ local markclass
+ if skipsome then
+ skipmark = flags[1]
+ skipligature = flags[2]
+ skipbase = flags[3]
+ markclass = sequence.markclass
+ end
+ local skipped -- = false
+ local startprev,
+ startnext = getboth(start)
+ local done -- = false
+
+ for k=1,contexts.n do -- or #contexts do
+ local current = start
+ local last = start
+ local ck = contexts[k]
+ local seq = ck[3]
+ -- local s = #seq
+ local s = seq.n -- or #seq
+ -- f..l = mid string
+ if s == 1 then
+ -- this seldom happens as it makes no sense (bril, ebgaramond, husayni, minion)
+ local char = ischar(current,currentfont)
+ if char and not seq[1][char] then
+ goto next
+ end
+ else
+ -- maybe we need a better space check (maybe check for glue or category or combination)
+ local f = ck[4]
+ local l = ck[5]
+ -- current match
+ -- seq[f][ischar(current,currentfont)] is not nil
+ if l > f then
+ -- before/current/after | before/current | current/after
+ local discfound -- = nil
+ local n = f + 1
+ last = startnext -- the second in current (first already matched)
+ while n <= l do
+ if not last and postreplace then
+ last = getnext(sweepnode)
+ sweeptype = nil
+ end
+ if last then
+ local char, id = ischar(last,currentfont)
+ if char then
+ if skipsome then
+ local class = classes[char]
+ -- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ if class == skipmark or (markclass and class == "mark" and not markclass[char]) or class == skipligature or class == skipbase then
+ skipped = true
+ if trace_skips then
+ show_skip(dataset,sequence,char,ck,class)
+ end
+ last = getnext(last)
+ elseif seq[n][char] then
+ if n < l then
+ last = getnext(last)
+ end
+ n = n + 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ else
+ if seq[n][char] then
+ if n < l then
+ last = getnext(last)
+ end
+ n = n + 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ end
+ elseif char == false then
+ if discfound then
+ notmatchreplace[discfound] = true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ elseif id == disc_code then
+ -- elseif id == disc_code and (not discs or discs[last]) then
+ diskseen = true
+ discfound = last
+ notmatchpre[last] = nil
+ notmatchpost[last] = true
+ notmatchreplace[last] = nil
+ local pre, post, replace = getdisc(last)
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ if n > l then
+ break
+ end
+ pre = getnext(pre)
+ else
+ notmatchpre[last] = true
+ break
+ end
+ end
+ if n <= l then
+ notmatchpre[last] = true
+ end
+ else
+ notmatchpre[last] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ if n > l then
+ break
+ end
+ replace = getnext(replace)
+ else
+ notmatchreplace[last] = true
+ if notmatchpre[last] then
+ goto next
+ end
+ break
+ end
+ end
+ -- why here again
+ if notmatchpre[last] then
+ goto next
+ end
+ end
+ -- maybe only if match
+ last = getnext(last)
+ else
+ goto next
+ end
+ else
+ goto next
+ end
+ end
+ end
+ -- before
+ if f > 1 then
+ if startprev then
+ local prev = startprev
+ if prereplace and prev == checkdisc then
+ prev = getprev(sweepnode)
+ end
+ if prev then
+ local discfound -- = nil
+ local n = f - 1
+ while n >= 1 do
+ if prev then
+ local char, id = ischar(prev,currentfont)
+ if char then
+ if skipsome then
+ local class = classes[char]
+ -- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ if class == skipmark or (markclass and class == "mark" and not markclass[char]) or class == skipligature or class == skipbase then
+ skipped = true
+ if trace_skips then
+ show_skip(dataset,sequence,char,ck,class)
+ end
+ prev = getprev(prev)
+ elseif seq[n][char] then
+ if n > 1 then
+ prev = getprev(prev)
+ end
+ n = n - 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ if notmatchpost[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ else
+ if seq[n][char] then
+ if n > 1 then
+ prev = getprev(prev)
+ end
+ n = n - 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ if notmatchpost[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ end
+ elseif char == false then
+ if discfound then
+ notmatchreplace[discfound] = true
+ if notmatchpost[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ elseif id == disc_code then
+ -- elseif id == disc_code and (not discs or discs[prev]) then
+ -- the special case: f i where i becomes dottless i ..
+ diskseen = true
+ discfound = prev
+ notmatchpre[prev] = true
+ notmatchpost[prev] = nil
+ notmatchreplace[prev] = nil
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(prev,true)
+ if pre ~= start and post ~= start and replace ~= start then
+ if post then
+ local n = n
+ while posttail do
+ if seq[n][getchar(posttail)] then
+ n = n - 1
+ if posttail == post then
+ break
+ else
+ if n < 1 then
+ break
+ end
+ posttail = getprev(posttail)
+ end
+ else
+ notmatchpost[prev] = true
+ break
+ end
+ end
+ if n >= 1 then
+ notmatchpost[prev] = true
+ end
+ else
+ notmatchpost[prev] = true
+ end
+ if replace then
+ -- we seldom enter this branch (e.g. on brill efficient)
+ while replacetail do
+ if seq[n][getchar(replacetail)] then
+ n = n - 1
+ if replacetail == replace then
+ break
+ else
+ if n < 1 then
+ break
+ end
+ replacetail = getprev(replacetail)
+ end
+ else
+ notmatchreplace[prev] = true
+ if notmatchpost[prev] then
+ goto next
+ end
+ break
+ end
+ end
+ end
+ end
+ prev = getprev(prev)
+ elseif id == glue_code and seq[n][32] and isspace(prev,threshold,id) then
+ n = n - 1
+ prev = getprev(prev)
+ else
+ goto next
+ end
+ else
+ goto next
+ end
+ end
+ else
+ goto next
+ end
+ else
+ goto next
+ end
+ end
+ -- after
+ if s > l then
+ local current = last and getnext(last)
+ if not current and postreplace then
+ current = getnext(sweepnode)
+ end
+ if current then
+ local discfound -- = nil
+ local n = l + 1
+ while n <= s do
+ if current then
+ local char, id = ischar(current,currentfont)
+ if char then
+ if skipsome then
+ local class = classes[char]
+ -- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ if class == skipmark or (markclass and class == "mark" and not markclass[char]) or class == skipligature or class == skipbase then
+ skipped = true
+ if trace_skips then
+ show_skip(dataset,sequence,char,ck,class)
+ end
+ current = getnext(current) -- was absent
+ elseif seq[n][char] then
+ if n < s then -- new test
+ current = getnext(current) -- was absent
+ end
+ n = n + 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ else
+ if seq[n][char] then
+ if n < s then -- new test
+ current = getnext(current) -- was absent
+ end
+ n = n + 1
+ else
+ if discfound then
+ notmatchreplace[discfound] = true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ end
+ elseif char == false then
+ if discfound then
+ notmatchreplace[discfound] = true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ elseif id == disc_code then
+ -- elseif id == disc_code and (not discs or discs[current]) then
+ diskseen = true
+ discfound = current
+ notmatchpre[current] = nil
+ notmatchpost[current] = true
+ notmatchreplace[current] = nil
+ local pre, post, replace = getdisc(current)
+ if pre then
+ local n = n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n = n + 1
+ if n > s then
+ break
+ end
+ pre = getnext(pre)
+ else
+ notmatchpre[current] = true
+ break
+ end
+ end
+ if n <= s then
+ notmatchpre[current] = true
+ end
+ else
+ notmatchpre[current] = true
+ end
+ if replace then
+ -- so far we never entered this branch
+ while replace do
+ if seq[n][getchar(replace)] then
+ n = n + 1
+ if n > s then
+ break
+ end
+ replace = getnext(replace)
+ else
+ notmatchreplace[current] = true
+ -- different than others, needs checking if "not" is okay
+ if not notmatchpre[current] then
+ goto next
+ end
+ break
+ end
+ end
+ else
+ -- skip 'm
+ end
+ current = getnext(current)
+ elseif id == glue_code and seq[n][32] and isspace(current,threshold,id) then
+ n = n + 1
+ current = getnext(current)
+ else
+ goto next
+ end
+ else
+ goto next
+ end
+ end
+ else
+ goto next
+ end
+ end
+ end
+ if trace_contexts then
+ chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,true)
+ end
+ if diskseen or sweepnode then
+ head, start, done = chaindisk(head,start,dataset,sequence,rlmode,ck,skipped)
+ else
+ head, start, done = chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
+ end
+ if done then
+ break
+ -- else
+ -- next context
+ end
+ ::next::
+ -- if trace_chains then
+ -- chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,match)
+ -- end
+ end
+ if diskseen then
+ notmatchpre = { }
+ notmatchpost = { }
+ notmatchreplace = { }
+ end
+ return head, start, done
+end
+
+directives.register("otf.optimizechains",function(v)
+ if v then
+ report_chain()
+ report_chain("using experimental optimized code")
+ report_chain()
+ end
+ local handle = v and optimized_handle_contextchain or handle_contextchain
+ handlers.gsub_context = handle
+ handlers.gsub_contextchain = handle
+ handlers.gsub_reversecontextchain = handle
+ handlers.gpos_contextchain = handle
+ handlers.gpos_context = handle
+end)
+
------------------------------
handlers.gsub_context = handle_contextchain
@@ -3275,7 +3787,9 @@ chainprocs.gpos_context = chained_contextchain
-- end
-- end
-local missing = setmetatableindex("table")
+local missing = setmetatableindex("table")
+local logwarning = report_process
+local resolved = { } -- we only resolve a font,script,language pair once
local function logprocess(...)
if trace_steps then
@@ -3284,19 +3798,6 @@ local function logprocess(...)
report_process(...)
end
-local logwarning = report_process
-
-local function report_missing_coverage(dataset,sequence)
- local t = missing[currentfont]
- if not t[sequence] then
- t[sequence] = true
- logwarning("missing coverage for feature %a, lookup %a, type %a, font %a, name %a",
- dataset[4],sequence.name,sequence.type,currentfont,tfmdata.properties.fullname)
- end
-end
-
-local resolved = { } -- we only resolve a font,script,language pair once
-
-- todo: pass all these 'locals' in a table
local sequencelists = setmetatableindex(function(t,font)
@@ -3582,12 +4083,11 @@ local function testrun(disc,t_run,c_run,...)
end
local d_post = t_run(post,next,...)
local d_replace = t_run(replace,next,...)
- if (d_post and d_post > 0) or (d_replace and d_replace > 0) then
- local d = d_replace or d_post
- if d_post and d < d_post then
- d = d_post
- end
- local head, tail = getnext(disc), disc
+ if d_post > 0 or d_replace > 0 then
+ local d = d_replace > d_post and d_replace or d_post
+ local head = getnext(disc)
+ -- local tail = disc -- bug
+ local tail = head
for i=1,d do
tail = getnext(tail)
if getid(tail) == disc_code then
@@ -3696,7 +4196,6 @@ end
-- 1{2{\oldstyle\discretionary{3}{4}{5}}6}7\par
-- 1{2\discretionary{3{\oldstyle3}}{{\oldstyle4}4}{5{\oldstyle5}5}6}7\par
-
local nesting = 0
local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
@@ -3818,6 +4317,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
break
end
end
+ return 0
end
local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
@@ -3865,22 +4365,18 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
for i=1,nofsteps do
local step = steps[i]
local lookupcache = step.coverage
- if lookupcache then
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- -- we could move all code inline but that makes things even more unreadable
- local ok
- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- if ok then
- done = true
- break
- elseif not start then
- -- don't ask why ... shouldn't happen
- break
- end
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- we could move all code inline but that makes things even more unreadable
+ local ok
+ head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+ if ok then
+ done = true
+ break
+ elseif not start then
+ -- don't ask why ... shouldn't happen
+ break
end
- else
- report_missing_coverage(dataset,sequence)
end
end
if start then
@@ -3918,60 +4414,56 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
for i=1,nofsteps do
local step = steps[i]
local lookupcache = step.coverage
- if lookupcache then
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- -- if we need more than ligatures we can outline the code and use functions
- local s = startnext
- local ss = nil
- local sstop = s == stop
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- if we need more than ligatures we can outline the code and use functions
+ local s = startnext
+ local ss = nil
+ local sstop = s == stop
+ if not s then
+ s = ss
+ ss = nil
+ end
+ while getid(s) == disc_code do
+ ss = getnext(s)
+ s = getfield(s,"replace")
if not s then
s = ss
ss = nil
end
- while getid(s) == disc_code do
- ss = getnext(s)
- s = getfield(s,"replace")
+ end
+ local l = nil
+ local d = 0
+ while s do
+ local lg = lookupmatch[getchar(s)]
+ if lg then
+ if sstop then
+ d = 1
+ elseif d > 0 then
+ d = d + 1
+ end
+ l = lg
+ s = getnext(s)
+ sstop = s == stop
if not s then
s = ss
ss = nil
end
- end
- local l = nil
- local d = 0
- while s do
- local lg = lookupmatch[getchar(s)]
- if lg then
- if sstop then
- d = 1
- elseif d > 0 then
- d = d + 1
- end
- l = lg
- s = getnext(s)
- sstop = s == stop
+ while getid(s) == disc_code do
+ ss = getnext(s)
+ s = getfield(s,"replace")
if not s then
s = ss
ss = nil
end
- while getid(s) == disc_code do
- ss = getnext(s)
- s = getfield(s,"replace")
- if not s then
- s = ss
- ss = nil
- end
- end
- else
- break
end
- end
- if l and l.ligature then
- lastd = d
+ else
+ break
end
end
- else
- report_missing_coverage(dataset,sequence)
+ if l and l.ligature then
+ lastd = d
+ end
end
end
else
@@ -3985,6 +4477,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
break
end
end
+ return 0
end
local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
@@ -4002,16 +4495,12 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase
for i=1,nofsteps do
local step = steps[i]
local lookupcache = step.coverage
- if lookupcache then
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- local h, d, ok = handler(head,n,dataset,sequence,lookupmatch,rlmode,step,i,injection)
- if ok then
- return true
- end
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ local h, d, ok = handler(head,n,dataset,sequence,lookupmatch,rlmode,step,i,injection)
+ if ok then
+ return true
end
- else
- report_missing_coverage(dataset,sequence)
end
end
end
@@ -4074,6 +4563,26 @@ otf.helpers.pardirstate = pardirstate
do
+ -- reference:
+ --
+ -- local a = attr and getattr(start,0)
+ -- if a then
+ -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ -- else
+ -- a = not attribute or getprop(start,a_state) == attribute
+ -- end
+ --
+ -- used:
+ --
+ -- local a -- happens often so no assignment is faster
+ -- if attr then
+ -- if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then
+ -- a = true
+ -- end
+ -- elseif not attribute or getprop(start,a_state) == attribute then
+ -- a = true
+ -- end
+
-- This is a measurable experimental speedup (only with hyphenated text and multiple
-- fonts per processor call), especially for fonts with lots of contextual lookups.
@@ -4184,19 +4693,15 @@ do
-- for i=1,nofsteps do
-- local step = steps[i]
-- local lookupcache = step.coverage
- -- if lookupcache then
- -- local lookupmatch = lookupcache[char]
- -- if lookupmatch then
- -- -- todo: disc?
- -- local ok
- -- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- -- if ok then
- -- done = true
- -- break
- -- end
+ -- local lookupmatch = lookupcache[char]
+ -- if lookupmatch then
+ -- -- todo: disc?
+ -- local ok
+ -- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+ -- if ok then
+ -- done = true
+ -- break
-- end
- -- else
- -- report_missing_coverage(dataset,sequence)
-- end
-- end
-- if start then
@@ -4215,72 +4720,62 @@ do
-- if nofsteps == 1 then -- happens often
-- local step = steps[1]
-- local lookupcache = step.coverage
- -- if not lookupcache then
- -- report_missing_coverage(dataset,sequence)
- -- else
- -- while start do
- -- local char, id = ischar(start,font)
- -- if char then
- -- -- local a = attr and getattr(start,0)
- -- -- if a then
- -- -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
- -- -- else
- -- -- a = not attribute or getprop(start,a_state) == attribute
- -- -- end
- -- local a -- happens often so no assignment is faster
- -- if attr then
- -- if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then
- -- a = true
- -- end
- -- elseif not attribute or getprop(start,a_state) == attribute then
+ -- while start do
+ -- local char, id = ischar(start,font)
+ -- if char then
+ -- local a -- happens often so no assignment is faster
+ -- if attr then
+ -- if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then
-- a = true
-- end
- -- if a then
- -- local lookupmatch = lookupcache[char]
- -- if lookupmatch then
- -- local ok
- -- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
- -- if ok then
- -- done = true
- -- end
- -- end
- -- if start then
- -- start = getnext(start)
- -- end
- -- else
- -- start = getnext(start)
- -- end
- -- elseif char == false then
- -- -- whatever glyph
- -- start = getnext(start)
- -- elseif id == glue_code then
- -- -- happens often
- -- start = getnext(start)
- -- elseif id == disc_code then
- -- if not discs or discs[start] == true then
+ -- elseif not attribute or getprop(start,a_state) == attribute then
+ -- a = true
+ -- end
+ -- if a then
+ -- local lookupmatch = lookupcache[char]
+ -- if lookupmatch then
-- local ok
- -- if gpossing then
- -- start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- -- elseif typ == "gsub_ligature" then
- -- start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- -- else
- -- start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- -- end
+ -- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
-- if ok then
-- done = true
-- end
- -- else
+ -- end
+ -- if start then
-- start = getnext(start)
-- end
- -- elseif id == math_code then
- -- start = getnext(end_of_math(start))
- -- elseif id == dir_code then
- -- start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
- -- elseif id == localpar_code then
- -- start, rlparmode, rlmode = pardirstate(start)
+ -- else
+ -- start = getnext(start)
+ -- end
+ -- elseif char == false then
+ -- -- whatever glyph
+ -- start = getnext(start)
+ -- elseif id == glue_code then
+ -- -- happens often
+ -- start = getnext(start)
+ -- elseif id == disc_code then
+ -- if not discs or discs[start] == true then
+ -- local ok
+ -- if gpossing then
+ -- start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ -- elseif typ == "gsub_ligature" then
+ -- start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ -- else
+ -- start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ -- end
+ -- if ok then
+ -- done = true
+ -- end
-- else
-- start = getnext(start)
-- end
+ -- elseif id == math_code then
+ -- start = getnext(end_of_math(start))
+ -- elseif id == dir_code then
+ -- start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
+ -- elseif id == localpar_code then
+ -- start, rlparmode, rlmode = pardirstate(start)
+ -- else
+ -- start = getnext(start)
-- end
-- end
--
@@ -4288,12 +4783,6 @@ do
-- while start do
-- local char, id = ischar(start,font)
-- if char then
- -- -- local a = attr and getattr(start,0)
- -- -- if a then
- -- -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
- -- -- else
- -- -- a = not attribute or getprop(start,a_state) == attribute
- -- -- end
-- local a -- happens often so no assignment is faster
-- if attr then
-- if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then
@@ -4306,22 +4795,18 @@ do
-- for i=1,nofsteps do
-- local step = steps[i]
-- local lookupcache = step.coverage
- -- if lookupcache then
- -- local lookupmatch = lookupcache[char]
- -- if lookupmatch then
- -- -- we could move all code inline but that makes things even more unreadable
- -- local ok
- -- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- -- if ok then
- -- done = true
- -- break
- -- elseif not start then
- -- -- don't ask why ... shouldn't happen
- -- break
- -- end
+ -- local lookupmatch = lookupcache[char]
+ -- if lookupmatch then
+ -- -- we could move all code inline but that makes things even more unreadable
+ -- local ok
+ -- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+ -- if ok then
+ -- done = true
+ -- break
+ -- elseif not start then
+ -- -- don't ask why ... shouldn't happen
+ -- break
-- end
- -- else
- -- report_missing_coverage(dataset,sequence)
-- end
-- end
-- if start then
@@ -4381,6 +4866,14 @@ do
-- about 15% on arabtype .. then moving the a test also saves a bit (even when
-- often a is not set at all so that one is a bit debatable
+ local otfdataset = nil -- todo: make an installer
+
+ local getfastdics = function(t,k)
+ local v = usesfont(k,currentfont)
+ t[k] = v
+ return v
+ end
+
function otf.featuresprocessor(head,font,attr,direction,n)
local sequences = sequencelists[font] -- temp hack
@@ -4403,6 +4896,12 @@ do
factor = getthreshold(font)
checkmarks = tfmdata.properties.checkmarks
+ if not otfdataset then
+ otfdataset = otf.dataset
+ end
+
+ discs = fastdisc and n and n > 1 and setmetatableindex(getfastdisc) -- maybe inline
+
elseif currentfont ~= font then
report_warning("nested call with a different font, level %s, quitting",nesting)
@@ -4419,7 +4918,7 @@ do
-- attr = false
-- end
- head = tonut(head)
+ local head = tonut(head)
if trace_steps then
checkstep(head)
@@ -4428,7 +4927,8 @@ do
local initialrl = direction == "TRT" and -1 or 0
local done = false
- local datasets = otf.dataset(tfmdata,font,attr)
+ -- local datasets = otf.dataset(tfmdata,font,attr)
+ local datasets = otfdataset(tfmdata,font,attr)
local dirstack = { } -- could move outside function but we can have local runs
sweephead = { }
@@ -4438,12 +4938,6 @@ do
-- We don't goto the next node when a disc node is created so that we can then treat
-- the pre, post and replace. It's a bit of a hack but works out ok for most cases.
- local discs = fastdisc and n and n > 1 and setmetatableindex(function(t,k)
- local v = usesfont(k,font)
- t[k] = v
- return v
- end)
-
for s=1,#datasets do
local dataset = datasets[s]
----- featurevalue = dataset[1] -- todo: pass to function instead of using a global
@@ -4453,7 +4947,7 @@ do
local topstack = 0
local typ = sequence.type
local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- store in dataset
- local handler = handlers[typ]
+ local handler = handlers[typ] -- store in dataset
local steps = sequence.steps
local nofsteps = sequence.nofsteps
if not steps then
@@ -4489,19 +4983,15 @@ do
-- for i=1,#m do
-- local step = m[i]
local lookupcache = step.coverage
- if lookupcache then
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- -- todo: disc?
- local ok
- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- if ok then
- done = true
- break
- end
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- todo: disc?
+ local ok
+ head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+ if ok then
+ done = true
+ break
end
- else
- report_missing_coverage(dataset,sequence)
end
end
if start then
@@ -4523,74 +5013,64 @@ do
if nofsteps == 1 then -- happens often
local step = steps[1]
local lookupcache = step.coverage
- if not lookupcache then
- report_missing_coverage(dataset,sequence)
- else
- while start do
- local char, id = ischar(start,font)
- if char then
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- -- local a = attr and getattr(start,0)
- -- if a then
- -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
- -- else
- -- a = not attribute or getprop(start,a_state) == attribute
- -- end
- local a -- happens often so no assignment is faster
- if attr then
- if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then
- a = true
- end
- elseif not attribute or getprop(start,a_state) == attribute then
+ while start do
+ local char, id = ischar(start,font)
+ if char then
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ local a -- happens often so no assignment is faster
+ if attr then
+ if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then
a = true
end
- if a then
- local ok
- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
- if ok then
- done = true
- end
- if start then
- start = getnext(start)
- end
- else
- start = getnext(start)
- end
- else
- start = getnext(start)
+ elseif not attribute or getprop(start,a_state) == attribute then
+ a = true
end
- elseif char == false then
- -- whatever glyph
- start = getnext(start)
- elseif id == glue_code then
- -- happens often
- start = getnext(start)
- elseif id == disc_code then
- if not discs or discs[start] == true then
+ if a then
local ok
- if gpossing then
- start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- elseif typ == "gsub_ligature" then
- start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- else
- start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- end
+ head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
if ok then
done = true
end
+ if start then
+ start = getnext(start)
+ end
else
start = getnext(start)
end
- elseif id == math_code then
- start = getnext(end_of_math(start))
- elseif id == dir_code then
- start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
- elseif id == localpar_code then
- start, rlparmode, rlmode = pardirstate(start)
+ else
+ start = getnext(start)
+ end
+ elseif char == false then
+ -- whatever glyph
+ start = getnext(start)
+ elseif id == glue_code then
+ -- happens often
+ start = getnext(start)
+ elseif id == disc_code then
+ if not discs or discs[start] == true then
+ local ok
+ if gpossing then
+ start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ elseif typ == "gsub_ligature" then
+ start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ else
+ start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ done = true
+ end
else
start = getnext(start)
end
+ elseif id == math_code then
+ start = getnext(end_of_math(start))
+ elseif id == dir_code then
+ start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
+ elseif id == localpar_code then
+ start, rlparmode, rlmode = pardirstate(start)
+ else
+ start = getnext(start)
end
end
else
@@ -4600,12 +5080,6 @@ do
if char then
local m = merged[char]
if m then
- -- local a = attr and getattr(start,0)
- -- if a then
- -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
- -- else
- -- a = not attribute or getprop(start,a_state) == attribute
- -- end
local a -- happens often so no assignment is faster
if attr then
if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then
@@ -4620,22 +5094,18 @@ do
-- for i=1,#m do
-- local step = m[i]
local lookupcache = step.coverage
- if lookupcache then
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- -- we could move all code inline but that makes things even more unreadable
- local ok
- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- if ok then
- done = true
- break
- elseif not start then
- -- don't ask why ... shouldn't happen
- break
- end
+ local lookupmatch = lookupcache[char]
+ if lookupmatch then
+ -- we could move all code inline but that makes things even more unreadable
+ local ok
+ head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+ if ok then
+ done = true
+ break
+ elseif not start then
+ -- don't ask why ... shouldn't happen
+ break
end
- else
- report_missing_coverage(dataset,sequence)
end
end
if start then
@@ -4787,7 +5257,7 @@ local function hasspacekerns(data)
for i=1,#steps do
local coverage = steps[i].coverage
if not coverage then
- -- maybe an issue
+ -- maybe an issue, can't happen
elseif coverage[32] then
return true
else
@@ -4852,7 +5322,7 @@ local function spaceinitializer(tfmdata,value) -- attr
-- not now: analyze (simple) rules
elseif coverage then
-- what to do if we have no [1] but only [2]
- local single = format == gpos_single
+ local single = format == "gpos_single"
local kerns = coverage[32]
if kerns then
for k, v in next, kerns do
@@ -4877,12 +5347,14 @@ local function spaceinitializer(tfmdata,value) -- attr
left[k] = kern[3]
else
local one = kern[1]
- if one then
+ if one and one ~= true then
left[k] = one[3]
end
end
end
end
+ else
+ -- can't happen
end
end
last = i
diff --git a/tex/context/base/mkiv/font-oup.lua b/tex/context/base/mkiv/font-oup.lua
index 5ee6df505..9f4ded5b5 100644
--- a/tex/context/base/mkiv/font-oup.lua
+++ b/tex/context/base/mkiv/font-oup.lua
@@ -622,7 +622,7 @@ local function checklookups(fontdata,missing,nofmissing)
end
end
if next(done) then
- report("not unicoded: % t",table.sortedkeys(done))
+ report("not unicoded: % t",sortedkeys(done))
end
end
end
@@ -1067,13 +1067,14 @@ function readers.pack(data)
end
end
- local function pack_flat(v)
- local tag = tabstr_flat(v)
+ local function pack_normal_cc(v)
+ local tag = tabstr_normal(v)
local ht = h[tag]
if ht then
c[ht] = c[ht] + 1
return ht
else
+ v[1] = 0
nt = nt + 1
t[nt] = v
h[tag] = nt
@@ -1082,8 +1083,8 @@ function readers.pack(data)
end
end
- local function pack_boolean(v)
- local tag = tabstr_boolean(v)
+ local function pack_flat(v)
+ local tag = tabstr_flat(v)
local ht = h[tag]
if ht then
c[ht] = c[ht] + 1
@@ -1127,6 +1128,84 @@ function readers.pack(data)
end
end
+ -- saves a lot on noto sans
+
+ -- can be made more clever
+
+ local function pack_boolean(v)
+ local tag = tabstr_boolean(v)
+ local ht = h[tag]
+ if ht then
+ c[ht] = c[ht] + 1
+ return ht
+ else
+ nt = nt + 1
+ t[nt] = v
+ h[tag] = nt
+ c[nt] = 1
+ return nt
+ end
+ end
+
+ -- -- This was an experiment to see if we can bypass the luajit limits but loading is
+ -- -- still an issue due to other limits so we don't use this ... actually it can
+ -- -- prevent a luajittex crash but i don't care too much about that as we can't use
+ -- -- that engine anyway then.
+ --
+ -- local function check(t)
+ -- if type(t) == "table" then
+ -- local s = sortedkeys(t)
+ -- local n = #s
+ -- if n <= 10 then
+ -- return
+ -- end
+ -- local ranges = { }
+ -- local first, last
+ -- for i=1,#s do
+ -- local ti = s[i]
+ -- if not first then
+ -- first = ti
+ -- last = ti
+ -- elseif ti == last + 1 then
+ -- last = ti
+ -- elseif last - first < 10 then
+ -- -- we could permits a few exceptions
+ -- return
+ -- else
+ -- ranges[#ranges+1] = { first, last }
+ -- first, last = nil, nil
+ -- end
+ -- end
+ -- if #ranges > 0 then
+ -- return {
+ -- ranges = ranges
+ -- }
+ -- end
+ -- end
+ -- end
+ --
+ -- local function pack_boolean(v)
+ -- local tag
+ -- local r = check(v)
+ -- if r then
+ -- v = r
+ -- tag = tabstr_normal(v)
+ -- else
+ -- tag = tabstr_boolean(v)
+ -- end
+ -- local ht = h[tag]
+ -- if ht then
+ -- c[ht] = c[ht] + 1
+ -- return ht
+ -- else
+ -- nt = nt + 1
+ -- t[nt] = v
+ -- h[tag] = nt
+ -- c[nt] = 1
+ -- return nt
+ -- end
+ -- end
+
local function pack_final(v)
-- v == number
if c[v] <= criterium then
@@ -1146,6 +1225,25 @@ function readers.pack(data)
end
end
+ local function pack_final_cc(v)
+ -- v == number
+ if c[v] <= criterium then
+ return t[v]
+ else
+ -- compact hash
+ local hv = hh[v]
+ if hv then
+ return hv
+ else
+ ntt = ntt + 1
+ tt[ntt] = t[v]
+ hh[v] = ntt
+ cc[ntt] = c[v]
+ return ntt
+ end
+ end
+ end
+
local function success(stage,pass)
if nt == 0 then
if trace_loading or trace_packing then
@@ -1192,9 +1290,9 @@ function readers.pack(data)
local function packers(pass)
if pass == 1 then
- return pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed
+ return pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed, pack_normal_cc
else
- return pack_final, pack_final, pack_final, pack_final, pack_final
+ return pack_final, pack_final, pack_final, pack_final, pack_final, pack_final_cc
end
end
@@ -1212,15 +1310,13 @@ function readers.pack(data)
return
end
- --
-
for pass=1,2 do
if trace_packing then
report_otf("start packing: stage 1, pass %s",pass)
end
- local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
+ local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed, pack_normal_cc = packers(pass)
for unicode, description in next, descriptions do
local boundingbox = description.boundingbox
@@ -1267,8 +1363,8 @@ function readers.pack(data)
else
for g1, d1 in next, c do
for g2, d2 in next, d1 do
- local f = d2[1] if f then d2[1] = pack_indexed(f) end
- local s = d2[2] if s then d2[2] = pack_indexed(s) end
+ local f = d2[1] if f and f ~= true then d2[1] = pack_indexed(f) end
+ local s = d2[2] if s and s ~= true then d2[2] = pack_indexed(s) end
end
end
end
@@ -1280,7 +1376,9 @@ function readers.pack(data)
step.coverage = pack_normal(c)
else
for g1, d1 in next, c do
- c[g1] = pack_indexed(d1)
+ if d1 ~= true then
+ c[g1] = pack_indexed(d1)
+ end
end
end
end
@@ -1400,7 +1498,7 @@ function readers.pack(data)
for i=1,#deltas do
local di = deltas[i]
local d = di.deltas
- local r = di.regions
+ -- local r = di.regions
for j=1,#d do
d[j] = pack_indexed(d[j])
end
@@ -1440,7 +1538,7 @@ function readers.pack(data)
report_otf("start packing: stage 2, pass %s",pass)
end
- local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
+ local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed, pack_normal_cc = packers(pass)
for unicode, description in next, descriptions do
local math = description.math
@@ -1464,9 +1562,7 @@ function readers.pack(data)
if kind == "gpos_pair" then
local c = step.coverage
if c then
- if step.format == "kern" then
- -- todo !
- else
+ if step.format ~= "kern" then
for g1, d1 in next, c do
for g2, d2 in next, d1 do
d1[g2] = pack_normal(d2)
@@ -1474,11 +1570,22 @@ function readers.pack(data)
end
end
end
--- elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" or kind == "gpos_mark2ligature" then
--- local c = step.baseclasses
--- for k, v in next, c do
--- c[k] = pack_normal(v)
--- end
+ -- elseif kind == "gpos_cursive" then
+ -- local c = step.coverage -- new
+ -- if c then
+ -- for g1, d1 in next, c do
+ -- c[g1] = pack_normal_cc(d1)
+ -- end
+ -- end
+ elseif kind == "gpos_mark2ligature" then
+ local c = step.baseclasses -- new
+ if c then
+ for g1, d1 in next, c do
+ for g2, d2 in next, d1 do
+ d1[g2] = pack_normal(d2)
+ end
+ end
+ end
end
local rules = step.rules
if rules then
@@ -1526,7 +1633,7 @@ function readers.pack(data)
report_otf("start packing: stage 3, pass %s",pass)
end
- local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
+ local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed, pack_normal_cc = packers(pass)
local function packthem(sequences)
for i=1,#sequences do
@@ -1540,18 +1647,23 @@ function readers.pack(data)
if kind == "gpos_pair" then
local c = step.coverage
if c then
- if step.format == "kern" then
- -- todo !
- else
+ if step.format ~= "kern" then
for g1, d1 in next, c do
c[g1] = pack_normal(d1)
end
end
end
+ elseif kind == "gpos_cursive" then
+ local c = step.coverage
+ if c then
+ for g1, d1 in next, c do
+ c[g1] = pack_normal_cc(d1)
+ end
+ end
end
end
end
- end
+ end
end
if sequences then
@@ -1627,6 +1739,15 @@ function readers.unpack(data)
-- end
end
+ -- local function expandranges(t,ranges)
+ -- for i=1,#ranges do
+ -- local r = ranges[i]
+ -- for k=r[1],r[2] do
+ -- t[k] = true
+ -- end
+ -- end
+ -- end
+
local function unpackthem(sequences)
for i=1,#sequences do
local sequence = sequences[i]
@@ -1636,6 +1757,19 @@ function readers.unpack(data)
local features = sequence.features
local flags = sequence.flags
local markclass = sequence.markclass
+ if features then
+ local tv = tables[features]
+ if tv then
+ sequence.features = tv
+ features = tv
+ end
+ for script, feature in next, features do
+ local tv = tables[feature]
+ if tv then
+ features[script] = tv
+ end
+ end
+ end
if steps then
for i=1,#steps do
local step = steps[i]
@@ -1689,6 +1823,11 @@ function readers.unpack(data)
local c = step.coverage
if c then
for g1, d1 in next, c do
+ local tv = tables[d1]
+ if tv then
+ d1 = tv
+ c[g1] = d1
+ end
local f = tables[d1[2]] if f then d1[2] = f end
local s = tables[d1[3]] if s then d1[3] = s end
end
@@ -1696,12 +1835,6 @@ function readers.unpack(data)
elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" then
local c = step.baseclasses
if c then
--- for k, v in next, c do
--- local tv = tables[v]
--- if tv then
--- c[k] = tv
--- end
--- end
for g1, d1 in next, c do
for g2, d2 in next, d1 do
local tv = tables[d2]
@@ -1723,14 +1856,13 @@ function readers.unpack(data)
elseif kind == "gpos_mark2ligature" then
local c = step.baseclasses
if c then
--- for k, v in next, c do
--- local tv = tables[v]
--- if tv then
--- c[k] = tv
--- end
--- end
for g1, d1 in next, c do
for g2, d2 in next, d1 do
+ local tv = tables[d2] -- new
+ if tv then
+ d2 = tv
+ d1[g2] = d2
+ end
for g3, d3 in next, d2 do
local tv = tables[d2[g3]]
if tv then
@@ -1767,6 +1899,18 @@ function readers.unpack(data)
before[i] = tv
end
end
+ -- for i=1,#before do
+ -- local bi = before[i]
+ -- local tv = tables[bi]
+ -- if tv then
+ -- bi = tv
+ -- before[i] = bi
+ -- end
+ -- local ranges = bi.ranges
+ -- if ranges then
+ -- expandranges(bi,ranges)
+ -- end
+ -- end
end
local after = rule.after
if after then
@@ -1781,6 +1925,18 @@ function readers.unpack(data)
after[i] = tv
end
end
+ -- for i=1,#after do
+ -- local ai = after[i]
+ -- local tv = tables[ai]
+ -- if tv then
+ -- ai = tv
+ -- after[i] = ai
+ -- end
+ -- local ranges = ai.ranges
+ -- if ranges then
+ -- expandranges(ai,ranges)
+ -- end
+ -- end
end
local current = rule.current
if current then
@@ -1795,6 +1951,18 @@ function readers.unpack(data)
current[i] = tv
end
end
+ -- for i=1,#current do
+ -- local ci = current[i]
+ -- local tv = tables[ci]
+ -- if tv then
+ -- ci = tv
+ -- current[i] = ci
+ -- end
+ -- local ranges = ci.ranges
+ -- if ranges then
+ -- expandranges(ci,ranges)
+ -- end
+ -- end
end
-- local lookups = rule.lookups
-- if lookups then
@@ -1814,19 +1982,6 @@ function readers.unpack(data)
end
end
end
- if features then
- local tv = tables[features]
- if tv then
- sequence.features = tv
- features = tv
- end
- for script, feature in next, features do
- local tv = tables[feature]
- if tv then
- features[script] = tv
- end
- end
- end
if order then
local tv = tables[order]
if tv then
@@ -2140,11 +2295,14 @@ local function checkpairs(lookup)
for g1, d1 in next, coverage do
for g2, d2 in next, d1 do
if d2[2] then
+ --- true or { a, b, c, d }
kerns = false
break
else
local v = d2[1]
- if v[1] ~= 0 or v[2] ~= 0 or v[4] ~= 0 then
+ if v == true then
+ -- all zero
+ elseif v and (v[1] ~= 0 or v[2] ~= 0 or v[4] ~= 0) then
kerns = false
break
end
@@ -2155,7 +2313,12 @@ local function checkpairs(lookup)
report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
for g1, d1 in next, coverage do
for g2, d2 in next, d1 do
- d1[g2] = d2[1][3]
+ local v = d2[1]
+ if v == true then
+ d1[g2] = nil
+ elseif v then
+ d1[g2] = v[3]
+ end
end
end
step.format = "kern"
@@ -2185,6 +2348,7 @@ function readers.compact(data)
allsteps = allsteps + nofsteps
if nofsteps > 1 then
local kind = lookup.type
+ local merg = merged
if kind == "gsub_single" or kind == "gsub_alternate" or kind == "gsub_multiple" then
merged = merged + mergesteps_1(lookup)
elseif kind == "gsub_ligature" then
@@ -2200,6 +2364,9 @@ function readers.compact(data)
elseif kind == "gpos_mark2mark" or kind == "gpos_mark2base" or kind == "gpos_mark2ligature" then
merged = merged + mergesteps_3(lookup)
end
+ if merg ~= merged then
+ lookup.merged = true
+ end
end
end
else
@@ -2268,7 +2435,7 @@ function readers.expand(data)
for i=1,#t do
local step = t[i]
local coverage = step.coverage
- for k, v in next, coverage do
+ for k in next, coverage do
local m = merged[k]
if m then
m[2] = i
@@ -2291,6 +2458,7 @@ function readers.expand(data)
local sequence = sequences[i]
local steps = sequence.steps
if steps then
+ local nofsteps = sequence.nofsteps
setmetatableindex(steps,mergesteps)
@@ -2304,7 +2472,14 @@ function readers.expand(data)
sequence.markclass = markclasses[markclass]
end
end
- local nofsteps = sequence.nofsteps
+ local flags = sequence.flags
+ if flags then
+ flags[5] = flags[1] ~= false -- otherwise "mark"
+ or flags[2] ~= false -- otherwise "base"
+ or flags[3] ~= false -- otherwise "ligature"
+ or sequence.markclass
+ or false
+ end
for i=1,nofsteps do
local step = steps[i]
local baseclasses = step.baseclasses
@@ -2373,6 +2548,7 @@ function readers.expand(data)
end
end
if sequence[1] then -- we merge coverage into one
+ sequence.n = #sequence -- tiny speedup
rulesize = rulesize + 1
rulehash[rulesize] = {
nofrules, -- 1
@@ -2393,6 +2569,7 @@ function readers.expand(data)
end
end
end
+ rulehash.n = #rulehash -- tiny speedup
end
end
end
diff --git a/tex/context/base/mkiv/font-shp.lua b/tex/context/base/mkiv/font-shp.lua
index c465ec91b..918304a0b 100644
--- a/tex/context/base/mkiv/font-shp.lua
+++ b/tex/context/base/mkiv/font-shp.lua
@@ -362,7 +362,7 @@ local function addvariableshapes(tfmdata,key,value)
-- we need inline in order to support color
local bt, et = getactualtext(char.tounicode or char.unicode or unicode)
char.commands = {
- { "pdf", segmentstopdf(segments,factor,bt,et) }
+ { "pdf", "origin", segmentstopdf(segments,factor,bt,et) }
}
end
end
diff --git a/tex/context/base/mkiv/font-vf.lua b/tex/context/base/mkiv/font-vir.lua
index ded992850..03ad7fc85 100644
--- a/tex/context/base/mkiv/font-vf.lua
+++ b/tex/context/base/mkiv/font-vir.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['font-vf'] = {
+if not modules then modules = { } end modules ['font-vir'] = {
version = 1.001,
comment = "companion to font-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/tex/context/base/mkiv/hand-ini.mkiv b/tex/context/base/mkiv/hand-ini.mkiv
index d4bffdb14..f678a88da 100644
--- a/tex/context/base/mkiv/hand-ini.mkiv
+++ b/tex/context/base/mkiv/hand-ini.mkiv
@@ -60,6 +60,7 @@
\def\font_expansion_enable {\normaladjustspacing\plusthree}
\def\font_expansion_enable_k{\normaladjustspacing\plustwo}
+\def\font_expansion_enable_n{\normaladjustspacing\plusone}
\def\font_expansion_disable {\normaladjustspacing\zerocount}
\def\font_protruding_enable {\normalprotrudechars\plustwo }
diff --git a/tex/context/base/mkiv/l-package.lua b/tex/context/base/mkiv/l-package.lua
index 075fcde25..5f72dd6b2 100644
--- a/tex/context/base/mkiv/l-package.lua
+++ b/tex/context/base/mkiv/l-package.lua
@@ -23,6 +23,7 @@ local P, S, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.Cs, lpeg.match
local package = package
local searchers = package.searchers or package.loaders
+local insert, remove = table.insert, table.remove
-- dummies
@@ -191,7 +192,25 @@ local function registerpath(tag,what,target,...)
add(path)
end
end
- return paths
+end
+
+local function pushpath(tag,what,target,path)
+ local path = helpers.cleanpath(path)
+ insert(target,1,path)
+ if helpers.trace then
+ helpers.report("pushing %s path in front: %s",tag,path)
+ end
+end
+
+local function poppath(tag,what,target)
+ local path = remove(target,1)
+ if helpers.trace then
+ if path then
+ helpers.report("popping %s path from front: %s",tag,path)
+ else
+ helpers.report("no %s path to pop",tag)
+ end
+ end
end
helpers.registerpath = registerpath
@@ -199,10 +218,22 @@ helpers.registerpath = registerpath
function package.extraluapath(...)
registerpath("extra lua","lua",extraluapaths,...)
end
+function package.pushluapath(path)
+ pushpath("extra lua","lua",extraluapaths,path)
+end
+function package.popluapath()
+ poppath("extra lua","lua",extraluapaths)
+end
function package.extralibpath(...)
registerpath("extra lib","lib",extralibpaths,...)
end
+function package.pushlibpath(path)
+ pushpath("extra lib","lib",extralibpaths,path)
+end
+function package.poplibpath()
+ poppath("extra lib","lua",extralibpaths)
+end
-- lib loader (used elsewhere)
diff --git a/tex/context/base/mkiv/lpdf-col.lua b/tex/context/base/mkiv/lpdf-col.lua
index af01c7dd2..a1006f773 100644
--- a/tex/context/base/mkiv/lpdf-col.lua
+++ b/tex/context/base/mkiv/lpdf-col.lua
@@ -22,7 +22,7 @@ local nodeinjections = backends.pdf.nodeinjections
local codeinjections = backends.pdf.codeinjections
local registrations = backends.pdf.registrations
-local nodepool = nodes.pool
+local nodepool = nodes.nuts.pool
local register = nodepool.register
local pdfliteral = nodepool.pdfliteral
@@ -707,25 +707,25 @@ local f_slant = formatters["q 1 0 %F 1 0 0 cm"]
backends.pdf.tables.vfspecials = allocate { -- todo: distinguish between glyph and rule color
- red = { "pdf", "1 0 0 rg 1 0 0 RG" },
- green = { "pdf", "0 1 0 rg 0 1 0 RG" },
- blue = { "pdf", "0 0 1 rg 0 0 1 RG" },
- gray = { "pdf", ".75 g .75 G" },
- black = { "pdf", "0 g 0 G" },
+ red = { "pdf", "origin", "1 0 0 rg 1 0 0 RG" },
+ green = { "pdf", "origin", "0 1 0 rg 0 1 0 RG" },
+ blue = { "pdf", "origin", "0 0 1 rg 0 0 1 RG" },
+ gray = { "pdf", "origin", ".75 g .75 G" },
+ black = { "pdf", "origin", "0 g 0 G" },
rulecolors = {
- red = { "pdf", '1 0 0 rg' },
- green = { "pdf", '0 1 0 rg' },
- blue = { "pdf", '0 0 1 rg' },
- gray = { "pdf", '.5 g' },
- black = { "pdf", '0 g' },
- palered = { "pdf", '1 .75 .75 rg' },
- palegreen = { "pdf", '.75 1 .75 rg' },
- paleblue = { "pdf", '.75 .75 1 rg' },
- palegray = { "pdf", '.75 g' },
+ red = { "pdf", "origin", '1 0 0 rg' },
+ green = { "pdf", "origin", '0 1 0 rg' },
+ blue = { "pdf", "origin", '0 0 1 rg' },
+ gray = { "pdf", "origin", '.5 g' },
+ black = { "pdf", "origin", '0 g' },
+ palered = { "pdf", "origin", '1 .75 .75 rg' },
+ palegreen = { "pdf", "origin", '.75 1 .75 rg' },
+ paleblue = { "pdf", "origin", '.75 .75 1 rg' },
+ palegray = { "pdf", "origin", '.75 g' },
},
- startslant = function(a) return { "pdf", f_slant(a) } end,
- stopslant = { "pdf", "Q" },
+ startslant = function(a) return { "pdf", "origin", f_slant(a) } end,
+ stopslant = { "pdf", "origin", "Q" },
}
diff --git a/tex/context/base/mkiv/lpdf-mis.lua b/tex/context/base/mkiv/lpdf-mis.lua
index 91dd08afd..9d903ce96 100644
--- a/tex/context/base/mkiv/lpdf-mis.lua
+++ b/tex/context/base/mkiv/lpdf-mis.lua
@@ -25,9 +25,10 @@ local nodeinjections = backends.pdf.nodeinjections
local codeinjections = backends.pdf.codeinjections
local registrations = backends.pdf.registrations
-local copy_node = node.copy
+local nuts = nodes.nuts
+local copy_node = nuts.copy
-local nodepool = nodes.pool
+local nodepool = nuts.pool
local pdfliteral = nodepool.pdfliteral
local register = nodepool.register
diff --git a/tex/context/base/mkiv/lpdf-ren.lua b/tex/context/base/mkiv/lpdf-ren.lua
index 47075ee08..a57c550fd 100644
--- a/tex/context/base/mkiv/lpdf-ren.lua
+++ b/tex/context/base/mkiv/lpdf-ren.lua
@@ -49,7 +49,10 @@ local addtocatalog = lpdf.addtocatalog
local escaped = lpdf.escaped
-local nodepool = nodes.pool
+local nuts = nodes.nuts
+local copy_node = nuts.copy
+
+local nodepool = nuts.pool
local register = nodepool.register
local pdfliteral = nodepool.pdfliteral
@@ -62,8 +65,6 @@ local pdf_design = pdfconstant("Design")
local pdf_toggle = pdfconstant("Toggle")
local pdf_setocgstate = pdfconstant("SetOCGState")
-local copy_node = node.copy
-
local pdf_print = {
[v_yes] = pdfdictionary { PrintState = pdf_on },
[v_no ] = pdfdictionary { PrintState = pdf_off },
diff --git a/tex/context/base/mkiv/lpdf-xmp.lua b/tex/context/base/mkiv/lpdf-xmp.lua
index 26ced4aee..a0005eb8a 100644
--- a/tex/context/base/mkiv/lpdf-xmp.lua
+++ b/tex/context/base/mkiv/lpdf-xmp.lua
@@ -241,6 +241,8 @@ end
-- flushing
+local add_xmp_blob = true directives.register("backend.xmp",function(v) add_xmp_blob = v end)
+
local function flushxmpinfo()
commands.pushrandomseed()
commands.setrandomseed(os.time())
@@ -261,42 +263,45 @@ local function flushxmpinfo()
instanceid = "uuid:" .. os.uuid()
end
- pdfaddxmpinfo("DocumentID", documentid)
- pdfaddxmpinfo("InstanceID", instanceid)
- pdfaddxmpinfo("Producer", producer)
- pdfaddxmpinfo("CreatorTool", creator)
- pdfaddxmpinfo("CreateDate", time)
- pdfaddxmpinfo("ModifyDate", time)
- pdfaddxmpinfo("MetadataDate", time)
- pdfaddxmpinfo("PTEX.Fullbanner", fullbanner)
-
pdfaddtoinfo("Producer", producer)
pdfaddtoinfo("Creator", creator)
pdfaddtoinfo("CreationDate", time)
pdfaddtoinfo("ModDate", time)
-- pdfaddtoinfo("PTEX.Fullbanner", fullbanner) -- no checking done on existence
- local blob = xml.tostring(xml.first(xmp or valid_xmp(),"/x:xmpmeta"))
- local md = pdfdictionary {
- Subtype = pdfconstant("XML"),
- Type = pdfconstant("Metadata"),
- }
- if trace_xmp then
- report_xmp("data flushed, see log file")
- logs.pushtarget("logfile")
- report_xmp("start xmp blob")
- logs.newline()
- logs.writer(blob)
- logs.newline()
- report_xmp("stop xmp blob")
- logs.poptarget()
- end
- blob = format(xpacket,blob)
- if not verbose and pdf.getcompresslevel() > 0 then
- blob = gsub(blob,">%s+<","><")
+ if add_xmp_blob then
+
+ pdfaddxmpinfo("DocumentID", documentid)
+ pdfaddxmpinfo("InstanceID", instanceid)
+ pdfaddxmpinfo("Producer", producer)
+ pdfaddxmpinfo("CreatorTool", creator)
+ pdfaddxmpinfo("CreateDate", time)
+ pdfaddxmpinfo("ModifyDate", time)
+ pdfaddxmpinfo("MetadataDate", time)
+ pdfaddxmpinfo("PTEX.Fullbanner", fullbanner)
+
+ local blob = xml.tostring(xml.first(xmp or valid_xmp(),"/x:xmpmeta"))
+ local md = pdfdictionary {
+ Subtype = pdfconstant("XML"),
+ Type = pdfconstant("Metadata"),
+ }
+ if trace_xmp then
+ report_xmp("data flushed, see log file")
+ logs.pushtarget("logfile")
+ report_xmp("start xmp blob")
+ logs.newline()
+ logs.writer(blob)
+ logs.newline()
+ report_xmp("stop xmp blob")
+ logs.poptarget()
+ end
+ blob = format(xpacket,blob)
+ if not verbose and pdf.getcompresslevel() > 0 then
+ blob = gsub(blob,">%s+<","><")
+ end
+ local r = pdfflushstreamobject(blob,md,false) -- uncompressed
+ lpdf.addtocatalog("Metadata",pdfreference(r))
end
- local r = pdfflushstreamobject(blob,md,false) -- uncompressed
- lpdf.addtocatalog("Metadata",pdfreference(r))
commands.poprandomseed() -- hack
end
diff --git a/tex/context/base/mkiv/lxml-tex.lua b/tex/context/base/mkiv/lxml-tex.lua
index f79aa708f..76a20fbef 100644
--- a/tex/context/base/mkiv/lxml-tex.lua
+++ b/tex/context/base/mkiv/lxml-tex.lua
@@ -34,6 +34,8 @@ local commands = commands
local context = context
local contextsprint = context.sprint -- with catcodes (here we use fast variants, but with option for tracing)
+local synctex = luatex.synctex
+
local implement = interfaces.implement
local xmlelements = xml.elements
@@ -486,13 +488,8 @@ local noffiles = 0
local nofconverted = 0
local linenumbers = false
--- directives.register("lxml.linenumbers", function(v)
--- linenumbers = v
--- end)
-
-directives.register("system.synctex.xml",function(v)
- linenumbers = v
-end)
+synctex.registerenabler (function() linenumbers = true end)
+synctex.registerdisabler(function() linenumbers = false end)
function xml.load(filename,settings)
noffiles, nofconverted = noffiles + 1, nofconverted + 1
@@ -713,13 +710,8 @@ local setfilename = false
local trace_name = false
local report_name = logs.reporter("lxml")
-directives.register("system.synctex.xml",function(v)
- if v then
- setfilename = luatex.synctex.setfilename
- else
- setfilename = false
- end
-end)
+synctex.registerenabler (function() setfilename = synctex.setfilename end)
+synctex.registerdisabler(function() setfilename = false end)
local function syncfilename(e,where)
local cf = e.cf
@@ -1050,9 +1042,6 @@ xml.cprint = cprint local xmlcprint = cprint -- calls ct mathml -> will be re
function lxml.main(id)
local root = getid(id)
--- if setfilename then
--- syncfilename(root,"main")
--- end
xmlserialize(root,xmltexhandler) -- the real root (@rt@)
end
diff --git a/tex/context/base/mkiv/m-fonts-plugins.mkiv b/tex/context/base/mkiv/m-fonts-plugins.mkiv
index 7678f820c..85411025f 100644
--- a/tex/context/base/mkiv/m-fonts-plugins.mkiv
+++ b/tex/context/base/mkiv/m-fonts-plugins.mkiv
@@ -19,6 +19,8 @@
%D below should work in the generic loader too. It's anyhow an illustration of
%D how \type {ffi} can work be used in a practical application.
+% \enabletrackers[resolvers.ffilib]
+
\registerctxluafile{font-txt}{1.001} % generic text handler
\registerctxluafile{font-phb}{1.001} % harfbuzz plugin
@@ -201,10 +203,11 @@
[arabic-uniscribe]
[mode=plug,
features=harfbuzz,
- script=arab,language=dflt,ccmp=yes,
- init=yes,medi=yes,fina=yes,isol=yes,
- liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes,
- mark=yes,mkmk=yes,kern=yes,curs=yes,
+ script=arab,language=dflt,
+% ccmp=yes,
+% init=yes,medi=yes,fina=yes,isol=yes,
+% liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes,
+% mark=yes,mkmk=yes,kern=yes,curs=yes,
shaper=uniscribe]
\starttexdefinition RunLatinTest #1#2#3#4#5
@@ -320,7 +323,7 @@
context.RunLatinTest (name, 100, "context", "base", "latin")
context.RunLatinTest (name, 100, "context", "node", "latin")
context.RunLatinTest (name, 100, "harfbuzz", "native", "latin")
- -- context.RunLatinTest (name, 100, "harfbuzz", "uniscribe", "latin")
+ context.RunLatinTest (name, 100, "harfbuzz", "uniscribe", "latin")
-- context.RunLatinTest (name, 1, "context", "text", "latin")
-- context.RunLatinTest (name, 1, "harfbuzz", "binary", "latin")
@@ -336,7 +339,8 @@
-- ARABIC
local list = {
- "arabtype"
+ "arabtype",
+ "husayni",
}
data.timings["arabic"] = {
@@ -353,7 +357,7 @@
context.RunArabicTest (name, 100, "context", "base", "arabic")
context.RunArabicTest (name, 100, "context", "node", "arabic")
context.RunArabicTest (name, 100, "harfbuzz", "native", "arabic")
- -- context.RunArabicTest (name, 100, "harfbuzz", "uniscribe", "arabic")
+ context.RunArabicTest (name, 100, "harfbuzz", "uniscribe", "arabic")
-- context.RunArabicTest (name, 1, "context", "text", "arabic")
-- context.RunArabicTest (name, 1, "harfbuzz", "binary", "arabic")
@@ -369,7 +373,8 @@
-- MIXED
local list = {
- "arabtype"
+ "arabtype",
+ "husayni"
}
data.timings["mixed"] = {
@@ -386,7 +391,7 @@
context.RunArabicTest (name, 100, "context", "base", "mixed")
context.RunArabicTest (name, 100, "context", "node", "mixed")
context.RunArabicTest (name, 100, "harfbuzz", "native", "mixed")
- -- context.RunArabicTest (name, 100, "harfbuzz", "uniscribe", "mixed")
+ context.RunArabicTest (name, 100, "harfbuzz", "uniscribe", "mixed")
-- context.RunArabicTest (name, 1, "context", "text", "mixed")
-- context.RunArabicTest (name, 1, "harfbuzz", "binary", "mixed")
diff --git a/tex/context/base/mkiv/meta-fnt.lua b/tex/context/base/mkiv/meta-fnt.lua
index ea7f6f2bc..e7e83c694 100644
--- a/tex/context/base/mkiv/meta-fnt.lua
+++ b/tex/context/base/mkiv/meta-fnt.lua
@@ -66,7 +66,7 @@ local flusher = {
if inline then
characters[slot] = {
commands = {
- { "pdf", code },
+ { "pdf", "origin", code },
}
}
else
diff --git a/tex/context/base/mkiv/node-fin.lua b/tex/context/base/mkiv/node-fin.lua
index ffb2ae49e..5d01f6e5a 100644
--- a/tex/context/base/mkiv/node-fin.lua
+++ b/tex/context/base/mkiv/node-fin.lua
@@ -124,12 +124,6 @@ function nodes.installattributehandler(plugin)
return loadstripped(template)()
end
--- for the moment:
-
-local function copied(n)
- return copy_node(tonut(n))
-end
-
-- the injectors
local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger
@@ -163,13 +157,13 @@ function states.finalize(namespace,attribute,head) -- is this one ok?
if id == hlist_code or id == vlist_code then
local content = getlist(head)
if content then
- local list = insert_node_before(content,content,copied(nsnone)) -- two return values
+ local list = insert_node_before(content,content,copy_node(nsnone)) -- two return values
if list ~= content then
setlist(head,list)
end
end
else
- head = insert_node_before(head,head,copied(nsnone))
+ head = insert_node_before(head,head,copy_node(nsnone))
end
return tonode(head), true, true
end
@@ -178,7 +172,7 @@ end
-- we need to deal with literals too (reset as well as oval)
-local function process(namespace,attribute,head,inheritance,default) -- one attribute
+local function process(attribute,head,inheritance,default) -- one attribute
local stack = head
local done = false
local check = false
@@ -201,7 +195,7 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
if nstrigger and getattr(stack,nstrigger) then
local outer = getattr(stack,attribute)
if outer ~= inheritance then
- local list, ok = process(namespace,attribute,content,inheritance,outer)
+ local list, ok = process(attribute,content,inheritance,outer)
if content ~= list then
setlist(stack,list)
end
@@ -209,7 +203,7 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
done = true
end
else
- local list, ok = process(namespace,attribute,content,inheritance,default)
+ local list, ok = process(attribute,content,inheritance,default)
if content ~= list then
setlist(stack,list)
end
@@ -218,7 +212,7 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
end
end
else
- local list, ok = process(namespace,attribute,content,inheritance,default)
+ local list, ok = process(attribute,content,inheritance,default)
if content ~= list then
setlist(stack,list)
end
@@ -237,12 +231,12 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
if c then
if default and c == inheritance then
if current ~= default then
- head = insert_node_before(head,stack,copied(nsdata[default]))
+ head = insert_node_before(head,stack,copy_node(nsdata[default]))
current = default
done = true
end
elseif current ~= c then
- head = insert_node_before(head,stack,copied(nsdata[c]))
+ head = insert_node_before(head,stack,copy_node(nsdata[c]))
current = c
done = true
end
@@ -259,7 +253,7 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
if nstrigger and getattr(stack,nstrigger) then
local outer = getattr(stack,attribute)
if outer ~= inheritance then
- local list, ok = process(namespace,attribute,leader,inheritance,outer)
+ local list, ok = process(attribute,leader,inheritance,outer)
if leader ~= list then
setleader(stack,list)
end
@@ -267,7 +261,7 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
done = true
end
else
- local list, ok = process(namespace,attribute,leader,inheritance,default)
+ local list, ok = process(attribute,leader,inheritance,default)
if leader ~= list then
setleader(stack,list)
end
@@ -276,7 +270,7 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
end
end
else
- local list, ok = process(namespace,attribute,leader,inheritance,default)
+ local list, ok = process(attribute,leader,inheritance,default)
if leader ~= list then
setleader(stack,list)
end
@@ -290,12 +284,12 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
end
elseif default and inheritance then
if current ~= default then
- head = insert_node_before(head,stack,copied(nsdata[default]))
+ head = insert_node_before(head,stack,copy_node(nsdata[default]))
current = default
done = true
end
elseif current > 0 then
- head = insert_node_before(head,stack,copied(nsnone))
+ head = insert_node_before(head,stack,copy_node(nsnone))
current = 0
done = true
end
@@ -307,7 +301,7 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
end
states.process = function(namespace,attribute,head,default)
- local head, done = process(namespace,attribute,tonut(head),default)
+ local head, done = process(attribute,tonut(head),default)
return tonode(head), done
end
@@ -317,7 +311,8 @@ end
-- state changes while the main state stays the same (like two glyphs following
-- each other with the same color but different color spaces e.g. \showcolor)
-local function selective(namespace,attribute,head,inheritance,default) -- two attributes
+local function selective(attribute,head,inheritance,default) -- two attributes
+ -- local head = head
local stack = head
local done = false
local check = false
@@ -340,7 +335,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
if nstrigger and getattr(stack,nstrigger) then
local outer = getattr(stack,attribute)
if outer ~= inheritance then
- local list, ok = selective(namespace,attribute,content,inheritance,outer)
+ local list, ok = selective(attribute,content,inheritance,outer)
if content ~= list then
setlist(stack,list)
end
@@ -348,7 +343,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
done = true
end
else
- local list, ok = selective(namespace,attribute,content,inheritance,default)
+ local list, ok = selective(attribute,content,inheritance,default)
if content ~= list then
setlist(stack,list)
end
@@ -357,7 +352,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
end
end
else
- local list, ok = selective(namespace,attribute,content,inheritance,default)
+ local list, ok = selective(attribute,content,inheritance,default)
if content ~= list then
setlist(stack,list)
end
@@ -377,7 +372,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
if default and c == inheritance then
if current ~= default then
local data = nsdata[default]
- head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
+ head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector]))
current = default
if ok then
done = true
@@ -385,9 +380,11 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
end
else
local s = getattr(stack,nsselector)
+ -- local s = nsforced or getattr(stack,nsselector)
if current ~= c or current_selector ~= s then
local data = nsdata[c]
- head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
+ head = insert_node_before(head,stack,copy_node(data[nsforced or s or nsselector]))
+ -- head = insert_node_before(head,stack,copy_node(data[s or nsselector]))
current = c
current_selector = s
if ok then
@@ -400,7 +397,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
if nstrigger and getattr(stack,nstrigger) then
local outer = getatribute(stack,attribute)
if outer ~= inheritance then
- local list, ok = selective(namespace,attribute,leader,inheritance,outer)
+ local list, ok = selective(attribute,leader,inheritance,outer)
if leader ~= list then
setleader(stack,list)
end
@@ -408,7 +405,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
done = true
end
else
- local list, ok = selective(namespace,attribute,leader,inheritance,default)
+ local list, ok = selective(attribute,leader,inheritance,default)
if leader ~= list then
setleader(stack,list)
end
@@ -417,7 +414,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
end
end
else
- local list, ok = selective(namespace,attribute,leader,inheritance,default)
+ local list, ok = selective(attribute,leader,inheritance,default)
if leader ~= list then
setleader(stack,list)
end
@@ -431,12 +428,12 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
elseif default and inheritance then
if current ~= default then
local data = nsdata[default]
- head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
+ head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector]))
current = default
done = true
end
elseif current > 0 then
- head = insert_node_before(head,stack,copied(nsnone))
+ head = insert_node_before(head,stack,copy_node(nsnone))
current, current_selector, done = 0, 0, true
end
check = false
@@ -447,8 +444,8 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
end
states.selective = function(namespace,attribute,head,default)
- local head, done = selective(namespace,attribute,tonut(head),default)
- return tonode(head), done
+ local head = selective(attribute,tonut(head),default)
+ return tonode(head), true
end
-- Ideally the next one should be merged with the previous but keeping it separate is
@@ -460,7 +457,7 @@ end
-- Todo: make a better stacker. Keep track (in attribute) about nesting level. Not
-- entirely trivial and a generic solution is nicer (compares to the exporter).
-local function stacked(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise
+local function stacked(attribute,head,default) -- no triggering, no inheritance, but list-wise
local stack = head
local done = false
local current = default or 0
@@ -485,16 +482,16 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below
local p = current
current = a
- head = insert_node_before(head,stack,copied(nsdata[a]))
- local list = stacked(namespace,attribute,content,current) -- two return values
+ head = insert_node_before(head,stack,copy_node(nsdata[a]))
+ local list = stacked(attribute,content,current) -- two return values
if content ~= list then
setlist(stack,list)
end
- head, stack = insert_node_after(head,stack,copied(nsnone))
+ head, stack = insert_node_after(head,stack,copy_node(nsnone))
current = p
done = true
else
- local list, ok = stacked(namespace,attribute,content,current)
+ local list, ok = stacked(attribute,content,current)
if content ~= list then
setlist(stack,list) -- only if ok
end
@@ -503,7 +500,7 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
end
end
else
- local list, ok = stacked(namespace,attribute,content,current)
+ local list, ok = stacked(attribute,content,current)
if content ~= list then
setlist(stack,list) -- only if ok
end
@@ -520,13 +517,13 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
local a = getattr(stack,attribute)
if a then
if current ~= a then
- head = insert_node_before(head,stack,copied(nsdata[a]))
+ head = insert_node_before(head,stack,copy_node(nsdata[a]))
depth = depth + 1
current = a
done = true
end
if leader then
- local list, ok = stacked(namespace,attribute,content,current)
+ local list, ok = stacked(attribute,content,current)
if leader ~= list then
setleader(stack,list) -- only if ok
end
@@ -538,7 +535,7 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
elseif default > 0 then
--
elseif current > 0 then
- head = insert_node_before(head,stack,copied(nsnone))
+ head = insert_node_before(head,stack,copy_node(nsnone))
depth = depth - 1
current = 0
done = true
@@ -548,20 +545,20 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
stack = getnext(stack)
end
while depth > 0 do
- head = insert_node_after(head,stack,copied(nsnone))
+ head = insert_node_after(head,stack,copy_node(nsnone))
depth = depth - 1
end
return head, done
end
states.stacked = function(namespace,attribute,head,default)
- local head, done = stacked(namespace,attribute,tonut(head),default)
+ local head, done = stacked(attribute,tonut(head),default)
return tonode(head), done
end
-- experimental
-local function stacker(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise
+local function stacker(attribute,head,default) -- no triggering, no inheritance, but list-wise
-- nsbegin()
local stacked = false
@@ -589,15 +586,15 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in
elseif nslistwise then
local a = getattr(current,attribute)
if a and attrib ~= a and nslistwise[a] then -- viewerlayer
- head = insert_node_before(head,current,copied(nsdata[a]))
- local list = stacker(namespace,attribute,content,a)
+ head = insert_node_before(head,current,copy_node(nsdata[a]))
+ local list = stacker(attribute,content,a)
if list ~= content then
setlist(current,list)
end
done = true
- head, current = insert_node_after(head,current,copied(nsnone))
+ head, current = insert_node_after(head,current,copy_node(nsnone))
else
- local list, ok = stacker(namespace,attribute,content,attrib)
+ local list, ok = stacker(attribute,content,attrib)
if content ~= list then
setlist(current,list)
end
@@ -606,7 +603,7 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in
end
end
else
- local list, ok = stacker(namespace,attribute,content,default)
+ local list, ok = stacker(attribute,content,default)
if list ~= content then
setlist(current,list)
end
@@ -633,7 +630,7 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in
done = true
if leader then
-- tricky as a leader has to be a list so we cannot inject before
- local list, ok = stacker(namespace,attribute,leader,attrib)
+ local list, ok = stacker(attribute,leader,attrib)
if ok then
done = true
end
@@ -647,21 +644,19 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in
current = getnext(current)
end
-if stacked then
-
- local n = nsend()
- while n do
- head = insert_node_after(head,previous,tonut(n))
- n = nsend()
+ if stacked then
+ local n = nsend()
+ while n do
+ head = insert_node_after(head,previous,tonut(n))
+ n = nsend()
+ end
end
-end
-
return head, done
end
states.stacker = function(namespace,attribute,head,default)
- local head, done = stacker(namespace,attribute,tonut(head),default)
+ local head, done = stacker(attribute,tonut(head),default)
nsreset()
return tonode(head), done
end
diff --git a/tex/context/base/mkiv/node-fnt.lua b/tex/context/base/mkiv/node-fnt.lua
index 0f89e581f..c0d7eecc8 100644
--- a/tex/context/base/mkiv/node-fnt.lua
+++ b/tex/context/base/mkiv/node-fnt.lua
@@ -56,6 +56,7 @@ local getfield = nuts.getfield
----- getdisc = nuts.getdisc
local setchar = nuts.setchar
local setlink = nuts.setlink
+local setnext = nuts.setnext
local setfield = nuts.setfield
local setprev = nuts.setprev
@@ -71,6 +72,9 @@ local disc_code = nodecodes.disc
local boundary_code = nodecodes.boundary
local word_boundary = nodes.boundarycodes.word
+local protect_glyphs = nuts.protect_glyphs
+local unprotect_glyphs = nuts.unprotect_glyphs
+
local setmetatableindex = table.setmetatableindex
-- some tests with using an array of dynamics[id] and processes[id] demonstrated
@@ -212,8 +216,10 @@ function handlers.characters(head,groupcode,size,packtype,direction)
local done = false
local variants = nil
local redundant = nil
- local none = false
local nuthead = tonut(head)
+ local lastfont = nil
+ local lastproc = nil
+ local lastnone = nil
local a, u, b, r, e = 0, 0, 0, 0, 0
@@ -224,54 +230,91 @@ function handlers.characters(head,groupcode,size,packtype,direction)
-- There is no gain in checking for a single glyph and then having a fast path. On the
-- metafun manual (with some 2500 single char lists) the difference is just noise.
+ local function protectnone()
+ protect_glyphs(firstnone,lastnone)
+ firstnone = nil
+ end
+
+ local function setnone(n)
+ if firstnone then
+ protectnone()
+ end
+ if basefont then
+ basefont[2] = getprev(n)
+ basefont = false
+ end
+ if not firstnone then
+ firstnone = n
+ end
+ lastnone = n
+ end
+
+ local function setbase(n)
+ if firstnone then
+ protectnone()
+ end
+ if force_basepass then
+ if basefont then
+ basefont[2] = getprev(n)
+ end
+ b = b + 1
+ basefont = { n, false }
+ basefonts[b] = basefont
+ end
+ end
+
+ local function setnode(n,font,attr) -- we could use prevfont and prevattr when we set then first
+ if firstnone then
+ protectnone()
+ end
+ if basefont then
+ basefont[2] = getprev(n)
+ basefont = false
+ end
+ if attr > 0 then
+ local used = attrfonts[font]
+ if not used then
+ used = { }
+ attrfonts[font] = used
+ end
+ if not used[attr] then
+ local fd = setfontdynamics[font]
+ if fd then
+ used[attr] = fd[attr]
+ a = a + 1
+ end
+ end
+ else
+ local used = usedfonts[font]
+ if not used then
+ lastfont = font
+ lastproc = fontprocesses[font]
+ if lastproc then
+ usedfonts[font] = lastproc
+ u = u + 1
+ end
+ end
+ end
+ end
+
for n in traverse_char(nuthead) do
local font = getfont(n)
- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+ -- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+ local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
if font ~= prevfont or attr ~= prevattr then
prevfont = font
prevattr = attr
variants = fontvariants[font]
- none = fontmodes[font] == "none"
- if none then
- -- skip
- -- variants = false
- protect_glyph(n)
+ local fontmode = fontmodes[font]
+ if fontmode == "none" then
+ setnone(n)
+ elseif fontmode == "base" then
+ setbase(n)
else
- if basefont then
- basefont[2] = getprev(n)
- end
- if attr > 0 then
- local used = attrfonts[font]
- if not used then
- used = { }
- attrfonts[font] = used
- end
- if not used[attr] then
- local fd = setfontdynamics[font]
- if fd then
- used[attr] = fd[attr]
- a = a + 1
- elseif force_basepass then
- b = b + 1
- basefont = { n, false }
- basefonts[b] = basefont
- end
- end
- else
- local used = usedfonts[font]
- if not used then
- local fp = fontprocesses[font]
- if fp then
- usedfonts[font] = fp
- u = u + 1
- elseif force_basepass then
- b = b + 1
- basefont = { n, false }
- basefonts[b] = basefont
- end
- end
- end
+ setnode(n,font,attr)
end
+ elseif firstnone then
+ lastnone = n
end
if variants then
local char = getchar(n)
@@ -309,6 +352,10 @@ function handlers.characters(head,groupcode,size,packtype,direction)
end
end
+ if firstnone then
+ protectnone()
+ end
+
if force_boundaryrun then
-- we can inject wordboundaries and then let the hyphenator do its work
@@ -376,43 +423,29 @@ function handlers.characters(head,groupcode,size,packtype,direction)
local none = false
for n in traverse_char(r) do
local font = getfont(n)
- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+ local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
if font ~= prevfont or attr ~= prevattr then
prevfont = font
prevattr = attr
- none = fontmodes[font] == "none" -- very unlikely that we run into disc nodes in none mode
- if none then
- -- skip
- -- variants = false
- protect_glyph(n)
- elseif attr > 0 then
- local used = attrfonts[font]
- if not used then
- used = { }
- attrfonts[font] = used
- end
- if not used[attr] then
- local fd = setfontdynamics[font]
- if fd then
- used[attr] = fd[attr]
- a = a + 1
- end
- end
+ local fontmode = fontmodes[font]
+ if fontmode == "none" then
+ setnone(n)
+ elseif fontmode == "base" then
+ setbase(n)
else
- local used = usedfonts[font]
- if not used then
- local fp = fontprocesses[font]
- if fp then
- usedfonts[font] = fp
- u = u + 1
- end
- end
+ setnode(n,font,attr)
end
+ elseif firstnone then
+ -- lastnone = n
+ lastnone = nil
end
-- we assume one font for now (and if there are more and we get into issues then
-- we can always remove the break)
break
end
+ if firstnone then
+ protectnone()
+ end
elseif expanders then
local subtype = getsubtype(d)
if subtype == automatic_code or subtype == explicit_code then
@@ -432,11 +465,9 @@ function handlers.characters(head,groupcode,size,packtype,direction)
if u == 0 then
-- skip
elseif u == 1 then
- local font, processors = next(usedfonts)
- -- local attr = a == 0 and false or 0 -- 0 is the savest way
local attr = a > 0 and 0 or false -- 0 is the savest way
- for i=1,#processors do
- local h, d = processors[i](head,font,attr,direction)
+ for i=1,#lastproc do
+ local h, d = lastproc[i](head,lastfont,attr,direction)
if d then
if h then
head = h
@@ -549,19 +580,5 @@ function handlers.characters(head,groupcode,size,packtype,direction)
return head, true
end
-local d_protect_glyphs = nuts.protect_glyphs
-local d_unprotect_glyphs = nuts.unprotect_glyphs
-
-handlers.protectglyphs = function(n) return d_protect_glyphs (tonut(n)) end
-handlers.unprotectglyphs = function(n) return d_unprotect_glyphs(tonut(n)) end
-
--- function handlers.protectglyphs(h)
--- local h = tonut(h)
--- for n in traverse_id(disc_code,h) do
--- local pre, post, replace = getdisc(n)
--- if pre then d_protect_glyphs(pre) end
--- if post then d_protect_glyphs(post) end
--- if replace then d_protect_glyphs(replace) end
--- end
--- return d_protect_glyphs(h)
--- end
+handlers.protectglyphs = function(n) protect_glyphs (tonut(n)) return n, true end
+handlers.unprotectglyphs = function(n) unprotect_glyphs(tonut(n)) return n, true end
diff --git a/tex/context/base/mkiv/node-ini.mkiv b/tex/context/base/mkiv/node-ini.mkiv
index 369b06ab2..0f5a2df7e 100644
--- a/tex/context/base/mkiv/node-ini.mkiv
+++ b/tex/context/base/mkiv/node-ini.mkiv
@@ -36,6 +36,7 @@
%registerctxluafile{node-prp}{1.001} % makes no sense (yet)
\registerctxluafile{node-ppt}{1.001}
\registerctxluafile{node-scn}{1.001}
+\registerctxluafile{node-syn}{1.001}
\newcount\c_node_tracers_show_box % box number
diff --git a/tex/context/base/mkiv/node-met.lua b/tex/context/base/mkiv/node-met.lua
index e6d0f4689..2686aa990 100644
--- a/tex/context/base/mkiv/node-met.lua
+++ b/tex/context/base/mkiv/node-met.lua
@@ -110,8 +110,9 @@ nodes.set_attribute = node.set_attribute
nodes.find_attribute = node.find_attribute
nodes.unset_attribute = node.unset_attribute
-nodes.protect_glyphs = node.protect_glyphs
nodes.protect_glyph = node.protect_glyph
+nodes.protect_glyphs = node.protect_glyphs
+nodes.unprotect_glyph = node.unprotect_glyph
nodes.unprotect_glyphs = node.unprotect_glyphs
nodes.kerning = node.kerning
nodes.ligaturing = node.ligaturing
@@ -669,3 +670,46 @@ end
nodes.keys = keys -- [id][subtype]
nodes.fields = nodefields -- (n)
+
+-- for the moment (pre 6380)
+
+if not nodes.unprotect_glyph then
+
+ local protect_glyph = nodes.protect_glyph
+ local protect_glyphs = nodes.protect_glyphs
+ local unprotect_glyph = nodes.unprotect_glyph
+ local unprotect_glyphs = nodes.unprotect_glyphs
+
+ local getnext = nodes.getnext
+ local setnext = nodes.setnext
+
+ function nodes.protectglyphs(first,last)
+ if first == last then
+ return protect_glyph(first)
+ elseif last then
+ local nxt = getnext(last)
+ setnext(last)
+ local f, b = protect_glyphs(first)
+ setnext(last,nxt)
+ return f, b
+ else
+ return protect_glyphs(first)
+ end
+ end
+
+ function nodes.unprotectglyphs(first,last)
+ if first == last then
+ return unprotect_glyph(first)
+ elseif last then
+ local nxt = getnext(last)
+ setnext(last)
+ local f, b = unprotect_glyphs(first)
+ setnext(last,nxt)
+ return f, b
+ else
+ return unprotect_glyphs(first)
+ end
+ end
+
+end
+
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index 787afd888..87df5d5b2 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -283,8 +283,9 @@ nuts.has_attribute = direct.has_attribute
nuts.set_attribute = direct.set_attribute
nuts.unset_attribute = direct.unset_attribute
-nuts.protect_glyphs = direct.protect_glyphs
nuts.protect_glyph = direct.protect_glyph
+nuts.protect_glyphs = direct.protect_glyphs
+nuts.unprotect_glyph = direct.unprotect_glyph
nuts.unprotect_glyphs = direct.unprotect_glyphs
nuts.ligaturing = direct.ligaturing
nuts.kerning = direct.kerning
@@ -409,18 +410,32 @@ local d_setlink = direct.setlink
local d_setboth = direct.setboth
local d_getboth = direct.getboth
+-- local function remove(head,current,free_too)
+-- local t = current
+-- head, current = d_remove_node(head,current)
+-- if not t then
+-- -- forget about it
+-- elseif free_too then
+-- d_flush_node(t)
+-- t = nil
+-- else
+-- d_setboth(t) -- (t,nil,nil)
+-- end
+-- return head, current, t
+-- end
+
local function remove(head,current,free_too)
- local t = current
- head, current = d_remove_node(head,current)
- if not t then
- -- forget about it
- elseif free_too then
- d_flush_node(t)
- t = nil
- else
- d_setboth(t) -- (t,nil,nil)
+ if current then
+ local h, c = d_remove_node(head,current)
+ if free_too then
+ d_flush_node(current)
+ return h, c
+ else
+ d_setboth(current)
+ return h, c, current
+ end
end
- return head, current, t
+ return head, current
end
-- alias
@@ -902,3 +917,45 @@ if not nuts.uses_font then
end
+-- for the moment (pre 6380)
+
+if not nuts.unprotect_glyph then
+
+ local protect_glyph = nuts.protect_glyph
+ local protect_glyphs = nuts.protect_glyphs
+ local unprotect_glyph = nuts.unprotect_glyph
+ local unprotect_glyphs = nuts.unprotect_glyphs
+
+ local getnext = nuts.getnext
+ local setnext = nuts.setnext
+
+ function nuts.protectglyphs(first,last)
+ if first == last then
+ return protect_glyph(first)
+ elseif last then
+ local nxt = getnext(last)
+ setnext(last)
+ local f, b = protect_glyphs(first)
+ setnext(last,nxt)
+ return f, b
+ else
+ return protect_glyphs(first)
+ end
+ end
+
+ function nuts.unprotectglyphs(first,last)
+ if first == last then
+ return unprotect_glyph(first)
+ elseif last then
+ local nxt = getnext(last)
+ setnext(last)
+ local f, b = unprotect_glyphs(first)
+ setnext(last,nxt)
+ return f, b
+ else
+ return unprotect_glyphs(first)
+ end
+ end
+
+end
+
diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua
index b313a00b6..f2f660e67 100644
--- a/tex/context/base/mkiv/node-ref.lua
+++ b/tex/context/base/mkiv/node-ref.lua
@@ -371,61 +371,30 @@ end
-- we need to do vlists differently
local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main
- if head then
- local current, first, last, firstdir, reference = head, nil, nil, nil, nil
- pardir = pardir or "==="
- txtdir = txtdir or "==="
- while current do
- local id = getid(current)
- if id == hlist_code or id == vlist_code then
- local r = getattr(current,attribute)
- -- test \goto{test}[page(2)] test \gotobox{test}[page(2)]
- -- test \goto{\TeX}[page(2)] test \gotobox{\hbox {x} \hbox {x}}[page(2)]
- -- if r and (not skip or r >) skip then -- maybe no > test
- -- inject_list(id,current,r,make,stack,pardir,txtdir)
- -- end
- if r then
- if not reference then
- reference, first, last, firstdir = r, current, current, txtdir
- elseif r == reference then
- -- same link
- last = current
- elseif (done[reference] or 0) == 0 then
- if not skip or r > skip then -- maybe no > test
- head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
- reference, first, last, firstdir = nil, nil, nil, nil
- end
- else
- reference, first, last, firstdir = r, current, current, txtdir
- end
- done[r] = (done[r] or 0) + 1
- end
- local list = getlist(current)
- if list then
- local h, ok
- h, ok , pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir)
- if h ~= current then
- setlist(current,h)
- end
- end
- if r then
- done[r] = done[r] - 1
- end
- elseif id == dir_code then
- txtdir = getdir(current)
- elseif id == localpar_code then
- pardir = getdir(current)
- elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left?
- --
- else
- local r = getattr(current,attribute)
- if not r then
- -- just go on, can be kerns
- elseif not reference then
+ local first, last, firstdir, reference
+ if not pardir then
+ pardir = "==="
+ end
+ if not texdir then
+ txtdir = "==="
+ end
+ local current = head
+ while current do
+ local id = getid(current)
+ if id == hlist_code or id == vlist_code then
+ local r = getattr(current,attribute)
+ -- test \goto{test}[page(2)] test \gotobox{test}[page(2)]
+ -- test \goto{\TeX}[page(2)] test \gotobox{\hbox {x} \hbox {x}}[page(2)]
+ -- if r and (not skip or r >) skip then -- maybe no > test
+ -- inject_list(id,current,r,make,stack,pardir,txtdir)
+ -- end
+ if r then
+ if not reference then
reference, first, last, firstdir = r, current, current, txtdir
elseif r == reference then
+ -- same link
last = current
- elseif (done[reference] or 0) == 0 then -- or id == glue_code and getsubtype(current) == right_skip_code
+ elseif (done[reference] or 0) == 0 then
if not skip or r > skip then -- maybe no > test
head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
reference, first, last, firstdir = nil, nil, nil, nil
@@ -433,53 +402,89 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
else
reference, first, last, firstdir = r, current, current, txtdir
end
+ done[r] = (done[r] or 0) + 1
end
- current = getnext(current)
- end
- if reference and (done[reference] or 0) == 0 then
- head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
- end
- end
- return head, true, pardir, txtdir
-end
-
-local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) -- singular !
- if head then
- pardir = pardir or "==="
- txtdir = txtdir or "==="
- local current = head
- while current do
- local id = getid(current)
- if id == hlist_code or id == vlist_code then
- local r = getattr(current,attribute)
- if r and not done[r] then
- done[r] = true
- inject_list(id,current,r,make,stack,pardir,txtdir)
+ local list = getlist(current)
+ if list then
+ local h, ok
+ h, ok, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir)
+ if h ~= current then
+ setlist(current,h)
end
- local list = getlist(current)
- if list then
- local h = inject_area(list,attribute,make,stack,done,current,pardir,txtdir)
- if h ~= current then
- setlist(current,h)
- end
+ end
+ if r then
+ done[r] = done[r] - 1
+ end
+ elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left?
+ --
+ elseif id == dir_code then
+ txtdir = getdir(current)
+ elseif id == localpar_code then -- only test at begin
+ pardir = getdir(current)
+ else
+ local r = getattr(current,attribute)
+ if not r then
+ -- just go on, can be kerns
+ elseif not reference then
+ reference, first, last, firstdir = r, current, current, txtdir
+ elseif r == reference then
+ last = current
+ elseif (done[reference] or 0) == 0 then -- or id == glue_code and getsubtype(current) == right_skip_code
+ if not skip or r > skip then -- maybe no > test
+ head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+ reference, first, last, firstdir = nil, nil, nil, nil
end
- elseif id == dir_code then
- txtdir = getdir(current)
- elseif id == localpar_code then
- pardir = getdir(current)
else
- local r = getattr(current,attribute)
- if r and not done[r] then
- done[r] = true
- head, current = inject_range(head,current,current,r,make,stack,parent,pardir,txtdir)
- end
+ reference, first, last, firstdir = r, current, current, txtdir
end
- current = getnext(current)
end
+ current = getnext(current)
end
- return head, true
+ if reference and (done[reference] or 0) == 0 then
+ head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+ end
+ return head, true, pardir, txtdir
end
+-- local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) -- singular !
+-- if not pardir then
+-- pardir = "==="
+-- end
+-- if not texdir then
+-- txtdir = "==="
+-- end
+-- local current = head
+-- while current do
+-- local id = getid(current)
+-- if id == hlist_code or id == vlist_code then
+-- local r = getattr(current,attribute)
+-- if r and not done[r] then
+-- done[r] = true
+-- inject_list(id,current,r,make,stack,pardir,txtdir)
+-- end
+-- local list = getlist(current)
+-- if list then
+-- local h = inject_area(list,attribute,make,stack,done,current,pardir,txtdir)
+-- if h ~= current then
+-- setlist(current,h)
+-- end
+-- end
+-- elseif id == dir_code then
+-- txtdir = getdir(current)
+-- elseif id == localpar_code then
+-- pardir = getdir(current)
+-- else
+-- local r = getattr(current,attribute)
+-- if r and not done[r] then
+-- done[r] = true
+-- head, current = inject_range(head,current,current,r,make,stack,parent,pardir,txtdir)
+-- end
+-- end
+-- current = getnext(current)
+-- end
+-- return head, true
+-- end
+
-- tracing: todo: use predefined colors
local register_color = colors.register
@@ -669,17 +674,9 @@ local function makereference(width,height,depth,reference) -- height and depth a
end
end
--- function nodes.references.handler(head)
--- if topofstack > 0 then
--- return inject_areas(head,attribute,makereference,stack,done)
--- else
--- return head, false
--- end
--- end
-
function nodes.references.handler(head)
- if topofstack > 0 then
- head = tonut(head)
+ if head and topofstack > 0 then
+ local head = tonut(head)
local head, done = inject_areas(head,attribute,makereference,stack,done)
return tonode(head), done
else
@@ -791,7 +788,7 @@ local function makedestination(width,height,depth,reference)
end
-- function nodes.destinations.handler(head)
--- if topofstack > 0 then
+-- if head and topofstack > 0 then
-- return inject_area(head,attribute,makedestination,stack,done) -- singular
-- else
-- return head, false
@@ -799,8 +796,8 @@ end
-- end
function nodes.destinations.handler(head)
- if topofstack > 0 then
- head = tonut(head)
+ if head and topofstack > 0 then
+ local head = tonut(head)
local head, done = inject_areas(head,attribute,makedestination,stack,done)
return tonode(head), done
else
@@ -808,7 +805,6 @@ function nodes.destinations.handler(head)
end
end
-
-- will move
function references.mark(reference,h,d,view)
diff --git a/tex/context/base/mkiv/node-syn.lua b/tex/context/base/mkiv/node-syn.lua
index bd8cc7964..1c070c45f 100644
--- a/tex/context/base/mkiv/node-syn.lua
+++ b/tex/context/base/mkiv/node-syn.lua
@@ -69,6 +69,7 @@ local kerncodes = nodes.kerncodes
local glyph_code = nodecodes.glyph
local disc_code = nodecodes.disc
local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
local kern_code = nodecodes.kern
----- rule_code = nodecodes.rule
local hlist_code = nodecodes.hlist
@@ -81,7 +82,7 @@ local insert_after = nuts.insert_after
local nodepool = nuts.pool
local new_latelua = nodepool.latelua
local new_rule = nodepool.rule
-local new_hlist = nodepool.hlist
+local new_kern = nodepool.kern
local getdimensions = nuts.dimensions
local getrangedimensions = nuts.rangedimensions
@@ -321,7 +322,8 @@ local function inject(head,first,last,tag,line)
d = depth
end
if trace then
- head = insert_before(head,first,new_hlist(new_rule(w,fulltrace and h or traceheight,fulltrace and d or tracedepth)))
+ head = insert_before(head,first,new_rule(w,fulltrace and h or traceheight,fulltrace and d or tracedepth))
+ head = insert_before(head,first,new_kern(-w))
end
head = x_hlist(head,first,tag,line,w,h,d)
return head
@@ -389,7 +391,8 @@ local function inject(parent,head,first,last,tag,line)
d = depth
end
if trace then
- head = insert_before(head,first,new_hlist(new_rule(w,fulltrace and h or traceheight,fulltrace and d or tracedepth)))
+ head = insert_before(head,first,new_rule(w,fulltrace and h or traceheight,fulltrace and d or tracedepth))
+ head = insert_before(head,first,new_kern(-w))
end
head = x_hlist(head,first,tag,line,w,h,d)
return head
@@ -451,6 +454,8 @@ local function collect_max(head,parent)
break
end
id = nil -- so no test later on
+ elseif id == penalty_code then
+ -- go on (and be nice for math)
else
if tag > 0 then
head = inject(parent,head,first,last,tag,line)
@@ -516,16 +521,28 @@ function synctex.stop()
end
end
+local enablers = { }
+local disablers = { }
+
+function synctex.registerenabler(f)
+ enablers[#enablers+1] = f
+end
+function synctex.registerdisabler(f)
+ disablers[#disablers+1] = f
+end
+
function synctex.enable()
if not enabled then
enabled = true
set_synctex_mode(3) -- we want details
if not used then
- directives.enable("system.synctex.xml")
nodes.tasks.appendaction("shipouts", "after", "luatex.synctex.collect")
report_system("synctex functionality is enabled, expect 5-10 pct runtime overhead!")
used = true
end
+ for i=1,#enablers do
+ enablers[i](true)
+ end
end
end
@@ -534,6 +551,9 @@ function synctex.disable()
set_synctex_mode(0)
report_system("synctex functionality is disabled!")
enabled = false
+ for i=1,#disablers do
+ disablers[i](false)
+ end
end
end
@@ -563,14 +583,6 @@ end
luatex.registerstopactions(synctex.finish)
-directives.register("system.synctex", function(v)
- if v then
- synctex.enable()
- else
- synctex.disable()
- end
-end)
-
statistics.register("synctex tracing",function()
if used then
return string.format("%i referenced files, %i files ignored, %i objects flushed, logfile: %s",
@@ -595,26 +607,28 @@ interfaces.implement {
actions = synctex.resetfilename,
}
+function synctex.setup(t)
+ if t.method == interfaces.variables.max then
+ collect = collect_max
+ else
+ collect = collect_min
+ end
+ if t.state == interfaces.variables.start then
+ synctex.enable()
+ else
+ synctex.disable()
+ end
+end
+
interfaces.implement {
name = "setupsynctex",
+ actions = synctex.setup,
arguments = {
{
{ "state" },
{ "method" },
},
},
- actions = function(t)
- if t.method == interfaces.variables.max then
- collect = collect_max
- else
- collect = collect_min
- end
- if t.state == interfaces.variables.start then
- synctex.enable()
- else
- synctex.disable()
- end
- end
}
interfaces.implement {
diff --git a/tex/context/base/mkiv/spac-chr.lua b/tex/context/base/mkiv/spac-chr.lua
index fe402ed87..b8a53d2a1 100644
--- a/tex/context/base/mkiv/spac-chr.lua
+++ b/tex/context/base/mkiv/spac-chr.lua
@@ -48,6 +48,7 @@ local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local remove_node = nuts.remove
local traverse_id = nuts.traverse_id
+local traverse_char = nuts.traverse_char
local tasks = nodes.tasks
@@ -148,16 +149,37 @@ function characters.replacenbsp(head,original)
return head, current
end
+-- function characters.replacenbspaces(head)
+-- for current in traverse_id(glyph_code,head) do
+-- if getchar(current) == 0x00A0 then
+-- local h = nbsp(head,current)
+-- if h then
+-- head = remove_node(h,current,true)
+-- end
+-- end
+-- end
+-- return head
+-- end
+
function characters.replacenbspaces(head)
- for current in traverse_id(glyph_code,head) do
+ local head = tonut(head)
+ local wipe = false
+ for current in traverse_id(glyph_code,head) do -- can be anytiem so no traverse_char
if getchar(current) == 0x00A0 then
+ if wipe then
+ head = remove_node(h,current,true)
+ wipe = false
+ end
local h = nbsp(head,current)
if h then
- head = remove_node(h,current,true)
+ wipe = current
end
end
end
- return head
+ if wipe then
+ head = remove_node(h,current,true)
+ end
+ return tonode(head)
end
-- This initialization might move someplace else if we need more of it. The problem is that
@@ -283,29 +305,60 @@ local methods = {
characters.methods = methods
-function characters.handler(head) -- todo: use traverse_id
- head = tonut(head)
- local current = head
- local done = false
- while current do
- local char, id = isglyph(current)
+-- function characters.handler(head) -- todo: use traverse_id
+-- head = tonut(head)
+-- local current = head
+-- local done = false
+-- while current do
+-- local char, id = isglyph(current)
+-- if char then
+-- local next = getnext(current)
+-- local method = methods[char]
+-- if method then
+-- if trace_characters then
+-- report_characters("replacing character %C, description %a",char,lower(chardata[char].description))
+-- end
+-- local h = method(head,current)
+-- if h then
+-- head = remove_node(h,current,true)
+-- end
+-- done = true
+-- end
+-- current = next
+-- else
+-- current = getnext(current)
+-- end
+-- end
+-- return tonode(head), done
+-- end
+
+-- for current, char, font in traverse_char_data(head) will save 0.015 on a 300 page doc
+
+function characters.handler(head)
+ local head = tonut(head)
+ local wipe = false
+ for current in traverse_char(head) do
+ local char = getchar(current)
if char then
- local next = getnext(current)
local method = methods[char]
if method then
+ if wipe then
+ head = remove_node(head,wipe,true)
+ wipe = false
+ end
if trace_characters then
report_characters("replacing character %C, description %a",char,lower(chardata[char].description))
end
local h = method(head,current)
if h then
- head = remove_node(h,current,true)
+ wipe = current
end
done = true
end
- current = next
- else
- current = getnext(current)
end
end
+ if wipe then
+ head = remove_node(head,wipe,true)
+ end
return tonode(head), done
end
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 72baf08cc..83c6b914d 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index b33293a23..9950ca3a6 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/strc-con.mkvi b/tex/context/base/mkiv/strc-con.mkvi
index 18ce17355..522026556 100644
--- a/tex/context/base/mkiv/strc-con.mkvi
+++ b/tex/context/base/mkiv/strc-con.mkvi
@@ -73,6 +73,8 @@
\c!display=\v!yes,
\c!width=7\emwidth,
\c!distance=\emwidth,
+ \c!stretch=.50,
+ \c!shrink=.25,
\c!titledistance=.5\emwidth,
%c!hang=,
%c!sample=,
@@ -410,8 +412,12 @@
\installcommandhandler \??constructionalternative {constructionalternative} \??constructionalternative
\setupconstructionalternative
- [\c!width=\constructionparameter\c!width,
- \c!distance=\constructionparameter\c!distance]
+ [%c!left=, % no inheritance
+ %c!right=,% no inheritance
+ \c!width=\constructionparameter\c!width,
+ \c!distance=\constructionparameter\c!distance,
+ \c!stretch=\constructionparameter\c!stretch,
+ \c!shrink=\constructionparameter\c!shrink]
\defineconstructionalternative
[\v!left]
@@ -463,7 +469,7 @@
\defineconstructionalternative
[\v!hanging]
- [%\c!width=\v!fit,
+ [%\c!width=.75\emwidth
\c!renderingsetup=\??constructionrenderings:\v!hanging]
\defineconstructionalternative
@@ -778,7 +784,10 @@
\flushconstructionheadbox
\ifconditional\c_strc_constructions_distance_none \else
\nobreak
- \hskip\constructionsheaddistance \s!plus .5\constructionsheaddistance \s!minus .25\constructionsheaddistance\relax
+ \hskip\constructionsheaddistance
+ \s!plus \constructionalternativeparameter\c!stretch\constructionsheaddistance
+ \s!minus\constructionalternativeparameter\c!shrink \constructionsheaddistance
+ \relax
\fi
\useconstructionstyleandcolor\c!style\c!color
\ignorespaces
@@ -822,9 +831,9 @@
\ifconditional\c_strc_constructions_distance_none \else
% we used to have just a kern, but long lines look bad then
\scratchdistance\ifdim\constructionsheaddistance=\zeropoint .75\emwidth\else\constructionsheaddistance\fi
- \hskip \scratchdistance
- \s!plus .25\scratchdistance
- \s!minus.25\scratchdistance
+ \hskip \scratchdistance
+ \s!plus \constructionalternativeparameter\c!stretch\scratchdistance
+ \s!minus\constructionalternativeparameter\c!shrink \scratchdistance
\fi
\ifhmode
\ifx\p_strc_constructions_width\v!line
diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua
index b9bf0ccf0..fc206b6d2 100644
--- a/tex/context/base/mkiv/supp-box.lua
+++ b/tex/context/base/mkiv/supp-box.lua
@@ -350,6 +350,7 @@ implement {
local result = new_hlist()
setlist(result,head)
setbox(target,result)
+ -- setbox(target,new_hlist(head))
end
}
diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua
index d58114d71..38bad03e2 100644
--- a/tex/context/base/mkiv/trac-vis.lua
+++ b/tex/context/base/mkiv/trac-vis.lua
@@ -6,11 +6,11 @@ if not modules then modules = { } end modules ['trac-vis'] = {
license = "see context related readme files"
}
-local string, number, table = string, number, table
local node, nodes, attributes, fonts, tex = node, nodes, attributes, fonts, tex
local type = type
local gmatch = string.gmatch
local formatters = string.formatters
+local compactfloat = number.compactfloat
-- This module started out in the early days of mkiv and luatex with
-- visualizing kerns related to fonts. In the process of cleaning up the
@@ -166,6 +166,7 @@ local trace_user
local trace_math
local trace_italic
local trace_discretionary
+local trace_expansion
local report_visualize = logs.reporter("visualize")
@@ -190,10 +191,11 @@ local modes = {
italic = 8192,
origin = 16384,
discretionary = 32768,
+ expansion = 65536,
}
local usedfont, exheight, emwidth
-local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic, l_origin, l_discretionary
+local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic, l_origin, l_discretionary, l_expansion
local enabled = false
local layers = { }
@@ -243,6 +245,7 @@ local function enable()
l_italic = layers.italic
l_origin = layers.origin
l_discretionary = layers.discretionary
+ l_expansion = layers.expansion
enableaction("shipouts","nodes.visualizers.handler")
report_visualize("enabled")
enabled = true
@@ -355,6 +358,7 @@ local c_white = "trace:w"
local c_math = "trace:r"
local c_origin = "trace:o"
local c_discretionary = "trace:o"
+local c_expansion = "trace:o"
local c_positive_d = "trace:db"
local c_negative_d = "trace:dr"
@@ -369,6 +373,7 @@ local c_white_d = "trace:dw"
local c_math_d = "trace:dr"
local c_origin_d = "trace:do"
local c_discretionary_d = "trace:do"
+local c_expansion_d = "trace:do"
local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed
local text = hpack_string(str,usedfont)
@@ -435,6 +440,78 @@ local fontkern do
end
+local glyphexpansion do
+
+ local f_cache = caches["glyphexpansion"]
+
+ glyphexpansion = function(head,current)
+ local extra = getfield(current,"expansion_factor")
+ if extra ~= 0 then
+ extra = extra / 1000
+ local info = f_cache[extra]
+ if info then
+ -- print("hit fontkern")
+ else
+ local text = hpack_string(compactfloat(extra,"%.1f"),usedfont)
+ local rule = new_rule(emwidth/fraction,exheight,2*exheight)
+ local list = getlist(text)
+ if extra > 0 then
+ setlistcolor(list,c_positive_d)
+ elseif extra < 0 then
+ setlistcolor(list,c_negative_d)
+ end
+ setlisttransparency(list,c_text_d)
+ setcolor(rule,c_text_d)
+ settransparency(rule,c_text_d)
+ setshift(text,1.5 * exheight)
+ info = new_hlist(setlink(rule,text))
+ setattr(info,a_layer,l_expansion)
+ f_cache[extra] = info
+ end
+ head = insert_node_before(head,current,copy_list(info))
+ return head, current
+ end
+ return head, current
+ end
+
+end
+
+local kernexpansion do
+
+ local f_cache = caches["kernexpansion"]
+
+ kernexpansion = function(head,current)
+ local extra = getfield(current,"expansion_factor")
+ if extra ~= 0 then
+ extra = extra / 1000
+ local info = f_cache[extra]
+ if info then
+ -- print("hit fontkern")
+ else
+ local text = hpack_string(compactfloat(extra,"%.1f"),usedfont)
+ local rule = new_rule(emwidth/fraction,exheight,4*exheight)
+ local list = getlist(text)
+ if extra > 0 then
+ setlistcolor(list,c_positive_d)
+ elseif extra < 0 then
+ setlistcolor(list,c_negative_d)
+ end
+ setlisttransparency(list,c_text_d)
+ setcolor(rule,c_text_d)
+ settransparency(rule,c_text_d)
+ setshift(text,3.5 * exheight)
+ info = new_hlist(setlink(rule,text))
+ setattr(info,a_layer,l_expansion)
+ f_cache[extra] = info
+ end
+ head = insert_node_before(head,current,copy_list(info))
+ return head, current
+ end
+ return head, current
+ end
+
+end
+
local whatsit do
local w_cache = caches["whatsit"]
@@ -929,151 +1006,161 @@ local ruledpenalty do
end
-local function visualize(head,vertical,forced,parent)
- local trace_hbox = false
- local trace_vbox = false
- local trace_vtop = false
- local trace_kern = false
- local trace_glue = false
- local trace_penalty = false
- local trace_fontkern = false
- local trace_strut = false
- local trace_whatsit = false
- local trace_glyph = false
- local trace_simple = false
- local trace_user = false
- local trace_math = false
- local trace_italic = false
- local trace_origin = false
- local current = head
- local previous = nil
- local attr = unsetvalue
- local prev_trace_fontkern = nil
- while current do
- local id = getid(current)
- local a = forced or getattr(current,a_visual) or unsetvalue
- if a ~= attr then
- prev_trace_fontkern = trace_fontkern
- if a == unsetvalue then
- trace_hbox = false
- trace_vbox = false
- trace_vtop = false
- trace_kern = false
- trace_glue = false
- trace_penalty = false
- trace_fontkern = false
- trace_strut = false
- trace_whatsit = false
- trace_glyph = false
- trace_simple = false
- trace_user = false
- trace_math = false
- trace_italic = false
- trace_origin = false
- trace_discretionary = false
- else -- dead slow:
- trace_hbox = hasbit(a, 1)
- trace_vbox = hasbit(a, 2)
- trace_vtop = hasbit(a, 4)
- trace_kern = hasbit(a, 8)
- trace_glue = hasbit(a, 16)
- trace_penalty = hasbit(a, 32)
- trace_fontkern = hasbit(a, 64)
- trace_strut = hasbit(a, 128)
- trace_whatsit = hasbit(a, 256)
- trace_glyph = hasbit(a, 512)
- trace_simple = hasbit(a, 1024)
- trace_user = hasbit(a, 2048)
- trace_math = hasbit(a, 4096)
- trace_italic = hasbit(a, 8192)
- trace_origin = hasbit(a,16384)
- trace_discretionary = hasbit(a,32768)
- end
- attr = a
- end
- if trace_strut then
- setattr(current,a_layer,l_strut)
- elseif id == glyph_code then
- if trace_glyph then
- head, current = ruledglyph(head,current,previous)
- end
- elseif id == disc_code then
- if trace_discretionary then
- head, current = ruleddiscretionary(head,current)
- end
- local pre, post, replace = getdisc(current)
- if pre then
- pre = visualize(pre,false,a,parent)
- end
- if post then
- post = visualize(post,false,a,parent)
- end
- if replace then
- replace = visualize(replace,false,a,parent)
+do
+
+ local function visualize(head,vertical,forced,parent)
+ local trace_hbox = false
+ local trace_vbox = false
+ local trace_vtop = false
+ local trace_kern = false
+ local trace_glue = false
+ local trace_penalty = false
+ local trace_fontkern = false
+ local trace_strut = false
+ local trace_whatsit = false
+ local trace_glyph = false
+ local trace_simple = false
+ local trace_user = false
+ local trace_math = false
+ local trace_italic = false
+ local trace_origin = false
+ local current = head
+ local previous = nil
+ local attr = unsetvalue
+ local prev_trace_fontkern = nil
+ local prev_trace_expansion = nil
+ while current do
+ local id = getid(current)
+ local a = forced or getattr(current,a_visual) or unsetvalue
+ if a ~= attr then
+ prev_trace_fontkern = trace_fontkern
+ prev_trace_expansion = trace_expansion
+ if a == unsetvalue then
+ trace_hbox = false
+ trace_vbox = false
+ trace_vtop = false
+ trace_kern = false
+ trace_glue = false
+ trace_penalty = false
+ trace_fontkern = false
+ trace_strut = false
+ trace_whatsit = false
+ trace_glyph = false
+ trace_simple = false
+ trace_user = false
+ trace_math = false
+ trace_italic = false
+ trace_origin = false
+ trace_discretionary = false
+ trace_expansion = false
+ else -- dead slow:
+ trace_hbox = hasbit(a, 1)
+ trace_vbox = hasbit(a, 2)
+ trace_vtop = hasbit(a, 4)
+ trace_kern = hasbit(a, 8)
+ trace_glue = hasbit(a, 16)
+ trace_penalty = hasbit(a, 32)
+ trace_fontkern = hasbit(a, 64)
+ trace_strut = hasbit(a, 128)
+ trace_whatsit = hasbit(a, 256)
+ trace_glyph = hasbit(a, 512)
+ trace_simple = hasbit(a, 1024)
+ trace_user = hasbit(a, 2048)
+ trace_math = hasbit(a, 4096)
+ trace_italic = hasbit(a, 8192)
+ trace_origin = hasbit(a,16384)
+ trace_discretionary = hasbit(a,32768)
+ trace_expansion = hasbit(a,65536)
+ end
+ attr = a
end
- setdisc(current,pre,post,replace)
- elseif id == kern_code then
- local subtype = getsubtype(current)
- if subtype == font_kern_code then
- if trace_fontkern or prev_trace_fontkern then
- head, current = fontkern(head,current)
+ if trace_strut then
+ setattr(current,a_layer,l_strut)
+ elseif id == glyph_code then
+ if trace_glyph then
+ head, current = ruledglyph(head,current,previous)
end
- else -- if subtype == user_kern_code then
- if trace_italic then
- head, current = ruleditalic(head,current)
- elseif trace_kern then
- head, current = ruledkern(head,current,vertical)
+ if trace_expansion then
+ head, current = glyphexpansion(head,current)
+ end
+ elseif id == disc_code then
+ if trace_discretionary then
+ head, current = ruleddiscretionary(head,current)
+ end
+ local pre, post, replace = getdisc(current)
+ if pre then
+ pre = visualize(pre,false,a,parent)
+ end
+ if post then
+ post = visualize(post,false,a,parent)
+ end
+ if replace then
+ replace = visualize(replace,false,a,parent)
+ end
+ setdisc(current,pre,post,replace)
+ elseif id == kern_code then
+ local subtype = getsubtype(current)
+ if subtype == font_kern_code then
+ if trace_fontkern or prev_trace_fontkern then
+ head, current = fontkern(head,current)
+ end
+ if trace_expansion or prev_trace_expansion then
+ head, current = kernexpansion(head,current)
+ end
+ else -- if subtype == user_kern_code then
+ if trace_italic then
+ head, current = ruleditalic(head,current)
+ elseif trace_kern then
+ head, current = ruledkern(head,current,vertical)
+ end
+ end
+ elseif id == glue_code then
+ local content = getleader(current)
+ if content then
+ setleader(current,visualize(content,false,nil,parent))
+ elseif trace_glue then
+ head, current = ruledglue(head,current,vertical,parent)
+ end
+ elseif id == penalty_code then
+ if trace_penalty then
+ head, current = ruledpenalty(head,current,vertical)
+ end
+ elseif id == hlist_code then
+ local content = getlist(current)
+ if content then
+ setlist(current,visualize(content,false,nil,current))
+ end
+ if trace_hbox then
+ head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent)
+ end
+ elseif id == vlist_code then
+ local content = getlist(current)
+ if content then
+ setlist(current,visualize(content,true,nil,current))
+ end
+ if trace_vtop then
+ head, current = ruledbox(head,current,true,l_vtop,"_T_",trace_simple,previous,trace_origin,parent)
+ elseif trace_vbox then
+ head, current = ruledbox(head,current,true,l_vbox,"__V",trace_simple,previous,trace_origin,parent)
+ end
+ elseif id == whatsit_code then
+ if trace_whatsit then
+ head, current = whatsit(head,current)
+ end
+ elseif id == user_code then
+ if trace_user then
+ head, current = user(head,current)
+ end
+ elseif id == math_code then
+ if trace_math then
+ head, current = math(head,current)
end
end
- elseif id == glue_code then
- local content = getleader(current)
- if content then
- setleader(current,visualize(content,false,nil,parent))
- elseif trace_glue then
- head, current = ruledglue(head,current,vertical,parent)
- end
- elseif id == penalty_code then
- if trace_penalty then
- head, current = ruledpenalty(head,current,vertical)
- end
- elseif id == hlist_code then
- local content = getlist(current)
- if content then
- setlist(current,visualize(content,false,nil,current))
- end
- if trace_hbox then
- head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent)
- end
- elseif id == vlist_code then
- local content = getlist(current)
- if content then
- setlist(current,visualize(content,true,nil,current))
- end
- if trace_vtop then
- head, current = ruledbox(head,current,true,l_vtop,"_T_",trace_simple,previous,trace_origin,parent)
- elseif trace_vbox then
- head, current = ruledbox(head,current,true,l_vbox,"__V",trace_simple,previous,trace_origin,parent)
- end
- elseif id == whatsit_code then
- if trace_whatsit then
- head, current = whatsit(head,current)
- end
- elseif id == user_code then
- if trace_user then
- head, current = user(head,current)
- end
- elseif id == math_code then
- if trace_math then
- head, current = math(head,current)
- end
+ previous = current
+ current = getnext(current)
end
- previous = current
- current = getnext(current)
+ return head
end
- return head
-end
-
-do
local function cleanup()
for tag, cache in next, caches do
@@ -1101,20 +1188,20 @@ do
luatex.registerstopactions(cleanup)
-end
-
-function visualizers.box(n)
- if usedfont then
- starttiming(visualizers)
- local box = getbox(n)
- if box then
- setlist(box,visualize(getlist(box),getid(box) == vlist_code))
+ function visualizers.box(n)
+ if usedfont then
+ starttiming(visualizers)
+ local box = getbox(n)
+ if box then
+ setlist(box,visualize(getlist(box),getid(box) == vlist_code))
+ end
+ stoptiming(visualizers)
+ return head, true
+ else
+ return head, false
end
- stoptiming(visualizers)
- return head, true
- else
- return head, false
end
+
end
do
@@ -1162,40 +1249,44 @@ end)
-- interface
-local implement = interfaces.implement
+do
-implement {
- name = "setvisual",
- arguments = "string",
- actions = visualizers.setvisual
-}
+ local implement = interfaces.implement
-implement {
- name = "setvisuals",
- arguments = "string",
- actions = visualizers.setvisual
-}
+ implement {
+ name = "setvisual",
+ arguments = "string",
+ actions = visualizers.setvisual
+ }
-implement {
- name = "getvisual",
- arguments = "string",
- actions = { setvisual, context }
-}
+ implement {
+ name = "setvisuals",
+ arguments = "string",
+ actions = visualizers.setvisual
+ }
implement {
- name = "setvisuallayer",
- arguments = "string",
- actions = visualizers.setlayer
-}
+ name = "getvisual",
+ arguments = "string",
+ actions = { setvisual, context }
+ }
-implement {
- name = "markvisualfonts",
- arguments = "integer",
- actions = visualizers.markfonts
-}
+ implement {
+ name = "setvisuallayer",
+ arguments = "string",
+ actions = visualizers.setlayer
+ }
-implement {
- name = "setvisualfont",
- arguments = "integer",
- actions = visualizers.setfont
-}
+ implement {
+ name = "markvisualfonts",
+ arguments = "integer",
+ actions = visualizers.markfonts
+ }
+
+ implement {
+ name = "setvisualfont",
+ arguments = "integer",
+ actions = visualizers.setfont
+ }
+
+end
diff --git a/tex/context/base/mkiv/trac-vis.mkiv b/tex/context/base/mkiv/trac-vis.mkiv
index 894408222..fbe59a875 100644
--- a/tex/context/base/mkiv/trac-vis.mkiv
+++ b/tex/context/base/mkiv/trac-vis.mkiv
@@ -119,6 +119,9 @@
\unexpanded\def\showfontkerns
{\clf_setvisual{fontkern}}
+\unexpanded\def\showfontexpansion
+ {\clf_setvisual{expansion}}
+
\unexpanded\def\setvisualizerfont
{\dosingleempty\syst_visualizers_setfont}
diff --git a/tex/context/base/mkiv/typo-del.mkiv b/tex/context/base/mkiv/typo-del.mkiv
index 84fe2c469..b7ebb28d9 100644
--- a/tex/context/base/mkiv/typo-del.mkiv
+++ b/tex/context/base/mkiv/typo-del.mkiv
@@ -369,7 +369,7 @@
%\c!language=\v!local,
\c!repeat=\v!no]
-\def\typo_delimited_repeat_ideed
+\def\typo_delimited_repeat_indeed
{\relax\ifcase\delimitedtextlevel\else
\typo_delimited_handle_middle\c!middle
\fi}
diff --git a/tex/context/base/mkiv/util-lib.lua b/tex/context/base/mkiv/util-lib.lua
index ab26afe46..5c3f5f3cf 100644
--- a/tex/context/base/mkiv/util-lib.lua
+++ b/tex/context/base/mkiv/util-lib.lua
@@ -343,10 +343,17 @@ We use the same lookup logic for ffi loading.
local trace_ffilib = false
local savedffiload = ffi.load
+ -- local pushlibpath = package.pushlibpath
+ -- local poplibpath = package.poplibpath
+
-- ffi.savedload = savedffiload
trackers.register("resolvers.ffilib", function(v) trace_ffilib = v end)
+ -- pushlibpath(pathpart(name))
+ -- local message, library = pcall(savedffiload,nameonly(name))
+ -- poplibpath()
+
local function locateindeed(name)
local message, library = pcall(savedffiload,removesuffix(name))
if type(message) == "userdata" then
diff --git a/tex/context/base/mkiv/util-sbx.lua b/tex/context/base/mkiv/util-sbx.lua
index 66a650875..9318ee38a 100644
--- a/tex/context/base/mkiv/util-sbx.lua
+++ b/tex/context/base/mkiv/util-sbx.lua
@@ -28,6 +28,7 @@ local concat = string.concat
local unquoted = string.unquoted
local optionalquoted = string.optionalquoted
local basename = file.basename
+local nameonly = file.nameonly
local sandbox = sandbox
local validroots = { }
@@ -122,9 +123,9 @@ local function registerlibrary(name)
return
end
if validlibraries == true then
- validlibraries = { [name] = true }
+ validlibraries = { [nameonly(name)] = true }
else
- validlibraries[name] = true
+ validlibraries[nameonly(name)] = true
end
elseif name == true then
validlibraries = { }
@@ -562,9 +563,9 @@ if FFISUPPORTED and ffi then
end
end
- local load = ffi.load
+ local fiiload = ffi.load
- if load then
+ if fiiload then
local reported = { }
@@ -573,10 +574,10 @@ if FFISUPPORTED and ffi then
-- all blocked
elseif validlibraries == true then
-- all permitted
- return load(name,...)
- elseif validlibraries[name] then
+ return fiiload(name,...)
+ elseif validlibraries[nameonly(name)] then
-- 'name' permitted
- return load(name,...)
+ return fiiload(name,...)
else
-- 'name' not permitted
end
diff --git a/tex/context/base/mkiv/util-seq.lua b/tex/context/base/mkiv/util-seq.lua
index 5836f5eca..d302ff276 100644
--- a/tex/context/base/mkiv/util-seq.lua
+++ b/tex/context/base/mkiv/util-seq.lua
@@ -361,6 +361,6 @@ function sequencers.nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug
end
end
local processor = #calls > 0 and formatters[nostate and template_yes_nostate or template_yes_state](concat(vars,"\n"),args,concat(calls,"\n")) or template_nop
--- print(processor)
+ -- print(processor)
return processor
end
diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua
index cebbc6be2..6d8f198ab 100644
--- a/tex/context/base/mkiv/util-str.lua
+++ b/tex/context/base/mkiv/util-str.lua
@@ -423,6 +423,27 @@ end
-- print(number.formatted(12345678,true))
-- print(number.formatted(1234.56,"!","?"))
+local p = Cs(
+ P("-")^0
+ * (P("0")^1/"")^0
+ * (1-P("."))^0
+ * (P(".") * P("0")^1 * P(-1)/"" + P(".")^0)
+ * P(1-P("0")^1*P(-1))^0
+ )
+
+function number.compactfloat(n,fmt)
+ if n == 0 then
+ return "0"
+ elseif n == 1 then
+ return "1"
+ end
+ n = lpegmatch(p,format(fmt or "%0.3f",n))
+ if n == "." or n == "" or n == "-" then
+ return "0"
+ end
+ return n
+end
+
local zero = P("0")^1 / ""
local plus = P("+") / ""
local minus = P("-")
@@ -1183,3 +1204,21 @@ local pattern = Cs((newline / (os.newline or "\r") + 1)^0)
function string.replacenewlines(str)
return lpegmatch(pattern,str)
end
+
+--
+
+function strings.newcollector()
+ local result, r = { }, 0
+ return
+ function(fmt,str,...) -- write
+ r = r + 1
+ result[r] = str == nil and fmt or formatters[fmt](str,...)
+ end,
+ function(connector) -- flush
+ if result then
+ local str = concat(result,connector)
+ result, r = { }, 0
+ return str
+ end
+ end
+end
diff --git a/tex/context/base/mkiv/util-tab.lua b/tex/context/base/mkiv/util-tab.lua
index fb2702228..05038f2fb 100644
--- a/tex/context/base/mkiv/util-tab.lua
+++ b/tex/context/base/mkiv/util-tab.lua
@@ -616,6 +616,10 @@ local is_simple_table = table.is_simple_table
-- return nil
-- end
+-- In order to overcome the luajit (65K constant) limitation I tried a split approach,
+-- i.e. outputting the first level tables as locals but that failed with large cjk
+-- fonts too so I removed that ... just use luatex instead.
+
local function serialize(root,name,specification)
if type(specification) == "table" then
diff --git a/tex/context/interface/mkii/keys-en.xml b/tex/context/interface/mkii/keys-en.xml
index a1c935db8..be455e9fc 100644
--- a/tex/context/interface/mkii/keys-en.xml
+++ b/tex/context/interface/mkii/keys-en.xml
@@ -693,6 +693,7 @@
<cd:constant name='bottomoffset' value='bottomoffset'/>
<cd:constant name='bottomspace' value='bottomspace'/>
<cd:constant name='bottomstate' value='bottomstate'/>
+ <cd:constant name='break' value='break'/>
<cd:constant name='buffer' value='buffer'/>
<cd:constant name='cache' value='cache'/>
<cd:constant name='calculate' value='calculate'/>
diff --git a/tex/context/interface/mkii/keys-pe.xml b/tex/context/interface/mkii/keys-pe.xml
index 91f778c5e..4033b45f8 100644
--- a/tex/context/interface/mkii/keys-pe.xml
+++ b/tex/context/interface/mkii/keys-pe.xml
@@ -693,6 +693,7 @@
<cd:constant name='bottomoffset' value='آفست‌پایین'/>
<cd:constant name='bottomspace' value='فضای‌پایین'/>
<cd:constant name='bottomstate' value='وضعیت‌پایین'/>
+ <cd:constant name='break' value='break'/>
<cd:constant name='buffer' value='buffer'/>
<cd:constant name='cache' value='میانگیر'/>
<cd:constant name='calculate' value='محاسبه'/>
diff --git a/tex/context/interface/mkiv/context-en.xml b/tex/context/interface/mkiv/context-en.xml
index b6308269d..ce9a81b5a 100644
--- a/tex/context/interface/mkiv/context-en.xml
+++ b/tex/context/interface/mkiv/context-en.xml
@@ -7361,6 +7361,12 @@
<cd:constant type="none"/>
<cd:constant type="cd:dimension"/>
</cd:parameter>
+ <cd:parameter name="stretch">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="shrink">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
<cd:parameter name="hang">
<cd:constant type="fit"/>
<cd:constant type="broad"/>
@@ -8081,6 +8087,12 @@
<cd:constant type="none"/>
<cd:constant type="cd:dimension"/>
</cd:parameter>
+ <cd:parameter name="stretch">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="shrink">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
<cd:parameter name="hang">
<cd:constant type="fit"/>
<cd:constant type="broad"/>
@@ -25269,6 +25281,12 @@
<cd:constant type="none"/>
<cd:constant type="cd:dimension"/>
</cd:parameter>
+ <cd:parameter name="stretch">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="shrink">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
<cd:parameter name="hang">
<cd:constant type="fit"/>
<cd:constant type="broad"/>
diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf
index 42aaf874c..22a0fdd48 100644
--- a/tex/context/interface/mkiv/i-context.pdf
+++ b/tex/context/interface/mkiv/i-context.pdf
Binary files differ
diff --git a/tex/context/interface/mkiv/i-description.xml b/tex/context/interface/mkiv/i-description.xml
index 6f836f326..66da76acc 100644
--- a/tex/context/interface/mkiv/i-description.xml
+++ b/tex/context/interface/mkiv/i-description.xml
@@ -84,6 +84,12 @@
<cd:constant type="none"/>
<cd:constant type="cd:dimension"/>
</cd:parameter>
+ <cd:parameter name="stretch">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="shrink">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
<cd:parameter name="hang">
<cd:constant type="fit"/>
<cd:constant type="broad"/>
diff --git a/tex/context/interface/mkiv/i-enumeration.xml b/tex/context/interface/mkiv/i-enumeration.xml
index 2469a9713..575d192a5 100644
--- a/tex/context/interface/mkiv/i-enumeration.xml
+++ b/tex/context/interface/mkiv/i-enumeration.xml
@@ -130,6 +130,12 @@
<cd:constant type="none"/>
<cd:constant type="cd:dimension"/>
</cd:parameter>
+ <cd:parameter name="stretch">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="shrink">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
<cd:parameter name="hang">
<cd:constant type="fit"/>
<cd:constant type="broad"/>
diff --git a/tex/context/interface/mkiv/i-note.xml b/tex/context/interface/mkiv/i-note.xml
index 339bb58ad..734702264 100644
--- a/tex/context/interface/mkiv/i-note.xml
+++ b/tex/context/interface/mkiv/i-note.xml
@@ -138,6 +138,12 @@
<cd:constant type="none"/>
<cd:constant type="cd:dimension"/>
</cd:parameter>
+ <cd:parameter name="stretch">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
+ <cd:parameter name="shrink">
+ <cd:constant type="cd:number"/>
+ </cd:parameter>
<cd:parameter name="hang">
<cd:constant type="fit"/>
<cd:constant type="broad"/>
diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf
index 1ad38df61..3c36718a9 100644
--- a/tex/context/interface/mkiv/i-readme.pdf
+++ b/tex/context/interface/mkiv/i-readme.pdf
Binary files differ
diff --git a/tex/context/test/mkiv/pdf-ua.mkiv b/tex/context/test/mkiv/pdf-ua.mkiv
index e048b9717..e83bd88b9 100644
--- a/tex/context/test/mkiv/pdf-ua.mkiv
+++ b/tex/context/test/mkiv/pdf-ua.mkiv
@@ -13,7 +13,7 @@
\setuptagging[state=start] % should be set automatically, if 'tagging = true'
\setuplanguage[en]
-
+
% DisplayDocTitle key is not set to true
%
% [from PDFUA-Reference-09_(English-invoice).pdf]
@@ -21,6 +21,7 @@
% <</Type/Catalog/Pages 1 0 R/ViewerPreferences<</DisplayDocTitle true>>/PageMode/UseOutlines/Outlines 43 0 R/Lang(en)/StructTreeRoot 2 0 R/MarkInfo<</Marked true/Suspects false>>/OutputIntents[ 128 0 R]/Metadata 127 0 R>>
% endobj
% this may interfer with other ViewerPreferences settings?
+
\startluacode
lpdf.addtocatalog("ViewerPreferences",lpdf.dictionary{DisplayDocTitle = true})
\stopluacode
@@ -29,13 +30,13 @@
\starttext
Warning: This document may contain errors and traces of hazelnuts.
-
+
\blank[big]
\startMPcode
fill fullcircle scaled 3cm withcolor red;
\stopMPcode
-
+
\blank[big]
The \quote{Matterhorn Protocol} gives a condensed overview of the possible failure conditions
diff --git a/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua b/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua
index 1fc1c79f7..1e4256003 100644
--- a/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua
+++ b/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua
@@ -8,12 +8,12 @@ if not modules then modules = { } end modules ['luatex-fonts-demo-vf-1'] = {
local identifiers = fonts.hashes.identifiers
-local defaults = {
- { "pdf", "0 g" },
- { "pdf", "1 0 0 rg" },
- { "pdf", "0 1 0 rg" },
- { "pdf", "0 0 1 rg" },
- { "pdf", "0 0 1 rg" },
+local defaults = { [0] =
+ { "pdf", "origin", "0 g" },
+ { "pdf", "origin", "1 0 0 rg" },
+ { "pdf", "origin", "0 1 0 rg" },
+ { "pdf", "origin", "0 0 1 rg" },
+ { "pdf", "origin", "0 0 1 rg" },
}
return function(specification)
@@ -28,9 +28,6 @@ return function(specification)
{ id = id2 },
{ id = id3 },
}
- local color = {
- [0] = defaults,
- }
local chars = {
identifiers[id1].characters,
identifiers[id2].characters,
@@ -40,9 +37,9 @@ return function(specification)
local n = math.floor(math.random(1,3)+0.5)
local c = chars[n][u] or v
v.commands = {
- color[n],
+ defaults[n] or defaults[0],
{ 'slot', n, u },
- color[0],
+ defaults[0],
{ 'nop' }
}
v.kerns = nil
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 51e10df43..725d23268 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 07/05/17 23:01:18
+-- merge date : 07/14/17 19:35:39
do -- begin closure to overcome local limits and interference
@@ -3762,6 +3762,21 @@ function number.formatted(n,sep1,sep2)
return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".")
end
end
+local p=Cs(
+ P("-")^0*(P("0")^1/"")^0*(1-P("."))^0*(P(".")*P("0")^1*P(-1)/""+P(".")^0)*P(1-P("0")^1*P(-1))^0
+ )
+function number.compactfloat(n,fmt)
+ if n==0 then
+ return "0"
+ elseif n==1 then
+ return "1"
+ end
+ n=lpegmatch(p,format(fmt or "%0.3f",n))
+ if n=="." or n=="" or n=="-" then
+ return "0"
+ end
+ return n
+end
local zero=P("0")^1/""
local plus=P("+")/""
local minus=P("-")
@@ -4274,6 +4289,21 @@ local pattern=Cs((newline/(os.newline or "\r")+1)^0)
function string.replacenewlines(str)
return lpegmatch(pattern,str)
end
+function strings.newcollector()
+ local result,r={},0
+ return
+ function(fmt,str,...)
+ r=r+1
+ result[r]=str==nil and fmt or formatters[fmt](str,...)
+ end,
+ function(connector)
+ if result then
+ local str=concat(result,connector)
+ result,r={},0
+ return str
+ end
+ end
+end
end -- closure
@@ -14796,12 +14826,12 @@ local function readvariation(f,offset)
end
local function readposition(f,format,mainoffset,getdelta)
if format==0 then
- return
+ return false
end
if format==0x04 then
local h=readshort(f)
if h==0 then
- return
+ return true
else
return { 0,0,h,0 }
end
@@ -14810,7 +14840,7 @@ local function readposition(f,format,mainoffset,getdelta)
local x=readshort(f)
local h=readshort(f)
if x==0 and h==0 then
- return
+ return true
else
return { x,0,h,0 }
end
@@ -14829,7 +14859,7 @@ local function readposition(f,format,mainoffset,getdelta)
skipshort(f,1)
end
if h==0 then
- return
+ return true
else
return { 0,0,h,0 }
end
@@ -14875,7 +14905,7 @@ local function readposition(f,format,mainoffset,getdelta)
end
return { x,y,h,v }
elseif x==0 and y==0 and h==0 and v==0 then
- return
+ return true
else
return { x,y,h,v }
end
@@ -15537,7 +15567,7 @@ function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofgly
local first=value[2]
local second=value[3]
if first or second then
- hash[other]={ first,second }
+ hash[other]={ first,second or nil }
else
hash[other]=nil
end
@@ -15573,7 +15603,7 @@ function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofgly
local first=offsets[1]
local second=offsets[2]
if first or second then
- hash[paired]={ first,second }
+ hash[paired]={ first,second or nil }
else
end
end
@@ -15605,17 +15635,20 @@ function gposhandlers.cursive(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local entry=readushort(f)
local exit=readushort(f)
records[i]={
- entry=entry~=0 and (tableoffset+entry) or false,
- exit=exit~=0 and (tableoffset+exit ) or false,
+ entry~=0 and (tableoffset+entry) or false,
+ exit~=0 and (tableoffset+exit ) or nil,
}
end
+ local cc=(fontdata.temporary.cursivecount or 0)+1
+ fontdata.temporary.cursivecount=cc
+ cc="cc-"..cc
coverage=readcoverage(f,coverage)
for i=1,nofrecords do
local r=records[i]
records[i]={
- 1,
- readanchor(f,r.entry,getdelta) or nil,
- readanchor(f,r.exit,getdelta) or nil,
+ cc,
+ readanchor(f,r[1],getdelta) or false,
+ readanchor(f,r[2],getdelta) or nil,
}
end
for index,newindex in next,coverage do
@@ -17881,7 +17914,7 @@ local function checklookups(fontdata,missing,nofmissing)
end
end
if next(done) then
- report("not unicoded: % t",table.sortedkeys(done))
+ report("not unicoded: % t",sortedkeys(done))
end
end
end
@@ -18270,13 +18303,14 @@ function readers.pack(data)
return nt
end
end
- local function pack_flat(v)
- local tag=tabstr_flat(v)
+ local function pack_normal_cc(v)
+ local tag=tabstr_normal(v)
local ht=h[tag]
if ht then
c[ht]=c[ht]+1
return ht
else
+ v[1]=0
nt=nt+1
t[nt]=v
h[tag]=nt
@@ -18284,8 +18318,8 @@ function readers.pack(data)
return nt
end
end
- local function pack_boolean(v)
- local tag=tabstr_boolean(v)
+ local function pack_flat(v)
+ local tag=tabstr_flat(v)
local ht=h[tag]
if ht then
c[ht]=c[ht]+1
@@ -18326,6 +18360,20 @@ function readers.pack(data)
return nt
end
end
+ local function pack_boolean(v)
+ local tag=tabstr_boolean(v)
+ local ht=h[tag]
+ if ht then
+ c[ht]=c[ht]+1
+ return ht
+ else
+ nt=nt+1
+ t[nt]=v
+ h[tag]=nt
+ c[nt]=1
+ return nt
+ end
+ end
local function pack_final(v)
if c[v]<=criterium then
return t[v]
@@ -18342,6 +18390,22 @@ function readers.pack(data)
end
end
end
+ local function pack_final_cc(v)
+ if c[v]<=criterium then
+ return t[v]
+ else
+ local hv=hh[v]
+ if hv then
+ return hv
+ else
+ ntt=ntt+1
+ tt[ntt]=t[v]
+ hh[v]=ntt
+ cc[ntt]=c[v]
+ return ntt
+ end
+ end
+ end
local function success(stage,pass)
if nt==0 then
if trace_loading or trace_packing then
@@ -18387,9 +18451,9 @@ function readers.pack(data)
end
local function packers(pass)
if pass==1 then
- return pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed
+ return pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed,pack_normal_cc
else
- return pack_final,pack_final,pack_final,pack_final,pack_final
+ return pack_final,pack_final,pack_final,pack_final,pack_final,pack_final_cc
end
end
local resources=data.resources
@@ -18407,7 +18471,7 @@ function readers.pack(data)
if trace_packing then
report_otf("start packing: stage 1, pass %s",pass)
end
- local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
+ local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed,pack_normal_cc=packers(pass)
for unicode,description in next,descriptions do
local boundingbox=description.boundingbox
if boundingbox then
@@ -18444,8 +18508,8 @@ function readers.pack(data)
else
for g1,d1 in next,c do
for g2,d2 in next,d1 do
- local f=d2[1] if f then d2[1]=pack_indexed(f) end
- local s=d2[2] if s then d2[2]=pack_indexed(s) end
+ local f=d2[1] if f and f~=true then d2[1]=pack_indexed(f) end
+ local s=d2[2] if s and s~=true then d2[2]=pack_indexed(s) end
end
end
end
@@ -18457,7 +18521,9 @@ function readers.pack(data)
step.coverage=pack_normal(c)
else
for g1,d1 in next,c do
- c[g1]=pack_indexed(d1)
+ if d1~=true then
+ c[g1]=pack_indexed(d1)
+ end
end
end
end
@@ -18565,7 +18631,6 @@ function readers.pack(data)
for i=1,#deltas do
local di=deltas[i]
local d=di.deltas
- local r=di.regions
for j=1,#d do
d[j]=pack_indexed(d[j])
end
@@ -18597,7 +18662,7 @@ function readers.pack(data)
if trace_packing then
report_otf("start packing: stage 2, pass %s",pass)
end
- local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
+ local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed,pack_normal_cc=packers(pass)
for unicode,description in next,descriptions do
local math=description.math
if math then
@@ -18619,8 +18684,7 @@ function readers.pack(data)
if kind=="gpos_pair" then
local c=step.coverage
if c then
- if step.format=="kern" then
- else
+ if step.format~="kern" then
for g1,d1 in next,c do
for g2,d2 in next,d1 do
d1[g2]=pack_normal(d2)
@@ -18628,6 +18692,15 @@ function readers.pack(data)
end
end
end
+ elseif kind=="gpos_mark2ligature" then
+ local c=step.baseclasses
+ if c then
+ for g1,d1 in next,c do
+ for g2,d2 in next,d1 do
+ d1[g2]=pack_normal(d2)
+ end
+ end
+ end
end
local rules=step.rules
if rules then
@@ -18670,7 +18743,7 @@ function readers.pack(data)
if trace_packing then
report_otf("start packing: stage 3, pass %s",pass)
end
- local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
+ local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed,pack_normal_cc=packers(pass)
local function packthem(sequences)
for i=1,#sequences do
local sequence=sequences[i]
@@ -18683,13 +18756,19 @@ function readers.pack(data)
if kind=="gpos_pair" then
local c=step.coverage
if c then
- if step.format=="kern" then
- else
+ if step.format~="kern" then
for g1,d1 in next,c do
c[g1]=pack_normal(d1)
end
end
end
+ elseif kind=="gpos_cursive" then
+ local c=step.coverage
+ if c then
+ for g1,d1 in next,c do
+ c[g1]=pack_normal_cc(d1)
+ end
+ end
end
end
end
@@ -18758,6 +18837,19 @@ function readers.unpack(data)
local features=sequence.features
local flags=sequence.flags
local markclass=sequence.markclass
+ if features then
+ local tv=tables[features]
+ if tv then
+ sequence.features=tv
+ features=tv
+ end
+ for script,feature in next,features do
+ local tv=tables[feature]
+ if tv then
+ features[script]=tv
+ end
+ end
+ end
if steps then
for i=1,#steps do
local step=steps[i]
@@ -18811,6 +18903,11 @@ function readers.unpack(data)
local c=step.coverage
if c then
for g1,d1 in next,c do
+ local tv=tables[d1]
+ if tv then
+ d1=tv
+ c[g1]=d1
+ end
local f=tables[d1[2]] if f then d1[2]=f end
local s=tables[d1[3]] if s then d1[3]=s end
end
@@ -18841,6 +18938,11 @@ function readers.unpack(data)
if c then
for g1,d1 in next,c do
for g2,d2 in next,d1 do
+ local tv=tables[d2]
+ if tv then
+ d2=tv
+ d1[g2]=d2
+ end
for g3,d3 in next,d2 do
local tv=tables[d2[g3]]
if tv then
@@ -18917,19 +19019,6 @@ function readers.unpack(data)
end
end
end
- if features then
- local tv=tables[features]
- if tv then
- sequence.features=tv
- features=tv
- end
- for script,feature in next,features do
- local tv=tables[feature]
- if tv then
- features[script]=tv
- end
- end
- end
if order then
local tv=tables[order]
if tv then
@@ -19220,7 +19309,8 @@ local function checkpairs(lookup)
break
else
local v=d2[1]
- if v[1]~=0 or v[2]~=0 or v[4]~=0 then
+ if v==true then
+ elseif v and (v[1]~=0 or v[2]~=0 or v[4]~=0) then
kerns=false
break
end
@@ -19231,7 +19321,12 @@ local function checkpairs(lookup)
report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
for g1,d1 in next,coverage do
for g2,d2 in next,d1 do
- d1[g2]=d2[1][3]
+ local v=d2[1]
+ if v==true then
+ d1[g2]=nil
+ elseif v then
+ d1[g2]=v[3]
+ end
end
end
step.format="kern"
@@ -19260,6 +19355,7 @@ function readers.compact(data)
allsteps=allsteps+nofsteps
if nofsteps>1 then
local kind=lookup.type
+ local merg=merged
if kind=="gsub_single" or kind=="gsub_alternate" or kind=="gsub_multiple" then
merged=merged+mergesteps_1(lookup)
elseif kind=="gsub_ligature" then
@@ -19275,6 +19371,9 @@ function readers.compact(data)
elseif kind=="gpos_mark2mark" or kind=="gpos_mark2base" or kind=="gpos_mark2ligature" then
merged=merged+mergesteps_3(lookup)
end
+ if merg~=merged then
+ lookup.merged=true
+ end
end
end
else
@@ -19334,7 +19433,7 @@ function readers.expand(data)
for i=1,#t do
local step=t[i]
local coverage=step.coverage
- for k,v in next,coverage do
+ for k in next,coverage do
local m=merged[k]
if m then
m[2]=i
@@ -19353,6 +19452,7 @@ function readers.expand(data)
local sequence=sequences[i]
local steps=sequence.steps
if steps then
+ local nofsteps=sequence.nofsteps
setmetatableindex(steps,mergesteps)
local kind=sequence.type
local markclass=sequence.markclass
@@ -19364,7 +19464,14 @@ function readers.expand(data)
sequence.markclass=markclasses[markclass]
end
end
- local nofsteps=sequence.nofsteps
+ local flags=sequence.flags
+ if flags then
+ flags[5]=flags[1]~=false
+ or flags[2]~=false
+ or flags[3]~=false
+ or sequence.markclass
+ or false
+ end
for i=1,nofsteps do
local step=steps[i]
local baseclasses=step.baseclasses
@@ -19432,6 +19539,7 @@ function readers.expand(data)
end
end
if sequence[1] then
+ sequence.n=#sequence
rulesize=rulesize+1
rulehash[rulesize]={
nofrules,
@@ -19451,6 +19559,7 @@ function readers.expand(data)
end
end
end
+ rulehash.n=#rulehash
end
end
end
@@ -19492,7 +19601,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_de
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
-otf.version=3.031
+otf.version=3.032
otf.cache=containers.define("fonts","otl",otf.version,true)
otf.svgcache=containers.define("fonts","svg",otf.version,true)
otf.sbixcache=containers.define("fonts","sbix",otf.version,true)
@@ -20420,9 +20529,11 @@ local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist
local character=characters[unicode]
local kerns=character.kerns
for otherunicode,kern in next,data do
- if not kern[2] and not (kerns and kerns[otherunicode]) then
+ local other=kern[2]
+ if other==true or (not other and not (kerns and kerns[otherunicode])) then
local kern=kern[1]
- if kern[1]~=0 or kern[2]~=0 or kern[4]~=0 then
+ if kern==true then
+ elseif kern[1]~=0 or kern[2]~=0 or kern[4]~=0 then
else
kern=kern[3]
if kern~=0 then
@@ -20447,6 +20558,42 @@ local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist
end
local function initializehashes(tfmdata)
end
+local function checkmathreplacements(tfmdata,fullname)
+ if tfmdata.mathparameters then
+ local characters=tfmdata.characters
+ local changed=tfmdata.changed
+ if next(changed) then
+ if trace_preparing or trace_baseinit then
+ report_prepare("checking math replacements for %a",fullname)
+ end
+ for unicode,replacement in next,changed do
+ local u=characters[unicode]
+ local r=characters[replacement]
+ local n=u.next
+ local v=u.vert_variants
+ local h=u.horiz_variants
+ if n and not r.next then
+ if trace_preparing then
+ report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement)
+ end
+ r.next=n
+ end
+ if v and not r.vert_variants then
+ if trace_preparing then
+ report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement)
+ end
+ r.vert_variants=v
+ end
+ if h and not r.horiz_variants then
+ if trace_preparing then
+ report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement)
+ end
+ r.horiz_variants=h
+ end
+ end
+ end
+ end
+end
local function featuresinitializer(tfmdata,value)
if true then
local starttime=trace_preparing and os.clock()
@@ -20463,6 +20610,8 @@ local function featuresinitializer(tfmdata,value)
local rawfeatures=rawresources and rawresources.features
local basesubstitutions=rawfeatures and rawfeatures.gsub
local basepositionings=rawfeatures and rawfeatures.gpos
+ local substitutionsdone=false
+ local positioningsdone=false
if basesubstitutions or basepositionings then
local sequences=tfmdata.resources.sequences
for s=1,#sequences do
@@ -20483,12 +20632,14 @@ local function featuresinitializer(tfmdata,value)
end
preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
registerbasefeature(feature,value)
+ substitutionsdone=true
elseif basepositionings and basepositionings[feature] then
if trace_preparing then
report_prepare("filtering base %a feature %a for %a with value %a","pos",feature,fullname,value)
end
preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
registerbasefeature(feature,value)
+ positioningsdone=true
end
end
end
@@ -20496,6 +20647,9 @@ local function featuresinitializer(tfmdata,value)
end
end
end
+ if substitutionsdone then
+ checkmathreplacements(tfmdata,fullname)
+ end
registerbasehash(tfmdata)
end
if trace_preparing then
@@ -20926,7 +21080,7 @@ local function show(n,what,nested,symbol)
end
local function showsub(n,what,where)
report_injections("begin subrun: %s",where)
- for n in traverse_id(glyph_code,n) do
+ for n in traverse_char(n) do
showchar(n,where)
show(n,what,where," ")
end
@@ -20993,7 +21147,6 @@ local function inject_kerns_only(head,where)
local prev=nil
local next=nil
local prevdisc=nil
- local prevglyph=nil
local pre=nil
local post=nil
local replace=nil
@@ -21049,10 +21202,8 @@ local function inject_kerns_only(head,where)
end
end
prevdisc=nil
- prevglyph=current
elseif char==false then
prevdisc=nil
- prevglyph=current
elseif id==disc_code then
pre,post,replace,pretail,posttail,replacetail=getdisc(current,true)
local done=false
@@ -21104,10 +21255,8 @@ local function inject_kerns_only(head,where)
if done then
setdisc(current,pre,post,replace)
end
- prevglyph=nil
prevdisc=current
else
- prevglyph=nil
prevdisc=nil
end
prev=current
@@ -21331,7 +21480,7 @@ local function inject_pairs_only(head,where)
if keepregisteredcounts then
keepregisteredcounts=false
else
- nofregisteredkerns=0
+ nofregisteredpairs=0
end
if trace_injections then
show_result(head)
@@ -21802,7 +21951,7 @@ local function injectspaces(head)
threshold,
factor=getthreshold(font)
end
- for n in traverse_id(glue_code,tonut(head)) do
+ for n in traverse_char(tonut(head)) do
local prev,next=getspaceboth(n)
local prevchar=prev and ischar(prev)
local nextchar=next and ischar(next)
@@ -22313,7 +22462,6 @@ local trace_discruns=false registertracker("otf.discruns",function(v) trace_disc
local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end)
local trace_testruns=false registertracker("otf.testruns",function(v) trace_testruns=v end)
local forcediscretionaries=false
-local optimizekerns=true
directives.register("otf.forcediscretionaries",function(v)
forcediscretionaries=v
end)
@@ -22365,7 +22513,6 @@ local flush_node_list=nuts.flush_list
local flush_node=nuts.flush_node
local end_of_math=nuts.end_of_math
local traverse_nodes=nuts.traverse
-local traverse_id=nuts.traverse_id
local set_components=nuts.set_components
local take_components=nuts.take_components
local count_components=nuts.count_components
@@ -22410,6 +22557,7 @@ local currentfont=false
local factor=0
local threshold=0
local checkmarks=false
+local discs=false
local sweepnode=nil
local sweephead={}
local notmatchpre={}
@@ -22430,44 +22578,51 @@ end
local function logwarning(...)
report_direct(...)
end
-local f_unicode=formatters["U+%X"]
-local f_uniname=formatters["U+%X (%s)"]
-local f_unilist=formatters["% t (% t)"]
-local function gref(n)
- if type(n)=="number" then
- local description=descriptions[n]
- local name=description and description.name
- if name then
- return f_uniname(n,name)
- else
- return f_unicode(n)
- end
- elseif n then
- local num,nam={},{}
- for i=1,#n do
- local ni=n[i]
- if tonumber(ni) then
- local di=descriptions[ni]
- num[i]=f_unicode(ni)
- nam[i]=di and di.name or "-"
+local gref do
+ local f_unicode=formatters["U+%X"]
+ local f_uniname=formatters["U+%X (%s)"]
+ local f_unilist=formatters["% t (% t)"]
+ gref=function(n)
+ if type(n)=="number" then
+ local description=descriptions[n]
+ local name=description and description.name
+ if name then
+ return f_uniname(n,name)
+ else
+ return f_unicode(n)
end
+ elseif n then
+ local num,nam={},{}
+ for i=1,#n do
+ local ni=n[i]
+ if tonumber(ni) then
+ local di=descriptions[ni]
+ num[i]=f_unicode(ni)
+ nam[i]=di and di.name or "-"
+ end
+ end
+ return f_unilist(num,nam)
+ else
+ return "<error in node mode tracing>"
end
- return f_unilist(num,nam)
- else
- return "<error in node mode tracing>"
end
end
local function cref(dataset,sequence,index)
if not dataset then
return "no valid dataset"
- elseif index then
- return formatters["feature %a, type %a, chain lookup %a, index %a"](dataset[4],sequence.type,sequence.name,index)
+ end
+ local merged=sequence.merged and "merged " or ""
+ if index then
+ return formatters["feature %a, type %a, %schain lookup %a, index %a"](
+ dataset[4],sequence.type,merged,sequence.name,index)
else
- return formatters["feature %a, type %a, chain lookup %a"](dataset[4],sequence.type,sequence.name)
+ return formatters["feature %a, type %a, %schain lookup %a"](
+ dataset[4],sequence.type,merged,sequence.name)
end
end
local function pref(dataset,sequence)
- return formatters["feature %a, type %a, lookup %a"](dataset[4],sequence.type,sequence.name)
+ return formatters["feature %a, type %a, %slookup %a"](
+ dataset[4],sequence.type,sequence.merged and "merged " or "",sequence.name)
end
local function mref(rlmode)
if not rlmode or rlmode==0 then
@@ -22757,7 +22912,7 @@ function handlers.gsub_alternate(head,start,dataset,sequence,alternative)
setchar(start,choice)
else
if trace_alternatives then
- logwarning("%s: no variant %a for %s, %s",pref(dataset,sequence),value,gref(getchar(start)),comment)
+ logwarning("%s: no variant %a for %s, %s",pref(dataset,sequence),value,gref(getchar(start)),comment)
end
end
return head,start,true
@@ -22910,28 +23065,23 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
break
elseif step.format=="pair" then
local a,b=krn[1],krn[2]
- if optimizekerns then
- if not b and a[1]==0 and a[2]==0 and a[4]==0 then
- local k=setkern(snext,factor,rlmode,a[3],injection)
- if trace_kerns then
- logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
- end
- return head,start,true
- end
- end
- if a and #a>0 then
+ if a==true then
+ elseif a then
local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,injection)
if trace_kerns then
local startchar=getchar(start)
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
end
end
- if b and #b>0 then
+ if b==true then
+ start=snext
+ elseif b then
local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
if trace_kerns then
local startchar=getchar(snext)
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
end
+ start=snext
end
return head,start,true
elseif krn~=0 then
@@ -23412,28 +23562,23 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
break
elseif step.format=="pair" then
local a,b=krn[1],krn[2]
- if optimizekerns then
- if not b and a[1]==0 and a[2]==0 and a[4]==0 then
- local k=setkern(snext,factor,rlmode,a[3],"injections")
- if trace_kerns then
- logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k)
- end
- return head,start,true
- end
- end
- if a and #a>0 then
- local startchar=getchar(start)
+ if a then
+ elseif a then
local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,"injections")
if trace_kerns then
+ local startchar=getchar(start)
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
end
end
- if b and #b>0 then
- local startchar=getchar(start)
+ if b==true then
+ start=snext
+ elseif b then
local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,"injections")
if trace_kerns then
+ local startchar=getchar(start)
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
end
+ start=snext
end
return head,start,true
elseif krn~=0 then
@@ -23742,12 +23887,9 @@ end
local noflags={ false,false,false,false }
local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
local size=ck[5]-ck[4]+1
- local flags=sequence.flags or noflags
- local done=false
- local skipmark=flags[1]
local chainlookups=ck[6]
+ local done=false
if chainlookups then
- local nofchainlookups=#chainlookups
if size==1 then
local chainlookup=chainlookups[1]
for j=1,#chainlookup do
@@ -23765,10 +23907,22 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
end
end
else
+ local skipmark
+ local skipligature
+ local skipbase
+ local markclass
+ if skipped then
+ local flags=sequence.flags or noflags
+ skipmark=flags[1]
+ skipligature=flags[2]
+ skipbase=flags[3]
+ markclass=sequence.markclass
+ end
local i=1
local laststart=start
+ local nofchainlookups=#chainlookups
while start do
- if skipped then
+ if skipped then
while start do
local char,id=ischar(start,currentfont)
if char then
@@ -24155,11 +24309,11 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local checkdisc=sweeptype and getprev(head)
local flags=sequence.flags or noflags
local done=false
+ local markclass=sequence.markclass
local skipmark=flags[1]
local skipligature=flags[2]
local skipbase=flags[3]
- local markclass=sequence.markclass
- local skipsome=skipmark~=false or skipligature~=false or skipbase~=false or markclass
+ local skipsome=flags[5]
local skipped=false
local startprev,
startnext=getboth(start)
@@ -24170,7 +24324,6 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local ck=contexts[k]
local seq=ck[3]
local s=#seq
- local size=1
if s==1 then
local char=ischar(current,currentfont)
if char and not seq[1][char] then
@@ -24179,8 +24332,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
local f=ck[4]
local l=ck[5]
- size=l-f+1
- if size>1 then
+ if l>f then
local discfound
local n=f+1
last=startnext
@@ -24596,6 +24748,469 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
return head,start,done
end
+local function optimized_handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
+ local sweepnode=sweepnode
+ local sweeptype=sweeptype
+ local postreplace
+ local prereplace
+ local checkdisc
+ local diskseen
+ if sweeptype then
+ if sweeptype=="replace" then
+ postreplace=true
+ prereplace=true
+ else
+ postreplace=sweeptype=="post"
+ prereplace=sweeptype=="pre"
+ end
+ checkdisc=getprev(head)
+ end
+ local currentfont=currentfont
+ local flags=sequence.flags or noflags
+ local skipsome=flags[5]
+ local skipmark
+ local skipligature
+ local skipbase
+ local markclass
+ if skipsome then
+ skipmark=flags[1]
+ skipligature=flags[2]
+ skipbase=flags[3]
+ markclass=sequence.markclass
+ end
+ local skipped
+ local startprev,
+ startnext=getboth(start)
+ local done
+ for k=1,contexts.n do
+ local current=start
+ local last=start
+ local ck=contexts[k]
+ local seq=ck[3]
+ local s=seq.n
+ if s==1 then
+ local char=ischar(current,currentfont)
+ if char and not seq[1][char] then
+ goto next
+ end
+ else
+ local f=ck[4]
+ local l=ck[5]
+ if l>f then
+ local discfound
+ local n=f+1
+ last=startnext
+ while n<=l do
+ if not last and postreplace then
+ last=getnext(sweepnode)
+ sweeptype=nil
+ end
+ if last then
+ local char,id=ischar(last,currentfont)
+ if char then
+ if skipsome then
+ local class=classes[char]
+ if class==skipmark or (markclass and class=="mark" and not markclass[char]) or class==skipligature or class==skipbase then
+ skipped=true
+ if trace_skips then
+ show_skip(dataset,sequence,char,ck,class)
+ end
+ last=getnext(last)
+ elseif seq[n][char] then
+ if n<l then
+ last=getnext(last)
+ end
+ n=n+1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ else
+ if seq[n][char] then
+ if n<l then
+ last=getnext(last)
+ end
+ n=n+1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ end
+ elseif char==false then
+ if discfound then
+ notmatchreplace[discfound]=true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ elseif id==disc_code then
+ diskseen=true
+ discfound=last
+ notmatchpre[last]=nil
+ notmatchpost[last]=true
+ notmatchreplace[last]=nil
+ local pre,post,replace=getdisc(last)
+ if pre then
+ local n=n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n=n+1
+ if n>l then
+ break
+ end
+ pre=getnext(pre)
+ else
+ notmatchpre[last]=true
+ break
+ end
+ end
+ if n<=l then
+ notmatchpre[last]=true
+ end
+ else
+ notmatchpre[last]=true
+ end
+ if replace then
+ while replace do
+ if seq[n][getchar(replace)] then
+ n=n+1
+ if n>l then
+ break
+ end
+ replace=getnext(replace)
+ else
+ notmatchreplace[last]=true
+ if notmatchpre[last] then
+ goto next
+ end
+ break
+ end
+ end
+ if notmatchpre[last] then
+ goto next
+ end
+ end
+ last=getnext(last)
+ else
+ goto next
+ end
+ else
+ goto next
+ end
+ end
+ end
+ if f>1 then
+ if startprev then
+ local prev=startprev
+ if prereplace and prev==checkdisc then
+ prev=getprev(sweepnode)
+ end
+ if prev then
+ local discfound
+ local n=f-1
+ while n>=1 do
+ if prev then
+ local char,id=ischar(prev,currentfont)
+ if char then
+ if skipsome then
+ local class=classes[char]
+ if class==skipmark or (markclass and class=="mark" and not markclass[char]) or class==skipligature or class==skipbase then
+ skipped=true
+ if trace_skips then
+ show_skip(dataset,sequence,char,ck,class)
+ end
+ prev=getprev(prev)
+ elseif seq[n][char] then
+ if n>1 then
+ prev=getprev(prev)
+ end
+ n=n-1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ if notmatchpost[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ else
+ if seq[n][char] then
+ if n>1 then
+ prev=getprev(prev)
+ end
+ n=n-1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ if notmatchpost[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ end
+ elseif char==false then
+ if discfound then
+ notmatchreplace[discfound]=true
+ if notmatchpost[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ elseif id==disc_code then
+ diskseen=true
+ discfound=prev
+ notmatchpre[prev]=true
+ notmatchpost[prev]=nil
+ notmatchreplace[prev]=nil
+ local pre,post,replace,pretail,posttail,replacetail=getdisc(prev,true)
+ if pre~=start and post~=start and replace~=start then
+ if post then
+ local n=n
+ while posttail do
+ if seq[n][getchar(posttail)] then
+ n=n-1
+ if posttail==post then
+ break
+ else
+ if n<1 then
+ break
+ end
+ posttail=getprev(posttail)
+ end
+ else
+ notmatchpost[prev]=true
+ break
+ end
+ end
+ if n>=1 then
+ notmatchpost[prev]=true
+ end
+ else
+ notmatchpost[prev]=true
+ end
+ if replace then
+ while replacetail do
+ if seq[n][getchar(replacetail)] then
+ n=n-1
+ if replacetail==replace then
+ break
+ else
+ if n<1 then
+ break
+ end
+ replacetail=getprev(replacetail)
+ end
+ else
+ notmatchreplace[prev]=true
+ if notmatchpost[prev] then
+ goto next
+ end
+ break
+ end
+ end
+ end
+ end
+ prev=getprev(prev)
+ elseif id==glue_code and seq[n][32] and isspace(prev,threshold,id) then
+ n=n-1
+ prev=getprev(prev)
+ else
+ goto next
+ end
+ else
+ goto next
+ end
+ end
+ else
+ goto next
+ end
+ else
+ goto next
+ end
+ end
+ if s>l then
+ local current=last and getnext(last)
+ if not current and postreplace then
+ current=getnext(sweepnode)
+ end
+ if current then
+ local discfound
+ local n=l+1
+ while n<=s do
+ if current then
+ local char,id=ischar(current,currentfont)
+ if char then
+ if skipsome then
+ local class=classes[char]
+ if class==skipmark or (markclass and class=="mark" and not markclass[char]) or class==skipligature or class==skipbase then
+ skipped=true
+ if trace_skips then
+ show_skip(dataset,sequence,char,ck,class)
+ end
+ current=getnext(current)
+ elseif seq[n][char] then
+ if n<s then
+ current=getnext(current)
+ end
+ n=n+1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ else
+ if seq[n][char] then
+ if n<s then
+ current=getnext(current)
+ end
+ n=n+1
+ else
+ if discfound then
+ notmatchreplace[discfound]=true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ end
+ end
+ elseif char==false then
+ if discfound then
+ notmatchreplace[discfound]=true
+ if notmatchpre[discfound] then
+ goto next
+ end
+ else
+ goto next
+ end
+ break
+ elseif id==disc_code then
+ diskseen=true
+ discfound=current
+ notmatchpre[current]=nil
+ notmatchpost[current]=true
+ notmatchreplace[current]=nil
+ local pre,post,replace=getdisc(current)
+ if pre then
+ local n=n
+ while pre do
+ if seq[n][getchar(pre)] then
+ n=n+1
+ if n>s then
+ break
+ end
+ pre=getnext(pre)
+ else
+ notmatchpre[current]=true
+ break
+ end
+ end
+ if n<=s then
+ notmatchpre[current]=true
+ end
+ else
+ notmatchpre[current]=true
+ end
+ if replace then
+ while replace do
+ if seq[n][getchar(replace)] then
+ n=n+1
+ if n>s then
+ break
+ end
+ replace=getnext(replace)
+ else
+ notmatchreplace[current]=true
+ if not notmatchpre[current] then
+ goto next
+ end
+ break
+ end
+ end
+ else
+ end
+ current=getnext(current)
+ elseif id==glue_code and seq[n][32] and isspace(current,threshold,id) then
+ n=n+1
+ current=getnext(current)
+ else
+ goto next
+ end
+ else
+ goto next
+ end
+ end
+ else
+ goto next
+ end
+ end
+ end
+ if trace_contexts then
+ chaintrac(head,start,dataset,sequence,rlmode,ck,skipped,true)
+ end
+ if diskseen or sweepnode then
+ head,start,done=chaindisk(head,start,dataset,sequence,rlmode,ck,skipped)
+ else
+ head,start,done=chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
+ end
+ if done then
+ break
+ end
+ ::next::
+ end
+ if diskseen then
+ notmatchpre={}
+ notmatchpost={}
+ notmatchreplace={}
+ end
+ return head,start,done
+end
+directives.register("otf.optimizechains",function(v)
+ if v then
+ report_chain()
+ report_chain("using experimental optimized code")
+ report_chain()
+ end
+ local handle=v and optimized_handle_contextchain or handle_contextchain
+ handlers.gsub_context=handle
+ handlers.gsub_contextchain=handle
+ handlers.gsub_reversecontextchain=handle
+ handlers.gpos_contextchain=handle
+ handlers.gpos_context=handle
+end)
handlers.gsub_context=handle_contextchain
handlers.gsub_contextchain=handle_contextchain
handlers.gsub_reversecontextchain=handle_contextchain
@@ -24615,22 +25230,14 @@ chainprocs.gsub_reversecontextchain=chained_contextchain
chainprocs.gpos_contextchain=chained_contextchain
chainprocs.gpos_context=chained_contextchain
local missing=setmetatableindex("table")
+local logwarning=report_process
+local resolved={}
local function logprocess(...)
if trace_steps then
registermessage(...)
end
report_process(...)
end
-local logwarning=report_process
-local function report_missing_coverage(dataset,sequence)
- local t=missing[currentfont]
- if not t[sequence] then
- t[sequence]=true
- logwarning("missing coverage for feature %a, lookup %a, type %a, font %a, name %a",
- dataset[4],sequence.name,sequence.type,currentfont,tfmdata.properties.fullname)
- end
-end
-local resolved={}
local sequencelists=setmetatableindex(function(t,font)
local sequences=fontdata[font].resources.sequences
if not sequences or not next(sequences) then
@@ -24857,12 +25464,10 @@ local function testrun(disc,t_run,c_run,...)
end
local d_post=t_run(post,next,...)
local d_replace=t_run(replace,next,...)
- if (d_post and d_post>0) or (d_replace and d_replace>0) then
- local d=d_replace or d_post
- if d_post and d<d_post then
- d=d_post
- end
- local head,tail=getnext(disc),disc
+ if d_post>0 or d_replace>0 then
+ local d=d_replace>d_post and d_replace or d_post
+ local head=getnext(disc)
+ local tail=head
for i=1,d do
tail=getnext(tail)
if getid(tail)==disc_code then
@@ -25049,6 +25654,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
break
end
end
+ return 0
end
local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
local a
@@ -25093,20 +25699,16 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
for i=1,nofsteps do
local step=steps[i]
local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- if ok then
- done=true
- break
- elseif not start then
- break
- end
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local ok
+ head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+ if ok then
+ done=true
+ break
+ elseif not start then
+ break
end
- else
- report_missing_coverage(dataset,sequence)
end
end
if start then
@@ -25139,59 +25741,55 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
for i=1,nofsteps do
local step=steps[i]
local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local s=startnext
- local ss=nil
- local sstop=s==stop
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local s=startnext
+ local ss=nil
+ local sstop=s==stop
+ if not s then
+ s=ss
+ ss=nil
+ end
+ while getid(s)==disc_code do
+ ss=getnext(s)
+ s=getfield(s,"replace")
if not s then
s=ss
ss=nil
end
- while getid(s)==disc_code do
- ss=getnext(s)
- s=getfield(s,"replace")
+ end
+ local l=nil
+ local d=0
+ while s do
+ local lg=lookupmatch[getchar(s)]
+ if lg then
+ if sstop then
+ d=1
+ elseif d>0 then
+ d=d+1
+ end
+ l=lg
+ s=getnext(s)
+ sstop=s==stop
if not s then
s=ss
ss=nil
end
- end
- local l=nil
- local d=0
- while s do
- local lg=lookupmatch[getchar(s)]
- if lg then
- if sstop then
- d=1
- elseif d>0 then
- d=d+1
- end
- l=lg
- s=getnext(s)
- sstop=s==stop
+ while getid(s)==disc_code do
+ ss=getnext(s)
+ s=getfield(s,"replace")
if not s then
s=ss
ss=nil
end
- while getid(s)==disc_code do
- ss=getnext(s)
- s=getfield(s,"replace")
- if not s then
- s=ss
- ss=nil
- end
- end
- else
- break
end
- end
- if l and l.ligature then
- lastd=d
+ else
+ break
end
end
- else
- report_missing_coverage(dataset,sequence)
+ if l and l.ligature then
+ lastd=d
+ end
end
end
else
@@ -25204,6 +25802,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
break
end
end
+ return 0
end
local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
local a
@@ -25220,16 +25819,12 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase
for i=1,nofsteps do
local step=steps[i]
local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local h,d,ok=handler(head,n,dataset,sequence,lookupmatch,rlmode,step,i,injection)
- if ok then
- return true
- end
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local h,d,ok=handler(head,n,dataset,sequence,lookupmatch,rlmode,step,i,injection)
+ if ok then
+ return true
end
- else
- report_missing_coverage(dataset,sequence)
end
end
end
@@ -25278,6 +25873,12 @@ otf.helpers.pardirstate=pardirstate
do
local fastdisc=true
directives.register("otf.fastdisc",function(v) fastdisc=v end)
+ local otfdataset=nil
+ local getfastdics=function(t,k)
+ local v=usesfont(k,currentfont)
+ t[k]=v
+ return v
+ end
function otf.featuresprocessor(head,font,attr,direction,n)
local sequences=sequencelists[font]
if not sequencelists then
@@ -25295,25 +25896,24 @@ do
threshold,
factor=getthreshold(font)
checkmarks=tfmdata.properties.checkmarks
+ if not otfdataset then
+ otfdataset=otf.dataset
+ end
+ discs=fastdisc and n and n>1 and setmetatableindex(getfastdisc)
elseif currentfont~=font then
report_warning("nested call with a different font, level %s, quitting",nesting)
nesting=nesting-1
return head,false
end
- head=tonut(head)
+ local head=tonut(head)
if trace_steps then
checkstep(head)
end
local initialrl=direction=="TRT" and -1 or 0
local done=false
- local datasets=otf.dataset(tfmdata,font,attr)
+ local datasets=otfdataset(tfmdata,font,attr)
local dirstack={}
sweephead={}
- local discs=fastdisc and n and n>1 and setmetatableindex(function(t,k)
- local v=usesfont(k,font)
- t[k]=v
- return v
- end)
for s=1,#datasets do
local dataset=datasets[s]
local attribute=dataset[2]
@@ -25322,7 +25922,7 @@ do
local topstack=0
local typ=sequence.type
local gpossing=typ=="gpos_single" or typ=="gpos_pair"
- local handler=handlers[typ]
+ local handler=handlers[typ]
local steps=sequence.steps
local nofsteps=sequence.nofsteps
if not steps then
@@ -25350,18 +25950,14 @@ do
for i=m[1],m[2] do
local step=steps[i]
local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- if ok then
- done=true
- break
- end
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local ok
+ head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+ if ok then
+ done=true
+ break
end
- else
- report_missing_coverage(dataset,sequence)
end
end
if start then
@@ -25383,66 +25979,62 @@ do
if nofsteps==1 then
local step=steps[1]
local lookupcache=step.coverage
- if not lookupcache then
- report_missing_coverage(dataset,sequence)
- else
- while start do
- local char,id=ischar(start,font)
- if char then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local a
- if attr then
- if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) then
- a=true
- end
- elseif not attribute or getprop(start,a_state)==attribute then
+ while start do
+ local char,id=ischar(start,font)
+ if char then
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local a
+ if attr then
+ if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) then
a=true
end
- if a then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
- if ok then
- done=true
- end
- if start then
- start=getnext(start)
- end
- else
- start=getnext(start)
- end
- else
- start=getnext(start)
+ elseif not attribute or getprop(start,a_state)==attribute then
+ a=true
end
- elseif char==false then
- start=getnext(start)
- elseif id==glue_code then
- start=getnext(start)
- elseif id==disc_code then
- if not discs or discs[start]==true then
+ if a then
local ok
- if gpossing then
- start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- elseif typ=="gsub_ligature" then
- start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- else
- start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- end
+ head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
if ok then
done=true
end
+ if start then
+ start=getnext(start)
+ end
else
start=getnext(start)
end
- elseif id==math_code then
- start=getnext(end_of_math(start))
- elseif id==dir_code then
- start,topstack,rlmode=txtdirstate(start,dirstack,topstack,rlparmode)
- elseif id==localpar_code then
- start,rlparmode,rlmode=pardirstate(start)
else
start=getnext(start)
end
+ elseif char==false then
+ start=getnext(start)
+ elseif id==glue_code then
+ start=getnext(start)
+ elseif id==disc_code then
+ if not discs or discs[start]==true then
+ local ok
+ if gpossing then
+ start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ elseif typ=="gsub_ligature" then
+ start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ else
+ start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ done=true
+ end
+ else
+ start=getnext(start)
+ end
+ elseif id==math_code then
+ start=getnext(end_of_math(start))
+ elseif id==dir_code then
+ start,topstack,rlmode=txtdirstate(start,dirstack,topstack,rlparmode)
+ elseif id==localpar_code then
+ start,rlparmode,rlmode=pardirstate(start)
+ else
+ start=getnext(start)
end
end
else
@@ -25464,20 +26056,16 @@ do
for i=m[1],m[2] do
local step=steps[i]
local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- if ok then
- done=true
- break
- elseif not start then
- break
- end
+ local lookupmatch=lookupcache[char]
+ if lookupmatch then
+ local ok
+ head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
+ if ok then
+ done=true
+ break
+ elseif not start then
+ break
end
- else
- report_missing_coverage(dataset,sequence)
end
end
if start then
@@ -25659,7 +26247,7 @@ local function spaceinitializer(tfmdata,value)
local format=step.format
if rules then
elseif coverage then
- local single=format==gpos_single
+ local single=format=="gpos_single"
local kerns=coverage[32]
if kerns then
for k,v in next,kerns do
@@ -25684,12 +26272,13 @@ local function spaceinitializer(tfmdata,value)
left[k]=kern[3]
else
local one=kern[1]
- if one then
+ if one and one~=true then
left[k]=one[3]
end
end
end
end
+ else
end
end
last=i
@@ -28530,8 +29119,6 @@ local function addfeature(data,feature,specifications)
if rules then
local rulehash={}
local rulesize=0
- local sequence={}
- local nofsequences=0
local lookuptype=types[featuretype]
for nofrules=1,#rules do
local rule=rules[nofrules]
@@ -28617,8 +29204,10 @@ local function addfeature(data,feature,specifications)
coverage[unic]=rulehash
end
end
+ sequence.n=nofsequences
end
end
+ rulehash.n=rulesize
end
return coverage
end