diff options
author | Hans Hagen <pragma@wxs.nl> | 2020-03-10 15:42:39 +0100 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2020-03-10 15:42:39 +0100 |
commit | 0b0256403b7e111df0ecdb8ca589f20df787dacd (patch) | |
tree | 49b02d80ccbb26aa235351ae3dfd2d099635ea72 /tex | |
parent | 631a40d69d7fb4e5beff90039d21da5472dd1020 (diff) | |
download | context-0b0256403b7e111df0ecdb8ca589f20df787dacd.tar.gz |
2020-03-10 14:47:00
Diffstat (limited to 'tex')
68 files changed, 1369 insertions, 1316 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 682160a36..5c13c209d 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2020.02.17 12:06} +\newcontextversion{2020.03.10 14:44} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index bc6869fec..db1940639 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2020.02.17 12:06} +\edef\contextversion{2020.03.10 14:44} %D For those who want to use this: diff --git a/tex/context/base/mkii/syst-new.mkii b/tex/context/base/mkii/syst-new.mkii index 34b535b90..5a515dbab 100644 --- a/tex/context/base/mkii/syst-new.mkii +++ b/tex/context/base/mkii/syst-new.mkii @@ -315,17 +315,25 @@ % awaiting the definitive implementation +\let\normalelapsedtime\elapsedtime + \ifx\resettimer\undefined \let\resettimer \relax \newcount\elapsedtime \fi \newcount\featuretest - -\def\testfeature#1#2% - {\def\dotestfeature - {\advance\featuretest \plusone - \ifnum\featuretest>#1\else#2\expandafter\dotestfeature\fi}% +\newcount\noffeaturetest +\newcount\featuretesttime + +\def\testfeature#1#2% brought in sync with mkiv + {\noffeaturetest#1\relax + \def\dotestfeature + {\advance\featuretest\plusone + \ifnum\featuretest>\noffeaturetest\else#2\expandafter\dotestfeature\fi}% + \def\notestfeature + {\advance\featuretest\plusone + \ifnum\featuretest>\noffeaturetest\else\expandafter\notestfeature\fi}% \retestfeature} \def\retestfeature % timer support is new per 10/5/2005 @@ -333,12 +341,22 @@ \ifcase\interactionmode\let\wait\relax\fi \writestatus\m!systems{starting feature test}\wait \resettimer + \bgroup + \featuretest\zerocount \notestfeature + \global\featuretesttime\normalelapsedtime + \egroup + \resettimer + \bgroup \featuretest\zerocount \dotestfeature - \writestatus\m!systems{feature test done (\elapsedseconds s)}% + \egroup + \global\featuretesttime\numexpr\normalelapsedtime-\featuretesttime\relax + \writestatus\m!systems{feature test done (used: \elapsedseconds s)}% \wait \egroup} -\def\elapsedseconds{\expandafter\withoutpt\the\dimexpr\elapsedtime sp\relax} +\def\elapsedseconds{\expandafter\withoutpt\the\dimexpr\featuretesttime sp\relax} + +\let\elapsedtime\elapsedseconds \def\showtimer#1% {\writestatus{runtime}{\elapsedseconds\space s / #1}} diff --git a/tex/context/base/mkiv/attr-col.lua b/tex/context/base/mkiv/attr-col.lua index 15590dccc..88358aeb7 100644 --- a/tex/context/base/mkiv/attr-col.lua +++ b/tex/context/base/mkiv/attr-col.lua @@ -259,12 +259,19 @@ local function graytohsv(s) return 0, 0, s end +local function hwbtorgb(hue,black,white) + local r, g, b = hsvtorgb(hue,1,.5) + local f = 1 - white - black + return f * r + white, f * g + white , f * b + white +end + colors.rgbtocmyk = rgbtocmyk colors.rgbtogray = rgbtogray colors.cmyktorgb = cmyktorgb colors.cmyktogray = cmyktogray colors.rgbtohsv = rgbtohsv colors.hsvtorgb = hsvtorgb +colors.hwbtorgb = hwbtorgb colors.hsvtogray = hsvtogray colors.graytohsv = graytohsv diff --git a/tex/context/base/mkiv/attr-ini.mkiv b/tex/context/base/mkiv/attr-ini.mkiv index 49a1126b9..6889f9e63 100644 --- a/tex/context/base/mkiv/attr-ini.mkiv +++ b/tex/context/base/mkiv/attr-ini.mkiv @@ -160,7 +160,7 @@ %D performance is better when we put frequently accessed attributes at the front. %D So, we might move more here. -\definesystemattribute [state] % nomath +%definesystemattribute [state] % nomath \definesystemattribute [color] [public] % global \definesystemattribute [colormodel] [public,global] % \definesystemattribute [skip] diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua index 00c939b99..22822d7dd 100644 --- a/tex/context/base/mkiv/back-exp.lua +++ b/tex/context/base/mkiv/back-exp.lua @@ -2178,7 +2178,7 @@ do local n = 0 for k, v in next, a do n = n + 1 - r[n] = f_attribute(k,v) -- lpegmatch(p_escaped,v) + r[n] = f_attribute(k,tostring(v)) -- tostring because of %q end sort(r) return concat(r,"") @@ -2189,7 +2189,7 @@ do local n = 0 for k, v in next, a do n = n + 1 - r[n] = f_property(exportproperties,k,v) + r[n] = f_property(exportproperties,k,tostring(v)) -- tostring because of %q end sort(r) return concat(r,"") diff --git a/tex/context/base/mkiv/char-utf.lua b/tex/context/base/mkiv/char-utf.lua index 110a4a48c..fb47b5208 100644 --- a/tex/context/base/mkiv/char-utf.lua +++ b/tex/context/base/mkiv/char-utf.lua @@ -25,7 +25,7 @@ educational purposes.</p> local next, type = next, type local gsub, find = string.gsub, string.find local concat, sortedhash, keys, sort = table.concat, table.sortedhash, table.keys, table.sort -local utfchar, utfbyte, utfcharacters, utfvalues = utf.char, utf.byte, utf.characters, utf.values +local utfchar, utfbyte, utfcharacters = utf.char, utf.byte, utf.characters local P, Cs, Cmt, Ct = lpeg.P, lpeg.Cs, lpeg.Cmt, lpeg.Ct if not characters then require("char-def") end diff --git a/tex/context/base/mkiv/cldf-bas.lua b/tex/context/base/mkiv/cldf-bas.lua index 9e789a72f..ac17a9381 100644 --- a/tex/context/base/mkiv/cldf-bas.lua +++ b/tex/context/base/mkiv/cldf-bas.lua @@ -34,6 +34,8 @@ local ctxcore = context.core local variables = interfaces.variables local ctx_flushnode = context.nuts.flush +local ctx_sprint = context.sprint +local txtcatcodes = tex.txtcatcodes local nuts = nodes.nuts local tonode = nuts.tonode @@ -47,6 +49,8 @@ local setattrlist = nuts.setattrlist local texgetcount = tex.getcount local texsetcount = tex.setcount +local is_letter = characters.is_letter + -- a set of basic fast ones function context.setfontid(n) @@ -72,6 +76,14 @@ function context.char(k) -- used as escape too, so don't change to utf end end +function context.safechar(c) + if characters.is_letter[c] then -- not yet loaded + ctx_sprint(c) + else + ctx_sprint(txtcatcodes,c) + end +end + function context.utfchar(k) if type(k) == "string" then k = tonumber(k) diff --git a/tex/context/base/mkiv/colo-ini.lua b/tex/context/base/mkiv/colo-ini.lua index 6b3f515b9..5bfe4635c 100644 --- a/tex/context/base/mkiv/colo-ini.lua +++ b/tex/context/base/mkiv/colo-ini.lua @@ -449,7 +449,8 @@ local function defineprocesscolor(name,str,global,freeze) -- still inconsistent local r = settings.r local g = settings.g local b = settings.b - if r or g or b then + local w = settings.w + if r or g or (b and not w) then -- we can consider a combined rgb cmyk s definition definecolor(name, register_color(name,'rgb', tonumber(r) or 0, tonumber(g) or 0, tonumber(b) or 0), global) else @@ -467,16 +468,21 @@ local function defineprocesscolor(name,str,global,freeze) -- still inconsistent r, g, b = colors.hsvtorgb(tonumber(h) or 0, tonumber(s) or 1, tonumber(v) or 1) -- maybe later native definecolor(name, register_color(name,'rgb',r,g,b), global) else - local x = settings.x or h - if x then - r, g, b = lpegmatch(hexpattern,x) -- can be inlined - if r and g and b then - definecolor(name, register_color(name,'rgb',r,g,b), global) + if w then + r, g, b = colors.hwbtorgb(tonumber(h) or 0, tonumber(b) or 1, tonumber(w) or 1) -- maybe later native + definecolor(name, register_color(name,'rgb',r,g,b), global) + else + local x = settings.x or h + if x then + r, g, b = lpegmatch(hexpattern,x) -- can be inlined + if r and g and b then + definecolor(name, register_color(name,'rgb',r,g,b), global) + else + definecolor(name, register_color(name,'gray',r or 0), global) + end else - definecolor(name, register_color(name,'gray',r or 0), global) + definecolor(name, register_color(name,'gray',tonumber(s) or 0), global) end - else - definecolor(name, register_color(name,'gray',tonumber(s) or 0), global) end end end @@ -520,7 +526,8 @@ local function defineprocesscolordirect(settings) local r = settings.r local g = settings.g local b = settings.b - if r or g or b then + local w = settings.w + if r or g or (b and not w) then -- we can consider a combined rgb cmyk s definition register_color(name,'rgb', r or 0, g or 0, b or 0) else @@ -538,16 +545,21 @@ local function defineprocesscolordirect(settings) r, g, b = colors.hsvtorgb(h or 0, s or 1, v or 1) -- maybe later native register_color(name,'rgb',r,g,b) else - local x = settings.x or h - if x then - r, g, b = lpegmatch(hexpattern,x) -- can be inlined - if r and g and b then - register_color(name,'rgb',r,g,b) + if w then + r, g, b = colors.hwbtorgb((tonumber(h) or 0) / 360, tonumber(b) or 1, tonumber(w) or 1) -- maybe later native + register_color(name,'rgb',r,g,b) + else + local x = settings.x or h + if x then + r, g, b = lpegmatch(hexpattern,x) -- can be inlined + if r and g and b then + register_color(name,'rgb',r,g,b) + else + register_color(name,'gray',r or 0) + end else - register_color(name,'gray',r or 0) + register_color(name,'gray',s or 0) end - else - register_color(name,'gray',s or 0) end end end diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 97d5d2071..7d76e05de 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2020.02.17 12:06} +\newcontextversion{2020.03.10 14:44} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 9cdb78c47..ff4c7f6c6 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.02.17 12:06} +\edef\contextversion{2020.03.10 14:44} \edef\contextkind {beta} %D Kind of special: @@ -140,7 +140,7 @@ %D This needs more checking for clashes: %D %D \starttyping -%D \doifelsefileexists{l-macro-imp-codes.lua}{\registerctxluafile{l-macro-imp-codes}{}}{} +%D \doifelsefileexists{l-macro-imp-codes-luatex.lua}{\registerctxluafile{l-macro-imp-codes-luatex}{}}{} %D \stoptyping \loadmarkfile{supp-dir} diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl index 5cb85c4cd..13e6a100b 100644 --- a/tex/context/base/mkiv/context.mkxl +++ b/tex/context/base/mkiv/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.02.17 12:06} +\edef\contextversion{2020.03.10 14:44} \edef\contextkind {beta} %D Kind of special: @@ -126,7 +126,7 @@ %D This needs more checking for clashes: %D %D \starttyping -%D \doifelsefileexists{l-macro-imp-codes.lua}{\registerctxluafile{l-macro-imp-codes}{}}{} +%D \doifelsefileexists{l-macro-imp-codes-luametatex.lua}{\registerctxluafile{l-macro-imp-codes-luametatex}{}}{} %D \stoptyping \loadmarkfile{supp-dir} diff --git a/tex/context/base/mkiv/data-ini.lua b/tex/context/base/mkiv/data-ini.lua index 0fe70b5f1..2e9010085 100644 --- a/tex/context/base/mkiv/data-ini.lua +++ b/tex/context/base/mkiv/data-ini.lua @@ -217,12 +217,6 @@ end environment.texroot = file.collapsepath(texroot) --- if type(profiler) == "table" and not jit then --- directives.register("system.profile",function() --- profiler.start("luatex-profile.log") --- end) --- end - -- a forward definition -- Because we use resolvers.resolve a lot later on, we will implement the basics here and diff --git a/tex/context/base/mkiv/data-tex.lua b/tex/context/base/mkiv/data-tex.lua index e7c4941ca..e4795d09d 100644 --- a/tex/context/base/mkiv/data-tex.lua +++ b/tex/context/base/mkiv/data-tex.lua @@ -84,6 +84,19 @@ local function splitlines(str) return lpegmatch(linesplitter,str) end +-- not really a bottleneck, but it might become: +-- +-- local splitlines = string.splitlines or function(str) +-- return lpegmatch(linesplitter,str) +-- end +-- +-- directives.register("system.linesplitmethod",function(v) +-- linesplitter = linesplitters[tonumber(v) or 1] or linesplitters[1] +-- splitlines = function(str) +-- return lpegmatch(linesplitter,str) +-- end +-- end) + ----------------------------------------- local wideutfcoding = { diff --git a/tex/context/base/mkiv/driv-shp.lua b/tex/context/base/mkiv/driv-shp.lua index a4e36105d..5cf7cfcc6 100644 --- a/tex/context/base/mkiv/driv-shp.lua +++ b/tex/context/base/mkiv/driv-shp.lua @@ -87,7 +87,6 @@ local dir_code <const> = nodecodes.dir local disc_code <const> = nodecodes.disc local math_code <const> = nodecodes.math local rule_code <const> = nodecodes.rule -local marginkern_code <const> = nodecodes.marginkern local whatsit_code <const> = nodecodes.whatsit ----- penalty_code <const> = nodecodes.penalty ----- boundary_code <const> = nodecodes.boundary @@ -317,7 +316,8 @@ local function flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommand code(font,char,pos_h,pos_v) end elseif command == "node" then - hlist_out(packet[2]) + local h = packet[2] + hlist_out(h,getlist(h)) elseif command == "image" then -- doesn't work because intercepted by engine so we use a different -- mechanism (for now) @@ -364,7 +364,7 @@ flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r local width, height, depth, naturalwidth if current then - naturalwidth, height, depth, factor = getwhd(current,true) + naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width if factor == 0 then width = naturalwidth else @@ -549,12 +549,12 @@ local hlist_out, vlist_out do boxheight, boxdepth = getwhd(this_box) - local cur_h = 0 - local cur_v = 0 + local cur_h = 0 + local cur_v = 0 - if not current then - current = getlist(this_box) - end + -- if not current then + -- current = getlist(this_box) + -- end -- we can encounter localpar, boundary and penalty nodes but a special -- iterator over content nodes won't save much @@ -572,7 +572,6 @@ local hlist_out, vlist_out do pos_v = ref_v - (cur_v - y_offset) -- synced end - -- local wd, ht, dp = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r) local wd = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r) cur_h = cur_h + wd elseif id == glue_code then @@ -653,9 +652,9 @@ local hlist_out, vlist_out do outer_doing_leaders = doing_leaders doing_leaders = true if getid(leader) == vlist_code then - vlist_out(leader) + vlist_out(leader,getlist(leader)) else - hlist_out(leader) + hlist_out(leader,getlist(leader)) end doing_leaders = outer_doing_leaders cur_h = cur_h + width + lx @@ -758,7 +757,7 @@ local hlist_out, vlist_out do elseif id == kern_code then local kern, factor = getkern(current,true) if kern ~= 0 then - if factor and factor ~= 0 then + if factor ~= 0 then cur_h = cur_h + (1.0 + factor/1000000.0) * kern else cur_h = cur_h + kern @@ -866,8 +865,6 @@ local hlist_out, vlist_out do elseif subtype == openwhatsit_code then flushopenout(current) end - elseif id == marginkern_code then - cur_h = cur_h + getkern(current) -- elseif id == localpar_code and start_of_par(current) then -- local pardir = getdirection(current) or lefttoright_code -- if pardir == righttoleft_code then @@ -901,10 +898,9 @@ local hlist_out, vlist_out do boxheight, boxdepth = getwhd(this_box) - local cur_h = 0 - local cur_v = - boxheight - - local top_edge = cur_v + local cur_h = 0 + local cur_v = - boxheight + local top_edge = cur_v if pos_r == righttoleft_code then pos_h = ref_h - cur_h @@ -914,9 +910,9 @@ local hlist_out, vlist_out do pos_v = ref_v - cur_v -- synced - if not current then - current = getlist(this_box) - end + -- if not current then + -- current = getlist(this_box) + -- end -- while current do -- local id = getid(current) @@ -984,9 +980,9 @@ local hlist_out, vlist_out do outer_doing_leaders = doing_leaders doing_leaders = true if getid(leader) == vlist_code then - vlist_out(leader) + vlist_out(leader,getlist(leader)) else - hlist_out(leader) + hlist_out(leader,getlist(leader)) end doing_leaders = outer_doing_leaders cur_v = cur_v + total + ly @@ -1272,9 +1268,9 @@ function drivers.converters.lmtx(driver,box,smode,objnum,specification) lastfont = nil -- this forces a sync each page / object if getid(box) == vlist_code then - vlist_out(box) + vlist_out(box,getlist(box)) else - hlist_out(box) + hlist_out(box,getlist(box)) end ::DONE:: diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua index bf14dd309..6f8354de8 100644 --- a/tex/context/base/mkiv/font-ctx.lua +++ b/tex/context/base/mkiv/font-ctx.lua @@ -83,8 +83,7 @@ local nextchar = nuts.traversers.char local getattr = nuts.getattr local setattr = nuts.setattr -local getprop = nuts.getprop -local setprop = nuts.setprop +local getstate = nuts.getstate local setsubtype = nuts.setsubtype local texgetdimen = tex.getdimen @@ -109,6 +108,7 @@ local parameters = hashes.parameters local designsizefilename = fontgoodies.designsizes.filename local ctx_char = context.char +local ctx_safechar = context.safechar local ctx_getvalue = context.getvalue local otffeatures = otf.features @@ -320,6 +320,7 @@ function definers.resetnullfont() parameters.x_height = 0 -- 5 parameters.quad = 0 -- 6 parameters.extra_space = 0 -- 7 + parameters.designsize = 655360 -- constructors.enhanceparameters(parameters) -- official copies for us -- @@ -2105,7 +2106,7 @@ do -- else too many locals implement { name = "tochar", - actions = { tochar, context }, + actions = { tochar, ctx_safechar }, arguments = "string", } @@ -2651,7 +2652,6 @@ do 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 { } local glyph_code = nodes.nodecodes.glyph @@ -2680,7 +2680,7 @@ do head = tonut(head) local model = getattr(head,a_colormodel) or 1 for glyph in nextchar, head do - local a = getprop(glyph,a_state) + local a = getstate(glyph) if a then local name = colornames[a] if name then diff --git a/tex/context/base/mkiv/font-hsh.lua b/tex/context/base/mkiv/font-hsh.lua index 8d1e85145..7e90e1502 100644 --- a/tex/context/base/mkiv/font-hsh.lua +++ b/tex/context/base/mkiv/font-hsh.lua @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['font-hsh'] = { local rawget = rawget local setmetatableindex = table.setmetatableindex -local currentfont = font.current +local currentfont = font and font.current -- used in the web service local allocate = utilities.storage.allocate local fonts = fonts @@ -103,7 +103,7 @@ setmetatableindex(identifiers, function(t,k) return k == true and identifiers[currentfont()] or nulldata end) -do +if font then -- to be used @@ -370,8 +370,12 @@ setmetatableindex(variants, function(t,k) end end) -function font.getfont(id) - return identifiers[id] +if font then + + function font.getfont(id) + return identifiers[id] + end + end -- font.setfont = currentfont -- bah, no native 'setfont' as name diff --git a/tex/context/base/mkiv/font-imp-tweaks.lua b/tex/context/base/mkiv/font-imp-tweaks.lua new file mode 100644 index 000000000..9cbda97fa --- /dev/null +++ b/tex/context/base/mkiv/font-imp-tweaks.lua @@ -0,0 +1,25 @@ +if not modules then modules = { } end modules ['font-imp-tweaks'] = { + version = 1.001, + comment = "companion to font-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if not context then return end + +local addfeature = fonts.handlers.otf.addfeature + +addfeature { + name = "uppercasing", + type = "substitution", + prepend = true, + data = characters.uccodes +} + +addfeature { + name = "lowercasing", + type = "substitution", + prepend = true, + data = characters.lccodes +} diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi index 8953c9b32..b3cade5ff 100644 --- a/tex/context/base/mkiv/font-lib.mkvi +++ b/tex/context/base/mkiv/font-lib.mkvi @@ -24,8 +24,6 @@ \registerctxluafile{font-cid}{} % cid maps \registerctxluafile{font-map}{optimize} -% the otf font loader: - % helpers \registerctxluafile{font-otr}{optimize} % opentype fontloader @@ -118,6 +116,7 @@ \registerctxluafile{font-imp-italics}{} \registerctxluafile{font-imp-dimensions}{} \registerctxluafile{font-imp-spacekerns}{} +\registerctxluafile{font-imp-tweaks}{} \doifelsefileexists{font-imp-scripts.lua} { \registerctxluafile{font-imp-scripts}{} @@ -175,6 +174,41 @@ \setbox\zerocount\hpack{\typethreemacro}% \setbox\zerocount\hpack{\raise\dp\zerocount\box\zerocount}% } - - \protect \endinput + +% Some simple test with an upgraded data handling. Because in the +% end most users will use lmtx we can sacrifice some performance +% in mkiv unless I decide to ship different ots files. The gain +% in lmtx is hard to determine but the fact that it runs about +% as fast as luametatex looks quite ok, given the fact that the +% backend has a significant performance hit. (We're talking of +% two changes actually, also the state handling got changed which +% has a bit more impact on lmtx.) +% +% \starttext \start +% +% Performance can be better in luatex when I decide to backport +% but it is somewhat context (font) specific which contradicts +% the fact that we don't want to add package specific features +% to the engines (which in the end could hurt the other packages) +% so that might never happen. +% +% latin modern (fastest time): +% +% old: luatex 2.979 | luametatex 3.198 +% new: luatex 3.399 | luametatex 3.198 +% +% % \setupbodyfont[pagella] \smallcaps +% +% pagella (fastest time): +% +% old: luatex 5.098 | luametatex 5.104 +% new: luatex 6.178 | luametatex 4.975 +% +% \testfeatureonce{1000}{\samplefile{tufte}\par} +% +% \page \elapsedtime \stop \stoptext +% +% In then end this upgrade was rejected and the experimental code +% was thrashed (pending possible future lmtx specific variants of +% font-*.lua). diff --git a/tex/context/base/mkiv/font-map.lua b/tex/context/base/mkiv/font-map.lua index d931b822e..84a28a8b7 100644 --- a/tex/context/base/mkiv/font-map.lua +++ b/tex/context/base/mkiv/font-map.lua @@ -12,7 +12,7 @@ local match, format, find, concat, gsub, lower = string.match, string.format, st local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match local formatters = string.formatters local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys -local rshift = bit32.rshift +local idiv = number.idiv local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end) local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_mapping = v end) @@ -23,44 +23,23 @@ local report_fonts = logs.reporter("fonts","loading") -- not otf only local force_ligatures = false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures = v end) -local fonts = fonts or { } -local mappings = fonts.mappings or { } -fonts.mappings = mappings - -local allocate = utilities.storage.allocate - ---[[ldx-- -<p>Eventually this code will disappear because map files are kind -of obsolete. Some code may move to runtime or auxiliary modules.</p> -<p>The name to unciode related code will stay of course.</p> ---ldx]]-- - --- local function loadlumtable(filename) -- will move to font goodies --- local lumname = file.replacesuffix(file.basename(filename),"lum") --- local lumfile = resolvers.findfile(lumname,"map") or "" --- if lumfile ~= "" and lfs.isfile(lumfile) then --- if trace_loading or trace_mapping then --- report_fonts("loading map table %a",lumfile) --- end --- lumunic = dofile(lumfile) --- return lumunic, lumfile --- end --- end +local fonts = fonts or { } +local mappings = fonts.mappings or { } +fonts.mappings = mappings -local hex = R("AF","af","09") ------ hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end ------ hexsix = (hex*hex*hex*hex*hex*hex) / function(s) return tonumber(s,16) end -local hexfour = (hex*hex*hex^-2) / function(s) return tonumber(s,16) end -local hexsix = (hex*hex*hex^-4) / function(s) return tonumber(s,16) end -local dec = (R("09")^1) / tonumber -local period = P(".") -local unicode = (P("uni") + P("UNI")) * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true)) -- base planes -local ucode = (P("u") + P("U") ) * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true)) -- extended -local index = P("index") * dec * Cc(false) +local allocate = utilities.storage.allocate -local parser = unicode + ucode + index +local hex = R("AF","af","09") +local hexfour = (hex*hex*hex^-2) / function(s) return tonumber(s,16) end +local hexsix = (hex*hex*hex^-4) / function(s) return tonumber(s,16) end +local dec = (R("09")^1) / tonumber +local period = P(".") +local unicode = (P("uni") + P("UNI")) * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true)) -- base planes +local ucode = (P("u") + P("U") ) * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true)) -- extended +local index = P("index") * dec * Cc(false) -local parsers = { } +local parser = unicode + ucode + index +local parsers = { } local function makenameparser(str) if not str or str == "" then @@ -75,82 +54,24 @@ local function makenameparser(str) end end -local f_single = formatters["%04X"] -local f_double = formatters["%04X%04X"] - --- floor(x/256) => rshift(x, 8) --- floor(x/1024) => rshift(x,10) - --- 0.684 0.661 0,672 0.650 : cache at lua end (more mem) --- 0.682 0,672 0.698 0.657 : no cache (moderate mem i.e. lua strings) --- 0.644 0.647 0.655 0.645 : convert in c (less mem in theory) - --- local tounicodes = table.setmetatableindex(function(t,unicode) --- local s --- if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then --- s = f_single(unicode) --- else --- unicode = unicode - 0x10000 --- s = f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00) --- end --- t[unicode] = s --- return s --- end) --- --- local function tounicode16(unicode,name) --- local s = tounicodes[unicode] --- if s then --- return s --- else --- report_fonts("can't convert %a in %a into tounicode",unicode,name) --- end --- end --- --- local function tounicode16sequence(unicodes,name) --- local t = { } --- for l=1,#unicodes do --- local u = unicodes[l] --- local s = tounicodes[u] --- if s then --- t[l] = s --- else --- report_fonts ("can't convert %a in %a into tounicode",u,name) --- return --- end --- end --- return concat(t) --- end --- --- local function tounicode(unicode,name) --- if type(unicode) == "table" then --- local t = { } --- for l=1,#unicode do --- local u = unicode[l] --- local s = tounicodes[u] --- if s then --- t[l] = s --- else --- report_fonts ("can't convert %a in %a into tounicode",u,name) --- return --- end --- end --- return concat(t) --- else --- local s = tounicodes[unicode] --- if s then --- return s --- else --- report_fonts("can't convert %a in %a into tounicode",unicode,name) --- end --- end --- end +local f_single = formatters["%04X"] +local f_double = formatters["%04X%04X"] +local s_unknown = "FFFD" local function tounicode16(unicode) if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then return f_single(unicode) + elseif unicode >= 0x00E000 and unicode <= 0x00F8FF then + return s_unknown + elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFF then + return s_unknown + elseif unicode >= 0x100000 and unicode <= 0x10FFFF then + return s_unknown + elseif unicode >= 0x00D800 and unicode <= 0x00DFFF then + return s_unknown else unicode = unicode - 0x10000 - return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00) + return f_double(idiv(k,0x400)+0xD800,unicode%0x400+0xDC00) end end @@ -160,132 +81,33 @@ local function tounicode16sequence(unicodes) local u = unicodes[l] if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then t[l] = f_single(u) + elseif unicode >= 0x00E000 and unicode <= 0x00F8FF then + t[l] = s_unknown + elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFF then + t[l] = s_unknown + elseif unicode >= 0x100000 and unicode <= 0x10FFFF then + t[l] = s_unknown + -- elseif unicode >= 0x00D800 and unicode <= 0x00DFFF then + elseif unicode >= 0x00D7FF and unicode <= 0x00DFFF then + t[l] = s_unknown else u = u - 0x10000 - t[l] = f_double(rshift(u,10)+0xD800,u%1024+0xDC00) + t[l] = f_double(idiv(k,0x400)+0xD800,u%0x400+0xDC00) end end return concat(t) end --- local function tounicode(unicode) --- if type(unicode) == "table" then --- local t = { } --- for l=1,#unicode do --- local u = unicode[l] --- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then --- t[l] = f_single(u) --- else --- u = u - 0x10000 --- t[l] = f_double(rshift(u,10)+0xD800,u%1024+0xDC00) --- end --- end --- return concat(t) --- else --- if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then --- return f_single(unicode) --- else --- unicode = unicode - 0x10000 --- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00) --- end --- end --- end - -local unknown = f_single(0xFFFD) - --- local function tounicode(unicode) --- if type(unicode) == "table" then --- local t = { } --- for l=1,#unicode do --- t[l] = tounicode(unicode[l]) --- end --- return concat(t) --- elseif unicode >= 0x00E000 and unicode <= 0x00F8FF then --- return unknown --- elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFF then --- return unknown --- elseif unicode >= 0x100000 and unicode <= 0x10FFFF then --- return unknown --- elseif unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then --- return f_single(unicode) --- else --- unicode = unicode - 0x10000 --- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00) --- end --- end - --- local hash = table.setmetatableindex(function(t,k) --- local v --- if k >= 0x00E000 and k <= 0x00F8FF then --- v = unknown --- elseif k >= 0x0F0000 and k <= 0x0FFFFF then --- v = unknown --- elseif k >= 0x100000 and k <= 0x10FFFF then --- v = unknown --- elseif k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then --- v = f_single(k) --- else --- local k = k - 0x10000 --- v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00) --- end --- t[k] = v --- return v --- end) --- --- table.makeweak(hash) --- --- local function tounicode(unicode) --- if type(unicode) == "table" then --- local t = { } --- for l=1,#unicode do --- t[l] = hash[unicode[l]] --- end --- return concat(t) --- else --- return hash[unicode] --- end --- end local hash = { } local conc = { } --- table.makeweak(hash) - --- table.setmetatableindex(hash,function(t,k) --- if type(k) == "table" then --- local n = #k --- for l=1,n do --- conc[l] = hash[k[l]] --- end --- return concat(conc,"",1,n) --- end --- local v --- if k >= 0x00E000 and k <= 0x00F8FF then --- v = unknown --- elseif k >= 0x0F0000 and k <= 0x0FFFFF then --- v = unknown --- elseif k >= 0x100000 and k <= 0x10FFFF then --- v = unknown --- elseif k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then --- v = f_single(k) --- else --- local k = k - 0x10000 --- v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00) --- end --- t[k] = v --- return v --- end) --- --- local function tounicode(unicode) --- return hash[unicode] --- end - table.setmetatableindex(hash,function(t,k) if k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then v = f_single(k) else local k = k - 0x10000 - v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00) + v = f_double(idiv(k,0x400)+0xD800,k%0x400+0xDC00) end t[k] = v return v @@ -299,11 +121,14 @@ local function tounicode(k) end return concat(conc,"",1,n) elseif k >= 0x00E000 and k <= 0x00F8FF then - return unknown + return s_unknown elseif k >= 0x0F0000 and k <= 0x0FFFFF then - return unknown + return s_unknown elseif k >= 0x100000 and k <= 0x10FFFF then - return unknown + return s_unknown + -- elseif k >= 0x00D800 and k <= 0x00DFFF then + elseif k >= 0x00D7FF and k <= 0x00DFFF then + return s_unknown else return hash[k] end @@ -314,7 +139,6 @@ local function fromunicode16(str) return tonumber(str,16) else local l, r = match(str,"(....)(....)") - -- return (tonumber(l,16))*0x400 + tonumber(r,16) - 0xDC00 return 0x10000 + (tonumber(l,16)-0xD800)*0x400 + tonumber(r,16) - 0xDC00 end end diff --git a/tex/context/base/mkiv/font-ocl.lua b/tex/context/base/mkiv/font-ocl.lua index eef221e46..1890e5ec5 100644 --- a/tex/context/base/mkiv/font-ocl.lua +++ b/tex/context/base/mkiv/font-ocl.lua @@ -49,6 +49,10 @@ if context then else + -- Actually we don't need a generic branch at all because (according the the + -- internet) other macro packages rely on hb for emoji etc and never used this + -- feature of the font loader. So maybe I should just remove this from generic. + local tounicode = fonts.mappings.tounicode16 function otf.getactualtext(s) diff --git a/tex/context/base/mkiv/font-ogr.lua b/tex/context/base/mkiv/font-ogr.lua index b45728c6c..94cf91494 100644 --- a/tex/context/base/mkiv/font-ogr.lua +++ b/tex/context/base/mkiv/font-ogr.lua @@ -83,6 +83,8 @@ do return slot, droppedin, d_tfmdata, d_properties end + -- todo: delay this, in which case we can be leaner and meaner + function dropins.clone(method,tfmdata,shapes,...) -- by index if method and shapes then local characters = tfmdata.characters @@ -456,7 +458,7 @@ local initializeoverlay do local idx = 255 local slot = 0 -- - -- todo: delay + -- maybe delay in which case we have less fonts as we can be sparse -- for k, v in next, characters do local index = v.index diff --git a/tex/context/base/mkiv/font-osd.lua b/tex/context/base/mkiv/font-osd.lua index b97ac9c6f..87453d9e2 100644 --- a/tex/context/base/mkiv/font-osd.lua +++ b/tex/context/base/mkiv/font-osd.lua @@ -113,6 +113,8 @@ local setprev = nuts.setprev local setchar = nuts.setchar local getprop = nuts.getprop local setprop = nuts.setprop +local getstate = nuts.getstate +local setstate = nuts.setstate local ischar = nuts.ischar @@ -128,7 +130,6 @@ local unsetvalue = attributes.unsetvalue local fontdata = fonts.hashes.identifiers -local a_state = attributes.private('state') local a_syllabe = attributes.private('syllabe') local dotted_circle = 0x25CC @@ -958,7 +959,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) current = start else current = getnext(n) - setprop(start,a_state,s_rphf) + setstate(start,s_rphf) end end @@ -993,9 +994,9 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) local nextcurrent = copy_node(current) copyinjection(nextcurrent,current) -- KE: necessary? HH: probably not as positioning comes later and we rawget/set setlink(tempcurrent,nextcurrent) - setprop(tempcurrent,a_state,s_blwf) + setstate(tempcurrent,s_blwf) tempcurrent = processcharacters(tempcurrent,font) - setprop(tempcurrent,a_state,unsetvalue) + setstate(tempcurrent,unsetvalue) if getchar(next) == getchar(tempcurrent) then flush_list(tempcurrent) if show_syntax_errors then @@ -1021,7 +1022,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) -- find base consonant local char = getchar(current) if consonant[char] then - setprop(current,a_state,s_half) + setstate(current,s_half) if not firstcons then firstcons = current end @@ -1030,10 +1031,10 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) base = current elseif blwfcache[char] then -- consonant has below-base form - setprop(current,a_state,s_blwf) + setstate(current,s_blwf) elseif pstfcache[char] then -- consonant has post-base form - setprop(current,a_state,s_pstf) + setstate(current,s_pstf) else base = current end @@ -1107,15 +1108,15 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) while current ~= stop do local next = getnext(current) if next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwnj then - setprop(current,a_state,unsetvalue) + setstate(current,unsetvalue) end current = next end - if base ~= stop and getprop(base,a_state) then -- a_state can also be init + if base ~= stop and getstate(base) then -- state can also be init local next = getnext(base) if halant[getchar(next)] and not (next ~= stop and getchar(getnext(next)) == c_zwj) then - setprop(base,a_state,unsetvalue) + setstate(base,unsetvalue) end end @@ -1261,7 +1262,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) end bn = next end - if getprop(current,a_state) == s_rphf then + if getstate(current,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 @@ -1357,7 +1358,7 @@ function handlers.devanagari_reorder_matras(head,start) -- no leak local char = ischar(current,startfont) local next = getnext(current) if char and getprop(current,a_syllabe) == startattr then - if halant[char] then -- a_state can also be init + if halant[char] then -- state can also be init if next then local char = ischar(next,startfont) if char and zw_char[char] and getprop(next,a_syllabe) == startattr then @@ -1373,7 +1374,7 @@ function handlers.devanagari_reorder_matras(head,start) -- no leak -- setlink(current,start,next) -- maybe start = startnext break - -- elseif consonant[char] and ( not getprop(current,a_state) or getprop(current,a_state) == s_init) then + -- elseif consonant[char] and (not getstate(current) or getstate(current,s_init) then -- startnext = getnext(start) -- head = remove_node(head,start) -- if current == head then @@ -1473,7 +1474,7 @@ function handlers.devanagari_reorder_reph(head,start) while current do local char = ischar(current,startfont) if char and getprop(current,a_syllabe) == startattr then - if consonant[char] and not getprop(current,a_state) == s_pref then + if consonant[char] and not getstate(current,s_pref) then startnext = getnext(start) head = remove_node(head,start) setlink(current,start) @@ -1504,7 +1505,7 @@ function handlers.devanagari_reorder_reph(head,start) while current do local char = ischar(current,startfont) if char and getprop(current,a_syllabe) == startattr then - if getprop(current,a_state) == s_pstf then -- post-base + if getstate(current,s_pstf) then -- post-base startnext = getnext(start) head = remove_node(head,start) setlink(getprev(current),start) @@ -1547,7 +1548,7 @@ function handlers.devanagari_reorder_reph(head,start) while current do local char = ischar(current,startfont) if char and getprop(current,a_syllabe) == startattr then - local state = getprop(current,a_state) + local state = getstate(current) if before_subscript[rephbase] and (state == s_blwf or state == s_pstf) then c = current elseif after_subscript[rephbase] and (state == s_pstf) then @@ -1628,7 +1629,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) local char = ischar(current,startfont) local next = getnext(current) if char and getprop(current,a_syllabe) == startattr then - if halant[char] then -- a_state can also be init + if halant[char] then -- state can also be init if next then local char = ischar(next,startfont) if char and zw_char[char] and getprop(next,a_syllabe) == startattr then @@ -1645,7 +1646,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) reordered_pre_base_reordering_consonants[start] = true start = startnext return head, start, true - -- elseif consonant[char] and ( not getprop(current,a_state) or getprop(current,a_state) == s_init) then + -- elseif consonant[char] and (not getstate(current) or getstate(current,s_init)) then -- startnext = getnext(start) -- head = remove_node(head,start) -- if current == head then @@ -1668,7 +1669,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) local current = getprev(start) while current and getprop(current,a_syllabe) == startattr do local char = ischar(current) - if ( not dependent_vowel[char] and not getprop(current,a_state) or getprop(current,a_state) == s_init) then + if (not dependent_vowel[char] and (not getstate(current) or getstate(current,s_init))) then startnext = getnext(start) head = remove_node(head,start) if current == head then @@ -1764,7 +1765,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas if afternext and zw_char[getchar(afternext)] then -- ZWJ and ZWNJ prevent creation of reph current = afternext -- getnext(next) elseif current == start then - setprop(current,a_state,s_rphf) + setstate(current,s_rphf) current = next else current = next @@ -1784,9 +1785,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas if found then -- pre-base: pref Halant + Consonant local next = getnext(current) if found[getchar(next)] or contextchain(found, next) then - if (not getprop(current,a_state) and not getprop(next,a_state)) then --KE: a_state can also be init... - setprop(current,a_state,s_pref) - setprop(next,a_state,s_pref) + if (not getstate(current) and not getstate(next)) then --KE: state can also be init... + setstate(current,s_pref) + setstate(next,s_pref) current = next end end @@ -1806,8 +1807,8 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas if found[getchar(next)] or contextchain(found, next) then if next ~= stop and getchar(getnext(next)) == c_zwnj then -- zwnj prevent creation of half current = next - elseif (not getprop(current,a_state)) then --KE: a_state can also be init... - setprop(current,a_state,s_half) + elseif (not getstate(current)) then --KE: state can also be init... + setstate(current,s_half) if not halfpos then halfpos = current end @@ -1828,9 +1829,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas if found then local next = getnext(current) if found[getchar(next)] or contextchain(found, next) then - if (not getprop(current,a_state) and not getprop(next,a_state)) then --KE: a_state can also be init... - setprop(current,a_state,s_blwf) - setprop(next,a_state,s_blwf) + if (not getstate(current) and not getstate(next)) then --KE: state can also be init... + setstate(current,s_blwf) + setstate(next,s_blwf) current = next subpos = current end @@ -1849,9 +1850,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas if found then local next = getnext(current) if found[getchar(next)] or contextchain(found, next) then - if (not getprop(current,a_state) and not getprop(next,a_state)) then --KE: a_state can also be init... - setprop(current,a_state,s_pstf) - setprop(next,a_state,s_pstf) + if (not getstate(current) and not getstate(next)) then -- KE: state can also be init... + setstate(current,s_pstf) + setstate(next,s_pstf) current = next postpos = current end @@ -1865,7 +1866,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas local current, base, firstcons = start, nil, nil - if getprop(start,a_state) == s_rphf then + if getstate(start,s_rphf) then -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants current = getnext(getnext(start)) end @@ -1895,13 +1896,13 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas local tmp = getnext(next) local changestop = next == stop setnext(next) - setprop(current,a_state,s_pref) + setstate(current,s_pref) current = processcharacters(current,font) - setprop(current,a_state,s_blwf) + setstate(current,s_blwf) current = processcharacters(current,font) - setprop(current,a_state,s_pstf) + setstate(current,s_pstf) current = processcharacters(current,font) - setprop(current,a_state,unsetvalue) + setstate(current,unsetvalue) if halant[getchar(current)] then setnext(getnext(current),tmp) if show_syntax_errors then @@ -1927,7 +1928,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas firstcons = current end -- check whether consonant has below-base or post-base form or is pre-base reordering Ra - local a = getprop(current,a_state) + local a = getstate(current) if not (a == s_blwf or a == s_pstf or (a ~= s_rphf and a ~= s_blwf and ra[getchar(current)])) then base = current end @@ -1941,13 +1942,13 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas end if not base then - if getprop(start,a_state) == s_rphf then - setprop(start,a_state,unsetvalue) + if getstate(start,s_rphf) then + setstate(start,unsetvalue) end return head, stop, nbspaces else - if getprop(base,a_state) then -- a_state can also be init - setprop(base,a_state,unsetvalue) + if getstate(base) then -- state can also be init + setstate(base,unsetvalue) end basepos = base end @@ -2004,7 +2005,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas local ppos = getprev(pos) -- necessary? while ppos and getprop(ppos,a_syllabe) == getprop(pos,a_syllabe) do - if getprop(ppos,a_state) == s_pref then + if getstate(ppos,s_pref) then pos = ppos end ppos = getprev(ppos) @@ -2086,7 +2087,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas while current ~= last do local char = getchar(current) local cn = getnext(current) - if halant[char] and ra[ischar(cn)] and getprop(cn,a_state) ~= s_rphf and getprop(cn,a_state) ~= s_blwf then + if halant[char] and ra[ischar(cn)] and (not getstate(cn,s_rphf)) and (not getstate(cn,s_blwf)) then if after_main[ischar(cn)] then local prev = getprev(current) local next = getnext(cn) @@ -2730,8 +2731,8 @@ local function method_one(head,font,attr) while current do local char = ischar(current,font) if char then - if n == 0 and not getprop(current,a_state) then - setprop(current,a_state,s_init) + if n == 0 and not getstate(current) then + setstate(current,s_init) end n = n + 1 else @@ -2820,7 +2821,7 @@ local function method_two(head,font,attr) end if not syllableend and show_syntax_errors then local char = ischar(current,font) - if char and not getprop(current,a_state) then -- a_state can also be init + if char and not getstate(current) then -- state can also be init local mark = mark_four[char] if mark then head, current = inject_syntax_error(head,current,char) @@ -2840,8 +2841,8 @@ local function method_two(head,font,attr) while current do local char = ischar(current,font) if char then - if n == 0 and not getprop(current,a_state) then -- a_state can also be init - setprop(current,a_state,s_init) + if n == 0 and not getstate(current) then -- state can also be init + setstate(current,s_init) end n = n + 1 else diff --git a/tex/context/base/mkiv/font-ota.lua b/tex/context/base/mkiv/font-ota.lua index 3d217b3f4..6cbf4bb86 100644 --- a/tex/context/base/mkiv/font-ota.lua +++ b/tex/context/base/mkiv/font-ota.lua @@ -27,8 +27,6 @@ local methods = allocate() analyzers.initializers = initializers analyzers.methods = methods -local a_state = attributes.private('state') - local nuts = nodes.nuts local tonut = nuts.tonut @@ -60,6 +58,26 @@ local registerotffeature = otffeatures.register process features right.</p> --ldx]]-- +local setstate = nuts.setstate +local getstate = nuts.getstate + +if not setstate or not getstate then + -- generic (might move to the nod lib) + setstate = function(n,v) + setprop(n,"state",v) + end + getstate = function(n,v) + local s = getprop(n,"state") + if v then + return s == v + else + return s + end + end + nuts.setstate = setstate + nuts.getstate = getstate +end + -- never use these numbers directly local s_init = 1 local s_rphf = 7 @@ -120,37 +138,37 @@ function analyzers.setstate(head,font) current = tonut(current) while current do local char, id = ischar(current,font) - if char and not getprop(current,a_state) then + if char and not getstate(current) then done = true local d = descriptions[char] if d then if d.class == "mark" then done = true - setprop(current,a_state,s_mark) + setstate(current,s_mark) elseif useunicodemarks and categories[char] == "mn" then done = true - setprop(current,a_state,s_mark) + setstate(current,s_mark) elseif n == 0 then first, last, n = current, current, 1 - setprop(current,a_state,s_init) + setstate(current,s_init) else last, n = current, n+1 - setprop(current,a_state,s_medi) + setstate(current,s_medi) end else -- finish if first and first == last then - setprop(last,a_state,s_isol) + setstate(last,s_isol) elseif last then - setprop(last,a_state,s_fina) + setstate(last,s_fina) end first, last, n = nil, nil, 0 end elseif char == false then -- other font if first and first == last then - setprop(last,a_state,s_isol) + setstate(last,s_isol) elseif last then - setprop(last,a_state,s_fina) + setstate(last,s_fina) end first, last, n = nil, nil, 0 if id == math_code then @@ -160,13 +178,13 @@ function analyzers.setstate(head,font) -- always in the middle .. it doesn't make much sense to assign a property -- here ... we might at some point decide to flag the components when present -- but even then it's kind of bogus - setprop(current,a_state,s_medi) + setstate(current,s_medi) last = current else -- finish if first and first == last then - setprop(last,a_state,s_isol) + setstate(last,s_isol) elseif last then - setprop(last,a_state,s_fina) + setstate(last,s_fina) end first, last, n = nil, nil, 0 if id == math_code then @@ -176,9 +194,9 @@ function analyzers.setstate(head,font) current = getnext(current) end if first and first == last then - setprop(last,a_state,s_isol) + setstate(last,s_isol) elseif last then - setprop(last,a_state,s_fina) + setstate(last,s_fina) end return head, done end @@ -308,91 +326,91 @@ function methods.arab(head,font,attr) current = tonut(current) while current do local char, id = ischar(current,font) - if char and not getprop(current,a_state) then + if char and not getstate(current) then done = true local classifier = classifiers[char] if not classifier then if last then if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end first, last = nil, nil elseif first then if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end first = nil end elseif classifier == s_mark then - setprop(current,a_state,s_mark) + setstate(current,s_mark) elseif classifier == s_isol then if last then if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end first, last = nil, nil elseif first then if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end first = nil end - setprop(current,a_state,s_isol) + setstate(current,s_isol) elseif classifier == s_medi then if first then last = current c_last = classifier - setprop(current,a_state,s_medi) + setstate(current,s_medi) else - setprop(current,a_state,s_init) + setstate(current,s_init) first = current c_first = classifier end elseif classifier == s_fina then if last then - if getprop(last,a_state) ~= s_init then - setprop(last,a_state,s_medi) + if getstate(last) ~= s_init then + setstate(last,s_medi) end - setprop(current,a_state,s_fina) + setstate(current,s_fina) first, last = nil, nil elseif first then - -- if getprop(first,a_state) ~= s_init then + -- if getstate(first) ~= s_init then -- -- needs checking - -- setprop(first,a_state,s_medi) + -- setstate(first,s_medi) -- end - setprop(current,a_state,s_fina) + setstate(current,s_fina) first = nil else - setprop(current,a_state,s_isol) + setstate(current,s_isol) end else -- classifier == s_rest - setprop(current,a_state,s_rest) + setstate(current,s_rest) if last then if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end first, last = nil, nil elseif first then if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end first = nil end @@ -400,18 +418,18 @@ function methods.arab(head,font,attr) else if last then if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end first, last = nil, nil elseif first then if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end first = nil end @@ -423,17 +441,17 @@ function methods.arab(head,font,attr) end if last then if c_last == s_medi or c_last == s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end elseif first then if c_first == s_medi or c_first == s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end end return head, done diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua index c4f89c156..f20a349ee 100644 --- a/tex/context/base/mkiv/font-ots.lua +++ b/tex/context/base/mkiv/font-ots.lua @@ -114,6 +114,14 @@ mechanisms. Both put some constraints on the code here.</p> -- -- Todo: just (0=l2r and 1=r2l) or maybe (r2l = true) +-- Experiments with returning the data with the ischar are positive for lmtx but +-- have a performance hit on mkiv because there we need to wrap ischardata (pending +-- extensions to luatex which is unlikely to happen for such an experiment because +-- we then can't remove it). Actually it might make generic slightly faster. Also, +-- there are some corner cases where a data check comes before a char fetch and +-- we're talking of millions of calls there. At some point I might make a version +-- for lmtx that does it slightly different anyway. + local type, next, tonumber = type, next, tonumber local random = math.random local formatters = string.formatters @@ -184,8 +192,7 @@ local setprev = nuts.setprev local getboth = nuts.getboth local setboth = nuts.setboth local getid = nuts.getid -local getprop = nuts.getprop -local setprop = nuts.setprop +local getstate = nuts.getstate local getsubtype = nuts.getsubtype local setsubtype = nuts.setsubtype local getchar = nuts.getchar @@ -194,15 +201,26 @@ local getdisc = nuts.getdisc local setdisc = nuts.setdisc local getreplace = nuts.getreplace local setlink = nuts.setlink -local getcomponents = nuts.getcomponents -- the original one, not yet node-aux -local setcomponents = nuts.setcomponents -- the original one, not yet node-aux local getwidth = nuts.getwidth local getattr = nuts.getattr local getglyphdata = nuts.getglyphdata +--------------------------------------------------------------------------------------- + +-- Beware: In ConTeXt components no longer are real components. We only keep track of +-- their positions because some complex ligatures might need that. For the moment we +-- use an x_ prefix because for now generic follows the other approach. + +local copy_no_components = nuts.copy_no_components +local copy_only_glyphs = nuts.copy_only_glyphs +local count_components = nuts.count_components +local set_components = nuts.set_components +local get_components = nuts.get_components + +--------------------------------------------------------------------------------------- + local ischar = nuts.ischar -local isglyph = nuts.isglyph local usesfont = nuts.uses_font local insert_node_after = nuts.insert_after @@ -237,7 +255,6 @@ local localpar_code = nodecodes.localpar local discretionarydisc_code = disccodes.discretionary local ligatureglyph_code = glyphcodes.ligature -local a_state = attributes.private('state') local a_noligature = attributes.private("noligature") local injections = nodes.injections @@ -450,32 +467,6 @@ local function appenddisc(disc,list) setdisc(disc,pre,post,replace) end --- start is a mark and we need to keep that one - -local copy_no_components = nuts.copy_no_components -local copy_only_glyphs = nuts.copy_only_glyphs - -local set_components = setcomponents -local take_components = getcomponents - -local function count_components(start,marks) - local char = isglyph(start) - if char then - if getsubtype(start) == ligatureglyph_code then - local i = 0 - local components = getcomponents(start) - while components do - i = i + count_components(components,marks) - components = getnext(components) - end - return i - elseif not marks[char] then - return 1 - end - end - return 0 -end - local function markstoligature(head,start,stop,char) if start == stop and getchar(start) == char then return head, start @@ -531,7 +522,7 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou setlink(prev,base,next) if not discfound then local deletemarks = not skiphash or hasmarks - local components = start + local components = start -- not used local baseindex = 0 local componentindex = 0 local head = base @@ -586,18 +577,19 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou -- anyway local pre, post, replace, pretail, posttail, replacetail = getdisc(discfound,true) if not replace then + -- looks like we never come here as it's not okay local prev = getprev(base) - local comp = take_components(base) + -- local comp = get_components(base) -- already set local copied = copy_only_glyphs(comp) if pre then setlink(discprev,pre) else setnext(discprev) -- also blocks funny assignments end - pre = comp + pre = comp -- is start if post then setlink(posttail,discnext) - setprev(post) + setprev(post) -- nil anyway else post = discnext setprev(discnext) -- also blocks funny assignments @@ -3179,7 +3171,7 @@ local function testrun(disc,t_run,c_run,...) end local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true) local renewed = false - if (post or replace) then -- and prev then -- hm, we can start with a disc + if post or replace then -- and prev then -- hm, we can start with a disc if post then setlink(posttail,next) else @@ -3287,28 +3279,6 @@ local function testrun(disc,t_run,c_run,...) return getnext(disc), renewed end --- We can make some assumptions with respect to discretionaries. First of all it is very --- unlikely that some of the analysis related attributes applies. Then we can also assume --- that the ConTeXt specific dynamic attribute is different, although we do use explicit --- discretionaries (maybe we need to tag those some day). So, at least for now, we don't --- have the following test in the sub runs: --- --- -- local a = getglyhpdata(start) --- -- if a then --- -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute) --- -- else --- -- a = not attribute or getprop(start,a_state) == attribute --- -- end --- -- if a then --- --- but use this instead: --- --- -- local a = getglyphdata(start) --- -- if not a or (a == attr) then --- --- and even that one is probably not needed. However, we can handle interesting --- cases now: --- -- 1{2{\oldstyle\discretionary{3}{4}{5}}6}7\par -- 1{2\discretionary{3{\oldstyle3}}{{\oldstyle4}4}{5{\oldstyle5}5}6}7\par @@ -3420,7 +3390,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) ss = nil end end -lookupmatch = lg + lookupmatch = lg else break end @@ -3431,14 +3401,14 @@ lookupmatch = lg if l and l.ligature then -- so we test for ligature lastd = d end --- why not: if not l then break elseif l.ligature then return d end + -- why not: if not l then break elseif l.ligature then return d end else --- why not: break + -- why not: break -- no match (yet) end else -- go on can be a mixed one --- why not: break + -- why not: break end if lastd then return lastd @@ -3461,7 +3431,7 @@ local function k_run_single(sub,injection,last,font,attr,lookupcache,step,datase if n == last then break end - local char = ischar(n) + local char = ischar(n,font) if char then local lookupmatch = lookupcache[char] if lookupmatch then @@ -3590,7 +3560,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) ss = nil end end -lookupmatch = lg + lookupmatch = lg else break end @@ -3711,26 +3681,6 @@ otf.helpers.pardirstate = pardirstate do - -- reference: - -- - -- local a = attr and getglyphdata(start) - -- if a then - -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute) - -- else - -- a = not attribute or getprop(start,a_state) == attribute - -- end - -- - -- used: - -- - -- local a -- happens often so no assignment is faster - -- if attr then - -- if getglyphdata(start) == attr and (not attribute or getprop(start,a_state) == attribute) then - -- a = true - -- end - -- elseif not attribute or getprop(start,a_state) == attribute then - -- a = true - -- end - -- This is a measurable experimental speedup (only with hyphenated text and multiple -- fonts per processor call), especially for fonts with lots of contextual lookups. @@ -3911,10 +3861,10 @@ do if lookupmatch then local a -- happens often so no assignment is faster if attr then - if getglyphdata(start) == attr and (not attribute or getprop(start,a_state) == attribute) then + if getglyphdata(start) == attr and (not attribute or getstate(start,attribute)) then a = true end - elseif not attribute or getprop(start,a_state) == attribute then + elseif not attribute or getstate(start,attribute) then a = true end if a then @@ -3978,10 +3928,10 @@ do if m then local a -- happens often so no assignment is faster if attr then - if getglyphdata(start) == attr and (not attribute or getprop(start,a_state) == attribute) then + if getglyphdata(start) == attr and (not attribute or getstate(start,attribute)) then a = true end - elseif not attribute or getprop(start,a_state) == attribute then + elseif not attribute or getstate(start,attribute) then a = true end if a then diff --git a/tex/context/base/mkiv/font-oup.lua b/tex/context/base/mkiv/font-oup.lua index 0e7e25808..2c49bc993 100644 --- a/tex/context/base/mkiv/font-oup.lua +++ b/tex/context/base/mkiv/font-oup.lua @@ -1368,65 +1368,6 @@ function readers.pack(data) end end - -- -- This was an experiment to see if we can bypass the luajit limits but loading is - -- -- still an issue due to other limits so we don't use this ... actually it can - -- -- prevent a luajittex crash but i don't care too much about that as we can't use - -- -- that engine anyway then. - -- - -- local function check(t) - -- if type(t) == "table" then - -- local s = sortedkeys(t) - -- local n = #s - -- if n <= 10 then - -- return - -- end - -- local ranges = { } - -- local first, last - -- for i=1,#s do - -- local ti = s[i] - -- if not first then - -- first = ti - -- last = ti - -- elseif ti == last + 1 then - -- last = ti - -- elseif last - first < 10 then - -- -- we could permits a few exceptions - -- return - -- else - -- ranges[#ranges+1] = { first, last } - -- first, last = nil, nil - -- end - -- end - -- if #ranges > 0 then - -- return { - -- ranges = ranges - -- } - -- end - -- end - -- end - -- - -- local function pack_boolean(v) - -- local tag - -- local r = check(v) - -- if r then - -- v = r - -- tag = tabstr_normal(v) - -- else - -- tag = tabstr_boolean(v) - -- end - -- local ht = h[tag] - -- if ht then - -- c[ht] = c[ht] + 1 - -- return ht - -- else - -- nt = nt + 1 - -- t[nt] = v - -- h[tag] = nt - -- c[nt] = 1 - -- return nt - -- end - -- end - local function pack_final(v) -- v == number if c[v] <= criterium then diff --git a/tex/context/base/mkiv/font-pre.mkiv b/tex/context/base/mkiv/font-pre.mkiv index 721c4c6eb..8e2e0a7a9 100644 --- a/tex/context/base/mkiv/font-pre.mkiv +++ b/tex/context/base/mkiv/font-pre.mkiv @@ -855,6 +855,15 @@ % \endgroup} %D \macros +%D {uppercasing, lowercasing} + +\definefontfeature[lowercasing][lowercasing=yes] +\definefontfeature[uppercasing][uppercasing=yes] + +\unexpanded\def\uppercasing{\addff{uppercasing}} +\unexpanded\def\lowercasing{\addff{lowercasing}} + +%D \macros %D {tinyfont} %D %D By default we load the Computer Modern Roman fonts (but diff --git a/tex/context/base/mkiv/l-macro-imp-optimize.lua b/tex/context/base/mkiv/l-macro-imp-optimize.lua index 7d7fafefd..1ecaef7d4 100644 --- a/tex/context/base/mkiv/l-macro-imp-optimize.lua +++ b/tex/context/base/mkiv/l-macro-imp-optimize.lua @@ -33,26 +33,12 @@ if LUAVERSION >= 5.3 and lua.macros then -- We need to check for 64 usage: 0xFFFFFFFFFFFFFFFF (-1) - -- lua.macros.resolvestring [[ - -- #define band(a,b) (a & b) - -- #define bnot(a) (~a & 0xFFFFFFFF) - -- #define bor(a,b) ((a | b) & 0xFFFFFFFF) - -- #define btest(a,b) ((a & b) ~= 0) - -- #define bxor(a,b) ((a ~ b) & 0xFFFFFFFF) - -- #define rshift(a,b) ((a & b) ~= 0) - -- #define extract(a,b,c) ((a >> b) & ~(-1 << c)) - -- #define extract(a,b) ((a >> b) & 0x1)) - -- #define lshift(a,b) ((a << b) & 0xFFFFFFFF) - -- #define rshift(a,b) ((a >> b) & 0xFFFFFFFF) - -- ]] - lua.macros.resolvestring [[ #define band(a,b) ((a)&(b)) #define bnot(a) (~(a)&0xFFFFFFFF) #define bor(a,b) (((a)|(b))&0xFFFFFFFF) #define btest(a,b) (((a)&(b))~=0) #define bxor(a,b) (((a)~(b))&0xFFFFFFFF) -#define rshift(a,b) (((a)&(b))~=0) #define extract(a,b,c) (((a)>>(b))&~(-1<<(c))) #define extract(a,b) (((a)>>(b))&0x1) #define extract1(a,b) ((a >> b) & 0x01) diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua index 64c7de567..9aa8b8aa7 100644 --- a/tex/context/base/mkiv/l-os.lua +++ b/tex/context/base/mkiv/l-os.lua @@ -459,7 +459,7 @@ end local d function os.timezone(delta) - d = d or tonumber(tonumber(date("%H")-date("!%H"))) + d = d or ((tonumber(date("%H")) or 0) - (tonumber(date("!%H")) or 0)) if delta then if d > 0 then return format("+%02i:00",d) diff --git a/tex/context/base/mkiv/lang-ini.lua b/tex/context/base/mkiv/lang-ini.lua index 30e086e15..ce2b89f3c 100644 --- a/tex/context/base/mkiv/lang-ini.lua +++ b/tex/context/base/mkiv/lang-ini.lua @@ -22,7 +22,7 @@ local type, tonumber, next = type, tonumber, next local utfbyte = utf.byte local format, gsub, gmatch, find = string.format, string.gsub, string.gmatch, string.find local concat, sortedkeys, sortedpairs, keys, insert = table.concat, table.sortedkeys, table.sortedpairs, table.keys, table.insert -local utfbytes, strip, utfcharacters = string.utfvalues, string.strip, utf.characters +local utfvalues, strip, utfcharacters = string.utfvalues, string.strip, utf.characters local context = context local commands = commands @@ -194,7 +194,7 @@ local function sethjcodes(instance,loaded,what,factor) setcode(utfbyte(l)) end else - for l in utfbytes(c) do + for l in utfvalues(c) do setcode(l) end end diff --git a/tex/context/base/mkiv/lang-url.lua b/tex/context/base/mkiv/lang-url.lua index 17ad15cd8..7428d64ab 100644 --- a/tex/context/base/mkiv/lang-url.lua +++ b/tex/context/base/mkiv/lang-url.lua @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['lang-url'] = { license = "see context related readme files" } -local utfcharacters, utfvalues, utfbyte, utfchar = utf.characters, utf.values, utf.byte, utf.char +local utfcharacters, utfbyte, utfchar = utf.characters, utf.byte, utf.char local min, max = math.min, math.max local context = context diff --git a/tex/context/base/mkiv/lpdf-lmt.lua b/tex/context/base/mkiv/lpdf-lmt.lua index 0ad0c4e5e..3966143b4 100644 --- a/tex/context/base/mkiv/lpdf-lmt.lua +++ b/tex/context/base/mkiv/lpdf-lmt.lua @@ -102,12 +102,12 @@ end local function reset_variables(specification) pdf_h, pdf_v = 0, 0 - cmrx, cmry = 1, 1 - cmsx, cmsy = 0, 0 - cmtx, cmty = 0, 0 - tmrx, tmry = 1, 1 - tmsx, tmsy = 0, 0 - tmtx, tmty = 0, 0 + cmrx, cmry = 1.0, 1.0 + cmsx, cmsy = 0.0, 0.0 + cmtx, cmty = 0.0, 0.0 + tmrx, tmry = 1.0, 1.0 + tmsx, tmsy = 0.0, 0.0 + tmtx, tmty = 0.0, 0.0 need_tm = false need_tf = false need_width = 0 @@ -117,17 +117,17 @@ local function reset_variables(specification) mode = "page" shippingmode = specification.shippingmode objectnumber = specification.objectnumber - cur_tmrx = 0 + cur_tmrx = 0.0 f_cur = 0 f_pdf_cur = 0 -- nullfont f_pdf = 0 -- nullfont fs_cur = 0 fs = 0 - tj_delta = 0 cur_factor = 0 cur_f = false cur_e = false - cw = 0 + tj_delta = 0.0 + cw = 0.0 usedfonts = setmetatableindex(usefont) usedxforms = { } usedximages = { } @@ -137,7 +137,7 @@ end -- buffer -local buffer = { } +local buffer = lua.newtable(1024,0) -- { } local b = 0 local function reset_buffer() @@ -384,16 +384,21 @@ local flushcharacter do local f = parameters[font].hfactor local v = setmetatableindex(function(t,char) local e = d and d[char] - local w = 0 + local w if e then w = e.width if w then w = w * f end end - e = c[char] - if e then - w = e.width or 0 + if not w then + e = c[char] + if e then + w = e.width or 0 + end + end + if not w then + w = 0 end t[char] = w return w @@ -599,9 +604,7 @@ local flushcharacter do begin_charmode() end - -- cw = cw + naturalwidth - -- cw = cw + width - cw = cw + naturalwidth[char] + cw = cw + naturalwidth[char] * tmrx local index = data.index or char diff --git a/tex/context/base/mkiv/luat-cod.lua b/tex/context/base/mkiv/luat-cod.lua index 3125495b4..8d5d65a45 100644 --- a/tex/context/base/mkiv/luat-cod.lua +++ b/tex/context/base/mkiv/luat-cod.lua @@ -154,7 +154,7 @@ if LUATEXFORMATID == nil then end if JITSUPPORTED == nil then - JITSUPPORTED = LUATEXENGINE == "luajittex" or jit + JITSUPPORTED = LUATEXENGINE == "luajittex" or jit -- "or jit" can go end if INITEXMODE == nil then diff --git a/tex/context/base/mkiv/luat-fmt.lua b/tex/context/base/mkiv/luat-fmt.lua index 5502e1a1d..538556ed2 100644 --- a/tex/context/base/mkiv/luat-fmt.lua +++ b/tex/context/base/mkiv/luat-fmt.lua @@ -21,9 +21,6 @@ local function primaryflags(arguments) if arguments.silent then flags[#flags+1] = "--interaction=batchmode" end - -- if arguments.jit then - -- flags[#flags+1] = "--jiton" - -- end return concat(flags," ") end @@ -43,9 +40,6 @@ local function secondaryflags(arguments) if arguments.errors then flags[#flags+1] = "--c:errors" end - if arguments.jit then - flags[#flags+1] = "--c:jiton" - end if arguments.ansi then flags[#flags+1] = "--c:ansi" end @@ -248,9 +242,9 @@ function environment.make_format(formatname) if silent then specification.redirect = "> temp.log" end - statistics.starttiming() + statistics.starttiming("format") local result = runner(specification) - local runtime = statistics.stoptiming() + statistics.stoptiming("format") if silent then os.remove("temp.log") end @@ -269,7 +263,7 @@ function environment.make_format(formatname) report_format("secondary flags : %s",secondaryflags) end report_format("context file : %s",fulltexsourcename) - report_format("run time : %.3f seconds",runtime) + report_format("run time : %.3f seconds",statistics.elapsed("format")) report_format("return value : %s",result == 0 and "okay" or "error") report_format() -- last we go back to the home base diff --git a/tex/context/base/mkiv/m-fonts-plugins.mkiv b/tex/context/base/mkiv/m-fonts-plugins.mkiv index 255a2ac72..ec1c05e7a 100644 --- a/tex/context/base/mkiv/m-fonts-plugins.mkiv +++ b/tex/context/base/mkiv/m-fonts-plugins.mkiv @@ -11,18 +11,19 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D See source code for comments. I wrote this a follow up on a presentation by -%D Kai Eigner, left it for a while, and sort of finalized it the last quarter of -%D 2016. As I don't use this module, apart from maybe testing something, it is -%D not guaranteed to work. Also, plugins can interfere with other functionality -%D in \CONTEXT\ so don't expect too much support. The two modules mentioned -%D below should work in the generic loader too. It's anyhow an illustration of -%D how \type {ffi} can work be used in a practical application. +%D See source code for comments. I wrote this a follow up on a presentation by Kai +%D Eigner at an NTG meeting, then left it for a while, and sort of finalized it the +%D last quarter of 2016. As I don't use this module, apart from maybe testing +%D something, it is not guaranteed to work (but fixing should be a no real problem +%D as I expect apis to be stable). Plugins liek this can interfere with other +%D functionality in \CONTEXT\ so don't expect too much support. The two modules +%D mentioned below should work in the generic loader too. It's anyhow an +%D illustration of how \type {ffi} be used in a practical application. % \enabletrackers[resolvers.ffilib] \registerctxluafile{font-txt}{} % generic text handler -\registerctxluafile{font-phb}{} % harfbuzz plugin +\registerctxluafile{font-phb}{} % harfbuzz plugin: binary or library (ffi/optional) \startluacode diff --git a/tex/context/base/mkiv/math-ini.mkiv b/tex/context/base/mkiv/math-ini.mkiv index caddfca53..c79d3579c 100644 --- a/tex/context/base/mkiv/math-ini.mkiv +++ b/tex/context/base/mkiv/math-ini.mkiv @@ -1492,7 +1492,7 @@ \to \everymathematics \setupmathematics - [\s!collapsing=\v!none] % was 3 : mathlist wins over specials + [\s!collapsing=1] % so that we at least do primes %D Math italics (experiment) diff --git a/tex/context/base/mkiv/math-tag.lua b/tex/context/base/mkiv/math-tag.lua index daa757f6a..9267e0f39 100644 --- a/tex/context/base/mkiv/math-tag.lua +++ b/tex/context/base/mkiv/math-tag.lua @@ -31,7 +31,7 @@ local getsubtype = nuts.getsubtype local getattr = nuts.getattr local getattrlist = nuts.getattrlist local setattr = nuts.setattr -local getcomponents = nuts.getcomponents -- not really needed +----- getcomponents = nuts.getcomponents -- not really needed local getwidth = nuts.getwidth local getnucleus = nuts.getnucleus @@ -346,10 +346,10 @@ process = function(start) -- we cannot use the processor as we have no finalizer runner(getlist(n),depth+1) elseif id == glyph_code then -- this should not be needed - local components = getcomponents(n) -- unlikely set - if components then - runner(getcomponent,depth+1) - end + -- local components = getcomponents(n) -- unlikely set + -- if components then + -- runner(getcomponent,depth+1) + -- end elseif id == disc_code then -- this should not be needed local pre, post, replace = getdisc(n) diff --git a/tex/context/base/mkiv/meta-ini.mkiv b/tex/context/base/mkiv/meta-ini.mkiv index 97d2e1a7d..ac920450e 100644 --- a/tex/context/base/mkiv/meta-ini.mkiv +++ b/tex/context/base/mkiv/meta-ini.mkiv @@ -494,6 +494,8 @@ %D Currently the inheritance of backgrounds does not work and we might drop it %D anyway (too messy) +%D This will be cleaned up in \LMTX: we can delay a lot of this. + \newbox\b_meta_variable_box \let \currentmpvariableclass \empty @@ -593,6 +595,8 @@ \endgroup\meta_prepare_variable_dimension \fi}} +% One of these says we need to enable this! + % \def\meta_prepare_variable_yes % {\expandafter\edef\csname\m_meta_current_variable_template\endcsname % {\clf_prepareMPvariable {\m_meta_current_variable}}} diff --git a/tex/context/base/mkiv/mlib-lmp.lua b/tex/context/base/mkiv/mlib-lmp.lua index 402c194fe..f000f4282 100644 --- a/tex/context/base/mkiv/mlib-lmp.lua +++ b/tex/context/base/mkiv/mlib-lmp.lua @@ -142,7 +142,7 @@ if CONTEXTLMTXMODE > 0 then function mp.lmt_svg_include() local labelfile = metapost.getparameter { "labelfile" } - if labelfile then + if labelfile and labelfile ~= "" then local labels = table.load(labelfile) -- todo: same path as svg file if type(labels) == "table" then for i=1,#labels do @@ -160,28 +160,35 @@ if CONTEXTLMTXMODE > 0 then end return end + local colorfile = metapost.getparameter { "colormap" } + local colormap = false + if colorfile and colorfile ~= "" then + colormap = metapost.svgcolorremapper(colorfile) + end local filename = metapost.getparameter { "filename" } if filename and filename ~= "" then mpdirect ( metapost.svgtomp { - data = io.loaddata(filename), - remap = true, + data = io.loaddata(filename), + remap = true, + colormap = colormap, } ) - return - end - local buffer = metapost.getparameter { "buffer" } - if buffer then - mpdirect ( metapost.svgtomp { - data = buffers.getcontent(buffer), - -- remap = true, - } ) - return - end - local code = metapost.getparameter { "code" } - if code then - mpdirect ( metapost.svgtomp { - data = code, - } ) - return + else + local buffer = metapost.getparameter { "buffer" } + if buffer then + mpdirect ( metapost.svgtomp { + data = buffers.getcontent(buffer), + -- remap = true, + colormap = colormap, + } ) + else + local code = metapost.getparameter { "code" } + if code then + mpdirect ( metapost.svgtomp { + data = code, + colormap = colormap, + } ) + end + end end end @@ -213,3 +220,5 @@ if CONTEXTLMTXMODE > 0 then end end + +todecimal = xdecimal and xdecimal.new or tonumber -- bonus diff --git a/tex/context/base/mkiv/mlib-svg.lua b/tex/context/base/mkiv/mlib-svg.lua index f4b3117a6..3d15840a7 100644 --- a/tex/context/base/mkiv/mlib-svg.lua +++ b/tex/context/base/mkiv/mlib-svg.lua @@ -390,7 +390,45 @@ local p_path = Ct ( ( -- local function hexcolor (c) return hexhash [c] end -- directly do hexhash [c] -- local function hexcolor3(c) return hexhash3[c] end -- directly do hexhash3[c] -local rgbcomponents, withcolor, thecolor do +local colormap = false + +local function prepared(t) + if type(t) == "table" then + local mapping = t.mapping or { } + local mapper = t.mapper + local colormap = setmetatableindex(mapping) + if mapper then + setmetatableindex(colormap,function(t,k) + local v = mapper(k) + t[k] = v or k + return v + end) + end + return colormap + else + return false + end +end + +local colormaps = setmetatableindex(function(t,k) + local v = false + if type(k) == "string" then + v = prepared(table.load(k)) -- todo: same path as svg file + elseif type(k) == "table" then + v = prepared(k) + k = k.name or k + end + t[k] = v + return v +end) + +function metapost.svgcolorremapper(colormap) + return colormaps[colormap] +end + +-- todo: cache colors per image / remapper + +local colorcomponents, withcolor, thecolor do local svgcolors = { aliceblue = 0xF0F8FF, antiquewhite = 0xFAEBD7, aqua = 0x00FFFF, aquamarine = 0x7FFFD4, @@ -433,11 +471,13 @@ local rgbcomponents, withcolor, thecolor do } local f_rgb = formatters['withcolor svgcolor(%.3N,%.3N,%.3N)'] + local f_cmyk = formatters['withcolor svgcmyk(%.3N,%.3N,%.3N,%.3N)'] local f_gray = formatters['withcolor svggray(%.3N)'] local f_rgba = formatters['withcolor svgcolor(%.3N,%.3N,%.3N) withtransparency (1,%.3N)'] local f_graya = formatters['withcolor svggray(%.3N) withtransparency (1,%.3N)'] local f_name = formatters['withcolor "%s"'] local f_svgcolor = formatters['svgcolor(%.3N,%.3N,%.3N)'] + local f_svgcmyk = formatters['svgcmyk(%.3N,%.3N,%.3N,%.3N)'] local f_svggray = formatters['svggray(%.3N)'] local f_svgname = formatters['"%s"'] @@ -455,88 +495,192 @@ local rgbcomponents, withcolor, thecolor do return v end) - local p_fraction = C(p_number) * C("%")^-1 / function(a,b) - a = tonumber(a) return a / (b and 100 or 255) + local p_fraction = C(p_number) * C("%")^-1 / function(a,b) return tonumber(a) / (b and 100 or 255) end + local p_angle = C(p_number) * P("deg")^0 / function(a) return tonumber(a) end + local p_percent = C(p_number) * P("%") / function(a) return tonumber(a) / 100 end + local p_absolute = C(p_number) / tonumber + + local p_left = P("(") + local p_right = P(")") + local p_a = P("a")^-1 + local p_h_a_color = p_left + * p_angle + * p_separator * p_percent + * p_separator * p_percent + * p_separator^0 * p_absolute^0 + * p_right + + local colors = attributes.colors + local colorvalues = colors.values + local colorindex = attributes.list[attributes.private('color')] + local hsvtorgb = colors.hsvtorgb + local hwbtorgb = colors.hwbtorgb + local forcedmodel = colors.forcedmodel + + local p_splitcolor = + P("#") * C(p_hexdigit*p_hexdigit)^1 / function(r,g,b) + return "rgb", + tonumber(r or 0, 16) / 255 or 0, + tonumber(g or 0, 16) / 255 or 0, + tonumber(b or 0, 16) / 255 or 0 + end + + + P("rgb") * p_a + * p_left * (p_fraction + p_separator)^-3 * (p_absolute + p_separator)^0 * p_right / function(r,g,b,a) + return "rgb", r or 0, g or 0, b or 0, a or false + end + + P("cmyk") + * p_left * (p_absolute + p_separator)^0 * p_right / function(c,m,y,k) + return "cmyk", c or 0, m or 0, y or 0, k or 0 + end + + P("hsl") * p_a + * p_h_a_color / function(h,s,l,a) + local r, g, b = hsvtorgb(h,s,l,a) + return "rgb", r or 0, g or 0, b or 0, a or false + end + + P("hwb") * p_a + * p_h_a_color / function(h,w,b,a) + local r, g, b = hwbtorgb(h,w,b) + return "rgb", r or 0, g or 0, b or 0, a or false + end + + function metapost.svgsplitcolor(color) + if type(color) == "string" then + local what, s1, s2, s3, s4 = lpegmatch(p_splitcolor,color) + if not what then + local t = triplets[color] + if t then + what, s1, s2, s3 = "rgb", t[1], t[2], t[3] + end + end + return what, s1, s2, s3, s4 + else + return "gray", 0, false + end end - local p_hexcolor = P("#") * C(p_hexdigit*p_hexdigit)^1 / function(r,g,b) - return r and tonumber(r,16)/255 or nil, g and tonumber(g,16)/255 or nil, b and tonumber(b,16)/255 or nil + + + local function registeredcolor(name) + local color = colorindex[name] + if color then + local v = colorvalues[color] + local t = forcedmodel(v[1]) + if t == 2 then + return "gray", v[2] + elseif t == 3 then + return "rgb", v[3], v[4], v[5] + elseif t == 4 then + return "cmyk", v[6], v[7], v[8], v[9] + else + -- + end + end end - local p_rgbacolor = P("rgb") * (P("a")^-1) * P("(") * (p_fraction + p_separator)^1 * P(")") - rgbcomponents = function(color) - local h = lpegmatch(p_hexcolor,color) - if h then - return h + -- we can have a fast check for #000000 + + local function validcolor(color) + if colormap then + local c = colormap[color] + local t = type(c) + if t == "table" then + local what = t[1] + if what == "rgb" then + return + what, + tonumber(t[2]) or 0, + tonumber(t[3]) or 0, + tonumber(t[4]) or 0, + tonumber(t[4]) or false + elseif what == "cmyk" then + return + what, + tonumber(t[2]) or 0, + tonumber(t[3]) or 0, + tonumber(t[4]) or 0, + tonumber(t[5]) or 0 + elseif what == "gray" then + return + what, + tonumber(t[2]) or 0, + tonumber(t[3]) or false + end + elseif t == "string" then + color = c + end + end + local what, s1, s2, s3, s4 = registeredcolor(color) + if what then + return what, s1, s2, s3, s4 end - local r, g, b, a = lpegmatch(p_rgbacolor,color) - if r then - return r, g or r, b or r + what, s1, s2, s3, s4 = lpegmatch(p_splitcolor,color) + if not what then + local t = triplets[color] + if t then + s1, s3, s3 = t[1], t[2], t[3] + what = "rgb" + end end - local t = triplets[color] - return t[1], t[2], t[3] + return what, s1, s2, s3, s4 + end + colorcomponents = function(color) + local what, s1, s2, s3, s4 = validcolor(color) + return s1, s2, s3, s4 -- so 4 means cmyk end withcolor = function(color) - local r, g, b = lpegmatch(p_hexcolor,color) - if b and not (r == g and g == b) then - return f_rgb(r,g,b) - elseif r then - return f_gray(r) - end - local r, g, b, a = lpegmatch(p_rgbacolor,color) - if a then - if a == 1 then - if r == g and g == b then - return f_gray(r) + local what, s1, s2, s3, s4 = validcolor(color) + -- print(color,what, s1, s2, s3, s4) + if what == "rgb" then + if s4 then + if s1 == s2 and s1 == s3 then + return f_graya(s1,s4) else - return f_rgb(r,g,b) + return f_rgba(s1,s2,s3,s4) end else - if r == g and g == b then - return f_graya(r,a) + if s1 == s2 and s1 == s3 then + return f_gray(s1) else - return f_rgba(r,g,b,a) + return f_rgb(s1,s2,s3) end end - end - if not r then - local t = triplets[color] - if t then - r, g, b = t[1], t[2], t[3] - end - end - if r then - if r == g and g == b then - return f_gray(r) - elseif g and b then - return f_rgb(r,g,b) + elseif what == "cmyk" then + return f_cmyk(s1,s2,s3,s4) + elseif what == "gray" then + if s2 then + return f_graya(s1,s2) else - return f_gray(r) + return f_gray(s1) end end return f_name(color) end thecolor = function(color) - local h = lpegmatch(p_hexcolor,color) - if h then - return h - end - local r, g, b, a = lpegmatch(p_rgbacolor,color) - if not r then - local t = triplets[color] - if t then - r, g, b = t[1], t[2], t[3] + local what, s1, s2, s3, s4 = validcolor(color) + if what == "rgb" then + if s4 then + if s1 == s2 and s1 == s3 then + return f_svggraya(s1,s4) + else + return f_svgrgba(s1,s2,s3,s4) + end + else + if s1 == s2 and s1 == s3 then + return f_svggray(s1) + else + return f_svgrgb(s1,s2,s3) + end end - end - if r then - if r == g and g == b then - return f_svggray(r) - elseif g and b then - return f_svgcolor(r,g,b) + elseif what == "cmyk" then + return f_cmyk(s1,s2,s3,s4) + elseif what == "gray" then + if s2 then + return f_svggraya(s1,s2) else - return f_svggray(r) + return f_svggray(s1) end end return f_svgname(color) @@ -2517,8 +2661,8 @@ do -- local ecolored = v_fill and v_fill ~= "" or false if ecolored then - -- todo - local r, g, b = rgbcomponents(v_fill) + -- todo cmyk + local r, g, b = colorcomponents(v_fill) if r and g and b then t[#t+1] = f_colored(r,g,b) else @@ -2677,7 +2821,7 @@ do end - function handlers.svg(c,x,y,w,h,noclip,notransform,normalize,usetextindex) + function handlers.svg(c,x,y,w,h,noclip,notransform,normalize) local at = c.at local wrapupviewport @@ -2739,7 +2883,6 @@ do if boffset then r = r + 1 result[r] = boffset end - textindex = usetextindex and 0 or false at["transform"] = false at["viewBox"] = false @@ -2805,6 +2948,7 @@ do definitions = { } tagstyles = { } classstyles = { } + colormap = specification.colormap for s in xmlcollected(c,"style") do -- can also be in a def, so let's play safe handlestyle(c) end @@ -2824,8 +2968,14 @@ do if trace_result then report("result graphic:\n %\n t",result) end - mps = concat(result," ") - root, result, r, definitions, styles = false, false, false, false, false + mps = concat(result," ") + root = false + result = false + r = false + definitions = false + tagstyles = false + classstyles = false + colormap = false else report("missing svg root element") end diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua index 2a747f3b5..d13db4bba 100644 --- a/tex/context/base/mkiv/node-aux.lua +++ b/tex/context/base/mkiv/node-aux.lua @@ -22,6 +22,7 @@ local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local attributelist_code = nodecodes.attributelist -- temporary local localpar_code = nodecodes.localpar +local ligatureglyph_code = nodes.glyphcodes.ligature local nuts = nodes.nuts local tonut = nuts.tonut @@ -36,7 +37,6 @@ local getlist = nuts.getlist local getattr = nuts.getattr local getboth = nuts.getboth local getprev = nuts.getprev -local getcomponents = nuts.getcomponents local getwidth = nuts.getwidth local setwidth = nuts.setwidth local getboxglue = nuts.getboxglue @@ -64,6 +64,7 @@ local copy_node = nuts.copy local find_tail = nuts.tail local getbox = nuts.getbox local count = nuts.count +local isglyph = nuts.isglyph local nodepool = nuts.pool local new_glue = nodepool.glue @@ -381,89 +382,162 @@ function nodes.rehpack(n,...) rehpack(tonut(n),...) end --- nodemode helper: the next and prev pointers are untouched +if CONTEXTLMTXMODE > 0 then -function nuts.copy_no_components(g,copyinjection) - local components = getcomponents(g) - if components then - setcomponents(g) - local n = copy_node(g) - if copyinjection then - copyinjection(n,g) - end - setcomponents(g,components) - -- maybe also upgrade the subtype but we don't use it anyway - return n - else - local n = copy_node(g) - if copyinjection then - copyinjection(n,g) + local fastcopy = table.fastcopy + local getprop = nuts.getprop + local setprop = nuts.setprop + + local function set_components(base,list) + local t = { } + local n = 0 + while list do + local char = isglyph(list) + if char then + n = n + 1 + t[n] = char + end + list = getnext(list) end - return n + setprop(base,"components",n > 0 and t or false) end -end -function nuts.copy_only_glyphs(current) - local head = nil - local previous = nil - for n in nextglyph, current do - n = copy_node(n) - if head then - setlink(previous,n) - else - head = n - end - previous = n + local function get_components(base) + return getprop(base,"components") end - return head -end --- node- and basemode helper - -function nuts.use_components(head,current) - local components = getcomponents(current) - if not components then - return head, current, current - end - local prev, next = getboth(current) - local first = current - local last = next - while components do - local gone = current - local tail = find_tail(components) - if prev then - setlink(prev,components) + local function copy_no_components(base) + local copy = copy_node(base) + setprop(copy,"components",false) -- no metatable lookup! + return copy + end + + local function copy_only_glyphs(base) + local t = getprop(base,"components") -- also metatable + if t then + return fastcopy(t) end - if next then - setlink(tail,next) + end + + local function do_count(t,marks) + local n = 0 + if t then + for i=1,#t do + local c = t[i] + if type(c) == "table" then + n = n + do_count(t,marks) + elseif not marks[c] then + n = n + 1 + else + --marks don't count + end + end end - if first == current then - first = components + return n + end + + -- start is a mark and we need to keep that one + + local done = false + + local function count_components(base,marks) + local char = isglyph(base) + if char then + if getsubtype(base) == ligatureglyph_code then + if not done then + logs.report("fonts","!") + logs.report("fonts","! check count_components with mkiv !") + logs.report("fonts","!") + done = true + end + local t = getprop(base,"components") + if t then + return do_count(t,marks) + end + elseif not marks[char] then + return 1 + end end - if head == current then - head = components + return 0 + end + + nuts.set_components = set_components + nuts.get_components = get_components + nuts.copy_only_glyphs = copy_only_glyphs + nuts.copy_no_components = copy_no_components + nuts.count_components = count_components + +else + + local get_components = node.direct.getcomponents + local set_components = node.direct.setcomponents + + local function copy_no_components(g,copyinjection) + local components = get_components(g) + if components then + set_components(g) + local n = copy_node(g) + if copyinjection then + copyinjection(n,g) + end + set_components(g,components) + -- maybe also upgrade the subtype but we don't use it anyway + return n + else + local n = copy_node(g) + if copyinjection then + copyinjection(n,g) + end + return n end - current = components - setcomponents(gone) - flush_node(gone) - while true do - components = getcomponents(current) - if components then - next = getnext(current) - break -- current is composed + end + + local function copy_only_glyphs(current) + local head = nil + local previous = nil + for n in nextglyph, current do + n = copy_node(n) + if head then + setlink(previous,n) + else + head = n end - if next == last then - last = current - break -- components is false + previous = n + end + return head + end + + -- start is a mark and we need to keep that one + + local function count_components(start,marks) + local char = isglyph(start) + if char then + if getsubtype(start) == ligatureglyph_code then + local n = 0 + local components = get_components(start) + while components do + n = n + count_components(components,marks) + components = getnext(components) + end + return n + elseif not marks[char] then + return 1 end - prev = current - current = next - next = getnext(current) end + return 0 end - return head, first, last + + nuts.set_components = set_components + nuts.get_components = get_components + nuts.copy_only_glyphs = copy_only_glyphs + nuts.copy_no_components = copy_no_components + nuts.count_components = count_components + end +nuts.setcomponents = function() report_error("unsupported: %a","setcomponents") end +nuts.getcomponents = function() report_error("unsupported: %a","getcomponents") end + do local localparcodes = nodes.localparcodes @@ -543,8 +617,8 @@ do nuts.find_node = find_node - nodes.getnormalizeline = nodes.getnormalizeline or function() return 0 end - nodes.setnormalizeline = nodes.setnormalizeline or function() end + nodes.getnormalizeline = node.getnormalizeline or function() return 0 end + nodes.setnormalizeline = node.setnormalizeline or function() end nuts.getnormalizedline = direct.getnormalizedline or function(h) if getid(h) == hlist_code and getsubtype(h) == line_code then diff --git a/tex/context/base/mkiv/node-ini.lua b/tex/context/base/mkiv/node-ini.lua index 806ac5658..8ebec4a1c 100644 --- a/tex/context/base/mkiv/node-ini.lua +++ b/tex/context/base/mkiv/node-ini.lua @@ -83,7 +83,7 @@ local fillcodes = mark(getsubtypes("fill")) local boundarycodes = mark(getsubtypes("boundary")) local penaltycodes = mark(getsubtypes("penalty")) local kerncodes = mark(getsubtypes("kern")) -local margincodes = mark(getsubtypes("marginkern")) +local margincodes = CONTEXTLMTXMODE == 0 and mark(getsubtypes("marginkern")) or { } local mathcodes = mark(getsubtypes("math")) local noadcodes = mark(getsubtypes("noad")) local radicalcodes = mark(getsubtypes("radical")) @@ -246,7 +246,7 @@ nodes.subtypes = allocate { [nodecodes.hlist] = listcodes, [nodecodes.kern] = kerncodes, [nodecodes.localpar] = localparcodes, - [nodecodes.marginkern] = margincodes, + -- [nodecodes.marginkern] = margincodes, [nodecodes.math] = mathcodes, [nodecodes.noad] = noadcodes, [nodecodes.penalty] = penaltycodes, @@ -257,6 +257,10 @@ nodes.subtypes = allocate { [nodecodes.whatsit] = whatcodes, } +if CONTEXTLMTXMODE == 0 then + nodes.subtypes[nodecodes.marginkern] = margincodes +end + table.setmetatableindex(nodes.subtypes,function(t,k) local v = { } t[k] = v diff --git a/tex/context/base/mkiv/node-ltp.lua b/tex/context/base/mkiv/node-ltp.lua index dd655f93d..a85bdfe01 100644 --- a/tex/context/base/mkiv/node-ltp.lua +++ b/tex/context/base/mkiv/node-ltp.lua @@ -347,7 +347,7 @@ local new_temp = nodepool.temp local new_rule = nodepool.rule local new_hlist = nodepool.hlist -local getnormalizeline = nuts.getnormalizeline +local getnormalizeline = nodes.getnormalizeline -- helpers -- @@ -3120,7 +3120,8 @@ do elseif id == dir_code then -- no need to deal with directions here (as we only support two) elseif id == marginkern_code then - natural = natural + getwidth(current) + -- not in lmtx + natural = natural + getwidth(current) end current = getnext(current) end diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua index 7174bd475..e722bbd66 100644 --- a/tex/context/base/mkiv/node-nut.lua +++ b/tex/context/base/mkiv/node-nut.lua @@ -829,6 +829,34 @@ nuts.theprop = function(n) return p end +local getstate = direct.getstate +local setstate = direct.setstate + +if not setstate or not getstate then + setstate = function(n,v) + local p = propertydata[n] + if p then + p.state = v + else + propertydata[n] = { state = v } + end + end + getstate = function(n,v) + local p = propertydata[n] + if p then + if v then + return p.state == v + else + return p.state + end + else + return nil + end + end + nuts.setstate = setstate + nuts.getstate = getstate +end + nuts.isdone = function(n,k) local p = propertydata[n] if not p then diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua index a27f5c4e5..1832a0d1e 100644 --- a/tex/context/base/mkiv/node-res.lua +++ b/tex/context/base/mkiv/node-res.lua @@ -176,8 +176,15 @@ if CONTEXTLMTXMODE == 0 then setfield(user_node,"type",usercodes.number) end -local left_margin_kern = register_nut(new_nut(nodecodes.marginkern,0)) -local right_margin_kern = register_nut(new_nut(nodecodes.marginkern,1)) +local left_margin_kern, right_margin_kern + +if CONTEXTLMTXMODE > 0 then + left_margin_kern = register_nut(new_nut(kern_code,kerncodes.leftmargincode)) + right_margin_kern = register_nut(new_nut(kern_code,kerncodes.rightmargincode)) +else + left_margin_kern = register_nut(new_nut(nodecodes.marginkern,0)) + right_margin_kern = register_nut(new_nut(nodecodes.marginkern,1)) +end local lineskip = register_nut(new_nut(glue_code,gluecodes.lineskip)) local baselineskip = register_nut(new_nut(glue_code,gluecodes.baselineskip)) diff --git a/tex/context/base/mkiv/sort-ini.lua b/tex/context/base/mkiv/sort-ini.lua index 0916337b1..98f516c22 100644 --- a/tex/context/base/mkiv/sort-ini.lua +++ b/tex/context/base/mkiv/sort-ini.lua @@ -51,7 +51,7 @@ have language etc properties that then can be used.</p> ]]-- local gsub, find, rep, sub, sort, concat, tohash, format = string.gsub, string.find, string.rep, string.sub, table.sort, table.concat, table.tohash, string.format -local utfbyte, utfchar, utfcharacters, utfvalues = utf.byte, utf.char, utf.characters, utf.values +local utfbyte, utfchar, utfcharacters = utf.byte, utf.char, utf.characters local next, type, tonumber, rawget, rawset = next, type, tonumber, rawget, rawset local P, Cs, R, S, lpegmatch, lpegpatterns = lpeg.P, lpeg.Cs, lpeg.R, lpeg.S, lpeg.match, lpeg.patterns diff --git a/tex/context/base/mkiv/spac-prf.lua b/tex/context/base/mkiv/spac-prf.lua index 049e62ac5..7731b21f7 100644 --- a/tex/context/base/mkiv/spac-prf.lua +++ b/tex/context/base/mkiv/spac-prf.lua @@ -244,6 +244,7 @@ local function getprofile(line,step) dp = 0 progress() elseif id == marginkern_code then + -- not in lmtx wd = getwidth(current) ht = 0 dp = 0 diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex baed04d32..01dde89ff 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 9e63b48f6..105405cc4 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/symb-ini.mkiv b/tex/context/base/mkiv/symb-ini.mkiv index 428fcd381..be520743f 100644 --- a/tex/context/base/mkiv/symb-ini.mkiv +++ b/tex/context/base/mkiv/symb-ini.mkiv @@ -11,9 +11,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D The macros described here used to be part of the \type -%D {core-con} module. I decided to move them here when -%D symbolsets saw the light. Let their light shine. +%D The macros described here used to be part of the \type {core-con} module. I +%D decided to move them here when symbolsets saw the light. Let their light shine. \writestatus{loading}{ConTeXt Symbol Libraries / Initialization} @@ -24,19 +23,17 @@ %D \macros %D {definesymbol, symbol} %D -%D Converting numbers or levels into a character, romannumeral, -%D symbol or something else, is supported by many \CONTEXT\ -%D commands. Therefore we need a mechanism for linking such -%D numbers to their counterparts. +%D Converting numbers or levels into a character, romannumeral, symbol or something +%D else, is supported by many \CONTEXT\ commands. Therefore we need a mechanism for +%D linking such numbers to their counterparts. %D -%D First we take care of symbols. These are for instance used -%D in enumerations and itemizations. We have: +%D First we take care of symbols. These are for instance used in enumerations and +%D itemizations. We have: %D %D \showsetup{definesymbol} %D \showsetup{symbol} %D -%D Symbols are simply linked to a tag. Such tags can be numbers -%D or strings. +%D Symbols are simply linked to a tag. Such tags can be numbers or strings. %D %D \starttyping %D \definesymbol [1] [$\bullet$] @@ -72,8 +69,8 @@ \newtoks\everysymbol -%D We don't use the commandhandler as symbols have their own -%D subsystem for resolving values. +%D We don't use the commandhandler as symbols have their own subsystem for resolving +%D values. \unexpanded\def\definesymbol {\dotripleempty\symb_define} @@ -100,9 +97,8 @@ \def\symbolset#1{\begincsname\??symbolset#1\endcsname} % no [#1], to be used in commalists etc -%D Since symbols are used frequently in interactive -%D documents, we speed up this one. Well, that was history, -%D since now we simplified things a bit, because the low +%D Since symbols are used frequently in interactive documents, we speed up this one. +%D Well, that was history, since now we simplified things a bit, because the low %D level macros have been sped up every now and then. % We support both: @@ -241,8 +237,8 @@ %D %D \showsetup{definefiguresymbol} %D -%D By default, such symbols scale along the current bodyfont -%D size or running font size (which is better). +%D By default, such symbols scale along the current bodyfont size or running font +%D size (which is better). \def\defaultsymbolfactor{10} \def\defaultsymbolheight{1.25ex} @@ -306,8 +302,8 @@ %D \macros %D {setupsymbolset,startsymbolset} %D -%D From these macro definitions one can deduce that symbols can -%D be grouped in symbol sets: +%D From these macro definitions one can deduce that symbols can be grouped in +%D symbol sets: %D %D \starttyping %D \startsymbolset [navigation 1] @@ -388,9 +384,8 @@ \unexpanded\def\usesymbols[#1]{\clf_usesymbols{#1}} -%D As longs as symbols are linked to levels or numbers, we can -%D also use the conversion mechanism, but in for instance the -%D itemization macros, we prefer symbols because they can more -%D easier be (partially) redefined. +%D As longs as symbols are linked to levels or numbers, we can also use the +%D conversion mechanism, but in for instance the itemization macros, we prefer +%D symbols because they can more easier be (partially) redefined. \protect \endinput diff --git a/tex/context/base/mkiv/syst-ini.mkxl b/tex/context/base/mkiv/syst-ini.mkxl index baca0bb5c..9394807c8 100644 --- a/tex/context/base/mkiv/syst-ini.mkxl +++ b/tex/context/base/mkiv/syst-ini.mkxl @@ -133,7 +133,7 @@ %D anyway because there are differences (no backend, to mention one). \directlua { - local primitives = tex.extraprimitives() % "core","tex","etex","luatex" + local primitives = tex.extraprimitives() % "tex","etex","luatex" tex.enableprimitives("normal",primitives) % could default to everything function tex.enableprimitives() end % so we kind of protect what's there } @@ -1108,4 +1108,9 @@ \def\wildcardsymbol{*} +%D For a while we will keep these useless numbers as for instance tikz checks for them: + +\chardef\eTeXversion 2 +\def \eTeXrevision {2} + \protect \endinput diff --git a/tex/context/base/mkiv/tabl-tbl.mkiv b/tex/context/base/mkiv/tabl-tbl.mkiv index 6e87d1863..434b26095 100644 --- a/tex/context/base/mkiv/tabl-tbl.mkiv +++ b/tex/context/base/mkiv/tabl-tbl.mkiv @@ -1109,8 +1109,8 @@ \let\tabl_tabulate_insert_head\empty \fi \ifcsname\??tabulatefoot\currenttabulation\endcsname - \expandafter\ifx\csname\??tabulatefoot\currenttabulation\endcsname\empty - %\expandafter\ifx\lastnamedcs\empty + %\expandafter\ifx\csname\??tabulatefoot\currenttabulation\endcsname\empty + \expandafter\ifx\lastnamedcs\empty \let\tabl_tabulate_insert_foot\empty \else \let\tabl_tabulate_insert_foot\tabl_tabulate_insert_foot_content diff --git a/tex/context/base/mkiv/trac-inf.lua b/tex/context/base/mkiv/trac-inf.lua index 40dfe854e..244ba4604 100644 --- a/tex/context/base/mkiv/trac-inf.lua +++ b/tex/context/base/mkiv/trac-inf.lua @@ -45,12 +45,19 @@ end local ticks = clock local seconds = function(n) return n or 0 end -if lua.getpreciseticks then +if os.type ~= "windows" then + + -- doesn't work well yet on unix (system time vs process time so a mtxrun + -- timing with nested call gives the wrong result) + +elseif lua.getpreciseticks then ticks = lua.getpreciseticks seconds = lua.getpreciseseconds -elseif FFISUPPORTED and ffi and os.type == "windows" then +elseif FFISUPPORTED then + + -- Do we really care when not in luametatex? For now we do, so: local okay, kernel = pcall(ffi.load,"kernel32") @@ -221,12 +228,12 @@ function statistics.show() -- end) if LUATEXENGINE == "luametatex" then register("used engine", function() - return format("%s version %s, functionality level %s, format id %s", - LUATEXENGINE, LUATEXVERSION, LUATEXFUNCTIONALITY, LUATEXFORMATID) + return format("%s version: %s, functionality level: %s, format id: %s, compiler: %s", + LUATEXENGINE, LUATEXVERSION, LUATEXFUNCTIONALITY, LUATEXFORMATID, status.used_compiler) end) else register("used engine", function() - return format("%s version %s with functionality level %s, banner: %s", + return format("%s version: %s, functionality level: %s, banner: %s", LUATEXENGINE, LUATEXVERSION, LUATEXFUNCTIONALITY, lower(status.banner)) end) end @@ -234,7 +241,7 @@ function statistics.show() return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra) end) register("callbacks", statistics.callbacks) - if TEXENGINE == "luajittex" and JITSUPPORTED then + if JITSUPPORTED then local jitstatus = jit.status if jitstatus then local jitstatus = { jitstatus() } @@ -272,7 +279,7 @@ end function statistics.memused() -- no math.round yet -) local round = math.round or math.floor - return format("%s MB, ctx: %s MB, max: %s MB)", + return format("%s MB, ctx: %s MB, max: %s MB", round(collectgarbage("count")/1000), round(status.luastate_bytes/1000000), status.luastate_bytes_max and round(status.luastate_bytes_max/1000000) or "unknown" diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua index e592b7d0c..0ca50899b 100644 --- a/tex/context/base/mkiv/trac-vis.lua +++ b/tex/context/base/mkiv/trac-vis.lua @@ -142,34 +142,34 @@ local enableaction = nodes.tasks.enableaction local report_visualize = logs.reporter("visualize") local modes = { - hbox = 1, - vbox = 2, - vtop = 4, - kern = 8, - glue = 16, - -- skip = 16, - penalty = 32, - fontkern = 64, - strut = 128, - whatsit = 256, - glyph = 512, - simple = 1024, - simplehbox = 1024 + 1, - simplevbox = 1024 + 2, - simplevtop = 1024 + 4, - user = 2048, - math = 4096, - italic = 8192, - origin = 16384, - discretionary = 32768, - expansion = 65536, - line = 131072, - space = 262144, - depth = 524288, + hbox = 0x000001, + vbox = 0x000002, + vtop = 0x000004, + kern = 0x000008, + glue = 0x000010, + penalty = 0x000020, + fontkern = 0x000040, + strut = 0x000080, + whatsit = 0x000100, + glyph = 0x000200, + simple = 0x000400, + simplehbox = 0x000401, + simplevbox = 0x000402, + simplevtop = 0x000404, + user = 0x000800, + math = 0x001000, + italic = 0x002000, + origin = 0x004000, + discretionary = 0x008000, + expansion = 0x010000, + line = 0x020000, + space = 0x040000, + depth = 0x080000, + marginkern = 0x100000, } local usedfont, exheight, emwidth -local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic, l_origin, l_discretionary, l_expansion, l_line, l_space, l_depth +local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_marginkern, l_italic, l_origin, l_discretionary, l_expansion, l_line, l_space, l_depth local enabled = false local layers = { } @@ -178,7 +178,7 @@ local preset_boxes = modes.hbox + modes.vbox + modes.origin local preset_makeup = preset_boxes + modes.kern + modes.glue + modes.penalty local preset_all = preset_makeup - + modes.fontkern + modes.whatsit + modes.glyph + modes.user + modes.math + + modes.fontkern + modes.marginkern + modes.whatsit + modes.glyph + modes.user + modes.math function visualizers.setfont(id) usedfont = id or current_font() @@ -222,6 +222,7 @@ local function initialize() l_user = layers.user l_math = layers.math l_italic = layers.italic + l_marginkern = layers.marginkern l_origin = layers.origin l_discretionary = layers.discretionary l_expansion = layers.expansion @@ -462,10 +463,11 @@ end local caches = setmetatableindex("table") -local fontkern, italickern do +local fontkern, italickern, marginkern do local f_cache = caches["fontkern"] local i_cache = caches["italickern"] + local m_cache = caches["marginkern"] local function somekern(head,current,cache,color,layer) local width = getkern(current) @@ -503,6 +505,10 @@ local fontkern, italickern do return somekern(head,current,i_cache,c_glyph_d,l_italic) end + marginkern = function(head,current) + return somekern(head,current,m_cache,c_glyph_d,l_marginkern) + end + end local glyphexpansion do @@ -1053,6 +1059,31 @@ local ruleditalic do end +local ruledmarginkern do + + local m_cache = caches["marginkern"] + + ruledmarginkern = function(head,current) + local kern = getkern(current) + local info = m_cache[kern] + if not info then + local amount = formatters["%s:%0.3f"]("MK",kern*pt_factor) + if kern > 0 then + info = sometext(amount,l_marginkern,c_positive) + elseif kern < 0 then + info = sometext(amount,l_marginkern,c_negative) + else + info = sometext(amount,l_marginkern,c_zero) + end + m_cache[kern] = info + end + info = copy_list(info) + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + local ruleddiscretionary do local d_cache = caches["discretionary"] @@ -1122,10 +1153,12 @@ do local vlist_code = nodecodes.vlist local marginkern_code = nodecodes.marginkern - local kerncodes = nodes.kerncodes - local fontkern_code = kerncodes.fontkern - local italickern_code = kerncodes.italiccorrection - ----- userkern_code = kerncodes.userkern + local kerncodes = nodes.kerncodes + local fontkern_code = kerncodes.fontkern + local italickern_code = kerncodes.italiccorrection + local leftmarginkern_code = kerncodes.leftmarginkern + local rightmarginkern_code = kerncodes.rightmarginkern + ----- userkern_code = kerncodes.userkern local listcodes = nodes.listcodes local linelist_code = listcodes.line @@ -1133,32 +1166,33 @@ do local cache local function visualize(head,vertical,forced,parent) - local trace_hbox = false - local trace_vbox = false - local trace_vtop = false - local trace_kern = false - local trace_glue = false - local trace_penalty = false - local trace_fontkern = false - local trace_strut = false - local trace_whatsit = false - local trace_glyph = false - local trace_simple = false - local trace_user = false - local trace_math = false - local trace_italic = false - local trace_origin = false - local trace_discretionary = false - local trace_expansion = false - local trace_line = false - local trace_space = false - local trace_depth = false - local current = head - local previous = nil - local attr = unsetvalue - local prev_trace_fontkern = nil - local prev_trace_italic = nil - local prev_trace_expansion = nil + local trace_hbox = false + local trace_vbox = false + local trace_vtop = false + local trace_kern = false + local trace_glue = false + local trace_penalty = false + local trace_fontkern = false + local trace_strut = false + local trace_whatsit = false + local trace_glyph = false + local trace_simple = false + local trace_user = false + local trace_math = false + local trace_italic = false + local trace_origin = false + local trace_discretionary = false + local trace_expansion = false + local trace_line = false + local trace_space = false + local trace_depth = false + local current = head + local previous = nil + local attr = unsetvalue + local prev_trace_fontkern = nil + local prev_trace_marginkern = nil + local prev_trace_italic = nil + local prev_trace_expansion = nil -- local function setthem(t,k) -- local v_trace_hbox = band(k, 1) ~= 0 @@ -1215,9 +1249,10 @@ do local id = getid(current) local a = forced or getattr(current,a_visual) or unsetvalue if a ~= attr then - prev_trace_fontkern = trace_fontkern - prev_trace_italic = trace_italic - prev_trace_expansion = trace_expansion + prev_trace_fontkern = trace_fontkern + prev_trace_italic = trace_italic + prev_trace_marginkern = trace_marginkern + prev_trace_expansion = trace_expansion attr = a if a == unsetvalue then trace_hbox = false @@ -1240,29 +1275,31 @@ do trace_line = false trace_space = false trace_depth = false + trace_marginkern = false goto list else -- dead slow: -- cache[a]() - trace_hbox = band(a, 1) ~= 0 - trace_vbox = band(a, 2) ~= 0 - trace_vtop = band(a, 4) ~= 0 - trace_kern = band(a, 8) ~= 0 - trace_glue = band(a, 16) ~= 0 - trace_penalty = band(a, 32) ~= 0 - trace_fontkern = band(a, 64) ~= 0 - trace_strut = band(a, 128) ~= 0 - trace_whatsit = band(a, 256) ~= 0 - trace_glyph = band(a, 512) ~= 0 - trace_simple = band(a, 1024) ~= 0 - trace_user = band(a, 2048) ~= 0 - trace_math = band(a, 4096) ~= 0 - trace_italic = band(a, 8192) ~= 0 - trace_origin = band(a, 16384) ~= 0 - trace_discretionary = band(a, 32768) ~= 0 - trace_expansion = band(a, 65536) ~= 0 - trace_line = band(a,131072) ~= 0 - trace_space = band(a,262144) ~= 0 - trace_depth = band(a,524288) ~= 0 + trace_hbox = band(a,0x000001) ~= 0 + trace_vbox = band(a,0x000002) ~= 0 + trace_vtop = band(a,0x000004) ~= 0 + trace_kern = band(a,0x000008) ~= 0 + trace_glue = band(a,0x000010) ~= 0 + trace_penalty = band(a,0x000020) ~= 0 + trace_fontkern = band(a,0x000040) ~= 0 + trace_strut = band(a,0x000080) ~= 0 + trace_whatsit = band(a,0x000100) ~= 0 + trace_glyph = band(a,0x000200) ~= 0 + trace_simple = band(a,0x000400) ~= 0 + trace_user = band(a,0x000800) ~= 0 + trace_math = band(a,0x001000) ~= 0 + trace_italic = band(a,0x002000) ~= 0 + trace_origin = band(a,0x004000) ~= 0 + trace_discretionary = band(a,0x008000) ~= 0 + trace_expansion = band(a,0x010000) ~= 0 + trace_line = band(a,0x020000) ~= 0 + trace_space = band(a,0x040000) ~= 0 + trace_depth = band(a,0x080000) ~= 0 + trace_marginkern = band(a,0x100000) ~= 0 end elseif a == unsetvalue then goto list @@ -1306,6 +1343,12 @@ do elseif trace_kern then head, current = ruleditalic(head,current) end + elseif subtype == leftmarginkern_code or subtype == rightmarginkern_code then + if trace_marginkern or prev_trace_marginkern then + head, current = marginkern(head,current) + elseif trace_kern then + head, current = ruledmarginkern(head,current) + end else if trace_kern then head, current = ruledkern(head,current,vertical) diff --git a/tex/context/base/mkiv/typo-brk.mkiv b/tex/context/base/mkiv/typo-brk.mkiv index 10b2f8e21..6071221dd 100644 --- a/tex/context/base/mkiv/typo-brk.mkiv +++ b/tex/context/base/mkiv/typo-brk.mkiv @@ -59,11 +59,12 @@ \endgroup} \unexpanded\def\setbreakpoints[#1]% - {\exhyphenchar\minusone % we use a different order tha n base tex, so we really need this + {\exhyphenchar\minusone % we use a different order than base tex, so we really need this \clf_setbreakpoints{#1}} \unexpanded\def\resetbreakpoints - {\attribute\breakpointattribute\attributeunsetvalue} + {\exhyphenchar\hyphenasciicode % 2020.03.05 + \attribute\breakpointattribute\attributeunsetvalue} \definebreakpoints[compound] diff --git a/tex/context/base/mkiv/typo-cap.mkiv b/tex/context/base/mkiv/typo-cap.mkiv index 890b08186..20e2eb7a9 100644 --- a/tex/context/base/mkiv/typo-cap.mkiv +++ b/tex/context/base/mkiv/typo-cap.mkiv @@ -40,7 +40,6 @@ \definecapitals[\v!capital] % one upper + font \definecapitals[\v!Capital] % some upper + font \definecapitals[\v!mixed] % UpperCase -\definecapitals[\v!WORD] % all lower \definecapitals[\v!Word] % one upper + font \definecapitals[\v!Words] % some upper \definecapitals[\v!camel] % lowers first diff --git a/tex/context/base/mkiv/typo-dha.lua b/tex/context/base/mkiv/typo-dha.lua index 9a6e39f42..7d5c7751b 100644 --- a/tex/context/base/mkiv/typo-dha.lua +++ b/tex/context/base/mkiv/typo-dha.lua @@ -59,6 +59,7 @@ local getdirection = nuts.getdirection local isglyph = nuts.isglyph -- or ischar local setprop = nuts.setprop +local setstate = nuts.setstate local setchar = nuts.setchar local insert_node_before = nuts.insert_before @@ -100,7 +101,6 @@ local directions = typesetters.directions local setcolor = directions.setcolor local getglobal = directions.getglobal -local a_state = attributes.private('state') local a_directions = attributes.private('directions') local strip = false @@ -191,7 +191,7 @@ local function process(start) end elseif lro or override < 0 then if direction == "r" or direction == "al" then - setprop(current,a_state,s_isol) -- hm + setstate(current,s_isol) -- hm direction = "l" reversed = true end diff --git a/tex/context/base/mkiv/typo-fln.lua b/tex/context/base/mkiv/typo-fln.lua index 6cca92480..326d3acf5 100644 --- a/tex/context/base/mkiv/typo-fln.lua +++ b/tex/context/base/mkiv/typo-fln.lua @@ -180,6 +180,8 @@ actions[v_line] = function(head,setting) -- nodes.handlers.protectglyphs(temp) -- not needed as we discard -- temp = typesetters.spacings.handler(temp) -- maybe when enabled -- temp = typesetters.kerns.handler(temp) -- maybe when enabled +-- temp = typesetters.cases.handler(temp) -- maybe when enabled +flush_node_list(temp); local width = getdimensions(temp) return width end diff --git a/tex/context/base/mkiv/typo-itc.lua b/tex/context/base/mkiv/typo-itc.lua index 64701abcc..c3a583fe4 100644 --- a/tex/context/base/mkiv/typo-itc.lua +++ b/tex/context/base/mkiv/typo-itc.lua @@ -45,7 +45,7 @@ local getkern = nuts.getkern local getheight = nuts.getheight local insert_node_after = nuts.insert_after -local delete_node = nuts.delete +local remove_node = nuts.remove local end_of_math = nuts.end_of_math local texgetattribute = tex.getattribute @@ -315,7 +315,7 @@ local function texthandler(head) if trace_italics then report_italics("deleting last correction before %s %C",char,"glyph") end - delete_node(prevhead,previnserted) + remove_node(prevhead,previnserted,true) else -- if replaceitalic ~= 0 then @@ -327,7 +327,7 @@ local function texthandler(head) if trace_italics then report_italics("deleting last correction before %s %C","replace",char) end - delete_node(replacehead,replaceinserted) + remove_node(replacehead,replaceinserted,true) end -- if postitalic ~= 0 then @@ -339,7 +339,7 @@ local function texthandler(head) if trace_italics then report_italics("deleting last correction before %s %C","post",char) end - delete_node(posthead,postinserted) + remove_node(posthead,postinserted,true) end end -- diff --git a/tex/context/base/mkiv/typo-krn.lua b/tex/context/base/mkiv/typo-krn.lua index f4f1215e1..489375e9b 100644 --- a/tex/context/base/mkiv/typo-krn.lua +++ b/tex/context/base/mkiv/typo-krn.lua @@ -28,7 +28,6 @@ local flush_node = nuts.flush_node local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after local end_of_math = nuts.end_of_math -local use_components = nuts.use_components local copy_node = nuts.copy local getnext = nuts.getnext @@ -365,209 +364,6 @@ local function closest_bound(b,get) end end --- function kerns.handler(head) --- local start = head --- local lastfont = nil --- local keepligature = kerns.keepligature --- local keeptogether = kerns.keeptogether --- local fillup = false --- local bound = false --- local prev = nil --- local previd = nil --- local prevchar = nil --- local prevfont = nil --- local prevmark = nil --- while start do --- -- fontkerns don't get the attribute but they always sit between glyphs so --- -- are always valid bound .. disc nodes also somtimes don't get them --- local id = getid(start) --- local attr = takeattr(start,a_kerns) --- if attr and attr > 0 then --- local krn = mapping[attr] --- if krn == v_max then --- krn = .25 --- fillup = true --- else --- fillup = false --- end --- if not krn or krn == 0 then --- bound = false --- elseif id == glyph_code then --- if keepligature and keepligature(start) then --- -- keep 'm --- else --- -- we could use the subtype ligature but that's also a call --- -- todo: check tounicode and use that information to split --- head, start = use_components(head,start) --- end --- local char, font = isglyph(start) --- local mark = markdata[font] --- if not bound then --- -- yet --- elseif mark[char] then --- -- skip --- elseif previd == kern_code then --- if getsubtype(prev) == fontkern_code then --- local inject = true --- if keeptogether then --- if previd == glyph_code and keeptogether(prev,start) then --- inject = false --- end --- end --- if inject then --- -- not yet ok, as injected kerns can be overlays (from node-inj.lua) --- setkern(prev,getkern(prev) + quaddata[font]*krn,userkern_code) --- end --- end --- elseif previd == glyph_code then --- if prevfont == font then --- if keeptogether and keeptogether(prev,start) then --- -- keep 'm --- else --- local data = chardata[font][prevchar] --- local kerns = data and data.kerns --- local kern = (kerns and kerns[char] or 0) + quaddata[font]*krn --- insert_node_before(head,start,kern_injector(fillup,kern)) --- end --- else --- insert_node_before(head,start,kern_injector(fillup,quaddata[font]*krn)) --- end --- end --- prev = start --- prevchar = char --- prevfont = font --- prevmark = mark --- previd = id --- bound = true --- elseif id == disc_code then --- local prev, next, pglyph, nglyph -- delayed till needed --- local subtype = getsubtype(start) --- -- if subtype == automaticdisc_code then --- -- -- this is kind of special, as we have already injected the --- -- -- previous kern --- -- local prev = getprev(start) --- -- local pglyph = prev and getid(prev) == glyph_code --- -- languages.expand(start,pglyph and prev) --- -- -- we can have a different start now --- -- elseif subtype ~= discretionarydisc_code then --- -- prev = getprev(start) --- -- pglyph = prev and getid(prev) == glyph_code --- -- languages.expand(start,pglyph and prev) --- -- end --- local pre, post, replace = getdisc(start) --- local indeed = false --- if pre then --- local okay = false --- if not prev then --- prev = getprev(start) --- pglyph = prev and getid(prev) == glyph_code --- end --- if pglyph then --- pre, okay = inject_begin(pre,prev,keeptogether,krn,okay) --- end --- pre, okay = process_list(pre,keeptogether,krn,false,okay) --- if okay then --- indeed = true --- end --- end --- if post then --- local okay = false --- if not next then --- next = getnext(start) --- nglyph = next and getid(next) == glyph_code --- end --- if nglyph then --- post, okay = inject_end(post,next,keeptogether,krn,okay) --- end --- post, okay = process_list(post,keeptogether,krn,false,okay) --- if okay then --- indeed = true --- end --- end --- if replace then --- local okay = false --- if not prev then --- prev = getprev(start) --- pglyph = prev and getid(prev) == glyph_code --- end --- if pglyph then --- replace, okay = inject_begin(replace,prev,keeptogether,krn,okay) --- end --- if not next then --- next = getnext(start) --- nglyph = next and getid(next) == glyph_code --- end --- if nglyph then --- replace, okay = inject_end(replace,next,keeptogether,krn,okay) --- end --- replace, okay = process_list(replace,keeptogether,krn,false,okay) --- if okay then --- indeed = true --- end --- elseif prevfont then --- replace = new_kern(quaddata[prevfont]*krn) --- indeed = true --- end --- if indeed then --- setdisc(start,pre,post,replace) --- end --- bound = false --- elseif id == kern_code then --- bound = getsubtype(start) == fontkern_code --- prev = start --- previd = id --- elseif id == glue_code then --- local subtype = getsubtype(start) --- if subtype == userskip_code or subtype == xspaceskip_code or subtype == spaceskip_code then --- local width, stretch, shrink, stretch_order, shrink_order = getglue(start) --- if width > 0 then --- local w = width + gluefactor * width * krn --- stretch = stretch * w / width --- shrink = shrink * w / width --- if fillup then --- stretch = 2 * stretch --- shrink = 2 * shrink --- stretch_order = 1 --- -- shrink_order = 1 ? --- end --- setglue(start,w,stretch,shrink,stretch_order,shrink_order) --- end --- end --- bound = false --- elseif id == hlist_code or id == vlist_code then --- local subtype = getsubtype(start) --- if subtype == unknownlist_code or subtype == boxlist_code then --- -- special case --- local b, f = closest_bound(start,getprev) --- if b then --- insert_node_before(head,start,kern_injector(fillup,quaddata[f]*krn)) --- end --- local b, f = closest_bound(start,getnext) --- if b then --- insert_node_after(head,start,kern_injector(fillup,quaddata[f]*krn)) --- end --- end --- bound = false --- elseif id == math_code then --- start = end_of_math(start) --- bound = false --- end --- if start then --- start = getnext(start) --- end --- elseif id == kern_code then --- bound = getsubtype(start) == fontkern_code --- prev = start --- previd = id --- start = getnext(start) --- else --- bound = false --- start = getnext(start) --- end --- end --- return head --- end - function kerns.handler(head) local start = head local lastfont = nil @@ -601,7 +397,6 @@ function kerns.handler(head) if keepligature and keepligature(start) then -- keep 'm else - -- head, start = use_components(head,start) -- beware, these are not kerned so we mighty need a kern only pass -- maybe some day .. anyway, one should disable ligaturing local data = chardata[font][char] diff --git a/tex/context/base/mkiv/typo-rep.lua b/tex/context/base/mkiv/typo-rep.lua index d29eb17b8..2538a014d 100644 --- a/tex/context/base/mkiv/typo-rep.lua +++ b/tex/context/base/mkiv/typo-rep.lua @@ -28,7 +28,7 @@ local isglyph = nuts.isglyph local getattr = nuts.getattr -local delete_node = nuts.delete +local remove_node = nuts.remove local replace_node = nuts.replace local copy_node = nuts.copy @@ -62,7 +62,7 @@ local function process(what,head,current,char) if trace_stripping then report_stripping("deleting %C from text",char) end - head, current = delete_node(head,current) + head, current = remove_node(head,current,true) elseif type(what) == "function" then head, current = what(head,current) current = getnext(current) diff --git a/tex/context/base/mkiv/util-soc-imp-copas.lua b/tex/context/base/mkiv/util-soc-imp-copas.lua index 1268613d1..cbcc40173 100644 --- a/tex/context/base/mkiv/util-soc-imp-copas.lua +++ b/tex/context/base/mkiv/util-soc-imp-copas.lua @@ -1,5 +1,10 @@ -- original file : copas.lua --- for more into : see util-soc.lua +-- for more info : see util-soc.lua +-- copyright : see below +-- comment : this version is a it cleaned up and adapted + +-- there is an official update but i'll wait till it is stable before i check +-- it out (after all what we have now seems to work ok) local socket = socket or require("socket") local ssl = ssl or nil -- only loaded upon demand diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua index 4d23f88b7..aba7859c3 100644 --- a/tex/context/base/mkiv/util-str.lua +++ b/tex/context/base/mkiv/util-str.lua @@ -1273,7 +1273,6 @@ local function make(t,str) f = function() return str end end end - -- if jit then jit.on(f,true) end t[str] = f return f end diff --git a/tex/context/modules/mkiv/s-math-ligatures.mkiv b/tex/context/modules/mkiv/s-math-ligatures.mkiv index 39fc4d2a3..08457e031 100644 --- a/tex/context/modules/mkiv/s-math-ligatures.mkiv +++ b/tex/context/modules/mkiv/s-math-ligatures.mkiv @@ -31,20 +31,21 @@ \continueifinputfile{s-math-ligatures.mkiv} -\setupbodyfont[dejavu,10pt] - -\setuplayout - [width=middle, - height=middle, - topspace=15mm, - backspace=15mm, - bottomspace=15mm, - header=1cm, - headerdistance=0.5cm, - footer=0pt] +\usemodule[article-basics] \setuplayout[tight] \setupbodyfont[10pt] \starttext - \showmathligatures +\showmathligatures + +\blank[2*big] + +\starttyping +sp = special +ml = mathlist + +\setupmathematics[collapsing=1] : special +\setupmathematics[collapsing=2] : special mathlist +\setupmathematics[collapsing=3] : mathlist special +\stoptyping \stoptext diff --git a/tex/context/modules/mkiv/x-mathml.lua b/tex/context/modules/mkiv/x-mathml.lua index 05feecf47..c8c773475 100644 --- a/tex/context/modules/mkiv/x-mathml.lua +++ b/tex/context/modules/mkiv/x-mathml.lua @@ -15,7 +15,7 @@ local strip = string.strip local xmlsprint, xmlcprint, xmltext, xmlcontent, xmlempty = xml.sprint, xml.cprint, xml.text, xml.content, xml.empty local lxmlcollected, lxmlfilter = lxml.collected, lxml.filter local getid = lxml.getid -local utfchar, utfcharacters, utfvalues, utfsplit, utflen = utf.char, utf.characters, utf.values, utf.split, utf.len +local utfchar, utfcharacters, utfsplit, utflen = utf.char, utf.characters, utf.split, utf.len local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns local P, Cs = lpeg.P, lpeg.Cs diff --git a/tex/generic/context/luatex/luatex-basics-nod.lua b/tex/generic/context/luatex/luatex-basics-nod.lua index be82277bd..0fb768cf8 100644 --- a/tex/generic/context/luatex/luatex-basics-nod.lua +++ b/tex/generic/context/luatex/luatex-basics-nod.lua @@ -96,7 +96,6 @@ nuts.tonut = tonut nuts.getattr = direct.get_attribute nuts.getboth = direct.getboth nuts.getchar = direct.getchar -nuts.getcomponents = direct.getcomponents nuts.getdirection = direct.getdirection nuts.getdisc = direct.getdisc nuts.getreplace = direct.getreplace @@ -137,7 +136,6 @@ nuts.isglyph = direct.is_glyph nuts.copy = direct.copy nuts.copy_list = direct.copy_list nuts.copy_node = direct.copy -nuts.delete = direct.delete nuts.end_of_math = direct.end_of_math nuts.flush = direct.flush nuts.flush_list = direct.flush_list @@ -196,9 +194,8 @@ local getnext = nuts.getnext local setlink = nuts.setlink local getfield = nuts.getfield local setfield = nuts.setfield -local getcomponents = nuts.getcomponents -local setcomponents = nuts.setcomponents - +local getsubtype = nuts.getsubtype +local isglyph = nuts.isglyph local find_tail = nuts.tail local flush_list = nuts.flush_list local flush_node = nuts.flush_node @@ -206,40 +203,72 @@ local traverse_id = nuts.traverse_id local copy_node = nuts.copy_node local glyph_code = nodes.nodecodes.glyph +local ligature_code = nodes.glyphcodes.ligature + +do -function nuts.copy_no_components(g,copyinjection) - local components = getcomponents(g) - if components then - setcomponents(g) - local n = copy_node(g) - if copyinjection then - copyinjection(n,g) + local get_components = node.direct.getcomponents + local set_components = node.direct.setcomponents + + local function copy_no_components(g,copyinjection) + local components = get_components(g) + if components then + set_components(g) + local n = copy_node(g) + if copyinjection then + copyinjection(n,g) + end + set_components(g,components) + -- maybe also upgrade the subtype but we don't use it anyway + return n + else + local n = copy_node(g) + if copyinjection then + copyinjection(n,g) + end + return n end - setcomponents(g,components) - -- maybe also upgrade the subtype but we don't use it anyway - return n - else - local n = copy_node(g) - if copyinjection then - copyinjection(n,g) + end + + local function copy_only_glyphs(current) + local head = nil + local previous = nil + for n in traverse_id(glyph_code,current) do + n = copy_node(n) + if head then + setlink(previous,n) + else + head = n + end + previous = n end - return n + return head end -end -function nuts.copy_only_glyphs(current) - local head = nil - local previous = nil - for n in traverse_id(glyph_code,current) do - n = copy_node(n) - if head then - setlink(previous,n) - else - head = n + local function count_components(start,marks) + local char = isglyph(start) + if char then + if getsubtype(start) == ligature_code then + local n = 0 + local components = get_components(start) + while components do + n = n + count_components(components,marks) + components = getnext(components) + end + return n + elseif not marks[char] then + return 1 + end end - previous = n + return 0 end - return head + + nuts.set_components = set_components + nuts.get_components = get_components + nuts.copy_only_glyphs = copy_only_glyphs + nuts.copy_no_components = copy_no_components + nuts.count_components = count_components + end nuts.uses_font = direct.uses_font diff --git a/tex/generic/context/luatex/luatex-core.lua b/tex/generic/context/luatex/luatex-core.lua index a0f46dd2e..538d8f903 100644 --- a/tex/generic/context/luatex/luatex-core.lua +++ b/tex/generic/context/luatex/luatex-core.lua @@ -7,7 +7,7 @@ -- copyright = 'LuaTeX Development Team', -- } -LUATEXCOREVERSION = 1.112 -- we reflect the luatex version where changes happened +LUATEXCOREVERSION = 1.120 -- we reflect the luatex version where changes happened -- This file overloads some Lua functions. The readline variants provide the same -- functionality as LuaTeX <= 1.04 and doing it this way permits us to keep the @@ -194,12 +194,20 @@ end if saferoption == 1 or shellescape ~= 1 then + package.loadlib = function() end + package.searchers[4] = nil + package.searchers[3] = nil + ffi = require('ffi') - for k, v in next, ffi do - if k ~= 'gc' then - ffi[k] = nil + + if ffi then + for k, v in next, ffi do + if k ~= 'gc' then + ffi[k] = nil + end end end + ffi = nil end diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 41fbe10fd..0d467a244 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2020-02-17 12:06 +-- merge date : 2020-03-10 14:44 do -- begin closure to overcome local limits and interference @@ -4923,7 +4923,6 @@ nuts.tonut=tonut nuts.getattr=direct.get_attribute nuts.getboth=direct.getboth nuts.getchar=direct.getchar -nuts.getcomponents=direct.getcomponents nuts.getdirection=direct.getdirection nuts.getdisc=direct.getdisc nuts.getreplace=direct.getreplace @@ -4961,7 +4960,6 @@ nuts.isglyph=direct.is_glyph nuts.copy=direct.copy nuts.copy_list=direct.copy_list nuts.copy_node=direct.copy -nuts.delete=direct.delete nuts.end_of_math=direct.end_of_math nuts.flush=direct.flush nuts.flush_list=direct.flush_list @@ -5009,45 +5007,72 @@ local getnext=nuts.getnext local setlink=nuts.setlink local getfield=nuts.getfield local setfield=nuts.setfield -local getcomponents=nuts.getcomponents -local setcomponents=nuts.setcomponents +local getsubtype=nuts.getsubtype +local isglyph=nuts.isglyph local find_tail=nuts.tail local flush_list=nuts.flush_list local flush_node=nuts.flush_node local traverse_id=nuts.traverse_id local copy_node=nuts.copy_node local glyph_code=nodes.nodecodes.glyph -function nuts.copy_no_components(g,copyinjection) - local components=getcomponents(g) - if components then - setcomponents(g) - local n=copy_node(g) - if copyinjection then - copyinjection(n,g) - end - setcomponents(g,components) - return n - else - local n=copy_node(g) - if copyinjection then - copyinjection(n,g) +local ligature_code=nodes.glyphcodes.ligature +do + local get_components=node.direct.getcomponents + local set_components=node.direct.setcomponents + local function copy_no_components(g,copyinjection) + local components=get_components(g) + if components then + set_components(g) + local n=copy_node(g) + if copyinjection then + copyinjection(n,g) + end + set_components(g,components) + return n + else + local n=copy_node(g) + if copyinjection then + copyinjection(n,g) + end + return n end - return n end -end -function nuts.copy_only_glyphs(current) - local head=nil - local previous=nil - for n in traverse_id(glyph_code,current) do - n=copy_node(n) - if head then - setlink(previous,n) - else - head=n + local function copy_only_glyphs(current) + local head=nil + local previous=nil + for n in traverse_id(glyph_code,current) do + n=copy_node(n) + if head then + setlink(previous,n) + else + head=n + end + previous=n end - previous=n + return head end - return head + local function count_components(start,marks) + local char=isglyph(start) + if char then + if getsubtype(start)==ligature_code then + local n=0 + local components=get_components(start) + while components do + n=n+count_components(components,marks) + components=getnext(components) + end + return n + elseif not marks[char] then + return 1 + end + end + return 0 + end + nuts.set_components=set_components + nuts.get_components=get_components + nuts.copy_only_glyphs=copy_only_glyphs + nuts.copy_no_components=copy_no_components + nuts.count_components=count_components end nuts.uses_font=direct.uses_font do @@ -10354,7 +10379,7 @@ local match,format,find,concat,gsub,lower=string.match,string.format,string.find local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match local formatters=string.formatters local sortedhash,sortedkeys=table.sortedhash,table.sortedkeys -local rshift=bit32.rshift +local idiv=number.idiv local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end) local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_mapping=v end) local report_fonts=logs.reporter("fonts","loading") @@ -10387,12 +10412,21 @@ local function makenameparser(str) end local f_single=formatters["%04X"] local f_double=formatters["%04X%04X"] +local s_unknown="FFFD" local function tounicode16(unicode) if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then return f_single(unicode) + elseif unicode>=0x00E000 and unicode<=0x00F8FF then + return s_unknown + elseif unicode>=0x0F0000 and unicode<=0x0FFFFF then + return s_unknown + elseif unicode>=0x100000 and unicode<=0x10FFFF then + return s_unknown + elseif unicode>=0x00D800 and unicode<=0x00DFFF then + return s_unknown else unicode=unicode-0x10000 - return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00) + return f_double(idiv(k,0x400)+0xD800,unicode%0x400+0xDC00) end end local function tounicode16sequence(unicodes) @@ -10401,14 +10435,21 @@ local function tounicode16sequence(unicodes) local u=unicodes[l] if u<0xD7FF or (u>0xDFFF and u<=0xFFFF) then t[l]=f_single(u) + elseif unicode>=0x00E000 and unicode<=0x00F8FF then + t[l]=s_unknown + elseif unicode>=0x0F0000 and unicode<=0x0FFFFF then + t[l]=s_unknown + elseif unicode>=0x100000 and unicode<=0x10FFFF then + t[l]=s_unknown + elseif unicode>=0x00D7FF and unicode<=0x00DFFF then + t[l]=s_unknown else u=u-0x10000 - t[l]=f_double(rshift(u,10)+0xD800,u%1024+0xDC00) + t[l]=f_double(idiv(k,0x400)+0xD800,u%0x400+0xDC00) end end return concat(t) end -local unknown=f_single(0xFFFD) local hash={} local conc={} table.setmetatableindex(hash,function(t,k) @@ -10416,7 +10457,7 @@ table.setmetatableindex(hash,function(t,k) v=f_single(k) else local k=k-0x10000 - v=f_double(rshift(k,10)+0xD800,k%1024+0xDC00) + v=f_double(idiv(k,0x400)+0xD800,k%0x400+0xDC00) end t[k]=v return v @@ -10429,11 +10470,13 @@ local function tounicode(k) end return concat(conc,"",1,n) elseif k>=0x00E000 and k<=0x00F8FF then - return unknown + return s_unknown elseif k>=0x0F0000 and k<=0x0FFFFF then - return unknown + return s_unknown elseif k>=0x100000 and k<=0x10FFFF then - return unknown + return s_unknown + elseif k>=0x00D7FF and k<=0x00DFFF then + return s_unknown else return hash[k] end @@ -25929,7 +25972,6 @@ local initializers=allocate() local methods=allocate() analyzers.initializers=initializers analyzers.methods=methods -local a_state=attributes.private('state') local nuts=nodes.nuts local tonut=nuts.tonut local getnext=nuts.getnext @@ -25949,6 +25991,23 @@ local categories=characters and characters.categories or {} local chardata=characters and characters.data local otffeatures=fonts.constructors.features.otf local registerotffeature=otffeatures.register +local setstate=nuts.setstate +local getstate=nuts.getstate +if not setstate or not getstate then + setstate=function(n,v) + setprop(n,"state",v) + end + getstate=function(n,v) + local s=getprop(n,"state") + if v then + return s==v + else + return s + end + end + nuts.setstate=setstate + nuts.getstate=getstate +end local s_init=1 local s_rphf=7 local s_medi=2 local s_half=8 local s_fina=3 local s_pref=9 @@ -25996,49 +26055,49 @@ function analyzers.setstate(head,font) current=tonut(current) while current do local char,id=ischar(current,font) - if char and not getprop(current,a_state) then + if char and not getstate(current) then done=true local d=descriptions[char] if d then if d.class=="mark" then done=true - setprop(current,a_state,s_mark) + setstate(current,s_mark) elseif useunicodemarks and categories[char]=="mn" then done=true - setprop(current,a_state,s_mark) + setstate(current,s_mark) elseif n==0 then first,last,n=current,current,1 - setprop(current,a_state,s_init) + setstate(current,s_init) else last,n=current,n+1 - setprop(current,a_state,s_medi) + setstate(current,s_medi) end else if first and first==last then - setprop(last,a_state,s_isol) + setstate(last,s_isol) elseif last then - setprop(last,a_state,s_fina) + setstate(last,s_fina) end first,last,n=nil,nil,0 end elseif char==false then if first and first==last then - setprop(last,a_state,s_isol) + setstate(last,s_isol) elseif last then - setprop(last,a_state,s_fina) + setstate(last,s_fina) end first,last,n=nil,nil,0 if id==math_code then current=end_of_math(current) end elseif id==disc_code then - setprop(current,a_state,s_medi) + setstate(current,s_medi) last=current else if first and first==last then - setprop(last,a_state,s_isol) + setstate(last,s_isol) elseif last then - setprop(last,a_state,s_fina) + setstate(last,s_fina) end first,last,n=nil,nil,0 if id==math_code then @@ -26048,9 +26107,9 @@ function analyzers.setstate(head,font) current=getnext(current) end if first and first==last then - setprop(last,a_state,s_isol) + setstate(last,s_isol) elseif last then - setprop(last,a_state,s_fina) + setstate(last,s_fina) end return head,done end @@ -26154,87 +26213,87 @@ function methods.arab(head,font,attr) current=tonut(current) while current do local char,id=ischar(current,font) - if char and not getprop(current,a_state) then + if char and not getstate(current) then done=true local classifier=classifiers[char] if not classifier then if last then if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end first,last=nil,nil elseif first then if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end first=nil end elseif classifier==s_mark then - setprop(current,a_state,s_mark) + setstate(current,s_mark) elseif classifier==s_isol then if last then if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end first,last=nil,nil elseif first then if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end first=nil end - setprop(current,a_state,s_isol) + setstate(current,s_isol) elseif classifier==s_medi then if first then last=current c_last=classifier - setprop(current,a_state,s_medi) + setstate(current,s_medi) else - setprop(current,a_state,s_init) + setstate(current,s_init) first=current c_first=classifier end elseif classifier==s_fina then if last then - if getprop(last,a_state)~=s_init then - setprop(last,a_state,s_medi) + if getstate(last)~=s_init then + setstate(last,s_medi) end - setprop(current,a_state,s_fina) + setstate(current,s_fina) first,last=nil,nil elseif first then - setprop(current,a_state,s_fina) + setstate(current,s_fina) first=nil else - setprop(current,a_state,s_isol) + setstate(current,s_isol) end else - setprop(current,a_state,s_rest) + setstate(current,s_rest) if last then if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end first,last=nil,nil elseif first then if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end first=nil end @@ -26242,18 +26301,18 @@ function methods.arab(head,font,attr) else if last then if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end first,last=nil,nil elseif first then if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end first=nil end @@ -26265,17 +26324,17 @@ function methods.arab(head,font,attr) end if last then if c_last==s_medi or c_last==s_fina then - setprop(last,a_state,s_fina) + setstate(last,s_fina) else warning(last,"fina") - setprop(last,a_state,s_error) + setstate(last,s_error) end elseif first then if c_first==s_medi or c_first==s_fina then - setprop(first,a_state,s_isol) + setstate(first,s_isol) else warning(first,"isol") - setprop(first,a_state,s_error) + setstate(first,s_error) end end return head,done @@ -26355,8 +26414,7 @@ local setprev=nuts.setprev local getboth=nuts.getboth local setboth=nuts.setboth local getid=nuts.getid -local getprop=nuts.getprop -local setprop=nuts.setprop +local getstate=nuts.getstate local getsubtype=nuts.getsubtype local setsubtype=nuts.setsubtype local getchar=nuts.getchar @@ -26365,13 +26423,15 @@ local getdisc=nuts.getdisc local setdisc=nuts.setdisc local getreplace=nuts.getreplace local setlink=nuts.setlink -local getcomponents=nuts.getcomponents -local setcomponents=nuts.setcomponents local getwidth=nuts.getwidth local getattr=nuts.getattr local getglyphdata=nuts.getglyphdata +local copy_no_components=nuts.copy_no_components +local copy_only_glyphs=nuts.copy_only_glyphs +local count_components=nuts.count_components +local set_components=nuts.set_components +local get_components=nuts.get_components local ischar=nuts.ischar -local isglyph=nuts.isglyph local usesfont=nuts.uses_font local insert_node_after=nuts.insert_after local copy_node=nuts.copy @@ -26396,7 +26456,6 @@ local dir_code=nodecodes.dir local localpar_code=nodecodes.localpar local discretionarydisc_code=disccodes.discretionary local ligatureglyph_code=glyphcodes.ligature -local a_state=attributes.private('state') local a_noligature=attributes.private("noligature") local injections=nodes.injections local setmark=injections.setmark @@ -26557,27 +26616,6 @@ local function appenddisc(disc,list) end setdisc(disc,pre,post,replace) end -local copy_no_components=nuts.copy_no_components -local copy_only_glyphs=nuts.copy_only_glyphs -local set_components=setcomponents -local take_components=getcomponents -local function count_components(start,marks) - local char=isglyph(start) - if char then - if getsubtype(start)==ligatureglyph_code then - local i=0 - local components=getcomponents(start) - while components do - i=i+count_components(components,marks) - components=getnext(components) - end - return i - elseif not marks[char] then - return 1 - end - end - return 0 -end local function markstoligature(head,start,stop,char) if start==stop and getchar(start)==char then return head,start @@ -26623,7 +26661,7 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou setlink(prev,base,next) if not discfound then local deletemarks=not skiphash or hasmarks - local components=start + local components=start local baseindex=0 local componentindex=0 local head=base @@ -26669,17 +26707,16 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou local pre,post,replace,pretail,posttail,replacetail=getdisc(discfound,true) if not replace then local prev=getprev(base) - local comp=take_components(base) local copied=copy_only_glyphs(comp) if pre then setlink(discprev,pre) else setnext(discprev) end - pre=comp + pre=comp if post then setlink(posttail,discnext) - setprev(post) + setprev(post) else post=discnext setprev(discnext) @@ -28863,7 +28900,7 @@ local function testrun(disc,t_run,c_run,...) end local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true) local renewed=false - if (post or replace) then + if post or replace then if post then setlink(posttail,next) else @@ -29056,7 +29093,7 @@ local function t_run_single(start,stop,font,attr,lookupcache) ss=nil end end -lookupmatch=lg + lookupmatch=lg else break end @@ -29091,7 +29128,7 @@ local function k_run_single(sub,injection,last,font,attr,lookupcache,step,datase if n==last then break end - local char=ischar(n) + local char=ischar(n,font) if char then local lookupmatch=lookupcache[char] if lookupmatch then @@ -29210,7 +29247,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps) ss=nil end end -lookupmatch=lg + lookupmatch=lg else break end @@ -29433,10 +29470,10 @@ do if lookupmatch then local a if attr then - if getglyphdata(start)==attr and (not attribute or getprop(start,a_state)==attribute) then + if getglyphdata(start)==attr and (not attribute or getstate(start,attribute)) then a=true end - elseif not attribute or getprop(start,a_state)==attribute then + elseif not attribute or getstate(start,attribute) then a=true end if a then @@ -29489,10 +29526,10 @@ do if m then local a if attr then - if getglyphdata(start)==attr and (not attribute or getprop(start,a_state)==attribute) then + if getglyphdata(start)==attr and (not attribute or getstate(start,attribute)) then a=true end - elseif not attribute or getprop(start,a_state)==attribute then + elseif not attribute or getstate(start,attribute) then a=true end if a then @@ -29935,6 +29972,8 @@ local setprev=nuts.setprev local setchar=nuts.setchar local getprop=nuts.getprop local setprop=nuts.setprop +local getstate=nuts.getstate +local setstate=nuts.setstate local ischar=nuts.ischar local insert_node_after=nuts.insert_after local copy_node=nuts.copy @@ -29944,7 +29983,6 @@ local flush_node=nuts.flush_node local copyinjection=nodes.injections.copy local unsetvalue=attributes.unsetvalue local fontdata=fonts.hashes.identifiers -local a_state=attributes.private('state') local a_syllabe=attributes.private('syllabe') local dotted_circle=0x25CC local c_nbsp=0x00A0 @@ -30677,7 +30715,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) current=start else current=getnext(n) - setprop(start,a_state,s_rphf) + setstate(start,s_rphf) end end if getchar(current)==c_nbsp then @@ -30710,9 +30748,9 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) local nextcurrent=copy_node(current) copyinjection(nextcurrent,current) setlink(tempcurrent,nextcurrent) - setprop(tempcurrent,a_state,s_blwf) + setstate(tempcurrent,s_blwf) tempcurrent=processcharacters(tempcurrent,font) - setprop(tempcurrent,a_state,unsetvalue) + setstate(tempcurrent,unsetvalue) if getchar(next)==getchar(tempcurrent) then flush_list(tempcurrent) if show_syntax_errors then @@ -30736,7 +30774,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) while not basefound do local char=getchar(current) if consonant[char] then - setprop(current,a_state,s_half) + setstate(current,s_half) if not firstcons then firstcons=current end @@ -30744,9 +30782,9 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) if not base then base=current elseif blwfcache[char] then - setprop(current,a_state,s_blwf) + setstate(current,s_blwf) elseif pstfcache[char] then - setprop(current,a_state,s_pstf) + setstate(current,s_pstf) else base=current end @@ -30811,14 +30849,14 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) while current~=stop do local next=getnext(current) if next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwnj then - setprop(current,a_state,unsetvalue) + setstate(current,unsetvalue) end current=next end - if base~=stop and getprop(base,a_state) then + if base~=stop and getstate(base) then local next=getnext(base) if halant[getchar(next)] and not (next~=stop and getchar(getnext(next))==c_zwj) then - setprop(base,a_state,unsetvalue) + setstate(base,unsetvalue) end end local current,allreordered,moved=start,false,{ [base]=true } @@ -30955,7 +30993,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) end bn=next end - if getprop(current,a_state)==s_rphf then + if getstate(current,s_rphf) then if b~=current then if current==start then if head==start then @@ -31106,7 +31144,7 @@ function handlers.devanagari_reorder_reph(head,start) while current do local char=ischar(current,startfont) if char and getprop(current,a_syllabe)==startattr then - if consonant[char] and not getprop(current,a_state)==s_pref then + if consonant[char] and not getstate(current,s_pref) then startnext=getnext(start) head=remove_node(head,start) setlink(current,start) @@ -31130,7 +31168,7 @@ function handlers.devanagari_reorder_reph(head,start) while current do local char=ischar(current,startfont) if char and getprop(current,a_syllabe)==startattr then - if getprop(current,a_state)==s_pstf then + if getstate(current,s_pstf) then startnext=getnext(start) head=remove_node(head,start) setlink(getprev(current),start) @@ -31163,7 +31201,7 @@ function handlers.devanagari_reorder_reph(head,start) while current do local char=ischar(current,startfont) if char and getprop(current,a_syllabe)==startattr then - local state=getprop(current,a_state) + local state=getstate(current) if before_subscript[rephbase] and (state==s_blwf or state==s_pstf) then c=current elseif after_subscript[rephbase] and (state==s_pstf) then @@ -31243,7 +31281,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) local current=getprev(start) while current and getprop(current,a_syllabe)==startattr do local char=ischar(current) - if (not dependent_vowel[char] and not getprop(current,a_state) or getprop(current,a_state)==s_init) then + if (not dependent_vowel[char] and (not getstate(current) or getstate(current,s_init))) then startnext=getnext(start) head=remove_node(head,start) if current==head then @@ -31323,7 +31361,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) if afternext and zw_char[getchar(afternext)] then current=afternext elseif current==start then - setprop(current,a_state,s_rphf) + setstate(current,s_rphf) current=next else current=next @@ -31343,9 +31381,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) if found then local next=getnext(current) if found[getchar(next)] or contextchain(found,next) then - if (not getprop(current,a_state) and not getprop(next,a_state)) then - setprop(current,a_state,s_pref) - setprop(next,a_state,s_pref) + if (not getstate(current) and not getstate(next)) then + setstate(current,s_pref) + setstate(next,s_pref) current=next end end @@ -31365,8 +31403,8 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) if found[getchar(next)] or contextchain(found,next) then if next~=stop and getchar(getnext(next))==c_zwnj then current=next - elseif (not getprop(current,a_state)) then - setprop(current,a_state,s_half) + elseif (not getstate(current)) then + setstate(current,s_half) if not halfpos then halfpos=current end @@ -31387,9 +31425,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) if found then local next=getnext(current) if found[getchar(next)] or contextchain(found,next) then - if (not getprop(current,a_state) and not getprop(next,a_state)) then - setprop(current,a_state,s_blwf) - setprop(next,a_state,s_blwf) + if (not getstate(current) and not getstate(next)) then + setstate(current,s_blwf) + setstate(next,s_blwf) current=next subpos=current end @@ -31408,9 +31446,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) if found then local next=getnext(current) if found[getchar(next)] or contextchain(found,next) then - if (not getprop(current,a_state) and not getprop(next,a_state)) then - setprop(current,a_state,s_pstf) - setprop(next,a_state,s_pstf) + if (not getstate(current) and not getstate(next)) then + setstate(current,s_pstf) + setstate(next,s_pstf) current=next postpos=current end @@ -31422,7 +31460,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) end end local current,base,firstcons=start,nil,nil - if getprop(start,a_state)==s_rphf then + if getstate(start,s_rphf) then current=getnext(getnext(start)) end if current~=getnext(stop) and getchar(current)==c_nbsp then @@ -31449,13 +31487,13 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) local tmp=getnext(next) local changestop=next==stop setnext(next) - setprop(current,a_state,s_pref) + setstate(current,s_pref) current=processcharacters(current,font) - setprop(current,a_state,s_blwf) + setstate(current,s_blwf) current=processcharacters(current,font) - setprop(current,a_state,s_pstf) + setstate(current,s_pstf) current=processcharacters(current,font) - setprop(current,a_state,unsetvalue) + setstate(current,unsetvalue) if halant[getchar(current)] then setnext(getnext(current),tmp) if show_syntax_errors then @@ -31480,7 +31518,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) if not firstcons then firstcons=current end - local a=getprop(current,a_state) + local a=getstate(current) if not (a==s_blwf or a==s_pstf or (a~=s_rphf and a~=s_blwf and ra[getchar(current)])) then base=current end @@ -31493,13 +31531,13 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) end end if not base then - if getprop(start,a_state)==s_rphf then - setprop(start,a_state,unsetvalue) + if getstate(start,s_rphf) then + setstate(start,unsetvalue) end return head,stop,nbspaces else - if getprop(base,a_state) then - setprop(base,a_state,unsetvalue) + if getstate(base) then + setstate(base,unsetvalue) end basepos=base end @@ -31545,7 +31583,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) end local ppos=getprev(pos) while ppos and getprop(ppos,a_syllabe)==getprop(pos,a_syllabe) do - if getprop(ppos,a_state)==s_pref then + if getstate(ppos,s_pref) then pos=ppos end ppos=getprev(ppos) @@ -31617,7 +31655,7 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) while current~=last do local char=getchar(current) local cn=getnext(current) - if halant[char] and ra[ischar(cn)] and getprop(cn,a_state)~=s_rphf and getprop(cn,a_state)~=s_blwf then + if halant[char] and ra[ischar(cn)] and (not getstate(cn,s_rphf)) and (not getstate(cn,s_blwf)) then if after_main[ischar(cn)] then local prev=getprev(current) local next=getnext(cn) @@ -32217,8 +32255,8 @@ local function method_one(head,font,attr) while current do local char=ischar(current,font) if char then - if n==0 and not getprop(current,a_state) then - setprop(current,a_state,s_init) + if n==0 and not getstate(current) then + setstate(current,s_init) end n=n+1 else @@ -32294,7 +32332,7 @@ local function method_two(head,font,attr) end if not syllableend and show_syntax_errors then local char=ischar(current,font) - if char and not getprop(current,a_state) then + if char and not getstate(current) then local mark=mark_four[char] if mark then head,current=inject_syntax_error(head,current,char) @@ -32312,8 +32350,8 @@ local function method_two(head,font,attr) while current do local char=ischar(current,font) if char then - if n==0 and not getprop(current,a_state) then - setprop(current,a_state,s_init) + if n==0 and not getstate(current) then + setstate(current,s_init) end n=n+1 else |