diff options
30 files changed, 1405 insertions, 1102 deletions
diff --git a/fonts/misc/xetex/fontmapping/tlig.map b/fonts/misc/xetex/fontmapping/tlig.map new file mode 100644 index 000000000..2f296f311 --- /dev/null +++ b/fonts/misc/xetex/fontmapping/tlig.map @@ -0,0 +1,16 @@ +; TECkit mapping for TeX input conventions <-> Unicode characters +; +; Based on tex-text.map used in XeTeX, but with less ligatures (olny the most important ones) +; This part of ConTeXt distribution, but may be used for any purpose + +LHSName "tlig" +RHSName "UNICODE" + +pass(Unicode) + +; ligatures from Knuth's original CMR fonts +U+002D U+002D <> U+2013 ; -- -> en dash +U+002D U+002D U+002D <> U+2014 ; --- -> em dash + +U+0027 <> U+2019 ; ' -> right single quote + diff --git a/fonts/misc/xetex/fontmapping/tlig.tec b/fonts/misc/xetex/fontmapping/tlig.tec Binary files differnew file mode 100644 index 000000000..ab2268c20 --- /dev/null +++ b/fonts/misc/xetex/fontmapping/tlig.tec diff --git a/scripts/context/lua/luatools.lua b/scripts/context/lua/luatools.lua index 26902a4bc..abfc345e4 100644 --- a/scripts/context/lua/luatools.lua +++ b/scripts/context/lua/luatools.lua @@ -1330,6 +1330,17 @@ function number.toset(n) return (tostring(n)):match("(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)") end +local format = string.format + +function number.toevenhex(n) + local s = format("%X",n) + if #s % 2 == 0 then + return s + else + return "0" .. s + end +end + -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5% -- on -- @@ -1568,26 +1579,32 @@ dir = { } -- optimizing for no string.find (*) does not save time -if lfs then +if lfs then do + + local attributes = lfs.attributes + local walkdir = lfs.dir - function dir.glob_pattern(path,patt,recurse,action) - local ok, scanner = xpcall(function() return lfs.dir(path) end, function() end) -- kepler safe + local function glob_pattern(path,patt,recurse,action) + local ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe if ok and type(scanner) == "function" then + if not path:find("/$") then path = path .. '/' end for name in scanner do - local full = path .. '/' .. name - local mode = lfs.attributes(full,'mode') + local full = path .. name + local mode = attributes(full,'mode') if mode == 'file' then if name:find(patt) then action(full) end elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then - dir.glob_pattern(full,patt,recurse,action) + glob_pattern(full,patt,recurse,action) end end end end - function dir.glob(pattern, action) + dir.glob_pattern = glob_pattern + + local function glob(pattern, action) local t = { } local action = action or function(name) table.insert(t,name) end local path, patt = pattern:match("^(.*)/*%*%*/*(.-)$") @@ -1603,22 +1620,26 @@ if lfs then patt = patt:gsub("%?", ".") patt = "^" .. patt .. "$" -- print('path: ' .. path .. ' | pattern: ' .. patt .. ' | recurse: ' .. tostring(recurse)) - dir.glob_pattern(path,patt,recurse,action) + glob_pattern(path,patt,recurse,action) return t end - function dir.globfiles(path,recurse,func,files) + dir.glob = glob + + -- todo: speedup + + local function globfiles(path,recurse,func,files) if type(func) == "string" then local s = func -- alas, we need this indirect way func = function(name) return name:find(s) end end files = files or { } - for name in lfs.dir(path) do + for name in walkdir(path) do if name:find("^%.") then --- skip - elseif lfs.attributes(name,'mode') == "directory" then + elseif attributes(name,'mode') == "directory" then if recurse then - dir.globfiles(path .. "/" .. name,recurse,func,files) + globfiles(path .. "/" .. name,recurse,func,files) end elseif func then if func(name) then @@ -1631,6 +1652,8 @@ if lfs then return files end + dir.globfiles = globfiles + -- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex") -- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex") -- t = dir.glob("c:/data/develop/context/texmf/**/*.tex") @@ -1639,7 +1662,7 @@ if lfs then -- print(dir.ls("*.tex")) function dir.ls(pattern) - return table.concat(dir.glob(pattern),"\n") + return table.concat(glob(pattern),"\n") end --~ mkdirs("temp") @@ -1666,7 +1689,7 @@ if lfs then dir.makedirs = dir.mkdirs -end +end end -- filename : l-boolean.lua diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index 5a0e3aaeb..011ee8bb2 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -1365,6 +1365,17 @@ function number.toset(n) return (tostring(n)):match("(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)") end +local format = string.format + +function number.toevenhex(n) + local s = format("%X",n) + if #s % 2 == 0 then + return s + else + return "0" .. s + end +end + -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5% -- on -- @@ -1583,26 +1594,32 @@ dir = { } -- optimizing for no string.find (*) does not save time -if lfs then +if lfs then do + + local attributes = lfs.attributes + local walkdir = lfs.dir - function dir.glob_pattern(path,patt,recurse,action) - local ok, scanner = xpcall(function() return lfs.dir(path) end, function() end) -- kepler safe + local function glob_pattern(path,patt,recurse,action) + local ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe if ok and type(scanner) == "function" then + if not path:find("/$") then path = path .. '/' end for name in scanner do - local full = path .. '/' .. name - local mode = lfs.attributes(full,'mode') + local full = path .. name + local mode = attributes(full,'mode') if mode == 'file' then if name:find(patt) then action(full) end elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then - dir.glob_pattern(full,patt,recurse,action) + glob_pattern(full,patt,recurse,action) end end end end - function dir.glob(pattern, action) + dir.glob_pattern = glob_pattern + + local function glob(pattern, action) local t = { } local action = action or function(name) table.insert(t,name) end local path, patt = pattern:match("^(.*)/*%*%*/*(.-)$") @@ -1618,22 +1635,26 @@ if lfs then patt = patt:gsub("%?", ".") patt = "^" .. patt .. "$" -- print('path: ' .. path .. ' | pattern: ' .. patt .. ' | recurse: ' .. tostring(recurse)) - dir.glob_pattern(path,patt,recurse,action) + glob_pattern(path,patt,recurse,action) return t end - function dir.globfiles(path,recurse,func,files) + dir.glob = glob + + -- todo: speedup + + local function globfiles(path,recurse,func,files) if type(func) == "string" then local s = func -- alas, we need this indirect way func = function(name) return name:find(s) end end files = files or { } - for name in lfs.dir(path) do + for name in walkdir(path) do if name:find("^%.") then --- skip - elseif lfs.attributes(name,'mode') == "directory" then + elseif attributes(name,'mode') == "directory" then if recurse then - dir.globfiles(path .. "/" .. name,recurse,func,files) + globfiles(path .. "/" .. name,recurse,func,files) end elseif func then if func(name) then @@ -1646,6 +1667,8 @@ if lfs then return files end + dir.globfiles = globfiles + -- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex") -- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex") -- t = dir.glob("c:/data/develop/context/texmf/**/*.tex") @@ -1654,7 +1677,7 @@ if lfs then -- print(dir.ls("*.tex")) function dir.ls(pattern) - return table.concat(dir.glob(pattern),"\n") + return table.concat(glob(pattern),"\n") end --~ mkdirs("temp") @@ -1681,7 +1704,7 @@ if lfs then dir.makedirs = dir.mkdirs -end +end end -- filename : l-boolean.lua diff --git a/tex/context/base/colo-new.lua b/tex/context/base/colo-new.lua index b009c5e9b..a4650ba9c 100644 --- a/tex/context/base/colo-new.lua +++ b/tex/context/base/colo-new.lua @@ -24,23 +24,23 @@ do -- maybe combine spotcolorname - local s_template_g = "\\doregistergrayspotcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away) - local s_template_r = "\\doregisterrgbspotcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b - local s_template_c = "\\doregistercmykspotcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k + local s_template_g = "\\dodoPDFregistergrayspotcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away) + local s_template_r = "\\dodoPDFregisterrgbspotcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b + local s_template_c = "\\dodoPDFregistercmykspotcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k function backends.pdf.registergrayspotcolor(n,f,d,p,s) states.collect(s_template_g:format(n,f,d,p,s)) end function backends.pdf.registerrgbspotcolor (n,f,d,p,r,g,b) states.collect(s_template_r:format(n,f,d,p,r,g,b)) end function backends.pdf.registercmykspotcolor(n,f,d,p,c,m,y,k) states.collect(s_template_c:format(n,f,d,p,c,m,y,k)) end - local m_template_g = "\\doregistergrayindexcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away) - local m_template_r = "\\doregisterrgbindexcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b - local m_template_c = "\\doregistercmykindexcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k + local m_template_g = "\\doPDFregistergrayindexcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away) + local m_template_r = "\\doPDFregisterrgbindexcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b + local m_template_c = "\\doPDFregistercmykindexcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k function backends.pdf.registergrayindexcolor(n,f,d,p,s) states.collect(m_template_g:format(n,f,d,p,s)) end function backends.pdf.registerrgbindexcolor (n,f,d,p,r,g,b) states.collect(m_template_r:format(n,f,d,p,r,g,b)) end function backends.pdf.registercmykindexcolor(n,f,d,p,c,m,y,k) states.collect(m_template_c:format(n,f,d,p,c,m,y,k)) end - local s_template_e = "\\doregisterspotcolorname{%s}{%s}" -- name, e + local s_template_e = "\\doPDFregisterspotcolorname{%s}{%s}" -- name, e function backends.pdf.registerspotcolorname(name,e) if e and e ~= "" then diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex index 0e317a304..1136aee54 100644 --- a/tex/context/base/cont-new.tex +++ b/tex/context/base/cont-new.tex @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2007.12.07 19:14} +\newcontextversion{2007.12.17 14:54} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new @@ -31,6 +31,41 @@ \let\then\relax % \ifnum1>2\then -) +% very experimental, used in \testpagesync which is used in splitting (e.g. core-ntb) + +% \installoutput\flushpagesofar +% {\ifvoid\normalpagebox\else +% \global\setbox\normalpagebox\vbox +% {\unvbox\normalpagebox +% \setbox\scratchbox\lastbox}% +% \unvbox\normalpagebox +% \fi} + +% \let\normalflushpagesofar\flushpagesofar + +% \def\flushpagesofar +% {\ifdim\pagetotal>\pagegoal +% \endgraf +% \begingroup +% \forgetall +% \normalvbox{\hsize\zeropoint\strut\endgraf\strut}% +% %normalvbox{\hsize\zeropoint\strut flush }% +% %normalvbox{\hsize\zeropoint\strut flush page so far}% +% \endgroup +% \endgraf +% \normalflushpagesofar +% \fi} + +\def\flushpagesofar + {\endgraf + \ifdim\pagetotal>\pagegoal + \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal + \penalty\outputpenalty + \else + \page + \fi + \fi} + % \setupcaption [figure] [align=flushleft] % \setupcaption [figure-1] [align=flushleft,leftmargin=10mm] % \setupcaption [figure-2] [align=flushleft,leftmargin=10mm,rightmargin=-10mm,width=\textwidth] diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex index 5da080f07..4992ab981 100644 --- a/tex/context/base/context.tex +++ b/tex/context/base/context.tex @@ -42,7 +42,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2007.12.07 19:14} +\edef\contextversion{2007.12.17 14:54} %D For those who want to use this: diff --git a/tex/context/base/core-fig.tex b/tex/context/base/core-fig.tex index 27825ba5c..9a2eb8474 100644 --- a/tex/context/base/core-fig.tex +++ b/tex/context/base/core-fig.tex @@ -1167,6 +1167,46 @@ \expanded{\doifinset{\v!default}{\@@exlocation}} {\appendtocommalist\defaultfigurepathsignal\figurepathlist}} +% \def\analyzefigurefilename#1#2% +% {\sanitizefilename#1\to\expandedfigurename +% \expanded{\checkfilename{\expandedfigurename}}% +% \ifcase\kindoffile +% \splitfigurefilename +% \ifcase\splitoffkind +% \let\wantedfigurepath\empty % no . either +% \setfigurepathlist +% \setfalse\figurefileisqualified +% \else +% \splitfigurefilename +% \let\figurepathlist\wantedfigurepath +% \let\wantedfigurepath\empty +% \settrue\figurefileisqualified +% \fi +% \else % fully qualified +% \splitfigurefilename +% \let\figurepathlist\wantedfigurepath +% \let\wantedfigurepath\empty +% \settrue\figurefileisqualified +% \fi +% \ifx\figurepathlist\empty +% \let\figurepathlist\defaultfigurepathsignal % will prepend no path +% \fi +% \doifelsenothing\wantedfiguretype +% {\doifparentfileelse\wantedfigurename +% {\@EA\removefromcommalist\@EA{\jobsuffix }\wantedfiguretypelist +% \@EA\removefromcommalist\@EA{\jobfilesuffix}\wantedfiguretypelist} +% {}} +% {\let\wantedfiguretypelist\empty +% \let\wantedfiguretypespec\wantedfiguretype}% +% \edef\wantedfigurelabel{#2}% +% \doshowfigurestate{type check : \ifx\wantedfiguretypelist\empty forced type \wantedfiguretypespec\else\wantedfiguretypelist\fi}% +% \doshowfigurestate{file specs : \wantedfigurefull\space [\wantedfigurepath] [\wantedfigurename] [\wantedfiguretype]}% +% \doshowfigurestate{file type : \ifconditional\figurefileisqualified qualified\else simple\fi}} + +% The combined path and qualified path hack is dedicated to Onno Tomson, +% our partner in fighting inconsistent and faulty image specifications in +% user files. + \def\analyzefigurefilename#1#2% {\sanitizefilename#1\to\expandedfigurename \expanded{\checkfilename{\expandedfigurename}}% @@ -1178,13 +1218,24 @@ \setfalse\figurefileisqualified \else \splitfigurefilename +% will become splitoffkind 3 ! ! ! ! +\setfalse\figurefileisqualified +\doifinstring{$$/}{$$\wantedfigurepath}{\settrue\figurefileisqualified}% +\doifinstring {:} {\wantedfigurepath}{\settrue\figurefileisqualified}% +\ifconditional\figurefileisqualified \let\figurepathlist\wantedfigurepath \let\wantedfigurepath\empty \settrue\figurefileisqualified +\else + \let\figurepathlist\@@exdirectory + \let\oldfigurepathlist\figurepathlist + \let\figurepathlist\wantedfigurepath + \def\docommand##1{\edef\figurepathlist{\figurepathlist,##1/\wantedfigurepath}}% + \processcommacommand[\oldfigurepathlist]\docommand +\fi \fi \else % fully qualified \splitfigurefilename - \let\figurepathlist\wantedfigurepath \let\wantedfigurepath\empty \settrue\figurefileisqualified \fi diff --git a/tex/context/base/core-ntb.tex b/tex/context/base/core-ntb.tex index a57739c8b..7d5a04d13 100644 --- a/tex/context/base/core-ntb.tex +++ b/tex/context/base/core-ntb.tex @@ -12,7 +12,14 @@ %C details. %D This is an unfinished, preliminary module. At least two -%D runs are needed to get the table fixed. +%D runs are needed to get the table fixed. Ugly code. + +% todo: special parsetb for argless variant +% todo: protect \tbl... +% todo: tblnx also count +% todo: get rid of recurse +% todo: fast if +% todo: avoid halign (just do it manual) and thereby globals % optie=rek beschrijven @@ -118,7 +125,7 @@ \fi \fi} -\newcounter\currenttbl +\newcount\currenttbl \def\@@tbl{tbl} \def\tblcell{1} \def\tblnone{2} @@ -128,55 +135,84 @@ % \let as well as \expandafter\edef's -\def\settbltag#1#2#3{\setevalue{\@@tblprefix#1:#2:s}{#3}} % \number#3 -\def\settblcol#1#2#3{\setevalue{\@@tblprefix#1:#2:c}{#3}} -\def\settblrow#1#2#3{\setevalue{\@@tblprefix#1:#2:r}{#3}} +\newcounter\TBLlevel -\def\settblwd #1#2#3{\setxvalue{\@@tblprefix#1:#2:wd}{#3}} % global ! -\def\settblht #1#2#3{\setxvalue{\@@tblprefix#1:#2:ht}{#3}} % global ! +\def\@@tblprefix{\@@tbl:\ifnum\TBLlevel>1 :\TBLlevel:\fi} -\def\gettbltag#1#2{\csname\@@tblprefix#1:#2:s\endcsname} -\def\gettblcol#1#2{\csname\@@tblprefix#1:#2:c\endcsname} -\def\gettblrow#1#2{\csname\@@tblprefix#1:#2:r\endcsname} +% \def\tblsetprefix % not yet used, figure out when .. may interfere with setup +% {\edef\@@tblprefix{\@@tbl:\ifnum\TBLlevel>1 :\TBLlevel:\fi}} -\def\gettblwd #1#2{\csname\@@tblprefix#1:#2:wd\endcsname} -\def\gettblht #1#2{\csname\@@tblprefix#1:#2:ht\endcsname} +\def\settblnob#1{\expandafter\let\csname\@@tblprefix\number#1:b\endcsname\plusone} +\def\gettblnob#1{\ifcsname\@@tblprefix\number#1:b\endcsname\plusone\else\zerocount\fi} -\def\settblwid#1#2{\setxvalue{\@@tblprefix#1:w}{#2}} % global ! -\def\settblhei#1#2{\setxvalue{\@@tblprefix#1:h}{#2}} % global ! -\def\settbldis#1#2{\setxvalue{\@@tblprefix#1:d}{#2}} % global ! -\def\settblaut#1#2{\setxvalue{\@@tblprefix#1:a}{#2}} % global ! +\def\settbltag#1#2{\expandafter\edef\csname\@@tblprefix\number#1:\number#2:s\endcsname} +\def\settblcol#1#2{\expandafter\edef\csname\@@tblprefix\number#1:\number#2:c\endcsname} +\def\settblrow#1#2{\expandafter\edef\csname\@@tblprefix\number#1:\number#2:r\endcsname} -\def\gettblwid#1{\executeifdefined{\@@tblprefix#1:w}\zeropoint} -\def\gettblhei#1{\executeifdefined{\@@tblprefix#1:h}\zeropoint} -\def\gettbldis#1{\executeifdefined{\@@tblprefix#1:d}\zeropoint} -\def\gettblaut#1{\csname\@@tblprefix#1:a\endcsname} +\def\lettbltag#1#2{\expandafter\let\csname\@@tblprefix\number#1:\number#2:s\endcsname} +\def\lettblcol#1#2{\expandafter\let\csname\@@tblprefix\number#1:\number#2:c\endcsname} +\def\lettblrow#1#2{\expandafter\let\csname\@@tblprefix\number#1:\number#2:r\endcsname} -\def\doiftbltag #1#2{\doifdefined {\@@tblprefix#1:#2:s}} -\def\doifnottbltag #1#2{\doifundefined {\@@tblprefix#1:#2:s}} -\def\doifelsetbltag#1#2{\doifdefinedelse{\@@tblprefix#1:#2:s}} -\def\doiftblrow #1#2{\doifdefined {\@@tblprefix#1:#2:r}} -\def\doiftblcol #1#2{\doifdefined {\@@tblprefix#1:#2:c}} -\def\doifnottblcol #1#2{\doifundefined {\@@tblprefix#1:#2:c}} +\def\settblwd#1#2{\expandafter\xdef\csname\@@tblprefix\number#1:\number#2:wd\endcsname} % global ! +\def\settblht#1#2{\expandafter\xdef\csname\@@tblprefix\number#1:\number#2:ht\endcsname} % global ! +\def\lettblwd#1#2{\global\expandafter\let\csname\@@tblprefix\number#1:\number#2:wd\endcsname} % global ! +\def\lettblht#1#2{\global\expandafter\let\csname\@@tblprefix\number#1:\number#2:ht\endcsname} % global ! -% \def\settblspn#1#2{\setvalue {\@@tblprefix#1:s}{#2}} -% \def\doiftblspn #1{\doifelsevalue{\@@tblprefix#1:s}{1}} +\def\gettbltag#1#2{\csname\@@tblprefix\number#1:\number#2:s\endcsname} +\def\gettblcol#1#2{\csname\@@tblprefix\number#1:\number#2:c\endcsname} +\def\gettblrow#1#2{\csname\@@tblprefix\number#1:\number#2:r\endcsname} -\def\settblspn #1{\setvalue {\@@tblprefix#1:s}{1}} -\def\doifelsetblspn#1{\doifelsevalue{\@@tblprefix#1:s}{1}} +\def\gettblwd #1#2{\csname\@@tblprefix\number#1:\number#2:wd\endcsname} +\def\gettblht #1#2{\csname\@@tblprefix\number#1:\number#2:ht\endcsname} -\def\settbltxt#1#2{\long\setvalue{\@@tblprefix:#1:#2:t}} -\def\gettbltxt#1#2{\csname\@@tblprefix:#1:#2:t\endcsname} +\def\settblwid#1{\expandafter\xdef\csname\@@tblprefix\number#1:w\endcsname} % {#2} global ! +\def\settblhei#1{\expandafter\xdef\csname\@@tblprefix\number#1:h\endcsname} % {#2} global ! +\def\settbldis#1{\expandafter\xdef\csname\@@tblprefix\number#1:d\endcsname} % {#2} global ! +\def\settblaut#1{\expandafter\xdef\csname\@@tblprefix\number#1:a\endcsname} % {#2} global ! -%\def\doiftbl #1#2#3{\ifcase0\getvalue{\@@tblprefix#1:#2:s}\relax \else#3\fi} -%\def\doifnottbl #1#2#3{\ifcase0\getvalue{\@@tblprefix#1:#2:s}\relax #3\fi} -%\def\doifelsetbl#1#2#3#4{\ifcase0\getvalue{\@@tblprefix#1:#2:s}\relax#4\else#3\fi} -% -%\let\doiftbltag \doiftbl -%\let\doifnottbltag \doifnottbl -%\let\doifelsetbltag\doifelsetbl +\def\lettblwid#1{\global\expandafter\let\csname\@@tblprefix\number#1:w\endcsname} % {#2} global ! +\def\lettblhei#1{\global\expandafter\let\csname\@@tblprefix\number#1:h\endcsname} % {#2} global ! +\def\lettbldis#1{\global\expandafter\let\csname\@@tblprefix\number#1:d\endcsname} % {#2} global ! +\def\lettblaut#1{\global\expandafter\let\csname\@@tblprefix\number#1:a\endcsname} % {#2} global ! + +\def\gettblwid#1{\ifcsname\@@tblprefix\number#1:w\endcsname\csname\@@tblprefix\number#1:w\endcsname\else\zeropoint\fi} +\def\gettblhei#1{\ifcsname\@@tblprefix\number#1:h\endcsname\csname\@@tblprefix\number#1:h\endcsname\else\zeropoint\fi} +\def\gettbldis#1{\ifcsname\@@tblprefix\number#1:d\endcsname\csname\@@tblprefix\number#1:d\endcsname\else\zeropoint\fi} +\def\gettblaut#1{\csname \@@tblprefix\number#1:a\endcsname} + +\def\doiftbltag #1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi} +\def\doifnottbltag #1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\@EA\gobbleoneargument \else\@EA\firstofoneargument \fi} +\def\doifelsetbltag#1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\@EA\firstoftwoarguments\else\@EA\secondoftwoarguments\fi} +\def\doiftblrow #1#2{\ifcsname\@@tblprefix\number#1:\number#2:r\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi} +\def\doiftblcol #1#2{\ifcsname\@@tblprefix\number#1:\number#2:c\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi} +\def\doifnottblcol #1#2{\ifcsname\@@tblprefix\number#1:\number#2:c\endcsname\@EA\gobbleoneargument \else\@EA\firstofoneargument \fi} + +\def\tbltagstate#1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\zerocount\else\plusone\fi} +\def\tblrowstate#1#2{\ifcsname\@@tblprefix\number#1:\number#2:r\endcsname\zerocount\else\plusone\fi} +\def\tblcolstate#1#2{\ifcsname\@@tblprefix\number#1:\number#2:c\endcsname\zerocount\else\plusone\fi} + +\def\settblspn #1{\expandafter\let\csname\@@tblprefix\number#1:s\endcsname \!!plusone} +\def\doifelsetblspn#1{\doifelse {\csname\@@tblprefix\number#1:s\endcsname}\!!plusone} +% \def\doifelsetblspn#1{\@EA\ifx\csname\@@tblprefix\number#1:s\endcsname\plusone\@EA\firstoftwoarguments\else\@EA\secondoftwoarguments\fi} + +\def\settblspn #1{\setvalue {\@@tblprefix\number#1:s}{1}} +\def\doifelsetblspn#1{\doifelsevalue{\@@tblprefix\number#1:s}{1}} + +% \long\def\settbltxt#1#2#3% +% {\setxvalue{\@@tblprefix#1:#2:l}{\TBLlevel}% +% \long\setvalue{\@@tblprefix#1:#2:t}% +% {\doifdefined{\@@tblprefix#1:#2:l} +% {\edef\TBLlevel{\getvalue{\@@tblprefix#1:#2:l}}}% +% #3}} + +\long\def\settbltxt#1#2#3% + {\long\@EA\def\csname\@@tblprefix\number#1:\number#2:t\@EA\endcsname\@EA{\@EA\def\@EA\TBLlevel\@EA{\TBLlevel}#3}} + +\def\gettbltxt#1#2% + {\csname\@@tblprefix\number#1:\number#2:t\endcsname} \newtoks\tbltoks +\newtoks\tblrowtoks \let\pushTBLparameters\relax \let\popTBLparameters \relax @@ -314,30 +350,30 @@ \csname\@@tblprefix\c!x\v!oddeven\positivecol\endcsname \csname\@@tblprefix\c!x\v!oddeven\positivecol\c!y\v!oddeven\positiverow\endcsname % row/col number combinations - \executeifdefined{\@@tblprefix\c!y\positiverow}\donothing - \executeifdefined{\@@tblprefix\c!y\negativerow}\donothing + \ifcsname\@@tblprefix\c!y\positiverow\endcsname\csname\@@tblprefix\c!y\positiverow\endcsname\fi + \ifcsname\@@tblprefix\c!y\negativerow\endcsname\csname\@@tblprefix\c!y\negativerow\endcsname\fi \csname\@@tbl\@@tbl\c!extras\endcsname - \letvalue{\@@tbl\@@tbl\c!extras}\relax % new, see x-fo - \executeifdefined{\@@tblprefix\c!x\positivecol}\donothing - \executeifdefined{\@@tblprefix\c!x\negativecol}\donothing + \@EA\let\csname\@@tbl\@@tbl\c!extras\endcsname\relax % new, see x-fo + \ifcsname\@@tblprefix\c!x\positivecol\endcsname\csname\@@tblprefix\c!x\positivecol\endcsname\fi + \ifcsname\@@tblprefix\c!x\negativecol\endcsname\csname\@@tblprefix\c!x\negativecol\endcsname\fi \csname\@@tbl\@@tbl\c!extras\endcsname - \letvalue{\@@tbl\@@tbl\c!extras}\relax % new, see x-fo + \@EA\let\csname\@@tbl\@@tbl\c!extras\endcsname\relax % new, see x-fo % first/last combinations \ifnum\positiverow=\plusone \csname\@@tblprefix\c!y\v!first\endcsname - \executeifdefined{\@@tblprefix\c!x\positivecol\c!y\v!first}\donothing + \ifcsname\@@tblprefix\c!x\positivecol\c!y\v!first\endcsname\csname\@@tblprefix\c!x\positivecol\c!y\v!first\endcsname\fi \fi \ifnum\positivecol=\plusone \csname\@@tblprefix\c!x\v!first\endcsname - \executeifdefined{\@@tblprefix\c!x\v!first\c!y\positiverow}\donothing + \ifcsname\@@tblprefix\c!x\v!first\c!y\positiverow\endcsname\csname\@@tblprefix\c!x\v!first\c!y\positiverow\endcsname\fi \fi \ifnum\positiverow=\maximumrow\relax \csname\@@tblprefix\c!y\v!last\endcsname - \executeifdefined{\@@tblprefix\c!x\positivecol\c!y\v!last}\donothing + \ifcsname\@@tblprefix\c!x\positivecol\c!y\v!last\endcsname\csname\@@tblprefix\c!x\positivecol\c!y\v!last\endcsname\fi \fi \ifnum\positivecol=\maximumcol\relax \csname\@@tblprefix\c!x\v!last\endcsname - \executeifdefined{\@@tblprefix\c!x\v!last\c!y\positiverow}\donothing + \ifcsname\@@tblprefix\c!x\v!last\c!y\positiverow\endcsname\csname\@@tblprefix\c!x\v!last\c!y\positiverow\endcsname\fi \fi \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\maximumcol\relax \csname\@@tblprefix\c!x\v!last\c!y\v!last\endcsname @@ -353,29 +389,29 @@ \fi\fi % special case: two rows and last row : two&first and two&last (round corners) \ifnum\maximumrow=\plustwo\relax - \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\plusone - \csname\@@tblprefix\c!x\v!first\c!y\v!two\endcsname - \fi\fi - \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\maximumcol\relax - \csname\@@tblprefix\c!x\v!last\c!y\v!two\endcsname - \fi\fi + \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\plusone + \csname\@@tblprefix\c!x\v!first\c!y\v!two\endcsname + \fi\fi + \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\maximumcol\relax + \csname\@@tblprefix\c!x\v!last\c!y\v!two\endcsname + \fi\fi + \fi + \ifnum\gettblcol\positiverow\positivecol=\maximumcol\relax % top span over whole width + \ifnum\positiverow=\plusone + \csname\@@tblprefix\c!x\v!one\c!y\v!first\endcsname + \fi + \ifnum\positiverow=\maximumrow\relax + \csname\@@tblprefix\c!x\v!one\c!y\v!last\endcsname + \fi \fi -\ifnum\gettblcol\positiverow\positivecol=\maximumcol\relax % top span over whole width - \ifnum\positiverow=\plusone - \csname\@@tblprefix\c!x\v!one\c!y\v!first\endcsname - \fi - \ifnum\positiverow=\maximumrow\relax - \csname\@@tblprefix\c!x\v!one\c!y\v!last\endcsname - \fi -\fi % header things \ifnum#1>\noftblhdnxlines\else - \executeifdefined{\@@tblprefix\v!header\v!each }\donothing - \executeifdefined{\@@tblprefix\v!header\positivecol}\donothing + \ifcsname\@@tblprefix\v!header\v!each \endcsname\csname\@@tblprefix\v!header\v!each \endcsname\fi + \ifcsname\@@tblprefix\v!header\positivecol\endcsname\csname\@@tblprefix\v!header\positivecol\endcsname\fi \fi % explicit cells - \executeifdefined{\@@tblprefix\c!x\positivecol\c!y\positiverow}\donothing - \executeifdefined{\@@tblprefix\c!x\negativecol\c!y\negativerow}\donothing + \ifcsname\@@tblprefix\c!x\positivecol\c!y\positiverow\endcsname\csname\@@tblprefix\c!x\positivecol\c!y\positiverow\endcsname\fi + \ifcsname\@@tblprefix\c!x\negativecol\c!y\negativerow\endcsname\csname\@@tblprefix\c!x\negativecol\c!y\negativerow\endcsname\fi % done \global\letcscsname\@@tblsplitafter\csname\@@tbl\@@tbl\c!after\endcsname \relax} @@ -403,69 +439,92 @@ % \bTR \bTD left \eTD\bTD right \eTD\eTR % \eTABLE -% \long\def\parseTR[#1][#2]#3\eTR% [#2] is dummy that kills spaces -% {\def\currentcol{0}\increment\maximumrow#3} +% todo: protect counters + +\newcount\row \newcount\col +\newcount\xrow \newcount\xcol +\newcount\xxrow \newcount\xxcol +\newcount\maximumrow \newcount\maximumcol \newcount\maximumrowspan + \newcount\currentcol +\newcount\tblspn \def\parseTR[#1][#2]% [#2] is dummy that kills spaces / no #3 argument - {\def\currentcol{0}\increment\maximumrow - \let\currentcolpos\currentcol + {\currentcol\zerocount + \advance\maximumrow\plusone \let\eTR\relax % handy in \expanded - \setupTABLE[\v!row][\maximumrow][#1]} + \iffirstargument\setTABLEparameters[\c!y\number\maximumrow][#1]\fi} \long\def\parseTD[#1][#2]#3\eTD % [#2] is dummy that kills spaces - {\getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,\c!n=\currentcol,\c!m=,#1]% + {\def\tblny{\tblnr}% + \def\tblnx{\tblnc}% + \let\tblnc\plusone + \let\tblnr\plusone + \let\tbln\currentcol + \let\tblm\empty + \iffirstargument\getparameters[\@@tbl][#1]\fi % goto first cell % NEW, n/m=cellnumber - \increment\currentcolpos - \doifelsevaluenothing{\@@tbl\c!n} - {\increment(\spnTBL,\tblnx)\relax} - {\ifnum\getvalue{\@@tbl\c!n}=\currentcol\else - \scratchcounter\getvalue{\@@tbl\c!n}% - \advance\scratchcounter-\currentcol - \advance\scratchcounter\minusone -\advance\scratchcounter-\spnTBL - \ifnum\scratchcounter>\zerocount - \expanded{\parseTD[\c!nx=\the\scratchcounter,\c!n=,\c!m=,*sq=\v!no][]}\eTD - \fi - \getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,#1,\c!n=,\c!m=]% - \fi}% - \doifvaluesomething{\@@tbl\c!m} - {\ifnum\getvalue{\@@tbl\c!m}=\currentcol\else - \scratchcounter\getvalue{\@@tbl\c!m}% - \advance\scratchcounter-\currentcol - \advance\scratchcounter\minusone -% \advance\scratchcounter-\spnTBL - \dorecurse\scratchcounter{\expanded{\parseTD[\c!n=,\c!m=][]}\eTD}% - \getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,#1,\c!n=,\c!m=]% - \fi}% - \doloop - {\increment\currentcol + \edef\@@tblnindeed{\csname\@@tbl\c!n\endcsname}% + \ifx\@@tblnindeed\empty + \global\advance\tblspn\tblnx\relax + \else\ifnum\@@tblnindeed=\currentcol\else + \scratchcounter\numexpr\@@tblnindeed-\currentcol+\minusone-\tblspn\relax + \ifnum\scratchcounter>\zerocount + \expanded{\parseTD[\c!nx=\the\scratchcounter,\c!n=,\c!m=,*sq=\v!no][]}\eTD + \fi + % can also be made faster + \getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,#1,\c!n=,\c!m=]% + \fi\fi + \edef\@@tblmindeed{\csname\@@tbl\c!m\endcsname}% + \ifx\@@tblmindeed\empty \else + \ifnum\@@tblmindeed=\currentcol \else + \scratchcounter\numexpr\@@tblmindeed-\currentcol+\minusone-\tblspn\relax + \dorecurse\scratchcounter{\expanded{\parseTD[\c!n=,\c!m=][]}\eTD}% + % can be sped up + \getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,#1,\c!n=,\c!m=]% + \fi + \fi + \doloop % skip over columns that result from earlier span + {\advance\currentcol\plusone \doifnottbltag\maximumrow\currentcol\exitloop}% + % == \def\next{\advance\currentcol\plusone\doiftbltag\maximumrow\currentcol\next}\next % fill r*c cells and set span - \let\row\maximumrow - \let\col\currentcol + \ifnum\tblnx=\plusone + \ifnum\tblny=\plusone + \ifnum\currentcol>\maximumcol\relax + \maximumcol\currentcol + \fi + \else + \presetTBLcell + \fi + \else + \presetTBLcell + \fi + % set values + \lettbltag\maximumrow\currentcol\tblcell + \settblcol\maximumrow\currentcol{\number\tblnx}% + \settblrow\maximumrow\currentcol{\number\tblny}% + % save text + \edef\celltag{{\number\maximumrow}{\number\currentcol}}% + \@EA\settbltxt\@EA\maximumrow\@EA\currentcol\@EA{\@EA\handleTBLcell\celltag[#1]{#3}}} + +\def\presetTBLcell + {\row\maximumrow + \col\currentcol \dorecurse\tblny - {\let\col\currentcol - \settblcol\row\col\tblnx + {\col\currentcol + \settblcol\row\col{\number\tblnx}% \ifnum\tblnx>\maximumrowspan\relax - \let\maximumrowspan\tblnx + \maximumrowspan\tblnx \fi \dorecurse\tblnx - {\settbltag\row\col\tblnone - \increment\col}% - \increment\row}% + {\lettbltag\row\col\tblnone + \advance\col\plusone}% + \advance\row\plusone}% % check max column - \decrement\col\relax + \advance\col\minusone \ifnum\col>\maximumcol\relax - \let\maximumcol\col - \fi - % set values - \settbltag\maximumrow\currentcol\tblcell - \settblcol\maximumrow\currentcol\tblnx - \settblrow\maximumrow\currentcol\tblny - % save text - \edef\celltag{{\maximumrow}{\currentcol}}% - \@EA\settbltxt\@EA\maximumrow\@EA\currentcol\@EA - {\@EA\handleTBLcell\celltag[#1]{#3}}} + \maximumcol\col + \fi} %D The usage of n and m: %D @@ -580,9 +639,9 @@ \let\pushTBL\relax \let\popTBL \relax -\chardef\TBLpass=0 +\chardef\tblpass=0 -\def\presetallTABLEparameters% each odd|even level +\def\presetallTABLEparameters% each odd|even level / can be sped up but only once per table {\executeifdefined{\@@rawtblprefix\v!start\v!each}\relax \executeifdefined{\@@rawtblprefix\v!start\v!oddeven\TBLlevel}\relax \executeifdefined{\@@rawtblprefix\v!start\number\TBLlevel}\relax} @@ -594,10 +653,10 @@ {\pushTBL % box not here \bgroup -\TBLhead\emptytoks -\TBLnext\emptytoks -\TBLbody\emptytoks -\TBLfoot\emptytoks + \TBLhead\emptytoks + \TBLnext\emptytoks + \TBLbody\emptytoks + \TBLfoot\emptytoks \ifhmode\kern\zeropoint\fi % blocks \removeunwantedspaces: check this on icare handelingsschema \resetcharacteralign % new \getparameters @@ -612,14 +671,6 @@ \processaction [\tbltblheader] [\v!repeat=>\multipleTBLheadstrue]% -% \ifnum\TBLlevel>\plusone -% \vbox -% \else\ifenableTBLbreak -% % no \vbox -% \else -% \vbox -% \fi\fi -% \bgroup \localcolortrue \presetallTABLEparameters \ExpandFirstAfter\processallactionsinset @@ -627,10 +678,10 @@ [\v!stretch=>\autoTBLspreadtrue]% \linewidth\tbltblrulethickness % needs to be frozen \dontcomplain - \let\currentcol\!!zerocount - \let\maximumrowspan\!!plusone - \let\maximumcol\currentcol - \let\maximumrow\currentcol + \currentcol\zerocount + \maximumrowspan\plusone + \maximumcol\zerocount + \maximumrow\zerocount \def\bTR{\dodoubleempty\parseTR}% \def\bTD{\dodoubleempty\parseTD}% \def\bTH{\dodoubleempty\parseTH}% @@ -645,84 +696,79 @@ \def\eTABLE % beware, we need to get rid of spurious spaces when in hmode {% tricky and dirty order -) - \doifsometokselse\TBLhead + \doifsometokselse\TBLhead % slow, better a flag {\the\TBLhead \edef\noftblheadlines{\number\maximumrow}% \doifsometokselse\TBLnext {\the\TBLnext - \scratchcounter\maximumrow \advance\scratchcounter-\noftblheadlines - \edef\noftblnextlines{\number\scratchcounter}}% - {\let\noftblnextlines\!!zerocount}% was 1 + \edef\noftblnextlines{\number\numexpr\maximumrow-\noftblheadlines\relax}}% + {\let\noftblnextlines\zerocount}% was 1 \edef\noftblhdnxlines{\number\maximumrow}} - {\let\noftblheadlines\!!zerocount % was 1 - \let\noftblnextlines\!!zerocount - \let\noftblhdnxlines\!!zerocount}% + {\let\noftblheadlines\zerocount % was 1 + \let\noftblnextlines\zerocount + \let\noftblhdnxlines\zerocount}% \the\TBLbody \the\TBLfoot \removeunwantedspaces % only if hmode % finish cells \dorecurse\maximumrow - {\let\row\recurselevel + {\row\recurselevel\relax \dorecurse\maximumcol - {\let\col\recurselevel \let\xxcol\col \let\xxrow\row + {\col\recurselevel\relax \doifnottbltag\row\col - {\let\xrow\row + {\xxcol\col + \xxrow\row + \xrow\row \doloop - {\let\xcol\col + {\xcol\col \doloop - {\doifelsetbltag\xrow\xcol - {\exitloop} - {\increment\xcol \relax + {\doifelsetbltag\xrow\xcol \exitloop + {\advance\xcol\plusone \ifnum\xcol>\maximumcol\relax \exitloop \fi}}% - \doifelsetbltag\xrow\xcol - {\exitloop} - {\let\xxrow\xrow \let\xxcol\xcol \increment\xrow \relax - \ifnum\xrow>\maximumrow \exitloop \fi}}}% - \ifnum\xxrow>\maximumrow\let\xxrow\maximumrow\fi - \ifnum\xxcol>\maximumcol\let\xxcol\maximumcol\fi - \decrement(\xxrow,\row)\increment\xxrow - \decrement(\xxcol,\col)\increment\xxcol - \doifnottbltag\row\col - {\let\xrow\row - \dorecurse\xxrow - {\let\xcol\col \settblcol\xrow\xcol\xxcol + \doifelsetbltag\xrow\xcol \exitloop + {\xxrow\xrow \xxcol\xcol \advance\xrow\plusone + \ifnum\xrow>\maximumrow \exitloop \fi}}% + \ifnum\xxrow>\maximumrow\xxrow\maximumrow\fi + \ifnum\xxcol>\maximumcol\xxcol\maximumcol\fi + \xxrow\numexpr\xxrow-\row+\plusone\relax + \xxcol\numexpr\xxcol-\col+\plusone\relax + \xrow\row + \dorecurse\xxrow + {\xcol\col \settblcol\xrow\xcol{\number\xxcol}% \dorecurse\xxcol - {\settbltag\xrow\xcol\tblnone \increment\xcol}% - \increment\xrow}% - \settbltag\row\col\tblcell - \settblcol\row\col\xxcol - \settblrow\row\col\xxrow + {\lettbltag\xrow\xcol\tblnone \advance\xcol\plusone}% + \advance\xrow\plusone}% + \lettbltag\row\col\tblcell + \settblcol\row\col{\the\xxcol}% + \settblrow\row\col{\the\xxrow}% \ifautoTBLemptycell - \edef\celltag{{\row}{\col}}% - \@EA\settbltxt\@EA\row\@EA\col\@EA - {\@EA\handleTBLcell\celltag[]{\strut}}% + \edef\celltag{{\number\row}{\number\col}}% + \@EA\settbltxt\@EA\row\@EA\col\@EA{\@EA\handleTBLcell\celltag[]{\strut}}% \fi}}}% % to be sure \dorecurse\maximumrow - {\let\row\recurselevel + {\row\recurselevel\relax \dorecurse\maximumcol - {\let\col\recurselevel + {\col\recurselevel\relax \doiftblrow\row\col - {\scratchcounter\maximumrow - \advance\scratchcounter -\row - \advance\scratchcounter \plusone + {\scratchcounter\numexpr\maximumrow-\row+\plusone\relax \ifnum\gettblrow\row\col>\scratchcounter \settblrow\row\col{\the\scratchcounter}% \fi}% - \settblht\row\col\!!zeropoint - \settblwd\row\col\!!zeropoint - \doifnottblcol\row\col{\settblcol\row\col\!!zerocount}% - \doifnottbltag\row\col{\settbltag\row\col\tblnone}}}% + \lettblht\row\col\zeropoint + \lettblwd\row\col\zeropoint + \doifnottblcol\row\col{\lettblcol\row\col\zerocount}% + \doifnottbltag\row\col{\lettbltag\row\col\tblnone}}}% % check and do \ifcase\maximumcol\else \startTBLprocessing \begTBL \dorecurse\maximumrow {\bTBL - \let\row\recurselevel + \row\recurselevel\relax \dorecurse\maximumcol - {\let\col\recurselevel - \expanded{\doTBL{\row}{\col}}}% + {\col\recurselevel\relax + \expanded{\doTBL{\number\row}{\number\col}}}% \eTBL}% \removeunwantedspaces % only if hmode \endTBL @@ -738,88 +784,81 @@ \let\startTBLprocessing\relax \let\stopTBLprocessing \relax -% \def\processTBL -% {\begTBL -% \dorecurse\maximumrow -% {\bTBL -% \let\row\recurselevel -% \dorecurse\maximumcol -% {\let\col\recurselevel -% \expanded{\doTBL{\row}{\col}}}% -% \eTBL}% -% \removeunwantedspaces % only if hmode -% \endTBL} +\newcount\prelocatedTBLrows % \prelocateTBLrows{1000} may speed up large tables -\def\spanTBL#1#2% - {\scratchcounter\gettblcol{#1}{#2}\relax - \ifnum\scratchcounter>\zerocount - \advance\scratchcounter \minusone - \dorecurse\scratchcounter{\appendtoks\spantblcol\to\tbltoks}% - \dorecurse\scratchcounter{\appendtoks\skiptblcol\to\tbltoks}% - \appendtoks\nexttblcol\to\tbltoks - \fi} +\def\bTBL{\tblrowtoks\emptytoks} +\def\eTBL{\tbltoks\@EA\@EA\@EA{\@EA\the\@EA\tbltoks\@EA\begintblrow\the\tblrowtoks\endtblrow}}% -\def\bTBL{\appendtoks\begintblrow\to\tbltoks} -\def\eTBL{\appendtoks\endtblrow \to\tbltoks} +\def\prelocateTBLerror + {\writestatus\m!systems{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \number\prelocatedTBLrows)}} + +\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway + {\dostepwiserecurse\prelocatedTBLrows{#1}\plusone{\expandafter\newtoks\csname tbl:\recurselevel\endcsname}% + \def\bTBL + {\ifnum\tblrow<\prelocatedTBLrows\relax + \@EA\let\@EA\tblrowtoks\csname tbl:\the\tblrow\endcsname\tblrowtoks\emptytoks + \else + \prelocateTBLerror + \fi}% + \def\eTBL + {\tbltoks\@EA\@EA\@EA{\@EA\the\@EA\tbltoks\@EA\begintblrow\@EA\the\csname tbl:\the\tblrow\endcsname\endtblrow}}% + \global\prelocatedTBLrows#1\relax} + +% \prelocateTBLrows{1000} % may speed up large tables % We use aligments to handle the empty (skipped) columns, so % that we don't have to (re|)|calculate these. \def\skiptblcol - {\doglobal\increment\colTBL} + {\global\advance\tblcol\plusone} \def\nexttblcol - {\doglobal\increment\colTBL + {\global\advance\tblcol\plusone \kern\tbltblcolumndistance &} \def\spantblcol {\span} -\newcounter\rowTBL -\newcounter\colTBL -\newcounter\spnTBL +\newcount\tblrow +\newcount\tblcol + +\let\savedtblrow\!!zerocount +\let\savedtblcol\!!zerocount \def\begintblrow {\noalign - {\doglobal\increment \rowTBL - \doglobal\newcounter\spnTBL - \doglobal\newcounter\colTBL}% + {\global\advance\tblrow\plusone + \global\tblcol\zerocount + \global\tblspn\zerocount}% \nexttblcol - \kern\tbltblleftmargindistance - \kern-\tbltblcolumndistance} + \kern\dimexpr\tbltblleftmargindistance-\tbltblcolumndistance\relax} \def\endtblrow - {\kern-\tbltblcolumndistance - \kern\tbltblrightmargindistance + {\kern\dimexpr\tbltblrightmargindistance-\tbltblcolumndistance\relax \crcr \noalign {\nointerlineskip - \allowbreak + \ifnum\gettblnob\tblrow=\zerocount + \allowbreak + \fi \bgroup % protect local vars \@@tblsplitafter \egroup \bgroup % protect local vars - \increment\rowTBL\relax - \ifnum\rowTBL>\noftblhdnxlines\relax - \ifnum\rowTBL<\maximumrow\relax + \scratchcounter\numexpr\tblrow+\plusone\relax + \ifnum\scratchcounter>\noftblhdnxlines\relax + \ifnum\scratchcounter<\maximumrow\relax \doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}% \fi \fi \egroup}} -%\def\begintbl -% {\doglobal\newcounter\colTBL -% \doglobal\newcounter\rowTBL -% \doglobal\decrement\rowTBL -% \tabskip\zeropoint -% \halign\bgroup\ignorespaces##\unskip&&\ignorespaces##\unskip\cr} - \def\begintbl - {\doglobal\newcounter\colTBL - \doglobal\newcounter\rowTBL - \doglobal\newcounter\spnTBL - \doglobal\decrement\rowTBL + {\global\tblspn\zerocount + \global\tblcol\zerocount + \global\tblrow\zerocount + \global\advance\tblrow\minusone \tabskip\zeropoint \halign\bgroup \registerparoptions % new @@ -832,72 +871,134 @@ {\spanTBL{#1}{#2}} \setvalue{\tblcell TBL}#1#2% - {\appendtoks - \makeTBL{#1}{#2}% % append nog isoleren - \to\tbltoks + {\tblrowtoks\expandafter{\the\tblrowtoks\makeTBL #1 #2 }% space delimited -> less tokens \spanTBL{#1}{#2}} +\def\spanTBL#1#2% + {\scratchcounter\gettblcol{#1}{#2}\relax + \ifnum\scratchcounter>\zerocount + \advance\scratchcounter \minusone + \dorecurse\scratchcounter{\tblrowtoks\expandafter{\the\tblrowtoks\spantblcol}}% + \dorecurse\scratchcounter{\tblrowtoks\expandafter{\the\tblrowtoks\skiptblcol}}% + \tblrowtoks\expandafter{\the\tblrowtoks\nexttblcol}% + \fi} + \def\doTBL#1#2% - {\getvalue{\gettbltag{#1}{#2}TBL}{#1}{#2}} + {\csname\gettbltag{#1}{#2}TBL\endcsname{#1}{#2}} \def\begTBL - {\doglobal\newcounter\rowTBL - \doglobal\newcounter\colTBL - \doglobal\newcounter\spnTBL - \chardef\TBLpass\zerocount - \tbltoks\emptytoks - \appendtoks - \begintbl - \to\tbltoks} + {\global\tblspn\zerocount + \global\tblrow\zerocount + \global\tblcol\zerocount + \chardef\tblpass\zerocount + \tbltoks\emptytoks} + +\def\flushtbltoks{\begintbl\the\tbltoks\endtbl} + +\def\domakeTBLone#1 #2 % + {\gettbltxt{#1}{#2}}% + +\def\domakeTBLtwo#1 #2 % meer in cellD + {\scratchdimen\zeropoint + \scratchcounter\tblcol + \!!counta\gettblcol{#1}{#2}\relax + \dorecurse\!!counta + {\advance\scratchdimen\dimexpr\gettblwid\scratchcounter+\tbltblcolumndistance\relax + \ifnum\recurselevel<\!!counta \advance\scratchdimen \gettbldis\scratchcounter\fi + \advance\scratchcounter\plusone}% + \edef\widthTBL{\the\dimexpr\scratchdimen-\tbltblcolumndistance\relax}% + \setbox\scratchbox\hbox{\gettbltxt{#1}{#2}}% + \settblht{#1}{#2}{\the\ht\scratchbox}% + \settblwd{#1}{#2}{\the\wd\scratchbox}% + \ifdim\ht\scratchbox>\gettblhei{#1}\relax + \settblhei{#1}{\the\ht\scratchbox}% + \fi}% + +\def\domakeTBLthree#1 #2 % + {% height + \!!counta \gettblcol{#1}{#2}\relax + \!!countb \gettblrow{#1}{#2}\relax + \!!heighta\gettblht {#1}{#2}\relax + \scratchdimen\zeropoint + \ifnum\!!counta=\maximumcol\relax + % case: nc=maxcolumns + \else + \scratchcounter#1\relax + \dorecurse\!!countb + {\advance\scratchdimen + \gettblhei\scratchcounter + \advance\scratchcounter\plusone}% + \ifdim\scratchdimen<\!!heighta\relax + \scratchdimen\!!heighta + \fi + \fi + \edef\heightTBL{\the\scratchdimen}% + % width + \scratchdimen\zeropoint + \scratchcounter\tblcol + \dorecurse\!!counta + {\advance\scratchdimen\dimexpr\gettblwid\scratchcounter+\tbltblcolumndistance\relax + \ifnum\recurselevel<\!!counta \advance\scratchdimen \gettbldis\scratchcounter\fi + \advance\scratchcounter\plusone}% + \edef\widthTBL{\the\dimexpr\scratchdimen-\tbltblcolumndistance\relax}% + % cell + \setbox\scratchbox\hbox{\gettbltxt{#1}{#2}}% + \ifnum\!!counta=\maximumcol\relax + % case: nc=maxcolumns + \else + \scratchdimen\gettblhei{#1}% + \setbox\scratchbox\hbox + {\lower\ht\scratchbox\hbox{\raise\scratchdimen\box\scratchbox}}% + \ht\scratchbox\scratchdimen + \fi + \dp\scratchbox\zeropoint + \box\scratchbox} + +\def\inTBLcell#1#2% hm, do we need #1 #2 ? we use tblcol anyway + {\ExpandBothAfter\doifinsetelse\localwidth{\v!fit,\v!broad} % user set + {} + {\scratchdimen\gettblaut\tblcol\relax + \ifdim\localwidth>\scratchdimen + \settblaut\tblcol{\the\dimexpr\localwidth\relax}% + \fi}}% \def\endTBL - {\appendtoks - \endtbl - \to\tbltoks - \setbox\scratchbox\hbox + {\setbox\scratchbox\hbox {\localframed [\@@tbl\@@tbl] [\c!frame=\v!off,\c!background=,\c!align=\v!no] {\strut}}% \edef\minimalcellheight{\the\ht\scratchbox}% \dorecurse\maximumcol - {\settblaut\recurselevel\!!zeropoint % \zeropoint etc + {\lettblaut\recurselevel\zeropoint % new - \let\xcol\recurselevel + \xcol\recurselevel\relax \dorecurse\maximumrow - {\settblwd \recurselevel\xcol\!!zeropoint - \settblht \recurselevel\xcol\!!zeropoint}% + {\lettblwd\recurselevel\xcol\zeropoint + \lettblht\recurselevel\xcol\zeropoint}% % till here - \settblwid\recurselevel\!!zeropoint - \settbldis\recurselevel\!!zeropoint}% + \lettblwid\recurselevel\zeropoint + \lettbldis\recurselevel\zeropoint}% \dorecurse\maximumrow - {\settblhei\recurselevel\maxdimen}% - \chardef\TBLpass\plusone + {\lettblhei\recurselevel\maxdimen}% + \chardef\tblpass\plusone + \let\makeTBL\domakeTBLone \let\handleTBLcell\dohandleTBLcellA - \def\makeTBL##1##2% - {\gettbltxt{##1}{##2}}% - \def\inTBLcell##1##2% - {\ExpandBothAfter\doifinsetelse\localwidth{\v!fit,\v!broad} % user set - {} - {\scratchdimen\gettblaut\colTBL\relax - \ifdim\localwidth>\scratchdimen - \settblaut\colTBL\localwidth - \fi}}% - \setbox0\vbox{\trialtypesettingtrue \the\tbltoks}% -\settbldis\maximumcol{\zeropoint}% + \setbox0\vbox{\trialtypesettingtrue \flushtbltoks}% + \lettbldis\maximumcol\zeropoint \ifautoTBLspread % experimental, stretch non fixed cells to \hsize \checktblwidthsone % trial run \checktblwidthstwo % real run \stretchtblwidths \let\handleTBLcell\dohandleTBLcellB - \setbox\scratchbox\vbox{\trialtypesettingtrue \the\tbltoks}% + \setbox\scratchbox\vbox{\trialtypesettingtrue \flushtbltoks}% \else\ifdim\wd0>\hsize \ifautoTBLhsize \checktblwidthsone % trial run \checktblwidthstwo % real run \let\handleTBLcell\dohandleTBLcellB - \setbox\scratchbox\vbox{\trialtypesettingtrue \the\tbltoks}% + \setbox\scratchbox\vbox{\trialtypesettingtrue \flushtbltoks}% \fi \else\ifautoTBLrowspan\ifnum\maximumrowspan>1 % max ? % added jan 2002 because nx=* did no longer work @@ -908,101 +1009,40 @@ \hsize\savedhsize % \let\handleTBLcell\dohandleTBLcellC - \setbox\scratchbox\vbox{\trialtypesettingtrue \the\tbltoks}% + \setbox\scratchbox\vbox{\trialtypesettingtrue \flushtbltoks}% \fi\fi\fi\fi \let\handleTBLcell\dohandleTBLcellD - \chardef\TBLpass\plustwo - \def\makeTBL##1##2% meer in cellD - {\dimen2\zeropoint - \globalpushmacro\colTBL - \dorecurse{\gettblcol{##1}{##2}} - {\advance\dimen2 \gettblwid\colTBL - \advance\dimen2 \tbltblcolumndistance - \ifnum\recurselevel<\gettblcol{##1}{##2}\relax \advance\dimen2 \gettbldis\colTBL\fi - \increment\colTBL}% - \advance\dimen2 -\tbltblcolumndistance - \edef\widthTBL{\the\dimen2}% - \globalpopmacro\colTBL - \setbox\scratchbox\hbox{\gettbltxt{##1}{##2}}% - \settblht{##1}{##2}{\the\ht\scratchbox}% - \settblwd{##1}{##2}{\the\wd\scratchbox}% - \ifdim\ht\scratchbox>\gettblhei{##1}\relax - \settblhei{##1}{\the\ht\scratchbox}% - \fi}% - \setbox\scratchbox\vbox{\trialtypesettingtrue \the\tbltoks}% + \chardef\tblpass\plustwo + \let\makeTBL\domakeTBLtwo + \setbox\scratchbox\vbox{\trialtypesettingtrue \flushtbltoks}% \checktblheightsone \checktblheightstwo \let\handleTBLcell\dohandleTBLcellE - \chardef\TBLpass\plusthree - \def\makeTBL##1##2% - {% height - \globalpushmacro\rowTBL - \scratchdimen\zeropoint - \def\rowTBL{##1}% - \ifnum\gettblcol{##1}{##2}=\maximumcol\relax - % case: nc=maxcolumns - \else - \dorecurse{\gettblrow{##1}{##2}} - {\advance\scratchdimen \gettblhei\rowTBL - \increment\rowTBL}% - \ifdim\scratchdimen<\gettblht{##1}{##2}\relax - \scratchdimen\gettblht{##1}{##2}\relax - \fi - \fi - \edef\heightTBL{\the\scratchdimen}% - \globalpopmacro\rowTBL - % width - \globalpushmacro\colTBL - \scratchdimen\zeropoint - \dorecurse{\gettblcol{##1}{##2}} - {\advance\scratchdimen \gettblwid\colTBL - \advance\scratchdimen \tbltblcolumndistance -\ifnum\recurselevel<\gettblcol{##1}{##2}\relax \advance\scratchdimen \gettbldis\colTBL\fi - \increment\colTBL}% - \advance\scratchdimen -\tbltblcolumndistance - \edef\widthTBL{\the\scratchdimen}% - \globalpopmacro\colTBL - % cell - \setbox\scratchbox\hbox{\gettbltxt{##1}{##2}}% - \ifnum\gettblcol{##1}{##2}=\maximumcol\relax - % case: nc=maxcolumns - \else - \scratchdimen\gettblhei{##1}% - \setbox\scratchbox\hbox - {\lower\ht\scratchbox\hbox{\raise\scratchdimen\box\scratchbox}}% - \ht\scratchbox\scratchdimen - \fi - \dp\scratchbox\zeropoint - \box\scratchbox}% - \iftraceTABLE\showtbltoks\fi + \chardef\tblpass\plusthree + \let\makeTBL\domakeTBLthree \ifnum\TBLlevel>\plusone \@EA\notsplittblbox \else\ifenableTBLbreak \@EAEAEA\splittblbox \else \@EAEAEA\notsplittblbox - \fi\fi{\the\tbltoks}} + \fi\fi{\flushtbltoks}} \def\stretchtblwidths {\ifcase\maximumcol\else % else division by zero \!!dimend\zeropoint \!!dimene\hsize \dorecurse\maximumcol - {\advance\!!dimend \gettblwid\recurselevel - \advance\!!dimend \tbltblcolumndistance + {\advance\!!dimend\dimexpr\gettblwid\recurselevel+\tbltblcolumndistance\relax \advance\!!dimene-\gettbldis\recurselevel}% - \advance\!!dimend-\tbltblcolumndistance - \advance\!!dimend\tbltblleftmargindistance - \advance\!!dimend\tbltblrightmargindistance + \advance\!!dimend\dimexpr-\tbltblcolumndistance+\tbltblleftmargindistance+\tbltblrightmargindistance\relax % distribute width (stretch) \ifdim\!!dimend<\!!dimene \advance\!!dimend-\!!dimene \!!dimend-\!!dimend \divide\!!dimend\maximumcol \dorecurse\maximumcol - {\scratchdimen\gettblwid\recurselevel - \advance\scratchdimen\!!dimend - \settblwid\recurselevel{\the\scratchdimen}}% + {\settblwid\recurselevel{\the\dimexpr\gettblwid\recurselevel+\!!dimend\relax}}% \fi \fi} @@ -1015,13 +1055,6 @@ \box\finaltblbox \afterTABLEbox} -% \def\splittblbox#1% -% {\ifinsidefloat -% \notsplittblbox{#1}% -% \else -% \executeifdefined{splittblbox\tbltblsplitmethod}\splittblboxa{#1}% -% \fi} - \def\splittblbox#1% {\ifinsidesplitfloat \donetrue @@ -1040,181 +1073,6 @@ \let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox -% todo: mode: first|next (of niets) - -% \def\dosplittblboxa#1% spacing between rows gets lost in split -% {\setbox\TABLEsplitbox\vbox{#1}% -% \setbox8\vbox{\doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}}% -% \ifmultipleTBLheads -% \setbox2\vbox{}% -% \setbox4\vbox{}% -% \dorecurse\noftblheadlines -% {\setbox0\vsplit\TABLEsplitbox to \lineheight -% \setbox2\vbox{\unvcopy2\unvcopy0}}% -% \dorecurse\noftblnextlines -% {\setbox0\vsplit\TABLEsplitbox to \lineheight -% \setbox4\vbox{\unvcopy4\unvcopy0}}% -% \ifcase\noftblheadlines\else -% \ifdim\pagegoal<\maxdimen -% \dimen0\ht2 -% \advance\dimen0\ht8 -% \advance\dimen0\pagetotal\relax -% \ifdim\dimen0>\pagegoal -% \bgroup\page\egroup % make sure that local vars are kept -% \fi -% \fi -% \unvcopy2 -% \ifcase\noftblnextlines\else -% \setbox2\box4 -% \fi -% \fi -% \fi -% \donefalse -% \!!doneafalse -% \doloop -% {\setbox0\vsplit\TABLEsplitbox to \lineheight -% \if!!donea -% \ifdim\pagegoal<\maxdimen -% \setbox0\vbox{\unvbox0}% -% \ifdim\ht0>\zeropoint -% \dimen0\ht0 -% \advance\dimen0\ht8 -% \advance\dimen0\pagetotal\relax -% \ifdim\dimen0>\pagegoal -% \bgroup\page\egroup % make sure that local vars are kept -% \ifmultipleTBLheads -% \ifcase\noftblheadlines\else\unvcopy2\fi -% \fi -% \fi -% \fi -% \fi -% \fi -% \!!doneatrue -% \ifdone -% \doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}% -% \fi -% \unvbox0 -% %\allowbreak -% \bgroup -% % todo: what if tblnextlines ? -% \scratchcounter\recurselevel -% \ifmultipleTBLheads -% \advance\scratchcounter\noftblheadlines -% \fi -% \setupTBLcell{\number\scratchcounter}1 -% \ifx\@@tblsplitafter\relax -% \allowbreak -% \else -% \doifelsenothing\@@tblsplitafter -% \allowbreak -% {\scratchcounter\realpageno -% \@@tblsplitafter -% \ifmultipleTBLheads -% \ifnum\scratchcounter<\realpageno -% \ifcase\noftblheadlines\else\unvcopy2\fi -% \fi -% \fi}% -% \fi -% \egroup -% \ifvoid\TABLEsplitbox \exitloop \else \donetrue \fi}} - -% \def\dosplittblboxb#1% -% {\scratchdimen-\extratblsplitheight -% \advance\scratchdimen-\tbltblsplitoffset -% \expanded{\testpage[2][\the\scratchdimen]}% quite save since a row is > 1 lineheight and we don't want one-liners -% \setbox\TABLEsplitbox\vbox{#1}% -% \setbox8\vbox{\doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}}% -% \dimen8\ht8\advance\dimen8\dp8 -% \ifmultipleTBLheads -% \setbox2\vbox{}% -% \setbox4\vbox{}% -% \dorecurse\noftblheadlines -% {\setbox0\vsplit\TABLEsplitbox to \lineheight -% \setbox2\vbox{\unvcopy2\unvcopy0}}% -% \dorecurse\noftblnextlines -% {\setbox0\vsplit\TABLEsplitbox to \lineheight -% \setbox4\vbox{\unvcopy4\unvcopy0}}% -% \fi -% \!!doneafalse -% \doloop -% {\ifdim\pagegoal<\maxdimen -% \scratchdimen\pagegoal -% \advance\scratchdimen-\pagetotal -% \!!donecfalse -% \else -% \scratchdimen\textheight -% \!!donectrue -% \fi -% \advance\scratchdimen-\dimen8 -% \advance\scratchdimen-\extratblsplitheight -% \advance\scratchdimen-\tbltblsplitoffset -% \setbox\finaltblbox\vbox -% {\ifmultipleTBLheads -% \ifcase\noftblheadlines\else -% \unvcopy2 \doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}% -% \fi -% \fi}% -% \if!!donea\else\ifcase\noftblnextlines\else -% \setbox2\box4 -% \fi\fi -% \!!doneatrue -% % alternatively we could use a kind of balancing like splitter -% % first to scratchdimen and then smaller etc; more code and copy -) -% \!!counta\zerocount -% \doloop -% {\setbox\scratchbox\vsplit\TABLEsplitbox to \onepoint -% \setbox\scratchbox\vbox{\unvbox\scratchbox}% -% \bgroup -% \advance\scratchdimen-\ht\scratchbox -% \advance\scratchdimen-\dp\scratchbox -% \advance\scratchdimen-\ht\finaltblbox -% \advance\scratchdimen-\dp\finaltblbox\relax -% \ifdim\scratchdimen>\zeropoint -% \egroup -% \setbox\finaltblbox\vbox -% {\unvbox\finaltblbox -% \unvbox\scratchbox}% -% \ifvoid\TABLEsplitbox \exitloop \fi -% \else\if!!donec -% % we have text height available, but the (one) cell is too -% % large to fit, so, in order to avoid loops/deadcycles we do: -% \egroup -% \setbox\finaltblbox\vbox -% {\unvbox\finaltblbox -% \unvbox\scratchbox}% -% \exitloop -% \else -% \egroup -% \setbox\TABLEsplitbox\vbox -% {\unvbox\scratchbox -% \ifvoid\TABLEsplitbox\else\unvbox\TABLEsplitbox\allowbreak\fi}% -% \exitloop -% \fi\fi}% -% % -% \postprocessTABLEsplitbox\finaltblbox -% \ifvoid\TABLEsplitbox -% \beforeTABLEsplitbox -% \box\finaltblbox -% \afterTABLEsplitbox -% \@@tblsplitafter -% \exitloop -% \else -% % hack -% \ifdim\pagegoal<\maxdimen -% \scratchdimen\pagegoal -% \advance\scratchdimen \lineheight -% \global\pagegoal\scratchdimen -% \fi -% % brrr -% \ifdim\ht\finaltblbox>\zeropoint -% \beforeTABLEsplitbox -% \box\finaltblbox -% \afterTABLEsplitbox -% \@@tblsplitafter -% \fi -% \page -% \fi}} - \def\dosplittblbox#1% {\resettsplit \def\tsplitminimumfreelines{2}% @@ -1222,7 +1080,7 @@ \def\tsplitbeforeresult {\beforeTABLEsplitbox}% \def\tsplitafterresult {\afterTABLEsplitbox}% \def\tsplitafter {\@@tblsplitafter}% - \setbox\tsplitcontent\vbox{#1}% \the\tbltoks + \setbox\tsplitcontent\vbox{#1}% \ifmultipleTBLheads \dorecurse\noftblheadlines {\setbox\scratchbox\vsplit\tsplitcontent to \lineheight @@ -1251,22 +1109,17 @@ \def\dochecktblwidths#1% {\iftraceTABLE\showtblwids{B#1}\fi - \!!dimena\hsize \!!counta\zerocount -% test, dunno yet -\advance\!!dimena-\tbltblleftmargindistance -\advance\!!dimena-\tbltblrightmargindistance -\advance\!!dimena-\tbltblcolumndistance + \!!dimena\dimexpr\hsize-\tbltblleftmargindistance-\tbltblrightmargindistance-\tbltblcolumndistance\relax \dorecurse\maximumcol {\scratchdimen\gettblaut\recurselevel\relax -% test, seems to work ok -\advance\!!dimena-\gettbldis\recurselevel\relax + \advance\!!dimena-\gettbldis\recurselevel\relax \ifdim\scratchdimen>\zeropoint\relax \advance\!!dimena -\scratchdimen \else \scratchdimen\gettblwid\recurselevel\relax \ifdim\scratchdimen>\tbltblmaxwidth\relax - \ifcase#1\else\settblwid\recurselevel\!!zeropoint\fi + \ifcase#1\else\lettblwid\recurselevel\zeropoint\fi \advance\!!counta \plusone \else \ifdim\scratchdimen>\zeropoint\relax @@ -1292,57 +1145,72 @@ \fi}% \iftraceTABLE\showtblwids{E#1}\fi} +\newcount\xrowTBL +\newcount\xcolTBL +\newcount\xxrowTBL + +% dikke arg naar recurse wegwerken + +\def\dochecktblheightsone + {\!!countb\gettblrow\xrowTBL\xcolTBL\relax + % check row span + \ifnum\!!countb>\plusone + % current height in row + \dimen0=\gettblht\xrowTBL\xcolTBL + % find nearest height in row + \dimen2=\zeropoint + \dorecurse\maximumcol + {\ifnum\recurselevel=\xcolTBL\else + \doiftblrow\xrowTBL\recurselevel + {\!!countc=\gettblrow\xrowTBL\recurselevel\relax + \ifnum\!!countc=\plusone + \dimen4=\gettblht\xrowTBL\recurselevel\relax + \ifdim\dimen2<\dimen4 + \dimen2=\dimen4 + \fi + \fi}% + \fi}% + \xxrowTBL\xrowTBL + % calculate cummulative height + \dimen4=\dimen2 + \!!countc\xrowTBL + \advance\!!countc\minusone + \dorecurse\!!countb + {\ifnum\xxrowTBL=\xrowTBL\else + \advance\dimen4 \gettblhei\xxrowTBL + \fi + \ifnum\recurselevel=\!!countb\else + \settblnob\!!countc + \advance\!!countc\plusone + \fi + \advance\xxrowTBL\plusone}% + % distribute overshoot equally + \ifdim\dimen4<\dimen0 + \advance\dimen0 -\dimen4 + \divide\dimen0 \!!countb + \xxrowTBL\xrowTBL + \settblhei\xrowTBL{\the\dimen2}% + \dorecurse\!!countb + {\dorecurse\maximumcol + {\ifnum\recurselevel=\xcolTBL\else + \scratchdimen\dimexpr\gettblht\xxrowTBL\recurselevel+\dimen0\relax + \settblht\xxrowTBL\recurselevel{\the\scratchdimen}% + \ifdim\gettblhei\xxrowTBL<\scratchdimen + \settblhei\xxrowTBL{\the\scratchdimen}% + \fi + \fi}% + \advance\xxrowTBL\plusone}% + \else\ifdim\dimen4>\dimen0 + \settblhei\xrowTBL{\the\dimen2}% + \fi\fi + \fi} + \def\checktblheightsone {\dorecurse\maximumrow - {\let\xrowTBL\recurselevel + {\xrowTBL\recurselevel\relax \dorecurse\maximumcol - {\let\xcolTBL\recurselevel - \!!countb=0\gettblrow\xrowTBL\xcolTBL\relax - % check row span - \ifnum\!!countb>1 - % current height in row - \dimen0=\gettblht\xrowTBL\xcolTBL - % find nearest height in row - \dimen2=\zeropoint - \dorecurse\maximumcol - {\ifnum\recurselevel=\xcolTBL\else - \!!countc=0\gettblrow\xrowTBL\recurselevel\relax - \ifnum\!!countc=\plusone - \dimen4=\gettblht\xrowTBL\recurselevel\relax - \ifdim\dimen2<\dimen4 - \dimen2=\dimen4 - \fi - \fi - \fi}% - \let\xxrowTBL\xrowTBL - % calculate cummulative height - \dimen4=\dimen2 - \dorecurse\!!countb - {\ifnum\xxrowTBL=\xrowTBL\else - \advance\dimen4 \gettblhei\xxrowTBL - \fi - \increment\xxrowTBL}% - % distribute overshoot equally - \ifdim\dimen4<\dimen0 - \advance\dimen0 -\dimen4 - \divide\dimen0 \!!countb - \let\xxrowTBL\xrowTBL - \settblhei\xrowTBL{\the\dimen2}% - \dorecurse\!!countb - {\dorecurse\maximumcol - {\ifnum\recurselevel=\xcolTBL\else - \scratchdimen\gettblht\xxrowTBL\recurselevel - \advance\scratchdimen \dimen0 - \settblht\xxrowTBL\recurselevel{\the\scratchdimen}% - \ifdim\gettblhei\xxrowTBL<\scratchdimen - \settblhei\xxrowTBL{\the\scratchdimen}% - \fi - \fi}% - \increment\xxrowTBL}% - \else\ifdim\dimen4>\dimen0 - \settblhei\xrowTBL{\the\dimen2}% - \fi\fi - \fi}}} + {\xcolTBL\recurselevel\relax + \doiftblrow\xrowTBL\xcolTBL\dochecktblheightsone}}} \def\checktblheightstwo {} @@ -1350,18 +1218,9 @@ \def\showtblwids#1% {\vbox {\forgetall\tttf[#1]\dorecurse\maximumcol - {\scratchdimen\gettblwid\recurselevel + {\scratchdimen\gettblwid\recurselevel\relax [\recurselevel:\the\scratchdimen]}}} -\def\showtbltoks - {\vbox - {\forgetall\tttf - \let\begintbl \relax \let\endtbl \relax - \let\begintblrow\par \let\endtblrow \par - \def\nexttblcol {[next]}\def\spantblcol{[span]} - \def\makeTBL##1##2{[##1,##2]} - \the\tbltoks}} - \def\TBLcharalign {\doifelse\tbltblaligncharacter\v!yes \doTBLcharalign\gobbleoneargument} @@ -1369,7 +1228,7 @@ \long\def\doTBLcharalign#1#2% column data {\edef\alignmentclass{#1}% \edef\alignmentcharacter{\tbltblalignmentcharacter}% - \ifcase\TBLpass\or + \ifcase\tblpass\or \setfirstpasscharacteralign\checkalignment{#2}% {\strut#2\unskip}% \fi % force hsize, so always a second \setsecondpasscharacteralign \checkalignment{#2}% {\strut#2\unskip}% @@ -1389,7 +1248,7 @@ [\@@tbl\@@tbl] [#3,\c!background=,\c!frame=\v!off]% 25% faster {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL\inTBLcell{#1}{#2}}}% - \scratchdimen\gettblwid\colTBL\relax + \scratchdimen\gettblwid\tblcol\relax \ifdim\wd\scratchbox>\scratchdimen \ifsqueezeTBLspan \ifautosqueezeTBLspan @@ -1398,34 +1257,34 @@ \else \donetrue \fi - \ifdone - \ifnum0\number\gettblcol{#1}{#2}>1\relax \settblspn\colTBL \fi + \ifdone % brr, 0 + \ifnum\number\gettblcol{#1}{#2}>\plusone \settblspn\tblcol\fi \fi \fi - \doifelsetblspn\colTBL + \doifelsetblspn\tblcol \donothing - {\ifdim\gettblwid\colTBL<\wd\scratchbox - \settblwid\colTBL{\the\wd\scratchbox}% + {\ifdim\gettblwid\tblcol<\wd\scratchbox + \settblwid\tblcol{\the\wd\scratchbox}% \fi}% auto set \fi - \let\rowTBLx\rowTBL\increment\rowTBLx - \scratchdimen\gettblhei\rowTBLx\relax + \scratchcounter\numexpr\tblrow+\plusone\relax + \scratchdimen\gettblhei\scratchcounter\relax \ifdim\ht\scratchbox<\scratchdimen - \settblhei\rowTBLx{\the\ht\scratchbox}% auto set + \settblhei\scratchcounter{\the\ht\scratchbox}% auto set \fi \settblht{#1}{#2}{\the\ht\scratchbox}% \settblwd{#1}{#2}{\the\wd\scratchbox}% \ifautoTBLcheckwidth \ifdim\wd\scratchbox<.75\hsize \ifdim\ht\scratchbox>2\openlineheight % honor width since this - \scratchdimen\gettblaut\colTBL\relax % can be a figure or so + \scratchdimen\gettblaut\tblcol\relax % can be a figure or so \ifdim\scratchdimen=\zeropoint % side effect: when width is set to 0pt, % we can force a span that fits the sum of spans widths - \settblaut\colTBL{\the\scratchdimen}% + \settblaut\tblcol{\the\scratchdimen}% \else\ifdim\wd\scratchbox>\scratchdimen % unless span - \settblaut\colTBL{\the\wd\scratchbox}% + \settblaut\tblcol{\the\wd\scratchbox}% % to be translated \writestatus\m!TABLE {no auto width in (\number#1,\number#2)\space\the\wd\scratchbox/\the\hsize}% @@ -1448,28 +1307,32 @@ \setbox2\null \wd2\wd\scratchbox \ht2\ht\scratchbox \dp2\dp\scratchbox \ifautoTBLrowspan - \let\rowTBLx\rowTBL\increment\rowTBLx - \scratchdimen\gettblhei\rowTBLx\relax - \ifnum\gettblrow\rowTBLx\colTBL>1 \ifdim\ht\scratchbox>\scratchdimen - \scratchdimen-\scratchdimen \advance\scratchdimen -\ht\scratchbox - \ht2\scratchdimen - \fi \fi + \scratchcounter\numexpr\tblrow+\plusone\relax + \doiftblrow\scratchcounter\tblcol + {\scratchdimen\gettblhei\scratchcounter\relax % moved inside test + \ifnum\gettblrow\scratchcounter\tblcol>\plusone \ifdim\ht\scratchbox>\scratchdimen + \scratchdimen-\scratchdimen \advance\scratchdimen -\ht\scratchbox + \ht2\scratchdimen + \fi \fi}% \fi \box2 } \long\def\dohandleTBLcellB#1#2[#3]#4% - {\scratchdimen\gettblaut\colTBL\relax + {\scratchdimen\gettblaut\tblcol\relax \ifdim\scratchdimen>\zeropoint\relax - \let\tblwidthkey\c!width \edef\tblwidth{\the\scratchdimen}% + \let\tblwidthkey\c!width + \edef\tblwidth{\the\scratchdimen}% \else - \scratchdimen\gettblwid\colTBL\relax + \scratchdimen\gettblwid\tblcol\relax \ifdim\scratchdimen>\zeropoint\relax \ifnum\gettblcol{#1}{#2}=\maximumcol\relax \scratchdimen\hsize \fi - \let\tblwidthkey\c!width \edef\tblwidth{\the\scratchdimen}% + \let\tblwidthkey\c!width + \edef\tblwidth{\the\scratchdimen}% \else - \let\tblwidthkey\s!unknown \let \tblwidth \!!zeropoint + \let\tblwidthkey\s!unknown + \let\tblwidth\zeropoint \fi \fi \dohandleTBLcellBC{\tblwidthkey=\tblwidth}{#1}{#2}[#3]{\TBLcharalign{#2}{#4}}} @@ -1534,27 +1397,11 @@ %D We have already prepared the previous macros for nesting, %D so we only have to pop in the right ones: -%D Redefined: - -\newcounter\TBLlevel - -\def\@@tblprefix{\@@tbl:\ifnum\TBLlevel>1 :\TBLlevel:\fi} - -\long\def\settbltxt#1#2#3% - {\setxvalue{\@@tblprefix#1:#2:l}{\TBLlevel}% - \long\setvalue{\@@tblprefix#1:#2:t}% - {\doifdefined{\@@tblprefix#1:#2:l} - {\edef\TBLlevel{\getvalue{\@@tblprefix#1:#2:l}}}% - #3}} - -\def\gettbltxt#1#2% - {\getvalue{\@@tblprefix#1:#2:t}} - %D New: \def\pushTBLparameters {\globalpushmacro\TBLlevel - \ifcase\TBLpass + \ifcase\tblpass % we're just after \bTABLE \else\ifnum\TBLlevel>\zerocount \doglobal\increment\TBLlevel\relax @@ -1565,21 +1412,22 @@ \def\pushTBL {\ifnum\TBLlevel=\zerocount - \doglobal\increment\currenttbl\relax + \global\advance\currenttbl\plusone \fi \doglobal\increment\TBLlevel\relax \ifnum\TBLlevel>\plusone \resetallTABLEparameters - \globalpushmacro\colTBL - \globalpushmacro\rowTBL + % we need a proper count push/pop + \xdef\savedtblrow{\the\tblrow}\globalpushmacro\savedtblrow + \xdef\savedtblcol{\the\tblcol}\globalpushmacro\savedtblcol \else \global\intabletrue \fi} \def\popTBL {\ifnum\TBLlevel>\plusone - \globalpopmacro\rowTBL - \globalpopmacro\colTBL + \globalpopmacro\savedtblrow\global\tblrow\savedtblrow + \globalpopmacro\savedtblcol\global\tblcol\savedtblcol \else \global\intablefalse \fi @@ -1698,3 +1546,5 @@ {\bTR[]#2\eTR}} \protect \endinput + +% todo: mode: first|next (of niets) diff --git a/tex/context/base/core-spa.lua b/tex/context/base/core-spa.lua index 9b7486722..c6827e1c2 100644 --- a/tex/context/base/core-spa.lua +++ b/tex/context/base/core-spa.lua @@ -364,11 +364,13 @@ do local kern, prev = map.left, start.prev if kern and kern ~= 0 and prev and prev.id == glyph then node.insert_before(head,start,nodes.kern(tex.scale(fontids[start.font].parameters[6],kern))) + -- node.insert_before(head,start,nodes.kern(fontids[start.font].parameters[6]*kern)) done = true end local kern, next = map.right, start.next if kern and kern ~= 0 and next and next.id == glyph then node.insert_after(head,start,nodes.kern(tex.scale(fontids[start.font].parameters[6],kern))) + -- node.insert_after(head,start,nodes.kern(fontids[start.font].parameters[6]*kern)) done = true end end @@ -438,6 +440,7 @@ do elseif pid == kern and prev.subtype == 0 then prev.subtype = 1 prev.kern = prev.kern + scale(fontids[lastfont].parameters[6],krn) + -- prev.kern = prev.kern + fontids[lastfont].parameters[6]*krn done = true elseif pid == glyph then -- fontdata access can be done more efficient @@ -447,54 +450,18 @@ do local ickern = tfm.kerns if ickern and ickern[lastchar] then krn = scale(ickern[lastchar]+fontids[lastfont].parameters[6],krn) + -- krn = krn*(ickern[lastchar]+fontids[lastfont].parameters[6]) else krn = scale(fontids[lastfont].parameters[6],krn) + -- krn = krn*fontids[lastfont].parameters[6] end else krn = scale(fontids[lastfont].parameters[6],krn) + -- krn = krn*fontids[lastfont].parameters[6] end node.insert_before(head,start,nodes.kern(krn)) done = true elseif pid == disc then - -- probably wrong anyway - -- currently this hooks into the node handlere before - -- hyphenation takes place, but this may change - -- - -- local d = start.prev - -- local pre, post = d.pre, d.post - -- if pre then - -- local p = d.prev - -- local nn, pp = p.prev, p.next - -- p.prev, p.next = nil, pre -- hijack node - -- pre = kerns.process(namespace,attribute,p) - -- pre = pre.next - -- pre.prev = nil - -- p.prev, p.next = nn, pp - -- d.pre = pre - -- end - -- if post then -- more checks needed - -- local tail = node.slide(post) - -- local nn, pp = d.next.prev, d.next.next - -- d.next.next, d.next.prev = nil, tail - -- tail.next = start.next -- hijack node - -- post = kerns.process(namespace,attribute,post) - -- tail.next = nil - -- d.next.prev, d.next.next = nn, pp - -- d.post = post - -- end - -- local prevchar, nextchar = d.prev.char, d.next.char -- == start.char - -- local tfm = fti[lastfont].characters[prevchar] - -- local ickern = tfm.kerns - -- if ickern and ickern[nextchar] then - -- krn = scale(ickern[nextchar]+fontids[lastfont].parameters[6],krn) - -- else - -- krn = scale(fontids[lastfont].parameters[6],krn) - -- end - -- node.insert_before(head,start,nodes.kern(krn)) - -- d.replace = d.replace + 1 - -- - -- untested: - -- local disc = start.prev -- disc local pre, post, replace = disc.pre, disc.post, disc.replace if pre then -- must pair with start.prev @@ -545,22 +512,26 @@ do if w > 0 then local width, stretch, shrink = w+2*scale(w,krn), s.stretch, s.shrink start.spec = nodes.glue_spec(width,scale(stretch,width/w),scale(shrink,width/w)) - -- node.free(ss) + -- local width, stretch, shrink = w+2*w*krn, s.stretch, s.shrink + -- start.spec = nodes.glue_spec(width,stretch*width/w,shrink*width/w)) done = true end elseif false and id == kern and start.subtype == 0 then -- handle with glyphs local sk = start.kern if sk > 0 then - start.kern = scale(sk,krn) + -- start.kern = scale(sk,krn) + start.kern = sk*krn done = true end elseif lastfont and (id == hlist or id == vlist) then -- todo: lookahead if start.prev then node.insert_before(head,start,nodes.kern(scale(fontids[lastfont].parameters[6],krn))) + -- node.insert_before(head,start,nodes.kern(fontids[lastfont].parameters[6]*krn)) done = true end if start.next then node.insert_after(head,start,nodes.kern(scale(fontids[lastfont].parameters[6],krn))) + -- node.insert_after(head,start,nodes.kern(fontids[lastfont].parameters[6]*krn)) done = true end end diff --git a/tex/context/base/core-tsp.tex b/tex/context/base/core-tsp.tex index 5523c2ccd..806e45053 100644 --- a/tex/context/base/core-tsp.tex +++ b/tex/context/base/core-tsp.tex @@ -228,7 +228,7 @@ \def\handletsplit {\analyzesplitfloatcaption\tsplitcontent \global\setfalse\tsplitfirstdone - \testpage + \testpagesync % new, sync, but still tricky [\tsplitminimumfreelines] [\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]% \setbox\scratchbox\vbox{\tsplitinbetween}% diff --git a/tex/context/base/font-afm.lua b/tex/context/base/font-afm.lua index b8c2eea59..23cc7421e 100644 --- a/tex/context/base/font-afm.lua +++ b/tex/context/base/font-afm.lua @@ -19,7 +19,7 @@ away.</p> fonts = fonts or { } fonts.afm = fonts.afm or { } -fonts.afm.version = 1.21 -- incrementing this number one up will force a re-cache +fonts.afm.version = 1.22 -- incrementing this number one up will force a re-cache fonts.afm.syncspace = true -- when true, nicer stretch values fonts.afm.enhance_data = true -- best leave this set to true fonts.afm.trace_features = false @@ -124,7 +124,7 @@ do end chr.index = ind elseif k == 'WX' then - chr.wx = v + chr.width = v elseif k == 'N' then str = v elseif k == 'B' then @@ -304,9 +304,10 @@ function fonts.afm.add_ligatures(afmdata,ligatures) for _, b in pairs(v) do two, three = b[1], b[2] if two and three and chars[two] and chars[three] then - if one[ligatures] then - if not one.ligatures[two] then - one[ligatures][two] = three + local ol = one[ligatures] + if ol then + if not ol[two] then -- was one.ligatures ... bug + ol[two] = three end else one[ligatures] = { [two] = three } @@ -330,8 +331,9 @@ function fonts.afm.add_kerns(afmdata) if v.kerns then local k = { } for complex,simple in pairs(characters.uncomposed[what]) do - if k[simple] and not k[complex] then - k[complex] = k[simple] + local ks = k[simple] + if ks and not k[complex] then + k[complex] = ks end end if not table.is_empty(k) then @@ -363,7 +365,21 @@ end --ldx]]-- -- once we have otf sorted out (new format) we can try to make the afm --- cache similar to it +-- cache similar to it (similar tables) + +function fonts.afm.add_dimensions(data) -- we need to normalize afm to otf i.e. indexed table instead of name + if data then + for n, d in pairs(data.characters) do + local bb = d.boundingbox + if bb then + local ht, dp = bb[4], -bb[2] + if ht ~= 0 then d.height = ht end + if dp ~= 0 then d.depth = dp end + end + d.name = n + end + end +end function fonts.afm.copy_to_tfm(data) if data and data.characters then @@ -372,16 +388,7 @@ function fonts.afm.copy_to_tfm(data) local characters, parameters = tfm.characters, tfm.parameters if afmcharacters then for k, v in pairs(afmcharacters) do - local b, u = v.boundingbox, v.unicode - characters[u] = { - height = b[4], - depth = - b[2], - width = v.wx, - boundingbox = b, - index = v.index, - name = k, - unicode = u, - } + characters[v.unicode] = { description = v } end end tfm.encodingbytes = data.encodingbytes or 2 @@ -400,15 +407,15 @@ function fonts.afm.copy_to_tfm(data) local spaceunits = 500 tfm.spacer = "500 units" if data.isfixedpitch then - if afmcharacters['space'] and afmcharacters['space'].wx then - spaceunits, tfm.spacer = afmcharacters['space'].wx, "space" - elseif afmcharacters['emdash'] and afmcharacters['emdash'].wx then -- funny default - spaceunits, tfm.spacer = afmcharacters['emdash'].wx, "emdash" + if afmcharacters['space'] and afmcharacters['space'].width then + spaceunits, tfm.spacer = afmcharacters['space'].width, "space" + elseif afmcharacters['emdash'] and afmcharacters['emdash'].width then -- funny default + spaceunits, tfm.spacer = afmcharacters['emdash'].width, "emdash" elseif data.charwidth then spaceunits, tfm.spacer = data.charwidth, "charwidth" end - elseif afmcharacters['space'] and afmcharacters['space'].wx then - spaceunits, tfm.spacer = afmcharacters['space'].wx, "space" + elseif afmcharacters['space'] and afmcharacters['space'].width then + spaceunits, tfm.spacer = afmcharacters['space'].width, "space" elseif data.charwidth then spaceunits, tfm.spacer = data.charwidth, "charwidth variable" end @@ -433,24 +440,16 @@ function fonts.afm.copy_to_tfm(data) parameters[3] = 0 parameters[4] = 0 elseif fonts.afm.syncspace then - -- too little - -- parameters[3] = .2*spaceunits -- space_stretch - -- parameters[4] = .1*spaceunits -- space_shrink - -- taco's suggestion: - -- parameters[3] = .4*spaceunits -- space_stretch - -- parameters[4] = .1*spaceunits -- space_shrink - -- knuthian values: (for the moment compatible) parameters[3] = spaceunits/2 -- space_stretch parameters[4] = spaceunits/3 -- space_shrink end if data.xheight and data.xheight > 0 then parameters[5] = data.xheight elseif afmcharacters['x'] and afmcharacters['x'].height then - parameters[5] = afmcharacters['x'].height + parameters[5] = afmcharacters['x'].height or 0 end local fd = data.fontdimens - if fd and fd[8] and fd[9] and fd[10] then - -- we're dealing with a tex math font + if fd and fd[8] and fd[9] and fd[10] then -- math for k,v in pairs(fd) do parameters[k] = v end @@ -556,6 +555,7 @@ function fonts.afm.afm_to_tfm(specification) if not tfmdata then local afmdata = fonts.afm.load(afmname) if not table.is_empty(afmdata) then + fonts.afm.add_dimensions(afmdata) tfmdata = fonts.afm.copy_to_tfm(afmdata) if not table.is_empty(tfmdata) then tfmdata.shared = tfmdata.shared or { } @@ -647,7 +647,7 @@ function fonts.afm.features.prepare_kerns(tfmdata,kerns,value) if value then local charlist = tfmdata.shared.afmdata.characters for _, chr in pairs(tfmdata.characters) do - local newkerns = charlist[chr.name][kerns] + local newkerns = charlist[chr.description.name][kerns] if newkerns then local t = chr.kerns or { } for k,v in pairs(newkerns) do diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index d0cab7203..79f0e08ba 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -244,10 +244,10 @@ function fonts.tfm.read(specification) else tfmtable.embedding = "subset" end + fonts.tfm.fonts[hash] = tfmtable + fonts.designsizes[specification.hash] = tfmtable.designsize -- we only know this for sure after loading once + --~ tfmtable.mode = specification.features.normal.mode or "base" end - fonts.tfm.fonts[hash] = tfmtable -fonts.designsizes[specification.hash] = tfmtable.designsize -- we only know this for sure after loading once ---~ tfmtable.mode = specification.features.normal.mode or "base" end input.stoptiming(fonts) garbagecollector.pop() diff --git a/tex/context/base/font-fbk.lua b/tex/context/base/font-fbk.lua index e5975a38e..5056e6f88 100644 --- a/tex/context/base/font-fbk.lua +++ b/tex/context/base/font-fbk.lua @@ -51,8 +51,6 @@ end fonts.fallbacks['textcent'] = function (g) local c = string.byte("c") local t = table.fastcopy(g.characters[c]) ---~ local s = fonts.tfm.scaled(g.specification.size or g.size or g.private.size) ---~ local s = fonts.tfm.scaled(g.size or g.private.size) local s = fonts.tfm.scaled(g.specification.size or g.size) local a = - math.tan(math.rad(g.italicangle)) local special, red, green, blue, black = fonts.vf.aux.combine.initialize_trace() @@ -89,8 +87,6 @@ end fonts.fallbacks['texteuro'] = function (g) local c = string.byte("C") local t = table.fastcopy(g.characters[c]) ---~ local s = fonts.tfm.scaled(g.specification.size or g.size or g.private.size) ---~ local s = fonts.tfm.scaled(g.size or g.private.size) local s = fonts.tfm.scaled(g.specification.size or g.size) local d = math.cos(math.rad(90+g.italicangle)) local special, red, green, blue, black = fonts.vf.aux.combine.initialize_trace() @@ -111,69 +107,144 @@ end fonts.vf.aux.combine.force_composed = false - fonts.vf.aux.combine.commands["complete-composed-characters"] = function(g,v) +--~ fonts.vf.aux.combine.commands["complete-composed-characters"] = function(g,v) +--~ local chars = g.characters +--~ local xchar = chars[string.byte("X")] +--~ if xchar.boundingbox then +--~ local cap_lly = xchar.boundingbox[4] +--~ local ita_cor = math.cos(math.rad(90+g.italicangle)) +--~ local force = fonts.vf.aux.combine.force_composed +--~ local special, red, green, blue, black = fonts.vf.aux.combine.initialize_trace() +--~ for i,c in pairs(characters.data) do +--~ if force or not chars[i] then +--~ local s = c.specials +--~ if s and s[1] == 'char' then +--~ local chr = s[2] +--~ if chars[chr] then +--~ local cc = c.category +--~ if (cc == 'll') or (cc == 'lu') or (cc == 'lt') then +--~ local acc = s[3] +--~ local t = table.fastcopy(chars[chr]) +--~ t.name = "" +--~ t.index = i +--~ t.unicode = i +--~ if chars[acc] then +--~ local cb = chars[chr].boundingbox +--~ local ab = chars[acc].boundingbox +--~ if cd and ab then +--~ local c_llx, c_lly, c_urx, c_ury = cb[1], cb[2], cb[3], cb[4] +--~ local a_llx, a_lly, a_urx, a_ury = ab[1], ab[2], ab[3], ab[4] +--~ local dx = (c_urx - a_urx - a_llx + c_llx)/2 +--~ local dd = (c_urx-c_llx)*ita_cor +--~ if a_ury < 0 then +--~ local dy = cap_lly-a_lly +--~ t.commands = { +--~ {"push"}, +--~ {"right", dx-dd}, +--~ {"down", -dy}, -- added +--~ {special, red}, +--~ {"slot", 1, acc}, +--~ {special, black}, +--~ {"pop"}, +--~ {"slot", 1, chr}, +--~ } +--~ elseif c_ury > a_lly then +--~ local dy = cap_lly-a_lly +--~ t.commands = { +--~ {"push"}, +--~ {"right", dx+dd}, +--~ {"down", -dy}, +--~ {special, green}, +--~ {"slot", 1, acc}, +--~ {special, black}, +--~ {"pop"}, +--~ {"slot", 1, chr}, +--~ } +--~ else +--~ t.commands = { +--~ {"push"}, +--~ {"right", dx+dd}, +--~ {special, blue}, +--~ {"slot", 1, acc}, +--~ {special, black}, +--~ {"pop"}, +--~ {"slot", 1, chr}, +--~ } +--~ end +--~ end +--~ end +--~ chars[i] = t +--~ end +--~ end +--~ end +--~ end +--~ end +--~ end +--~ end + +fonts.vf.aux.combine.commands["complete-composed-characters"] = function(g,v) local chars = g.characters - local cap_lly = chars[string.byte("X")].boundingbox[4] - local ita_cor = math.cos(math.rad(90+g.italicangle)) - local force = fonts.vf.aux.combine.force_composed - local special, red, green, blue, black = fonts.vf.aux.combine.initialize_trace() - for i,c in pairs(characters.data) do - if force or not chars[i] then - local s = c.specials - if s and s[1] == 'char' then - local chr = s[2] - if chars[chr] then - local cc = c.category - if (cc == 'll') or (cc == 'lu') or (cc == 'lt') then - local acc = s[3] - local t = table.fastcopy(chars[chr]) -t.name = "" -t.index = i -t.unicode = i - if chars[acc] then - local cb = chars[chr].boundingbox - local ab = chars[acc].boundingbox - local c_llx, c_lly, c_urx, c_ury = cb[1], cb[2], cb[3], cb[4] - local a_llx, a_lly, a_urx, a_ury = ab[1], ab[2], ab[3], ab[4] - -- local dx = (c_urx-a_urx) - (c_urx-c_llx-a_urx+a_llx)/2 - -- local dx = (c_urx-a_urx) - (c_urx-a_urx-c_llx+a_llx)/2 - local dx = (c_urx - a_urx - a_llx + c_llx)/2 - -- local dd = chars[chr].width*ita_cor - local dd = (c_urx-c_llx)*ita_cor - if a_ury < 0 then - local dy = cap_lly-a_lly - t.commands = { - {"push"}, - {"right", dx-dd}, - {"down", -dy}, -- added - {special, red}, - {"slot", 1, acc}, - {special, black}, - {"pop"}, - {"slot", 1, chr}, - } - elseif c_ury > a_lly then - local dy = cap_lly-a_lly - t.commands = { - {"push"}, - {"right", dx+dd}, - {"down", -dy}, - {special, green}, - {"slot", 1, acc}, - {special, black}, - {"pop"}, - {"slot", 1, chr}, - } - else - t.commands = { - {"push"}, - {"right", dx+dd}, - {special, blue}, - {"slot", 1, acc}, - {special, black}, - {"pop"}, - {"slot", 1, chr}, - } + local xchar = chars[string.byte("X")] + if xchar then + local xheight = xchar.height + local ita_cor = math.cos(math.rad(90+g.italicangle)) + local force = fonts.vf.aux.combine.force_composed + local special, red, green, blue, black = fonts.vf.aux.combine.initialize_trace() + for i,c in pairs(characters.data) do + if force or not chars[i] then + local s = c.specials + if s and s[1] == 'char' then + local chr = s[2] + if chars[chr] then + local cc = c.category + if (cc == 'll') or (cc == 'lu') or (cc == 'lt') then + local acc = s[3] + local t = table.fastcopy(chars[chr]) + t.name = "" + t.index = i + t.unicode = i + if chars[acc] then + local c = chars[chr] + local a = chars[acc] + if c and a then + local dx = (c.width-a.width)/2 + local dd = c.width*ita_cor + if a.height < 0 then + local dy = xheight+a.depth + t.commands = { + {"push"}, + {"right", dx-dd}, + {"down", -dy}, -- added + {special, red}, + {"slot", 1, acc}, + {special, black}, + {"pop"}, + {"slot", 1, chr}, + } + elseif c.height > -a.depth then + local dy = xheight+a.depth + t.commands = { + {"push"}, + {"right", dx+dd}, + {"down", -dy}, + {special, green}, + {"slot", 1, acc}, + {special, black}, + {"pop"}, + {"slot", 1, chr}, + } + else + t.commands = { + {"push"}, + {"right", dx+dd}, + {special, blue}, + {"slot", 1, acc}, + {special, black}, + {"pop"}, + {"slot", 1, chr}, + } + end + end end chars[i] = t end diff --git a/tex/context/base/font-ini.tex b/tex/context/base/font-ini.tex index f42a26563..65cb3ae00 100644 --- a/tex/context/base/font-ini.tex +++ b/tex/context/base/font-ini.tex @@ -1541,14 +1541,14 @@ % this may move to another file, maybe font-xtx - \remapfontfeature tlig yes mapping=tex-text - \remapfontfeature tlig no mapping= - \remapfontfeature trep yes mapping=tex-text - \remapfontfeature trep no mapping= - \remapfontfeature texligatures yes mapping=tex-text - \remapfontfeature texligatures no mapping= - \remapfontfeature texquotes yes mapping=tex-text - \remapfontfeature texquotes no mapping= + \remapfontfeature tlig yes mapping=tlig + %remapfontfeature tlig no mapping= + %remapfontfeature trep yes mapping=tex-text + %remapfontfeature trep no mapping= + \remapfontfeature texligatures yes mapping=tlig + %remapfontfeature texligatures no mapping= + %remapfontfeature texquotes yes mapping=tex-text + %remapfontfeature texquotes no mapping= \endXETEX diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua index 23898d302..26932109d 100644 --- a/tex/context/base/font-otf.lua +++ b/tex/context/base/font-otf.lua @@ -6,8 +6,16 @@ if not modules then modules = { } end modules ['font-otf'] = { license = "see context related readme files" } +-- the flattening code is a prelude to a more compact table format (so, we're now +-- at the fourth version) + --- todo: featuredata is now indexed by kind,lookup but probably lookup is okay too +-- todo: now that we pack ... resolve strings to unicode points +-- todo: unpack already in tmc file, i.e. save tables and return ref''d version +-- todo: dependents etc resolve too, maybe even reorder glyphs to unicode +-- todo: pack ignoreflags + -- abvf abvs blwf blwm blws dist falt half halt jalt lfbd ljmo -- mset opbd palt pwid qwid rand rtbd rtla ruby size tjmo twid valt vatu vert -- vhal vjmo vkna vkrn vpal vrt2 @@ -32,7 +40,8 @@ number by one when there's a fix in the <l n='fontforge'/> library or fonts = fonts or { } fonts.otf = fonts.otf or { } -fonts.otf.version = 1.73 +fonts.otf.version = 2.00 +fonts.otf.pack = true fonts.otf.tables = fonts.otf.tables or { } fonts.otf.meanings = fonts.otf.meanings or { } fonts.otf.enhance_data = false @@ -716,26 +725,18 @@ do local h = { } for k,v in pairs(features) do k = (k:lower()):gsub("[^a-z]","") - if k == "language" or k =="lang" then + if k == "language" or k == "lang" then v = (v:lower()):gsub("[^a-z]","") k = language if not languages[v] then - if to_languages[v] then - h.language = to_languages[v] - else - h.language = "dflt" - end + h.language = to_languages[v] or "dflt" else h.language = v end elseif k == "script" then v = (v:lower()):gsub("[^a-z]","") if not scripts[v] then - if to_scripts[v] then - h.script = to_scripts[v] - else - h.script = "dflt" - end + h.script = to_scripts[v] or "dflt" else h.script = v end @@ -748,11 +749,7 @@ do v = b end end - if to_features[k] then - h[to_features[k]] = v - else - h[k] = v - end + h[to_features[k] or k] = v end end return h @@ -816,12 +813,20 @@ function fonts.otf.load(filename,format,sub,featurefile) if data then logs.report("load otf","enhance: before") fonts.otf.enhance.before(data,filename) + logs.report("load otf","enhance: flatten") + fonts.otf.enhance.flatten(data,filename) logs.report("load otf","enhance: analyze") fonts.otf.enhance.analyze(data,filename) logs.report("load otf","enhance: after") fonts.otf.enhance.after(data,filename) logs.report("load otf","enhance: patch") fonts.otf.enhance.patch(data,filename) + logs.report("load otf","enhance: strip") + fonts.otf.enhance.strip(data,filename) + if fonts.otf.pack then + logs.report("load otf","enhance: pack") + fonts.otf.enhance.pack(data) + end logs.report("load otf","saving: in cache") data = containers.write(fonts.otf.cache, hash, data) else @@ -829,22 +834,125 @@ function fonts.otf.load(filename,format,sub,featurefile) end end end ---~ if data then ---~ local map = data.map.map ---~ local backmap = data.map.backmap ---~ local unicodes = data.luatex.unicodes ---~ local glyphs = data.glyphs ---~ -- maybe handy some day, not used ---~ data.name_to_unicode = function (n) return unicodes[n] end ---~ data.name_to_index = function (n) return map[unicodes[n]] end ---~ data.index_to_name = function (i) return glyphs[i].name end ---~ data.unicode_to_name = function (u) return glyphs[map[u]].name end ---~ data.index_to_unicode = function (u) return backmap[u] end ---~ data.unicode_to_index = function (u) return map[u] end ---~ end + fonts.otf.enhance.unpack(data) return data end +-- memory saver .. + +function fonts.otf.enhance.pack(data) + if data then + local h, t = { }, { } + local concat = table.concat + local function tabstr(t) + for i=1,#t do + if type(t[i]) == "boolean" then + local s = tostring(t[1]) + for i=2,#t do + s = s .. ",".. tostring(t[i]) + end + return s + end + end + return concat(t,",") + end + local function pack(v) + local tag = tabstr(v,",") + if not h[tag] then + t[#t+1] = v + h[tag] = #t + end + return h[tag] + end + for k, v in pairs(data.glyphs) do + v.boundingbox = pack(v.boundingbox) + if v.lookups then + for k,v in pairs(v.lookups) do + for kk, vv in ipairs(v) do + v[kk] = pack(vv) + end + end + end + end + if data.lookups then + for k, v in pairs(data.lookups) do + if v.rules then + for kk, vv in pairs(v.rules) do + local l = vv.lookups + if l then + vv.lookups = pack(l) + end + local c = vv.coverage + if c then + c.before = c.before and pack(c.before ) + c.after = c.after and pack(c.after ) + c.current = c.current and pack(c.current) + end + end + end + end + end + if data.luatex then + local li = data.luatex.ignore_flags + if li then + for k, v in pairs(li) do + li[k] = pack(v) + end + end + end + if #t > 0 then + data.tables = t + end + end +end + +function fonts.otf.enhance.unpack(data) + if data then + local t = data.tables + if t then + for k, v in pairs(data.glyphs) do + v.boundingbox = t[v.boundingbox] + local l = v.lookups + if l then + for k,v in pairs(l) do + for i=1,#v do + v[i] = t[v[i]] + end + end + end + end + if data.lookups then + for k, v in pairs(data.lookups) do + local r = v.rules + if r then + for kk, vv in pairs(r) do + local l = vv.lookups + if l then + vv.lookups = t[l] + end + local c = vv.coverage + if c then + if c.before then c.before = t[c.before] end + if c.after then c.after = t[c.after] end + if c.current then c.current = t[c.current] end + end + end + end + end + end + if data.luatex then + local li = data.luatex.ignore_flags + if li then + for k, v in pairs(li) do + li[k] = t[v] + end + end + end + data.tables = nil + end + end +end + -- todo: normalize, design_size => designsize function fonts.otf.enhance.analyze(data,filename) @@ -861,38 +969,6 @@ function fonts.otf.enhance.analyze(data,filename) data.luatex = t end ---~ function fonts.otf.load_cidmap(filename) -- lpeg ---~ local data = io.loaddata(filename) ---~ if data then ---~ local unicodes, names = { }, {} ---~ data = data:gsub("^(%d+)%s+(%d+)\n","") ---~ for a,b in data:gmatch("(%d+)%s+([%d%a]+)\n") do ---~ unicodes[tonumber(a)] = tonumber(b,16) ---~ end ---~ for a,b,c in data:gmatch("(%d+)%.%.(%d+)%s+([%d%a]+)%s*\n") do ---~ c = tonumber(c,16) ---~ for i=tonumber(a),tonumber(b) do ---~ unicodes[i] = c ---~ c = c + 1 ---~ end ---~ end ---~ for a,b in data:gmatch("(%d+)%s+\/(%S+)%s*\n") do ---~ names[tonumber(a)] = b ---~ end ---~ local supplement, registry, ordering = filename:match("^(.-)%-(.-)%-()%.(.-)$") ---~ return { ---~ supplement = supplement, ---~ registry = registry, ---~ ordering = ordering, ---~ filename = filename, ---~ unicodes = unicodes, ---~ names = names ---~ } ---~ else ---~ return nil ---~ end ---~ end - do -- original string parsr: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap -- @@ -999,7 +1075,7 @@ function fonts.otf.enhance.before(data,filename) if cidinfo.registry then local cidmap = fonts.otf.cidmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement) if cidmap then - local glyphs, uni_to_int, int_to_uni, nofnames, nofunicodes, zerobox = { }, { }, { }, 0, 0, { 0, 0, 0, 0 } + local glyphs, uni_to_int, int_to_uni, nofnames, nofunicodes = { }, { }, { }, 0, 0 local unicodes, names = cidmap.unicodes, cidmap.names for n, subfont in pairs(data.subfonts) do for index, g in pairs(subfont.glyphs) do @@ -1008,15 +1084,15 @@ function fonts.otf.enhance.before(data,filename) else local unicode, name = unicodes[index], names[index] g.cidindex = n - g.boundingbox = g.boundingbox or zerobox + g.boundingbox = g.boundingbox -- or zerobox g.name = g.name or name or "unknown" if unicode then - g.unicodeenc = unicode + g.unicode = unicode uni_to_int[unicode] = index int_to_uni[index] = unicode nofunicodes = nofunicodes + 1 elseif name then - g.unicodeenc = -1 + g.unicode = -1 nofnames = nofnames + 1 end glyphs[index] = g @@ -1041,14 +1117,14 @@ function fonts.otf.enhance.before(data,filename) local int_to_uni = data.map.backmap for index, glyph in pairs(data.glyphs) do if glyph.name then - local unic = glyph.unicodeenc or -1 + local unic = glyph.unicode or -1 if index > 0 and (unic == -1 or unic >= 0x110000) then while uni_to_int[private] do private = private + 1 end uni_to_int[private] = index int_to_uni[index] = private - glyph.unicodeenc = private + glyph.unicode = private if fonts.trace then logs.report("load otf",string.format("enhance: glyph %s at index %s is moved to private unicode slot %s",glyph.name,index,private)) end @@ -1154,7 +1230,6 @@ function fonts.otf.enhance.after(data,filename) -- to be split mykerns[lookup] = lookupkerns end for sk, sv in pairs(seconds) do - -- for second in sv:gmatch("([^ ]+)") do for second in sv:gmatch("[^ ]+") do lookupkerns[unicodes[second]] = offsets[(fk-1) * maxseconds + sk] end @@ -1162,20 +1237,113 @@ function fonts.otf.enhance.after(data,filename) -- to be split end end end + subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables." + subtable.kernclass = { } end - subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables." - subtable.kernclass = { } end end end end end - if data.map then - data.map.enc = nil -- not needed +end + +function fonts.otf.enhance.strip(data) +--~ if data.map then +--~ data.map.enc = nil -- not needed +--~ end +--~ data.map = { map = {}, backmap = {} } + for k, v in pairs(data.glyphs) do + local d = v.dependents + if d then v.dependents = nil end end + data.map = nil + data.names = nil data.luatex.comment = "Glyph tables have their original index. When present, mykern tables are indexed by unicode." end +function fonts.otf.enhance.flatten(data,filename) -- to be split + logs.report("load otf", "flattening 'specifications' tables") + for k, v in pairs(data.glyphs) do + if v.lookups then + for kk, vv in pairs(v.lookups) do + for kkk, vvv in ipairs(vv) do + local s = vvv.specification + if s then + local t = vvv.type + if t == "ligature" then + vv[kkk] = { "ligature", s.components, s.char } + elseif t == "alternate" then + vv[kkk] = { "alternate", s.components } + elseif t == "substitution" then + vv[kkk] = { "substitution", s.variant } + elseif t == "multiple" then + vv[kkk] = { "multiple", s.components } + elseif t == "position" then + vv[kkk] = { "position", s.x or 0, s.y or 0, s.h or 0, s.v or 0 } + elseif t == "pair" then + local one, two, paired = s.offsets[1], s.offsets[2], s.paired or "" + if one then + if two then + vv[kkk] = { "pair", paired, one.x or 0, one.y or 0, one.h or 0, one.v or 0, two.x or 0, two.y or 0, two.h or 0, two.v or 0 } + else + vv[kkk] = { "pair", paired, one.x or 0, one.y or 0, one.h or 0 } + end + else + if two then + vv[kkk] = { "pair", paired, 0, 0, 0, 0, two.x or 0, two.y or 0, two.h or 0, two.v or 0 } + else + vv[kkk] = { "pair", paired } + end + end + else + logs.report("load otf", "flattening needed, warn Hans and/or Taco") + for a, b in pairs(s) do + if vvv[a] then + logs.report("load otf", "flattening conflict, warn Hans and/or Taco") + end + vvv[a] = b + end + vvv.specification = nil + end + end + end + end + end + end + logs.report("load otf", "flattening 'anchor' tables") + for k, v in pairs(data.glyphs) do + if v.anchors then + for kk, vv in pairs(v.anchors) do + for kkk, vvv in pairs(vv) do + if vvv.x or vvv.y then -- kkk == "centry" + vv[kkk] = { vvv.x or 0, vvv.y or 0 } + else + for kkkk, vvvv in ipairs(vvv) do + vvv[kkkk] = { vvvv.x or 0, vvvv.y or 0 } + end + end + end + end + end + end + for _, tag in pairs({"gpos","gsub"}) do + if data[tag] then + logs.report("load otf", "flattening '" .. tag.. "' tables") + for k, v in pairs(data[tag]) do + if v.features then + for kk, vv in ipairs(v.features) do + local t = { } + for kkk, vvv in ipairs(vv.scripts) do + t[vvv.script] = vvv.langs + end + vv.scripts = t + end + end + end + end + end +end + fonts.otf.enhance.patches = { } function fonts.otf.enhance.patch(data,filename) @@ -1209,7 +1377,7 @@ function fonts.otf.analyze_class(data,class) local classes = { } for index, glyph in pairs(data.glyphs) do if glyph.class == class then - classes[glyph.unicodeenc] = true + classes[glyph.unicode] = true end end return classes @@ -1230,14 +1398,13 @@ function fonts.otf.analyze_subtables(data) for _, feature in ipairs(v.features) do local ft = feature.tag:lower() subtables[ft] = subtables[ft] or { } - for _, script in ipairs(feature.scripts) do - local ss = script.script - ss = ss:lower() - ss = ss:strip() + for script, languages in pairs(feature.scripts) do + script = script:lower() + script = script:strip() sft = subtables[ft] - sft[ss] = sft[ss] or { } - local sfts = sft[ss] - for _, language in ipairs(script.langs) do + sft[script] = sft[script] or { } + local sfts = sft[script] + for _, language in ipairs(languages) do language = language:lower() language = language:strip() sfts[language] = sfts[language] or { } @@ -1267,7 +1434,6 @@ function fonts.otf.analyze_subtables(data) if stl then lookups[#lookups+1] = stl valid[stl] = true - -- name_to_type[stl] = type always_valid[stl] = true end end @@ -1289,7 +1455,7 @@ function fonts.otf.analyze_unicodes(data) local unicodes = { } for _, blob in pairs(data.glyphs) do if blob.name then - unicodes[blob.name] = blob.unicodeenc or 0 + unicodes[blob.name] = blob.unicode or 0 end end unicodes['space'] = unicodes['space'] or 32 -- handly later on @@ -1417,14 +1583,15 @@ function fonts.otf.otf_to_tfm(specification) if not tfmdata then local otfdata = fonts.otf.load(filename,format,sub,features and features.featurefile) if not table.is_empty(otfdata) then -if true then - otfdata._shared_ = otfdata._shared_ or { -- aggressive sharing - processes = { }, - lookuptable = { }, - featuredata = { }, - featurecache = { }, - } -end + fonts.otf.add_dimensions(otfdata) + if true then + otfdata._shared_ = otfdata._shared_ or { -- aggressive sharing + processes = { }, + lookuptable = { }, + featuredata = { }, + featurecache = { }, + } + end tfmdata = fonts.otf.copy_to_tfm(otfdata) if not table.is_empty(tfmdata) then tfmdata.unique = tfmdata.unique or { } @@ -1497,37 +1664,38 @@ function fonts.otf.features.prepare_base_kerns(tfmdata,kind,value) -- todo what end end end -function fonts.otf.copy_to_tfm(data) + +function fonts.otf.add_dimensions(data) + if data then + local force = fonts.otf.notdef + for k, d in pairs(data.glyphs) do + local bb, wd = d.boundingbox, d.width or 0 + if force and not d.name then + d.name = ".notdef" + end + if wd ~= 0 and d.class == "mark" then + d.width = -wd + end + if bb then + local ht, dp = bb[4], -bb[2] + if ht ~= 0 then d.height = ht end + if dp ~= 0 then d.depth = dp end + end + d.index = k + end + end +end + +function fonts.otf.copy_to_tfm(data) -- we can save a copy when we reorder the tma to unicode if data then local tfm = { characters = { }, parameters = { } } local unicodes = data.luatex.unicodes local characters = tfm.characters local parameters = tfm.parameters - local force = fonts.otf.notdef - local zerobox = { 0, 0, 0, 0 } local glyphs = data.glyphs - for k,v in pairs(data.map.map) do - -- k = unicode, v = slot - local d = glyphs[v] - if d then - local name = d.name - if force or name then - local b = d.boundingbox or zerobox - local w = d.width or 0 - if d.class == "mark" then - w = - w - end - characters[k] = { - index = v, - unicode = k, - name = name or ".notdef", - boundingbox = b, - width = w, - height = b[4], - depth = - b[2], - class = d.class, - } - end + for k, d in pairs(glyphs) do + if d.name then + characters[d.unicode] = { description = d } end end local designsize = data.designsize or data.design_size or 100 @@ -1558,20 +1726,20 @@ function fonts.otf.copy_to_tfm(data) local endash, emdash = unicodes['space'], unicodes['emdash'] if data.isfixedpitch then if characters[endash] then - spaceunits, tfm.spacer = characters[endash].width, "space" + spaceunits, tfm.spacer = characters[endash].description.width, "space" end if not spaceunits and characters[emdash] then - spaceunits, tfm.spacer = characters[emdash].width, "emdash" + spaceunits, tfm.spacer = characters[emdash].description.width, "emdash" end if not spaceunits and data.charwidth then spaceunits, tfm.spacer = data.charwidth, "charwidth" end else if characters[endash] then - spaceunits, tfm.spacer = characters[endash].width, "space" + spaceunits, tfm.spacer = characters[endash].description.width, "space" end if not spaceunits and characters[emdash] then - spaceunits, tfm.spacer = characters[emdash].width/2, "emdash/2" + spaceunits, tfm.spacer = characters[emdash].description.width/2, "emdash/2" end if not spaceunits and data.charwidth then spaceunits, tfm.spacer = data.charwidth, "charwidth" @@ -1606,7 +1774,7 @@ function fonts.otf.copy_to_tfm(data) else local x = characters[unicodes['x']] if x then - parameters[5] = x.height + parameters[5] = x.description.height end end -- [6] @@ -1761,7 +1929,11 @@ function fonts.otf.features.aux.resolve_ligatures(tfmdata,ligatures,kind) for k,v in pairs(ligatures) do local lig = v[1] if not done[lig] then - local ligs = lig:split(" ") +--~ local ligs = lig:split(" ") +local ligs = { } +for s in lig:gmatch("[^ ]+") do + ligs[#ligs+1] = s +end if #ligs == 2 then local c, f, s = chars[v[2]], ligs[1], ligs[2] local uf, us = unicodes[f], unicodes[s] @@ -1778,15 +1950,15 @@ function fonts.otf.features.aux.resolve_ligatures(tfmdata,ligatures,kind) first.ligatures = t end t[second] = { - char = unicodes[c.name], + char = unicodes[c.description.name], type = 0 } if trace then - logs.report("define otf",string.format("%s: %s (%s) + %s (%s) = %s (%s)",kind,f,uf,s,us,c.name,unicodes[c.name])) + logs.report("define otf",string.format("%s: %s (%s) + %s (%s) = %s (%s)",kind,f,uf,s,us,c.description.name,unicodes[c.name])) end end end - ok, done[lig] = true, c.name + ok, done[lig] = true, c.description.name end end end @@ -1823,30 +1995,28 @@ function fonts.otf.features.prepare_base_substitutions(tfmdata,kind,value) -- we if somevalid[lookup] then for i=1,#ps do local p = ps[i] - local t = p.type + local t = p[1] if t == 'substitution' then - local ps = p.specification - if ps and ps.variant then - local pv = ps.variant - if pv then - local upv = unicodes[pv] - if upv and chars[upv] then - if trace then - logs.report("define otf",string.format("%s: %s (%s) => %s (%s)",kind,chars[k].name,k,chars[upv].name,upv)) - end - chars[k] = chars[upv] - changed[k] = true + local pv = p[2] -- p.variant + if pv then + local upv = unicodes[pv] + if upv and chars[upv] then + if trace then + logs.report("define otf",string.format("%s: %s (%s) => %s (%s)",kind,chars[k].description.name,k,chars[upv].description.name,upv)) end + chars[k] = chars[upv] + changed[k] = true end end elseif t == 'alternate' then - local pa = p.specification if pa and pa.components then - local pc = pa.components:match("([^ ]+)") + local pc = p[2] -- p.components + if pc then + pc = pa.components:match("([^ ]+)") if pc then local upc = unicodes[pc] if upc and chars[upc] then if trace then - logs.report("define otf",string.format("%s: %s (%s) => %s (%s)",kind,chars[k].name,k,chars[upc].name,upc)) + logs.report("define otf",string.format("%s: %s (%s) => %s (%s)",kind,chars[k].description.name,k,chars[upc].description.name,upc)) end chars[k] = chars[upc] changed[k] = true @@ -1854,15 +2024,12 @@ function fonts.otf.features.prepare_base_substitutions(tfmdata,kind,value) -- we end end elseif t == 'ligature' and not changed[k] then - local pl = p.specification - if pl then - local plc = pl.components - if plc then - if trace then - logs.report("define otf",string.format("%s: %s => %s (%s)",kind,plc,chars[k].name,k)) - end - ligatures[#ligatures+1] = { plc, k } + local pc = p[2] + if pc then + if trace then + logs.report("define otf",string.format("%s: %s => %s (%s)",kind,pc,chars[k].description.name,k)) end + ligatures[#ligatures+1] = { pc, k } end end end @@ -1996,9 +2163,9 @@ do local function collect(lookup,o,ps) for i=1,#ps do local p = ps[i] - if p.specification and p.type == 'ligature' then + if p[1] == 'ligature' then if trace then - logs.report("define otf",string.format("feature %s ligature %s => %s",kind,p.specification.components,o.name)) + logs.report("define otf",string.format("feature %s ligature %s => %s",kind,p.components,o.name)) end local t = ligatures[lookup] if not t then @@ -2006,7 +2173,7 @@ do ligatures[lookup] = t end local first = true - for s in p.specification.components:gmatch("[^ ]+") do + for s in p[2]:gmatch("[^ ]+") do local u = unicodes[s] if first then if not t[u] then @@ -2022,7 +2189,7 @@ do t = t1[u] end end - t[2] = o.unicodeenc + t[2] = o.unicode end end end @@ -2070,8 +2237,8 @@ do if lookup == lookupname then for i=1,#ps do local p = ps[i] - if p.specification and p.type == 'substitution' then - local old, new = o.unicodeenc, unicodes[p.specification.variant] + if p[1] == 'substitution' then + local old, new = o.unicode, unicodes[p[2]] substitutions[old] = new if trace then logs.report("define otf",string.format("%s:%s substitution %s => %s",kind,lookupname,old,new)) @@ -2102,11 +2269,10 @@ do if lookup == lookupname then for i=1,#ps do local p = ps[i] - if p.specification and p.type == 'multiple' then - local old, new = o.unicodeenc, { } + if p[1] == 'multiple' then + local old, new = o.unicode, { } substitutions[old] = new - -- for pc in p.specification.components:gmatch("([^ ]+)") do - for pc in p.specification.components:gmatch("[^ ]+") do + for pc in p[2]:gmatch("[^ ]+") do new[#new+1] = unicodes[pc] end if trace then @@ -2139,11 +2305,10 @@ do if lookup == lookupname then for i=1,#ps do local p = ps[i] - if p.specification and p.type == 'alternate' then - local old = o.unicodeenc + if p[1] == 'alternate' then + local old = o.unicode local t = { } - -- for pc in p.specification.components:gmatch("([^ ]+)") do - for pc in p.specification.components:gmatch("[^ ]+") do + for pc in p[2]:gmatch("[^ ]+") do t[#t+1] = unicodes[pc] end substitutions[old] = t @@ -2299,7 +2464,7 @@ do end end if ok then - anchors[o.unicodeenc] = t + anchors[o.unicode] = t end end end @@ -2337,7 +2502,7 @@ do if list then local omk = list[lookupname] if omk then - local one = o.unicodeenc + local one = o.unicode for char, off in pairs(omk) do local two = char local krn = kerns[one] @@ -2352,7 +2517,7 @@ do end end elseif o.kerns then - local one = o.unicodeenc + local one = o.unicode local okerns = o.kerns for ok=1,#okerns do local k = okerns[ok] @@ -2375,19 +2540,18 @@ do end list = o.lookups if list then - local one = o.unicodeenc + local one = o.unicode for lookup,ps in pairs(list) do if lookup == lookupname then for i=1,#ps do local p = ps[i] - if p.type == 'pair' then - local specification = p.specification - local two = unicodes[specification.paired] + if p[1] == 'pair' then + local two = unicodes[p[2]] local krn = kerns[one] if krn then - krn[two] = specification.offsets + krn[two] = p else - kerns[one] = { two = specification.offsets } + kerns[one] = { two = p } end if trace then logs.report("define otf",string.format("feature %s kern pair %s - %s",kind,one,two)) @@ -2794,8 +2958,8 @@ do for anchor,data in pairs(marks) do local ba = bases[anchor] if ba then - local dx = scale(ba.x-data.x, factor) - local dy = scale(ba.y-data.y, factor) + local dx = scale(ba[1]-data[1], factor) + local dy = scale(ba[2]-data[2], factor) component.xoffset = start.xoffset - dx component.yoffset = start.yoffset + dy if trace then @@ -2843,8 +3007,8 @@ do local n = has_attribute(component,marknumber) local ban = ba[n] if ban then - local dx = scale(ban.x-data.x, factor) - local dy = scale(ban.y-data.y, factor) + local dx = scale(ban[1]-data[1], factor) + local dy = scale(ban[2]-data[2], factor) component.xoffset = start.xoffset - dx component.yoffset = start.yoffset + dy if trace then @@ -2894,8 +3058,8 @@ do for anchor,data in pairs(marks) do local ba = bases[anchor] if ba then - local dx = scale(ba.x-data.x, factor) - local dy = scale(ba.y-data.y, factor) + local dx = scale(ba[1]-data[1], factor) + local dy = scale(ba[2]-data[2], factor) component.xoffset = start.xoffset - dx component.yoffset = start.yoffset + dy if trace then @@ -2938,6 +3102,7 @@ do first = first.next else first.yoffset = scale(total, factor) + -- first.yoffset = factor*total if first == next then break else @@ -2963,7 +3128,7 @@ do local exit = cexit[anchor] if exit then if not first then first = start end - t[#t+1] = exit.y + entry.y + t[#t+1] = exit[2] + entry[2] total = total + t[#t] done = true break @@ -3005,12 +3170,9 @@ do if not krn then -- skip elseif type(krn) == "table" then - local a, b = krn[1], krn[2] - if a and a.x then - local k = nodes.kern(scale(a.x,factor)) - if b and b.x then - report("otf process","we need to do something with the second kern xoff " .. b.x) - end + local a, b = krn[3], krn[7] + if a and a ~= 0 then + local k = nodes.kern(scale(a,factor)) k.next = next k.prev = prev prev.next = k @@ -3019,6 +3181,9 @@ do -- todo end end + if b and b ~= 0 then + report("otf process","we need to do something with the second kern xoff " .. b) + end else -- todo, just start, next = node.insert_before(head,next,nodes.kern(scale(kern,factor))) local k = nodes.kern(scale(krn,factor)) @@ -3056,7 +3221,7 @@ do for l=1,#lookups do local lv = looks[lookups[l]] if lv then - replacement = unicodes[lv[1].specification.variant] or char + replacement = unicodes[lv[1][2]] or char cacheslot[char] = replacement break end @@ -3089,8 +3254,7 @@ do local lv = looks[lookups[l]] if lv then replacement = { } - -- for c in lv[1].specification.components:gmatch("([^ ]+)") do - for c in lv[1].specification.components:gmatch("[^ ]+") do + for c in lv[1][2]:gmatch("[^ ]+") do replacement[#replacement+1] = unicodes[c] end cacheslot[char] = replacement @@ -3141,8 +3305,7 @@ do local lv = looks[lookups[l]] if lv then replacement = { } - -- for c in lv[1].specification.components:gmatch("([^ ]+)") do - for c in lv[1].specification.components:gmatch("[^ ]+") do + for c in lv[1][2]:gmatch("[^ ]+") do replacement[#replacement+1] = unicodes[c] end cacheslot[char] = replacement @@ -3244,8 +3407,8 @@ do for anchor,data in pairs(markanchors) do local ba = baseanchors[anchor] if ba then - local dx = scale(ba.x-data.x, factor) - local dy = scale(ba.y-data.y, factor) + local dx = scale(ba[1]-data[1], factor) + local dy = scale(ba[2]-data[2], factor) component.xoffset = start.xoffset - dx component.yoffset = start.yoffset + dy if trace then @@ -3306,8 +3469,8 @@ do local n = has_attribute(component,marknumber) local ban = ba[n] if ban then - local dx = scale(ban.x-data.x, factor) - local dy = scale(ban.y-data.y, factor) + local dx = scale(ban[1]-data[1], factor) + local dy = scale(ban[2]-data[2], factor) component.xoffset = start.xoffset - dx component.yoffset = start.yoffset + dy if trace then @@ -3367,8 +3530,8 @@ do for anchor,data in pairs(markanchors) do local ba = baseanchors[anchor] if ba then - local dx = scale(ba.x-data.x, factor) - local dy = scale(ba.y-data.y, factor) + local dx = scale(ba[1]-data[1], factor) + local dy = scale(ba[2]-data[2], factor) component.xoffset = start.xoffset - dx component.yoffset = start.yoffset + dy if trace then @@ -3878,7 +4041,7 @@ end --~ if otfdata and otfdata.luatex then --~ for k,v in pairs(otfdata.glyphs) do --~ if v.name:find(name) then ---~ temp[v.name] = v.unicodeenc +--~ temp[v.name] = v.unicode --~ end --~ end --~ end diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua index abe3eaf36..32ea6232a 100644 --- a/tex/context/base/font-tfm.lua +++ b/tex/context/base/font-tfm.lua @@ -151,15 +151,15 @@ function fonts.tfm.check_virtual_id(tfmdata, id) end end --- if t.tounicode = 1 then also characters[n].tounicode = "string" +--[[ldx-- +<p>Beware, the boundingbox is passed as reference so we may not overwrite it +in the process; numbers are of course copies. Here 65536 equals 1pt. (Due to +excessive memory usage in CJK fonts, we no longer pass the boundingbox.)</p> +--ldx]]-- + +local xxx = 0 function fonts.tfm.do_scale(tfmtable, scaledpoints) - -- beware, the boundingbox is passed as reference so we may not overwrite it - -- in the process, numbers are of course copies - -- - -- 65536 = 1pt - -- 1000 units per designsize (not always) - local scale, round = tex.scale, tex.round -- replaces math.floor(n*m+0.5) if scaledpoints < 0 then scaledpoints = (- scaledpoints/1000) * tfmtable.designsize -- already in sp end @@ -171,36 +171,41 @@ function fonts.tfm.do_scale(tfmtable, scaledpoints) end local tc = t.characters local trace = fonts.trace + -- local zerobox = { 0, 0, 0, 0 } for k,v in pairs(tfmtable.characters) do - local w, h, d = v.width, v.height, v.depth + local description = v.description or v -- shared data local chr = { - unicode = v.unicode, - name = v.name, - index = v.index or k, - width = (w == 0 and 0) or scale(w, delta), - height = (h == 0 and 0) or scale(h, delta), - depth = (d == 0 and 0) or scale(d, delta), - class = v.class + unicode = description.unicode, + name = description.name, + index = description.index or k, + width = delta*(description.width or 0), + height = delta*(description.height or 0), + depth = delta*(description.depth or 0), + class = description.class } if trace then - logs.report("define font", string.format("n=%s, u=%s, i=%s, n=%s c=%s",k,v.unicode,v.index,v.name or '-',v.class or '-')) - end - local vb = v.boundingbox - if vb then - chr.boundingbox = scale(vb,delta) + logs.report("define font", string.format("n=%s, u=%s, i=%s, n=%s c=%s",k,description.unicode,description.index,description.name or '-',description.class or '-')) end - local vi = v.italic + -- local vb = v.boundingbox + -- if vb then + -- chr.boundingbox = { vb[1]*delta, vb[2]*delta, vb[3]*delta, vb[4]*delta } + -- else + -- -- chr.boundingbox = zerobox -- most afm en otf files have bboxes so .. + -- end + local vi = description.italic if vi then - chr.italic = scale(vi,delta) + chr.italic = vi*delta end local vk = v.kerns if vk then - chr.kerns = scale(vk,delta) + local tt = {} + for k,v in pairs(vk) do tt[k] = v*delta end + chr.kerns = tt end local vl = v.ligatures if vl then if true then - chr.ligatures = v.ligatures -- shared + chr.ligatures = vl -- shared else local tt = { } for i,l in pairs(vl) do @@ -217,12 +222,11 @@ function fonts.tfm.do_scale(tfmtable, scaledpoints) local ivc = vc[i] local key = ivc[1] if key == "right" or key == "left" or key == "down" or key == "up" then - tt[#tt+1] = { key, scale(ivc[2],delta) } + tt[#tt+1] = { key, ivc[2]*delta } else tt[#tt+1] = ivc -- shared since in cache and untouched end end ---~ print(table.serialize(vc),table.serialize(tt)) chr.commands = tt end tc[k] = chr @@ -230,9 +234,9 @@ function fonts.tfm.do_scale(tfmtable, scaledpoints) local tp = t.parameters for k,v in pairs(tfmtable.parameters) do if k == 1 then - tp[k] = round(v) + tp[k] = v else - tp[k] = scale(v,delta) + tp[k] = v*delta end end -- t.encodingbytes, t.filename, t.fullname, t.name: elsewhere @@ -251,11 +255,10 @@ wasted day but an experience richer.</p> --ldx]]-- function fonts.tfm.scale(tfmtable, scaledpoints) - local scale = tex.scale local t, factor = fonts.tfm.do_scale(tfmtable, scaledpoints) t.factor = factor - t.ascender = scale(tfmtable.ascender or 0, factor) - t.descender = scale(tfmtable.descender or 0, factor) + t.ascender = factor*(tfmtable.ascender or 0) + t.descender = factor*(tfmtable.descender or 0) t.shared = tfmtable.shared or { } t.unique = table.fastcopy(tfmtable.unique or {}) --~ print("scaling", t.name, t.factor) -- , fonts.tfm.hash_features(tfmtable.specification)) diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua index dfacfb291..4ee2871ce 100644 --- a/tex/context/base/l-dir.lua +++ b/tex/context/base/l-dir.lua @@ -10,26 +10,32 @@ dir = { } -- optimizing for no string.find (*) does not save time -if lfs then +if lfs then do - function dir.glob_pattern(path,patt,recurse,action) - local ok, scanner = xpcall(function() return lfs.dir(path) end, function() end) -- kepler safe + local attributes = lfs.attributes + local walkdir = lfs.dir + + local function glob_pattern(path,patt,recurse,action) + local ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe if ok and type(scanner) == "function" then + if not path:find("/$") then path = path .. '/' end for name in scanner do - local full = path .. '/' .. name - local mode = lfs.attributes(full,'mode') + local full = path .. name + local mode = attributes(full,'mode') if mode == 'file' then if name:find(patt) then action(full) end elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then - dir.glob_pattern(full,patt,recurse,action) + glob_pattern(full,patt,recurse,action) end end end end - function dir.glob(pattern, action) + dir.glob_pattern = glob_pattern + + local function glob(pattern, action) local t = { } local action = action or function(name) table.insert(t,name) end local path, patt = pattern:match("^(.*)/*%*%*/*(.-)$") @@ -45,22 +51,26 @@ if lfs then patt = patt:gsub("%?", ".") patt = "^" .. patt .. "$" -- print('path: ' .. path .. ' | pattern: ' .. patt .. ' | recurse: ' .. tostring(recurse)) - dir.glob_pattern(path,patt,recurse,action) + glob_pattern(path,patt,recurse,action) return t end - function dir.globfiles(path,recurse,func,files) + dir.glob = glob + + -- todo: speedup + + local function globfiles(path,recurse,func,files) if type(func) == "string" then local s = func -- alas, we need this indirect way func = function(name) return name:find(s) end end files = files or { } - for name in lfs.dir(path) do + for name in walkdir(path) do if name:find("^%.") then --- skip - elseif lfs.attributes(name,'mode') == "directory" then + elseif attributes(name,'mode') == "directory" then if recurse then - dir.globfiles(path .. "/" .. name,recurse,func,files) + globfiles(path .. "/" .. name,recurse,func,files) end elseif func then if func(name) then @@ -73,6 +83,8 @@ if lfs then return files end + dir.globfiles = globfiles + -- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex") -- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex") -- t = dir.glob("c:/data/develop/context/texmf/**/*.tex") @@ -81,7 +93,7 @@ if lfs then -- print(dir.ls("*.tex")) function dir.ls(pattern) - return table.concat(dir.glob(pattern),"\n") + return table.concat(glob(pattern),"\n") end --~ mkdirs("temp") @@ -108,4 +120,4 @@ if lfs then dir.makedirs = dir.mkdirs -end +end end diff --git a/tex/context/base/lang-ini.mkii b/tex/context/base/lang-ini.mkii index 88282a003..7a1937ec5 100644 --- a/tex/context/base/lang-ini.mkii +++ b/tex/context/base/lang-ini.mkii @@ -29,6 +29,16 @@ \dodoloadpatterns{#1}{#2}{}{}% \fi} +\beginXETEX + +\def\mkdoloadpatterns#1#2% + {\letvalue{\??la#2\s!encoding}\empty + \letvalue{\??la#2\s!mapping }\empty + \dodoloadpatterns{#1}{#2}{}{}} + +\endXETEX + + \def\setuphyppatencoding {\pathypsettings \enableregime[utf]} diff --git a/tex/context/base/lang-mis.tex b/tex/context/base/lang-mis.tex index 9fe9df0c6..cfd189e18 100644 --- a/tex/context/base/lang-mis.tex +++ b/tex/context/base/lang-mis.tex @@ -178,7 +178,8 @@ %D words. \TEX\ hackers will recognise the next two macro's: \ifx\prewordbreak \undefined \def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi -\ifx\postwordbreak \undefined \def\postwordbreak{\penalty\zerocount\prewordbreak} \fi +%ifx\postwordbreak \undefined \def\postwordbreak{\penalty\zerocount \prewordbreak } \fi +\ifx\postwordbreak \undefined \def\postwordbreak{\penalty\zerocount \hskip\zeropoint\relax} \fi \ifx\hspaceamount \undefined \def\hspaceamount#1#2{\kern.16667em} \fi % language specific @@ -382,7 +383,7 @@ \else\ifconditional\punctafterdiscretionary \prewordbreak\hbox{#1}\relax \else - \prewordbreak\discretionary{#2}{#3}{#4}\prewordbreak + \prewordbreak\discretionary{#2}{#3}{#4}\postwordbreak % was prewordbreak \fi\fi} \definetextmodediscretionary {} @@ -412,7 +413,7 @@ \definetextmodediscretionary ^ {\prewordbreak\discretionary{\hbox{$|$}}{}{\hbox{$|$}}% - \allowbreak\postwordbreak} + \allowbreak\postwordbreak} % bugged \definetextmodediscretionary < {\beginofsubsentence\prewordbreak\beginofsubsentencespacing} diff --git a/tex/context/base/luat-lib.tex b/tex/context/base/luat-lib.tex index d557ca4b6..149e4d350 100644 --- a/tex/context/base/luat-lib.tex +++ b/tex/context/base/luat-lib.tex @@ -59,6 +59,7 @@ \registerctxluafile{luat-log} {1.001} \registerctxluafile{luat-zip} {1.001} \registerctxluafile{luat-tex} {1.001} +\registerctxluafile{luat-tre} {1.001} \startruntimeluacode \edef\asciia{\ctxlua{tex.sprint(input.logmode())}} diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua index d2cfc17e0..5750a5ef9 100644 --- a/tex/context/base/node-ini.lua +++ b/tex/context/base/node-ini.lua @@ -509,26 +509,60 @@ callback.register('hpack_filter' , nodes.processors.hpack_filter) do - local expand = { - list = true, - pre = true, - post = true, - spec = true, - attr = true, - components = true, + -- beware, some field names will change in a next release of luatex + + local expand = table.tohash { + "list", -- list_ptr & ins_ptr & adjust_ptr + "pre", -- + "post", -- + "spec", -- glue_ptr + "top_skip", -- + "attr", -- + "replace", -- nobreak + "components", -- lig_ptr + "box_left", -- + "box_right", -- + "glyph", -- margin_char + "leader", -- leader_ptr + "action", -- action_ptr + "value", -- user_defined nodes with subtype 'a' en 'n' + } + + -- page_insert: "height", "last_ins_ptr", "best_ins_ptr" + -- split_insert: "height", "last_ins_ptr", "best_ins_ptr", "broken_ptr", "broken_ins" + + local ignore = table.tohash { + "page_insert", + "split_insert", + "ref_count", + } + + local dimension = table.tohash { + "width", "height", "depth", "shift", + "stretch", "shrink", + "xoffset", "yoffset", + "surround", + "kern", + "box_left_width", "box_right_width" } -- flat: don't use next, but indexes -- verbose: also add type -- can be sped up - function nodes.astable(n,sparse) + nodes.dimensionfields = dimension + nodes.listablefields = expand + nodes.ignorablefields = ignore + + -- not ok yet: + + function nodes.astable(n,sparse) -- not yet ok local f, t = node.fields(n.id,n.subtype), { } for i=1,#f do local v = f[i] local d = n[v] if d then - if v == "ref_count" or v == "id" then + if ignore[v] or v == "id" then -- skip elseif expand[v] then -- or: type(n[v]) ~= "string" or type(n[v]) ~= "number" or type(n[v]) ~= "table" t[v] = "pointer to list" @@ -545,23 +579,36 @@ do return t end - function nodes.totable(n,flat,verbose) - local function totable(n) - local f = node.fields(n.id,n.subtype) + local nodefields = node.fields + local nodetype = node.type + + -- under construction: + + local function totable(n,flat,verbose) + local function to_table(n) + local f = nodefields(n.id,n.subtype) local tt = { } - for _,v in ipairs(f) do - if n[v] then - if v == "ref_count" then + for k=1,#f do + local v = f[k] + local nv = n[v] + if nv then + if ignore[v] then -- skip - elseif expand[v] then -- or: type(n[v]) ~= "string" or type(n[v]) ~= "number" or type(n[v]) ~= "table" - tt[v] = nodes.totable(n[v],flat,verbose) + elseif expand[v] then + if type(nv) == "number" or type(nv) == "string" then + tt[v] = nv + else + tt[v] = totable(nv,flat,verbose) + end + elseif type(nv) == "table" then + tt[v] = nv -- totable(nv,flat,verbose) -- data else - tt[v] = n[v] + tt[v] = nv end end end if verbose then - tt.type = node.type(tt.id) + tt.type = nodetype(tt.id) end return tt end @@ -569,14 +616,14 @@ do if flat then local t = { } while n do - t[#t+1] = totable(n) + t[#t+1] = to_table(n) n = n.next end return t else - local t = totable(n) + local t = to_table(n) if n.next then - t.next = nodes.totable(n.next,flat,verbose) + t.next = totable(n.next,flat,verbose) end return t end @@ -585,10 +632,14 @@ do end end + nodes.totable = totable + local function key(k) return ((type(k) == "number") and "["..k.."]") or k end + -- not ok yet: + local function serialize(root,name,handle,depth,m) handle = handle or print if depth then @@ -612,7 +663,7 @@ do if root then local fld if root.id then - fld = node.fields(root.id,root.subtype) -- we can cache these (todo) + fld = nodefields(root.id,root.subtype) -- we can cache these (todo) else fld = table.sortedkeys(root) end @@ -756,3 +807,19 @@ do end end + +-- goodie +-- +-- if node.valid(tex.box[0]) then print("valid node") end + +--~ do +--~ local n = node.new(0,0) +--~ local m = getmetatable(n) +--~ m.__metatable = 'node' +--~ node.free(n) + +--~ function node.valid(n) +--~ return n and getmetatable(n) == 'node' +--~ end +--~ end + diff --git a/tex/context/base/page-ini.tex b/tex/context/base/page-ini.tex index 783a358c9..6c0760d8b 100644 --- a/tex/context/base/page-ini.tex +++ b/tex/context/base/page-ini.tex @@ -1463,11 +1463,12 @@ \chardef\testpagemethod \zerocount % todo: \testnewpage[method=,lines=,voffset=] \chardef\testpagetrigger\zerocount -\def\testpage {\dotripleempty\dotestpage[\plusone]} % -\def\testpageonly{\dotripleempty\dotestpage[\plustwo]} % no penalties added to the mvl +\def\testpage {\dotripleempty\dotestpage[\plusone ]} % +\def\testpageonly{\dotripleempty\dotestpage[\plustwo ]} % no penalties added to the mvl +\def\testpagesync{\dotripleempty\dotestpage[\plusthree]} % force sync \def\dotestpage[#1][#2][#3]% don't change, only add more methods - {%\relax % needed before \if + {\relax % needed before \if \ifpaginageblokkeerd \endgraf \else @@ -1516,13 +1517,18 @@ \fi \fi \else - % force page break / new / does not work as expected - % never: \penalty-\!!tenthousand\relax + \ifnum#1=\plusthree + \flushpagesofar + \fi \fi \else \ifnum#1=\plusone\goodbreak\fi \fi \fi} + +\ifx\flushpagesofar\undefined + \let\flushpagesofar\relax +\fi \def\testcolumn {\dodoubleempty\dotestcolumn} diff --git a/tex/context/interface/keys-cz.xml b/tex/context/interface/keys-cz.xml index 5fee5f4ff..f5254e44e 100644 --- a/tex/context/interface/keys-cz.xml +++ b/tex/context/interface/keys-cz.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="cz" version="2007.12.07 19:14"> +<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="cz" version="2007.12.17 14:54"> <cd:variables> <cd:variable name="lesshyphenation" value="lesshyphenation"/> diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml index 08e389849..a68dcc203 100644 --- a/tex/context/interface/keys-de.xml +++ b/tex/context/interface/keys-de.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="de" version="2007.12.07 19:14"> +<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="de" version="2007.12.17 14:54"> <cd:variables> <cd:variable name="lesshyphenation" value="lesshyphenation"/> diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml index ef8c7d8bb..f015b51eb 100644 --- a/tex/context/interface/keys-en.xml +++ b/tex/context/interface/keys-en.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="en" version="2007.12.07 19:14"> +<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="en" version="2007.12.17 14:54"> <cd:variables> <cd:variable name="lesshyphenation" value="lesshyphenation"/> diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml index 983cd6543..ec8bef3ca 100644 --- a/tex/context/interface/keys-fr.xml +++ b/tex/context/interface/keys-fr.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="fr" version="2007.12.07 19:14"> +<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="fr" version="2007.12.17 14:54"> <cd:variables> <cd:variable name="lesshyphenation" value="lesshyphenation"/> diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml index 59f634049..246bfddbf 100644 --- a/tex/context/interface/keys-it.xml +++ b/tex/context/interface/keys-it.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="it" version="2007.12.07 19:14"> +<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="it" version="2007.12.17 14:54"> <cd:variables> <cd:variable name="lesshyphenation" value="lesshyphenation"/> diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml index 971eac041..729027cc5 100644 --- a/tex/context/interface/keys-nl.xml +++ b/tex/context/interface/keys-nl.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="nl" version="2007.12.07 19:14"> +<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="nl" version="2007.12.17 14:54"> <cd:variables> <cd:variable name="lesshyphenation" value="lesshyphenation"/> diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml index 23eb24d3d..c9fa172e5 100644 --- a/tex/context/interface/keys-ro.xml +++ b/tex/context/interface/keys-ro.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="ro" version="2007.12.07 19:14"> +<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="ro" version="2007.12.17 14:54"> <cd:variables> <cd:variable name="lesshyphenation" value="lesshyphenation"/> |