From 7be0d39244155e874321d77ef81078c5bd2817a9 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Tue, 5 Mar 2013 16:40:00 +0100 Subject: beta 2013.03.05 16:40 --- tex/context/base/attr-mkr.lua | 12 +- tex/context/base/back-exp.lua | 39 +- tex/context/base/cont-new.mkii | 2 +- tex/context/base/cont-new.mkiv | 2 +- tex/context/base/context-version.pdf | Bin 4123 -> 4135 bytes tex/context/base/context-version.png | Bin 40213 -> 40313 bytes tex/context/base/context.mkii | 2 +- tex/context/base/context.mkiv | 2 +- tex/context/base/font-ctx.lua | 30 +- tex/context/base/font-gds.lua | 3 +- tex/context/base/font-odv.lua | 1305 +++----------------- tex/context/base/font-ota.lua | 106 +- tex/context/base/font-otd.lua | 4 +- tex/context/base/font-otn.lua | 336 +++-- tex/context/base/font-sol.lua | 16 +- tex/context/base/l-boolean.lua | 16 +- tex/context/base/lang-wrd.lua | 10 +- tex/context/base/lpdf-tag.lua | 14 +- tex/context/base/math-noa.lua | 295 +++-- tex/context/base/math-tag.lua | 72 +- tex/context/base/node-acc.lua | 14 +- tex/context/base/node-aux.lua | 31 +- tex/context/base/node-bck.lua | 32 +- tex/context/base/node-fin.lua | 61 +- tex/context/base/node-fnt.lua | 170 +-- tex/context/base/node-inj.lua | 71 +- tex/context/base/node-mig.lua | 8 +- tex/context/base/node-ref.lua | 19 +- tex/context/base/node-rul.lua | 22 +- tex/context/base/node-tra.lua | 33 +- tex/context/base/page-lin.lua | 11 +- tex/context/base/scrn-hlp.lua | 3 +- tex/context/base/scrp-cjk.lua | 19 +- tex/context/base/scrp-eth.lua | 5 +- tex/context/base/scrp-ini.lua | 16 +- tex/context/base/spac-adj.lua | 17 +- tex/context/base/spac-ali.lua | 8 +- tex/context/base/spac-chr.lua | 12 +- tex/context/base/spac-ver.lua | 41 +- tex/context/base/status-files.pdf | Bin 24788 -> 24803 bytes tex/context/base/status-lua.pdf | Bin 208938 -> 209215 bytes tex/context/base/strc-mar.lua | 5 +- tex/context/base/trac-jus.lua | 8 +- tex/context/base/trac-vis.lua | 70 +- tex/context/base/typo-bld.lua | 3 +- tex/context/base/typo-brk.lua | 7 +- tex/context/base/typo-cap.lua | 11 +- tex/context/base/typo-cln.lua | 5 +- tex/context/base/typo-dig.lua | 7 +- tex/context/base/typo-dir.lua | 13 +- tex/context/base/typo-itc.lua | 3 +- tex/context/base/typo-krn.lua | 8 +- tex/context/base/typo-mar.lua | 15 +- tex/context/base/typo-pag.lua | 13 +- tex/context/base/typo-par.lua | 11 +- tex/context/base/typo-rep.lua | 3 +- tex/context/base/typo-spa.lua | 6 +- tex/generic/context/luatex/luatex-fonts-merged.lua | 18 +- 58 files changed, 984 insertions(+), 2081 deletions(-) (limited to 'tex') diff --git a/tex/context/base/attr-mkr.lua b/tex/context/base/attr-mkr.lua index c809d53a9..976598fa0 100644 --- a/tex/context/base/attr-mkr.lua +++ b/tex/context/base/attr-mkr.lua @@ -6,23 +6,21 @@ if not modules then modules = { } end modules ['attr-mkr'] = { license = "see context related readme files" } -local has_attribute = node.has_attribute - local markers = nodes.markers or { } nodes.markers = markers -local cache = { } -local numbers = attributes.numbers -local unknown = attributes.private("marker:unknown") +local cache = { } +local numbers = attributes.numbers +local a_unknown = attributes.private("marker:unknown") table.setmetatableindex(cache,function(t,k) local k = "marker:" .. k - local v = numbers[k] or unknown + local v = numbers[k] or a_unknown t[k] = v return v end) function markers.get(n,name) local a = cache[name] - return a and has_attribute(n,a) or nil + return a and n[a] or nil end diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua index 37af87505..5d8b4cc8c 100644 --- a/tex/context/base/back-exp.lua +++ b/tex/context/base/back-exp.lua @@ -88,15 +88,12 @@ local a_reference = attributes.private('reference') local a_textblock = attributes.private("textblock") -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute local traverse_id = node.traverse_id local traverse_nodes = node.traverse local slide_nodelist = node.slide local texattribute = tex.attribute local texdimen = tex.dimen local texcount = tex.count -local unsetvalue = attributes.unsetvalue local locate_node = nodes.locate local references = structures.references @@ -1844,7 +1841,7 @@ local function collectresults(head,list) -- is last used (we also have currentat for n in traverse_nodes(head) do local id = n.id -- 14: image, 8: literal (mp) if id == glyph_code then - local at = has_attribute(n,a_tagged) + local at = n[a_tagged] if not at then -- we need to tag the pagebody stuff as being valid skippable -- @@ -1863,7 +1860,7 @@ local function collectresults(head,list) -- is last used (we also have currentat -- end pushcontent() currentnesting = tl - currentparagraph = has_attribute(n,a_taggedpar) + currentparagraph = n[a_taggedpar] currentattribute = at last = at pushentry(currentnesting) @@ -1872,13 +1869,13 @@ local function collectresults(head,list) -- is last used (we also have currentat end -- We need to intercept this here; maybe I will also move this -- to a regular setter at the tex end. - local r = has_attribute(n,a_reference) + local r = n[a_reference] if r then referencehash[tl[#tl]] = r -- fulltag end -- elseif last then - local ap = has_attribute(n,a_taggedpar) + local ap = n[a_taggedpar] if ap ~= currentparagraph then pushcontent(format("new paragraph (%s -> %s)",tostring(currentparagraph),tostring(ap))) pushentry(currentnesting) @@ -1893,7 +1890,7 @@ local function collectresults(head,list) -- is last used (we also have currentat report_export("%s",spaces[currentdepth],tracedchar(c),at) end end - local s = has_attribute(n,a_exportstatus) + local s = n[a_exportstatus] if s then c = s end @@ -1902,7 +1899,7 @@ local function collectresults(head,list) -- is last used (we also have currentat report_export("%s",spaces[currentdepth]) end elseif c == 0x20 then - local a = has_attribute(n,a_characters) + local a = n[a_characters] nofcurrentcontent = nofcurrentcontent + 1 if a then if trace_export then @@ -1947,11 +1944,11 @@ local function collectresults(head,list) -- is last used (we also have currentat collectresults(n.replace,nil) elseif id == glue_code then -- we need to distinguish between hskips and vskips - local ca = has_attribute(n,a_characters) + local ca = n[a_characters] if ca == 0 then -- skip this one ... already converted special character (node-acc) elseif ca then - local a = has_attribute(n,a_tagged) + local a = n[a_tagged] if a then local c = specialspaces[ca] if last ~= a then @@ -1961,13 +1958,13 @@ local function collectresults(head,list) -- is last used (we also have currentat end pushcontent() currentnesting = tl - currentparagraph = has_attribute(n,a_taggedpar) + currentparagraph = n[a_taggedpar] currentattribute = a last = a pushentry(currentnesting) -- no reference check (see above) elseif last then - local ap = has_attribute(n,a_taggedpar) + local ap = n[a_taggedpar] if ap ~= currentparagraph then pushcontent(format("new paragraph (%s -> %s)",tostring(currentparagraph),tostring(ap))) pushentry(currentnesting) @@ -1992,7 +1989,7 @@ local function collectresults(head,list) -- is last used (we also have currentat if subtype == userskip_code then if n.spec.width > threshold then if last and not somespace[currentcontent[nofcurrentcontent]] then - local a = has_attribute(n,a_tagged) + local a = n[a_tagged] if a == last then if trace_export then report_export("%s",spaces[currentdepth]) @@ -2019,7 +2016,7 @@ local function collectresults(head,list) -- is last used (we also have currentat end elseif subtype == spaceskip_code or subtype == xspaceskip_code then if not somespace[currentcontent[nofcurrentcontent]] then - local a = has_attribute(n,a_tagged) + local a = n[a_tagged] if a == last then if trace_export then report_export("%s",spaces[currentdepth]) @@ -2048,7 +2045,7 @@ local function collectresults(head,list) -- is last used (we also have currentat nofcurrentcontent = nofcurrentcontent - 1 end elseif not somespace[r] then - local a = has_attribute(n,a_tagged) + local a = n[a_tagged] if a == last then if trace_export then report_export("%s",spaces[currentdepth]) @@ -2076,9 +2073,9 @@ local function collectresults(head,list) -- is last used (we also have currentat end end elseif id == hlist_code or id == vlist_code then - local ai = has_attribute(n,a_image) + local ai = n[a_image] if ai then - local at = has_attribute(n,a_tagged) + local at = n[a_tagged] if nofcurrentcontent > 0 then pushcontent() pushentry(currentnesting) -- ?? @@ -2102,7 +2099,7 @@ local function collectresults(head,list) -- is last used (we also have currentat end if kern > limit then if last and not somespace[currentcontent[nofcurrentcontent]] then - local a = has_attribute(n,a_tagged) + local a = n[a_tagged] if a == last then if not somespace[currentcontent[nofcurrentcontent]] then if trace_export then @@ -2155,9 +2152,9 @@ function builders.paragraphs.tag(head) for n in traverse_id(hlist_code,head) do local subtype = n.subtype if subtype == line_code then - set_attribute(n,a_textblock,noftextblocks) + n[a_textblock] = noftextblocks elseif subtype == glue_code or subtype == kern_code then - set_attribute(n,a_textblock,0) + n[a_textblock] = 0 end end return false diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii index 595673889..d48699773 100644 --- a/tex/context/base/cont-new.mkii +++ b/tex/context/base/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2013.03.04 18:28} +\newcontextversion{2013.03.05 16:40} %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/cont-new.mkiv b/tex/context/base/cont-new.mkiv index d57ae6a48..5f1458551 100644 --- a/tex/context/base/cont-new.mkiv +++ b/tex/context/base/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2013.03.04 18:28} +\newcontextversion{2013.03.05 16:40} %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/context-version.pdf b/tex/context/base/context-version.pdf index b1f6dc675..b4229a6ae 100644 Binary files a/tex/context/base/context-version.pdf and b/tex/context/base/context-version.pdf differ diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png index d0dbca3ea..429cde9e0 100644 Binary files a/tex/context/base/context-version.png and b/tex/context/base/context-version.png differ diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii index d99c0fea8..6295767a5 100644 --- a/tex/context/base/context.mkii +++ b/tex/context/base/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2013.03.04 18:28} +\edef\contextversion{2013.03.05 16:40} %D For those who want to use this: diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index 1be6780bf..991356070 100644 --- a/tex/context/base/context.mkiv +++ b/tex/context/base/context.mkiv @@ -25,7 +25,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2013.03.04 18:28} +\edef\contextversion{2013.03.05 16:40} %D For those who want to use this: diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua index 1e10e2e68..611da4c97 100644 --- a/tex/context/base/font-ctx.lua +++ b/tex/context/base/font-ctx.lua @@ -1635,9 +1635,8 @@ local registerotffeature = otffeatures.register local analyzers = fonts.analyzers local methods = analyzers.methods -local get_attribute = node.has_attribute -local set_attribute = node.set_attribute -local unset_attribute = node.unset_attribute +local unsetvalue = attributes.unsetvalue + local traverse_by_id = node.traverse_id local a_color = attributes.private('color') @@ -1647,23 +1646,34 @@ local m_color = attributes.list[a_color] or { } local glyph_code = nodes.nodecodes.glyph +local states = analyzers.states + local names = { - "font:1", "font:2", "font:3", "font:3", -- arabic - "font:4", "font:5", "font:6", "font:7", "font:8", "font:9", -- devanagary + [states.init] = "font:1", + [states.medi] = "font:2", + [states.fina] = "font:3", + [states.isol] = "font:4", + [states.mark] = "font:5", + [states.rest] = "font:6", + [states.rphf] = "font:1", + [states.half] = "font:2", + [states.pref] = "font:3", + [states.blwf] = "font:4", + [states.pstf] = "font:5", } local function markstates(head) if head then - local model = get_attribute(head,a_colormodel) or 1 + local model = head[a_colormodel] or 1 for glyph in traverse_by_id(glyph_code,head) do - local a = get_attribute(glyph,a_state) + local a = glyph[a_state] if a then local name = names[a] if name then local color = m_color[name] if color then - set_attribute(glyph,a_colormodel,model) - set_attribute(glyph,a_color,color) + glyph[a_colormodel] = model + glyph[a_color] = color end end end @@ -1707,7 +1717,7 @@ registerotffeature { -- adapts function methods.nocolor(head,font,attr) for n in traverse_by_id(glyph_code,head) do if not font or n.font == font then - unset_attribute(n,a_color) + n[a_color] = unsetvalue end end return head, true diff --git a/tex/context/base/font-gds.lua b/tex/context/base/font-gds.lua index ea24b203a..68a2317ab 100644 --- a/tex/context/base/font-gds.lua +++ b/tex/context/base/font-gds.lua @@ -300,7 +300,6 @@ end local fontdata = fonts.hashes.identifiers local setnodecolor = nodes.tracers.colors.set -local has_attribute = node.has_attribute local traverse_id = node.traverse_id local a_colorscheme = attributes.private('colorscheme') local glyph = node.id("glyph") @@ -309,7 +308,7 @@ function colorschemes.coloring(head) local lastfont, lastscheme local done = false for n in traverse_id(glyph,head) do - local a = has_attribute(n,a_colorscheme) + local a = n[a_colorscheme] if a then local f = n.font if f ~= lastfont then diff --git a/tex/context/base/font-odv.lua b/tex/context/base/font-odv.lua index c4def223e..7904bdb59 100644 --- a/tex/context/base/font-odv.lua +++ b/tex/context/base/font-odv.lua @@ -6,20 +6,6 @@ if not modules then modules = { } end modules ['font-odv'] = { license = "see context related readme files" } -if true then - -- Not yet as there is some change in headnode handling as needed - -- for this mechanism and I won't adapt this code because soon there's - -- another adaption coming (already in my private tree) but that need - -- a newer luatex. - return -end - --- Kai: we're leaking nodes (happens when assigning start nodes behind start, also --- in the original code) so this needs to be sorted out. As I touched nearly all code, --- reshuffled, etc. etc. (imagine how much can get messed up in nearly 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. - -- A few remarks: -- -- This code is a partial rewrite of the code that deals with devanagari. The data and logic @@ -29,6 +15,12 @@ end -- deva: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/introO.mspx -- dev2: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/intro.mspx -- +-- 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 @@ -38,16 +30,17 @@ end -- 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. I kept the comments but added a few more. 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. +-- 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 with both variants so it's worth the effort. 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). +-- 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. -- @@ -108,15 +101,14 @@ local registerotffeature = otffeatures.register local processcharacters = nodes.handlers.characters -local set_attribute = node.set_attribute -local unset_attribute = node.unset_attribute -local has_attribute = node.has_attribute local insert_node_after = node.insert_after local copy_node = node.copy local free_node = node.free local remove_node = node.remove local flush_list = node.flush_list +local unsetvalue = attributes.unsetvalue + local fontdata = fonts.hashes.identifiers local a_state = attributes.private('state') @@ -124,6 +116,14 @@ 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 + -- 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. @@ -176,35 +176,15 @@ local stress_tone_mark = { [0x0951] = true, [0x0952] = true, [0x0953] = true, [0x0954] = true, } -local nukta = { - [0x093C] = true, -} - -local halant = { - [0x094D] = true, -} - -local ra = { - [0x0930] = true, -} - -local anudatta = { - [0x0952] = true, -} - -local nbsp = { -- might become a constant instead of table - [0x00A0] = true, -} - -local zwnj = { -- might become a constant instead of table - [0x200C] = true, -} - -local zwj = { -- might become a constant instead of table - [0x200D] = true, -} +local c_nukta = 0x093C -- used to be tables +local c_halant = 0x094D -- used to be tables +local c_ra = 0x0930 -- used to be tables +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 = { +local zw_char = { -- could also be inlined [0x200C] = true, [0x200D] = true, } @@ -292,7 +272,10 @@ local deva_defaults = { local false_flags = { false, false, false, false } -local both_joiners_true = { [0x200C] = true, [0x200D] = true } +local both_joiners_true = { + [0x200C] = true, + [0x200D] = true, +} local sequence_reorder_matras = { chain = 0, @@ -483,38 +466,38 @@ local function deva_reorder(head,start,stop,font,attr) local lastcons = nil local basefound = false - if ra[start.char] and halant[n.char] and reph then + if start.char == c_ra and n.char == c_halant 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 + if n.next.char == c_zwj then current = start else current = n.next - set_attribute(start,a_state,5) -- rphf + start[a_state] = s_rphf end end - if nbsp[current.char] then + if current.char == c_nbsp then -- Stand Alone cluster if current == stop then stop = stop.prev - head = remove_node(head, current) + head = remove_node(head,current) free_node(current) return head, stop else base, firstcons, lastcons = current, current, current current = current.next if current ~= stop then - if nukta[current.char] then + if current.char == c_nukta then current = current.next end - if zwj[current.char] then + if current.char == c_zwj then if current ~= stop then local next = current.next - if next ~= stop and halant[next.char] then + if next ~= stop and next.char == c_halant then current = next next = current.next local tmp = next.next @@ -523,9 +506,9 @@ local function deva_reorder(head,start,stop,font,attr) local nextcurrent = copy_node(current) tempcurrent.next = nextcurrent nextcurrent.prev = tempcurrent - set_attribute(tempcurrent,a_state,8) --blwf + tempcurrent[a_state] = s_blwf tempcurrent = processcharacters(tempcurrent) - unset_attribute(tempcurrent,a_state) + tempcurrent[a_state] = unsetvalue if next.char == tempcurrent.char then flush_list(tempcurrent) local n = copy_node(current) @@ -552,7 +535,7 @@ local function deva_reorder(head,start,stop,font,attr) while not basefound do -- find base consonant if consonant[current.char] then - set_attribute(current,a_state,6) -- half + current[a_state] = s_half if not firstcons then firstcons = current end @@ -561,7 +544,7 @@ local function deva_reorder(head,start,stop,font,attr) base = current elseif blwfcache[current.char] then -- consonant has below-base (or post-base) form - set_attribute(current,a_state,8) -- blwf + current[a_state] = s_blwf else base = current end @@ -574,14 +557,14 @@ local function deva_reorder(head,start,stop,font,attr) -- if base consonant is not last one then move halant from base consonant to last one local np = base local n = base.next - if nukta[n.char] then + if n.char == c_nukta then np = n n = n.next end - if halant[n.char] then + if n.char == c_halant then if lastcons ~= stop then local ln = lastcons.next - if nukta[ln.char] then + if ln.char == c_nukta then lastcons = ln end end @@ -603,7 +586,7 @@ local function deva_reorder(head,start,stop,font,attr) end n = start.next - if ra[start.char] and halant[n.char] and not (n ~= stop and zw_char[n.next.char]) then + if start.char == c_ra and n.char == c_halant and not (n ~= stop and zw_char[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 @@ -640,16 +623,16 @@ local function deva_reorder(head,start,stop,font,attr) local current = start while current ~= stop do local next = current.next - if next ~= stop and halant[next.char] and zwnj[next.next.char] then - unset_attribute(current,a_state) + if next ~= stop and next.char == c_halant and next.next.char == c_zwnj then + current[a_state] = unsetvalue end current = next end - if base ~= stop and has_attribute(base,a_state) then + if base ~= stop and base[a_state] then local next = base.next - if halant[next.char] and not (next ~= stop and zwj[next.next.char]) then - unset_attribute(base,a_state) + if next.char == c_halant and not (next ~= stop and next.next.char == c_zwj) then + base[a_state] = unsetvalue end end @@ -660,7 +643,7 @@ local function deva_reorder(head,start,stop,font,attr) 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 + if base ~= stop and bn.char == c_nukta then a, b, p = bn, bn, bn end while not allreordered do @@ -669,12 +652,12 @@ local function deva_reorder(head,start,stop,font,attr) local n = current.next local l = nil -- used ? if c ~= stop then - if nukta[n.char] then + if n.char == c_nukta then c = n n = n.next end if c ~= stop then - if halant[n.char] then + if n.char == c_halant then c = n n = n.next end @@ -734,7 +717,7 @@ local function deva_reorder(head,start,stop,font,attr) while current ~= stop do local c = current local n = current.next - if ra[current.char] and halant[n.char] then + if current.char == c_ra and n.char == c_halant then c = n n = n.next local b, bn = base, base @@ -745,7 +728,7 @@ local function deva_reorder(head,start,stop,font,attr) end bn = next end - if has_attribute(current,a_state) == 5 then + if 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 @@ -797,10 +780,10 @@ local function deva_reorder(head,start,stop,font,attr) end else local char = current.char - if consonant[char] or nbsp[char] then -- maybe combined hash + if consonant[char] or char == c_nbsp then -- maybe combined hash cns = current local next = cns.next - if halant[next.char] then + if next.char == c_halant then cns = next end end @@ -809,7 +792,7 @@ local function deva_reorder(head,start,stop,font,attr) end end - if nbsp[base.char] then + if base.char == c_nbsp then head = remove_node(head,base) free_node(base) end @@ -826,19 +809,19 @@ end -- 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(start,kind,lookupname,replacement) -- no leak +function handlers.devanagari_reorder_matras(head,start,kind,lookupname,replacement) -- no leak local current = start -- we could cache attributes here local startfont = start.font - local startattr = has_attribute(start,a_syllabe) + local startattr = start[a_syllabe] -- can be fast loop - while current and current.id == glyph_code and current.subtype<256 and current.font == font and has_attribute(current,a_syllabe) == startattr do + while current and current.id == glyph_code and current.subtype<256 and current.font == font and current[a_syllabe] == startattr do local next = current.next - if halant[current.char] and not has_attribute(current,a_state) then - if next and next.id == glyph_code and next.subtype<256 and next.font == font and has_attribute(next,a_syllabe) == startattr and zw_char[next.char] then + if current.char == c_halant and not current[a_state] then + if next and next.id == glyph_code and next.subtype<256 and next.font == font and next[a_syllabe] == startattr and zw_char[next.char] then current = next end local startnext = start.next - remove_node(start,start) + head = remove_node(head,start) local next = current.next if next then next.prev = start @@ -851,7 +834,7 @@ function handlers.devanagari_reorder_matras(start,kind,lookupname,replacement) - end current = next end - return start, true + return head, start, true end -- todo: way more caching of attributes and font @@ -878,22 +861,22 @@ end -- hm, this only looks at the start of a nodelist ... is this supposed to be line based? -function handlers.devanagari_reorder_reph(start,kind,lookupname,replacement) +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 = start.next local startnext = nil local startprev = nil local startfont = start.font - local startattr = has_attribute(start,a_syllabe) - while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and has_attribute(current,a_syllabe) == startattr do --step 2 - if halant[current.char] and not has_attribute(current,a_state) then + local startattr = start[a_syllabe] + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do --step 2 + if current.char == c_halant and not current[a_state] then local next = current.next - if next and next.id == glyph_code and next.subtype<256 and next.font == startfont and has_attribute(next,a_syllabe) == startattr and zw_char[next.char] then + if next and next.id == glyph_code and next.subtype<256 and next.font == startfont and next[a_syllabe] == startattr and zw_char[next.char] then current = next end startnext = start.next - remove_node(start,start) + head = remove_node(head,start) local next = current.next if next then next.prev = start @@ -902,24 +885,24 @@ function handlers.devanagari_reorder_reph(start,kind,lookupname,replacement) current.next = start start.prev = current start = startnext - startattr = has_attribute(start,a_syllabe) + startattr = start[a_syllabe] break end current = current.next end if not startnext then current = start.next - while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and has_attribute(current,a_syllabe) == startattr do --step 4 - if has_attribute(current,a_state) == 9 then --post-base + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do --step 4 + if current[a_state] == s_pstf then --post-base startnext = start.next - remove_node(start,start) + head = remove_node(head,start) local prev = current.prev start.prev = prev prev.next = start start.next = current current.prev = start start = startnext - startattr = has_attribute(start,a_syllabe) + startattr = start[a_syllabe] break end current = current.next @@ -931,7 +914,7 @@ function handlers.devanagari_reorder_reph(start,kind,lookupname,replacement) if not startnext then current = start.next local c = nil - while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and has_attribute(current,a_syllabe) == startattr do --step 5 + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do --step 5 if not c then local char = current.char -- todo: combine in one @@ -944,27 +927,28 @@ function handlers.devanagari_reorder_reph(start,kind,lookupname,replacement) -- here we can loose the old start node: maybe best split cases if c then startnext = start.next - remove_node(start,start) + head = remove_node(head,start) local prev = c.prev start.prev = prev prev.next = start start.next = c c.prev = start + -- end start = startnext - startattr = has_attribute(start,a_syllabe) + startattr = start[a_syllabe] end end -- leaks if not startnext then current = start local next = current.next - while next and next.id == glyph_code and next.subtype<256 and next.font == startfont and has_attribute(next,a_syllabe) == startattr do --step 6 + while next and next.id == glyph_code and next.subtype<256 and next.font == startfont and next[a_syllabe] == startattr do --step 6 current = next next = current.next end if start ~= current then startnext = start.next - remove_node(start,start) + head = remove_node(head,start) local next = current.next if next then next.prev = start @@ -976,7 +960,7 @@ function handlers.devanagari_reorder_reph(start,kind,lookupname,replacement) end end -- - return start, true + return head, start, true end -- we can cache some checking (v) @@ -990,19 +974,19 @@ end -- UNTESTED: NOT CALLED IN EXAMPLE -function handlers.devanagari_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement) +function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start,kind,lookupname,replacement) local current = start local startnext = nil local startprev = nil local startfont = start.font - local startattr = has_attribute(start,a_syllabe) + local startattr = start[a_syllabe] -- can be fast for loop + caching state - while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and has_attribute(current,a_syllabe) == startattr do + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do local next = current.next - if halant[current.char] and not has_attribute(current,a_state) then - if next and next.id == glyph_code and next.subtype<256 and next.font == font and has_attribute(next,a_syllabe) == startattr then + if current.char == c_halant and not current[a_state] then + if next and next.id == glyph_code and next.subtype<256 and next.font == font and next[a_syllabe] == startattr then local char = next.char - if zw_char[char] then + if char == c_zwnj or char == c_zwj then current = next end end @@ -1022,9 +1006,9 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(start,kind,l end if not startnext then current = start.next - startattr = has_attribute(start,a_syllabe) - while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and has_attribute(current,a_syllabe) == startattr do - if not consonant[current.char] and has_attribute(current,a_state) then --main + startattr = start[a_syllabe] + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do + if not consonant[current.char] and current[a_state] then --main startnext = start.next removenode(start,start) local prev = current.prev @@ -1038,15 +1022,15 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(start,kind,l current = current.next end end - return start, true + return head, start, true end -function handlers.devanagari_remove_joiners(start,kind,lookupname,replacement) +function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement) local stop = start.next local startfont = start.font while stop and stop.id == glyph_code and stop.subtype<256 and stop.font == startfont do local char = stop.char - if zw_char[char] then + if char == c_zwnj or char == c_zwj then stop = stop.next else break @@ -1061,7 +1045,7 @@ function handlers.devanagari_remove_joiners(start,kind,lookupname,replacement) prev.next = stop end flush_list(start) - return stop, true + return head, stop, true end local valid = { @@ -1174,7 +1158,7 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( current = next current = current.next elseif current == start then - set_attribute(current,a_state,5) + current[a_state] = s_rphf current = next else current = next @@ -1201,8 +1185,8 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( local next = current.next local n = locl[next] or next.char if found[n] then - set_attribute(current,a_state,7) - set_attribute(next,a_state,7) + current[a_state] = s_pref + next[a_state] = s_pref current = next end end @@ -1220,10 +1204,10 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( local next = current.next local n = locl[next] or next.char if found[n] then - if next ~= stop and zwnj[next.next.char] then --ZWNJ prevent creation of half + if next ~= stop and next.next.char == c_zwnj then --ZWNJ prevent creation of half current = current.next else - set_attribute(current,a_state,6) + current[a_state] = s_half if not halfpos then halfpos = current end @@ -1245,8 +1229,8 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( local next = current.next local n = locl[next] or next.char if found[n] then - set_attribute(current,a_state,8) - set_attribute(next,a_state,8) + current[a_state] = s_blwf + next[a_state] = s_blwf current = next subpos = current end @@ -1265,8 +1249,8 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( local next = current.next local n = locl[next] or next.char if found[n] then - set_attribute(current,a_state,9) - set_attribute(next,a_state,9) + current[a_state] = s_pstf + next[a_state] = s_pstf current = next postpos = current end @@ -1284,12 +1268,12 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( local current, base, firstcons = start, nil, nil - if has_attribute(start,a_state) == 5 then + if 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 = start.next.next end - if current ~= stop.next and nbsp[current.char] then + if current ~= stop.next and current.char == c_nbsp then -- Stand Alone cluster if current == stop then stop = stop.prev @@ -1301,26 +1285,26 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( current = current.next if current ~= stop then local char = current.char - if nukta[char] then + if char == c_nukta then current = current.next char = current.char end - if zwj[char] then + if char == c_zwj then local next = current.next - if current ~= stop and next ~= stop and halant[next.char] then + if current ~= stop and next ~= stop and next.char == c_halant then current = next next = current.next local tmp = next.next local changestop = next == stop next.next = nil - set_attribute(current,a_state,7) --pref + current[a_state] = s_pref current = processcharacters(current) - set_attribute(current,a_state,8) --blwf + current[a_state] = s_blwf current = processcharacters(current) - set_attribute(current,a_state,9) --pstf + current[a_state] = s_pstf current = processcharacters(current) - unset_attribute(current,a_state) - if halant[current.char] then + current[a_state] = unsetvalue + if current.char == c_halant then current.next.next = tmp local nc = copy_node(current) current.char = dotted_circle @@ -1340,13 +1324,13 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( while current ~= last do -- find base consonant local next = current.next if consonant[current.char] then - if not (current ~= stop and next ~= stop and halant[next.char] and zwj[next.next.char]) then + if not (current ~= stop and next ~= stop and next.char == c_halant and next.next.char == 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 = has_attribute(current,a_state) - if not (a == 7 or a == 8 or a == 9) then + local a = current[a_state] + if not (a == s_pref or a == s_blwf or a == pstf) then base = current end end @@ -1359,13 +1343,13 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( end if not base then - if has_attribute(start,a_state) == 5 then - unset_attribute(start,a_state) + if start[a_state] == s_rphf then + start[a_state] = unsetvalue end return head, stop else - if has_attribute(base,a_state) then - unset_attribute(base,a_state) + if base[a_state] then + base[a_state] = unsetvalue end basepos = base end @@ -1464,7 +1448,7 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( local current, c = start, nil while current ~= stop do local char = current.char - if halant[char] or stress_tone_mark[char] then + if char == c_halant or stress_tone_mark[char] then if not c then c = current end @@ -1472,7 +1456,7 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( c = nil end local next = current.next - if c and nukta[next.char] then + if c and next.char == c_nukta then if head == c then head = next end @@ -1497,7 +1481,7 @@ local function dev2_reorder(head,start,stop,font,attr) -- maybe do a pass over ( current = current.next end - if nbsp[base.char] then + if base.char == c_nbsp then head = remove_node(head, base) free_node(base) end @@ -1514,8 +1498,9 @@ imerge(separator,independent_vowel) imerge(separator,dependent_vowel) imerge(separator,vowel_modifier) imerge(separator,stress_tone_mark) -imerge(separator,nukta) -imerge(separator,halant) + +separator[0x093C] = true -- nukta +separator[0x094D] = true -- halant 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 @@ -1525,7 +1510,7 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe end if variant == 1 then local v = n.id == glyph_code and n.subtype<256 and n.font == font - if v and nukta[n.char] then + if v and n.char == c_nukta then n = n.next if n then v = n.id == glyph_code and n.subtype<256 and n.font == font @@ -1538,9 +1523,9 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe if nnn and nnn.id == glyph_code and nnn.subtype<256 and nnn.font == font then local nnc = nn.char local nnnc = nnn.char - if zwj[nnc] and consonant[nnnc] then + if nnc == c_zwj and consonant[nnnc] then c = nnn - elseif zw_char[nnc] and halant[nnnc] then + elseif (nnc == c_zwnj or nnc == c_zwj) and nnnc == c_halant then local nnnn = nnn.next if nnnn and nnnn.id == glyph_code and consonant[nnnn.char] and nnnn.subtype<256 and nnnn.font == font then c = nnnn @@ -1550,7 +1535,7 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe end end elseif variant == 2 then - if n.id == glyph_code and nukta[n.char] and n.subtype<256 and n.font == font then + if n.id == glyph_code and n.char == c_nukta and n.subtype<256 and n.font == font then c = n end n = c.next @@ -1563,7 +1548,7 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe nn = nn.next nv = nn.id == glyph_code and nn.subtype<256 and nn.font == font end - if nn and nv and halant[n.char] and consonant[nn.char] then + if nn and nv and n.char == c_halant and consonant[nn.char] then c = nn end end @@ -1591,7 +1576,7 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe end char = n.char end - if nukta[char] then + if char == c_nukta then c = c.next n = c.next if not n then @@ -1603,7 +1588,7 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe end char = n.char end - if halant[char] then + if char == c_halant then c = c.next n = c.next if not n then @@ -1651,7 +1636,7 @@ local function analyze_next_chars_two(c,font) if not n then return c end - if n.id == glyph_code and nukta[n.char] and n.subtype<256 and n.font == font then + if n.id == glyph_code and n.char == c_nukta and n.subtype<256 and n.font == font then c = n end n = c @@ -1659,16 +1644,16 @@ local function analyze_next_chars_two(c,font) local nn = n.next if nn and nn.id == glyph_code and nn.subtype<256 and nn.font == font then local char = nn.char - if halant[char] then + if char == c_halant then n = nn local nnn = nn.next if nnn and nnn.id == glyph_code and zw_char[nnn.char] and nnn.subtype<256 and nnn.font == font then n = nnn end - elseif zw_char[char] then + elseif char == c_zwnj or char == c_zwj then -- n = nn -- not here (?) local nnn = nn.next - if nnn and nnn.id == glyph_code and halant[nnn.char] and nnn.subtype<256 and nnn.font == font then + if nnn and nnn.id == glyph_code and nnn.char == c_halant and nnn.subtype<256 and nnn.font == font then n = nnn end else @@ -1678,7 +1663,7 @@ local function analyze_next_chars_two(c,font) if nn and nn.id == glyph_code and consonant[nn.char] and nn.subtype<256 and nn.font == font then n = nn local nnn = nn.next - if nnn and nnn.id == glyph_code and nukta[nnn.char] and nnn.subtype<256 and nnn.font == font then + if nnn and nnn.id == glyph_code and nnn.char == c_nukta and nnn.subtype<256 and nnn.font == font then n = nnn end c = n @@ -1703,7 +1688,7 @@ local function analyze_next_chars_two(c,font) return c end local char = n.char - if anudatta[char] then + if char == c_anudatta then c = n n = c.next if not n then @@ -1715,7 +1700,7 @@ local function analyze_next_chars_two(c,font) end char = n.char end - if halant[char] then + if char == c_halant then c = c.next n = c.next if not n then @@ -1726,7 +1711,7 @@ local function analyze_next_chars_two(c,font) return c end char = n.char - if zw_char[char] then + if char == c_zwnj or char == c_zwj then c = c.next n = c.next if not n then @@ -1753,7 +1738,7 @@ local function analyze_next_chars_two(c,font) end char = n.char end - if nukta[char] then + if char == c_nukta then c = c.next n = c.next if not n then @@ -1765,7 +1750,7 @@ local function analyze_next_chars_two(c,font) end char = n.char end - if halant[char] then + if char == c_halant then c = c.next n = c.next if not n then @@ -1832,13 +1817,13 @@ function methods.deva(head,font,attr) local syllableend = nil local c = current local n = c.next - if n and ra[c.char] and n.id == glyph_code and halant[n.char] and n.subtype<256 and n.font == font then + if n and c.char == c_ra and n.id == glyph_code and n.char == c_halant and n.subtype<256 and n.font == font then local n = n.next if n and n.id == glyph_code and n.subtype<256 and n.font == font then c = n end end - local standalone = nbsp[c.char] + local standalone = c.char == c_nbsp if standalone then local prev = current.prev if not prev then @@ -1859,7 +1844,7 @@ function methods.deva(head,font,attr) current = current.next end else - -- we can delay the n.subtype and n.font and test for say halant[c] first + -- we can delay the n.subtype and n.font 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 = current.char @@ -1877,7 +1862,7 @@ function methods.deva(head,font,attr) break end local c = n.char - if nukta[c] then + if c == c_nukta then n = n.next if not n then break @@ -1888,7 +1873,7 @@ function methods.deva(head,font,attr) end c = n.char end - if halant[c] then + if c == c_halant then n = n.next if not n then break @@ -1898,7 +1883,7 @@ function methods.deva(head,font,attr) break end c = n.char - if zw_char[c] then + if c == c_zwnj or c == c_zwj then n = n.next if not n then break @@ -1916,7 +1901,7 @@ function methods.deva(head,font,attr) end end local n = current.next - if n and n.id == glyph_code and nukta[n.char] and n.subtype<256 and n.font == font then + if n and n.id == glyph_code and n.char == c_nukta and n.subtype<256 and n.font == font then -- nukta (not specified in Microsft Devanagari OpenType specification) current = n n = current.next @@ -1926,7 +1911,7 @@ function methods.deva(head,font,attr) if current then local v = current.id == glyph_code and current.subtype<256 and current.font == font if v then - if halant[current.char] then + if current.char == c_halant then -- syllable containing consonant without vowels: {C + [Nukta] + H} + C + H local n = current.next if n and n.id == glyph_code and zw_char[n.char] and n.subtype<256 and n.font == font then @@ -2009,7 +1994,7 @@ 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(start,kind,lookupname,lookupmatch,sequence,lookuphash,1) +-- handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1) function methods.dev2(head,font,attr) local current = head @@ -2023,7 +2008,7 @@ function methods.dev2(head,font,attr) syllablestart = current local c = current local n = current.next - if n and ra[c.char] and n.id == glyph_code and halant[n.char] and n.subtype<256 and n.font == font then + if n and c.char == c_ra and n.id == glyph_code and n.char == c_halant and n.subtype<256 and n.font == font then local n = n.next if n and n.id == glyph_code and n.subtype<256 and n.font == font then c = n @@ -2035,7 +2020,7 @@ function methods.dev2(head,font,attr) current = analyze_next_chars_one(c,font,1) syllableend = current else - local standalone = nbsp[char] + local standalone = char == c_nbsp if standalone then local p = current.prev if not p then @@ -2066,14 +2051,14 @@ function methods.dev2(head,font,attr) local c = syllablestart local n = syllableend.next while c ~= n do - set_attribute(c,a_syllabe,syllabe) + c[a_syllabe] = syllabe 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 current.id == glyph_code and current.subtype<256 and current.font == font and not has_attribute(current,a_state) then + if not syllableend and current.id == glyph_code and current.subtype<256 and current.font == font and not current[a_state] then local mark = mark_four[current.char] if mark then head, current = inject_syntax_error(head,current,mark) @@ -2085,961 +2070,3 @@ function methods.dev2(head,font,attr) return head, done end - --- Temporary checker: - -if false then -- when true we can see how much nodes bleed - - local function check(what,action,head,kind,lookupname,replacement) - local n_before = nodes.count(head) - local s_before = nodes.listtoutf(head) - local head, done = action(head,kind,lookupname,replacement) - local n_after = nodes.count(head) - local s_after = nodes.listtoutf(head) - if n_before ~= n_after then - print("leak",what) - print(n_before,s_before) - print(n_after,s_after) - end - return head, done - end - - local devanagari_reorder_matras = handlers.devanagari_reorder_matras - local devanagari_reorder_reph = handlers.devanagari_reorder_reph - local devanagari_reorder_pre_base_reordering_consonants = handlers.devanagari_reorder_pre_base_reordering_consonants - local devanagari_remove_joiners = handlers.devanagari_remove_joiners - - function handlers.devanagari_reorder_matras(start,kind,lookupname,replacement) - if trace then - return check("matras",devanagari_reorder_matras,start,kind,lookupname,replacement) - else - return devanagari_reorder_matras(start,kind,lookupname,replacement) - end - end - - function handlers.devanagari_reorder_reph(start,kind,lookupname,replacement) - if trace then - return check("reph",devanagari_reorder_reph,start,kind,lookupname,replacement) - else - return devanagari_reorder_reph(start,kind,lookupname,replacement) - end - end - - function handlers.devanagari_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement) - if trace then - return check("consonants",devanagari_reorder_pre_base_reordering_consonants,start,kind,lookupname,replacement) - else - return devanagari_reorder_pre_base_reordering_consonants(start,kind,lookupname,replacement) - end - end - - function handlers.devanagari_remove_joiners(start,kind,lookupname,replacement) - if trace then - return check("joiners",devanagari_remove_joiners,start,kind,lookupname,replacement) - else - return devanagari_remove_joiners(start,kind,lookupname,replacement) - end - end - -end - --- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --- 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). -- --- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - --- 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]+[<[]+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]+[<[]+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]+[<[]+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>} + C+[N]+[A] + [< H+[] | {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/font-ota.lua b/tex/context/base/font-ota.lua index 11615ea8b..61081cb9b 100644 --- a/tex/context/base/font-ota.lua +++ b/tex/context/base/font-ota.lua @@ -28,16 +28,17 @@ analyzers.initializers = initializers analyzers.methods = methods analyzers.useunicodemarks = false +local a_state = attributes.private('state') + local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph +local math_code = nodecodes.math -local set_attribute = node.set_attribute -local has_attribute = node.has_attribute local traverse_id = node.traverse_id local traverse_node_list = node.traverse +local endofmath = nodes.endofmath local fontdata = fonts.hashes.identifiers -local state = attributes.private('state') local categories = characters and characters.categories or { } -- sorry, only in context local otffeatures = fonts.constructors.newfeatures("otf") @@ -48,19 +49,40 @@ local registerotffeature = otffeatures.register process features right.

--ldx]]-- -analyzers.constants = { - init = 1, - medi = 2, - fina = 3, - isol = 4, - -- devanagari - rphf = 5, - half = 6, - pref = 7, - blwf = 8, - pstf = 9, +-- never use these numbers directly + +local s_init = 1 local s_rphf = 7 +local s_medi = 2 local s_half = 8 +local s_fina = 3 local s_pref = 9 +local s_isol = 4 local s_blwf = 10 +local s_mark = 5 local s_pstf = 11 +local s_rest = 6 + +local states = { + init = s_init, + medi = s_medi, + fina = s_fina, + isol = s_isol, + mark = s_mark, + rest = s_rest, + rphf = s_rphf, + half = s_half, + pref = s_pref, + blwf = s_blwf, + pstf = s_pstf, +} + +local features = { + init = s_init, + medi = s_medi, + fina = s_fina, + isol = s_isol, + -- mark = s_mark, } +analyzers.states = states +analyzers.features = features + -- todo: analyzers per script/lang, cross font, so we need an font id hash -> script -- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace @@ -78,40 +100,42 @@ function analyzers.setstate(head,font) if d then if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then done = true - set_attribute(current,state,5) -- mark + current[a_state] = s_mark elseif n == 0 then first, last, n = current, current, 1 - set_attribute(current,state,1) -- init + current[a_state] = s_init else last, n = current, n+1 - set_attribute(current,state,2) -- medi + current[a_state] = s_medi end else -- finish if first and first == last then - set_attribute(last,state,4) -- isol + last[a_state] = s_isol elseif last then - set_attribute(last,state,3) -- fina + last[a_state] = s_fina end first, last, n = nil, nil, 0 end elseif id == disc_code then -- always in the middle - set_attribute(current,state,2) -- midi + current[a_state] = s_midi last = current else -- finish if first and first == last then - set_attribute(last,state,4) -- isol + last[a_state] = s_isol elseif last then - set_attribute(last,state,3) -- fina + last[a_state] = s_fina end first, last, n = nil, nil, 0 +-- elseif id == math_code then +-- current = endofmath(current) end current = current.next end if first and first == last then - set_attribute(last,state,4) -- isol + last[a_state] = s_isol elseif last then - set_attribute(last,state,3) -- fina + last[a_state] = s_fina end return head, done end @@ -273,19 +297,19 @@ local function finish(first,last) if first == last then local fc = first.char if isol_fina_medi_init[fc] or isol_fina[fc] then - set_attribute(first,state,4) -- isol + first[a_state] = s_isol else warning(first,"isol") - set_attribute(first,state,0) -- error + first[a_state] = s_error end else local lc = last.char if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ? -- if laststate == 1 or laststate == 2 or laststate == 4 then - set_attribute(last,state,3) -- fina + last[a_state] = s_fina else warning(last,"fina") - set_attribute(last,state,0) -- error + last[a_state] = s_error end end first, last = nil, nil @@ -293,10 +317,10 @@ local function finish(first,last) -- first and last are either both set so we never com here local fc = first.char if isol_fina_medi_init[fc] or isol_fina[fc] then - set_attribute(first,state,4) -- isol + first[a_state] = s_isol else warning(first,"isol") - set_attribute(first,state,0) -- error + first[a_state] = s_error end first = nil end @@ -309,43 +333,45 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr local marks = tfmdata.resources.marks local first, last, current, done = nil, nil, head, false while current do - if current.id == glyph_code and current.font == font and current.subtype<256 and not has_attribute(current,state) then + if current.id == glyph_code and current.font == font and current.subtype<256 and not current[a_state] then done = true local char = current.char if marks[char] or (useunicodemarks and categories[char] == "mn") then - set_attribute(current,state,5) -- mark + current[a_state] = s_mark elseif isol[char] then -- can be zwj or zwnj too first, last = finish(first,last) - set_attribute(current,state,4) -- isol + current[a_state] = s_isol first, last = nil, nil elseif not first then if isol_fina_medi_init[char] then - set_attribute(current,state,1) -- init + current[a_state] = s_init first, last = first or current, current elseif isol_fina[char] then - set_attribute(current,state,4) -- isol + current[a_state] = s_isol first, last = nil, nil else -- no arab first, last = finish(first,last) end elseif isol_fina_medi_init[char] then first, last = first or current, current - set_attribute(current,state,2) -- medi + current[a_state] = s_medi elseif isol_fina[char] then - if not has_attribute(last,state,1) then + if not last[a_state] == s_init then -- tricky, we need to check what last may be ! - set_attribute(last,state,2) -- medi + last[a_state] = s_medi end - set_attribute(current,state,3) -- fina + current[a_state] = s_fina first, last = nil, nil elseif char >= 0x0600 and char <= 0x06FF then - set_attribute(current,state,6) -- rest + current[a_state] = s_rest first, last = finish(first,last) else --no first, last = finish(first,last) end else first, last = finish(first,last) +-- elseif id == math_code then +-- current = endofmath(current).next end current = current.next end diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua index 89f84804c..cedc66a72 100644 --- a/tex/context/base/font-otd.lua +++ b/tex/context/base/font-otd.lua @@ -116,7 +116,7 @@ end -- we reimplement the dataset resolver -local constants = fonts.analyzers.constants +local autofeatures = fonts.analyzers.features -- was: constants local resolved = { } -- we only resolve a font,script,language,attribute pair once local wildcard = "*" @@ -147,7 +147,7 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr what = wildcard end if valid then - local attribute = constants[kind] or false + local attribute = autofeatures[kind] or false if a_e and dynamic < 0 then valid = false end diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua index 5cf1423ea..cfdbdbaca 100644 --- a/tex/context/base/font-otn.lua +++ b/tex/context/base/font-otn.lua @@ -173,10 +173,10 @@ local insert_node_after = node.insert_after local delete_node = nodes.delete local copy_node = node.copy local find_node_tail = node.tail or node.slide -local set_attribute = node.set_attribute -local has_attribute = node.has_attribute local flush_node_list = node.flush_list +local endofmath = nodes.endofmath + local setmetatableindex = table.setmetatableindex local zwnj = 0x200C @@ -192,6 +192,7 @@ local glyph_code = nodecodes.glyph local glue_code = nodecodes.glue local disc_code = nodecodes.disc local whatsit_code = nodecodes.whatsit +local math_code = nodecodes.math local dir_code = whatcodes.dir local localpar_code = whatcodes.localpar @@ -206,15 +207,15 @@ local privateattribute = attributes.private -- more complex than an average font) but I need proper examples of all cases, not -- of only some. -local state = privateattribute('state') -local markbase = privateattribute('markbase') -local markmark = privateattribute('markmark') -local markdone = privateattribute('markdone') -- assigned at the injection end -local cursbase = privateattribute('cursbase') -local curscurs = privateattribute('curscurs') -local cursdone = privateattribute('cursdone') -local kernpair = privateattribute('kernpair') -local ligacomp = privateattribute('ligacomp') -- assigned here (ideally it should be combined) +local a_state = privateattribute('state') +local a_markbase = privateattribute('markbase') +local a_markmark = privateattribute('markmark') +local a_markdone = privateattribute('markdone') -- assigned at the injection end +local a_cursbase = privateattribute('cursbase') +local a_curscurs = privateattribute('curscurs') +local a_cursdone = privateattribute('cursdone') +local a_kernpair = privateattribute('kernpair') +local a_ligacomp = privateattribute('ligacomp') -- assigned here (ideally it should be combined) local injections = nodes.injections local setmark = injections.setmark @@ -236,8 +237,7 @@ local onetimemessage = fonts.loggers.onetimemessage otf.defaultnodealternate = "none" -- first last --- we share some vars here, after all, we have no nested lookups and --- less code +-- we share some vars here, after all, we have no nested lookups and less code local tfmdata = false local characters = false @@ -337,35 +337,18 @@ end -- start is a mark and we need to keep that one --- local function markstoligature(kind,lookupname,start,stop,char) --- -- [start]..[stop] --- local keep = start --- local prev = start.prev --- local next = stop.next --- local base = copy_glyph(start) --- local current, start = insert_node_after(start,start,base) --- -- [current][start]..[stop] --- current.next = next --- if next then --- next.prev = current --- end --- start.prev = nil --- stop.next = nil --- current.char = char --- current.subtype = ligature_code --- current.components = start --- return keep --- end - -local function markstoligature(kind,lookupname,start,stop,char) +local function markstoligature(kind,lookupname,head,start,stop,char) if start == stop and start.char == char then - return start + return head, start else local prev = start.prev local next = stop.next start.prev = nil stop.next = nil local base = copy_glyph(start) + if head == start then + head = base + end base.char = char base.subtype = ligature_code base.components = start @@ -377,7 +360,7 @@ local function markstoligature(kind,lookupname,start,stop,char) end base.next = next base.prev = prev - return base + return head, base end end @@ -406,16 +389,19 @@ local function getcomponentindex(start) end end -local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head +local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) -- brr head if start == stop and start.char == char then start.char = char - return start + return head, start end local prev = start.prev local next = stop.next start.prev = nil stop.next = nil local base = copy_glyph(start) + if start == head then + head = base + end base.char = char base.subtype = ligature_code base.components = start -- start can have components @@ -440,9 +426,9 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- baseindex = baseindex + componentindex componentindex = getcomponentindex(start) elseif not deletemarks then -- quite fishy - set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) + start[a_ligacomp] = baseindex + (start[a_ligacomp] or componentindex) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) end head, current = insert_node_after(head,current,copy_node(start)) -- unlikely that mark has components end @@ -452,9 +438,9 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- while start and start.id == glyph_code do -- hm, is id test needed ? local char = start.char if marks[char] then - set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex)) + start[a_ligacomp] = baseindex + (start[a_ligacomp] or componentindex) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp)) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) end else break @@ -462,15 +448,15 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- start = start.next end end - return base + return head, base end -function handlers.gsub_single(start,kind,lookupname,replacement) +function handlers.gsub_single(head,start,kind,lookupname,replacement) if trace_singles then logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement)) end start.char = replacement - return start, true + return head, start, true end local function get_alternative_glyph(start,alternatives,value) @@ -510,7 +496,7 @@ local function get_alternative_glyph(start,alternatives,value) return choice end -local function multiple_glyphs(start,multiple) -- marks ? +local function multiple_glyphs(head,start,multiple) -- marks ? local nofmultiples = #multiple if nofmultiples > 0 then start.char = multiple[1] @@ -528,16 +514,16 @@ local function multiple_glyphs(start,multiple) -- marks ? start = n end end - return start, true + return head, start, true else if trace_multiples then logprocess("no multiple for %s",gref(start.char)) end - return start, false + return head, start, false end end -function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence) +function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence) local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue local choice = get_alternative_glyph(start,alternative,value) if choice then @@ -550,17 +536,17 @@ function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence) logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(start.char)) end end - return start, true + return head, start, true end -function handlers.gsub_multiple(start,kind,lookupname,multiple) +function handlers.gsub_multiple(head,start,kind,lookupname,multiple) if trace_multiples then logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple)) end - return multiple_glyphs(start,multiple) + return multiple_glyphs(head,start,multiple) end -function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) +function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) local s, stop, discfound = start.next, nil, false local startchar = start.char if marks[startchar] then @@ -584,12 +570,12 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) if lig then if trace_ligatures then local stopchar = stop.char - start = markstoligature(kind,lookupname,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + head, start = markstoligature(kind,lookupname,start,stop,lig) + logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) else - start = markstoligature(kind,lookupname,start,stop,lig) + head, start = markstoligature(kind,lookupname,start,stop,lig) end - return start, true + return head, start, true else -- ok, goto next lookup end @@ -628,18 +614,18 @@ function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence) if lig then if trace_ligatures then local stopchar = stop.char - start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + 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(start.char)) else - start = toligature(kind,lookupname,start,stop,lig,skipmark,discfound) + head, start = toligature(kind,lookupname,head, start,stop,lig,skipmark,discfound) end - return start, true + return head, start, true else -- ok, goto next lookup end end end - return start, false + return head, start, false end --[[ldx-- @@ -647,7 +633,7 @@ end we need to explicitly test for basechar, baselig and basemark entries.

