summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
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/mkiv/char-obs.lua269
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/font-afk.lua2
-rw-r--r--tex/context/base/mkiv/font-afm.lua1232
-rw-r--r--tex/context/base/mkiv/font-cft.lua6
-rw-r--r--tex/context/base/mkiv/font-cid.lua2
-rw-r--r--tex/context/base/mkiv/font-col.lua10
-rw-r--r--tex/context/base/mkiv/font-con.lua4
-rw-r--r--tex/context/base/mkiv/font-ctx.lua37
-rw-r--r--tex/context/base/mkiv/font-inj.lua1194
-rw-r--r--tex/context/base/mkiv/font-ldr.lua70
-rw-r--r--tex/context/base/mkiv/font-lib.mkvi3
-rw-r--r--tex/context/base/mkiv/font-mat.mkvi131
-rw-r--r--tex/context/base/mkiv/font-ocl.lua2
-rw-r--r--tex/context/base/mkiv/font-odk.lua904
-rw-r--r--tex/context/base/mkiv/font-odv.lua2380
-rw-r--r--tex/context/base/mkiv/font-osd.lua22
-rw-r--r--tex/context/base/mkiv/font-ota.lua2
-rw-r--r--tex/context/base/mkiv/font-otb.lua705
-rw-r--r--tex/context/base/mkiv/font-otc.lua2
-rw-r--r--tex/context/base/mkiv/font-otf.lua2968
-rw-r--r--tex/context/base/mkiv/font-otl.lua2
-rw-r--r--tex/context/base/mkiv/font-otn.lua3927
-rw-r--r--tex/context/base/mkiv/font-oto.lua4
-rw-r--r--tex/context/base/mkiv/font-otp.lua894
-rw-r--r--tex/context/base/mkiv/font-ott.lua2
-rw-r--r--tex/context/base/mkiv/m-oldotf.mkiv77
-rw-r--r--tex/context/base/mkiv/math-fbk.lua210
-rw-r--r--tex/context/base/mkiv/metatex.lus9
-rw-r--r--tex/context/base/mkiv/metatex.tex143
-rw-r--r--tex/context/base/mkiv/node-nut.lua2
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin25616 -> 25828 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin424658 -> 424659 bytes
-rw-r--r--tex/context/base/mkiv/status-mkiv.lua7441
-rw-r--r--tex/context/base/mkiv/status-mkiv.tex328
-rw-r--r--tex/context/interface/mkiv/i-context.pdfbin846956 -> 846813 bytes
-rw-r--r--tex/context/interface/mkiv/i-readme.pdfbin60771 -> 60772 bytes
-rw-r--r--tex/context/sample/common/jojomayer.tex3
-rw-r--r--tex/context/sample/common/mcnish.tex73
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua17
-rw-r--r--tex/generic/context/luatex/luatex-fonts.lua18
44 files changed, 311 insertions, 22792 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 148c8d7c3..954f50c13 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.05.25 12:50}
+\newcontextversion{2017.05.27 18:52}
%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 8c265aa46..e332fe5d7 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.05.25 12:50}
+\edef\contextversion{2017.05.27 18:52}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/char-obs.lua b/tex/context/base/mkiv/char-obs.lua
deleted file mode 100644
index 0f0e43d3c..000000000
--- a/tex/context/base/mkiv/char-obs.lua
+++ /dev/null
@@ -1,269 +0,0 @@
-------------------------
------ char-ini.lua -----
-------------------------
-
--- local template_a = "\\startextendcatcodetable{%s}\\chardef\\l=11\\chardef\\a=13\\let\\c\\catcode%s\\let\\a\\undefined\\let\\l\\undefined\\let\\c\\undefined\\stopextendcatcodetable"
--- local template_b = "\\chardef\\l=11\\chardef\\a=13\\let\\c\\catcode%s\\let\\a\\undefined\\let\\l\\undefined\\let\\c\\undefined"
---
--- function characters.define(tobelettered, tobeactivated) -- catcodetables
--- local lettered, activated, l, a = { }, { }, 0, 0
--- for u, chr in next, data do
--- -- we can use a macro instead of direct settings
--- local fallback = chr.fallback
--- if fallback then
--- -- texprint(format("{\\catcode %s=13\\unexpanded\\gdef %s{\\checkedchar{%s}{%s}}}",u,utfchar(u),u,fallback))
--- texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}") -- no texprint
--- a = a + 1
--- activated[a] = "\\c"..u.."\\a"
--- else
--- local contextname = chr.contextname
--- local category = chr.category
--- if contextname then
--- if is_character[category] then
--- -- by this time, we're still in normal catcode mode
--- -- subtle: not "\\",contextname but "\\"..contextname
--- if chr.unicodeslot < 128 then
--- texprint(ctxcatcodes,format("\\chardef\\%s=%s",contextname,u))
--- else
--- texprint(ctxcatcodes,format("\\let\\%s=%s",contextname,utfchar(u)))
--- if is_letter[category] then
--- l = l + 1
--- lettered[l] = "\\c"..u.."\\l"
--- end
--- end
--- elseif is_command[category] then
--- -- this might change: contextcommand ipv contextname
--- -- texprint(format("{\\catcode %s=13\\unexpanded\\gdef %s{\\%s}}",u,utfchar(u),contextname))
--- texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}") -- no texprint
--- a = a + 1
--- activated[a] = "\\c"..u.."\\a"
--- end
--- elseif is_letter[category] then
--- if u >= 128 and u <= 65536 then -- catch private mess
--- l = l + 1
--- lettered[l] = "\\c"..u.."\\l"
--- end
--- end
--- end
--- local range = chr.range
--- if range then
--- l = l + 1
--- lettered[l] = format('\\dofastrecurse{"%05X}{"%05X}{1}{\\c\\fastrecursecounter\\l}',range.first,range.last)
--- end
--- end
--- -- if false then
--- l = l + 1
--- lettered[l] = "\\c"..0x200C.."\\l" -- non-joiner
--- l = l + 1
--- lettered[l] = "\\c"..0x200D.."\\l" -- joiner
--- -- fi
--- if tobelettered then
--- lettered = concat(lettered)
--- if true then
--- texsprint(ctxcatcodes,format(template_b,lettered)) -- global
--- else
--- for l=1,#tobelettered do
--- texsprint(ctxcatcodes,format(template_a,tobelettered[l],lettered))
--- end
--- end
--- end
--- if tobeactivated then
--- activated = concat(activated)
--- for a=1,#tobeactivated do
--- texsprint(ctxcatcodes,format(template_a,tobeactivated[a],activated))
--- end
--- end
--- end
---
--- function characters.setcodes()
--- for code, chr in next, data do
--- local cc = chr.category
--- if cc == 'll' or cc == 'lu' or cc == 'lt' then
--- local lc, uc = chr.lccode, chr.uccode
--- if not lc then chr.lccode, lc = code, code end
--- if not uc then chr.uccode, uc = code, code end
--- texsprint(ctxcatcodes,format("\\setcclcuc{%i}{%i}{%i}",code,lc,uc))
--- end
--- if cc == "lu" then
--- texprint(ctxcatcodes,"\\sfcode ",code,"999 ")
--- end
--- if cc == "lo" then
--- local range = chr.range
--- if range then
--- texsprint(ctxcatcodes,format('\\dofastrecurse{"%05X}{"%05X}{1}{\\setcclcucself\\fastrecursecounter}',range.first,range.last))
--- end
--- end
--- end
--- end
-
--- --[[ldx--
--- <p>The next variant has lazy token collecting, on a 140 page mk.tex this saves
--- about .25 seconds, which is understandable because we have no graphemes and
--- not collecting tokens is not only faster but also saves garbage collecting.
--- </p>
--- --ldx]]--
---
--- function utffilters.collapse(str,filename) -- we can make high a seperate pass (never needed with collapse)
--- if skippable[filesuffix(filename)] then
--- return str
--- -- elseif find(filename,"^virtual://") then
--- -- return str
--- -- else
--- -- -- print("\n"..filename)
--- end
--- if str and str ~= "" then
--- local nstr = #str
--- if nstr > 1 then
--- if initialize then -- saves a call
--- initialize()
--- end
--- local tokens, t, first, done, n = { }, 0, false, false, 0
--- for second in utfcharacters(str) do
--- if done then
--- if first then
--- if second == " " then
--- t = t + 1
--- tokens[t] = first
--- first = second
--- else
--- -- local crs = high[second]
--- -- if crs then
--- -- t = t + 1
--- -- tokens[t] = first
--- -- first = crs
--- -- else
--- local cgf = graphemes[first]
--- if cgf and cgf[second] then
--- first = cgf[second]
--- else
--- t = t + 1
--- tokens[t] = first
--- first = second
--- end
--- -- end
--- end
--- elseif second == " " then
--- first = second
--- else
--- -- local crs = high[second]
--- -- if crs then
--- -- first = crs
--- -- else
--- first = second
--- -- end
--- end
--- elseif second == " " then
--- first = nil
--- n = n + 1
--- else
--- -- local crs = high[second]
--- -- if crs then
--- -- for s in utfcharacters(str) do
--- -- if n == 1 then
--- -- break
--- -- else
--- -- t = t + 1
--- -- tokens[t] = s
--- -- n = n - 1
--- -- end
--- -- end
--- -- if first then
--- -- t = t + 1
--- -- tokens[t] = first
--- -- end
--- -- first = crs
--- -- done = true
--- -- else
--- local cgf = graphemes[first]
--- if cgf and cgf[second] then
--- for s in utfcharacters(str) do
--- if n == 1 then
--- break
--- else
--- t = t + 1
--- tokens[t] = s
--- n = n - 1
--- end
--- end
--- first = cgf[second]
--- done = true
--- else
--- first = second
--- n = n + 1
--- end
--- -- end
--- end
--- end
--- if done then
--- if first then
--- t = t + 1
--- tokens[t] = first
--- end
--- return concat(tokens) -- seldom called
--- end
--- elseif nstr > 0 then
--- return high[str] or str -- this will go from here
--- end
--- end
--- return str
--- end
-
--- function utffilters.decompose(str)
--- if str and str ~= "" then
--- local nstr = #str
--- if nstr > 1 then
--- -- if initialize then -- saves a call
--- -- initialize()
--- -- end
--- local tokens, t, done, n = { }, 0, false, 0
--- for s in utfcharacters(str) do
--- local dec = decomposed[s]
--- if dec then
--- if not done then
--- if n > 0 then
--- for s in utfcharacters(str) do
--- if n == 0 then
--- break
--- else
--- t = t + 1
--- tokens[t] = s
--- n = n - 1
--- end
--- end
--- end
--- done = true
--- end
--- t = t + 1
--- tokens[t] = dec
--- elseif done then
--- t = t + 1
--- tokens[t] = s
--- else
--- n = n + 1
--- end
--- end
--- if done then
--- return concat(tokens) -- seldom called
--- end
--- end
--- end
--- return str
--- end
-
--- local replacer = nil
--- local finder = nil
---
--- function utffilters.decompose(str) -- 3 to 4 times faster than the above
--- if not replacer then
--- if initialize then
--- initialize()
--- end
--- local tree = utfchartabletopattern(decomposed)
--- finder = lpeg.finder(tree,false,true)
--- replacer = lpeg.replacer(tree,decomposed,false,true)
--- end
--- if str and str ~= "" and #str > 1 and lpegmatch(finder,str) then
--- return lpegmatch(replacer,str)
--- end
--- return str
--- end
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index a80d41e5e..a59640f48 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.05.25 12:50}
+\newcontextversion{2017.05.27 18:52}
%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/context.mkiv b/tex/context/base/mkiv/context.mkiv
index e7037678d..a1160475a 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -39,7 +39,7 @@
%D up and the dependencies are more consistent.
\edef\contextformat {\jobname}
-\edef\contextversion{2017.05.25 12:50}
+\edef\contextversion{2017.05.27 18:52}
\edef\contextkind {beta}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/font-afk.lua b/tex/context/base/mkiv/font-afk.lua
index 8b65b0631..761016d34 100644
--- a/tex/context/base/mkiv/font-afk.lua
+++ b/tex/context/base/mkiv/font-afk.lua
@@ -1,6 +1,6 @@
if not modules then modules = { } end modules ['font-afk'] = {
version = 1.001,
- comment = "companion to font-afm.lua",
+ comment = "companion to font-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files",
diff --git a/tex/context/base/mkiv/font-afm.lua b/tex/context/base/mkiv/font-afm.lua
deleted file mode 100644
index a9fbe89f1..000000000
--- a/tex/context/base/mkiv/font-afm.lua
+++ /dev/null
@@ -1,1232 +0,0 @@
-if not modules then modules = { } end modules ['font-afm'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
---[[ldx--
-<p>Some code may look a bit obscure but this has to do with the
-fact that we also use this code for testing and much code evolved
-in the transition from <l n='tfm'/> to <l n='afm'/> to <l
-n='otf'/>.</p>
-
-<p>The following code still has traces of intermediate font support
-where we handles font encodings. Eventually font encoding goes
-away.</p>
-
-<p>The embedding of a font involves creating temporary files and
-depending on your system setup that can fail. It took more than a
-day to figure out why sometimes embedding failed in mingw luatex
-where running on a real path like c:\... failed while running on
-say e:\... being a link worked well. The native windows binaries
-don't have this issue.</p>
-
---ldx]]--
-
-local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers
-
-local next, type, tonumber = next, type, tonumber
-local match, gmatch, lower, gsub, strip, find = string.match, string.gmatch, string.lower, string.gsub, string.strip, string.find
-local char, byte, sub = string.char, string.byte, string.sub
-local abs = math.abs
-local bxor, rshift = bit32.bxor, bit32.rshift
-local P, S, R, Cmt, C, Ct, Cs, Cg, Cf, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Cg, lpeg.Cf, lpeg.match, lpeg.patterns
-local derivetable = table.derive
-
-local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
-local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
-local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
-local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
-
-local report_afm = logs.reporter("fonts","afm loading")
-local report_pfb = logs.reporter("fonts","pfb loading")
-
-local setmetatableindex = table.setmetatableindex
-
-local findbinfile = resolvers.findbinfile
-
-local definers = fonts.definers
-local readers = fonts.readers
-local constructors = fonts.constructors
-
-local afm = constructors.handlers.afm
-local pfb = constructors.handlers.pfb
-
-local afmfeatures = constructors.features.afm
-local registerafmfeature = afmfeatures.register
-
-afm.version = 1.501 -- incrementing this number one up will force a re-cache
-afm.cache = containers.define("fonts", "afm", afm.version, true)
-afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
-
-afm.helpdata = { } -- set later on so no local for this
-afm.syncspace = true -- when true, nicer stretch values
-afm.addligatures = true -- best leave this set to true
-afm.addtexligatures = true -- best leave this set to true
-afm.addkerns = true -- best leave this set to true
-
-local overloads = fonts.mappings.overloads
-
-local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
-
-local function setmode(tfmdata,value)
- if value then
- tfmdata.properties.mode = lower(value)
- end
-end
-
-registerafmfeature {
- name = "mode",
- description = "mode",
- initializers = {
- base = setmode,
- node = setmode,
- }
-}
-
---[[ldx--
-<p>We start with the basic reader which we give a name similar to the
-built in <l n='tfm'/> and <l n='otf'/> reader.</p>
---ldx]]--
-
---~ Comment FONTIDENTIFIER LMMATHSYMBOLS10
---~ Comment CODINGSCHEME TEX MATH SYMBOLS
---~ Comment DESIGNSIZE 10.0 pt
---~ Comment CHECKSUM O 4261307036
---~ Comment SPACE 0 plus 0 minus 0
---~ Comment QUAD 1000
---~ Comment EXTRASPACE 0
---~ Comment NUM 676.508 393.732 443.731
---~ Comment DENOM 685.951 344.841
---~ Comment SUP 412.892 362.892 288.889
---~ Comment SUB 150 247.217
---~ Comment SUPDROP 386.108
---~ Comment SUBDROP 50
---~ Comment DELIM 2390 1010
---~ Comment AXISHEIGHT 250
-
-local comment = P("Comment")
-local spacing = patterns.spacer -- S(" \t")^1
-local lineend = patterns.newline -- S("\n\r")
-local words = C((1 - lineend)^1)
-local number = C((R("09") + S("."))^1) / tonumber * spacing^0
-local data = lpeg.Carg(1)
-
-local pattern = ( -- needs testing ... not used anyway as we no longer need math afm's
- comment * spacing *
- (
- data * (
- ("CODINGSCHEME" * spacing * words ) / function(fd,a) end +
- ("DESIGNSIZE" * spacing * number * words ) / function(fd,a) fd[ 1] = a end +
- ("CHECKSUM" * spacing * number * words ) / function(fd,a) fd[ 2] = a end +
- ("SPACE" * spacing * number * "plus" * number * "minus" * number) / function(fd,a,b,c) fd[ 3], fd[ 4], fd[ 5] = a, b, c end +
- ("QUAD" * spacing * number ) / function(fd,a) fd[ 6] = a end +
- ("EXTRASPACE" * spacing * number ) / function(fd,a) fd[ 7] = a end +
- ("NUM" * spacing * number * number * number ) / function(fd,a,b,c) fd[ 8], fd[ 9], fd[10] = a, b, c end +
- ("DENOM" * spacing * number * number ) / function(fd,a,b ) fd[11], fd[12] = a, b end +
- ("SUP" * spacing * number * number * number ) / function(fd,a,b,c) fd[13], fd[14], fd[15] = a, b, c end +
- ("SUB" * spacing * number * number ) / function(fd,a,b) fd[16], fd[17] = a, b end +
- ("SUPDROP" * spacing * number ) / function(fd,a) fd[18] = a end +
- ("SUBDROP" * spacing * number ) / function(fd,a) fd[19] = a end +
- ("DELIM" * spacing * number * number ) / function(fd,a,b) fd[20], fd[21] = a, b end +
- ("AXISHEIGHT" * spacing * number ) / function(fd,a) fd[22] = a end
- )
- + (1-lineend)^0
- )
- + (1-comment)^1
-)^0
-
-local function scan_comment(str)
- local fd = { }
- lpegmatch(pattern,str,1,fd)
- return fd
-end
-
--- On a rainy day I will rewrite this in lpeg ... or we can use the (slower) fontloader
--- as in now supports afm/pfb loading but it's not too bad to have different methods
--- for testing approaches.
-
-local keys = { }
-
-function keys.FontName (data,line) data.metadata.fontname = strip (line) -- get rid of spaces
- data.metadata.fullname = strip (line) end
-function keys.ItalicAngle (data,line) data.metadata.italicangle = tonumber (line) end
-function keys.IsFixedPitch(data,line) data.metadata.monospaced = toboolean(line,true) end
-function keys.CharWidth (data,line) data.metadata.charwidth = tonumber (line) end
-function keys.XHeight (data,line) data.metadata.xheight = tonumber (line) end
-function keys.Descender (data,line) data.metadata.descender = tonumber (line) end
-function keys.Ascender (data,line) data.metadata.ascender = tonumber (line) end
-function keys.Comment (data,line)
- -- Comment DesignSize 12 (pts)
- -- Comment TFM designsize: 12 (in points)
- line = lower(line)
- local designsize = match(line,"designsize[^%d]*(%d+)")
- if designsize then data.metadata.designsize = tonumber(designsize) end
-end
-
-local function get_charmetrics(data,charmetrics,vector)
- local characters = data.characters
- local chr, ind = { }, 0
- for k, v in gmatch(charmetrics,"([%a]+) +(.-) *;") do
- if k == 'C' then
- v = tonumber(v)
- if v < 0 then
- ind = ind + 1 -- ?
- else
- ind = v
- end
- chr = {
- index = ind
- }
- elseif k == 'WX' then
- chr.width = tonumber(v)
- elseif k == 'N' then
- characters[v] = chr
- elseif k == 'B' then
- local llx, lly, urx, ury = match(v,"^ *(.-) +(.-) +(.-) +(.-)$")
- chr.boundingbox = { tonumber(llx), tonumber(lly), tonumber(urx), tonumber(ury) }
- elseif k == 'L' then
- local plus, becomes = match(v,"^(.-) +(.-)$")
- local ligatures = chr.ligatures
- if ligatures then
- ligatures[plus] = becomes
- else
- chr.ligatures = { [plus] = becomes }
- end
- end
- end
-end
-
-local function get_kernpairs(data,kernpairs)
- local characters = data.characters
- for one, two, value in gmatch(kernpairs,"KPX +(.-) +(.-) +(.-)\n") do
- local chr = characters[one]
- if chr then
- local kerns = chr.kerns
- if kerns then
- kerns[two] = tonumber(value)
- else
- chr.kerns = { [two] = tonumber(value) }
- end
- end
- end
-end
-
-local function get_variables(data,fontmetrics)
- for key, rest in gmatch(fontmetrics,"(%a+) *(.-)[\n\r]") do
- local keyhandler = keys[key]
- if keyhandler then
- keyhandler(data,rest)
- end
- end
-end
-
-local get_indexes
-
-do
-
- -- old font loader
-
- local fontloader = fontloader
- local get_indexes_old = false
-
- if fontloader then
-
- local font_to_table = fontloader.to_table
- local open_font = fontloader.open
- local close_font = fontloader.close
-
- get_indexes_old = function(data,pfbname)
- local pfbblob = open_font(pfbname)
- if pfbblob then
- local characters = data.characters
- local pfbdata = font_to_table(pfbblob)
- if pfbdata then
- local glyphs = pfbdata.glyphs
- if glyphs then
- if trace_loading then
- report_afm("getting index data from %a",pfbname)
- end
- for index, glyph in next, glyphs do
- local name = glyph.name
- if name then
- local char = characters[name]
- if char then
- if trace_indexing then
- report_afm("glyph %a has index %a",name,index)
- end
- char.index = index
- end
- end
- end
- elseif trace_loading then
- report_afm("no glyph data in pfb file %a",pfbname)
- end
- elseif trace_loading then
- report_afm("no data in pfb file %a",pfbname)
- end
- close_font(pfbblob)
- elseif trace_loading then
- report_afm("invalid pfb file %a",pfbname)
- end
- end
-
- end
-
- -- new (unfinished) font loader but i see no differences between
- -- old and new (one bad vector with old)
-
- local n, m
-
- local progress = function(str,position,name,size)
- local forward = position + tonumber(size) + 3 + 2
- n = n + 1
- if n >= m then
- return #str, name
- elseif forward < #str then
- return forward, name
- else
- return #str, name
- end
- end
-
- local initialize = function(str,position,size)
- n = 0
- m = size -- % tonumber(size)
- return position + 1
- end
-
- local charstrings = P("/CharStrings")
- local encoding = P("/Encoding")
- local dup = P("dup")
- local put = P("put")
- local array = P("array")
- local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
- local digits = R("09")^1
- local cardinal = digits / tonumber
- local spaces = P(" ")^1
- local spacing = patterns.whitespace^0
-
- local p_filternames = Ct (
- (1-charstrings)^0 * charstrings * spaces * Cmt(cardinal,initialize)
- * (Cmt(name * spaces * cardinal, progress) + P(1))^1
- )
-
- -- /Encoding 256 array
- -- 0 1 255 {1 index exch /.notdef put} for
- -- dup 0 /Foo put
-
- local p_filterencoding =
- (1-encoding)^0 * encoding * spaces * digits * spaces * array * (1-dup)^0
- * Cf(
- Ct("") * Cg(spacing * dup * spaces * cardinal * spaces * name * spaces * put)^1
- ,rawset)
-
- -- if one of first 4 not 0-9A-F then binary else hex
-
- local decrypt
-
- do
-
- local r, c1, c2, n = 0, 0, 0, 0
-
- local function step(c)
- local cipher = byte(c)
- local plain = bxor(cipher,rshift(r,8))
- r = ((cipher + r) * c1 + c2) % 65536
- return char(plain)
- end
-
- decrypt = function(binary)
- r, c1, c2, n = 55665, 52845, 22719, 4
- binary = gsub(binary,".",step)
- return sub(binary,n+1)
- end
-
- -- local pattern = Cs((P(1) / step)^1)
- --
- -- decrypt = function(binary)
- -- r, c1, c2, n = 55665, 52845, 22719, 4
- -- binary = lpegmatch(pattern,binary)
- -- return sub(binary,n+1)
- -- end
-
- end
-
- local function loadpfbvector(filename)
- -- for the moment limited to encoding only
-
- local data = io.loaddata(resolvers.findfile(filename))
-
- if not data then
- report_pfb("no data in %a",filename)
- return
- end
-
- if not (find(data,"!PS%-AdobeFont%-") or find(data,"%%!FontType1")) then
- report_pfb("no font in %a",filename)
- return
- end
-
- local ascii, binary = match(data,"(.*)eexec%s+......(.*)")
-
- if not binary then
- report_pfb("no binary data in %a",filename)
- return
- end
-
- binary = decrypt(binary,4)
-
- local vector = lpegmatch(p_filternames,binary)
-
- if vector[1] == ".notdef" then
- -- tricky
- vector[0] = table.remove(vector,1)
- end
-
- if not vector then
- report_pfb("no vector in %a",filename)
- return
- end
-
- local encoding = lpegmatch(p_filterencoding,ascii)
-
- return vector, encoding
-
- end
-
- local pfb = handlers.pfb or { }
- handlers.pfb = pfb
- pfb.loadvector = loadpfbvector
-
- get_indexes = function(data,pfbname)
- local vector = loadpfbvector(pfbname)
- if vector then
- local characters = data.characters
- if trace_loading then
- report_afm("getting index data from %a",pfbname)
- end
- for index=1,#vector do
- local name = vector[index]
- local char = characters[name]
- if char then
- if trace_indexing then
- report_afm("glyph %a has index %a",name,index)
- end
- char.index = index
- end
- end
- end
- end
-
- if get_indexes_old then
-
- afm.use_new_indexer = true
- get_indexes_new = get_indexes
-
- get_indexes = function(data,pfbname)
- if afm.use_new_indexer then
- return get_indexes_new(data,pfbname)
- else
- return get_indexes_old(data,pfbname)
- end
- end
-
- end
-
-
-end
-
-local function readafm(filename)
- local ok, afmblob, size = resolvers.loadbinfile(filename) -- has logging
- if ok and afmblob then
- local data = {
- resources = {
- filename = resolvers.unresolve(filename),
- version = afm.version,
- creator = "context mkiv",
- },
- properties = {
- hasitalics = false,
- },
- goodies = {
- },
- metadata = {
- filename = file.removesuffix(file.basename(filename))
- },
- characters = {
- -- a temporary store
- },
- descriptions = {
- -- the final store
- },
- }
- afmblob = gsub(afmblob,"StartCharMetrics(.-)EndCharMetrics", function(charmetrics)
- if trace_loading then
- report_afm("loading char metrics")
- end
- get_charmetrics(data,charmetrics,vector)
- return ""
- end)
- afmblob = gsub(afmblob,"StartKernPairs(.-)EndKernPairs", function(kernpairs)
- if trace_loading then
- report_afm("loading kern pairs")
- end
- get_kernpairs(data,kernpairs)
- return ""
- end)
- afmblob = gsub(afmblob,"StartFontMetrics%s+([%d%.]+)(.-)EndFontMetrics", function(version,fontmetrics)
- if trace_loading then
- report_afm("loading variables")
- end
- data.afmversion = version
- get_variables(data,fontmetrics)
- data.fontdimens = scan_comment(fontmetrics) -- todo: all lpeg, no time now
- return ""
- end)
- return data
- else
- if trace_loading then
- report_afm("no valid afm file %a",filename)
- end
- return nil
- end
-end
-
---[[ldx--
-<p>We cache files. Caching is taken care of in the loader. We cheat a bit
-by adding ligatures and kern information to the afm derived data. That
-way we can set them faster when defining a font.</p>
---ldx]]--
-
-local addkerns, addligatures, addtexligatures, unify, normalize, fixnames -- we will implement these later
-
-function afm.load(filename)
- -- hm, for some reasons not resolved yet
- filename = resolvers.findfile(filename,'afm') or ""
- if filename ~= "" and not fonts.names.ignoredfile(filename) then
- local name = file.removesuffix(file.basename(filename))
- local data = containers.read(afm.cache,name)
- local attr = lfs.attributes(filename)
- local size, time = attr.size or 0, attr.modification or 0
- --
- local pfbfile = file.replacesuffix(name,"pfb")
- local pfbname = resolvers.findfile(pfbfile,"pfb") or ""
- if pfbname == "" then
- pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or ""
- end
- local pfbsize, pfbtime = 0, 0
- if pfbname ~= "" then
- local attr = lfs.attributes(pfbname)
- pfbsize = attr.size or 0
- pfbtime = attr.modification or 0
- end
- if not data or data.size ~= size or data.time ~= time or data.pfbsize ~= pfbsize or data.pfbtime ~= pfbtime then
- report_afm("reading %a",filename)
- data = readafm(filename)
- if data then
- if pfbname ~= "" then
- data.resources.filename = resolvers.unresolve(pfbname)
- get_indexes(data,pfbname)
- elseif trace_loading then
- report_afm("no pfb file for %a",filename)
- -- data.resources.filename = "unset" -- better than loading the afm file
- end
- report_afm("unifying %a",filename)
- unify(data,filename)
- if afm.addligatures then
- report_afm("add ligatures")
- addligatures(data)
- end
- if afm.addtexligatures then
- report_afm("add tex ligatures")
- addtexligatures(data)
- end
- if afm.addkerns then
- report_afm("add extra kerns")
- addkerns(data)
- end
- normalize(data)
- fixnames(data)
- report_afm("add tounicode data")
- fonts.mappings.addtounicode(data,filename)
- data.size = size
- data.time = time
- data.pfbsize = pfbsize
- data.pfbtime = pfbtime
- report_afm("saving %a in cache",name)
- data.resources.unicodes = nil -- consistent with otf but here we save not much
- data = containers.write(afm.cache, name, data)
- data = containers.read(afm.cache,name)
- end
- if applyruntimefixes and data then
- applyruntimefixes(filename,data)
- end
- end
- return data
- else
- return nil
- end
-end
-
-local uparser = fonts.mappings.makenameparser()
-
-unify = function(data, filename)
- local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context
- local unicodes = { }
- local names = { }
- local private = constructors.privateoffset
- local descriptions = data.descriptions
- for name, blob in next, data.characters do
- local code = unicodevector[name] -- or characters.name_to_unicode[name]
- if not code then
- code = lpegmatch(uparser,name)
- if not code then
- code = private
- private = private + 1
- report_afm("assigning private slot %U for unknown glyph name %a",code,name)
- end
- end
- local index = blob.index
- unicodes[name] = code
- names[name] = index
- blob.name = name
- descriptions[code] = {
- boundingbox = blob.boundingbox,
- width = blob.width,
- kerns = blob.kerns,
- index = index,
- name = name,
- }
- end
- for unicode, description in next, descriptions do
- local kerns = description.kerns
- if kerns then
- local krn = { }
- for name, kern in next, kerns do
- local unicode = unicodes[name]
- if unicode then
- krn[unicode] = kern
- else
- -- print(unicode,name)
- end
- end
- description.kerns = krn
- end
- end
- data.characters = nil
- local resources = data.resources
- local filename = resources.filename or file.removesuffix(file.basename(filename))
- resources.filename = resolvers.unresolve(filename) -- no shortcut
- resources.unicodes = unicodes -- name to unicode
- resources.marks = { } -- todo
- -- resources.names = names -- name to index
- resources.private = private
-end
-
-local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
-local noflags = { false, false, false, false }
-
-afm.experimental_normalize = false
-
-normalize = function(data)
- if type(afm.experimental_normalize) == "function" then
- afm.experimental_normalize(data)
- end
-end
-
-fixnames = function(data)
- for k, v in next, data.descriptions do
- local n = v.name
- local r = overloads[n]
- if r then
- local name = r.name
- if trace_indexing then
- report_afm("renaming characters %a to %a",n,name)
- end
- v.name = name
- v.unicode = r.unicode
- end
- end
-end
-
---[[ldx--
-<p>These helpers extend the basic table with extra ligatures, texligatures
-and extra kerns. This saves quite some lookups later.</p>
---ldx]]--
-
-local addthem = function(rawdata,ligatures)
- if ligatures then
- local descriptions = rawdata.descriptions
- local resources = rawdata.resources
- local unicodes = resources.unicodes
- -- local names = resources.names
- for ligname, ligdata in next, ligatures do
- local one = descriptions[unicodes[ligname]]
- if one then
- for _, pair in next, ligdata do
- local two, three = unicodes[pair[1]], unicodes[pair[2]]
- if two and three then
- local ol = one.ligatures
- if ol then
- if not ol[two] then
- ol[two] = three
- end
- else
- one.ligatures = { [two] = three }
- end
- end
- end
- end
- end
- end
-end
-
-addligatures = function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end
-addtexligatures = function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end
-
---[[ldx--
-<p>We keep the extra kerns in separate kerning tables so that we can use
-them selectively.</p>
---ldx]]--
-
--- This is rather old code (from the beginning when we had only tfm). If
--- we unify the afm data (now we have names all over the place) then
--- we can use shcodes but there will be many more looping then. But we
--- could get rid of the tables in char-cmp then. Als, in the generic version
--- we don't use the character database. (Ok, we can have a context specific
--- variant).
-
-addkerns = function(rawdata) -- using shcodes is not robust here
- local descriptions = rawdata.descriptions
- local resources = rawdata.resources
- local unicodes = resources.unicodes
- local function do_it_left(what)
- if what then
- for unicode, description in next, descriptions do
- local kerns = description.kerns
- if kerns then
- local extrakerns
- for complex, simple in next, what do
- complex = unicodes[complex]
- simple = unicodes[simple]
- if complex and simple then
- local ks = kerns[simple]
- if ks and not kerns[complex] then
- if extrakerns then
- extrakerns[complex] = ks
- else
- extrakerns = { [complex] = ks }
- end
- end
- end
- end
- if extrakerns then
- description.extrakerns = extrakerns
- end
- end
- end
- end
- end
- local function do_it_copy(what)
- if what then
- for complex, simple in next, what do
- complex = unicodes[complex]
- simple = unicodes[simple]
- if complex and simple then
- local complexdescription = descriptions[complex]
- if complexdescription then -- optional
- local simpledescription = descriptions[complex]
- if simpledescription then
- local extrakerns
- local kerns = simpledescription.kerns
- if kerns then
- for unicode, kern in next, kerns do
- if extrakerns then
- extrakerns[unicode] = kern
- else
- extrakerns = { [unicode] = kern }
- end
- end
- end
- local extrakerns = simpledescription.extrakerns
- if extrakerns then
- for unicode, kern in next, extrakerns do
- if extrakerns then
- extrakerns[unicode] = kern
- else
- extrakerns = { [unicode] = kern }
- end
- end
- end
- if extrakerns then
- complexdescription.extrakerns = extrakerns
- end
- end
- end
- end
- end
- end
- end
- -- add complex with values of simplified when present
- do_it_left(afm.helpdata.leftkerned)
- do_it_left(afm.helpdata.bothkerned)
- -- copy kerns from simple char to complex char unless set
- do_it_copy(afm.helpdata.bothkerned)
- do_it_copy(afm.helpdata.rightkerned)
-end
-
---[[ldx--
-<p>The copying routine looks messy (and is indeed a bit messy).</p>
---ldx]]--
-
-local function adddimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name
- if data then
- for unicode, description in next, data.descriptions do
- local bb = description.boundingbox
- if bb then
- local ht, dp = bb[4], -bb[2]
- if ht == 0 or ht < 0 then
- -- no need to set it and no negative heights, nil == 0
- else
- description.height = ht
- end
- if dp == 0 or dp < 0 then
- -- no negative depths and no negative depths, nil == 0
- else
- description.depth = dp
- end
- end
- end
- end
-end
-
-local function copytotfm(data)
- if data and data.descriptions then
- local metadata = data.metadata
- local resources = data.resources
- local properties = derivetable(data.properties)
- local descriptions = derivetable(data.descriptions)
- local goodies = derivetable(data.goodies)
- local characters = { }
- local parameters = { }
- local unicodes = resources.unicodes
- --
- for unicode, description in next, data.descriptions do -- use parent table
- characters[unicode] = { }
- end
- --
- local filename = constructors.checkedfilename(resources)
- local fontname = metadata.fontname or metadata.fullname
- local fullname = metadata.fullname or metadata.fontname
- local endash = 0x0020 -- space
- local emdash = 0x2014
- local spacer = "space"
- local spaceunits = 500
- --
- local monospaced = metadata.monospaced
- local charwidth = metadata.charwidth
- local italicangle = metadata.italicangle
- local charxheight = metadata.xheight and metadata.xheight > 0 and metadata.xheight
- properties.monospaced = monospaced
- parameters.italicangle = italicangle
- parameters.charwidth = charwidth
- parameters.charxheight = charxheight
- -- same as otf
- if properties.monospaced then
- if descriptions[endash] then
- spaceunits, spacer = descriptions[endash].width, "space"
- end
- if not spaceunits and descriptions[emdash] then
- spaceunits, spacer = descriptions[emdash].width, "emdash"
- end
- if not spaceunits and charwidth then
- spaceunits, spacer = charwidth, "charwidth"
- end
- else
- if descriptions[endash] then
- spaceunits, spacer = descriptions[endash].width, "space"
- end
- if not spaceunits and charwidth then
- spaceunits, spacer = charwidth, "charwidth"
- end
- end
- spaceunits = tonumber(spaceunits)
- if spaceunits < 200 then
- -- todo: warning
- end
- --
- parameters.slant = 0
- parameters.space = spaceunits
- parameters.space_stretch = 500
- parameters.space_shrink = 333
- parameters.x_height = 400
- parameters.quad = 1000
- --
- if italicangle and italicangle ~= 0 then
- parameters.italicangle = italicangle
- parameters.italicfactor = math.cos(math.rad(90+italicangle))
- parameters.slant = - math.tan(italicangle*math.pi/180)
- end
- if monospaced then
- parameters.space_stretch = 0
- parameters.space_shrink = 0
- elseif afm.syncspace then
- parameters.space_stretch = spaceunits/2
- parameters.space_shrink = spaceunits/3
- end
- parameters.extra_space = parameters.space_shrink
- if charxheight then
- parameters.x_height = charxheight
- else
- -- same as otf
- local x = 0x0078 -- x
- if x then
- local x = descriptions[x]
- if x then
- parameters.x_height = x.height
- end
- end
- --
- end
- local fd = data.fontdimens
- if fd and fd[8] and fd[9] and fd[10] then -- math
- for k,v in next, fd do
- parameters[k] = v
- end
- end
- --
- parameters.designsize = (metadata.designsize or 10)*65536
- parameters.ascender = abs(metadata.ascender or 0)
- parameters.descender = abs(metadata.descender or 0)
- parameters.units = 1000
- --
- properties.spacer = spacer
- properties.encodingbytes = 2
- properties.format = fonts.formats[filename] or "type1"
- properties.filename = filename
- properties.fontname = fontname
- properties.fullname = fullname
- properties.psname = fullname
- properties.name = filename or fullname or fontname
- --
- if next(characters) then
- return {
- characters = characters,
- descriptions = descriptions,
- parameters = parameters,
- resources = resources,
- properties = properties,
- goodies = goodies,
- }
- end
- end
- return nil
-end
-
---[[ldx--
-<p>Originally we had features kind of hard coded for <l n='afm'/>
-files but since I expect to support more font formats, I decided
-to treat this fontformat like any other and handle features in a
-more configurable way.</p>
---ldx]]--
-
-function afm.setfeatures(tfmdata,features)
- local okay = constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm)
- if okay then
- return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm)
- else
- return { } -- will become false
- end
-end
-
-local function addtables(data)
- local resources = data.resources
- local lookuptags = resources.lookuptags
- local unicodes = resources.unicodes
- if not lookuptags then
- lookuptags = { }
- resources.lookuptags = lookuptags
- end
- setmetatableindex(lookuptags,function(t,k)
- local v = type(k) == "number" and ("lookup " .. k) or k
- t[k] = v
- return v
- end)
- if not unicodes then
- unicodes = { }
- resources.unicodes = unicodes
- setmetatableindex(unicodes,function(t,k)
- setmetatableindex(unicodes,nil)
- for u, d in next, data.descriptions do
- local n = d.name
- if n then
- t[n] = u
- end
- end
- return rawget(t,k)
- end)
- end
- constructors.addcoreunicodes(unicodes) -- do we really need this?
-end
-
-local function afmtotfm(specification)
- local afmname = specification.filename or specification.name
- if specification.forced == "afm" or specification.format == "afm" then -- move this one up
- if trace_loading then
- report_afm("forcing afm format for %a",afmname)
- end
- else
- local tfmname = findbinfile(afmname,"ofm") or ""
- if tfmname ~= "" then
- if trace_loading then
- report_afm("fallback from afm to tfm for %a",afmname)
- end
- return -- just that
- end
- end
- if afmname ~= "" then
- -- weird, isn't this already done then?
- local features = constructors.checkedfeatures("afm",specification.features.normal)
- specification.features.normal = features
- constructors.hashinstance(specification,true) -- also weird here
- --
- specification = definers.resolve(specification) -- new, was forgotten
- local cache_id = specification.hash
- local tfmdata = containers.read(constructors.cache, cache_id) -- cache with features applied
- if not tfmdata then
- local rawdata = afm.load(afmname)
- if rawdata and next(rawdata) then
- addtables(rawdata)
- adddimensions(rawdata)
- tfmdata = copytotfm(rawdata)
- if tfmdata and next(tfmdata) then
- local shared = tfmdata.shared
- if not shared then
- shared = { }
- tfmdata.shared = shared
- end
- shared.rawdata = rawdata
- shared.features = features
- shared.processes = afm.setfeatures(tfmdata,features)
- end
- elseif trace_loading then
- report_afm("no (valid) afm file found with name %a",afmname)
- end
- tfmdata = containers.write(constructors.cache,cache_id,tfmdata)
- end
- return tfmdata
- end
-end
-
---[[ldx--
-<p>As soon as we could intercept the <l n='tfm'/> reader, I implemented an
-<l n='afm'/> reader. Since traditional <l n='pdftex'/> could use <l n='opentype'/>
-fonts with <l n='afm'/> companions, the following method also could handle
-those cases, but now that we can handle <l n='opentype'/> directly we no longer
-need this features.</p>
---ldx]]--
-
-local function read_from_afm(specification)
- local tfmdata = afmtotfm(specification)
- if tfmdata then
- tfmdata.properties.name = specification.name
- tfmdata = constructors.scale(tfmdata, specification)
- local allfeatures = tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm)
- fonts.loggers.register(tfmdata,'afm',specification)
- end
- return tfmdata
-end
-
---[[ldx--
-<p>Here comes the implementation of a few features. We only implement
-those that make sense for this format.</p>
---ldx]]--
-
-local function prepareligatures(tfmdata,ligatures,value)
- if value then
- local descriptions = tfmdata.descriptions
- local hasligatures = false
- for unicode, character in next, tfmdata.characters do
- local description = descriptions[unicode]
- local dligatures = description.ligatures
- if dligatures then
- local cligatures = character.ligatures
- if not cligatures then
- cligatures = { }
- character.ligatures = cligatures
- end
- for unicode, ligature in next, dligatures do
- cligatures[unicode] = {
- char = ligature,
- type = 0
- }
- end
- hasligatures = true
- end
- end
- tfmdata.properties.hasligatures = hasligatures
- end
-end
-
-local function preparekerns(tfmdata,kerns,value)
- if value then
- local rawdata = tfmdata.shared.rawdata
- local resources = rawdata.resources
- local unicodes = resources.unicodes
- local descriptions = tfmdata.descriptions
- local haskerns = false
- for u, chr in next, tfmdata.characters do
- local d = descriptions[u]
- local newkerns = d[kerns]
- if newkerns then
- local kerns = chr.kerns
- if not kerns then
- kerns = { }
- chr.kerns = kerns
- end
- for k,v in next, newkerns do
- local uk = unicodes[k]
- if uk then
- kerns[uk] = v
- end
- end
- haskerns = true
- end
- end
- tfmdata.properties.haskerns = haskerns
- end
-end
-
-local list = {
- -- [0x0022] = 0x201D,
- [0x0027] = 0x2019,
- -- [0x0060] = 0x2018,
-}
-
-local function texreplacements(tfmdata,value)
- local descriptions = tfmdata.descriptions
- local characters = tfmdata.characters
- for k, v in next, list do
- characters [k] = characters [v] -- we forget about kerns
- descriptions[k] = descriptions[v] -- we forget about kerns
- end
-end
-
-local function ligatures (tfmdata,value) prepareligatures(tfmdata,'ligatures', value) end
-local function texligatures(tfmdata,value) prepareligatures(tfmdata,'texligatures',value) end
-local function kerns (tfmdata,value) preparekerns (tfmdata,'kerns', value) end
-local function extrakerns (tfmdata,value) preparekerns (tfmdata,'extrakerns', value) end
-
-registerafmfeature {
- name = "liga",
- description = "traditional ligatures",
- initializers = {
- base = ligatures,
- node = ligatures,
- }
-}
-
-registerafmfeature {
- name = "kern",
- description = "intercharacter kerning",
- initializers = {
- base = kerns,
- node = kerns,
- }
-}
-
-registerafmfeature {
- name = "extrakerns",
- description = "additional intercharacter kerning",
- initializers = {
- base = extrakerns,
- node = extrakerns,
- }
-}
-
-registerafmfeature {
- name = 'tlig',
- description = 'tex ligatures',
- initializers = {
- base = texligatures,
- node = texligatures,
- }
-}
-
-registerafmfeature {
- name = 'trep',
- description = 'tex replacements',
- initializers = {
- base = texreplacements,
- node = texreplacements,
- }
-}
-
--- readers
-
-fonts.formats.afm = "type1"
-fonts.formats.pfb = "type1"
-
-local function check_afm(specification,fullname)
- local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure
- if foundname == "" then
- foundname = fonts.names.getfilename(fullname,"afm") or ""
- end
- if foundname == "" and afm.autoprefixed then
- local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.*
- if encoding and shortname and fonts.encodings.known[encoding] then
- shortname = findbinfile(shortname,'afm') or "" -- just to be sure
- if shortname ~= "" then
- foundname = shortname
- if trace_defining then
- report_afm("stripping encoding prefix from filename %a",afmname)
- end
- end
- end
- end
- if foundname ~= "" then
- specification.filename = foundname
- specification.format = "afm"
- return read_from_afm(specification)
- end
-end
-
-function readers.afm(specification,method)
- local fullname, tfmdata = specification.filename or "", nil
- if fullname == "" then
- local forced = specification.forced or ""
- if forced ~= "" then
- tfmdata = check_afm(specification,specification.name .. "." .. forced)
- end
- if not tfmdata then
- local check_tfm = readers.check_tfm
- method = (check_tfm and (method or definers.method or "afm or tfm")) or "afm"
- if method == "tfm" then
- tfmdata = check_tfm(specification,specification.name)
- elseif method == "afm" then
- tfmdata = check_afm(specification,specification.name)
- elseif method == "tfm or afm" then
- tfmdata = check_tfm(specification,specification.name) or check_afm(specification,specification.name)
- else -- method == "afm or tfm" or method == "" then
- tfmdata = check_afm(specification,specification.name) or check_tfm(specification,specification.name)
- end
- end
- else
- tfmdata = check_afm(specification,fullname)
- end
- return tfmdata
-end
-
-function readers.pfb(specification,method) -- only called when forced
- local original = specification.specification
- if trace_defining then
- report_afm("using afm reader for %a",original)
- end
- specification.specification = gsub(original,"%.pfb",".afm")
- specification.forced = "afm"
- return readers.afm(specification,method)
-end
diff --git a/tex/context/base/mkiv/font-cft.lua b/tex/context/base/mkiv/font-cft.lua
index 63c056022..fcc5d7b5a 100644
--- a/tex/context/base/mkiv/font-cft.lua
+++ b/tex/context/base/mkiv/font-cft.lua
@@ -7,16 +7,18 @@ if not modules then modules = { } end modules ['font-cft'] = {
}
-- context font tables
-
+--
-- todo: extra:
--
-- extra_space => space.extra
-- space => space.width
-- space_stretch => space.stretch
-- space_shrink => space.shrink
-
+--
-- We do keep the x-height, extra_space, space_shrink and space_stretch
-- around as these are low level official names.
+--
+-- Needs to be checked and updated.
local type = type
diff --git a/tex/context/base/mkiv/font-cid.lua b/tex/context/base/mkiv/font-cid.lua
index 0eaacdfbd..781bc9fec 100644
--- a/tex/context/base/mkiv/font-cid.lua
+++ b/tex/context/base/mkiv/font-cid.lua
@@ -1,6 +1,6 @@
if not modules then modules = { } end modules ['font-cid'] = {
version = 1.001,
- comment = "companion to font-otf.lua (cidmaps)",
+ comment = "companion to font-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
diff --git a/tex/context/base/mkiv/font-col.lua b/tex/context/base/mkiv/font-col.lua
index bce16fae7..8c96202ec 100644
--- a/tex/context/base/mkiv/font-col.lua
+++ b/tex/context/base/mkiv/font-col.lua
@@ -49,6 +49,7 @@ collections.vectors = vectors
local fontdata = fonts.hashes.identifiers
local chardata = fonts.hashes.characters
+local propdata = fonts.hashes.properties
local currentfont = font.current
local fontpatternhassize = fonts.helpers.fontpatternhassize
@@ -220,13 +221,15 @@ function collections.prepare(name) -- we can do this in lua now .. todo
if vectors[current] then
return
end
- if fontdata[current].mathparameters then
+ local properties = propdata[current]
+ local mathsize = properties.mathsize
+ if mathsize == 1 or mathsize == 2 or mathsize == 3 then
return
end
local d = definitions[name]
if d then
if trace_collecting then
- local filename = file.basename(fontdata[current].properties.filename or "?")
+ local filename = file.basename(properties.filename or "?")
report_fonts("applying collection %a to %a, file %a",name,current,filename)
end
list = { }
@@ -246,9 +249,6 @@ function collections.prepare(name) -- we can do this in lua now .. todo
context.font_fallbacks_prepare_clone_vectors(name)
context.font_fallbacks_stop_cloning()
context.popcatcodes() -- context.protect()
- elseif trace_collecting then
- local filename = file.basename(fontdata[current].properties.filename or "?")
- report_fonts("error while applying collection %a to %a, file %a",name,current,filename)
end
end
diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua
index 85ac33a10..e328d56d2 100644
--- a/tex/context/base/mkiv/font-con.lua
+++ b/tex/context/base/mkiv/font-con.lua
@@ -322,7 +322,7 @@ function constructors.scale(tfmdata,specification)
--
local mathsize = tonumber(specification.mathsize) or 0
local textsize = tonumber(specification.textsize) or scaledpoints
- local forcedsize = tonumber(parameters.mathsize ) or 0
+ local forcedsize = tonumber(parameters.mathsize ) or 0 -- can be set by the feature "mathsize"
local extrafactor = tonumber(specification.factor ) or 1
if (mathsize == 2 or forcedsize == 2) and parameters.scriptpercentage then
scaledpoints = parameters.scriptpercentage * textsize / 100
@@ -330,6 +330,8 @@ function constructors.scale(tfmdata,specification)
scaledpoints = parameters.scriptscriptpercentage * textsize / 100
elseif forcedsize > 1000 then -- safeguard
scaledpoints = forcedsize
+ else
+ -- in context x and xx also use mathsize
end
targetparameters.mathsize = mathsize -- context specific
targetparameters.textsize = textsize -- context specific
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 578babc75..d375d4679 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -1299,6 +1299,8 @@ do -- else too many locals
-- stoptiming(fonts)
-- end
+ local busy = false
+
scanners.definefont_two = function()
local global = scanboolean() -- \ifx\fontclass\empty\s!false\else\s!true\fi
@@ -1420,6 +1422,7 @@ do -- else too many locals
-- setting the extra characters will move elsewhere
local characters = tfmdata.characters
local parameters = tfmdata.parameters
+ local properties = tfmdata.properties
-- we use char0 as signal; cf the spec pdf can handle this (no char in slot)
characters[0] = nil
-- characters[0x00A0] = { width = parameters.space }
@@ -1428,25 +1431,32 @@ do -- else too many locals
--
constructors.checkvirtualids(tfmdata) -- experiment, will become obsolete when slots can selfreference
local fallbacks = specification.fallbacks
- if fallbacks and fallbacks ~= "" and tfmdata.properties.hasmath then
+ local mathsize = (mathsize == 1 or mathsize == 2 or mathsize == 3) and mathsize or nil -- can be unset so we test 1 2 3
+ if fallbacks and fallbacks ~= "" and mathsize and not busy then
+ busy = true
-- We need this ugly hack in order to resolve fontnames (at the \TEX end). Originally
-- math was done in Lua after loading (plugged into aftercopying).
--
- -- After tl 2017 I'll also do text falbacks this way (although backups there are done
+ -- After tl 2017 I'll also do text fallbacks this way (although backups there are done
-- in a completely different way.
+ if trace_defining then
+ report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,1)
+ end
mathematics.resolvefallbacks(tfmdata,specification,fallbacks)
context(function()
+ busy = false
mathematics.finishfallbacks(tfmdata,specification,fallbacks)
local id = definefont(tfmdata)
csnames[id] = specification.cs
- tfmdata.properties.id = id
+ properties.id = id
definers.register(tfmdata,id) -- to be sure, normally already done
texdefinefont(global,cs,id)
constructors.cleanuptable(tfmdata)
constructors.finalize(tfmdata)
if trace_defining then
- report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a",
- name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks)
+ report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,2)
end
-- resolved (when designsize is used):
local size = tfmdata.parameters.size or 655360
@@ -1455,13 +1465,20 @@ do -- else too many locals
texsetcount("scaledfontsize",size)
lastfontid = id
--
+ if trace_defining then
+ report_defining("memory usage after: %s",statistics.memused())
+ report_defining("stop stage two")
+ end
+ --
texsetcount("global","lastfontid",lastfontid)
specifiers[lastfontid] = { str, size }
if not mathsize then
- -- forget about it
+ -- forget about it (can't happen here)
elseif mathsize == 0 then
+ -- can't happen (here)
lastmathids[1] = lastfontid
else
+ -- maybe only 1 2 3 (we already test for this)
lastmathids[mathsize] = lastfontid
end
stoptiming(fonts)
@@ -1470,14 +1487,14 @@ do -- else too many locals
else
local id = definefont(tfmdata)
csnames[id] = specification.cs
- tfmdata.properties.id = id
+ properties.id = id
definers.register(tfmdata,id) -- to be sure, normally already done
texdefinefont(global,cs,id)
constructors.cleanuptable(tfmdata)
constructors.finalize(tfmdata)
if trace_defining then
- report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a",
- name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks)
+ report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,"-")
end
-- resolved (when designsize is used):
local size = tfmdata.parameters.size or 655360
@@ -1516,7 +1533,7 @@ do -- else too many locals
-- forget about it
elseif mathsize == 0 then
lastmathids[1] = lastfontid
- else
+ else -- maybe only 1 2 3
lastmathids[mathsize] = lastfontid
end
--
diff --git a/tex/context/base/mkiv/font-inj.lua b/tex/context/base/mkiv/font-inj.lua
deleted file mode 100644
index ccc41d3f3..000000000
--- a/tex/context/base/mkiv/font-inj.lua
+++ /dev/null
@@ -1,1194 +0,0 @@
-if not modules then modules = { } end modules ['font-inj'] = {
- version = 1.001,
- comment = "companion to font-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
--- This property based variant is not faster but looks nicer than the attribute one. We
--- need to use rawget (which is apbout 4 times slower than a direct access but we cannot
--- get/set that one for our purpose! This version does a bit more with discretionaries
--- (and Kai has tested it with his collection of weird fonts.)
-
--- There is some duplicate code here (especially in the the pre/post/replace branches) but
--- we go for speed. We could store a list of glyph and mark nodes when registering but it's
--- cleaner to have an identification pass here. Also, I need to keep tracing in mind so
--- being too clever here is dangerous.
-
--- The subtype test is not needed as there will be no (new) properties set, given that we
--- reset the properties.
-
-if not nodes.properties then return end
-
-local next, rawget = next, rawget
-local fastcopy = table.fastcopy
-
-local trace_injections = false trackers.register("fonts.injections", function(v) trace_injections = v end)
-
-local report_injections = logs.reporter("fonts","injections")
-
-local attributes, nodes, node = attributes, nodes, node
-
-fonts = fonts
-local fontdata = fonts.hashes.identifiers
-
-nodes.injections = nodes.injections or { }
-local injections = nodes.injections
-
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
-local disc_code = nodecodes.disc
-local kern_code = nodecodes.kern
-
-local nuts = nodes.nuts
-local nodepool = nuts.pool
-
-local newkern = nodepool.kern
-
-local tonode = nuts.tonode
-local tonut = nuts.tonut
-
-local getfield = nuts.getfield
-local setfield = nuts.setfield
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local getid = nuts.getid
-local getfont = nuts.getfont
-local getsubtype = nuts.getsubtype
-local getchar = nuts.getchar
-
-local traverse_id = nuts.traverse_id
-local insert_node_before = nuts.insert_before
-local insert_node_after = nuts.insert_after
-local find_tail = nuts.tail
-
-local properties = nodes.properties.data
-
-function injections.installnewkern(nk)
- newkern = nk or newkern
-end
-
-local nofregisteredkerns = 0
-local nofregisteredpairs = 0
-local nofregisteredmarks = 0
-local nofregisteredcursives = 0
-local keepregisteredcounts = false
-
-function injections.keepcounts()
- keepregisteredcounts = true
-end
-
-function injections.resetcounts()
- nofregisteredkerns = 0
- nofregisteredpairs = 0
- nofregisteredmarks = 0
- nofregisteredcursives = 0
- keepregisteredcounts = false
-end
-
--- We need to make sure that a possible metatable will not kick in unexpectedly.
-
--- function injections.reset(n)
--- local p = rawget(properties,n)
--- if p and rawget(p,"injections") then
--- p.injections = nil
--- end
--- end
-
--- function injections.copy(target,source)
--- local sp = rawget(properties,source)
--- if sp then
--- local tp = rawget(properties,target)
--- local si = rawget(sp,"injections")
--- if si then
--- si = fastcopy(si)
--- if tp then
--- tp.injections = si
--- else
--- propertydata[target] = {
--- injections = si,
--- }
--- end
--- else
--- if tp then
--- tp.injections = nil
--- end
--- end
--- end
--- end
-
-function injections.reset(n)
- local p = rawget(properties,n)
- if p then
- p.injections = false -- { }
- else
- properties[n] = false -- { injections = { } }
- end
-end
-
-function injections.copy(target,source)
- local sp = rawget(properties,source)
- if sp then
- local tp = rawget(properties,target)
- local si = rawget(sp,"injections")
- if si then
- si = fastcopy(si)
- if tp then
- tp.injections = si
- else
- propertydata[target] = {
- injections = si,
- }
- end
- elseif tp then
- tp.injections = false -- { }
- else
- properties[target] = { injections = { } }
- end
- else
- local tp = rawget(properties,target)
- if tp then
- tp.injections = false -- { }
- else
- properties[target] = false -- { injections = { } }
- end
- end
-end
-
-function injections.setligaindex(n,index)
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,"injections")
- if i then
- i.ligaindex = index
- else
- p.injections = {
- ligaindex = index
- }
- end
- else
- properties[n] = {
- injections = {
- ligaindex = index
- }
- }
- end
-end
-
-function injections.getligaindex(n,default)
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,"injections")
- if i then
- return i.ligaindex or default
- end
- end
- return default
-end
-
-function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) -- hm: nuts or nodes
- local dx = factor*(exit[1]-entry[1])
- local dy = -factor*(exit[2]-entry[2])
- local ws = tfmstart.width
- local wn = tfmnext.width
- nofregisteredcursives = nofregisteredcursives + 1
- if rlmode < 0 then
- dx = -(dx + wn)
- else
- dx = dx - ws
- end
- --
- local p = rawget(properties,start)
- if p then
- local i = rawget(p,"injections")
- if i then
- i.cursiveanchor = true
- else
- p.injections = {
- cursiveanchor = true,
- }
- end
- else
- properties[start] = {
- injections = {
- cursiveanchor = true,
- },
- }
- end
- local p = rawget(properties,nxt)
- if p then
- local i = rawget(p,"injections")
- if i then
- i.cursivex = dx
- i.cursivey = dy
- else
- p.injections = {
- cursivex = dx,
- cursivey = dy,
- }
- end
- else
- properties[nxt] = {
- injections = {
- cursivex = dx,
- cursivey = dy,
- },
- }
- end
- return dx, dy, nofregisteredcursives
-end
-
-function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2lflag & tfmchr not used
- local x = factor*spec[1]
- local y = factor*spec[2]
- local w = factor*spec[3]
- local h = factor*spec[4]
- if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then -- okay?
- local yoffset = y - h
- local leftkern = x -- both kerns are set in a pair kern compared
- local rightkern = w - x -- to normal kerns where we set only leftkern
- if leftkern ~= 0 or rightkern ~= 0 or yoffset ~= 0 then
- nofregisteredpairs = nofregisteredpairs + 1
- if rlmode and rlmode < 0 then
- leftkern, rightkern = rightkern, leftkern
- end
- if not injection then
- injection = "injections"
- end
- local p = rawget(properties,current)
- if p then
- local i = rawget(p,injection)
- if i then
- if leftkern ~= 0 then
- i.leftkern = (i.leftkern or 0) + leftkern
- end
- if rightkern ~= 0 then
- i.rightkern = (i.rightkern or 0) + rightkern
- end
- if yoffset ~= 0 then
- i.yoffset = (i.yoffset or 0) + yoffset
- end
- elseif leftkern ~= 0 or rightkern ~= 0 then
- p[injection] = {
- leftkern = leftkern,
- rightkern = rightkern,
- yoffset = yoffset,
- }
- else
- p[injection] = {
- yoffset = yoffset,
- }
- end
- elseif leftkern ~= 0 or rightkern ~= 0 then
- properties[current] = {
- [injection] = {
- leftkern = leftkern,
- rightkern = rightkern,
- yoffset = yoffset,
- },
- }
- else
- properties[current] = {
- [injection] = {
- yoffset = yoffset,
- },
- }
- end
- return x, y, w, h, nofregisteredpairs
- end
- end
- return x, y, w, h -- no bound
-end
-
--- This needs checking for rl < 0 but it is unlikely that a r2l script uses kernclasses between
--- glyphs so we're probably safe (KE has a problematic font where marks interfere with rl < 0 in
--- the previous case)
-
-function injections.setkern(current,factor,rlmode,x,injection)
- local dx = factor * x
- if dx ~= 0 then
- nofregisteredkerns = nofregisteredkerns + 1
- local p = rawget(properties,current)
- if not injection then
- injection = "injections"
- end
- if p then
- local i = rawget(p,injection)
- if i then
- i.leftkern = dx + (i.leftkern or 0)
- else
- p[injection] = {
- leftkern = dx,
- }
- end
- else
- properties[current] = {
- [injection] = {
- leftkern = dx,
- },
- }
- end
- return dx, nofregisteredkerns
- else
- return 0, 0
- end
-end
-
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=baseanchor, ma=markanchor
- local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
- nofregisteredmarks = nofregisteredmarks + 1
- -- markanchors[nofregisteredmarks] = base
- if rlmode >= 0 then
- dx = tfmbase.width - dx -- see later commented ox
- end
- local p = rawget(properties,start)
- -- hm, dejavu serif does a sloppy mark2mark before mark2base
- if p then
- local i = rawget(p,"injections")
- if i then
- if i.markmark then
- -- out of order mkmk: yes or no or option
- else
- i.markx = dx
- i.marky = dy
- i.markdir = rlmode or 0
- i.markbase = nofregisteredmarks
- i.markbasenode = base
- i.markmark = mkmk
- end
- else
- p.injections = {
- markx = dx,
- marky = dy,
- markdir = rlmode or 0,
- markbase = nofregisteredmarks,
- markbasenode = base,
- markmark = mkmk,
- }
- end
- else
- properties[start] = {
- injections = {
- markx = dx,
- marky = dy,
- markdir = rlmode or 0,
- markbase = nofregisteredmarks,
- markbasenode = base,
- markmark = mkmk,
- },
- }
- end
- return dx, dy, nofregisteredmarks
-end
-
-local function dir(n)
- return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset"
-end
-
-local function showchar(n,nested)
- local char = getchar(n)
- report_injections("%wfont %s, char %U, glyph %c",nested and 2 or 0,getfont(n),char,char)
-end
-
-local function show(n,what,nested,symbol)
- if n then
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,what)
- if i then
- local leftkern = i.leftkern or 0
- local rightkern = i.rightkern or 0
- local yoffset = i.yoffset or 0
- local markx = i.markx or 0
- local marky = i.marky or 0
- local markdir = i.markdir or 0
- local markbase = i.markbase or 0
- local cursivex = i.cursivex or 0
- local cursivey = i.cursivey or 0
- local ligaindex = i.ligaindex or 0
- local cursbase = i.cursiveanchor
- local margin = nested and 4 or 2
- --
- if rightkern ~= 0 or yoffset ~= 0 then
- report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset)
- elseif leftkern ~= 0 then
- report_injections("%w%s kern: dx %p",margin,symbol,leftkern)
- end
- if markx ~= 0 or marky ~= 0 or markbase ~= 0 then
- report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase ~= 0 and "yes" or "no")
- end
- if cursivex ~= 0 or cursivey ~= 0 then
- if cursbase then
- report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
- else
- report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
- end
- elseif cursbase then
- report_injections("%w%s curs: base",margin,symbol)
- end
- if ligaindex ~= 0 then
- report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
- end
- end
- end
- end
-end
-
-local function showsub(n,what,where)
- report_injections("begin subrun: %s",where)
- for n in traverse_id(glyph_code,n) do
- showchar(n,where)
- show(n,what,where," ")
- end
- report_injections("end subrun")
-end
-
-local function trace(head,where)
- report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered",
- where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives)
- local n = head
- while n do
- local id = getid(n)
- if id == glyph_code then
- showchar(n)
- show(n,"injections",false," ")
- show(n,"preinjections",false,"<")
- show(n,"postinjections",false,">")
- show(n,"replaceinjections",false,"=")
- elseif id == disc_code then
- local pre = getfield(n,"pre")
- local post = getfield(n,"post")
- local replace = getfield(n,"replace")
- if pre then
- showsub(pre,"preinjections","pre")
- end
- if post then
- showsub(post,"postinjections","post")
- end
- if replace then
- showsub(replace,"replaceinjections","replace")
- end
- end
- n = getnext(n)
- end
- report_injections("end run")
-end
-
-local function show_result(head)
- local current = head
- local skipping = false
- while current do
- local id = getid(current)
- if id == glyph_code then
- report_injections("char: %C, width %p, xoffset %p, yoffset %p",
- getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
- skipping = false
- elseif id == kern_code then
- report_injections("kern: %p",getfield(current,"kern"))
- skipping = false
- elseif not skipping then
- report_injections()
- skipping = true
- end
- current = getnext(current)
- end
-end
-
-local function collect_glyphs(head,offsets)
- local glyphs, glyphi, nofglyphs = { }, { }, 0
- local marks, marki, nofmarks = { }, { }, 0
- local nf, tm = nil, nil
- local n = head
-
- local function identify(n,what)
- local f = getfont(n)
- if f ~= nf then
- nf = f
- -- other hash in ctx:
- tm = fontdata[nf].resources
- if tm then
- tm = tm.marks
- end
- end
- if tm and tm[getchar(n)] then
- nofmarks = nofmarks + 1
- marks[nofmarks] = n
- marki[nofmarks] = "injections"
- else
- nofglyphs = nofglyphs + 1
- glyphs[nofglyphs] = n
- glyphi[nofglyphs] = what
- end
- if offsets then
- -- yoffsets can influence curs steps
- local p = rawget(properties,n)
- if p then
- local i = rawget(p,what)
- if i then
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
- end
- end
- end
- end
-
- while n do -- only needed for relevant fonts
- local id = getid(n)
- if id == glyph_code then
- identify(n,"injections")
- elseif id == disc_code then
- local d = getfield(n,"pre")
- if d then
- for n in traverse_id(glyph_code,d) do
- if getsubtype(n) < 256 then
- identify(n,"preinjections")
- end
- end
- end
- local d = getfield(n,"post")
- if d then
- for n in traverse_id(glyph_code,d) do
- if getsubtype(n) < 256 then
- identify(n,"postinjections")
- end
- end
- end
- local d = getfield(n,"replace")
- if d then
- for n in traverse_id(glyph_code,d) do
- if getsubtype(n) < 256 then
- identify(n,"replaceinjections")
- end
- end
- end
- end
- n = getnext(n)
- end
-
- return glyphs, glyphi, nofglyphs, marks, marki, nofmarks
-end
-
-local function inject_marks(marks,marki,nofmarks)
- for i=1,nofmarks do
- local n = marks[i]
- local pn = rawget(properties,n)
- if pn then
- local ni = marki[i]
- local pn = rawget(pn,ni)
- if pn then
- local p = pn.markbasenode
- if p then
- local px = getfield(p,"xoffset")
- local ox = 0
- local rightkern = nil
- local pp = rawget(properties,p)
- if pp then
- pp = rawget(pp,ni)
- if pp then
- rightkern = pp.rightkern
- end
- end
- if rightkern then -- x and w ~= 0
- if pn.markdir < 0 then
- -- kern(w-x) glyph(p) kern(x) mark(n)
- ox = px - pn.markx - rightkern
- -- report_injections("r2l case 1: %p",ox)
- else
- -- kern(x) glyph(p) kern(w-x) mark(n)
- -- ox = px - getfield(p,"width") + pn.markx - pp.leftkern
- --
- -- According to Kai we don't need to handle leftkern here but I'm
- -- pretty sure I've run into a case where it was needed so maybe
- -- some day we need something more clever here.
- --
- if false then
- -- a mark with kerning
- local leftkern = pp.leftkern
- if leftkern then
- ox = px - pn.markx - leftkern
- else
- ox = px - pn.markx
- end
- else
- ox = px - pn.markx
- end
- end
- else
- -- we need to deal with fonts that have marks with width
- -- if pn.markdir < 0 then
- -- ox = px - pn.markx
- -- -- report_injections("r2l case 3: %p",ox)
- -- else
- -- -- ox = px - getfield(p,"width") + pn.markx
- ox = px - pn.markx
- -- report_injections("l2r case 3: %p",ox)
- -- end
- local wn = getfield(n,"width") -- in arial marks have widths
- if wn ~= 0 then
- -- bad: we should center
- -- insert_node_before(head,n,newkern(-wn/2))
- -- insert_node_after(head,n,newkern(-wn/2))
- pn.leftkern = -wn/2
- pn.rightkern = -wn/2
- -- wx[n] = { 0, -wn/2, 0, -wn }
- end
- end
- setfield(n,"xoffset",ox)
- --
- local py = getfield(p,"yoffset")
- -- local oy = 0
- -- if marks[p] then
- -- oy = py + pn.marky
- -- else
- -- oy = getfield(n,"yoffset") + py + pn.marky
- -- end
- local oy = getfield(n,"yoffset") + py + pn.marky
- setfield(n,"yoffset",oy)
- else
- -- normally this can't happen (only when in trace mode which is a special case anyway)
- -- report_injections("missing mark anchor %i",pn.markbase or 0)
- end
- end
- end
- end
-end
-
-local function inject_cursives(glyphs,glyphi,nofglyphs)
- local cursiveanchor, lastanchor = nil, nil
- local minc, maxc, last = 0, 0, nil
- for i=1,nofglyphs do
- local n = glyphs[i]
- local pn = rawget(properties,n)
- if pn then
- pn = rawget(pn,glyphi[i])
- end
- if pn then
- local cursivex = pn.cursivex
- if cursivex then
- if cursiveanchor then
- if cursivex ~= 0 then
- pn.leftkern = (pn.leftkern or 0) + cursivex
- end
- if lastanchor then
- if maxc == 0 then
- minc = lastanchor
- end
- maxc = lastanchor
- properties[cursiveanchor].cursivedy = pn.cursivey
- end
- last = n
- else
- maxc = 0
- end
- elseif maxc > 0 then
- local ny = getfield(n,"yoffset")
- for i=maxc,minc,-1 do
- local ti = glyphs[i]
- ny = ny + properties[ti].cursivedy
- setfield(ti,"yoffset",ny) -- why not add ?
- end
- maxc = 0
- end
- if pn.cursiveanchor then
- cursiveanchor = n
- lastanchor = i
- else
- cursiveanchor = nil
- lastanchor = nil
- if maxc > 0 then
- local ny = getfield(n,"yoffset")
- for i=maxc,minc,-1 do
- local ti = glyphs[i]
- ny = ny + properties[ti].cursivedy
- setfield(ti,"yoffset",ny) -- why not add ?
- end
- maxc = 0
- end
- end
- elseif maxc > 0 then
- local ny = getfield(n,"yoffset")
- for i=maxc,minc,-1 do
- local ti = glyphs[i]
- ny = ny + properties[ti].cursivedy
- setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) -- ?
- end
- maxc = 0
- cursiveanchor = nil
- lastanchor = nil
- end
- -- if maxc > 0 and not cursiveanchor then
- -- local ny = getfield(n,"yoffset")
- -- for i=maxc,minc,-1 do
- -- local ti = glyphs[i][1]
- -- ny = ny + properties[ti].cursivedy
- -- setfield(ti,"yoffset",ny) -- why not add ?
- -- end
- -- maxc = 0
- -- end
- end
- if last and maxc > 0 then
- local ny = getfield(last,"yoffset")
- for i=maxc,minc,-1 do
- local ti = glyphs[i]
- ny = ny + properties[ti].cursivedy
- setfield(ti,"yoffset",ny) -- why not add ?
- end
- end
-end
-
--- G +D-pre G
--- D-post+
--- +D-replace+
---
--- G +D-pre +D-pre
--- D-post +D-post
--- +D-replace +D-replace
-
-local function inject_kerns(head,glist,ilist,length) -- not complete ! compare with inject_kerns_only (but unlikely disc here)
- for i=1,length do
- local n = glist[i]
- local pn = rawget(properties,n)
- if pn then
- local dp = nil
- local dr = nil
- local ni = ilist[i]
- local p = nil
- if ni == "injections" then
- p = getprev(n)
- if p then
- local id = getid(p)
- if id == disc_code then
- dp = getfield(p,"post")
- dr = getfield(p,"replace")
- end
- end
- end
- if dp then
- local i = rawget(pn,"postinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- local t = find_tail(dp)
- insert_node_after(dp,t,newkern(leftkern))
- setfield(p,"post",dp) -- currently we need to force a tail refresh
- end
- end
- end
- if dr then
- local i = rawget(pn,"replaceinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- local t = find_tail(dr)
- insert_node_after(dr,t,newkern(leftkern))
- setfield(p,"replace",dr) -- currently we need to force a tail refresh
- end
- end
- else
- local i = rawget(pn,ni)
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- insert_node_before(head,n,newkern(leftkern)) -- type 0/2
- end
- local rightkern = i.rightkern
- if rightkern and rightkern ~= 0 then
- insert_node_after(head,n,newkern(rightkern)) -- type 0/2
- end
- end
- end
- end
- end
-end
-
-local function inject_everything(head,where)
- head = tonut(head)
- if trace_injections then
- trace(head,"everything")
- end
- local glyphs, glyphi, nofglyphs, marks, marki, nofmarks = collect_glyphs(head,nofregisteredpairs > 0)
- if nofglyphs > 0 then
- if nofregisteredcursives > 0 then
- inject_cursives(glyphs,glyphi,nofglyphs)
- end
- if nofregisteredmarks > 0 then -- and nofmarks > 0
- inject_marks(marks,marki,nofmarks)
- end
- inject_kerns(head,glyphs,glyphi,nofglyphs)
- end
- if nofmarks > 0 then
- inject_kerns(head,marks,marki,nofmarks)
- end
- if keepregisteredcounts then
- keepregisteredcounts = false
- else
- nofregisteredkerns = 0
- nofregisteredpairs = 0
- nofregisteredmarks = 0
- nofregisteredcursives = 0
- end
- return tonode(head), true
-end
-
--- G +D-pre G
--- D-post+
--- +D-replace+
---
--- G +D-pre +D-pre
--- D-post +D-post
--- +D-replace +D-replace
-
-local function inject_kerns_only(head,where)
- head = tonut(head)
- if trace_injections then
- trace(head,"kerns")
- end
- local n = head
- local p = nil -- disc node when non-nil
- while n do
- local id = getid(n)
- if id == glyph_code then
- if getsubtype(n) < 256 then
- local pn = rawget(properties,n)
- if pn then
- if p then
- local d = getfield(p,"post")
- if d then
- local i = rawget(pn,"postinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- local t = find_tail(d)
- insert_node_after(d,t,newkern(leftkern))
- setfield(p,"post",d) -- currently we need to force a tail refresh
- end
- end
- end
- local d = getfield(p,"replace")
- if d then
- local i = rawget(pn,"replaceinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- local t = find_tail(d)
- insert_node_after(d,t,newkern(leftkern))
- setfield(p,"replace",d) -- currently we need to force a tail refresh
- end
- end
- else
- local i = rawget(pn,"injections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- setfield(p,"replace",newkern(leftkern))
- end
- end
- end
- else
- -- this is the most common case
- local i = rawget(pn,"injections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- head = insert_node_before(head,n,newkern(leftkern))
- end
- end
- end
- end
- end
- p = nil
- elseif id == disc_code then
- local d = getfield(n,"pre")
- if d then
- local h = d
- for n in traverse_id(glyph_code,d) do
- if getsubtype(n) < 256 then
- local pn = rawget(properties,n)
- if pn then
- local i = rawget(pn,"preinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- h = insert_node_before(h,n,newkern(leftkern))
- end
- end
- end
- else
- break
- end
- end
- if h ~= d then
- setfield(n,"pre",h)
- end
- end
- local d = getfield(n,"post")
- if d then
- local h = d
- for n in traverse_id(glyph_code,d) do
- if getsubtype(n) < 256 then
- local pn = rawget(properties,n)
- if pn then
- local i = rawget(pn,"postinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- h = insert_node_before(h,n,newkern(leftkern))
- end
- end
- end
- else
- break
- end
- end
- if h ~= d then
- setfield(n,"post",h)
- end
- end
- local d = getfield(n,"replace")
- if d then
- local h = d
- for n in traverse_id(glyph_code,d) do
- if getsubtype(n) < 256 then
- local pn = rawget(properties,n)
- if pn then
- local i = rawget(pn,"replaceinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- h = insert_node_before(h,n,newkern(leftkern))
- end
- end
- end
- else
- break
- end
- end
- if h ~= d then
- setfield(n,"replace",h)
- end
- end
- p = n
- else
- p = nil
- end
- n = getnext(n)
- end
- --
- if keepregisteredcounts then
- keepregisteredcounts = false
- else
- nofregisteredkerns = 0
- end
- return tonode(head), true
-end
-
-local function inject_pairs_only(head,where)
- head = tonut(head)
- if trace_injections then
- trace(head,"pairs")
- end
- local n = head
- local p = nil -- disc node when non-nil
- while n do
- local id = getid(n)
- if id == glyph_code then
- if getsubtype(n) < 256 then
- local pn = rawget(properties,n)
- if pn then
- if p then
- local d = getfield(p,"post")
- if d then
- local i = rawget(pn,"postinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- local t = find_tail(d)
- insert_node_after(d,t,newkern(leftkern))
- setfield(p,"post",d) -- currently we need to force a tail refresh
- end
- -- local rightkern = i.rightkern
- -- if rightkern and rightkern ~= 0 then
- -- insert_node_after(head,n,newkern(rightkern))
- -- n = getnext(n) -- to be checked
- -- end
- end
- end
- local d = getfield(p,"replace")
- if d then
- local i = rawget(pn,"replaceinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- local t = find_tail(d)
- insert_node_after(d,t,newkern(leftkern))
- setfield(p,"replace",d) -- currently we need to force a tail refresh
- end
- -- local rightkern = i.rightkern
- -- if rightkern and rightkern ~= 0 then
- -- insert_node_after(head,n,newkern(rightkern))
- -- n = getnext(n) -- to be checked
- -- end
- end
- else
- local i = rawget(pn,"injections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- setfield(p,"replace",newkern(leftkern))
- end
- -- local rightkern = i.rightkern
- -- if rightkern and rightkern ~= 0 then
- -- insert_node_after(head,n,newkern(rightkern))
- -- n = getnext(n) -- to be checked
- -- end
- end
- end
- else
- -- this is the most common case
- local i = rawget(pn,"injections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- head = insert_node_before(head,n,newkern(leftkern))
- end
- local rightkern = i.rightkern
- if rightkern and rightkern ~= 0 then
- insert_node_after(head,n,newkern(rightkern))
- n = getnext(n) -- to be checked
- end
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
- end
- end
- end
- end
- p = nil
- elseif id == disc_code then
- local d = getfield(n,"pre")
- if d then
- local h = d
- for n in traverse_id(glyph_code,d) do
- if getsubtype(n) < 256 then
- local pn = rawget(properties,n)
- if pn then
- local i = rawget(pn,"preinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- h = insert_node_before(h,n,newkern(leftkern))
- end
- local rightkern = i.rightkern
- if rightkern and rightkern ~= 0 then
- insert_node_after(head,n,newkern(rightkern))
- n = getnext(n) -- to be checked
- end
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
- end
- end
- else
- break
- end
- end
- if h ~= d then
- setfield(n,"pre",h)
- end
- end
- local d = getfield(n,"post")
- if d then
- local h = d
- for n in traverse_id(glyph_code,d) do
- if getsubtype(n) < 256 then
- local pn = rawget(properties,n)
- if pn then
- local i = rawget(pn,"postinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- h = insert_node_before(h,n,newkern(leftkern))
- end
- local rightkern = i.rightkern
- if rightkern and rightkern ~= 0 then
- insert_node_after(head,n,newkern(rightkern))
- n = getnext(n) -- to be checked
- end
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
- end
- end
- else
- break
- end
- end
- if h ~= d then
- setfield(n,"post",h)
- end
- end
- local d = getfield(n,"replace")
- if d then
- local h = d
- for n in traverse_id(glyph_code,d) do
- if getsubtype(n) < 256 then
- local pn = rawget(properties,n)
- if pn then
- local i = rawget(pn,"replaceinjections")
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- h = insert_node_before(h,n,newkern(leftkern))
- end
- local rightkern = i.rightkern
- if rightkern and rightkern ~= 0 then
- insert_node_after(head,n,newkern(rightkern))
- n = getnext(n) -- to be checked
- end
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
- end
- end
- end
- else
- break
- end
- end
- if h ~= d then
- setfield(n,"replace",h)
- end
- end
- p = n
- else
- p = nil
- end
- n = getnext(n)
- end
- --
- if keepregisteredcounts then
- keepregisteredcounts = false
- else
- nofregisteredpairs = 0
- nofregisteredkerns = 0
- end
- return tonode(head), true
-end
-
-function injections.handler(head,where)
- if nofregisteredmarks > 0 or nofregisteredcursives > 0 then
- return inject_everything(head,where)
- elseif nofregisteredpairs > 0 then
- return inject_pairs_only(head,where)
- elseif nofregisteredkerns > 0 then
- return inject_kerns_only(head,where)
- else
- return head, false
- end
-end
diff --git a/tex/context/base/mkiv/font-ldr.lua b/tex/context/base/mkiv/font-ldr.lua
deleted file mode 100644
index 175b4d0cc..000000000
--- a/tex/context/base/mkiv/font-ldr.lua
+++ /dev/null
@@ -1,70 +0,0 @@
-if not modules then modules = { } end modules ['font-ldr'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- This module provides an experimental replacement for fontloader.to_table
--- but is not used that much.
-
-local fields = fontloader.fields
-
-if fields then
-
- local glyphfields
-
- local function get_glyphs(r)
- local t = { }
- local g = r.glyphs
- for i=1,r.glyphmax-1 do
- local gi = g[i]
- if gi then
- if not glyphfields then
- glyphfields = fields(gi)
- end
- local h = { }
- for i=1,#glyphfields do
- local s = glyphfields[i]
- h[s] = gi[s]
- end
- t[i] = h
- end
- end
- return t
- end
-
- local function to_table(r)
- local f = fields(r)
- if f then
- local t = { }
- for i=1,#f do
- local fi = f[i]
- local ri = r[fi]
- if not ri then
- -- skip
- elseif fi == "glyphs" then
- t.glyphs = get_glyphs(r)
- elseif fi == "subfonts" then
- t[fi] = ri
- ri.glyphs = get_glyphs(ri)
- else
- t[fi] = r[fi]
- end
- end
- return t
- end
- end
-
- -- currently glyphs, subfont-glyphs and the main table are userdata
-
- function fonts.to_table(raw)
- return to_table(raw)
- end
-
-else
-
- fonts.to_table = fontloader.to_table
-
-end
diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi
index d9cae503b..7ae94c99b 100644
--- a/tex/context/base/mkiv/font-lib.mkvi
+++ b/tex/context/base/mkiv/font-lib.mkvi
@@ -34,8 +34,6 @@
\registerctxluafile{font-dsp}{1.001} % ... for this one
\registerctxluafile{font-off}{1.001} % the old loader
-% \registerctxluafile{font-tfm}{1.001}
-
\registerctxluafile{font-hsh}{1.001} % hashes used by context
\registerctxluafile{font-nod}{1.001}
@@ -58,7 +56,6 @@
\registerctxluafile{font-onr}{1.001}
\registerctxluafile{font-one}{1.001}
-%registerctxluafile{font-afm}{1.001}
\registerctxluafile{font-afk}{1.001}
% tfm
diff --git a/tex/context/base/mkiv/font-mat.mkvi b/tex/context/base/mkiv/font-mat.mkvi
index cbc78aca8..6ce782ee3 100644
--- a/tex/context/base/mkiv/font-mat.mkvi
+++ b/tex/context/base/mkiv/font-mat.mkvi
@@ -24,18 +24,16 @@
%D \macros
%D {textonly}
%D
-%D Traditionally math has a big impact on font definitions, mainly
-%D because we need to define alphabet variants using families and
-%D fonts. This means that one can easily get 10 fonts loaded per
-%D math size. In \MKIV\ we use a different approach: one family
-%D which has either a virtual font made of traditional fonts, or
-%D an \OPENTYPE\ font that has it all.
+%D Traditionally math has a big impact on font definitions, mainly because we need
+%D to define alphabet variants using families and fonts. This means that one can
+%D easily get 10 fonts loaded per math size. In \MKIV\ we use a different approach:
+%D one family which has either a virtual font made of traditional fonts, or an
+%D \OPENTYPE\ font that has it all.
%D
-%D We currently use only one math family but in the future we
-%D might consider using a second one for bold math. For the
-%D moment we keep the \MKII\ method of using a token register
-%D for definitions but we already dropped the text and symbols
-%D ones since they now live in the same family.
+%D We currently use only one math family but in the future we might consider using a
+%D second one for bold math. For the moment we keep the \MKII\ method of using a
+%D token register for definitions but we already dropped the text and symbols ones
+%D since they now live in the same family.
\newtoks \t_font_math_strategies
\newconditional\c_font_synchronize_math_fonts \settrue\c_font_synchronize_math_fonts
@@ -45,14 +43,12 @@
\unexpanded\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this
-%D The main math font definer. We have removed some optimized
-%D code simply because we now always have a fontclass. We could
-%D check for fontclass being default or empty and save a few
-%D tests but it does not help us when no math is defined.
-
-%D Because we want to keep mr=.. and mb=... settings (read: not
-%D break downward compatibility by enforcing mrlr etc) we need a
-%D bit more code that optimal.
+%D The main math font definer. We have removed some optimized code simply because we
+%D now always have a fontclass. We could check for fontclass being default or empty
+%D and save a few tests but it does not help us when no math is defined.
+%D
+%D Because we want to keep mr=.. and mb=... settings (read: not break downward
+%D compatibility by enforcing mrlr etc) we need a bit more code that optimal.
% todo: \c_font_fam_mr
@@ -75,33 +71,9 @@
\def\mathsizesuffix{\ifcase\fontface\or\mathtextsuffix\or\mathscriptsuffix\or\mathscriptscriptsuffix\fi}
-% Beware: truefontname also does a fallback on defaultfontclass so there
-% can be some interference here, which is why we use a different method
-% for bold.
-
-% \def\font_helpers_set_math_family_a
-% {\ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
-% \csname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
-% \ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
-% \csname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \else
-% \font_helpers_set_math_family_b
-% \fi\fi}
-
-% \def\font_helpers_set_math_family_b
-% {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
-% \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
-% \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
-% \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \else
-% \font_helpers_set_math_family_c
-% \fi\fi}
-
-% \def\font_helpers_set_math_family_c
-% {\ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
-% \csname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
-% \ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
-% \csname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \else
-% \settrue \c_font_auto_size
-% \fi\fi}
+%D Beware: truefontname also does a fallback on defaultfontclass so there
+%D can be some interference here, which is why we use a different method
+%D for bold.
\def\font_helpers_set_math_family_a
{\ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
@@ -133,21 +105,20 @@
{\let\savedfontbody\fontbody
\let\fontfamily#family%
% the order is important as we depend on known id's when completing fonts
- \let\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree\font_helpers_set_math_family_a\scriptscriptfont#mrtag\font
- \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo \font_helpers_set_math_family_a\scriptfont #mrtag\font
- \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone \font_helpers_set_math_family_a\textfont #mrtag\font
+ % enabling is needed when we have fallbacks which spoils the families
+ \let\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree
+ \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % defines
+ \font_helpers_set_math_family_a\scriptscriptfont#mrtag\font % enables
+ \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo
+ \font_helpers_set_math_family_a\scriptfont #mrtag\font % defines
+ \font_helpers_set_math_family_a\scriptfont #mrtag\font % enables
+ \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone
+ \font_helpers_set_math_family_a\textfont #mrtag\font % defines
+ \font_helpers_set_math_family_a\textfont #mrtag\font % enables
\let\mathsizesuffix\empty \let\fontface\!!zerocount
\let\fontbody\savedfontbody
\setfalse\c_font_auto_size}
-% \def\font_helpers_set_math_family_bold_a#font#mbfam#mrfam%
-% {\ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
-% \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname #font#mbfam\font \else
-% \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
-% \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname #font#mbfam\font \else
-% #font#mbfam#font#mrfam%
-% \fi\fi}
-
\def\font_helpers_set_math_family_bold_a#font#mbfam#mrfam%
{\ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
\lastnamedcs #font#mbfam\font \else
@@ -161,9 +132,15 @@
\let\defaultfontclass\fontclass % else truefontname falls back on the wrong one
\let\savedfontbody\fontbody
\let\fontfamily#familytag%
- \let\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree\font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam%
- \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam%
- \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam%
+ \let\mathsizesuffix\mathscriptscriptsuffix\let\fontface\!!plusthree
+ \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% defines
+ \font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam% enables
+ \let\mathsizesuffix\mathscriptsuffix \let\fontface\!!plustwo
+ \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% defines
+ \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam% enables
+ \let\mathsizesuffix\mathtextsuffix \let\fontface\!!plusone
+ \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% defines
+ \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam% enables
\let\mathsizesuffix\empty \let\fontface\!!zerocount
\let\fontbody\savedfontbody
\let\defaultfontclass\savedfontclass
@@ -203,9 +180,8 @@
\font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam%
\fi}
-%D It can happen that we use a bodyfont with no math in which case
-%D we have a problem with setting the global bodyfont size in the
-%D page builder. For instance in:
+%D It can happen that we use a bodyfont with no math in which case we have a problem
+%D with setting the global bodyfont size in the page builder. For instance in:
%D
%D \starttext
%D \definetypeface[test][rm][serif][pagella][default]
@@ -213,9 +189,9 @@
%D test
%D \stoptext
%D
-%D This is why we need the check. At the cost of some extra checking we gain a little
-%D in restoring global states and, what's more important, we get rid of large math parameter
-%D push/pop in tracingall when not needed.
+%D This is why we need the check. At the cost of some extra checking we gain a
+%D little in restoring global states and, what's more important, we get rid of large
+%D math parameter push/pop in tracingall when not needed.
\def\font_helpers_preset_math_family_indeed#fam#familytag%
{\expandafter\let\expandafter\v_font_math_one\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname
@@ -235,13 +211,14 @@
\let\font_helpers_reset_fontclass_math_families\gobbleoneargument
-% It would be nice if characters could be defined in a neutral way (say fam 255) and
-% be mapped to a real family during noad list construction. However, this changes
-% tex in critical places so for the moment we simulate this using manipulation.
-
-% For tracing purposes we use three families but in l2r mode 1 and 2 are copies of 0
-% while in rl mode 0 is a copy of 1. There is no real overhead involved in this. This
-% also permits different font definitions for normal and mixed.
+%D It would be nice if characters could be defined in a neutral way (say fam 255)
+%D and be mapped to a real family during noad list construction. However, this
+%D changes tex in critical places so for the moment we simulate this using
+%D manipulation.
+%D
+%D For tracing purposes we use three families but in l2r mode 1 and 2 are copies of
+%D 0 while in rl mode 0 is a copy of 1. There is no real overhead involved in this.
+%D This also permits different font definitions for normal and mixed.
\let\m_font_class_direction\empty
\let\m_font_class_features \empty
@@ -439,10 +416,10 @@
\font_helpers_synchronize_math_bold_strategy
\to \everymathematics
-% Bold is somewhat special as we might want both full-bold-math mixed
-% regular-math, as well as automatic adaption to outer bold (in titles
-% and inline text bold) so we will need explicit switches as well as
-% an automatic one. (We will use lucida as an example.)
+%D Bold is somewhat special as we might want both full-bold-math mixed regular-math,
+%D as well as automatic adaption to outer bold (in titles and inline text bold) so
+%D we will need explicit switches as well as an automatic one. (We will use lucida
+%D as an example.)
\ifdefined\mathdefault \else \let\mathdefault\relax \fi
diff --git a/tex/context/base/mkiv/font-ocl.lua b/tex/context/base/mkiv/font-ocl.lua
index 2ecf1ba42..b3f368836 100644
--- a/tex/context/base/mkiv/font-ocl.lua
+++ b/tex/context/base/mkiv/font-ocl.lua
@@ -1,6 +1,6 @@
if not modules then modules = { } end modules ['font-ocl'] = {
version = 1.001,
- comment = "companion to font-otf.lua (context)",
+ comment = "companion to font-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
diff --git a/tex/context/base/mkiv/font-odk.lua b/tex/context/base/mkiv/font-odk.lua
deleted file mode 100644
index c34efc120..000000000
--- a/tex/context/base/mkiv/font-odk.lua
+++ /dev/null
@@ -1,904 +0,0 @@
--- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
--- We keep the original around for a while so that we can check it --
--- when the above code does it wrong (data tables are not included). --
--- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-
--- author : Kai Eigner, TAT Zetwerk
--- copyright : TAT Zetwerk
--- comment : see font-odv.lua for current implementation
-
--- local state = attributes.private('state')
--- local sylnr = attributes.private('syllabe')
---
--- local function install_dev(tfmdata)
--- local features = tfmdata.resources.features
--- local sequences = tfmdata.resources.sequences
---
--- local insertpos = 1
--- for s=1,#sequences do -- classify chars
--- for k in pairs(basic_shaping_forms) do
--- if sequences[s].features and ( sequences[s].features[k] or sequences[s].features.locl ) then insertpos = s + 1 end
--- end
--- end
---
--- features.gsub["dev2_reorder_matras"] = { ["dev2"] = { ["dflt"] = true } }
--- features.gsub["dev2_reorder_reph"] = { ["dev2"] = { ["dflt"] = true } }
--- features.gsub["dev2_reorder_pre_base_reordering_consonants"] = { ["dev2"] = { ["dflt"] = true } }
--- features.gsub["remove_joiners"] = { ["deva"] = { ["dflt"] = true }, ["dev2"] = { ["dflt"] = true } }
---
--- local sequence_dev2_reorder_matras = {
--- chain = 0,
--- features = { dev2_reorder_matras = { dev2 = { dflt = true } } },
--- flags = { false, false, false, false },
--- name = "dev2_reorder_matras",
--- subtables = { "dev2_reorder_matras" },
--- type = "dev2_reorder_matras",
--- }
--- local sequence_dev2_reorder_reph = {
--- chain = 0,
--- features = { dev2_reorder_reph = { dev2 = { dflt = true } } },
--- flags = { false, false, false, false },
--- name = "dev2_reorder_reph",
--- subtables = { "dev2_reorder_reph" },
--- type = "dev2_reorder_reph",
--- }
--- local sequence_dev2_reorder_pre_base_reordering_consonants = {
--- chain = 0,
--- features = { dev2_reorder_pre_base_reordering_consonants = { dev2 = { dflt = true } } },
--- flags = { false, false, false, false },
--- name = "dev2_reorder_pre_base_reordering_consonants",
--- subtables = { "dev2_reorder_pre_base_reordering_consonants" },
--- type = "dev2_reorder_pre_base_reordering_consonants",
--- }
--- local sequence_remove_joiners = {
--- chain = 0,
--- features = { remove_joiners = { deva = { dflt = true }, dev2 = { dflt = true } } },
--- flags = { false, false, false, false },
--- name = "remove_joiners",
--- subtables = { "remove_joiners" },
--- type = "remove_joiners",
--- }
--- table.insert(sequences, insertpos, sequence_dev2_reorder_pre_base_reordering_consonants)
--- table.insert(sequences, insertpos, sequence_dev2_reorder_reph)
--- table.insert(sequences, insertpos, sequence_dev2_reorder_matras)
--- table.insert(sequences, insertpos, sequence_remove_joiners)
--- end
---
--- local function deva_reorder(head,start,stop,font,attr)
--- local tfmdata = fontdata[font]
--- local lookuphash = tfmdata.resources.lookuphash
--- local sequences = tfmdata.resources.sequences
---
--- if not lookuphash["remove_joiners"] then install_dev(tfmdata) end --install Devanagari-features
---
--- local sharedfeatures = tfmdata.shared.features
--- sharedfeatures["remove_joiners"] = true
--- local datasets = otf.dataset(tfmdata,font,attr)
---
--- lookuphash["remove_joiners"] = { [0x200C] = true, [0x200D] = true }
---
--- local current, n, base, firstcons, lastcons, basefound = start, start.next, nil, nil, nil, false
--- local reph, vattu = false, false
--- for s=1,#sequences do
--- local dataset = datasets[s]
--- featurevalue = dataset and dataset[1]
--- if featurevalue and dataset[4] == "rphf" then reph = true end
--- if featurevalue and dataset[4] == "blwf" then vattu = true end
--- end
--- if ra[start.char] and halant[n.char] and reph then -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants
--- if n == stop then return head, stop end
--- if zwj[n.next.char] then
--- current = start
--- else
--- current = n.next
--- set_attribute(start,state,5) -- rphf
--- end
--- end
---
--- if nbsp[current.char] then --Stand Alone cluster
--- if current == stop then
--- stop = stop.prev
--- head = node.remove(head, current)
--- node.free(current)
--- return head, stop
--- else
--- base, firstcons, lastcons = current, current, current
--- current = current.next
--- if current ~= stop then
--- if nukta[current.char] then current = current.next end
--- if zwj[current.char] then
--- if current ~= stop and current.next ~= stop and halant[current.next.char] then
--- current = current.next
--- local tmp = current.next.next
--- local changestop = current.next == stop
--- local tempcurrent = node.copy(current.next)
--- tempcurrent.next = node.copy(current)
--- tempcurrent.next.prev = tempcurrent
--- set_attribute(tempcurrent,state,8) --blwf
--- tempcurrent = nodes.handlers.characters(tempcurrent)
--- unset_attribute(tempcurrent,state)
--- if current.next.char == tempcurrent.char then
--- node.flush_list(tempcurrent)
--- local n = node.copy(current)
--- current.char = dotted_circle
--- head = node.insert_after(head, current, n)
--- else
--- current.char = tempcurrent.char -- (assumes that result of blwf consists of one node)
--- local freenode = current.next
--- current.next = tmp
--- tmp.prev = current
--- node.free(freenode)
--- node.flush_list(tempcurrent)
--- if changestop then stop = current end
--- end
--- end
--- end
--- end
--- end
--- end
---
--- while not basefound do -- find base consonant
--- if consonant[current.char] then
--- set_attribute(current, state, 6) -- half
--- if not firstcons then firstcons = current end
--- lastcons = current
--- if not base then
--- base = current
--- else --check whether consonant has below-base (or post-base) form
--- local baseform = true
--- for s=1,#sequences do
--- local sequence = sequences[s]
--- local dataset = datasets[s]
--- featurevalue = dataset and dataset[1]
--- if featurevalue and dataset[4] == "blwf" then
--- local subtables = sequence.subtables
--- for i=1,#subtables do
--- local lookupname = subtables[i]
--- local lookupcache = lookuphash[lookupname]
--- if lookupcache then
--- local lookupmatch = lookupcache[current.char]
--- if lookupmatch then
--- set_attribute(current, state, 8) -- blwf
--- baseform = false
--- end
--- end
--- end
--- end
--- end
--- if baseform then base = current end
--- end
--- end
--- basefound = current == stop
--- current = current.next
--- end
--- if base ~= lastcons then -- if base consonant is not last one then move halant from base consonant to last one
--- n = base.next
--- if nukta[n.char] then n = n.next end
--- if halant[n.char] then
--- if lastcons ~= stop then
--- local ln = lastcons.next
--- if nukta[ln.char] then lastcons = ln end
--- end
--- local np, nn, ln = n.prev, n.next, lastcons.next
--- np.next = n.next
--- nn.prev = n.prev
--- lastcons.next = n
--- if ln then ln.prev = n end
--- n.next = ln
--- n.prev = lastcons
--- if lastcons == stop then stop = n end
--- end
--- end
---
--- n = start.next
--- if ra[start.char] and halant[n.char] and not ( n ~= stop and ( zwj[n.next.char] or zwnj[n.next.char] ) ) then -- if syllable starts with Ra + H then move this combination so that it follows either: the post-base 'matra' (if any) or the base consonant
--- local matra = base
--- if base ~= stop and dependent_vowel[base.next.char] then matra = base.next end
--- local sp, nn, mn = start.prev, n.next, matra.next
--- if sp then sp.next = nn end
--- nn.prev = sp
--- matra.next = start
--- start.prev = matra
--- n.next = mn
--- if mn then mn.prev = n end
--- if head == start then head = nn end
--- start = nn
--- if matra == stop then stop = n end
--- end
---
--- local current = start
--- while current ~= stop do
--- if halant[current.next.char] and current.next ~= stop and zwnj[current.next.next.char] then unset_attribute(current, state) end
--- current = current.next
--- end
---
--- if has_attribute(base, state) and base ~= stop and halant[base.next.char] and not ( base.next ~= stop and zwj[base.next.next.char] ) then unset_attribute(base, state) end
---
--- local current, allreordered, moved = start, false, { [base] = true }
--- local a, b, p, bn = base, base, base, base.next
--- if base ~= stop and nukta[bn.char] then a, b, p = bn, bn, bn end
--- while not allreordered do
--- local c, n, l = current, current.next, nil --current is always consonant
--- if c ~= stop and nukta[n.char] then c = n n = n.next end
--- if c ~= stop and halant[n.char] then c = n n = n.next end
--- while c ~= stop and dependent_vowel[n.char] do c = n n = n.next end
--- if c ~= stop and vowel_modifier[n.char] then c = n n = n.next end
--- if c ~= stop and stress_tone_mark[n.char] then c = n n = n.next end
--- local bp, cn = firstcons.prev, current.next
--- while cn ~= c.next do -- move pre-base matras...
--- if pre_mark[cn.char] then
--- if bp then bp.next = cn end
--- cn.prev.next = cn.next
--- if cn.next then cn.next.prev = cn.prev end
--- if cn == stop then stop = cn.prev end
--- cn.prev = bp
--- cn.next = firstcons
--- firstcons.prev = cn
--- if firstcons == start then
--- if head == start then head = cn end
--- start = cn
--- end
--- break
--- end
--- cn = cn.next
--- end
--- allreordered = c == stop
--- current = c.next
--- end
---
--- if reph or vattu then
--- local current, cns = start, nil
--- while current ~= stop do
--- local c, n = current, current.next
--- if ra[current.char] and halant[n.char] then
--- c, n = n, n.next
--- local b, bn = base, base
--- while bn ~= stop do
--- if dependent_vowel[bn.next.char] then b = bn.next end
--- bn = bn.next
--- end
--- if has_attribute(current,state,attribute) == 5 then -- position Reph (Ra + H) after post-base 'matra' (if any) since these become marks on the 'matra', not on the base glyph
--- if b ~= current then
--- if current == start then
--- if head == start then head = n end
--- start = n
--- end
--- if b == stop then stop = c end
--- if current.prev then current.prev.next = n end
--- if n then n.prev = current.prev end
--- c.next = b.next
--- if b.next then b.next.prev = c end
--- b.next = current
--- current.prev = b
--- end
--- elseif cns and cns.next ~= current then -- position below-base Ra (vattu) following the consonants on which it is placed (either the base consonant or one of the pre-base consonants)
--- local cp, cnsn = current.prev, cns.next
--- if cp then cp.next = n end
--- if n then n.prev = cp end
--- cns.next = current
--- current.prev = cns
--- c.next = cnsn
--- if cnsn then cnsn.prev = c end
--- if c == stop then stop = cp break end
--- current = n.prev
--- end
--- elseif consonant[current.char] or nbsp[current.char] then
--- cns = current
--- if halant[cns.next.char] then cns = cns.next end
--- end
--- current = current.next
--- end
--- end
---
--- if nbsp[base.char] then
--- head = node.remove(head, base)
--- node.free(base)
--- end
---
--- return head, stop
--- end
---
--- function dev2_reorder_matras(start,kind,lookupname,replacement)
--- local current = start
--- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do
--- if halant[current.char] and not has_attribute(current, state) then
--- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end
--- local sn = start.next
--- start.next.prev = start.prev
--- if start.prev then start.prev.next = start.next end
--- if current.next then current.next.prev = start end
--- start.next = current.next
--- current.next = start
--- start.prev = current
--- start = sn
--- break
--- end
--- current = current.next
--- end
--- return start, true
--- end
---
--- function dev2_reorder_reph(start,kind,lookupname,replacement)
--- local current, sn = start.next, nil
--- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do --step 2
--- if halant[current.char] and not has_attribute(current, state) then
--- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end
--- sn = start.next
--- start.next.prev = start.prev
--- if start.prev then start.prev.next = start.next end
--- if current.next then current.next.prev = start end
--- start.next = current.next
--- current.next = start
--- start.prev = current
--- start = sn
--- break
--- end
--- current = current.next
--- end
--- if not sn then
--- current = start.next
--- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do --step 4
--- if has_attribute(current, state) == 9 then --post-base
--- sn = start.next
--- start.next.prev = start.prev
--- if start.prev then start.prev.next = start.next end
--- start.prev = current.prev
--- current.prev.next = start
--- start.next = current
--- current.prev = start
--- start = sn
--- break
--- end
--- current = current.next
--- end
--- end
--- if not sn then
--- current = start.next
--- local c = nil
--- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do --step 5
--- if not c and ( above_mark[current.char] or below_mark[current.char] or post_mark[current.char] ) and ReorderClass[current.char] ~= "after subscript" then c = current end
--- current = current.next
--- end
--- if c then
--- sn = start.next
--- start.next.prev = start.prev
--- if start.prev then start.prev.next = start.next end
--- start.prev = c.prev
--- c.prev.next = start
--- start.next = c
--- c.prev = start
--- start = sn
--- end
--- end
--- if not sn then
--- current = start
--- while current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) do --step 6
--- current = current.next
--- end
--- if start ~= current then
--- sn = start.next
--- start.next.prev = start.prev
--- if start.prev then start.prev.next = start.next end
--- if current.next then current.next.prev = start end
--- start.next = current.next
--- current.next = start
--- start.prev = current
--- start = sn
--- end
--- end
--- return start, true
--- end
---
--- function dev2_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement)
--- local current, sn = start, nil
--- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do
--- if halant[current.char] and not has_attribute(current, state) then
--- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == start.font and has_attribute(current.next, sylnr) == has_attribute(start, sylnr) and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end
--- sn = start.next
--- start.next.prev = start.prev
--- if start.prev then start.prev.next = start.next end
--- if current.next then current.next.prev = start end
--- start.next = current.next
--- current.next = start
--- start.prev = current
--- start = sn
--- break
--- end
--- current = current.next
--- end
--- if not sn then
--- current = start.next
--- while current and current.id == glyph and current.subtype<256 and current.font == start.font and has_attribute(current, sylnr) == has_attribute(start, sylnr) do
--- if not consonant[current.char] and has_attribute(current, state) then --main
--- sn = start.next
--- start.next.prev = start.prev
--- if start.prev then start.prev.next = start.next end
--- start.prev = current.prev
--- current.prev.next = start
--- start.next = current
--- current.prev = start
--- start = sn
--- break
--- end
--- current = current.next
--- end
--- end
--- return start, true
--- end
---
--- function remove_joiners(start,kind,lookupname,replacement)
--- local stop = start.next
--- while stop and stop.id == glyph and stop.subtype<256 and stop.font == start.font and (zwj[stop.char] or zwnj[stop.char]) do stop = stop.next end
--- if stop then stop.prev.next = nil stop.prev = start.prev end
--- if start.prev then start.prev.next = stop end
--- node.flush_list(start)
--- return stop, true
--- end
---
--- local function dev2_reorder(head,start,stop,font,attr)
--- local tfmdata = fontdata[font]
--- local lookuphash = tfmdata.resources.lookuphash
--- local sequences = tfmdata.resources.sequences
---
--- if not lookuphash["remove_joiners"] then install_dev(tfmdata) end --install Devanagari-features
---
--- local sharedfeatures = tfmdata.shared.features
--- sharedfeatures["dev2_reorder_matras"] = true
--- sharedfeatures["dev2_reorder_reph"] = true
--- sharedfeatures["dev2_reorder_pre_base_reordering_consonants"] = true
--- sharedfeatures["remove_joiners"] = true
--- local datasets = otf.dataset(tfmdata,font,attr)
---
--- local reph, pre_base_reordering_consonants = false, nil
--- local halfpos, basepos, subpos, postpos = nil, nil, nil, nil
--- local locl = { }
---
--- for s=1,#sequences do -- classify chars
--- local sequence = sequences[s]
--- local dataset = datasets[s]
--- featurevalue = dataset and dataset[1]
--- if featurevalue and dataset[4] then
--- local subtables = sequence.subtables
--- for i=1,#subtables do
--- local lookupname = subtables[i]
--- local lookupcache = lookuphash[lookupname]
--- if lookupcache then
--- if dataset[4] == "rphf" then
--- if dataset[3] ~= 0 then --rphf is result of of chain
--- else
--- reph = lookupcache[0x0930] and lookupcache[0x0930][0x094D] and lookupcache[0x0930][0x094D]["ligature"]
--- end
--- end
--- if dataset[4] == "pref" and not pre_base_reordering_consonants then
--- for k, v in pairs(lookupcache[0x094D]) do
--- pre_base_reordering_consonants[k] = v and v["ligature"] --ToDo: reph might also be result of chain
--- end
--- end
--- local current = start
--- while current ~= stop.next do
--- if dataset[4] == "locl" then locl[current] = lookupcache[current.char] end --ToDo: locl might also be result of chain
--- if current ~= stop then
--- local c, n = locl[current] or current.char, locl[current.next] or current.next.char
--- if dataset[4] == "rphf" and lookupcache[c] and lookupcache[c][n] then --above-base: rphf Consonant + Halant
--- if current.next ~= stop and ( zwj[current.next.next.char] or zwnj[current.next.next.char] ) then --ZWJ and ZWNJ prevent creation of reph
--- current = current.next
--- elseif current == start then
--- set_attribute(current,state,5)
--- end
--- current = current.next
--- end
--- if dataset[4] == "half" and lookupcache[c] and lookupcache[c][n] then --half forms: half Consonant + Halant
--- if current.next ~= stop and zwnj[current.next.next.char] then --ZWNJ prevent creation of half
--- current = current.next
--- else
--- set_attribute(current,state,6)
--- if not halfpos then halfpos = current end
--- end
--- current = current.next
--- end
--- if dataset[4] == "pref" and lookupcache[c] and lookupcache[c][n] then --pre-base: pref Halant + Consonant
--- set_attribute(current,state,7)
--- set_attribute(current.next,state,7)
--- current = current.next
--- end
--- if dataset[4] == "blwf" and lookupcache[c] and lookupcache[c][n] then --below-base: blwf Halant + Consonant
--- set_attribute(current,state,8)
--- set_attribute(current.next,state,8)
--- current = current.next
--- subpos = current
--- end
--- if dataset[4] == "pstf" and lookupcache[c] and lookupcache[c][n] then --post-base: pstf Halant + Consonant
--- set_attribute(current,state,9)
--- set_attribute(current.next,state,9)
--- current = current.next
--- postpos = current
--- end
--- end
--- current = current.next
--- end
--- end
--- end
--- end
--- end
---
--- lookuphash["dev2_reorder_matras"] = pre_mark
--- lookuphash["dev2_reorder_reph"] = { [reph] = true }
--- lookuphash["dev2_reorder_pre_base_reordering_consonants"] = pre_base_reordering_consonants or { }
--- lookuphash["remove_joiners"] = { [0x200C] = true, [0x200D] = true }
---
--- local current, base, firstcons = start, nil, nil
--- if has_attribute(start,state) == 5 then current = start.next.next end -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants
---
--- if current ~= stop.next and nbsp[current.char] then --Stand Alone cluster
--- if current == stop then
--- stop = stop.prev
--- head = node.remove(head, current)
--- node.free(current)
--- return head, stop
--- else
--- base = current
--- current = current.next
--- if current ~= stop then
--- if nukta[current.char] then current = current.next end
--- if zwj[current.char] then
--- if current ~= stop and current.next ~= stop and halant[current.next.char] then
--- current = current.next
--- local tmp = current.next.next
--- local changestop = current.next == stop
--- current.next.next = nil
--- set_attribute(current,state,7) --pref
--- current = nodes.handlers.characters(current)
--- set_attribute(current,state,8) --blwf
--- current = nodes.handlers.characters(current)
--- set_attribute(current,state,9) --pstf
--- current = nodes.handlers.characters(current)
--- unset_attribute(current,state)
--- if halant[current.char] then
--- current.next.next = tmp
--- local nc = node.copy(current)
--- current.char = dotted_circle
--- head = node.insert_after(head, current, nc)
--- else
--- current.next = tmp -- (assumes that result of pref, blwf, or pstf consists of one node)
--- if changestop then stop = current end
--- end
--- end
--- end
--- end
--- end
--- else --not Stand Alone cluster
--- while current ~= stop.next do -- find base consonant
--- if consonant[current.char] and not ( current ~= stop and halant[current.next.char] and current.next ~= stop and zwj[current.next.next.char] ) then
--- if not firstcons then firstcons = current end
--- if not ( has_attribute(current, state) == 7 or has_attribute(current, state) == 8 or has_attribute(current, state) == 9 ) then base = current end --check whether consonant has below-base or post-base form or is pre-base reordering Ra
--- end
--- current = current.next
--- end
--- if not base then
--- base = firstcons
--- end
--- end
---
--- if not base then
--- if has_attribute(start, state) == 5 then unset_attribute(start, state) end
--- return head, stop
--- else
--- if has_attribute(base, state) then unset_attribute(base, state) end
--- basepos = base
--- end
--- if not halfpos then halfpos = base end
--- if not subpos then subpos = base end
--- if not postpos then postpos = subpos or base end
---
--- --Matra characters are classified and reordered by which consonant in a conjunct they have affinity for
--- local moved = { }
--- current = start
--- while current ~= stop.next do
--- local char, target, cn = locl[current] or current.char, nil, current.next
--- if not moved[current] and dependent_vowel[char] then
--- if pre_mark[char] then -- Before first half form in the syllable
--- moved[current] = true
--- if current.prev then current.prev.next = current.next end
--- if current.next then current.next.prev = current.prev end
--- if current == stop then stop = current.prev end
--- if halfpos == start then
--- if head == start then head = current end
--- start = current
--- end
--- if halfpos.prev then halfpos.prev.next = current end
--- current.prev = halfpos.prev
--- halfpos.prev = current
--- current.next = halfpos
--- halfpos = current
--- elseif above_mark[char] then -- After main consonant
--- target = basepos
--- if subpos == basepos then subpos = current end
--- if postpos == basepos then postpos = current end
--- basepos = current
--- elseif below_mark[char] then -- After subjoined consonants
--- target = subpos
--- if postpos == subpos then postpos = current end
--- subpos = current
--- elseif post_mark[char] then -- After post-form consonant
--- target = postpos
--- postpos = current
--- end
--- if ( above_mark[char] or below_mark[char] or post_mark[char] ) and current.prev ~= target then
--- if current.prev then current.prev.next = current.next end
--- if current.next then current.next.prev = current.prev end
--- if current == stop then stop = current.prev end
--- if target.next then target.next.prev = current end
--- current.next = target.next
--- target.next = current
--- current.prev = target
--- end
--- end
--- current = cn
--- end
---
--- --Reorder marks to canonical order: Adjacent nukta and halant or nukta and vedic sign are always repositioned if necessary, so that the nukta is first.
--- local current, c = start, nil
--- while current ~= stop do
--- if halant[current.char] or stress_tone_mark[current.char] then
--- if not c then c = current end
--- else
--- c = nil
--- end
--- if c and nukta[current.next.char] then
--- if head == c then head = current.next end
--- if stop == current.next then stop = current end
--- if c.prev then c.prev.next = current.next end
--- current.next.prev = c.prev
--- current.next = current.next.next
--- if current.next.next then current.next.next.prev = current end
--- c.prev = current.next
--- current.next.next = c
--- end
--- if stop == current then break end
--- current = current.next
--- end
---
--- if nbsp[base.char] then
--- head = node.remove(head, base)
--- node.free(base)
--- end
---
--- return head, stop
--- end
---
--- function fonts.analyzers.methods.deva(head,font,attr)
--- local orighead = head
--- local current, start, done = head, true, false
--- while current do
--- if current.id == glyph and current.subtype<256 and current.font == font then
--- done = true
--- local syllablestart, syllableend = current, nil
---
--- local c = current --Checking Stand Alone cluster (this behavior is copied from dev2)
--- if ra[c.char] and c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] and c.next.next and c.next.next.id == glyph and c.next.next.subtype<256 and c.next.next.font == font then c = c.next.next end
--- if nbsp[c.char] and ( not current.prev or current.prev.id ~= glyph or current.prev.subtype>=256 or current.prev.font ~= font or
--- ( not consonant[current.prev.char] and not independent_vowel[current.prev.char] and not dependent_vowel[current.prev.char] and
--- not vowel_modifier[current.prev.char] and not stress_tone_mark[current.prev.char] and not nukta[current.prev.char] and not halant[current.prev.char] )
--- ) then --Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
--- local n = c.next
--- if n and n.id == glyph and n.subtype<256 and n.font == font then
--- local ni = n.next
--- if ( zwj[n.char] or zwnj[n.char] ) and ni and ni.id == glyph and ni.subtype<256 and ni.font == font then n = ni ni = ni.next end
--- if halant[n.char] and ni and ni.id == glyph and ni.subtype<256 and ni.font == font and consonant[ni.char] then c = ni end
--- end
--- while c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] do c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
--- current = c.next
--- syllableend = c
--- if syllablestart ~= syllableend then
--- head, current = deva_reorder(head, syllablestart,syllableend,font,attr)
--- current = current.next
--- end
--- elseif consonant[current.char] then -- syllable containing consonant
--- prevc = true
--- while prevc do
--- prevc = false
--- local n = current.next
--- if n and n.id == glyph and n.subtype<256 and n.font == font and nukta[n.char] then n = n.next end
--- if n and n.id == glyph and n.subtype<256 and n.font == font and halant[n.char] then
--- local n = n.next
--- if n and n.id == glyph and n.subtype<256 and n.font == font and ( zwj[n.char] or zwnj[n.char] ) then n = n.next end
--- if n and n.id == glyph and n.subtype<256 and n.font == font and consonant[n.char] then
--- prevc = true
--- current = n
--- end
--- end
--- end
--- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == font and nukta[current.next.char] then current = current.next end -- nukta (not specified in Microsft Devanagari OpenType specification)
--- syllableend = current
--- current = current.next
--- if current and current.id == glyph and current.subtype<256 and current.font == font and halant[current.char] then -- syllable containing consonant without vowels: {C + [Nukta] + H} + C + H
--- if current.next and current.next.id == glyph and current.next.subtype<256 and current.next.font == font and ( zwj[current.next.char] or zwnj[current.next.char] ) then current = current.next end
--- syllableend = current
--- current = current.next
--- else -- syllable containing consonant with vowels: {C + [Nukta] + H} + C + [M] + [VM] + [SM]
--- if current and current.id == glyph and current.subtype<256 and current.font == font and dependent_vowel[current.char] then
--- syllableend = current
--- current = current.next
--- end
--- if current and current.id == glyph and current.subtype<256 and current.font == font and vowel_modifier[current.char] then
--- syllableend = current
--- current = current.next
--- end
--- if current and current.id == glyph and current.subtype<256 and current.font == font and stress_tone_mark[current.char] then
--- syllableend = current
--- current = current.next
--- end
--- end
--- if syllablestart ~= syllableend then
--- head, current = deva_reorder(head,syllablestart,syllableend,font,attr)
--- current = current.next
--- end
--- elseif current.id == glyph and current.subtype<256 and current.font == font and independent_vowel[current.char] then -- syllable without consonants: VO + [VM] + [SM]
--- syllableend = current
--- current = current.next
--- if current and current.id == glyph and current.subtype<256 and current.font == font and vowel_modifier[current.char] then
--- syllableend = current
--- current = current.next
--- end
--- if current and current.id == glyph and current.subtype<256 and current.font == font and stress_tone_mark[current.char] then
--- syllableend = current
--- current = current.next
--- end
--- else -- Syntax error
--- if pre_mark[current.char] or above_mark[current.char] or below_mark[current.char] or post_mark[current.char] then
--- local n = node.copy(current)
--- if pre_mark[current.char] then
--- n.char = dotted_circle
--- else
--- current.char = dotted_circle
--- end
--- head, current = node.insert_after(head, current, n)
--- end
--- current = current.next
--- end
--- else
--- current = current.next
--- end
--- start = false
--- end
---
--- return head, done
--- end
---
--- function fonts.analyzers.methods.dev2(head,font,attr)
--- local current, start, done, syl_nr = head, true, false, 0
--- while current do
--- local syllablestart, syllableend = nil, nil
--- if current.id == glyph and current.subtype<256 and current.font == font then
--- syllablestart = current
--- done = true
--- local c, n = current, current.next
--- if ra[current.char] and n and n.id == glyph and n.subtype<256 and n.font == font and halant[n.char] and n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font then c = n.next end
--- if independent_vowel[c.char] then --Vowel-based syllable: [Ra+H]+V+[N]+[<[<ZWJ|ZWNJ>]+H+C|ZWJ+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
--- n = c.next
--- local ni, nii = nil, nil
--- if n and n.id == glyph and n.subtype<256 and n.font == font and nukta[n.char] then n = n.next end
--- if n and n.id == glyph and n.subtype<256 and n.font == font then local ni = n.next end
--- if ni and ni.id == glyph and ni.subtype<256 and ni.font == font and ni.next and ni.next.id == glyph and ni.next.subtype<256 and ni.next.font == font then
--- nii = ni.next
--- if zwj[ni.char] and consonant[nii.char] then
--- c = nii
--- elseif (zwj[ni.char] or zwnj[ni.char]) and halant[nii.char] and nii.next and nii.next.id == glyph and nii.next.subtype<256 and nii.next.font == font and consonant[nii.next.char] then
--- c = nii.next
--- end
--- end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
--- current = c
--- syllableend = c
--- elseif nbsp[c.char] and ( not current.prev or current.prev.id ~= glyph or current.prev.subtype>=256 or current.prev.font ~= font or
--- ( not consonant[current.prev.char] and not independent_vowel[current.prev.char] and not dependent_vowel[current.prev.char] and
--- not vowel_modifier[current.prev.char] and not stress_tone_mark[current.prev.char] and not nukta[current.prev.char] and not halant[current.prev.char] )
--- ) then --Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
--- n = c.next
--- if n and n.id == glyph and n.subtype<256 and n.font == font then
--- local ni = n.next
--- if ( zwj[n.char] or zwnj[n.char] ) and ni and ni.id == glyph and ni.subtype<256 and ni.font == font then n = ni ni = ni.next end
--- if halant[n.char] and ni and ni.id == glyph and ni.subtype<256 and ni.font == font and consonant[ni.char] then c = ni end
--- end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
--- current = c
--- syllableend = c
--- elseif consonant[current.char] then --Consonant syllable: {C+[N]+<H+[<ZWNJ|ZWJ>]|<ZWNJ|ZWJ>+H>} + C+[N]+[A] + [< H+[<ZWNJ|ZWJ>] | {M}+[N]+[H]>]+[SM]+[(VD)]
--- c = current
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
--- n = c
--- while n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and ( halant[n.next.char] or zwnj[n.next.char] or zwj[n.next.char] ) do
--- if halant[n.next.char] then
--- n = n.next
--- if n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and ( zwnj[n.next.char] or zwj[n.next.char] ) then n = n.next end
--- else
--- if n.next.next and n.next.next.id == glyph and n.next.next.subtype<256 and n.next.next.font == font and halant[n.next.next.char] then n = n.next.next end
--- end
--- if n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and consonant[n.next.char] then
--- n = n.next
--- if n.next and n.next.id == glyph and n.next.subtype<256 and n.next.font == font and nukta[n.next.char] then n = n.next end
--- c = n
--- else
--- break
--- end
--- end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and anudatta[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then
--- c = c.next
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and ( zwnj[c.next.char] or zwj[c.next.char] ) then c = c.next end
--- else
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and dependent_vowel[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and nukta[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and halant[c.next.char] then c = c.next end
--- end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and vowel_modifier[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
--- if c.next and c.next.id == glyph and c.next.subtype<256 and c.next.font == font and stress_tone_mark[c.next.char] then c = c.next end
--- current = c
--- syllableend = c
--- end
--- end
---
--- if syllableend then
--- syl_nr = syl_nr + 1
--- c = syllablestart
--- while c ~= syllableend.next do
--- set_attribute(c,sylnr,syl_nr)
--- c = c.next
--- end
--- end
--- if syllableend and syllablestart ~= syllableend then
--- head, current = dev2_reorder(head,syllablestart,syllableend,font,attr)
--- end
---
--- if not syllableend and not has_attribute(current, state) and current.id == glyph and current.subtype<256 and current.font == font then -- Syntax error
--- if pre_mark[current.char] or above_mark[current.char] or below_mark[current.char] or post_mark[current.char] then
--- local n = node.copy(current)
--- if pre_mark[current.char] then
--- n.char = dotted_circle
--- else
--- current.char = dotted_circle
--- end
--- head, current = node.insert_after(head, current, n)
--- end
--- end
---
--- start = false
--- current = current.next
--- end
---
--- return head, done
--- end
---
--- function otf.handlers.dev2_reorder_matras(start,kind,lookupname,replacement)
--- return dev2_reorder_matras(start,kind,lookupname,replacement)
--- end
---
--- function otf.handlers.dev2_reorder_reph(start,kind,lookupname,replacement)
--- return dev2_reorder_reph(start,kind,lookupname,replacement)
--- end
---
--- function otf.handlers.dev2_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement)
--- return dev2_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement)
--- end
---
--- function otf.handlers.remove_joiners(start,kind,lookupname,replacement)
--- return remove_joiners(start,kind,lookupname,replacement)
--- end
diff --git a/tex/context/base/mkiv/font-odv.lua b/tex/context/base/mkiv/font-odv.lua
deleted file mode 100644
index 345b17a52..000000000
--- a/tex/context/base/mkiv/font-odv.lua
+++ /dev/null
@@ -1,2380 +0,0 @@
-if not modules then modules = { } end modules ['font-odv'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv",
- author = "Kai Eigner, TAT Zetwerk / Hans Hagen, PRAGMA ADE",
- copyright = "TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- One day I'll speed this up ... char swapping and properties.
-
--- A few remarks:
---
--- This code is a partial rewrite of the code that deals with devanagari. The data and logic
--- is by Kai Eigner and based based on Microsoft's OpenType specifications for specific
--- scripts, but with a few improvements. More information can be found at:
---
--- deva: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/introO.mspx
--- dev2: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/intro.mspx
---
--- Rajeesh Nambiar provided patches for the malayalam variant. Thansk to feedback from
--- the mailing list some aspects could be improved.
---
--- As I touched nearly all code, reshuffled it, optimized a lot, etc. etc. (imagine how
--- much can get messed up in over a week work) it could be that I introduced bugs. There
--- is more to gain (esp in the functions applied to a range) but I'll do that when
--- everything works as expected. Kai's original code is kept in font-odk.lua as a reference
--- so blame me (HH) for bugs.
---
--- Interesting is that Kai managed to write this on top of the existing otf handler. Only a
--- few extensions were needed, like a few more analyzing states and dealing with changed
--- head nodes in the core scanner as that only happens here. There's a lot going on here
--- and it's only because I touched nearly all code that I got a bit of a picture of what
--- happens. For in-depth knowledge one needs to consult Kai.
---
--- The rewrite mostly deals with efficiency, both in terms of speed and code. We also made
--- sure that it suits generic use as well as use in ConTeXt. I removed some buglets but can
--- as well have messed up the logic by doing this. For this we keep the original around
--- as that serves as reference. Due to the lots of reshuffling glyphs quite some leaks
--- occur(red) but once I'm satisfied with the rewrite I'll weed them. I also integrated
--- initialization etc into the regular mechanisms.
---
--- In the meantime, we're down from 25.5-3.5=22 seconds to 17.7-3.5=14.2 seconds for a 100
--- page sample (mid 2012) with both variants so it's worth the effort. Some more speedup is
--- to be expected. Due to the method chosen it will never be real fast. If I ever become a
--- power user I'll have a go at some further speed up. I will rename some functions (and
--- features) once we don't need to check the original code. We now use a special subset
--- sequence for use inside the analyzer (after all we could can store this in the dataset
--- and save redundant analysis).
---
--- I might go for an array approach with respect to attributes (and reshuffling). Easier.
---
--- Some data will move to char-def.lua (some day).
---
--- Hans Hagen, PRAGMA-ADE, Hasselt NL
---
--- We could have c_nukta, c_halant, c_ra is we know that they are never used mixed within
--- one script .. yes or no?
---
--- Matras: according to Microsoft typography specifications "up to one of each type:
--- pre-, above-, below- or post- base", but that does not seem to be right. It could
--- become an option.
---
--- The next code looks weird anyway: the "and boolean" should move inside the if
--- or we should check differently (case vs successive).
---
--- local function ms_matra(c)
--- local prebase, abovebase, belowbase, postbase = true, true, true, true
--- local n = getnext(c)
--- while n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font do
--- local char = getchar(n)
--- if not dependent_vowel[char] then
--- break
--- elseif pre_mark[char] and prebase then
--- prebase = false
--- elseif above_mark[char] and abovebase then
--- abovebase = false
--- elseif below_mark[char] and belowbase then
--- belowbase = false
--- elseif post_mark[char] and postbase then
--- postbase = false
--- else
--- return c
--- end
--- c = getnext(c)
--- end
--- return c
--- end
-
--- todo: first test for font then for subtype
-
-local insert, imerge = table.insert, table.imerge
-local next = next
-
-local report_devanagari = logs.reporter("otf","devanagari")
-
-fonts = fonts or { }
-fonts.analyzers = fonts.analyzers or { }
-fonts.analyzers.methods = fonts.analyzers.methods or { node = { otf = { } } }
-
-local otf = fonts.handlers.otf
-
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
-
-local handlers = otf.handlers
-local methods = fonts.analyzers.methods
-
-local otffeatures = fonts.constructors.features.otf
-local registerotffeature = otffeatures.register
-
-local nuts = nodes.nuts
-local tonode = nuts.tonode
-local tonut = nuts.tonut
-
-local getnext = nuts.getnext
-local setnext = nuts.setnext
-local getprev = nuts.getprev
-local setprev = nuts.setprev
-local getid = nuts.getid
-local getchar = nuts.getchar
-local setchar = nuts.setchar
-local getfont = nuts.getfont
-local getsubtype = nuts.getsubtype
-local getprop = nuts.getprop
-local setprop = nuts.setprop
-
-local insert_node_after = nuts.insert_after
-local copy_node = nuts.copy
-local remove_node = nuts.remove
-local flush_list = nuts.flush_list
-local flush_node = nuts.flush_node
-
-local copyinjection = nodes.injections.copy -- KE: is this necessary? HH: probably not as positioning comes later and we rawget/set
-
-local unsetvalue = attributes.unsetvalue
-
-local fontdata = fonts.hashes.identifiers
-
-local a_state = attributes.private('state')
-local a_syllabe = attributes.private('syllabe')
-
-local dotted_circle = 0x25CC
-
-local states = fonts.analyzers.states -- not features
-
-local s_rphf = states.rphf
-local s_half = states.half
-local s_pref = states.pref
-local s_blwf = states.blwf
-local s_pstf = states.pstf
-
-local replace_all_nbsp = nil
-
-replace_all_nbsp = function(head) -- delayed definition
- replace_all_nbsp = typesetters and typesetters.characters and typesetters.characters.replacenbspaces or function(head)
- return head
- end
- return replace_all_nbsp(head)
-end
-
-local xprocesscharacters = nil
-
-if context then
- xprocesscharacters = function(head,font)
- xprocesscharacters = nodes.handlers.characters
- return xprocesscharacters(head,font)
- end
-else
- xprocesscharacters = function(head,font)
- xprocesscharacters = nodes.handlers.nodepass -- generic
- return xprocesscharacters(head,font)
- end
-end
-
-local function processcharacters(head,font)
- return tonut(xprocesscharacters(tonode(head)))
-end
-
--- local fontprocesses = fonts.hashes.processes
---
--- function processcharacters(head,font)
--- local processors = fontprocesses[font]
--- for i=1,#processors do
--- head = processors[i](head,font,0)
--- end
--- return head, true
--- end
-
--- In due time there will be entries here for scripts like Bengali, Gujarati,
--- Gurmukhi, Kannada, Malayalam, Oriya, Tamil, Telugu. Feel free to provide the
--- code points.
-
--- We can assume that script are not mixed in the source but if that is the case
--- we might need to have consonants etc per script and initialize a local table
--- pointing to the right one.
-
--- new, to be checked:
---
--- U+00978 : DEVANAGARI LETTER MARWARI DDA
--- U+00980 : BENGALI ANJI
--- U+00C00 : TELUGU SIGN COMBINING CANDRABINDU ABOVE
--- U+00C34 : TELUGU LETTER LLLA
--- U+00C81 : KANNADA SIGN CANDRABINDU
--- U+00D01 : MALAYALAM SIGN CANDRABINDU
--- U+00DE6 : SINHALA LITH DIGIT ZERO
--- U+00DE7 : SINHALA LITH DIGIT ONE
--- U+00DE8 : SINHALA LITH DIGIT TWO
--- U+00DE9 : SINHALA LITH DIGIT THREE
--- U+00DEA : SINHALA LITH DIGIT FOUR
--- U+00DEB : SINHALA LITH DIGIT FIVE
--- U+00DEC : SINHALA LITH DIGIT SIX
--- U+00DED : SINHALA LITH DIGIT SEVEN
--- U+00DEE : SINHALA LITH DIGIT EIGHT
--- U+00DEF : SINHALA LITH DIGIT NINE
-
-local consonant = {
- -- devanagari
- [0x0915] = true, [0x0916] = true, [0x0917] = true, [0x0918] = true,
- [0x0919] = true, [0x091A] = true, [0x091B] = true, [0x091C] = true,
- [0x091D] = true, [0x091E] = true, [0x091F] = true, [0x0920] = true,
- [0x0921] = true, [0x0922] = true, [0x0923] = true, [0x0924] = true,
- [0x0925] = true, [0x0926] = true, [0x0927] = true, [0x0928] = true,
- [0x0929] = true, [0x092A] = true, [0x092B] = true, [0x092C] = true,
- [0x092D] = true, [0x092E] = true, [0x092F] = true, [0x0930] = true,
- [0x0931] = true, [0x0932] = true, [0x0933] = true, [0x0934] = true,
- [0x0935] = true, [0x0936] = true, [0x0937] = true, [0x0938] = true,
- [0x0939] = true, [0x0958] = true, [0x0959] = true, [0x095A] = true,
- [0x095B] = true, [0x095C] = true, [0x095D] = true, [0x095E] = true,
- [0x095F] = true, [0x0979] = true, [0x097A] = true,
- -- kannada
- [0x0C95] = true, [0x0C96] = true, [0x0C97] = true, [0x0C98] = true,
- [0x0C99] = true, [0x0C9A] = true, [0x0C9B] = true, [0x0C9C] = true,
- [0x0C9D] = true, [0x0C9E] = true, [0x0C9F] = true, [0x0CA0] = true,
- [0x0CA1] = true, [0x0CA2] = true, [0x0CA3] = true, [0x0CA4] = true,
- [0x0CA5] = true, [0x0CA6] = true, [0x0CA7] = true, [0x0CA8] = true,
- [0x0CA9] = true, [0x0CAA] = true, [0x0CAB] = true, [0x0CAC] = true,
- [0x0CAD] = true, [0x0CAE] = true, [0x0CAF] = true, [0x0CB0] = true,
- [0x0CB1] = true, [0x0CB2] = true, [0x0CB3] = true, [0x0CB4] = true,
- [0x0CB5] = true, [0x0CB6] = true, [0x0CB7] = true, [0x0CB8] = true,
- [0x0CB9] = true,
- [0x0CDE] = true, -- obsolete
- -- malayalam
- [0x0D15] = true, [0x0D16] = true, [0x0D17] = true, [0x0D18] = true,
- [0x0D19] = true, [0x0D1A] = true, [0x0D1B] = true, [0x0D1C] = true,
- [0x0D1D] = true, [0x0D1E] = true, [0x0D1F] = true, [0x0D20] = true,
- [0x0D21] = true, [0x0D22] = true, [0x0D23] = true, [0x0D24] = true,
- [0x0D25] = true, [0x0D26] = true, [0x0D27] = true, [0x0D28] = true,
- [0x0D29] = true, [0x0D2A] = true, [0x0D2B] = true, [0x0D2C] = true,
- [0x0D2D] = true, [0x0D2E] = true, [0x0D2F] = true, [0x0D30] = true,
- [0x0D31] = true, [0x0D32] = true, [0x0D33] = true, [0x0D34] = true,
- [0x0D35] = true, [0x0D36] = true, [0x0D37] = true, [0x0D38] = true,
- [0x0D39] = true, [0x0D3A] = true,
-}
-
-local independent_vowel = {
- -- devanagari
- [0x0904] = true, [0x0905] = true, [0x0906] = true, [0x0907] = true,
- [0x0908] = true, [0x0909] = true, [0x090A] = true, [0x090B] = true,
- [0x090C] = true, [0x090D] = true, [0x090E] = true, [0x090F] = true,
- [0x0910] = true, [0x0911] = true, [0x0912] = true, [0x0913] = true,
- [0x0914] = true, [0x0960] = true, [0x0961] = true, [0x0972] = true,
- [0x0973] = true, [0x0974] = true, [0x0975] = true, [0x0976] = true,
- [0x0977] = true,
- -- kannada
- [0x0C85] = true, [0x0C86] = true, [0x0C87] = true, [0x0C88] = true,
- [0x0C89] = true, [0x0C8A] = true, [0x0C8B] = true, [0x0C8C] = true,
- [0x0C8D] = true, [0x0C8E] = true, [0x0C8F] = true, [0x0C90] = true,
- [0x0C91] = true, [0x0C92] = true, [0x0C93] = true, [0x0C94] = true,
- -- malayalam
- [0x0D05] = true, [0x0D06] = true, [0x0D07] = true, [0x0D08] = true,
- [0x0D09] = true, [0x0D0A] = true, [0x0D0B] = true, [0x0D0C] = true,
- [0x0D0E] = true, [0x0D0F] = true, [0x0D10] = true, [0x0D12] = true,
- [0x0D13] = true, [0x0D14] = true,
-}
-
-local dependent_vowel = { -- matra
- -- devanagari
- [0x093A] = true, [0x093B] = true, [0x093E] = true, [0x093F] = true,
- [0x0940] = true, [0x0941] = true, [0x0942] = true, [0x0943] = true,
- [0x0944] = true, [0x0945] = true, [0x0946] = true, [0x0947] = true,
- [0x0948] = true, [0x0949] = true, [0x094A] = true, [0x094B] = true,
- [0x094C] = true, [0x094E] = true, [0x094F] = true, [0x0955] = true,
- [0x0956] = true, [0x0957] = true, [0x0962] = true, [0x0963] = true,
- -- kannada
- [0x0CBE] = true, [0x0CBF] = true, [0x0CC0] = true, [0x0CC1] = true,
- [0x0CC2] = true, [0x0CC3] = true, [0x0CC4] = true, [0x0CC5] = true,
- [0x0CC6] = true, [0x0CC7] = true, [0x0CC8] = true, [0x0CC9] = true,
- [0x0CCA] = true, [0x0CCB] = true, [0x0CCC] = true,
- -- malayalam
- [0x0D3E] = true, [0x0D3F] = true, [0x0D40] = true, [0x0D41] = true,
- [0x0D42] = true, [0x0D43] = true, [0x0D44] = true, [0x0D46] = true,
- [0x0D47] = true, [0x0D48] = true, [0x0D4A] = true, [0x0D4B] = true,
- [0x0D4C] = true, [0x0D57] = true,
-}
-
-local vowel_modifier = {
- -- devanagari
- [0x0900] = true, [0x0901] = true, [0x0902] = true, [0x0903] = true,
- -- A8E0 - A8F1 are cantillation marks for the Samaveda and may not belong here.
- [0xA8E0] = true, [0xA8E1] = true, [0xA8E2] = true, [0xA8E3] = true,
- [0xA8E4] = true, [0xA8E5] = true, [0xA8E6] = true, [0xA8E7] = true,
- [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true,
- [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true,
- [0xA8F0] = true, [0xA8F1] = true,
- -- malayalam
- [0x0D02] = true, [0x0D03] = true,
-}
-
-local stress_tone_mark = {
- [0x0951] = true, [0x0952] = true, [0x0953] = true, [0x0954] = true,
- -- kannada
- [0x0CCD] = true,
- -- malayalam
- [0x0D4D] = true,
-}
-
-local nukta = {
- -- devanagari
- [0x093C] = true,
- -- kannada:
- [0x0CBC] = true,
-}
-
-local halant = {
- -- devanagari
- [0x094D] = true,
- -- kannada
- [0x0CCD] = true,
- -- malayalam
- [0x0D4D] = true,
-}
-
-local ra = {
- -- devanagari
- [0x0930] = true,
- -- kannada
- [0x0CB0] = true,
- -- malayalam
- [0x0D30] = true,
-}
-
-local c_anudatta = 0x0952 -- used to be tables
-local c_nbsp = 0x00A0 -- used to be tables
-local c_zwnj = 0x200C -- used to be tables
-local c_zwj = 0x200D -- used to be tables
-
-local zw_char = { -- could also be inlined
- [0x200C] = true,
- [0x200D] = true,
-}
-
--- 0C82 anusvara
--- 0C83 visarga
--- 0CBD avagraha
--- 0CD5 length mark
--- 0CD6 ai length mark
--- 0CE0 letter ll
--- 0CE1 letter rr
--- 0CE2 vowel sign l
--- 0CE2 vowel sign ll
--- 0CF1 sign
--- 0CF2 sign
--- OCE6 - OCEF digits
-
-local pre_mark = {
- [0x093F] = true, [0x094E] = true,
- -- malayalam
- [0x0D46] = true, [0x0D47] = true, [0x0D48] = true,
-}
-
-local above_mark = {
- [0x0900] = true, [0x0901] = true, [0x0902] = true, [0x093A] = true,
- [0x0945] = true, [0x0946] = true, [0x0947] = true, [0x0948] = true,
- [0x0951] = true, [0x0953] = true, [0x0954] = true, [0x0955] = true,
- [0xA8E0] = true, [0xA8E1] = true, [0xA8E2] = true, [0xA8E3] = true,
- [0xA8E4] = true, [0xA8E5] = true, [0xA8E6] = true, [0xA8E7] = true,
- [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true,
- [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true,
- [0xA8F0] = true, [0xA8F1] = true,
- -- malayalam
- [0x0D4E] = true,
-}
-
-local below_mark = {
- [0x093C] = true, [0x0941] = true, [0x0942] = true, [0x0943] = true,
- [0x0944] = true, [0x094D] = true, [0x0952] = true, [0x0956] = true,
- [0x0957] = true, [0x0962] = true, [0x0963] = true,
-}
-
-local post_mark = {
- [0x0903] = true, [0x093B] = true, [0x093E] = true, [0x0940] = true,
- [0x0949] = true, [0x094A] = true, [0x094B] = true, [0x094C] = true,
- [0x094F] = true,
-}
-
-local twopart_mark = {
- -- malayalam
- [0x0D4A] = { 0x0D46, 0x0D3E, }, -- ൊ
- [0x0D4B] = { 0x0D47, 0x0D3E, }, -- ോ
- [0x0D4C] = { 0x0D46, 0x0D57, }, -- ൌ
-}
-
-local mark_four = { } -- As we access these frequently an extra hash is used.
-
-for k, v in next, pre_mark do mark_four[k] = pre_mark end
-for k, v in next, above_mark do mark_four[k] = above_mark end
-for k, v in next, below_mark do mark_four[k] = below_mark end
-for k, v in next, post_mark do mark_four[k] = post_mark end
-
-local mark_above_below_post = { }
-
-for k, v in next, above_mark do mark_above_below_post[k] = above_mark end
-for k, v in next, below_mark do mark_above_below_post[k] = below_mark end
-for k, v in next, post_mark do mark_above_below_post[k] = post_mark end
-
--- Again, this table can be extended for other scripts than devanagari. Actually,
--- for ConTeXt this kind of data is kept elsewhere so eventually we might move
--- tables to someplace else.
-
-local reorder_class = {
- -- devanagari
- [0x0930] = "before postscript",
- [0x093F] = "before half",
- [0x0940] = "after subscript",
- [0x0941] = "after subscript",
- [0x0942] = "after subscript",
- [0x0943] = "after subscript",
- [0x0944] = "after subscript",
- [0x0945] = "after subscript",
- [0x0946] = "after subscript",
- [0x0947] = "after subscript",
- [0x0948] = "after subscript",
- [0x0949] = "after subscript",
- [0x094A] = "after subscript",
- [0x094B] = "after subscript",
- [0x094C] = "after subscript",
- [0x0962] = "after subscript",
- [0x0963] = "after subscript",
- [0x093E] = "after subscript",
- -- kannada:
- [0x0CB0] = "after postscript", -- todo in code below
- [0x0CBF] = "before subscript", -- todo in code below
- [0x0CC6] = "before subscript", -- todo in code below
- [0x0CCC] = "before subscript", -- todo in code below
- [0x0CBE] = "before subscript", -- todo in code below
- [0x0CE2] = "before subscript", -- todo in code below
- [0x0CE3] = "before subscript", -- todo in code below
- [0x0CC1] = "before subscript", -- todo in code below
- [0x0CC2] = "before subscript", -- todo in code below
- [0x0CC3] = "after subscript",
- [0x0CC4] = "after subscript",
- [0x0CD5] = "after subscript",
- [0x0CD6] = "after subscript",
- -- malayalam
-}
-
--- We use some pseudo features as we need to manipulate the nodelist based
--- on information in the font as well as already applied features.
-
-local dflt_true = {
- dflt = true
-}
-
-local dev2_defaults = {
- dev2 = dflt_true,
-}
-
-local deva_defaults = {
- dev2 = dflt_true,
- deva = dflt_true,
-}
-
-local false_flags = { false, false, false, false }
-
-local both_joiners_true = {
- [0x200C] = true,
- [0x200D] = true,
-}
-
-local sequence_reorder_matras = {
- chain = 0,
- features = { dv01 = dev2_defaults },
- flags = false_flags,
- name = "dv01_reorder_matras",
- order = { "dv01" },
- subtables = { "dv01_reorder_matras" },
- type = "devanagari_reorder_matras",
-}
-
-local sequence_reorder_reph = {
- chain = 0,
- features = { dv02 = dev2_defaults },
- flags = false_flags,
- name = "dv02_reorder_reph",
- order = { "dv02" },
- subtables = { "dv02_reorder_reph" },
- type = "devanagari_reorder_reph",
-}
-
-local sequence_reorder_pre_base_reordering_consonants = {
- chain = 0,
- features = { dv03 = dev2_defaults },
- flags = false_flags,
- name = "dv03_reorder_pre_base_reordering_consonants",
- order = { "dv03" },
- subtables = { "dv03_reorder_pre_base_reordering_consonants" },
- type = "devanagari_reorder_pre_base_reordering_consonants",
-}
-
-local sequence_remove_joiners = {
- chain = 0,
- features = { dv04 = deva_defaults },
- flags = false_flags,
- name = "dv04_remove_joiners",
- order = { "dv04" },
- subtables = { "dv04_remove_joiners" },
- type = "devanagari_remove_joiners",
-}
-
--- Looping over feature twice as efficient as looping over basic forms (some
--- 350 checks instead of 750 for one font). This is something to keep an eye on
--- as it might depends on the font. Not that it's a bottleneck.
-
-local basic_shaping_forms = {
- nukt = true,
- akhn = true,
- rphf = true,
- pref = true,
- rkrf = true,
- blwf = true,
- half = true,
- pstf = true,
- vatu = true,
- cjct = true,
-}
-
-local function initializedevanagi(tfmdata)
- local script, language = otf.scriptandlanguage(tfmdata,attr) -- todo: take fast variant
- if script == "deva" or script == "dev2" or script =="mlym" or script == "mlm2" then
- local resources = tfmdata.resources
- local lookuphash = resources.lookuphash
- if not lookuphash["dv01"] then
- report_devanagari("adding devanagari features to font")
- --
- local features = resources.features
- local gsubfeatures = features.gsub
- local sequences = resources.sequences
- local sharedfeatures = tfmdata.shared.features
- --
- local lastmatch = 0
- for s=1,#sequences do -- classify chars
- local features = sequences[s].features
- if features then
- for k, v in next, features do
- if basic_shaping_forms[k] then
- lastmatch = s
- end
- end
- end
- end
- local insertindex = lastmatch + 1
- --
- lookuphash["dv04_remove_joiners"] = both_joiners_true
- --
- gsubfeatures["dv01"] = dev2_defaults -- reorder matras
- gsubfeatures["dv02"] = dev2_defaults -- reorder reph
- gsubfeatures["dv03"] = dev2_defaults -- reorder pre base reordering consonants
- gsubfeatures["dv04"] = deva_defaults -- remove joiners
- --
- insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants)
- insert(sequences,insertindex,sequence_reorder_reph)
- insert(sequences,insertindex,sequence_reorder_matras)
- insert(sequences,insertindex,sequence_remove_joiners)
- --
- if script == "deva" then
- sharedfeatures["dv04"] = true -- dv04_remove_joiners
- elseif script == "dev2" then
- sharedfeatures["dv01"] = true -- dv01_reorder_matras
- sharedfeatures["dv02"] = true -- dv02_reorder_reph
- sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants
- sharedfeatures["dv04"] = true -- dv04_remove_joiners
- elseif script == "mlym" then
- sharedfeatures["pstf"] = true
- elseif script == "mlm2" then
- sharedfeatures["pstf"] = true
- sharedfeatures["pref"] = true
- sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants
- gsubfeatures["dv03"] = dev2_defaults -- reorder pre base reordering consonants
- insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants)
- end
- end
- end
-end
-
-registerotffeature {
- name = "devanagari",
- description = "inject additional features",
- default = true,
- initializers = {
- node = initializedevanagi,
- },
-}
-
--- hm, this is applied to one character:
-
-local function deva_initialize(font,attr)
-
- local tfmdata = fontdata[font]
- local resources = tfmdata.resources
- local lookuphash = resources.lookuphash
-
- local datasets = otf.dataset(tfmdata,font,attr)
- local devanagaridata = datasets.devanagari
-
- if devanagaridata then -- maybe also check for e.g. reph
-
- return lookuphash, devanagaridata.reph, devanagaridata.vattu, devanagaridata.blwfcache
-
- else
-
- devanagaridata = { }
- datasets.devanagari = devanagaridata
-
- local reph = false
- local vattu = false
- local blwfcache = { }
-
- local sequences = resources.sequences
-
- for s=1,#sequences do -- triggers creation of dataset
- -- local sequence = sequences[s]
- local dataset = datasets[s]
- if dataset and dataset[1] then -- value
- local kind = dataset[4]
- if kind == "rphf" then
- -- deva
- reph = true
- elseif kind == "blwf" then
- -- deva
- vattu = true
- -- dev2
- local subtables = dataset[3].subtables
- for i=1,#subtables do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- for k, v in next, lookupcache do
- blwfcache[k] = blwfcache[k] or v
- end
- end
- end
- end
- end
- end
-
- devanagaridata.reph = reph
- devanagaridata.vattu = vattu
- devanagaridata.blwfcache = blwfcache
-
- return lookuphash, reph, vattu, blwfcache
-
- end
-
-end
-
-local function deva_reorder(head,start,stop,font,attr,nbspaces)
-
- local lookuphash, reph, vattu, blwfcache = deva_initialize(font,attr) -- could be inlines but ugly
-
- local current = start
- local n = getnext(start)
- local base = nil
- local firstcons = nil
- local lastcons = nil
- local basefound = false
-
- if ra[getchar(start)] and halant[getchar(n)] and reph then
- -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph
- -- from candidates for base consonants
- if n == stop then
- return head, stop, nbspaces
- end
- if getchar(getnext(n)) == c_zwj then
- current = start
- else
- current = getnext(n)
- setprop(start,a_state,s_rphf)
- end
- end
-
- if getchar(current) == c_nbsp then
- -- Stand Alone cluster
- if current == stop then
- stop = getprev(stop)
- head = remove_node(head,current)
- flush_node(current)
- return head, stop, nbspaces
- else
- nbspaces = nbspaces + 1
- base = current
- firstcons = current
- lastcons = current
- current = getnext(current)
- if current ~= stop then
- if nukta[getchar(current)] then
- current = getnext(current)
- end
- if getchar(current) == c_zwj then
- if current ~= stop then
- local next = getnext(current)
- if next ~= stop and halant[getchar(next)] then
- current = next
- next = getnext(current)
- local tmp = next and getnext(next) or nil -- needs checking
- local changestop = next == stop
- local tempcurrent = copy_node(next)
- copyinjection(tempcurrent,next)
- local nextcurrent = copy_node(current)
- copyinjection(nextcurrent,current) -- KE: necessary? HH: probably not as positioning comes later and we rawget/set
- setnext(tempcurrent,nextcurrent)
- setprev(nextcurrent,tempcurrent)
- setprop(tempcurrent,a_state,s_blwf)
- tempcurrent = processcharacters(tempcurrent,font)
- setprop(tempcurrent,a_state,unsetvalue)
- if getchar(next) == getchar(tempcurrent) then
- flush_list(tempcurrent)
- local n = copy_node(current)
- copyinjection(n,current) -- KE: necessary? HH: probably not as positioning comes later and we rawget/set
- setchar(current,dotted_circle)
- head = insert_node_after(head, current, n)
- else
- setchar(current,getchar(tempcurrent)) -- we assumes that the result of blwf consists of one node
- local freenode = getnext(current)
- setnext(current,tmp)
- if tmp then
- setprev(tmp,current)
- end
- flush_node(freenode)
- flush_list(tempcurrent)
- if changestop then
- stop = current
- end
- end
- end
- end
- end
- end
- end
- end
-
- while not basefound do
- -- find base consonant
- if consonant[getchar(current)] then
- setprop(current,a_state,s_half)
- if not firstcons then
- firstcons = current
- end
- lastcons = current
- if not base then
- base = current
- elseif blwfcache[getchar(current)] then
- -- consonant has below-base (or post-base) form
- setprop(current,a_state,s_blwf)
- else
- base = current
- end
- end
- basefound = current == stop
- current = getnext(current)
- end
-
- if base ~= lastcons then
- -- if base consonant is not last one then move halant from base consonant to last one
- local np = base
- local n = getnext(base)
- if nukta[getchar(n)] then
- np = n
- n = getnext(n)
- end
- if halant[getchar(n)] then
- if lastcons ~= stop then
- local ln = getnext(lastcons)
- if nukta[getchar(ln)] then
- lastcons = ln
- end
- end
- -- local np = getprev(n)
- local nn = getnext(n)
- local ln = getnext(lastcons) -- what if lastcons is nn ?
- setnext(np,nn)
- setprev(nn,np)
- setnext(lastcons,n)
- if ln then
- setprev(ln,n)
- end
- setnext(n,ln)
- setprev(n,lastcons)
- if lastcons == stop then
- stop = n
- end
- end
- end
-
- n = getnext(start)
- if n ~= stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then
- -- if syllable starts with Ra + H then move this combination so that it follows either:
- -- the post-base 'matra' (if any) or the base consonant
- local matra = base
- if base ~= stop then
- local next = getnext(base)
- if dependent_vowel[getchar(next)] then
- matra = next
- end
- end
- -- [sp][start][n][nn] [matra|base][?]
- -- [matra|base][start] [n][?] [sp][nn]
- local sp = getprev(start)
- local nn = getnext(n)
- local mn = getnext(matra)
- if sp then
- setnext(sp,nn)
- end
- setprev(nn,sp)
- setnext(matra,start)
- setprev(start,matra)
- setnext(n,mn)
- if mn then
- setprev(mn,n)
- end
- if head == start then
- head = nn
- end
- start = nn
- if matra == stop then
- stop = n
- end
- end
-
- local current = start
- while current ~= stop do
- local next = getnext(current)
- if next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwnj then
- setprop(current,a_state,unsetvalue)
- end
- current = next
- end
-
- if base ~= stop and getprop(base,a_state) then
- local next = getnext(base)
- if halant[getchar(next)] and not (next ~= stop and getchar(getnext(next)) == c_zwj) then
- setprop(base,a_state,unsetvalue)
- end
- end
-
- -- ToDo: split two- or three-part matras into their parts. Then, move the left 'matra' part to the beginning of the syllable.
- -- Not necessary for Devanagari. However it is necessay for other scripts, such as Tamil (e.g. TAMIL VOWEL SIGN O - 0BCA)
-
- -- classify consonants and 'matra' parts as pre-base, above-base (Reph), below-base or post-base, and group elements of the syllable (consonants and 'matras') according to this classification
-
- local current, allreordered, moved = start, false, { [base] = true }
- local a, b, p, bn = base, base, base, getnext(base)
- if base ~= stop and nukta[getchar(bn)] then
- a, b, p = bn, bn, bn
- end
- while not allreordered do
- -- current is always consonant
- local c = current
- local n = getnext(current)
- local l = nil -- used ?
- if c ~= stop then
- if nukta[getchar(n)] then
- c = n
- n = getnext(n)
- end
- if c ~= stop then
- if halant[getchar(n)] then
- c = n
- n = getnext(n)
- end
- while c ~= stop and dependent_vowel[getchar(n)] do
- c = n
- n = getnext(n)
- end
- if c ~= stop then
- if vowel_modifier[getchar(n)] then
- c = n
- n = getnext(n)
- end
- if c ~= stop and stress_tone_mark[getchar(n)] then
- c = n
- n = getnext(n)
- end
- end
- end
- end
- local bp = getprev(firstcons)
- local cn = getnext(current)
- local last = getnext(c)
- while cn ~= last do
- -- move pre-base matras...
- if pre_mark[getchar(cn)] then
- if bp then
- setnext(bp,cn)
- end
- local next = getnext(cn)
- local prev = getprev(cn)
- if next then
- setprev(next,prev)
- end
- setnext(prev,next)
- if cn == stop then
- stop = prev
- end
- setprev(cn,bp)
- setnext(cn,firstcons)
- setprev(firstcons,cn)
- if firstcons == start then
- if head == start then
- head = cn
- end
- start = cn
- end
- break
- end
- cn = getnext(cn)
- end
- allreordered = c == stop
- current = getnext(c)
- end
-
- if reph or vattu then
- local current, cns = start, nil
- while current ~= stop do
- local c = current
- local n = getnext(current)
- if ra[getchar(current)] and halant[getchar(n)] then
- c = n
- n = getnext(n)
- local b, bn = base, base
- while bn ~= stop do
- local next = getnext(bn)
- if dependent_vowel[getchar(next)] then
- b = next
- end
- bn = next
- end
- if getprop(current,a_state) == s_rphf then
- -- position Reph (Ra + H) after post-base 'matra' (if any) since these
- -- become marks on the 'matra', not on the base glyph
- if b ~= current then
- if current == start then
- if head == start then
- head = n
- end
- start = n
- end
- if b == stop then
- stop = c
- end
- local prev = getprev(current)
- if prev then
- setnext(prev,n)
- end
- if n then
- setprev(n,prev)
- end
- local next = getnext(b)
- setnext(c,next)
- if next then
- setprev(next,c)
- end
- setnext(c,next)
- setnext(b,current)
- setprev(current,b)
- end
- elseif cns and getnext(cns) ~= current then -- todo: optimize next
- -- position below-base Ra (vattu) following the consonants on which it is placed (either the base consonant or one of the pre-base consonants)
- local cp, cnsn = getprev(current), getnext(cns)
- if cp then
- setnext(cp,n)
- end
- if n then
- setprev(n,cp)
- end
- setnext(cns,current)
- setprev(current,cns)
- setnext(c,cnsn)
- if cnsn then
- setprev(cnsn,c)
- end
- if c == stop then
- stop = cp
- break
- end
- current = getprev(n)
- end
- else
- local char = getchar(current)
- if consonant[char] then
- cns = current
- local next = getnext(cns)
- if halant[getchar(next)] then
- cns = next
- end
- elseif char == c_nbsp then
- nbspaces = nbspaces + 1
- cns = current
- local next = getnext(cns)
- if halant[getchar(next)] then
- cns = next
- end
- end
- end
- current = getnext(current)
- end
- end
-
- if getchar(base) == c_nbsp then
- nbspaces = nbspaces - 1
- head = remove_node(head,base)
- flush_node(base)
- end
-
- return head, stop, nbspaces
-end
-
--- If a pre-base matra character had been reordered before applying basic features,
--- the glyph can be moved closer to the main consonant based on whether half-forms had been formed.
--- Actual position for the matra is defined as “after last standalone halant glyph,
--- after initial matra position and before the main consonant”.
--- If ZWJ or ZWNJ follow this halant, position is moved after it.
-
--- so we break out ... this is only done for the first 'word' (if we feed words we can as
--- well test for non glyph.
-
-function handlers.devanagari_reorder_matras(head,start,kind,lookupname,replacement) -- no leak
- local current = start -- we could cache attributes here
- local startfont = getfont(start)
- local startattr = getprop(start,a_syllabe)
- -- can be fast loop
- while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font and getprop(current,a_syllabe) == startattr do
- local next = getnext(current)
- if halant[getchar(current)] and not getprop(current,a_state) then
- if next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == font and getprop(next,a_syllabe) == startattr and zw_char[getchar(next)] then
- current = next
- end
- local startnext = getnext(start)
- head = remove_node(head,start)
- local next = getnext(current)
- if next then
- setprev(next,start)
- end
- setnext(start,next)
- setnext(current,start)
- setprev(start,current)
- start = startnext
- break
- end
- current = next
- end
- return head, start, true
-end
-
--- todo: way more caching of attributes and font
-
--- Reph’s original position is always at the beginning of the syllable, (i.e. it is not reordered at the character reordering stage).
--- However, it will be reordered according to the basic-forms shaping results.
--- Possible positions for reph, depending on the script, are; after main, before post-base consonant forms,
--- and after post-base consonant forms.
-
--- 1 If reph should be positioned after post-base consonant forms, proceed to step 5.
--- 2 If the reph repositioning class is not after post-base: target position is after the first explicit halant glyph between
--- the first post-reph consonant and last main consonant. If ZWJ or ZWNJ are following this halant, position is moved after it.
--- If such position is found, this is the target position. Otherwise, proceed to the next step.
--- Note: in old-implementation fonts, where classifications were fixed in shaping engine,
--- there was no case where reph position will be found on this step.
--- 3 If reph should be repositioned after the main consonant: from the first consonant not ligated with main,
--- or find the first consonant that is not a potential pre-base reordering Ra.
--- 4 If reph should be positioned before post-base consonant, find first post-base classified consonant not ligated with main.
--- If no consonant is found, the target position should be before the first matra, syllable modifier sign or vedic sign.
--- 5 If no consonant is found in steps 3 or 4, move reph to a position immediately before the first post-base matra,
--- syllable modifier sign or vedic sign that has a reordering class after the intended reph position.
--- For example, if the reordering position for reph is post-main, it will skip above-base matras that also have a post-main position.
--- 6 Otherwise, reorder reph to the end of the syllable.
-
--- hm, this only looks at the start of a nodelist ... is this supposed to be line based?
-
-function handlers.devanagari_reorder_reph(head,start,kind,lookupname,replacement)
- -- since in Devanagari reph has reordering position 'before postscript' dev2 only follows step 2, 4, and 6,
- -- the other steps are still ToDo (required for scripts other than dev2)
- local current = getnext(start)
- local startnext = nil
- local startprev = nil
- local startfont = getfont(start)
- local startattr = getprop(start,a_syllabe)
- while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do --step 2
- if halant[getchar(current)] and not getprop(current,a_state) then
- local next = getnext(current)
- if next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == startfont and getprop(next,a_syllabe) == startattr and zw_char[getchar(next)] then
- current = next
- end
- startnext = getnext(start)
- head = remove_node(head,start)
- local next = getnext(current)
- if next then
- setprev(next,start)
- end
- setnext(start,next)
- setnext(current,start)
- setprev(start,current)
- start = startnext
- startattr = getprop(start,a_syllabe)
- break
- end
- current = getnext(current)
- end
- if not startnext then
- current = getnext(start)
- while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do --step 4
- if getprop(current,a_state) == s_pstf then --post-base
- startnext = getnext(start)
- head = remove_node(head,start)
- local prev = getprev(current)
- setprev(start,prev)
- setnext(prev,start)
- setnext(start,current)
- setprev(current,start)
- start = startnext
- startattr = getprop(start,a_syllabe)
- break
- end
- current = getnext(current)
- end
- end
- -- ToDo: determine position for reph with reordering position other than 'before postscript'
- -- (required for scripts other than dev2)
- -- leaks
- if not startnext then
- current = getnext(start)
- local c = nil
- while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do --step 5
- if not c then
- local char = getchar(current)
- -- todo: combine in one
- if mark_above_below_post[char] and reorder_class[char] ~= "after subscript" then
- c = current
- end
- end
- current = getnext(current)
- end
- -- here we can loose the old start node: maybe best split cases
- if c then
- startnext = getnext(start)
- head = remove_node(head,start)
- local prev = getprev(c)
- setprev(start,prev)
- setnext(prev,start)
- setnext(start,c)
- setprev(c,start)
- -- end
- start = startnext
- startattr = getprop(start,a_syllabe)
- end
- end
- -- leaks
- if not startnext then
- current = start
- local next = getnext(current)
- while next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == startfont and getprop(next,a_syllabe) == startattr do --step 6
- current = next
- next = getnext(current)
- end
- if start ~= current then
- startnext = getnext(start)
- head = remove_node(head,start)
- local next = getnext(current)
- if next then
- setprev(next,start)
- end
- setnext(star,next)
- setnext(current,start)
- setprev(start,current)
- start = startnext
- end
- end
- --
- return head, start, true
-end
-
--- we can cache some checking (v)
-
--- If a pre-base reordering consonant is found, reorder it according to the following rules:
---
--- 1 Only reorder a glyph produced by substitution during application of the feature.
--- (Note that a font may shape a Ra consonant with the feature generally but block it in certain contexts.)
--- 2 Try to find a target position the same way as for pre-base matra. If it is found, reorder pre-base consonant glyph.
--- 3 If position is not found, reorder immediately before main consonant.
-
--- UNTESTED: NOT CALLED IN EXAMPLE
-
-function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start,kind,lookupname,replacement)
- local current = start
- local startnext = nil
- local startprev = nil
- local startfont = getfont(start)
- local startattr = getprop(start,a_syllabe)
- -- can be fast for loop + caching state
- while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do
- local next = getnext(current)
- if halant[getchar(current)] and not getprop(current,a_state) then
- if next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == font and getprop(next,a_syllabe) == startattr then
- local char = getchar(next)
- if char == c_zwnj or char == c_zwj then
- current = next
- end
- end
- startnext = getnext(start)
- removenode(start,start)
- local next = getnext(current)
- if next then
- setprev(next,start)
- end
- setnext(start,next)
- setnext(current,start)
- setprev(start,current)
- start = startnext
- break
- end
- current = next
- end
- if not startnext then
- current = getnext(start)
- startattr = getprop(start,a_syllabe)
- while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getprop(current,a_syllabe) == startattr do
- if not consonant[getchar(current)] and getprop(current,a_state) then --main
- startnext = getnext(start)
- removenode(start,start)
- local prev = getprev(current)
- setprev(start,prev)
- setnext(prev,start)
- setnext(start,current)
- setprev(current,start)
- start = startnext
- break
- end
- current = getnext(current)
- end
- end
- return head, start, true
-end
-
-function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement)
- local stop = getnext(start)
- local startfont = getfont(start)
- while stop and getid(stop) == glyph_code and getsubtype(stop) < 256 and getfont(stop) == startfont do
- local char = getchar(stop)
- if char == c_zwnj or char == c_zwj then
- stop = getnext(stop)
- else
- break
- end
- end
- if stop then
- setnext(getprev(stop),nil)
- setprev(stop,getprev(start))
- end
- local prev = getprev(start)
- if prev then
- setnext(prev,stop)
- end
- if head == start then
- head = stop
- end
- flush_list(start)
- return head, stop, true
-end
-
-local valid = {
- akhn = true, -- malayalam
- rphf = true,
- pref = true,
- half = true,
- blwf = true,
- pstf = true,
- pres = true, -- malayalam
- blws = true, -- malayalam
- psts = true, -- malayalam
-}
-
-local function dev2_initialize(font,attr)
-
- local tfmdata = fontdata[font]
- local resources = tfmdata.resources
- local lookuphash = resources.lookuphash
-
- local datasets = otf.dataset(tfmdata,font,attr)
- local devanagaridata = datasets.devanagari
-
- if devanagaridata then -- maybe also check for e.g. seqsubset
-
- return lookuphash, devanagaridata.seqsubset
-
- else
-
- devanagaridata = { }
- datasets.devanagari = devanagaridata
-
- local seqsubset = { }
- devanagaridata.seqsubset = seqsubset
-
- local sequences = resources.sequences
-
- for s=1,#sequences do
- -- local sequence = sequences[s]
- local dataset = datasets[s]
- if dataset and dataset[1] then -- featurevalue
- local kind = dataset[4]
- if kind and valid[kind] then
- -- could become a function call
- local subtables = dataset[3].subtables
- for i=1,#subtables do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local reph = false
- local chain = dataset[3]
- if chain ~= 0 then --rphf is result of of chain
- -- rphf might be result of other handler/chainproc
- else
- -- rphf acts on consonant + halant
- for k, v in next, ra do
- local r = lookupcache[k]
- if r then
- local h = false
- for k, v in next, halant do
- local h = r[k]
- if h then
- reph = h.ligature or false
- break
- end
- end
- if reph then
- break
- end
- end
- end
- end
- seqsubset[#seqsubset+1] = { kind, lookupcache, reph }
- end
- end
- end
- end
- end
-
- lookuphash["dv01_reorder_matras"] = pre_mark -- move to initializer ?
-
- return lookuphash, seqsubset
-
- end
-
-end
-
--- this one will be merged into the caller: it saves a call, but we will then make function
--- of the actions
-
-local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pass over (determine stop in sweep)
-
- local lookuphash, seqsubset = dev2_initialize(font,attr)
-
- local pre_base_reordering_consonants = { } -- was nil ... probably went unnoticed because never assigned
-
- local reph = false -- was nil ... probably went unnoticed because never assigned
- local halfpos = nil
- local basepos = nil
- local subpos = nil
- local postpos = nil
- local locl = { }
-
- for i=1,#seqsubset do
-
- -- maybe quit if start == stop
-
- local subset = seqsubset[i]
- local kind = subset[1]
- local lookupcache = subset[2]
- if kind == "rphf" then
- for k, v in next, ra do
- local r = lookupcache[k]
- if r then
- for k, v in next, halant do
- local h = r[k]
- if h then
- reph = h.ligature or false
- break
- end
- end
- if reph then
- break
- end
- end
- end
- local current = start
- local last = getnext(stop)
- while current ~= last do
- if current ~= stop then
- local c = locl[current] or getchar(current)
- local found = lookupcache[c]
- if found then
- local next = getnext(current)
- local n = locl[next] or getchar(next)
- if found[n] then --above-base: rphf Consonant + Halant
- local afternext = next ~= stop and getnext(next)
- if afternext and zw_char[getchar(afternext)] then -- ZWJ and ZWNJ prevent creation of reph
- current = next
- current = getnext(current)
- elseif current == start then
- setprop(current,a_state,s_rphf)
- current = next
- else
- current = next
- end
- end
- end
- end
- current = getnext(current)
- end
- elseif kind == "pref" then
- -- why not global? pretty ineffient this way
- -- this will move to the initializer and we will store the hash in dataset
- -- todo: reph might also be result of chain
- for k, v in next, halant do
- local h = lookupcache[k]
- if h then
- local found = false
- for k, v in next, h do
- found = v and v.ligature
- if found then
- pre_base_reordering_consonants[k] = found
- break
- end
- end
- if found then
- break
- end
- end
- end
- --
- local current = start
- local last = getnext(stop)
- while current ~= last do
- if current ~= stop then
- local c = locl[current] or getchar(current)
- local found = lookupcache[c]
- if found then
- local next = getnext(current)
- local n = locl[next] or getchar(next)
- if found[n] then
- setprop(current,a_state,s_pref)
- setprop(next,a_state,s_pref)
- current = next
- end
- end
- end
- current = getnext(current)
- end
- elseif kind == "half" then -- half forms: half / Consonant + Halant
- local current = start
- local last = getnext(stop)
- while current ~= last do
- if current ~= stop then
- local c = locl[current] or getchar(current)
- local found = lookupcache[c]
- if found then
- local next = getnext(current)
- local n = locl[next] or getchar(next)
- if found[n] then
- if next ~= stop and getchar(getnext(next)) == c_zwnj then -- zwnj prevent creation of half
- current = next
- else
- setprop(current,a_state,s_half)
- if not halfpos then
- halfpos = current
- end
- end
- current = getnext(current)
- end
- end
- end
- current = getnext(current)
- end
- elseif kind == "blwf" then -- below-base: blwf / Halant + Consonant
- local current = start
- local last = getnext(stop)
- while current ~= last do
- if current ~= stop then
- local c = locl[current] or getchar(current)
- local found = lookupcache[c]
- if found then
- local next = getnext(current)
- local n = locl[next] or getchar(next)
- if found[n] then
- setprop(current,a_state,s_blwf)
- setprop(next,a_state,s_blwf)
- current = next
- subpos = current
- end
- end
- end
- current = getnext(current)
- end
- elseif kind == "pstf" then -- post-base: pstf / Halant + Consonant
- local current = start
- local last = getnext(stop)
- while current ~= last do
- if current ~= stop then
- local c = locl[current] or getchar(current)
- local found = lookupcache[c]
- if found then
- local next = getnext(current)
- local n = locl[next] or getchar(next)
- if found[n] then
- setprop(current,a_state,s_pstf)
- setprop(next,a_state,s_pstf)
- current = next
- postpos = current
- end
- end
- end
- current = getnext(current)
- end
- end
- end
-
- -- this one changes per word
-
- lookuphash["dv02_reorder_reph"] = { [reph] = true }
- lookuphash["dv03_reorder_pre_base_reordering_consonants"] = pre_base_reordering_consonants
-
- local current, base, firstcons = start, nil, nil
-
- if getprop(start,a_state) == s_rphf then
- -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants
- current = getnext(getnext(start))
- end
-
- if current ~= getnext(stop) and getchar(current) == c_nbsp then
- -- Stand Alone cluster
- if current == stop then
- stop = getprev(stop)
- head = remove_node(head,current)
- flush_node(current)
- return head, stop, nbspaces
- else
- nbspaces = nbspaces + 1
- base = current
- current = getnext(current)
- if current ~= stop then
- local char = getchar(current)
- if nukta[char] then
- current = getnext(current)
- char = getchar(current)
- end
- if char == c_zwj then
- local next = getnext(current)
- if current ~= stop and next ~= stop and halant[getchar(next)] then
- current = next
- next = getnext(current)
- local tmp = getnext(next)
- local changestop = next == stop
- setnext(next,nil)
- setprop(current,a_state,s_pref)
- current = processcharacters(current,font)
- setprop(current,a_state,s_blwf)
- current = processcharacters(current,font)
- setprop(current,a_state,s_pstf)
- current = processcharacters(current,font)
- setprop(current,a_state,unsetvalue)
- if halant[getchar(current)] then
- setnext(getnext(current),tmp)
- local nc = copy_node(current)
- copyinjection(nc,current)
- setchar(current,dotted_circle)
- head = insert_node_after(head,current,nc)
- else
- setnext(current,tmp) -- assumes that result of pref, blwf, or pstf consists of one node
- if changestop then
- stop = current
- end
- end
- end
- end
- end
- end
- else -- not Stand Alone cluster
- local last = getnext(stop)
- while current ~= last do -- find base consonant
- local next = getnext(current)
- if consonant[getchar(current)] then
- if not (current ~= stop and next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwj) then
- if not firstcons then
- firstcons = current
- end
- -- check whether consonant has below-base or post-base form or is pre-base reordering Ra
- local a = getprop(current,a_state)
- if not (a == s_pref or a == s_blwf or a == s_pstf) then
- base = current
- end
- end
- end
- current = next
- end
- if not base then
- base = firstcons
- end
- end
-
- if not base then
- if getprop(start,a_state) == s_rphf then
- setprop(start,a_state,unsetvalue)
- end
- return head, stop, nbspaces
- else
- if getprop(base,a_state) then
- setprop(base,a_state,unsetvalue)
- end
- basepos = base
- end
- if not halfpos then
- halfpos = base
- end
- if not subpos then
- subpos = base
- end
- if not postpos then
- postpos = subpos or base
- end
-
- -- Matra characters are classified and reordered by which consonant in a conjunct they have affinity for
-
- local moved = { }
- local current = start
- local last = getnext(stop)
- while current ~= last do
- local char, target, cn = locl[current] or getchar(current), nil, getnext(current)
- -- not so efficient (needed for malayalam)
- local tpm = twopart_mark[char]
- if tpm then
- local extra = copy_node(current)
- copyinjection(extra,current)
- char = tpm[1]
- setchar(current,char)
- setchar(extra,tpm[2])
- head = insert_node_after(head,current,extra)
- end
- --
- if not moved[current] and dependent_vowel[char] then
- if pre_mark[char] then -- Before first half form in the syllable
- moved[current] = true
- local prev = getprev(current)
- local next = getnext(current)
- if prev then
- setnext(prev,next)
- end
- if next then
- setprev(next,prev)
- end
- if current == stop then
- stop = getprev(current)
- end
- if halfpos == start then
- if head == start then
- head = current
- end
- start = current
- end
- local prev = getprev(halfpos)
- if prev then
- setnext(prev,current)
- end
- setprev(current,prev)
- setprev(halfpos,current)
- setnext(current,halfpos)
- halfpos = current
- elseif above_mark[char] then -- After main consonant
- target = basepos
- if subpos == basepos then
- subpos = current
- end
- if postpos == basepos then
- postpos = current
- end
- basepos = current
- elseif below_mark[char] then -- After subjoined consonants
- target = subpos
- if postpos == subpos then
- postpos = current
- end
- subpos = current
- elseif post_mark[char] then -- After post-form consonant
- target = postpos
- postpos = current
- end
- if mark_above_below_post[char] then
- local prev = getprev(current)
- if prev ~= target then
- local next = getnext(current)
- if prev then -- not needed, already tested with target
- setnext(prev,next)
- end
- if next then
- setprev(next,prev)
- end
- if current == stop then
- stop = prev
- end
- local next = getnext(target)
- if next then
- setprev(next,current)
- end
- setnext(current,next)
- setnext(target,current)
- setprev(current,target)
- end
- end
- end
- current = cn
- end
-
- -- Reorder marks to canonical order: Adjacent nukta and halant or nukta and vedic sign are always repositioned if necessary, so that the nukta is first.
-
- local current, c = start, nil
- while current ~= stop do
- local char = getchar(current)
- if halant[char] or stress_tone_mark[char] then
- if not c then
- c = current
- end
- else
- c = nil
- end
- local next = getnext(current)
- if c and nukta[getchar(next)] then
- if head == c then
- head = next
- end
- if stop == next then
- stop = current
- end
- local prev = getprev(c)
- if prev then
- setnext(prev,next)
- end
- setprev(next,prev)
- local nextnext = getnext(next)
- setnext(current,nextnext)
- local nextnextnext = getnext(nextnext)
- if nextnextnext then
- setprev(nextnextnext,current)
- end
- setprev(c,nextnext)
- setnext(nextnext,c)
- end
- if stop == current then break end
- current = getnext(current)
- end
-
- if getchar(base) == c_nbsp then
- nbspaces = nbspaces - 1
- head = remove_node(head, base)
- flush_node(base)
- end
-
- return head, stop, nbspaces
-end
-
--- cleaned up and optimized ... needs checking (local, check order, fixes, extra hash, etc)
-
-local separator = { }
-
-imerge(separator,consonant)
-imerge(separator,independent_vowel)
-imerge(separator,dependent_vowel)
-imerge(separator,vowel_modifier)
-imerge(separator,stress_tone_mark)
-
-for k, v in next, nukta do separator[k] = true end
-for k, v in next, halant do separator[k] = true end
-
-local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowel
- -- why two variants ... the comment suggests that it's the same ruleset
- local n = getnext(c)
- if not n then
- return c
- end
- if variant == 1 then
- local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if v and nukta[getchar(n)] then
- n = getnext(n)
- if n then
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- end
- end
- if n and v then
- local nn = getnext(n)
- if nn and getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font then
- local nnn = getnext(nn)
- if nnn and getid(nnn) == glyph_code and getsubtype(nnn) < 256 and getfont(nnn) == font then
- local nnc = getchar(nn)
- local nnnc = getchar(nnn)
- if nnc == c_zwj and consonant[nnnc] then
- c = nnn
- elseif (nnc == c_zwnj or nnc == c_zwj) and halant[nnnc] then
- local nnnn = getnext(nnn)
- if nnnn and getid(nnnn) == glyph_code and consonant[getchar(nnnn)] and getsubtype(nnnn) < 256 and getfont(nnnn) == font then
- c = nnnn
- end
- end
- end
- end
- end
- elseif variant == 2 then
- if getid(n) == glyph_code and nukta[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
- c = n
- end
- n = getnext(c)
- if n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font then
- local nn = getnext(n)
- if nn then
- local nv = getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font
- if nv and zw_char[getchar(n)] then
- n = nn
- nn = getnext(nn)
- nv = nn and getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font
- end
- if nv and halant[getchar(n)] and consonant[getchar(nn)] then
- c = nn
- end
- end
- end
- end
- -- c = ms_matra(c)
- local n = getnext(c)
- if not n then
- return c
- end
- local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- local char = getchar(n)
- if dependent_vowel[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if nukta[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if halant[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if vowel_modifier[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if stress_tone_mark[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if stress_tone_mark[char] then
- return n
- else
- return c
- end
-end
-
-local function analyze_next_chars_two(c,font)
- local n = getnext(c)
- if not n then
- return c
- end
- if getid(n) == glyph_code and nukta[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
- c = n
- end
- n = c
- while true do
- local nn = getnext(n)
- if nn and getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font then
- local char = getchar(nn)
- if halant[char] then
- n = nn
- local nnn = getnext(nn)
- if nnn and getid(nnn) == glyph_code and zw_char[getchar(nnn)] and getsubtype(nnn) < 256 and getfont(nnn) == font then
- n = nnn
- end
- elseif char == c_zwnj or char == c_zwj then
- -- n = nn -- not here (?)
- local nnn = getnext(nn)
- if nnn and getid(nnn) == glyph_code and halant[getchar(nnn)] and getsubtype(nnn) < 256 and getfont(nnn) == font then
- n = nnn
- end
- else
- break
- end
- local nn = getnext(n)
- if nn and getid(nn) == glyph_code and consonant[getchar(nn)] and getsubtype(nn) < 256 and getfont(nn) == font then
- n = nn
- local nnn = getnext(nn)
- if nnn and getid(nnn) == glyph_code and nukta[getchar(nnn)] and getsubtype(nnn) < 256 and getfont(nnn) == font then
- n = nnn
- end
- c = n
- else
- break
- end
- else
- break
- end
- end
- --
- if not c then
- -- This shouldn't happen I guess.
- return
- end
- local n = getnext(c)
- if not n then
- return c
- end
- local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- local char = getchar(n)
- if char == c_anudatta then
- c = n
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if halant[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- if char == c_zwnj or char == c_zwj then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- else
- -- c = ms_matra(c)
- -- same as one
- if dependent_vowel[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if nukta[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if halant[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- end
- -- same as one
- if vowel_modifier[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if stress_tone_mark[char] then
- c = getnext(c)
- n = getnext(c)
- if not n then
- return c
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- return c
- end
- char = getchar(n)
- end
- if stress_tone_mark[char] then
- return n
- else
- return c
- end
-end
-
-local function inject_syntax_error(head,current,mark)
- local signal = copy_node(current)
- copyinjection(signal,current)
- if mark == pre_mark then
- setchar(signal,dotted_circle)
- else
- setchar(current,dotted_circle)
- end
- return insert_node_after(head,current,signal)
-end
-
--- It looks like these two analyzers were written independently but they share
--- a lot. Common code has been synced.
-
-function methods.deva(head,font,attr)
- head = tonut(head)
- local current = head
- local start = true
- local done = false
- local nbspaces = 0
- while current do
- if getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font then
- done = true
- local syllablestart = current
- local syllableend = nil
- local c = current
- local n = getnext(c)
- if n and ra[getchar(c)] and getid(n) == glyph_code and halant[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
- local n = getnext(n)
- if n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font then
- c = n
- end
- end
- local standalone = getchar(c) == c_nbsp
- if standalone then
- local prev = getprev(current)
- if not prev then
- -- begin of paragraph or box
- elseif getid(prev) ~= glyph_code or getsubtype(prev) >= 256 or getfont(prev) ~= font then
- -- different font or language so quite certainly a different word
- elseif not separator[getchar(prev)] then
- -- something that separates words
- else
- standalone = false
- end
- end
- if standalone then
- -- stand alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
- local syllableend = analyze_next_chars_one(c,font,2)
- current = getnext(syllableend)
- if syllablestart ~= syllableend then
- head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
- current = getnext(current)
- end
- else
- -- we can delay the getsubtype(n) and getfont(n) and test for say halant first
- -- as an table access is faster than two function calls (subtype and font are
- -- pseudo fields) but the code becomes messy (unless we make it a function)
- local char = getchar(current)
- if consonant[char] then
- -- syllable containing consonant
- local prevc = true
- while prevc do
- prevc = false
- local n = getnext(current)
- if not n then
- break
- end
- local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- break
- end
- local c = getchar(n)
- if nukta[c] then
- n = getnext(n)
- if not n then
- break
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- break
- end
- c = getchar(n)
- end
- if halant[c] then
- n = getnext(n)
- if not n then
- break
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- break
- end
- c = getchar(n)
- if c == c_zwnj or c == c_zwj then
- n = getnext(n)
- if not n then
- break
- end
- v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font
- if not v then
- break
- end
- c = getchar(n)
- end
- if consonant[c] then
- prevc = true
- current = n
- end
- end
- end
- local n = getnext(current)
- if n and getid(n) == glyph_code and nukta[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
- -- nukta (not specified in Microsft Devanagari OpenType specification)
- current = n
- n = getnext(current)
- end
- syllableend = current
- current = n
- if current then
- local v = getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
- if v then
- if halant[getchar(current)] then
- -- syllable containing consonant without vowels: {C + [Nukta] + H} + C + H
- local n = getnext(current)
- if n and getid(n) == glyph_code and zw_char[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
- -- code collapsed, probably needs checking with intention
- syllableend = n
- current = getnext(n)
- else
- syllableend = current
- current = n
- end
- else
- -- syllable containing consonant with vowels: {C + [Nukta] + H} + C + [M] + [VM] + [SM]
- local c = getchar(current)
- if dependent_vowel[c] then
- syllableend = current
- current = getnext(current)
- v = current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
- if v then
- c = getchar(current)
- end
- end
- if v and vowel_modifier[c] then
- syllableend = current
- current = getnext(current)
- v = current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
- if v then
- c = getchar(current)
- end
- end
- if v and stress_tone_mark[c] then
- syllableend = current
- current = getnext(current)
- end
- end
- end
- end
- if syllablestart ~= syllableend then
- head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
- current = getnext(current)
- end
- elseif independent_vowel[char] then
- -- syllable without consonants: VO + [VM] + [SM]
- syllableend = current
- current = getnext(current)
- if current then
- local v = getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
- if v then
- local c = getchar(current)
- if vowel_modifier[c] then
- syllableend = current
- current = getnext(current)
- v = current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font
- if v then
- c = getchar(current)
- end
- end
- if v and stress_tone_mark[c] then
- syllableend = current
- current = getnext(current)
- end
- end
- end
- else
- local mark = mark_four[char]
- if mark then
- head, current = inject_syntax_error(head,current,mark)
- end
- current = getnext(current)
- end
- end
- else
- current = getnext(current)
- end
- start = false
- end
-
- if nbspaces > 0 then
- head = replace_all_nbsp(head)
- end
-
- head = tonode(head)
-
- return head, done
-end
-
--- there is a good change that when we run into one with subtype < 256 that the rest is also done
--- so maybe we can omit this check (it's pretty hard to get glyphs in the stream out of the blue)
-
--- handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
-
-function methods.dev2(head,font,attr)
- head = tonut(head)
- local current = head
- local start = true
- local done = false
- local syllabe = 0
- local nbspaces = 0
- while current do
- local syllablestart, syllableend = nil, nil
- if getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font then
- done = true
- syllablestart = current
- local c = current
- local n = getnext(current)
- if n and ra[getchar(c)] and getid(n) == glyph_code and halant[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then
- local n = getnext(n)
- if n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font then
- c = n
- end
- end
- local char = getchar(c)
- if independent_vowel[char] then
- -- vowel-based syllable: [Ra+H]+V+[N]+[<[<ZWJ|ZWNJ>]+H+C|ZWJ+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
- current = analyze_next_chars_one(c,font,1)
- syllableend = current
- else
- local standalone = char == c_nbsp
- if standalone then
- nbspaces = nbspaces + 1
- local p = getprev(current)
- if not p then
- -- begin of paragraph or box
- elseif getid(p) ~= glyph_code or getsubtype(p) >= 256 or getfont(p) ~= font then
- -- different font or language so quite certainly a different word
- elseif not separator[getchar(p)] then
- -- something that separates words
- else
- standalone = false
- end
- end
- if standalone then
- -- Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)]
- current = analyze_next_chars_one(c,font,2)
- syllableend = current
- elseif consonant[getchar(current)] then
- -- WHY current INSTEAD OF c ?
-
- -- Consonant syllable: {C+[N]+<H+[<ZWNJ|ZWJ>]|<ZWNJ|ZWJ>+H>} + C+[N]+[A] + [< H+[<ZWNJ|ZWJ>] | {M}+[N]+[H]>]+[SM]+[(VD)]
- current = analyze_next_chars_two(current,font) -- not c !
- syllableend = current
- end
- end
- end
- if syllableend then
- syllabe = syllabe + 1
- local c = syllablestart
- local n = getnext(syllableend)
- while c ~= n do
- setprop(c,a_syllabe,syllabe)
- c = getnext(c)
- end
- end
- if syllableend and syllablestart ~= syllableend then
- head, current, nbspaces = dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
- end
- if not syllableend and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font and not getprop(current,a_state) then
- local mark = mark_four[getchar(current)]
- if mark then
- head, current = inject_syntax_error(head,current,mark)
- end
- end
- start = false
- current = getnext(current)
- end
-
- if nbspaces > 0 then
- head = replace_all_nbsp(head)
- end
-
- head = tonode(head)
-
- return head, done
-end
-
-methods.mlym = methods.deva
-methods.mlm2 = methods.dev2
diff --git a/tex/context/base/mkiv/font-osd.lua b/tex/context/base/mkiv/font-osd.lua
index ca20f6782..2ee8a2286 100644
--- a/tex/context/base/mkiv/font-osd.lua
+++ b/tex/context/base/mkiv/font-osd.lua
@@ -6,13 +6,6 @@ if not modules then modules = { } end modules ['font-osd'] = { -- script devanag
license = "see context related readme files"
}
--- I'll optimize this one with ischar (much faster) when I see a reason (read: I need a
--- proper test case first).
-
--- This is a version of font-odv.lua adapted to the new font loader and more
--- direct hashing. The initialization code has been adapted (more efficient). One day
--- I'll speed this up ... char swapping and properties.
-
-- A few remarks:
--
-- This code is a partial rewrite of the code that deals with devanagari. The data and logic
@@ -29,7 +22,8 @@ if not modules then modules = { } end modules ['font-osd'] = { -- script devanag
-- much can get messed up in over a week work) it could be that I introduced bugs. There
-- is more to gain (esp in the functions applied to a range) but I'll do that when
-- everything works as expected. Kai's original code is kept in font-odk.lua as a reference
--- so blame me (HH) for bugs.
+-- so blame me (HH) for bugs. (We no longer ship that file as the code below has diverted
+-- too much and in the meantime has more than doubled in size.)
--
-- Interesting is that Kai managed to write this on top of the existing otf handler. Only a
-- few extensions were needed, like a few more analyzing states and dealing with changed
@@ -1140,7 +1134,7 @@ function handlers.devanagari_reorder_matras(head,start) -- no leak
head = remove_node(head,start)
setlink(start,next)
setlink(current,start)
- -- setlink(current,start,next) -- maybe
+ -- setlink(current,start,next) -- maybe
start = startnext
break
end
@@ -1200,7 +1194,7 @@ function handlers.devanagari_reorder_reph(head,start)
head = remove_node(head,start)
setlink(start,next)
setlink(current,start)
- -- setlink(current,start,next) -- maybe
+ -- setlink(current,start,next) -- maybe
start = startnext
startattr = getprop(start,a_syllabe)
break
@@ -1220,7 +1214,7 @@ function handlers.devanagari_reorder_reph(head,start)
head = remove_node(head,start)
setlink(getprev(current),start)
setlink(start,current)
- -- setlink(getprev(current),start,current) -- maybe
+ -- setlink(getprev(current),start,current) -- maybe
start = startnext
startattr = getprop(start,a_syllabe)
break
@@ -1254,7 +1248,7 @@ function handlers.devanagari_reorder_reph(head,start)
head = remove_node(head,start)
setlink(getprev(c),start)
setlink(start,c)
- -- setlink(getprev(c),start,c) -- maybe
+ -- setlink(getprev(c),start,c) -- maybe
-- end
start = startnext
startattr = getprop(start,a_syllabe)
@@ -1278,7 +1272,7 @@ function handlers.devanagari_reorder_reph(head,start)
head = remove_node(head,start)
setlink(start,getnext(current))
setlink(current,start)
- -- setlink(current,start,getnext(current)) -- maybe
+ -- setlink(current,start,getnext(current)) -- maybe
start = startnext
end
end
@@ -1322,7 +1316,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
removenode(start,start)
setlink(start,next)
setlink(current,start)
- -- setlink(current,start,next) -- maybe
+ -- setlink(current,start,next) -- maybe
start = startnext
break
end
diff --git a/tex/context/base/mkiv/font-ota.lua b/tex/context/base/mkiv/font-ota.lua
index 232c2586a..743951d50 100644
--- a/tex/context/base/mkiv/font-ota.lua
+++ b/tex/context/base/mkiv/font-ota.lua
@@ -1,6 +1,6 @@
if not modules then modules = { } end modules ['font-ota'] = {
version = 1.001,
- comment = "companion to font-otf.lua (analysing)",
+ comment = "companion to font-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
diff --git a/tex/context/base/mkiv/font-otb.lua b/tex/context/base/mkiv/font-otb.lua
deleted file mode 100644
index a31079225..000000000
--- a/tex/context/base/mkiv/font-otb.lua
+++ /dev/null
@@ -1,705 +0,0 @@
-if not modules then modules = { } end modules ['font-otb'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-local concat = table.concat
-local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
-local type, next, tonumber, tostring, rawget = type, next, tonumber, tostring, rawget
-
-local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = v end)
-local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end)
-local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end)
-local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end)
-local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end)
-local trace_ligatures_detail = false trackers.register("otf.ligatures.detail", function(v) trace_ligatures_detail = v end)
-local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
-local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
-
-local report_prepare = logs.reporter("fonts","otf prepare")
-
-local fonts = fonts
-local otf = fonts.handlers.otf
-
-local otffeatures = otf.features
-local registerotffeature = otffeatures.register
-
-otf.defaultbasealternate = "none" -- first last
-
-local wildcard = "*"
-local default = "dflt"
-
-local formatters = string.formatters
-local f_unicode = formatters["%U"]
-local f_uniname = formatters["%U (%s)"]
-local f_unilist = formatters["% t (% t)"]
-
-local function gref(descriptions,n)
- if type(n) == "number" then
- local name = descriptions[n].name
- if name then
- return f_uniname(n,name)
- else
- return f_unicode(n)
- end
- elseif n then
- local num, nam, j = { }, { }, 0
- for i=1,#n do
- local ni = n[i]
- if tonumber(ni) then -- first is likely a key
- j = j + 1
- local di = descriptions[ni]
- num[j] = f_unicode(ni)
- nam[j] = di and di.name or "-"
- end
- end
- return f_unilist(num,nam)
- else
- return "<error in base mode tracing>"
- end
-end
-
-local function cref(feature,lookuptags,lookupname)
- if lookupname then
- return formatters["feature %a, lookup %a"](feature,lookuptags[lookupname])
- else
- return formatters["feature %a"](feature)
- end
-end
-
-local function report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,comment)
- report_prepare("%s: base alternate %s => %s (%S => %S)",
- cref(feature,lookuptags,lookupname),
- gref(descriptions,unicode),
- replacement and gref(descriptions,replacement),
- value,
- comment)
-end
-
-local function report_substitution(feature,lookuptags,lookupname,descriptions,unicode,substitution)
- report_prepare("%s: base substitution %s => %S",
- cref(feature,lookuptags,lookupname),
- gref(descriptions,unicode),
- gref(descriptions,substitution))
-end
-
-local function report_ligature(feature,lookuptags,lookupname,descriptions,unicode,ligature)
- report_prepare("%s: base ligature %s => %S",
- cref(feature,lookuptags,lookupname),
- gref(descriptions,ligature),
- gref(descriptions,unicode))
-end
-
-local function report_kern(feature,lookuptags,lookupname,descriptions,unicode,otherunicode,value)
- report_prepare("%s: base kern %s + %s => %S",
- cref(feature,lookuptags,lookupname),
- gref(descriptions,unicode),
- gref(descriptions,otherunicode),
- value)
-end
-
-local basemethods = { }
-local basemethod = "<unset>"
-
-local function applybasemethod(what,...)
- local m = basemethods[basemethod][what]
- if m then
- return m(...)
- end
-end
-
--- We need to make sure that luatex sees the difference between
--- base fonts that have different glyphs in the same slots in fonts
--- that have the same fullname (or filename). LuaTeX will merge fonts
--- eventually (and subset later on). If needed we can use a more
--- verbose name as long as we don't use <()<>[]{}/%> and the length
--- is < 128.
-
-local basehash, basehashes, applied = { }, 1, { }
-
-local function registerbasehash(tfmdata)
- local properties = tfmdata.properties
- local hash = concat(applied," ")
- local base = basehash[hash]
- if not base then
- basehashes = basehashes + 1
- base = basehashes
- basehash[hash] = base
- end
- properties.basehash = base
- properties.fullname = properties.fullname .. "-" .. base
- -- report_prepare("fullname base hash '%a, featureset %a",tfmdata.properties.fullname,hash)
- applied = { }
-end
-
-local function registerbasefeature(feature,value)
- applied[#applied+1] = feature .. "=" .. tostring(value)
-end
-
--- The original basemode ligature builder used the names of components
--- and did some expression juggling to get the chain right. The current
--- variant starts with unicodes but still uses names to make the chain.
--- This is needed because we have to create intermediates when needed
--- but use predefined snippets when available. To some extend the
--- current builder is more stupid but I don't worry that much about it
--- as ligatures are rather predicatable.
---
--- Personally I think that an ff + i == ffi rule as used in for instance
--- latin modern is pretty weird as no sane person will key that in and
--- expect a glyph for that ligature plus the following character. Anyhow,
--- as we need to deal with this, we do, but no guarantes are given.
---
--- latin modern dejavu
---
--- f+f 102 102 102 102
--- f+i 102 105 102 105
--- f+l 102 108 102 108
--- f+f+i 102 102 105
--- f+f+l 102 102 108 102 102 108
--- ff+i 64256 105 64256 105
--- ff+l 64256 108
---
--- As you can see here, latin modern is less complete than dejavu but
--- in practice one will not notice it.
---
--- The while loop is needed because we need to resolve for instance
--- pseudo names like hyphen_hyphen to endash so in practice we end
--- up with a bit too many definitions but the overhead is neglectable.
---
--- We can have changed[first] or changed[second] but it quickly becomes
--- messy if we need to take that into account.
-
-local trace = false
-
-local function finalize_ligatures(tfmdata,ligatures)
- local nofligatures = #ligatures
- if nofligatures > 0 then
- local characters = tfmdata.characters
- local descriptions = tfmdata.descriptions
- local resources = tfmdata.resources
- local unicodes = resources.unicodes -- we use rawget in order to avoid bulding the table
- local private = resources.private
- local alldone = false
- while not alldone do
- local done = 0
- for i=1,nofligatures do
- local ligature = ligatures[i]
- if ligature then
- local unicode, lookupdata = ligature[1], ligature[2]
- if trace_ligatures_detail then
- report_prepare("building % a into %a",lookupdata,unicode)
- end
- local size = #lookupdata
- local firstcode = lookupdata[1] -- [2]
- local firstdata = characters[firstcode]
- local okay = false
- if firstdata then
- local firstname = "ctx_" .. firstcode
- for i=1,size-1 do -- for i=2,size-1 do
- local firstdata = characters[firstcode]
- if not firstdata then
- firstcode = private
- if trace_ligatures_detail then
- report_prepare("defining %a as %a",firstname,firstcode)
- end
- unicodes[firstname] = firstcode
- firstdata = { intermediate = true, ligatures = { } }
- characters[firstcode] = firstdata
- descriptions[firstcode] = { name = firstname }
- private = private + 1
- end
- local target
- local secondcode = lookupdata[i+1]
- local secondname = firstname .. "_" .. secondcode
- if i == size - 1 then
- target = unicode
- if not rawget(unicodes,secondname) then
- unicodes[secondname] = unicode -- map final ligature onto intermediates
- end
- okay = true
- else
- target = rawget(unicodes,secondname)
- if not target then
- break
- end
- end
- if trace_ligatures_detail then
- report_prepare("codes (%a,%a) + (%a,%a) -> %a",firstname,firstcode,secondname,secondcode,target)
- end
- local firstligs = firstdata.ligatures
- if firstligs then
- firstligs[secondcode] = { char = target }
- else
- firstdata.ligatures = { [secondcode] = { char = target } }
- end
- firstcode = target
- firstname = secondname
- end
- elseif trace_ligatures_detail then
- report_prepare("no glyph (%a,%a) for building %a",firstname,firstcode,target)
- end
- if okay then
- ligatures[i] = false
- done = done + 1
- end
- end
- end
- alldone = done == 0
- end
- if trace_ligatures_detail then
- for k, v in table.sortedhash(characters) do
- if v.ligatures then
- table.print(v,k)
- end
- end
- end
- resources.private = private
- return true
- end
-end
-
-local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
- local characters = tfmdata.characters
- local descriptions = tfmdata.descriptions
- local resources = tfmdata.resources
- local properties = tfmdata.properties
- local changed = tfmdata.changed
- local lookuphash = resources.lookuphash
- local lookuptypes = resources.lookuptypes
- local lookuptags = resources.lookuptags
-
- local ligatures = { }
- local alternate = tonumber(value) or true and 1
- local defaultalt = otf.defaultbasealternate
-
- local trace_singles = trace_baseinit and trace_singles
- local trace_alternatives = trace_baseinit and trace_alternatives
- local trace_ligatures = trace_baseinit and trace_ligatures
-
- local actions = {
- substitution = function(lookupdata,lookuptags,lookupname,description,unicode)
- if trace_singles then
- report_substitution(feature,lookuptags,lookupname,descriptions,unicode,lookupdata)
- end
- changed[unicode] = lookupdata
- end,
- alternate = function(lookupdata,lookuptags,lookupname,description,unicode)
- local replacement = lookupdata[alternate]
- if replacement then
- changed[unicode] = replacement
- if trace_alternatives then
- report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"normal")
- end
- elseif defaultalt == "first" then
- replacement = lookupdata[1]
- changed[unicode] = replacement
- if trace_alternatives then
- report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
- end
- elseif defaultalt == "last" then
- replacement = lookupdata[#data]
- if trace_alternatives then
- report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
- end
- else
- if trace_alternatives then
- report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"unknown")
- end
- end
- end,
- ligature = function(lookupdata,lookuptags,lookupname,description,unicode)
- if trace_ligatures then
- report_ligature(feature,lookuptags,lookupname,descriptions,unicode,lookupdata)
- end
- ligatures[#ligatures+1] = { unicode, lookupdata }
- end,
- }
-
- for unicode, character in next, characters do
- local description = descriptions[unicode]
- local lookups = description.slookups
- if lookups then
- for l=1,#lookuplist do
- local lookupname = lookuplist[l]
- local lookupdata = lookups[lookupname]
- if lookupdata then
- local lookuptype = lookuptypes[lookupname]
- local action = actions[lookuptype]
- if action then
- action(lookupdata,lookuptags,lookupname,description,unicode)
- end
- end
- end
- end
- local lookups = description.mlookups
- if lookups then
- for l=1,#lookuplist do
- local lookupname = lookuplist[l]
- local lookuplist = lookups[lookupname]
- if lookuplist then
- local lookuptype = lookuptypes[lookupname]
- local action = actions[lookuptype]
- if action then
- for i=1,#lookuplist do
- action(lookuplist[i],lookuptags,lookupname,description,unicode)
- end
- end
- end
- end
- end
- end
- properties.hasligatures = finalize_ligatures(tfmdata,ligatures)
-end
-
-local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist) -- todo what kind of kerns, currently all
- local characters = tfmdata.characters
- local descriptions = tfmdata.descriptions
- local resources = tfmdata.resources
- local properties = tfmdata.properties
- local lookuptags = resources.lookuptags
- local sharedkerns = { }
- local traceindeed = trace_baseinit and trace_kerns
- local haskerns = false
- for unicode, character in next, characters do
- local description = descriptions[unicode]
- local rawkerns = description.kerns -- shared
- if rawkerns then
- local s = sharedkerns[rawkerns]
- if s == false then
- -- skip
- elseif s then
- character.kerns = s
- else
- local newkerns = character.kerns
- local done = false
- for l=1,#lookuplist do
- local lookup = lookuplist[l]
- local kerns = rawkerns[lookup]
- if kerns then
- for otherunicode, value in next, kerns do
- if value == 0 then
- -- maybe no 0 test here
- elseif not newkerns then
- newkerns = { [otherunicode] = value }
- done = true
- if traceindeed then
- report_kern(feature,lookuptags,lookup,descriptions,unicode,otherunicode,value)
- end
- elseif not newkerns[otherunicode] then -- first wins
- newkerns[otherunicode] = value
- done = true
- if traceindeed then
- report_kern(feature,lookuptags,lookup,descriptions,unicode,otherunicode,value)
- end
- end
- end
- end
- end
- if done then
- sharedkerns[rawkerns] = newkerns
- character.kerns = newkerns -- no empty assignments
- haskerns = true
- else
- sharedkerns[rawkerns] = false
- end
- end
- end
- end
- properties.haskerns = haskerns
-end
-
-basemethods.independent = {
- preparesubstitutions = preparesubstitutions,
- preparepositionings = preparepositionings,
-}
-
-local function makefake(tfmdata,name,present)
- local resources = tfmdata.resources
- local private = resources.private
- local character = { intermediate = true, ligatures = { } }
- resources.unicodes[name] = private
- tfmdata.characters[private] = character
- tfmdata.descriptions[private] = { name = name }
- resources.private = private + 1
- present[name] = private
- return character
-end
-
-local function make_1(present,tree,name)
- for k, v in next, tree do
- if k == "ligature" then
- present[name] = v
- else
- make_1(present,v,name .. "_" .. k)
- end
- end
-end
-
-local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done,lookuptags,lookupname)
- for k, v in next, tree do
- if k == "ligature" then
- local character = characters[preceding]
- if not character then
- if trace_baseinit then
- report_prepare("weird ligature in lookup %a, current %C, preceding %C",lookuptags[lookupname],v,preceding)
- end
- character = makefake(tfmdata,name,present)
- end
- local ligatures = character.ligatures
- if ligatures then
- ligatures[unicode] = { char = v }
- else
- character.ligatures = { [unicode] = { char = v } }
- end
- if done then
- local d = done[lookupname]
- if not d then
- done[lookupname] = { "dummy", v }
- else
- d[#d+1] = v
- end
- end
- else
- local code = present[name] or unicode
- local name = name .. "_" .. k
- make_2(present,tfmdata,characters,v,name,code,k,done,lookuptags,lookupname)
- end
- end
-end
-
-local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
- local characters = tfmdata.characters
- local descriptions = tfmdata.descriptions
- local resources = tfmdata.resources
- local changed = tfmdata.changed
- local lookuphash = resources.lookuphash
- local lookuptypes = resources.lookuptypes
- local lookuptags = resources.lookuptags
-
- local ligatures = { }
- local alternate = tonumber(value) or true and 1
- local defaultalt = otf.defaultbasealternate
-
- local trace_singles = trace_baseinit and trace_singles
- local trace_alternatives = trace_baseinit and trace_alternatives
- local trace_ligatures = trace_baseinit and trace_ligatures
-
- for l=1,#lookuplist do
- local lookupname = lookuplist[l]
- local lookupdata = lookuphash[lookupname]
- local lookuptype = lookuptypes[lookupname]
- for unicode, data in next, lookupdata do
- if lookuptype == "substitution" then
- if trace_singles then
- report_substitution(feature,lookuptags,lookupname,descriptions,unicode,data)
- end
- changed[unicode] = data
- elseif lookuptype == "alternate" then
- local replacement = data[alternate]
- if replacement then
- changed[unicode] = replacement
- if trace_alternatives then
- report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"normal")
- end
- elseif defaultalt == "first" then
- replacement = data[1]
- changed[unicode] = replacement
- if trace_alternatives then
- report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
- end
- elseif defaultalt == "last" then
- replacement = data[#data]
- if trace_alternatives then
- report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,defaultalt)
- end
- else
- if trace_alternatives then
- report_alternate(feature,lookuptags,lookupname,descriptions,unicode,replacement,value,"unknown")
- end
- end
- elseif lookuptype == "ligature" then
- ligatures[#ligatures+1] = { unicode, data, lookupname }
- if trace_ligatures then
- report_ligature(feature,lookuptags,lookupname,descriptions,unicode,data)
- end
- end
- end
- end
-
- local nofligatures = #ligatures
-
- if nofligatures > 0 then
-
- local characters = tfmdata.characters
- local present = { }
- local done = trace_baseinit and trace_ligatures and { }
-
- for i=1,nofligatures do
- local ligature = ligatures[i]
- local unicode, tree = ligature[1], ligature[2]
- make_1(present,tree,"ctx_"..unicode)
- end
-
- for i=1,nofligatures do
- local ligature = ligatures[i]
- local unicode, tree, lookupname = ligature[1], ligature[2], ligature[3]
- make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,lookuptags,lookupname)
- end
-
- end
-
-end
-
-local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
- local characters = tfmdata.characters
- local descriptions = tfmdata.descriptions
- local resources = tfmdata.resources
- local properties = tfmdata.properties
- local lookuphash = resources.lookuphash
- local lookuptags = resources.lookuptags
- local traceindeed = trace_baseinit and trace_kerns
- -- check out this sharedkerns trickery
- for l=1,#lookuplist do
- local lookupname = lookuplist[l]
- local lookupdata = lookuphash[lookupname]
- for unicode, data in next, lookupdata do
- local character = characters[unicode]
- local kerns = character.kerns
- if not kerns then
- kerns = { }
- character.kerns = kerns
- end
- if traceindeed then
- for otherunicode, kern in next, data do
- if not kerns[otherunicode] and kern ~= 0 then
- kerns[otherunicode] = kern
- report_kern(feature,lookuptags,lookup,descriptions,unicode,otherunicode,kern)
- end
- end
- else
- for otherunicode, kern in next, data do
- if not kerns[otherunicode] and kern ~= 0 then
- kerns[otherunicode] = kern
- end
- end
- end
- end
- end
-
-end
-
-local function initializehashes(tfmdata)
- nodeinitializers.features(tfmdata)
-end
-
-basemethods.shared = {
- initializehashes = initializehashes,
- preparesubstitutions = preparesubstitutions,
- preparepositionings = preparepositionings,
-}
-
-basemethod = "independent"
-
-local function featuresinitializer(tfmdata,value)
- if true then -- value then
- local starttime = trace_preparing and os.clock()
- local features = tfmdata.shared.features
- local fullname = tfmdata.properties.fullname or "?"
- if features then
- applybasemethod("initializehashes",tfmdata)
- local collectlookups = otf.collectlookups
- local rawdata = tfmdata.shared.rawdata
- local properties = tfmdata.properties
- local script = properties.script -- or "dflt" -- can be nil
- local language = properties.language -- or "dflt" -- can be nil
- local basesubstitutions = rawdata.resources.features.gsub
- local basepositionings = rawdata.resources.features.gpos
- --
- -- if basesubstitutions then
- -- for feature, data in next, basesubstitutions do
- -- local value = features[feature]
- -- if value then
- -- local validlookups, lookuplist = collectlookups(rawdata,feature,script,language)
- -- if validlookups then
- -- applybasemethod("preparesubstitutions",tfmdata,feature,value,validlookups,lookuplist)
- -- registerbasefeature(feature,value)
- -- end
- -- end
- -- end
- -- end
- -- if basepositionings then
- -- for feature, data in next, basepositionings do
- -- local value = features[feature]
- -- if value then
- -- local validlookups, lookuplist = collectlookups(rawdata,feature,script,language)
- -- if validlookups then
- -- applybasemethod("preparepositionings",tfmdata,feature,features[feature],validlookups,lookuplist)
- -- registerbasefeature(feature,value)
- -- end
- -- end
- -- end
- -- end
- --
- if basesubstitutions or basepositionings then
- local sequences = tfmdata.resources.sequences
- for s=1,#sequences do
- local sequence = sequences[s]
- local sfeatures = sequence.features
- if sfeatures then
- local order = sequence.order
- if order then
- for i=1,#order do --
- local feature = order[i]
- local value = features[feature]
- if value then
- local validlookups, lookuplist = collectlookups(rawdata,feature,script,language)
- if not validlookups then
- -- skip
- elseif basesubstitutions and basesubstitutions[feature] then
- if trace_preparing then
- report_prepare("filtering base %s feature %a for %a with value %a","sub",feature,fullname,value)
- end
- applybasemethod("preparesubstitutions",tfmdata,feature,value,validlookups,lookuplist)
- registerbasefeature(feature,value)
- 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
- applybasemethod("preparepositionings",tfmdata,feature,value,validlookups,lookuplist)
- registerbasefeature(feature,value)
- end
- end
- end
- end
- end
- end
- end
- --
- registerbasehash(tfmdata)
- end
- if trace_preparing then
- report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,fullname)
- end
- end
-end
-
-registerotffeature {
- name = "features",
- description = "features",
- default = true,
- initializers = {
- -- position = 1, -- after setscript (temp hack ... we need to force script / language to 1
- base = featuresinitializer,
- }
-}
-
--- independent : collect lookups independently (takes more runtime ... neglectable)
--- shared : shares lookups with node mode (takes more memory unless also a node mode variant is used ... noticeable)
-
-directives.register("fonts.otf.loader.basemethod", function(v)
- if basemethods[v] then
- basemethod = v
- end
-end)
diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua
index 034cba613..0af588b74 100644
--- a/tex/context/base/mkiv/font-otc.lua
+++ b/tex/context/base/mkiv/font-otc.lua
@@ -1,6 +1,6 @@
if not modules then modules = { } end modules ['font-otc'] = {
version = 1.001,
- comment = "companion to font-otf.lua (context)",
+ comment = "companion to font-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
diff --git a/tex/context/base/mkiv/font-otf.lua b/tex/context/base/mkiv/font-otf.lua
deleted file mode 100644
index 1db80272e..000000000
--- a/tex/context/base/mkiv/font-otf.lua
+++ /dev/null
@@ -1,2968 +0,0 @@
-if not modules then modules = { } end modules ['font-otf'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- langs -> languages enz
--- anchor_classes vs kernclasses
--- modification/creationtime in subfont is runtime dus zinloos
--- to_table -> totable
--- ascent descent
-
--- to be checked: combinations like:
---
--- current="ABCD" with [A]=nothing, [BC]=ligature, [D]=single (applied to result of BC so funny index)
---
--- unlikely but possible
-
--- more checking against low level calls of functions
-
-local gmatch, gsub, find, match, lower, strip = string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
-local type, next, tonumber, tostring = type, next, tonumber, tostring
-local abs = math.abs
-local reversed, concat, insert, remove, sortedkeys = table.reversed, table.concat, table.insert, table.remove, table.sortedkeys
-local fastcopy, tohash, derivetable, copy = table.fastcopy, table.tohash, table.derive, table.copy
-local formatters = string.formatters
-local P, R, S, C, Ct, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.match
-
-local setmetatableindex = table.setmetatableindex
-local allocate = utilities.storage.allocate
-local registertracker = trackers.register
-local registerdirective = directives.register
-local starttiming = statistics.starttiming
-local stoptiming = statistics.stoptiming
-local elapsedtime = statistics.elapsedtime
-local findbinfile = resolvers.findbinfile
-
-local trace_private = false registertracker("otf.private", function(v) trace_private = v end)
-local trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end)
-local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end)
-local trace_features = false registertracker("otf.features", function(v) trace_features = v end)
-local trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end)
-local trace_sequences = false registertracker("otf.sequences", function(v) trace_sequences = v end)
-local trace_markwidth = false registertracker("otf.markwidth", function(v) trace_markwidth = v end)
-local trace_defining = false registertracker("fonts.defining", function(v) trace_defining = v end)
-
-local compact_lookups = true registertracker("otf.compactlookups", function(v) compact_lookups = v end)
-local purge_names = true registertracker("otf.purgenames", function(v) purge_names = v end)
-
-local report_otf = logs.reporter("fonts","otf loading")
-
-local fonts = fonts
-local otf = fonts.handlers.otf
-
-otf.glists = { "gsub", "gpos" }
-
-otf.version = 2.826 -- beware: also sync font-mis.lua and in mtx-fonts
-otf.cache = containers.define("fonts", "otf", otf.version, true)
-
-local hashes = fonts.hashes
-local definers = fonts.definers
-local readers = fonts.readers
-local constructors = fonts.constructors
-
-local fontdata = hashes and hashes.identifiers
-local chardata = characters and characters.data -- not used
-
-local otffeatures = constructors.features.otf
-local registerotffeature = otffeatures.register
-
-local otfenhancers = constructors.enhancers.otf
-local registerotfenhancer = otfenhancers.register
-
-local forceload = false
-local cleanup = 0 -- mk: 0=885M 1=765M 2=735M (regular run 730M)
-local packdata = true
-local syncspace = true
-local forcenotdef = false
-local includesubfonts = false
-local overloadkerns = false -- experiment
-
-local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
-
-local wildcard = "*"
-local default = "dflt"
-
-local fontloader = fontloader
-local open_font = fontloader.open
-local close_font = fontloader.close
-local font_fields = fontloader.fields
-local apply_featurefile = fontloader.apply_featurefile
-
-local mainfields = nil
-local glyphfields = nil -- not used yet
-
-local formats = fonts.formats
-
-formats.otf = "opentype"
-formats.ttf = "truetype"
-formats.ttc = "truetype"
-formats.dfont = "truetype"
-
-registerdirective("fonts.otf.loader.cleanup", function(v) cleanup = tonumber(v) or (v and 1) or 0 end)
-registerdirective("fonts.otf.loader.force", function(v) forceload = v end)
-registerdirective("fonts.otf.loader.pack", function(v) packdata = v end)
-registerdirective("fonts.otf.loader.syncspace", function(v) syncspace = v end)
-registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef = v end)
-registerdirective("fonts.otf.loader.overloadkerns", function(v) overloadkerns = v end)
------------------("fonts.otf.loader.alldimensions", function(v) alldimensions = v end)
-
-function otf.fileformat(filename)
- local leader = lower(io.loadchunk(filename,4))
- local suffix = lower(file.suffix(filename))
- if leader == "otto" then
- return formats.otf, suffix == "otf"
- elseif leader == "ttcf" then
- return formats.ttc, suffix == "ttc"
- -- elseif leader == "true" then
- -- return formats.ttf, suffix == "ttf"
- elseif suffix == "ttc" then
- return formats.ttc, true
- elseif suffix == "dfont" then
- return formats.dfont, true
- else
- return formats.ttf, suffix == "ttf"
- end
-end
-
--- local function otf_format(filename)
--- -- return formats[lower(file.suffix(filename))]
--- end
-
-local function otf_format(filename)
- local format, okay = otf.fileformat(filename)
- if not okay then
- report_otf("font %a is actually an %a file",filename,format)
- end
- return format
-end
-
-local function load_featurefile(raw,featurefile)
- if featurefile and featurefile ~= "" then
- if trace_loading then
- report_otf("using featurefile %a", featurefile)
- end
- apply_featurefile(raw, featurefile)
- end
-end
-
-local function showfeatureorder(rawdata,filename)
- local sequences = rawdata.resources.sequences
- if sequences and #sequences > 0 then
- if trace_loading then
- report_otf("font %a has %s sequences",filename,#sequences)
- report_otf(" ")
- end
- for nos=1,#sequences do
- local sequence = sequences[nos]
- local typ = sequence.type or "no-type"
- local name = sequence.name or "no-name"
- local subtables = sequence.subtables or { "no-subtables" }
- local features = sequence.features
- if trace_loading then
- report_otf("%3i %-15s %-20s [% t]",nos,name,typ,subtables)
- end
- if features then
- for feature, scripts in next, features do
- local tt = { }
- if type(scripts) == "table" then
- for script, languages in next, scripts do
- local ttt = { }
- for language, _ in next, languages do
- ttt[#ttt+1] = language
- end
- tt[#tt+1] = formatters["[%s: % t]"](script,ttt)
- end
- if trace_loading then
- report_otf(" %s: % t",feature,tt)
- end
- else
- if trace_loading then
- report_otf(" %s: %S",feature,scripts)
- end
- end
- end
- end
- end
- if trace_loading then
- report_otf("\n")
- end
- elseif trace_loading then
- report_otf("font %a has no sequences",filename)
- end
-end
-
---[[ldx--
-<p>We start with a lot of tables and related functions.</p>
---ldx]]--
-
-local valid_fields = table.tohash {
- -- "anchor_classes",
- "ascent",
- -- "cache_version",
- "cidinfo",
- "copyright",
- -- "creationtime",
- "descent",
- "design_range_bottom",
- "design_range_top",
- "design_size",
- "encodingchanged",
- "extrema_bound",
- "familyname",
- "fontname",
- "fontstyle_id",
- "fontstyle_name",
- "fullname",
- -- "glyphs",
- "hasvmetrics",
- -- "head_optimized_for_cleartype",
- "horiz_base",
- "issans",
- "isserif",
- "italicangle",
- -- "kerns",
- -- "lookups",
- "macstyle",
- -- "modificationtime",
- "notdef_loc",
- "onlybitmaps",
- "origname",
- "os2_version",
- "pfminfo",
- -- "private",
- "serifcheck",
- "sfd_version",
- -- "size",
- "strokedfont",
- "strokewidth",
- -- "subfonts",
- "table_version",
- -- "tables",
- -- "ttf_tab_saved",
- "ttf_tables",
- "uni_interp",
- "uniqueid",
- "units_per_em",
- "upos",
- "use_typo_metrics",
- "uwidth",
- "validation_state",
- "version",
- "vert_base",
- "weight",
- "weight_width_slope_only",
- -- "xuid",
- -- "truetype", -- maybe as check
-}
-
-local function adddimensions(data,filename)
- -- todo: forget about the width if it's the defaultwidth (saves mem)
- -- we could also build the marks hash here (instead of storing it)
- if data then
- local descriptions = data.descriptions
- local resources = data.resources
- local defaultwidth = resources.defaultwidth or 0
- local defaultheight = resources.defaultheight or 0
- local defaultdepth = resources.defaultdepth or 0
- local basename = trace_markwidth and file.basename(filename)
- for _, d in next, descriptions do
- local bb, wd = d.boundingbox, d.width
- if not wd then
- -- or bb?
- d.width = defaultwidth
- elseif trace_markwidth and wd ~= 0 and d.class == "mark" then
- report_otf("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
- -- d.width = -wd
- end
- if bb then
- local ht = bb[4]
- local dp = -bb[2]
- -- if alldimensions then
- -- if ht ~= 0 then
- -- d.height = ht
- -- end
- -- if dp ~= 0 then
- -- d.depth = dp
- -- end
- -- else
- if ht == 0 or ht < 0 then
- -- not set
- else
- d.height = ht
- end
- if dp == 0 or dp < 0 then
- -- not set
- else
- d.depth = dp
- end
- -- end
- end
- end
- end
-end
-
-function otf.load(filename,sub,featurefile) -- second argument (format) is gone !
- local base = file.basename(file.removesuffix(filename))
- local name = file.removesuffix(base)
- local attr = lfs.attributes(filename)
- local size = attr and attr.size or 0
- local time = attr and attr.modification or 0
- if featurefile then
- name = name .. "@" .. file.removesuffix(file.basename(featurefile))
- end
- -- or: sub = tonumber(sub)
- if sub == "" then
- sub = false
- end
- local hash = name
- if sub then
- hash = hash .. "-" .. sub
- end
- hash = containers.cleanname(hash)
- local featurefiles
- if featurefile then
- featurefiles = { }
- for s in gmatch(featurefile,"[^,]+") do
- local name = resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
- if name == "" then
- report_otf("loading error, no featurefile %a",s)
- else
- local attr = lfs.attributes(name)
- featurefiles[#featurefiles+1] = {
- name = name,
- size = attr and attr.size or 0,
- time = attr and attr.modification or 0,
- }
- end
- end
- if #featurefiles == 0 then
- featurefiles = nil
- end
- end
- local data = containers.read(otf.cache,hash)
- local reload = not data or data.size ~= size or data.time ~= time
- if forceload then
- report_otf("forced reload of %a due to hard coded flag",filename)
- reload = true
- end
- if not reload then
- local featuredata = data.featuredata
- if featurefiles then
- if not featuredata or #featuredata ~= #featurefiles then
- reload = true
- else
- for i=1,#featurefiles do
- local fi, fd = featurefiles[i], featuredata[i]
- if fi.name ~= fd.name or fi.size ~= fd.size or fi.time ~= fd.time then
- reload = true
- break
- end
- end
- end
- elseif featuredata then
- reload = true
- end
- if reload then
- report_otf("loading: forced reload due to changed featurefile specification %a",featurefile)
- end
- end
- if reload then
- starttiming("fontloader")
- report_otf("loading %a, hash %a",filename,hash)
- local fontdata, messages
- if sub then
- fontdata, messages = open_font(filename,sub)
- else
- fontdata, messages = open_font(filename)
- end
- if fontdata then
- mainfields = mainfields or (font_fields and font_fields(fontdata))
- end
- if trace_loading and messages and #messages > 0 then
- if type(messages) == "string" then
- report_otf("warning: %s",messages)
- else
- for m=1,#messages do
- report_otf("warning: %S",messages[m])
- end
- end
- else
- report_otf("loading done")
- end
- if fontdata then
- if featurefiles then
- for i=1,#featurefiles do
- load_featurefile(fontdata,featurefiles[i].name)
- end
- end
- local unicodes = {
- -- names to unicodes
- }
- local splitter = lpeg.splitter(" ",unicodes)
- data = {
- size = size,
- time = time,
- subfont = sub,
- format = otf_format(filename),
- featuredata = featurefiles,
- resources = {
- filename = resolvers.unresolve(filename), -- no shortcut
- version = otf.version,
- creator = "context mkiv",
- unicodes = unicodes,
- indices = {
- -- index to unicodes
- },
- duplicates = {
- -- alternative unicodes
- },
- variants = {
- -- alternative unicodes (variants)
- },
- lookuptypes = {
- },
- },
- warnings = {
- },
- metadata = {
- -- raw metadata, not to be used
- },
- properties = {
- -- normalized metadata
- },
- descriptions = {
- },
- goodies = {
- },
- helpers = { -- might go away
- tounicodelist = splitter,
- tounicodetable = Ct(splitter),
- },
- }
- report_otf("file size: %s", size)
- otfenhancers.apply(data,filename,fontdata)
- local packtime = { }
- if packdata then
- if cleanup > 0 then
- collectgarbage("collect")
- end
- starttiming(packtime)
- otf.packdata(data,filename,nil) -- implemented elsewhere
- stoptiming(packtime)
- end
- report_otf("saving %a in cache",filename)
- data = containers.write(otf.cache, hash, data)
- if cleanup > 1 then
- collectgarbage("collect")
- end
- stoptiming("fontloader")
- if elapsedtime then
- report_otf("loading, optimizing, packing and caching time %s, pack time %s",
- elapsedtime("fontloader"),packdata and elapsedtime(packtime) or 0)
- end
- close_font(fontdata) -- free memory
- if cleanup > 3 then
- collectgarbage("collect")
- end
- data = containers.read(otf.cache, hash) -- this frees the old table and load the sparse one
- if cleanup > 2 then
- collectgarbage("collect")
- end
- else
- stoptiming("fontloader")
- data = nil
- report_otf("loading failed due to read error")
- end
- end
- if data then
- if trace_defining then
- report_otf("loading from cache using hash %a",hash)
- end
- otf.unpackdata(data,filename,nil,false) -- implemented elsewhere
- --
- local resources = data.resources
- local lookuptags = resources.lookuptags
- local unicodes = resources.unicodes
- if not lookuptags then
- lookuptags = { }
- resources.lookuptags = lookuptags
- end
- setmetatableindex(lookuptags,function(t,k)
- local v = type(k) == "number" and ("lookup " .. k) or k
- t[k] = v
- return v
- end)
- if not unicodes then
- unicodes = { }
- resources.unicodes = unicodes
- setmetatableindex(unicodes,function(t,k)
- -- use rawget when no table has to be built
- setmetatableindex(unicodes,nil)
- for u, d in next, data.descriptions do
- local n = d.name
- if n then
- t[n] = u
- -- report_otf("accessing known name %a",k)
- else
- -- report_otf("accessing unknown name %a",k)
- end
- end
- return rawget(t,k)
- end)
- end
- constructors.addcoreunicodes(unicodes) -- do we really need this?
- --
- if applyruntimefixes then
- applyruntimefixes(filename,data)
- end
- adddimensions(data,filename,nil,false)
- if trace_sequences then
- showfeatureorder(data,filename)
- end
- end
- return data
-end
-
-local mt = {
- __index = function(t,k) -- maybe set it
- if k == "height" then
- local ht = t.boundingbox[4]
- return ht < 0 and 0 or ht
- elseif k == "depth" then
- local dp = -t.boundingbox[2]
- return dp < 0 and 0 or dp
- elseif k == "width" then
- return 0
- elseif k == "name" then -- or maybe uni*
- return forcenotdef and ".notdef"
- end
- end
-}
-
-local function enhance_prepare_tables(data,filename,raw)
- data.properties.hasitalics = false
-end
-
-local function somecopy(old) -- fast one
- if old then
- local new = { }
- if type(old) == "table" then
- for k, v in next, old do
- if k == "glyphs" then
- -- skip
- elseif type(v) == "table" then
- new[k] = somecopy(v)
- else
- new[k] = v
- end
- end
- else
- for i=1,#mainfields do
- local k = mainfields[i]
- local v = old[k]
- if k == "glyphs" then
- -- skip
- elseif type(v) == "table" then
- new[k] = somecopy(v)
- else
- new[k] = v
- end
- end
- end
- return new
- else
- return { }
- end
-end
-
--- not setting hasitalics and class (when nil) during table construction can save some mem
-
-local function enhance_prepare_glyphs(data,filename,raw)
- local rawglyphs = raw.glyphs
- local rawsubfonts = raw.subfonts
- local rawcidinfo = raw.cidinfo
- local criterium = constructors.privateoffset
- local private = criterium
- local resources = data.resources
- local metadata = data.metadata
- local properties = data.properties
- local descriptions = data.descriptions
- local unicodes = resources.unicodes -- name to unicode
- local indices = resources.indices -- index to unicode
- local duplicates = resources.duplicates
- local variants = resources.variants
- local notdefindex = -1
-
- if rawsubfonts then
-
- metadata.subfonts = includesubfonts and { }
- properties.cidinfo = rawcidinfo
-
- if rawcidinfo.registry then
- local cidmap = fonts.cid.getmap(rawcidinfo)
- if cidmap then
- rawcidinfo.usedname = cidmap.usedname
- local nofnames = 0
- local nofunicodes = 0
- local cidunicodes = cidmap.unicodes
- local cidnames = cidmap.names
- local cidtotal = 0
- local unique = trace_subfonts and { }
- for cidindex=1,#rawsubfonts do
- local subfont = rawsubfonts[cidindex]
- local cidglyphs = subfont.glyphs
- if includesubfonts then
- metadata.subfonts[cidindex] = somecopy(subfont)
- end
- local cidcnt = subfont.glyphcnt
- local cidmin = subfont.glyphmin
- local cidmax = subfont.glyphmax
- local notdef = (tonumber(raw.table_version) or 0) > 0.4 and subfont.notdef_loc or -1
- if notdeffound == -1 and notdef >= 0 then
- notdeffound = notdef
- end
- if trace_subfonts then
- local cidtot = cidmax - cidmin + 1
- cidtotal = cidtotal + cidtot
- report_otf("subfont: %i, min: %i, max: %i, cnt: %i, n: %i",cidindex,cidmin,cidmax,cidtot,cidcnt)
- end
- if cidcnt > 0 then
- for index=cidmin,cidmax do
- local glyph = cidglyphs[index]
- if glyph then
- if trace_subfonts then
- unique[index] = true
- end
- local unicode = glyph.unicode
- if unicode >= 0x00E000 and unicode <= 0x00F8FF then
- unicode = -1
- elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFD then
- unicode = -1
- elseif unicode >= 0x100000 and unicode <= 0x10FFFD then
- unicode = -1
- end
- local name = glyph.name or cidnames[index]
- if not unicode or unicode == -1 then -- or unicode >= criterium then
- unicode = cidunicodes[index]
- end
- if unicode and descriptions[unicode] then
- if trace_private then
- report_otf("preventing glyph %a at index %H to overload unicode %U",name or "noname",index,unicode)
- end
- unicode = -1
- end
- if not unicode or unicode == -1 then -- or unicode >= criterium then
- if not name then
- name = formatters["u%06X.ctx"](private)
- end
- unicode = private
- unicodes[name] = private
- if trace_private then
- report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
- end
- private = private + 1
- nofnames = nofnames + 1
- else
- -- if unicode > criterium then
- -- local taken = descriptions[unicode]
- -- if taken then
- -- private = private + 1
- -- descriptions[private] = taken
- -- unicodes[taken.name] = private
- -- indices[taken.index] = private
- -- if trace_private then
- -- report_otf("slot %U is moved to %U due to private in font",unicode)
- -- end
- -- end
- -- end
- if not name then
- name = formatters["u%06X.ctx"](unicode)
- end
- unicodes[name] = unicode
- nofunicodes = nofunicodes + 1
- end
- indices[index] = unicode -- each index is unique (at least now)
- local description = {
- -- width = glyph.width,
- boundingbox = glyph.boundingbox,
- -- name = glyph.name or name or "unknown", -- uniXXXX
- name = name or "unknown", -- uniXXXX
- -- cidindex = cidindex,
- index = index,
- glyph = glyph,
- }
- descriptions[unicode] = description
- local altuni = glyph.altuni
- if altuni then
- -- local d
- for i=1,#altuni do
- local a = altuni[i]
- local u = a.unicode
- if u ~= unicode then
- local v = a.variant
- if v then
- -- tricky: no addition to d? needs checking but in practice such dups are either very simple
- -- shapes or e.g cjk with not that many features
- local vv = variants[v]
- if vv then
- vv[u] = unicode
- else -- xits-math has some:
- vv = { [u] = unicode }
- variants[v] = vv
- end
- -- elseif d then
- -- d[#d+1] = u
- -- else
- -- d = { u }
- end
- end
- end
- -- if d then
- -- duplicates[unicode] = d -- is this needed ?
- -- end
- end
- end
- end
- else
- report_otf("potential problem: no glyphs found in subfont %i",cidindex)
- end
- end
- if trace_subfonts then
- report_otf("nofglyphs: %i, unique: %i",cidtotal,table.count(unique))
- end
- if trace_loading then
- report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
- end
- elseif trace_loading then
- report_otf("unable to remap cid font, missing cid file for %a",filename)
- end
- elseif trace_loading then
- report_otf("font %a has no glyphs",filename)
- end
-
- else
-
- local cnt = raw.glyphcnt or 0
- local min = raw.glyphmin or 0
- local max = raw.glyphmax or (raw.glyphcnt - 1)
- notdeffound = (tonumber(raw.table_version) or 0) > 0.4 and raw.notdef_loc or -1
- if cnt > 0 then
- for index=min,max do
- local glyph = rawglyphs[index]
- if glyph then
- local unicode = glyph.unicode
- local name = glyph.name
- if not unicode or unicode == -1 then -- or unicode >= criterium then
- unicode = private
- unicodes[name] = private
- if trace_private then
- report_otf("glyph %a at index %H is moved to private unicode slot %U",name,index,private)
- end
- private = private + 1
- else
- -- We have a font that uses and exposes the private area. As this is rather unreliable it's
- -- advised no to trust slots here (better use glyphnames). Anyway, we need a double check:
- -- we need to move already moved entries and we also need to bump the next private to after
- -- the (currently) last slot. This could leave us with a hole but we have holes anyway.
- if unicode > criterium then
- -- \definedfont[file:HANBatang-LVT.ttf] \fontchar{uF0135} \char"F0135
- local taken = descriptions[unicode]
- if taken then
- if unicode >= private then
- private = unicode + 1 -- restart private (so we can have mixed now)
- else
- private = private + 1 -- move on
- end
- descriptions[private] = taken
- unicodes[taken.name] = private
- indices[taken.index] = private
- if trace_private then
- report_otf("slot %U is moved to %U due to private in font",unicode)
- end
- else
- if unicode >= private then
- private = unicode + 1 -- restart (so we can have mixed now)
- end
- end
- end
- unicodes[name] = unicode
- end
- indices[index] = unicode
- -- if not name then
- -- name = formatters["u%06X"](unicode) -- u%06X.ctx
- -- end
- descriptions[unicode] = {
- -- width = glyph.width,
- boundingbox = glyph.boundingbox,
- name = name,
- index = index,
- glyph = glyph,
- }
- local altuni = glyph.altuni
- if altuni then
- -- local d
- for i=1,#altuni do
- local a = altuni[i]
- local u = a.unicode
- if u ~= unicode then
- local v = a.variant
- if v then
- -- tricky: no addition to d? needs checking but in practice such dups are either very simple
- -- shapes or e.g cjk with not that many features
- local vv = variants[v]
- if vv then
- vv[u] = unicode
- else -- xits-math has some:
- vv = { [u] = unicode }
- variants[v] = vv
- end
- -- elseif d then
- -- d[#d+1] = u
- -- else
- -- d = { u }
- end
- end
- end
- -- if d then
- -- duplicates[unicode] = d -- is this needed ?
- -- end
- end
- else
- report_otf("potential problem: glyph %U is used but empty",index)
- end
- end
- else
- report_otf("potential problem: no glyphs found")
- end
-
- end
-
- if notdeffound == -1 then
- report_otf("warning: no .notdef found in %a",filename)
- elseif notdeffound ~= 0 then
- report_otf("warning: .notdef found at position %a in %a",notdeffound,filename)
- end
- metadata.notdef = notdeffound
-
- resources.private = private
-
-end
-
--- the next one is still messy but will get better when we have
--- flattened map/enc tables in the font loader
-
--- the next one is not using a valid base for unicode privates
---
--- PsuedoEncodeUnencoded(EncMap *map,struct ttfinfo *info)
-
-local function enhance_check_encoding(data,filename,raw)
- local descriptions = data.descriptions
- local resources = data.resources
- local properties = data.properties
- local unicodes = resources.unicodes -- name to unicode
- local indices = resources.indices -- index to unicodes
- local duplicates = resources.duplicates
-
- -- begin of messy (not needed when cidmap)
-
- local mapdata = raw.map or { }
- local unicodetoindex = mapdata and mapdata.map or { }
- local indextounicode = mapdata and mapdata.backmap or { }
- -- local encname = lower(data.enc_name or raw.enc_name or mapdata.enc_name or "")
- local encname = lower(data.enc_name or mapdata.enc_name or "")
- local criterium = 0xFFFF -- for instance cambria has a lot of mess up there
- local privateoffset = constructors.privateoffset
-
- -- end of messy
-
- if find(encname,"unicode") then -- unicodebmp, unicodefull, ...
- if trace_loading then
- report_otf("checking embedded unicode map %a",encname)
- end
- local reported = { }
- -- we loop over the original unicode->index mapping but we
- -- need to keep in mind that that one can have weird entries
- -- so we need some extra checking
- for maybeunicode, index in next, unicodetoindex do
- if descriptions[maybeunicode] then
- -- we ignore invalid unicodes (unicode = -1) (ff can map wrong to non private)
- else
- local unicode = indices[index]
- if not unicode then
- -- weird (cjk or so?)
- elseif maybeunicode == unicode then
- -- no need to add
- elseif unicode > privateoffset then
- -- we have a non-unicode
- else
- local d = descriptions[unicode]
- if d then
- local c = d.copies
- if c then
- c[maybeunicode] = true
- else
- d.copies = { [maybeunicode] = true }
- end
- elseif index and not reported[index] then
- report_otf("missing index %i",index)
- reported[index] = true
- end
- end
- end
- end
- for unicode, data in next, descriptions do
- local d = data.copies
- if d then
- duplicates[unicode] = sortedkeys(d)
- data.copies = nil
- end
- end
- elseif properties.cidinfo then
- report_otf("warning: no unicode map, used cidmap %a",properties.cidinfo.usedname)
- else
- report_otf("warning: non unicode map %a, only using glyph unicode data",encname or "whatever")
- end
-
- if mapdata then
- mapdata.map = { } -- clear some memory (virtual and created each time anyway)
- mapdata.backmap = { } -- clear some memory (virtual and created each time anyway)
- end
-end
-
--- for the moment we assume that a font with lookups will not use
--- altuni so we stick to kerns only .. alternatively we can always
--- do an indirect lookup uni_to_uni . but then we need that in
--- all lookups
-
-local function enhance_add_duplicates(data,filename,raw)
- local descriptions = data.descriptions
- local resources = data.resources
- local properties = data.properties
- local unicodes = resources.unicodes -- name to unicode
- local indices = resources.indices -- index to unicodes
- local duplicates = resources.duplicates
- -- for unicode, d in next, duplicates do
- for unicode, d in table.sortedhash(duplicates) do -- nicer for log
- local nofduplicates = #d
- if nofduplicates > 4 then
- if trace_loading then
- report_otf("ignoring excessive duplicates of %U (n=%s)",unicode,nofduplicates)
- end
- else
- -- local validduplicates = { }
- for i=1,nofduplicates do
- local u = d[i]
- if not descriptions[u] then
- local description = descriptions[unicode]
- local n = 0
- for _, description in next, descriptions do
- local kerns = description.kerns
- if kerns then
- for _, k in next, kerns do
- local ku = k[unicode]
- if ku then
- k[u] = ku
- n = n + 1
- end
- end
- end
- -- todo: lookups etc
- end
- if u > 0 then -- and
- local duplicate = copy(description) -- else packing problem
- duplicate.comment = formatters["copy of %U"](unicode)
- descriptions[u] = duplicate
- -- validduplicates[#validduplicates+1] = u
- if trace_loading then
- report_otf("duplicating %06U to %06U with index %H (%s kerns)",unicode,u,description.index,n)
- end
- end
- end
- end
- -- duplicates[unicode] = #validduplicates > 0 and validduplicates or nil
- end
- end
-end
-
--- class : nil base mark ligature component (maybe we don't need it in description)
--- boundingbox: split into ht/dp takes more memory (larger tables and less sharing)
-
-local function enhance_analyze_glyphs(data,filename,raw) -- maybe integrate this in the previous
- local descriptions = data.descriptions
- local resources = data.resources
- local metadata = data.metadata
- local properties = data.properties
- local hasitalics = false
- local widths = { }
- local marks = { } -- always present (saves checking)
- for unicode, description in next, descriptions do
- local glyph = description.glyph
- local italic = glyph.italic_correction -- only in a math font (we also have vert/horiz)
- if not italic then
- -- skip
- elseif italic == 0 then
- -- skip
- else
- description.italic = italic
- hasitalics = true
- end
- local width = glyph.width
- widths[width] = (widths[width] or 0) + 1
- local class = glyph.class
- if class then
- if class == "mark" then
- marks[unicode] = true
- end
- description.class = class
- end
- end
- -- flag italic
- properties.hasitalics = hasitalics
- -- flag marks
- resources.marks = marks
- -- share most common width for cjk fonts
- local wd, most = 0, 1
- for k,v in next, widths do
- if v > most then
- wd, most = k, v
- end
- end
- if most > 1000 then -- maybe 500
- if trace_loading then
- report_otf("most common width: %s (%s times), sharing (cjk font)",wd,most)
- end
- for unicode, description in next, descriptions do
- if description.width == wd then
- -- description.width = nil
- else
- description.width = description.glyph.width
- end
- end
- resources.defaultwidth = wd
- else
- for unicode, description in next, descriptions do
- description.width = description.glyph.width
- end
- end
-end
-
-local function enhance_reorganize_mark_classes(data,filename,raw)
- local mark_classes = raw.mark_classes
- if mark_classes then
- local resources = data.resources
- local unicodes = resources.unicodes
- local markclasses = { }
- resources.markclasses = markclasses -- reversed
- for name, class in next, mark_classes do
- local t = { }
- for s in gmatch(class,"[^ ]+") do
- t[unicodes[s]] = true
- end
- markclasses[name] = t
- end
- end
-end
-
-local function enhance_reorganize_features(data,filename,raw) -- combine with other
- local features = { }
- data.resources.features = features
- for k=1,#otf.glists do
- local what = otf.glists[k]
- local dw = raw[what]
- if dw then
- local f = { }
- features[what] = f
- for i=1,#dw do
- local d= dw[i]
- local dfeatures = d.features
- if dfeatures then
- for i=1,#dfeatures do
- local df = dfeatures[i]
- local tag = strip(lower(df.tag))
- local ft = f[tag]
- if not ft then
- ft = { }
- f[tag] = ft
- end
- local dscripts = df.scripts
- for i=1,#dscripts do
- local d = dscripts[i]
- local languages = d.langs
- local script = strip(lower(d.script))
- local fts = ft[script] if not fts then fts = {} ft[script] = fts end
- for i=1,#languages do
- fts[strip(lower(languages[i]))] = true
- end
- end
- end
- end
- end
- end
- end
-end
-
-local function enhance_reorganize_anchor_classes(data,filename,raw)
- local resources = data.resources
- local anchor_to_lookup = { }
- local lookup_to_anchor = { }
- resources.anchor_to_lookup = anchor_to_lookup
- resources.lookup_to_anchor = lookup_to_anchor
- local classes = raw.anchor_classes -- anchor classes not in final table
- if classes then
- for c=1,#classes do
- local class = classes[c]
- local anchor = class.name
- local lookups = class.lookup
- if type(lookups) ~= "table" then
- lookups = { lookups }
- end
- local a = anchor_to_lookup[anchor]
- if not a then
- a = { }
- anchor_to_lookup[anchor] = a
- end
- for l=1,#lookups do
- local lookup = lookups[l]
- local l = lookup_to_anchor[lookup]
- if l then
- l[anchor] = true
- else
- l = { [anchor] = true }
- lookup_to_anchor[lookup] = l
- end
- a[lookup] = true
- end
- end
- end
-end
-
--- local function checklookups(data,missing,nofmissing)
--- local resources = data.resources
--- local unicodes = resources.unicodes
--- local lookuptypes = resources.lookuptypes
--- if not unicodes or not lookuptypes then
--- return
--- elseif nofmissing <= 0 then
--- return
--- end
--- local descriptions = data.descriptions
--- local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
--- --
--- local ns, nl = 0, 0
---
--- local guess = { }
--- -- helper
--- local function check(gname,code,unicode)
--- local description = descriptions[code]
--- -- no need to add a self reference
--- local variant = description.name
--- if variant == gname then
--- return
--- end
--- -- the variant already has a unicode (normally that results in a default tounicode to self)
--- local unic = unicodes[variant]
--- if unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
--- -- no default mapping and therefore maybe no tounicode yet
--- else
--- return
--- end
--- -- the variant already has a tounicode
--- if descriptions[code].unicode then
--- return
--- end
--- -- add to the list
--- local g = guess[variant]
--- -- local r = overloads[unicode]
--- -- if r then
--- -- unicode = r.unicode
--- -- end
--- if g then
--- g[gname] = unicode
--- else
--- guess[variant] = { [gname] = unicode }
--- end
--- end
--- --
--- for unicode, description in next, descriptions do
--- local slookups = description.slookups
--- if slookups then
--- local gname = description.name
--- for tag, data in next, slookups do
--- local lookuptype = lookuptypes[tag]
--- if lookuptype == "alternate" then
--- for i=1,#data do
--- check(gname,data[i],unicode)
--- end
--- elseif lookuptype == "substitution" then
--- check(gname,data,unicode)
--- end
--- end
--- end
--- local mlookups = description.mlookups
--- if mlookups then
--- local gname = description.name
--- for tag, list in next, mlookups do
--- local lookuptype = lookuptypes[tag]
--- if lookuptype == "alternate" then
--- for i=1,#list do
--- local data = list[i]
--- for i=1,#data do
--- check(gname,data[i],unicode)
--- end
--- end
--- elseif lookuptype == "substitution" then
--- for i=1,#list do
--- check(gname,list[i],unicode)
--- end
--- end
--- end
--- end
--- end
--- -- resolve references
--- local done = true
--- while done do
--- done = false
--- for k, v in next, guess do
--- if type(v) ~= "number" then
--- for kk, vv in next, v do
--- if vv == -1 or vv >= private or (vv >= 0xE000 and vv <= 0xF8FF) or vv == 0xFFFE or vv == 0xFFFF then
--- local uu = guess[kk]
--- if type(uu) == "number" then
--- guess[k] = uu
--- done = true
--- end
--- else
--- guess[k] = vv
--- done = true
--- end
--- end
--- end
--- end
--- end
--- -- wrap up
--- local orphans = 0
--- local guessed = 0
--- for k, v in next, guess do
--- if type(v) == "number" then
--- descriptions[unicodes[k]].unicode = descriptions[v].unicode or v -- can also be a table
--- guessed = guessed + 1
--- else
--- local t = nil
--- local l = lower(k)
--- local u = unicodes[l]
--- if not u then
--- orphans = orphans + 1
--- elseif u == -1 or u >= private or (u >= 0xE000 and u <= 0xF8FF) or u == 0xFFFE or u == 0xFFFF then
--- local unicode = descriptions[u].unicode
--- if unicode then
--- descriptions[unicodes[k]].unicode = unicode
--- guessed = guessed + 1
--- else
--- orphans = orphans + 1
--- end
--- else
--- orphans = orphans + 1
--- end
--- end
--- end
--- if trace_loading and orphans > 0 or guessed > 0 then
--- report_otf("%s glyphs with no related unicode, %s guessed, %s orphans",guessed+orphans,guessed,orphans)
--- end
--- end
-
-local function enhance_prepare_tounicode(data,filename,raw)
- fonts.mappings.addtounicode(data,filename)
-end
-
-local g_directions = {
- gsub_contextchain = 1,
- gpos_contextchain = 1,
- -- gsub_context = 1,
- -- gpos_context = 1,
- gsub_reversecontextchain = -1,
- gpos_reversecontextchain = -1,
-}
--- The following is no longer needed as AAT is ignored per end October 2013.
---
--- -- Research by Khaled Hosny has demonstrated that the font loader merges
--- -- regular and AAT features and that these can interfere (especially because
--- -- we dropped checking for valid features elsewhere. So, we just check for
--- -- the special flag and drop the feature if such a tag is found.
---
--- local function supported(features)
--- for i=1,#features do
--- if features[i].ismac then
--- return false
--- end
--- end
--- return true
--- end
-
-local function enhance_reorganize_subtables(data,filename,raw)
- local resources = data.resources
- local sequences = { }
- local lookups = { }
- local chainedfeatures = { }
- resources.sequences = sequences
- resources.lookups = lookups -- we also have lookups in data itself
- for k=1,#otf.glists do
- local what = otf.glists[k]
- local dw = raw[what]
- if dw then
- for k=1,#dw do
- local gk = dw[k]
- local features = gk.features
- -- if not features or supported(features) then -- not always features !
- local typ = gk.type
- local chain = g_directions[typ] or 0
- local subtables = gk.subtables
- if subtables then
- local t = { }
- for s=1,#subtables do
- t[s] = subtables[s].name
- end
- subtables = t
- end
- local flags, markclass = gk.flags, nil
- if flags then
- local t = { -- forcing false packs nicer
- (flags.ignorecombiningmarks and "mark") or false,
- (flags.ignoreligatures and "ligature") or false,
- (flags.ignorebaseglyphs and "base") or false,
- flags.r2l or false,
- }
- markclass = flags.mark_class
- if markclass then
- markclass = resources.markclasses[markclass]
- end
- flags = t
- end
- --
- local name = gk.name
- --
- if not name then
- -- in fact an error
- report_otf("skipping weird lookup number %s",k)
- elseif features then
- -- scripts, tag, ismac
- local f = { }
- local o = { }
- for i=1,#features do
- local df = features[i]
- local tag = strip(lower(df.tag))
- local ft = f[tag]
- if not ft then
- ft = { }
- f[tag] = ft
- o[#o+1] = tag
- end
- local dscripts = df.scripts
- for i=1,#dscripts do
- local d = dscripts[i]
- local languages = d.langs
- local script = strip(lower(d.script))
- local fts = ft[script] if not fts then fts = {} ft[script] = fts end
- for i=1,#languages do
- fts[strip(lower(languages[i]))] = true
- end
- end
- end
- sequences[#sequences+1] = {
- type = typ,
- chain = chain,
- flags = flags,
- name = name,
- subtables = subtables,
- markclass = markclass,
- features = f,
- order = o,
- }
- else
- lookups[name] = {
- type = typ,
- chain = chain,
- flags = flags,
- subtables = subtables,
- markclass = markclass,
- }
- end
- -- end
- end
- end
- end
-end
-
-local function enhance_prepare_lookups(data,filename,raw)
- local lookups = raw.lookups
- if lookups then
- data.lookups = lookups
- end
-end
-
--- The reverse handler does a bit redundant splitting but it's seldom
--- seen so we don't bother too much. We could store the replacement
--- in the current list (value instead of true) but it makes other code
--- uglier. Maybe some day.
-
-local function t_uncover(splitter,cache,covers)
- local result = { }
- for n=1,#covers do
- local cover = covers[n]
- local uncovered = cache[cover]
- if not uncovered then
- uncovered = lpegmatch(splitter,cover)
- cache[cover] = uncovered
- end
- result[n] = uncovered
- end
- return result
-end
-
-local function s_uncover(splitter,cache,cover)
- if cover == "" then
- return nil
- else
- local uncovered = cache[cover]
- if not uncovered then
- uncovered = lpegmatch(splitter,cover)
- -- for i=1,#uncovered do
- -- uncovered[i] = { [uncovered[i]] = true }
- -- end
- cache[cover] = uncovered
- end
- return { uncovered }
- end
-end
-
-local function t_hashed(t,cache)
- if t then
- local ht = { }
- for i=1,#t do
- local ti = t[i]
- local tih = cache[ti]
- if not tih then
- local tn = #ti
- if tn == 1 then
- tih = { [ti[1]] = true }
- else
- tih = { }
- for i=1,tn do
- tih[ti[i]] = true
- end
- end
- cache[ti] = tih
- end
- ht[i] = tih
- end
- return ht
- else
- return nil
- end
-end
-
--- local s_hashed = t_hashed
-
-local function s_hashed(t,cache)
- if t then
- local tf = t[1]
- local nf = #tf
- if nf == 1 then
- return { [tf[1]] = true }
- else
- local ht = { }
- for i=1,nf do
- ht[i] = { [tf[i]] = true }
- end
- return ht
- end
- else
- return nil
- end
-end
-
-local function r_uncover(splitter,cache,cover,replacements)
- if cover == "" then
- return nil
- else
- -- we always have current as { } even in the case of one
- local uncovered = cover[1]
- local replaced = cache[replacements]
- if not replaced then
- replaced = lpegmatch(splitter,replacements)
- cache[replacements] = replaced
- end
- local nu, nr = #uncovered, #replaced
- local r = { }
- if nu == nr then
- for i=1,nu do
- r[uncovered[i]] = replaced[i]
- end
- end
- return r
- end
-end
-
-local function enhance_reorganize_lookups(data,filename,raw) -- we could check for "" and n == 0
- -- we prefer the before lookups in a normal order
- if data.lookups then
- local helpers = data.helpers
- local duplicates = data.resources.duplicates
- local splitter = helpers.tounicodetable
- local t_u_cache = { }
- local s_u_cache = t_u_cache -- string keys
- local t_h_cache = { }
- local s_h_cache = t_h_cache -- table keys (so we could use one cache)
- local r_u_cache = { } -- maybe shared
- helpers.matchcache = t_h_cache -- so that we can add duplicates
- --
- for _, lookup in next, data.lookups do
- local rules = lookup.rules
- if rules then
- local format = lookup.format
- if format == "class" then
- local before_class = lookup.before_class
- if before_class then
- before_class = t_uncover(splitter,t_u_cache,reversed(before_class))
- end
- local current_class = lookup.current_class
- if current_class then
- current_class = t_uncover(splitter,t_u_cache,current_class)
- end
- local after_class = lookup.after_class
- if after_class then
- after_class = t_uncover(splitter,t_u_cache,after_class)
- end
- for i=1,#rules do
- local rule = rules[i]
- local class = rule.class
- local before = class.before
- if before then
- for i=1,#before do
- before[i] = before_class[before[i]] or { }
- end
- rule.before = t_hashed(before,t_h_cache)
- end
- local current = class.current
- local lookups = rule.lookups
- if current then
- for i=1,#current do
- current[i] = current_class[current[i]] or { }
- -- let's not be sparse
- if lookups and not lookups[i] then
- lookups[i] = "" -- (was: false) e.g. we can have two lookups and one replacement
- end
- -- end of fix
- end
- rule.current = t_hashed(current,t_h_cache)
- end
- local after = class.after
- if after then
- for i=1,#after do
- after[i] = after_class[after[i]] or { }
- end
- rule.after = t_hashed(after,t_h_cache)
- end
- rule.class = nil
- end
- lookup.before_class = nil
- lookup.current_class = nil
- lookup.after_class = nil
- lookup.format = "coverage"
- elseif format == "coverage" then
- for i=1,#rules do
- local rule = rules[i]
- local coverage = rule.coverage
- if coverage then
- local before = coverage.before
- if before then
- before = t_uncover(splitter,t_u_cache,reversed(before))
- rule.before = t_hashed(before,t_h_cache)
- end
- local current = coverage.current
- if current then
- current = t_uncover(splitter,t_u_cache,current)
- -- let's not be sparse
- local lookups = rule.lookups
- if lookups then
- for i=1,#current do
- if not lookups[i] then
- lookups[i] = "" -- fix sparse array
- end
- end
- end
- --
- rule.current = t_hashed(current,t_h_cache)
- end
- local after = coverage.after
- if after then
- after = t_uncover(splitter,t_u_cache,after)
- rule.after = t_hashed(after,t_h_cache)
- end
- rule.coverage = nil
- end
- end
- elseif format == "reversecoverage" then -- special case, single substitution only
- for i=1,#rules do
- local rule = rules[i]
- local reversecoverage = rule.reversecoverage
- if reversecoverage then
- local before = reversecoverage.before
- if before then
- before = t_uncover(splitter,t_u_cache,reversed(before))
- rule.before = t_hashed(before,t_h_cache)
- end
- local current = reversecoverage.current
- if current then
- current = t_uncover(splitter,t_u_cache,current)
- rule.current = t_hashed(current,t_h_cache)
- end
- local after = reversecoverage.after
- if after then
- after = t_uncover(splitter,t_u_cache,after)
- rule.after = t_hashed(after,t_h_cache)
- end
- local replacements = reversecoverage.replacements
- if replacements then
- rule.replacements = r_uncover(splitter,r_u_cache,current,replacements)
- end
- rule.reversecoverage = nil
- end
- end
- elseif format == "glyphs" then
- -- I could store these more efficient (as not we use a nested tables for before,
- -- after and current but this features happens so seldom that I don't bother
- -- about it right now.
- for i=1,#rules do
- local rule = rules[i]
- local glyphs = rule.glyphs
- if glyphs then
- local fore = glyphs.fore
- if fore and fore ~= "" then
- fore = s_uncover(splitter,s_u_cache,fore)
- rule.after = s_hashed(fore,s_h_cache)
- end
- local back = glyphs.back
- if back then
- back = s_uncover(splitter,s_u_cache,back)
- rule.before = s_hashed(back,s_h_cache)
- end
- local names = glyphs.names
- if names then
- names = s_uncover(splitter,s_u_cache,names)
- rule.current = s_hashed(names,s_h_cache)
- end
- rule.glyphs = nil
- local lookups = rule.lookups
- if lookups then
- for i=1,#names do
- if not lookups[i] then
- lookups[i] = "" -- fix sparse array
- end
- end
- end
- end
- end
- end
- end
- end
- end
-end
-
-local function enhance_expand_lookups(data,filename,raw) -- we could check for "" and n == 0
- if data.lookups then
- local cache = data.helpers.matchcache
- if cache then
- local duplicates = data.resources.duplicates
- for key, hash in next, cache do
- local done = nil
- for key in next, hash do
- local unicode = duplicates[key]
- if not unicode then
- -- no duplicate
- elseif type(unicode) == "table" then
- -- multiple duplicates
- for i=1,#unicode do
- local u = unicode[i]
- if hash[u] then
- -- already in set
- elseif done then
- done[u] = key
- else
- done = { [u] = key }
- end
- end
- else
- -- one duplicate
- if hash[unicode] then
- -- already in set
- elseif done then
- done[unicode] = key
- else
- done = { [unicode] = key }
- end
- end
- end
- if done then
- for u in next, done do
- hash[u] = true
- end
- end
- end
- end
- end
-end
-
-local function check_variants(unicode,the_variants,splitter,unicodes)
- local variants = the_variants.variants
- if variants then -- use splitter
- local glyphs = lpegmatch(splitter,variants)
- local done = { [unicode] = true }
- local n = 0
- for i=1,#glyphs do
- local g = glyphs[i]
- if done[g] then
- if i > 1 then
- report_otf("skipping cyclic reference %U in math variant %U",g,unicode)
- end
- else
- if n == 0 then
- n = 1
- variants = { g }
- else
- n = n + 1
- variants[n] = g
- end
- done[g] = true
- end
- end
- if n == 0 then
- variants = nil
- end
- end
- local parts = the_variants.parts
- if parts then
- local p = #parts
- if p > 0 then
- for i=1,p do
- local pi = parts[i]
- pi.glyph = unicodes[pi.component] or 0
- pi.component = nil
- end
- else
- parts = nil
- end
- end
- local italic = the_variants.italic
- if italic and italic == 0 then
- italic = nil
- end
- return variants, parts, italic
-end
-
-local function enhance_analyze_math(data,filename,raw)
- if raw.math then
- data.metadata.math = raw.math
- local unicodes = data.resources.unicodes
- local splitter = data.helpers.tounicodetable
- for unicode, description in next, data.descriptions do
- local glyph = description.glyph
- local mathkerns = glyph.mathkern -- singular
- local hvariants = glyph.horiz_variants
- local vvariants = glyph.vert_variants
- local accent = glyph.top_accent
- local italic = glyph.italic_correction
- if mathkerns or hvariants or vvariants or accent or italic then
- local math = { }
- if accent then
- math.accent = accent
- end
- if mathkerns then
- local topright = mathkerns.top_right
- local topleft = mathkerns.top_left
- local bottomright = mathkerns.bottom_right
- local bottomleft = mathkerns.bottom_left
- math.kerns = {
- topright = topright and next(topright) and topright or nil,
- topleft = topleft and next(topleft) and topleft or nil,
- bottomright = bottomright and next(bottomright) and bottomright or nil,
- bottomleft = bottomleft and next(bottomleft) and bottomleft or nil,
- }
- end
- if hvariants then
- math.hvariants, math.hparts, math.hitalic = check_variants(unicode,hvariants,splitter,unicodes)
- end
- if vvariants then
- math.vvariants, math.vparts, math.vitalic = check_variants(unicode,vvariants,splitter,unicodes)
- end
- if italic and italic ~= 0 then
- math.italic = italic
- end
- description.math = math
- end
- end
- end
-end
-
-local function enhance_reorganize_glyph_kerns(data,filename,raw)
- local descriptions = data.descriptions
- local resources = data.resources
- local unicodes = resources.unicodes
- for unicode, description in next, descriptions do
- local kerns = description.glyph.kerns
- if kerns then
- local newkerns = { }
- for k, kern in next, kerns do
- local name = kern.char
- local offset = kern.off
- local lookup = kern.lookup
- if name and offset and lookup then
- local unicode = unicodes[name]
- if unicode then
- if type(lookup) == "table" then
- for l=1,#lookup do
- local lookup = lookup[l]
- local lookupkerns = newkerns[lookup]
- if lookupkerns then
- lookupkerns[unicode] = offset
- else
- newkerns[lookup] = { [unicode] = offset }
- end
- end
- else
- local lookupkerns = newkerns[lookup]
- if lookupkerns then
- lookupkerns[unicode] = offset
- else
- newkerns[lookup] = { [unicode] = offset }
- end
- end
- elseif trace_loading then
- report_otf("problems with unicode %a of kern %a of glyph %U",name,k,unicode)
- end
- end
- end
- description.kerns = newkerns
- end
- end
-end
-
-local function enhance_merge_kern_classes(data,filename,raw)
- local gposlist = raw.gpos
- if gposlist then
- local descriptions = data.descriptions
- local resources = data.resources
- local unicodes = resources.unicodes
- local splitter = data.helpers.tounicodetable
- local ignored = 0
- local blocked = 0
- for gp=1,#gposlist do
- local gpos = gposlist[gp]
- local subtables = gpos.subtables
- if subtables then
- local first_done = { } -- could become an option so that we can deal with buggy fonts that don't get fixed
- local split = { } -- saves time .. although probably not that much any more in the fixed luatex kernclass table
- for s=1,#subtables do
- local subtable = subtables[s]
- local kernclass = subtable.kernclass -- name is inconsistent with anchor_classes
- local lookup = subtable.lookup or subtable.name
- if kernclass then -- the next one is quite slow
- -- as fas as i can see the kernclass is a table with one entry and offsets
- -- have no [1] so we could remov eon elevel (kernclass) and start offsets
- -- at 1 but we're too far down the road now to fix that
- if #kernclass > 0 then
- kernclass = kernclass[1]
- lookup = type(kernclass.lookup) == "string" and kernclass.lookup or lookup
- report_otf("fixing kernclass table of lookup %a",lookup)
- end
- local firsts = kernclass.firsts
- local seconds = kernclass.seconds
- local offsets = kernclass.offsets
- -- if offsets[1] == nil then
- -- offsets[1] = "" -- defaults ?
- -- end
- for n, s in next, firsts do
- split[s] = split[s] or lpegmatch(splitter,s)
- end
- local maxseconds = 0
- for n, s in next, seconds do
- if n > maxseconds then
- maxseconds = n
- end
- split[s] = split[s] or lpegmatch(splitter,s)
- end
- for fk=1,#firsts do -- maxfirsts ?
- local fv = firsts[fk]
- local splt = split[fv]
- if splt then
- local extrakerns = { }
- local baseoffset = (fk-1) * maxseconds
- -- for sk, sv in next, seconds do
- for sk=2,maxseconds do
- local sv = seconds[sk]
- if sv then
- local splt = split[sv]
- if splt then -- redundant test
- local offset = offsets[baseoffset + sk]
- if offset then
- for i=1,#splt do
- extrakerns[splt[i]] = offset
- end
- end
- end
- end
- end
- for i=1,#splt do
- local first_unicode = splt[i]
- if first_done[first_unicode] then
- report_otf("lookup %a: ignoring further kerns of %C",lookup,first_unicode)
- blocked = blocked + 1
- else
- first_done[first_unicode] = true
- local description = descriptions[first_unicode]
- if description then
- local kerns = description.kerns
- if not kerns then
- kerns = { } -- unicode indexed !
- description.kerns = kerns
- end
- local lookupkerns = kerns[lookup]
- if not lookupkerns then
- lookupkerns = { }
- kerns[lookup] = lookupkerns
- end
- if overloadkerns then
- for second_unicode, kern in next, extrakerns do
- lookupkerns[second_unicode] = kern
- end
- else
- for second_unicode, kern in next, extrakerns do
- local k = lookupkerns[second_unicode]
- if not k then
- lookupkerns[second_unicode] = kern
- elseif k ~= kern then
- if trace_loading then
- report_otf("lookup %a: ignoring overload of kern between %C and %C, rejecting %a, keeping %a",lookup,first_unicode,second_unicode,k,kern)
- end
- ignored = ignored + 1
- end
- end
- end
- elseif trace_loading then
- report_otf("no glyph data for %U", first_unicode)
- end
- end
- end
- end
- end
- subtable.kernclass = { }
- end
- end
- end
- end
- if ignored > 0 then
- report_otf("%s kern overloads ignored",ignored)
- end
- if blocked > 0 then
- report_otf("%s successive kerns blocked",blocked)
- end
- end
-end
-
-local function enhance_check_glyphs(data,filename,raw)
- for unicode, description in next, data.descriptions do
- description.glyph = nil
- end
-end
-
--- future versions will remove _
-
-local valid = (R("\x00\x7E") - S("(){}[]<>%/ \n\r\f\v"))^0 * P(-1)
-
-local function valid_ps_name(str)
- return str and str ~= "" and #str < 64 and lpegmatch(valid,str) and true or false
-end
-
-local function enhance_check_metadata(data,filename,raw)
- local metadata = data.metadata
- for _, k in next, mainfields do
- if valid_fields[k] then
- local v = raw[k]
- if not metadata[k] then
- metadata[k] = v
- end
- end
- end
- -- metadata.pfminfo = raw.pfminfo -- not already done?
- local ttftables = metadata.ttf_tables
- if ttftables then
- for i=1,#ttftables do
- ttftables[i].data = "deleted"
- end
- end
- --
- local state = metadata.validation_state
- local names = raw.names
- --
- if state and table.contains(state,"bad_ps_fontname") then
- -- the ff library does a bit too much (and wrong) checking ... so we need to catch this
- -- at least for now
- local function valid(what)
- if names then
- for i=1,#names do
- local list = names[i]
- local names = list.names
- if names then
- local name = names[what]
- if name and valid_ps_name(name) then
- return name
- end
- end
- end
- end
- end
- local function check(what)
- local oldname = metadata[what]
- if valid_ps_name(oldname) then
- report_otf("ignoring warning %a because %s %a is proper ASCII","bad_ps_fontname",what,oldname)
- else
- local newname = valid(what)
- if not newname then
- newname = formatters["bad-%s-%s"](what,file.nameonly(filename))
- end
- local warning = formatters["overloading %s from invalid ASCII name %a to %a"](what,oldname,newname)
- data.warnings[#data.warnings+1] = warning
- report_otf(warning)
- metadata[what] = newname
- end
- end
- check("fontname")
- check("fullname")
- end
- --
- if names then
- local psname = metadata.psname
- if not psname or psname == "" then
- for i=1,#names do
- local name = names[i]
- -- Currently we use the same restricted search as in the new context (specific) font loader
- -- but we might add more lang checks (it worked ok in the new loaded so now we're in sync)
- -- This check here is also because there are (esp) cjk fonts out there with psnames different
- -- from fontnames (gives a bad lookup in backend).
- if lower(name.lang) == "english (us)" then
- local specification = name.names
- if specification then
- local postscriptname = specification.postscriptname
- if postscriptname then
- psname = postscriptname
- end
- end
- end
- break
- end
- end
- if psname ~= metadata.fontname then
- report_otf("fontname %a, fullname %a, psname %a",metadata.fontname,metadata.fullname,psname)
- end
- metadata.psname = psname
- end
- --
- if state and table.contains(state,"bad_cmap_table") then
- report_otf("fontfile %a has bad cmap tables",filename)
- end
-end
-
-local function enhance_cleanup_tables(data,filename,raw)
- local duplicates = data.resources.duplicates
- if duplicates then
- for k, v in next, duplicates do
- if #v == 1 then
- duplicates[k] = v[1]
- end
- end
- end
- data.resources.indices = nil -- not needed
- data.resources.unicodes = nil -- delayed
- data.helpers = nil -- tricky as we have no unicodes any more
-end
-
--- kern: ttf has a table with kerns
---
--- Weird, as maxfirst and maxseconds can have holes, first seems to be indexed, but
--- seconds can start at 2 .. this need to be fixed as getn as well as # are sort of
--- unpredictable alternatively we could force an [1] if not set (maybe I will do that
--- anyway).
-
--- we can share { } as it is never set
-
--- ligatures have an extra specification.char entry that we don't use
-
--- mlookups only with pairs and ligatures
-
-local function enhance_reorganize_glyph_lookups(data,filename,raw)
- local resources = data.resources
- local unicodes = resources.unicodes
- local descriptions = data.descriptions
- local splitter = data.helpers.tounicodelist
-
- local lookuptypes = resources.lookuptypes
-
- for unicode, description in next, descriptions do
- local lookups = description.glyph.lookups
- if lookups then
- for tag, lookuplist in next, lookups do
- for l=1,#lookuplist do
- local lookup = lookuplist[l]
- local specification = lookup.specification
- local lookuptype = lookup.type
- local lt = lookuptypes[tag]
- if not lt then
- lookuptypes[tag] = lookuptype
- elseif lt ~= lookuptype then
- report_otf("conflicting lookuptypes, %a points to %a and %a",tag,lt,lookuptype)
- end
- if lookuptype == "ligature" then
- lookuplist[l] = { lpegmatch(splitter,specification.components) }
- elseif lookuptype == "alternate" then
- lookuplist[l] = { lpegmatch(splitter,specification.components) }
- elseif lookuptype == "substitution" then
- lookuplist[l] = unicodes[specification.variant]
- elseif lookuptype == "multiple" then
- lookuplist[l] = { lpegmatch(splitter,specification.components) }
- elseif lookuptype == "position" then
- lookuplist[l] = {
- specification.x or 0,
- specification.y or 0,
- specification.h or 0,
- specification.v or 0
- }
- elseif lookuptype == "pair" then
- local one = specification.offsets[1]
- local two = specification.offsets[2]
- local paired = unicodes[specification.paired]
- if one then
- if two then
- lookuplist[l] = { paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0 } }
- else
- lookuplist[l] = { paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 } }
- end
- else
- if two then
- lookuplist[l] = { paired, { }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0} } -- maybe nil instead of { }
- else
- lookuplist[l] = { paired }
- end
- end
- end
- end
- end
- local slookups, mlookups
- for tag, lookuplist in next, lookups do
- if #lookuplist == 1 then
- if slookups then
- slookups[tag] = lookuplist[1]
- else
- slookups = { [tag] = lookuplist[1] }
- end
- else
- if mlookups then
- mlookups[tag] = lookuplist
- else
- mlookups = { [tag] = lookuplist }
- end
- end
- end
- if slookups then
- description.slookups = slookups
- end
- if mlookups then
- description.mlookups = mlookups
- end
- -- description.lookups = nil
- end
- end
-end
-
-local zero = { 0, 0 }
-
-local function enhance_reorganize_glyph_anchors(data,filename,raw)
- local descriptions = data.descriptions
- for unicode, description in next, descriptions do
- local anchors = description.glyph.anchors
- if anchors then
- for class, data in next, anchors do
- if class == "baselig" then
- for tag, specification in next, data do
- -- for i=1,#specification do
- -- local si = specification[i]
- -- specification[i] = { si.x or 0, si.y or 0 }
- -- end
- -- can be sparse so we need to fill the holes
- local n = 0
- for k, v in next, specification do
- if k > n then
- n = k
- end
- local x, y = v.x, v.y
- if x or y then
- specification[k] = { x or 0, y or 0 }
- else
- specification[k] = zero
- end
- end
- local t = { }
- for i=1,n do
- t[i] = specification[i] or zero
- end
- data[tag] = t -- so # is okay (nicer for packer)
- end
- else
- for tag, specification in next, data do
- local x, y = specification.x, specification.y
- if x or y then
- data[tag] = { x or 0, y or 0 }
- else
- data[tag] = zero
- end
- end
- end
- end
- description.anchors = anchors
- end
- end
-end
-
-local bogusname = (P("uni") + P("u")) * R("AF","09")^4
- + (P("index") + P("glyph") + S("Ii") * P("dentity") * P(".")^0) * R("09")^1
-local uselessname = (1-bogusname)^0 * bogusname
-
-local function enhance_purge_names(data,filename,raw) -- not used yet
- if purge_names then
- local n = 0
- for u, d in next, data.descriptions do
- if lpegmatch(uselessname,d.name) then
- n = n + 1
- d.name = nil
- end
- -- d.comment = nil
- end
- if n > 0 then
- report_otf("%s bogus names removed",n)
- end
- end
-end
-
-local function enhance_compact_lookups(data,filename,raw)
- if not compact_lookups then
- report_otf("not compacting")
- return
- end
- -- create keyhash
- local last = 0
- local tags = table.setmetatableindex({ },
- function(t,k)
- last = last + 1
- t[k] = last
- return last
- end
- )
- --
- local descriptions = data.descriptions
- local resources = data.resources
- --
- for u, d in next, descriptions do
- --
- -- -- we can also compact anchors and cursives (basechar basemark baselig mark)
- --
- local slookups = d.slookups
- if type(slookups) == "table" then
- local s = { }
- for k, v in next, slookups do
- s[tags[k]] = v
- end
- d.slookups = s
- end
- --
- local mlookups = d.mlookups
- if type(mlookups) == "table" then
- local m = { }
- for k, v in next, mlookups do
- m[tags[k]] = v
- end
- d.mlookups = m
- end
- --
- local kerns = d.kerns
- if type(kerns) == "table" then
- local t = { }
- for k, v in next, kerns do
- t[tags[k]] = v
- end
- d.kerns = t
- end
- end
- --
- local lookups = data.lookups
- if lookups then
- local l = { }
- for k, v in next, lookups do
- local rules = v.rules
- if rules then
- for i=1,#rules do
- local l = rules[i].lookups
- if type(l) == "table" then
- for i=1,#l do
- l[i] = tags[l[i]]
- end
- end
- end
- end
- l[tags[k]] = v
- end
- data.lookups = l
- end
- --
- local lookups = resources.lookups
- if lookups then
- local l = { }
- for k, v in next, lookups do
- local s = v.subtables
- if type(s) == "table" then
- for i=1,#s do
- s[i] = tags[s[i]]
- end
- end
- l[tags[k]] = v
- end
- resources.lookups = l
- end
- --
- local sequences = resources.sequences
- if sequences then
- for i=1,#sequences do
- local s = sequences[i]
- local n = s.name
- if n then
- s.name = tags[n]
- end
- local t = s.subtables
- if type(t) == "table" then
- for i=1,#t do
- t[i] = tags[t[i]]
- end
- end
- end
- end
- --
- local lookuptypes = resources.lookuptypes
- if lookuptypes then
- local l = { }
- for k, v in next, lookuptypes do
- l[tags[k]] = v
- end
- resources.lookuptypes = l
- end
- --
- local anchor_to_lookup = resources.anchor_to_lookup
- if anchor_to_lookup then
- for anchor, lookups in next, anchor_to_lookup do
- local l = { }
- for lookup, value in next, lookups do
- l[tags[lookup]] = value
- end
- anchor_to_lookup[anchor] = l
- end
- end
- --
- local lookup_to_anchor = resources.lookup_to_anchor
- if lookup_to_anchor then
- local l = { }
- for lookup, value in next, lookup_to_anchor do
- l[tags[lookup]] = value
- end
- resources.lookup_to_anchor = l
- end
- --
- tags = table.swapped(tags)
- --
- report_otf("%s lookup tags compacted",#tags)
- --
- resources.lookuptags = tags
-end
-
--- modes: node, base, none
-
-function otf.setfeatures(tfmdata,features)
- local okay = constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf)
- if okay then
- return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf)
- else
- return { } -- will become false
- end
-end
-
--- the first version made a top/mid/not extensible table, now we just
--- pass on the variants data and deal with it in the tfm scaler (there
--- is no longer an extensible table anyway)
---
--- we cannot share descriptions as virtual fonts might extend them (ok,
--- we could use a cache with a hash
---
--- we already assign an empty tabel to characters as we can add for
--- instance protruding info and loop over characters; one is not supposed
--- to change descriptions and if one does so one should make a copy!
-
-local function copytotfm(data,cache_id)
- if data then
- local metadata = data.metadata
- local warnings = data.warnings
- local resources = data.resources
- local properties = derivetable(data.properties)
- local descriptions = derivetable(data.descriptions)
- local goodies = derivetable(data.goodies)
- local characters = { }
- local parameters = { }
- local mathparameters = { }
- --
- local pfminfo = metadata.pfminfo or { }
- local resources = data.resources
- local unicodes = resources.unicodes
- -- local mode = data.mode or "base"
- local spaceunits = 500
- local spacer = "space"
- local designsize = metadata.designsize or metadata.design_size or 100
- local minsize = metadata.minsize or metadata.design_range_bottom or designsize
- local maxsize = metadata.maxsize or metadata.design_range_top or designsize
- local mathspecs = metadata.math
- --
- if designsize == 0 then
- designsize = 100
- minsize = 100
- maxsize = 100
- end
- if mathspecs then
- for name, value in next, mathspecs do
- mathparameters[name] = value
- end
- end
- for unicode, _ in next, data.descriptions do -- use parent table
- characters[unicode] = { }
- end
- if mathspecs then
- -- we could move this to the scaler but not that much is saved
- -- and this is cleaner
- for unicode, character in next, characters do
- local d = descriptions[unicode]
- local m = d.math
- if m then
- -- watch out: luatex uses horiz_variants for the parts
- --
- local italic = m.italic
- local vitalic = m.vitalic
- --
- local variants = m.hvariants
- local parts = m.hparts
- -- local done = { [unicode] = true }
- if variants then
- local c = character
- for i=1,#variants do
- local un = variants[i]
- -- if done[un] then
- -- -- report_otf("skipping cyclic reference %U in math variant %U",un,unicode)
- -- else
- c.next = un
- c = characters[un]
- -- done[un] = true
- -- end
- end -- c is now last in chain
- c.horiz_variants = parts
- elseif parts then
- character.horiz_variants = parts
- italic = m.hitalic
- end
- --
- local variants = m.vvariants
- local parts = m.vparts
- -- local done = { [unicode] = true }
- if variants then
- local c = character
- for i=1,#variants do
- local un = variants[i]
- -- if done[un] then
- -- -- report_otf("skipping cyclic reference %U in math variant %U",un,unicode)
- -- else
- c.next = un
- c = characters[un]
- -- done[un] = true
- -- end
- end -- c is now last in chain
- c.vert_variants = parts
- elseif parts then
- character.vert_variants = parts
- end
- --
- if italic and italic ~= 0 then
- character.italic = italic -- overload
- end
- if vitalic and vitalic ~= 0 then
- character.vert_italic = vitalic
- end
- --
- local accent = m.accent
- if accent then
- character.accent = accent
- end
- --
- local kerns = m.kerns
- if kerns then
- character.mathkerns = kerns
- end
- end
- end
- end
- -- end math
- -- we need a runtime lookup because of running from cdrom or zip, brrr (shouldn't we use the basename then?)
- local filename = constructors.checkedfilename(resources)
- local fontname = metadata.fontname
- local fullname = metadata.fullname or fontname
- local psname = metadata.psname or fontname or fullname
- local units = metadata.units or metadata.units_per_em or 1000
- --
- if units == 0 then -- catch bugs in fonts
- units = 1000 -- maybe 2000 when ttf
- metadata.units = 1000
- report_otf("changing %a units to %a",0,units)
- end
- --
- local monospaced = metadata.monospaced or metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion == "Monospaced")
- local charwidth = pfminfo.avgwidth -- or unset
- local charxheight = pfminfo.os2_xheight and pfminfo.os2_xheight > 0 and pfminfo.os2_xheight
--- charwidth = charwidth * units/1000
--- charxheight = charxheight * units/1000
- local italicangle = metadata.italicangle
- properties.monospaced = monospaced
- parameters.italicangle = italicangle
- parameters.charwidth = charwidth
- parameters.charxheight = charxheight
- --
- local space = 0x0020
- local emdash = 0x2014
- if monospaced then
- if descriptions[space] then
- spaceunits, spacer = descriptions[space].width, "space"
- end
- if not spaceunits and descriptions[emdash] then
- spaceunits, spacer = descriptions[emdash].width, "emdash"
- end
- if not spaceunits and charwidth then
- spaceunits, spacer = charwidth, "charwidth"
- end
- else
- if descriptions[space] then
- spaceunits, spacer = descriptions[space].width, "space"
- end
- if not spaceunits and descriptions[emdash] then
- spaceunits, spacer = descriptions[emdash].width/2, "emdash/2"
- end
- if not spaceunits and charwidth then
- spaceunits, spacer = charwidth, "charwidth"
- end
- end
- spaceunits = tonumber(spaceunits) or units/2
- --
- parameters.slant = 0
- parameters.space = spaceunits -- 3.333 (cmr10)
- parameters.space_stretch = units/2 -- 500 -- 1.666 (cmr10)
- parameters.space_shrink = 1*units/3 -- 333 -- 1.111 (cmr10)
- parameters.x_height = 2*units/5 -- 400
- parameters.quad = units -- 1000
- if spaceunits < 2*units/5 then
- -- todo: warning
- end
- if italicangle and italicangle ~= 0 then
- parameters.italicangle = italicangle
- parameters.italicfactor = math.cos(math.rad(90+italicangle))
- parameters.slant = - math.tan(italicangle*math.pi/180)
- end
- if monospaced then
- parameters.space_stretch = 0
- parameters.space_shrink = 0
- elseif syncspace then --
- parameters.space_stretch = spaceunits/2
- parameters.space_shrink = spaceunits/3
- end
- parameters.extra_space = parameters.space_shrink -- 1.111 (cmr10)
- if charxheight then
- parameters.x_height = charxheight
- else
- local x = 0x0078
- if x then
- local x = descriptions[x]
- if x then
- parameters.x_height = x.height
- end
- end
- end
- --
- parameters.designsize = (designsize/10)*65536
- parameters.minsize = (minsize /10)*65536
- parameters.maxsize = (maxsize /10)*65536
- parameters.ascender = abs(metadata.ascender or metadata.ascent or 0)
- parameters.descender = abs(metadata.descender or metadata.descent or 0)
- parameters.units = units
- --
- properties.space = spacer
- properties.encodingbytes = 2
- properties.format = data.format or otf_format(filename) or formats.otf
- properties.noglyphnames = true
- properties.filename = filename
- properties.fontname = fontname
- properties.fullname = fullname
- properties.psname = psname
- properties.name = filename or fullname
- --
- -- properties.name = specification.name
- -- properties.sub = specification.sub
- --
- if warnings and #warnings > 0 then
- report_otf("warnings for font: %s",filename)
- report_otf()
- for i=1,#warnings do
- report_otf(" %s",warnings[i])
- end
- report_otf()
- end
- return {
- characters = characters,
- descriptions = descriptions,
- parameters = parameters,
- mathparameters = mathparameters,
- resources = resources,
- properties = properties,
- goodies = goodies,
- warnings = warnings,
- }
- end
-end
-
-local function otftotfm(specification)
- local cache_id = specification.hash
- local tfmdata = containers.read(constructors.cache,cache_id)
- if not tfmdata then
- local name = specification.name
- local sub = specification.sub
- local filename = specification.filename
- -- local format = specification.format
- local features = specification.features.normal
- local rawdata = otf.load(filename,sub,features and features.featurefile)
- if rawdata and next(rawdata) then
- local descriptions = rawdata.descriptions
- local duplicates = rawdata.resources.duplicates
- if duplicates then
- local nofduplicates, nofduplicated = 0, 0
- for parent, list in next, duplicates do
- if type(list) == "table" then
- local n = #list
- for i=1,n do
- local unicode = list[i]
- if not descriptions[unicode] then
- descriptions[unicode] = descriptions[parent] -- or copy
- nofduplicated = nofduplicated + 1
- end
- end
- nofduplicates = nofduplicates + n
- else
- if not descriptions[list] then
- descriptions[list] = descriptions[parent] -- or copy
- nofduplicated = nofduplicated + 1
- end
- nofduplicates = nofduplicates + 1
- end
- end
- if trace_otf and nofduplicated ~= nofduplicates then
- report_otf("%i extra duplicates copied out of %i",nofduplicated,nofduplicates)
- end
- end
- rawdata.lookuphash = { }
- tfmdata = copytotfm(rawdata,cache_id)
- if tfmdata and next(tfmdata) then
- -- at this moment no characters are assigned yet, only empty slots
- local features = constructors.checkedfeatures("otf",features)
- local shared = tfmdata.shared
- if not shared then
- shared = { }
- tfmdata.shared = shared
- end
- shared.rawdata = rawdata
- -- shared.features = features -- default
- shared.dynamics = { }
- -- shared.processes = { }
- tfmdata.changed = { }
- shared.features = features
- shared.processes = otf.setfeatures(tfmdata,features)
- end
- end
- containers.write(constructors.cache,cache_id,tfmdata)
- end
- return tfmdata
-end
-
-local function read_from_otf(specification)
- local tfmdata = otftotfm(specification)
- if tfmdata then
- -- this late ? .. needs checking
- tfmdata.properties.name = specification.name
- tfmdata.properties.sub = specification.sub
- --
- tfmdata = constructors.scale(tfmdata,specification)
- local allfeatures = tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf)
- constructors.setname(tfmdata,specification) -- only otf?
- fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification)
- end
- return tfmdata
-end
-
-local function checkmathsize(tfmdata,mathsize)
- local mathdata = tfmdata.shared.rawdata.metadata.math
- local mathsize = tonumber(mathsize)
- if mathdata then -- we cannot use mathparameters as luatex will complain
- local parameters = tfmdata.parameters
- parameters.scriptpercentage = mathdata.ScriptPercentScaleDown
- parameters.scriptscriptpercentage = mathdata.ScriptScriptPercentScaleDown
- parameters.mathsize = mathsize
- end
-end
-
-registerotffeature {
- name = "mathsize",
- description = "apply mathsize specified in the font",
- initializers = {
- base = checkmathsize,
- node = checkmathsize,
- }
-}
-
--- helpers
-
-function otf.collectlookups(rawdata,kind,script,language)
- local sequences = rawdata.resources.sequences
- if sequences then
- local featuremap, featurelist = { }, { }
- for s=1,#sequences do
- local sequence = sequences[s]
- local features = sequence.features
- features = features and features[kind]
- features = features and (features[script] or features[default] or features[wildcard])
- features = features and (features[language] or features[default] or features[wildcard])
- if features then
- local subtables = sequence.subtables
- if subtables then
- for s=1,#subtables do
- local ss = subtables[s]
- if not featuremap[s] then
- featuremap[ss] = true
- featurelist[#featurelist+1] = ss
- end
- end
- end
- end
- end
- if #featurelist > 0 then
- return featuremap, featurelist
- end
- end
- return nil, nil
-end
-
--- readers (a bit messy, this forced so I might redo that bit: foo.ttf FOO.ttf foo.TTF FOO.TTF)
-
-local function check_otf(forced,specification,suffix)
- local name = specification.name
- if forced then
- name = specification.forcedname -- messy
- end
- local fullname = findbinfile(name,suffix) or ""
- if fullname == "" then
- fullname = fonts.names.getfilename(name,suffix) or ""
- end
- if fullname ~= "" and not fonts.names.ignoredfile(fullname) then
- specification.filename = fullname
- return read_from_otf(specification)
- end
-end
-
-local function opentypereader(specification,suffix)
- local forced = specification.forced or ""
- if formats[forced] then
- return check_otf(true,specification,forced)
- else
- return check_otf(false,specification,suffix)
- end
-end
-
-readers.opentype = opentypereader -- kind of useless and obsolete
-
-function readers.otf (specification) return opentypereader(specification,"otf") end
-function readers.ttf (specification) return opentypereader(specification,"ttf") end
-function readers.ttc (specification) return opentypereader(specification,"ttf") end
-function readers.dfont(specification) return opentypereader(specification,"ttf") end
-
--- this will be overloaded
-
-function otf.scriptandlanguage(tfmdata,attr)
- local properties = tfmdata.properties
- return properties.script or "dflt", properties.language or "dflt"
-end
-
--- a little bit of abstraction
-
-local function justset(coverage,unicode,replacement)
- coverage[unicode] = replacement
-end
-
-otf.coverup = {
- stepkey = "subtables",
- actions = {
- substitution = justset,
- alternate = justset,
- multiple = justset,
- ligature = justset,
- kern = justset,
- pair = justset,
- chainsubstitution = justset,
- chainposition = justset,
- },
- register = function(coverage,lookuptype,format,feature,n,descriptions,resources)
- local name = formatters["ctx_%s_%s_%s"](feature,lookuptype,n) -- we can have a mix of types
- if lookuptype == "kern" then
- resources.lookuptypes[name] = "position"
- else
- resources.lookuptypes[name] = lookuptype
- end
- for u, c in next, coverage do
- local description = descriptions[u]
- local slookups = description.slookups
- if slookups then
- slookups[name] = c
- else
- description.slookups = { [name] = c }
- end
- end
- return name
- end
-}
-
--- moved from font-oth.lua
-
-local function getgsub(tfmdata,k,kind)
- local description = tfmdata.descriptions[k]
- if description then
- local slookups = description.slookups -- we assume only slookups (we can always extend)
- if slookups then
- local shared = tfmdata.shared
- local rawdata = shared and shared.rawdata
- if rawdata then
- local lookuptypes = rawdata.resources.lookuptypes
- if lookuptypes then
- local properties = tfmdata.properties
- -- we could cache these
- local validlookups, lookuplist = otf.collectlookups(rawdata,kind,properties.script,properties.language)
- if validlookups then
- for l=1,#lookuplist do
- local lookup = lookuplist[l]
- local found = slookups[lookup]
- if found then
- return found, lookuptypes[lookup]
- end
- end
- end
- end
- end
- end
- end
-end
-
-otf.getgsub = getgsub -- returns value, gsub_kind
-
-function otf.getsubstitution(tfmdata,k,kind,value)
- local found, kind = getgsub(tfmdata,k,kind)
- if not found then
- --
- elseif kind == "substitution" then
- return found
- elseif kind == "alternate" then
- local choice = tonumber(value) or 1 -- no random here (yet)
- return found[choice] or found[1] or k
- end
- return k
-end
-
-otf.getalternate = otf.getsubstitution
-
-function otf.getmultiple(tfmdata,k,kind)
- local found, kind = getgsub(tfmdata,k,kind)
- if found and kind == "multiple" then
- return found
- end
- return { k }
-end
-
-function otf.getkern(tfmdata,left,right,kind)
- local kerns = getgsub(tfmdata,left,kind or "kern",true) -- for now we use getsub
- if kerns then
- local found = kerns[right]
- local kind = type(found)
- if kind == "table" then
- found = found[1][3] -- can be more clever
- elseif kind ~= "number" then
- found = false
- end
- if found then
- return found * tfmdata.parameters.factor
- end
- end
- return 0
-end
-
-
-registerotfenhancer("prepare tables", enhance_prepare_tables)
-
-registerotfenhancer("prepare glyphs", enhance_prepare_glyphs)
-registerotfenhancer("prepare lookups", enhance_prepare_lookups)
-
-registerotfenhancer("analyze glyphs", enhance_analyze_glyphs)
-registerotfenhancer("analyze math", enhance_analyze_math)
-
-registerotfenhancer("reorganize lookups", enhance_reorganize_lookups)
-registerotfenhancer("reorganize mark classes", enhance_reorganize_mark_classes)
-registerotfenhancer("reorganize anchor classes", enhance_reorganize_anchor_classes)
-
-registerotfenhancer("reorganize glyph kerns", enhance_reorganize_glyph_kerns)
-registerotfenhancer("reorganize glyph lookups", enhance_reorganize_glyph_lookups)
-registerotfenhancer("reorganize glyph anchors", enhance_reorganize_glyph_anchors)
-
-registerotfenhancer("merge kern classes", enhance_merge_kern_classes)
-
-registerotfenhancer("reorganize features", enhance_reorganize_features)
-registerotfenhancer("reorganize subtables", enhance_reorganize_subtables)
-
-registerotfenhancer("check glyphs", enhance_check_glyphs)
-registerotfenhancer("check metadata", enhance_check_metadata)
-
-registerotfenhancer("prepare tounicode", enhance_prepare_tounicode)
-
-registerotfenhancer("check encoding", enhance_check_encoding)
-registerotfenhancer("add duplicates", enhance_add_duplicates)
-
-registerotfenhancer("expand lookups", enhance_expand_lookups)
-
-registerotfenhancer("check extra features", function() end) --placeholder, will be overloaded
-
-registerotfenhancer("cleanup tables", enhance_cleanup_tables)
-
-registerotfenhancer("compact lookups", enhance_compact_lookups)
-registerotfenhancer("purge names", enhance_purge_names)
diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua
index bbe05304c..ee57d1d8f 100644
--- a/tex/context/base/mkiv/font-otl.lua
+++ b/tex/context/base/mkiv/font-otl.lua
@@ -558,7 +558,7 @@ local function checkmathsize(tfmdata,mathsize)
local parameters = tfmdata.parameters
parameters.scriptpercentage = mathdata.ScriptPercentScaleDown
parameters.scriptscriptpercentage = mathdata.ScriptScriptPercentScaleDown
- parameters.mathsize = mathsize
+ parameters.mathsize = mathsize -- only when a number !
end
end
diff --git a/tex/context/base/mkiv/font-otn.lua b/tex/context/base/mkiv/font-otn.lua
deleted file mode 100644
index d48021347..000000000
--- a/tex/context/base/mkiv/font-otn.lua
+++ /dev/null
@@ -1,3927 +0,0 @@
-if not modules then modules = { } end modules ['font-otn'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
--- this is a context version which can contain experimental code, but when we
--- have serious patches we also need to change the other two font-otn files
-
--- at some point i might decide to convert the whole list into a table and then
--- run over that instead (but it has some drawbacks as we also need to deal with
--- attributes and such so we need to keep a lot of track - which is why i rejected
--- that method - although it has become a bit easier in the meantime so it might
--- become an alternative (by that time i probably have gone completely lua) .. the
--- usual chicken-egg issues ... maybe mkix as it's no real tex any more then
-
--- preprocessors = { "nodes" }
-
--- anchor class : mark, mkmk, curs, mklg (todo)
--- anchor type : mark, basechar, baselig, basemark, centry, cexit, max (todo)
-
--- this is still somewhat preliminary and it will get better in due time;
--- much functionality could only be implemented thanks to the husayni font
--- of Idris Samawi Hamid to who we dedicate this module.
-
--- in retrospect it always looks easy but believe it or not, it took a lot
--- of work to get proper open type support done: buggy fonts, fuzzy specs,
--- special made testfonts, many skype sessions between taco, idris and me,
--- torture tests etc etc ... unfortunately the code does not show how much
--- time it took ...
-
--- todo:
---
--- extension infrastructure (for usage out of context)
--- sorting features according to vendors/renderers
--- alternative loop quitters
--- check cursive and r2l
--- find out where ignore-mark-classes went
--- default features (per language, script)
--- handle positions (we need example fonts)
--- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere)
--- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests)
--- remove some optimizations (when I have a faster machine)
---
--- beware:
---
--- we do some disc jugling where we need to keep in mind that the
--- pre, post and replace fields can have prev pointers to a nesting
--- node ... i wonder if that is still needed
---
--- not possible:
---
--- \discretionary {alpha-} {betagammadelta}
--- {\discretionary {alphabeta-} {gammadelta}
--- {\discretionary {alphabetagamma-} {delta}
--- {alphabetagammadelta}}}
-
---[[ldx--
-<p>This module is a bit more split up that I'd like but since we also want to test
-with plain <l n='tex'/> it has to be so. This module is part of <l n='context'/>
-and discussion about improvements and functionality mostly happens on the
-<l n='context'/> mailing list.</p>
-
-<p>The specification of OpenType is kind of vague. Apart from a lack of a proper
-free specifications there's also the problem that Microsoft and Adobe
-may have their own interpretation of how and in what order to apply features.
-In general the Microsoft website has more detailed specifications and is a
-better reference. There is also some information in the FontForge help files.</p>
-
-<p>Because there is so much possible, fonts might contain bugs and/or be made to
-work with certain rederers. These may evolve over time which may have the side
-effect that suddenly fonts behave differently.</p>
-
-<p>After a lot of experiments (mostly by Taco, me and Idris) we're now at yet another
-implementation. Of course all errors are mine and of course the code can be
-improved. There are quite some optimizations going on here and processing speed
-is currently acceptable. Not all functions are implemented yet, often because I
-lack the fonts for testing. Many scripts are not yet supported either, but I will
-look into them as soon as <l n='context'/> users ask for it.</p>
-
-<p>The specification leaves room for interpretation. In case of doubt the microsoft
-implementation is the reference as it is the most complete one. As they deal with
-lots of scripts and fonts, Kai and Ivo did a lot of testing of the generic code and
-their suggestions help improve the code. I'm aware that not all border cases can be
-taken care of, unless we accept excessive runtime, and even then the interference
-with other mechanisms (like hyphenation) are not trivial.</p>
-
-<p>Glyphs are indexed not by unicode but in their own way. This is because there is no
-relationship with unicode at all, apart from the fact that a font might cover certain
-ranges of characters. One character can have multiple shapes. However, at the
-<l n='tex'/> end we use unicode so and all extra glyphs are mapped into a private
-space. This is needed because we need to access them and <l n='tex'/> has to include
-then in the output eventually.</p>
-
-<p>The raw table as it coms from <l n='fontforge'/> gets reorganized in to fit out needs.
-In <l n='context'/> that table is packed (similar tables are shared) and cached on disk
-so that successive runs can use the optimized table (after loading the table is
-unpacked). The flattening code used later is a prelude to an even more compact table
-format (and as such it keeps evolving).</p>
-
-<p>This module is sparsely documented because it is a moving target. The table format
-of the reader changes and we experiment a lot with different methods for supporting
-features.</p>
-
-<p>As with the <l n='afm'/> code, we may decide to store more information in the
-<l n='otf'/> table.</p>
-
-<p>Incrementing the version number will force a re-cache. We jump the number by one
-when there's a fix in the <l n='fontforge'/> library or <l n='lua'/> code that
-results in different tables.</p>
---ldx]]--
-
--- action handler chainproc
---
--- gsub_single ok ok
--- gsub_multiple ok ok
--- gsub_alternate ok ok
--- gsub_ligature ok ok
--- gsub_context ok --
--- gsub_contextchain ok --
--- gsub_reversecontextchain ok --
--- chainsub -- ok
--- reversesub -- ok
--- gpos_mark2base ok ok
--- gpos_mark2ligature ok ok
--- gpos_mark2mark ok ok
--- gpos_cursive ok untested
--- gpos_single ok ok
--- gpos_pair ok ok
--- gpos_context ok --
--- gpos_contextchain ok --
---
--- todo: contextpos
---
--- actions:
---
--- handler : actions triggered by lookup
--- chainproc : actions triggered by contextual lookup
--- chainmore : multiple substitutions triggered by contextual lookup (e.g. fij -> f + ij)
---
--- remark: the 'not implemented yet' variants will be done when we have fonts that use them
-
--- We used to have independent hashes for lookups but as the tags are unique
--- we now use only one hash. If needed we can have multiple again but in that
--- case I will probably prefix (i.e. rename) the lookups in the cached font file.
-
--- Todo: make plugin feature that operates on char/glyphnode arrays
-
-local type, next, tonumber = type, next, tonumber
-local random = math.random
-local formatters = string.formatters
-
-local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes
-
-local registertracker = trackers.register
-local registerdirective = directives.register
-
-local fonts = fonts
-local otf = fonts.handlers.otf
-
-local trace_lookups = false registertracker("otf.lookups", function(v) trace_lookups = v end)
-local trace_singles = false registertracker("otf.singles", function(v) trace_singles = v end)
-local trace_multiples = false registertracker("otf.multiples", function(v) trace_multiples = v end)
-local trace_alternatives = false registertracker("otf.alternatives", function(v) trace_alternatives = v end)
-local trace_ligatures = false registertracker("otf.ligatures", function(v) trace_ligatures = v end)
-local trace_contexts = false registertracker("otf.contexts", function(v) trace_contexts = v end)
-local trace_marks = false registertracker("otf.marks", function(v) trace_marks = v end)
-local trace_kerns = false registertracker("otf.kerns", function(v) trace_kerns = v end)
-local trace_cursive = false registertracker("otf.cursive", function(v) trace_cursive = v end)
-local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end)
-local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end)
-local trace_details = false registertracker("otf.details", function(v) trace_details = v end)
-local trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
-local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end)
-local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
-local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
-
-local trace_kernruns = false registertracker("otf.kernruns", function(v) trace_kernruns = v end)
-local trace_discruns = false registertracker("otf.discruns", function(v) trace_discruns = v end)
-local trace_compruns = false registertracker("otf.compruns", function(v) trace_compruns = v end)
-
-local quit_on_no_replacement = true -- maybe per font
-local zwnjruns = true
-
-registerdirective("otf.zwnjruns", function(v) zwnjruns = v end)
-registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement = value end)
-
-local report_direct = logs.reporter("fonts","otf direct")
-local report_subchain = logs.reporter("fonts","otf subchain")
-local report_chain = logs.reporter("fonts","otf chain")
-local report_process = logs.reporter("fonts","otf process")
-local report_prepare = logs.reporter("fonts","otf prepare")
-local report_run = logs.reporter("fonts","otf run")
-
-registertracker("otf.substitutions", "otf.singles","otf.multiples","otf.alternatives","otf.ligatures")
-registertracker("otf.positions", "otf.marks","otf.kerns","otf.cursive")
-registertracker("otf.actions", "otf.substitutions","otf.positions")
-registertracker("otf.sample", "otf.steps","otf.substitutions","otf.positions","otf.analyzing")
-
-registertracker("otf.chain.verbose", function(v) otf.setcontextchain(v and "verbose") end)
-registertracker("otf.chain.normal", function(v) otf.setcontextchain(v and "normal") end)
-
-local nuts = nodes.nuts
-local tonode = nuts.tonode
-local tonut = nuts.tonut
-
-local getfield = nuts.getfield
-local setfield = nuts.setfield
-local getnext = nuts.getnext
-local setnext = nuts.setnext
-local getprev = nuts.getprev
-local setprev = nuts.setprev
-local getid = nuts.getid
-local getattr = nuts.getattr
-local setattr = nuts.setattr
-local getprop = nuts.getprop
-local setprop = nuts.setprop
-local getfont = nuts.getfont
-local getsubtype = nuts.getsubtype
-local setsubtype = nuts.setsubtype
-local getchar = nuts.getchar
-local setchar = nuts.setchar
-
-local insert_node_after = nuts.insert_after
-local copy_node = nuts.copy
-local copy_node_list = nuts.copy_list
-local find_node_tail = nuts.tail
-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 setmetatableindex = table.setmetatableindex
-
-local zwnj = 0x200C
-local zwj = 0x200D
-local wildcard = "*"
-local default = "dflt"
-
-local nodecodes = nodes.nodecodes
-local glyphcodes = nodes.glyphcodes
-local disccodes = nodes.disccodes
-
-local glyph_code = nodecodes.glyph
-local disc_code = nodecodes.disc
-local math_code = nodecodes.math
-local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
-
-local discretionary_code = disccodes.discretionary
-local ligature_code = glyphcodes.ligature
-
-local privateattribute = attributes.private
-
--- Something is messed up: we have two mark / ligature indices, one at the injection
--- end and one here ... this is based on KE's patches but there is something fishy
--- there as I'm pretty sure that for husayni we need some connection (as it's much
--- more complex than an average font) but I need proper examples of all cases, not
--- of only some.
-
-local a_state = privateattribute('state')
-local a_cursbase = privateattribute('cursbase') -- to be checked, probably can go
-
-local injections = nodes.injections
-local setmark = injections.setmark
-local setcursive = injections.setcursive
-local setkern = injections.setkern
-local setpair = injections.setpair
-local resetinjection = injections.reset
-local copyinjection = injections.copy
-local setligaindex = injections.setligaindex
-local getligaindex = injections.getligaindex
-
-local cursonce = true
-
-local fonthashes = fonts.hashes
-local fontdata = fonthashes.identifiers
-
-local otffeatures = fonts.constructors.features.otf
-local registerotffeature = otffeatures.register
-
-local onetimemessage = fonts.loggers.onetimemessage or function() end
-
-local getrandom = utilities and utilities.randomizer and utilities.randomizer.get
-
-otf.defaultnodealternate = "none" -- first last
-
--- we share some vars here, after all, we have no nested lookups and less code
-
-local tfmdata = false
-local characters = false
-local descriptions = false
-local resources = false
-local marks = false
-local currentfont = false
-local lookuptable = false
-local anchorlookups = false
-local lookuptypes = false
-local lookuptags = false
-local handlers = { }
-local rlmode = 0
-local featurevalue = false
-
-local sweephead = { }
-local sweepnode = nil
-local sweepprev = nil
-local sweepnext = nil
-
-local notmatchpre = { }
-local notmatchpost = { }
-local notmatchreplace = { }
-
--- we use this for special testing and documentation
-
-local checkstep = (nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
-local registerstep = (nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
-local registermessage = (nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
-
-local function logprocess(...)
- if trace_steps then
- registermessage(...)
- end
- report_direct(...)
-end
-
-local function logwarning(...)
- report_direct(...)
-end
-
-local f_unicode = formatters["%U"]
-local f_uniname = formatters["%U (%s)"]
-local f_unilist = formatters["% t (% t)"]
-
-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 "-"
- end
- end
- return f_unilist(num,nam)
- else
- return "<error in node mode tracing>"
- end
-end
-
-local function cref(kind,chainname,chainlookupname,lookupname,index) -- not in the mood to alias f_
- if index then
- return formatters["feature %a, chain %a, sub %a, lookup %a, index %a"](kind,chainname,chainlookupname,lookuptags[lookupname],index)
- elseif lookupname then
- return formatters["feature %a, chain %a, sub %a, lookup %a"](kind,chainname,chainlookupname,lookuptags[lookupname])
- elseif chainlookupname then
- return formatters["feature %a, chain %a, sub %a"](kind,lookuptags[chainname],lookuptags[chainlookupname])
- elseif chainname then
- return formatters["feature %a, chain %a"](kind,lookuptags[chainname])
- else
- return formatters["feature %a"](kind)
- end
-end
-
-local function pref(kind,lookupname)
- return formatters["feature %a, lookup %a"](kind,lookuptags[lookupname])
-end
-
--- We can assume that languages that use marks are not hyphenated. We can also assume
--- that at most one discretionary is present.
-
--- We do need components in funny kerning mode but maybe I can better reconstruct then
--- as we do have the font components info available; removing components makes the
--- previous code much simpler. Also, later on copying and freeing becomes easier.
--- However, for arabic we need to keep them around for the sake of mark placement
--- and indices.
-
-local function copy_glyph(g) -- next and prev are untouched !
- local components = getfield(g,"components")
- if components then
- setfield(g,"components",nil)
- local n = copy_node(g)
- copyinjection(n,g) -- we need to preserve the lig indices
- setfield(g,"components",components)
- return n
- else
- local n = copy_node(g)
- copyinjection(n,g) -- we need to preserve the lig indices
- return n
- end
-end
-
-local function flattendisk(head,disc)
- local replace = getfield(disc,"replace")
- setfield(disc,"replace",nil)
- flush_node(disc)
- if head == disc then
- local next = getnext(disc)
- if replace then
- if next then
- local tail = find_node_tail(replace)
- setnext(tail,next)
- setprev(next,tail)
- end
- return replace, replace
- elseif next then
- return next, next
- else
- return -- maybe warning
- end
- else
- local next = getnext(disc)
- local prev = getprev(disc)
- if replace then
- local tail = find_node_tail(replace)
- if next then
- setnext(tail,next)
- setprev(next,tail)
- end
- setnext(prev,replace)
- setprev(replace,prev)
- return head, replace
- else
- if next then
- setprev(next,prev)
- end
- setnext(prev,next)
- return head, next
- end
- end
-end
-
-local function appenddisc(disc,list)
- local post = getfield(disc,"post")
- local replace = getfield(disc,"replace")
- local phead = list
- local rhead = copy_node_list(list)
- local ptail = find_node_tail(post)
- local rtail = find_node_tail(replace)
- if post then
- setnext(ptail,phead)
- setprev(phead,ptail)
- else
- setfield(disc,"post",phead)
- end
- if replace then
- setnext(rtail,rhead)
- setprev(rhead,rtail)
- else
- setfield(disc,"replace",rhead)
- end
-end
-
--- start is a mark and we need to keep that one
-
-local function markstoligature(kind,lookupname,head,start,stop,char)
- if start == stop and getchar(start) == char then
- return head, start
- else
- local prev = getprev(start)
- local next = getnext(stop)
- setprev(start,nil)
- setnext(stop,nil)
- local base = copy_glyph(start)
- if head == start then
- head = base
- end
- resetinjection(base)
- setchar(base,char)
- setsubtype(base,ligature_code)
- setfield(base,"components",start)
- if prev then
- setnext(prev,base)
- end
- if next then
- setprev(next,base)
- end
- setnext(base,next)
- setprev(base,prev)
- return head, base
- end
-end
-
--- The next code is somewhat complicated by the fact that some fonts can have ligatures made
--- from ligatures that themselves have marks. This was identified by Kai in for instance
--- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes
--- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next
--- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
--- third component.
-
-local function getcomponentindex(start) -- we could store this offset in the glyph (nofcomponents)
- if getid(start) ~= glyph_code then -- and then get rid of all components
- return 0
- elseif getsubtype(start) == ligature_code then
- local i = 0
- local components = getfield(start,"components")
- while components do
- i = i + getcomponentindex(components)
- components = getnext(components)
- end
- return i
- elseif not marks[getchar(start)] then
- return 1
- else
- return 0
- end
-end
-
-local a_noligature = attributes.private("noligature")
-
-local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) -- brr head
- if getattr(start,a_noligature) == 1 then
- -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first)
- return head, start
- end
- if start == stop and getchar(start) == char then
- resetinjection(start)
- setchar(start,char)
- return head, start
- end
- -- needs testing (side effects):
- local components = getfield(start,"components")
- if components then
- -- we get a double free .. needs checking
- -- flush_node_list(components)
- end
- --
- local prev = getprev(start)
- local next = getnext(stop)
- local comp = start
- setprev(start,nil)
- setnext(stop,nil)
- local base = copy_glyph(start)
- if start == head then
- head = base
- end
- resetinjection(base)
- setchar(base,char)
- setsubtype(base,ligature_code)
- setfield(base,"components",comp) -- start can have components ... do we need to flush?
- if prev then
- setnext(prev,base)
- end
- if next then
- setprev(next,base)
- end
- setprev(base,prev)
- setnext(base,next)
- if not discfound then
- local deletemarks = markflag ~= "mark"
- local components = start
- local baseindex = 0
- local componentindex = 0
- local head = base
- local current = base
- -- first we loop over the glyphs in start .. stop
- while start do
- local char = getchar(start)
- if not marks[char] then
- baseindex = baseindex + componentindex
- componentindex = getcomponentindex(start)
- elseif not deletemarks then -- quite fishy
- setligaindex(start,baseindex + getligaindex(start,componentindex))
- if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
- end
- local n = copy_node(start)
- copyinjection(n,start)
- head, current = insert_node_after(head,current,n) -- unlikely that mark has components
- elseif trace_marks then
- logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char))
- end
- start = getnext(start)
- end
- -- we can have one accent as part of a lookup and another following
- -- local start = components -- was wrong (component scanning was introduced when more complex ligs in devanagari was added)
- local start = getnext(current)
- while start and getid(start) == glyph_code do
- local char = getchar(start)
- if marks[char] then
- setligaindex(start,baseindex + getligaindex(start,componentindex))
- if trace_marks then
- logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),getligaindex(start))
- end
- else
- break
- end
- start = getnext(start)
- end
- else
- -- discfound ... forget about marks .. probably no scripts that hyphenate and have marks
- local discprev = getprev(discfound)
- local discnext = getnext(discfound)
- if discprev and discnext then
- -- we assume normalization in context, and don't care about generic ... especially
- -- \- can give problems as there we can have a negative char but that won't match
- -- anyway
- local pre = getfield(discfound,"pre")
- local post = getfield(discfound,"post")
- local replace = getfield(discfound,"replace")
- if not replace then -- todo: signal simple hyphen
- local prev = getprev(base)
- local copied = copy_node_list(comp)
- setprev(discnext,nil) -- also blocks funny assignments
- setnext(discprev,nil) -- also blocks funny assignments
- if pre then
- setnext(discprev,pre)
- setprev(pre,discprev)
- end
- pre = comp
- if post then
- local tail = find_node_tail(post)
- setnext(tail,discnext)
- setprev(discnext,tail)
- setprev(post,nil)
- else
- post = discnext
- end
- setnext(prev,discfound)
- setprev(discfound,prev)
- setnext(discfound,next)
- setprev(next,discfound)
- setnext(base,nil)
- setprev(base,nil)
- setfield(base,"components",copied)
- setfield(discfound,"pre",pre)
- setfield(discfound,"post",post)
- setfield(discfound,"replace",base)
- setsubtype(discfound,discretionary_code)
- base = prev -- restart
- end
- end
- end
- return head, base
-end
-
-local function multiple_glyphs(head,start,multiple,ignoremarks)
- local nofmultiples = #multiple
- if nofmultiples > 0 then
- resetinjection(start)
- setchar(start,multiple[1])
- if nofmultiples > 1 then
- local sn = getnext(start)
- for k=2,nofmultiples do -- todo: use insert_node
--- untested:
---
--- while ignoremarks and marks[getchar(sn)] then
--- local sn = getnext(sn)
--- end
- local n = copy_node(start) -- ignore components
- resetinjection(n)
- setchar(n,multiple[k])
- setprev(n,start)
- setnext(n,sn)
- if sn then
- setprev(sn,n)
- end
- setnext(start,n)
- start = n
- end
- end
- return head, start, true
- else
- if trace_multiples then
- logprocess("no multiple for %s",gref(getchar(start)))
- end
- return head, start, false
- end
-end
-
-local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
- local n = #alternatives
- if value == "random" then
- local r = getrandom and getrandom("glyph",1,n) or random(1,n)
- return alternatives[r], trace_alternatives and formatters["value %a, taking %a"](value,r)
- elseif value == "first" then
- return alternatives[1], trace_alternatives and formatters["value %a, taking %a"](value,1)
- elseif value == "last" then
- return alternatives[n], trace_alternatives and formatters["value %a, taking %a"](value,n)
- else
- value = tonumber(value)
- if type(value) ~= "number" then
- return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
- elseif value > n then
- local defaultalt = otf.defaultnodealternate
- if defaultalt == "first" then
- return alternatives[n], trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
- elseif defaultalt == "last" then
- return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,n)
- else
- return false, trace_alternatives and formatters["invalid value %a, %s"](value,"out of range")
- end
- elseif value == 0 then
- return getchar(start), trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
- elseif value < 1 then
- return alternatives[1], trace_alternatives and formatters["invalid value %a, taking %a"](value,1)
- else
- return alternatives[value], trace_alternatives and formatters["value %a, taking %a"](value,value)
- end
- end
-end
-
--- handlers
-
-function handlers.gsub_single(head,start,kind,lookupname,replacement)
- if trace_singles then
- logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
- end
- resetinjection(start)
- setchar(start,replacement)
- return head, start, true
-end
-
-function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
- local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
- local choice, comment = get_alternative_glyph(start,alternative,value,trace_alternatives)
- if choice then
- if trace_alternatives then
- logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment)
- end
- resetinjection(start)
- setchar(start,choice)
- else
- if trace_alternatives then
- logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment)
- end
- end
- return head, start, true
-end
-
-function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence)
- if trace_multiples then
- logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple))
- end
- return multiple_glyphs(head,start,multiple,sequence.flags[1])
-end
-
-function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
- local s, stop = getnext(start), nil
- local startchar = getchar(start)
- if marks[startchar] then
- while s do
- local id = getid(s)
- if id == glyph_code and getfont(s) == currentfont and getsubtype(s)<256 then
- local lg = ligature[getchar(s)]
- if lg then
- stop = s
- ligature = lg
- s = getnext(s)
- else
- break
- end
- else
- break
- end
- end
- if stop then
- local lig = ligature.ligature
- if lig then
- if trace_ligatures then
- local stopchar = getchar(stop)
- head, start = markstoligature(kind,lookupname,head,start,stop,lig)
- logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
- else
- head, start = markstoligature(kind,lookupname,head,start,stop,lig)
- end
- return head, start, true, false
- else
- -- ok, goto next lookup
- end
- end
- else
- local skipmark = sequence.flags[1]
- local discfound = false
- local lastdisc = nil
- while s do
- local id = getid(s)
- if id == glyph_code and getsubtype(s)<256 then -- not needed
- if getfont(s) == currentfont then -- also not needed only when mark
- local char = getchar(s)
- if skipmark and marks[char] then
- s = getnext(s)
- else -- ligature is a tree
- local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font
- if lg then
- if not discfound and lastdisc then
- discfound = lastdisc
- lastdisc = nil
- end
- stop = s -- needed for fake so outside then
- ligature = lg
- s = getnext(s)
- else
- break
- end
- end
- else
- break
- end
- elseif id == disc_code then
- lastdisc = s
- s = getnext(s)
- else
- break
- end
- end
- local lig = ligature.ligature -- can't we get rid of this .ligature?
- if lig then
- if stop then
- if trace_ligatures then
- local stopchar = getchar(stop)
- head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
- logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
- else
- head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
- end
- else
- -- weird but happens (in some arabic font)
- resetinjection(start)
- setchar(start,lig)
- if trace_ligatures then
- logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig))
- end
- end
- return head, start, true, discfound
- else
- -- weird but happens, pseudo ligatures ... just the components
- end
- end
- return head, start, false, discfound
-end
-
-function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
- local startchar = getchar(start)
- local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,injection) -- ,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
- end
- return head, start, false
-end
-
-function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence,lookuphash,i,injection)
- -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too
- -- todo: kerns in components of ligatures
- local snext = getnext(start)
- if not snext then
- return head, start, false
- else
- local prev = start
- local done = false
- local factor = tfmdata.parameters.factor
- local lookuptype = lookuptypes[lookupname]
- while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
- local nextchar = getchar(snext)
- local krn = kerns[nextchar]
- if not krn and marks[nextchar] then
- prev = snext
- snext = getnext(snext)
- else
- if not krn then
- -- skip
- elseif type(krn) == "table" then
- if lookuptype == "pair" then -- probably not needed
- local a, b = krn[2], krn[3]
- if a and #a > 0 then
- local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,injection) -- characters[startchar])
- if trace_kerns then
- local startchar = getchar(start)
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- if b and #b > 0 then
- local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,injection) -- characters[nextchar])
- if trace_kerns then
- local startchar = getchar(start)
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- else -- wrong ... position has different entries
- report_process("%s: check this out (old kern stuff)",pref(kind,lookupname))
- -- local a, b = krn[2], krn[6]
- -- if a and a ~= 0 then
- -- local k = setkern(snext,factor,rlmode,a)
- -- if trace_kerns then
- -- logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
- -- end
- -- end
- -- if b and b ~= 0 then
- -- logwarning("%s: ignoring second kern xoff %s",pref(kind,lookupname),b*factor)
- -- end
- end
- done = true
- elseif krn ~= 0 then
- local k = setkern(snext,factor,rlmode,krn,injection)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar)) -- prev?
- end
- done = true
- end
- break
- end
- end
- return head, start, done
- end
-end
-
---[[ldx--
-<p>We get hits on a mark, but we're not sure if the it has to be applied so
-we need to explicitly test for basechar, baselig and basemark entries.</p>
---ldx]]--
-
-function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence)
- local markchar = getchar(start)
- if marks[markchar] then
- local base = getprev(start) -- [glyph] [start=mark]
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
- local basechar = getchar(base)
- if marks[basechar] then
- while true do
- base = getprev(base)
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
- basechar = getchar(base)
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar))
- end
- return head, start, false
- end
- end
- end
- local baseanchors = descriptions[basechar]
- if baseanchors then
- baseanchors = baseanchors.anchors
- end
- if baseanchors then
- local baseanchors = baseanchors['basechar']
- if baseanchors then
- local al = anchorlookups[lookupname]
- for anchor,ba in next, baseanchors do
- if al[anchor] then
- local ma = markanchors[anchor]
- if ma then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
- pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return head, start, true
- end
- end
- end
- if trace_bugs then
- logwarning("%s, no matching anchors for mark %s and base %s",pref(kind,lookupname),gref(markchar),gref(basechar))
- end
- end
- elseif trace_bugs then
- -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
- onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no char",pref(kind,lookupname))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
- end
- return head, start, false
-end
-
-function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence)
- -- check chainpos variant
- local markchar = getchar(start)
- if marks[markchar] then
- local base = getprev(start) -- [glyph] [optional marks] [start=mark]
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
- local basechar = getchar(base)
- if marks[basechar] then
- while true do
- base = getprev(base)
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
- basechar = getchar(base)
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar))
- end
- return head, start, false
- end
- end
- end
- local index = getligaindex(start)
- local baseanchors = descriptions[basechar]
- if baseanchors then
- baseanchors = baseanchors.anchors
- if baseanchors then
- local baseanchors = baseanchors['baselig']
- if baseanchors then
- local al = anchorlookups[lookupname]
- for anchor, ba in next, baseanchors do
- if al[anchor] then
- local ma = markanchors[anchor]
- if ma then
- ba = ba[index]
- if ba then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar]) -- index
- if trace_marks then
- logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
- pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
- end
- return head, start, true
- else
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(kind,lookupname),gref(markchar),gref(basechar),index)
- end
- end
- end
- end
- end
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and baselig %s",pref(kind,lookupname),gref(markchar),gref(basechar))
- end
- end
- end
- elseif trace_bugs then
- -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
- onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no char",pref(kind,lookupname))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
- end
- return head, start, false
-end
-
-function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence)
- local markchar = getchar(start)
- if marks[markchar] then
- local base = getprev(start) -- [glyph] [basemark] [start=mark]
- local slc = getligaindex(start)
- if slc then -- a rather messy loop ... needs checking with husayni
- while base do
- local blc = getligaindex(base)
- if blc and blc ~= slc then
- base = getprev(base)
- else
- break
- end
- end
- end
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then -- subtype test can go
- local basechar = getchar(base)
- local baseanchors = descriptions[basechar]
- if baseanchors then
- baseanchors = baseanchors.anchors
- if baseanchors then
- baseanchors = baseanchors['basemark']
- if baseanchors then
- local al = anchorlookups[lookupname]
- for anchor,ba in next, baseanchors do
- if al[anchor] then
- local ma = markanchors[anchor]
- if ma then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
- pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return head, start, true
- end
- end
- end
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and basemark %s",pref(kind,lookupname),gref(markchar),gref(basechar))
- end
- end
- end
- elseif trace_bugs then
- -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
- onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no mark",pref(kind,lookupname))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
- end
- return head, start, false
-end
-
-function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) -- to be checked
- local alreadydone = cursonce and getprop(start,a_cursbase)
- if not alreadydone then
- local done = false
- local startchar = getchar(start)
- if marks[startchar] then
- if trace_cursive then
- logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
- end
- else
- local nxt = getnext(start)
- while not done and nxt and getid(nxt) == glyph_code and getfont(nxt) == currentfont and getsubtype(nxt)<256 do
- local nextchar = getchar(nxt)
- if marks[nextchar] then
- -- should not happen (maybe warning)
- nxt = getnext(nxt)
- else
- local entryanchors = descriptions[nextchar]
- if entryanchors then
- entryanchors = entryanchors.anchors
- if entryanchors then
- entryanchors = entryanchors['centry']
- if entryanchors then
- local al = anchorlookups[lookupname]
- for anchor, entry in next, entryanchors do
- if al[anchor] then
- local exit = exitanchors[anchor]
- if exit then
- local dx, dy, bound = setcursive(start,nxt,tfmdata.parameters.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
- if trace_cursive then
- logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode)
- end
- done = true
- break
- end
- end
- end
- end
- end
- elseif trace_bugs then
- -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
- onetimemessage(currentfont,startchar,"no entry anchors",report_fonts)
- end
- break
- end
- end
- end
- return head, start, done
- else
- if trace_cursive and trace_details then
- logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
- end
- return head, start, false
- end
-end
-
---[[ldx--
-<p>I will implement multiple chain replacements once I run into a font that uses
-it. It's not that complex to handle.</p>
---ldx]]--
-
-local chainprocs = { }
-
-local function logprocess(...)
- if trace_steps then
- registermessage(...)
- end
- report_subchain(...)
-end
-
-local logwarning = report_subchain
-
-local function logprocess(...)
- if trace_steps then
- registermessage(...)
- end
- report_chain(...)
-end
-
-local logwarning = report_chain
-
--- We could share functions but that would lead to extra function calls with many
--- arguments, redundant tests and confusing messages.
-
-function chainprocs.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname)
- logwarning("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
- return head, start, false
-end
-
--- The reversesub is a special case, which is why we need to store the replacements
--- in a bit weird way. There is no lookup and the replacement comes from the lookup
--- itself. It is meant mostly for dealing with Urdu.
-
-function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements)
- local char = getchar(start)
- local replacement = replacements[char]
- if replacement then
- if trace_singles then
- logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement))
- end
- resetinjection(start)
- setchar(start,replacement)
- return head, start, true
- else
- return head, start, false
- end
-end
-
---[[ldx--
-<p>This chain stuff is somewhat tricky since we can have a sequence of actions to be
-applied: single, alternate, multiple or ligature where ligature can be an invalid
-one in the sense that it will replace multiple by one but not neccessary one that
-looks like the combination (i.e. it is the counterpart of multiple then). For
-example, the following is valid:</p>
-
-<typing>
-<line>xxxabcdexxx [single a->A][multiple b->BCD][ligature cde->E] xxxABCDExxx</line>
-</typing>
-
---[[ldx--
-<p>Here we replace start by a single variant.</p>
---ldx]]--
-
-function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
- -- todo: marks ?
- local current = start
- local subtables = currentlookup.subtables
- if #subtables > 1 then
- logwarning("todo: check if we need to loop over the replacements: % t",subtables)
- end
- while current do
- if getid(current) == glyph_code then
- local currentchar = getchar(current)
- local lookupname = subtables[1] -- only 1
- local replacement = lookuphash[lookupname]
- if not replacement then
- if trace_bugs then
- logwarning("%s: no single hits",cref(kind,chainname,chainlookupname,lookupname,chainindex))
- end
- else
- replacement = replacement[currentchar]
- if not replacement or replacement == "" then
- if trace_bugs then
- logwarning("%s: no single for %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar))
- end
- else
- if trace_singles then
- logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
- end
- resetinjection(current)
- setchar(current,replacement)
- end
- end
- return head, start, true
- elseif current == stop then
- break
- else
- current = getnext(current)
- end
- end
- return head, start, false
-end
-
---[[ldx--
-<p>Here we replace start by a sequence of new glyphs.</p>
---ldx]]--
-
-function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- -- local head, n = delete_till_stop(head,start,stop)
- local startchar = getchar(start)
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local replacements = lookuphash[lookupname]
- if not replacements then
- if trace_bugs then
- logwarning("%s: no multiple hits",cref(kind,chainname,chainlookupname,lookupname))
- end
- else
- replacements = replacements[startchar]
- if not replacements or replacement == "" then
- if trace_bugs then
- logwarning("%s: no multiple for %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar))
- end
- else
- if trace_multiples then
- logprocess("%s: replacing %s by multiple characters %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar),gref(replacements))
- end
- return multiple_glyphs(head,start,replacements,currentlookup.flags[1])
- end
- end
- return head, start, false
-end
-
---[[ldx--
-<p>Here we replace start by new glyph. First we delete the rest of the match.</p>
---ldx]]--
-
--- char_1 mark_1 -> char_x mark_1 (ignore marks)
--- char_1 mark_1 -> char_x
-
--- to be checked: do we always have just one glyph?
--- we can also have alternates for marks
--- marks come last anyway
--- are there cases where we need to delete the mark
-
-function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local current = start
- local subtables = currentlookup.subtables
- local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
- while current do
- if getid(current) == glyph_code then -- is this check needed?
- local currentchar = getchar(current)
- local lookupname = subtables[1]
- local alternatives = lookuphash[lookupname]
- if not alternatives then
- if trace_bugs then
- logwarning("%s: no alternative hit",cref(kind,chainname,chainlookupname,lookupname))
- end
- else
- alternatives = alternatives[currentchar]
- if alternatives then
- local choice, comment = get_alternative_glyph(current,alternatives,value,trace_alternatives)
- if choice then
- if trace_alternatives then
- logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment)
- end
- resetinjection(start)
- setchar(start,choice)
- else
- if trace_alternatives then
- logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment)
- end
- end
- elseif trace_bugs then
- logwarning("%s: no alternative for %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar),comment)
- end
- end
- return head, start, true
- elseif current == stop then
- break
- else
- current = getnext(current)
- end
- end
- return head, start, false
-end
-
---[[ldx--
-<p>When we replace ligatures we use a helper that handles the marks. I might change
-this function (move code inline and handle the marks by a separate function). We
-assume rather stupid ligatures (no complex disc nodes).</p>
---ldx]]--
-
-function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
- local startchar = getchar(start)
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local ligatures = lookuphash[lookupname]
- if not ligatures then
- if trace_bugs then
- logwarning("%s: no ligature hits",cref(kind,chainname,chainlookupname,lookupname,chainindex))
- end
- else
- ligatures = ligatures[startchar]
- if not ligatures then
- if trace_bugs then
- logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
- end
- else
- local s = getnext(start)
- local discfound = false
- local last = stop
- local nofreplacements = 1
- local skipmark = currentlookup.flags[1]
- while s do
- local id = getid(s)
- if id == disc_code then
- if not discfound then
- discfound = s
- end
- if s == stop then
- break -- okay? or before the disc
- else
- s = getnext(s)
- end
- else
- local schar = getchar(s)
- if skipmark and marks[schar] then -- marks
- s = getnext(s)
- else
- local lg = ligatures[schar]
- if lg then
- ligatures, last, nofreplacements = lg, s, nofreplacements + 1
- if s == stop then
- break
- else
- s = getnext(s)
- end
- else
- break
- end
- end
- end
- end
- local l2 = ligatures.ligature
- if l2 then
- if chainindex then
- stop = last
- end
- if trace_ligatures then
- if start == stop then
- logprocess("%s: replacing character %s by ligature %s case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2))
- else
- logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)),gref(l2))
- end
- end
- head, start = toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
- return head, start, true, nofreplacements, discfound
- elseif trace_bugs then
- if start == stop then
- logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
- else
- logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)))
- end
- end
- end
- end
- return head, start, false, 0, false
-end
-
-function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- -- untested .. needs checking for the new model
- local startchar = getchar(start)
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local kerns = lookuphash[lookupname]
- if kerns then
- kerns = kerns[startchar] -- needed ?
- if kerns then
- local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns) -- ,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h)
- end
- end
- end
- return head, start, false
-end
-
-function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local snext = getnext(start)
- if snext then
- local startchar = getchar(start)
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local kerns = lookuphash[lookupname]
- if kerns then
- kerns = kerns[startchar]
- if kerns then
- local lookuptype = lookuptypes[lookupname]
- local prev, done = start, false
- local factor = tfmdata.parameters.factor
- while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do
- local nextchar = getchar(snext)
- local krn = kerns[nextchar]
- if not krn and marks[nextchar] then
- prev = snext
- snext = getnext(snext)
- else
- if not krn then
- -- skip
- elseif type(krn) == "table" then
- if lookuptype == "pair" then
- local a, b = krn[2], krn[3]
- if a and #a > 0 then
- local startchar = getchar(start)
- local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a) -- ,characters[startchar])
- if trace_kerns then
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- if b and #b > 0 then
- local startchar = getchar(start)
- local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b) -- ,characters[nextchar])
- if trace_kerns then
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- else
- report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname))
- -- local a, b = krn[2], krn[6]
- -- if a and a ~= 0 then
- -- local k = setkern(snext,factor,rlmode,a)
- -- if trace_kerns then
- -- logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
- -- end
- -- end
- -- if b and b ~= 0 then
- -- logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor)
- -- end
- end
- done = true
- elseif krn ~= 0 then
- local k = setkern(snext,factor,rlmode,krn)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
- end
- done = true
- end
- break
- end
- end
- return head, start, done
- end
- end
- end
- return head, start, false
-end
-
-function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local markchar = getchar(start)
- if marks[markchar] then
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local markanchors = lookuphash[lookupname]
- if markanchors then
- markanchors = markanchors[markchar]
- end
- if markanchors then
- local base = getprev(start) -- [glyph] [start=mark]
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
- local basechar = getchar(base)
- if marks[basechar] then
- while true do
- base = getprev(base)
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
- basechar = getchar(base)
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar))
- end
- return head, start, false
- end
- end
- end
- local baseanchors = descriptions[basechar].anchors
- if baseanchors then
- local baseanchors = baseanchors['basechar']
- if baseanchors then
- local al = anchorlookups[lookupname]
- for anchor,ba in next, baseanchors do
- if al[anchor] then
- local ma = markanchors[anchor]
- if ma then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
- cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return head, start, true
- end
- end
- end
- if trace_bugs then
- logwarning("%s, no matching anchors for mark %s and base %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
- end
- end
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no char",cref(kind,chainname,chainlookupname,lookupname))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
- end
- return head, start, false
-end
-
-function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local markchar = getchar(start)
- if marks[markchar] then
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local markanchors = lookuphash[lookupname]
- if markanchors then
- markanchors = markanchors[markchar]
- end
- if markanchors then
- local base = getprev(start) -- [glyph] [optional marks] [start=mark]
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
- local basechar = getchar(base)
- if marks[basechar] then
- while true do
- base = getprev(base)
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then
- basechar = getchar(base)
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s",cref(kind,chainname,chainlookupname,lookupname),markchar)
- end
- return head, start, false
- end
- end
- end
- -- todo: like marks a ligatures hash
- local index = getligaindex(start)
- local baseanchors = descriptions[basechar].anchors
- if baseanchors then
- local baseanchors = baseanchors['baselig']
- if baseanchors then
- local al = anchorlookups[lookupname]
- for anchor,ba in next, baseanchors do
- if al[anchor] then
- local ma = markanchors[anchor]
- if ma then
- ba = ba[index]
- if ba then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar])
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
- cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
- end
- return head, start, true
- end
- end
- end
- end
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and baselig %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
- end
- end
- end
- elseif trace_bugs then
- logwarning("feature %s, lookup %s: prev node is no char",kind,lookupname)
- end
- elseif trace_bugs then
- logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
- end
- return head, start, false
-end
-
-function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local markchar = getchar(start)
- if marks[markchar] then
- -- local markanchors = descriptions[markchar].anchors markanchors = markanchors and markanchors.mark
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local markanchors = lookuphash[lookupname]
- if markanchors then
- markanchors = markanchors[markchar]
- end
- if markanchors then
- local base = getprev(start) -- [glyph] [basemark] [start=mark]
- local slc = getligaindex(start)
- if slc then -- a rather messy loop ... needs checking with husayni
- while base do
- local blc = getligaindex(base)
- if blc and blc ~= slc then
- base = getprev(base)
- else
- break
- end
- end
- end
- if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then -- subtype test can go
- local basechar = getchar(base)
- local baseanchors = descriptions[basechar].anchors
- if baseanchors then
- baseanchors = baseanchors['basemark']
- if baseanchors then
- local al = anchorlookups[lookupname]
- for anchor,ba in next, baseanchors do
- if al[anchor] then
- local ma = markanchors[anchor]
- if ma then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,characters[basechar],true)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
- cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return head, start, true
- end
- end
- end
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and basemark %s",gref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar))
- end
- end
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no mark",cref(kind,chainname,chainlookupname,lookupname))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar))
- end
- return head, start, false
-end
-
-function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local alreadydone = cursonce and getprop(start,a_cursbase)
- if not alreadydone then
- local startchar = getchar(start)
- local subtables = currentlookup.subtables
- local lookupname = subtables[1]
- local exitanchors = lookuphash[lookupname]
- if exitanchors then
- exitanchors = exitanchors[startchar]
- end
- if exitanchors then
- local done = false
- if marks[startchar] then
- if trace_cursive then
- logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
- end
- else
- local nxt = getnext(start)
- while not done and nxt and getid(nxt) == glyph_code and getfont(nxt) == currentfont and getsubtype(nxt)<256 do
- local nextchar = getchar(nxt)
- if marks[nextchar] then
- -- should not happen (maybe warning)
- nxt = getnext(nxt)
- else
- local entryanchors = descriptions[nextchar]
- if entryanchors then
- entryanchors = entryanchors.anchors
- if entryanchors then
- entryanchors = entryanchors['centry']
- if entryanchors then
- local al = anchorlookups[lookupname]
- for anchor, entry in next, entryanchors do
- if al[anchor] then
- local exit = exitanchors[anchor]
- if exit then
- local dx, dy, bound = setcursive(start,nxt,tfmdata.parameters.factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
- if trace_cursive then
- logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode)
- end
- done = true
- break
- end
- end
- end
- end
- end
- elseif trace_bugs then
- -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar))
- onetimemessage(currentfont,startchar,"no entry anchors",report_fonts)
- end
- break
- end
- end
- end
- return head, start, done
- else
- if trace_cursive and trace_details then
- logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
- end
- return head, start, false
- end
- end
- return head, start, false
-end
-
--- what pointer to return, spec says stop
--- to be discussed ... is bidi changer a space?
--- elseif char == zwnj and sequence[n][32] then -- brrr
-
--- somehow l or f is global
--- we don't need to pass the currentcontext, saves a bit
--- make a slow variant then can be activated but with more tracing
-
-local function show_skip(kind,chainname,char,ck,class)
- if ck[9] then
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10])
- else
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2])
- end
-end
-
--- A previous version had disc collapsing code in the (single sub) handler plus some
--- checking in the main loop, but that left the pre/post sequences undone. The best
--- solution is to add some checking there and backtrack when a replace/post matches
--- but it takes a bit of work to figure out an efficient way (this is what the sweep*
--- names refer to). I might look into that variant one day again as it can replace
--- some other code too. In that approach we can have a special version for gub and pos
--- which gains some speed. This method does the test and passes info to the handlers
--- (sweepnode, sweepmode, sweepprev, sweepnext, etc). Here collapsing is handled in the
--- main loop which also makes code elsewhere simpler (i.e. no need for the other special
--- runners and disc code in ligature building). I also experimented with pushing preceding
--- glyphs sequences in the replace/pre fields beforehand which saves checking afterwards
--- but at the cost of duplicate glyphs (memory) but it's too much overhead (runtime).
---
--- In the meantime Kai had moved the code from the single chain into a more general handler
--- and this one (renamed to chaindisk) is used now. I optimized the code a bit and brought
--- it in sycn with the other code. Hopefully I didn't introduce errors. Note: this somewhat
--- complex approach is meant for fonts that implement (for instance) ligatures by character
--- replacement which to some extend is not that suitable for hyphenation. I also use some
--- helpers. This method passes some states but reparses the list. There is room for a bit of
--- speed up but that will be done in the context version. (In fact a partial rewrite of all
--- code can bring some more efficientry.)
---
--- I didn't test it with extremes but successive disc nodes still can give issues but in
--- order to handle that we need more complex code which also slows down even more. The main
--- loop variant could deal with that: test, collapse, backtrack.
-
-local function chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,chainindex,sequence,chainproc)
-
- if not start then
- return head, start, false
- end
-
- local startishead = start == head
- local seq = ck[3]
- local f = ck[4]
- local l = ck[5]
- local s = #seq
- local done = false
- local sweepnode = sweepnode
- local sweeptype = sweeptype
- local sweepoverflow = false
- local checkdisc = getprev(head) -- hm bad name head
- local keepdisc = not sweepnode
- local lookaheaddisc = nil
- local backtrackdisc = nil
- local current = start
- local last = start
- local prev = getprev(start)
-
- -- fishy: so we can overflow and then go on in the sweep?
-
- local i = f
- while i <= l do
- local id = getid(current)
- if id == glyph_code then
- i = i + 1
- last = current
- current = getnext(current)
- elseif id == disc_code then
- if keepdisc then
- keepdisc = false
- if notmatchpre[current] ~= notmatchreplace[current] then
- lookaheaddisc = current
- end
- local replace = getfield(current,"replace")
- while replace and i <= l do
- if getid(replace) == glyph_code then
- i = i + 1
- end
- replace = getnext(replace)
- end
- last = current
- current = getnext(c)
- else
- head, current = flattendisk(head,current)
- end
- else
- last = current
- current = getnext(current)
- end
- if current then
- -- go on
- elseif sweepoverflow then
- -- we already are folling up on sweepnode
- break
- elseif sweeptype == "post" or sweeptype == "replace" then
- current = getnext(sweepnode)
- if current then
- sweeptype = nil
- sweepoverflow = true
- else
- break
- end
- else
- break -- added
- end
- end
-
- if sweepoverflow then
- local prev = current and getprev(current)
- if not current or prev ~= sweepnode then
- local head = getnext(sweepnode)
- local tail = nil
- if prev then
- tail = prev
- setprev(current,sweepnode)
- else
- tail = find_node_tail(head)
- end
- setnext(sweepnode,current)
- setprev(head,nil)
- setnext(tail,nil)
- appenddisc(sweepnode,head)
- end
- end
-
- if l < s then
- local i = l
- local t = sweeptype == "post" or sweeptype == "replace"
- while current and i < s do
- local id = getid(current)
- if id == glyph_code then
- i = i + 1
- current = getnext(current)
- elseif id == disc_code then
- if keepdisc then
- keepdisc = false
- if notmatchpre[current] ~= notmatchreplace[current] then
- lookaheaddisc = current
- end
- local replace = getfield(c,"replace")
- while replace and i < s do
- if getid(replace) == glyph_code then
- i = i + 1
- end
- replace = getnext(replace)
- end
- current = getnext(current)
- elseif notmatchpre[current] ~= notmatchreplace[current] then
- head, current = flattendisk(head,current)
- else
- current = getnext(current) -- HH
- end
- else
- current = getnext(current)
- end
- if not current and t then
- current = getnext(sweepnode)
- if current then
- sweeptype = nil
- end
- end
- end
- end
-
- if f > 1 then
- local current = prev
- local i = f
- local t = sweeptype == "pre" or sweeptype == "replace"
- if not current and t and current == checkdisk then
- current = getprev(sweepnode)
- end
- while current and i > 1 do -- missing getprev added / moved outside
- local id = getid(current)
- if id == glyph_code then
- i = i - 1
- elseif id == disc_code then
- if keepdisc then
- keepdisc = false
- if notmatchpost[current] ~= notmatchreplace[current] then
- backtrackdisc = current
- end
- local replace = getfield(current,"replace")
- while replace and i > 1 do
- if getid(replace) == glyph_code then
- i = i - 1
- end
- replace = getnext(replace)
- end
- elseif notmatchpost[current] ~= notmatchreplace[current] then
- head, current = flattendisk(head,current)
- end
- end
- current = getprev(current)
- if t and current == checkdisk then
- current = getprev(sweepnode)
- end
- end
- end
-
- local ok = false
- if lookaheaddisc then
-
- local cf = start
- local cl = getprev(lookaheaddisc)
- local cprev = getprev(start)
- local insertedmarks = 0
-
- while cprev and getid(cf) == glyph_code and getfont(cf) == currentfont and getsubtype(cf) < 256 and marks[getchar(cf)] do
- insertedmarks = insertedmarks + 1
- cf = cprev
- startishead = cf == head
- cprev = getprev(cprev)
- end
-
- setprev(lookaheaddisc,cprev)
- if cprev then
- setnext(cprev,lookaheaddisc)
- end
- setprev(cf,nil)
- setnext(cl,nil)
- if startishead then
- head = lookaheaddisc
- end
-
- local replace = getfield(lookaheaddisc,"replace")
- local pre = getfield(lookaheaddisc,"pre")
- local new = copy_node_list(cf)
- local cnew = new
- for i=1,insertedmarks do
- cnew = getnext(cnew)
- end
- local clast = cnew
- for i=f,l do
- clast = getnext(clast)
- end
- if not notmatchpre[lookaheaddisc] then
- cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
- end
- if not notmatchreplace[lookaheaddisc] then
- new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
- end
- if pre then
- setnext(cl,pre)
- setprev(pre,cl)
- end
- if replace then
- local tail = find_node_tail(new)
- setnext(tail,replace)
- setprev(replace,tail)
- end
- setfield(lookaheaddisc,"pre",cf) -- also updates tail
- setfield(lookaheaddisc,"replace",new) -- also updates tail
-
- start = getprev(lookaheaddisc)
- sweephead[cf] = getnext(clast)
- sweephead[new] = getnext(last)
-
- elseif backtrackdisc then
-
- local cf = getnext(backtrackdisc)
- local cl = start
- local cnext = getnext(start)
- local insertedmarks = 0
-
- while cnext and getid(cnext) == glyph_code and getfont(cnext) == currentfont and getsubtype(cnext) < 256 and marks[getchar(cnext)] do
- insertedmarks = insertedmarks + 1
- cl = cnext
- cnext = getnext(cnext)
- end
- if cnext then
- setprev(cnext,backtrackdisc)
- end
- setnext(backtrackdisc,cnext)
- setprev(cf,nil)
- setnext(cl,nil)
- local replace = getfield(backtrackdisc,"replace")
- local post = getfield(backtrackdisc,"post")
- local new = copy_node_list(cf)
- local cnew = find_node_tail(new)
- for i=1,insertedmarks do
- cnew = getprev(cnew)
- end
- local clast = cnew
- for i=f,l do
- clast = getnext(clast)
- end
- if not notmatchpost[backtrackdisc] then
- cf, start, ok = chainproc(cf,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
- end
- if not notmatchreplace[backtrackdisc] then
- new, cnew, ok = chainproc(new,cnew,clast,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
- end
- if post then
- local tail = find_node_tail(post)
- setnext(tail,cf)
- setprev(cf,tail)
- else
- post = cf
- end
- if replace then
- local tail = find_node_tail(replace)
- setnext(tail,new)
- setprev(new,tail)
- else
- replace = new
- end
- setfield(backtrackdisc,"post",post) -- also updates tail
- setfield(backtrackdisc,"replace",replace) -- also updates tail
- start = getprev(backtrackdisc)
- sweephead[post] = getnext(clast)
- sweephead[replace] = getnext(last)
-
- else
-
- head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
-
- end
-
- return head, start, ok
-end
-
-local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
- local sweepnode = sweepnode
- local sweeptype = sweeptype
- local diskseen = false
- local checkdisc = getprev(head)
- local flags = sequence.flags
- local done = false
- local skipmark = flags[1]
- local skipligature = flags[2]
- local skipbase = flags[3]
- local markclass = sequence.markclass
- local skipped = false
-
- for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu)
- local match = true
- local current = start
- local last = start
- local ck = contexts[k]
- local seq = ck[3]
- local s = #seq
- -- f..l = mid string
- if s == 1 then
- -- never happens
- match = getid(current) == glyph_code and getfont(current) == currentfont and getsubtype(current)<256 and seq[1][getchar(current)]
- else
- -- maybe we need a better space check (maybe check for glue or category or combination)
- -- we cannot optimize for n=2 because there can be disc nodes
- local f = ck[4]
- local l = ck[5]
- -- current match
- if f == 1 and f == l then -- current only
- -- already a hit
- -- match = true
- else -- before/current/after | before/current | current/after
- -- no need to test first hit (to be optimized)
- if f == l then -- new, else last out of sync (f is > 1)
- -- match = true
- else
- local discfound = nil
- local n = f + 1
- last = getnext(last)
- while n <= l do
- if not last and (sweeptype == "post" or sweeptype == "replace") then
- last = getnext(sweepnode)
- sweeptype = nil
- end
- if last then
- local id = getid(last)
- if id == glyph_code then
- if getfont(last) == currentfont and getsubtype(last)<256 then
- local char = getchar(last)
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class or "base"
- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
- skipped = true
- if trace_skips then
- show_skip(kind,chainname,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
- match = not notmatchpre[discfound]
- else
- match = false
- end
- break
- end
- else
- if discfound then
- notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
- else
- match = false
- end
- break
- end
- else
- if discfound then
- notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
- else
- match = false
- end
- break
- end
- elseif id == disc_code then
- diskseen = true
- discfound = last
- notmatchpre[last] = nil
- notmatchpost[last] = true
- notmatchreplace[last] = nil
- local pre = getfield(last,"pre")
- local replace = getfield(last,"replace")
- if pre then
- local n = n
- while pre do
- if seq[n][getchar(pre)] then
- n = n + 1
- pre = getnext(pre)
- if n > l then
- break
- end
- 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
- replace = getnext(replace)
- if n > l then
- break
- end
- else
- notmatchreplace[last] = true
- match = not notmatchpre[last]
- break
- end
- end
- match = not notmatchpre[last]
- end
- last = getnext(last)
- else
- match = false
- break
- end
- else
- match = false
- break
- end
- end
- end
- end
- -- before
- if match and f > 1 then
- local prev = getprev(start)
- if prev then
- if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then
- prev = getprev(sweepnode)
- -- sweeptype = nil
- end
- if prev then
- local discfound = nil
- local n = f - 1
- while n >= 1 do
- if prev then
- local id = getid(prev)
- if id == glyph_code then
- if getfont(prev) == currentfont and getsubtype(prev)<256 then -- normal char
- local char = getchar(prev)
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class
- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
- skipped = true
- if trace_skips then
- show_skip(kind,chainname,char,ck,class)
- end
- elseif seq[n][char] then
- n = n -1
- else
- if discfound then
- notmatchreplace[discfound] = true
- match = not notmatchpost[discfound]
- else
- match = false
- end
- break
- end
- else
- if discfound then
- notmatchreplace[discfound] = true
- match = not notmatchpost[discfound]
- else
- match = false
- end
- break
- end
- else
- if discfound then
- notmatchreplace[discfound] = true
- match = not notmatchpost[discfound]
- else
- match = false
- end
- break
- end
- elseif id == disc_code 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 = getfield(prev,"pre")
- local post = getfield(prev,"post")
- local replace = getfield(prev,"replace")
- if pre ~= start and post ~= start and replace ~= start then
- if post then
- local n = n
- local posttail = find_node_tail(post)
- while posttail do
- if seq[n][getchar(posttail)] then
- n = n - 1
- if posttail == post then
- break
- else
- posttail = getprev(posttail)
- if n < 1 then
- break
- end
- 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)
- local replacetail = find_node_tail(replace)
- while replacetail do
- if seq[n][getchar(replacetail)] then
- n = n - 1
- if replacetail == replace then
- break
- else
- replacetail = getprev(replacetail)
- if n < 1 then
- break
- end
- end
- else
- notmatchreplace[prev] = true
- match = not notmatchpost[prev]
- break
- end
- end
- if not match then
- break
- end
- else
- -- skip 'm
- end
- else
- -- skip 'm
- end
- elseif seq[n][32] then
- n = n -1
- else
- match = false
- break
- end
- prev = getprev(prev)
- elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
- n = n - 1
- else
- match = false
- break
- end
- end
- else
- match = false
- end
- else
- match = false
- end
- end
- -- after
- if match and s > l then
- local current = last and getnext(last)
- if not current then
- if sweeptype == "post" or sweeptype == "replace" then
- current = getnext(sweepnode)
- -- sweeptype = nil
- end
- end
- if current then
- local discfound = nil
- -- removed optimization for s-l == 1, we have to deal with marks anyway
- local n = l + 1
- while n <= s do
- if current then
- local id = getid(current)
- if id == glyph_code then
- if getfont(current) == currentfont and getsubtype(current)<256 then -- normal char
- local char = getchar(current)
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class
- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
- skipped = true
- if trace_skips then
- show_skip(kind,chainname,char,ck,class)
- end
- elseif seq[n][char] then
- n = n + 1
- else
- if discfound then
- notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
- else
- match = false
- end
- break
- end
- else
- if discfound then
- notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
- else
- match = false
- end
- break
- end
- else
- if discfound then
- notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
- else
- match = false
- end
- break
- end
- elseif id == disc_code then
- diskseen = true
- discfound = current
- notmatchpre[current] = nil
- notmatchpost[current] = true
- notmatchreplace[current] = nil
- local pre = getfield(current,"pre")
- local replace = getfield(current,"replace")
- if pre then
- local n = n
- while pre do
- if seq[n][getchar(pre)] then
- n = n + 1
- pre = getnext(pre)
- if n > s then
- break
- end
- 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
- replace = getnext(replace)
- if n > s then
- break
- end
- else
- notmatchreplace[current] = true
- match = notmatchpre[current]
- break
- end
- end
- if not match then
- break
- end
- else
- -- skip 'm
- end
- elseif seq[n][32] then -- brrr
- n = n + 1
- else
- match = false
- break
- end
- current = getnext(current)
- elseif seq[n][32] then
- n = n + 1
- else
- match = false
- break
- end
- end
- else
- match = false
- end
- end
- end
- if match then
- -- can lookups be of a different type ?
- local diskchain = diskseen or sweepnode
- if trace_contexts then
- local rule, lookuptype, f, l = ck[1], ck[2], ck[4], ck[5]
- local char = getchar(start)
- if ck[9] then
- logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a",
- cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10])
- else
- logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a",
- cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype)
- end
- end
- local chainlookups = ck[6]
- if chainlookups then
- local nofchainlookups = #chainlookups
- -- we can speed this up if needed
- if nofchainlookups == 1 then
- local chainlookupname = chainlookups[1]
- local chainlookup = lookuptable[chainlookupname]
- if chainlookup then
- local chainproc = chainprocs[chainlookup.type]
- if chainproc then
- local ok
- if diskchain then
- head, start, ok = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
- else
- head, start, ok = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
- end
- if ok then
- done = true
- end
- else
- logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
- end
- else -- shouldn't happen
- logprocess("%s is not yet supported",cref(kind,chainname,chainlookupname))
- end
- else
- local i = 1
- while start and true do
- if skipped then
- while true do -- todo: use properties
- local char = getchar(start)
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class or "base"
- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
- start = getnext(start)
- else
- break
- end
- else
- break
- end
- end
- end
- -- see remark in ms standard under : LookupType 5: Contextual Substitution Subtable
- local chainlookupname = chainlookups[i]
- local chainlookup = lookuptable[chainlookupname]
- if not chainlookup then
- -- we just advance
- i = i + 1
- else
- local chainproc = chainprocs[chainlookup.type]
- if not chainproc then
- -- actually an error
- logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
- i = i + 1
- else
- local ok, n
- if diskchain then
- head, start, ok = chaindisk(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence,chainproc)
- else
- head, start, ok, n = chainproc(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
- end
- -- messy since last can be changed !
- if ok then
- done = true
- if n and n > 1 then
- -- we have a ligature (cf the spec we advance one but we really need to test it
- -- as there are fonts out there that are fuzzy and have too many lookups:
- --
- -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes
- --
- if i + n > nofchainlookups then
- -- if trace_contexts then
- -- logprocess("%s: quitting lookups",cref(kind,chainname))
- -- end
- break
- else
- -- we need to carry one
- end
- end
- end
- i = i + 1
- end
- end
- if i > nofchainlookups or not start then
- break
- elseif start then
- start = getnext(start)
- end
- end
- end
- else
- local replacements = ck[7]
- if replacements then
- head, start, done = chainprocs.reversesub(head,start,last,kind,chainname,ck,lookuphash,replacements) -- sequence
- else
- done = quit_on_no_replacement -- can be meant to be skipped / quite inconsistent in fonts
- if trace_contexts then
- logprocess("%s: skipping match",cref(kind,chainname))
- end
- end
- end
- if done then
- break -- out of contexts (new, needs checking)
- end
- end
- end
- if diskseen then -- maybe move up so that we can turn checking on/off
- notmatchpre = { }
- notmatchpost = { }
- notmatchreplace = { }
- end
- return head, start, done
-end
-
--- Because we want to keep this elsewhere (an because speed is less an issue) we
--- pass the font id so that the verbose variant can access the relevant helper tables.
-
-local verbose_handle_contextchain = function(font,...)
- logwarning("no verbose handler installed, reverting to 'normal'")
- otf.setcontextchain()
- return normal_handle_contextchain(...)
-end
-
-otf.chainhandlers = {
- normal = normal_handle_contextchain,
- verbose = verbose_handle_contextchain,
-}
-
-local handle_contextchain = nil
-
--- normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash)
-
-local function chained_contextchain(head,start,stop,...)
- local steps = currentlookup.steps
- local nofsteps = currentlookup.nofsteps
- if nofsteps > 1 then
- reportmoresteps(dataset,sequence)
- end
- return handle_contextchain(head,start,...)
-end
-
-function otf.setcontextchain(method)
- if not method or method == "normal" or not otf.chainhandlers[method] then
- if handle_contextchain then -- no need for a message while making the format
- logwarning("installing normal contextchain handler")
- end
- handle_contextchain = normal_handle_contextchain
- else
- logwarning("installing contextchain handler %a",method)
- local handler = otf.chainhandlers[method]
- handle_contextchain = function(...)
- return handler(currentfont,...) -- hm, get rid of ...
- end
- end
-
- handlers.gsub_context = handle_contextchain
- handlers.gsub_contextchain = handle_contextchain
- handlers.gsub_reversecontextchain = handle_contextchain
- handlers.gpos_contextchain = handle_contextchain
- handlers.gpos_context = handle_contextchain
-
- handlers.contextchain = handle_contextchain
-
-end
-
-chainprocs.gsub_context = chained_contextchain
-chainprocs.gsub_contextchain = chained_contextchain
-chainprocs.gsub_reversecontextchain = chained_contextchain
-chainprocs.gpos_contextchain = chained_contextchain
-chainprocs.gpos_context = chained_contextchain
-
-otf.setcontextchain()
-
-local missing = { } -- we only report once
-
-local function logprocess(...)
- if trace_steps then
- registermessage(...)
- end
- report_process(...)
-end
-
-local logwarning = report_process
-
-local function report_missing_cache(typ,lookup)
- local f = missing[currentfont] if not f then f = { } missing[currentfont] = f end
- local t = f[typ] if not t then t = { } f[typ] = t end
- if not t[lookup] then
- t[lookup] = true
- logwarning("missing cache for lookup %a, type %a, font %a, name %a",lookup,typ,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 lookuphashes = { }
-
-setmetatableindex(lookuphashes, function(t,font)
- local lookuphash = fontdata[font].resources.lookuphash
- if not lookuphash or not next(lookuphash) then
- lookuphash = false
- end
- t[font] = lookuphash
- return lookuphash
-end)
-
--- fonts.hashes.lookups = lookuphashes
-
-local autofeatures = fonts.analyzers.features
-local featuretypes = otf.tables.featuretypes
-local defaultscript = otf.features.checkeddefaultscript
-local defaultlanguage = otf.features.checkeddefaultlanguage
-
-local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
- local features = sequence.features
- if features then
- local order = sequence.order
- if order then
- local featuretype = featuretypes[sequence.type or "unknown"]
- for i=1,#order do
- local kind = order[i]
- local valid = enabled[kind]
- if valid then
- local scripts = features[kind]
- local languages = scripts and (
- scripts[script] or
- scripts[wildcard] or
- (autoscript and defaultscript(featuretype,autoscript,scripts))
- )
- local enabled = languages and (
- languages[language] or
- languages[wildcard] or
- (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
- )
- if enabled then
- return { valid, autofeatures[kind] or false, sequence, kind }
- end
- end
- end
- else
- -- can't happen
- end
- end
- return false
-end
-
-function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
- local shared = tfmdata.shared
- local properties = tfmdata.properties
- local language = properties.language or "dflt"
- local script = properties.script or "dflt"
- local enabled = shared.features
- local autoscript = enabled and enabled.autoscript
- local autolanguage = enabled and enabled.autolanguage
- local res = resolved[font]
- if not res then
- res = { }
- resolved[font] = res
- end
- local rs = res[script]
- if not rs then
- rs = { }
- res[script] = rs
- end
- local rl = rs[language]
- if not rl then
- rl = {
- -- indexed but we can also add specific data by key
- }
- rs[language] = rl
- local sequences = tfmdata.resources.sequences
- if sequences then
- for s=1,#sequences do
- local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
- if v then
- rl[#rl+1] = v
- end
- end
- end
- end
- return rl
-end
-
--- assumptions:
---
--- * languages that use complex disc nodes
-
-local function kernrun(disc,run)
- --
- -- we catch <font 1><disc font 2>
- --
- if trace_kernruns then
- report_run("kern") -- will be more detailed
- end
- --
- local prev = getprev(disc) -- todo, keep these in the main loop
- local next = getnext(disc) -- todo, keep these in the main loop
- --
- local pre = getfield(disc,"pre")
- local post = getfield(disc,"post")
- local replace = getfield(disc,"replace")
- --
- local prevmarks = prev
- --
- -- can be optional, because why on earth do we get a disc after a mark (okay, maybe when a ccmp
- -- has happened but then it should be in the disc so basically this test indicates an error)
- --
- while prevmarks and getid(prevmarks) == glyph_code and marks[getchar(prevmarks)] and getfont(prevmarks) == currentfont and getsubtype(prevmarks) < 256 do
- prevmarks = getprev(prevmarks)
- end
- --
- if prev and (pre or replace) and not (getid(prev) == glyph_code and getfont(prev) == currentfont and getsubtype(prev)<256) then
- prev = false
- end
- if next and (post or replace) and not (getid(next) == glyph_code and getfont(next) == currentfont and getsubtype(next)<256) then
- next = false
- end
- --
- if not pre then
- -- go on
- elseif prev then
- local nest = getprev(pre)
- setprev(pre,prev)
- setnext(prev,pre)
- run(prevmarks,"preinjections")
- setprev(pre,nest)
- setnext(prev,disc)
- else
- run(pre,"preinjections")
- end
- --
- if not post then
- -- go on
- elseif next then
- local tail = find_node_tail(post)
- setnext(tail,next)
- setprev(next,tail)
- run(post,"postinjections",next)
- setnext(tail,nil)
- setprev(next,disc)
- else
- run(post,"postinjections")
- end
- --
- if not replace and prev and next then
- -- this should be already done by discfound
- setnext(prev,next)
- setprev(next,prev)
- run(prevmarks,"injections",next)
- setnext(prev,disc)
- setprev(next,disc)
- elseif prev and next then
- local tail = find_node_tail(replace)
- local nest = getprev(replace)
- setprev(replace,prev)
- setnext(prev,replace)
- setnext(tail,next)
- setprev(next,tail)
- run(prevmarks,"replaceinjections",next)
- setprev(replace,nest)
- setnext(prev,disc)
- setnext(tail,nil)
- setprev(next,disc)
- elseif prev then
- local nest = getprev(replace)
- setprev(replace,prev)
- setnext(prev,replace)
- run(prevmarks,"replaceinjections")
- setprev(replace,nest)
- setnext(prev,disc)
- elseif next then
- local tail = find_node_tail(replace)
- setnext(tail,next)
- setprev(next,tail)
- run(replace,"replaceinjections",next)
- setnext(tail,nil)
- setprev(next,disc)
- else
- run(replace,"replaceinjections")
- end
-end
-
--- the if new test might be dangerous as luatex will check / set some tail stuff
--- in a temp node
-
-local function comprun(disc,run)
- if trace_compruns then
- report_run("comp: %s",languages.serializediscretionary(disc))
- end
- --
- local pre = getfield(disc,"pre")
- if pre then
- sweepnode = disc
- sweeptype = "pre" -- in alternative code preinjections is used (also used then for proeprties, saves a variable)
- local new, done = run(pre)
- if done then
- setfield(disc,"pre",new)
- end
- end
- --
- local post = getfield(disc,"post")
- if post then
- sweepnode = disc
- sweeptype = "post"
- local new, done = run(post)
- if done then
- setfield(disc,"post",new)
- end
- end
- --
- local replace = getfield(disc,"replace")
- if replace then
- sweepnode = disc
- sweeptype = "replace"
- local new, done = run(replace)
- if done then
- setfield(disc,"replace",new)
- end
- end
- sweepnode = nil
- sweeptype = nil
-end
-
-local function testrun(disc,trun,crun) -- use helper
- local next = getnext(disc)
- if next then
- local replace = getfield(disc,"replace")
- if replace then
- local prev = getprev(disc)
- if prev then
- -- only look ahead
- local tail = find_node_tail(replace)
- -- local nest = getprev(replace)
- setnext(tail,next)
- setprev(next,tail)
- if trun(replace,next) then
- setfield(disc,"replace",nil) -- beware, side effects of nest so first
- setnext(prev,replace)
- setprev(replace,prev)
- setprev(next,tail)
- setnext(tail,next)
- setprev(disc,nil)
- setnext(disc,nil)
- flush_node_list(disc)
- return replace -- restart
- else
- setnext(tail,nil)
- setprev(next,disc)
- end
- else
- -- weird case
- end
- else
- -- no need
- end
- else
- -- weird case
- end
- comprun(disc,crun)
- return next
-end
-
-local function discrun(disc,drun,krun)
- local next = getnext(disc)
- local prev = getprev(disc)
- if trace_discruns then
- report_run("disc") -- will be more detailed
- end
- if next and prev then
- setnext(prev,next)
- -- setprev(next,prev)
- drun(prev)
- setnext(prev,disc)
- -- setprev(next,disc)
- end
- --
- local pre = getfield(disc,"pre")
- if not pre then
- -- go on
- elseif prev then
- local nest = getprev(pre)
- setprev(pre,prev)
- setnext(prev,pre)
- krun(prev,"preinjections")
- setprev(pre,nest)
- setnext(prev,disc)
- else
- krun(pre,"preinjections")
- end
- return next
-end
-
--- todo: maybe run lr and rl stretches
-
-local function featuresprocessor(head,font,attr)
-
- local lookuphash = lookuphashes[font] -- we can also check sequences here
-
- if not lookuphash then
- return head, false
- end
-
- head = tonut(head)
-
- if trace_steps then
- checkstep(head)
- end
-
- tfmdata = fontdata[font]
- descriptions = tfmdata.descriptions
- characters = tfmdata.characters
- resources = tfmdata.resources
-
- marks = resources.marks
- anchorlookups = resources.lookup_to_anchor
- lookuptable = resources.lookups
- lookuptypes = resources.lookuptypes
- lookuptags = resources.lookuptags
-
- currentfont = font
- rlmode = 0
- sweephead = { }
-
- local sequences = resources.sequences
- local done = false
- local datasets = otf.dataset(tfmdata,font,attr)
-
- local dirstack = { } -- could move outside function
-
- -- We could work on sub start-stop ranges instead but I wonder if there is that
- -- much speed gain (experiments showed that it made not much sense) and we need
- -- to keep track of directions anyway. Also at some point I want to play with
- -- font interactions and then we do need the full sweeps.
-
- -- Keeping track of the headnode is needed for devanagari (I generalized it a bit
- -- so that multiple cases are also covered.)
-
- -- We don't goto the next node of a disc node is created so that we can then treat
- -- the pre, post and replace. It's abit of a hack but works out ok for most cases.
-
- -- there can be less subtype and attr checking in the comprun etc helpers
-
- for s=1,#datasets do
- local dataset = datasets[s]
- featurevalue = dataset[1] -- todo: pass to function instead of using a global
- local attribute = dataset[2]
- local sequence = dataset[3] -- sequences[s] -- also dataset[5]
- local kind = dataset[4]
- ----- chain = dataset[5] -- sequence.chain or 0
- local rlparmode = 0
- local topstack = 0
- local success = false
- local typ = sequence.type
- local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- maybe all of them
- local subtables = sequence.subtables
- local handler = handlers[typ]
- if typ == "gsub_reversecontextchain" then -- chain < 0
- -- this is a limited case, no special treatments like 'init' etc
- -- we need to get rid of this slide! probably no longer needed in latest luatex
- local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
- while start do
- local id = getid(start)
- if id == glyph_code then
- if getfont(start) == font and getsubtype(start) < 256 then
- local a = getattr(start,0)
- if a then
- a = a == attr
- else
- a = true
- end
- if a then
- local char = getchar(start)
- for i=1,#subtables do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- -- todo: disc?
- head, start, success = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,i)
- if success then
- break
- end
- end
- else
- report_missing_cache(typ,lookupname)
- end
- end
- if start then start = getprev(start) end
- else
- start = getprev(start)
- end
- else
- start = getprev(start)
- end
- else
- start = getprev(start)
- end
- end
- else
- local ns = #subtables
- local start = head -- local ?
- rlmode = 0 -- to be checked ?
- if ns == 1 then -- happens often
- local lookupname = subtables[1]
- local lookupcache = lookuphash[lookupname]
- if not lookupcache then -- also check for empty cache
- report_missing_cache(typ,lookupname)
- else
-
- local function c_run(head) -- no need to check for 256 and attr probably also the same
- local done = false
- local start = sweephead[head]
- if start then
- sweephead[head] = nil
- else
- start = head
- end
- while start do
- local id = getid(start)
- if id ~= glyph_code then
- -- very unlikely
- start = getnext(start)
- elseif getfont(start) == font and getsubtype(start) < 256 then
- local a = 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
- if a then
- local lookupmatch = lookupcache[getchar(start)]
- if lookupmatch then
- -- sequence kan weg
- local ok
- head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
- if ok then
- done = true
- end
- end
- if start then start = getnext(start) end
- else
- start = getnext(start)
- end
- else
- return head, false
- end
- end
- if done then
- success = true -- needed in this subrun?
- end
- return head, done
- end
-
- local function t_run(start,stop)
- while start ~= stop do
- local id = getid(start)
- if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
- local a = 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
- if a then
- local lookupmatch = lookupcache[getchar(start)]
- if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check
- -- if we need more than ligatures we can outline the code and use functions
- local s = getnext(start)
- local l = nil
- while s do
- local lg = lookupmatch[getchar(s)]
- if lg then
- l = lg
- s = getnext(s)
- else
- break
- end
- end
- if l and l.ligature then
- return true
- end
- end
- end
- start = getnext(start)
- else
- break
- end
- end
- end
-
- local function d_run(prev) -- we can assume that prev and next are glyphs
- local a = getattr(prev,0)
- if a then
- a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
- else
- a = not attribute or getprop(prev,a_state) == attribute
- end
- if a then
- local lookupmatch = lookupcache[getchar(prev)]
- if lookupmatch then
- -- sequence kan weg
- local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,1)
- if ok then
- done = true
- success = true
- end
- end
- end
- end
-
- local function k_run(sub,injection,last)
- local a = getattr(sub,0)
- if a then
- a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
- else
- a = not attribute or getprop(sub,a_state) == attribute
- end
- if a then
- -- sequence kan weg
- for n in traverse_nodes(sub) do -- only gpos
- if n == last then
- break
- end
- local id = getid(n)
- if id == glyph_code then
- local lookupmatch = lookupcache[getchar(n)]
- if lookupmatch then
- local h, d, ok = handler(sub,n,kind,lookupname,lookupmatch,sequence,lookuphash,1,injection)
- if ok then
- done = true
- success = true
- end
- end
- else
- -- message
- end
- end
- end
- end
-
- while start do
- local id = getid(start)
- if id == glyph_code then
- if getfont(start) == font and getsubtype(start) < 256 then -- why a 256 test ...
- local a = 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
- if a then
- local char = getchar(start)
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- -- sequence kan weg
- local ok
- head, start, ok = handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1)
- if ok then
- success = true
- elseif gpossing and zwnjruns and char == zwnj then
- discrun(start,d_run)
- end
- elseif gpossing and zwnjruns and char == zwnj then
- discrun(start,d_run)
- end
- if start then start = getnext(start) end
- else
- start = getnext(start)
- end
- else
- start = getnext(start)
- end
- elseif id == disc_code then
- if gpossing then
- kernrun(start,k_run)
- start = getnext(start)
- elseif typ == "gsub_ligature" then
- start = testrun(start,t_run,c_run)
- else
- comprun(start,c_run)
- start = getnext(start)
- end
- elseif id == math_code then
- start = getnext(end_of_math(start))
- elseif id == dir_code then
- local dir = getfield(start,"dir")
- if dir == "+TLT" then
- topstack = topstack + 1
- dirstack[topstack] = dir
- rlmode = 1
- elseif dir == "+TRT" then
- topstack = topstack + 1
- dirstack[topstack] = dir
- rlmode = -1
- elseif dir == "-TLT" or dir == "-TRT" then
- topstack = topstack - 1
- rlmode = dirstack[topstack] == "+TRT" and -1 or 1
- else
- rlmode = rlparmode
- end
- if trace_directions then
- report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
- end
- start = getnext(start)
- elseif id == localpar_code then
- local dir = getfield(start,"dir")
- if dir == "TRT" then
- rlparmode = -1
- elseif dir == "TLT" then
- rlparmode = 1
- else
- rlparmode = 0
- end
- -- one might wonder if the par dir should be looked at, so we might as well drop the next line
- rlmode = rlparmode
- if trace_directions then
- report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
- end
- start = getnext(start)
- else
- start = getnext(start)
- end
- end
- end
-
- else
-
- local function c_run(head)
- local done = false
- local start = sweephead[head]
- if start then
- sweephead[head] = nil
- else
- start = head
- end
- while start do
- local id = getid(start)
- if id ~= glyph_code then
- -- very unlikely
- start = getnext(start)
- elseif getfont(start) == font and getsubtype(start) < 256 then
- local a = 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
- if a then
- local char = getchar(start)
- for i=1,ns do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- 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,kind,lookupname,lookupmatch,sequence,lookuphash,i)
- if ok then
- done = true
- break
- elseif not start then
- -- don't ask why ... shouldn't happen
- break
- end
- end
- else
- report_missing_cache(typ,lookupname)
- end
- end
- if start then start = getnext(start) end
- else
- start = getnext(start)
- end
- else
- return head, false
- end
- end
- if done then
- success = true
- end
- return head, done
- end
-
- local function d_run(prev)
- local a = getattr(prev,0)
- if a then
- a = (a == attr) and (not attribute or getprop(prev,a_state) == attribute)
- else
- a = not attribute or getprop(prev,a_state) == attribute
- end
- if a then
- -- brr prev can be disc
- local char = getchar(prev)
- for i=1,ns do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- -- we could move all code inline but that makes things even more unreadable
- local h, d, ok = handler(head,prev,kind,lookupname,lookupmatch,sequence,lookuphash,i)
- if ok then
- done = true
- break
- end
- end
- else
- report_missing_cache(typ,lookupname)
- end
- end
- end
- end
-
- local function k_run(sub,injection,last)
- local a = getattr(sub,0)
- if a then
- a = (a == attr) and (not attribute or getprop(sub,a_state) == attribute)
- else
- a = not attribute or getprop(sub,a_state) == attribute
- end
- if a then
- for n in traverse_nodes(sub) do -- only gpos
- if n == last then
- break
- end
- local id = getid(n)
- if id == glyph_code then
- local char = getchar(n)
- for i=1,ns do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local lookupmatch = lookupcache[char]
- if lookupmatch then
- local h, d, ok = handler(head,n,kind,lookupname,lookupmatch,sequence,lookuphash,i,injection)
- if ok then
- done = true
- break
- end
- end
- else
- report_missing_cache(typ,lookupname)
- end
- end
- else
- -- message
- end
- end
- end
- end
-
- local function t_run(start,stop)
- while start ~= stop do
- local id = getid(start)
- if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then
- local a = 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
- if a then
- local char = getchar(start)
- for i=1,ns do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- 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 = getnext(start)
- local l = nil
- while s do
- local lg = lookupmatch[getchar(s)]
- if lg then
- l = lg
- s = getnext(s)
- else
- break
- end
- end
- if l and l.ligature then
- return true
- end
- end
- else
- report_missing_cache(typ,lookupname)
- end
- end
- end
- start = getnext(start)
- else
- break
- end
- end
- end
-
- while start do
- local id = getid(start)
- if id == glyph_code then
- if getfont(start) == font and getsubtype(start) < 256 then
- local a = 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
- if a then
- for i=1,ns do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local char = getchar(start)
- 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,kind,lookupname,lookupmatch,sequence,lookuphash,i)
- if ok then
- success = true
- break
- elseif not start then
- -- don't ask why ... shouldn't happen
- break
- elseif gpossing and zwnjruns and char == zwnj then
- discrun(start,d_run)
- end
- elseif gpossing and zwnjruns and char == zwnj then
- discrun(start,d_run)
- end
- else
- report_missing_cache(typ,lookupname)
- end
- end
- if start then start = getnext(start) end
- else
- start = getnext(start)
- end
- else
- start = getnext(start)
- end
- elseif id == disc_code then
- if gpossing then
- kernrun(start,k_run)
- start = getnext(start)
- elseif typ == "gsub_ligature" then
- start = testrun(start,t_run,c_run)
- else
- comprun(start,c_run)
- start = getnext(start)
- end
- elseif id == math_code then
- start = getnext(end_of_math(start))
- elseif id == dir_code then
- local dir = getfield(start,"dir")
- if dir == "+TLT" then
- topstack = topstack + 1
- dirstack[topstack] = dir
- rlmode = 1
- elseif dir == "+TRT" then
- topstack = topstack + 1
- dirstack[topstack] = dir
- rlmode = -1
- elseif dir == "-TLT" or dir == "-TRT" then
- topstack = topstack - 1
- rlmode = dirstack[topstack] == "+TRT" and -1 or 1
- else
- rlmode = rlparmode
- end
- if trace_directions then
- report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
- end
- start = getnext(start)
- elseif id == localpar_code then
- local dir = getfield(start,"dir")
- if dir == "TRT" then
- rlparmode = -1
- elseif dir == "TLT" then
- rlparmode = 1
- else
- rlparmode = 0
- end
- rlmode = rlparmode
- if trace_directions then
- report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
- end
- start = getnext(start)
- else
- start = getnext(start)
- end
- end
- end
- end
- if success then
- done = true
- end
- if trace_steps then -- ?
- registerstep(head)
- end
-
- end
-
- head = tonode(head)
-
- return head, done
-end
-
--- this might move to the loader
-
-local function generic(lookupdata,lookupname,unicode,lookuphash)
- local target = lookuphash[lookupname]
- if target then
- target[unicode] = lookupdata
- else
- lookuphash[lookupname] = { [unicode] = lookupdata }
- end
-end
-
-local function ligature(lookupdata,lookupname,unicode,lookuphash)
- local target = lookuphash[lookupname]
- if not target then
- target = { }
- lookuphash[lookupname] = target
- end
- for i=1,#lookupdata do
- local li = lookupdata[i]
- local tu = target[li]
- if not tu then
- tu = { }
- target[li] = tu
- end
- target = tu
- end
- target.ligature = unicode
-end
-
--- this is not ok .. it doesn't work for the old loader with new loader extension
--- specs
-
-local function pair(lookupdata,lookupname,unicode,lookuphash)
- local target = lookuphash[lookupname]
- if not target then
- target = { }
- lookuphash[lookupname] = target
- end
- local others = target[unicode]
- local paired = lookupdata[1]
- if not paired then
- -- something is wrong
- elseif others then
- others[paired] = lookupdata
- else
- others = { [paired] = lookupdata }
- target[unicode] = others
- end
-end
-
-local action = {
- substitution = generic,
- multiple = generic,
- alternate = generic,
- position = generic,
- ligature = ligature,
- pair = pair,
- kern = pair,
-}
-
-local function prepare_lookups(tfmdata)
-
- local rawdata = tfmdata.shared.rawdata
- local resources = rawdata.resources
- local lookuphash = resources.lookuphash
- local anchor_to_lookup = resources.anchor_to_lookup
- local lookup_to_anchor = resources.lookup_to_anchor
- local lookuptypes = resources.lookuptypes
- local characters = tfmdata.characters
- local descriptions = tfmdata.descriptions
- local duplicates = resources.duplicates
-
- -- we cannot free the entries in the descriptions as sometimes we access
- -- then directly (for instance anchors) ... selectively freeing does save
- -- much memory as it's only a reference to a table and the slot in the
- -- description hash is not freed anyway
-
- -- we can delay this using metatables so that we don't make the hashes for
- -- features we don't use but then we need to loop over the characters
- -- many times so we gain nothing
-
- for unicode, character in next, characters do -- we cannot loop over descriptions !
-
- local description = descriptions[unicode]
-
- if description then
-
- local lookups = description.slookups
- if lookups then
- for lookupname, lookupdata in next, lookups do
- action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash,duplicates)
- end
- end
-
- local lookups = description.mlookups
- if lookups then
- for lookupname, lookuplist in next, lookups do
- local lookuptype = lookuptypes[lookupname]
- for l=1,#lookuplist do
- local lookupdata = lookuplist[l]
- action[lookuptype](lookupdata,lookupname,unicode,lookuphash,duplicates)
- end
- end
- end
-
- local list = description.kerns
- if list then
- for lookup, krn in next, list do -- ref to glyph, saves lookup
- local target = lookuphash[lookup]
- if target then
- target[unicode] = krn
- else
- lookuphash[lookup] = { [unicode] = krn }
- end
- end
- end
-
- local list = description.anchors
- if list then
- for typ, anchors in next, list do -- types
- if typ == "mark" or typ == "cexit" then -- or entry?
- for name, anchor in next, anchors do
- local lookups = anchor_to_lookup[name]
- if lookups then
- for lookup in next, lookups do
- local target = lookuphash[lookup]
- if target then
- target[unicode] = anchors
- else
- lookuphash[lookup] = { [unicode] = anchors }
- end
- end
- end
- end
- end
- end
- end
-
- end
-
- end
-
-end
-
--- so far
-
-local function split(replacement,original)
- local result = { }
- for i=1,#replacement do
- result[original[i]] = replacement[i]
- end
- return result
-end
-
-local valid = { -- does contextpos work?
- coverage = { chainsub = true, chainpos = true, contextsub = true, contextpos = true },
- reversecoverage = { reversesub = true },
- glyphs = { chainsub = true, chainpos = true, contextsub = true, contextpos = true },
-}
-
-local function prepare_contextchains(tfmdata)
- local rawdata = tfmdata.shared.rawdata
- local resources = rawdata.resources
- local lookuphash = resources.lookuphash
- local lookuptags = resources.lookuptags
- local lookups = rawdata.lookups
- if lookups then
- for lookupname, lookupdata in next, rawdata.lookups do
- local lookuptype = lookupdata.type
- if lookuptype then
- local rules = lookupdata.rules
- if rules then
- local format = lookupdata.format
- local validformat = valid[format]
- if not validformat then
- report_prepare("unsupported format %a",format)
- elseif not validformat[lookuptype] then
- -- todo: dejavu-serif has one (but i need to see what use it has)
- report_prepare("unsupported format %a, lookuptype %a, lookupname %a",format,lookuptype,lookuptags[lookupname])
- else
- local contexts = lookuphash[lookupname]
- if not contexts then
- contexts = { }
- lookuphash[lookupname] = contexts
- end
- local t, nt = { }, 0
- for nofrules=1,#rules do
- local rule = rules[nofrules]
- local current = rule.current
- local before = rule.before
- local after = rule.after
- local replacements = rule.replacements
- local sequence = { }
- local nofsequences = 0
- -- Eventually we can store start, stop and sequence in the cached file
- -- but then less sharing takes place so best not do that without a lot
- -- of profiling so let's forget about it.
- if before then
- for n=1,#before do
- nofsequences = nofsequences + 1
- sequence[nofsequences] = before[n]
- end
- end
- local start = nofsequences + 1
- for n=1,#current do
- nofsequences = nofsequences + 1
- sequence[nofsequences] = current[n]
- end
- local stop = nofsequences
- if after then
- for n=1,#after do
- nofsequences = nofsequences + 1
- sequence[nofsequences] = after[n]
- end
- end
- if sequence[1] then
- -- Replacements only happen with reverse lookups as they are single only. We
- -- could pack them into current (replacement value instead of true) and then
- -- use sequence[start] instead but it's somewhat ugly.
- nt = nt + 1
- t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements }
- for unic in next, sequence[start] do
- local cu = contexts[unic]
- if not cu then
- contexts[unic] = t
- end
- end
- end
- end
- end
- else
- -- no rules
- end
- else
- report_prepare("missing lookuptype for lookupname %a",lookuptags[lookupname])
- end
- end
- end
-end
-
--- we can consider lookuphash == false (initialized but empty) vs lookuphash == table
-
-local function featuresinitializer(tfmdata,value)
- if true then -- value then
- -- beware we need to use the topmost properties table
- local rawdata = tfmdata.shared.rawdata
- local properties = rawdata.properties
- if not properties.initialized then
- local starttime = trace_preparing and os.clock()
- local resources = rawdata.resources
- resources.lookuphash = resources.lookuphash or { }
- prepare_contextchains(tfmdata)
- prepare_lookups(tfmdata)
- properties.initialized = true
- if trace_preparing then
- report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,tfmdata.properties.fullname)
- end
- end
- end
-end
-
-registerotffeature {
- name = "features",
- description = "features",
- default = true,
- initializers = {
- position = 1,
- node = featuresinitializer,
- },
- processors = {
- node = featuresprocessor,
- }
-}
-
--- This can be used for extra handlers, but should be used with care!
-
-otf.handlers = handlers
diff --git a/tex/context/base/mkiv/font-oto.lua b/tex/context/base/mkiv/font-oto.lua
index 13568799b..9c42a54bd 100644
--- a/tex/context/base/mkiv/font-oto.lua
+++ b/tex/context/base/mkiv/font-oto.lua
@@ -6,10 +6,6 @@ if not modules then modules = { } end modules ['font-oto'] = { -- original tex
license = "see context related readme files"
}
--- This is a version of font-otb adapted to the new fontloader code. We used to have two
--- base initialization methods but now we have only one. This means that instead of the
--- old default (independent) we now use the one more similar to node node (shared).
-
local concat, unpack = table.concat, table.unpack
local insert, remove = table.insert, table.remove
local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
diff --git a/tex/context/base/mkiv/font-otp.lua b/tex/context/base/mkiv/font-otp.lua
deleted file mode 100644
index c52e574b9..000000000
--- a/tex/context/base/mkiv/font-otp.lua
+++ /dev/null
@@ -1,894 +0,0 @@
-if not modules then modules = { } end modules ['font-otp'] = {
- version = 1.001,
- comment = "companion to font-otf.lua (packing)",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- todo: pack math (but not that much to share)
---
--- pitfall 5.2: hashed tables can suddenly become indexed with nil slots
---
--- unless we sort all hashes we can get a different pack order (no big deal but size can differ)
-
-local next, type, tostring = next, type, tostring
-local sort, concat = table.sort, table.concat
-
-local trace_packing = false trackers.register("otf.packing", function(v) trace_packing = v end)
-local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
-
-local report_otf = logs.reporter("fonts","otf loading")
-
--- also used in other scripts so we need to check some tables:
-
-fonts = fonts or { }
-
-local handlers = fonts.handlers or { }
-fonts.handlers = handlers
-
-local otf = handlers.otf or { }
-handlers.otf = otf
-
-local glists = otf.glists or { "gsub", "gpos" }
-otf.glists = glists
-
-local criterium = 1
-local threshold = 0
-
-local function tabstr_normal(t)
- local s = { }
- local n = 0
- for k, v in next, t do
- n = n + 1
- if type(v) == "table" then
- s[n] = k .. ">" .. tabstr_normal(v)
- elseif v == true then
- s[n] = k .. "+" -- "=true"
- elseif v then
- s[n] = k .. "=" .. v
- else
- s[n] = k .. "-" -- "=false"
- end
- end
- if n == 0 then
- return ""
- elseif n == 1 then
- return s[1]
- else
- sort(s) -- costly but needed (occasional wrong hit otherwise)
- return concat(s,",")
- end
-end
-
-local function tabstr_flat(t)
- local s = { }
- local n = 0
- for k, v in next, t do
- n = n + 1
- s[n] = k .. "=" .. v
- end
- if n == 0 then
- return ""
- elseif n == 1 then
- return s[1]
- else
- sort(s) -- costly but needed (occasional wrong hit otherwise)
- return concat(s,",")
- end
-end
-
-local function tabstr_mixed(t) -- indexed
- local s = { }
- local n = #t
- if n == 0 then
- return ""
- elseif n == 1 then
- local k = t[1]
- if k == true then
- return "++" -- we need to distinguish from "true"
- elseif k == false then
- return "--" -- we need to distinguish from "false"
- else
- return tostring(k) -- number or string
- end
- else
- for i=1,n do
- local k = t[i]
- if k == true then
- s[i] = "++" -- we need to distinguish from "true"
- elseif k == false then
- s[i] = "--" -- we need to distinguish from "false"
- else
- s[i] = k -- number or string
- end
- end
- return concat(s,",")
- end
-end
-
-local function tabstr_boolean(t)
- local s = { }
- local n = 0
- for k, v in next, t do
- n = n + 1
- if v then
- s[n] = k .. "+"
- else
- s[n] = k .. "-"
- end
- end
- if n == 0 then
- return ""
- elseif n == 1 then
- return s[1]
- else
- sort(s) -- costly but needed (occasional wrong hit otherwise)
- return concat(s,",")
- end
-end
-
--- tabstr_boolean_x = tabstr_boolean
-
--- tabstr_boolean = function(t)
--- local a = tabstr_normal(t)
--- local b = tabstr_boolean_x(t)
--- print(a)
--- print(b)
--- return b
--- end
-
--- beware: we cannot unpack and repack the same table because then sharing
--- interferes (we could catch this if needed) .. so for now: save, reload
--- and repack in such cases (never needed anyway) .. a tricky aspect is that
--- we then need to sort more thanks to random hashing
-
-function otf.packdata(data)
-
- if data then
- -- stripdata(data)
- local h, t, c = { }, { }, { }
- local hh, tt, cc = { }, { }, { }
- local nt, ntt = 0, 0
- local function pack_normal(v)
- local tag = tabstr_normal(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_flat(v)
- local tag = tabstr_flat(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_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_indexed(v)
- local tag = concat(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_mixed(v)
- local tag = tabstr_mixed(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)
- -- 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
- report_otf("pack quality: nothing to pack")
- end
- return false
- elseif nt >= threshold then
- local one, two, rest = 0, 0, 0
- if pass == 1 then
- for k,v in next, c do
- if v == 1 then
- one = one + 1
- elseif v == 2 then
- two = two + 1
- else
- rest = rest + 1
- end
- end
- else
- for k,v in next, cc do
- if v > 20 then
- rest = rest + 1
- elseif v > 10 then
- two = two + 1
- else
- one = one + 1
- end
- end
- data.tables = tt
- end
- if trace_loading or trace_packing then
- report_otf("pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)", stage, pass, one+two+rest, one, two, rest, criterium)
- end
- return true
- else
- if trace_loading or trace_packing then
- report_otf("pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)", stage, pass, nt, threshold)
- end
- return false
- end
- end
- local function packers(pass)
- if pass == 1 then
- return pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed
- else
- return pack_final, pack_final, pack_final, pack_final, pack_final
- end
- end
- local resources = data.resources
- local lookuptypes = resources.lookuptypes
- 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)
- for unicode, description in next, data.descriptions do
- local boundingbox = description.boundingbox
- if boundingbox then
- description.boundingbox = pack_indexed(boundingbox)
- end
- local slookups = description.slookups
- if slookups then
- for tag, slookup in next, slookups do
- local what = lookuptypes[tag]
- if what == "pair" then
- local t = slookup[2] if t then slookup[2] = pack_indexed(t) end
- local t = slookup[3] if t then slookup[3] = pack_indexed(t) end
- elseif what ~= "substitution" then
- slookups[tag] = pack_indexed(slookup) -- true is new
- end
- end
- end
- local mlookups = description.mlookups
- if mlookups then
- for tag, mlookup in next, mlookups do
- local what = lookuptypes[tag]
- if what == "pair" then
- for i=1,#mlookup do
- local lookup = mlookup[i]
- local t = lookup[2] if t then lookup[2] = pack_indexed(t) end
- local t = lookup[3] if t then lookup[3] = pack_indexed(t) end
- end
- elseif what ~= "substitution" then
- for i=1,#mlookup do
- mlookup[i] = pack_indexed(mlookup[i]) -- true is new
- end
- end
- end
- end
- local kerns = description.kerns
- if kerns then
- for tag, kern in next, kerns do
- kerns[tag] = pack_flat(kern)
- end
- end
- local math = description.math
- if math then
- local kerns = math.kerns
- if kerns then
- for tag, kern in next, kerns do
- kerns[tag] = pack_normal(kern)
- end
- end
- end
- local anchors = description.anchors
- if anchors then
- for what, anchor in next, anchors do
- if what == "baselig" then
- for _, a in next, anchor do
- for k=1,#a do
- a[k] = pack_indexed(a[k])
- end
- end
- else
- for k, v in next, anchor do
- anchor[k] = pack_indexed(v)
- end
- end
- end
- end
- local altuni = description.altuni
- if altuni then
- for i=1,#altuni do
- altuni[i] = pack_flat(altuni[i])
- end
- end
- end
- local lookups = data.lookups
- if lookups then
- for _, lookup in next, lookups do
- local rules = lookup.rules
- if rules then
- for i=1,#rules do
- local rule = rules[i]
- local r = rule.before if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
- local r = rule.after if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
- local r = rule.current if r then for i=1,#r do r[i] = pack_boolean(r[i]) end end
- local r = rule.replacements if r then rule.replacements = pack_flat (r) end -- can have holes
- local r = rule.lookups if r then rule.lookups = pack_indexed(r) end -- can have ""
- -- local r = rule.lookups if r then rule.lookups = pack_flat(r) end -- can have holes (already taken care of some cases)
- end
- end
- end
- end
- local anchor_to_lookup = resources.anchor_to_lookup
- if anchor_to_lookup then
- for anchor, lookup in next, anchor_to_lookup do
- anchor_to_lookup[anchor] = pack_normal(lookup)
- end
- end
- local lookup_to_anchor = resources.lookup_to_anchor
- if lookup_to_anchor then
- for lookup, anchor in next, lookup_to_anchor do
- lookup_to_anchor[lookup] = pack_normal(anchor)
- end
- end
- local sequences = resources.sequences
- if sequences then
- for feature, sequence in next, sequences do
- local flags = sequence.flags
- if flags then
- sequence.flags = pack_normal(flags)
- end
- local subtables = sequence.subtables
- if subtables then
- sequence.subtables = pack_normal(subtables)
- end
- local features = sequence.features
- if features then
- for script, feature in next, features do
- features[script] = pack_normal(feature)
- end
- end
- local order = sequence.order
- if order then
- sequence.order = pack_indexed(order)
- end
- local markclass = sequence.markclass
- if markclass then
- sequence.markclass = pack_boolean(markclass)
- end
- end
- end
- local lookups = resources.lookups
- if lookups then
- for name, lookup in next, lookups do
- local flags = lookup.flags
- if flags then
- lookup.flags = pack_normal(flags)
- end
- local subtables = lookup.subtables
- if subtables then
- lookup.subtables = pack_normal(subtables)
- end
- end
- end
- local features = resources.features
- if features then
- for _, what in next, glists do
- local list = features[what]
- if list then
- for feature, spec in next, list do
- list[feature] = pack_normal(spec)
- end
- end
- end
- end
- if not success(1,pass) then
- return
- end
- end
- if nt > 0 then
- for pass=1,2 do
- 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)
- for unicode, description in next, data.descriptions do
- local kerns = description.kerns
- if kerns then
- description.kerns = pack_normal(kerns)
- end
- local math = description.math
- if math then
- local kerns = math.kerns
- if kerns then
- math.kerns = pack_normal(kerns)
- end
- end
- local anchors = description.anchors
- if anchors then
- description.anchors = pack_normal(anchors)
- end
- local mlookups = description.mlookups
- if mlookups then
- for tag, mlookup in next, mlookups do
- mlookups[tag] = pack_normal(mlookup)
- end
- end
- local altuni = description.altuni
- if altuni then
- description.altuni = pack_normal(altuni)
- end
- end
- local lookups = data.lookups
- if lookups then
- for _, lookup in next, lookups do
- local rules = lookup.rules
- if rules then
- for i=1,#rules do -- was next loop
- local rule = rules[i]
- local r = rule.before if r then rule.before = pack_normal(r) end
- local r = rule.after if r then rule.after = pack_normal(r) end
- local r = rule.current if r then rule.current = pack_normal(r) end
- end
- end
- end
- end
- local sequences = resources.sequences
- if sequences then
- for feature, sequence in next, sequences do
- sequence.features = pack_normal(sequence.features)
- end
- end
- if not success(2,pass) then
- -- return
- end
- end
-
- for pass=1,2 do
- local pack_normal, pack_indexed, pack_flat, pack_boolean, pack_mixed = packers(pass)
- for unicode, description in next, data.descriptions do
- local slookups = description.slookups
- if slookups then
- description.slookups = pack_normal(slookups)
- end
- local mlookups = description.mlookups
- if mlookups then
- description.mlookups = pack_normal(mlookups)
- end
- end
- end
-
- end
- end
-end
-
-local unpacked_mt = {
- __index =
- function(t,k)
- t[k] = false
- return k -- next time true
- end
-}
-
-function otf.unpackdata(data)
-
- if data then
- local tables = data.tables
- if tables then
- local resources = data.resources
- local lookuptypes = resources.lookuptypes
- local unpacked = { }
- setmetatable(unpacked,unpacked_mt)
- for unicode, description in next, data.descriptions do
- local tv = tables[description.boundingbox]
- if tv then
- description.boundingbox = tv
- end
- local slookups = description.slookups
- if slookups then
- local tv = tables[slookups]
- if tv then
- description.slookups = tv
- slookups = unpacked[tv]
- end
- if slookups then
- for tag, lookup in next, slookups do
- local what = lookuptypes[tag]
- if what == "pair" then
- local tv = tables[lookup[2]]
- if tv then
- lookup[2] = tv
- end
- local tv = tables[lookup[3]]
- if tv then
- lookup[3] = tv
- end
- elseif what ~= "substitution" then
- local tv = tables[lookup]
- if tv then
- slookups[tag] = tv
- end
- end
- end
- end
- end
- local mlookups = description.mlookups
- if mlookups then
- local tv = tables[mlookups]
- if tv then
- description.mlookups = tv
- mlookups = unpacked[tv]
- end
- if mlookups then
- for tag, list in next, mlookups do
- local tv = tables[list]
- if tv then
- mlookups[tag] = tv
- list = unpacked[tv]
- end
- if list then
- local what = lookuptypes[tag]
- if what == "pair" then
- for i=1,#list do
- local lookup = list[i]
- local tv = tables[lookup[2]]
- if tv then
- lookup[2] = tv
- end
- local tv = tables[lookup[3]]
- if tv then
- lookup[3] = tv
- end
- end
- elseif what ~= "substitution" then
- for i=1,#list do
- local tv = tables[list[i]]
- if tv then
- list[i] = tv
- end
- end
- end
- end
- end
- end
- end
- local kerns = description.kerns
- if kerns then
- local tm = tables[kerns]
- if tm then
- description.kerns = tm
- kerns = unpacked[tm]
- end
- if kerns then
- for k, kern in next, kerns do
- local tv = tables[kern]
- if tv then
- kerns[k] = tv
- end
- end
- end
- end
- local math = description.math
- if math then
- local kerns = math.kerns
- if kerns then
- local tm = tables[kerns]
- if tm then
- math.kerns = tm
- kerns = unpacked[tm]
- end
- if kerns then
- for k, kern in next, kerns do
- local tv = tables[kern]
- if tv then
- kerns[k] = tv
- end
- end
- end
- end
- end
- local anchors = description.anchors
- if anchors then
- local ta = tables[anchors]
- if ta then
- description.anchors = ta
- anchors = unpacked[ta]
- end
- if anchors then
- for tag, anchor in next, anchors do
- if tag == "baselig" then
- for _, list in next, anchor do
- for i=1,#list do
- local tv = tables[list[i]]
- if tv then
- list[i] = tv
- end
- end
- end
- else
- for a, data in next, anchor do
- local tv = tables[data]
- if tv then
- anchor[a] = tv
- end
- end
- end
- end
- end
- end
- local altuni = description.altuni
- if altuni then
- local altuni = tables[altuni]
- if altuni then
- description.altuni = altuni
- for i=1,#altuni do
- local tv = tables[altuni[i]]
- if tv then
- altuni[i] = tv
- end
- end
- end
- end
- end
- local lookups = data.lookups
- if lookups then
- for _, lookup in next, lookups do
- local rules = lookup.rules
- if rules then
- for i=1,#rules do -- was next loop
- local rule = rules[i]
- local before = rule.before
- if before then
- local tv = tables[before]
- if tv then
- rule.before = tv
- before = unpacked[tv]
- end
- if before then
- for i=1,#before do
- local tv = tables[before[i]]
- if tv then
- before[i] = tv
- end
- end
- end
- end
- local after = rule.after
- if after then
- local tv = tables[after]
- if tv then
- rule.after = tv
- after = unpacked[tv]
- end
- if after then
- for i=1,#after do
- local tv = tables[after[i]]
- if tv then
- after[i] = tv
- end
- end
- end
- end
- local current = rule.current
- if current then
- local tv = tables[current]
- if tv then
- rule.current = tv
- current = unpacked[tv]
- end
- if current then
- for i=1,#current do
- local tv = tables[current[i]]
- if tv then
- current[i] = tv
- end
- end
- end
- end
- local replacements = rule.replacements
- if replacements then
- local tv = tables[replacements]
- if tv then
- rule.replacements = tv
- end
- end
- -- local fore = rule.fore
- -- if fore then
- -- local tv = tables[fore]
- -- if tv then
- -- rule.fore = tv
- -- end
- -- end
- -- local back = rule.back
- -- if back then
- -- local tv = tables[back]
- -- if tv then
- -- rule.back = tv
- -- end
- -- end
- -- local names = rule.names
- -- if names then
- -- local tv = tables[names]
- -- if tv then
- -- rule.names = tv
- -- end
- -- end
- --
- local lookups = rule.lookups
- if lookups then
- local tv = tables[lookups]
- if tv then
- rule.lookups = tv
- end
- end
- end
- end
- end
- end
- local anchor_to_lookup = resources.anchor_to_lookup
- if anchor_to_lookup then
- for anchor, lookup in next, anchor_to_lookup do
- local tv = tables[lookup]
- if tv then
- anchor_to_lookup[anchor] = tv
- end
- end
- end
- local lookup_to_anchor = resources.lookup_to_anchor
- if lookup_to_anchor then
- for lookup, anchor in next, lookup_to_anchor do
- local tv = tables[anchor]
- if tv then
- lookup_to_anchor[lookup] = tv
- end
- end
- end
- local ls = resources.sequences
- if ls then
- for _, feature in next, ls do
- local flags = feature.flags
- if flags then
- local tv = tables[flags]
- if tv then
- feature.flags = tv
- end
- end
- local subtables = feature.subtables
- if subtables then
- local tv = tables[subtables]
- if tv then
- feature.subtables = tv
- end
- end
- local features = feature.features
- if features then
- local tv = tables[features]
- if tv then
- feature.features = tv
- features = unpacked[tv]
- end
- if features then
- for script, data in next, features do
- local tv = tables[data]
- if tv then
- features[script] = tv
- end
- end
- end
- end
- local order = feature.order
- if order then
- local tv = tables[order]
- if tv then
- feature.order = tv
- end
- end
- local markclass = feature.markclass
- if markclass then
- local tv = tables[markclass]
- if tv then
- feature.markclass = tv
- end
- end
- end
- end
- local lookups = resources.lookups
- if lookups then
- for _, lookup in next, lookups do
- local flags = lookup.flags
- if flags then
- local tv = tables[flags]
- if tv then
- lookup.flags = tv
- end
- end
- local subtables = lookup.subtables
- if subtables then
- local tv = tables[subtables]
- if tv then
- lookup.subtables = tv
- end
- end
- end
- end
- local features = resources.features
- if features then
- for _, what in next, glists do
- local feature = features[what]
- if feature then
- for tag, spec in next, feature do
- local tv = tables[spec]
- if tv then
- feature[tag] = tv
- end
- end
- end
- end
- end
- data.tables = nil
- end
- end
-end
diff --git a/tex/context/base/mkiv/font-ott.lua b/tex/context/base/mkiv/font-ott.lua
index cba3758dc..9f9900dc2 100644
--- a/tex/context/base/mkiv/font-ott.lua
+++ b/tex/context/base/mkiv/font-ott.lua
@@ -1,6 +1,6 @@
if not modules then modules = { } end modules ['font-ott'] = {
version = 1.001,
- comment = "companion to font-otf.lua (tables)",
+ comment = "companion to font-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files",
diff --git a/tex/context/base/mkiv/m-oldotf.mkiv b/tex/context/base/mkiv/m-oldotf.mkiv
deleted file mode 100644
index f860df712..000000000
--- a/tex/context/base/mkiv/m-oldotf.mkiv
+++ /dev/null
@@ -1,77 +0,0 @@
-%D \module
-%D [ file=m-oldotf,
-%D version=2015.07.08,
-%D title=\CONTEXT\ Extra Modules,
-%D subtitle=Traditional OTF Loader,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-\unprotect
-
-\startluacode
- local files = {
- "font-otf",
- "font-otb",
- "font-inj",
--- "font-ota",
- "font-otn",
- "font-otd",
- "font-otp",
- "font-otc",
- "font-oth",
- "font-odv",
- "font-one",
- "font-map",
- "font-fbk",
- }
- local report = logs.reporter("oldotf")
- local findfile = resolvers.findfile
- local addsuffix = file.addsuffix
- report()
- report("using traditional font loader code")
- report()
- for i=1,#files do
- local foundfile = findfile(addsuffix(files[i],"lua"))
- if foundfile and foundfile ~= "" then
- report("loading %a",foundfile)
- dofile(foundfile)
- end
- end
- report()
-
- -- needed for testing:
-
- local nuts = nodes.nuts
- local copy_node = nuts.copy
- local kern = nuts.pool.register(nuts.pool.kern())
- local setfield = nuts.setfield
-
- nuts.setattr(kern,attributes.private('fontkern'),1) -- we can have several, attributes are shared
-
- nodes.injections.installnewkern(function(k)
- local c = copy_node(kern)
- setfield(c,"kern",k)
- return c
- end)
-
- directives.register("fonts.injections.fontkern", function(v) setfield(kern,"subtype",v and 0 or 1) end)
-
- local fonts = fonts
- local handlers = fonts.handlers
- local otf = handlers.otf -- brrr
- local afm = handlers.afm -- brrr
- local getters = fonts.getters
-
- getters.kern .opentype = otf.getkern
- getters.substitution.opentype = otf.getsubstitution
- getters.alternate .opentype = otf.getalternate
- getters.multiple .opentype = otf.getmultiple
-
-\stopluacode
-
-\protect \endinput
diff --git a/tex/context/base/mkiv/math-fbk.lua b/tex/context/base/mkiv/math-fbk.lua
index 7621b6525..5a6a42e26 100644
--- a/tex/context/base/mkiv/math-fbk.lua
+++ b/tex/context/base/mkiv/math-fbk.lua
@@ -35,111 +35,117 @@ local lastmathids = fonts.hashes.lastmathids
-- in context define three sizes but pass them later i.e. do virtualize afterwards
function fallbacks.apply(target,original)
- local mathparameters = target.mathparameters -- why not hasmath
- if mathparameters then
- local characters = target.characters
- local parameters = target.parameters
- local mathsize = parameters.mathsize
- local size = parameters.size
- local usedfonts = target.fonts
- if not usedfonts then
- usedfonts = { }
- target.fonts = usedfonts
- end
- -- This is not okay yet ... we have no proper way to refer to 'self'
- -- otherwise I will make my own id allocator).
- local self = #usedfonts == 0 and font.nextid() or nil -- will be true
- local textid, scriptid, scriptscriptid
- local textindex, scriptindex, scriptscriptindex
- local textdata, scriptdata, scriptscriptdata
- if mathsize == 3 then
- -- scriptscriptsize
- -- textid = nil -- self
- -- scriptid = nil -- no smaller
- -- scriptscriptid = nil -- no smaller
- textid = self
- scriptid = self
- scriptscriptid = self
- elseif mathsize == 2 then
- -- scriptsize
- -- textid = nil -- self
- textid = self
- scriptid = lastmathids[3]
- scriptscriptid = lastmathids[3]
- else
- -- textsize
- -- textid = nil -- self
- textid = self
- scriptid = lastmathids[2]
- scriptscriptid = lastmathids[3]
- end
- if textid then
- textindex = #usedfonts + 1
- usedfonts[textindex] = { id = textid }
--- textdata = identifiers[textid] or target
- textdata = target
- else
- textdata = target
- end
- if scriptid then
- scriptindex = #usedfonts + 1
- usedfonts[scriptindex] = { id = scriptid }
- scriptdata = identifiers[scriptid]
- else
- scriptindex = textindex
- scriptdata = textdata
- end
- if scriptscriptid then
- scriptscriptindex = #usedfonts + 1
- usedfonts[scriptscriptindex] = { id = scriptscriptid }
- scriptscriptdata = identifiers[scriptscriptid]
- else
- scriptscriptindex = scriptindex
- scriptscriptdata = scriptdata
- end
- -- report_fallbacks("used textid: %S, used script id: %S, used scriptscript id: %S",textid,scriptid,scriptscriptid)
- local data = {
- textdata = textdata,
- scriptdata = scriptdata,
- scriptscriptdata = scriptscriptdata,
- textindex = textindex,
- scriptindex = scriptindex,
- scriptscriptindex = scriptscriptindex,
- textid = textid,
- scriptid = scriptid,
- scriptscriptid = scriptscriptid,
- characters = characters,
- unicode = k,
- target = target,
- original = original,
- size = size,
- mathsize = mathsize,
- }
- target.mathrelation = data
- -- inspect(usedfonts)
- for k, v in next, virtualcharacters do
- if not characters[k] then
- local tv = type(v)
- local cd = nil
- if tv == "table" then
- cd = v
- elseif tv == "number" then
- cd = characters[v]
- elseif tv == "function" then
- cd = v(data)
- end
- if cd then
- characters[k] = cd
- else
- -- something else
- end
- if trace_fallbacks and characters[k] then
- report_fallbacks("extending math font %a with %U",target.properties.fullname,k)
- end
+ local mathparameters = target.mathparameters
+ if not mathparameters then
+ return
+ end
+ -- we also have forcedsize ... at this moment we already passed through
+ -- constructors.scale so we have this set
+ local parameters = target.parameters
+ local mathsize = parameters.mathsize
+ if mathsize < 1 or mathsize > 3 then
+ return
+ end
+ local characters = target.characters
+ local size = parameters.size
+ local usedfonts = target.fonts
+ if not usedfonts then
+ usedfonts = { }
+ target.fonts = usedfonts
+ end
+ -- This is not okay yet ... we have no proper way to refer to 'self'
+ -- otherwise I will make my own id allocator).
+ local self = #usedfonts == 0 and font.nextid() or nil -- will be true
+ local textid, scriptid, scriptscriptid
+ local textindex, scriptindex, scriptscriptindex
+ local textdata, scriptdata, scriptscriptdata
+ if mathsize == 3 then
+ -- scriptscriptsize
+ -- textid = nil -- self
+ -- scriptid = nil -- no smaller
+ -- scriptscriptid = nil -- no smaller
+ textid = self
+ scriptid = self
+ scriptscriptid = self
+ elseif mathsize == 2 then
+ -- scriptsize
+ -- textid = nil -- self
+ textid = self
+ scriptid = lastmathids[3]
+ scriptscriptid = lastmathids[3]
+ else
+ -- textsize
+ -- textid = nil -- self
+ textid = self
+ scriptid = lastmathids[2]
+ scriptscriptid = lastmathids[3]
+ end
+ if textid then
+ textindex = #usedfonts + 1
+ usedfonts[textindex] = { id = textid }
+ -- textdata = identifiers[textid] or target
+ textdata = target
+ else
+ textdata = target
+ end
+ if scriptid then
+ scriptindex = #usedfonts + 1
+ usedfonts[scriptindex] = { id = scriptid }
+ scriptdata = identifiers[scriptid]
+ else
+ scriptindex = textindex
+ scriptdata = textdata
+ end
+ if scriptscriptid then
+ scriptscriptindex = #usedfonts + 1
+ usedfonts[scriptscriptindex] = { id = scriptscriptid }
+ scriptscriptdata = identifiers[scriptscriptid]
+ else
+ scriptscriptindex = scriptindex
+ scriptscriptdata = scriptdata
+ end
+ -- report_fallbacks("used textid: %S, used script id: %S, used scriptscript id: %S",textid,scriptid,scriptscriptid)
+ local data = {
+ textdata = textdata,
+ scriptdata = scriptdata,
+ scriptscriptdata = scriptscriptdata,
+ textindex = textindex,
+ scriptindex = scriptindex,
+ scriptscriptindex = scriptscriptindex,
+ textid = textid,
+ scriptid = scriptid,
+ scriptscriptid = scriptscriptid,
+ characters = characters,
+ unicode = k,
+ target = target,
+ original = original,
+ size = size,
+ mathsize = mathsize,
+ }
+ target.mathrelation = data
+ -- inspect(usedfonts)
+ for k, v in next, virtualcharacters do
+ if not characters[k] then
+ local tv = type(v)
+ local cd = nil
+ if tv == "table" then
+ cd = v
+ elseif tv == "number" then
+ cd = characters[v]
+ elseif tv == "function" then
+ cd = v(data)
+ end
+ if cd then
+ characters[k] = cd
+ else
+ -- something else
+ end
+ if trace_fallbacks and characters[k] then
+ report_fallbacks("extending math font %a with %U",target.properties.fullname,k)
end
end
- data.unicode = nil
end
+ data.unicode = nil
end
utilities.sequencers.appendaction("aftercopyingcharacters","system","mathematics.fallbacks.apply")
diff --git a/tex/context/base/mkiv/metatex.lus b/tex/context/base/mkiv/metatex.lus
deleted file mode 100644
index df7bc1914..000000000
--- a/tex/context/base/mkiv/metatex.lus
+++ /dev/null
@@ -1,9 +0,0 @@
-if not modules then modules = { } end modules ['metatex'] = {
- version = 1.001,
- comment = "companion to metatex.tex",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-return "luat-cod.lua"
diff --git a/tex/context/base/mkiv/metatex.tex b/tex/context/base/mkiv/metatex.tex
index b5f54c4ee..7c8a7ff01 100644
--- a/tex/context/base/mkiv/metatex.tex
+++ b/tex/context/base/mkiv/metatex.tex
@@ -22,144 +22,9 @@
%D A format is generated with the command;
%D
%D \starttyping
-%D luatools --make --compile metatex
+%D mtxrun --script metatex --make
%D \stoptyping
%D
-%D Remark: this is far from complete. We will gradually add
-%D more. Also, it's not yet clean what exactly will be part
-%D of it. This is a prelude to a configureable macro package.
-
-\catcode`\{=1 \catcode`\}=2 \catcode`\#=6
-
-\edef\metatexformat {\jobname}
-\edef\metatexversion{2007.04.03 13:01}
-
-\let\fmtname \metatexformat
-\let\fmtversion\metatexversion
-
-\ifx\normalinput\undefined \let\normalinput\input \fi
-
-\def\loadcorefile#1{\normalinput#1.tex \relax}
-\def\loadmarkfile#1{\normalinput#1.mkiv\relax}
-
-\loadmarkfile{syst-ini}
-
-\ifnum\luatexversion<60 % also change message
- \writestatus{!!!!}{Your luatex binary is too old, you need at least version 0.60!}
- \expandafter\end
-\fi
-
-\newtoks\metatexversiontoks \metatexversiontoks\expandafter{\metatexversion} % at the lua end
-
-\loadmarkfile{syst-pln} % plain tex initializations of internal registers (no further code)
-\loadmarkfile{syst-mes}
-
-\loadmarkfile{luat-cod} %
-\loadmarkfile{luat-bas} %
-\loadmarkfile{luat-lib} %
-
-% needs stripping:
-
-\loadmarkfile{catc-ini} % catcode table management
-\loadmarkfile{catc-act} % active character definition mechanisms
-\loadmarkfile{catc-def} % some generic catcode tables
-\loadmarkfile{catc-ctx} % a couple of context specific tables but expected by later modules
-\loadmarkfile{catc-sym} % some definitions related to \letter<tokens>
-
-% helpers, maybe less
-
-\loadmarkfile{syst-aux} % a whole lot of auxiliary macros
-%loadmarkfile{syst-lua} % some helpers using lua instead
-%loadmarkfile{syst-con} % some rather basic conversions
-%loadmarkfile{syst-fnt}
-%loadmarkfile{syst-str}
-%loadmarkfile{syst-rtp}
-
-% not needed
-
-% \loadmarkfile{supp-fil}
-% \loadmarkfile{supp-dir}
-
-% characters
-
-\loadmarkfile{char-utf}
-\loadmarkfile{char-ini}
-\loadmarkfile{char-enc} % \registerctxluafile{char-enc}{1.001}
-
-% attributes
-
-\loadmarkfile{attr-ini}
-
-% nodes
-
-\loadmarkfile{node-ini}
-%loadmarkfile{node-fin}
-%loadmarkfile{node-par}
-
-% attributes, not needed:
-
-%loadmarkfile{attr-ini}
-
-% regimes
-
-% \loadmarkfile{regi-ini}
-% \loadcorefile{regi-syn}
-
-% languages
-
-% fonts
-
-% \loadcorefile{enco-ini.mkiv}
-% \loadcorefile{hand-ini.mkiv}
-
-\registerctxluafile{font-ini}{1.001}
-
-\registerctxluafile{node-fnt}{1.001}
-
-\registerctxluafile{font-enc}{1.001}
-\registerctxluafile{font-map}{1.001}
-\registerctxluafile{font-syn}{1.001}
-\registerctxluafile{font-tfm}{1.001}
-\registerctxluafile{font-afm}{1.001}
-\registerctxluafile{font-cid}{1.001}
-\registerctxluafile{font-ott}{1.001}
-\registerctxluafile{font-otf}{1.001}
-\registerctxluafile{font-otb}{1.001}
-\registerctxluafile{font-otn}{1.001}
-\registerctxluafile{font-ota}{1.001}
-\registerctxluafile{font-otp}{1.001}
-\registerctxluafile{font-otc}{1.001}
-%registerctxluafile{font-vf} {1.001}
-\registerctxluafile{font-def}{1.001}
-%registerctxluafile{font-ctx}{1.001}
-\registerctxluafile{font-xtx}{1.001}
-%registerctxluafile{font-fbk}{1.001}
-%registerctxluafile{font-ext}{1.001}
-\registerctxluafile{font-pat}{1.001}
-%registerctxluafile{font-chk}{1.001}
-
-%registerctxluafile{math-ini}{1.001}
-%registerctxluafile{math-dim}{1.001}
-%registerctxluafile{math-ent}{1.001}
-%registerctxluafile{math-ext}{1.001}
-%registerctxluafile{math-vfu}{1.001}
-%registerctxluafile{math-map}{1.001}
-%registerctxluafile{math-noa}{1.001}
-
-\registerctxluafile{task-ini}{1.001}
-
-%registerctxluafile{l-xml}{1.001} % needed for font database
-
-% why not ...
-
-\pdfoutput\plusone
-
-% too
-
-\appendtoks
- \ctxlua{statistics.savefmtstatus("\jobname","\metatexversion","metatex.tex")}% can become automatic
-\to \everydump
-
-% done
-
-\errorstopmode \dump \endinput
+%D For the moment this is a placeholder. Maybe some day ... the old
+%D file history/metatex/metatex.tex so I can pick up from there if
+%D needed.
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index cbaeb8977..b42727e06 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -782,7 +782,7 @@ nodes.properties = {
}
------.set_properties_mode(true,false) -- shallow copy ... problem: in fonts we then affect the originals too
-direct.set_properties_mode(true,true) -- create metatable, slower but needed for font-inj.lua (unless we use an intermediate table)
+direct.set_properties_mode(true,true) -- create metatable, slower but needed for font-otj.lua (unless we use an intermediate table)
-- todo:
--
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index a38925207..7e122efb5 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 8e140db0c..f10b35e86 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/status-mkiv.lua b/tex/context/base/mkiv/status-mkiv.lua
deleted file mode 100644
index ab1419c98..000000000
--- a/tex/context/base/mkiv/status-mkiv.lua
+++ /dev/null
@@ -1,7441 +0,0 @@
-return {
- ["core"]={
- {
- ["category"]="mkvi",
- ["filename"]="font-gds",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-run",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-sel",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="grph-pat",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="grph-rul",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-rep",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="luat-usr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="math-mis",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="math-rad",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-cst",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="page-inj",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="page-lin",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="publ-imp-author",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="publ-imp-cite",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="publ-imp-commands",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="publ-imp-default",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="publ-imp-definitions",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="publ-imp-list",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="publ-imp-page",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="spac-flr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="spac-prf",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="strc-not",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="toks-map",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="toks-tra",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-chr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-inj",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-lig",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-lin",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-par",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-wrp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="syst-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="norm-ctx",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="syst-pln",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="syst-mes",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="luat-cod",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe combine (3)",
- ["filename"]="luat-bas",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe combine (3)",
- ["filename"]="luat-lib",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="catc-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="forward dependency",
- ["filename"]="catc-act",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="catc-def",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="catc-ctx",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="catc-sym",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="only needed for mkii xml parser",
- ["filename"]="catc-xml",
- ["loading"]="module",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe combine (1)",
- ["filename"]="cldf-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="syst-aux",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe combine (1)",
- ["filename"]="syst-lua",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe combine (1)",
- ["filename"]="syst-con",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe combine (1)",
- ["filename"]="syst-fnt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe combine (1)",
- ["filename"]="syst-rtp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="maybe combine (2)",
- ["filename"]="file-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="maybe combine (2)",
- ["filename"]="file-res",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="file-lib",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="supp-dir",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="char-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="char-utf",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="forward dependency",
- ["filename"]="char-act",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="mult-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="mult-sys",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="mult-aux",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="mult-def",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="mult-chk",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="mult-dim",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cldf-int",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="luat-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="toks-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="attr-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="attr-mkr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="code might move from here",
- ["filename"]="core-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="might need more redoing",
- ["filename"]="core-env",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="in due time more might move to here",
- ["filename"]="layo-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe this becomes a runtime module",
- ["filename"]="node-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe use context.generics/context.sprint here",
- ["filename"]="cldf-bas",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="might need more redoing",
- ["filename"]="node-fin",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="needs integration and configuration",
- ["filename"]="node-mig",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-bld",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-sus",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="node-pag",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="back-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="attr-col",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="attr-lay",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="attr-neg",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="attr-eff",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="needs more usage",
- ["filename"]="trac-tex",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="trac-deb",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="trac-ctx",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="supp-box",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="supp-ran",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will be moved to the math-* modules",
- ["filename"]="supp-mat",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will grow",
- ["filename"]="typo-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="file-syn",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="file-mod",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="core-con",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-fil",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-nop",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-yes",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="regi-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="enco-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="hand-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="namespace should be languages",
- ["filename"]="lang-lab",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-hyp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="unic-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="core-uti",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe rename to core-two",
- ["filename"]="core-two",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="core-dat",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-ext",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-grp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="node-bck",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="pack-cut",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-mis",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-url",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-def",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-hyp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-frq",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-frd",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lang-wrd",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="might need more redoing",
- ["filename"]="file-job",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="symb-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="sort-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="pack-mis",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="pack-rul",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="endpar experimental code",
- ["filename"]="pack-mrl",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="pack-bck",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="pack-fen",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lxml-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="lxml-sor",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="typo-prc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="strc-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="strc-tag",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this module might go away when code has been moved",
- ["filename"]="strc-doc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="still some rough edges",
- ["filename"]="strc-num",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="strc-mar",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="strc-sbe",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="strc-lst",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="some of the local current and synchronization macros will be renamed",
- ["filename"]="strc-sec",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="strc-pag",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="(support for) setups might get improved",
- ["filename"]="strc-ren",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this module might go away",
- ["filename"]="strc-xml",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="strc-def",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="some more low level names might change",
- ["filename"]="strc-ref",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="use setups for rendering",
- ["filename"]="strc-reg",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="strc-lev",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe some tuning is needed / will happen",
- ["filename"]="spac-ali",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="probably needs some more work",
- ["filename"]="spac-hor",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe some changes will happen",
- ["filename"]="spac-ver",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="could be improved if needed",
- ["filename"]="spac-lin",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this needs to be checked occasionally",
- ["filename"]="spac-pag",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="spac-par",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="spac-def",
- ["loading"]="always",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="needs thinking and redoing",
- ["filename"]="spac-grd",
- ["loading"]="always",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="in transition",
- ["filename"]="anch-pos",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="maybe change locationattribute names",
- ["filename"]="scrn-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="namespace needs checking",
- ["filename"]="scrn-ref",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will change when we have objects at lua end",
- ["filename"]="pack-obj",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="strc-itm",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="maybe more common counter code here and setups need to be improved",
- ["filename"]="strc-con",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="strc-des",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="(interactive) coupling is not yet working",
- ["filename"]="strc-enu",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="strc-ind",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="needs to be adapted when strc-con/des/enu changes",
- ["filename"]="strc-lab",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="strc-syn",
- ["loading"]="always",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="a funny mix",
- ["filename"]="core-sys",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-var",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="page-otr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="code might end up elsewhere",
- ["filename"]="page-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="dealing with insertions might change",
- ["filename"]="page-ins",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-fac",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="otr commands will be redone",
- ["filename"]="page-brk",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="helpers for columns",
- ["filename"]="page-col",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="room for improvement and extension",
- ["filename"]="page-inf",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-grd",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will be extended when columns are redone",
- ["filename"]="page-flt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-bck",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-not",
- ["loading"]="always",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="can probably be improved",
- ["filename"]="page-one",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-lay",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="page-box",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="a few things left",
- ["filename"]="page-txt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-sid",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="in due time we need a further cleanup",
- ["filename"]="strc-flt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-pst",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="might be extended",
- ["filename"]="page-mbk",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will be reimplemented",
- ["filename"]="page-mul",
- ["loading"]="always",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="work in progress",
- ["filename"]="page-mix",
- ["loading"]="always",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will be reimplemented",
- ["filename"]="page-set",
- ["loading"]="always",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="pack-lyr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="pack-pos",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="page-mak",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="might get extended",
- ["filename"]="page-par",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-pag",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-mar",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-itm",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="check other modules for buffer usage",
- ["filename"]="buff-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="check obsolete processbuffer",
- ["filename"]="buff-ver",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="experimental code",
- ["filename"]="buff-par",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="symb-imp-cc",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="buff-imp-default",
- ["loading"]="indirect",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="buff-imp-escaped",
- ["loading"]="indirect",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="buff-imp-nested",
- ["loading"]="indirect",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="strc-blk",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-imp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="maybe some extensions and delayed loading, needs checking",
- ["filename"]="page-sel",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-com",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="namespace needs checking",
- ["filename"]="scrn-pag",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="functionality needs checking",
- ["filename"]="scrn-wid",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="namespace needs checking",
- ["filename"]="scrn-but",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="namespace needs checking",
- ["filename"]="scrn-bar",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="strc-bkm",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-tal",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="somewhat weird",
- ["filename"]="tabl-com",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="unchecked",
- ["filename"]="tabl-pln",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="tabl-tab",
- ["loading"]="always",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["comment"]="can probably be improved (names and such)",
- ["filename"]="tabl-tbl",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="frozen functionaly so no drastic cleanup",
- ["filename"]="tabl-ntb",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="tabl-mis",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="tabl-nte",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will be redone when needed",
- ["filename"]="tabl-ltb",
- ["loading"]="always",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will be adapted when needed (and rest is done)",
- ["filename"]="tabl-tsp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="namespace needs checking",
- ["filename"]="tabl-xtb",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="only when natural tables need a replacement",
- ["filename"]="tabl-xnt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="java-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="namespace needs checking",
- ["filename"]="scrn-fld",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="namespace needs checking",
- ["filename"]="scrn-hlp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="char-enc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-lib",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-fil",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-var",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-fea",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-mat",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="needs occasional checking and upgrading",
- ["filename"]="font-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-sym",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-sty",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-set",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-emp",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-col",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="font-pre",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="font-unk",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="likely this will become a module",
- ["filename"]="font-tra",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this could become a module",
- ["filename"]="font-chk",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this one might be merged",
- ["filename"]="font-uni",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-col",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="font-aux",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-lan",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this is work in progress",
- ["filename"]="lxml-css",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="spac-chr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="work in progress",
- ["filename"]="blob-ini",
- ["loading"]="always",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["filename"]="trac-jus",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="trac-vis",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-cln",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-spa",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="do we keep the style and color or not",
- ["filename"]="typo-krn",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="typo-itc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe singular setup",
- ["filename"]="typo-dir",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-brk",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-cap",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-dig",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-rep",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="maybe there will be a nicer interface",
- ["filename"]="typo-txt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-drp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-fln",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="type-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-set",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-def",
- ["loading"]="type-set",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-fbk",
- ["loading"]="type-set",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-lua",
- ["loading"]="type-set",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-one",
- ["loading"]="type-set",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-otf",
- ["loading"]="type-set",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-siz",
- ["loading"]="type-set",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="placeholder to prevent other loading",
- ["filename"]="type-tmf",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="scrp-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this module is obsolete",
- ["filename"]="prop-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="mlib-ctx",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="metapost code is always evolving",
- ["filename"]="meta-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="code used in a project",
- ["filename"]="meta-lua",
- ["loading"]="experimental",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-fnt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-tex",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe this one will be merged",
- ["filename"]="meta-fun",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="might get updated when mp code gets cleaned up",
- ["filename"]="meta-pag",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-grd",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-mrk",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-flw",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-spr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will be made better",
- ["filename"]="page-plg",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="needs more work (and thinking)",
- ["filename"]="page-str",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="in transition",
- ["filename"]="anch-pgr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="in transition",
- ["filename"]="anch-bck",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will stay experimental for a while",
- ["filename"]="anch-tab",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="anch-bar",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="interesting old mechanism to keep around (module?)",
- ["filename"]="anch-snc",
- ["loading"]="always",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["filename"]="math-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this file might merge into others",
- ["filename"]="math-pln",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="math-for",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="eventually this will be split and spread",
- ["filename"]="math-def",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will be checked and improved",
- ["filename"]="math-ali",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="needs testing",
- ["filename"]="math-arr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="math-stc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="math-acc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="at least for the moment",
- ["filename"]="math-frc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="math-scr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="math-int",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="code get replaced (by autodelimiters)",
- ["filename"]="math-del",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="math-fen",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="code might move to here",
- ["filename"]="math-inl",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="code might move to here",
- ["filename"]="math-dis",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="phys-dim",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="some more functionality will end up here",
- ["filename"]="strc-mat",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="chem-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="chem-str",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-scr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="maybe some cleanup is needed",
- ["filename"]="node-rul",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["comment"]="needs testing",
- ["filename"]="font-sol",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="strc-not",
- ["loading"]="always",
- ["status"]="todo",
- },
- {
- ["category"]="mkvi",
- ["comment"]="will be extended as part of crited",
- ["filename"]="strc-lnt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="pack-com",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-del",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="grph-trf",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="grph-inc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="grph-fig",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="grph-raw",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="pack-box",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="pack-bar",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-app",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-fig",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="more or less obsolete",
- ["filename"]="lang-spa",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="bibl-bib",
- ["loading"]="on demand",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["filename"]="bibl-tra",
- ["loading"]="on demand",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["comment"]="not needed",
- ["filename"]="meta-xml",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-log",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="task-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cldf-ver",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cldf-com",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="core-ctx",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="will always be messy",
- ["filename"]="core-def",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="object related code might move or change",
- ["filename"]="back-pdf",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="no code, just an example of usage",
- ["filename"]="back-swf",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="no code, just an example of usage",
- ["filename"]="back-u3d",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="mlib-pdf",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="mlib-pps",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-pdf",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="might need more work",
- ["filename"]="grph-epd",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="some parameters might move from export to backend",
- ["filename"]="back-exp",
- ["loading"]="always",
- ["status"]="okay",
- },
- },
- ["extras"]={
- {
- ["category"]="tex",
- ["comment"]="add-on for mtx-context",
- ["filename"]="mtx-context-arrange",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["comment"]="add-on for mtx-context",
- ["filename"]="mtx-context-combine",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["comment"]="add-on for mtx-context",
- ["filename"]="mtx-context-common",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["comment"]="add-on for mtx-context",
- ["filename"]="mtx-context-ideas",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["comment"]="add-on for mtx-context",
- ["filename"]="mtx-context-listing",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["comment"]="add-on for mtx-context",
- ["filename"]="mtx-context-markdown",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["comment"]="add-on for mtx-context",
- ["filename"]="mtx-context-select",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["comment"]="add-on for mtx-context",
- ["filename"]="mtx-context-timing",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- },
- ["implementations"]={
- {
- ["category"]="mkiv",
- ["filename"]="symb-imp-fontawesome",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-ebgaramond",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-gentium",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-ipaex",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-lato",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-libertinus",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-mathdigits",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-minion",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-opendyslexic",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-source",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="buff-imp-tex",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="buff-imp-mp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="buff-imp-lua",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="buff-imp-xml",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="buff-imp-parsed-xml",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-grid",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-mat",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-outlines",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-tab",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="publ-imp-apa",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="publ-imp-aps",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-imp-crayola",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-imp-rainbow",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-imp-ral",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-imp-dem",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-imp-ema",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-imp-rgb",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-imp-x11",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-imp-xwi",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="java-imp-exa",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="java-imp-fil",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="java-imp-fld",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="java-imp-rhh",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="java-imp-stp",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-clp",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-dum",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-fen",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-mis",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-nav",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-pre",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="meta-imp-txt",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="symb-imp-cow",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="symb-imp-eur",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="symb-imp-jmn",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="symb-imp-mis",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="symb-imp-mvs",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="symb-imp-nav",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-antykwa",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-antykwapoltawskiego",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-asana",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-averia",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-buy",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-cambria",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-charter",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-cleartype",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-computer-modern-unicode",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-cow",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-dejavu",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-euler",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-ghz",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-hgz",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-husayni",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-hvmath",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-inconsolata",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-informal",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-iwona",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-kurier",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-latinmodern",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-liberation",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-libertine",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-lmnames",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-lucida-opentype",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-lucida-typeone",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-mathdesign",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-mathtimes",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-mscore",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-osx",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-postscript",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-punknova",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-texgyre",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-unfonts",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-xits",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="type-imp-xitsbidi",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="publ-ini",
- ["loading"]="always",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["filename"]="publ-old",
- ["loading"]="always",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["filename"]="publ-tra",
- ["loading"]="always",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["filename"]="publ-usr",
- ["loading"]="always",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["filename"]="publ-xml",
- ["loading"]="always",
- ["status"]="pending",
- },
- },
- ["lua"]={
- {
- ["category"]="lua",
- ["filename"]="anch-pgr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="bibl-tst",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="char-fio",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="cldf-prs",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="cldf-scn",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="cldf-stp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="cont-run",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-cff",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-cft",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-dsp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-gbn",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-hsh",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-mps",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-nod",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-ocl",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-odk",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-odv",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-off",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-one",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-onr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-osd",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-otj",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-otl",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-oto",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-otr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-ots",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-oup",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-sel",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-shp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-ttf",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-web",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-xtx",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="good-ctx",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="good-gen",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="good-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="good-mth",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-con",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-mem",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-pat",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-rul",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="l-gzip",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="l-lua",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="l-package",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="l-sandbox",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-cnt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-frq-de",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-frq-en",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-frq-nl",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-frq-pt",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-rep",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-usr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-ini",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="math-dir",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="mlib-int",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="mlib-lua",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="node-ltp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="node-scn",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="node-met",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="node-nut",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="page-cst",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="page-inj",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-imp-apa",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-imp-aps",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-imp-default",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-imp-replacements",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-jrn",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-reg",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-sor",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-ibm",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-pdfdoc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="scrp-tha",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="spac-prf",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="toks-map",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="toks-tra",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-par",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-chr",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-duc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-inj",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-lin",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-tal",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-wrp",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-fil",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-lib-imp-gm",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-lib-imp-gs",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-ran",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sac",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sbx",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sci",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-soc",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql-imp-client",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql-imp-library",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql-imp-sqlite",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql-imp-swiglib",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql-loggers",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql-sessions",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql-tickets",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql-tracers",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql-users",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-you",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="m-escrito",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-characters-properties",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-languages-words",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-xml-analyzers",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="x-math-svg",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="anch-pos",
- ["loading"]="anch-pos",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="attr-col",
- ["loading"]="attr-col",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="attr-eff",
- ["loading"]="attr-eff",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="attr-ini",
- ["loading"]="attr-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="attr-lay",
- ["loading"]="attr-lay",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="attr-neg",
- ["loading"]="attr-neg",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="attr-mkr",
- ["loading"]="attr-mkr",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="experimental code, maybe some will move elsewhere",
- ["filename"]="back-exp",
- ["loading"]="back-exp",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="back-ini",
- ["loading"]="back-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="back-pdf",
- ["loading"]="back-pdf",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="bibl-bib",
- ["loading"]="on demand",
- },
- {
- ["category"]="lua",
- ["filename"]="bibl-tra",
- ["loading"]="on demand",
- },
- {
- ["category"]="lua",
- ["filename"]="blob-ini",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="buff-imp-default",
- ["loading"]="buff-imp-default",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="buff-imp-escaped",
- ["loading"]="buff-imp-escaped",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="todo: colorization and nesting as in scite",
- ["filename"]="buff-imp-lua",
- ["loading"]="buff-imp-lua",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="todo: colorization and nesting as in scite",
- ["filename"]="buff-imp-mp",
- ["loading"]="buff-imp-mp",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="buff-imp-nested",
- ["loading"]="buff-imp-nested",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="buff-imp-parsed-xml",
- ["loading"]="buff-imp-parsed-xml",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="todo: colorization and nesting as in scite",
- ["filename"]="buff-imp-tex",
- ["loading"]="buff-imp-tex",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="todo: colorization and nesting as in scite",
- ["filename"]="buff-imp-xml",
- ["loading"]="buff-imp-xml",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="buff-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="buff-par",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="maybe we will provide a few more (nesting) methods",
- ["filename"]="buff-ver",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="catc-ini",
- ["loading"]="catc-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="char-cjk",
- ["loading"]="char-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="char-def",
- ["loading"]="char-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="maybe dataonly",
- ["filename"]="char-enc",
- ["loading"]="char-enc",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="char-ent",
- ["loading"]="char-ent",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="maybe move blocks table to separate (dataonly) file",
- ["filename"]="char-ini",
- ["loading"]="char-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="char-map",
- ["loading"]="char-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="char-tex",
- ["loading"]="char-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="char-utf",
- ["loading"]="char-utf",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="chem-ini",
- ["loading"]="chem-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="chem-str",
- ["loading"]="chem-str",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="will be extended and can be optimized if needed",
- ["filename"]="cldf-bas",
- ["loading"]="cldf-bas",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="might change or even go away",
- ["filename"]="cldf-com",
- ["loading"]="cldf-com",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="cldf-ini",
- ["loading"]="cldf-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="cldf-int",
- ["loading"]="cldf-int",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["comment"]="maybe this code can be redone more efficiently/robust",
- ["filename"]="cldf-ver",
- ["loading"]="cldf-ver",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["comment"]="also used in mtx-*",
- ["filename"]="colo-icc",
- ["loading"]="colo-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="colo-ini",
- ["loading"]="colo-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="this code might move to a module",
- ["filename"]="colo-run",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="core-con",
- ["loading"]="core-con",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="core-ctx",
- ["loading"]="core-ctx",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="core-dat",
- ["loading"]="core-dat",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="maybe abusing the tex namespace is wrong",
- ["filename"]="core-env",
- ["loading"]="core-env",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="core-sys",
- ["loading"]="core-sys",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["commands"]="this is in fact replaced by core-dat",
- ["filename"]="core-two",
- ["loading"]="core-two",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="some code will move to better places",
- ["filename"]="core-uti",
- ["loading"]="core-uti",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="data-aux",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-bin",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-con",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-crl",
- ["loading"]="never",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-ctx",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-env",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-exp",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-fil",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-gen",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-ini",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-inp",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-lst",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-lua",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-met",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-out",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-pre",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-res",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-sch",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-tex",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-tmf",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-tmp",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-tre",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-use",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-vir",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="data-zip",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="file-ini",
- ["loading"]="file-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="file-job",
- ["loading"]="file-job",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="file-lib",
- ["loading"]="file-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="file-mod",
- ["loading"]="file-mod",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="file-res",
- ["loading"]="file-res",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="file-syn",
- ["loading"]="file-syn",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-afm",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-afk",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="only used in luatex-fonts",
- ["filename"]="font-age",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-agl",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="needs some documentation in usage",
- ["filename"]="font-aux",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="move more to the commands namespace",
- ["filename"]="font-chk",
- ["loading"]="font-chk",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-cid",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-col",
- ["loading"]="font-col",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-con",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="will be improved over time",
- ["filename"]="font-ctx",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-def",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="part of this code is obsolete",
- ["filename"]="font-enc",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="needs documentation at the tex end",
- ["filename"]="font-enh",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="maybe some data tables can be be external",
- ["filename"]="font-ext",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="okay but can be improved",
- ["filename"]="font-fbk",
- ["loading"]="font-lib",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="font-ini",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-inj",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-ldr",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-log",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="currently rather minimalistic",
- ["filename"]="font-lua",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="the lum file support will be dropped / no map files anyway",
- ["filename"]="font-map",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-mis",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="when more scripts are supported we might end up with imp files",
- ["filename"]="font-ota",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-otb",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-otc",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-otd",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-otf",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-oth",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-oti",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-otn",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-otp",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-ott",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="is mostly replaced by lfg files",
- ["filename"]="font-pat",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-sol",
- ["loading"]="font-sol",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="also loaded on demand",
- ["filename"]="font-syn",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-tfm",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-trt",
- ["loading"]="font-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="font-vf",
- ["loading"]="font-lib",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-epd",
- ["loading"]="grph-epd",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-fil",
- ["loading"]="grph-inc",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-inc",
- ["loading"]="grph-inc",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-raw",
- ["loading"]="grph-raw",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-swf",
- ["loading"]="grph-swf",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="grph-u3d",
- ["loading"]="grph-u3d",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="experiment with graphic magick library",
- ["filename"]="grph-wnd",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="java-ini",
- ["loading"]="java-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="l-boolean",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-dir",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-file",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-function",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-io",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-lpeg",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-math",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-md5",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-number",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-os",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-pdfview",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-set",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-string",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-table",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-unicode",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-url",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="l-xml",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-def",
- ["loading"]="lang-def",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-dis",
- ["loading"]="lang-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-hyp",
- ["loading"]="lang-hyp",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-ini",
- ["loading"]="lang-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-lab",
- ["loading"]="lang-lab",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-hyp",
- ["loading"]="lang-hyp",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-txt",
- ["loading"]="lang-lab",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="maybe another approach is nicer",
- ["filename"]="lang-url",
- ["loading"]="lang-url",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-wrd",
- ["loading"]="lang-wrd",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="more will end up here",
- ["filename"]="layo-ini",
- ["loading"]="layo-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-ano",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-res",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-col",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-enc",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-epa",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-epd",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-fld",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-fmt",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-grp",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-ini",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-mis",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-mov",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-nod",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-ren",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-swf",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-tag",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-u3d",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-wid",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lpdf-xmp",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["comment"]="replacement code for wd/ht/dp",
- ["filename"]="luat-bwc",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-cbk",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-cnf",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="maybe some code should move",
- ["filename"]="luat-cod",
- ["loading"]="luat-cod",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-env",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-exe",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-fio",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-fmt",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="will be upgraded when we have Lua 5.2",
- ["filename"]="luat-ini",
- ["loading"]="luat-lib",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["comment"]="will be upgraded when we have Lua 5.2",
- ["filename"]="util-env",
- ["loading"]="luat-lib",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-iop",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="this is likely to change some day",
- ["filename"]="luat-lua",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-mac",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-run",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="related to the socket code",
- ["filename"]="luat-soc",
- ["loading"]="on demand",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-sta",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="luat-sto",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-aux",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-css",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-ctx",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-dir",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-ent",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-inf",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-lpt",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-mis",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-sor",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-tab",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-tex",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="lxml-xml",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="m-chart",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="m-database",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="m-nodechart",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="m-markdown",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="m-pstricks",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="m-spreadsheet",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="m-steps",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="math-act",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="math-frc",
- ["loading"]="math-frc",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="could be made look nicer, but who cares",
- ["filename"]="math-dim",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="the code is related to math-vfu",
- ["filename"]="math-ext",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="math-fbk",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="math-frc",
- ["loading"]="math-frc",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="okay, but we might have a few more low level definers some day",
- ["filename"]="math-ini",
- ["loading"]="math-ini",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="math-map",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="math-noa",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="math-ren",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="math-tag",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="math-ttv",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="math-vfu",
- ["loading"]="math-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="this is just a first version",
- ["filename"]="meta-fun",
- ["loading"]="meta-fun",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="meta-ini",
- ["loading"]="meta-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="meta-lua",
- ["loading"]="meta-lua",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="meta-fnt",
- ["loading"]="meta-fnt",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="could be done nicer nowadays but who needs it",
- ["filename"]="meta-pdf",
- ["loading"]="meta-pdf",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="this is historic code that we keep around",
- ["filename"]="meta-pdh",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="meta-tex",
- ["loading"]="meta-tex",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="mlib-ctx",
- ["loading"]="mlib-ctx",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="mlib-pdf",
- ["loading"]="mlib-pdf",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="mlib-pps",
- ["loading"]="mlib-pdf",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="mlib-run",
- ["loading"]="mlib-ctx",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="this is an experiment, namespaces need to be dealt with properly",
- ["filename"]="mult-aux",
- ["loading"]="mult-aux",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["comment"]="this is an experiment",
- ["filename"]="mult-chk",
- ["loading"]="mult-chk",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="mult-def",
- ["loading"]="mult-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="used for generating editor lexing files",
- ["filename"]="mult-fun",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="mult-ini",
- ["loading"]="mult-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="used for generating editor lexing files",
- ["filename"]="mult-low",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="all messages need to be checked",
- ["filename"]="mult-mes",
- ["loading"]="mult-ini",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["comment"]="used for generating editor lexing files",
- ["filename"]="mult-mps",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="used for generating editor lexing files",
- ["filename"]="mult-prm",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="node-acc",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-aux",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-bck",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-dir",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-ext",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-fin",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-fnt",
- ["loading"]="font-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-ini",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-mig",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-pag",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-ppt",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-pro",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-ref",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-res",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-rul",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-ser",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-shp",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-tex",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-tra",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-snp",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-tsk",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-tst",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="node-typ",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["comment"]="will be extended when we have opened up pdf objects",
- ["filename"]="pack-obj",
- ["loading"]="pack-obj",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="pack-rul",
- ["loading"]="pack-rul",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="page-otr",
- ["loading"]="page-otr",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="page-flt",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="page-ins",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="page-lin",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="page-mix",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="page-pst",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="page-str",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="phys-dim",
- ["loading"]="phys-dim",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-1",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-10",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-11",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-13",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-14",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-15",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-16",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-2",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-3",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-4",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-5",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-6",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-7",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-8",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-8859-9",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-cp1250",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-cp1251",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-cp1252",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-cp1253",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-cp1254",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-cp1255",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-cp1256",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-cp1257",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-cp1258",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="just a demo file",
- ["filename"]="regi-demo",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="regi-ini",
- ["loading"]="regi-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-fonts-coverage",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-fonts-features",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-fonts-missing",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-fonts-shapes",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-fonts-system",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-fonts-tables",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-fonts-vectors",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-languages-counters",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-languages-frequencies",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-languages-hyphenation",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-languages-sorting",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-languages-system",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-math-characters",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-math-coverage",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-fonts-goodies",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-math-parameters",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-pre-71",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="s-sql-tables",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="scrn-but",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="scrn-fld",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="scrn-hlp",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="scrn-ini",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="scrn-pag",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="scrn-ref",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="scrn-wid",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["comment"]="we can speed this up",
- ["filename"]="scrp-cjk",
- ["loading"]="scrp-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="we can speed this up",
- ["filename"]="scrp-eth",
- ["loading"]="scrp-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="scrp-ini",
- ["loading"]="scrp-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="sort-ini",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="sort-lan",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="spac-adj",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="spac-ali",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="spac-chr",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="spac-hor",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="spac-ver",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="status-mkiv",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-bkm",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-blk",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-con",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-doc",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-flt",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-ini",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-itm",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-lev",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-lst",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-mar",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-mat",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-not",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-num",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-pag",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-ref",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-reg",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-rsc",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-syn",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="strc-tag",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="supp-box",
- ["loading"]="supp-box",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="supp-ran",
- ["loading"]="supp-ran",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="symb-ini",
- ["loading"]="symb-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="there will be more in here",
- ["filename"]="syst-aux",
- ["loading"]="syst-aux",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="do some tests with speedups (sprint)",
- ["filename"]="syst-con",
- ["loading"]="syst-con",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["comment"]="do some tests with speedups (less tokens)",
- ["filename"]="syst-lua",
- ["loading"]="syst-lua",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="tabl-tbl",
- ["loading"]="tabl-tbl",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="work in progress",
- ["filename"]="tabl-xtb",
- ["loading"]="tabl-xtb",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="we need a well defined defintion moment",
- ["filename"]="task-ini",
- ["loading"]="task-ini",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="toks-ini",
- ["loading"]="toks-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="toks-scn",
- ["loading"]="toks-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="must be applied in more places",
- ["filename"]="trac-ctx",
- ["loading"]="trac-ctx",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-deb",
- ["loading"]="trac-deb",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="for the moment somewhat private",
- ["filename"]="trac-fil",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-inf",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="will be redone and extended",
- ["filename"]="trac-lmx",
- ["loading"]="luat-lib",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-log",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-xml",
- ["loading"]="mtxrun",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-exp",
- ["loading"]="mtxrun",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="experimental code, will be redone when lua 5.2",
- ["filename"]="trac-pro",
- ["loading"]="luat-lib",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["comment"]="some code can better be in util-set",
- ["filename"]="trac-set",
- ["loading"]="luat-lib",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-tex",
- ["loading"]="trac-tex",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-tim",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-vis",
- ["loading"]="trac-vis",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="trac-jus",
- ["loading"]="trac-jus",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="type-ini",
- ["loading"]="type-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-bld",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-sus",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-brk",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-cap",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-cln",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-dig",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-dir",
- ["loading"]="typo-dir",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="work in progress",
- ["filename"]="typo-dha",
- ["loading"]="typo-dir",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-dua",
- ["loading"]="typo-dir",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["comment"]="work in progress",
- ["filename"]="typo-dub",
- ["loading"]="typo-dir",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-ini",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="typo-tal",
- ["loading"]="typo-tal",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-itc",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-krn",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-mar",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-pag",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-drp",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-fln",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-man",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-prc",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-lan",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-rep",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="typo-spa",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="unic-ini",
- ["loading"]="unic-ini",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-deb",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-dim",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-fmt",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-jsn",
- ["loading"]="m-json",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-lua",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-lib",
- ["loading"]="luat-lib",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="util-mrg",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-pck",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-prs",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-seq",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sql",
- ["loading"]="m-sql",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sta",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-sto",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-str",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-tab",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="util-tpl",
- ["loading"]="luat-lib",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="x-asciimath",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="x-calcmath",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="x-cals",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="x-chemml",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="x-ct",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="x-ldx",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="x-mathml",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-ini",
- ["loading"]="publ-ini.mkiv",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-aut",
- ["loading"]="publ-ini.mkiv",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-dat",
- ["loading"]="publ-ini.mkiv",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-oth",
- ["loading"]="publ-ini.mkiv",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-fnd",
- ["loading"]="publ-ini.mkiv",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-tra",
- ["loading"]="publ-ini.mkiv",
- ["status"]="pending",
- },
- {
- ["category"]="lua",
- ["filename"]="publ-usr",
- ["loading"]="publ-ini.mkiv",
- ["status"]="pending",
- },
- },
- ["main"]={
- {
- ["category"]="mkiv",
- ["filename"]="context",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="lus",
- ["comment"]="stub file for context",
- ["filename"]="context",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["filename"]="metatex",
- ["loading"]="parent",
- ["status"]="pending",
- },
- {
- ["category"]="lus",
- ["comment"]="stub file for metatex",
- ["filename"]="metatex",
- ["loading"]="parent",
- ["status"]="pending",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-cs",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-de",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-en",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-fr",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-gb",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-it",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-nl",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-pe",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="cont-ro",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="we keep this around for historic reasons",
- ["filename"]="ppchtex",
- ["loading"]="never",
- ["status"]="okay",
- },
- },
- ["metafun"]={
- {
- ["category"]="mpiv",
- ["comment"]="maybe more delayed loading",
- ["filename"]="metafun",
- ["loading"]="parent",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-base",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-tool",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-mlib",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["comment"]="sort of obsolete",
- ["filename"]="mp-core",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["comment"]="maybe some nicer synonyms",
- ["filename"]="mp-page",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-butt",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-shap",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-grph",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-grid",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["comment"]="a hack anyway",
- ["filename"]="mp-form",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-figs",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-func",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-text",
- ["loading"]="on demand",
- ["status"]="todo",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-crop",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["comment"]="follows m-chart",
- ["filename"]="mp-char",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["comment"]="follows m-steps",
- ["filename"]="mp-step",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-chem",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["comment"]="maybe some namespace changes",
- ["filename"]="mp-abck",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["comment"]="maybe some namespace changes",
- ["filename"]="mp-apos",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["comment"]="will be done when needed",
- ["filename"]="mp-asnc",
- ["loading"]="on demand",
- ["status"]="todo",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-back",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-bare",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-cows",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-fobg",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-grap",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-idea",
- ["loading"]="on demand",
- ["status"]="unknown",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-luas",
- ["loading"]="always",
- ["status"]="okay",
- },
- {
- ["category"]="mpiv",
- ["filename"]="mp-symb",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- },
- ["modules"]={
- {
- ["category"]="mkiv",
- ["comment"]="best use m-zint instead",
- ["filename"]="m-barcodes",
- ["loading"]="module",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="m-chart",
- ["loading"]="module",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this is a placeholder (chemistry is built-in)",
- ["filename"]="m-chemic",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-cweb",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-database",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="m-nodechart",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="add-on for mtx-context",
- ["filename"]="m-directives",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-educat",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-fields",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-format",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-graph",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-ipsum",
- ["loading"]="module",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-json",
- ["loading"]="module",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-layout",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="add-on for mtx-context",
- ["filename"]="m-logcategories",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-markdown",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-mathcrap",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-mkii",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-mkivhacks",
- ["status"]="todo",
- },
- {
- ["category"]="mkvi",
- ["filename"]="m-morse",
- ["loading"]="module",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-narrowtt",
- ["loading"]="module",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-ntb-to-xtb",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-obsolete",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-oldfun",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-oldnum",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-pictex",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-pstricks",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="keep an eye on changes in lua code",
- ["filename"]="m-punk",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-spreadsheet",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="m-steps",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-subsub",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-sql",
- ["loading"]="module",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-timing",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="add-on for mtx-context",
- ["filename"]="m-trackers",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-translate",
- ["status"]="okay",
- },
- {
- ["category"]="xsd",
- ["filename"]="x-chemml",
- ["status"]="todo",
- },
- {
- ["category"]="xsd",
- ["filename"]="x-contml",
- ["status"]="todo",
- },
- {
- ["category"]="rng",
- ["filename"]="x-corres",
- ["status"]="todo",
- },
- {
- ["category"]="dtd",
- ["filename"]="x-fig-00",
- ["status"]="todo",
- },
- {
- ["category"]="xsd",
- ["filename"]="x-fig-00",
- ["status"]="todo",
- },
- {
- ["category"]="ctx",
- ["filename"]="x-ldx",
- ["status"]="todo",
- },
- {
- ["category"]="xsd",
- ["filename"]="x-mathml",
- ["status"]="todo",
- },
- {
- ["category"]="xsl",
- ["filename"]="x-om2cml",
- ["status"]="todo",
- },
- {
- ["category"]="xsl",
- ["filename"]="x-openmath",
- ["status"]="todo",
- },
- {
- ["category"]="ctx",
- ["comment"]="runner for x-pfs-01",
- ["filename"]="x-pfsense",
- ["status"]="okay",
- },
- {
- ["category"]="xsd",
- ["filename"]="x-physml",
- ["status"]="todo",
- },
- {
- ["category"]="xsl",
- ["filename"]="x-sm2om",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-units",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-visual",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="m-zint",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["filename"]="s-abr-01",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-abr-02",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-abr-03",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-abr-04",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-art-01",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-cdr-01",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-def-01",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-faq-00",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-faq-01",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-faq-02",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-faq-03",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fnt-10",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fnt-20",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fnt-21",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fnt-24",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fonts-coverage",
- ["loading"]="s-fonts-coverage",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fonts-features",
- ["loading"]="s-fonts-features",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fonts-goodies",
- ["loading"]="s-fonts-goodies",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fonts-missing",
- ["loading"]="s-fonts-missing",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fonts-shapes",
- ["loading"]="s-fonts-shapes",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fonts-system",
- ["loading"]="s-fonts-system",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fonts-tables",
- ["loading"]="s-fonts-tables",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-fonts-vectors",
- ["loading"]="s-fonts-vectors",
- ["status"]="okay",
- },
- {
- ["category"]="mkvi",
- ["filename"]="s-inf-01",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-inf-02",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-inf-03",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-inf-04",
- ["status"]="todo",
- },
- {
- ["category"]="lua",
- ["filename"]="s-languages-counters",
- ["loading"]="s-languages-counters",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-languages-frequencies",
- ["loading"]="s-languages-frequencies",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="s-languages-hyphenation",
- ["loading"]="s-languages-hyphenation",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-languages-sorting",
- ["loading"]="s-languages-sorting",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-languages-system",
- ["loading"]="s-languages-system",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-mag-01",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-map-10",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-math-characters",
- ["loading"]="s-math-characters",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-math-coverage",
- ["loading"]="s-math-coverage",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-math-extensibles",
- ["loading"]="s-math-extensibles",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-math-parameters",
- ["loading"]="s-math-parameters",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-math-repertoire",
- ["loading"]="s-math-repertoire",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-mod-00",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-mod-01",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-mod-02",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-pages-statistics",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-physics-units",
- ["loading"]="s-physics-units",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-00",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-01",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-02",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-03",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-04",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-05",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-06",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-07",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-08",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-09",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-10",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-11",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-12",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-13",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-14",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-15",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-16",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-pre-17",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-18",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-19",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-22",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-23",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-26",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-27",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-pre-30",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-present-tiles",
- ["status"]="okay",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-50",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-pre-60",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-61",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-62",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-63",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-64",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-66",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-67",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-68",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-pre-69",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-pre-70",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-pre-71",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-93",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="s-pre-96",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-reg-01",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="s-sql-tables",
- ["loading"]="s-sql-tables",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-asciimath",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-calcmath",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-cals",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-chemml",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-ct",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-entities",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-foxet",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-ldx",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-mathml",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-newmml",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="pfsense xml configuration rendering",
- ["filename"]="x-pfs-01",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-physml",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-res-01",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-res-50",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="x-udhr",
- ["status"]="okay",
- },
- },
- ["optional"]={
- {
- ["category"]="mkiv",
- ["filename"]="bxml-apa",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="colo-run",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="always needs some work",
- ["filename"]="cont-new",
- ["loading"]="runtime",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["filename"]="font-run",
- ["loading"]="on demand",
- ["status"]="todo",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this is an experimental module",
- ["filename"]="lxml-ctx",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this is historic code that we keep around",
- ["filename"]="meta-pdh",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["comment"]="this is just a helper for generating files",
- ["filename"]="mult-prm",
- ["loading"]="never",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="page-run",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="mkiv",
- ["filename"]="spac-adj",
- ["loading"]="never",
- ["status"]="obsolete",
- },
- {
- ["category"]="mkiv",
- ["comment"]="replaced by a more modern variant",
- ["filename"]="supp-vis",
- ["loading"]="never",
- ["status"]="obsolete",
- },
- {
- ["category"]="mkiv",
- ["filename"]="symb-run",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- },
- ["patterns"]={
- {
- ["category"]="lua",
- ["filename"]="lang-af",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-agr",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-ala",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-bg",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-ca",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-cs",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-cy",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-da",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-de",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-deo",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-es",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-et",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-eu",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-fi",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-fr",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-gb",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-hr",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-hu",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-is",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-it",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-la",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-lt",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-lv",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-ml",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-mn",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-nb",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-nl",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-nn",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-pl",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-pt",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-ro",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-ru",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-sk",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-sl",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-sr",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-sv",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-th",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-tk",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-tr",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-uk",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-us",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="lang-zh",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- {
- ["category"]="lua",
- ["filename"]="word-xx",
- ["loading"]="on demand",
- ["status"]="okay",
- },
- },
- ["resources"]={
- {
- ["category"]="ori",
- ["comment"]="template for a user configuration file (with suffix mkiv)",
- ["filename"]="cont-sys",
- ["loading"]="runtime",
- ["status"]="okay",
- },
- {
- ["category"]="lmx",
- ["filename"]="context-base",
- ["status"]="todo",
- },
- {
- ["category"]="lmx",
- ["filename"]="context-characters",
- ["status"]="todo",
- },
- {
- ["category"]="lmx",
- ["filename"]="context-debug",
- ["status"]="todo",
- },
- {
- ["category"]="lmx",
- ["filename"]="context-error",
- ["status"]="todo",
- },
- {
- ["category"]="lmx",
- ["filename"]="context-fonttest",
- ["status"]="todo",
- },
- {
- ["category"]="lmx",
- ["filename"]="context-help",
- ["status"]="todo",
- },
- {
- ["category"]="lmx",
- ["filename"]="context-timing",
- ["status"]="todo",
- },
- {
- ["category"]="pdf",
- ["filename"]="context-version",
- ["status"]="todo",
- },
- {
- ["category"]="png",
- ["filename"]="context-version",
- ["status"]="todo",
- },
- {
- ["category"]="css",
- ["comment"]="layout specification for debug and error pages and web services",
- ["filename"]="context",
- ["status"]="okay",
- },
- {
- ["category"]="rme",
- ["comment"]="readme file",
- ["filename"]="context",
- ["status"]="okay",
- },
- {
- ["category"]="ctx",
- ["comment"]="example of a ctx file (for mtx-context)",
- ["filename"]="core-ctx",
- ["status"]="okay",
- },
- {
- ["category"]="css",
- ["filename"]="export-example",
- ["status"]="todo",
- },
- {
- ["category"]="rng",
- ["filename"]="export-example",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="export-example",
- ["status"]="todo",
- },
- {
- ["category"]="xml",
- ["comment"]="this file is auto-generated by mtx-language",
- ["filename"]="lang-all",
- ["status"]="okay",
- },
- {
- ["category"]="xml",
- ["filename"]="lpdf-pda",
- ["status"]="todo",
- },
- {
- ["category"]="xml",
- ["filename"]="lpdf-pdx",
- ["status"]="todo",
- },
- {
- ["category"]="rlx",
- ["filename"]="rlxcache",
- ["status"]="todo",
- },
- {
- ["category"]="rlx",
- ["filename"]="rlxtools",
- ["status"]="todo",
- },
- {
- ["category"]="ctx",
- ["filename"]="s-mod",
- ["status"]="todo",
- },
- {
- ["category"]="pdf",
- ["filename"]="status-files",
- ["status"]="todo",
- },
- {
- ["category"]="pdf",
- ["filename"]="status-lua",
- ["status"]="todo",
- },
- {
- ["category"]="tex",
- ["filename"]="status-mkiv",
- ["status"]="todo",
- },
- },
- ["todo"]={
- {
- ["category"]="lua",
- ["filename"]="core-run",
- ["status"]="idea",
- },
- },
-}
diff --git a/tex/context/base/mkiv/status-mkiv.tex b/tex/context/base/mkiv/status-mkiv.tex
deleted file mode 100644
index 8685c97ad..000000000
--- a/tex/context/base/mkiv/status-mkiv.tex
+++ /dev/null
@@ -1,328 +0,0 @@
-\usemodule[abr-02]
-
-\setupbodyfont
- [dejavu,9pt]
-
-\setuppapersize
- [A4,landscape]
-
-\setuplayout
- [width=middle,
- height=middle,
- backspace=.5cm,
- topspace=.5cm,
- footer=0pt,
- header=1.25cm]
-
-\setuphead
- [title]
- [style=\bfa,
- page=yes,
- after={\blank[line]}]
-
-\setuppagenumbering
- [location=]
-
-\setupheadertexts
- [\currentdate]
- [MkIV Status / Page \pagenumber]
-
-% \showmakeup
-% \showallmakeup
-
-\starttext
-
-% logs.report (immediate) versus logs.messenger (in flow)
-
-\starttitle[title=Todo]
-
-\startitemize[packed]
- \startitem currently the new namespace prefixes are not consistent but this
- will be done when we're satisfied with one scheme \stopitem
- \startitem there will be additional columns in the table, like for namespace
- so we need another round of checking then \stopitem
- \startitem the lua code will be cleaned up upgraded as some is quite old
- and experimental \stopitem
- \startitem we need a proper dependency tree and better defined loading order \stopitem
- \startitem all dotag.. will be moved to the tags_.. namespace \stopitem
- \startitem we need to check what messages are gone (i.e.\ clean up mult-mes) \stopitem
- \startitem some commands can go from mult-def (and the xml file) \stopitem
- \startitem check for setuphandler vs simplesetuphandler \stopitem
- \startitem for the moment we will go for \type {xxxx_} namespaces that (mostly) match
- the filename but later we can replace these by longer names (via a script) so
- module writers should {\bf not} use the core commands with \type{_} in the
- name \stopitem
- \startitem the message system will be unified \stopitem
- \startitem maybe rename dowhatevertexcommand to fromluawhatevertexcommand \stopitem
- \startitem consider moving setups directly to lua end (e.g. in characterspacing, breakpoint, bitmaps etc.) \stopitem
- \startitem more local temporary \type {\temp...} will become \type {\p_...} \stopitem
- \startitem check all ctxlua calls for ctxcommand \stopitem
- \startitem rename all those \type {\current<whatever>}s in strc \stopitem
- \startitem check \type {option} vs \type {options} \stopitem
- \startitem check \type {type} vs \type {kind} \stopitem
- \startitem check \type {label} vs \type {name} vs \type {tag} \stopitem
- \startitem check \type {limop}, different limops should should be classes \stopitem
- \startitem too many positions in simple files (itemize etc) \stopitem
- \startitem math domains/dictionaries \stopitem
- \startitem xtables don't span vertically with multilines (yet) \stopitem
- \startitem notes in mixed columns \stopitem
- \startitem floats in mixed columns \stopitem
- \startitem check return values \type {os.execute} \stopitem
- \startitem more r, d, k in xml code \stopitem
- \startitem mathml, more in \LUA \stopitem
- \startitem style: font-size, font, color handling in \HTML\ (lxml-css) \stopitem
- \startitem a \type {\name {A.B.C DEF}} auto-nobreakspace \stopitem
- \startitem redo \CWEB\ module with \LUA \stopitem
- \startitem maybe move characters.blocks to its own file \stopitem
- \startitem more local context = context in \LUA\ files \stopitem
- \startitem check and optimize all storage.register and locals (cosmetics) \stopitem
- \startitem check all used modules in \LUA\ (and local them) \stopitem
- \startitem environment and basic lua helpers are now spread over too many files \stopitem
- \startitem isolate tracers and showers \stopitem
- \startitem check all possible usage of ctxcommand \stopitem
- \startitem there are more s-* modules, like s-fnt-41 \stopitem
- \startitem check (un)marked tables \stopitem
-\stopitemize
-
-\stoptitle
-
-\starttitle[title=To keep an eye on]
-
-\startitemize[packed]
- \startitem Currently lpeg replacements interpret the percent sign so we need to escape it. \stopitem
- \startitem Currently numbers and strings are cast in comparisons bu tthat might change in the future. \stopitem
-\stopitemize
-
-\stoptitle
-
-\definehighlight[notabenered] [color=darkred, style=bold]
-\definehighlight[notabeneblue] [color=darkblue, style=bold]
-\definehighlight[notabeneyellow] [color=darkyellow, style=bold]
-\definehighlight[notabenemagenta][color=darkmagenta,style=bold]
-
-\startluacode
-
- local coremodules = dofile("status-mkiv.lua")
-
- local valid = table.tohash {
- "toks", "attr", "page", "buff", "font", "colo", "phys", "supp", "typo", "strc",
- "syst", "tabl", "spac", "scrn", "lang", "lxml", "mlib", "java", "pack", "math",
- "symb", "grph", "anch", "luat", "mult", "back", "node", "meta", "norm", "catc",
- "cldf", "file", "char", "core", "layo", "trac", "cont", "regi", "enco", "hand",
- "unic", "sort", "blob", "type", "scrp", "prop", "chem", "bibl", "task",
- "whatever", "mp", "s", "x", "m", "mtx",
- }
-
- local specialcategories = {
- mkvi = true,
- }
-
- local what = {
- "main", "core", "lua", "optional", "implementations", "extra", "extras", "metafun", "modules", "resources"
- }
-
- local totaltodo = 0
- local totalpending = 0
- local totalobsolete = 0
- local totalloaded = 0
-
- local function summary(nofloaded,noftodo,nofpending,nofobsolete)
-
- local nofdone = nofloaded - noftodo - nofpending - nofobsolete
-
- context.starttabulate { "|B|r|" }
- context.HL()
- context.NC() context("done") context.NC() context(nofdone) context.NC() context.NR()
- context.NC() context("todo") context.NC() context(noftodo) context.NC() context.NR()
- context.NC() context("pending") context.NC() context(nofpending) context.NC() context.NR()
- context.NC() context("obsolete") context.NC() context(nofobsolete) context.NC() context.NR()
- context.HL()
- context.NC() context("loaded") context.NC() context(nofloaded) context.NC() context.NR()
- context.HL()
- context.stoptabulate()
-
- end
-
- if coremodules then
-
- local function tabelize(loaded,what)
-
- if loaded then
-
- local noftodo = 0
- local nofpending = 0
- local nofobsolete = 0
- local nofloaded = #loaded
- local categories = { }
-
- for k, v in next, valid do
- categories[k] = { }
- end
-
- for i=1,nofloaded do
- local l = loaded[i]
- l.order = i
- local category = string.match(l.filename,"([^%-]+)%-") or "whatever"
- local c = categories[category]
- if c then
- c[#c+1] = l
- end
- end
-
- for k, loaded in table.sortedhash(categories) do
-
- local nofloaded = #loaded
-
- if nofloaded > 0 then
-
- table.sort(loaded,function(a,b) return a.filename < b.filename end) -- in place
-
- context.starttitle { title = string.format("%s: %s",what,k) }
-
- context.starttabulate { "|Tr|Tlw(3em)|Tlw(12em)|Tlw(12em)|Tlw(4em)|Tl|Tl|Tl|Tp|" }
- context.NC() context.bold("order")
- context.NC() context.bold("kind")
- context.NC() context.bold("file")
- context.NC() context.bold("loading")
- context.NC() context.bold("status")
- context.NC() context.bold("reference")
- context.NC() context.bold("manual")
- context.NC() context.bold("wiki")
- context.NC() context.bold("comment")
- context.NC() context.NR()
- context.HL()
- for i=1,nofloaded do
- local module = loaded[i]
- local status = module.status
- local category = module.category
- local filename = module.filename
- context.NC()
- context(module.order)
- context.NC()
- if specialcategories[category] then
- context.notabeneblue(category)
- else
- context(category)
- end
- context.NC()
- if #filename>20 then
- context(string.sub(filename,1,18) .. "..")
- else
- context(filename)
- end
- context.NC()
- context(module.loading)
- context.NC()
- if status == "todo" then
- context.notabenered(status)
- noftodo = noftodo + 1
- elseif status == "pending" then
- context.notabeneyellow(status)
- nofpending = nofpending + 1
- elseif status == "obsolete" then
- context.notabenemagenta(status)
- nofobsolete = nofobsolete + 1
- else
- context(status)
- end
- context.NC() context(module.reference)
- context.NC() context(module.manual)
- context.NC() context(module.wiki)
- context.NC() context(module.comment)
- context.NC() context.NR()
- end
- context.stoptabulate()
-
- context.stoptitle()
-
- end
-
- end
-
- context.starttitle { title = string.format("summary of %s modules",what) }
-
- summary(nofloaded,noftodo,nofpending,nofobsolete)
-
- context.stoptitle()
-
- totaltodo = totaltodo + noftodo
- totalpending = totalpending + nofpending
- totalobsolete = totalobsolete + nofobsolete
- totalloaded = totalloaded + nofloaded
-
- end
-
- end
-
- for i=1,#what do
- tabelize(coremodules[what[i]],what[i])
- end
-
- end
-
- -- context.starttitle { title = "Valid prefixes" }
- --
- -- for namespace, data in table.sortedhash(namespaces) do
- -- if valid[namespace] then
- -- context.type(namespace)
- -- end
- -- context.par()
- -- end
- --
- -- context.stoptitle()
-
- context.starttitle { title = string.format("summary of all",what) }
-
- summary(totalloaded,totaltodo,totalpending,totalobsolete)
-
- context.stoptitle()
-
- if io.exists("status-namespaces.lua") then
-
- context.starttitle { title = "messy namespaces" }
-
- local namespaces = dofile("status-namespaces.lua")
-
- for namespace, data in table.sortedhash(namespaces) do
- if valid[namespace] then
- else
- context(namespace)
- end
- context.par()
- end
-
- context.stoptitle()
-
- end
-
- if io.exists("status-registers.lua") then
-
- context.starttitle { title = "messy registers" }
-
- local registers = dofile("status-registers.lua")
-
- for register, data in table.sortedhash(registers) do
- context(register)
- context.par()
- for name in table.sortedhash(data) do
- context.quad()
- context.type(name)
- context.par()
- end
- context.par()
- end
-
- context.stoptitle()
-
- end
-
- context.starttitle { title = "callbacks" }
-
- commands.showcallbacks()
-
- context.stoptitle()
-
-\stopluacode
-
-
-\stoptext
diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf
index 23c4a1f20..d8fbecc32 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-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf
index 95d456ece..1bcd2b2f9 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/sample/common/jojomayer.tex b/tex/context/sample/common/jojomayer.tex
new file mode 100644
index 000000000..966b356a6
--- /dev/null
+++ b/tex/context/sample/common/jojomayer.tex
@@ -0,0 +1,3 @@
+If we surrender the thing that separates us from machines, we will be replaced by
+machines. The more advanced machines will be, the more human we will have to
+become.
diff --git a/tex/context/sample/common/mcnish.tex b/tex/context/sample/common/mcnish.tex
new file mode 100644
index 000000000..ab09ca0bc
--- /dev/null
+++ b/tex/context/sample/common/mcnish.tex
@@ -0,0 +1,73 @@
+% poetry, music and typesetting
+%
+% https://www.youtube.com/watch?v=SB8_2Yuj8Og
+%
+% Published on Nov 1, 2016
+% Taken from 'Poetry versus Orchestra'. Album by Hollie McNish and Metropole Orkest, conducted by Jules Buckley.
+% Released on MO Black, fall 2016.
+% www.mo.nl/poetry • www.holliepoetry.com
+%
+% Poem written by Hollie McNish, music by Jules Buckley
+% Artwork by me studio, Martin Pyper
+%
+MATHEMATICS
+
+he said
+“those goddamn pakistanis and their goddamn corner shops
+built a shop on every corner, took our british workers jobs”
+he said
+“those goddamn chinese and their goddamn china shops”
+i told him they’re from vietnam, but he didn’t give a toss
+i ask him what was there before that “damn japan man’s shop?”
+he looks at me and dreams a scene of british workers’ jobs
+of full-time, full-employment before the “goddamn boats all came”
+where everybody went to work for full-time full-hours every day
+“a british business stood their first”
+he claims
+“before the irish came
+now british people lost their jobs and bloody turkish they're to blame”
+i ask him how he knows that fact, he says, “because it’s true”
+i ask him how he knows it’s fact, he says, he read it in the news,
+“every time a somali comes here they take a job from us
+the mathematics one for one, from us to them, it just adds up.”
+he bites his cake, he sips his brew, he says again he knows the plot
+“the goddamn caribbean’s came and now good folk here don’t have jobs”
+i ask him what was there before the “goddamn persian curtain shop”
+i show him architectures’ plans
+of empty goddamn plots of land
+I show him the historic maps
+a bit of sand
+a barren land
+there was no goddamn shop before that pakistani came and planned
+man - i am sick of crappy mathematics
+cos i love a bit of sums
+i spent years into economics
+and i geek out over calculus
+and when i meet these paper claims
+that one of every new that came
+takes away ‘our’ daily wage
+i desperately want to scream
+“your math is stuck-in primary”
+cos some who come here also spend
+and some who come here also lend
+and some who come here also tend
+to set up work which employs them
+and all thosebalance sheets and trends
+they work with numbers, not with men
+and all this goddamn heated talk
+ignores the trade the polish brought
+ignores the men they give work to
+not plumbing jobs but further too
+ignores the guys they buy stock from
+accountants, builders, on and on
+and i know it’s nice to have someone
+to blame our lack of jobs upon
+but immigration’s not that plain
+despite the sums inside our brains
+as one for one
+as him for you
+as if he goes ‘home’, they’d employ you
+cos sometimes one that comes makes two
+and sometimes one can add three more
+and sometimes two times two is much, much more than four
+and most times immigrants bring more than minuses.
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index a94ba85af..0c8e40ce4 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 : 05/25/17 12:50:49
+-- merge date : 05/27/17 18:52:27
do -- begin closure to overcome local limits and interference
@@ -7758,7 +7758,7 @@ function constructors.scale(tfmdata,specification)
target.unscaled=tfmdata
local mathsize=tonumber(specification.mathsize) or 0
local textsize=tonumber(specification.textsize) or scaledpoints
- local forcedsize=tonumber(parameters.mathsize ) or 0
+ local forcedsize=tonumber(parameters.mathsize ) or 0
local extrafactor=tonumber(specification.factor ) or 1
if (mathsize==2 or forcedsize==2) and parameters.scriptpercentage then
scaledpoints=parameters.scriptpercentage*textsize/100
@@ -7766,6 +7766,7 @@ function constructors.scale(tfmdata,specification)
scaledpoints=parameters.scriptscriptpercentage*textsize/100
elseif forcedsize>1000 then
scaledpoints=forcedsize
+ else
end
targetparameters.mathsize=mathsize
targetparameters.textsize=textsize
@@ -8827,7 +8828,7 @@ do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['font-cid']={
version=1.001,
- comment="companion to font-otf.lua (cidmaps)",
+ comment="companion to font-ini.mkiv",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
@@ -19850,7 +19851,7 @@ local function checkmathsize(tfmdata,mathsize)
local parameters=tfmdata.parameters
parameters.scriptpercentage=mathdata.ScriptPercentScaleDown
parameters.scriptscriptpercentage=mathdata.ScriptScriptPercentScaleDown
- parameters.mathsize=mathsize
+ parameters.mathsize=mathsize
end
end
registerotffeature {
@@ -21771,7 +21772,7 @@ do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['font-ota']={
version=1.001,
- comment="companion to font-otf.lua (analysing)",
+ comment="companion to font-ini.mkiv",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
@@ -27534,7 +27535,7 @@ do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['font-ocl']={
version=1.001,
- comment="companion to font-otf.lua (context)",
+ comment="companion to font-ini.mkiv",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
@@ -27982,7 +27983,7 @@ do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['font-otc']={
version=1.001,
- comment="companion to font-otf.lua (context)",
+ comment="companion to font-ini.mkiv",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
@@ -29922,7 +29923,7 @@ do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['font-afk']={
version=1.001,
- comment="companion to font-afm.lua",
+ comment="companion to font-lib.mkiv",
author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files",
diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua
index 20690992c..93ead749e 100644
--- a/tex/generic/context/luatex/luatex-fonts.lua
+++ b/tex/generic/context/luatex/luatex-fonts.lua
@@ -231,21 +231,6 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('luatex-fonts-syn.lua')
loadmodule('font-oti.lua')
-
- -- These are the old loader and processing modules. These use the built-in font loader and
- -- will stay around (but not be extended), only fixed.
-
- -- font-otf.lua
- -- font-otb.lua
- -- font-inj.lua
- -- font-ota.lua
- -- font-otn.lua
- -- font-otp.lua
-
- -- Here come the new loader and processing modules. The loader is written in Lua and although
- -- initial loading is somewhat slower, identifying is faster, cached files can be slightly
- -- more efficient, and processing is somewhat faster (only measureable on complex fonts).
-
loadmodule('font-otr.lua')
loadmodule('font-cff.lua')
loadmodule('font-ttf.lua')
@@ -258,7 +243,6 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('font-ots.lua')
loadmodule('font-osd.lua')
loadmodule('font-ocl.lua') -- svg needs 0.97 (for fix in memstreams)
-
loadmodule('font-otc.lua')
-- type one code
@@ -277,7 +261,7 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('font-def.lua')
loadmodule('font-xtx.lua') -- xetex compatible specifiers (plain/latex only)
loadmodule('luatex-fonts-ext.lua') -- some extensions
- -- loadmodule('luatex-fonts-lig.lua') -- and another one
+ loadmodule('luatex-fonts-lig.lua') -- and another one
-- We need to plug into a callback and the following module implements the handlers. Actual
-- plugging in happens later.