diff options
Diffstat (limited to 'tex')
32 files changed, 1209 insertions, 775 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index ed4567e86..ffee0b4d9 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2017.02.25 16:24} +\newcontextversion{2017.03.01 13:40} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index bc277e721..55f420e79 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2017.02.25 16:24} +\edef\contextversion{2017.03.01 13:40} %D For those who want to use this: diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index d931309da..8578cd188 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2017.02.25 16:24} +\newcontextversion{2017.03.01 13:40} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 5b3bba8da..bd4fbb462 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -39,7 +39,7 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2017.02.25 16:24} +\edef\contextversion{2017.03.01 13:40} \edef\contextkind {beta} %D For those who want to use this: diff --git a/tex/context/base/mkiv/font-cff.lua b/tex/context/base/mkiv/font-cff.lua index 1c6bd56fd..e6f47e40b 100644 --- a/tex/context/base/mkiv/font-cff.lua +++ b/tex/context/base/mkiv/font-cff.lua @@ -23,7 +23,7 @@ if not modules then modules = { } end modules ['font-cff'] = { local next, type, tonumber = next, type, tonumber local byte = string.byte local concat, remove = table.concat, table.remove -local floor, abs, round, ceil = math.floor, math.abs, math.round, math.ceil +local floor, abs, round, ceil, min, max = math.floor, math.abs, math.round, math.ceil, math.min, math.max local P, C, R, S, C, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct local lpegmatch = lpeg.match local formatters = string.formatters @@ -31,14 +31,14 @@ local formatters = string.formatters local readers = fonts.handlers.otf.readers local streamreader = readers.streamreader -local readbytes = streamreader.readbytes local readstring = streamreader.readstring local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer local readuint = streamreader.readcardinal3 -- 24-bit unsigned integer -local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer +local readulong = streamreader.readcardinal4 -- 32-bit unsigned integer local setposition = streamreader.setposition local getposition = streamreader.getposition +local readbytetable = streamreader.readbytetable local setmetatableindex = table.setmetatableindex @@ -611,16 +611,17 @@ do -- All these indirect calls make this run slower but it's cleaner this way -- and we cache the result. As we moved the boundingbox code inline we gain - -- some back. + -- some back. I inlined some of then and a bit speed can be gained by more + -- inlining but not that much. - local function moveto(x,y) + local function moveto() if keepcurve then r = r + 1 result[r] = { x, y, "m" } end if checked then - if x < xmin then xmin = x elseif x > xmax then xmax = x end - if y < ymin then ymin = y elseif y > ymax then ymax = y end + if x > xmax then xmax = x elseif x < xmin then xmin = x end + if y > ymax then ymax = y elseif y < ymin then ymin = y end else xmin = x ymin = y @@ -630,14 +631,50 @@ do end end - local function lineto(x,y) + local function xmoveto() -- slight speedup + if keepcurve then + r = r + 1 + result[r] = { x, y, "m" } + end + if not checked then + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + elseif x > xmax then + xmax = x + elseif x < xmin then + xmin = x + end + end + + local function ymoveto() -- slight speedup + if keepcurve then + r = r + 1 + result[r] = { x, y, "m" } + end + if not checked then + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + elseif y > ymax then + ymax = y + elseif y < ymin then + ymin = y + end + end + + local function lineto() -- we could inline if keepcurve then r = r + 1 result[r] = { x, y, "l" } end if checked then - if x < xmin then xmin = x elseif x > xmax then xmax = x end - if y < ymin then ymin = y elseif y > ymax then ymax = y end + if x > xmax then xmax = x elseif x < xmin then xmin = x end + if y > ymax then ymax = y elseif y < ymin then ymin = y end else xmin = x ymin = y @@ -647,14 +684,50 @@ do end end + local function xlineto() -- slight speedup + if keepcurve then + r = r + 1 + result[r] = { x, y, "l" } + end + if not checked then + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + elseif x > xmax then + xmax = x + elseif x < xmin then + xmin = x + end + end + + local function ylineto() -- slight speedup + if keepcurve then + r = r + 1 + result[r] = { x, y, "l" } + end + if not checked then + xmin = x + ymin = y + xmax = x + ymax = y + checked = true + elseif y > ymax then + ymax = y + elseif y < ymin then + ymin = y + end + end + local function curveto(x1,y1,x2,y2,x3,y3) if keepcurve then r = r + 1 result[r] = { x1, y1, x2, y2, x3, y3, "c" } end if checked then - if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end - if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end + if x1 > xmax then xmax = x1 elseif x1 < xmin then xmin = x1 end + if y1 > ymax then ymax = y1 elseif y1 < ymin then ymin = y1 end else xmin = x1 ymin = y1 @@ -662,22 +735,22 @@ do ymax = y1 checked = true end - if x2 < xmin then xmin = x2 elseif x2 > xmax then xmax = x2 end - if y2 < ymin then ymin = y2 elseif y2 > ymax then ymax = y2 end - if x3 < xmin then xmin = x3 elseif x3 > xmax then xmax = x3 end - if y3 < ymin then ymin = y3 elseif y3 > ymax then ymax = y3 end + if x2 > xmax then xmax = x2 elseif x2 < xmin then xmin = x2 end + if y2 > ymax then ymax = y2 elseif y2 < ymin then ymin = y2 end + if x3 > xmax then xmax = x3 elseif x3 < xmin then xmin = x3 end + if y3 > ymax then ymax = y3 elseif y3 < ymin then ymin = y3 end end local function rmoveto() - if top > 2 then - if not width then + if not width then + if top > 2 then width = stack[1] if trace_charstrings then showvalue("width",width) end + else + width = true end - elseif not width then - width = true end if trace_charstrings then showstate("rmoveto") @@ -685,45 +758,45 @@ do x = x + stack[top-1] -- dx1 y = y + stack[top] -- dy1 top = 0 - moveto(x,y) + moveto() end local function hmoveto() - if top > 1 then - if not width then + if not width then + if top > 1 then width = stack[1] if trace_charstrings then showvalue("width",width) end + else + width = true end - elseif not width then - width = true end if trace_charstrings then showstate("hmoveto") end x = x + stack[top] -- dx1 top = 0 - moveto(x,y) + xmoveto() end local function vmoveto() - if top > 1 then - if not width then + if not width then + if top > 1 then width = stack[1] if trace_charstrings then showvalue("width",width) end + else + width = true end - elseif not width then - width = true end if trace_charstrings then showstate("vmoveto") end y = y + stack[top] -- dy1 top = 0 - moveto(x,y) + ymoveto() end local function rlineto() @@ -733,21 +806,7 @@ do for i=1,top,2 do x = x + stack[i] -- dxa y = y + stack[i+1] -- dya - lineto(x,y) - end - top = 0 - end - - local function xlineto(swap) -- x (y,x)+ | (x,y)+ - for i=1,top do - if swap then - x = x + stack[i] - swap = false - else - y = y + stack[i] - swap = true - end - lineto(x,y) + lineto() end top = 0 end @@ -756,14 +815,48 @@ do if trace_charstrings then showstate("hlineto") end - xlineto(true) + if top == 1 then + x = x + stack[1] + xlineto() + else + local swap = true + for i=1,top do + if swap then + x = x + stack[i] + xlineto() + swap = false + else + y = y + stack[i] + ylineto() + swap = true + end + end + end + top = 0 end local function vlineto() -- y (x,y)+ | (y,x)+ if trace_charstrings then showstate("vlineto") end - xlineto(false) + if top == 1 then + y = y + stack[1] + ylineto() + else + local swap = false + for i=1,top do + if swap then + x = x + stack[i] + xlineto() + swap = false + else + y = y + stack[i] + ylineto() + swap = true + end + end + end + top = 0 end local function rrcurveto() @@ -775,8 +868,8 @@ do local ay = y + stack[i+1] -- dya local bx = ax + stack[i+2] -- dxb local by = ay + stack[i+3] -- dyb - x = bx + stack[i+4] -- dxc - y = by + stack[i+5] -- dyc + x = bx + stack[i+4] -- dxc + y = by + stack[i+5] -- dyc curveto(ax,ay,bx,by,x,y) end top = 0 @@ -788,15 +881,15 @@ do end local s = 1 if top % 2 ~= 0 then - y = y + stack[1] -- dy1 + y = y + stack[1] -- dy1 s = 2 end for i=s,top,4 do - local ax = x + stack[i] -- dxa + local ax = x + stack[i] -- dxa local ay = y local bx = ax + stack[i+1] -- dxb local by = ay + stack[i+2] -- dyb - x = bx + stack[i+3] -- dxc + x = bx + stack[i+3] -- dxc y = by curveto(ax,ay,bx,by,x,y) end @@ -810,16 +903,16 @@ do local s = 1 local d = 0 if top % 2 ~= 0 then - d = stack[1] -- dx1 + d = stack[1] -- dx1 s = 2 end for i=s,top,4 do local ax = x + d - local ay = y + stack[i] -- dya + local ay = y + stack[i] -- dya local bx = ax + stack[i+1] -- dxb local by = ay + stack[i+2] -- dyb x = bx - y = by + stack[i+3] -- dyc + y = by + stack[i+3] -- dyc curveto(ax,ay,bx,by,x,y) d = 0 end @@ -831,7 +924,6 @@ do if last then top = top - 1 end - local sw = swap for i=1,top,4 do local ax, ay, bx, by if swap then @@ -893,7 +985,7 @@ do end x = x + stack[top-1] -- dxc y = y + stack[top] -- dyc - lineto(x,y) + lineto() top = 0 end @@ -905,7 +997,7 @@ do for i=1,top-6,2 do x = x + stack[i] y = y + stack[i+1] - lineto(x,y) + lineto() end end local ax = x + stack[top-5] @@ -945,7 +1037,7 @@ do if trace_charstrings then showstate("hflex") end - local ax = x + stack[1] -- dx1 + local ax = x + stack[1] -- dx1 local ay = y local bx = ax + stack[2] -- dx2 local by = ay + stack[3] -- dy2 @@ -956,7 +1048,7 @@ do local dy = by local ex = dx + stack[6] -- dx5 local ey = y - x = ex + stack[7] -- dx6 + x = ex + stack[7] -- dx6 curveto(dx,dy,ex,ey,x,y) top = 0 end @@ -976,7 +1068,7 @@ do local dy = by local ex = dx + stack[7] -- dx5 local ey = dy + stack[8] -- dy5 - x = ex + stack[9] -- dx6 + x = ex + stack[9] -- dx6 curveto(dx,dy,ex,ey,x,y) top = 0 end @@ -1218,9 +1310,9 @@ do [037] = flex1, } - local p_bytes = Ct((P(1)/byte)^0) + local process - local function call(scope,list,bias,process) + local function call(scope,list,bias) -- ,process) depth = depth + 1 if top == 0 then showstate(formatters["unknown %s call"](scope)) @@ -1233,10 +1325,10 @@ do end local tab = list[index] if tab then - if type(tab) == "string" then - tab = lpegmatch(p_bytes,tab) - list[index] = tab - end +-- if type(tab) == "string" then +-- tab = { byte(tab,1,#tab) } +-- list[index] = tab +-- end process(tab) else showstate(formatters["unknown %s call %i"](scope,index)) @@ -1246,54 +1338,64 @@ do depth = depth - 1 end - local function process(tab) + -- precompiling and reuse is much slower than redoing the calls + + process = function(tab) local i = 1 local n = #tab while i <= n do local t = tab[i] - if t >= 32 and t <= 246 then - -- -107 .. +107 - top = top + 1 - stack[top] = t - 139 - i = i + 1 - elseif t >= 247 and t <= 250 then - -- +108 .. +1131 - top = top + 1 - stack[top] = (t-247)*256 + tab[i+1] + 108 - i = i + 2 - elseif t >= 251 and t <= 254 then - -- -1131 .. -108 - top = top + 1 - stack[top] = -(t-251)*256 - tab[i+1] - 108 - i = i + 2 + if t >= 32 then + if t <= 246 then + -- -107 .. +107 + top = top + 1 + stack[top] = t - 139 + i = i + 1 + elseif t <= 250 then + -- +108 .. +1131 + top = top + 1 + -- stack[top] = (t-247)*256 + tab[i+1] + 108 + -- stack[top] = t*256 - 247*256 + tab[i+1] + 108 + stack[top] = t*256 - 63124 + tab[i+1] + i = i + 2 + elseif t <= 254 then + -- -1131 .. -108 + top = top + 1 + -- stack[top] = -(t-251)*256 - tab[i+1] - 108 + -- stack[top] = -t*256 + 251*256 - tab[i+1] - 108 + stack[top] = -t*256 + 64148 - tab[i+1] + i = i + 2 + else + local n = 0x100 * tab[i+1] + tab[i+2] + top = top + 1 + if n >= 0x8000 then + -- stack[top] = n - 0xFFFF - 1 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF + stack[top] = n - 0x10000 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF + else + stack[top] = n + (0x100 * tab[i+3] + tab[i+4])/0xFFFF + end + i = i + 5 + end elseif t == 28 then -- -32768 .. +32767 : b1<<8 | b2 top = top + 1 local n = 0x100 * tab[i+1] + tab[i+2] if n >= 0x8000 then - stack[top] = n - 0xFFFF - 1 + -- stack[top] = n - 0xFFFF - 1 + stack[top] = n - 0x10000 else stack[top] = n end i = i + 3 - elseif t == 255 then - local n = 0x100 * tab[i+1] + tab[i+2] - top = top + 1 - if n >= 0x8000 then - stack[top] = n - 0xFFFF - 1 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF - else - stack[top] = n + (0x100 * tab[i+3] + tab[i+4])/0xFFFF - end - i = i + 5 - elseif t == 11 then + elseif t == 11 then if trace_charstrings then showstate("return") end return elseif t == 10 then - call("local",locals,localbias,process) + call("local",locals,localbias) -- ,process) i = i + 1 - elseif t == 14 then -- endchar + elseif t == 14 then -- endchar if width then -- okay elseif top > 0 then @@ -1309,7 +1411,7 @@ do end return elseif t == 29 then - call("global",globals,globalbias,process) + call("global",globals,globalbias) -- ,process) i = i + 1 elseif t == 12 then i = i + 1 @@ -1356,7 +1458,7 @@ do -- if y < ymin then ymin = y end -- if y > ymax then ymax = y end -- -- we now have a reasonable start so we could - -- -- simplyfy the next checks + -- -- simplify the next checks -- for i=1,nofsegments do -- local s = segments[i] -- local x = s[1] @@ -1415,9 +1517,9 @@ do for i=1,#charstrings do local tab = charstrings[i] - if type(tab) == "string" then - tab = lpegmatch(p_bytes,tab) - end +-- if type(tab) == "string" then -- no real need as wel nil charstrings[i] at the end + tab = { byte(tab,1,#tab) } +-- end local index = i - 1 x = 0 y = 0 @@ -1425,7 +1527,7 @@ do r = 0 top = 0 stems = 0 - result = { } + result = { } -- we could reuse it when only boundingbox calculations are needed -- xmin = 0 xmax = 0 @@ -1450,15 +1552,7 @@ do -- -- trace_charstrings = index == 3078 -- todo: make tracker local glyph = glyphs[index] -- can be autodefined in otr - if not glyph then - glyphs[index] = { - segments = doshapes ~= false and result or nil, -- optional - boundingbox = boundingbox, - width = width, - name = charset[index], - -- sidebearing = 0, - } - else + if glyph then glyph.segments = doshapes ~= false and result or nil glyph.boundingbox = boundingbox if not glyph.width then @@ -1468,12 +1562,26 @@ do glyph.name = charset[index] end -- glyph.sidebearing = 0 -- todo + elseif doshapes then + glyphs[index] = { + segments = result, + boundingbox = boundingbox, + width = width, + name = charset[index], + -- sidebearing = 0, + } + else + glyphs[index] = { + boundingbox = boundingbox, + width = width, + name = charset[index], + } end if trace_charstrings then report("width: %s",tostring(width)) report("boundingbox: % t",boundingbox) end - charstrings[i] = nil -- free memory + charstrings[i] = nil -- free memory (what if used more often?) end return glyphs end @@ -1491,9 +1599,10 @@ do local nominalwidth = private and private.data.nominalwidthx or 0 local defaultwidth = private and private.data.defaultwidthx or 0 -- - if type(tab) == "string" then - tab = lpegmatch(p_bytes,tab) - end +-- if type(tab) == "string" then + -- a helper is not much faster but might be nicer for the stack + tab = { byte(tab,1,#tab) } +-- end -- x = 0 y = 0 @@ -1527,15 +1636,7 @@ do index = index - 1 -- local glyph = glyphs[index] -- can be autodefined in otr - if not glyph then - glyphs[index] = { - segments = doshapes ~= false and result or nil, -- optional - boundingbox = boundingbox, - width = width, - name = charset[index], - -- sidebearing = 0, - } - else + if glyph then glyph.segments = doshapes ~= false and result or nil glyph.boundingbox = boundingbox if not glyph.width then @@ -1545,6 +1646,20 @@ do glyph.name = charset[index] end -- glyph.sidebearing = 0 -- todo + elseif doshapes then + glyphs[index] = { + segments = result, + boundingbox = boundingbox, + width = width, + name = charset[index], + -- sidebearing = 0, + } + else + glyphs[index] = { + boundingbox = boundingbox, + width = width, + name = charset[index], + } end -- if trace_charstrings then @@ -1564,7 +1679,7 @@ end local function readglobals(f,data) local routines = readlengths(f) for i=1,#routines do - routines[i] = readstring(f,routines[i]) + routines[i] = readbytetable(f,routines[i]) end data.routines = routines end @@ -1627,7 +1742,7 @@ local function readlocals(f,data,dictionary) setposition(f,header.offset+private.offset+subroutineoffset) local subroutines = readlengths(f) for i=1,#subroutines do - subroutines[i] = readstring(f,subroutines[i]) + subroutines[i] = readbytetable(f,subroutines[i]) end dictionary.subroutines = subroutines private.data.subroutines = nil @@ -1757,6 +1872,7 @@ local function readfdselect(f,data,glyphs,doshapes,version) end for i=1,#charstrings do parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version) +charstrings[i] = nil end resetcharstrings() end diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua index a5a1ae7c0..c336441e3 100644 --- a/tex/context/base/mkiv/font-dsp.lua +++ b/tex/context/base/mkiv/font-dsp.lua @@ -71,18 +71,18 @@ local streamreader = readers.streamreader local setposition = streamreader.setposition local getposition = streamreader.getposition -local skipshort = streamreader.skipshort -local skipbytes = streamreader.skip local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer +local readinteger = streamreader.readinteger1 local readshort = streamreader.readinteger2 -- 16-bit signed integer -local readfword = readshort local readstring = streamreader.readstring local readtag = streamreader.readtag local readbytes = streamreader.readbytes local readfixed = streamreader.readfixed4 local read2dot14 = streamreader.read2dot14 -local readinteger = streamreader.readinteger1 +local skipshort = streamreader.skipshort +local skipbytes = streamreader.skip +local readfword = readshort local gsubhandlers = { } local gposhandlers = { } @@ -1820,61 +1820,65 @@ do report("ignoring global kern table using gpos kern feature") return end - report("adding global kern table as gpos feature %a",name) setposition(f,datatable.offset) local version = readushort(f) local noftables = readushort(f) - local kerns = setmetatableindex("table") - for i=1,noftables do - local version = readushort(f) - local length = readushort(f) - local coverage = readushort(f) - -- bit 8-15 of coverage: format 0 or 2 - local format = bit32.rshift(coverage,8) -- is this ok? - if format == 0 then - local nofpairs = readushort(f) - local searchrange = readushort(f) - local entryselector = readushort(f) - local rangeshift = readushort(f) - for i=1,nofpairs do - kerns[readushort(f)][readushort(f)] = readfword(f) + if noftables > 1 then + report("adding global kern table as gpos feature %a",name) + local kerns = setmetatableindex("table") + for i=1,noftables do + local version = readushort(f) + local length = readushort(f) + local coverage = readushort(f) + -- bit 8-15 of coverage: format 0 or 2 + local format = bit32.rshift(coverage,8) -- is this ok? + if format == 0 then + local nofpairs = readushort(f) + local searchrange = readushort(f) + local entryselector = readushort(f) + local rangeshift = readushort(f) + for i=1,nofpairs do + kerns[readushort(f)][readushort(f)] = readfword(f) + end + elseif format == 2 then + -- apple specific so let's ignore it + else + -- not supported by ms end - elseif format == 2 then - -- apple specific so let's ignore it - else - -- not supported by ms end - end - local feature = { dflt = { dflt = true } } - if not features then - fontdata.features = { gpos = { [name] = feature } } - elseif not gposfeatures then - fontdata.features.gpos = { [name] = feature } - else - gposfeatures[name] = feature - end - local sequences = fontdata.sequences - if not sequences then - sequences = { } - fontdata.sequences = sequences - end - local nofsequences = #sequences + 1 - sequences[nofsequences] = { - index = nofsequences, - name = name, - steps = { - { - coverage = kerns, - format = "kern", + local feature = { dflt = { dflt = true } } + if not features then + fontdata.features = { gpos = { [name] = feature } } + elseif not gposfeatures then + fontdata.features.gpos = { [name] = feature } + else + gposfeatures[name] = feature + end + local sequences = fontdata.sequences + if not sequences then + sequences = { } + fontdata.sequences = sequences + end + local nofsequences = #sequences + 1 + sequences[nofsequences] = { + index = nofsequences, + name = name, + steps = { + { + coverage = kerns, + format = "kern", + }, }, - }, - nofsteps = 1, - type = "gpos_pair", - -- type = "gpos_single", -- maybe better - flags = { false, false, false, false }, - order = { name }, - features = { [name] = feature }, - } + nofsteps = 1, + type = "gpos_pair", + -- type = "gpos_single", -- maybe better + flags = { false, false, false, false }, + order = { name }, + features = { [name] = feature }, + } + else + report("ignoring empty kern table of feature %a",name) + end end function readers.gsub(f,fontdata,specification) diff --git a/tex/context/base/mkiv/font-ext.lua b/tex/context/base/mkiv/font-ext.lua index 0b2bfd44f..6edfe7025 100644 --- a/tex/context/base/mkiv/font-ext.lua +++ b/tex/context/base/mkiv/font-ext.lua @@ -292,12 +292,11 @@ vectors['quality'] = table.merged( vectors['alpha'] ) --- As this is experimental code, users should not depend on it. The --- implications are still discussed on the ConTeXt Dev List and we're --- not sure yet what exactly the spec is (the next code is tested with --- a gyre font patched by / fea file made by Khaled Hosny). The double --- trick should not be needed it proper hanging punctuation is used in --- which case values < 1 can be used. +-- As this is experimental code, users should not depend on it. The implications are still +-- discussed on the ConTeXt Dev List and we're not sure yet what exactly the spec is (the +-- next code is tested with a gyre font patched by / fea file made by Khaled Hosny). The +-- double trick should not be needed it proper hanging punctuation is used in which case +-- values < 1 can be used. -- -- preferred (in context, usine vectors): -- @@ -345,17 +344,23 @@ local function map_opbd_onto_protrusion(tfmdata,value,opbd) if validlookups then for i=1,#lookuplist do local lookup = lookuplist[i] - local data = lookuphash[lookup] - if data then + local steps = lookup.steps + if steps then if trace_protrusion then - report_protrusions("setting left using lfbd lookup %a",lookuptags[lookup]) + report_protrusions("setting left using lfbd") end - for k, v in next, data do - -- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same - local p = - (v[1] / 1000) * factor * left - characters[k].left_protruding = p - if trace_protrusion then - report_protrusions("lfbd -> %s -> %C -> %0.03f (% t)",lookuptags[lookup],k,p,v) + for i=1,#steps do + local step = steps[i] + local coverage = step.coverage + if coverage then + for k, v in next, coverage do + -- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same + local p = - (v[1] / 1000) * factor * left + characters[k].left_protruding = p + if trace_protrusion then + report_protrusions("lfbd -> %C -> %p",k,p) + end + end end end done = true @@ -368,17 +373,23 @@ local function map_opbd_onto_protrusion(tfmdata,value,opbd) if validlookups then for i=1,#lookuplist do local lookup = lookuplist[i] - local data = lookuphash[lookup] - if data then + local steps = lookup.steps + if steps then if trace_protrusion then - report_protrusions("setting right using rtbd lookup %a",lookuptags[lookup]) + report_protrusions("setting right using rtbd") end - for k, v in next, data do - -- local p = v[3] / descriptions[k].width -- or 3 - local p = (v[1] / 1000) * factor * right - characters[k].right_protruding = p - if trace_protrusion then - report_protrusions("rtbd -> %s -> %C -> %0.03f (% t)",lookuptags[lookup],k,p,v) + for i=1,#steps do + local step = steps[i] + local coverage = step.coverage + if coverage then + for k, v in next, coverage do + -- local p = v[3] / descriptions[k].width -- or 3 + local p = (v[1] / 1000) * factor * right + characters[k].right_protruding = p + if trace_protrusion then + report_protrusions("rtbd -> %C -> %p",k,p) + end + end end end end @@ -397,10 +408,9 @@ local function map_opbd_onto_protrusion(tfmdata,value,opbd) end end --- The opbd test is just there because it was discussed on the --- context development list. However, the mentioned fxlbi.otf font --- only has some kerns for digits. So, consider this feature not --- supported till we have a proper test font. +-- The opbd test is just there because it was discussed on the context development list. However, +-- the mentioned fxlbi.otf font only has some kerns for digits. So, consider this feature not supported +-- till we have a proper test font. local function initializeprotrusion(tfmdata,value) if value then diff --git a/tex/context/base/mkiv/font-onr.lua b/tex/context/base/mkiv/font-onr.lua index 6c33b24c6..d986a0ddc 100644 --- a/tex/context/base/mkiv/font-onr.lua +++ b/tex/context/base/mkiv/font-onr.lua @@ -105,8 +105,8 @@ do local setroutine = function(str,position,index,size) local forward = position + tonumber(size) - local stream = sub(str,position+1,forward) - routines[index] = decrypt(stream,4330,4) + local stream = decrypt(sub(str,position+1,forward),4330,4) + routines[index] = { byte(stream,1,#stream) } return forward end diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua index c5c5d8f32..5d3609b35 100644 --- a/tex/context/base/mkiv/font-otr.lua +++ b/tex/context/base/mkiv/font-otr.lua @@ -107,15 +107,15 @@ local readstring = streamreader.readstring local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer local readuint = streamreader.readcardinal3 -- 24-bit unsigned integer -local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer +local readulong = streamreader.readcardinal4 -- 32-bit unsigned integer ----- readchar = streamreader.readinteger1 -- 8-bit signed integer local readshort = streamreader.readinteger2 -- 16-bit signed integer -local readlong = streamreader.readinteger4 -- 24-bit unsigned integer +local readlong = streamreader.readinteger4 -- 32-bit unsigned integer local readfixed = streamreader.readfixed4 +local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14) local readfword = readshort -- 16-bit signed integer that describes a quantity in FUnits local readufword = readushort -- 16-bit unsigned integer that describes a quantity in FUnits local readoffset = readushort -local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14) function streamreader.readtag(f) return lower(stripstring(readstring(f,4))) @@ -1996,13 +1996,22 @@ local function prepareglyps(fontdata) fontdata.mapping = { } end +local function readtable(tag,f,fontdata,specification) + local reader = readers[tag] + if reader then + -- local t = os.clock() + reader(f,fontdata,specification) + -- report("reading table %a took %0.4f seconds",tag,os.clock()-t) + end +end + local function readdata(f,offset,specification) local fontdata = loadtables(f,specification,offset) if specification.glyphs then prepareglyps(fontdata) end -- - readers["name"](f,fontdata,specification) + readtable("name",f,fontdata,specification) -- local askedname = specification.askedname if askedname then @@ -2014,33 +2023,35 @@ local function readdata(f,offset,specification) end end -- - readers["os/2"](f,fontdata,specification) - readers["head"](f,fontdata,specification) - readers["maxp"](f,fontdata,specification) - readers["hhea"](f,fontdata,specification) - readers["vhea"](f,fontdata,specification) - readers["hmtx"](f,fontdata,specification) - readers["vmtx"](f,fontdata,specification) - readers["vorg"](f,fontdata,specification) - readers["post"](f,fontdata,specification) - readers["cff" ](f,fontdata,specification) - readers["cmap"](f,fontdata,specification) - readers["loca"](f,fontdata,specification) - readers["glyf"](f,fontdata,specification) - readers["colr"](f,fontdata,specification) - readers["cpal"](f,fontdata,specification) - readers["svg" ](f,fontdata,specification) - readers["kern"](f,fontdata,specification) - readers["gdef"](f,fontdata,specification) - readers["gsub"](f,fontdata,specification) - readers["gpos"](f,fontdata,specification) - readers["math"](f,fontdata,specification) + readtable("os/2",f,fontdata,specification) + readtable("head",f,fontdata,specification) + readtable("maxp",f,fontdata,specification) + readtable("hhea",f,fontdata,specification) + readtable("vhea",f,fontdata,specification) + readtable("hmtx",f,fontdata,specification) + readtable("vmtx",f,fontdata,specification) + readtable("vorg",f,fontdata,specification) + readtable("post",f,fontdata,specification) + readtable("cff" ,f,fontdata,specification) + readtable("cmap",f,fontdata,specification) + readtable("loca",f,fontdata,specification) + readtable("glyf",f,fontdata,specification) + readtable("colr",f,fontdata,specification) + readtable("cpal",f,fontdata,specification) + readtable("svg" ,f,fontdata,specification) + readtable("kern",f,fontdata,specification) + readtable("gdef",f,fontdata,specification) + readtable("gsub",f,fontdata,specification) + readtable("gpos",f,fontdata,specification) + readtable("math",f,fontdata,specification) + -- + -- there are no proper fonts yet: -- - -- readers["fvar"](f,fontdata,specification) - -- readers["hvar"](f,fontdata,specification) - -- readers["vvar"](f,fontdata,specification) - -- readers["mvar"](f,fontdata,specification) - -- readers["vorg"](f,fontdata,specification) + -- readtable("fvar",f,fontdata,specification) -- probably + -- readtable("hvar",f,fontdata,specification) + -- readtable("vvar",f,fontdata,specification) + -- readtable("mvar",f,fontdata,specification) -- probably + -- readtable("vorg",f,fontdata,specification) -- fontdata.locations = nil fontdata.tables = nil diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua index 742a0c561..7ef395330 100644 --- a/tex/context/base/mkiv/font-ots.lua +++ b/tex/context/base/mkiv/font-ots.lua @@ -3758,7 +3758,7 @@ otf.helpers.pardirstate = pardirstate -- optimizations the principles of processing the features hasn't changed much since -- the beginning. -local function featuresprocessor(head,font,attr) +local function featuresprocessor(head,font,attr,direction) local sequences = sequencelists[font] -- temp hack @@ -3802,7 +3802,8 @@ local function featuresprocessor(head,font,attr) checkstep(head) end - local rlmode = 0 + local initialrl = direction == "TRT" and -1 or 0 + local done = false local datasets = otf.dataset(tfmdata,font,attr) local dirstack = { } -- could move outside function but we can have local runs @@ -3819,7 +3820,7 @@ local function featuresprocessor(head,font,attr) ----- featurevalue = dataset[1] -- todo: pass to function instead of using a global local attribute = dataset[2] local sequence = dataset[3] -- sequences[s] -- also dataset[5] - local rlparmode = 0 + local rlparmode = initialrl local topstack = 0 local typ = sequence.type local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- store in dataset @@ -3837,7 +3838,8 @@ local function featuresprocessor(head,font,attr) end elseif typ == "gsub_reversecontextchain" then -- this is a limited case, no special treatments like 'init' etc - local start = find_node_tail(head) + local start = find_node_tail(head) + local rlmode = 0 -- how important is this .. do we need to check for dir? while start do local char = ischar(start,font) if char then @@ -3875,8 +3877,8 @@ local function featuresprocessor(head,font,attr) end end else - local start = head -- local ? - rlmode = 0 -- to be checked ? + local start = head + local rlmode = initialrl if nofsteps == 1 then -- happens often local step = steps[1] local lookupcache = step.coverage diff --git a/tex/context/base/mkiv/l-io.lua b/tex/context/base/mkiv/l-io.lua index 2039017b2..75976b858 100644 --- a/tex/context/base/mkiv/l-io.lua +++ b/tex/context/base/mkiv/l-io.lua @@ -19,38 +19,48 @@ else io.fileseparator, io.pathseparator = "/" , ":" end -local function readall(f) - return f:read("*all") -end +-- local function readall(f) +-- return f:read("*all") +-- end -- The next one is upto 50% faster on large files and less memory consumption due -- to less intermediate large allocations. This phenomena was discussed on the -- luatex dev list. +local large = 2^24 -- 16 MB +local medium = large / 16 -- 1 MB +local small = medium / 8 + +-- local function readall(f) +-- local size = f:seek("end") +-- if size == 0 then +-- return "" +-- end +-- f:seek("set",0) +-- if size < medium then +-- return f:read('*all') +-- else +-- local step = (size > large) and large or (floor(size/(medium)) * small) +-- local data = { } +-- while true do +-- local r = f:read(step) +-- if not r then +-- return concat(data) +-- else +-- data[#data+1] = r +-- end +-- end +-- end +-- end + local function readall(f) +-- return f:read("*all") local size = f:seek("end") - if size == 0 then - return "" - end - f:seek("set",0) - if size < 1024*1024 then - return f:read('*all') + if size > 0 then + f:seek("set",0) + return f:read(size) else - local step - if size > 16*1024*1024 then - step = 16*1024*1024 - else - step = floor(size/(1024*1024)) * 1024 * 1024 / 8 - end - local data = { } - while true do - local r = f:read(step) - if not r then - return concat(data) - else - data[#data+1] = r - end - end + return "" end end @@ -59,52 +69,75 @@ io.readall = readall function io.loaddata(filename,textmode) -- return nil if empty local f = open(filename,(textmode and 'r') or 'rb') if f then - local data = readall(f) - f:close() - if #data > 0 then - return data + local size = f:seek("end") + local data = nil + if size > 0 then + -- data = f:read("*all") + f:seek("set",0) + data = f:read(size) end + f:close() + return data end end +-- function io.copydata(source,target,action) +-- local f = open(source,"rb") +-- if f then +-- local g = open(target,"wb") +-- if g then +-- local size = f:seek("end") +-- if size == 0 then +-- -- empty +-- else +-- f:seek("set",0) +-- if size < medium then +-- local data = f:read('*all') +-- if action then +-- data = action(data) +-- end +-- if data then +-- g:write(data) +-- end +-- else +-- local step = (size > large) and large or (floor(size/(medium)) * small) +-- while true do +-- local data = f:read(step) +-- if data then +-- if action then +-- data = action(data) +-- end +-- if data then +-- g:write(data) +-- end +-- else +-- break +-- end +-- end +-- end +-- end +-- g:close() +-- end +-- f:close() +-- flush() +-- end +-- end + function io.copydata(source,target,action) local f = open(source,"rb") if f then local g = open(target,"wb") if g then local size = f:seek("end") - if size == 0 then - -- empty - else + if size > 0 then + -- local data = f:read('*all') f:seek("set",0) - if size < 1024*1024 then - local data = f:read('*all') - if action then - data = action(data) - end - if data then - g:write(data) - end - else - local step - if size > 16*1024*1024 then - step = 16*1024*1024 - else - step = floor(size/(1024*1024)) * 1024 * 1024 / 8 - end - while true do - local data = f:read(step) - if data then - if action then - data = action(data) - end - if data then - g:write(data) - end - else - break - end - end + local data = f:read(size) + if action then + data = action(data) + end + if data then + g:write(data) end end g:close() @@ -134,32 +167,70 @@ end -- we can also chunk this one if needed: io.lines(filename,chunksize,"*l") -function io.loadlines(filename,n) -- return nil if empty - local f = open(filename,'r') - if not f then - -- no file - elseif n then - local lines = { } - for i=1,n do - local line = f:read("*lines") - if line then - lines[#lines+1] = line - else - break +-- ffi.readline + +if fio.readline then + + local readline = fio.readline + + function io.loadlines(filename,n) -- return nil if empty + local f = open(filename,'r') + if not f then + -- no file + elseif n then + local lines = { } + for i=1,n do + local line = readline(f) + if line then + lines[i] = line + else + break + end + end + f:close() + lines = concat(lines,"\n") + if #lines > 0 then + return lines + end + else + local line = readline(f) + f:close() + if line and #line > 0 then + return line end end - f:close() - lines = concat(lines,"\n") - if #lines > 0 then - return lines - end - else - local line = f:read("*line") or "" - f:close() - if #line > 0 then - return line + end + +else + + function io.loadlines(filename,n) -- return nil if empty + local f = open(filename,'r') + if not f then + -- no file + elseif n then + local lines = { } + for i=1,n do + local line = f:read("*lines") + if line then + lines[i] = line + else + break + end + end + f:close() + lines = concat(lines,"\n") + if #lines > 0 then + return lines + end + else + local line = f:read("*line") or "" + f:close() + if #line > 0 then + return line + end end end + end function io.loadchunk(filename,n) @@ -205,6 +276,7 @@ local function noflines(f) return 0 end else + -- todo: load and lpeg local n = 0 for _ in f:lines() do n = n + 1 @@ -216,7 +288,7 @@ end io.noflines = noflines --- inlined is faster +-- inlined is faster ... beware, better use util-fil local nextchar = { [ 4] = function(f) @@ -331,7 +403,7 @@ function io.ask(question,default,options) end end -local function readnumber(f,n,m) +local function readnumber(f,n,m) -- to be replaced if m then f:seek("set",n) n = m @@ -340,38 +412,32 @@ local function readnumber(f,n,m) return byte(f:read(1)) elseif n == 2 then local a, b = byte(f:read(2),1,2) - return 256 * a + b + return 0x100 * a + b elseif n == 3 then local a, b, c = byte(f:read(3),1,3) - return 256*256 * a + 256 * b + c + return 0x10000 * a + 0x100 * b + c elseif n == 4 then local a, b, c, d = byte(f:read(4),1,4) - return 256*256*256 * a + 256*256 * b + 256 * c + d + return 0x1000000 * a + 0x10000 * b + 0x100 * c + d elseif n == 8 then local a, b = readnumber(f,4), readnumber(f,4) - return 256 * a + b + return 0x100 * a + b elseif n == 12 then local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4) - return 256*256 * a + 256 * b + c + return 0x10000 * a + 0x100 * b + c elseif n == -2 then local b, a = byte(f:read(2),1,2) - return 256*a + b + return 0x100 * a + b elseif n == -3 then local c, b, a = byte(f:read(3),1,3) - return 256*256 * a + 256 * b + c + return 0x10000 * a + 0x100 * b + c elseif n == -4 then local d, c, b, a = byte(f:read(4),1,4) - return 256*256*256 * a + 256*256 * b + 256*c + d + return 0x1000000 * a + 0x10000 * b + 0x100*c + d elseif n == -8 then local h, g, f, e, d, c, b, a = byte(f:read(8),1,8) - return 256*256*256*256*256*256*256 * a + - 256*256*256*256*256*256 * b + - 256*256*256*256*256 * c + - 256*256*256*256 * d + - 256*256*256 * e + - 256*256 * f + - 256 * g + - h + return 0x100000000000000 * a + 0x1000000000000 * b + 0x10000000000 * c + 0x100000000 * d + + 0x1000000 * e + 0x10000 * f + 0x100 * g + h else return 0 end diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua index 5108faeef..9b54c9840 100644 --- a/tex/context/base/mkiv/l-os.lua +++ b/tex/context/base/mkiv/l-os.lua @@ -508,8 +508,10 @@ end -- These are moved from core-con.lua (as I needed them elsewhere). -local function isleapyear(year) - return (year % 400 == 0) or ((year % 100 ~= 0) and (year % 4 == 0)) +local function isleapyear(year) -- timed for bram's cs practicum + -- return (year % 400 == 0) or (year % 100 ~= 0 and year % 4 == 0) -- 3:4:1600:1900 = 9.9 : 8.2 : 5.0 : 6.8 (29.9) + return (year % 4 == 0) and (year % 100 ~= 0 or year % 400 == 0) -- 3:4:1600:1900 = 5.1 : 6.5 : 8.1 : 10.2 (29.9) + -- return (year % 4 == 0) and (year % 400 == 0 or year % 100 ~= 0) -- 3:4:1600:1900 = 5.2 : 8.5 : 6.8 : 10.1 (30.6) end os.isleapyear = isleapyear diff --git a/tex/context/base/mkiv/lxml-lpt.lua b/tex/context/base/mkiv/lxml-lpt.lua index 939a737ab..bb6fb4568 100644 --- a/tex/context/base/mkiv/lxml-lpt.lua +++ b/tex/context/base/mkiv/lxml-lpt.lua @@ -177,7 +177,7 @@ apply_axis['child'] = function(list) if dk.tg then c = c + 1 collected[c] = dk --- dk.ni = k -- refresh + dk.ni = k -- refresh en = en + 1 dk.ei = en end @@ -197,7 +197,7 @@ local function collect(list,collected,c) if dk.tg then c = c + 1 collected[c] = dk --- dk.ni = k -- refresh + dk.ni = k -- refresh en = en + 1 dk.ei = en c = collect(dk,collected,c) @@ -225,7 +225,7 @@ local function collect(list,collected,c) if dk.tg then c = c + 1 collected[c] = dk --- dk.ni = k -- refresh + dk.ni = k -- refresh en = en + 1 dk.ei = en c = collect(dk,collected,c) diff --git a/tex/context/base/mkiv/lxml-tab.lua b/tex/context/base/mkiv/lxml-tab.lua index 58b933c44..f2d38a654 100644 --- a/tex/context/base/mkiv/lxml-tab.lua +++ b/tex/context/base/mkiv/lxml-tab.lua @@ -264,7 +264,7 @@ local function add_empty(spacing, namespace, tag) tg = tag, at = at, dt = { }, - ni = nt, + ni = nil, -- preset slot __p__ = top } dt[nt] = t @@ -287,7 +287,7 @@ local function add_begin(spacing, namespace, tag) tg = tag, at = at, dt = { }, - ni = nt, -- preset slot + ni = nil, -- preset slot __p__ = stack[level] } setmetatable(top, mt) @@ -315,9 +315,7 @@ local function add_end(spacing, namespace, tag) end dt = top.dt nt = #dt + 1 - toclose.ni = nt dt[nt] = toclose - -- dt[0] = top -- nasty circular reference when serializing table if toclose.at.xmlns then remove(xmlns) end @@ -377,7 +375,7 @@ local function add_special(what, spacing, text) special = true, ns = "", tg = what, - ni = nt, + ni = nil, -- preset slot dt = { text }, } end diff --git a/tex/context/base/mkiv/node-fnt.lua b/tex/context/base/mkiv/node-fnt.lua index 85525cac2..3dc99e5f2 100644 --- a/tex/context/base/mkiv/node-fnt.lua +++ b/tex/context/base/mkiv/node-fnt.lua @@ -192,7 +192,7 @@ end report_fonts() end -function handlers.characters(head) +function handlers.characters(head,groupcode,size,packtype,direction) -- either next or not, but definitely no already processed list starttiming(nodes) @@ -430,7 +430,7 @@ function handlers.characters(head) -- local attr = a == 0 and false or 0 -- 0 is the savest way local attr = a > 0 and 0 or false -- 0 is the savest way for i=1,#processors do - local h, d = processors[i](head,font,attr) + local h, d = processors[i](head,font,attr,direction) if d then if h then head = h @@ -443,7 +443,7 @@ function handlers.characters(head) local attr = a > 0 and 0 or false -- 0 is the savest way for font, processors in next, usedfonts do -- unordered for i=1,#processors do - local h, d = processors[i](head,font,attr) + local h, d = processors[i](head,font,attr,direction) if d then if h then head = h @@ -459,7 +459,7 @@ function handlers.characters(head) local font, dynamics = next(attrfonts) for attribute, processors in next, dynamics do -- unordered, attr can switch in between for i=1,#processors do - local h, d = processors[i](head,font,attribute) + local h, d = processors[i](head,font,attribute,direction) if d then if h then head = h @@ -472,7 +472,7 @@ function handlers.characters(head) for font, dynamics in next, attrfonts do for attribute, processors in next, dynamics do -- unordered, attr can switch in between for i=1,#processors do - local h, d = processors[i](head,font,attribute) + local h, d = processors[i](head,font,attribute,direction) if d then if h then head = h diff --git a/tex/context/base/mkiv/page-ins.mkiv b/tex/context/base/mkiv/page-ins.mkiv index 51f2a3c1c..09ba70b70 100644 --- a/tex/context/base/mkiv/page-ins.mkiv +++ b/tex/context/base/mkiv/page-ins.mkiv @@ -60,6 +60,7 @@ % \global\count\currentinsertionnumber\numexpr\insertionparameter\c!factor/\insertionparameter\c!n\relax % \global\skip \currentinsertionnumber\insertionparameter\c!distance \relax % \global\dimen\currentinsertionnumber\insertionparameter\c!maxheight\relax} +% \floatingpenalty\zerocount \appendtoks \page_inserts_synchronize_registers diff --git a/tex/context/base/mkiv/page-one.mkiv b/tex/context/base/mkiv/page-one.mkiv index a41787133..9bd6951f3 100644 --- a/tex/context/base/mkiv/page-one.mkiv +++ b/tex/context/base/mkiv/page-one.mkiv @@ -213,7 +213,8 @@ \global\advance\d_page_floats_inserted_top\dimexpr\ht\floatbox+\dp\floatbox+\s_page_one_between_top_insert\relax} \def\page_one_insert_top_float % maybe remember last beforeskip - {\insert\namedinsertionnumber\s!topfloat\bgroup + {\floatingpenalty\zerocount + \insert\namedinsertionnumber\s!topfloat\bgroup \forgetall \ifconditional\c_page_one_top_of_insert \ifconditional\c_page_one_correct_top_insert @@ -284,6 +285,7 @@ \page_floats_get \global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax \ifdim\d_page_floats_inserted_bottom<\pagegoal\relax + \floatingpenalty\zerocount \insert\namedinsertionnumber\s!bottomfloat\bgroup \forgetall \blank[\rootfloatparameter\c!spacebefore]% @@ -570,6 +572,7 @@ \def\page_one_place_float_bottom_indeed {\global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax + \floatingpenalty\zerocount \insert\namedinsertionnumber\s!bottomfloat\bgroup \forgetall \blank[\rootfloatparameter\c!spacebefore]% diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua index 569dfb982..2f0191e6a 100644 --- a/tex/context/base/mkiv/spac-ver.lua +++ b/tex/context/base/mkiv/spac-ver.lua @@ -1289,7 +1289,7 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also local p = getprop(pagetail,"snapper") if p then local e = p.extra - if e < 0 then + if e and e < 0 then local t = texget("pagetotal") if t > 0 then local g = texget("pagegoal") -- 1073741823 is signal diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex aea5f09b7..7389dfad5 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 f36de8747..0adbb8f77 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/strc-not.mkvi b/tex/context/base/mkiv/strc-not.mkvi index f1a51c5ad..db27cb5af 100644 --- a/tex/context/base/mkiv/strc-not.mkvi +++ b/tex/context/base/mkiv/strc-not.mkvi @@ -1366,10 +1366,24 @@ \inheritmaintextcolor % but we do want to obey the textcolor \to \everybeforenoteinsert +% \def\strc_notes_set_penalties +% {\doif{\noteparameter\c!scope}\v!page{\floatingpenalty\maxdimen}% experiment +% %\interlinepenalty\maxdimen % todo +% \penalty\currentnotepenalty} + +\def\strc_notes_set_penalties + {% stored in insert node + \floatingpenalty \currentnotepenalty + % used when typesetting + \interlinepenalty\plushundred % plain value + % used when we need to split in columns + \ifnum\noteparameter\c!n>\plusone + \penalty\zerocount % otherwise no split in columns, maybe just always (tex just adds it to accumulated) + \fi} + + \appendtoks - \doif{\noteparameter\c!scope}\v!page{\floatingpenalty\maxdimen}% experiment - \penalty\currentnotepenalty - %\interlinepenalty\maxdimen % todo + \strc_notes_set_penalties \forgetall \strc_notes_set_bodyfont \redoconvertfont % to undo \undo calls in in headings etc diff --git a/tex/context/base/mkiv/trac-deb.lua b/tex/context/base/mkiv/trac-deb.lua index d1168a3a9..03df86825 100644 --- a/tex/context/base/mkiv/trac-deb.lua +++ b/tex/context/base/mkiv/trac-deb.lua @@ -326,16 +326,20 @@ end directives.register("system.showerror", lmx.overloaderror) -local debugger = utilities.debugger - -local function trace_calls(n) - debugger.enable() - luatex.registerstopactions(function() - debugger.disable() - debugger.savestats(tex.jobname .. "-luacalls.log",tonumber(n)) - end) - trace_calls = function() end -end +-- local debugger = utilities.debugger +-- +-- local function trace_calls(n) +-- debugger.enable() +-- luatex.registerstopactions(function() +-- debugger.disable() +-- debugger.savestats(tex.jobname .. "-luacalls.log",tonumber(n)) +-- end) +-- trace_calls = function() end +-- end +-- +-- directives.register("system.tracecalls", function(n) +-- trace_calls(n) +-- end) -- indirect is needed for nilling local editor = [[scite "-open:%filename%" -goto:%linenumber%]] @@ -354,8 +358,6 @@ callback.register("call_edit",function(filename,linenumber) end end) -directives.register("system.tracecalls", function(n) trace_calls(n) end) -- indirect is needed for nilling - implement { name = "showtrackers", actions = trackers.show } implement { name = "enabletrackers", actions = trackers.enable, arguments = "string" } implement { name = "disabletrackers", actions = trackers.disable, arguments = "string" } @@ -373,10 +375,12 @@ implement { name = "showdebuginfo", actions = lmx.showdebuginfo } implement { name = "overloaderror", actions = lmx.overloaderror } implement { name = "showlogcategories", actions = logs.show } -directives.register("system.profile",function() +local debugger = utilities.debugger + +directives.register("system.profile",function(n) luatex.registerstopactions(function() debugger.disable() - debugger.savestats("luatex-profile.log") + debugger.savestats("luatex-profile.log",tonumber(n) or 0) report_nl() logs.report("system","profiler stopped, log saved in %a","luatex-profile.log") report_nl() diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua index 8cca4752b..5d69b406d 100644 --- a/tex/context/base/mkiv/trac-vis.lua +++ b/tex/context/base/mkiv/trac-vis.lua @@ -506,8 +506,8 @@ end local math do local m_cache = { - b_cache = caches["bmath"], - e_cache = caches["emath"], + beginmath = caches["bmath"], + endmath = caches["emath"], } local tags = { diff --git a/tex/context/base/mkiv/typo-sus.lua b/tex/context/base/mkiv/typo-sus.lua index e81b36b65..f728993f6 100644 --- a/tex/context/base/mkiv/typo-sus.lua +++ b/tex/context/base/mkiv/typo-sus.lua @@ -51,6 +51,7 @@ local getlist = nuts.getlist local getkern = nuts.getkern local getpenalty = nuts.getpenalty local getwidth = nuts.getwidth +local getwhd = nuts.getwhd local isglyph = nuts.isglyph local setattr = nuts.setattr diff --git a/tex/context/base/mkiv/util-deb.lua b/tex/context/base/mkiv/util-deb.lua index 040a7a9cf..57e015386 100644 --- a/tex/context/base/mkiv/util-deb.lua +++ b/tex/context/base/mkiv/util-deb.lua @@ -13,9 +13,10 @@ if not modules then modules = { } end modules ['util-deb'] = { local debug = require "debug" local getinfo, sethook = debug.getinfo, debug.sethook -local type, next, tostring = type, next, tostring +local type, next, tostring, tonumber = type, next, tostring, tonumber local format, find, sub, gsub = string.format, string.find, string.sub, string.gsub local insert, remove, sort = table.insert, table.remove, table.sort +local setmetatableindex = table.setmetatableindex utilities = utilities or { } local debugger = utilities.debugger or { } @@ -30,63 +31,73 @@ local dummycalls = 10*1000 local nesting = 0 local names = { } -local function initialize() +local initialize = false - if FFISUPPORTED and ffi then +if not (FFISUPPORTED and ffi) then - if os.type == "windows" then - local okay, kernel = pcall(ffi.load,"kernel32") - if kernel then - local tonumber = ffi.number or tonumber -ffi.cdef[[ -int QueryPerformanceFrequency(int64_t *lpFrequency); -int QueryPerformanceCounter(int64_t *lpPerformanceCount); -]] - local target = ffi.new("__int64[1]") - ticks = function() - if kernel.QueryPerformanceCounter(target) == 1 then - return tonumber(target[0]) - else - return 0 - end - end - local target = ffi.new("__int64[1]") - seconds = function(ticks) - if kernel.QueryPerformanceFrequency(target) == 1 then - return ticks / tonumber(target[0]) - else - return 0 - end - end - end - elseif os.type == "unix" then - local C = ffi.C + -- we have no precise timer + +elseif os.type == "windows" then + + initialize = function() + local kernel = ffilib("kernel32","system") -- no checking + if kernel then local tonumber = ffi.number or tonumber - -- 1 = CLOCK_MONOTONIC - -- 2 = CLOCK_PROCESS_CPUTIME_ID -ffi.cdef [[ -struct timespec { long sec; long nsec; }; -int clock_gettime(int timerid, struct timespec *t); - ]] - local target = ffi.new("timespec[?]",1) - function ticks() - C.clock_gettime(2,target) - return tonumber(target[0].sec*1000000000 + target[0].nsec) + ffi.cdef[[ + int QueryPerformanceFrequency(int64_t *lpFrequency); + int QueryPerformanceCounter(int64_t *lpPerformanceCount); + ]] + local target = ffi.new("__int64[1]") + ticks = function() + if kernel.QueryPerformanceCounter(target) == 1 then + return tonumber(target[0]) + else + return 0 + end end + local target = ffi.new("__int64[1]") seconds = function(ticks) - return ticks/1000000000 + if kernel.QueryPerformanceFrequency(target) == 1 then + return ticks / tonumber(target[0]) + else + return 0 + end end - end + initialize = false end - initialize = false +elseif os.type == "unix" then + + -- for the values: echo '#include <time.h>' > foo.h; gcc -dM -E foo.h + + initialize = function() + local C = ffi.C + local tonumber = ffi.number or tonumber + ffi.cdef [[ + /* what a mess */ + typedef int clk_id_t; + typedef enum { CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID } clk_id; + typedef struct timespec { long sec; long nsec; } ctx_timespec; + int clock_gettime(clk_id_t timerid, struct timespec *t); + ]] + local target = ffi.new("ctx_timespec[?]",1) + local clock = C.CLOCK_PROCESS_CPUTIME_ID + ticks = function () + C.clock_gettime(clock,target) + return tonumber(target[0].sec*1000000000 + target[0].nsec) + end + seconds = function(ticks) + return ticks/1000000000 + end + initialize = false + end end -table.setmetatableindex(names,function(t,name) - local v = table.setmetatableindex(function(t,source) - local v = table.setmetatableindex(function(t,line) +setmetatableindex(names,function(t,name) + local v = setmetatableindex(function(t,source) + local v = setmetatableindex(function(t,line) local v = { total = 0, count = 0 } t[line] = v return v @@ -128,33 +139,39 @@ local function hook(where) end end -function debugger.showstats(printer) +function debugger.showstats(printer,threshold) local printer = printer or report local calls = 0 local functions = 0 local dataset = { } local length = 0 local wholetime = 0 + local threshold = threshold or 0 for name, sources in next, names do for source, lines in next, sources do for line, data in next, lines do - if #name > length then - length = #name - end - local total = data.total local count = data.count - local real = total - if real > 0 then - real = total - (count * overhead / dummycalls) - if real < 0 then - real = 0 + if count > threshold then + if #name > length then + length = #name end - wholetime = wholetime + real - end - if line < 0 then - line = 0 + local total = data.total + local real = total + if real > 0 then + real = total - (count * overhead / dummycalls) + if real < 0 then + real = 0 + end + wholetime = wholetime + real + end + if line < 0 then + line = 0 + end + -- if name = "a" then + -- -- weird name + -- end + dataset[#dataset+1] = { real, total, count, name, source, line } end - dataset[#dataset+1] = { real, total, count, name, source, line } end end end @@ -206,12 +223,14 @@ function debugger.showstats(printer) printer(format("functions : %i", functions)) printer(format("calls : %i", calls)) printer(format("overhead : %f", seconds(overhead/1000))) + + -- table.save("luatex-profile.lua",names) end -function debugger.savestats(filename) +function debugger.savestats(filename,threshold) local f = io.open(filename,'w') if f then - debugger.showstats(function(str) f:write(str,"\n") end) + debugger.showstats(function(str) f:write(str,"\n") end,threshold) f:close() end end diff --git a/tex/context/base/mkiv/util-fil.lua b/tex/context/base/mkiv/util-fil.lua index dba3b235c..4e66ba461 100644 --- a/tex/context/base/mkiv/util-fil.lua +++ b/tex/context/base/mkiv/util-fil.lua @@ -83,6 +83,12 @@ function files.readbytes(f,n) return byte(f:read(n),1,n) end +function files.readbytetable(f,n) + -- return { byte(f:read(n),1,n) } + local s = f:read(n or 1) + return { byte(s,1,#s) } -- best use the real length +end + function files.readchar(f) return f:read(1) end @@ -183,24 +189,24 @@ function files.readcardinal4le(f) return 0x1000000 * a + 0x10000 * b + 0x100 * c + d end +-- function files.readinteger4(f) +-- local a, b, c, d = byte(f:read(4),1,4) +-- local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d +-- if n >= 0x8000000 then +-- -- return n - 0xFFFFFFFF - 1 +-- return n - 0x100000000 +-- else +-- return n +-- end +-- end function files.readinteger4(f) local a, b, c, d = byte(f:read(4),1,4) - local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d - if n >= 0x8000000 then - -- return n - 0xFFFFFFFF - 1 - return n - 0x100000000 + if a >= 0x80 then + return 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000 else - return n + return 0x1000000 * a + 0x10000 * b + 0x100 * c + d end end - function files.readinteger4(f) - local a, b, c, d = byte(f:read(4),1,4) - if a >= 0x80 then - return 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000 - else - return 0x1000000 * a + 0x10000 * b + 0x100 * c + d - end - end function files.readinteger4le(f) local d, c, b, a = byte(f:read(4),1,4) local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d @@ -214,13 +220,12 @@ end function files.readfixed4(f) local a, b, c, d = byte(f:read(4),1,4) - local n = 0x100 * a + b - if n >= 0x8000 then - -- return n - 0xFFFF - 1 + (0x100 * c + d)/0xFFFF - return n - 0x10000 + (0x100 * c + d)/0xFFFF + if a >= 0x80 then + return (0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000)/65536.0 else - return n + (0x100 * c + d)/0xFFFF + return (0x1000000 * a + 0x10000 * b + 0x100 * c + d)/65536.0 end + end if extract then @@ -276,3 +281,38 @@ function files.writebyte(f,b) f:write(char(b)) end +if fio and fio.readcardinal1 then + + files.readcardinal1 = fio.readcardinal1 + files.readcardinal2 = fio.readcardinal2 + files.readcardinal3 = fio.readcardinal3 + files.readcardinal4 = fio.readcardinal4 + files.readinteger1 = fio.readinteger1 + files.readinteger2 = fio.readinteger2 + files.readinteger3 = fio.readinteger3 + files.readinteger4 = fio.readinteger4 + files.readfixed4 = fio.readfixed4 + files.read2dot14 = fio.read2dot14 + files.setposition = fio.setposition + files.getposition = fio.getposition + + files.readbyte = files.readcardinel1 + files.readsignedbyte = files.readinteger1 + files.readcardinal = files.readcardinal1 + files.readinteger = files.readinteger1 + + local skipposition = fio.skipposition + files.skipposition = skipposition + + files.readbytes = fio.readbytes + files.readbytetable = fio.readbytetable + + function files.skipshort(f,n) + skipposition(f,2*(n or 1)) + end + + function files.skiplong(f,n) + skipposition(f,4*(n or 1)) + end + +end diff --git a/tex/context/base/mkiv/util-lib.lua b/tex/context/base/mkiv/util-lib.lua index e9a968228..98c417b8e 100644 --- a/tex/context/base/mkiv/util-lib.lua +++ b/tex/context/base/mkiv/util-lib.lua @@ -327,15 +327,21 @@ We use the same lookup logic for ffi loading. trackers.register("resolvers.ffilib", function(v) trace_ffilib = v end) + local function locateindeed(name) + local message, library = pcall(savedffiload,removesuffix(name)) + if type(library) == "userdata" then + return library + else + return false + end + end + function ffilib(required,version) - return locate(required,version,trace_ffilib,report_ffilib,function(name) - local message, library = pcall(savedffiload,removesuffix(name)) - if type(library) == "userdata" then - return message, library - else - return message, false - end - end) + if version == "system" then + return locateindeed(name) + else + return locate(required,version,trace_ffilib,report_ffilib,locateindeed) + end end function ffi.load(name) diff --git a/tex/context/base/mkiv/util-sac.lua b/tex/context/base/mkiv/util-sac.lua index 5d16be3ec..1a52bfc58 100644 --- a/tex/context/base/mkiv/util-sac.lua +++ b/tex/context/base/mkiv/util-sac.lua @@ -82,6 +82,13 @@ function streams.readbytes(f,n) return byte(f[1],i,j-1) end +function streams.readbytetable(f,n) + local i = f[2] + local j = i + n + f[2] = j + return { byte(f[1],i,j-1) } +end + function streams.skipbytes(f,n) f[2] = f[2] + n end @@ -104,7 +111,8 @@ function streams.readinteger1(f) -- one byte f[2] = i + 1 local n = byte(f[1],i) if n >= 0x80 then - return n - 0xFF - 1 + -- return n - 0xFF - 1 + return n - 0x100 else return n end @@ -129,7 +137,8 @@ function streams.readinteger2(f) local a, b = byte(f[1],i,j) local n = 0x100 * a + b if n >= 0x8000 then - return n - 0xFFFF - 1 + -- return n - 0xFFFF - 1 + return n - 0x10000 else return n end @@ -158,7 +167,8 @@ function streams.readinteger4(f) local a, b, c, d = byte(f[1],i,j) local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d if n >= 0x8000000 then - return n - 0xFFFFFFFF - 1 + -- return n - 0xFFFFFFFF - 1 + return n - 0x100000000 else return n end @@ -171,7 +181,8 @@ function streams.readfixed4(f) local a, b, c, d = byte(f[1],i,j) local n = 0x100 * a + b if n >= 0x8000 then - return n - 0xFFFF - 1 + (0x100 * c + d)/0xFFFF + -- return n - 0xFFFF - 1 + (0x100 * c + d)/0xFFFF + return n - 0x10000 + (0x100 * c + d)/0xFFFF else return n + (0x100 * c + d)/0xFFFF end diff --git a/tex/context/fonts/mkiv/xits-math.lfg b/tex/context/fonts/mkiv/xits-math.lfg index dd09dd0f1..372224940 100644 --- a/tex/context/fonts/mkiv/xits-math.lfg +++ b/tex/context/fonts/mkiv/xits-math.lfg @@ -27,6 +27,11 @@ return { -- italics = { -- ["xits-math"] = italics, -- }, + -- kernpairs = { + -- [0x1D44A] = { -- 𝑊 + -- [0x1D434] = -200, -- 𝐴 + -- }, + -- }, alternates = { calligraphic = { feature = 'ss01', value = 1, comment = "Mathematical Calligraphic Alphabet" }, greekssup = { feature = 'ss02', value = 1, comment = "Mathematical Greek Sans Serif Alphabet" }, diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf Binary files differindex 16463b9be..1418c1aea 100644 --- a/tex/context/interface/mkiv/i-context.pdf +++ b/tex/context/interface/mkiv/i-context.pdf diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf Binary files differindex 98314b3a2..d05ac8701 100644 --- a/tex/context/interface/mkiv/i-readme.pdf +++ b/tex/context/interface/mkiv/i-readme.pdf diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 52344aa26..2690045cf 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 : 02/25/17 16:24:36 +-- merge date : 03/01/17 13:40:58 do -- begin closure to overcome local limits and interference @@ -2059,44 +2059,30 @@ if string.find(os.getenv("PATH"),";",1,true) then else io.fileseparator,io.pathseparator="/",":" end -local function readall(f) - return f:read("*all") -end +local large=2^24 +local medium=large/16 +local small=medium/8 local function readall(f) local size=f:seek("end") - if size==0 then - return "" - end - f:seek("set",0) - if size<1024*1024 then - return f:read('*all') + if size>0 then + f:seek("set",0) + return f:read(size) else - local step - if size>16*1024*1024 then - step=16*1024*1024 - else - step=floor(size/(1024*1024))*1024*1024/8 - end - local data={} - while true do - local r=f:read(step) - if not r then - return concat(data) - else - data[#data+1]=r - end - end + return "" end end io.readall=readall function io.loaddata(filename,textmode) local f=open(filename,(textmode and 'r') or 'rb') if f then - local data=readall(f) - f:close() - if #data>0 then - return data + local size=f:seek("end") + local data=nil + if size>0 then + f:seek("set",0) + data=f:read(size) end + f:close() + return data end end function io.copydata(source,target,action) @@ -2105,37 +2091,14 @@ function io.copydata(source,target,action) local g=open(target,"wb") if g then local size=f:seek("end") - if size==0 then - else + if size>0 then f:seek("set",0) - if size<1024*1024 then - local data=f:read('*all') - if action then - data=action(data) - end - if data then - g:write(data) - end - else - local step - if size>16*1024*1024 then - step=16*1024*1024 - else - step=floor(size/(1024*1024))*1024*1024/8 - end - while true do - local data=f:read(step) - if data then - if action then - data=action(data) - end - if data then - g:write(data) - end - else - break - end - end + local data=f:read(size) + if action then + data=action(data) + end + if data then + g:write(data) end end g:close() @@ -2161,29 +2124,59 @@ function io.savedata(filename,data,joiner) return false end end -function io.loadlines(filename,n) - local f=open(filename,'r') - if not f then - elseif n then - local lines={} - for i=1,n do - local line=f:read("*lines") - if line then - lines[#lines+1]=line - else - break +if fio.readline then + local readline=fio.readline + function io.loadlines(filename,n) + local f=open(filename,'r') + if not f then + elseif n then + local lines={} + for i=1,n do + local line=readline(f) + if line then + lines[i]=line + else + break + end + end + f:close() + lines=concat(lines,"\n") + if #lines>0 then + return lines + end + else + local line=readline(f) + f:close() + if line and #line>0 then + return line end end - f:close() - lines=concat(lines,"\n") - if #lines>0 then - return lines - end - else - local line=f:read("*line") or "" - f:close() - if #line>0 then - return line + end +else + function io.loadlines(filename,n) + local f=open(filename,'r') + if not f then + elseif n then + local lines={} + for i=1,n do + local line=f:read("*lines") + if line then + lines[i]=line + else + break + end + end + f:close() + lines=concat(lines,"\n") + if #lines>0 then + return lines + end + else + local line=f:read("*line") or "" + f:close() + if #line>0 then + return line + end end end end @@ -2344,7 +2337,7 @@ function io.ask(question,default,options) end end end -local function readnumber(f,n,m) +local function readnumber(f,n,m) if m then f:seek("set",n) n=m @@ -2353,31 +2346,31 @@ local function readnumber(f,n,m) return byte(f:read(1)) elseif n==2 then local a,b=byte(f:read(2),1,2) - return 256*a+b + return 0x100*a+b elseif n==3 then local a,b,c=byte(f:read(3),1,3) - return 256*256*a+256*b+c + return 0x10000*a+0x100*b+c elseif n==4 then local a,b,c,d=byte(f:read(4),1,4) - return 256*256*256*a+256*256*b+256*c+d + return 0x1000000*a+0x10000*b+0x100*c+d elseif n==8 then local a,b=readnumber(f,4),readnumber(f,4) - return 256*a+b + return 0x100*a+b elseif n==12 then local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4) - return 256*256*a+256*b+c + return 0x10000*a+0x100*b+c elseif n==-2 then local b,a=byte(f:read(2),1,2) - return 256*a+b + return 0x100*a+b elseif n==-3 then local c,b,a=byte(f:read(3),1,3) - return 256*256*a+256*b+c + return 0x10000*a+0x100*b+c elseif n==-4 then local d,c,b,a=byte(f:read(4),1,4) - return 256*256*256*a+256*256*b+256*c+d + return 0x1000000*a+0x10000*b+0x100*c+d elseif n==-8 then local h,g,f,e,d,c,b,a=byte(f:read(8),1,8) - return 256*256*256*256*256*256*256*a+256*256*256*256*256*256*b+256*256*256*256*256*c+256*256*256*256*d+256*256*256*e+256*256*f+256*g+h + return 0x100000000000000*a+0x1000000000000*b+0x10000000000*c+0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h else return 0 end @@ -4302,6 +4295,10 @@ end function files.readbytes(f,n) return byte(f:read(n),1,n) end +function files.readbytetable(f,n) + local s=f:read(n or 1) + return { byte(s,1,#s) } +end function files.readchar(f) return f:read(1) end @@ -4390,21 +4387,12 @@ function files.readcardinal4le(f) end function files.readinteger4(f) local a,b,c,d=byte(f:read(4),1,4) - local n=0x1000000*a+0x10000*b+0x100*c+d - if n>=0x8000000 then - return n-0x100000000 + if a>=0x80 then + return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000 else - return n + return 0x1000000*a+0x10000*b+0x100*c+d end end - function files.readinteger4(f) - local a,b,c,d=byte(f:read(4),1,4) - if a>=0x80 then - return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000 - else - return 0x1000000*a+0x10000*b+0x100*c+d - end - end function files.readinteger4le(f) local d,c,b,a=byte(f:read(4),1,4) local n=0x1000000*a+0x10000*b+0x100*c+d @@ -4416,11 +4404,10 @@ function files.readinteger4le(f) end function files.readfixed4(f) local a,b,c,d=byte(f:read(4),1,4) - local n=0x100*a+b - if n>=0x8000 then - return n-0x10000+(0x100*c+d)/0xFFFF + if a>=0x80 then + return (0x1000000*a+0x10000*b+0x100*c+d-0x100000000)/65536.0 else - return n+(0x100*c+d)/0xFFFF + return (0x1000000*a+0x10000*b+0x100*c+d)/65536.0 end end if extract then @@ -4465,6 +4452,34 @@ end function files.writebyte(f,b) f:write(char(b)) end +if fio and fio.readcardinal1 then + files.readcardinal1=fio.readcardinal1 + files.readcardinal2=fio.readcardinal2 + files.readcardinal3=fio.readcardinal3 + files.readcardinal4=fio.readcardinal4 + files.readinteger1=fio.readinteger1 + files.readinteger2=fio.readinteger2 + files.readinteger3=fio.readinteger3 + files.readinteger4=fio.readinteger4 + files.readfixed4=fio.readfixed4 + files.read2dot14=fio.read2dot14 + files.setposition=fio.setposition + files.getposition=fio.getposition + files.readbyte=files.readcardinel1 + files.readsignedbyte=files.readinteger1 + files.readcardinal=files.readcardinal1 + files.readinteger=files.readinteger1 + local skipposition=fio.skipposition + files.skipposition=skipposition + files.readbytes=fio.readbytes + files.readbytetable=fio.readbytetable + function files.skipshort(f,n) + skipposition(f,2*(n or 1)) + end + function files.skiplong(f,n) + skipposition(f,4*(n or 1)) + end +end end -- closure @@ -8106,10 +8121,10 @@ local readulong=streamreader.readcardinal4 local readshort=streamreader.readinteger2 local readlong=streamreader.readinteger4 local readfixed=streamreader.readfixed4 +local read2dot14=streamreader.read2dot14 local readfword=readshort local readufword=readushort local readoffset=readushort -local read2dot14=streamreader.read2dot14 function streamreader.readtag(f) return lower(stripstring(readstring(f,4))) end @@ -9421,12 +9436,18 @@ local function prepareglyps(fontdata) fontdata.glyphs=glyphs fontdata.mapping={} end +local function readtable(tag,f,fontdata,specification) + local reader=readers[tag] + if reader then + reader(f,fontdata,specification) + end +end local function readdata(f,offset,specification) local fontdata=loadtables(f,specification,offset) if specification.glyphs then prepareglyps(fontdata) end - readers["name"](f,fontdata,specification) + readtable("name",f,fontdata,specification) local askedname=specification.askedname if askedname then local fullname=getname(fontdata,"fullname") or "" @@ -9436,27 +9457,27 @@ local function readdata(f,offset,specification) return end end - readers["os/2"](f,fontdata,specification) - readers["head"](f,fontdata,specification) - readers["maxp"](f,fontdata,specification) - readers["hhea"](f,fontdata,specification) - readers["vhea"](f,fontdata,specification) - readers["hmtx"](f,fontdata,specification) - readers["vmtx"](f,fontdata,specification) - readers["vorg"](f,fontdata,specification) - readers["post"](f,fontdata,specification) - readers["cff" ](f,fontdata,specification) - readers["cmap"](f,fontdata,specification) - readers["loca"](f,fontdata,specification) - readers["glyf"](f,fontdata,specification) - readers["colr"](f,fontdata,specification) - readers["cpal"](f,fontdata,specification) - readers["svg" ](f,fontdata,specification) - readers["kern"](f,fontdata,specification) - readers["gdef"](f,fontdata,specification) - readers["gsub"](f,fontdata,specification) - readers["gpos"](f,fontdata,specification) - readers["math"](f,fontdata,specification) + readtable("os/2",f,fontdata,specification) + readtable("head",f,fontdata,specification) + readtable("maxp",f,fontdata,specification) + readtable("hhea",f,fontdata,specification) + readtable("vhea",f,fontdata,specification) + readtable("hmtx",f,fontdata,specification) + readtable("vmtx",f,fontdata,specification) + readtable("vorg",f,fontdata,specification) + readtable("post",f,fontdata,specification) + readtable("cff",f,fontdata,specification) + readtable("cmap",f,fontdata,specification) + readtable("loca",f,fontdata,specification) + readtable("glyf",f,fontdata,specification) + readtable("colr",f,fontdata,specification) + readtable("cpal",f,fontdata,specification) + readtable("svg",f,fontdata,specification) + readtable("kern",f,fontdata,specification) + readtable("gdef",f,fontdata,specification) + readtable("gsub",f,fontdata,specification) + readtable("gpos",f,fontdata,specification) + readtable("math",f,fontdata,specification) fontdata.locations=nil fontdata.tables=nil fontdata.cidmaps=nil @@ -9725,13 +9746,12 @@ if not modules then modules={} end modules ['font-cff']={ local next,type,tonumber=next,type,tonumber local byte=string.byte local concat,remove=table.concat,table.remove -local floor,abs,round,ceil=math.floor,math.abs,math.round,math.ceil +local floor,abs,round,ceil,min,max=math.floor,math.abs,math.round,math.ceil,math.min,math.max local P,C,R,S,C,Cs,Ct=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Ct local lpegmatch=lpeg.match local formatters=string.formatters local readers=fonts.handlers.otf.readers local streamreader=readers.streamreader -local readbytes=streamreader.readbytes local readstring=streamreader.readstring local readbyte=streamreader.readcardinal1 local readushort=streamreader.readcardinal2 @@ -9739,6 +9759,7 @@ local readuint=streamreader.readcardinal3 local readulong=streamreader.readcardinal4 local setposition=streamreader.setposition local getposition=streamreader.getposition +local readbytetable=streamreader.readbytetable local setmetatableindex=table.setmetatableindex local trace_charstrings=false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings=v end) local report=logs.reporter("otf reader","cff") @@ -10140,14 +10161,14 @@ do report("%w%-10s : %s",depth*2,where,tostring(value)) end end - local function moveto(x,y) + local function moveto() if keepcurve then r=r+1 result[r]={ x,y,"m" } end if checked then - if x<xmin then xmin=x elseif x>xmax then xmax=x end - if y<ymin then ymin=y elseif y>ymax then ymax=y end + if x>xmax then xmax=x elseif x<xmin then xmin=x end + if y>ymax then ymax=y elseif y<ymin then ymin=y end else xmin=x ymin=y @@ -10156,14 +10177,48 @@ do checked=true end end - local function lineto(x,y) + local function xmoveto() + if keepcurve then + r=r+1 + result[r]={ x,y,"m" } + end + if not checked then + xmin=x + ymin=y + xmax=x + ymax=y + checked=true + elseif x>xmax then + xmax=x + elseif x<xmin then + xmin=x + end + end + local function ymoveto() + if keepcurve then + r=r+1 + result[r]={ x,y,"m" } + end + if not checked then + xmin=x + ymin=y + xmax=x + ymax=y + checked=true + elseif y>ymax then + ymax=y + elseif y<ymin then + ymin=y + end + end + local function lineto() if keepcurve then r=r+1 result[r]={ x,y,"l" } end if checked then - if x<xmin then xmin=x elseif x>xmax then xmax=x end - if y<ymin then ymin=y elseif y>ymax then ymax=y end + if x>xmax then xmax=x elseif x<xmin then xmin=x end + if y>ymax then ymax=y elseif y<ymin then ymin=y end else xmin=x ymin=y @@ -10172,14 +10227,48 @@ do checked=true end end + local function xlineto() + if keepcurve then + r=r+1 + result[r]={ x,y,"l" } + end + if not checked then + xmin=x + ymin=y + xmax=x + ymax=y + checked=true + elseif x>xmax then + xmax=x + elseif x<xmin then + xmin=x + end + end + local function ylineto() + if keepcurve then + r=r+1 + result[r]={ x,y,"l" } + end + if not checked then + xmin=x + ymin=y + xmax=x + ymax=y + checked=true + elseif y>ymax then + ymax=y + elseif y<ymin then + ymin=y + end + end local function curveto(x1,y1,x2,y2,x3,y3) if keepcurve then r=r+1 result[r]={ x1,y1,x2,y2,x3,y3,"c" } end if checked then - if x1<xmin then xmin=x1 elseif x1>xmax then xmax=x1 end - if y1<ymin then ymin=y1 elseif y1>ymax then ymax=y1 end + if x1>xmax then xmax=x1 elseif x1<xmin then xmin=x1 end + if y1>ymax then ymax=y1 elseif y1<ymin then ymin=y1 end else xmin=x1 ymin=y1 @@ -10187,21 +10276,21 @@ do ymax=y1 checked=true end - if x2<xmin then xmin=x2 elseif x2>xmax then xmax=x2 end - if y2<ymin then ymin=y2 elseif y2>ymax then ymax=y2 end - if x3<xmin then xmin=x3 elseif x3>xmax then xmax=x3 end - if y3<ymin then ymin=y3 elseif y3>ymax then ymax=y3 end + if x2>xmax then xmax=x2 elseif x2<xmin then xmin=x2 end + if y2>ymax then ymax=y2 elseif y2<ymin then ymin=y2 end + if x3>xmax then xmax=x3 elseif x3<xmin then xmin=x3 end + if y3>ymax then ymax=y3 elseif y3<ymin then ymin=y3 end end local function rmoveto() - if top>2 then - if not width then + if not width then + if top>2 then width=stack[1] if trace_charstrings then showvalue("width",width) end + else + width=true end - elseif not width then - width=true end if trace_charstrings then showstate("rmoveto") @@ -10209,43 +10298,43 @@ do x=x+stack[top-1] y=y+stack[top] top=0 - moveto(x,y) + moveto() end local function hmoveto() - if top>1 then - if not width then + if not width then + if top>1 then width=stack[1] if trace_charstrings then showvalue("width",width) end + else + width=true end - elseif not width then - width=true end if trace_charstrings then showstate("hmoveto") end x=x+stack[top] top=0 - moveto(x,y) + xmoveto() end local function vmoveto() - if top>1 then - if not width then + if not width then + if top>1 then width=stack[1] if trace_charstrings then showvalue("width",width) end + else + width=true end - elseif not width then - width=true end if trace_charstrings then showstate("vmoveto") end y=y+stack[top] top=0 - moveto(x,y) + ymoveto() end local function rlineto() if trace_charstrings then @@ -10254,20 +10343,7 @@ do for i=1,top,2 do x=x+stack[i] y=y+stack[i+1] - lineto(x,y) - end - top=0 - end - local function xlineto(swap) - for i=1,top do - if swap then - x=x+stack[i] - swap=false - else - y=y+stack[i] - swap=true - end - lineto(x,y) + lineto() end top=0 end @@ -10275,13 +10351,47 @@ do if trace_charstrings then showstate("hlineto") end - xlineto(true) + if top==1 then + x=x+stack[1] + xlineto() + else + local swap=true + for i=1,top do + if swap then + x=x+stack[i] + xlineto() + swap=false + else + y=y+stack[i] + ylineto() + swap=true + end + end + end + top=0 end local function vlineto() if trace_charstrings then showstate("vlineto") end - xlineto(false) + if top==1 then + y=y+stack[1] + ylineto() + else + local swap=false + for i=1,top do + if swap then + x=x+stack[i] + xlineto() + swap=false + else + y=y+stack[i] + ylineto() + swap=true + end + end + end + top=0 end local function rrcurveto() if trace_charstrings then @@ -10292,8 +10402,8 @@ do local ay=y+stack[i+1] local bx=ax+stack[i+2] local by=ay+stack[i+3] - x=bx+stack[i+4] - y=by+stack[i+5] + x=bx+stack[i+4] + y=by+stack[i+5] curveto(ax,ay,bx,by,x,y) end top=0 @@ -10304,15 +10414,15 @@ do end local s=1 if top%2~=0 then - y=y+stack[1] + y=y+stack[1] s=2 end for i=s,top,4 do - local ax=x+stack[i] + local ax=x+stack[i] local ay=y local bx=ax+stack[i+1] local by=ay+stack[i+2] - x=bx+stack[i+3] + x=bx+stack[i+3] y=by curveto(ax,ay,bx,by,x,y) end @@ -10325,16 +10435,16 @@ do local s=1 local d=0 if top%2~=0 then - d=stack[1] + d=stack[1] s=2 end for i=s,top,4 do local ax=x+d - local ay=y+stack[i] + local ay=y+stack[i] local bx=ax+stack[i+1] local by=ay+stack[i+2] x=bx - y=by+stack[i+3] + y=by+stack[i+3] curveto(ax,ay,bx,by,x,y) d=0 end @@ -10345,7 +10455,6 @@ do if last then top=top-1 end - local sw=swap for i=1,top,4 do local ax,ay,bx,by if swap then @@ -10404,7 +10513,7 @@ do end x=x+stack[top-1] y=y+stack[top] - lineto(x,y) + lineto() top=0 end local function rlinecurve() @@ -10415,7 +10524,7 @@ do for i=1,top-6,2 do x=x+stack[i] y=y+stack[i+1] - lineto(x,y) + lineto() end end local ax=x+stack[top-5] @@ -10451,7 +10560,7 @@ do if trace_charstrings then showstate("hflex") end - local ax=x+stack[1] + local ax=x+stack[1] local ay=y local bx=ax+stack[2] local by=ay+stack[3] @@ -10688,8 +10797,8 @@ do [036]=hflex1, [037]=flex1, } - local p_bytes=Ct((P(1)/byte)^0) - local function call(scope,list,bias,process) + local process + local function call(scope,list,bias) depth=depth+1 if top==0 then showstate(formatters["unknown %s call"](scope)) @@ -10702,10 +10811,6 @@ do end local tab=list[index] if tab then - if type(tab)=="string" then - tab=lpegmatch(p_bytes,tab) - list[index]=tab - end process(tab) else showstate(formatters["unknown %s call %i"](scope,index)) @@ -10714,50 +10819,52 @@ do end depth=depth-1 end - local function process(tab) + process=function(tab) local i=1 local n=#tab while i<=n do local t=tab[i] - if t>=32 and t<=246 then - top=top+1 - stack[top]=t-139 - i=i+1 - elseif t>=247 and t<=250 then - top=top+1 - stack[top]=(t-247)*256+tab[i+1]+108 - i=i+2 - elseif t>=251 and t<=254 then - top=top+1 - stack[top]=-(t-251)*256-tab[i+1]-108 - i=i+2 + if t>=32 then + if t<=246 then + top=top+1 + stack[top]=t-139 + i=i+1 + elseif t<=250 then + top=top+1 + stack[top]=t*256-63124+tab[i+1] + i=i+2 + elseif t<=254 then + top=top+1 + stack[top]=-t*256+64148-tab[i+1] + i=i+2 + else + local n=0x100*tab[i+1]+tab[i+2] + top=top+1 + if n>=0x8000 then + stack[top]=n-0x10000+(0x100*tab[i+3]+tab[i+4])/0xFFFF + else + stack[top]=n+(0x100*tab[i+3]+tab[i+4])/0xFFFF + end + i=i+5 + end elseif t==28 then top=top+1 local n=0x100*tab[i+1]+tab[i+2] if n>=0x8000 then - stack[top]=n-0xFFFF-1 + stack[top]=n-0x10000 else stack[top]=n end i=i+3 - elseif t==255 then - local n=0x100*tab[i+1]+tab[i+2] - top=top+1 - if n>=0x8000 then - stack[top]=n-0xFFFF-1+(0x100*tab[i+3]+tab[i+4])/0xFFFF - else - stack[top]=n+(0x100*tab[i+3]+tab[i+4])/0xFFFF - end - i=i+5 elseif t==11 then if trace_charstrings then showstate("return") end return elseif t==10 then - call("local",locals,localbias,process) + call("local",locals,localbias) i=i+1 - elseif t==14 then + elseif t==14 then if width then elseif top>0 then width=stack[1] @@ -10772,7 +10879,7 @@ do end return elseif t==29 then - call("global",globals,globalbias,process) + call("global",globals,globalbias) i=i+1 elseif t==12 then i=i+1 @@ -10833,9 +10940,7 @@ do local defaultwidth=private.data.defaultwidthx or 0 for i=1,#charstrings do local tab=charstrings[i] - if type(tab)=="string" then - tab=lpegmatch(p_bytes,tab) - end + tab={ byte(tab,1,#tab) } local index=i-1 x=0 y=0 @@ -10861,14 +10966,7 @@ do width=nominalwidth+width end local glyph=glyphs[index] - if not glyph then - glyphs[index]={ - segments=doshapes~=false and result or nil, - boundingbox=boundingbox, - width=width, - name=charset[index], - } - else + if glyph then glyph.segments=doshapes~=false and result or nil glyph.boundingbox=boundingbox if not glyph.width then @@ -10877,6 +10975,19 @@ do if charset and not glyph.name then glyph.name=charset[index] end + elseif doshapes then + glyphs[index]={ + segments=result, + boundingbox=boundingbox, + width=width, + name=charset[index], + } + else + glyphs[index]={ + boundingbox=boundingbox, + width=width, + name=charset[index], + } end if trace_charstrings then report("width: %s",tostring(width)) @@ -10896,9 +11007,7 @@ do globalbias,localbias=setbias(globals,locals) local nominalwidth=private and private.data.nominalwidthx or 0 local defaultwidth=private and private.data.defaultwidthx or 0 - if type(tab)=="string" then - tab=lpegmatch(p_bytes,tab) - end + tab={ byte(tab,1,#tab) } x=0 y=0 width=false @@ -10924,14 +11033,7 @@ do end index=index-1 local glyph=glyphs[index] - if not glyph then - glyphs[index]={ - segments=doshapes~=false and result or nil, - boundingbox=boundingbox, - width=width, - name=charset[index], - } - else + if glyph then glyph.segments=doshapes~=false and result or nil glyph.boundingbox=boundingbox if not glyph.width then @@ -10940,6 +11042,19 @@ do if charset and not glyph.name then glyph.name=charset[index] end + elseif doshapes then + glyphs[index]={ + segments=result, + boundingbox=boundingbox, + width=width, + name=charset[index], + } + else + glyphs[index]={ + boundingbox=boundingbox, + width=width, + name=charset[index], + } end if trace_charstrings then report("width: %s",tostring(width)) @@ -10955,7 +11070,7 @@ end local function readglobals(f,data) local routines=readlengths(f) for i=1,#routines do - routines[i]=readstring(f,routines[i]) + routines[i]=readbytetable(f,routines[i]) end data.routines=routines end @@ -11013,7 +11128,7 @@ local function readlocals(f,data,dictionary) setposition(f,header.offset+private.offset+subroutineoffset) local subroutines=readlengths(f) for i=1,#subroutines do - subroutines[i]=readstring(f,subroutines[i]) + subroutines[i]=readbytetable(f,subroutines[i]) end dictionary.subroutines=subroutines private.data.subroutines=nil @@ -11131,6 +11246,7 @@ local function readfdselect(f,data,glyphs,doshapes,version) end for i=1,#charstrings do parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version) +charstrings[i]=nil end resetcharstrings() end @@ -11638,18 +11754,18 @@ local readers=fonts.handlers.otf.readers local streamreader=readers.streamreader local setposition=streamreader.setposition local getposition=streamreader.getposition -local skipshort=streamreader.skipshort -local skipbytes=streamreader.skip local readushort=streamreader.readcardinal2 local readulong=streamreader.readcardinal4 +local readinteger=streamreader.readinteger1 local readshort=streamreader.readinteger2 -local readfword=readshort local readstring=streamreader.readstring local readtag=streamreader.readtag local readbytes=streamreader.readbytes local readfixed=streamreader.readfixed4 local read2dot14=streamreader.read2dot14 -local readinteger=streamreader.readinteger1 +local skipshort=streamreader.skipshort +local skipbytes=streamreader.skip +local readfword=readshort local gsubhandlers={} local gposhandlers={} local lookupidoffset=-1 @@ -13168,57 +13284,61 @@ do report("ignoring global kern table using gpos kern feature") return end - report("adding global kern table as gpos feature %a",name) setposition(f,datatable.offset) local version=readushort(f) local noftables=readushort(f) - local kerns=setmetatableindex("table") - for i=1,noftables do - local version=readushort(f) - local length=readushort(f) - local coverage=readushort(f) - local format=bit32.rshift(coverage,8) - if format==0 then - local nofpairs=readushort(f) - local searchrange=readushort(f) - local entryselector=readushort(f) - local rangeshift=readushort(f) - for i=1,nofpairs do - kerns[readushort(f)][readushort(f)]=readfword(f) - end - elseif format==2 then + if noftables>1 then + report("adding global kern table as gpos feature %a",name) + local kerns=setmetatableindex("table") + for i=1,noftables do + local version=readushort(f) + local length=readushort(f) + local coverage=readushort(f) + local format=bit32.rshift(coverage,8) + if format==0 then + local nofpairs=readushort(f) + local searchrange=readushort(f) + local entryselector=readushort(f) + local rangeshift=readushort(f) + for i=1,nofpairs do + kerns[readushort(f)][readushort(f)]=readfword(f) + end + elseif format==2 then + else + end + end + local feature={ dflt={ dflt=true } } + if not features then + fontdata.features={ gpos={ [name]=feature } } + elseif not gposfeatures then + fontdata.features.gpos={ [name]=feature } else + gposfeatures[name]=feature end - end - local feature={ dflt={ dflt=true } } - if not features then - fontdata.features={ gpos={ [name]=feature } } - elseif not gposfeatures then - fontdata.features.gpos={ [name]=feature } + local sequences=fontdata.sequences + if not sequences then + sequences={} + fontdata.sequences=sequences + end + local nofsequences=#sequences+1 + sequences[nofsequences]={ + index=nofsequences, + name=name, + steps={ + { + coverage=kerns, + format="kern", + }, + }, + nofsteps=1, + type="gpos_pair", + flags={ false,false,false,false }, + order={ name }, + features={ [name]=feature }, + } else - gposfeatures[name]=feature - end - local sequences=fontdata.sequences - if not sequences then - sequences={} - fontdata.sequences=sequences + report("ignoring empty kern table of feature %a",name) end - local nofsequences=#sequences+1 - sequences[nofsequences]={ - index=nofsequences, - name=name, - steps={ - { - coverage=kerns, - format="kern", - }, - }, - nofsteps=1, - type="gpos_pair", - flags={ false,false,false,false }, - order={ name }, - features={ [name]=feature }, - } end function readers.gsub(f,fontdata,specification) if specification.details then @@ -21594,7 +21714,7 @@ end otf.helpers=otf.helpers or {} otf.helpers.txtdirstate=txtdirstate otf.helpers.pardirstate=pardirstate -local function featuresprocessor(head,font,attr) +local function featuresprocessor(head,font,attr,direction) local sequences=sequencelists[font] if not sequencelists then return head,false @@ -21620,7 +21740,7 @@ local function featuresprocessor(head,font,attr) if trace_steps then checkstep(head) end - local rlmode=0 + local initialrl=direction=="TRT" and -1 or 0 local done=false local datasets=otf.dataset(tfmdata,font,attr) local dirstack={} @@ -21629,7 +21749,7 @@ local function featuresprocessor(head,font,attr) local dataset=datasets[s] local attribute=dataset[2] local sequence=dataset[3] - local rlparmode=0 + local rlparmode=initialrl local topstack=0 local typ=sequence.type local gpossing=typ=="gpos_single" or typ=="gpos_pair" @@ -21646,6 +21766,7 @@ local function featuresprocessor(head,font,attr) end elseif typ=="gsub_reversecontextchain" then local start=find_node_tail(head) + local rlmode=0 while start do local char=ischar(start,font) if char then @@ -21682,8 +21803,8 @@ local function featuresprocessor(head,font,attr) end end else - local start=head - rlmode=0 + local start=head + local rlmode=initialrl if nofsteps==1 then local step=steps[1] local lookupcache=step.coverage @@ -25156,8 +25277,8 @@ do end local setroutine=function(str,position,index,size) local forward=position+tonumber(size) - local stream=sub(str,position+1,forward) - routines[index]=decrypt(stream,4330,4) + local stream=decrypt(sub(str,position+1,forward),4330,4) + routines[index]={ byte(stream,1,#stream) } return forward end local setvector=function(str,position,name,size) |