--ldx]]-- -function handlers.gpos_mark2base(start,kind,lookupname,markanchors,sequence) +function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence) local markchar = start.char if marks[markchar] then local base = start.prev -- [glyph] [start=mark] @@ -665,7 +651,7 @@ function handlers.gpos_mark2base(start,kind,lookupname,markanchors,sequence) if trace_bugs then logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar)) end - return start, false + return head, start, false end end end @@ -686,7 +672,7 @@ function handlers.gpos_mark2base(start,kind,lookupname,markanchors,sequence) logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%s,%s)", pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) end - return start, true + return head, start, true end end end @@ -704,10 +690,10 @@ function handlers.gpos_mark2base(start,kind,lookupname,markanchors,sequence) elseif trace_bugs then logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar)) end - return start, false + return head, start, false end -function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence) +function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence) -- check chainpos variant local markchar = start.char if marks[markchar] then @@ -726,11 +712,11 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence) if trace_bugs then logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar)) end - return start, false + return head, start, false end end end - local index = has_attribute(start,ligacomp) + local index = start[a_ligacomp] local baseanchors = descriptions[basechar] if baseanchors then baseanchors = baseanchors.anchors @@ -749,7 +735,7 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence) logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)", pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy) end - return start, true + return head, start, true end end end @@ -769,17 +755,17 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence) elseif trace_bugs then logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar)) end - return start, false + return head, start, false end -function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence) +function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence) local markchar = start.char if marks[markchar] then local base = start.prev -- [glyph] [basemark] [start=mark] - local slc = has_attribute(start,ligacomp) + local slc = start[a_ligacomp] if slc then -- a rather messy loop ... needs checking with husayni while base do - local blc = has_attribute(base,ligacomp) + local blc = base[a_ligacomp] if blc and blc ~= slc then base = base.prev else @@ -805,7 +791,7 @@ function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence) logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)", pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) end - return start,true + return head, start, true end end end @@ -824,11 +810,11 @@ function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence) elseif trace_bugs then logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar)) end - return start,false + return head, start, false end -function handlers.gpos_cursive(start,kind,lookupname,exitanchors,sequence) -- to be checked - local alreadydone = cursonce and has_attribute(start,cursbase) +function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) -- to be checked + local alreadydone = cursonce and start[a_cursbase] if not alreadydone then local done = false local startchar = start.char @@ -874,30 +860,30 @@ function handlers.gpos_cursive(start,kind,lookupname,exitanchors,sequence) -- to end end end - return start, done + return head, start, done else if trace_cursive and trace_details then logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) end - return start, false + return head, start, false end end -function handlers.gpos_single(start,kind,lookupname,kerns,sequence) +function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence) local startchar = start.char 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 (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),dx,dy,w,h) end - return start, false + return head, start, false end -function handlers.gpos_pair(start,kind,lookupname,kerns,sequence) +function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too -- todo: kerns in components of ligatures local snext = start.next if not snext then - return start, false + return head, start, false else local prev, done = start, false local factor = tfmdata.parameters.factor @@ -953,7 +939,7 @@ function handlers.gpos_pair(start,kind,lookupname,kerns,sequence) break end end - return start, done + return head, start, done end end @@ -986,21 +972,21 @@ 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(start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname) +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 start, false + return head, start, false end -function chainmores.chainsub(start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n) +function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n) logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname)) - return start, false + 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(start,stop,kind,chainname,currentcontext,lookuphash,replacements) +function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements) local char = start.char local replacement = replacements[char] if replacement then @@ -1008,9 +994,9 @@ function chainprocs.reversesub(start,stop,kind,chainname,currentcontext,lookupha logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement)) end start.char = replacement - return start, true + return head, start, true else - return start, false + return head, start, false end end @@ -1038,10 +1024,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start repeat -- start x x m x x stop => start m local next = start.next if not marks[next.char] then -local components = next.components -if components then -- probably not needed - flush_node_list(components) -end + local components = next.components + if components then -- probably not needed + flush_node_list(components) + end delete_node(start,next) end n = n + 1 @@ -1049,10 +1035,10 @@ end else -- start x x x stop => start repeat local next = start.next -local components = next.components -if components then -- probably not needed - flush_node_list(components) -end + local components = next.components + if components then -- probably not needed + flush_node_list(components) + end delete_node(start,next) n = n + 1 until next == stop @@ -1065,7 +1051,7 @@ end match.

