diff options
Diffstat (limited to 'tex')
67 files changed, 3644 insertions, 2970 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 9a66b4b07..c6ff7e991 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2019.05.18 10:42} +\newcontextversion{2019.05.25 10:45} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index e54769554..e5c386698 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2019.05.18 10:42} +\edef\contextversion{2019.05.25 10:45} %D For those who want to use this: @@ -34,10 +34,7 @@ \ifx\normalinput\undefined \let\normalinput\input \fi -\def\loadcorefile#1{\normalinput#1\relax} \def\loadmarkfile#1{\normalinput#1.\mksuffix\relax} -\def\loadmkiifile#1{\normalinput#1\relax} -\def\loadmkivfile#1{} %D First we load the system modules. These implement a lot of %D manipulation macros. The first one loads \PLAIN\ \TEX, as diff --git a/tex/context/base/mkii/mult-de.mkii b/tex/context/base/mkii/mult-de.mkii index 46a239304..5557eb7b8 100644 --- a/tex/context/base/mkii/mult-de.mkii +++ b/tex/context/base/mkii/mult-de.mkii @@ -373,6 +373,7 @@ \setinterfacevariable{nohz}{nohz} \setinterfacevariable{noline}{noline} \setinterfacevariable{nomarking}{keinebeschriftung} +\setinterfacevariable{nomenubar}{nomenubar} \setinterfacevariable{none}{kein} \setinterfacevariable{nonumber}{nonumber} \setinterfacevariable{norepeat}{norepeat} diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua index 56250e16d..e53c3c514 100644 --- a/tex/context/base/mkiv/anch-pos.lua +++ b/tex/context/base/mkiv/anch-pos.lua @@ -54,8 +54,6 @@ local texget = tex.get local texsp = tex.sp ----- texsp = string.todimen -- because we cache this is much faster but no rounding -local pdf = pdf -- h and v are variables - local setmetatableindex = table.setmetatableindex local setmetatablenewindex = table.setmetatablenewindex @@ -1449,3 +1447,12 @@ statistics.register("positions", function() return nil end end) + +-- We support the low level positional commands too: + +local newsavepos = nodes.pool.savepos +local implement = interfaces.implement + +implement { name = "savepos", actions = function() context(newsavepos()) end } +implement { name = "lastxpos", actions = function() context(gethpos()) end } +implement { name = "lastypos", actions = function() context(getvpos()) end } diff --git a/tex/context/base/mkiv/anch-pos.mkiv b/tex/context/base/mkiv/anch-pos.mkiv index fbebb5f17..68cb2f723 100644 --- a/tex/context/base/mkiv/anch-pos.mkiv +++ b/tex/context/base/mkiv/anch-pos.mkiv @@ -497,4 +497,10 @@ \let\doifpositionsusedelse\doifelsepositionsused +%D Moved here: + +\unexpanded\def\savepos {\clf_savepos} +\unexpanded\def\lastxpos{\numexpr\clf_lastxpos\relax} +\unexpanded\def\lastypos{\numexpr\clf_lastypos\relax} + \protect \endinput diff --git a/tex/context/base/mkiv/back-ini.lua b/tex/context/base/mkiv/back-ini.lua index b7ecce00b..bc4a67bc0 100644 --- a/tex/context/base/mkiv/back-ini.lua +++ b/tex/context/base/mkiv/back-ini.lua @@ -8,31 +8,21 @@ if not modules then modules = { } end modules ['back-ini'] = { local next, type = next, type local format = string.format -local sind, cosd, abs = math.sind, math.cosd, math.abs -local insert, remove = table.insert, table.remove -local unpack = unpack backends = backends or { } local backends = backends -local trace_backend = false trackers.register("backend.initializers", function(v) trace_finalizers = v end) +local context = context +local trace = false trackers.register("backend", function(v) trace = v end) local report = logs.reporter("backend") -local report_backend = logs.reporter("backend","initializing") local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex local setaction = nodes.tasks.setaction -local scanners = tokens.scanners -local scannumber = scanners.number -local scankeyword = scanners.keyword -local scancount = scanners.count -local scanstring = scanners.string - -local scanners = interfaces.scanners - local implement = interfaces.implement +local variables = interfaces.variables local texset = tex.set @@ -87,11 +77,11 @@ function backends.install(what) if type(what) == "string" then local backend = backends[what] if backend then - if trace_backend then + if trace then if backend.comment then - report_backend("initializing backend %a, %a",what,backend.comment) + report("initializing backend %a, %a",what,backend.comment) else - report_backend("initializing backend %a",what) + report("initializing backend %a",what) end end backends.current = what @@ -101,8 +91,8 @@ function backends.install(what) setmetatableindex(plugin, default) setmetatableindex(target, plugin) end - elseif trace_backend then - report_backend("no backend named %a",what) + elseif trace then + report("no backend named %a",what) end end end @@ -139,7 +129,7 @@ interfaces.implement { name = "setrealspaces", arguments = "string", actions = function(v) - setaction("shipouts","nodes.handlers.accessibility",v == interfaces.variables.yes) + setaction("shipouts","nodes.handlers.accessibility",v == variables.yes) end } @@ -197,120 +187,3 @@ implement { function backends.noflatelua() return status.late_callbacks or 0 end - --- - -local stack = { } -local restore = true -- false - -local nodepool = nodes.pool -local savenode = nodepool.save -local restorenode = nodepool.restore -local setmatrixnode = nodepool.setmatrix - -updaters.register("backend.update",function() - savenode = nodepool.save - restorenode = nodepool.restore - setmatrixnode = nodepool.setmatrix -end) - -local function stopsomething() - local top = remove(stack) - if top == false then - -- not wrapped - elseif top == true then - context(restorenode()) - elseif top then - context(setmatrixnode(unpack(top))) -- not really needed anymore - context(restorenode()) - else - -- nesting error - end -end - -local function startrotation() - local a = scannumber() - if a == 0 then - insert(stack,false) - else - local s, c = sind(a), cosd(a) - if abs(s) < 0.000001 then - s = 0 -- otherwise funny -0.00000 - end - if abs(c) < 0.000001 then - c = 0 -- otherwise funny -0.00000 - end - context(savenode()) - context(setmatrixnode(c,s,-s,c)) - insert(stack,restore and { c, -s, s, c } or true) - end -end - -implement { name = "startrotation", actions = startrotation } -implement { name = "stoprotation", actions = stopsomething } - -local function startscaling() -- at the tex end we use sx and sy instead of rx and ry - local rx, ry = 1, 1 - while true do - if scankeyword("rx") then - rx = scannumber() - elseif scankeyword("ry") then - ry = scannumber() - -- elseif scankeyword("revert") then - -- local top = stack[#stack] - -- if top then - -- rx = top[1] - -- ry = top[4] - -- else - -- rx = 1 - -- ry = 1 - -- end - else - break - end - end - if rx == 1 and ry == 1 then - insert(stack,false) - else - if rx == 0 then - rx = 0.0001 - end - if ry == 0 then - ry = 0.0001 - end - context(savenode()) - context(setmatrixnode(rx,0,0,ry)) - insert(stack,restore and { 1/rx, 0, 0, 1/ry } or true) - end -end - -implement { name = "startscaling", actions = startscaling } -implement { name = "stopscaling", actions = stopsomething } - -local function startmatrix() -- rx sx sy ry -- tx, ty - local rx, sx, sy, ry = 1, 0, 0, 1 - while true do - if scankeyword("rx") then rx = scannumber() - elseif scankeyword("ry") then ry = scannumber() - elseif scankeyword("sx") then sx = scannumber() - elseif scankeyword("sy") then sy = scannumber() - else break end - end - if rx == 1 and sx == 0 and sy == 0 and ry == 1 then - insert(stack,false) - else - context(savenode()) - context(setmatrixnode(rx,sx,sy,ry)) - insert(stack,store and { -rx, -sx, -sy, -ry } or true) - end -end - -implement { name = "startmatrix", actions = startmatrix } -implement { name = "stopmatrix", actions = stopsomething } - -local function startmirroring() - context(setmatrixnode(-1,0,0,1)) -end - -implement { name = "startmirroring", actions = startmirroring } -implement { name = "stopmirroring", actions = startmirroring } -- not: stopsomething diff --git a/tex/context/base/mkiv/back-ini.mkiv b/tex/context/base/mkiv/back-ini.mkiv index 8729403f8..ff19d0229 100644 --- a/tex/context/base/mkiv/back-ini.mkiv +++ b/tex/context/base/mkiv/back-ini.mkiv @@ -11,35 +11,12 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D Most will go away here as it is replaced by \LUA\ calls to -%D backend functions. - \writestatus{loading}{ConTeXt Backend Macros / Initialization} -%D The exact page model depends on the backend so we just define some -%D variables that are used. A helper at the \LUA\ end will synchronize -%D with the internal variables. We store these in the format. - -% \newdimen\backendpageheight -% \newdimen\backendpagewidth -% \newdimen\backendinchoffset \backendinchoffset=1in - -%D Now we load the \LUA\ code: - \registerctxluafile{back-ini}{} -\registerctxluafile{back-res}{} - -\doifelsefileexists{back-out.mkiv}{\loadmarkfile{back-out}}{} - -%D We currently have a curious mix between tex and lua backend handling but -%D eventually most will move to \LUA. \unprotect -\ifdefined\everybackendshipout \else \newtoks\everybackendshipout \fi -\ifdefined\everylastbackendshipout \else \newtoks\everylastbackendshipout \fi -\ifdefined\everybackendlastinshipout \else \newtoks\everybackendlastinshipout \fi % e.g. finalize via latelua - %D Right from the start \CONTEXT\ had a backend system based on runtime pluggable %D code. As most backend issues involved specials and since postprocessors had not %D that much in common, we ended up with a system where we could switch backend as @@ -52,104 +29,30 @@ %D At this moment \DVI\ is no longer used for advanced document output and we %D therefore dropped support for this format. Future versions might support more %D backends again, but this has a low priority. -%D -%D Not everything here makes sense and the content of this file will definitely -%D change (or even go away). - -% rotation - -\unexpanded\def\dostartrotation#1% - {\forcecolorhack - \clf_startrotation#1\relax} % todo: implement without Q q - -\unexpanded\def\dostoprotation - {\clf_stoprotation - \forcecolorhack} - -% scaling - -\unexpanded\def\dostartscaling#1#2% - {\forcecolorhack - \clf_startscaling rx #1 ry #2\relax} - -\unexpanded\def\dostopscaling - {\clf_stopscaling - \forcecolorhack} - -% mirroring - -\unexpanded\def\dostartmirroring - {\clf_startmirroring} - -\unexpanded\def\dostopmirroring - {\clf_stopmirroring} - -% transform - -\unexpanded\def\dotransformnextbox#1#2#3#4#5#6% - {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}} -\unexpanded\def\dodotransformnextbox#1#2#3#4#5#6% - {\hpack - {\kern #5\onebasepoint - \raise#6\onebasepoint - \hpack - {\clf_startmatrix rx #1 sx #2 sy #3 ry #4\relax - \box\nextbox - \clf_stopmatrix}}} +\ifdefined\outputmode + \outputmode\plusone + \let\outputmode\relax + \newcount\outputmode + \outputmode\plusone + \let\normaloutputmode\outputmode +\fi -%D \macros -%D {back_ovalbox} -%D -%D When we look at the implementation, this is a complicated one. There are seven -%D arguments. -%D -%D \starttyping -%D \back_ovalbox {w} {h} {d} {linewidth} {radius} {stroke} {fill} {variant} -%D \stoptyping -%D -%D This command has to return a \type {\vbox} which can be used to lay over another -%D one (with text). The radius is in degrees, the stroke and fill are~\type {1} -%D (true) of~\type {0} (false). - -\let\back_ovalbox \gobbleeightarguments - -%D \macros -%D {dostartclipping,dostopclipping} -%D -%D Clipping is implemented in such a way that an arbitrary code can be fed. -%D -%D \starttyping -%D \dostartclipping {pathname} {width} {height} -%D \dostopclipping -%D \stoptyping +%D The exact page model depends on the backend so we just define some variables that +%D are used. A helper at the \LUA\ end will synchronize with the internal variables. +%D We store these in the format. -\let \dostartclipping \gobblethreearguments -\let \dostopclipping \donothing - -%D \macros -%D {jobsuffix} -%D -%D By default, \TEX\ produces \DVI\ files which can be converted to other filetypes. -%D Sometimes it is handy to know what the target file will be. In other driver -%D modules we wil set \type {\jobsuffix} to \type {pdf}. - -%D Backend configuration: +\ifdefined\everybackendshipout \else \newtoks\everybackendshipout \fi +\ifdefined\everylastbackendshipout \else \newtoks\everylastbackendshipout \fi +\ifdefined\everybackendlastinshipout \else \newtoks\everybackendlastinshipout \fi \installcorenamespace{backend} \installsetuponlycommandhandler \??backend {backend} -\let\jobsuffix\empty - -\unexpanded\def\back_job_set_suffix#1% % checking could happen in mode - {\ifx\jobsuffix\empty\else\resetsystemmode\jobsuffix\fi - \edef\jobsuffix{#1}% - \ifx\jobsuffix\empty\else\setsystemmode \jobsuffix\fi} - -\back_job_set_suffix{pdf} % default - -% \setupbackend[space=yes] % replace spacing in (pdf) file +%D \starttyping +%D \setupbackend[space=yes] +%D \stoptyping \appendtoks \clf_setrealspaces{\backendparameter\c!space}% diff --git a/tex/context/base/mkiv/back-lua.mkiv b/tex/context/base/mkiv/back-lua.mkiv new file mode 100644 index 000000000..82ba8f9f1 --- /dev/null +++ b/tex/context/base/mkiv/back-lua.mkiv @@ -0,0 +1,18 @@ +%D \module +%D [ file=back-lua, +%D version=2018.07.26, +%D title=\CONTEXT\ Backend Macros, +%D subtitle=\LUA, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\ifcase\contextlmtxmode \else + \registerctxluafile{back-lua}{optimize} +\fi + +\endinput diff --git a/tex/context/base/mkiv/back-mps.mkiv b/tex/context/base/mkiv/back-mps.mkiv new file mode 100644 index 000000000..0a6640614 --- /dev/null +++ b/tex/context/base/mkiv/back-mps.mkiv @@ -0,0 +1,18 @@ +%D \module +%D [ file=back-mps, +%D version=2018.07.26, +%D title=\CONTEXT\ Backend Macros, +%D subtitle=\METAPOST, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\ifcase\contextlmtxmode \else + \registerctxluafile{back-mps}{optimize} +\fi + +\endinput diff --git a/tex/context/base/mkiv/back-out.lua b/tex/context/base/mkiv/back-out.lua index 176a71f78..8fc2a048f 100644 --- a/tex/context/base/mkiv/back-out.lua +++ b/tex/context/base/mkiv/back-out.lua @@ -1,6 +1,6 @@ if not modules then modules = { } end modules ['back-out'] = { version = 1.001, - comment = "companion to lpdf-ini.mkiv", + comment = "companion to back-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" diff --git a/tex/context/base/mkiv/back-out.mkiv b/tex/context/base/mkiv/back-out.mkiv index 26548a0a4..492af2463 100644 --- a/tex/context/base/mkiv/back-out.mkiv +++ b/tex/context/base/mkiv/back-out.mkiv @@ -11,6 +11,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +\ifcase\contextlmtxmode\endinput\fi + \registerctxluafile{back-out}{} \let\normalimmediate\immediate diff --git a/tex/context/base/mkiv/back-pdf.lua b/tex/context/base/mkiv/back-pdf.lua index 8886967e0..5f845fdcd 100644 --- a/tex/context/base/mkiv/back-pdf.lua +++ b/tex/context/base/mkiv/back-pdf.lua @@ -10,17 +10,38 @@ if not modules then modules = { } end modules ['back-pdf'] = { -- the way we manage resources, info, etc. Users should use the \type {lpdf} -- interface instead. If needed I will provide replacement functionality. +local setmetatableindex = table.setmetatableindex + interfaces.implement { name = "setpdfcompression", arguments = { "integer", "integer" }, actions = lpdf.setcompression, } -if CONTEXTLMTXMODE == 0 then - updaters.apply("backend.update.pdf") - updaters.apply("backend.update.lpdf") - updaters.apply("backend.update.tex") - updaters.apply("backend.update") +do + + local dummy = function() end + local report = logs.reporter("backend") + + local function unavailable(t,k) + report("calling unavailable pdf.%s function",k) + t[k] = dummy + return dummy + end + + updaters.register("backend.update",function() + -- + -- For now we keep this for tikz. If really needed some more can be made + -- accessible but it has to happen in a controlled way then, for instance + -- by first loading or enabling some compatibility layer so that we can + -- trace possible interferences. + -- + pdf = { + immediateobj = pdf.immediateobj + } + setmetatableindex(pdf,unavailable) + end) + end backends.install("pdf") diff --git a/tex/context/base/mkiv/back-pdf.mkiv b/tex/context/base/mkiv/back-pdf.mkiv index 776581413..80130577c 100644 --- a/tex/context/base/mkiv/back-pdf.mkiv +++ b/tex/context/base/mkiv/back-pdf.mkiv @@ -11,14 +11,23 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D The less there is here, the better. +%D The less there is here, the better. After a decade it is time to remove the \type +%D {\pdf*} ones completely. For the moment I keep them commented but even that will +%D go away. \writestatus{loading}{ConTeXt Backend Macros / PDF} \registerctxluafile{lpdf-ini}{optimize} \ifcase\contextlmtxmode\relax - \registerctxluafile{lpdf-nod}{} + % \doifelsefile {lpdf-nod-test.lua} { + % \registerctxluafile{lpdf-nod-test}{} + % } { + \registerctxluafile{lpdf-nod}{} + % } + \registerctxluafile{lpdf-eng}{optimize} +\else + \registerctxluafile{lpdf-lmt}{optimize} \fi \registerctxluafile{lpdf-col}{} @@ -47,10 +56,9 @@ \registerctxluafile{lpdf-emb}{optimize} \fi -\registerctxluafile{back-pdp}{} - \registerctxluafile{lpdf-fnt}{} +\registerctxluafile{back-pdp}{} \registerctxluafile{back-pdf}{} % some code will move to lpdf-* \loadmarkfile{back-u3d} % this will become a module @@ -61,167 +69,37 @@ %D We will minimize the number of calls to \PDF\ specific primitives and delegate %D all management and injection of code to the backend. %D -%D Here we initialize some internal quantities. We also protect them. - -\ifdefined\outputmode - \outputmode\plusone - \let\outputmode\relax - \newcount\outputmode - \outputmode\plusone - \let\normaloutputmode\outputmode -\fi - %D Because we do a lot in \LUA\ and don't want interferences, we nil most of the %D \PDFTEX\ primitives. Of course one can always use the \type {\pdfvariable}, %D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably %D have bad side effects. -%D For the moment we put these here as they are pdf related but they might move to a -%D better place. We overload the primitives with our own but use a bit of -%D indirection for the purpose of tracing. Some of these are needes for packages like -%D tikz. - -\unexpanded\def\saveboxresource {\clf_saveboxresource} -\unexpanded\def\lastsavedboxresourceindex {\numexpr\clf_lastsavedboxresourceindex\relax} -\unexpanded\def\useboxresource {\clf_useboxresource} - -\unexpanded\def\saveimageresource {\clf_saveimageresource} -\unexpanded\def\lastsavedimageresourceindex{\numexpr\clf_lastsavedimageresourceindex\relax} -\unexpanded\def\lastsavedimageresourcepages{\numexpr\clf_lastsavedimageresourcepages\relax} -\unexpanded\def\useimageresource {\clf_useimageresource} - -%D Maybe these are used: - -\unexpanded\def\savepos {\clf_savepos} - \def\lastxpos{\clf_lastxpos} - \def\lastypos{\clf_lastypos} - -%D We do some interception: - \unexpanded\def\pdfextension{\clf_pdfextension} \def\pdffeedback {\clf_pdffeedback} -%D These are no-ops and don't even intercept what comes next. We used to use -%D token registers for some so that they kept working but now we just abort the -%D run. - -\unexpanded\def\pdfannot {\clf_pdfannot} -\unexpanded\def\pdfcolorstack {\unsupportedcs\pdfcolorstack} -\unexpanded\def\pdfcolorstackinit{\unsupportedcs\pdfcolorstackinit} -\unexpanded\def\pdfdest {\clf_pdfdest} -\unexpanded\def\pdfendlink {\unsupportedcs\pdfendlink} -\unexpanded\def\pdfendthread {\unsupportedcs\pdfendthread} -\unexpanded\def\pdffontattr {\unsupportedcs\pdffontattr} -\unexpanded\def\pdfglyphtounicode{\unsupportedcs\pdfglyphtounicode} -\unexpanded\def\pdfoutline {\unsupportedcs\pdfoutline} -\unexpanded\def\pdfstartlink {\unsupportedcs\pdfstartlink} -\unexpanded\def\pdfstartthread {\unsupportedcs\pdfstartthread} -\unexpanded\def\pdfthread {\unsupportedcs\pdfthread} - -\unexpanded\def\pdfcatalog {\unsupportedcs\pdfcatalog} -\unexpanded\def\pdfinfo {\unsupportedcs\pdfinfo} -\unexpanded\def\pdfnames {\unsupportedcs\pdfnames} -\unexpanded\def\pdftrailer {\unsupportedcs\pdftrailer} -\unexpanded\def\pdfpageresources {\unsupportedcs\pdfpageresources} -\unexpanded\def\pdfpageattr {\unsupportedcs\pdfpageattr} -\unexpanded\def\pdfpagesattr {\unsupportedcs\pdfpagesattr} -\unexpanded\def\pdfxformattr {\unsupportedcs\pdfxformattr} -\unexpanded\def\pdfxformresources{\unsupportedcs\pdfxformresources} - -%D There is no need for these: - -\unexpanded\def\pdfmapfile {\unsupportedcs\pdfmapfile} -\unexpanded\def\pdfmapline {\unsupportedcs\pdfmapline} - -%D These have been no-ops for a long time so now we just abort on their usage. - -\unexpanded\def\pdfcompresslevel {\unsupportedcs\pdfcompresslevel} -\unexpanded\def\pdfobjcompresslevel{\unsupportedcs\pdfobjcompresslevel} - -%D But we still provide: - -\unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} -\unexpanded\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree} -\unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } -\unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} - -%D We don't support these directives, at least not this way. If they are needed -%D by third party modules we can provide some interface. - -% pdfcreationdate -\def\pdfdecimaldigits {\unsupportedcs\pdfdecimaldigits} -\def\pdfdestmargin {\unsupportedcs\pdfdestmargin} -% pdffontname -% pdffontobjnum -\def\pdffontsize {\unsupportedcs\pdffontsize} -\def\pdfgamma {\unsupportedcs\pdfgamma} -\def\pdfgentounicode {\unsupportedcs\pdfgentounicode} -\def\pdfhorigin {\unsupportedcs\pdfhorigin} -\def\pdfignoreunknownimages {\unsupportedcs\pdfignoreunknownimages} -\def\pdfimageaddfilename {\unsupportedcs\pdfimageaddfilename} -\def\pdfimageapplygamma {\unsupportedcs\pdfimageapplygamma} -\def\pdfimagegamma {\unsupportedcs\pdfimagegamma} -\def\pdfimagehicolor {\unsupportedcs\pdfimagehicolor} -\def\pdfimageresolution {\unsupportedcs\pdfimageresolution} -\def\pdfincludechars {\unsupportedcs\pdfincludechars} -\def\pdfinclusioncopyfonts {\unsupportedcs\pdfinclusioncopyfonts} -\def\pdfinclusionerrorlevel {\unsupportedcs\pdfinclusionerrorlevel} -\def\pdfinfoomitdate {\unsupportedcs\pdfinfoomitdate} -% pdflastannot -% pdflastlink -\def\pdflinkmargin {\unsupportedcs\pdflinkmargin} -\def\pdfmajorversion {\unsupportedcs\pdfmajorversion} -\def\pdfminorversion {\unsupportedcs\pdfminorversion} -\def\pdfpagebox {\unsupportedcs\pdfpagebox} -% pdfpageref -\def\pdfpkfixeddpi {\unsupportedcs\pdfpkfixeddpi} -\def\pdfpkmode {\unsupportedcs\pdfpkmode} -\def\pdfpkresolution {\unsupportedcs\pdfpkresolution} -% pdfretval -\def\pdfsuppressoptionalinfo {\unsupportedcs\pdfsuppressoptionalinfo} -\def\pdfsuppressptexinfo {\unsupportedcs\pdfsuppressptexinfo} -% pdftexrevision -% pdftexversion -\def\pdfthreadmargin {\unsupportedcs\pdfthreadmargin} -\def\pdftrailerid {\unsupportedcs\pdftrailerid} -\def\pdfuniqueresname {\unsupportedcs\pdfuniqueresname} -\def\pdfvorigin {\unsupportedcs\pdfvorigin} -\def\pdfxformmargin {\unsupportedcs\pdfxformmargin} -% \pdfxformname - -%D These are still accepted but are normally not needed. - -\let\pdfxform \saveboxresource -\let\pdfximage \saveimageresource - -\let\pdflastxform \lastsavedboxresourceindex -\let\pdflastximage \lastsavedimageresourceindex - -\let\pdfrefxform \useboxresource -\let\pdfrefximage \useimageresource - -\let\pdflastximagepages \lastsavedimageresourcepages - -\let\pdfsavepos \savepos -\let\pdflastxpos \lastxpos -\let\pdflastypos \lastypos - -%D For the moment we keep these as they are but they will become \LUA\ calls -%D eventually, after which we will nil the three \type {\pdf} interface primitives. - -\unexpanded\def\pdfliteral {\clf_pdfliteral}% +%D For the moment we keep this for tikz but hopefully it will at some point use +%D the proper ones. Consider them obsolete: +\unexpanded\def\pdfliteral {\clf_pdfliteral} \unexpanded\def\pdfobj {\clf_pdfobj}% -\unexpanded\def\pdflastobj {\numexpr\clf_pdflastobj\relax}% +\unexpanded\def\pdflastobj {\numexpr\clf_pdflastobj\relax} +\unexpanded\def\pdfrefobj {\clf_pdfrefobj } -\unexpanded\def\pdfrefobj {\pdfextension refobj } \unexpanded\def\pdfrestore {\clf_restore} \unexpanded\def\pdfsave {\clf_save} \unexpanded\def\pdfsetmatrix{\clf_setmatrix} -%D This one can be consulted by users although the suffix is also a system mode. + \let\pdfxform \saveboxresource + \let\pdflastxform \lastsavedboxresourceindex + \let\pdfrefxform \useboxresource -\back_job_set_suffix{pdf} +%D Here are quick and dirty compression flippers, mostly used when testing something +%D as one can best stick to the defaults that also adapt to specific standards. + +\unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} +\unexpanded\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree} +\unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } +\unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} %D PDF/X (maybe combine the two lua calls) @@ -229,11 +107,13 @@ [xmpfile=] \appendtoks - \doifsomething{\backendparameter{xmpfile}} - {\clf_setxmpfile{\backendparameter{xmpfile}}}% + \edef\p_file{\backendparameter{xmpfile}}% + \ifx\p_file\empty\else + \clf_setxmpfile{\p_file}% + \fi \to \everysetupbackend -% \doifsomething{\backendparameter\c!format} .. at the lua end +%D This will change: \appendtoks \clf_setformat @@ -246,281 +126,35 @@ \relax \to \everysetupbackend -%D For the moment we keep these. - -%newtoks \pdfbackendeveryximage -\newtoks \pdfbackendeveryxform +%D These are the only official methods to add stuff to the resources. If more is +%D needed for third party low level code, it can be added. -%D These are the only official methods to add stuff to the resources. +\unexpanded\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog{#1}{#2}} +\unexpanded\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo{#1}{#2}} +\unexpanded\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames{#1}{#2}} -\unexpanded\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog {#1}{#2}} -\unexpanded\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo {#1}{#2}} -\unexpanded\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames {#1}{#2}} +\unexpanded\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes{#1}{#2}} +\unexpanded\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes{#1}{#2}} +\unexpanded\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources{#1}{#2}} -\unexpanded\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes {#1}{#2}} -\unexpanded\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes {#1}{#2}} -\unexpanded\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources {#1}{#2}} - -\unexpanded\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate {#1}{#2}} +\unexpanded\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate{#1}{#2}} \unexpanded\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}} -\unexpanded\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern {#1}{#2}} -\unexpanded\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade {#1}{#2}} +\unexpanded\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern{#1}{#2}} +\unexpanded\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade{#1}{#2}} \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources} \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax} - \let\PDFcolor\pdfcolor - -% clipping - -\unexpanded\def\dostartclipping#1#2#3% we can move this to lua and only set a box here - {\forcecolorhack - \edef\width {\tobigpoints#2}% - \edef\height{\tobigpoints#3}% - \meta_grab_clip_path{#1}\width\height{% - 0 0 m % - \width\space 0 l % - \width\space \height\space l % - 0 \height\space l% - }% - \pdfliteral{q 0 w \MPclippath\space W n}} - -\unexpanded\def\dostopclipping - {\pdfliteral{Q}} -%D Temporary hack, will be removed or improved or default. +%D This is a temporary hack mthat will be removed, improved or somehow can become +%D default. -% attr {/Group << /S /Transparency /I false /K true >>} - -%def\TransparencyHack{\ctxlua{backends.codeinjections.addtransparencygroup()}} \def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]} -% Still here: - -%D \macros -%D {back_ovalbox} +%D Just in case one needs this \unknown: %D -%D Drawing frames with round corners is inherited from the main module. For drawing -%D ovals we use quite raw \PDF\ code. The next implementation does not differ that -%D much from the one implemented in the \POSTSCRIPT\ driver. This code is somewhat -%D obsolete as we now have metapost embedded. - -\unexpanded\def\back_ovalbox#1#2#3#4#5#6#7#8% - {\forcecolorhack - \bgroup - \edef\stroke{\tobigpoints\dimexpr#4\relax\space}% - \edef\radius{\tobigpoints\dimexpr#5\relax\space}% - \scratchdimen\dimexpr#4/\plustwo\relax - \edef\xmin {\tobigpoints \scratchdimen \space}% - \edef\xmax {\tobigpoints\dimexpr #1-\scratchdimen\relax\space}% - \edef\ymax {\tobigpoints\dimexpr #2-\scratchdimen\relax\space}% - \edef\ymin {\tobigpoints\dimexpr-#3+\scratchdimen\relax\space}% - \advance\scratchdimen by #5\relax - \edef\xxmin{\tobigpoints \scratchdimen \space}% - \edef\xxmax{\tobigpoints\dimexpr #1-\scratchdimen\relax\space}% - \edef\yymax{\tobigpoints\dimexpr #2-\scratchdimen\relax\space}% - \edef\yymin{\tobigpoints\dimexpr-#3+\scratchdimen\relax\space}% - % - \edef\dostroke{\number#6}% - \edef\dofill {\number#7}% - \scratchcounter#8\relax - \setbox\scratchbox\naturalhpack - {\ifnum\dostroke\dofill>\zerocount - \pdfliteral - {q - \stroke w - \ifcase\scratchcounter - \xxmin \ymin m - \xxmax \ymin l - \xmax \ymin \xmax \yymin y - \xmax \yymax l - \xmax \ymax \xxmax \ymax y - \xxmin \ymax l - \xmin \ymax \xmin \yymax y - \xmin \yymin l - \xmin \ymin \xxmin \ymin y - h - \or % 1 - \xxmin \ymin m - \xxmax \ymin l - \xmax \ymin \xmax \yymin y - \xmax \ymax l - \xmin \ymax l - \xmin \yymin l - \xmin \ymin \xxmin \ymin y - h - \or % 2 - \xxmin \ymin m - \xmax \ymin l - \xmax \ymax l - \xxmin \ymax l - \xmin \ymax \xmin \yymax y - \xmin \yymin l - \xmin \ymin \xxmin \ymin y - h - \or % 3 - \xmin \ymin m - \xmax \ymin l - \xmax \yymax l - \xmax \ymax \xxmax \ymax y - \xxmin \ymax l - \xmin \ymax \xmin \yymax y - \xmin \ymin l - h - \or % 4 - \xmin \ymin m - \xxmax \ymin l - \xmax \ymin \xmax \yymin y - \xmax \yymax l - \xmax \ymax \xxmax \ymax y - \xmin \ymax l - \xmin \ymin l - h - \or % 5 - \xmin \ymin m - \xmax \ymin l - \xmax \yymax l - \xmax \ymax \xxmax \ymax y - \xmin \ymax l - \xmin \ymin l - h - \or % 6 - \xmin \ymin m - \xxmax \ymin l - \xmax \ymin \xmax \yymin y - \xmax \ymax l - \xmin \ymax l - \xmin \ymin l - h - \or % 7 - \xxmin \ymin m - \xmax \ymin l - \xmax \ymax l - \xmin \ymax l - \xmin \yymin l - \xmin \ymin \xxmin \ymin y - h - \or % 8 - \xmin \ymin m - \xmax \ymin l - \xmax \ymax l - \xxmin \ymax l - \xmin \ymax \xmin \yymax y - \xmin \ymin l - h - \or % 9 top open - \xmin \ymax m - \xmin \yymin l - \xmin \ymin \xxmin \ymin y - \xxmax \ymin l - \xmax \ymin \xmax \yymin y - \xmax \ymax l - \or % 10 right open - \xmax \ymax m - \xxmin \ymax l - \xmin \ymax \xmin \yymax y - \xmin \yymin l - \xmin \ymin \xxmin \ymin y - \xmax \ymin l - \or % 11 bottom open - \xmax \ymin m - \xmax \yymax l - \xmax \ymax \xxmax \ymax y - \xxmin \ymax l - \xmin \ymax \xmin \yymax y - \xmin \ymin l - \or % 12 left open - \xmin \ymax m - \xxmax \ymax l - \xmax \ymax \xmax \yymax y - \xmax \yymin l - \xmax \ymin \xxmax \ymin y - \xmin \ymin l - \or % 13 - \xmin \ymax m - \xxmax \ymax l - \xmax \ymax \xmax \yymax y - \xmax \ymin l - \or % 14 - \xmax \ymax m - \xmax \yymin l - \xmax \ymin \xxmax \ymin y - \xmin \ymin l - \or % 15 - \xmax \ymin m - \xxmin \ymin l - \xmin \ymin \xmin \yymin y - \xmin \ymax l - \or % 16 - \xmin \ymin m - \xmin \yymax l - \xmin \ymax \xxmin \ymax y - \xmax \ymax l - \or % 17 - \xxmax \ymax m - \xmax \ymax \xmax \yymax y - \or % 18 - \xmax \yymin m - \xmax \ymin \xxmax \ymin y - \or % 19 - \xxmin \ymin m - \xmin \ymin \xmin \yymin y - \or % 20 - \xmin \yymax m - \xmin \ymax \xxmin \ymax y - \or % 21 - \xxmax \ymax m - \xmax \ymax \xmax \yymax y - \xmin \yymax m - \xmin \ymax \xxmin \ymax y - \or % 22 - \xxmax \ymax m - \xmax \ymax \xmax \yymax y - \xmax \yymin m - \xmax \ymin \xxmax \ymin y - \or % 23 - \xmax \yymin m - \xmax \ymin \xxmax \ymin y - \xxmin \ymin m - \xmin \ymin \xmin \yymin y - \or % 24 - \xxmin \ymin m - \xmin \ymin \xmin \yymin y - \xmin \yymax m - \xmin \ymax \xxmin \ymax y - \or % 25 - \xxmax \ymax m - \xmax \ymax \xmax \yymax y - \xmax \yymin m - \xmax \ymin \xxmax \ymin y - \xxmin \ymin m - \xmin \ymin \xmin \yymin y - \xmin \yymax m - \xmin \ymax \xxmin \ymax y - \or % 26 - \xmax \yymin m - \xmax \ymin \xxmax \ymin y - \xmin \yymax m - \xmin \ymax \xxmin \ymax y - \or % 27 - \xxmax \ymax m - \xmax \ymax \xmax \yymax y - \xxmin \ymin m - \xmin \ymin \xmin \yymin y - \or % 28 - \fi - \ifnum\scratchcounter>\pluseight - S - \else - \ifnum\dostroke=\plusone S \fi - \ifnum\dofill =\plusone f \fi - \fi - Q}% - \fi}% - \wd\scratchbox#1% - \ht\scratchbox#2% - \dp\scratchbox#3% - \box\scratchbox - \egroup} +%D \starttyping +%D text \pdfbackendactualtext{Meier}{Müller} text +%D \stoptyping \unexpanded\def\pdfbackendactualtext#1#2% not interfaced {\clf_startactualtext{#2}% @@ -529,8 +163,4 @@ \let\pdfactualtext\pdfbackendactualtext -% \starttext -% text \pdfbackendactualtext{Meier}{Müller} text -% \stoptext - \protect \endinput diff --git a/tex/context/base/mkiv/back-pdp.lua b/tex/context/base/mkiv/back-pdp.lua index d7033608c..6360dea47 100644 --- a/tex/context/base/mkiv/back-pdp.lua +++ b/tex/context/base/mkiv/back-pdp.lua @@ -9,7 +9,8 @@ if not modules then modules = { } end modules ['back-pdp'] = { -- This is temporary ... awaiting a better test .. basically we can -- always use this: pdf primitives. -local context = context +local context = context +local lpdf = lpdf local lpdfreserveobject = lpdf.reserveobject local lpdfcompresslevel = lpdf.compresslevel @@ -17,22 +18,17 @@ local lpdfobj = lpdf.obj local lpdfpagereference = lpdf.pagereference local lpdfxformname = lpdf.xformname -local jobpositions = job.positions -local gethpos = jobpositions.gethpos -local getvpos = jobpositions.getvpos - local tokenscanners = tokens.scanners local scanword = tokenscanners.word local scankeyword = tokenscanners.keyword local scanstring = tokenscanners.string local scaninteger = tokenscanners.integer -local scandimension = tokenscanners.dimension +local scanwhd = tokenscanners.whd -local trace = false trackers.register("commands", function(v) trace = v end) -local report = logs.reporter("command") +local trace = false trackers.register("backend", function(v) trace = v end) +local report = logs.reporter("backend") local nodepool = nodes.pool -local newsavepos = nodepool.savepos local newliteral = nodepool.literal local newsave = nodepool.save local newrestore = nodepool.restore @@ -42,183 +38,12 @@ local implement = interfaces.implement local constants = interfaces.constants local variables = interfaces.variables --- helper - -local function scanwhd() - local width, height, depth - while true do - if scankeyword("width") then - width = scandimension() - elseif scankeyword("height") then - height = scandimension() - elseif scankeyword("depth") then - depth = scandimension() - else - break - end - end - if width or height or depth then - return width or 0, height or 0, depth or 0 - else - -- we inherit - end -end - --- positions - -local function savepos() - context(newsavepos()) -end - -local function lastxpos() - context(gethpos()) -end - -local function lastypos() - context(getvpos()) -end - -implement { name = "savepos", actions = savepos } -implement { name = "lastxpos", actions = lastxpos } -implement { name = "lastypos", actions = lastypos } - -- literals local function pdfliteral() context(newliteral(scanword() or "origin",scanstring())) end -implement { name = "pdfliteral", actions = pdfliteral } - --- box resources - -local boxresources = tex.boxresources -local savebox = boxresources.save -local usebox = boxresources.use - -local lastindex = 0 - -local function saveboxresource() - local immediate = true - local kind = scankeyword("type") and scaninteger() or 0 - local attributes = scankeyword("attr") and scanstring() or nil - local resources = scankeyword("resources") and scanstring() or nil - local margin = scankeyword("margin") and scandimension() or 0 -- register - local boxnumber = scaninteger() - -- - lastindex = savebox(boxnumber,attributes,resources,immediate,kind,margin) - if trace then - report("\\saveboxresource: index %i",lastindex) - end -end - -local function lastsavedboxresourceindex() - if trace then - report("\\lastsaveboxresource: index %i",lastindex) - end - context("%i",lastindex) -end - -local function useboxresource() - local width, height, depth = scanwhd() - local index = scaninteger() - local node = usebox(index,width,height,depth) - if trace then - report("\\useboxresource: index %i",index) - end - context(node) -end - -implement { name = "saveboxresource", actions = saveboxresource } -implement { name = "lastsavedboxresourceindex", actions = lastsavedboxresourceindex } -implement { name = "useboxresource", actions = useboxresource } - --- image resources (messy: will move) - -local imageresources = { } -local lastindex = 0 -local lastpages = 1 - -local function saveimageresource() - local width, height, depth = scanwhd() - local page = 1 - local immediate = true - local margin = 0 -- or dimension - local attributes = scankeyword("attr") and scanstring() or nil - if scankeyword("named") then - scanstring() -- ignored - elseif scankeyword("page") then - page = scaninteger() - end - local userpassword = scankeyword("userpassword") and scanstring() or nil - local ownerpassword = scankeyword("ownerpassword") and scanstring() or nil - local visiblefilename = scankeyword("visiblefilename") and scanstring() or nil - local colorspace = scankeyword("colorspace") and scaninteger() or nil - local pagebox = scanword() or nil - local filename = scanstring() --- pcall - context.getfiguredimensions( { filename }, { - [constants.userpassword] = userpassword, - [constants.ownerpassword] = ownerpassword, - [constants.page] = page or 1, - [constants.size] = pagebox, - }) - context.relax() - lastindex = lastindex + 1 - lastpages = 1 - imageresources[lastindex] = { - filename = filename, - page = page or 1, - size = pagebox, - width = width, - height = height, - depth = depth, - attr = attributes, - -- margin = margin, - } -end - -local function lastsavedimageresourceindex() - context("%i",lastindex or 0) -end - -local function lastsavedimageresourcepages() - context("%i",lastpages or 0) -- todo -end - -local function useimageresource() - local width, height, depth = scanwhd() - if scankeyword("keepopen") then - -- ignored - end - local index = scaninteger() - local l = imageresources[index] - if l then - if not (width or height or depth) then - width = l.width - height = l.height - depth = l.depth - end --- pcall - context.externalfigure( { l.filename }, { - [constants.userpassword] = l.userpassword, - [constants.ownerpassword] = l.ownerpassword, - [constants.width] = width and (width .. "sp") or nil, - [constants.height] = height and (height .. "sp") or nil, - [constants.page] = l.page or 1, - [constants.size] = pagebox, - }) - context.relax() - else - print("no image resource",index) - end -end - -implement { name = "saveimageresource", actions = saveimageresource } -implement { name = "lastsavedimageresourceindex", actions = lastsavedimageresourceindex } -implement { name = "lastsavedimageresourcepages", actions = lastsavedimageresourcepages } -implement { name = "useimageresource", actions = useimageresource } - -- objects local lastobjnum = 0 @@ -271,10 +96,6 @@ local function pdfrefobj() end end -implement { name = "pdfobj", actions = pdfobj } -implement { name = "pdflastobj", actions = pdflastobj } -implement { name = "pdfrefobj", actions = pdfrefobj } - -- annotations local lastobjnum = 0 @@ -306,8 +127,6 @@ local function pdfannot() end end -implement { name = "pdfannot", actions = pdfannot } - local function pdfdest() local name = false local zoom = false @@ -345,8 +164,6 @@ local function pdfdest() context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit")) end -implement { name = "pdfdest", actions = pdfdest } - -- management local function pdfsave() @@ -398,8 +215,6 @@ local function pdfextension() end end -implement { name = "pdfextension", actions = pdfextension } - -- feedbacks: colorstackinit creationdate fontname fontobjnum fontsize lastannot -- lastlink lastobj pageref retval revision version xformname @@ -421,8 +236,6 @@ local function pdffeedback() end end -implement { name = "pdffeedback", actions = pdffeedback } - -- variables: (integers:) compresslevel decimaldigits gamma gentounicode -- ignoreunknownimages imageaddfilename imageapplygamma imagegamma imagehicolor -- imageresolution inclusioncopyfonts inclusionerrorlevel majorversion minorversion @@ -448,4 +261,17 @@ implement { name = "pdffeedback", actions = pdffeedback } -- end -- end ---------- { name = "pdfvariable", actions = pdfvariable } +-- kept: + +implement { name = "pdfextension", actions = pdfextension } +implement { name = "pdffeedback", actions = pdffeedback } +--------- { name = "pdfvariable", actions = pdfvariable } + +-- for the moment (tikz) + +implement { name = "pdfliteral", actions = pdfliteral } +implement { name = "pdfobj", actions = pdfobj } +implement { name = "pdflastobj", actions = pdflastobj } +implement { name = "pdfrefobj", actions = pdfrefobj } +--------- { name = "pdfannot", actions = pdfannot } +--------- { name = "pdfdest", actions = pdfdest } diff --git a/tex/context/base/mkiv/back-res.lua b/tex/context/base/mkiv/back-res.lua index be92c74a6..2ca4a5ac8 100644 --- a/tex/context/base/mkiv/back-res.lua +++ b/tex/context/base/mkiv/back-res.lua @@ -1,15 +1,32 @@ if not modules then modules = { } end modules ['back-res'] = { version = 1.001, - comment = "companion to lpdf-ini.mkiv", + comment = "companion to back-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } --- A box resource has an index. This happens to be an object number --- due to the pdf backend but in fact it's an abstraction. This is why --- we have explicit fetchers. The internal number (as in \Fm123) is yet --- another number. +local context = context + +local trace = false trackers.register("backend", function(v) trace = v end) +local report = logs.reporter("backend") + +local scanners = tokens.scanners +local scankeyword = scanners.keyword +local scaninteger = scanners.integer +local scanstring = scanners.string +local scandimension = scanners.dimension +local scanword = scanners.word +local scanwhd = scanners.whd + +local scanners = interfaces.scanners +local implement = interfaces.implement +local constants = interfaces.constants +local variables = interfaces.variables + +-- A box resource has an index. This happens to be an object number due to the pdf +-- backend but in fact it's an abstraction. This is why we have explicit fetchers. +-- The internal number (as in \Fm123) is yet another number. local tex_saveboxresource = tex.saveboxresource local tex_useboxresource = tex.useboxresource @@ -23,13 +40,20 @@ updaters.register("backend.update",function() tex_getboxresourcedimensions = tex.getboxresourcedimensions end) -tex.boxresources = { - save = function(...) return tex_saveboxresource(...) end, - use = function(...) return tex_useboxresource(...) end, - getbox = function(...) return tex_getboxresourcebox(...) end, - getdimensions = function(...) return tex_getboxresourcedimensions(...) end, +local savebox = function(...) return tex_saveboxresource(...) end +local usebox = function(...) return tex_useboxresource(...) end +local getbox = function(...) return tex_getboxresourcebox(...) end +local getwhd = function(...) return tex_getboxresourcedimensions(...) end + +local boxresources = { + save = savebox, + use = usebox, + getbox = getbox, + getdimensions = getwhd, } +tex.boxresources = boxresources + -- local tex_saveimageresource = tex.saveimageresource -- local tex_useimageresource = tex.useimageresource -- @@ -42,3 +66,126 @@ tex.boxresources = { -- save = function(...) return tex_saveimageresource(...) end, -- use = function(...) return tex_useimageresource(...) end, -- } + +local lastindex = 0 + +local function saveboxresource() + local immediate = true + local kind = scankeyword("type") and scaninteger() or 0 + local attributes = scankeyword("attr") and scanstring() or nil + local resources = scankeyword("resources") and scanstring() or nil + local margin = scankeyword("margin") and scandimension() or 0 -- register + local boxnumber = scaninteger() + -- + lastindex = savebox(boxnumber,attributes,resources,immediate,kind,margin) + if trace then + report("\\saveboxresource: index %i",lastindex) + end +end + +local function lastsavedboxresourceindex() + if trace then + report("\\lastsaveboxresource: index %i",lastindex) + end + context("%i",lastindex) +end + +local function useboxresource() + local width, height, depth = scanwhd() + local index = scaninteger() + local node = usebox(index,width,height,depth) + if trace then + report("\\useboxresource: index %i",index) + end + context(node) +end + +implement { name = "saveboxresource", actions = saveboxresource } +implement { name = "lastsavedboxresourceindex", actions = lastsavedboxresourceindex } +implement { name = "useboxresource", actions = useboxresource } + +-- image resources + +local imageresources = { } +local lastindex = 0 +local lastpages = 1 + +local function saveimageresource() + local width, height, depth = scanwhd() + local page = 1 + local immediate = true + local margin = 0 -- or dimension + local attributes = scankeyword("attr") and scanstring() or nil + if scankeyword("named") then + scanstring() -- ignored + elseif scankeyword("page") then + page = scaninteger() + end + local userpassword = scankeyword("userpassword") and scanstring() or nil + local ownerpassword = scankeyword("ownerpassword") and scanstring() or nil + local visiblefilename = scankeyword("visiblefilename") and scanstring() or nil + local colorspace = scankeyword("colorspace") and scaninteger() or nil + local pagebox = scanword() or nil + local filename = scanstring() +-- pcall + context.getfiguredimensions( { filename }, { + [constants.userpassword] = userpassword, + [constants.ownerpassword] = ownerpassword, + [constants.page] = page or 1, + [constants.size] = pagebox, + }) + context.relax() + lastindex = lastindex + 1 + lastpages = 1 + imageresources[lastindex] = { + filename = filename, + page = page or 1, + size = pagebox, + width = width, + height = height, + depth = depth, + attr = attributes, + -- margin = margin, + } +end + +local function lastsavedimageresourceindex() + context("%i",lastindex or 0) +end + +local function lastsavedimageresourcepages() + context("%i",lastpages or 0) -- todo +end + +local function useimageresource() + local width, height, depth = scanwhd() + if scankeyword("keepopen") then + -- ignored + end + local index = scaninteger() + local l = imageresources[index] + if l then + if not (width or height or depth) then + width = l.width + height = l.height + depth = l.depth + end + -- pcall / we could use a dedicated call instead: + context.externalfigure( { l.filename }, { + [constants.userpassword] = l.userpassword, + [constants.ownerpassword] = l.ownerpassword, + [constants.width] = width and (width .. "sp") or nil, + [constants.height] = height and (height .. "sp") or nil, + [constants.page] = l.page or 1, + [constants.size] = pagebox, + }) + context.relax() + else + report("no valid image resource %a",index) + end +end + +implement { name = "saveimageresource", actions = saveimageresource } +implement { name = "lastsavedimageresourceindex", actions = lastsavedimageresourceindex } +implement { name = "lastsavedimageresourcepages", actions = lastsavedimageresourcepages } +implement { name = "useimageresource", actions = useimageresource } diff --git a/tex/context/base/mkiv/back-res.mkiv b/tex/context/base/mkiv/back-res.mkiv new file mode 100644 index 000000000..fd7b208c9 --- /dev/null +++ b/tex/context/base/mkiv/back-res.mkiv @@ -0,0 +1,32 @@ +%D \module +%D [ file=back-res, +%D version=2019.05.23, % 2009.04.15, +%D title=\CONTEXT\ Backend Macros, +%D subtitle=Resources, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Backend Macros / Resources} + +\registerctxluafile{back-res}{} + +\unprotect + +%D We overload the primitives with our own but use a bit of indirection for the +%D purpose of tracing. Some of these are needes for packages like tikz. + +\unexpanded\def\saveboxresource {\clf_saveboxresource} +\unexpanded\def\lastsavedboxresourceindex {\numexpr\clf_lastsavedboxresourceindex\relax} +\unexpanded\def\useboxresource {\clf_useboxresource} + +\unexpanded\def\saveimageresource {\clf_saveimageresource} +\unexpanded\def\lastsavedimageresourceindex{\numexpr\clf_lastsavedimageresourceindex\relax} +\unexpanded\def\lastsavedimageresourcepages{\numexpr\clf_lastsavedimageresourcepages\relax} +\unexpanded\def\useimageresource {\clf_useimageresource} + +\protect \endinput diff --git a/tex/context/base/mkiv/back-trf.lua b/tex/context/base/mkiv/back-trf.lua new file mode 100644 index 000000000..721c856a9 --- /dev/null +++ b/tex/context/base/mkiv/back-trf.lua @@ -0,0 +1,155 @@ +if not modules then modules = { } end modules ['back-trf'] = { + version = 1.001, + comment = "companion to back-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local sind, cosd, abs = math.sind, math.cosd, math.abs +local insert, remove = table.insert, table.remove +local unpack = unpack + +local context = context + +local formatters = string.formatters + +local scanners = tokens.scanners +local scankeyword = scanners.keyword +local scaninteger = scanners.integer +local scannumber = scanners.number +local scanstring = scanners.string + +local implement = interfaces.implement + +local nodepool = nodes.pool +local savenode = nodepool.save +local restorenode = nodepool.restore +local setmatrixnode = nodepool.setmatrix +local literalnode = nodepool.literal -- has to become some nodeinjection + +local stack = { } +local restore = true -- false + +updaters.register("backend.update",function() + savenode = nodepool.save + restorenode = nodepool.restore + setmatrixnode = nodepool.setmatrix + literalnode = nodepool.literal -- has to become some nodeinjection +end) + +local function stopsomething() + local top = remove(stack) + if top == false then + -- not wrapped + elseif top == true then + context(restorenode()) + elseif top then + context(setmatrixnode(unpack(top))) -- not really needed anymore + context(restorenode()) + else + -- nesting error + end +end + +local function startrotation() + local a = scannumber() + if a == 0 then + insert(stack,false) + else + local s, c = sind(a), cosd(a) + if abs(s) < 0.000001 then + s = 0 -- otherwise funny -0.00000 + end + if abs(c) < 0.000001 then + c = 0 -- otherwise funny -0.00000 + end + context(savenode()) + context(setmatrixnode(c,s,-s,c)) + insert(stack,restore and { c, -s, s, c } or true) + end +end + +implement { name = "startrotation", actions = startrotation } +implement { name = "stoprotation", actions = stopsomething } + +local function startscaling() -- at the tex end we use sx and sy instead of rx and ry + local rx, ry = 1, 1 + while true do + if scankeyword("rx") then + rx = scannumber() + elseif scankeyword("ry") then + ry = scannumber() + -- elseif scankeyword("revert") then + -- local top = stack[#stack] + -- if top then + -- rx = top[1] + -- ry = top[4] + -- else + -- rx = 1 + -- ry = 1 + -- end + else + break + end + end + if rx == 1 and ry == 1 then + insert(stack,false) + else + if rx == 0 then + rx = 0.0001 + end + if ry == 0 then + ry = 0.0001 + end + context(savenode()) + context(setmatrixnode(rx,0,0,ry)) + insert(stack,restore and { 1/rx, 0, 0, 1/ry } or true) + end +end + +implement { name = "startscaling", actions = startscaling } +implement { name = "stopscaling", actions = stopsomething } + +local function startmatrix() -- rx sx sy ry -- tx, ty + local rx, sx, sy, ry = 1, 0, 0, 1 + while true do + if scankeyword("rx") then rx = scannumber() + elseif scankeyword("ry") then ry = scannumber() + elseif scankeyword("sx") then sx = scannumber() + elseif scankeyword("sy") then sy = scannumber() + else break end + end + if rx == 1 and sx == 0 and sy == 0 and ry == 1 then + insert(stack,false) + else + context(savenode()) + context(setmatrixnode(rx,sx,sy,ry)) + insert(stack,store and { -rx, -sx, -sy, -ry } or true) + end +end + +implement { name = "startmatrix", actions = startmatrix } +implement { name = "stopmatrix", actions = stopsomething } + +local function startmirroring() + context(setmatrixnode(-1,0,0,1)) +end + +implement { name = "startmirroring", actions = startmirroring } +implement { name = "stopmirroring", actions = startmirroring } -- not: stopsomething + +-- this could also run on top of pack-rul ... todo + +local function startclipping() + -- context(savenode()) + context(literalnode("origin",formatters["q 0 w %s W n"](scanstring()))) +end + +local function stopclipping() + -- context(restorenode()) + context(literalnode("Q")) +end + +implement { name = "startclipping", actions = startclipping } +implement { name = "stopclipping", actions = stopclipping } diff --git a/tex/context/base/mkiv/back-trf.mkiv b/tex/context/base/mkiv/back-trf.mkiv new file mode 100644 index 000000000..3d8477a82 --- /dev/null +++ b/tex/context/base/mkiv/back-trf.mkiv @@ -0,0 +1,79 @@ +%D \module +%D [ file=back-trf, +%D version=2019.02.08, % 2009.04.15, +%D title=\CONTEXT\ Backend Macros, +%D subtitle=Transformations, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\unprotect + +\registerctxluafile{back-trf}{} + +% rotation + +\unexpanded\def\dostartrotation#1% + {\forcecolorhack + \clf_startrotation#1\relax} % todo: implement without Q q + +\unexpanded\def\dostoprotation + {\clf_stoprotation + \forcecolorhack} + +% scaling + +\unexpanded\def\dostartscaling#1#2% + {\forcecolorhack + \clf_startscaling rx #1 ry #2\relax} + +\unexpanded\def\dostopscaling + {\clf_stopscaling + \forcecolorhack} + +% mirroring + +\unexpanded\def\dostartmirroring + {\clf_startmirroring} + +\unexpanded\def\dostopmirroring + {\clf_stopmirroring} + +% transform + +\unexpanded\def\dotransformnextbox#1#2#3#4#5#6% + {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}} + +\unexpanded\def\dodotransformnextbox#1#2#3#4#5#6% + {\hpack + {\kern #5\onebasepoint + \raise#6\onebasepoint + \hpack + {\clf_startmatrix rx #1 sx #2 sy #3 ry #4\relax + \box\nextbox + \clf_stopmatrix}}} + +%D \macros +%D {dostartclipping,dostopclipping} +%D +%D Clipping is implemented in such a way that an arbitrary code can be fed. +%D +%D \starttyping +%D \dostartclipping {pathname} {width} {height} +%D \dostopclipping +%D \stoptyping + +\unexpanded\def\dostartclipping#1#2#3% we can move this to lua and only set a box here + {\forcecolorhack + \meta_grab_clip_path{#1}{#2}{#3}% + \clf_startclipping{\MPclippath}% + \glet\MPclippath\empty} + +\unexpanded\def\dostopclipping + {\clf_stopclipping} + +\protect \endinput diff --git a/tex/context/base/mkiv/buff-imp-xml.lua b/tex/context/base/mkiv/buff-imp-xml.lua index 7bac868d7..b7fa85818 100644 --- a/tex/context/base/mkiv/buff-imp-xml.lua +++ b/tex/context/base/mkiv/buff-imp-xml.lua @@ -59,11 +59,11 @@ local closecdata = P("]]>") local grammar = visualizers.newgrammar("default", { "visualizer", sstring = makepattern(handler,"string",patterns.dquote) - * (V("whitespace") + makepattern(handler,"default",1-patterns.dquote))^0 + * (V("whitespace") + makepattern(handler,"default",(1-patterns.dquote)^0)) * makepattern(handler,"string",patterns.dquote), dstring = makepattern(handler,"string",patterns.squote) - * (V("whitespace") + makepattern(handler,"default",1-patterns.squote))^0 + * (V("whitespace") + makepattern(handler,"default",(1-patterns.squote)^0)) * makepattern(handler,"string",patterns.squote), entity = makepattern(handler,"entity",entity), diff --git a/tex/context/base/mkiv/char-fio.lua b/tex/context/base/mkiv/char-fio.lua index 9939bf041..ad61fee65 100644 --- a/tex/context/base/mkiv/char-fio.lua +++ b/tex/context/base/mkiv/char-fio.lua @@ -92,7 +92,11 @@ directives.register("filters.utf.reorder", function(v) configure("characters.f directives.register("filters.utf.collapse", function(v) configure("characters.filters.utf.collapse", v) end) directives.register("filters.utf.decompose", function(v) configure("characters.filters.utf.decompose",v) end) -utffilters.setskippable { "mkiv", "mkvi", "mkix", "mkxi" } +utffilters.setskippable { + "mkiv", "mkvi", + "mkix", "mkxi", + "mkil", "mkli", +} interfaces.implement { name = "enableutf", diff --git a/tex/context/base/mkiv/cont-log.mkiv b/tex/context/base/mkiv/cont-log.mkiv index 8a256a7a9..352e53ec9 100644 --- a/tex/context/base/mkiv/cont-log.mkiv +++ b/tex/context/base/mkiv/cont-log.mkiv @@ -278,6 +278,8 @@ \unexpanded\def\MKII{MkII} \unexpanded\def\MKIV{MkIV} \unexpanded\def\MKVI{MkVI} +\unexpanded\def\MKIL{MkIL} +\unexpanded\def\MKLI{MkLI} \unexpanded\def\MKIX{MkIX} \unexpanded\def\MKXI{MkXI} diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index fa1a405b7..0cd33a4eb 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2019.05.18 10:42} +\newcontextversion{2019.05.25 10:45} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index f05092fe9..2550292e1 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -18,9 +18,9 @@ % 0.2 sec : format dumped % 0.2 sec : char-def/char-ini (no bytecode) % -% So a format still saves some 1.5 seconds (with luajjitex) startup and -% on network shares cq. when no files are cached by the os it's of course -% much worse. A zero run is .27 sec with luajittex. +%D So a format still saves some 1.5 seconds (with luajjitex) startup and on network +%D shares cq. when no files are cached by the os it's of course much worse. A zero +%D run is .27 sec with luajittex. In luametatex it's faster anyway (2.4 sec). % http://build.contextgarden.net/waterfall?tag=c/luatex @@ -29,20 +29,19 @@ \catcode`\{=1 \catcode`\}=2 \catcode`\#=6 -%D From the next string (which is set by the script that assembles the -%D distribution) later on we will calculate a number that can be used -%D by use modules to identify the feature level. Starting with version -%D 2004.8.30 the low level interface is english. Watch out and adapt -%D your styles an modules. +%D From the next string (which is set by the script that assembles the distribution) +%D later on we will calculate a number that can be used by use modules to identify +%D the feature level. Starting with version 2004.8.30 the low level interface is +%D english. Watch out and adapt your styles an modules. % \everypar{\writestatus{!!!!}{some spurious input in line \the\inputlineno}\wait} -%D The order of loading will change when all modules have been cleaned -%D up and the dependencies are more consistent. beware, the version number -%D has to match \type {YYYY.MM.DD HH:MM} format. +%D The order of loading will change when all modules have been cleaned up and the +%D dependencies are more consistent. Beware, the version number has to match \type +%D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2019.05.18 10:42} +\edef\contextversion{2019.05.25 10:45} \edef\contextkind {beta} %D Kind of special: @@ -61,31 +60,30 @@ \ifx\normalinput\undefined \let\normalinput\input \fi -\def\loadcorefile#1{\normalinput#1\relax} -\def\loadmarkfile#1{\normalinput#1.\mksuffix\relax} -\def\loadmkiifile#1{} -\def\loadmkivfile#1{\normalinput#1.mkiv\relax} -\def\loadmkvifile#1{\normalinput#1.mkvi\relax} +\def\loadmarkfile#1{\normalinput{#1.\mksuffix}} +\def\loadmkivfile#1{\normalinput{#1.mkiv}} +\def\loadmkvifile#1{\normalinput{#1.mkvi}} +%def\loadmkilfile#1{\normalinput{#1.mkil}} +%def\loadmklifile#1{\normalinput{#1.mkli}} -%D First we load the system modules. These implement a lot of -%D manipulation macros. We start with setting up some basic \TEX\ -%D machinery. +%D First we load the system modules. These implement a lot of manipulation macros. +%D We start with setting up some basic \TEX\ machinery. \loadmarkfile{syst-ini} +%D We just quit if new functionality is expected. + +\ifnum\luatexversion<110 % also change message + \writestatus{!!!!}{Your luatex binary is too old, you need at least version 1.10!} + \expandafter\end +\fi + %D Some checking (more primitives are now defined): \ifdefined\defaultinterface \else \def\defaultinterface {english} \fi %ifdefined\messageinterface \else \let\messageinterface \defaultinterface \fi \ifdefined\defaultlanguagetag \else \def\defaultlanguagetag{en} \fi -%D We just quit if new functionality is expected. - -\ifnum\luatexversion<109 % also change message - \writestatus{!!!!}{Your luatex binary is too old, you need at least version 1.09!} - \expandafter\end -\fi - %D There is only this way to pass the version info to \LUA\ (currently). Hm, we could %D now put it into the environment. @@ -116,8 +114,8 @@ % \tracecatcodetables -% From here on we have \unexpanded being \normalprotected, as we already had -% \unexpanded long before etex came around. +%D From here on we have \unexpanded being \normalprotected, as we already had +%D \type {\unexpanded} long before etex came around. \loadmarkfile{luat-ini} \loadmarkfile{toks-scn} @@ -135,13 +133,13 @@ \loadmkvifile{file-res} \loadmkvifile{file-lib} -\loadmarkfile{core-lmt} +\loadmarkfile{core-lmt} % lmtx -% needs more checking for clashes: -% -% no need to register, just execute once, slightly faster -% -% \doifelsefileexists{l-macro-imp-codes.lua}{\registerctxluafile{l-macro-imp-codes}{}}{} +%D This needs more checking for clashes: +%D +%D \starttyping +%D \doifelsefileexists{l-macro-imp-codes.lua}{\registerctxluafile{l-macro-imp-codes}{}}{} +%D \stoptyping \loadmarkfile{supp-dir} @@ -154,7 +152,6 @@ \loadmarkfile{mult-aux} \loadmarkfile{mult-def} \loadmarkfile{mult-chk} -%loadmarkfile{mult-aux} % moved up \loadmkvifile{mult-dim} \loadmarkfile{cldf-int} % interface @@ -182,9 +179,12 @@ \loadmarkfile{node-mig} %loadmarkfile{node-pag} -\loadmarkfile{driv-ini} +\loadmarkfile{driv-ini} % lmtx \loadmarkfile{back-ini} +\loadmarkfile{back-res} +\loadmarkfile{back-trf} +\loadmarkfile{back-out} \loadmarkfile{attr-col} \loadmarkfile{attr-lay} @@ -580,8 +580,9 @@ % now we hook in backend code (needs checking) \loadmarkfile{back-exp} - -\loadmarkfile{back-pdf} % actually, this one should load the next three using document.arguments.backend +\loadmarkfile{back-pdf} +\loadmarkfile{back-mps} +\loadmarkfile{back-lua} \loadmarkfile{mlib-pdf} \loadmarkfile{mlib-pps} diff --git a/tex/context/base/mkiv/core-sys.mkiv b/tex/context/base/mkiv/core-sys.mkiv index 4d99d8647..7a04df840 100644 --- a/tex/context/base/mkiv/core-sys.mkiv +++ b/tex/context/base/mkiv/core-sys.mkiv @@ -78,18 +78,6 @@ \fi \to \everysetupsystem -\let\m_system_job_suffix\s!unknown - -\appendtoks - \resetsystemmode{suffix-\m_system_job_suffix}% - \edef\m_system_job_suffix{\jobsuffix}% - \setsystemmode{suffix-\m_system_job_suffix}% -\to \everysetupsystem - -% \appendtoks -% \ctxcommand{updatefilenames("\jobame","\inputfilename","\outputfilename")}% -% \to \everysetupsystem - \newconditional\prerollrun % when true it means that we have a forced number of runs % Some mechanisms (see x-res-01) use either \jobfilename or diff --git a/tex/context/base/mkiv/data-env.lua b/tex/context/base/mkiv/data-env.lua index 1b31caab6..611504db4 100644 --- a/tex/context/base/mkiv/data-env.lua +++ b/tex/context/base/mkiv/data-env.lua @@ -100,7 +100,7 @@ local relations = allocate { -- todo: handlers also here tex = { names = { "tex" }, variable = 'TEXINPUTS', - suffixes = { "tex", "mkvi", "mkiv", "mkii", "cld", "lfg", "xml" }, -- known suffixes have less lookups + suffixes = { "tex", "mkvi", "mkiv", "mkli", "mkil", "mkii", "cld", "lfg", "xml" }, -- known suffixes have less lookups usertype = true, }, icc = { diff --git a/tex/context/base/mkiv/driv-shp.lua b/tex/context/base/mkiv/driv-shp.lua index 4dffa947e..26bb06b39 100644 --- a/tex/context/base/mkiv/driv-shp.lua +++ b/tex/context/base/mkiv/driv-shp.lua @@ -150,7 +150,7 @@ local flushpdfsetmatrix local flushpdfsave local flushpdfrestore local flushspecial -local flushpdfimage +----- flushpdfimage -- make local @@ -1182,7 +1182,7 @@ function lpdf.convert(box,smode,objnum,specification) -- temp name flushpdfsetmatrix = flushers.pdfsetmatrix flushpdfsave = flushers.pdfsave flushpdfrestore = flushers.pdfrestore - flushpdfimage = flushers.pdfimage + -- flushpdfimage = flushers.pdfimage reset_dir_stack() reset_state() diff --git a/tex/context/base/mkiv/driv-shp.mkiv b/tex/context/base/mkiv/driv-shp.mkiv index 031d0265f..f92649a48 100644 --- a/tex/context/base/mkiv/driv-shp.mkiv +++ b/tex/context/base/mkiv/driv-shp.mkiv @@ -11,18 +11,14 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\ifcase\contextlmtxmode\expandafter\endinput\fi +\ifcase\contextlmtxmode \else + \registerctxluafile{driv-shp}{optimize} +\fi \unprotect -\registerctxluafile{driv-shp}{optimize} - -\registerctxluafile{back-lpd}{optimize} -\registerctxluafile{back-lua}{optimize} -\registerctxluafile{back-mps}{optimize} - \appendtoks - \clf_enabledriver{pdf}% for now this way + \clf_enabledriver{pdf}% \to \everyjob \protect \endinput diff --git a/tex/context/base/mkiv/font-ocl.lua b/tex/context/base/mkiv/font-ocl.lua index 0976cdb21..d79ed657e 100644 --- a/tex/context/base/mkiv/font-ocl.lua +++ b/tex/context/base/mkiv/font-ocl.lua @@ -330,39 +330,19 @@ do local hashed = { } local cache = { } - if epdf then - - local openpdf = epdf.openMemStream - - function otf.storepdfdata(pdf) - local done = hashed[pdf] - if not done then - nofstreams = nofstreams + 1 - local o, n = openpdf(pdf,#pdf,f_name(nofstreams)) - cache[n] = o -- we need to keep in mem - done = f_used(n) - hashed[pdf] = done - end - return done + local openpdf = pdfe.new + ----- prefix = "data:application/pdf," + + function otf.storepdfdata(pdf) + local done = hashed[pdf] + if not done then + nofstreams = nofstreams + 1 + local f = f_name(nofstreams) + local n = openpdf(pdf,#pdf,f) + done = f_used(n) + hashed[pdf] = done end - - else - - local openpdf = pdfe.new - ----- prefix = "data:application/pdf," - - function otf.storepdfdata(pdf) - local done = hashed[pdf] - if not done then - nofstreams = nofstreams + 1 - local f = f_name(nofstreams) - local n = openpdf(pdf,#pdf,f) - done = f_used(n) - hashed[pdf] = done - end - return done - end - + return done end end diff --git a/tex/context/base/mkiv/font-off.lua b/tex/context/base/mkiv/font-off.lua deleted file mode 100644 index 7e509c2c3..000000000 --- a/tex/context/base/mkiv/font-off.lua +++ /dev/null @@ -1,230 +0,0 @@ -if not modules then modules = { } end modules ['font-off'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local tonumber = tonumber -local lower = string.lower -local round = math.round -local setmetatableindex = table.setmetatableindex - -local fontloader = fontloader ------ font_to_table = fontloader.to_table -local open_font = fontloader.open ------ get_font_info = fontloader.info -local close_font = fontloader.close ------ font_fields = fontloader.fields - --- table={ --- ["familyname"]="TeXGyrePagella", --- ["fontname"]="TeXGyrePagella-Regular", --- ["fullname"]="TeXGyrePagella-Regular", --- ["italicangle"]=0, --- ["names"]={ --- { --- ["lang"]="English (US)", --- ["names"]={ --- ["copyright"]="Copyright 2006, 2009 for TeX Gyre extensions by B. Jackowski and J.M. Nowacki (on behalf of TeX users groups). This work is released under the GUST Font License -- see http://tug.org/fonts/licenses/GUST-FONT-LICENSE.txt for details.", --- ["family"]="TeXGyrePagella", --- ["fullname"]="TeXGyrePagella-Regular", --- ["postscriptname"]="TeXGyrePagella-Regular", --- ["preffamilyname"]="TeX Gyre Pagella", --- ["subfamily"]="Regular", --- ["trademark"]="Please refer to the Copyright section for the font trademark attribution notices.", --- ["uniqueid"]="2.004;UKWN;TeXGyrePagella-Regular", --- ["version"]="Version 2.004;PS 2.004;hotconv 1.0.49;makeotf.lib2.0.14853", --- }, --- }, --- }, --- ["pfminfo"]={ --- ["avgwidth"]=528, --- ["codepages"]={ 536871315, 0 }, --- ["firstchar"]=32, --- ["fstype"]=12, --- ["hhead_ascent"]=1098, --- ["hhead_descent"]=-283, --- ["hheadascent_add"]=0, --- ["hheaddescent_add"]=0, --- ["hheadset"]=1, --- ["lastchar"]=64260, --- ["linegap"]=0, --- ["os2_breakchar"]=32, --- ["os2_capheight"]=692, --- ["os2_defaultchar"]=0, --- ["os2_family_class"]=0, --- ["os2_strikeypos"]=269, --- ["os2_strikeysize"]=50, --- ["os2_subxoff"]=0, --- ["os2_subxsize"]=650, --- ["os2_subyoff"]=75, --- ["os2_subysize"]=600, --- ["os2_supxoff"]=0, --- ["os2_supxsize"]=650, --- ["os2_supyoff"]=350, --- ["os2_supysize"]=600, --- ["os2_typoascent"]=726, --- ["os2_typodescent"]=-274, --- ["os2_typolinegap"]=200, --- ["os2_vendor"]="UKWN", --- ["os2_winascent"]=1098, --- ["os2_windescent"]=283, --- ["os2_xheight"]=449, --- ["panose"]={ --- ["armstyle"]="Any", --- ["contrast"]="Any", --- ["familytype"]="Any", --- ["letterform"]="Any", --- ["midline"]="Any", --- ["proportion"]="Any", --- ["serifstyle"]="Any", --- ["strokevariation"]="Any", --- ["weight"]="Book", --- ["xheight"]="Any", --- }, --- ["panose_set"]=1, --- ["pfmfamily"]=81, --- ["pfmset"]=1, --- ["subsuper_set"]=1, --- ["typoascent_add"]=0, --- ["typodescent_add"]=0, --- ["unicoderanges"]={ 536871047, 0, 0, 0 }, --- ["vheadset"]=0, --- ["vlinegap"]=0, --- ["weight"]=400, --- ["width"]=5, --- ["winascent_add"]=0, --- ["windescent_add"]=0, --- }, --- ["units_per_em"]=1000, --- ["version"]="2.004;PS 2.004;hotconv 1.0.49;makeotf.lib2.0.14853", --- ["weight"]="Book", --- } - --- We had this as temporary solution because we needed a bit more info but in the --- meantime it got an interesting side effect: currently luatex delays loading of e.g. --- glyphs so here we first load and then discard which is a waste. In the past it did --- free memory because a full load was done. One of these things that goes unnoticed. --- --- local function get_full_info(...) -- check with taco what we get / could get --- local ff = open_font(...) --- if ff then --- local d = ff -- and font_to_table(ff) --- d.glyphs, d.subfonts, d.gpos, d.gsub, d.lookups = nil, nil, nil, nil, nil --- close_font(ff) --- return d --- else --- return nil, "error in loading font" --- end --- end - --- Phillip suggested this faster variant but it's still a hack as fontloader.info should --- return these keys/values (and maybe some more) but at least we close the loader which --- might save some memory in the end. - --- local function get_full_info(name) --- local ff = open_font(name) --- if ff then --- local fields = table.tohash(font_fields(ff),true) -- isn't that one stable --- local d = { --- names = fields.names and ff.names, --- familyname = fields.familyname and ff.familyname, --- fullname = fields.fullname and ff.fullname, --- fontname = fields.fontname and ff.fontname, --- weight = fields.weight and ff.weight, --- italicangle = fields.italicangle and ff.italicangle, --- units = fields.units_per_em and ff.units_per_em, --- designsize = fields.design_size and ff.design_size, --- minsize = fields.design_range_bottom and ff.design_range_bottom, --- maxsize = fields.design_range_top and ff.design_range_top, --- italicangle = fields.italicangle and ff.italicangle, --- pfmweight = pfminfo and pfminfo.weight or 400, --- pfmwidth = pfminfo and pfminfo.width or 5, --- } --- -- setmetatableindex(d,function(t,k) --- -- report_names("warning, trying to access field %a in font table of %a",k,name) --- -- end) --- close_font(ff) --- return d --- else --- return nil, "error in loading font" --- end --- end - --- more efficient: - -local fields = nil - -local function check_names(names) - if names then - for i=1,#names do - local name = names[i] - if lower(name.lang) == "english (us)" then -- lower added - return name.names - end - end - end -end - -local function get_full_info(name) - local ff = open_font(name) - if ff then - -- unfortunately luatex aborts when a field is not available but we just make - -- sure that we only access a few known ones - local pfminfo = ff.pfminfo or { } - local names = check_names(ff.names) or { } - local weight = names.weight or ff.weight - local width = names.width -- no: ff.width - local d = { - fontname = ff.fontname, - fullname = names.fullname or ff.fullname, - family = names.family, - subfamily = names.subfamily, - familyname = names.preffamilyname or names.family or ff.familyname, - subfamilyname = names.prefmodifiers or names.subfamily, - weight = weight and lower(weight), - width = width and lower(width), - italicangle = round(1000*(tonumber(ff.italicangle) or 0))/1000 or 0, - units = ff.units_per_em, - designsize = ff.design_size, - minsize = ff.design_range_bottom, - maxsize = ff.design_range_top, - pfmweight = pfminfo.weight or 400, - pfmwidth = pfminfo.width or 5, - monospaced = pfminfo.panose and pfminfo.panose.proportion == "Monospaced", - } - close_font(ff) - return d - else - return nil, "error in loading font" - end -end - --- As we have lazy loading anyway, this one still is full and with less code than --- the previous one. But this depends on the garbage collector to kick in and in the --- current version that somehow happens not that often (on my machine I end up with --- some 3 GB extra before that happens). - --- local function get_full_info(...) --- local ff = open_font(...) --- if ff then --- local d = { } -- ff is userdata so [1] or # fails on it --- setmetatableindex(d,ff) --- return d -- garbage collection will do the close_font(ff) --- else --- return nil, "error in loading font" --- end --- end - -fonts = fonts or { } -local handlers = fonts.handlers or { } -fonts.handlers = handlers -local otf = handlers.otf or { } -handlers.otf = otf -local readers = otf.readers or { } -otf.readers = readers - -fontloader.fullinfo = get_full_info -readers.getinfo = readers.getinfo or get_full_info diff --git a/tex/context/base/mkiv/font-syn.lua b/tex/context/base/mkiv/font-syn.lua index 18c25fbfd..a68276504 100644 --- a/tex/context/base/mkiv/font-syn.lua +++ b/tex/context/base/mkiv/font-syn.lua @@ -46,9 +46,6 @@ local findfile = resolvers.findfile local cleanpath = resolvers.cleanpath local resolveprefix = resolvers.resolve ------ fontloader = fontloader -- still needed for pfb (now) ------ get_font_info = fontloader.info - local settings_to_hash = utilities.parsers.settings_to_hash_tolerant local trace_names = false trackers.register("fonts.names", function(v) trace_names = v end) diff --git a/tex/context/base/mkiv/grph-bmp.lua b/tex/context/base/mkiv/grph-bmp.lua index 256b64309..d863b1a98 100644 --- a/tex/context/base/mkiv/grph-bmp.lua +++ b/tex/context/base/mkiv/grph-bmp.lua @@ -38,29 +38,39 @@ function bitmaps.new(xsize,ysize,colorspace,colordepth,mask) } end +-- function backends.codeinjections.bitmap(bitmap) +-- return lpdf.injectors.bitmap(bitmap) +-- end + local function flush(bitmap) - return wrapimage(lpdf.injectors.bitmap(bitmap)) + local specification = backends.codeinjections.bitmap(bitmap) + if specification then + return wrapimage(specification) + end end bitmaps.flush = flush function bitmaps.tocontext(bitmap,width,height) - if type(width) == "number" then - width = width .. "sp" - end - if type(height) == "number" then - height = height .. "sp" - end - if width or height then - context.scale ( - { - width = width, - height = height, - }, - flush(bitmap) - ) - else - context(flush(bitmap)) + local bmp = flush(bitmap) + if bmp then + if type(width) == "number" then + width = width .. "sp" + end + if type(height) == "number" then + height = height .. "sp" + end + if width or height then + context.scale ( + { + width = width, + height = height, + }, + bmp + ) + else + context(bmp) + end end end diff --git a/tex/context/base/mkiv/grph-img.lua b/tex/context/base/mkiv/grph-img.lua index 9acd1a5de..55ae5a3a0 100644 --- a/tex/context/base/mkiv/grph-img.lua +++ b/tex/context/base/mkiv/grph-img.lua @@ -32,9 +32,9 @@ local getposition = files.getposition local setmetatableindex = table.setmetatableindex local setmetatablecall = table.setmetatablecall -local lpdf = lpdf or { } -local pdfmajorversion = lpdf.majorversion -local pdfminorversion = lpdf.minorversion +----- lpdf = lpdf or { } +----- pdfmajorversion = lpdf.majorversion +----- pdfminorversion = lpdf.minorversion local graphics = graphics or { } local identifiers = { } @@ -254,8 +254,8 @@ do local orientation = 1 local okay = false local filesize = getsize(f) -- seek end - local majorversion = pdfmajorversion and pdfmajorversion() or 2 - local minorversion = pdfminorversion and pdfminorversion() or 2 + -- local majorversion = pdfmajorversion and pdfmajorversion() or 1 + -- local minorversion = pdfminorversion and pdfminorversion() or 7 while getposition(f) < filesize do local b = readbyte(f) if not b then @@ -280,10 +280,14 @@ do end local name = tagdata.name if name == "SOF0" or name == "SOF1" or name == "SOF2" then - if majorversion == 1 and minorversion <= 2 then - specification.error = "no progressive DCT in PDF <= 1.2" - break - end + -- + -- It makes no sense to support pdf < 1.3 so we now just omit this + -- test. There is no need to polute the code with useless tests. + -- + -- if majorversion == 1 and minorversion <= 2 then + -- specification.error = "no progressive DCT in PDF <= 1.2" + -- break + -- end length = readcardinal2(f) specification.colordepth = readcardinal(f) specification.ysize = readcardinal2(f) @@ -477,8 +481,6 @@ do local orientation = 1 local okay = false local filesize = getsize(f) -- seek end - local majorversion = pdfmajorversion and pdfmajorversion() or 2 - local minorversion = pdfminorversion and pdfminorversion() or 2 -- local pos = 0 -- signature diff --git a/tex/context/base/mkiv/grph-inc.lua b/tex/context/base/mkiv/grph-inc.lua index 0856e0de9..fdac5f1a9 100644 --- a/tex/context/base/mkiv/grph-inc.lua +++ b/tex/context/base/mkiv/grph-inc.lua @@ -157,36 +157,11 @@ function checkimage(figure) end end ---- begin of mapping / this will become graphics & code|nodeinjections but not this year +-- This is a bit of abstraction. Fro a while we will follow the luatex image +-- model. -local __img__ = type(img) == "table" and img or { } -images.__img__ =__img__ - -local imgnew = __img__.new -local imgscan = __img__.scan -local imgcopy = __img__.copy -local imgwrap = __img__.node -local imgembed = __img__.immediatewrite - -if imgnew then - -- catch (actually we should be less picky in img) - local __img__new__ = imgnew - imgnew = function(t) - t.kind = nil - return __img__new__(t) - end -end - -updaters.register("backend.update.img",function() - local img = images.__img__ - imgnew = img.new - imgscan = img.scan - imgcopy = img.copy - imgwrap = img.wrap - imgembed = img.embed -end) - -local imagekeys = { -- only relevant ones +local imagekeys = { + -- only relevant ones (permitted in luatex) "width", "height", "depth", "bbox", "colordepth", "colorspace", "filename", "filepath", "visiblefilename", @@ -214,28 +189,26 @@ images.keys = imagekeys images.types = imagetypes images.sizes = imagesizes --- new interface - local function createimage(specification) - return imgnew(specification) + return backends.codeinjections.newimage(specification) end local function copyimage(specification) - return imgcopy(specification) + return backends.codeinjections.copyimage(specification) end local function scanimage(specification) - return imgscan(specification) + return backends.codeinjections.scanimage(specification) end local function embedimage(specification) -- write the image to file - return imgembed(specification) + return backends.codeinjections.embedimage(specification) end local function wrapimage(specification) -- create an image rule - return imgwrap(specification) + return backends.codeinjections.wrapimage(specification) end images.create = createimage @@ -244,20 +217,20 @@ images.copy = copyimage images.wrap = wrapimage images.embed = embedimage --- now we reimplement img: - -img = { - new = createimage, - scan = scanimage, - copy = copyimage, - node = wrapimage, - write = function(specification) context(wrapimage(specification)) end, - immediatewrite = embedimage, - immediatewriteobject = function() end, -- not upported, experimental anyway - boxes = function() return sortedkeys(imagesizes) end, - fields = function() return imagekeys end, - types = function() return { unpack(imagetypes,0,#imagetypes) } end, -} +-- If really needed we can provide: +-- +-- img = { +-- new = createimage, +-- scan = scanimage, +-- copy = copyimage, +-- node = wrapimage, +-- write = function(specification) context(wrapimage(specification)) end, +-- immediatewrite = embedimage, +-- immediatewriteobject = function() end, -- not upported, experimental anyway +-- boxes = function() return sortedkeys(imagesizes) end, +-- fields = function() return imagekeys end, +-- types = function() return { unpack(imagetypes,0,#imagetypes) } end, +-- } -- end of copies / mapping diff --git a/tex/context/base/mkiv/grph-inc.mkiv b/tex/context/base/mkiv/grph-inc.mkiv index f2f626b28..abf9d709a 100644 --- a/tex/context/base/mkiv/grph-inc.mkiv +++ b/tex/context/base/mkiv/grph-inc.mkiv @@ -20,11 +20,10 @@ \writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion} -\ifcase\contextlmtxmode - \registerctxluafile{grph-inc}{} -\else - \registerctxluafile{grph-img}{} - \registerctxluafile{grph-inc}{} +\registerctxluafile{grph-img}{} +\registerctxluafile{grph-inc}{} + +\ifcase\contextlmtxmode \else \registerctxluafile{grph-bmp}{} \registerctxluafile{grph-chk}{} \fi diff --git a/tex/context/base/mkiv/grph-mem.lua b/tex/context/base/mkiv/grph-mem.lua index ff3548350..bde216826 100644 --- a/tex/context/base/mkiv/grph-mem.lua +++ b/tex/context/base/mkiv/grph-mem.lua @@ -21,142 +21,74 @@ local report = logs.reporter("memstream") local trace = false trackers.register ("graphics.memstreams", function(v) trace = v end) local data = { } -if pdfe then - - local function setmemstream(name,stream,once) - if once and data[name] then - if trace then - report("not overloading %a",name) -- - end - return data[name] - end - local kind = figures.guessfromstring(stream) - local identifier = false - if kind == "pdf" then - identifier = pdfe.new(stream,#stream,name) - if not identifier then - report("no valid pdf stream %a",name) - elseif trace then - report("setting %a with identifier %a",name,identifier) - end - else - identifier = "m_k_i_v_memstream_" .. name .. "." .. kind - io.savedata(identifier,stream) - end - if not identifier then - identifier = "invalid-memstream" - end - data[name] = identifier - return identifier - end - - resolvers.setmemstream = setmemstream - - function resolvers.finders.memstream(specification) - local name = specification.path - local identifier = data[name] - if identifier then - if trace then - report("reusing %a with identifier %a",name,identifier) - end - return identifier - end - local stream = io.loaddata(name) - if stream and stream ~= "" then - return setmemstream(name,stream) - end +local function setmemstream(name,stream,once) + if once and data[name] then if trace then - report("no valid memstream %a",name) + report("not overloading %a",name) -- end - return resolvers.finders.notfound() + return data[name] end - - local flush = { } - - function resolvers.resetmemstream(name,afterpage) - if afterpage then - flush[#flush+1] = name - end - end - - luatex.registerpageactions(function() - if #flush > 0 then - for i=1,#flush do - local identifier = data[name] - if identifier then - os.remove(identifier) - data[name] = nil - end - end - flush = { } - end - end) - -else - - local opened = { } - - local function setmemstream(name,stream,once) - if once and data[name] then - if trace then - report("not overloading %a",name) -- - end - return data[name] - end - local memstream, identifier = epdf.openMemStream(stream,#stream,name) + local kind = figures.guessfromstring(stream) + local identifier = false + if kind == "pdf" then + identifier = pdfe.new(stream,#stream,name) if not identifier then - report("no valid stream %a",name) - identifier = "invalid-memstream" + report("no valid pdf stream %a",name) elseif trace then report("setting %a with identifier %a",name,identifier) end - data [name] = identifier - opened[name] = memstream - return identifier + else + identifier = "m_k_i_v_memstream_" .. name .. "." .. kind + io.savedata(identifier,stream) end + if not identifier then + identifier = "invalid-memstream" + end + data[name] = identifier + return identifier +end - resolvers.setmemstream = setmemstream +resolvers.setmemstream = setmemstream - function resolvers.finders.memstream(specification) - local name = specification.path - local identifier = data[name] - if identifier then - if trace then - report("reusing %a with identifier %a",name,identifier) - end - return identifier - end - local stream = io.loaddata(name) - if not stream or stream == "" then - if trace then - report("no valid file %a",name) - end - return resolvers.finders.notfound() - else - return setmemstream(name,stream) +function resolvers.finders.memstream(specification) + local name = specification.path + local identifier = data[name] + if identifier then + if trace then + report("reusing %a with identifier %a",name,identifier) end + return identifier + end + local stream = io.loaddata(name) + if stream and stream ~= "" then + return setmemstream(name,stream) end + if trace then + report("no valid memstream %a",name) + end + return resolvers.finders.notfound() +end - local flush = { } +local flush = { } - function resolvers.resetmemstream(name,afterpage) - if afterpage then - flush[#flush+1] = name - else - opened[name] = nil - end +function resolvers.resetmemstream(name,afterpage) + if afterpage then + flush[#flush+1] = name end +end - luatex.registerpageactions(function() - if #flush > 0 then - for i=1,#flush do - opened[flush[i]] = nil -- we keep of course data[name] because of reuse +luatex.registerpageactions(function() + if #flush > 0 then + for i=1,#flush do + local identifier = data[name] + if identifier then + os.remove(identifier) + data[name] = nil end - flush = { } end - end) - -end + flush = { } + end +end) figures.identifiers.list[#figures.identifiers.list+1] = function(specification) local name = specification.request.name diff --git a/tex/context/base/mkiv/grph-rul.lua b/tex/context/base/mkiv/grph-rul.lua index 08edade1f..194823161 100644 --- a/tex/context/base/mkiv/grph-rul.lua +++ b/tex/context/base/mkiv/grph-rul.lua @@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['grph-rul'] = { } local tonumber, next, type = tonumber, next, type +local concat = table.concat local attributes = attributes local nodes = nodes @@ -15,6 +16,7 @@ local context = context local bpfactor = number.dimenfactors.bp local nuts = nodes.nuts +local nodepool = nuts.pool local userrule = nuts.rules.userrule local outlinerule = nuts.pool.outlinerule local ruleactions = nuts.rules.ruleactions @@ -24,6 +26,8 @@ local setattr = nuts.setattr local tonode = nuts.tonode local getattribute = tex.getattribute +local getwhd = nuts.getwhd +local setwhd = nuts.setwhd local lefttoright_code = nodes.dirvalues.lefttoright @@ -143,6 +147,184 @@ end do + -- This is the old oval method that we keep it for compatibility reasons. Of + -- course one can use mp instead. It could be improved but at the cost of more + -- code than I'm willing to add for something hardly used. + + local function round(p,kind) + local method = tonumber(p.corner) or 0 + if method < 0 or method > 27 then + method = 0 + end + local width = p.width or 0 + local height = p.height or 0 + local depth = p.depth or 0 + local total = height + depth + local radius = p.radius or 655360 + local line = p.line or 65536 + local how = (method > 8 or kind ~= "fill") and "S" or "f" + local half = line / 2 + local xmin = half * bpfactor + local xmax = ( width - half) * bpfactor + local ymax = ( height - half) * bpfactor + local ymin = (-depth + half) * bpfactor + local full = ( radius + half) + local xxmin = full * bpfactor + local xxmax = ( width - full) * bpfactor + local yymax = ( height - full) * bpfactor + local yymin = (-depth + full) * bpfactor + line = line * bpfactor + if xxmin <= xxmax and yymin <= yymax then + local list = nil + if method == 0 then + list = { + "q", line, "w", xxmin, ymin, "m", xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", + xmax, yymax, "l", xmax, ymax, xxmax, ymax, "y", xxmin, ymax, "l", xmin, ymax, + xmin, yymax, "y", xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", "h", how, "Q", + } + elseif method == 1 then + list = { + "q", line, "w", xxmin, ymin, "m", xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", + xmax, ymax, "l", xmin, ymax, "l", xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", + "h", how, "Q", + } + elseif method == 2 then + list = { + "q", line, "w", xxmin, ymin, "m", xmax, ymin, "l", xmax, ymax, "l", xxmin, ymax, + "l", xmin, ymax, xmin, yymax, "y", xmin, yymin, "l", xmin, ymin, xxmin, ymin, + "y", "h", how, "Q", + } + elseif method == 3 then + list = { + "q", line, "w", xmin, ymin, "m", xmax, ymin, "l", xmax, yymax, "l", xmax, ymax, + xxmax, ymax, "y", xxmin, ymax, "l", xmin, ymax, xmin, yymax, "y", xmin, ymin, + "l", "h", how, "Q", + } + + elseif method == 4 then + list = { + "q", line, "w", xmin, ymin, "m", xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", + xmax, yymax, "l", xmax, ymax, xxmax, ymax, "y", xmin, ymax, "l", xmin, ymin, "l", + "h", how, "Q", + } + elseif method == 5 then + list = { + "q", line, "w", xmin, ymin, "m", xmax, ymin, "l", xmax, yymax, "l", xmax, ymax, + xxmax, ymax, "y", xmin, ymax, "l", xmin, ymin, "l", "h", how, "Q", + } + elseif method == 6 then + list = { + "q", line, "w", xmin, ymin, "m", xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", + xmax, ymax, "l", xmin, ymax, "l", xmin, ymin, "l", "h", how, "Q", + } + elseif method == 7 then + list = { + "q", line, "w", xxmin, ymin, "m", xmax, ymin, "l", xmax, ymax, "l", xmin, ymax, + "l", xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", "h", how, "Q", + } + elseif method == 8 then + list = { + "q", line, "w", xmin, ymin, "m", xmax, ymin, "l", xmax, ymax, "l", xxmin, ymax, + "l", xmin, ymax, xmin, yymax, "y", xmin, ymin, "l", "h", how, "Q", + } + elseif method == 9 then + list = { + "q", line, "w", xmin, ymax, "m", xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", + xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", xmax, ymax, "l", how, "Q", + } + elseif method == 10 then + list = { + "q", line, "w", xmax, ymax, "m", xxmin, ymax, "l", xmin, ymax, xmin, yymax, "y", + xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", xmax, ymin, "l", how, "Q", + } + elseif method == 11 then + list = { + "q", line, "w", xmax, ymin, "m", xmax, yymax, "l", xmax, ymax, xxmax, ymax, "y", + xxmin, ymax, "l", xmin, ymax, xmin, yymax, "y", xmin, ymin, "l", how, "Q", + } + elseif method == 12 then + list = { + "q", line, "w", xmin, ymax, "m", xxmax, ymax, "l", xmax, ymax, xmax, yymax, "y", + xmax, yymin, "l", xmax, ymin, xxmax, ymin, "y", xmin, ymin, "l", how, "Q", + } + elseif method == 13 then + list = { + "q", line, "w", xmin, ymax, "m", xxmax, ymax, "l", xmax, ymax, xmax, yymax, "y", + xmax, ymin, "l", how, "Q", + } + elseif method == 14 then + list = { + "q", line, "w", xmax, ymax, "m", xmax, yymin, "l", xmax, ymin, xxmax, ymin, "y", + xmin, ymin, "l", how, "Q", + } + elseif method == 15 then + list = { + "q", line, "w", xmax, ymin, "m", xxmin, ymin, "l", xmin, ymin, xmin, yymin, "y", + xmin, ymax, "l", how, "Q", + } + elseif method == 16 then + list = { + "q", line, "w", xmin, ymin, "m", xmin, yymax, "l", xmin, ymax, xxmin, ymax, "y", + xmax, ymax, "l", how, "Q", + } + elseif method == 17 then + list = { + "q", line, "w", xxmax, ymax, "m", xmax, ymax, xmax, yymax, "y", how, "Q", + } + elseif method == 18 then + list = { + "q", line, "w", xmax, yymin, "m", xmax, ymin, xxmax, ymin, "y", how, "Q", + } + elseif method == 19 then + list = { + "q", line, "w", xxmin, ymin, "m", xmin, ymin, xmin, yymin, "y", how, "Q", + } + elseif method == 20 then + list = { + "q", line, "w", xmin, yymax, "m", xmin, ymax, xxmin, ymax, "y", how, "Q", + } + elseif method == 21 then + list = { + "q", line, "w", xxmax, ymax, m, xmax, ymax, xmax, yymax, "y", xmin, yymax, "m", + xmin, ymax, xxmin, ymax, "y", how, "Q", + } + elseif method == 22 then + list = { + "q", line, "w", xxmax, ymax, "m", xmax, ymax, xmax, yymax, "y", xmax, yymin, "m", + xmax, ymin, xxmax, ymin, "y", how, "Q", + } + elseif method == 23 then + list = { + "q", line, "w", xmax, yymin, "m", xmax, ymin, xxmax, ymin, "y", xxmin, ymin, "m", + xmin, ymin, xmin, yymin, "y", how, "Q", + } + elseif method == 24 then + list = { + "q", line, "w", xxmin, ymin, "m", xmin, ymin, xmin, yymin, "y", xmin, yymax, "m", + xmin, ymax, xxmin, ymax, "y", how, "Q", + } + elseif method == 25 then + list = { + "q", line, "w", xxmax, ymax, "m", xmax, ymax, xmax, yymax, "y", xmax, yymin, "m", + xmax, ymin, xxmax, ymin, "y", xxmin, ymin, "m", xmin, ymin, xmin, yymin, "y", + xmin, yymax, "m", xmin, ymax, xxmin, ymax, "y", how, "Q", + } + elseif method == 26 then + list = { + "q", line, "w", xmax, yymin, "m", xmax, ymin, xxmax, ymin, "y", xmin, yymax, "m", + xmin, ymax, xxmin, ymax, "y", how, "Q", + } + + elseif method == 27 then + list = { + "q", line, "w", xxmax, ymax, "m", xmax, ymax, xmax, yymax, "y", xxmin, ymin, "m", + xmin, ymin, xmin, yymin, "y", how, "Q", + } + end + pdfprint("direct",concat(list," ")) + end + end + -- maybe %.6F local f_rectangle = formatters["%.6F w %.6F %.6F %.6F %.6F re %s"] @@ -172,30 +354,32 @@ h %s]] end) ruleactions.fill = function(p,h,v,i,n) - local l = (p.line or 65536)*bpfactor - local r = p and (p.radius or 0)*bpfactor or 0 - local w = h * bpfactor - local h = v * bpfactor - local m = nil - local t = i == "fill" and "f" or "s" - local o = l / 2 - if r > 0 then - w = w - o - h = h - o - m = f_radtangle(l, r,o, w-r,o, w,o,w,r, w,h-r, w,h,w-r,h, r,h, o,h,o,h-r, o,r, o,o,r,o, t) + if p.corner then + return round(p,i) else - w = w - l - h = h - l - m = f_rectangle(l,o,o,w,h,t) + local l = (p.line or 65536)*bpfactor + local r = p and (p.radius or 0)*bpfactor or 0 + local w = h * bpfactor + local h = v * bpfactor + local m = nil + local t = i == "fill" and "f" or "s" + local o = l / 2 + if r > 0 then + w = w - o + h = h - o + m = f_radtangle(l, r,o, w-r,o, w,o,w,r, w,h-r, w,h,w-r,h, r,h, o,h,o,h-r, o,r, o,o,r,o, t) + else + w = w - l + h = h - l + m = f_rectangle(l,o,o,w,h,t) + end + pdfprint("direct",m) end - pdfprint("direct",m) end ruleactions.draw = ruleactions.fill ruleactions.stroke = ruleactions.fill - local getwhd = nodes.nuts.getwhd - ruleactions.box = function(p,h,v,i,n) local w, h, d = getwhd(n) local line = p.line or 65536 @@ -231,22 +415,17 @@ interfaces.implement { { "type", "string" }, { "data", "string" }, { "name", "string" }, + { "radius", "dimension" }, + { "corner", "string" }, } } , actions = function(t) - -- no nuts ! local rule = userrule(t) - local ma = getattribute(a_colormodel) or 1 - local ca = getattribute(a_color) - local ta = getattribute(a_transparency) - setattrlist(rule,true) if t.type == "mp" then - t.ma = ma - t.ca = ca - t.ta = ta + t.ma = getattribute(a_colormodel) or 1 + t.ca = getattribute(a_color) + t.ta = getattribute(a_transparency) else - setattr(rule,a_colormodel,ma) - setattr(rule,a_color,ca) - setattr(rule,a_transparency,ta) + setattrlist(rule,true) end context(tonode(rule)) -- will become context.nodes.flush end @@ -306,5 +485,3 @@ interfaces.implement { context(tonode(rule)) end } - - diff --git a/tex/context/base/mkiv/lpdf-eng.lua b/tex/context/base/mkiv/lpdf-eng.lua new file mode 100644 index 000000000..6f2e75c46 --- /dev/null +++ b/tex/context/base/mkiv/lpdf-eng.lua @@ -0,0 +1,106 @@ +if not modules then modules = { } end modules ['lpdf-eng'] = { + version = 1.001, + comment = "companion to lpdf-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +if CONTEXTLMTXMODE > 0 then + return +end + +-- Here we plug in the regular luatex image handler. The low level module itself +-- is hidden from the user. + +local codeinjections = backends.pdf.codeinjections +local imgnew = img.new + +function codeinjections.newimage(specification) + if type(specification) == "table" then + specification.kind = nil + end + return imgnew(specification) +end + +codeinjections.copyimage = img.copy +codeinjections.scanimage = img.scan +codeinjections.embedimage = img.immediatewrite +codeinjections.wrapimage = img.node + +-- We cannot nil the img table because the backend code explicitly accesses the +-- new field when dealing with virtual characters. I should patch luatex for that +-- and maybe I will. So no: +-- +-- img = nil +-- +-- We keep the low level img.new function but make the rest kind of unseen. At some +-- point the other ones will be gone and one has to use the images.* wrappers. + +local unpack = unpack +local sortedkeys = table.sortedkeys +local context = context + +img = table.setmetatableindex ( + { + new = images.create, + }, + { + -- new = images.create, + scan = images.scan, + copy = images.copy, + node = images.wrap, + write = function(specification) context(images.wrap(specification)) end, + immediatewrite = images.embed, + immediatewriteobject = function() end, -- not upported, experimental anyway + boxes = function() return sortedkeys(images.sizes) end, + fields = function() return images.keys end, + types = function() return { unpack(images.types,0,#images.types) } end, + } +) + +-- + +do + + local function prepare() + if not environment.initex then + -- install new functions in pdf namespace + updaters.apply("backend.update.pdf") + -- install new functions in lpdf namespace + updaters.apply("backend.update.lpdf") + -- adapt existing shortcuts to lpdf namespace + updaters.apply("backend.update.tex") + -- adapt existing shortcuts to tex namespace + updaters.apply("backend.update") + -- + end + end + + local function outputfilename() + if not filename then + filename = addsuffix(tex.jobname,"pdf") + end + return filename + end + + function lpdf.flushers() + return { } + end + + function lpdf.actions() + return { + convert = tex.shipout, + outputfilename = outputfilename, + prepare = prepare, + } + end + + drivers.install { + name = "pdf", + flushers = lpdf.flushers(), + actions = lpdf.actions(), + } + +end + diff --git a/tex/context/base/mkiv/lpdf-epa.lua b/tex/context/base/mkiv/lpdf-epa.lua index 01c4e237f..7ec331554 100644 --- a/tex/context/base/mkiv/lpdf-epa.lua +++ b/tex/context/base/mkiv/lpdf-epa.lua @@ -31,7 +31,6 @@ local report_field = logs.reporter("backend","field") local report_outline = logs.reporter("backend","outline") local lpdf = lpdf -local epdf = epdf local backends = backends local context = context diff --git a/tex/context/base/mkiv/lpdf-epd.lua b/tex/context/base/mkiv/lpdf-epd.lua deleted file mode 100644 index 86aa6f294..000000000 --- a/tex/context/base/mkiv/lpdf-epd.lua +++ /dev/null @@ -1,1313 +0,0 @@ -if not modules then modules = { } end modules ['lpdf-epd'] = { - version = 1.001, - comment = "companion to lpdf-epa.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- This is an experimental layer around the epdf library. The reason for this layer is that --- I want to be independent of the library (which implements a selection of what a file --- provides) and also because I want an interface closer to Lua's table model while the API --- stays close to the original xpdf library. Of course, after prototyping a solution, we can --- optimize it using the low level epdf accessors. However, not all are accessible (this will --- be fixed). --- --- It will be handy when we have a __length and __next that can trigger the resolve till then --- we will provide .n as #; maybe in Lua 5.3 or later. --- --- As there can be references to the parent we cannot expand a tree. I played with some --- expansion variants but it does not pay off; adding extra checks is not worth the trouble. --- --- The document stays open. In order to free memory one has to explicitly unload the loaded --- document. --- --- We have much more checking then needed in the prepare functions because occasionally --- we run into bugs in poppler or the epdf interface. It took us a while to realize that --- there was a long standing gc issue the on long runs with including many pages could --- crash the analyzer. --- --- Normally a value is fetched by key, as in foo.Title but as it can be in pdfdoc encoding --- a safer bet is foo("Title") which will return a decoded string (or the original if it --- already was unicode). - -local setmetatable, rawset, rawget, type, next = setmetatable, rawset, rawget, type, next -local tostring, tonumber, unpack = tostring, tonumber, unpack -local lower, match, char, byte, find = string.lower, string.match, string.char, string.byte, string.find -local abs = math.abs -local concat = table.concat -local toutf, toeight, utfchar = string.toutf, utf.toeight, utf.char -local setmetatableindex = table.setmetatableindex - -local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local P, C, S, R, Ct, Cc, V, Carg, Cs, Cf, Cg = lpeg.P, lpeg.C, lpeg.S, lpeg.R, lpeg.Ct, lpeg.Cc, lpeg.V, lpeg.Carg, lpeg.Cs, lpeg.Cf, lpeg.Cg - -local epdf = epdf - lpdf = lpdf or { } -local lpdf = lpdf -local lpdf_epdf = { } -lpdf.epdf = lpdf_epdf - --- local getDict, getArray, getReal, getNum, getString, getBool, getName, getRef, getRefNum --- local getType, getTypeName --- local dictGetLength, dictGetVal, dictGetValNF, dictGetKey --- local arrayGetLength, arrayGetNF, arrayGet --- local streamReset, streamGetDict, streamGetChar - --- We use as little as possible and also not an object interface. After all, we --- don't know how the library (and its api) evolves so we better can be prepared --- for wrappers. - -local registry = debug.getregistry() - -local object = registry["epdf.Object"] -local dictionary = registry["epdf.Dict"] -local array = registry["epdf.Array"] -local xref = registry["epdf.XRef"] -local catalog = registry["epdf.Catalog"] -local pdfdoc = registry["epdf.PDFDoc"] - -if not (object and dictionary and array and xref and catalog and pdfdoc) then - logs.report("fatal error","invalid pdf inclusion library (%s)",1) - os.exit() -end - -local openPDF = epdf.open - -local getMajorVersion = pdfdoc.getPDFMajorVersion -local getMinorVersion = pdfdoc.getPDFMinorVersion -local getXRef = pdfdoc.getXRef -local getRawCatalog = pdfdoc.getCatalog - -if not (openPDF and getMajorVersion and getMinorVersion and getXRef and getRawCatalog) then - logs.report("fatal error","invalid pdf inclusion library (%s)",2) - os.exit() -end - -local getDict = object.getDict -local getArray = object.getArray -local getReal = object.getReal -local getInt = object.getInt -local getString = object.getString -local getBool = object.getBool -local getName = object.getName -local getRef = object.getRef -local getRefNum = object.getRefNum - -local getType = object.getType - -if not (getDict and getArray and getReal and getInt and getString and getBool and getName and getRef and getRefNum and getType) then - logs.report("fatal error","invalid pdf inclusion library (%s)",3) - os.exit() -end - -local streamReset = object.streamReset -local streamGetDict = object.streamGetDict -local streamGetChar = object.streamGetChar -local streamGetAll = object.streamGetAll - -if not (streamReset and streamGetDict and streamGetChar) then - logs.report("fatal error","invalid pdf inclusion library (%s)",3) - os.exit() -end - -local dictGetLength = dictionary.getLength -local dictGetVal = dictionary.getVal -local dictGetValNF = dictionary.getValNF -local dictGetKey = dictionary.getKey - -if not (dictGetLength and dictGetVal and dictGetValNF and dictGetKey) then - logs.report("fatal error","invalid pdf inclusion library (%s)",4) - os.exit() -end - -local arrayGetLength = array.getLength -local arrayGetNF = array.getNF -local arrayGet = array.get - -if not (arrayGetLength and arrayGetNF and arrayGet) then - logs.report("fatal error","invalid pdf inclusion library (%s)",5) - os.exit() -end - --- these are kind of weird as they can't be accessed by (root) object - -local getNumPages = catalog.getNumPages -local getPageRef = catalog.getPageRef - -local fetch = xref.fetch -local getCatalog = xref.getCatalog -local getDocInfo = xref.getDocInfo - -if not (getNumPages and getPageRef and fetch and getCatalog and getDocInfo) then - logs.report("fatal error","invalid pdf inclusion library (%s)",6) - os.exit() -end - --- we're done with library shortcuts - -local typenames = { [0] = - "boolean", - "integer", - "real", - "string", - "name", - "null", - "array", - "dictionary", - "stream", - "ref", - "cmd", - "error", - "eof", - "none", - "integer64", -} - -local typenumbers = table.swapped(typenames) - -local null_object_code = typenumbers.null -local ref_object_code = typenumbers.ref - -local report_epdf = logs.reporter("epdf") - -local function fatal_error(...) - report_epdf(...) - report_epdf("aborting job in order to avoid crash") - os.exit() -end - --- epdf is the built-in library - -function epdf.type(o) - local t = lower(match(tostring(o),"[^ :]+")) - return t or "?" -end - -local checked_access - --- dictionaries (can be optimized: ... resolve and redefine when all locals set) - -local frompdfdoc = lpdf.frompdfdoc - -local get_flagged - -if lpdf.dictionary then - - local pdfdictionary = lpdf.dictionary - local pdfarray = lpdf.array - local pdfconstant = lpdf.constant - local pdfstring = lpdf.string - local pdfunicode = lpdf.unicode - - get_flagged = function(t,f,k) - local tk = t[k] -- triggers resolve - local fk = f[k] - if not fk then - return tk - elseif fk == "name" then - return pdfconstant(tk) - elseif fk == "array" then - return pdfarray(tk) - elseif fk == "dictionary" then - return pdfarray(tk) - elseif fk == "rawtext" then - return pdfstring(tk) - elseif fk == "unicode" then - return pdfunicode(tk) - else - return tk - end - end - -else - - get_flagged = function(t,f,k) - local tk = t[k] -- triggers resolve - local fk = f[k] - if not fk then - return tk - elseif fk == "rawtext" then - return frompdfdoc(tk) - else - return tk - end - end - -end - -local function prepare(document,d,t,n,k,mt,flags) - for i=1,n do - local v = dictGetVal(d,i) - if v then - local r = dictGetValNF(d,i) - local kind = getType(v) - if kind == null_object_code then - -- ignore - elseif kind then - local key = dictGetKey(d,i) - if r and getType(r) == ref_object_code then - local objnum = getRefNum(r) - local cached = document.__cache__[objnum] - if not cached then - cached = checked_access[kind](v,document,objnum,mt) - if cached then - document.__cache__[objnum] = cached - document.__xrefs__[cached] = objnum - end - end - t[key] = cached - else - local v, flag = checked_access[kind](v,document) - t[key] = v - if flag and flags then - flags[key] = flag -- flags - end - end - else - report_epdf("warning: nil value for key %a in dictionary",key) - end - else - fatal_error("error: invalid value at index %a in dictionary of %a",i,document.filename) - end - end - if mt then - setmetatable(t,mt) - else - getmetatable(t).__index = nil - end - return t[k] -end - --- local function prepare(document,d,t,n,k,mt,flags) --- for i=1,n do --- local v = dictGetValNF(d,i) --- if v then --- local key = dictGetKey(d,i) --- local kind = getType(v) --- if kind == ref_object_code then --- local objnum = getRefNum(v) --- local cached = document.__cache__[objnum] --- if not cached then --- local v = dictGetVal(d,i) --- local kind = getType(v) --- cached = checked_access[kind](v,document,objnum,mt) --- if cached then --- document.__cache__[objnum] = cached --- document.__xrefs__[cached] = objnum --- end --- end --- t[key] = cached --- else --- local v, flag = checked_access[kind](v,document) --- t[key] = v --- if flag and flags then --- flags[key] = flag -- flags --- end --- end --- end --- end --- if mt then --- setmetatable(t,mt) --- else --- getmetatable(t).__index = nil --- end --- return t[k] --- end - -local function some_dictionary(d,document) - local n = d and dictGetLength(d) or 0 - if n > 0 then - local t = { } - local f = { } - setmetatable(t, { - __index = function(t,k) - return prepare(document,d,t,n,k,_,_,f) - end, - __call = function(t,k) - return get_flagged(t,f,k) - end, - -- __kind = function(k) - -- return f[k] or type(t[k]) - -- end, - } ) - return t, "dictionary" - end -end - -local function get_dictionary(object,document,r,mt) - local d = getDict(object) - local n = d and dictGetLength(d) or 0 - if n > 0 then - local t = { } - local f = { } - setmetatable(t, { - __index = function(t,k) - return prepare(document,d,t,n,k,mt,f) - end, - __call = function(t,k) - return get_flagged(t,f,k) - end, - -- __kind = function(k) - -- return f[k] or type(t[k]) - -- end, - } ) - return t, "dictionary" - end -end - --- arrays (can be optimized: ... resolve and redefine when all locals set) - -local function prepare(document,a,t,n,k) - for i=1,n do - local v = arrayGet(a,i) - if v then - local kind = getType(v) - if kind == null_object_code then - -- ignore - elseif kind then - local r = arrayGetNF(a,i) - if r and getType(r) == ref_object_code then - local objnum = getRefNum(r) - local cached = document.__cache__[objnum] - if not cached then - cached = checked_access[kind](v,document,objnum) - document.__cache__[objnum] = cached - document.__xrefs__[cached] = objnum - end - t[i] = cached - else - t[i] = checked_access[kind](v,document) - end - else - report_epdf("warning: nil value for index %a in array",i) - end - else - fatal_error("error: invalid value at index %a in array of %a",i,document.filename) - end - end - local m = getmetatable(t) - if m then - m.__index = nil - m.__len = nil - end - if k then - return t[k] - end -end - --- local function prepare(document,a,t,n,k) --- for i=1,n do --- local v = arrayGetNF(a,i) --- if v then --- local kind = getType(v) --- if kind == ref_object_code then --- local objnum = getRefNum(v) --- local cached = document.__cache__[objnum] --- if not cached then --- local v = arrayGet(a,i) --- local kind = getType(v) --- cached = checked_access[kind](v,document,objnum) --- document.__cache__[objnum] = cached --- document.__xrefs__[cached] = objnum --- end --- t[i] = cached --- else --- t[i] = checked_access[kind](v,document) --- end --- end --- end --- local m = getmetatable(t) --- if m then --- m.__index = nil --- m.__len = nil --- end --- if k then --- return t[k] --- end --- end - -local function some_array(a,document) - local n = a and arrayGetLength(a) or 0 - if n > 0 then - local t = { n = n } - setmetatable(t, { - __index = function(t,k) - return prepare(document,a,t,n,k,_,_,f) - end, - __len = function(t) - prepare(document,a,t,n,_,_,f) - return n - end, - __call = function(t,k) - return get_flagged(t,f,k) - end, - -- __kind = function(k) - -- return f[k] or type(t[k]) - -- end, - } ) - return t, "array" - end -end - -local function get_array(object,document) - local a = getArray(object) - local n = a and arrayGetLength(a) or 0 - if n > 0 then - local t = { n = n } - local f = { } - setmetatable(t, { - __index = function(t,k) - return prepare(document,a,t,n,k,_,_,f) - end, - __len = function(t) - prepare(document,a,t,n,_,_,f) - return n - end, - __call = function(t,k) - return get_flagged(t,f,k) - end, - -- __kind = function(k) - -- return f[k] or type(t[k]) - -- end, - } ) - return t, "array" - end -end - --- todo: collect chunks - --- local function streamaccess(s,_,what) --- if not what or what == "all" or what == "*all" then --- local t, n = { }, 0 --- streamReset(s) --- while true do --- local c = streamGetChar(s) --- if c < 0 then --- break --- else --- n = n + 1 --- t[n] = char(c) --- end --- end --- return concat(t,"",1,n) --- end --- end - -local function getstream(s) - streamReset(s) - if streamGetAll then - return streamGetAll(s) - else - local t, b, n = { }, { }, 0 - while true do - local c = streamGetChar(s) - if c < 0 then - break - else - n = n + 1 - b[n] = c - end - if n == 2000 then - t[#t+1] = char(unpack(b,1,n)) - n = 1 - end - end - t[#t+1] = char(unpack(b,1,n)) - return concat(t) - end -end - -local function streamaccess(s,_,what) - if not what or what == "all" or what == "*all" then - return getstream(s) - end -end - -local function get_stream(d,document) - if d then - streamReset(d) - local s = some_dictionary(streamGetDict(d),document) - getmetatable(s).__call = function(...) return streamaccess(d,...) end - return s - end -end - --- We need to convert the string from utf16 although there is no way to --- check if we have a regular string starting with a bom. So, we have --- na dilemma here: a pdf doc encoded string can be invalid utf. - --- <hex encoded> : implicit 0 appended if odd --- (byte encoded) : \( \) \\ escaped --- --- <FE><FF> : utf16be --- --- \r \r \t \b \f \( \) \\ \NNN and \<newline> : append next line --- --- the getString function gives back bytes so we don't need to worry about --- the hex aspect. - -local u_pattern = lpeg.patterns.utfbom_16_be * lpeg.patterns.utf16_to_utf8_be ------ b_pattern = lpeg.patterns.hextobytes - -local function get_string(v) - -- the toutf function only converts a utf16 string and leaves the original - -- untouched otherwise; one might want to apply lpdf.frompdfdoc to a - -- non-unicode string - local s = getString(v) - if not s or s == "" then - return "" - end - local u = lpegmatch(u_pattern,s) - if u then - return u, "unicode" - end - -- this is too tricky and fails on e.g. reload of url www.pragma-ade.com) - -- local b = lpegmatch(b_pattern,s) - -- if b then - -- return b, "rawtext" - -- end - return s, "rawtext" -end - -local function get_name(v) - return getName(v), "name" -end - -local function get_null() - return nil -end - --- we have dual access: by typenumber and by typename - -local function invalidaccess(k,document) - local fullname = type(document) == "table" and document.fullname - if fullname then - fatal_error("error, asking for key %a in checker of %a",k,fullname) - else - fatal_error("error, asking for key %a in checker",k) - end -end - -checked_access = setmetatableindex(function(t,k) - return function(v,document) - invalidaccess(k,document) - end -end) - -checked_access[typenumbers.boolean] = getBool -checked_access[typenumbers.integer] = getInt -checked_access[typenumbers.real] = getReal -checked_access[typenumbers.string] = get_string -- getString -checked_access[typenumbers.name] = get_name -checked_access[typenumbers.null] = get_null -checked_access[typenumbers.array] = get_array -- d,document,r -checked_access[typenumbers.dictionary] = get_dictionary -- d,document,r -checked_access[typenumbers.stream] = get_stream -checked_access[typenumbers.ref] = getRef - -for i=0,#typenames do - local checker = checked_access[i] - if not checker then - checker = function() - return function(v,document) - invalidaccess(i,document) - end - end - checked_access[i] = checker - end - checked_access[typenames[i]] = checker -end - -local function getnames(document,n,target) -- direct - if n then - local Names = n.Names - if Names then - if not target then - target = { } - end - for i=1,Names.n,2 do - target[Names[i]] = Names[i+1] - end - else - local Kids = n.Kids - if Kids then - for i=1,Kids.n do - target = getnames(document,Kids[i],target) - end - end - end - return target - end -end - -local function getkids(document,n,target) -- direct - if n then - local Kids = n.Kids - if Kids then - for i=1,Kids.n do - target = getkids(document,Kids[i],target) - end - elseif target then - target[#target+1] = n - else - target = { n } - end - return target - end -end - --- /OCProperties << --- /OCGs [ 15 0 R 17 0 R 19 0 R 21 0 R 23 0 R 25 0 R 27 0 R ] --- /D << --- /Order [ 15 0 R 17 0 R 19 0 R 21 0 R 23 0 R 25 0 R 27 0 R ] --- /ON [ 15 0 R 17 0 R 19 0 R 21 0 R 23 0 R 25 0 R 27 0 R ] --- /OFF [ ] --- >> --- >> - -local function getlayers(document) - local properties = document.Catalog.OCProperties - if properties then - local layers = properties.OCGs - if layers then - local t = { } - local n = layers.n - for i=1,n do - local layer = layers[i] - t[i] = layer.Name - end - t.n = n - return t - end - end -end - -local function getstructure(document) - -- this might become a tree - return document.Catalog.StructTreeRoot -end - --- This is the only messy helper. We can't access the root as any object (it seems) --- so we need a few low level acessors. It's anyway sort of simple enough to deal --- with but it won't win a beauty contest. - -local function getpages(document,Catalog) - local __data__ = document.__data__ - local __xrefs__ = document.__xrefs__ - local __cache__ = document.__cache__ - local __xref__ = document.__xref__ - -- - local rawcatalog = getRawCatalog(__data__) - local nofpages = getNumPages(rawcatalog) - -- - local majorversion = getMajorVersion(__data__) - local minorversion = getMinorVersion(__data__) - -- - local pages = { } - local metatable = { __index = Catalog.Pages } -- somewhat empty - -- - for pagenumber=1,nofpages do - local pagereference = getPageRef(rawcatalog,pagenumber).num - local pageobject = fetch(__xref__,pagereference,0) - local pagedata = get_dictionary(pageobject,document,pagereference,metatable) - if pagedata then - -- rawset(pagedata,"number",pagenumber) - pagedata.number = pagenumber - pagedata.object = pageobject - pages[pagenumber] = pagedata - __xrefs__[pagedata] = pagereference - __cache__[pagereference] = pagedata - else - report_epdf("missing pagedata at slot %i",i) - end - end - -- - pages.n = nofpages - -- - document.pages = pages - document.majorversion = majorversion - document.minorversion = minorversion - -- - return pages -end - -local function resolve(document,k) - local entry = nil - local Catalog = document.Catalog - local Names = Catalog.Names - if k == "pages" then - entry = getpages(document,Catalog) - elseif k == "destinations" then - entry = getnames(document,Names and Names.Dests) - elseif k == "javascripts" then - entry = getnames(document,Names and Names.JS) - elseif k == "widgets" then - entry = getnames(document,Names and Names.AcroForm) - elseif k == "embeddedfiles" then - entry = getnames(document,Names and Names.EmbeddedFiles) - elseif k == "layers" then - entry = getlayers(document) - elseif k == "structure" then - entry = getstructure(document) - end - document[k] = entry - return entry -end - -local loaded = { } - -function lpdf_epdf.load(filename) - local document = loaded[filename] - if not document then - statistics.starttiming(lpdf_epdf) - local __data__ = openPDF(filename) -- maybe resolvers.find_file - if __data__ then - local __xref__ = getXRef(__data__) - document = { - filename = filename, - __cache__ = { }, - __xrefs__ = { }, - __fonts__ = { }, - __data__ = __data__, - __xref__ = __xref__ - } - document.Catalog = some_dictionary(getDict(getCatalog(__xref__)),document) - document.Info = some_dictionary(getDict(getDocInfo(__xref__)),document) - setmetatableindex(document,resolve) - -- - document.nofpages = getNumPages(getRawCatalog(__data__)) - else - document = false - end - loaded[filename] = document - loaded[document] = document - statistics.stoptiming(lpdf_epdf) - -- print(statistics.elapsedtime(lpdf_epdf)) - end - return document or nil -end - -function lpdf_epdf.unload(filename) - local document = loaded[filename] - if document then - loaded[document] = nil - loaded[filename] = nil - end -end - --- for k, v in next, expand(t) do - -local function expand(t) - if type(t) == "table" then - local dummy = t.dummy - end - return t -end - --- for k, v in expanded(t) do - -local function expanded(t) - if type(t) == "table" then - local dummy = t.dummy - end - return next, t -end - -lpdf_epdf.expand = expand -lpdf_epdf.expanded = expanded - --- we could resolve the text stream in one pass if we directly handle the --- font but why should we complicate things - -local hexdigit = R("09","AF") -local numchar = ( P("\\") * ( (R("09")^3/tonumber) + C(1) ) ) + C(1) -local number = lpegpatterns.number / tonumber -local spaces = lpegpatterns.whitespace^1 -local optspaces = lpegpatterns.whitespace^0 -local keyword = P("/") * C(R("AZ","az","09")^1) -local operator = C((R("AZ","az")+P("'")+P('"'))^1) - -local grammar = P { "start", - start = (keyword + number + V("dictionary") + V("unicode") + V("string") + V("unicode")+ V("array") + spaces)^1, - -- keyvalue = (keyword * spaces * V("start") + spaces)^1, - keyvalue = optspaces * Cf(Ct("") * Cg(keyword * optspaces * V("start") * optspaces)^1,rawset), - array = P("[") * Ct(V("start")^1) * P("]"), - dictionary = P("<<") * V("keyvalue") * P(">>"), - unicode = P("<") * Ct(Cc("hex") * C((1-P(">"))^1)) * P(">"), - string = P("(") * Ct(Cc("dec") * C((V("string")+numchar)^1)) * P(")"), -- untested -} - -local operation = Ct(grammar^1 * operator) -local parser = Ct((operation + P(1))^1) - --- beginbfrange : <start> <stop> <firstcode> --- <start> <stop> [ <firstsequence> <firstsequence> <firstsequence> ] --- beginbfchar : <code> <newcodes> - -local fromsixteen = lpdf.fromsixteen -- maybe inline the lpeg ... but not worth it - -local function f_bfchar(t,a,b) - t[tonumber(a,16)] = fromsixteen(b) -end - -local function f_bfrange_1(t,a,b,c) - print("todo 1",a,b,c) - -- c is string - -- todo t[tonumber(a,16)] = fromsixteen(b) -end - -local function f_bfrange_2(t,a,b,c) - print("todo 2",a,b,c) - -- c is table - -- todo t[tonumber(a,16)] = fromsixteen(b) -end - -local optionals = spaces^0 -local hexstring = optionals * P("<") * C((1-P(">"))^1) * P(">") -local bfchar = Carg(1) * hexstring * hexstring / f_bfchar -local bfrange = Carg(1) * hexstring * hexstring * hexstring / f_bfrange_1 - + Carg(1) * hexstring * hexstring * optionals * P("[") * Ct(hexstring^1) * optionals * P("]") / f_bfrange_2 -local fromunicode = ( - P("beginbfchar" ) * bfchar ^1 * optionals * P("endbfchar" ) + - P("beginbfrange") * bfrange^1 * optionals * P("endbfrange") + - spaces + - P(1) -)^1 * Carg(1) - -local function analyzefonts(document,resources) -- unfinished, see mtx-pdf for better code - local fonts = document.__fonts__ - if resources then - local fontlist = resources.Font - if fontlist then - for id, data in expanded(fontlist) do - if not fonts[id] then - -- a quick hack ... I will look into it more detail if I find a real - -- -application for it - local tounicode = data.ToUnicode() - if tounicode then - tounicode = lpegmatch(fromunicode,tounicode,1,{}) - end - fonts[id] = { - tounicode = type(tounicode) == "table" and tounicode or { } - } - setmetatableindex(fonts[id],"self") - end - end - end - end - return fonts -end - -local more = 0 -local unic = nil -- cheaper than passing each time as Carg(1) - -local p_hex_to_utf = C(4) / function(s) -- needs checking ! - local now = tonumber(s,16) - if more > 0 then - now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong - more = 0 - return unic[now] or utfchar(now) - elseif now >= 0xD800 and now <= 0xDBFF then - more = now - -- return "" - else - return unic[now] or utfchar(now) - end -end - -local p_dec_to_utf = C(1) / function(s) -- needs checking ! - local now = byte(s) - return unic[now] or utfchar(now) -end - -local p_hex_to_utf = P(true) / function() more = 0 end * Cs(p_hex_to_utf^1) -local p_dec_to_utf = P(true) / function() more = 0 end * Cs(p_dec_to_utf^1) - -function lpdf_epdf.getpagecontent(document,pagenumber) - - local page = document.pages[pagenumber] - - if not page then - return - end - - local fonts = analyzefonts(document,page.Resources) - - local content = page.Contents() or "" - local list = lpegmatch(parser,content) - local font = nil - -- local unic = nil - - for i=1,#list do - local entry = list[i] - local size = #entry - local operator = entry[size] - if operator == "Tf" then - font = fonts[entry[1]] - unic = font.tounicode - elseif operator == "TJ" then -- { array, TJ } - local list = entry[1] - for i=1,#list do - local li = list[i] - if type(li) == "table" then - if li[1] == "hex" then - list[i] = lpegmatch(p_hex_to_utf,li[2]) - else - list[i] = lpegmatch(p_dec_to_utf,li[2]) - end - else - -- kern - end - end - elseif operator == "Tj" or operator == "'" or operator == '"' then -- { string, Tj } { string, ' } { n, m, string, " } - local list = entry[size-1] - if list[1] == "hex" then - list[2] = lpegmatch(p_hex_to_utf,li[2]) - else - list[2] = lpegmatch(p_dec_to_utf,li[2]) - end - end - end - - unic = nil -- can be collected - - return list - -end - --- This is also an experiment. When I really need it I can improve it, for instance --- with proper position calculating. It might be usefull for some search or so. - -local softhyphen = utfchar(0xAD) .. "$" -local linefactor = 1.3 - -function lpdf_epdf.contenttotext(document,list) -- maybe signal fonts - local last_y = 0 - local last_f = 0 - local text = { } - local last = 0 - - for i=1,#list do - local entry = list[i] - local size = #entry - local operator = entry[size] - if operator == "Tf" then - last_f = entry[2] - elseif operator == "TJ" then - local list = entry[1] - for i=1,#list do - local li = list[i] - if type(li) == "string" then - last = last + 1 - text[last] = li - elseif li < -50 then - last = last + 1 - text[last] = " " - end - end - line = concat(list) - elseif operator == "Tj" then - last = last + 1 - text[last] = entry[size-1] - elseif operator == "cm" or operator == "Tm" then - local ty = entry[6] - local dy = abs(last_y - ty) - if dy > linefactor*last_f then - if last > 0 then - if find(text[last],softhyphen,1,true) then - -- ignore - else - last = last + 1 - text[last] = "\n" - end - end - end - last_y = ty - end - end - - return concat(text) -end - -function lpdf_epdf.getstructure(document,list) -- just a test - local depth = 0 - for i=1,#list do - local entry = list[i] - local size = #entry - local operator = entry[size] - if operator == "BDC" then - report_epdf("%w%s : %s",depth,entry[1] or "?",entry[2].MCID or "?") - depth = depth + 1 - elseif operator == "EMC" then - depth = depth - 1 - elseif operator == "TJ" then - local list = entry[1] - for i=1,#list do - local li = list[i] - if type(li) == "string" then - report_epdf("%w > %s",depth,li) - elseif li < -50 then - report_epdf("%w >",depth,li) - end - end - elseif operator == "Tj" then - report_epdf("%w > %s",depth,entry[size-1]) - end - end -end - --- document.Catalog.StructTreeRoot.ParentTree.Nums[2][1].A.P[1]) - --- helpers - --- function lpdf_epdf.getdestinationpage(document,name) --- local destination = document.__data__:findDest(name) --- return destination and destination.number --- end - --- This is experimental code that we need for testing the transition from --- poppler to a new lightweight library. Don't rely on this code to remain --- as it is now. Interesting is that performance of this variant is the same --- as the natural page includer. - -if img then do - - local copydictionary = nil - local copyarray = nil - - local ref_object_code = typenumbers.ref - local boolean_object_code = typenumbers.boolean - local integer_object_code = typenumbers.integer - local real_object_code = typenumbers.real - local string_object_code = typenumbers.string - local name_object_code = typenumbers.name - local null_object_code = typenumbers.null - local array_object_code = typenumbers.array - local dictionary_object_code = typenumbers.dictionary - local stream_object_code = typenumbers.stream - local cmd_object_code = typenumbers.cmd - - local pdfreserveobject = lpdf.reserveobject - local pdfflushobject = lpdf.flushobject - local pdfflushstreamobject = lpdf.flushstreamobject - local pdfreference = lpdf.reference - local pdfconstant = lpdf.constant - local pdfarray = lpdf.array - local pdfdictionary = lpdf.dictionary - local pdfunicode = lpdf.unicode - local pdfstring = lpdf.string - local pdfnull = lpdf.null - - local report = logs.reporter("backend","xobjects") - - local factor = 65536 / (7200/7227) -- 1/number.dimenfactors.bp - - local createimage = images.create - - local function scaledbbox(b) - return { b[1]*factor, b[2]*factor, b[3]*factor, b[4]*factor } - end - - local function copyobject(xref,copied,kind,r,v) - if kind == null_object_code then - return pdfnull() - elseif r and getType(r) == ref_object_code then - local objnum = getRefNum(r) - local r = copied[objnum] - if r then - -- report("%s object %i is reused",kind,objnum) - else - local o - r = pdfreserveobject() - copied[objnum] = r - if kind == array_object_code then - local a = copyarray(xref,copied,fetch(xref,objnum,0)) - pdfflushobject(r,tostring(a)) - elseif kind == dictionary_object_code then - local d = copydictionary(xref,copied,fetch(xref,objnum,0)) - pdfflushobject(r,tostring(d)) - elseif kind == stream_object_code then - local f = fetch(xref,objnum,0) - local d = copydictionary(xref,copied,false,streamGetDict(f)) - local s = getstream(f) - -- - d.Filter = nil - d.Length = nil - d.DecodeParms = nil - d.DL = nil - -- - pdfflushstreamobject(s,d,true,r) - else - report("reference not done: %s", kind) - end - end - return pdfreference(r) - elseif kind == array_object_code then - return copyarray(xref,copied,v) - elseif kind == dictionary_object_code then - return copydictionary(xref,copied,v) - elseif kind == integer_object_code then - return getInt(v) - elseif kind == real_object_code then - return getReal(v) - elseif kind == name_object_code then - return pdfconstant(getName(v)) - elseif kind == string_object_code then - local s = getString(v) - if not s or s == "" then - return "" - end - local u = lpegmatch(u_pattern,s) - if u then - return pdfunicode(s) - end - return pdfstring(s) - elseif kind == boolean_object_code then - return getBool(v) - elseif kind == stream_object_code then - -- hm ... - return getStream(v) - else - report("object not done: %s", kind) - end - end - - copyarray = function (xref,copied,object) - local a = getArray(object) - local n = a and arrayGetLength(a) or 0 - if n > 0 then - local target = pdfarray() - for i=1,n do - local v = arrayGet(a,i) - if v then - local kind = getType(v) - local r = arrayGetNF(a,i) - target[i] = copyobject(xref,copied,kind,r,v) - end - end - return target - end - end - - copydictionary = function (xref,copied,object,d) - local d = d or getDict(object) - local n = d and dictGetLength(d) or 0 - if n > 0 then - local target = pdfdictionary() - for i=1,n do - local v = dictGetVal(d,i) - if v then - local kind = getType(v) - local key = dictGetKey(d,i) - local r = dictGetValNF(d,i) - target[key] = copyobject(xref,copied,kind,r,v) - end - end - return target - end - end - - local function copy_resources(pdfdoc,xref,copied,pagedata) - local object = pagedata.object - if object then - local d = getDict(object) - local n = d and dictGetLength(d) or 0 - for i=1,n do - local k = dictGetKey(d,i) - if v and k == "Resources" then - local v = dictGetVal(d,i) - local kind = getType(v) - local r = dictGetValNF(d,i) - return copyobject(xref,copied,kind,r,v) - end - end - end - end - - local function openpdf(filename) - local pdfdoc = lpdf_epdf.load(filename) - if pdfdoc then - pdfdoc.__copied__ = pdfdoc.__copied__ or { } - pdfdoc.filename = filename - return pdfdoc - end - end - - local function closepdf(pdfdoc) - if pdfdoc then - lpdf_epdf.unload(pdfdoc.filename) - end - end - - local function querypdf(pdfdoc,pagenumber) - if pdfdoc then - if not pagenumber then - pagenumber = 1 - end - local root = pdfdoc.Catalog - local page = pdfdoc.pages[pagenumber] - if page then - local mediabox = page.MediaBox or { 0, 0, 0, 0 } - local cropbox = page.CropBox or mediabox - return { - filename = pdfdoc.filename, - pagenumber = pagenumber, - nofpages = pdfdoc.nofpages, - boundingbox = scaledbbox(cropbox), - cropbox = cropbox, - mediabox = mediabox, - bleedbox = page.BleedBox or cropbox, - trimbox = page.TrimBox or cropbox, - artbox = page.ArtBox or cropbox, - } - end - end - end - - local function copypage(pdfdoc,pagenumber,attributes) - if pdfdoc then - local root = pdfdoc.Catalog - local page = pdfdoc.pages[pagenumber or 1] - local pageinfo = querypdf(pdfdoc,pagenumber) - local contents = page.Contents - local xref = pdfdoc.__xref__ - local copied = pdfdoc.__copied__ - -- - local xobject = pdfdictionary { - Type = pdfconstant("XObject"), - Subtype = pdfconstant("Form"), - -- image attributes - FormType = 1, - BBox = pageinfo.cropbox, - -- Metadata = copy(xref,copied,root,"Metadata"), - -- Group = copy(xref,copied,page,"Group"), - -- LastModified = copy(xref,copied,page,"LastModified"), - -- Metadata = copy(xref,copied,page,"Metadata"), - -- PieceInfo = copy(xref,copied,page,"PieceInfo"), - Resources = copy_resources(pdfdoc,xref,copied,page), - -- SeparationInfo = copy(xref,copied,page,"SeparationInfo"), - } - if attributes then - for k, v in next, expand(attributes) do - page[k] = v -- maybe nested - end - end - return createimage { - bbox = pageinfo.boundingbox, - stream = contents(), - attr = xobject(), - } - end - end - - -- todo: codeinjections - - lpdf_epdf.image = { - open = openpdf, - close = closepdf, - query = querypdf, - copy = copypage, - } - -end end diff --git a/tex/context/base/mkiv/lpdf-img.lua b/tex/context/base/mkiv/lpdf-img.lua index ff89ad322..8f9c87ddd 100644 --- a/tex/context/base/mkiv/lpdf-img.lua +++ b/tex/context/base/mkiv/lpdf-img.lua @@ -1065,7 +1065,7 @@ do } end if trace then - report_png("%s: width %i, height %i, colordepth: %i, size: %i, palette %l, mask: %l, transparent %l, decode %l",filename,xsize,ysize,colordepth,#content,palette,mask,transparent,decode) + report_png("%s: width %i, height %i, colordepth %i, size %i, palette %l, mask %l, transparent %l, decode %l",filename,xsize,ysize,colordepth,#content,palette,mask,transparent,decode) end if specification.colorref then xobject.ColorSpace = pdfreference(specification.colorref) @@ -1180,6 +1180,8 @@ do } end + backends.pdf.codeinjections.bitmap = injectors.bitmap + end -- local function validcompression(data) diff --git a/tex/context/base/mkiv/lpdf-ini.lua b/tex/context/base/mkiv/lpdf-ini.lua index 050b1fa84..e39548ca6 100644 --- a/tex/context/base/mkiv/lpdf-ini.lua +++ b/tex/context/base/mkiv/lpdf-ini.lua @@ -205,8 +205,6 @@ do return pdfprint(...) end - pdfbackend.codeinjections.print = lpdf.print -- will go - -- local function transform(llx,lly,urx,ury,rx,sx,sy,ry) -- local x1 = llx * rx + lly * sy -- local y1 = llx * sx + lly * ry diff --git a/tex/context/base/mkiv/back-lpd.lua b/tex/context/base/mkiv/lpdf-lmt.lua index 9a52130b8..156d3486f 100644 --- a/tex/context/base/mkiv/back-lpd.lua +++ b/tex/context/base/mkiv/lpdf-lmt.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['back-lpd'] = { +if not modules then modules = { } end modules ['lpdf-lmt'] = { version = 1.001, comment = "companion to lpdf-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -6,11 +6,18 @@ if not modules then modules = { } end modules ['back-lpd'] = { license = "see context related readme files" } +-- The code below was originally in back-lpd.lua but it makes more sense in +-- this namespace. + +if CONTEXTLMTXMODE == 0 then + return +end + -- If you consider this complex, watch: -- -- https://www.youtube.com/watch?v=6H-cAzfB2qo -- --- or in distactionmode: +-- or in distractionmode: -- -- https://www.youtube.com/watch?v=TYuTE_1jvvE -- https://www.youtube.com/watch?v=nnicGKX3lvM @@ -20,7 +27,7 @@ if not modules then modules = { } end modules ['back-lpd'] = { local type, next, unpack, tonumber = type, next, unpack, tonumber local char, rep, find = string.char, string.rep, string.find -local formatters, splitstring = string.formatters, string.split +local formatters, splitupstring = string.formatters, string.splitup local band, extract = bit32.band, bit32.extract local concat, keys, sortedhash = table.concat, table.keys, table.sortedhash local setmetatableindex = table.setmetatableindex @@ -69,26 +76,6 @@ local properties = fonthashes.properties local report = logs.reporter("backend") -do - - local dummy = function() end - - local function unavailable(t,k) - report("calling unavailable pdf.%s function",k) - t[k] = dummy - return dummy - end - - updaters.register("backend.update.pdf",function() - setmetatableindex(pdf,unavailable) - end) - - updaters.register("backend.update",function() - pdf = setmetatableindex(unavailable) - end) - -end - -- used variables local pdf_h, pdf_v @@ -716,17 +703,17 @@ local flushpdfsave, flushpdfrestore, flushpdfsetmatrix do local function pdf_set_matrix(str,pos_h,pos_v) if shippingmode == "page" then - local rx, sx, sy, ry = splitstring(str," ") + local rx, sx, sy, ry = splitupstring(str," ") if rx and ry and sx and ry then - rx, sx, sy, ry = tonumber(rx), tonumber(ry), tonumber(sx), tonumber(sy) + rx, sx, sy, ry = tonumber(rx), tonumber(sx), tonumber(sy), tonumber(ry) local tx = pos_h * (1 - rx) - pos_v * sy local ty = pos_v * (1 - ry) - pos_h * sx if nofmatrices > 1 then local t = matrices[nofmatrices] local r_x, s_x, s_y, r_y, te, tf = t[1], t[2], t[3], t[4], t[5], t[6] - rx, sx = rx * r_x + sx * s_y, rx * s_x + sx * r_y - sy, ry = sy * r_x + ry * s_y, sy * s_x + ry * r_y - tx, ty = tx * r_x + ty * s_y + t_x, tx * s_x + ty * r_y + t_y + rx, sx = rx * r_x + sx * s_y, rx * s_x + sx * r_y + sy, ry = sy * r_x + ry * s_y, sy * s_x + ry * r_y + tx, ty = tx * r_x + ty * s_y, tx * s_x + ty * r_y end nofmatrices = nofmatrices + 1 matrices[nofmatrices] = { rx, sx, sy, ry, tx, ty } @@ -766,7 +753,7 @@ local flushpdfsave, flushpdfrestore, flushpdfsetmatrix do if nofmatrices > 0 then return unpack(matrices[nofmatrices]) else - return 0, 0, 0, 0, 0, 0 -- or 1 0 0 1 0 0 + return 1, 0, 0, 1, 0, 0 end end @@ -817,7 +804,7 @@ end local flushedxforms = { } -- actually box resources but can also be direct -local flushrule, flushsimplerule do +local flushrule, flushsimplerule, flushpdfimage do local rulecodes = nodes.rulecodes local newrule = nodes.pool.rule @@ -1153,8 +1140,6 @@ local flushrule, flushsimplerule do -- For the moment we need this hack because the engine checks the 'image' -- command in virtual fonts (so we use lua instead). - pdf.flushpdfimage = flushpdfimage - flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v) local subtype = getsubtype(current) @@ -1535,7 +1520,6 @@ local info = "" local catalog = "" local level = 0 local lastdeferred = false -local enginepdf = pdf local majorversion = 1 local minorversion = 7 local trailerid = true @@ -1601,12 +1585,6 @@ do end -local function pdfreserveobj() - nofobjects = nofobjects + 1 - objects[nofobjects] = false - return nofobjects -end - local addtocache, flushcache, cache do local data, d = { }, 0 @@ -1680,6 +1658,12 @@ local addtocache, flushcache, cache do end +local function pdfreserveobj() + nofobjects = nofobjects + 1 + objects[nofobjects] = false + return nofobjects +end + local pages = table.setmetatableindex(function(t,k) local v = pdfreserveobj() t[k] = v @@ -2148,6 +2132,8 @@ updaters.register("backend.update.pdf",function() -- reimplement what we need in context. This will change completely i.e. -- we will drop the low level interface! + local codeinjections = backends.pdf.codeinjections + local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream local img_none = imagetypes.none @@ -2163,19 +2149,19 @@ updaters.register("backend.update.pdf",function() local bpfactor = number.dimenfactors.bp - local function new_img(specification) + function codeinjections.newimage(specification) return specification end - local function copy_img(original) + function codeinjections.copyimage(original) return setmetatableindex(original) end - local function scan_img(specification) + function codeinjections.scanimgage(specification) return specification end - local function embed_img(specification) + local function embedimage(specification) lastindex = lastindex + 1 index = lastindex specification.index = index @@ -2239,11 +2225,13 @@ updaters.register("backend.update.pdf",function() return specification end - local function wrap_img(specification) + codeinjections.embedimage = embedimage + + function codeinjections.wrapimage(specification) -- local index = specification.index if not index then - embed_img(specification) + embedimage(specification) end -- local width = specification.width or 0 @@ -2256,15 +2244,6 @@ updaters.register("backend.update.pdf",function() return n end - -- plugged into the old stuff - - local img = images.__img__ - img.new = new_img - img.copy = copy_img - img.scan = scan_img - img.embed = embed_img - img.wrap = wrap_img - function pdf.includeimage(index) local specification = indices[index] if specification then @@ -2332,7 +2311,7 @@ updaters.register("backend.update.lpdf",function() topdf[id] = index end -- pdf.print or pdf.literal - pdf.flushpdfimage(index,wd,ht,dp,pos_h,pos_v) + flushpdfimage(index,wd,ht,dp,pos_h,pos_v) end local function pdfvfimage(wd,ht,dp,data,name) @@ -2365,7 +2344,7 @@ do local function prepare() if not environment.initex then - -- install new functions in pdf namespace + -- install new functions in pdf namespace updaters.apply("backend.update.pdf") -- install new functions in lpdf namespace updaters.apply("backend.update.lpdf") @@ -2374,10 +2353,6 @@ do -- adapt existing shortcuts to tex namespace updaters.apply("backend.update") -- - updaters.apply("backend.update.img") - -- - directives.enable("graphics.uselua") - -- -- if rawget(pdf,"setforcefile") then -- pdf.setforcefile(false) -- default anyway -- end @@ -2446,20 +2421,8 @@ do lpdf.convert(tex.box[boxnumber],"page") end - drivers.install { - name = "pdf", - actions = { - prepare = prepare, - wrapup = wrapup, - convert = convert, - cleanup = cleanup, - -- - initialize = initialize, - finalize = finalize, - updatefontstate = updatefontstate, - outputfilename = outputfilename, - }, - flushers = { + function lpdf.flushers() + return { character = flushcharacter, rule = flushrule, simplerule = flushsimplerule, @@ -2471,7 +2434,27 @@ do pdfsave = flushpdfsave, pdfrestore = flushpdfrestore, pdfimage = flushpdfimage, - }, + } + end + + function lpdf.actions() + return { + prepare = prepare, + wrapup = wrapup, + convert = convert, + cleanup = cleanup, + -- + initialize = initialize, + finalize = finalize, + updatefontstate = updatefontstate, + outputfilename = outputfilename, + } + end + + drivers.install { + name = "pdf", + flushers = lpdf.flushers(), + actions = lpdf.actions(), } end diff --git a/tex/context/base/mkiv/lpdf-pde.lua b/tex/context/base/mkiv/lpdf-pde.lua index c1680137d..cb6c112e7 100644 --- a/tex/context/base/mkiv/lpdf-pde.lua +++ b/tex/context/base/mkiv/lpdf-pde.lua @@ -60,29 +60,29 @@ if not (number and number.dimenfactors) then require("util-dim") end -local epdf = pdfe +local pdfe = pdfe lpdf = lpdf or { } local lpdf = lpdf local lpdf_epdf = { } -lpdf.epdf = lpdf_epdf - -local openPDF = epdf.open -local newPDF = epdf.new -local closePDF = epdf.close - -local getcatalog = epdf.getcatalog -local getinfo = epdf.getinfo -local gettrailer = epdf.gettrailer -local getnofpages = epdf.getnofpages -local getversion = epdf.getversion -local getbox = epdf.getbox -local getstatus = epdf.getstatus -local unencrypt = epdf.unencrypt - -local dictionarytotable = epdf.dictionarytotable -local arraytotable = epdf.arraytotable -local pagestotable = epdf.pagestotable -local readwholestream = epdf.readwholestream + lpdf.epdf = lpdf_epdf + +local pdfopen = pdfe.open +local pdfnew = pdfe.new +local pdfclose = pdfe.close + +local getcatalog = pdfe.getcatalog +local getinfo = pdfe.getinfo +local gettrailer = pdfe.gettrailer +local getnofpages = pdfe.getnofpages +local getversion = pdfe.getversion +local getbox = pdfe.getbox +local getstatus = pdfe.getstatus +local unencrypt = pdfe.unencrypt + +local dictionarytotable = pdfe.dictionarytotable +local arraytotable = pdfe.arraytotable +local pagestotable = pdfe.pagestotable +local readwholestream = pdfe.readwholestream local getfromreference = pdfe.getfromreference @@ -437,9 +437,9 @@ function lpdf_epdf.load(filename,userpassword,ownerpassword,fromstring) statistics.starttiming(lpdf_epdf) local __data__ if fromstring then - __data__ = newPDF(filename,#filename) + __data__ = pdfnew(filename,#filename) else - __data__ = openPDF(filename) + __data__ = pdfopen(filename) end if __data__ then if userpassword and getstatus(__data__) < 0 then @@ -491,8 +491,7 @@ function lpdf_epdf.unload(filename) if type(filename) == "string" then local document = loaded[filename] if document then --- report_epdf("%04i closed: %s",nofloaded,filename) --- nofloaded = nofloaded - 1 + -- pdfclose(document) loaded[document] = nil loaded[filename] = nil end @@ -793,7 +792,7 @@ function lpdf_epdf.getstructure(document,list) -- just a test end end -if img then do +if images then do -- This can be made a bit faster (just get raw data and pass it) but I will -- do that later. In the end the benefit is probably neglectable. diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua index cec4c414a..979ca36a0 100644 --- a/tex/context/base/mkiv/luat-cnf.lua +++ b/tex/context/base/mkiv/luat-cnf.lua @@ -70,9 +70,10 @@ function texconfig.init() "gzip", "zip", "zlib", "lfs", "ltn12", "mime", "socket", "md5", "fio", "unicode", "utf", }, extratex = { - "epdf", "kpse", "mplib", -- "fontloader", + "pdfe", "kpse", "mplib", }, obsolete = { + "epdf", "fontloader", -- can be filled by luat-log "kpse", }, diff --git a/tex/context/base/mkiv/luat-mac.lua b/tex/context/base/mkiv/luat-mac.lua index 44630b194..d13b69c42 100644 --- a/tex/context/base/mkiv/luat-mac.lua +++ b/tex/context/base/mkiv/luat-mac.lua @@ -268,6 +268,9 @@ function processors.mkxi(str,filename) return str end +processors.mkli = processors.mkvi +processors.mkil = processors.mkiv + function macros.processmk(str,filename) if filename then local suffix = filesuffix(filename) @@ -279,8 +282,18 @@ function macros.processmk(str,filename) return str end +local function validvi(filename,str) + local suffix = filesuffix(filename) + if suffix == "mkvi" or suffix == "mkli" then + return true + else + local check = lpegmatch(checker,str) + return check == "mkvi" or check == "mkli" + end +end + function macros.processmkvi(str,filename) - if filename and filesuffix(filename) == "mkvi" or lpegmatch(checker,str) == "mkvi" then + if filename and filename ~= "" and validvi(filename,str) then local oldsize = #str str = lpegmatch(parser,str,1,true) or str pushtarget("logfile") @@ -290,6 +303,8 @@ function macros.processmkvi(str,filename) return str end +macros.processmkli = macros.processmkvi + local sequencers = utilities.sequencers if sequencers then @@ -308,7 +323,7 @@ if resolvers.schemes then local path = hashed.path if path and path ~= "" then local str = resolvers.loadtexfile(path) - if filesuffix(path) == "mkvi" or lpegmatch(checker,str) == "mkvi" then + if validvi(path,str) then -- already done automatically io.savedata(cachename,str) else @@ -323,6 +338,7 @@ if resolvers.schemes then end resolvers.schemes.install('mkvi',handler,1) -- this will cache ! + resolvers.schemes.install('mkli',handler,1) -- bonus, best use just mkvi end diff --git a/tex/context/base/mkiv/meta-ini.mkiv b/tex/context/base/mkiv/meta-ini.mkiv index cf2dc883c..09d7b2c06 100644 --- a/tex/context/base/mkiv/meta-ini.mkiv +++ b/tex/context/base/mkiv/meta-ini.mkiv @@ -408,36 +408,41 @@ \let\stopMPclip\relax -\unexpanded\def\meta_grab_clip_path#1#2#3#4% #4 is alternative (called in backend code) +\unexpanded\def\meta_grab_clip_path#1#2#3% {\begingroup - \edef\width {#2}% \let\overlaywidth \width - \edef\height{#3}% \let\overlayheight\height - \d_overlay_width #2\onebasepoint - \d_overlay_height#3\onebasepoint + \d_overlay_width #2\relax + \d_overlay_height#3\relax + \edef\width {\the\d_overlay_width \space}% + \edef\height{\the\d_overlay_height\space}% \edef\currentMPclip{#1}% \ifcsname\??mpclip\currentMPclip\endcsname - \meta_grab_clip_path_indeed - \ifx\MPclippath\empty - \xdef\MPclippath{#4}% - \fi + \meta_grab_clip_path_yes \else - \xdef\MPclippath{#4}% + \meta_grab_clip_path_nop \fi \endgroup} -\def\meta_grab_clip_path_indeed +\def\meta_grab_clip_path_yes {\meta_start_current_graphic \normalexpanded{\noexpand\clf_mpsetclippath - instance {\currentMPinstance}% - format {\currentMPformat}% - data {\csname\??mpclip\currentMPclip\endcsname}% - initializations {\meta_flush_current_initializations}% - useextensions {\MPinstanceparameter\s!extensions}% - inclusions {\meta_flush_current_inclusions}% - method {\MPinstanceparameter\c!method}% + instance {\currentMPinstance}% + format {\currentMPformat}% + data {\csname\??mpclip\currentMPclip\endcsname}% + initializations {\meta_flush_current_initializations}% + useextensions {\MPinstanceparameter\s!extensions}% + inclusions {\meta_flush_current_inclusions}% + method {\MPinstanceparameter\c!method}% + width \d_overlay_width + height \d_overlay_height \relax}% \meta_stop_current_graphic} +\def\meta_grab_clip_path_nop + {\clf_mpsetclippath + width \d_overlay_width + height \d_overlay_height + \relax} + %D Since we want lables to follow the document settings, we also set the font %D related variables. @@ -574,7 +579,6 @@ \def\meta_prepare_variable_dimension {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\the\dimexpr\m_meta_current_variable}} - \startmkivmode \def\meta_prepare_variable_yes diff --git a/tex/context/base/mkiv/mlib-ctx.lua b/tex/context/base/mkiv/mlib-ctx.lua index 89f2fa0ee..e19f111b4 100644 --- a/tex/context/base/mkiv/mlib-ctx.lua +++ b/tex/context/base/mkiv/mlib-ctx.lua @@ -245,6 +245,8 @@ implement { arguments = "string", } +-- this has to become a codeinjection + function metapost.getclippath(specification) -- why not a special instance for this local mpx = metapost.pushformat(specification) local data = specification.data or "" @@ -304,7 +306,14 @@ end implement { name = "mpsetclippath", actions = function(specification) - setmacro("MPclippath",metapost.theclippath(specification),"global") + local p = specification.data and metapost.theclippath(specification) + if not p or p == "" then + local b = number.dimenfactors.bp + local w = b * (specification.width or 0) + local h = b * (specification.height or 0) + p = formatters["0 0 m %.6N 0 l %.6N %.6N l 0 %.6N l"](w,w,h,h) + end + setmacro("MPclippath",p,"global") end, arguments = { { @@ -316,6 +325,8 @@ implement { { "inclusions" }, { "method" }, { "namespace" }, + { "width", "dimension" }, + { "height", "dimension" }, }, } } diff --git a/tex/context/base/mkiv/mult-aux.mkiv b/tex/context/base/mkiv/mult-aux.mkiv index 6a2fd9fef..d77ec82a1 100644 --- a/tex/context/base/mkiv/mult-aux.mkiv +++ b/tex/context/base/mkiv/mult-aux.mkiv @@ -29,7 +29,7 @@ \unprotect -\edef\??empty{\Uchar25} \letvalue{\Uchar25}\empty % cancel: dec:24 hex:18 +\edef\??empty{\Uchar25} \letvalue{\Uchar25}\empty % hex 19 % \edef\s!parent{\Uchar29} % inlining is ugly, a tiny bit faster, but neglectable on a run @@ -227,7 +227,8 @@ \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}% \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% %\def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ? - \def#5##1##2{\ifx##1\relax\??empty\else#4##1{##2}\fi}% is {} needed around ##1 ? + %\def#5##1##2{\ifx##1\relax\??empty\else#4##1{##2}\fi}% is {} needed around ##1 ? + \def#5##1##2{\ifx##1\relax^^^^0019\else#4##1{##2}\fi}% is {} needed around ##1 ? \def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}% \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack \def#8##1{\begincsname#1#2:##1\endcsname}} diff --git a/tex/context/base/mkiv/node-syn.lua b/tex/context/base/mkiv/node-syn.lua index 35fb8fc7c..bb2eba780 100644 --- a/tex/context/base/mkiv/node-syn.lua +++ b/tex/context/base/mkiv/node-syn.lua @@ -225,6 +225,8 @@ local blockedsuffixes = { mkii = true, mkiv = true, mkvi = true, + mkil = true, + mkli = true, mkix = true, mkxi = true, -- lfg = true, diff --git a/tex/context/base/mkiv/pack-rul.mkiv b/tex/context/base/mkiv/pack-rul.mkiv index 5fb5c4853..34db6eec1 100644 --- a/tex/context/base/mkiv/pack-rul.mkiv +++ b/tex/context/base/mkiv/pack-rul.mkiv @@ -272,10 +272,15 @@ \fi} \def\pack_framed_filled_box_round - {\back_ovalbox - \d_framed_target_wd \d_framed_target_ht \d_framed_target_dp - \d_framed_linewidth \p_framed_backgroundradius - \zerocount \plusone {\ifx\p_framed_backgroundcorner\v!round0\else\number\p_framed_backgroundcorner\fi}} + {\frule + type fill + width \d_framed_target_wd + height \d_framed_target_ht + depth \d_framed_target_dp + line \d_framed_linewidth + radius \p_framed_backgroundradius\space + corner {\p_framed_backgroundcorner} + \relax} \def\pack_framed_stroked_box {\edef\p_framed_framecorner{\framedparameter\c!framecorner}% @@ -296,10 +301,14 @@ % \pack_framed_stroked_box_normal % later \def\pack_framed_stroked_box_round - {\back_ovalbox - \d_framed_target_wd \d_framed_target_ht \d_framed_target_dp - \d_framed_linewidth \p_framed_frameradius - \plusone \zerocount {\ifx\p_framed_framecorner\v!round0\else\number\p_framed_framecorner\fi}} + {\frule + width \d_framed_target_wd + height \d_framed_target_ht + depth \d_framed_target_dp + line \d_framed_linewidth + radius \p_framed_frameradius\space + corner {\p_framed_backgroundcorner} + \relax} % a lot of weird corners % diff --git a/tex/context/base/mkiv/publ-imp-apa.mkvi b/tex/context/base/mkiv/publ-imp-apa.mkvi index 36e4882d2..5603b79a5 100644 --- a/tex/context/base/mkiv/publ-imp-apa.mkvi +++ b/tex/context/base/mkiv/publ-imp-apa.mkvi @@ -703,20 +703,20 @@ apa:edition={Utgåva}, apa:Editor=Redaktör, apa:Editors=Redaktörer, - apa:Volume=Band, + apa:Volume=Band, apa:Volumes=Band, apa:nd={u.å.}, % utan årtal apa:supplement=Bilaga, % Supplement apa:MotionPicture=Spelfilm, % ? apa:Writer={Manusförfattare}, % Assuming for a movie - apa:Writers={Manusförfattare}, % + apa:Writers={Manusförfattare}, % apa:Producer=Producent, % Assuming for a movie - apa:Producers=Producenter, % + apa:Producers=Producenter, % apa:Director={Regissör}, % Assuming for a movie - apa:Directors={Regissörer}, % + apa:Directors={Regissörer}, % apa:Recordedby={Inspelad av}, % Assuming for a movie apa:Author={Författare}, - apa:Translator={Översättare}, + apa:Translator={Översättare}, apa:Advanced={Avancerad onlinepublikation}, % ? apa:Retrieved={Hämtad från}] diff --git a/tex/context/base/mkiv/publ-imp-chicago.lua b/tex/context/base/mkiv/publ-imp-chicago.lua new file mode 100644 index 000000000..cda76f52a --- /dev/null +++ b/tex/context/base/mkiv/publ-imp-chicago.lua @@ -0,0 +1,560 @@ +local specification = { + -- + -- metadata + -- + name = "chicago", + version = "1.00", + comment = "Chicago Manual of Style specification", + author = "Alan Braslau and Hans Hagen", + copyright = "ConTeXt development team", + -- + -- derived (combinations of) fields (all share the same default set) + -- + virtual = { + "authoryear", + "authoryears", + "authornum", + "num", + "suffix", + }, + -- + -- special datatypes + -- + types = { + -- + -- list of fields that are interpreted as names: "NAME [and NAME]" where + -- NAME is one of the following: + -- + -- First vons Last + -- vons Last, First + -- vons Last, Jrs, First + -- Vons, Last, Jrs, First + -- + author = "author", -- interpreted as name(s) + withauthor = "author", + editor = "author", + translator = "author", + artist = "author", + composer = "author", + producer = "author", + director = "author", + doi = "url", -- an external link + url = "url", + page = "pagenumber", -- number or range: f--t + pages = "pagenumber", + volume = "range", + number = "range", + keywords = "keyword", -- comma|-|separated list + year = "number", + }, + -- + -- categories with their specific fields + -- + categories = { + -- + -- categories are added below + -- + }, +} + +local generic = { + -- + -- A set returns the first field (in order of position below) that is found + -- present in an entry. A set having the same name as a field conditionally + -- allows the substitution of an alternate field. + -- + -- note that anything can get assigned a doi or be available online. + doi = { "doi", "url" }, + editionset = { "edition", "volume", "number", "pages" }, +} + +-- Definition of recognized categories and the fields that they contain. +-- Required fields should be present; optional fields may also be rendered; +-- all other fields will be ignored. + +-- Sets contain either/or in order of precedence. +-- +-- For a category *not* defined here yet present in the dataset, *all* fields +-- are taken as optional. This allows for flexibility in the addition of new +-- categories. + +local categories = specification.categories + +-- an article from a journal + +categories.article = { + sets = { + author = { "author", "organization", "editor", "title" }, + doi = generic.doi, + }, + required = { + "author", -- a set + }, + optional = { + "withauthor", "translator", + "year", + "subtitle", "type", "file", + "journal", "volume", "number", "pages", + "doi", "note", + -- APA ignores this: + -- + -- "month", + -- + -- fields defined in jabref but presently ignored: + -- + -- "issn", + }, +} + +-- an article from a magazine + +categories.magazine = { + sets = categories.article.sets, + required = { + "author", + "year", + "journal", + }, + optional = { + "withauthor", "translator", + "subtitle", "type", "file", + "number", + "month", "day", + "doi", "note", + }, +} + +categories.newspaper = categories.magazine + +-- (from jabref) to be identified and setup ... + +categories.periodical = { + sets = { + author = { "editor", "publisher", "organization", }, + doi = generic.doi, + }, + required = { + "title", + "year", + }, + optional = { + "author", "withauthor", "translator", + "subtitle", "file", + "series", "volume", "number", "month", + "organization", + "doi", "note", + }, +} + +-- (from jabref) to be identified and setup ... + +categories.standard = { + sets = { + author = { "author", "institution", "organization" }, + doi = generic.doi, + }, + required = { + "author", + "year", + "title", "subtitle", + "doi", "note", + }, + optional = { + "withauthor", "translator", + }, +} + +-- a book with an explicit publisher. + +categories.book = { + sets = { + author = { "author", "editor", "publisher", "title" }, + ineditor = { "editor" }, + editionset = generic.editionset, + doi = generic.doi, + }, + required = { "author" }, + optional = { + "ineditor", + "withauthor", "translator", + "year", "month", "day", + "subtitle", "type", "file", + "editionset", "series", + "address", + "doi", "note", + "abstract", + }, +} + +-- a part of a book, which may be a chapter (or section or whatever) and/or a range of pages. + +categories.inbook = { + sets = { + author = { "author", "organization", "editor", "publisher", "title", }, + ineditor = { "editor" }, + editionset = generic.editionset, + doi = generic.doi, + }, + required = { + "author", + "year" , + }, + optional = { + "ineditor", + "withauthor", "translator", + "subtitle", "type", "file", + "booktitle", "subbooktitle", + -- APA ignores this: "chapter", + "editionset", "series", + "month", + "address", + "doi", "note", + }, +} + +-- a book having its own title as part of a collection. +-- (like inbook, but we here make booktitle required) + +categories.incollection = { + sets = { + author = { "author", "editor", "publisher", "title", }, + ineditor = { "editor" }, + editionset = generic.editionset, + doi = generic.doi, + }, + required = { + "author", + "booktitle", + "year", + }, + optional = { + "ineditor", + "withauthor", "translator", + "subtitle", "type", "file", + "subbooktitle", + "editionset", "series", + -- APA ignores this: "chapter", + "month", + "address", + "doi", "note", + }, +} + +-- a work that is printed and bound, but without a named publisher or sponsoring institution. + +categories.booklet = { + sets = { + author = { "author", "title", }, + publisher = { "howpublished" }, -- no "publisher"! + doi = generic.doi, + }, + required = { + "author" + }, + optional = { + "withauthor", "translator", + "publisher", + "year", "month", + "subtitle", "type", "file", + "address", + "doi", "note", + }, +} + +-- the proceedings of a conference. + +categories.proceedings = { + sets = { + author = { "editor", "organization", "publisher", "title" }, -- no "author"! + publisher = { "publisher", "organization" }, + editionset = generic.editionset, + doi = generic.doi, + }, + required = { + "author", + "year" + }, + optional = { + "withauthor", "translator", + "publisher", + "subtitle", "file", + "editionset", "series", + "month", + "address", + "doi", "note", + }, +} + +-- an article in a conference proceedings. + +categories.inproceedings = { + sets = categories.incollection.sets, + required = categories.incollection.required, + optional = { + "withauthor", "translator", + "subtitle", "type", "file", + "month", + "edition", "series", + "address", "organization", + "doi", "note", + }, +} + +categories.conference = categories.inproceedings + +-- a thesis (of course). + +categories.thesis = { + sets = { + doi = generic.doi, + }, + required = { + "author", + "title", + "school", + "year", + "type" + }, + optional = { + "withauthor", "translator", + "subtitle", "file", + "month", + "address", + "doi", "note", + }, +} + +categories.mastersthesis = { + sets = categories.thesis.sets, + required = { + "author", + "title", + "school", + "year" + }, + optional = { + "withauthor", "translator", + "type", + "subtitle", "file", + "month", + "address", + "doi", "note", + }, +} +categories.phdthesis = categories.mastersthesis + +-- a report published by a school or other institution, usually numbered within a series. + +categories.techreport = { + sets = { + author = { "author", "institution", "publisher", "title" }, + publisher = { "publisher", "institution", }, + editionset = { "type", "volume", "number", "pages" }, -- no "edition"! + doi = generic.doi, + }, + required = { + "author", + "title", + "institution", + "year" + }, + optional = { + "withauthor", "translator", + "publisher", + "address", + "subtitle", "file", + "editionset", + "month", + "doi", "note", + }, +} + +-- technical documentation. + +categories.manual = { + sets = { + author = { "author", "organization", "publisher", "title" }, + publisher = { "publisher", "organization", }, + editionset = generic.editionset, + doi = generic.doi, + }, + required = { + "title" + }, + optional = { + "author", "publisher", + "withauthor", "translator", + "address", + "subtitle", "file", + "editionset", "month", "year", + "doi", "note", +-- "abstract", + }, +} + +-- a patent (of course). + +categories.patent = { + sets = { + author = { "author", "assignee", }, + publisher = { "publisher", "assignee", }, + year = { "year", "yearfiled", }, + month = { "month", "monthfiled", }, + day = { "day", "dayfiled", }, + doi = generic.doi, + }, + required = { + "nationality", + "number", + "year", + }, + optional = { + "type", + --check this: "language", + "author", "publisher", + "withauthor", "translator", + "title", "subtitle", "file", + "address", + "day", "month", + "doi", "note" + }, +} + +-- a document having an author and title, but not formally published. + +categories.unpublished = { + sets = { + doi = generic.doi, + }, + required = { + "author", + "title", + "note" + }, + optional = { + "withauthor", "translator", + "subtitle", "file", + "year", "month", + "doi" + }, +} + +-- like misc below but includes organization. + +categories.electronic = { + sets = { + doi = generic.doi, + author = { "author", "organization", }, + }, + required = { + "title" + }, + optional = { + "subtitle", "type", "file", + "year", "month", + "author", "withauthor", "translator", + "address", + "organization", + "howpublished", + "doi", "note" + }, +} + +-- not bibtex categories... + +categories.film = { + sets = { + doi = generic.doi, + author = { "author", "producer", "director", }, + }, + required = { + "author", + "title", + "year", + "address", "publisher", -- aka studio + }, + optional = { + "withauthor", "translator", + "type", + "note", + "doi", + }, +} + +categories.music = { + sets = { + doi = generic.doi, + author = { "composer", "artist", "title", "album" }, + title = { "title", "album", }, + }, + required = { + "author", + "title", + "year", + "address", "publisher", -- aka label + }, + optional = { + "withauthor", "translator", + "type", + "note", + "doi", + }, +} + +-- use this type when nothing else fits. + +categories.misc = { + sets = { + doi = generic.doi, + }, + required = { + -- nothing is really important here + }, + optional = { + "author", "withauthor", "translator", + "title", "subtitle", "file", + "year", "month", + "howpublished", + "doi", "note", + }, +} + +-- other (whatever jabref does not know!) + +categories.other = { + sets = { + doi = generic.doi, + }, + required = { + "author", + "title", + "year" + }, + optional = { + "withauthor", "translator", + "subtitle", "file", + "doi", "note", + }, +} + +-- if all else fails to match: + +categories.literal = { + sets = { + author = { "key" }, + doi = generic.doi, + }, + required = { + "author", + "text" + }, + optional = { + "withauthor", "translator", + "doi", "note" + }, + virtual = false, +} + +-- done + +return specification diff --git a/tex/context/base/mkiv/publ-imp-chicago.mkvi b/tex/context/base/mkiv/publ-imp-chicago.mkvi new file mode 100644 index 000000000..867535ca6 --- /dev/null +++ b/tex/context/base/mkiv/publ-imp-chicago.mkvi @@ -0,0 +1,1686 @@ +%D \module +%D [ file=publ-imp-chicago, +%D version=2019.05.20, +%D title=Chicago bibliography style, +%D subtitle=Publications, +%D author=Alan Braslau and Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is therefore copyrighted +%D by \PRAGMA. See mreadme.pdf for details. + +\startbtxrenderingdefinitions[chicago] + +\ifdefined\c!translate \else \def\c!translate{translate} \fi + +%D Reference: +%D \startTEX +%D @Book{Chicago2010, +%D title ={The Chicago Manual of Style}, +%D subtitle ={The Essential Guide for Writers, Editors, and Publishers}, +%D year ={2010}, +%D edition ={Sixteenth}, +%D address ={Chicago and London}, +%D publisher={The University of Chicago Press}, +%D Xpages ={1026}, +%D url ={https://www.chicagomanualofstyle.org/}, +%D } +%D \stopTEX + +% set ALL specific Chicago compliant values + +\definebtx + [chicago] + [\c!default=default, + \c!specification=chicago, + \c!otherstext={\btxspace\btxlabeltext{others}}, + %\c!journalconversion=\v!normal, + \c!monthconversion=\v!month, + \c!stopper:initials={. }, % with a (breakable) space + \c!separator:names:2={\btxcomma}, % aka namesep - in this namespace + \c!separator:names:3={\btxcomma\btxlabeltext{and}\space}, % comma separated list + \c!separator:names:4={\btxspace\btxlabeltext{and}\space}] % last of two, no comma! + +% First, define list and rendering parameters + +% The Chicago style sorts the unnumbered rendered list by authoryear + +\definebtxrendering + [chicago] + [\c!specification=chicago, + \c!sorttype=authoryear, + \c!numbering=\v!no] + +\setupbtxlist + [chicago] + [\c!alternative=\v!paragraph, + \c!align={normal,verytolerant,stretch}, + %\c!width=\v!fit, + %\c!distance=.5\emwidth, + \c!margin=3.5\emwidth] + +\definebtx + [chicago:\s!list] + [chicago] + %[\c!otherstext={\btxcomma\btxnobreakspace\textellipsis\space}, + % \c!etallimit=7, + % \c!etaldisplay=6, + % \c!etaloption=last, + [\c!authorconversion=inverted] + +% First, we define a namespace for a few special fields + +\definebtx + [chicago:\s!list:author] + [chicago:\s!list] + +\definebtx + [chicago:\s!list:withauthor] + [chicago:\s!list:author] + +\definebtx + [chicago:\s!list:editor] + [chicago:\s!list:author] + +\definebtx + [chicago:\s!list:ineditor] + [chicago:\s!list:editor] + [\c!authorconversion=normalshort] + +\definebtx + [chicago:\s!list:translator] + [chicago:\s!list:author] + [\c!authorconversion=normalshort] + +\definebtx + [chicago:\s!list:director] + [chicago:\s!list:author] + +\definebtx + [chicago:\s!list:producer] + [chicago:\s!list:author] + +\definebtx + [chicago:\s!list:suffix] + [chicago:\s!list] + +\definebtx + [chicago:\s!list:url] + [chicago:\s!list] + +\definebtx + [chicago:\s!list:doi] + [chicago:\s!list] + +\definebtx + [chicago:\s!list:\s!page] + [chicago:\s!list] + %[\c!separator:2={\btxcomma}, + % \c!separator:3={\btxcomma\btxlabeltext{and}\space}, + % \c!separator:4={\btxspace\btxlabeltext{and}\space}, + [\c!left={\btxleftparenthesis}, + \c!right={\btxrightparenthesis}, + \c!command={\wordright}] + +\definebtx + [chicago:\s!list:numbering] + [chicago:\s!list] + [\c!right={\btxspace}] + +\definebtx + [chicago:\s!list:numbering:default] + [chicago:\s!list:numbering] + +\definebtx + [chicago:\s!list:numbering:num] + [chicago:\s!list:numbering] + [\c!stopper={.}] + +\definebtx + [chicago:\s!list:numbering:short] + [chicago:\s!list:numbering] + +\definebtx + [chicago:\s!list:numbering:tag] + [chicago:\s!list:numbering] + +\definebtx + [chicago:\s!list:numbering:index] + [chicago:\s!list:numbering] + +% Next, we define a namespace for each category + +%D In order to be able to get journals expanded (or normalized or abbreviated) you need +%D to load a list: +%D +%D \starttyping +%D \btxloadjournallist[journals.txt] % the jabref list +%D \stoptyping + +\definebtx + [chicago:\s!list:journal] + [chicago:\s!list] + [\c!style=\v!italic] + %command=\btxexpandedjournal] % btxabbreviatedjournal + +\definebtx + [chicago:\s!list:volume] + [chicago:\s!list] + [\c!style=\v!italic] + +\definebtx + [chicago:\s!list:title] + [chicago:\s!list] + [\c!style=\v!italic, + \c!command=\Word, + \c!translate=\v!yes] + +\definebtx + [chicago:\s!list:title:article] + [chicago:\s!list:title] + [\c!style=] % journal is set in italics + +\definebtx + [chicago:\s!list:title:magazine] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:newspaper] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:periodical] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:standard] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:book] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:booktitle:inbook] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:inbook] + [chicago:\s!list:title] + [\c!style=] % booktitle is set in italics + +\definebtx + [chicago:\s!list:booktitle:incollection] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:incollection] + [chicago:\s!list:title] + [\c!style=] % booktitle is set in italics + +\definebtx + [chicago:\s!list:title:proceedings] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:booktitle:inproceedings] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:inproceedings] + [chicago:\s!list:title] + [\c!style=] % booktitle is set in italics + +\definebtx + [chicago:\s!list:booktitle:conference] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:conference] + [chicago:\s!list:title] + [\c!style=] % booktitle is set in italics + +\definebtx + [chicago:\s!list:title:thesis] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:phdthesis] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:mastersthesis] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:booklet] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:manual] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:techreport] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:unpublished] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:patent] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:electronic] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:music] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:film] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:other] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:misc] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:title:literal] + [chicago:\s!list:title] + +\definebtx + [chicago:\s!list:type] + [\c!command=\Word] + +% Then define and set cite parameters. + +\definebtx + [chicago:\s!cite] + [chicago] + [\c!alternative=authoryear, + \c!otherstext={\btxcomma\btxlabeltext{others}}, + \c!etallimit=1, + \c!etaldisplay=1, + \c!authorconversion=\v!name, + \c!sorttype=normal, % \v!normal ? + \c!style=, + \c!compress=\v!yes] % note that cite sorts only work with compress=yes. + +\definebtx + [chicago:\s!cite:name] + [chicago:\s!cite] + [\c!authorconversion=\v!name] + +\definebtx + [chicago:\s!cite:inverted] + [chicago:\s!cite] + [\c!authorconversion=\v!invertedshort] + +\definebtx + [chicago:\s!cite:invertedshort] + [chicago:\s!cite] + [\c!authorconversion=\v!invertedshort] + +\definebtx + [chicago:\s!cite:normalshort] + [chicago:\s!cite] + [\c!authorconversion=\v!normalshort] + +\definebtx + [chicago:\s!cite:normal] + [chicago:\s!cite] + [\c!authorconversion=\v!normal] + +\definebtx + [chicago:\s!cite:author] + [chicago:\s!cite] + +\definebtx + [chicago:\s!cite:editor] + [chicago:\s!cite:author] + +\definebtx + [chicago:\s!cite:translator] + [chicago:\s!cite:author] + +\definebtx + [chicago:\s!cite:organization] + [chicago:\s!cite] + +\definebtx + [chicago:\s!cite:authoryear] + [chicago:\s!cite:author] + [\c!left={(}, + \c!right={)}, + \c!inbetween={\btxspace}] + +\definebtx + [chicago:\s!cite:default] + [chicago:\s!cite:authoryear] + +\definebtx + [chicago:\s!cite:authoryears] + [chicago:\s!cite:author] + [\c!left=, % these two settings are perhaps redundant? + \c!right=, + \c!inbetween={\btxspace}] + +\definebtx + [chicago:\s!cite:authornum] + [chicago:\s!cite:author] + [\c!left={(}, + \c!right={)}] + +\definebtx + [chicago:\s!cite:author:num] % todo + [chicago:\s!cite:authornum] + [\c!left={\btxspace[}, + \c!right={]}] + +\definebtx + [chicago:\s!cite:author:year] % todo + [chicago:\s!cite] + +\definebtx + [chicago:\s!cite:author:years] % todo + [chicago:\s!cite:authoryears] + [\c!inbetween=, + \c!left={\btxspace(}, + \c!right={)}] + +\definebtx + [chicago:\s!cite:lefttext] + [chicago:\s!cite] + [\c!left=, + \c!right={\btxspace}] + +\definebtx + [chicago:\s!cite:righttext] + [chicago:\s!cite] + [\c!left={\btxcomma}, + \c!right=] + +\definebtx + [chicago:\s!cite:year] + [chicago:\s!cite] + [\c!separator:2={\btxcomma}, % :0 and :1 - between items of a list + \c!separator:3={\btxcomma\btxlabeltext{and}\space}, + \c!separator:4={\btxspace\btxlabeltext{and}\space}] + +\definebtx + [chicago:\s!cite:title] + [chicago:\s!cite] + [\c!separator:2={\btxcomma}, % :0 and :1 - between items of a list + \c!separator:3={\btxcomma\btxlabeltext{and}\space}, + \c!separator:4={\btxspace\btxlabeltext{and}\space}, + \c!command={\language[\currentbtxlanguage]}, % BAH + \c!sorttype=none, + \c!style=\v!italic] + +\definebtx + [chicago:\s!cite:subtitle] + [chicago:\s!cite:title] + +\definebtx + [chicago:\s!cite:booktitle] + [chicago:\s!cite:title] + +\definebtx + [chicago:\s!cite:subbooktitle] + [chicago:\s!cite:booktitle] + +% Will these get used? + +\definebtx + [chicago:\s!cite:title:inbook] + [chicago:\s!cite:title] + [\c!style=] % not italic + +\definebtx + [chicago:\s!cite:title:incollection] + [chicago:\s!cite:title:inbook] + +\definebtx + [chicago:\s!cite:title:inproceedings] + [chicago:\s!cite:title:inbook] + +\definebtx + [chicago:\s!cite:subtitle:inbook] + [chicago:\s!cite:title:inbook] + +\definebtx + [chicago:\s!cite:subtitle:incollection] + [chicago:\s!cite:title:incollection] + +\definebtx + [chicago:\s!cite:subtitle:inproceedings] + [chicago:\s!cite:title:inproceedings] + + +\definebtx + [chicago:\s!cite:tag] + [chicago:\s!cite] + [\c!left={[}, + \c!right={]}] + +\definebtx + [chicago:\s!cite:index] + [chicago:\s!cite] + [\c!left={[}, + \c!right={]}] + +\definebtx + [chicago:\s!cite:page] + [chicago:\s!cite] + [\c!left=, + \c!right=, + \c!separator:2={\btxcomma}, % :0 and :1 - between items of a list + \c!separator:3={\btxcomma\btxlabeltext{and}\space}, + \c!separator:4={\btxspace\btxlabeltext{and}\space}] + +\definebtx + [chicago:\s!cite:pages] + [chicago:\s!cite:page] + +\definebtx + [chicago:\s!cite:keywords] + [chicago:\s!cite] + +\definebtx + [chicago:\s!cite:short] + [chicago:\s!cite] + [\c!left={[}, + \c!right={]}] + +\definebtx + [chicago:\s!cite:category] + [chicago:\s!cite] + +\definebtx + [chicago:\s!cite:url] + [chicago:\s!cite] + [\c!left={(}, + \c!right={)}] + +\definebtx + [chicago:\s!cite:doi] + [chicago:\s!cite:url] + +\definebtx + [chicago:\s!cite:num] + [chicago:\s!cite] + [\c!left={[}, + \c!right={]}, + \c!separator:2={,}, % no space + \c!separator:3=\btxparameter{\c!separator:2}, + \c!separator:4=\btxparameter{\c!separator:2}] + +\definebtx + [chicago:\s!cite:textnum] + [chicago:\s!cite:num] + [\c!left={Ref.\nbsp}, + \c!right=, + \c!separator:2={\btxcomma}, + \c!separator:3={\btxspace\btxlabeltext{and}\space}, + \c!separator:4={\btxspace\btxlabeltext{and}\space}] + +\definebtx + [chicago:\s!cite:entry] + [chicago:\s!cite] + [\c!left=, + \c!right=, + \c!inbetween={\btxspace}, + \c!separator:2={\btxsemicolon}, + \c!separator:3=\btxparameter{\c!separator:2}, + \c!separator:4=\btxparameter{\c!separator:2}] + +\definebtx + [chicago:\s!cite:footnote] + [chicago:\s!cite:entry] + +% Now we setup for the details of the renderings + +%D Sometimes we have verbose injections in an entry and these can be language +%D dependent, so we use labels. +%D +%D Because we want to mix rendering (in the manual) we need a namespace in label +%D texts: + +\setupbtxlabeltext + [en] + [chicago:number={No.}, + chicago:edition={ed.}, + chicago:Editor={Ed.}, + chicago:Editors={Eds.}, + chicago:Volume={Vol.}, + chicago:Volumes={Vols.}, + chicago:nd={n.d.}, % no date + chicago:supplement={Suppl.}, % Supplement (not used?) + chicago:MotionPicture={Motion picture}, + chicago:Writer=Writer, + chicago:Writers=Writers, + chicago:Producer=Producer, + chicago:Producers=Producers, + chicago:Director=Director, + chicago:Directors=Directors, + chicago:Recordedby={Recorded by}, + chicago:Author=Author, + chicago:Translator={Trans.}, % Translator(s) + chicago:Advanced={Advanced online publication}, + chicago:Retrieved={Retrieved from}] % {Available from}] + +\setupbtxlabeltext + [nl] + [chicago:number={Nr.}, + chicago:edition={ed.}, % editie + chicago:Editor=Editor, % Ed./Eds. + chicago:Editors=Editors, + chicago:Volume={Vol.}, + chicago:Volumes={Vols.}, + chicago:nd={g.d.} % geen datum + chicago:supplement=Supplement, + chicago:MotionPicture=Film, % ? + chicago:Writer=Scenarioschrijver, % ? + chicago:Writers=Schrijvers, % ? + chicago:Producer=Producent, % ? + chicago:Producers=Producents, % ? + chicago:Director=Directeur, + chicago:Directors=Directeurs, + chicago:Recordedby={Opgenomen door}, % ? + chicago:Author=Auteur, + chicago:Translator=Vertaler, + chicago:Advanced={Geavanceerde online publicatie}, + chicago:Retrieved={Ontvangen van}] % {Beschikbaar vanaf}] + +\setupbtxlabeltext + [fr] + [chicago:number={N\high{o}}, + chicago:edition={édition}, + chicago:Editor=Éditeur, + chicago:Editors=Éditeurs, + chicago:Volume=Volume, + chicago:Volumes=Volumes, + chicago:nd={s.d.}, % sans date + chicago:supplement=Supplément, + chicago:MotionPicture={Film cinématographique}, + chicago:Writer=Scénariste, + chicago:Writers=Scénaristes, + chicago:Producer=Producteur, + chicago:Producers=Producteurs, + chicago:Director=Réalisateur, + chicago:Directors=Réalisateurs, + chicago:Recordedby={Enregistré par}, + chicago:Author=Auteur, + chicago:Translator=Traducteur, + chicago:Advanced={Publication en ligne anticipée}, + chicago:Retrieved={Téléchargé de}] % {Disponible à}] + +\setupbtxlabeltext + [de] + [chicago:number={Nr.}, + chicago:edition=Auf\/lage, + chicago:Editor=Herausgeber, % Hrsg./Hg. + chicago:Editors=Herausgeber, + chicago:Volume=Band, % Bd. + chicago:Volumes={Bände}, + chicago:nd={o.D.}, % ohne Datum (mostly: o.J. / ohne Jahr) + chicago:supplement={Beilage}, % Supplement + chicago:MotionPicture=Kinofilm, % ? + chicago:Writer=Drehbuchautor, % ? + chicago:Writers=Schriftsteller, % ? + chicago:Producer=Producer, % ? + chicago:Producers=Produzenten, % ? + chicago:Director=Director, % ? + chicago:Directors=Directors, % ? + chicago:Recordedby={per Einschreiben}, % ? + chicago:Author=Autor, + chicago:Translator={Übersetzer}, % Übers. + chicago:Advanced={Erweiterte Online-Publikation}, + chicago:Retrieved={heruntergeladen von}] + +% thanks: Andrea Valle + +\setupbtxlabeltext + [it] + [chicago:number={Nº}, + chicago:edition={ed.}, % edizione + chicago:Editor={A cura di}, + chicago:Editors={A cura di}, + chicago:Volume={Vol.}, % Volume + chicago:Volumes={Vol.}, % Volumi + chicago:nd={s.d.}, % senza data + chicago:supplement={Supplemento}, + chicago:MotionPicture=Film, % ? + chicago:Writer=Sceneggiatore, % ? + chicago:Writers=Scrittori, % ? + chicago:Producer=Produttore, + chicago:Producers=Produttori, + chicago:Director=Direttore, + chicago:Directors=Direttori, + chicago:Recordedby={Registrato da}, + chicago:Author=Autore, + chicago:Translator={Trad.}, % Translator(s) + chicago:Advanced={Pre-pubblicazione on line}, + chicago:Retrieved={Accessible online}] + +\setupbtxlabeltext + [es] + [chicago:number={Nº}, + chicago:edition={ed.}, % edición + chicago:Editor=Editor, % Ed./Eds. + chicago:Editors=Editores, + chicago:Volume={Vol.}, % Volumen + chicago:Volumes={Vols.}, % Volúmenes + chicago:nd={s.f.}, % sin fecha + chicago:supplement=Suplemento, + chicago:MotionPicture=Cinematográfica, + chicago:Writer=Guionista, % ? + chicago:Writers=Escritores, % ? + chicago:Producer=Productor, + chicago:Producers=Productores, + chicago:Director=Director, + chicago:Directors=Directores, + chicago:Recordedby={Grabada por}, + chicago:Author=Autor, + chicago:Translator=Traductor, + chicago:Advanced={Publicación en línea avanzada}, + chicago:Retrieved={Obtenido de}] % {Disponible desde}] + + +\setupbtxlabeltext + [sv] + [chicago:number={nr.}, + chicago:edition={Utgåva}, + chicago:Editor=Redaktör, + chicago:Editors=Redaktörer, + chicago:Volume=Band, + chicago:Volumes=Band, + chicago:nd={u.å.}, % utan årtal + chicago:supplement=Bilaga, % Supplement + chicago:MotionPicture=Spelfilm, % ? + chicago:Writer={Manusförfattare}, % Assuming for a movie + chicago:Writers={Manusförfattare}, % + chicago:Producer=Producent, % Assuming for a movie + chicago:Producers=Producenter, % + chicago:Director={Regissör}, % Assuming for a movie + chicago:Directors={Regissörer}, % + chicago:Recordedby={Inspelad av}, % Assuming for a movie + chicago:Author={Författare}, + chicago:Translator={Översättare}, + chicago:Advanced={Avancerad onlinepublikation}, % ? + chicago:Retrieved={Hämtad från}] + +% cite setups + +% The following differs from the default returning n.d. if year is empty + +\startsetups btx:chicago:cite:author:year + \ifx\currentbtxfirst\empty + \def\currentbtxfirst{\fastsetup{\s!btx:chicago:nd}} + \fi + \fastsetup{\s!btx:\s!cite:author:year} +\stopsetups + +\startsetups btx:chicago:cite:author:years + \ifx\currentbtxfirst\empty + \def\currentbtxfirst{\fastsetup{\s!btx:chicago:nd}} + \fi + \fastsetup{\s!btx:\s!cite:author:years} +\stopsetups + +% these setups need to be explicitly defined in order to get cite rendering + +\startsetups \s!btx:chicago:\s!cite:organization + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:chicago:\s!cite:subtitle + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:chicago:\s!cite:booktitle + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:chicago:\s!cite:subbooktitle + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +% are these needed? + +\startsetups \s!btx:chicago:\s!cite:title:inbook + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:chicago:\s!cite:title:incollection + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:chicago:\s!cite:title:inproceedings + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:chicago:\s!cite:subtitle:inbook + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:chicago:\s!cite:subtitle:incollection + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +\startsetups \s!btx:chicago:\s!cite:subtitle:inproceedings + \fastsetup{\s!btx:\s!cite:normal} +\stopsetups + +% used in publ-imp-page.mkvi + +\startsetups btx:chicago:list:page-or-pages + \ifx\currentbtxlastpage\empty + \btxlabeltext{p} + \else + \btxlabeltext{pp} + \fi + \btxnbsp +\stopsetups + +% The sameauthor feature may not be Chicago compliant +% (there is nothing in the manual cited above). +% It can be removed using the command: +% \resetsetups [chicago:list:sameauthor] + +% :rule, :empty or :ditto ... + +\startsetups chicago:list:sameauthor + \fastsetup{chicago:list:sameauthor:rule} +\stopsetups + +\startsetups chicago:list:sameauthor:rule + \blackrule + [\c!width=3em, + \c!height=1.5\linewidth]% \linewidth is just too thin with respect to font strokes... +\stopsetups + +\startsetups [chicago:list:sameauthor:\v!empty] + \kern\dimexpr\listparameter\c!margin-\interwordspace\relax +\stopsetups + +% horrible ! + +\startsetups chicago:list:sameauthor:ditto + \inframed + [\c!width=\dimexpr\listparameter\c!margin-\interwordspace\relax, + \c!frame=\v!off, + \c!align=\v!middle] + {\doubleprime} +\stopsetups + +%D Instead of texdefinitions without arguments, we could have used setups but in my +%D editor (hh, scite) the commands stand out better. It also saves an additional +%D component in the name (e.g. common:) because commands and setups have a different +%D namespace, so similar calls don't clash. Performance of definitions is somewhat +%D better. + +%D We use "texdefinitions" (with eventual arguments) for helpers that are used +%D in the rendering "setups" defined for each category below. + +%D Note that \btxdoif... and \btxflush rely on the definitions in +%D publ-imp-chicago.lua: fields that are not listed as required nor optional are +%D IGNORED. We also make heavy use of the notion of sets - comma-separated lists +%D of alternative fields to be used in hierarchal order. For example: +%D author = { "author", "editor", "publisher", "title" }, will return the +%D author field if it exists; if not, the editor field will be returned, if it +%D exists; if not, the publisher field will be returned, if it exists; if not, +%D the title field will be returned, it it exists; if not, nothing will be +%D returned. In lua syntax, it can be understood as +%D author or editor or publisher or title or "" + +% #title can be title or booktitle + +\starttexdefinition unexpanded btx:chicago:translated-title #title + \ifx\currentbtxlanguage\empty + % no need for an extra + \else\ifx\mainbtxlanguage\currentbtxlanguage + % no need for an extra + \else + \btxdoif {#title:\mainbtxlanguage} { + \begingroup + \language[\mainbtxlanguage] + \btxleftbracket + \btxusecommand [chicago:\s!list:#title:\currentbtxcategory] { + \btxflush{#title:\mainbtxlanguage} + } + \btxrightbracket + \endgroup + } + \fi\fi +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:composed-title #title + \btxstartstyleandcolor[chicago:\s!list:#title:\currentbtxcategory] + \begingroup + \language[\currentbtxlanguage] + \btxusecommand [chicago:\s!list:#title:\currentbtxcategory] { + \btxflush{#title} + \btxdoif {sub#title} { + \btxcolon + \btxflush{sub#title} + } + } + \endgroup + % which namespace? + %\doif{\btxparameter{translate}}\v!yes { + \texdefinition{btx:chicago:translated-title}{#title} + %} + \btxstopstyleandcolor +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:title + \setmode{btx:chicago:title-placed} + % we make the title active, opening "file" + \btxdoifelse {file} { + \texdefinition{btx:format:inject} + {url(file:\btxflush{file})} + { + \texdefinition{btx:chicago:composed-title}{title} + } + } { + \texdefinition{btx:chicago:composed-title}{title} + } + \btxdoif {title} { + % A book might have an editor AND an author + \doif {\currentbtxcategory} {book} { + \doifnot {\btxfoundname{author}} {editor} { + \btxdoif {ineditor} { % ineditor specific authorconversion + \btxleftparenthesis + \btxflush{ineditor} + \btxcomma + \btxsingularorplural {ineditor} { + \btxlabeltext{chicago:Editor} + } { + \btxlabeltext{chicago:Editors} + } + \btxrightparenthesis + } + } + } + \btxdoif {translator} { + \btxleftparenthesis + \btxflush{translator} + \btxcomma + \btxlabeltext{chicago:Translator} + \btxrightparenthesis + } + \btxperiod + % TODO: this period may NOT be wanted, as in: Title (2nd ed.). + } +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:title-if-not-placed + \doifelsemode {btx:chicago:title-placed} { + \resetmode{btx:chicago:title-placed} + } { + \btxdoif {title} { + \btxspace + \texdefinition {btx:chicago:title} + } + } +\stoptexdefinition + +\startsetups btx:chicago:nd + \btxlabeltext{chicago:nd} +\stopsetups + +\starttexdefinition unexpanded btx:chicago:suffixedyear + \btxdoifelse {year} { + \btxflush{year} + \btxflushsuffix + \btxdoif {month} { % month and day optional in publ-imp-chicago.lua + \btxcomma + \btxflush{month} + \btxdoif {day} { + \btxspace + \btxflush{day} + } + } + } { + \fastsetup{btx:chicago:nd} + % Hans: the following won't work but should. + \btxdoif {suffix} { + \btxspace + \btxflushsuffix + % Hans: similarly, why can't \btxflush{suffix} be made to work? + } + } +\stoptexdefinition + +% #author may be author(set) or editor + +\starttexdefinition unexpanded btx:chicago:author-or-editor #author + \btxdoifelse {#author} { + \btxstartstyleandcolor[chicago:\s!list:#author] + \btxusecommand[chicago:\s!list:#author]{ + \btxflush{#author} + } + \btxstopstyleandcolor + % use \processaction [] [] here? + \doifelse {\btxfoundname{#author}} {editor} { + \btxleftparenthesis + \btxsingularorplural {editor} { + \btxlabeltext{chicago:Editor} + } { + \btxlabeltext{chicago:Editors} + } + \btxrightparenthesis + } {\doif {\btxfoundname{#author}} {ineditor} { + \btxleftparenthesis + \btxsingularorplural {ineditor} { + \btxlabeltext{chicago:Editor} + } { + \btxlabeltext{chicago:Editors} + } + \btxrightparenthesis + } } + \doif {\currentbtxcategory} {film} { + \btxleftparenthesis + \doifelse {\btxfoundname{#author}} {director} { + \btxsingularorplural {director} { + \btxlabeltext{chicago:Director} + } { + \btxlabeltext{chicago:Directors} + } + } { + \doif {\btxfoundname{#author}} {author} { + \btxsingularorplural {author} { + \btxlabeltext{chicago:Writer} + } { + \btxlabeltext{chicago:Writers} + } + } + \doif {\btxfoundname{#author}} {producer} { + \btxsingularorplural {producer} { + \btxlabeltext{chicago:Producer} + } { + \btxlabeltext{chicago:Producers} + } + } + \btxdoif {director} { + \btxrightparenthesis + \removeunwantedspaces + \btxparameter{\c!separator:names:3} + \btxstartstyleandcolor[chicago:\s!list:director] + \btxusecommand[chicago:\s!list:director]{ + \btxflush{director} + } + \btxstopstyleandcolor + \btxleftparenthesis + \btxsingularorplural {director} { + \btxlabeltext{chicago:Director} + } { + \btxlabeltext{chicago:Directors} + } + } + } + \btxrightparenthesis + } + \btxdoif {withauthor} { + \btxleftparenthesis + \btxlabeltext{with} + \btxspace + \btxstartstyleandcolor[chicago:\s!list:withauthor] + \btxusecommand[chicago:\s!list:withauthor]{ + \btxflush{withauthor} + } + \btxstopstyleandcolor + \btxrightparenthesis + } + } { + \texdefinition{btx:chicago:title} + } +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:authoryear + % we make the authoryear active, pointing to the citation + \texdefinition{btx:format:inject} + {internal(\currentbtxinternal)} + { + \doifelsesetups{chicago:list:sameauthor} { + \btxdoifelsesameasprevious {author} { + \fastsetup{chicago:list:sameauthor} + } { + \texdefinition{btx:chicago:author-or-editor} {author} + } + } { + \texdefinition{btx:chicago:author-or-editor} {author} + } + \texdefinition{btx:chicago:suffixedyear} + } + % outside of interaction + \btxperiod + \doif {\btxfoundname{author}} {title} { + \setmode{btx:chicago:title-placed} + } +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:editor-in + \btxdoif {booktitle} { + \btxlabeltext{In} + \btxspace + \doifnot {\btxfoundname{author}} {editor} { + \texdefinition{btx:chicago:author-or-editor} {ineditor} + \btxcomma + } + \texdefinition{btx:chicago:composed-title}{booktitle} + \btxperiod + } +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:organization-if-not-author + \btxdoif {organization} { + \doifnot {\btxfoundname{author}} {organization} { + \btxspace + \btxflush{organization} + \btxcomma + } + } +\stoptexdefinition + +% TODO: The title is terminated with period. However, +% we probably don't want this before the parenthesis. + +\starttexdefinition unexpanded btx:chicago:leftparenthesis-or-comma + \doifelsemode {btx:chicago:editionset-is-empty} { + \btxleftparenthesis + \resetmode{btx:chicago:editionset-is-empty} + } { + \btxcomma + } +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:editionset + \setmode{btx:chicago:editionset-is-empty} + \doif {\currentbtxcategory} {techreport} { + \texdefinition{btx:chicago:leftparenthesis-or-comma} + \btxdoifelse {type} { + \btxusecommand [chicago:\s!list:type] { + \btxflush{type} + } + } { + \btxlabeltext{technicalreport} + } + } + \btxdoif {volume} { + \texdefinition{btx:chicago:leftparenthesis-or-comma} + \btxoneorrange {volume} { + \btxlabeltext{chicago:Volume} + } { + \btxlabeltext{chicago:Volumes} + } + \btxspace + \btxflush{volume} + } + \btxdoif {number} { + \texdefinition{btx:chicago:leftparenthesis-or-comma} + \btxlabeltext{chicago:number} + \btxspace + \btxflush{number} + } + \btxdoif {edition} { + \texdefinition{btx:chicago:leftparenthesis-or-comma} + \btxflush{edition} + \btxspace + \btxlabeltext{chicago:edition} + } + \btxdoif {pages} { + \texdefinition{btx:chicago:leftparenthesis-or-comma} + \btxoneorrange {pages} { + \btxlabeltext{p} + } { + \btxlabeltext{pp} + } + \btxnbsp + \btxflush{pages} + } + \doifnotmode {btx:chicago:editionset-is-empty} { + \btxrightparenthesisperiod + } +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:journal + \btxstartstyleandcolor[chicago:\s!list:journal] + \btxusecommand [chicago:\s!list:journal] { + \btxflush{journal} + } + \btxstopstyleandcolor +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:volume + \btxstartstyleandcolor[chicago:\s!list:volume] + \btxflush{volume} + \btxstopstyleandcolor +\stoptexdefinition + + % this could be simplified! + +\starttexdefinition unexpanded btx:chicago:journal-volume-number-pages + \btxdoif {journal} { + \btxspace + \texdefinition{btx:chicago:journal} + \btxdoifelse {volume} { + \btxcomma + \texdefinition{btx:chicago:volume} + \btxdoif {number} { + %\btxleftparenthesis + (\btxflush{number} + \btxrightparenthesis + } + } { + \btxdoif {number} { + \btxcomma + \btxleftparenthesis + \btxflush{number} + \btxrightparenthesis + } + } + \btxdoif {pages} { + \btxcomma + \doif {\currentbtxcategory} {newspaper} { + \btxoneorrange {pages} { + \btxlabeltext{p} + } { + \btxlabeltext{pp} + } + \btxnbsp + } + \btxflush{pages} + } + \btxperiod + \doifnot {\currentbtxcategory} {newspaper} { + \btxdoifnot {volume} { + \btxdoifnot {number} { + \btxdoifnot {pages} { + \btxdoif {doi} {%set: doi or url + \btxspace + \btxlabeltext{chicago:Advanced} + \btxperiod + } + } + } + } + } + } +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:wherefrom-publisher + \btxdoifelse {address} { + \btxflush{address} + \btxdoif {country} { + \btxcomma + \btxflush{country} + } + \btxcolon + } { + \btxdoif {country} { + \btxflush{country} + \btxcolon + } + } + \doifelse {\btxfoundname{author}} {\btxfoundname{publisher}} { + \btxlabeltext{chicago:Author} + } { + \btxdoifelse {publisher} { + \btxflush{publisher} + } { + \btxlabeltext{chicago:Author} + } + } + \btxperiod +\stoptexdefinition + +\definebreakpoints[doi] +\definebreakpoint [doi][:][nleft=3,type=1] +\definebreakpoint [doi][/][nleft=3,type=1] +\definebreakpoint [doi][-][nleft=3,type=1] +\definebreakpoint [doi][.][nleft=3,type=1] + +% use \btxentry here? + +\starttexdefinition unexpanded btx:chicago:url + \begingroup + \setbreakpoints[doi] + \ifconditional\btxinteractive + \goto { + \hyphenatedurl{\btxflush{url}} + } [ + url(\btxflush{url}) + ] + \else + \hyphenatedurl{\btxflush{url}} + \fi + \endgroup +\stoptexdefinition + +% use \btxentry here? + +\starttexdefinition unexpanded btx:chicago:doi + \begingroup + \setbreakpoints[doi] + \ifconditional\btxinteractive + \goto { + \hyphenatedurl{doi:\btxflush{doi}} + } [ + url(http://dx.doi.org/\btxflush{doi}) + ] + \else + \hyphenatedurl{doi:\btxflush{doi}} + \fi + \endgroup +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:note + \btxdoif {note} { + \btxleftparenthesis + \btxflush{note} + \btxrightparenthesis + } +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:url-doi-note + \doif {\btxfoundname{doi}} {url} { + \btxspace + \btxlabeltext{chicago:Retrieved} + \btxspace + \texdefinition{btx:chicago:url} + } + \doif {\btxfoundname{doi}} {doi} { + \btxspace + \texdefinition{btx:chicago:doi} + } + \texdefinition{btx:chicago:note} + \removeunwantedspaces +\stoptexdefinition + +\starttexdefinition unexpanded btx:chicago:type + \btxdoif {type} { + \btxleftbracket + \btxflush{type} + \btxrightbracketperiod + } +\stoptexdefinition + +% Then setups, by category + +% An article from a journal +% Required fields: author or organization or editor or title, journal, (year). +% Optional fields: volume, number, pages, type, doi, url, note. +% Note that bibtex (and tools) do not include editor (e.g. special issue or section) + +\startsetups btx:chicago:list:article + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \texdefinition{btx:chicago:type} + \texdefinition{btx:chicago:journal-volume-number-pages} + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +% An article from a magazine. +% Required fields: author or title, journal, (year). +% Optional fields: number, pages, type, month, day, doi, url, note. + +\startsetups btx:chicago:list:magazine + \fastsetup{btx:chicago:list:article} +\stopsetups + +% An article from a newspaper. +% Required fields: author or title, journal, (year). +% Optional fields: volume, number, pages, type, month, day, doi, url, note. + +\startsetups btx:chicago:list:newspaper + \fastsetup{btx:chicago:list:article} +\stopsetups + +% A complete issue of a periodical, such as a special issue of a journal. +% Required fields: title, year +% Optional fields: editor, publisher, subtitle, series, volume, number, month, organization, doi, url, issn, note + +% needs to be tuned... + +\startsetups btx:chicago:list:periodical + \fastsetup{btx:chicago:list:article} +\stopsetups + +% National and international standards issued by a standards body +% Required fields: author, institution, or organization, year, title +% Optional fields: subtitle, doi, url, note + +\startsetups btx:chicago:list:standard + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +% A book with an explicit publisher. +% Required fields: author or editor or publisher, title, (year). +% Optional fields: volume or number, series, address, edition, month, day, note. +% Chicago ignores: month, day + +% todo: series? + +\startsetups btx:chicago:list:book + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \texdefinition{btx:chicago:type} + \texdefinition{btx:chicago:editionset} + \texdefinition{btx:chicago:wherefrom-publisher} + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +% There is some debate about how inbook should differ from incollection + +% A part of a book, which may be a chapter (or section or whatever) and/or a range of pages. +% (note that inbook is handled differently by bibtex and biblatex) +% Required fields: author or editor, title, chapter and/or pages, publisher, year. +% Optional fields: volume or number, series, type, address, edition, month, note. +% We add optional: booktitle. +% Chicago ignores: chapter, month + +\startsetups btx:chicago:list:inbook + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \texdefinition{btx:chicago:type} + \texdefinition{btx:chicago:editor-in} + \texdefinition{btx:chicago:editionset} + \texdefinition{btx:chicago:wherefrom-publisher} + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +% A part of a book having its own title. +% Required fields: author, title, booktitle, publisher, year. +% Optional fields: editor, volume or number, series, type, chapter, pages, address, edition, month, note. +% Chicago ignores: chapter, month + +\startsetups btx:chicago:list:incollection + \fastsetup{btx:chicago:list:inbook} +\stopsetups + +% The proceedings of a conference. +% Required fields: title, year. +% Optional fields: editor, volume or number, series, address, month, organization, publisher, note. +% todo: series? + +\startsetups btx:chicago:list:proceedings + \fastsetup{btx:chicago:list:book} +\stopsetups + +% An article in a conference proceedings. +% Required fields: author, title, booktitle, year. +% Optional fields: editor, volume or number, series, pages, address, month, organization, publisher, note. + +\startsetups btx:chicago:list:inproceedings + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \texdefinition{btx:chicago:editor-in} + \texdefinition{btx:chicago:editionset} + \texdefinition{btx:chicago:organization-if-not-author} + \texdefinition{btx:chicago:wherefrom-publisher} + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +\startsetups btx:chicago:list:conference + \fastsetup{btx:chicago:list:inproceedings} +\stopsetups + +% A thesis. +% Required fields: author, title, school, year. +% Optional fields: type, address, month, note. + +\startsetups btx:chicago:list:thesis + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \btxleftparenthesis + \btxdoifelse {type} { + \btxusecommand [chicago:\s!list:type] { + \btxflush{type} + } + } { + \btxlabeltext{\currentbtxcategory} + } + \btxrightparenthesis + \btxdoif {school} { + \btxperiod + \btxflush{school} + } + \btxdoif {address} { + \btxdoifelse {school} { + \btxcomma + } { + \btxperiod + } + \btxflush{address} + \btxdoif {country} { + \btxcomma + \btxflush{country} + } + } + \btxperiod + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +\startsetups btx:chicago:list:phdthesis + \fastsetup{btx:chicago:list:thesis} +\stopsetups + +\startsetups btx:chicago:list:mastersthesis + \fastsetup{btx:chicago:list:thesis} +\stopsetups + +% A work that is printed and bound, but without a named publisher or sponsoring institution. +% Required field: title. +% Optional fields: author, howpublished, address, month, year, note. + +\startsetups btx:chicago:list:booklet + \fastsetup{btx:chicago:list:book} +\stopsetups + +% Technical documentation. +% Required field: title. +% Optional fields: author, organization, address, edition, month, year, note. + +\startsetups btx:chicago:list:manual + \fastsetup{btx:chicago:list:book} +\stopsetups + +% A report published by a school or other institution, usually numbered within a series. +% Required fields: author, title, institution, year. +% Optional fields: type, number, address, month, note. + +\startsetups btx:chicago:list:techreport + \fastsetup{btx:chicago:list:book} +\stopsetups + +% A document having an author and title, but not formally published. +% Required fields: author, title, note. +% Optional fields: month, year. + +\startsetups btx:chicago:list:unpublished + \fastsetup{btx:chicago:list:book} +\stopsetups + +% A patent. Note that this category was not defined with BIBTEX. Below from JabRef: +% Required fields: nationality, number, year, yearfiled +% Optional fields: author, title, assignee, address, type, number, day, dayfiled, month, monthfiled, note, url +% Also optional: publisher + +% todo: yearfiled, monthfiled, dayfiled + +\startsetups btx:chicago:list:patent + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \begingroup + \it + \btxdoif {nationality} { + \btxspace + \btxflush{nationality} + } + \btxspace + \btxdoifelse{type}{ + \btxflush{type} + }{ + \btxlabeltext{patent} + } + \btxdoif {number} { + \btxspace + \btxlabeltext{chicago:number} + \btxspace + \btxflush{number} + } + \btxperiod + \italiccorrection + \endgroup + \texdefinition{btx:chicago:wherefrom-publisher} + \texdefinition{btx:chicago:url} + \texdefinition{btx:chicago:note} +\stopsetups + +% Electronic. Note that this category was not defined with BIBTEX. Below from JabRef: +% Required fields: title +% Optional fields: address, author, howpublished, month, note, organization, url, year, doi +% Also optional: type + +% Like Misc below but includes organization. + +\startsetups btx:chicago:list:electronic + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \texdefinition{btx:chicago:type} + \texdefinition{btx:chicago:organization-if-not-author} + \btxdoif {howpublished} { + \btxspace + \btxflush{howpublished} + \btxperiod + } + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +% Film. Note that this category was not defined with BIBTEX. +% Required fields: producer, director, title, year, address, publisher +% Optional fields: subtitle, type, note, url, doi + +\startsetups btx:chicago:list:film + \texdefinition{btx:chicago:authoryear} + \texdefinition {btx:chicago:title} + \btxleftbracket + \btxdoifelse {type} { + \btxflush{type} + } { + \btxlabeltext{chicago:MotionPicture} + } + \btxrightbracketperiod + \texdefinition{btx:chicago:wherefrom-publisher} + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +% Music. Note that this category was not defined with BIBTEX. +% Required fields: composer, artist, title, album, year, address, publisher +% Optional fields: subtitle, type, note, url, doi + +\startsetups btx:chicago:list:music + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \doifnot {\btxfoundname{author}} {artist} { + \btxdoif {artist} { + \btxleftbracket + \btxlabeltext{chicago:Recordedby} + \btxspace + \btxflush{artist} + \btxrightbracketperiod + } + } + \doifnot {\btxfoundname{title}} {album} { + \btxdoif {album} { + \btxlabeltext{In} + \btxspace + \btxflush{album} + \btxperiod + } + } + \texdefinition{btx:chicago:type} + \texdefinition{btx:chicago:wherefrom-publisher} + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +% Other. Note that this category was not defined with BIBTEX. Below from JabRef: +% Required fields: author or title, year +% Optional fields: note, doi, url + +\startsetups btx:chicago:list:other + \fastsetup{btx:chicago:list:book} +\stopsetups + +% Use this category when nothing else fits. +% Required fields: none. +% Optional fields: author, title, howpublished, month, year, note. + +\startsetups btx:chicago:list:misc + \texdefinition{btx:chicago:authoryear} + \texdefinition{btx:chicago:title-if-not-placed} + \btxdoif {howpublished} { + \btxspace + \btxflush{howpublished} + \btxperiod + } + \texdefinition{btx:chicago:url-doi-note} +\stopsetups + +% If all else fails to match: + +\startsetups btx:chicago:list:literal + %\btxleftparenthesis + \removeunwantedspaces( + \btxflush{tag} + \btxrightparenthesis + \btxdoif {text} { + \btxflush{text} + } +\stopsetups + +% HH: an example of setting up translations using a sub rendering. Keep it here +% till we find another spot as otherwise I forget about it and I don't want to +% waste hours reinventing a wheel when something like this is needed. +% +% \definebtx +% [chicago:cite:title:translated] +% [chicago:cite:title] +% [left=\btxleftbracket, +% right=\btxrightbracket, +% style=\v!bolditalic] +% +% \startsetups btx:chicago:cite:title +% % need to add concat, etc. +% \btxcitereference +% \currentbtxfirst +% \doifmode {btx:chicago:translatedtitles} { +% \ifx\currentbtxlanguage\empty +% % no need for an extra +% \else\ifx\mainbtxlanguage\currentbtxlanguage +% % no need for an extra +% \else +% \btxdoif {title:\mainbtxlanguage} { +% \btxstartciterendering[title:translated] +% \language[\mainbtxlanguage] +% \btxflush{title:\mainbtxlanguage} +% \btxstopciterendering +% } +% \fi\fi +% } +% \stopsetups + +\stopbtxrenderingdefinitions diff --git a/tex/context/base/mkiv/publ-imp-cite.mkvi b/tex/context/base/mkiv/publ-imp-cite.mkvi index 56af83a1b..3a01b219a 100644 --- a/tex/context/base/mkiv/publ-imp-cite.mkvi +++ b/tex/context/base/mkiv/publ-imp-cite.mkvi @@ -168,6 +168,12 @@ \fastsetup{\s!btx:\s!cite:righttext} \stopsetups +\startsetups \s!btx:\s!cite:footnote + \startfootnote + \fastsetup{btx:cite:entry} + \stopfootnote +\stopsetups + % these three are goodies to get something but are not set up as it makes no % sense to have something root for combinations like this (esp not because one % gets default anyway diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua index f62352f07..aa55b40e9 100644 --- a/tex/context/base/mkiv/publ-ini.lua +++ b/tex/context/base/mkiv/publ-ini.lua @@ -502,13 +502,18 @@ local findallused do local luadata = current.luadata local details = current.details local ordered = current.ordered - if allused then + if allused then -- always true local registered = { } local function register(tag) local entry = forcethem and luadata[tag] if entry then if registered[tag] then + if trace_cite then + report_cite("dataset: %s, tag: %s, state: %s",dataset,tag,"already cited (1)") + end return + elseif trace_cite then + report_cite("dataset: %s, tag: %s, state: %s",dataset,tag,"okay") end okay[#okay+1] = entry -- todo[tag] = true @@ -516,6 +521,9 @@ local findallused do return tag end entry = allused[tag] + if trace_cite then + report_cite("dataset: %s, tag: %s, used: % t",dataset,tag,table.sortedkeys(allused)) + end if not entry then local parent = details[tag].parent if parent then @@ -524,9 +532,16 @@ local findallused do if entry then report("using reference of parent %a for %a",parent,tag) tag = parent + elseif trace_cite then + report_cite("dataset: %s, tag: %s, state: %s",dataset,tag,"not used") end + elseif trace_cite then + report_cite("dataset: %s, tag: %s, state: %s",dataset,tag,"used") end if registered[tag] then + if trace_cite then + report_cite("dataset: %s, tag: %s, state: %s",dataset,tag,"already cited (2)") + end return end if entry then @@ -564,7 +579,17 @@ local findallused do entry = entry[1] end end + if not entry then + report_cite("dataset: %s, tag: %s, state: %s",dataset,tag,"no entry (1)") + elseif trace_cite then + report_cite("dataset: %s, tag: %s, state: %s",dataset,tag,"new entry") + end okay[#okay+1] = entry + elseif not entry then + if trace_cite then + report_cite("dataset: %s, tag: %s, state: %s",dataset,tag,"no entry (2)") + end + -- okay[#okay+1] = luadata[tag] end todo[tag] = true registered[tag] = true @@ -1712,7 +1737,6 @@ do end end - -- tag | listindex | reference | userdata | dataindex local methods = { } @@ -1794,7 +1818,7 @@ do if traced then local l = traced[tag] if l then - l[#l+1] = u.btxint + l[#l+1] = u.btxint -- tonumber ? else local data = luadata[tag] local l = { tag, listindex, 0, u, data and data.index or 0 } diff --git a/tex/context/base/mkiv/publ-ini.mkiv b/tex/context/base/mkiv/publ-ini.mkiv index ead46929d..8e70ec5a7 100644 --- a/tex/context/base/mkiv/publ-ini.mkiv +++ b/tex/context/base/mkiv/publ-ini.mkiv @@ -1080,7 +1080,7 @@ \relax} \unexpanded\def\btx_reference_checked - {\dontleavehmode\hbox\bgroup + {\dontleavehmode\hbox\bgroup % \hpack \btx_reference_indeed \egroup} diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 0547dc574..328354ee5 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 63e611ca1..94132234a 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv index 4fbcbd0e6..d6f54f7d0 100644 --- a/tex/context/base/mkiv/syst-aux.mkiv +++ b/tex/context/base/mkiv/syst-aux.mkiv @@ -4231,8 +4231,8 @@ \stoplmtxmode -%D These macros can explictly take care of spaces, which means -%D that the next definition and calls are valid: +%D These macros can explictly take care of spaces, which means that the next +%D definition and calls are valid: %D %D \starttyping %D \def\test#1#2#3{[#1#2#3]} @@ -4673,8 +4673,7 @@ \unexpanded\def\newcounter#1% {\dodoglobal\let#1\zerocountervalue} -%D Nowadays we don't mind a few more tokens if we can gain a -%D bit of speed. +%D Nowadays we don't mind a few more tokens if we can gain a bit of speed. \def\syst_helpers_do_increment#1{\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\plusone \relax}} \def\syst_helpers_do_decrement#1{\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\minusone\relax}} @@ -4870,24 +4869,22 @@ #2\expandafter\doexpandedrecurse\expandafter{\the\numexpr#1-\plusone\relax}{#2}% \fi} -%D As we can see here, the simple command \type{\dorecurse} is -%D a special case of the more general: +%D As we can see here, the simple command \type{\dorecurse} is a special case of the +%D more general: %D %D \starttyping %D \dostepwiserecurse {from} {to} {step} {action} %D \stoptyping %D -%D This commands accepts positive and negative steps. Illegal -%D values are handles as good as possible and the macro accepts -%D numbers and \COUNTERS. +%D This commands accepts positive and negative steps. Illegal values are handles as +%D good as possible and the macro accepts numbers and \COUNTERS. %D %D \starttyping %D \dostepwiserecurse {1} {10} {2} {...} %D \dostepwiserecurse {10} {1} {-2} {...} %D \stoptyping %D -%D Because the simple case is used often, we implement it -%D more efficiently: +%D Because the simple case is used often, we implement it more efficiently: \unexpanded\def\dorecurse#1% {\ifcase#1\relax @@ -7952,9 +7949,8 @@ %D \freezedimensionwithunit\SomeDepth{\dp\strutbox} %D \stoptyping %D -%D As an alternative for the next macro we can use a global -%D assignment inside a box. The \type{\empty}'s permits -%D gobbling while preventing spurious \type{\relax}'s. +%D As an alternative for the next macro we can use a global assignment inside a box. +%D The \type {\empty}'s permits gobbling while preventing spurious \type {\relax}'s. \unexpanded\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick {\afterassignment\gobblefourarguments#1=#2#3pt\relax\empty\empty\empty\empty} diff --git a/tex/context/base/mkiv/toks-scn.lua b/tex/context/base/mkiv/toks-scn.lua index 297ef7121..f259bcee5 100644 --- a/tex/context/base/mkiv/toks-scn.lua +++ b/tex/context/base/mkiv/toks-scn.lua @@ -144,6 +144,26 @@ scanners.list = scanlist scanners.table = scantable scanners.conditional = scanconditional +function scanners.whd() + local width, height, depth + while true do + if scankeyword("width") then + width = scandimen() + elseif scankeyword("height") then + height = scandimen() + elseif scankeyword("depth") then + depth = scandimen() + else + break + end + end + if width or height or depth then + return width or 0, height or 0, depth or 0 + else + -- we inherit + end +end + local shortcuts = { tokens = tokens, bits = tokenbits, diff --git a/tex/context/base/mkiv/util-sbx.lua b/tex/context/base/mkiv/util-sbx.lua index 57c576870..d5cf691ce 100644 --- a/tex/context/base/mkiv/util-sbx.lua +++ b/tex/context/base/mkiv/util-sbx.lua @@ -637,16 +637,7 @@ end -- these are used later on if zip then - zip.open = register(zip.open, filehandlerone,"zip.open") -end - -if fontloader then - fontloader.open = register(fontloader.open,filehandlerone,"fontloader.open") - fontloader.info = register(fontloader.info,filehandlerone,"fontloader.info") -end - -if epdf then - epdf.open = register(epdf.open, filehandlerone,"epdf.open") + zip.open = register(zip.open, filehandlerone,"zip.open") end sandbox.registerroot = registerroot diff --git a/tex/context/base/mkiv/util-sci.lua b/tex/context/base/mkiv/util-sci.lua index fe28635a3..4565e089d 100644 --- a/tex/context/base/mkiv/util-sci.lua +++ b/tex/context/base/mkiv/util-sci.lua @@ -33,14 +33,27 @@ do end local knownlexers = { - tex = "tex", mkiv = "tex", mkvi = "tex", mkxi = "tex", mkix = "tex", mkii = "tex", cld = "tex", - lua = "lua", lfg = "lua", lus = "lua", - mp = "mps", mpiv = "mps", mpii = "mps", - w = "web", ww = "web", - c = "cpp", h = "cpp", cpp = "cpp", hpp = "cpp", cxx = "cpp", hxx = "cpp", - xml = "xml", lmx = "xml", ctx = "xml", xsl = "xml", xsd = "xml", rlx = "xml", css = "xml", dtd = "xml", - bib = "bibtex", - rme = "txt", + tex = "tex", + mkiv = "tex", mkvi = "tex", + mkil = "tex", mkli = "tex", + mkxi = "tex", mkix = "tex", + mkii = "tex", + bib = "bibtex", + cld = "tex", + lua = "lua", + lfg = "lua", lus = "lua", luv = "lua", + mp = "mps", + mpiv = "mps", + mpii = "mps", + w = "web", ww = "web", + c = "cpp", h = "cpp", + cpp = "cpp", hpp = "cpp", + cxx = "cpp", hxx = "cpp", + xml = "xml", xsl = "xml", xsd = "xml", dtd = "xml", + lmx = "xml", ctx = "xml", rlx = "xml", + css = "xml", + rme = "txt", + txt = "txt", -- todo: pat/hyp ori } diff --git a/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv b/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv index bba07f41d..5cafe503f 100644 --- a/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv +++ b/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv @@ -13,6 +13,19 @@ % Why so many features ... dead slow too +% renewed: +% +% Regular +% Italic +% Medium +% MediumItalic +% SemiBold +% SemiBoldItalic +% Bold +% BoldItalic +% ExtraBold +% ExtraBoldItalic + \definefontfeature [eb-garamond-normal] [default] @@ -29,17 +42,32 @@ \starttypescriptcollection[ebgaramond] + % \starttypescript [serif] [ebgaramond] + % \loadfontgoodies[ebgaramond] + % \setups[font:fallback:serif] + % \definefontsynonym [Serif] [file:ebgaramond-regular] [features=eb-garamond-normal] + % \definefontsynonym [SerifItalic] [file:ebgaramond-italic] [features=eb-garamond-normal] + % \definefontsynonym [SerifBold] [file:ebgaramond-regular] [features=eb-garamond-normal] % there is no bold + % \definefontsynonym [SerifCaps] [Serif] [features=eb-garamond-smallcaps] + % \stoptypescript + + % \starttypescript[ebgaramond] + % \definetypeface [ebgaramond] [rm] [serif] [ebgaramond] [default] [designsize=auto] + % \definetypeface [ebgaramond] [tt] [mono] [dejavu] [default] [rscale=0.8] % rather arbitrary but seldom mixed anyway + % \definetypeface [ebgaramond] [mm] [math] [bonum] [default] [rscale=0.8] % rather arbitrary but seldom mixed anyway + % \stoptypescript + \starttypescript [serif] [ebgaramond] - \loadfontgoodies[ebgaramond] \setups[font:fallback:serif] - \definefontsynonym [Serif] [file:ebgaramond-regular] [features=eb-garamond-normal] - \definefontsynonym [SerifItalic] [file:ebgaramond-italic] [features=eb-garamond-normal] - \definefontsynonym [SerifBold] [file:ebgaramond-regular] [features=eb-garamond-normal] % there is no bold - \definefontsynonym [SerifCaps] [Serif] [features=eb-garamond-smallcaps] + \definefontsynonym [Serif] [file:ebgaramond-regular] [features=eb-garamond-normal] + \definefontsynonym [SerifItalic] [file:ebgaramond-italic] [features=eb-garamond-normal] + \definefontsynonym [SerifBold] [file:ebgaramond-bold] [features=eb-garamond-normal] + \definefontsynonym [SerifBoldItalic][file:ebgaramond-bolditalic][features=eb-garamond-normal] + \definefontsynonym [SerifCaps] [Serif] [features=eb-garamond-smallcaps] \stoptypescript \starttypescript[ebgaramond] - \definetypeface [ebgaramond] [rm] [serif] [ebgaramond] [default] [designsize=auto] + \definetypeface [ebgaramond] [rm] [serif] [ebgaramond] [default] \definetypeface [ebgaramond] [tt] [mono] [dejavu] [default] [rscale=0.8] % rather arbitrary but seldom mixed anyway \definetypeface [ebgaramond] [mm] [math] [bonum] [default] [rscale=0.8] % rather arbitrary but seldom mixed anyway \stoptypescript diff --git a/tex/context/interface/mkii/keys-de.xml b/tex/context/interface/mkii/keys-de.xml index 701dc246b..e76ea9340 100644 --- a/tex/context/interface/mkii/keys-de.xml +++ b/tex/context/interface/mkii/keys-de.xml @@ -376,6 +376,7 @@ <cd:variable name='nohz' value='nohz'/> <cd:variable name='noline' value='noline'/> <cd:variable name='nomarking' value='keinebeschriftung'/> + <cd:variable name='nomenubar' value='nomenubar'/> <cd:variable name='none' value='kein'/> <cd:variable name='nonumber' value='nonumber'/> <cd:variable name='norepeat' value='norepeat'/> diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf Binary files differindex 3d5205666..e1f854a34 100644 --- a/tex/context/interface/mkiv/i-context.pdf +++ b/tex/context/interface/mkiv/i-context.pdf diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf Binary files differindex 7b6a077ef..007fc0e61 100644 --- a/tex/context/interface/mkiv/i-readme.pdf +++ b/tex/context/interface/mkiv/i-readme.pdf diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 8a940cc22..4379ead13 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 05/18/19 10:42:24 +-- merge date : 05/25/19 10:45:25 do -- begin closure to overcome local limits and interference @@ -31241,32 +31241,17 @@ do local f_used=context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ] local hashed={} local cache={} - if epdf then - local openpdf=epdf.openMemStream - function otf.storepdfdata(pdf) - local done=hashed[pdf] - if not done then - nofstreams=nofstreams+1 - local o,n=openpdf(pdf,#pdf,f_name(nofstreams)) - cache[n]=o - done=f_used(n) - hashed[pdf]=done - end - return done - end - else - local openpdf=pdfe.new - function otf.storepdfdata(pdf) - local done=hashed[pdf] - if not done then - nofstreams=nofstreams+1 - local f=f_name(nofstreams) - local n=openpdf(pdf,#pdf,f) - done=f_used(n) - hashed[pdf]=done - end - return done - end + local openpdf=pdfe.new + function otf.storepdfdata(pdf) + local done=hashed[pdf] + if not done then + nofstreams=nofstreams+1 + local f=f_name(nofstreams) + local n=openpdf(pdf,#pdf,f) + done=f_used(n) + hashed[pdf]=done + end + return done end end local function pdftovirtual(tfmdata,pdfshapes,kind) |