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"/>  | 