--ldx]]-- -function chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex) +function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex) -- todo: marks ? local current = start local subtables = currentlookup.subtables @@ -1094,14 +1080,14 @@ function chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,lookuph current.char = replacement end end - return start, true + return head, start, true elseif current == stop then break else current = current.next end end - return start, false + return head, start, false end chainmores.gsub_single = chainprocs.gsub_single @@ -1111,7 +1097,7 @@ chainmores.gsub_single = chainprocs.gsub_single the match.

--ldx]]-- -function chainprocs.gsub_multiple(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) +function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) delete_till_stop(start,stop) -- we could pass ignoremarks as #3 .. local startchar = start.char local subtables = currentlookup.subtables @@ -1123,7 +1109,7 @@ function chainprocs.gsub_multiple(start,stop,kind,chainname,currentcontext,looku end else replacements = replacements[startchar] - if not replacements then + if not replacements or replacement == "" then if trace_bugs then logwarning("%s: no multiple for %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar)) end @@ -1131,17 +1117,12 @@ function chainprocs.gsub_multiple(start,stop,kind,chainname,currentcontext,looku 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(start,replacements) + return multiple_glyphs(head,start,replacements) end end - return start, false + return head, start, false end --- function chainmores.gsub_multiple(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n) --- logprocess("%s: gsub_multiple not yet supported",cref(kind,chainname,chainlookupname)) --- return start, false --- end - chainmores.gsub_multiple = chainprocs.gsub_multiple --[[ldx-- @@ -1156,7 +1137,7 @@ chainmores.gsub_multiple = chainprocs.gsub_multiple -- marks come last anyway -- are there cases where we need to delete the mark -function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) +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 @@ -1187,21 +1168,16 @@ function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,look logwarning("%s: no alternative for %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar)) end end - return start, true + return head, start, true elseif current == stop then break else current = current.next end end - return start, false + return head, start, false end --- function chainmores.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n) --- logprocess("%s: gsub_alternate not yet supported",cref(kind,chainname,chainlookupname)) --- return start, false --- end - chainmores.gsub_alternate = chainprocs.gsub_alternate --[[ldx-- @@ -1210,7 +1186,7 @@ this function (move code inline and handle the marks by a separate function). We assume rather stupid ligatures (no complex disc nodes).

--ldx]]-- -function chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex) +function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex) local startchar = start.char local subtables = currentlookup.subtables local lookupname = subtables[1] @@ -1262,13 +1238,13 @@ function chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,looku end if trace_ligatures then if start == stop then - logprocess("%s: replacing character %s by ligature %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2)) + 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",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2)) + logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2)) end end - start = toligature(kind,lookupname,start,stop,l2,currentlookup.flags[1],discfound) - return start, true, nofreplacements + head, start = toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound) + return head, start, true, nofreplacements elseif trace_bugs then if start == stop then logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) @@ -1278,12 +1254,12 @@ function chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,looku end end end - return start, false, 0 + return head, start, false, 0 end chainmores.gsub_ligature = chainprocs.gsub_ligature -function chainprocs.gpos_mark2base(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) +function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) local markchar = start.char if marks[markchar] then local subtables = currentlookup.subtables @@ -1308,7 +1284,7 @@ function chainprocs.gpos_mark2base(start,stop,kind,chainname,currentcontext,look if trace_bugs then logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar)) end - return start, false + return head, start, false end end end @@ -1326,7 +1302,7 @@ function chainprocs.gpos_mark2base(start,stop,kind,chainname,currentcontext,look logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%s,%s)", cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) end - return start, true + return head, start, true end end end @@ -1344,10 +1320,10 @@ function chainprocs.gpos_mark2base(start,stop,kind,chainname,currentcontext,look elseif trace_bugs then logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar)) end - return start, false + return head, start, false end -function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) +function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) local markchar = start.char if marks[markchar] then local subtables = currentlookup.subtables @@ -1372,12 +1348,12 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext, if trace_bugs then logwarning("%s: no base for mark %s",cref(kind,chainname,chainlookupname,lookupname),markchar) end - return start, false + return head, start, false end end end -- todo: like marks a ligatures hash - local index = has_attribute(start,ligacomp) + local index = start[a_ligacomp] local baseanchors = descriptions[basechar].anchors if baseanchors then local baseanchors = baseanchors['baselig'] @@ -1394,7 +1370,7 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext, logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)", cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy) end - return start, true + return head, start, true end end end @@ -1413,13 +1389,13 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext, elseif trace_bugs then logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar)) end - return start, false + return head, start, false end -function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) +function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) local markchar = start.char if marks[markchar] then ---~ local alreadydone = markonce and has_attribute(start,markmark) +--~ local alreadydone = markonce and start[a_markmark] --~ if not alreadydone then -- local markanchors = descriptions[markchar].anchors markanchors = markanchors and markanchors.mark local subtables = currentlookup.subtables @@ -1430,10 +1406,10 @@ function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,look end if markanchors then local base = start.prev -- [glyph] [basemark] [start=mark] - local slc = has_attribute(start,ligacomp) + local slc = start[a_ligacomp] if slc then -- a rather messy loop ... needs checking with husayni while base do - local blc = has_attribute(base,ligacomp) + local blc = base[a_ligacomp] if blc and blc ~= slc then base = base.prev else @@ -1457,7 +1433,7 @@ function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,look logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)", cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) end - return start, true + return head, start, true end end end @@ -1478,13 +1454,11 @@ function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,look elseif trace_bugs then logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar)) end - return start, false + return head, start, false end --- ! ! ! untested ! ! ! - -function chainprocs.gpos_cursive(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local alreadydone = cursonce and has_attribute(start,cursbase) +function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) + local alreadydone = cursonce and start[a_cursbase] if not alreadydone then local startchar = start.char local subtables = currentlookup.subtables @@ -1537,18 +1511,18 @@ function chainprocs.gpos_cursive(start,stop,kind,chainname,currentcontext,lookup end end end - return start, done + return head, start, done else if trace_cursive and trace_details then logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) end - return start, false + return head, start, false end end - return start, false + return head, start, false end -function chainprocs.gpos_single(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) +function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) -- untested .. needs checking for the new model local startchar = start.char local subtables = currentlookup.subtables @@ -1563,12 +1537,12 @@ function chainprocs.gpos_single(start,stop,kind,chainname,currentcontext,lookuph end end end - return start, false + return head, start, false end -- when machines become faster i will make a shared function -function chainprocs.gpos_pair(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) +function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) -- logwarning("%s: gpos_pair not yet supported",cref(kind,chainname,chainlookupname)) local snext = start.next if snext then @@ -1632,11 +1606,11 @@ function chainprocs.gpos_pair(start,stop,kind,chainname,currentcontext,lookuphas break end end - return start, done + return head, start, done end end end - return start, false + return head, start, false end -- what pointer to return, spec says stop @@ -1655,7 +1629,7 @@ local function show_skip(kind,chainname,char,ck,class) end end -local function normal_handle_contextchain(start,kind,chainname,contexts,sequence,lookuphash) +local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash) -- local rule, lookuptype, sequence, f, l, lookups = ck[1], ck[2] ,ck[3], ck[4], ck[5], ck[6] local flags = sequence.flags local done = false @@ -1881,7 +1855,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence if chainlookup then local cp = chainprocs[chainlookup.type] if cp then - start, done = cp(start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence) + head, start, done = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence) else logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type) end @@ -1912,7 +1886,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence local cp = chainlookup and chainmores[chainlookup.type] if cp then local ok, n - start, ok, n = cp(start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence) + head, start, ok, n = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence) -- messy since last can be changed ! if ok then done = true @@ -1932,7 +1906,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence else local replacements = ck[7] if replacements then - start, done = chainprocs.reversesub(start,last,kind,chainname,ck,lookuphash,replacements) -- sequence + head, start, done = chainprocs.reversesub(head,start,last,kind,chainname,ck,lookuphash,replacements) -- sequence else done = true -- can be meant to be skipped if trace_contexts then @@ -1942,7 +1916,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence end end end - return start, done + return head, start, done end -- Because we want to keep this elsewhere (an because speed is less an issue) we @@ -1955,7 +1929,7 @@ local verbose_handle_contextchain = function(font,...) end otf.chainhandlers = { - normal = normal_handle_contextchain, + normal = normal_handle_contextchain, verbose = verbose_handle_contextchain, } @@ -2018,7 +1992,7 @@ end) -- fonts.hashes.lookups = lookuphashes -local constants = fonts.analyzers.constants +local autofeatures = fonts.analyzers.features -- was: constants local function initialize(sequence,script,language,enabled) local features = sequence.features @@ -2028,7 +2002,7 @@ local function initialize(sequence,script,language,enabled) if valid then local languages = scripts[script] or scripts[wildcard] if languages and (languages[language] or languages[wildcard]) then - return { valid, constants[kind] or false, sequence.chain or 0, kind, sequence } + return { valid, autofeatures[kind] or false, sequence.chain or 0, kind, sequence } end end end @@ -2149,7 +2123,7 @@ local function featuresprocessor(head,font,attr) local id = start.id if id == glyph_code then if start.font == font and start.subtype<256 then - local a = has_attribute(start,0) + local a = start[0] if a then a = a == attr else @@ -2162,12 +2136,8 @@ local function featuresprocessor(head,font,attr) if lookupcache then local lookupmatch = lookupcache[start.char] if lookupmatch then - -- local headnode = start == head - start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) + head, start, success = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if success then - -- if headnode then - -- head = start - -- end break end end @@ -2201,30 +2171,28 @@ local function featuresprocessor(head,font,attr) local id = start.id if id == glyph_code then if start.font == font and start.subtype<256 then - local a = has_attribute(start,0) + local a = start[0] if a then - a = (a == attr) and (not attribute or has_attribute(start,state,attribute)) + a = (a == attr) and (not attribute or start[a_state] == attribute) else - a = not attribute or has_attribute(start,state,attribute) + a = not attribute or start[a_state] == attribute end if a then local lookupmatch = lookupcache[start.char] if lookupmatch then -- sequence kan weg - -- local headnode = start == head local ok - start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) + head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) if ok then success = true - -- if headnode then - -- head = start - -- end end end if start then start = start.next end else start = start.next end +elseif id == math_code then + start = endofmath(start).next else start = start.next end @@ -2264,6 +2232,8 @@ local function featuresprocessor(head,font,attr) end end start = start.next +elseif id == math_code then + start = endofmath(start).next else start = start.next end @@ -2274,11 +2244,11 @@ local function featuresprocessor(head,font,attr) local id = start.id if id == glyph_code then if start.font == font and start.subtype<256 then - local a = has_attribute(start,0) + local a = start[0] if a then - a = (a == attr) and (not attribute or has_attribute(start,state,attribute)) + a = (a == attr) and (not attribute or start[a_state] == attribute) else - a = not attribute or has_attribute(start,state,attribute) + a = not attribute or start[a_state] == attribute end if a then for i=1,ns do @@ -2288,14 +2258,10 @@ local function featuresprocessor(head,font,attr) local lookupmatch = lookupcache[start.char] if lookupmatch then -- we could move all code inline but that makes things even more unreadable - -- local headnode = start == head local ok - start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) + head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if ok then success = true - -- if headnode then - -- head = start - -- end break end end @@ -2346,6 +2312,8 @@ local function featuresprocessor(head,font,attr) end end start = start.next +elseif id == math_code then + start = endofmath(start).next else start = start.next end @@ -2622,6 +2590,6 @@ registerotffeature { } } --- this will change but is needed for an experiment: +-- This can be used for extra handlers, but should be used with care! otf.handlers = handlers diff --git a/tex/context/base/font-sol.lua b/tex/context/base/font-sol.lua index b44594349..874a485cc 100644 --- a/tex/context/base/font-sol.lua +++ b/tex/context/base/font-sol.lua @@ -51,8 +51,6 @@ local settings_to_hash = utilities.parsers.settings_to_hash local find_node_tail = node.tail or node.slide local free_node = node.free local free_nodelist = node.flush_list -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute local copy_nodelist = node.copy_list local traverse_nodes = node.traverse local traverse_ids = node.traverse_id @@ -334,7 +332,7 @@ function splitters.split(head) else local current = start while true do - set_attribute(current,a_word,n) + current[a_word] = n if current == stop then break else @@ -370,7 +368,7 @@ function splitters.split(head) local id = current.id if id == glyph_code then if current.subtype < 256 then - local a = has_attribute(current,a_split) + local a = current[a_split] if not a then start, stop = nil, nil elseif not start then @@ -440,7 +438,7 @@ local function collect_words(list) -- can be made faster for attributes -- todo: disc and kern local id = current.id if id == glyph_code or id == disc_code then - local a = has_attribute(current,a_word) + local a = current[a_word] if a then if a == index then -- same word @@ -473,7 +471,7 @@ local function collect_words(list) -- can be made faster for attributes report_splitters("skipped: %s",utfchar(current.char)) end end - elseif id == kern_code and (current.subtype == fontkern_code or has_attribute(current,a_fontkern)) then + elseif id == kern_code and (current.subtype == fontkern_code or current[a_fontkern]) then if first then last = current else @@ -557,17 +555,17 @@ local function doit(word,list,best,width,badness,line,set,listdir) local first = copy_nodelist(original) if not trace_colors then for n in traverse_nodes(first) do -- maybe fast force so no attr needed - set_attribute(n,0,featurenumber) -- this forces dynamics + n[0] = featurenumber -- this forces dynamics end elseif set == "less" then for n in traverse_nodes(first) do setnodecolor(n,"font:isol") -- yellow - set_attribute(n,0,featurenumber) + n[0] = featurenumber end else for n in traverse_nodes(first) do setnodecolor(n,"font:medi") -- green - set_attribute(n,0,featurenumber) + n[0] = featurenumber end end local font = found.font diff --git a/tex/context/base/l-boolean.lua b/tex/context/base/l-boolean.lua index 2b94de76b..f087f1a4c 100644 --- a/tex/context/base/l-boolean.lua +++ b/tex/context/base/l-boolean.lua @@ -15,7 +15,7 @@ function boolean.tonumber(b) if b then return 1 else return 0 end -- test and return or return end -function toboolean(str,tolerant) +function toboolean(str,tolerant) -- global if str == nil then return false elseif str == false then @@ -40,18 +40,16 @@ end string.toboolean = toboolean function string.booleanstring(str) - if str == nil then - return false - elseif str == false then + if str == "0" then return false - elseif str == true then - return true - elseif str == "true" then + elseif str == "1" then return true - elseif str == "false" then + elseif str == "" then return false - elseif str == 0 then + elseif str == "false" then return false + elseif str == "true" then + return true elseif (tonumber(str) or 0) > 0 then return true else diff --git a/tex/context/base/lang-wrd.lua b/tex/context/base/lang-wrd.lua index 84d6107d4..c093d11d7 100644 --- a/tex/context/base/lang-wrd.lua +++ b/tex/context/base/lang-wrd.lua @@ -26,13 +26,13 @@ words.threshold = 4 local numbers = languages.numbers local registered = languages.registered -local set_attribute = node.set_attribute -local unset_attribute = node.unset_attribute local traverse_nodes = node.traverse local wordsdata = words.data local chardata = characters.data local tasks = nodes.tasks +local unsetvalue = attributes.unsetvalue + local nodecodes = nodes.nodecodes local kerncodes = nodes.kerncodes @@ -207,7 +207,7 @@ table.setmetatableindex(cache, function(t,k) -- k == language, numbers[k] == tag else c = colist["word:" .. (numbers[k] or "unset")] or colist["word:unknown"] end - local v = c and function(n) set_attribute(n,a_color,c) end or false + local v = c and function(n) n[a_color] = c end or false t[k] = v return v end) @@ -226,7 +226,7 @@ end methods[1] = function(head) for n in traverse_nodes(head) do - unset_attribute(n,a_color) -- hm, not that selective (reset color) + n[a_color] = unsetvalue -- hm, not that selective (reset color) end return mark_words(head,sweep) end @@ -327,7 +327,7 @@ end methods[3] = function(head) for n in traverse_nodes(head) do - unset_attribute(n,a_color) + n[a_color] = unsetvalue end return mark_words(head,sweep) end diff --git a/tex/context/base/lpdf-tag.lua b/tex/context/base/lpdf-tag.lua index 0be9d3452..2763633c2 100644 --- a/tex/context/base/lpdf-tag.lua +++ b/tex/context/base/lpdf-tag.lua @@ -45,9 +45,11 @@ local glyph_code = nodecodes.glyph local a_tagged = attributes.private('tagged') local a_image = attributes.private('image') -local has_attribute, set_attribute, traverse_nodes, traverse_id = node.has_attribute, node.set_attribute, node.traverse, node.traverse_id -local tosequence = nodes.tosequence -local copy_node, slide_nodelist = node.copy, node.slide +local traverse_nodes = node.traverse +local traverse_id = node.traverse_id +local tosequence = nodes.tosequence +local copy_node = node.copy +local slide_nodelist = node.slide local structure_stack = { } local structure_kids = pdfarray() @@ -226,7 +228,7 @@ local function collectranges(head,list) for n in traverse_nodes(head) do local id = n.id -- 14: image, 8: literal (mp) if id == glyph_code then - local at = has_attribute(n,a_tagged) + local at = n[a_tagged] if not at then range = nil elseif last ~= at then @@ -237,9 +239,9 @@ local function collectranges(head,list) range[4] = n -- stop end elseif id == hlist_code or id == vlist_code then - local at = has_attribute(n,a_image) + local at = n[a_image] if at then - local at = has_attribute(n,a_tagged) + local at = n[a_tagged] if not at then range = nil else diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua index 3c67d26a2..2e97750a1 100644 --- a/tex/context/base/math-noa.lua +++ b/tex/context/base/math-noa.lua @@ -51,8 +51,9 @@ local report_alternates = logs.reporter("mathematics","alternates") local report_italics = logs.reporter("mathematics","italics") local report_families = logs.reporter("mathematics","families") -local set_attribute = node.set_attribute -local has_attribute = node.has_attribute +local a_mathrendering = attributes.private("mathrendering") +local a_exportstatus = attributes.private("exportstatus") + local mlist_to_hlist = node.mlist_to_hlist local font_of_family = node.family_font local insert_node_after = node.insert_after @@ -94,12 +95,12 @@ local tasks = nodes.tasks local nodecodes = nodes.nodecodes local noadcodes = nodes.noadcodes -local noad_ord = noadcodes.ord -local noad_rel = noadcodes.rel -local noad_punct = noadcodes.punct -local noad_opdisplaylimits = noadcodes.opdisplaylimits -local noad_oplimits = noadcodes.oplimits -local noad_opnolimits = noadcodes.opnolimits +local noad_ord = noadcodes.ord +local noad_rel = noadcodes.rel +local noad_punct = noadcodes.punct +local noad_opdisplaylimits= noadcodes.opdisplaylimits +local noad_oplimits = noadcodes.oplimits +local noad_opnolimits = noadcodes.opnolimits local math_noad = nodecodes.noad -- attr nucleus sub sup local math_accent = nodecodes.accent -- attr nucleus sub sup accent @@ -201,10 +202,94 @@ end noads.process = processnoads +-- experiment (when not present fall back to fam 0) -- needs documentation + +-- 0-2 regular +-- 3-5 bold +-- 6-8 pseudobold + +local families = { } +local a_mathfamily = attributes.private("mathfamily") +local boldmap = mathematics.boldmap + +local familymap = { [0] = + "regular", + "regular", + "regular", + "bold", + "bold", + "bold", + "pseudobold", + "pseudobold", + "pseudobold", +} + +families[math_char] = function(pointer) + if pointer.fam == 0 then + local a = pointer[a_mathfamily] + if a and a > 0 then + pointer[a_mathfamily] = 0 + if a > 5 then + local char = pointer.char + local bold = boldmap[char] + local newa = a - 3 + if bold then + pointer[a_exportstatus] = char + pointer.char = bold + if trace_families then + report_families("replacing U+%05X (%s) by bold U+%05X (%s), family %s (%s) becomes %s (%s)", + char,utfchar(char),bold,utfchar(bold),a,familymap[a],newa,familymap[newa]) + end + else + if trace_families then + report_families("no bold replacement for U+%05X (%s), family %s (%s) becomes %s (%s)", + char,utfchar(char),a,familymap[a],newa,familymap[newa]) + end + end + pointer.fam = newa + else + if trace_families then + local char = pointer.char + report_families("family of U+%05X (%s) becomes %s (%s)", + char,utfchar(char),a,familymap[a]) + end + pointer.fam = a + end + else + -- pointer.fam = 0 + end + end +end + +families[math_delim] = function(pointer) + if pointer.small_fam == 0 then + local a = pointer[a_mathfamily] + if a and a > 0 then + pointer[a_mathfamily] = 0 + if a > 5 then + -- no bold delimiters in unicode + a = a - 3 + end + pointer.small_fam = a + pointer.large_fam = a + else + pointer.small_fam = 0 + pointer.large_fam = 0 + end + end +end + +families[math_textchar] = families[math_char] + +function handlers.families(head,style,penalties) + processnoads(head,families,"families") + return true +end + -- character remapping -local mathalphabet = attributes.private("mathalphabet") -local mathgreek = attributes.private("mathgreek") +local a_mathalphabet = attributes.private("mathalphabet") +local a_mathgreek = attributes.private("mathgreek") processors.relocate = { } @@ -212,8 +297,9 @@ local function report_remap(tag,id,old,new,extra) report_remapping("remapping %s in font %s from U+%05X (%s) to U+%05X (%s)%s",tag,id,old,utfchar(old),new,utfchar(new),extra or "") end -local remapalphabets = mathematics.remapalphabets -local setnodecolor = nodes.tracers.colors.set +local remapalphabets = mathematics.remapalphabets +local fallbackstyleattr = mathematics.fallbackstyleattr +local setnodecolor = nodes.tracers.colors.set --~ This does not work out well, as there are no fallbacks. Ok, we could --~ define a poor mans simplify mechanism. @@ -233,22 +319,62 @@ local function checked(pointer) if trace_analyzing then setnodecolor(pointer,"font:isol") end - set_attribute(pointer,exportstatus,char) -- testcase: exponentiale + pointer[a_exportstatus] = char -- testcase: exponentiale pointer.char = newchar return true end end end +-- processors.relocate[math_char] = function(pointer) +-- local g = pointer[a_mathgreek] or 0 +-- local a = pointer[a_mathalphabet] or 0 +-- if a > 0 or g > 0 then +-- if a > 0 then +-- pointer[a_mathgreek] = 0 +-- end +-- if g > 0 then +-- pointer[a_mathalphabet] = 0 +-- end +-- local char = pointer.char +-- local newchar = remapalphabets(char,a,g) +-- if newchar then +-- local fam = pointer.fam +-- local id = font_of_family(fam) +-- local characters = fontcharacters[id] +-- if characters and characters[newchar] then +-- if trace_remapping then +-- report_remap("char",id,char,newchar) +-- end +-- if trace_analyzing then +-- setnodecolor(pointer,"font:isol") +-- end +-- pointer.char = newchar +-- return true +-- else +-- if trace_remapping then +-- report_remap("char",id,char,newchar," fails") +-- end +-- end +-- end +-- end +-- if trace_analyzing then +-- setnodecolor(pointer,"font:medi") +-- end +-- if check_coverage then +-- return checked(pointer) +-- end +-- end + processors.relocate[math_char] = function(pointer) - local g = has_attribute(pointer,mathgreek) or 0 - local a = has_attribute(pointer,mathalphabet) or 0 + local g = pointer[a_mathgreek] or 0 + local a = pointer[a_mathalphabet] or 0 if a > 0 or g > 0 then if a > 0 then - set_attribute(pointer,mathgreek,0) + pointer[a_mathgreek] = 0 end if g > 0 then - set_attribute(pointer,mathalphabet,0) + pointer[a_mathalphabet] = 0 end local char = pointer.char local newchar = remapalphabets(char,a,g) @@ -256,7 +382,7 @@ processors.relocate[math_char] = function(pointer) local fam = pointer.fam local id = font_of_family(fam) local characters = fontcharacters[id] - if characters and characters[newchar] then + if characters[newchar] then if trace_remapping then report_remap("char",id,char,newchar) end @@ -266,8 +392,27 @@ processors.relocate[math_char] = function(pointer) pointer.char = newchar return true else - if trace_remapping then - report_remap("char",id,char,newchar," fails") + local fallback = fallbackstyleattr(a) + if fallback then + local newchar = remapalphabets(char,fallback,g) + if newchar then + if characters[newchar] then + if trace_remapping then + report_remap("char",id,char,newchar," (fallback remapping used)") + end + if trace_analyzing then + setnodecolor(pointer,"font:isol") + end + pointer.char = newchar + return true + elseif trace_remapping then + report_remap("char",id,char,newchar," fails (no fallback character)") + end + elseif trace_remapping then + report_remap("char",id,char,newchar," fails (no fallback remap character)") + end + elseif trace_remapping then + report_remap("char",id,char,newchar," fails (no fallback style)") end end end @@ -299,15 +444,12 @@ end -- rendering (beware, not exported) -local a_mathrendering = attributes.private("mathrendering") -local a_exportstatus = attributes.private("exportstatus") - processors.render = { } local rendersets = mathematics.renderings.numbers or { } -- store processors.render[math_char] = function(pointer) - local attr = has_attribute(pointer,a_mathrendering) + local attr = pointer[a_mathrendering] if attr and attr > 0 then local char = pointer.char local renderset = rendersets[attr] @@ -319,7 +461,7 @@ processors.render[math_char] = function(pointer) local characters = fontcharacters[id] if characters and characters[newchar] then pointer.char = newchar - set_attribute(pointer,a_exportstatus,char) + pointer[a_exportstatus] = char end end end @@ -347,9 +489,9 @@ local resize = { } processors.resize = resize resize[math_fence] = function(pointer) if pointer.subtype == left_fence_code then - local a = has_attribute(pointer,mathsize) + local a = pointer[mathsize] if a and a > 0 then - set_attribute(pointer,mathsize,0) + pointer[mathsize] = 0 local d = pointer.delim local df = d.small_fam local id = font_of_family(df) @@ -377,9 +519,9 @@ end -- respace[math_char] = function(pointer,what,n,parent) -- not math_noad .. math_char ... and then parent -- pointer = parent -- if pointer and pointer.subtype == noad_ord then --- local a = has_attribute(pointer,mathpunctuation) +-- local a = pointer[mathpunctuation] -- if a and a > 0 then --- set_attribute(pointer,mathpunctuation,0) +-- pointer[mathpunctuation] = 0 -- local current_nucleus = pointer.nucleus -- if current_nucleus.id == math_char then -- local current_char = current_nucleus.char @@ -433,7 +575,7 @@ end -- local current_nucleus = pointer.nucleus -- if current_nucleus.id == math_char then -- local current_char = current_nucleus.char --- local a = has_attribute(pointer,mathpunctuation) +-- local a = pointer[mathpunctuation] -- if not a or a == 0 then -- if current_char == comma then -- -- default tex: 2,5 or 2, 5 --> 2, 5 @@ -506,6 +648,8 @@ mathpairs[0x2033] = { [0x2032] = 0x2034 } -- (doubleprime,pri mathpairs[0x222B] = { [0x222B] = 0x222C, [0x222C] = 0x222D } mathpairs[0x222C] = { [0x222B] = 0x222D } +mathpairs[0x007C] = { [0x007C] = 0x2016 } -- double bars + local validpair = { [noad_rel] = true, [noad_ord] = true, @@ -729,9 +873,9 @@ function mathematics.setalternate(fam,tag) end alternate[math_char] = function(pointer) - local a = has_attribute(pointer,a_mathalternate) + local a = pointer[a_mathalternate] if a and a > 0 then - set_attribute(pointer,a_mathalternate,0) + pointer[a_mathalternate] = 0 local tfmdata = fontdata[font_of_family(pointer.fam)] -- we can also have a famdata local mathalternatesattributes = tfmdata.shared.mathalternatesattributes if mathalternatesattributes then @@ -753,89 +897,6 @@ function handlers.check(head,style,penalties) return true end --- experiment (when not present fall back to fam 0) -- needs documentation - --- 0-2 regular --- 3-5 bold --- 6-8 pseudobold - -local families = { } -local a_mathfamily = attributes.private("mathfamily") -local boldmap = mathematics.boldmap - -local tracemap = { [0] = - "regular", - "regular", - "regular", - "bold", - "bold", - "bold", - "pseudobold", - "pseudobold", - "pseudobold", -} - -families[math_char] = function(pointer) - if pointer.fam == 0 then - local a = has_attribute(pointer,a_mathfamily) - if a and a > 0 then - set_attribute(pointer,a_mathfamily,0) - if a > 5 then - local char = pointer.char - local bold = boldmap[char] - local newa = a - 3 - if bold then - set_attribute(pointer,exportstatus,char) - pointer.char = bold - if trace_families then - report_families("replacing U+%05X by bold U+%05X, family %s (%s) becomes %s (%s)", - char,bold,a,tracemap[a],newa,tracemap[newa]) - end - else - if trace_families then - report_families("no bold replacement for U+%05X, family %s (%s) becomes %s (%s)", - char,a,tracemap[a],newa,tracemap[newa]) - end - end - pointer.fam = newa - else - if trace_families then - report_families("family of U+%05X becomes %s (%s)", - pointer.char,a,tracemap[a]) - end - pointer.fam = a - end - else - -- pointer.fam = 0 - end - end -end - -families[math_delim] = function(pointer) - if pointer.small_fam == 0 then - local a = has_attribute(pointer,a_mathfamily) - if a and a > 0 then - set_attribute(pointer,a_mathfamily,0) - if a > 5 then - -- no bold delimiters in unicode - a = a - 3 - end - pointer.small_fam = a - pointer.large_fam = a - else - pointer.small_fam = 0 - pointer.large_fam = 0 - end - end -end - -families[math_textchar] = families[math_char] - -function handlers.families(head,style,penalties) - processnoads(head,families,"families") - return true -end - -- italics: we assume that only characters matter -- -- = we check for correction first because accessing nodes is slower @@ -943,7 +1004,7 @@ trackers.register("math.italics", function(v) end) italics[math_char] = function(pointer,what,n,parent) - local method = has_attribute(pointer,a_mathitalics) + local method = pointer[a_mathitalics] if method and method > 0 then local char = pointer.char local font = font_of_family(pointer.fam) -- todo: table @@ -1103,7 +1164,7 @@ variants[math_char] = function(pointer,what,n,parent) -- also set export value end if variant then pointer.char = variant - set_attribute(pointer,exportstatus,char) -- we don't export the variant as it's visual markup + pointer[a_exportstatus] = char -- we don't export the variant as it's visual markup if trace_variants then report_variants("variant (U+%05X,U+%05X) replaced by U+%05X",char,selector,variant) end diff --git a/tex/context/base/math-tag.lua b/tex/context/base/math-tag.lua index c504b610a..6e634fd30 100644 --- a/tex/context/base/math-tag.lua +++ b/tex/context/base/math-tag.lua @@ -11,8 +11,6 @@ local insert, remove = table.insert, table.remove local attributes, nodes = attributes, nodes -local get_attribute = nodes.getattribute -local set_attribute = nodes.setattribute local set_attributes = nodes.setattributes local traverse_nodes = node.traverse @@ -64,19 +62,19 @@ local function processsubsup(start) local nucleus, sup, sub = start.nucleus, start.sup, start.sub if sub then if sup then - set_attribute(start,a_tagged,start_tagged("msubsup")) + start[a_tagged] = start_tagged("msubsup") process(nucleus) process(sub) process(sup) stop_tagged() else - set_attribute(start,a_tagged,start_tagged("msub")) + start[a_tagged] = start_tagged("msub") process(nucleus) process(sub) stop_tagged() end elseif sup then - set_attribute(start,a_tagged,start_tagged("msup")) + start[a_tagged] = start_tagged("msup") process(nucleus) process(sup) stop_tagged() @@ -97,7 +95,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer if id == math_char_code then local char = start.char -- check for code - local a = get_attribute(start,a_mathcategory) + local a = start[a_mathcategory] if a then a = { detail = a } end @@ -120,22 +118,22 @@ process = function(start) -- we cannot use the processor as we have no finalizer tag = "mo" end -- print(start,a,tag) - set_attribute(start,a_tagged,start_tagged(tag,a)) + start[a_tagged] = start_tagged(tag,a) stop_tagged() break -- okay? elseif id == math_textchar_code then -- check for code - local a = get_attribute(start,a_mathcategory) + local a = start[a_mathcategory] if a then - set_attribute(start,a_tagged,start_tagged("ms",{ detail = a })) + start[a_tagged] = start_tagged("ms",{ detail = a }) else - set_attribute(start,a_tagged,start_tagged("ms")) + start[a_tagged] = start_tagged("ms") end stop_tagged() break elseif id == math_delim_code then -- check for code - set_attribute(start,a_tagged,start_tagged("mo")) + start[a_tagged] = start_tagged("mo") stop_tagged() break elseif id == math_style_code then @@ -144,13 +142,13 @@ process = function(start) -- we cannot use the processor as we have no finalizer processsubsup(start) elseif id == math_box_code or id == hlist_code or id == vlist_code then -- keep an eye on math_box_code and see what ends up in there - local attr = get_attribute(start,a_tagged) + local attr = start[a_tagged] local last = attr and taglist[attr] if last and find(last[#last],"formulacaption[:%-]") then -- leave alone, will nicely move to the outer level else local text = start_tagged("mtext") - set_attribute(start,a_tagged,text) + start[a_tagged] = text local list = start.list if not list then -- empty list @@ -168,7 +166,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer local cache = { } -- we can have nested unboxed mess so best local to runner for n in traverse_nodes(list) do local id = n.id - local aa = get_attribute(n,a_tagged) + local aa = n[a_tagged] if aa then local ac = cache[aa] if not ac then @@ -186,9 +184,9 @@ process = function(start) -- we cannot use the processor as we have no finalizer end cache[aa] = ac end - set_attribute(n,a_tagged,ac) + n[a_tagged] = ac else - set_attribute(n,a_tagged,text) + n[a_tagged] = text end if id == hlist_code or id == vlist_code then runner(n.list) @@ -202,23 +200,23 @@ process = function(start) -- we cannot use the processor as we have no finalizer elseif id == math_sub_code then local list = start.list if list then - local attr = get_attribute(start,a_tagged) + local attr = start[a_tagged] local last = attr and taglist[attr] local action = last and match(last[#last],"maction:(.-)%-") if action and action ~= "" then if actionstack[#actionstack] == action then - set_attribute(start,a_tagged,start_tagged("mrow")) + start[a_tagged] = start_tagged("mrow") process(list) stop_tagged() else insert(actionstack,action) - set_attribute(start,a_tagged,start_tagged("mrow",{ detail = action })) + start[a_tagged] = start_tagged("mrow",{ detail = action }) process(list) stop_tagged() remove(actionstack) end else - set_attribute(start,a_tagged,start_tagged("mrow")) + start[a_tagged] = start_tagged("mrow") process(list) stop_tagged() end @@ -226,16 +224,16 @@ process = function(start) -- we cannot use the processor as we have no finalizer elseif id == math_fraction_code then local num, denom, left, right = start.num, start.denom, start.left, start.right if left then - set_attribute(left,a_tagged,start_tagged("mo")) + left[a_tagged] = start_tagged("mo") process(left) stop_tagged() end - set_attribute(start,a_tagged,start_tagged("mfrac")) + start[a_tagged] = start_tagged("mfrac") process(num) process(denom) stop_tagged() if right then - set_attribute(right,a_tagged,start_tagged("mo")) + right[a_tagged] = start_tagged("mo") process(right) stop_tagged() end @@ -258,22 +256,22 @@ process = function(start) -- we cannot use the processor as we have no finalizer local subtype = start.subtype if subtype == 1 then -- left - set_attribute(start,a_tagged,start_tagged("mfenced")) + start[a_tagged] = start_tagged("mfenced") if delim then - set_attribute(start,a_tagged,start_tagged("mleft")) + start[a_tagged] = start_tagged("mleft") process(delim) stop_tagged() end elseif subtype == 2 then -- middle if delim then - set_attribute(start,a_tagged,start_tagged("mmiddle")) + start[a_tagged] = start_tagged("mmiddle") process(delim) stop_tagged() end elseif subtype == 3 then if delim then - set_attribute(start,a_tagged,start_tagged("mright")) + start[a_tagged] = start_tagged("mright") process(delim) stop_tagged() end @@ -289,12 +287,12 @@ process = function(start) -- we cannot use the processor as we have no finalizer stop_tagged() end if degree then -- not good enough, can be empty mlist - set_attribute(start,a_tagged,start_tagged("mroot")) + start[a_tagged] = start_tagged("mroot") processsubsup(start) process(degree) stop_tagged() else - set_attribute(start,a_tagged,start_tagged("msqrt")) + start[a_tagged] = start_tagged("msqrt") processsubsup(start) stop_tagged() end @@ -302,19 +300,19 @@ process = function(start) -- we cannot use the processor as we have no finalizer local accent, bot_accent = start.accent, start.bot_accent if bot_accent then if accent then - set_attribute(start,a_tagged,start_tagged("munderover",{ detail = "accent" })) + start[a_tagged] = start_tagged("munderover",{ detail = "accent" }) processsubsup(start) process(bot_accent) process(accent) stop_tagged() else - set_attribute(start,a_tagged,start_tagged("munder",{ detail = "accent" })) + start[a_tagged] = start_tagged("munder",{ detail = "accent" }) processsubsup(start) process(bot_accent) stop_tagged() end elseif accent then - set_attribute(start,a_tagged,start_tagged("mover",{ detail = "accent" })) + start[a_tagged] = start_tagged("mover",{ detail = "accent" }) processsubsup(start) process(accent) stop_tagged() @@ -322,10 +320,10 @@ process = function(start) -- we cannot use the processor as we have no finalizer processsubsup(start) end elseif id == glue_code then - set_attribute(start,a_tagged,start_tagged("mspace")) + start[a_tagged] = start_tagged("mspace") stop_tagged() else - set_attribute(start,a_tagged,start_tagged("merror", { detail = nodecodes[i] } )) + start[a_tagged] = start_tagged("merror", { detail = nodecodes[i] }) stop_tagged() end start = start.next @@ -335,9 +333,9 @@ end function noads.handlers.tags(head,style,penalties) local v_math = start_tagged("math") local v_mrow = start_tagged("mrow") - local v_mode = get_attribute(head,a_mathmode) - set_attribute(head,a_tagged,v_math) - set_attribute(head,a_tagged,v_mrow) + local v_mode = head[a_mathmode] + head[a_tagged] = v_math + head[a_tagged] = v_mrow tags.setattributehash(v_math,"mode",v_mode == 1 and "display" or "inline") process(head) stop_tagged() diff --git a/tex/context/base/node-acc.lua b/tex/context/base/node-acc.lua index d91bb921b..4380ec3a4 100644 --- a/tex/context/base/node-acc.lua +++ b/tex/context/base/node-acc.lua @@ -13,8 +13,6 @@ local tasks = nodes.tasks local traverse_nodes = node.traverse local traverse_id = node.traverse_id -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute local copy_node = node.copy local free_nodelist = node.flush_list @@ -46,17 +44,17 @@ local function injectspaces(head) g.components = nil g.subtype = 256 end - local a = has_attribute(n,a_characters) + local a = n[a_characters] local s = copy_node(n.spec) g.char, n.spec = 32, s p.next, g.prev = g, p g.next, n.prev = n, g s.width = s.width - g.width if a then - set_attribute(g,a_characters,a) + g[a_characters] = a end - set_attribute(s,a_characters,0) - set_attribute(n,a_characters,0) + s[a_characters] = 0 + n[a_characters] = 0 end --~ end elseif id == hlist_code or id == vlist_code then @@ -110,7 +108,7 @@ nodes.handlers.accessibility = injectspaces --~ hyphenated[str] = hsh --~ codes[hsh] = str --~ end ---~ set_attribute(n,a_hyphenated,hsh) +--~ n[a_hyphenated] = hsh --~ end --~ elseif id == hlist_code or id == vlist_code then --~ injectspans(n.list) @@ -127,7 +125,7 @@ nodes.handlers.accessibility = injectspaces --~ for n in traverse_nodes(head) do --~ local id = n.id --~ if id == disc then ---~ local a = has_attribute(n,a_hyphenated) +--~ local a = n[a_hyphenated] --~ if a then --~ local str = codes[a] --~ local b = new_pdfliteral(format("/Span << /ActualText %s >> BDC", lpdf.tosixteen(str))) diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua index ebfd3976d..d5a4d6f08 100644 --- a/tex/context/base/node-aux.lua +++ b/tex/context/base/node-aux.lua @@ -20,6 +20,7 @@ local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local attributelist_code = nodecodes.attributelist -- temporary +local math_code = nodecodes.math local nodepool = nodes.pool @@ -30,9 +31,6 @@ local traverse_nodes = node.traverse local traverse_id = node.traverse_id local free_node = node.free local hpack_nodes = node.hpack -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute -local get_attribute = node.get_attribute local unset_attribute = node.unset_attribute local first_glyph = node.first_glyph or node.first_character local copy_node = node.copy @@ -41,6 +39,8 @@ local slide_nodes = node.slide local insert_node_after = node.insert_after local isnode = node.is_node +local unsetvalue = attributes.unsetvalue + local current_font = font.current local texbox = tex.box @@ -58,7 +58,7 @@ end local function set_attributes(head,attr,value) for n in traverse_nodes(head) do - set_attribute(n,attr,value) + n[attr] = value local id = n.id if id == hlist_node or id == vlist_node then set_attributes(n.list,attr,value) @@ -68,8 +68,8 @@ end local function set_unset_attributes(head,attr,value) for n in traverse_nodes(head) do - if not has_attribute(n,attr) then - set_attribute(n,attr,value) + if not n[attr] then + n[attr] = value end local id = n.id if id == hlist_code or id == vlist_code then @@ -80,7 +80,7 @@ end local function unset_attributes(head,attr) for n in traverse_nodes(head) do - unset_attribute(n,attr) + n[attr] = unsetvalue local id = n.id if id == hlist_code or id == vlist_code then unset_attributes(n.list,attr) @@ -88,16 +88,16 @@ local function unset_attributes(head,attr) end end +nodes.setattribute = node.set_attribute +nodes.getattribute = node.has_attribute +nodes.unsetattribute = node.unset_attribute +nodes.has_attribute = node.has_attribute + nodes.firstglyph = first_glyph -nodes.setattribute = set_attribute -nodes.getattribute = has_attribute -nodes.unsetattribute = unset_attribute nodes.setattributes = set_attributes nodes.setunsetattributes = set_unset_attributes nodes.unsetattributes = unset_attributes -nodes.has_attribute = has_attribute - -- function nodes.is_skipable(a,id) -- skipable nodes at the margins during character protrusion -- return ( -- id ~= glyph_node @@ -204,6 +204,13 @@ function nodes.firstcharinbox(n) return 0 end +function nodes.endofmath(n) + for n in traverse_id(math_code,n.next) do + return n + end +end + + -- local function firstline(n) -- while n do -- local id = n.id diff --git a/tex/context/base/node-bck.lua b/tex/context/base/node-bck.lua index 2630df2f4..feaa2c684 100644 --- a/tex/context/base/node-bck.lua +++ b/tex/context/base/node-bck.lua @@ -19,8 +19,6 @@ local vlist_code = nodecodes.vlist local glyph_code = nodecodes.glyph local cell_code = listcodes.cell -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute local traverse = node.traverse local traverse_id = node.traverse_id @@ -51,25 +49,25 @@ local function add_backgrounds(head) -- rather old code .. to be redone end local width = current.width if width > 0 then - local background = has_attribute(current,a_background) + local background = current[a_background] if background then -- direct to hbox -- colorspace is already set so we can omit that and stick to color - local mode = has_attribute(current,a_colorspace) + local mode = current[a_colorspace] if mode then local height = current.height local depth = current.depth local skip = id == hlist_code and width or (height + depth) local glue = new_glue(-skip) local rule = new_rule(width,height,depth) - local color = has_attribute(current,a_color) - local transparency = has_attribute(current,a_transparency) - set_attribute(rule,a_colorspace,mode) + local color = current[a_color] + local transparency = current[a_transparency] + rule[a_colorspace] = mode if color then - set_attribute(rule,a_color,color) + rule[a_color] = color end if transparency then - set_attribute(rule,a_transparency,transparency) + rule[a_transparency] = transparency end rule.next = glue glue.prev = rule @@ -99,7 +97,7 @@ local function add_alignbackgrounds(head) local background = nil local found = nil -- for l in traverse(list) do - -- background = has_attribute(l,a_alignbackground) + -- background = l[a_alignbackground] -- if background then -- found = l -- break @@ -108,7 +106,7 @@ local function add_alignbackgrounds(head) -- we know that it's a fake hlist (could be user node) -- but we cannot store tables in user nodes yet for l in traverse_id(hpack_code,list) do - background = has_attribute(l,a_alignbackground) + background = l[a_alignbackground] if background then found = l end @@ -119,18 +117,18 @@ local function add_alignbackgrounds(head) -- current has subtype 5 (cell) local width = current.width if width > 0 then - local mode = has_attribute(found,a_colorspace) + local mode = found[a_colorspace] if mode then local glue = new_glue(-width) local rule = new_rule(width,current.height,current.depth) - local color = has_attribute(found,a_color) - local transparency = has_attribute(found,a_transparency) - set_attribute(rule,a_colorspace, mode) + local color = found[a_color] + local transparency = found[a_transparency] + rule[a_colorspace] = mode if color then - set_attribute(rule,a_color, color) + rule[a_color] = color end if transparency then - set_attribute(rule,a_transparency,transparency) + rule[a_transparency] = transparency end rule.next = glue glue.prev = rule diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua index 9bcfa0a7b..cad45c6a2 100644 --- a/tex/context/base/node-fin.lua +++ b/tex/context/base/node-fin.lua @@ -13,7 +13,6 @@ local next, type, format = next, type, string.format local attributes, nodes, node = attributes, nodes, node -local has_attribute = node.has_attribute local copy_node = node.copy local find_tail = node.slide @@ -32,7 +31,7 @@ local pdfliteral_code = whatcodes.pdfliteral local states = attributes.states local numbers = attributes.numbers -local trigger = attributes.private('trigger') +local a_trigger = attributes.private('trigger') local triggering = false local starttiming = statistics.starttiming @@ -188,7 +187,7 @@ function states.initialize(namespace,attribute,head) nsforced = namespace.forced nsselector = namespace.selector nslistwise = namespace.listwise - nstrigger = triggering and namespace.triggering and trigger + nstrigger = triggering and namespace.triggering and a_trigger current = 0 current_selector = 0 done = false -- todo: done cleanup @@ -226,7 +225,7 @@ end -- while stack do -- local id = stack.id -- if id == glyph_code or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code --- local c = has_attribute(stack,attribute) +-- local c = stack[attribute] -- if c then -- if default and c == inheritance then -- if current ~= default then @@ -253,8 +252,8 @@ end -- current = 0 -- end -- local ok = false --- if nstrigger and has_attribute(stack,nstrigger) then --- local outer = has_attribute(stack,attribute) +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] -- if outer ~= inheritance then -- stack.leader, ok = process(namespace,attribute,content,inheritance,outer) -- else @@ -282,8 +281,8 @@ end -- local content = stack.list -- if content then -- local ok = false --- if nstrigger and has_attribute(stack,nstrigger) then --- local outer = has_attribute(stack,attribute) +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] -- if outer ~= inheritance then -- stack.list, ok = process(namespace,attribute,content,inheritance,outer) -- else @@ -304,7 +303,7 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr local stack, done = head, false local function check() - local c = has_attribute(stack,attribute) + local c = stack[attribute] if c then if default and c == inheritance then if current ~= default then @@ -332,8 +331,8 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr end local function nested(content) - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] if outer ~= inheritance then return process(namespace,attribute,content,inheritance,outer) else @@ -401,20 +400,20 @@ states.process = process -- -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code -- if id == glyph_code -- or id == disc_code -- or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code --- local c = has_attribute(stack,attribute) +-- local c = stack[attribute] -- if c then -- if default and c == inheritance then -- if current ~= default then -- local data = nsdata[default] --- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) +-- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) -- current = default -- done = true -- end -- else --- local s = has_attribute(stack,nsselector) +-- local s = stack[nsselector] -- if current ~= c or current_selector ~= s then -- local data = nsdata[c] --- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) +-- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) -- current = c -- current_selector = s -- done = true @@ -423,7 +422,7 @@ states.process = process -- elseif default and inheritance then -- if current ~= default then -- local data = nsdata[default] --- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) +-- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) -- current = default -- done = true -- end @@ -444,8 +443,8 @@ states.process = process -- current = 0 -- end -- local ok = false --- if nstrigger and has_attribute(stack,nstrigger) then --- local outer = has_attribute(stack,attribute) +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] -- if outer ~= inheritance then -- stack.leader, ok = selective(namespace,attribute,content,inheritance,outer) -- else @@ -462,8 +461,8 @@ states.process = process -- local content = stack.list -- if content then -- local ok = false --- if nstrigger and has_attribute(stack,nstrigger) then --- local outer = has_attribute(stack,attribute) +-- if nstrigger and stack[nstrigger] then +-- local outer = stack[attribute] -- if outer ~= inheritance then -- stack.list, ok = selective(namespace,attribute,content,inheritance,outer) -- else @@ -484,20 +483,20 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at local stack, done = head, false local function check() - local c = has_attribute(stack,attribute) + local c = stack[attribute] if c then if default and c == inheritance then if current ~= default then local data = nsdata[default] - head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) + head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) current = default done = true end else - local s = has_attribute(stack,nsselector) + local s = stack[nsselector] if current ~= c or current_selector ~= s then local data = nsdata[c] - head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) + head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) current = c current_selector = s done = true @@ -506,7 +505,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at elseif default and inheritance then if current ~= default then local data = nsdata[default] - head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector])) + head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) current = default done = true end @@ -518,8 +517,8 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at end local function nested(content) - if nstrigger and has_attribute(stack,nstrigger) then - local outer = has_attribute(stack,attribute) + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] if outer ~= inheritance then return selective(namespace,attribute,content,inheritance,outer) else @@ -595,7 +594,7 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in local current, depth = default or 0, 0 local function check() - local a = has_attribute(stack,attribute) + local a = stack[attribute] if a then if current ~= a then head = insert_node_before(head,stack,copy_node(nsdata[a])) @@ -628,7 +627,7 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in if content then -- the problem is that broken lines gets the attribute which can be a later one if nslistwise then - local a = has_attribute(stack,attribute) + local a = stack[attribute] if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below local p = current current, done = a, true @@ -671,7 +670,7 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in local attrib = default or unsetvalue local function check() - local a = has_attribute(current,attribute) or unsetvalue + local a = current[attribute] or unsetvalue if a ~= attrib then local n = nsstep(a) if n then @@ -700,7 +699,7 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in if not content then -- skip elseif nslistwise then - local a = has_attribute(current,attribute) + local a = current[attribute] if a and attrib ~= a and nslistwise[a] then -- viewerlayer done = true head = insert_node_before(head,current,copy_node(nsdata[a])) diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua index a97c98d83..530659eaa 100644 --- a/tex/context/base/node-fnt.lua +++ b/tex/context/base/node-fnt.lua @@ -24,7 +24,6 @@ local fontdata = fonthashes.identifiers local otf = fonts.handlers.otf local traverse_id = node.traverse_id -local has_attribute = node.has_attribute local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming local nodecodes = nodes.nodecodes @@ -85,9 +84,10 @@ function handlers.characters(head) report_fonts() local n = head while n do - if n.id == glyph_code then + local id = n.id + if id == glyph_code then local font = n.font - local attr = has_attribute(n,0) or 0 + local attr = n[0] or 0 report_fonts("font %03i, dynamic %03i, glyph %s",font,attr,utf.char(n.char)) else report_fonts("[%s]",nodecodes[n.id]) @@ -95,10 +95,11 @@ function handlers.characters(head) n = n.next end end + -- todo: time a while and skip over or make a special traverse_id that skips over math for n in traverse_id(glyph_code,head) do -- if n.subtype<256 then -- all are 1 local font = n.font - local attr = has_attribute(n,0) or 0 -- zero attribute is reserved for fonts in context + local attr = n[0] or 0 -- zero attribute is reserved for fonts in context if font ~= prevfont or attr ~= prevattr then if attr > 0 then local used = attrfonts[font] @@ -219,166 +220,5 @@ function handlers.characters(head) return head, true end --- function handlers.characters(head) --- -- either next or not, but definitely no already processed list --- starttiming(nodes) --- local usedfonts, attrfonts, done = { }, { }, false --- local a, u, prevfont, prevattr = 0, 0, nil, nil --- local ap = 0 --- if trace_fontrun then --- run = run + 1 --- report_fonts() --- report_fonts("checking node list, run %s",run) --- report_fonts() --- local n = head --- while n do --- if n.id == glyph_code then --- local font = n.font --- local attr = has_attribute(n,0) or 0 --- report_fonts("font %03i, dynamic %03i, glyph %s",font,attr,utf.char(n.char)) --- else --- report_fonts("[%s]",nodecodes[n.id]) --- end --- n = n.next --- end --- end --- for n in traverse_id(glyph_code,head) do --- -- if n.subtype<256 then --- local font = n.font --- local attr = n.attr --- if attr ~= prevattr then --- local an = has_attribute(n,0) or 0 --- if ap ~= an and an > 0 then --- local used = attrfonts[font] --- if not used then --- used = { } --- attrfonts[font] = used --- end --- if not used[an] then --- local sd = setfontdynamics[font] --- if sd then -- always true ? --- local d = sd(font,an) -- can we cache this one? --- if d then --- used[an] = d --- a = a + 1 --- else --- -- can't happen ... otherwise best use nil/false distinction --- end --- end --- end --- elseif font ~= prevfont then --- local used = usedfonts[font] --- if not used then --- local fp = fontprocesses[font] --- if fp then --- usedfonts[font] = fp --- u = u + 1 --- else --- -- can't happen ... otherwise best use nil/false distinction --- end --- end --- end --- prevfont = font --- prevattr = attr --- ap = an --- elseif font ~= prevfont then --- local used = usedfonts[font] --- if not used then --- local fp = fontprocesses[font] --- if fp then --- usedfonts[font] = fp --- u = u + 1 --- else --- -- can't happen ... otherwise best use nil/false distinction --- end --- end --- prevfont = font --- end --- -- end --- end --- if trace_fontrun then --- report_fonts() --- report_fonts("statics : %s",(u > 0 and concat(keys(usedfonts)," ")) or "none") --- report_fonts("dynamics: %s",(a > 0 and concat(keys(attrfonts)," ")) or "none") --- report_fonts() --- end --- -- we could combine these and just make the attribute nil --- if u == 1 then --- local font, processors = next(usedfonts) --- local n = #processors --- if n > 0 then --- local h, d = processors[1](head,font,0) --- head = h or head --- done = done or d --- if n > 1 then --- for i=2,n do --- local h, d = processors[i](head,font,0) --- head = h or head --- done = done or d --- end --- end --- end --- elseif u > 0 then --- for font, processors in next, usedfonts do --- local n = #processors --- local h, d = processors[1](head,font,0) --- head = h or head --- done = done or d --- if n > 1 then --- for i=2,n do --- local h, d = processors[i](head,font,0) --- head = h or head --- done = done or d --- end --- end --- end --- end --- if a == 1 then --- local font, dynamics = next(attrfonts) --- for attribute, processors in next, dynamics do -- attr can switch in between --- local n = #processors --- if n == 0 then --- report_fonts("no processors associated with dynamic %s",attribute) --- else --- local h, d = processors[1](head,font,attribute) --- head = h or head --- done = done or d --- if n > 1 then --- for i=2,n do --- local h, d = processors[i](head,font,attribute) --- head = h or head --- done = done or d --- end --- end --- end --- end --- elseif a > 0 then --- for font, dynamics in next, attrfonts do --- for attribute, processors in next, dynamics do -- attr can switch in between --- local n = #processors --- if n == 0 then --- report_fonts("no processors associated with dynamic %s",attribute) --- else --- local h, d = processors[1](head,font,attribute) --- head = h or head --- done = done or d --- if n > 1 then --- for i=2,n do --- local h, d = processors[i](head,font,attribute) --- head = h or head --- done = done or d --- end --- end --- end --- end --- end --- end --- stoptiming(nodes) --- if trace_characters then --- nodes.report(head,done) --- end --- return head, true --- end - handlers.protectglyphs = node.protect_glyphs handlers.unprotectglyphs = node.unprotect_glyphs diff --git a/tex/context/base/node-inj.lua b/tex/context/base/node-inj.lua index b03ded9f2..e96c6e5fe 100644 --- a/tex/context/base/node-inj.lua +++ b/tex/context/base/node-inj.lua @@ -12,6 +12,7 @@ if not modules then modules = { } end modules ['node-inj'] = { -- that can be of help. Some optimizations can go away when we have faster machines. local next = next +local utfchar = utf.char local trace_injections = false trackers.register("nodes.injections", function(v) trace_injections = v end) @@ -31,20 +32,17 @@ local nodepool = nodes.pool local newkern = nodepool.kern local traverse_id = node.traverse_id -local unset_attribute = node.unset_attribute -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute local insert_node_before = node.insert_before local insert_node_after = node.insert_after -local kernpair = attributes.private('kernpair') -local ligacomp = attributes.private('ligacomp') -local markbase = attributes.private('markbase') -local markmark = attributes.private('markmark') -local markdone = attributes.private('markdone') -local cursbase = attributes.private('cursbase') -local curscurs = attributes.private('curscurs') -local cursdone = attributes.private('cursdone') +local a_kernpair = attributes.private('kernpair') +local a_ligacomp = attributes.private('ligacomp') +local a_markbase = attributes.private('markbase') +local a_markmark = attributes.private('markmark') +local a_markdone = attributes.private('markdone') +local a_cursbase = attributes.private('cursbase') +local a_curscurs = attributes.private('curscurs') +local a_cursdone = attributes.private('cursdone') -- This injector has been tested by Idris Samawi Hamid (several arabic fonts as well as -- the rather demanding Husayni font), Khaled Hosny (latin and arabic) and Kaj Eigner @@ -70,8 +68,8 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne local dx, dy = factor*(exit[1]-entry[1]), factor*(exit[2]-entry[2]) local ws, wn = tfmstart.width, tfmnext.width local bound = #cursives + 1 - set_attribute(start,cursbase,bound) - set_attribute(nxt,curscurs,bound) + start[a_cursbase] = bound + nxt[a_curscurs] = bound cursives[bound] = { rlmode, dx, dy, ws, wn } return dx, dy, bound end @@ -80,14 +78,14 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr) local x, y, w, h = factor*spec[1], factor*spec[2], factor*spec[3], factor*spec[4] -- dy = y - h if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then - local bound = has_attribute(current,kernpair) + local bound = current[a_kernpair] if bound then local kb = kerns[bound] -- inefficient but singles have less, but weird anyway, needs checking kb[2], kb[3], kb[4], kb[5] = (kb[2] or 0) + x, (kb[3] or 0) + y, (kb[4] or 0)+ w, (kb[5] or 0) + h else bound = #kerns + 1 - set_attribute(current,kernpair,bound) + current[a_kernpair] = bound kerns[bound] = { rlmode, x, y, w, h, r2lflag, tfmchr.width } end return x, y, w, h, bound @@ -99,7 +97,7 @@ function injections.setkern(current,factor,rlmode,x,tfmchr) local dx = factor*x if dx ~= 0 then local bound = #kerns + 1 - set_attribute(current,kernpair,bound) + current[a_kernpair] = bound kerns[bound] = { rlmode, dx } return dx, bound else @@ -109,7 +107,7 @@ end function injections.setmark(start,base,factor,rlmode,ba,ma,index) -- ba=baseanchor, ma=markanchor local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2]) -- the index argument is no longer used but when this - local bound = has_attribute(base,markbase) -- fails again we should pass it + local bound = base[a_markbase] -- fails again we should pass it local index = 1 if bound then local mb = marks[bound] @@ -117,8 +115,8 @@ local index = 1 -- if not index then index = #mb + 1 end index = #mb + 1 mb[index] = { dx, dy, rlmode } - set_attribute(start,markmark,bound) - set_attribute(start,markdone,index) + start[a_markmark] = bound + start[a_markdone] = index return dx, dy, bound else report_injections("possible problem, U+%05X is base mark without data (id: %s)",base.char,bound) @@ -127,9 +125,9 @@ index = #mb + 1 -- index = index or 1 index = index or 1 bound = #marks + 1 - set_attribute(base,markbase,bound) - set_attribute(start,markmark,bound) - set_attribute(start,markdone,index) + base[a_markbase] = bound + start[a_markmark] = bound + start[a_markdone] = index marks[bound] = { [index] = { dx, dy, rlmode } } return dx, dy, bound end @@ -142,13 +140,14 @@ local function trace(head) report_injections("begin run") for n in traverse_id(glyph_code,head) do if n.subtype < 256 then - local kp = has_attribute(n,kernpair) - local mb = has_attribute(n,markbase) - local mm = has_attribute(n,markmark) - local md = has_attribute(n,markdone) - local cb = has_attribute(n,cursbase) - local cc = has_attribute(n,curscurs) - report_injections("char U+%05X, font=%s",n.char,n.font) + local kp = n[a_kernpair] + local mb = n[a_markbase] + local mm = n[a_markmark] + local md = n[a_markdone] + local cb = n[a_cursbase] + local cc = n[a_curscurs] + local char = n.char + report_injections("char U+%05X, font %s, glyph %s",char,n.font,utfchar(char)) if kp then local k = kerns[kp] if k[3] then @@ -213,7 +212,7 @@ function injections.handler(head,where,keep) if tm then mk[n] = tm[n.char] end - local k = has_attribute(n,kernpair) + local k = n[a_kernpair] if k then local kk = kerns[k] if kk then @@ -262,9 +261,9 @@ function injections.handler(head,where,keep) for i=1,nofvalid do -- valid == glyphs local n = valid[i] if not mk[n] then - local n_cursbase = has_attribute(n,cursbase) + local n_cursbase = n[a_cursbase] if p_cursbase then - local n_curscurs = has_attribute(n,curscurs) + local n_curscurs = n[a_curscurs] if p_cursbase == n_curscurs then local c = cursives[n_curscurs] if c then @@ -325,14 +324,14 @@ function injections.handler(head,where,keep) if has_marks then for i=1,nofvalid do local p = valid[i] - local p_markbase = has_attribute(p,markbase) + local p_markbase = p[a_markbase] if p_markbase then local mrks = marks[p_markbase] local nofmarks = #mrks for n in traverse_id(glyph_code,p.next) do - local n_markmark = has_attribute(n,markmark) + local n_markmark = n[a_markmark] if p_markbase == n_markmark then - local index = has_attribute(n,markdone) or 1 + local index = n[a_markdone] or 1 local d = mrks[index] if d then local rlmode = d[3] @@ -435,7 +434,7 @@ function injections.handler(head,where,keep) end for n in traverse_id(glyph_code,head) do if n.subtype < 256 then - local k = has_attribute(n,kernpair) + local k = n[a_kernpair] if k then local kk = kerns[k] if kk then diff --git a/tex/context/base/node-mig.lua b/tex/context/base/node-mig.lua index 1384f6024..14a9885ba 100644 --- a/tex/context/base/node-mig.lua +++ b/tex/context/base/node-mig.lua @@ -10,8 +10,6 @@ local format = string.format local attributes, nodes, node = attributes, nodes, node -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute local remove_nodes = nodes.remove local nodecodes = nodes.nodecodes @@ -22,7 +20,7 @@ local vlist_code = nodecodes.vlist local insert_code = nodecodes.ins local mark_code = nodecodes.mark -local migrated = attributes.private("migrated") +local a_migrated = attributes.private("migrated") local trace_migrations = false trackers.register("nodes.migrations", function(v) trace_migrations = v end) @@ -77,8 +75,8 @@ function nodes.handlers.migrate(head,where) local id = current.id -- inserts_too is a temp hack, we should only do them when it concerns -- newly placed (flushed) inserts - if id == vlist_code or id == hlist_code or (inserts_too and id == insert_code) and not has_attribute(current,migrated) then - set_attribute(current,migrated,1) + if id == vlist_code or id == hlist_code or (inserts_too and id == insert_code) and not current[a_migrated] then + current[a_migrated] = 1 t_sweeps = t_sweeps + 1 local h = current.list local first, last, ni, nm diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua index 7e7b3be3b..f39d29ae3 100644 --- a/tex/context/base/node-ref.lua +++ b/tex/context/base/node-ref.lua @@ -68,7 +68,6 @@ local nodepool = nodes.pool local new_kern = nodepool.kern -local has_attribute = node.has_attribute local traverse = node.traverse local find_node_tail = node.tail or node.slide local tosequence = nodes.tosequence @@ -212,7 +211,7 @@ end -- txtdir = txtdir or "===" -- while current do -- local id = current.id --- local r = has_attribute(current,attribute) +-- local r = current[attribute] -- if id == hlist_code or id == vlist_code then -- -- somehow reference is true so the following fails (second one not done) in -- -- test \goto{test}[page(2)] test \gotobox{test}[page(2)] @@ -272,7 +271,7 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx while current do local id = current.id if id == hlist_code or id == vlist_code then - local r = has_attribute(current,attribute) + local r = current[attribute] -- somehow reference is true so the following fails (second one not done) in -- test \goto{test}[page(2)] test \gotobox{test}[page(2)] -- so let's wait till this fails again @@ -301,7 +300,7 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx elseif id == glue_code and current.subtype == leftskip_code then -- any glue at the left? -- else - local r = has_attribute(current,attribute) + local r = current[attribute] if not r then -- just go on, can be kerns elseif not reference then @@ -333,7 +332,7 @@ end -- local current = head -- while current do -- local id = current.id --- local r = has_attribute(current,attribute) +-- local r = current[attribute] -- if id == hlist_code or id == vlist_code then -- if r and not done[r] then -- done[r] = true @@ -365,7 +364,7 @@ local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) while current do local id = current.id if id == hlist_code or id == vlist_code then - local r = has_attribute(current,attribute) + local r = current[attribute] if r and not done[r] then done[r] = true inject_list(id,current,r,make,stack,pardir,txtdir) @@ -382,7 +381,7 @@ local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) txtdir = current.dir end else - local r = has_attribute(current,attribute) + local r = current[attribute] if r and not done[r] then done[r] = true head, current = inject_range(head,current,current,r,make,stack,parent,pardir,txtdir) @@ -439,9 +438,9 @@ local function colorize(width,height,depth,n,reference,what) depth = height end local rule = new_rule(width,height,depth) - set_attribute(rule,a_colormodel,1) -- gray color model - set_attribute(rule,a_color,u_color) - set_attribute(rule,a_transparency,u_transparency) + rule[a_colormodel] = 1 -- gray color model + rule[a_color] = u_color + rule[a_transparency] = u_transparency if width < 0 then local kern = new_kern(width) rule.width = -width diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua index 9dba642f2..c7b7b7be9 100644 --- a/tex/context/base/node-rul.lua +++ b/tex/context/base/node-rul.lua @@ -77,8 +77,6 @@ local insert_node_before = node.insert_before local insert_node_after = node.insert_after local striprange = nodes.striprange local list_dimensions = node.dimensions -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute local hpack_nodes = node.hpack @@ -142,7 +140,7 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi while n do local id = n.id if id == glyph_code or id == rule_code then - local aa = has_attribute(n,attribute) + local aa = n[attribute] if aa then if aa == a then if not f then -- ? @@ -195,7 +193,7 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi elseif id == glue_code then -- catch \underbar{a} \underbar{a} (subtype test is needed) local subtype = n.subtype - if continue and has_attribute(n,attribute) and + if continue and n[attribute] and (subtype == userskip_code or subtype == spaceskip_code or subskip == xspaceskip_code) then l = n else @@ -261,9 +259,9 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a local method, offset, continue, dy, order, max = d.method, d.offset, d.continue, d.dy, d.order, d.max local rulethickness, unit = d.rulethickness, d.unit local ma, ca, ta = d.ma, d.ca, d.ta - local colorspace = (ma > 0 and ma) or has_attribute(f,a_colorspace) or 1 - local color = (ca > 0 and ca) or has_attribute(f,a_color) - local transparency = (ta > 0 and ta) or has_attribute(f,a_transparency) + local colorspace = (ma > 0 and ma) or f[a_colorspace] or 1 + local color = (ca > 0 and ca) or f[a_color] + local transparency = (ta > 0 and ta) or f[a_transparency] local foreground = order == variables.foreground local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node @@ -296,18 +294,18 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a local ht = (offset+(i-1)*dy)*e + rulethickness - m local dp = -(offset+(i-1)*dy)*e + rulethickness + m local r = new_rule(w,ht,dp) - local v = has_attribute(f,a_viewerlayer) + local v = f[a_viewerlayer] -- quick hack if v then - set_attribute(r,a_viewerlayer,v) + r[a_viewerlayer] = v end -- if color then - set_attribute(r,a_colorspace,colorspace) - set_attribute(r,a_color,color) + r[a_colorspace] = colorspace + r[a_color] = color end if transparency then - set_attribute(r,a_transparency,transparency) + r[a_transparency] = transparency end local k = new_kern(-w) if foreground then diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua index 1d7a19896..3538b5e34 100644 --- a/tex/context/base/node-tra.lua +++ b/tex/context/base/node-tra.lua @@ -712,24 +712,21 @@ number.nopts = nopts local colors = { } tracers.colors = colors -local get_attribute = node.has_attribute -local set_attribute = node.set_attribute -local unset_attribute = node.unset_attribute +local unsetvalue = attributes.unsetvalue local a_color = attributes.private('color') local a_colormodel = attributes.private('colormodel') -local a_state = attributes.private('state') local m_color = attributes.list[a_color] or { } function colors.set(n,c,s) local mc = m_color[c] if not mc then - unset_attribute(n,a_color) + n[a_color] = unsetvalue else - if not get_attribute(n,a_colormodel) then - set_attribute(n,a_colormodel,s or 1) + if not n[a_colormodel] then + n[a_colormodel] = s or 1 end - set_attribute(n,a_color,mc) + n[a_color] = mc end return n end @@ -739,12 +736,12 @@ function colors.setlist(n,c,s) while n do local mc = m_color[c] if not mc then - unset_attribute(n,a_color) + n[a_color] = unsetvalue else - if not get_attribute(n,a_colormodel) then - set_attribute(n,a_colormodel,s or 1) + if not n[a_colormodel] then + n[a_colormodel] = s or 1 end - set_attribute(n,a_color,mc) + n[a_color] = mc end n = n.next end @@ -752,7 +749,7 @@ function colors.setlist(n,c,s) end function colors.reset(n) - unset_attribute(n,a_color) + n[a_color] = unsetvalue return n end @@ -767,9 +764,9 @@ local m_transparency = attributes.list[a_transparency] or { } function transparencies.set(n,t) local mt = m_transparency[t] if not mt then - unset_attribute(n,a_transparency) + n[a_transparency] = unsetvalue else - set_attribute(n,a_transparency,mt) + n[a_transparency] = mt end return n end @@ -779,9 +776,9 @@ function transparencies.setlist(n,c,s) while n do local mt = m_transparency[c] if not mt then - unset_attribute(n,a_transparency) + n[a_transparency] = unsetvalue else - set_attribute(n,a_transparency,mt) + n[a_transparency] = mt end n = n.next end @@ -789,7 +786,7 @@ function transparencies.setlist(n,c,s) end function transparencies.reset(n) - unset_attribute(n,a_transparency) + n[a_transparency] = unsetvalue return n end diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua index 4dec0deec..76afc6c35 100644 --- a/tex/context/base/page-lin.lua +++ b/tex/context/base/page-lin.lua @@ -49,7 +49,6 @@ local current_list = { } local cross_references = { } local chunksize = 250 -- not used in boxed -local has_attribute = node.has_attribute local traverse_id = node.traverse_id local traverse = node.traverse local copy_node = node.copy @@ -70,7 +69,7 @@ local function resolve(n,m) -- we can now check the 'line' flag (todo) while n do local id = n.id if id == whatsit_code then -- why whatsit - local a = has_attribute(n,a_linereference) + local a = n[a_linereference] if a then cross_references[a] = m end @@ -190,7 +189,7 @@ end local function identify(list) if list then for n in traverse_id(hlist_code,list) do - if has_attribute(n,a_linenumber) then + if n[a_linenumber] then return list end end @@ -230,7 +229,7 @@ function boxed.stage_one(n,nested) -- skip funny hlists -- todo: check line subtype else local list = n.list - local a = has_attribute(list,a_linenumber) + local a = list[a_linenumber] if a and a > 0 then if last_a ~= a then local da = data[a] @@ -245,12 +244,12 @@ function boxed.stage_one(n,nested) report_lines("starting line number range %s: start %s, continue",a,da.start,da.continue or "no") end end - if has_attribute(n,a_displaymath) then + if n[a_displaymath] then if nodes.is_display_math(n) then check_number(n,a,skip) end else - local v = has_attribute(list,a_verbatimline) + local v = list[a_verbatimline] if not v or v ~= last_v then last_v = v check_number(n,a,skip) diff --git a/tex/context/base/scrn-hlp.lua b/tex/context/base/scrn-hlp.lua index 81d68840b..5f8368c6d 100644 --- a/tex/context/base/scrn-hlp.lua +++ b/tex/context/base/scrn-hlp.lua @@ -13,7 +13,6 @@ interactions.help = help local a_help = attributes.private("help") -local has_attribute = node.has_attribute local copy_nodelist = node.copy_list local hpack_nodelist = node.hpack @@ -62,7 +61,7 @@ local function collect(head,used) while head do local id = head.id if id == hlist_code then - local a = has_attribute(head,a_help) + local a = head[a_help] if a then if not used then used = { a } diff --git a/tex/context/base/scrp-cjk.lua b/tex/context/base/scrp-cjk.lua index ab09ce9c8..c44f42e9c 100644 --- a/tex/context/base/scrp-cjk.lua +++ b/tex/context/base/scrp-cjk.lua @@ -11,7 +11,6 @@ if not modules then modules = { } end modules ['scrp-cjk'] = { local utfchar = utf.char -local has_attribute = node.has_attribute local insert_node_after = node.insert_after local insert_node_before = node.insert_before local remove_node = nodes.remove @@ -411,7 +410,7 @@ local function process(head,first,last) while true do local upcoming, id = first.next, first.id if id == glyph_code then - local a = has_attribute(first,a_prestat) + local a = first[a_prestat] local current = numbertocategory[a] local action = injectors[previous] if action then @@ -420,7 +419,7 @@ local function process(head,first,last) local font = first.font if font ~= lastfont then lastfont = font - set_parameters(font,numbertodataset[has_attribute(first,a_preproc)]) + set_parameters(font,numbertodataset[first[a_preproc]]) end action(head,first) end @@ -431,7 +430,7 @@ local function process(head,first,last) if p and n then local pid, nid = p.id, n.id if pid == glyph_code and nid == glyph_code then - local pa, na = has_attribute(p,a_prestat), has_attribute(n,a_prestat) + local pa, na = p[a_prestat], n[a_prestat] local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na] if not pcjk or not ncjk or pcjk == "korean" or ncjk == "korean" @@ -632,7 +631,7 @@ local function process(head,first,last) while true do local upcoming, id = first.next, first.id if id == glyph_code then - local a = has_attribute(first,a_prestat) + local a = first[a_prestat] local current = numbertocategory[a] local action = injectors[previous] if action then @@ -641,7 +640,7 @@ local function process(head,first,last) local font = first.font if font ~= lastfont then lastfont = font - set_parameters(font,numbertodataset[has_attribute(first,a_preproc)]) + set_parameters(font,numbertodataset[first[a_preproc]]) end action(head,first) end @@ -652,7 +651,7 @@ local function process(head,first,last) if p and n then local pid, nid = p.id, n.id if pid == glyph_code and nid == glyph_code then - local pa, na = has_attribute(p,a_prestat), has_attribute(n,a_prestat) + local pa, na = p[a_prestat], n[a_prestat] local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na] if not pcjk or not ncjk or pcjk == "korean" or ncjk == "korean" @@ -854,7 +853,7 @@ local function process(head,first,last) while true do local upcoming, id = first.next, first.id if id == glyph_code then - local a = has_attribute(first,a_prestat) + local a = first[a_prestat] local current = numbertocategory[a] local action = injectors[previous] if action then @@ -863,7 +862,7 @@ local function process(head,first,last) local font = first.font if font ~= lastfont then lastfont = font - set_parameters(font,numbertodataset[has_attribute(first,a_preproc)]) + set_parameters(font,numbertodataset[first[a_preproc]]) end action(head,first) end @@ -874,7 +873,7 @@ local function process(head,first,last) if p and n then local pid, nid = p.id, n.id if pid == glyph_code and nid == glyph_code then - local pa, na = has_attribute(p,a_prestat), has_attribute(n,a_prestat) + local pa, na = p[a_prestat], n[a_prestat] local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na] if not pcjk or not ncjk or pcjk == "korean" or ncjk == "korean" diff --git a/tex/context/base/scrp-eth.lua b/tex/context/base/scrp-eth.lua index 75fad2481..e1b8df432 100644 --- a/tex/context/base/scrp-eth.lua +++ b/tex/context/base/scrp-eth.lua @@ -9,7 +9,6 @@ if not modules then modules = { } end modules ['scrp-eth'] = { -- at some point I will review the script code but for the moment we -- do it this way; so space settings like with cjk yet -local has_attribute = node.has_attribute local insert_node_before = node.insert_before local nodepool = nodes.pool @@ -38,7 +37,7 @@ local inter_character_stretch_factor = 1 local inter_character_shrink_factor = 1 local function space_glue(current) - local data = numbertodataset[has_attribute(current,a_preproc)] + local data = numbertodataset[current[a_preproc]] if data then inter_character_space_factor = data.inter_character_space_factor or 1 inter_character_stretch_factor = data.inter_character_stretch_factor or 1 @@ -107,7 +106,7 @@ local function process(head,first,last) while current do local id = current.id if id == glyph_code then - local prestat = has_attribute(current,a_prestat) + local prestat = current[a_prestat] local category = numbertocategory[prestat] if injector then local action = injector[category] diff --git a/tex/context/base/scrp-ini.lua b/tex/context/base/scrp-ini.lua index 16d33d5d7..e75a32dd2 100644 --- a/tex/context/base/scrp-ini.lua +++ b/tex/context/base/scrp-ini.lua @@ -18,8 +18,6 @@ local report_preprocessing = logs.reporter("scripts","preprocessing") local utfchar = utf.char -local set_attribute = node.set_attribute -local has_attribute = node.has_attribute local first_glyph = node.first_glyph or node.first_character local traverse_id = node.traverse_id @@ -347,7 +345,7 @@ scripts.numbertocategory = numbertocategory local function colorize(start,stop) for n in traverse_id(glyph_code,start) do - local kind = numbertocategory[has_attribute(n,a_prestat)] + local kind = numbertocategory[n[a_prestat]] if kind then local ac = scriptcolors[kind] if ac then @@ -388,7 +386,7 @@ function scripts.preprocess(head) while start do local id = start.id if id == glyph_code then - local a = has_attribute(start,a_preproc) + local a = start[a_preproc] if a then if a ~= last_a then if first then @@ -426,7 +424,7 @@ function scripts.preprocess(head) end local h = hash[c] if h then - set_attribute(start,a_prestat,categorytonumber[h]) + start[a_prestat] = categorytonumber[h] if not first then first, last = start, start else @@ -535,13 +533,13 @@ setmetatableindex(cache_nop,function(t,k) local v = { } t[k] = v return v end) function autofontfeature.handler(head) for n in traverse_id(glyph_code,head) do - -- if has_attribute(n,a_preproc) then + -- if n[a_preproc] then -- -- already tagged by script feature, maybe some day adapt -- else local char = n.char local script = otfscripts[char] if script then - local dynamic = has_attribute(n,0) or 0 + local dynamic = n[0] or 0 local font = n.font if dynamic > 0 then local slot = cache_yes[font] @@ -554,7 +552,7 @@ function autofontfeature.handler(head) end end if attr ~= 0 then - set_attribute(n,0,attr) + n[0] = attr -- maybe set preproc when associated end else @@ -568,7 +566,7 @@ function autofontfeature.handler(head) end end if attr ~= 0 then - set_attribute(n,0,attr) + n[0] = attr -- maybe set preproc when associated end end diff --git a/tex/context/base/spac-adj.lua b/tex/context/base/spac-adj.lua index 4cba2f91e..c87a9d17f 100644 --- a/tex/context/base/spac-adj.lua +++ b/tex/context/base/spac-adj.lua @@ -8,17 +8,16 @@ if not modules then modules = { } end modules ['spac-adj'] = { -- sort of obsolete code -local attribute = attributes.private('graphicvadjust') +local a_vadjust = attributes.private('graphicvadjust') -local nodecodes = nodes.nodecodes +local nodecodes = nodes.nodecodes -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist -local remove_node = nodes.remove -local hpack_node = node.hpack -local vpack_node = node.vpack -local has_attribute = node.has_attribute +local remove_node = nodes.remove +local hpack_node = node.hpack +local vpack_node = node.vpack function nodes.handlers.graphicvadjust(head,groupcode) -- we can make an actionchain for mvl only if groupcode == "" then -- mvl only @@ -26,7 +25,7 @@ function nodes.handlers.graphicvadjust(head,groupcode) -- we can make an actionc while h do local id = h.id if id == hlist_code or id == vlist_code then - local a = has_attribute(h,attribute) + local a = h[a_vadjust] if a then if p then local n diff --git a/tex/context/base/spac-ali.lua b/tex/context/base/spac-ali.lua index 998df3aa6..744b1d810 100644 --- a/tex/context/base/spac-ali.lua +++ b/tex/context/base/spac-ali.lua @@ -15,11 +15,11 @@ local prependaction = tasks.prependaction local disableaction = tasks.disableaction local enableaction = tasks.enableaction -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute local slide_nodes = node.slide local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here +local unsetvalue = attributes.unsetvalue + local concat_nodes = nodes.concat local nodecodes = nodes.nodecodes @@ -61,7 +61,7 @@ local function handler(head,leftpage,realpageno) local id = current.id if id == hlist_code then if current.subtype == line_code then - local a = has_attribute(current,a_realign) + local a = current[a_realign] if not a or a == 0 then -- skip else @@ -92,7 +92,7 @@ local function handler(head,leftpage,realpageno) done = true nofrealigned = nofrealigned + 1 end - unset_attribute(current,a_realign) + current[a_realign] = unsetvalue end end handler(current.list,leftpage,realpageno) diff --git a/tex/context/base/spac-chr.lua b/tex/context/base/spac-chr.lua index 2db0b9a7b..8ab7c4b8a 100644 --- a/tex/context/base/spac-chr.lua +++ b/tex/context/base/spac-chr.lua @@ -20,8 +20,6 @@ report_characters = logs.reporter("typesetting","characters") local nodes, node = nodes, node -local set_attribute = node.set_attribute -local has_attribute = node.has_attribute local insert_node_after = node.insert_after local remove_node = nodes.remove -- ! nodes local copy_node_list = node.copy_list @@ -65,8 +63,8 @@ local function inject_quad_space(unicode,head,current,fraction) local glue = new_glue(fraction) -- glue.attr = copy_node_list(attr) glue.attr = attr -current.attr = nil - set_attribute(glue,a_character,unicode) + current.attr = nil + glue[a_character] = unicode head, current = insert_node_after(head,current,glue) return head, current end @@ -79,7 +77,7 @@ local function inject_char_space(unicode,head,current,parent) -- glue.attr = copy_node_list(current.attr) glue.attr = current.attr current.attr = nil - set_attribute(glue,a_character,unicode) + glue[a_character] = unicode head, current = insert_node_after(head,current,glue) return head, current end @@ -92,7 +90,7 @@ local function inject_nobreak_space(unicode,head,current,space,spacestretch,spac glue.attr = attr current.attr = nil -- penalty.attr = attr - set_attribute(glue,a_character,unicode) + glue[a_character] = unicode head, current = insert_node_after(head,current,penalty) head, current = insert_node_after(head,current,glue) return head, current @@ -105,7 +103,7 @@ local methods = { [0x00A0] = function(head,current) -- nbsp local para = fontparameters[current.font] - if has_attribute(current,a_alignstate) == 1 then -- flushright + if current[a_alignstate] == 1 then -- flushright head, current = inject_nobreak_space(0x00A0,head,current,para.space,0,0) current.subtype = space_skip_code else diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua index 68554acb9..50aeb82c0 100644 --- a/tex/context/base/spac-ver.lua +++ b/tex/context/base/spac-ver.lua @@ -62,9 +62,6 @@ local a_skiporder = attributes.private('skiporder') local a_snapmethod = attributes.private('snapmethod') local a_snapvbox = attributes.private('snapvbox') -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute -local set_attribute = node.set_attribute local find_node_tail = node.tail local free_node = node.free local free_node_list = node.flush_list @@ -240,9 +237,9 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only --~ local i = 0 for n in traverse_nodes(list) do local id = n.id ---~ i = i + 1 print(i,nodecodes[id],has_attribute(n,a_snapmethod)) +--~ i = i + 1 print(i,nodecodes[id],n[a_snapmethod]) if id == hlist_code or id == vlist_code then - local a = has_attribute(n,a_snapmethod) + local a = n[a_snapmethod] if not a then -- return true -- not snapped at all elseif a == 0 then @@ -482,8 +479,8 @@ h, d = ch, cd t[#t+1] = format("after offset: %s (width %s height %s depth %s)", points(offset),points(current.width),points(current.height),points(current.depth)) end - set_attribute(shifted,a_snapmethod,0) - set_attribute(current,a_snapmethod,0) + shifted[a_snapmethod] = 0 + current[a_snapmethod] = 0 end if not height then current.height = ch @@ -802,7 +799,7 @@ function vspacing.snapbox(n,how) local box = texbox[n] local list = box.list if list then - local s = has_attribute(list,a_snapmethod) + local s = list[a_snapmethod] if s == 0 then if trace_vsnapping then -- report_snapper("box list not snapped, already done") @@ -822,8 +819,8 @@ function vspacing.snapbox(n,how) report_snapper("box list snapped from (%s,%s) to (%s,%s) using method '%s' (%s) for '%s' (%s lines): %s", h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list)) end - set_attribute(box, a_snapmethod,0) -- - set_attribute(list,a_snapmethod,0) -- yes or no + box[a_snapmethod] = 0 -- + list[a_snapmethod] = 0 -- yes or no end end end @@ -896,7 +893,7 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also -- needs checking, why so many calls if snap then local list = current.list - local s = has_attribute(current,a_snapmethod) + local s = current[a_snapmethod] if not s then -- if trace_vsnapping then -- report_snapper("mvl list not snapped") @@ -925,7 +922,7 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also elseif trace_vsnapping then report_snapper("mvl %s not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list)) end - set_attribute(current,a_snapmethod,0) + current[a_snapmethod] = 0 end else -- @@ -948,9 +945,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also elseif id == glue_code then local subtype = current.subtype if subtype == userskip_code then - local sc = has_attribute(current,a_skipcategory) -- has no default, no unset (yet) - local so = has_attribute(current,a_skiporder ) or 1 -- has 1 default, no unset (yet) - local sp = has_attribute(current,a_skippenalty ) -- has no default, no unset (yet) + local sc = current[a_skipcategory] -- has no default, no unset (yet) + local so = current[a_skiporder] or 1 -- has 1 default, no unset (yet) + local sp = current[a_skippenalty] -- has no default, no unset (yet) if sp and sc == penalty then if not penalty_data then penalty_data = sp @@ -1076,9 +1073,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also end elseif subtype == lineskip_code then if snap then - local s = has_attribute(current,a_snapmethod) + local s = current[a_snapmethod] if s and s ~= 0 then - set_attribute(current,a_snapmethod,0) + current[a_snapmethod] = 0 if current.spec.writable then local spec = writable_spec(current) spec.width = 0 @@ -1097,9 +1094,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also current = current.next elseif subtype == baselineskip_code then if snap then - local s = has_attribute(current,a_snapmethod) + local s = current[a_snapmethod] if s and s ~= 0 then - set_attribute(current,a_snapmethod,0) + current[a_snapmethod] = 0 if current.spec.writable then local spec = writable_spec(current) spec.width = 0 @@ -1136,9 +1133,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also end elseif subtype == topskip_code or subtype == splittopskip_code then if snap then - local s = has_attribute(current,a_snapmethod) + local s = current[a_snapmethod] if s and s ~= 0 then - set_attribute(current,a_snapmethod,0) + current[a_snapmethod] = 0 local sv = snapmethods[s] local w, cw = snap_topskip(current,sv) if trace_vsnapping then @@ -1254,7 +1251,7 @@ function vspacing.pagehandler(newhead,where) if id ~= glue_code then flush = true elseif n.subtype == userskip_code then - if has_attribute(n,a_skipcategory) then + if n[a_skipcategory] then stackhack = true else flush = true diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf index 414724f9e..3bd3b5a33 100644 Binary files a/tex/context/base/status-files.pdf and b/tex/context/base/status-files.pdf differ diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf index 4eeba1cd7..bd56f837b 100644 Binary files a/tex/context/base/status-lua.pdf and b/tex/context/base/status-lua.pdf differ diff --git a/tex/context/base/strc-mar.lua b/tex/context/base/strc-mar.lua index c7ef2d4e1..1557c1956 100644 --- a/tex/context/base/strc-mar.lua +++ b/tex/context/base/strc-mar.lua @@ -22,7 +22,6 @@ local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist -local getattribute = nodes.getattribute local traversenodes = node.traverse local texsetattribute = tex.setattribute local texbox = tex.box @@ -103,7 +102,7 @@ local function sweep(head,first,last) for n in traversenodes(head) do local id = n.id if id == glyph_code then - local a = getattribute(n,a_marks) + local a = n[a_marks] if not a then -- next elseif first == 0 then @@ -112,7 +111,7 @@ local function sweep(head,first,last) last = a end elseif id == hlist_code or id == vlist_code then - local a = getattribute(n,a_marks) + local a = n[a_marks] if not a then -- next elseif first == 0 then diff --git a/tex/context/base/trac-jus.lua b/tex/context/base/trac-jus.lua index 412ede90e..9d99f059d 100644 --- a/tex/context/base/trac-jus.lua +++ b/tex/context/base/trac-jus.lua @@ -25,8 +25,6 @@ local concat_nodes = nodes.concat local hpack_nodes = node.hpack local copy_node = node.copy local get_list_dimensions = node.dimensions -local set_attribute = node.set_attribute -local has_attribute = node.has_attribute local hlist_code = nodes.nodecodes.hlist local tex_set_attribute = tex.setattribute @@ -65,8 +63,8 @@ end) function checkers.handler(head) for current in node.traverse_id(hlist_code,head) do - if has_attribute(current,a_justification,1) then - set_attribute(current,a_justification,0) + if current[a_justification] == 1 then + current[a_justification] = 0 local width = current.width if width > 0 then local list = current.list @@ -92,7 +90,7 @@ function checkers.handler(head) current.list = concat_nodes { list, rule } -- current.list = concat_nodes { list, new_kern(-naturalwidth+width), rule } elseif delta <= min_threshold then - local alignstate = has_attribute(list,a_alignstate) + local alignstate = list[a_alignstate] if alignstate == 1 then local rule = new_rule(-delta,naturalheight,naturaldepth) setcolor(rule,"trace:dc") diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua index e20171959..05b6c724c 100644 --- a/tex/context/base/trac-vis.lua +++ b/tex/context/base/trac-vis.lua @@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['trac-vis'] = { local string, number, table = string, number, table local node, nodes, attributes, fonts, tex = node, nodes, attributes, fonts, tex - +local type = type local format = string.format -- This module started out in the early days of mkiv and luatex with @@ -67,14 +67,13 @@ local copy_node = node.copy local copy_list = node.copy_list local free_node = node.free local free_node_list = node.flush_list -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute -local unset_attribute = node.unset_attribute local insert_node_before = node.insert_before local insert_node_after = node.insert_after local fast_hpack = nodes.fasthpack +local traverse_nodes = node.traverse local tex_attribute = tex.attribute +local tex_box = tex.box local unsetvalue = attributes.unsetvalue local current_font = font.current @@ -100,13 +99,6 @@ local setlisttransparency = tracers.transparencies.setlist local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming --- local function setlistattribute(list,a,v) --- while list do --- set_attribute(list,a,v) --- list = list.next --- end --- end - local a_visual = attributes.private("visual") local a_fontkern = attributes.private("fontkern") local a_layer = attributes.private("viewerlayer") @@ -296,7 +288,7 @@ local function sometext(str,layer,color) setlisttransparency(info,c_zero) info = fast_hpack(info) if layer then - set_attribute(info,a_layer,layer) + info[a_layer] = layer end local width = info.width info.width = 0 @@ -331,7 +323,7 @@ local function fontkern(head,current) text, } info = fast_hpack(info) - set_attribute(info,a_layer,l_fontkern) + info[a_layer] = l_fontkern info.width = 0 info.height = 0 info.depth = 0 @@ -382,7 +374,7 @@ local function whatsit(head,current) else local tag = whatsitcodes[what] info = sometext(format("W:%s",tag and tags[tag] or what),usedfont) - set_attribute(info,a_layer,l_whatsit) + info[a_layer] = l_whatsit w_cache[what] = info end head, current = insert_node_after(head,current,copy_list(info)) @@ -396,7 +388,7 @@ local function user(head,current) -- print("hit user") else info = sometext(format("U:%s",what),usedfont) - set_attribute(info,a_layer,l_user) + info[a_layer] = l_user w_cache[what] = info end head, current = insert_node_after(head,current,copy_list(info)) @@ -480,7 +472,7 @@ local function ruledbox(head,current,vertical,layer,what,simple) info.width = 0 info.height = 0 info.depth = 0 - set_attribute(info,a_layer,layer) + info[a_layer] = layer local info = concat_nodes { current, new_kern(-wd), @@ -535,7 +527,7 @@ local function ruledglyph(head,current) info.width = 0 info.height = 0 info.depth = 0 - set_attribute(info,a_layer,l_glyph) + info[a_layer] = l_glyph local info = concat_nodes { current, new_kern(-wd), @@ -695,7 +687,7 @@ local function visualize(head,vertical) local attr = unsetvalue while current do local id = current.id - local a = has_attribute(current,a_visual) or unsetvalue + local a = current[a_visual] or unsetvalue if a ~= attr then prev_trace_fontkern = trace_fontkern if a == unsetvalue then @@ -728,7 +720,7 @@ local function visualize(head,vertical) attr = a end if trace_strut then - set_attribute(current,a_layer,l_strut) + current[a_layer] = l_strut elseif id == glyph_code then if trace_glyph then head, current = ruledglyph(head,current) @@ -751,7 +743,7 @@ local function visualize(head,vertical) elseif id == kern_code then local subtype = current.subtype -- tricky ... we don't copy the trace attribute in node-inj (yet) - if subtype == font_kern_code or has_attribute(current,a_fontkern) then + if subtype == font_kern_code or current[a_fontkern] then if trace_fontkern or prev_trace_fontkern then head, current = fontkern(head,current) end @@ -848,7 +840,43 @@ function visualizers.handler(head) end function visualizers.box(n) - tex.box[n].list = visualizers.handler(tex.box[n].list) + tex_box[n].list = visualizers.handler(tex_box[n].list) +end + +local last = nil +local used = nil + +local mark = { + "trace:1", "trace:2", "trace:3", + "trace:4", "trace:5", "trace:6", + "trace:7", +} + +local function markfonts(list) + for n in traverse_nodes(list) do + local id = n.id + if id == glyph_code then + local font = n.font + local okay = used[font] + if not okay then + last = last + 1 + okay = mark[last] + used[font] = okay + end + setcolor(n,okay) + elseif id == hlist_code or id == vlist_code then + markfonts(n.list) + end + end +end + +function visualizers.markfonts(list) + last, used = 0, { } + markfonts(type(n) == "number" and tex_box[n].list or n) +end + +function commands.markfonts(n) + visualizers.markfonts(n) end statistics.register("visualization time",function() diff --git a/tex/context/base/typo-bld.lua b/tex/context/base/typo-bld.lua index 87d280541..97893ad2b 100644 --- a/tex/context/base/typo-bld.lua +++ b/tex/context/base/typo-bld.lua @@ -30,7 +30,6 @@ constructors.attribute = a_parbuilder local unsetvalue = attributes.unsetvalue local texsetattribute = tex.setattribute -local has_attribute = node.has_attribute local texnest = tex.nest local nodepool = nodes.pool @@ -100,7 +99,7 @@ function constructors.handler(head,followed_by_display) if type(head) == "boolean" then return head else - local attribute = has_attribute(head,a_parbuilder) -- or mainconstructor + local attribute = head[a_parbuilder] -- or mainconstructor if attribute then local method = names[attribute] if method then diff --git a/tex/context/base/typo-brk.lua b/tex/context/base/typo-brk.lua index 726518a85..d6326ebeb 100644 --- a/tex/context/base/typo-brk.lua +++ b/tex/context/base/typo-brk.lua @@ -20,9 +20,6 @@ local report_breakpoints = logs.reporter("typesetting","breakpoints") local nodes, node = nodes, node local settings_to_array = utilities.parsers.settings_to_array -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute -local set_attribute = node.set_attribute local copy_node = node.copy local copy_nodelist = node.copy_list local free_node = node.free @@ -164,9 +161,9 @@ local function process(namespace,attribute,head) while start do local id = start.id if id == glyph_code then - local attr = has_attribute(start,a_breakpoints) + local attr = start[a_breakpoints] if attr and attr > 0 then - unset_attribute(start,a_breakpoints) -- maybe test for subtype > 256 (faster) + start[a_breakpoints] = unsetvalue -- maybe test for subtype > 256 (faster) -- look ahead and back n chars local data = mapping[attr] if data then diff --git a/tex/context/base/typo-cap.lua b/tex/context/base/typo-cap.lua index 3233a6ba2..0b9e52749 100644 --- a/tex/context/base/typo-cap.lua +++ b/tex/context/base/typo-cap.lua @@ -16,9 +16,6 @@ local report_casing = logs.reporter("typesetting","casing") local nodes, node = nodes, node -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute -local set_attribute = node.set_attribute local traverse_id = node.traverse_id local copy_node = node.copy @@ -171,8 +168,8 @@ local function Word(start,attribute,attr) if not prev or prev.id ~= glyph_code then --- only the first character is treated for n in traverse_id(glyph_code,start.next) do - if has_attribute(n,attribute) == attr then - unset_attribute(n,attribute) + if n[attribute] == attr then + n[attribute] = unsetvalue else -- break -- we can have nested mess end @@ -264,13 +261,13 @@ local function process(namespace,attribute,head) -- not real fast but also not u while start do -- while because start can jump ahead local id = start.id if id == glyph_code then - local attr = has_attribute(start,attribute) + local attr = start[attribute] if attr and attr > 0 then if attr ~= lastattr then lastfont = nil lastattr = attr end - unset_attribute(start,attribute) + start[attribute] = unsetvalue local action = actions[attr%100] -- map back to low number if action then start, ok = action(start,attribute,attr) diff --git a/tex/context/base/typo-cln.lua b/tex/context/base/typo-cln.lua index c6a270791..be00ac10d 100644 --- a/tex/context/base/typo-cln.lua +++ b/tex/context/base/typo-cln.lua @@ -28,9 +28,10 @@ local tasks = nodes.tasks local texattribute = tex.attribute -local has_attribute = node.has_attribute local traverse_id = node.traverse_id +local unsetvalue = attributes.unsetvalue + local glyph_code = nodecodes.glyph local uccodes = characters.uccodes @@ -52,7 +53,7 @@ local function process(namespace,attribute,head) if resetter[char] then inline = false elseif not inline then - local a = has_attribute(n,attribute) + local a = n[attribute] if a == 1 then -- currently only one cleaner so no need to be fancy local upper = uccodes[char] if type(upper) == "table" then diff --git a/tex/context/base/typo-dig.lua b/tex/context/base/typo-dig.lua index a3a0feb3e..30d7d96ac 100644 --- a/tex/context/base/typo-dig.lua +++ b/tex/context/base/typo-dig.lua @@ -19,9 +19,6 @@ local report_digits = logs.reporter("typesetting","digits") local nodes, node = nodes, node -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute -local set_attribute = node.set_attribute local hpack_node = node.hpack local traverse_id = node.traverse_id local insert_node_before = node.insert_before @@ -109,9 +106,9 @@ local function process(namespace,attribute,head) local done, current, ok = false, head, false while current do if current.id == glyph_code then - local attr = has_attribute(current,attribute) + local attr = current[attribute] if attr and attr > 0 then - unset_attribute(current,attribute) + current[attribute] = unsetvalue local action = actions[attr%100] -- map back to low number if action then head, current, ok = action(head,current,attribute,attr) diff --git a/tex/context/base/typo-dir.lua b/tex/context/base/typo-dir.lua index da324b7e2..7f8975082 100644 --- a/tex/context/base/typo-dir.lua +++ b/tex/context/base/typo-dir.lua @@ -18,9 +18,6 @@ local trace_directions = false trackers.register("typesetters.directions", func local report_directions = logs.reporter("typesetting","directions") -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute -local set_attribute = node.set_attribute local traverse_id = node.traverse_id local insert_node_before = node.insert_before local insert_node_after = node.insert_after @@ -168,6 +165,8 @@ end -- todo: use new dir functions +local s_isol = fonts.analyzers.states.isol + function directions.process(namespace,attribute,start) -- todo: make faster if not start.next then return start, false @@ -193,9 +192,9 @@ function directions.process(namespace,attribute,start) -- todo: make faster elseif inmath then current = current.next else - local attr = has_attribute(current,attribute) + local attr = current[attribute] if attr and attr > 0 then - -- unset_attribute(current,attribute) -- slow, needed? + -- current[attribute] = unsetvalue -- slow, needed? if attr == 1 then -- bidi parsing mode elseif attr ~= prevattr then @@ -239,7 +238,7 @@ function directions.process(namespace,attribute,start) -- todo: make faster end elseif lro or override < 0 then if d == "r" or d == "al" then - set_attribute(current,a_state,4) -- maybe better have a special bidi attr value -> override (9) -> todo + current[a_state] = s_isol -- maybe better have a special bidi attr value -> override (9) -> todo if trace_directions then list[#list+1] = format("char %s (%s / U+%04X) of class %s overidden to l (bidi=%s) (state=isol)",utfchar(char),char,char,d,attr) end @@ -420,7 +419,7 @@ end --~ if n then --~ local id = n.id --~ if id == glyph_code then ---~ local attr = has_attribute(n,attribute) +--~ local attr = n[attribute] --~ if attr and attr > 0 then --~ local d = chardirs[n.char] --~ if d == "r" or d == "al" then -- override diff --git a/tex/context/base/typo-itc.lua b/tex/context/base/typo-itc.lua index d294dd60a..57b4e38b8 100644 --- a/tex/context/base/typo-itc.lua +++ b/tex/context/base/typo-itc.lua @@ -25,7 +25,6 @@ local tasks = nodes.tasks local insert_node_after = node.insert_after local delete_node = nodes.delete -local has_attribute = node.has_attribute local texattribute = tex.attribute local a_italics = attributes.private("italics") @@ -121,7 +120,7 @@ local function process(namespace,attribute,head) lastfont = font end if data then - local attr = forcedvariant or has_attribute(current,attribute) + local attr = forcedvariant or current[attribute] if attr and attr > 0 then local cd = data[char] if not cd then diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua index cd2639c67..6dd3e6bd7 100644 --- a/tex/context/base/typo-krn.lua +++ b/tex/context/base/typo-krn.lua @@ -11,8 +11,6 @@ local utfchar = utf.char local nodes, node, fonts = nodes, node, fonts -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute local find_node_tail = node.tail or node.slide local free_node = node.free local free_nodelist = node.flush_list @@ -116,9 +114,9 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that local fillup = false while start do -- faster to test for attr first - local attr = force or has_attribute(start,attribute) + local attr = force or start[attribute] if attr and attr > 0 then - unset_attribute(start,attribute) + start[attribute] = unsetvalue local krn = mapping[attr] if krn == v_max then krn = .25 @@ -166,7 +164,7 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that if not pid then -- nothing elseif pid == kern_code then - if prev.subtype == kerning_code or has_attribute(prev,a_fontkern) then + if prev.subtype == kerning_code or prev[a_fontkern] then if keeptogether and prev.prev.id == glyph_code and keeptogether(prev.prev,start) then -- we could also pass start -- keep 'm else diff --git a/tex/context/base/typo-mar.lua b/tex/context/base/typo-mar.lua index db8508a4a..02f425298 100644 --- a/tex/context/base/typo-mar.lua +++ b/tex/context/base/typo-mar.lua @@ -115,9 +115,6 @@ local v_first = variables.first local v_text = variables.text local v_column = variables.column -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute -local unset_attribute = node.unset_attribute local copy_node_list = node.copy_list local slide_nodes = node.slide local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here @@ -635,7 +632,7 @@ local function inject(parent,head,candidate) box.next = head head = box end - set_attribute(box,a_margindata,nofstatus) + box[a_margindata] = nofstatus if trace_margindata then report_margindata("injected, location: %s, shift: %s",location,shift) end @@ -722,10 +719,10 @@ local function flushed(scope,parent) -- current is hlist done = done or don end if done then - local a = has_attribute(head,a_linenumber) -- hack .. we need a more decent critical attribute inheritance mechanism + local a = head[a_linenumber] -- hack .. we need a more decent critical attribute inheritance mechanism parent.list = hpack_nodes(head,parent.width,"exactly") if a then - set_attribute(parent.list,a_linenumber,a) + parent.list[a_linenumber] = a end -- resetstacked() end @@ -744,10 +741,10 @@ local function handler(scope,head,group) local done = false while current do local id = current.id - if (id == vlist_code or id == hlist_code) and not has_attribute(current,a_margindata) then + if (id == vlist_code or id == hlist_code) and not current[a_margindata] then local don, continue = flushed(scope,current) if don then - set_attribute(current,a_margindata,0) -- signal to prevent duplicate processing + current[a_margindata] = 0 -- signal to prevent duplicate processing if continue then markovershoot(current) end @@ -817,7 +814,7 @@ local function finalhandler(head) while current do local id = current.id if id == hlist_code then - local a = has_attribute(current,a_margindata) + local a = current[a_margindata] if not a or a == 0 then finalhandler(current.list) elseif realigned(current,a) then diff --git a/tex/context/base/typo-pag.lua b/tex/context/base/typo-pag.lua index 482a3a9f8..6488b7c6b 100644 --- a/tex/context/base/typo-pag.lua +++ b/tex/context/base/typo-pag.lua @@ -16,9 +16,8 @@ local penalty_code = nodecodes.penalty local insert_node_after = node.insert_after local new_penalty = nodes.pool.penalty -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute -local set_attribute = node.set_attribute + +local unsetvalue = attributes.unsetvalue local points = number.points @@ -40,7 +39,7 @@ function builders.paragraphs.registertogether(line,specification) -- might chang if not enabled then nodes.tasks.enableaction("finalizers","builders.paragraphs.keeptogether") end - local a = has_attribute(line,a_keeptogether) + local a = line[a_keeptogether] local c = a and cache[a] if c then local height = specification.height @@ -67,7 +66,7 @@ function builders.paragraphs.registertogether(line,specification) -- might chang if not specification.slack then specification.slack = 0 end - set_attribute(line,a_keeptogether,last) + line[a_keeptogether] = last end if trace_keeptogether then local a = a or last @@ -169,10 +168,10 @@ function builders.paragraphs.keeptogether(head) local current = head while current do if current.id == hlist_code then - local a = has_attribute(current,a_keeptogether) + local a = current[a_keeptogether] if a and a > 0 then keeptogether(current,a) - unset_attribute(current,a_keeptogether) + current[a_keeptogether] = unsetvalue cache[a] = nil done = true end diff --git a/tex/context/base/typo-par.lua b/tex/context/base/typo-par.lua index 0261d2e4e..b25ae4a5b 100644 --- a/tex/context/base/typo-par.lua +++ b/tex/context/base/typo-par.lua @@ -29,9 +29,6 @@ local variables = interfaces.variables local texattribute = tex.attribute local unsetvalue = attributes.unsetvalue -local has_attribute = node.has_attribute -local set_attribute = node.set_attribute - local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local kern_node = nodecodes.kern @@ -84,7 +81,7 @@ local function process(namespace,attribute,head) local done = false if head.id == whatsit_code and head.subtype == localpar_code then -- begin of par - local a = has_attribute(head,attribute) + local a = head[attribute] if a and a > 0 then if dropper.enabled then dropper.enabled = false -- dangerous for e.g. nested || in tufte @@ -112,11 +109,11 @@ local function process(namespace,attribute,head) local ca = dropper.ca local ta = dropper.ta if ca and ca > 0 then - set_attribute(first,a_colorspace,ma == 0 and 1 or ma) - set_attribute(first,a_color,ca) + first[a_colorspace] = ma == 0 and 1 or ma + first[a_color] = ca end if ta and ta > 0 then - set_attribute(first,a_transparency,ta) + first[a_transparency] = ta end -- local width = first.width diff --git a/tex/context/base/typo-rep.lua b/tex/context/base/typo-rep.lua index 0d9bf8cc1..6534bf457 100644 --- a/tex/context/base/typo-rep.lua +++ b/tex/context/base/typo-rep.lua @@ -20,7 +20,6 @@ local nodes, node = nodes, node local delete_node = nodes.delete local replace_node = nodes.replace local copy_node = node.copy -local has_attribute = node.has_attribute local chardata = characters.data local collected = false @@ -79,7 +78,7 @@ function nodes.handlers.stripping(head) while current do if current.id == glyph_code then -- it's more efficient to keep track of what needs to be kept - local todo = has_attribute(current,a_stripping) + local todo = current[a_stripping] if todo == 1 then local char = current.char local what = glyphs[char] diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua index d40aed579..764ee0cfb 100644 --- a/tex/context/base/typo-spa.lua +++ b/tex/context/base/typo-spa.lua @@ -15,8 +15,6 @@ local report_spacing = logs.reporter("typesetting","spacing") local nodes, fonts, node = nodes, fonts, node -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute local insert_node_before = node.insert_before local insert_node_after = node.insert_after local remove_node = nodes.remove @@ -73,12 +71,12 @@ local function process(namespace,attribute,head) -- penalty followed by glue while start do if start.id == glyph_code then - local attr = has_attribute(start,attribute) + local attr = start[attribute] if attr and attr > 0 then local data = mapping[attr] if data then local map = data.characters[start.char] - unset_attribute(start,attribute) -- needed? + start[attribute] = unsetvalue -- needed? if map then local left = map.left local right = map.right diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index fe68795ec..9b7689ac1 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 : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 03/04/13 18:28:23 +-- merge date : 03/05/13 16:40:59 do -- begin closure to overcome local limits and interference @@ -2209,7 +2209,7 @@ local boolean=boolean function boolean.tonumber(b) if b then return 1 else return 0 end end -function toboolean(str,tolerant) +function toboolean(str,tolerant) if str==nil then return false elseif str==false then @@ -2232,18 +2232,16 @@ function toboolean(str,tolerant) end string.toboolean=toboolean function string.booleanstring(str) - if str==nil then - return false - elseif str==false then + if str=="0" then return false - elseif str==true then - return true - elseif str=="true" then + elseif str=="1" then return true - elseif str=="false" then + elseif str=="" then return false - elseif str==0 then + elseif str=="false" then return false + elseif str=="true" then + return true elseif (tonumber(str) or 0)>0 then return true else -- cgit v1.2.3