summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3backend/l3backend-header.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-11-27 03:01:12 +0000
committerNorbert Preining <norbert@preining.info>2019-11-27 03:01:12 +0000
commit5142daa13e19b32afa064863e039da3afaf06e83 (patch)
treed8299dbf426b9b0e6cafacc4cbe5a6a762bf28a9 /macros/latex/contrib/l3backend/l3backend-header.dtx
parentbd1c54bb99e58d8c140acb0b0a536037f96349b4 (diff)
CTAN sync 201911270301
Diffstat (limited to 'macros/latex/contrib/l3backend/l3backend-header.dtx')
-rw-r--r--macros/latex/contrib/l3backend/l3backend-header.dtx574
1 files changed, 574 insertions, 0 deletions
diff --git a/macros/latex/contrib/l3backend/l3backend-header.dtx b/macros/latex/contrib/l3backend/l3backend-header.dtx
new file mode 100644
index 0000000000..b1f2495c79
--- /dev/null
+++ b/macros/latex/contrib/l3backend/l3backend-header.dtx
@@ -0,0 +1,574 @@
+% \iffalse meta-comment
+%
+%% File: l3backend-header.dtx
+%
+% Copyright (C) 2019 The LaTeX3 Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% https://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3backend bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+% https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full,kernel]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \textsf{l3backend-header} package\\ Backend graphics support^^A
+% }
+%
+% \author{^^A
+% The \LaTeX3 Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2019-11-25}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3backend-header} Implementation}
+%
+% \begin{macrocode}
+%<*dvips&header>
+% \end{macrocode}
+%
+% \begin{macro}{pdf.globaldict}
+% A small global dictionary for backend use.
+% \begin{macrocode}
+true setglobal
+/pdf.globaldict 4 dict def
+false setglobal
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% pdf.cvs ,
+% pdf.dvi.pt ,
+% pdf.pt.dvi ,
+% pdf.rect.ht
+% }
+% Small utilities for PostScript manipulations. Conversion to DVI dimensions
+% is done here to allow for |Resolution|. The total height of a rectangle
+% (an array) needs a little maths, in contrast to simply extracting a value.
+% \begin{macrocode}
+
+/pdf.cvs { 65534 string cvs } def
+/pdf.dvi.pt { 72.27 mul Resolution div } def
+/pdf.pt.dvi { 72.27 div Resolution mul } def
+/pdf.rect.ht { dup 1 get neg exch 3 get add } def
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{pdf.linkmargin, pdf.linkdp.pad, pdf.linkht.pad}
+% Settings which are defined up-front in |SDict|.
+% \begin{macrocode}
+/pdf.linkmargin { 1 pdf.pt.dvi } def
+/pdf.linkdp.pad { 0 } def
+/pdf.linkht.pad { 0 } def
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% pdf.rect ,
+% pdf.save.ll ,
+% pdf.save.ur ,
+% pdf.save.linkll ,
+% pdf.save.linkur ,
+% pdf.llx ,
+% pdf.lly ,
+% pdf.urx ,
+% pdf.ury
+% }
+% Functions for marking the limits of an annotation/link, plus drawing the
+% border. We separate links for generic annotations to support adding a
+% margin and setting a minimal size.
+% \begin{macrocode}
+/pdf.rect
+ { /Rect [ pdf.llx pdf.lly pdf.urx pdf.ury ] } def
+/pdf.save.ll
+ {
+ currentpoint
+ /pdf.lly exch def
+ /pdf.llx exch def
+ }
+ def
+/pdf.save.ur
+ {
+ currentpoint
+ /pdf.ury exch def
+ /pdf.urx exch def
+ }
+ def
+/pdf.save.linkll
+ {
+ currentpoint
+ pdf.linkmargin add
+ pdf.linkdp.pad add
+ /pdf.lly exch def
+ pdf.linkmargin sub
+ /pdf.llx exch def
+ }
+ def
+/pdf.save.linkur
+ {
+ currentpoint
+ pdf.linkmargin sub
+ pdf.linkht.pad sub
+ /pdf.ury exch def
+ pdf.linkmargin add
+ /pdf.urx exch def
+ }
+ def
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% pdf.dest.anchor ,
+% pdf.dest.x ,
+% pdf.dest.y ,
+% pdf.dest.point ,
+% pdf.dest2device ,
+% pdf.dev.x ,
+% pdf.dev.y ,
+% pdf.tmpa ,
+% pdf.tmpb ,
+% pdf.tmpc ,
+% pdf.tmpd
+% }
+% For finding the anchor point of a destination link. We make the use case
+% a separate function as it comes up a lot, and as this makes it easier to
+% adjust if we need additional effects. We also need a more complex approach
+% to convert a co-ordinate pair correctly when defining a rectangle: this
+% can otherwise be out when using a landscape page. (Thanks to Alexander
+% Grahn for the approach here.)
+% \begin{macrocode}
+/pdf.dest.anchor
+ {
+ currentpoint exch
+ pdf.dvi.pt 72 add
+ /pdf.dest.x exch def
+ pdf.dvi.pt
+ vsize 72 sub exch sub
+ /pdf.dest.y exch def
+ }
+ def
+/pdf.dest.point
+ { pdf.dest.x pdf.dest.y } def
+/pdf.dest2device
+ {
+ /pdf.dest.y exch def
+ /pdf.dest.x exch def
+ matrix currentmatrix
+ matrix defaultmatrix
+ matrix invertmatrix
+ matrix concatmatrix
+ cvx exec
+ /pdf.dev.y exch def
+ /pdf.dev.x exch def
+ /pdf.tmpd exch def
+ /pdf.tmpc exch def
+ /pdf.tmpb exch def
+ /pdf.tmpa exch def
+ pdf.dest.x pdf.tmpa mul
+ pdf.dest.y pdf.tmpc mul add
+ pdf.dev.x add
+ pdf.dest.x pdf.tmpb mul
+ pdf.dest.y pdf.tmpd mul add
+ pdf.dev.y add
+ }
+ def
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% pdf.bordertracking ,
+% pdf.bordertracking.begin ,
+% pdf.bordertracking.end ,
+% pdf.leftboundary ,
+% pdf.rightboundary ,
+% pdf.brokenlink.rect ,
+% pdf.brokenlink.skip ,
+% pdf.brokenlink.dict ,
+% pdf.bordertracking.endpage ,
+% pdf.bordertracking.continue ,
+% pdf.originx ,
+% pdf.originy
+% }
+% To know where a breakable link can go, we need to track the boundary
+% rectangle. That can be done by hooking into |a| and |x| operations:
+% those names have to be retained. The boundary is stored at the end of
+% the operation. Special effort is needed at the start and end of pages
+% (or rather galleys), such that everything works properly.
+% \begin{macrocode}
+/pdf.bordertracking false def
+/pdf.bordertracking.begin
+ {
+ SDict /pdf.bordertracking true put
+ SDict /pdf.leftboundary undef
+ SDict /pdf.rightboundary undef
+ /a where
+ {
+ /a
+ {
+ currentpoint pop
+ SDict /pdf.rightboundary known dup
+ {
+ SDict /pdf.rightboundary get 2 index lt
+ { not }
+ if
+ }
+ if
+ { pop }
+ { SDict exch /pdf.rightboundary exch put }
+ ifelse
+ moveto
+ currentpoint pop
+ SDict /pdf.leftboundary known dup
+ {
+ SDict /pdf.leftboundary get 2 index gt
+ { not }
+ if
+ }
+ if
+ { pop }
+ { SDict exch /pdf.leftboundary exch put }
+ ifelse
+ }
+ put
+ }
+ if
+ }
+ def
+/pdf.bordertracking.end
+ {
+ /a where { /a { moveto } put } if
+ /x where { /x { 0 exch rmoveto } put } if
+ SDict /pdf.leftboundary known
+ { pdf.outerbox 0 pdf.leftboundary put }
+ if
+ SDict /pdf.rightboundary known
+ { pdf.outerbox 2 pdf.rightboundary put }
+ if
+ SDict /pdf.bordertracking false put
+ }
+ def
+ /pdf.bordertracking.endpage
+{
+ pdf.bordertracking
+ {
+ pdf.bordertracking.end
+ true setglobal
+ pdf.globaldict
+ /pdf.brokenlink.rect [ pdf.outerbox aload pop ] put
+ pdf.globaldict
+ /pdf.brokenlink.skip pdf.baselineskip put
+ pdf.globaldict
+ /pdf.brokenlink.dict
+ pdf.link.dict pdf.cvs put
+ false setglobal
+ mark pdf.link.dict cvx exec /Rect
+ [
+ pdf.llx
+ pdf.lly
+ pdf.outerbox 2 get pdf.linkmargin add
+ currentpoint exch pop
+ pdf.outerbox pdf.rect.ht sub pdf.linkmargin sub
+ ]
+ /ANN pdf.pdfmark
+ }
+ if
+}
+ def
+/pdf.bordertracking.continue
+ {
+ /pdf.link.dict pdf.globaldict
+ /pdf.brokenlink.dict get def
+ /pdf.outerbox pdf.globaldict
+ /pdf.brokenlink.rect get def
+ /pdf.baselineskip pdf.globaldict
+ /pdf.brokenlink.skip get def
+ pdf.globaldict dup dup
+ /pdf.brokenlink.dict undef
+ /pdf.brokenlink.skip undef
+ /pdf.brokenlink.rect undef
+ currentpoint
+ /pdf.originy exch def
+ /pdf.originx exch def
+ /a where
+ {
+ /a
+ {
+ moveto
+ SDict
+ begin
+ currentpoint pdf.originy ne exch
+ pdf.originx ne or
+ {
+ pdf.save.linkll
+ /pdf.lly
+ pdf.lly pdf.outerbox 1 get sub def
+ pdf.bordertracking.begin
+ }
+ if
+ end
+ }
+ put
+ }
+ if
+ /x where
+ {
+ /x
+ {
+ 0 exch rmoveto
+ SDict~
+ begin
+ currentpoint
+ pdf.originy ne exch pdf.originx ne or
+ {
+ pdf.save.linkll
+ /pdf.lly
+ pdf.lly pdf.outerbox 1 get sub def
+ pdf.bordertracking.begin
+ }
+ if
+ end
+ }
+ put
+ }
+ if
+ }
+ def
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% pdf.breaklink ,
+% pdf.breaklink.write ,
+% pdf.count ,
+% pdf.currentrect
+% }
+% Dealing with link breaking itself has multiple stage. The first step is to
+% find the |Rect| entry in the dictionary, looping over key--value pairs.
+% The first line is handled first, adjusting the rectangle to stay inside the
+% text area. The second phase is a loop over the height of the bulk of the
+% link area, done on the basis of a number of baselines. Finally, the end of
+% the link area is tidied up, again from the boundary of the text area.
+% \begin{macrocode}
+/pdf.breaklink
+ {
+ pop
+ counttomark 2 mod 0 eq
+ {
+ counttomark /pdf.count exch def
+ {
+ pdf.count 0 eq { exit } if
+ counttomark 2 roll
+ 1 index /Rect eq
+ {
+ dup 4 array copy
+ dup dup
+ 1 get
+ pdf.outerbox pdf.rect.ht
+ pdf.linkmargin 2 mul add sub
+ 3 exch put
+ dup
+ pdf.outerbox 2 get
+ pdf.linkmargin add
+ 2 exch put
+ dup dup
+ 3 get
+ pdf.outerbox pdf.rect.ht
+ pdf.linkmargin 2 mul add add
+ 1 exch put
+ /pdf.currentrect exch def
+ pdf.breaklink.write
+ {
+ pdf.currentrect
+ dup
+ pdf.outerbox 0 get
+ pdf.linkmargin sub
+ 0 exch put
+ dup
+ pdf.outerbox 2 get
+ pdf.linkmargin add
+ 2 exch put
+ dup dup
+ 1 get
+ pdf.baselineskip add
+ 1 exch put
+ dup dup
+ 3 get
+ pdf.baselineskip add
+ 3 exch put
+ /pdf.currentrect exch def
+ pdf.breaklink.write
+ }
+ 1 index 3 get
+ pdf.linkmargin 2 mul add
+ pdf.outerbox pdf.rect.ht add
+ 2 index 1 get sub
+ pdf.baselineskip div round cvi 1 sub
+ exch
+ repeat
+ pdf.currentrect
+ dup
+ pdf.outerbox 0 get
+ pdf.linkmargin sub
+ 0 exch put
+ dup dup
+ 1 get
+ pdf.baselineskip add
+ 1 exch put
+ dup dup
+ 3 get
+ pdf.baselineskip add
+ 3 exch put
+ dup 2 index 2 get 2 exch put
+ /pdf.currentrect exch def
+ pdf.breaklink.write
+ SDict /pdf.pdfmark.good false put
+ exit
+ }
+ { pdf.count 2 sub /pdf.count exch def }
+ ifelse
+ }
+ loop
+ }
+ if
+ /ANN
+}
+ def
+/pdf.breaklink.write
+ {
+ counttomark 1 sub
+ index /_objdef eq
+ {
+ counttomark -2 roll
+ dup wcheck
+ {
+ readonly
+ counttomark 2 roll
+ }
+ { pop pop }
+ ifelse
+ }
+ if
+ counttomark 1 add copy
+ pop pdf.currentrect
+ /ANN pdfmark
+ }
+ def
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% pdf.pdfmark ,
+% pdf.pdfmark.good ,
+% pdf.outerbox ,
+% pdf.baselineskip ,
+% pdf.pdfmark.dict
+% }
+% The business end of breaking links starts by hooking into |pdfmarks|.
+% Unlike \pkg{hypdvips}, we avoid altering any links we have not created
+% by using a copy of the core |pdfmarks| function. Only mark types which
+% are known are altered. At present, this is purely |ANN| marks, which are
+% measured relative to the size of the baseline skip. If they are
+% more than one apparent line high, breaking is applied.
+% \begin{macrocode}
+/pdf.pdfmark
+ {
+ SDict /pdf.pdfmark.good true put
+ dup /ANN eq
+ {
+ pdf.pdfmark.store
+ pdf.pdfmark.dict
+ begin
+ Subtype /Link eq
+ currentdict /Rect known and
+ SDict /pdf.outerbox known and
+ SDict /pdf.baselineskip known and
+ {
+ Rect 3 get
+ pdf.linkmargin 2 mul add
+ pdf.outerbox pdf.rect.ht add
+ Rect 1 get sub
+ pdf.baselineskip div round cvi 0 gt
+ { pdf.breaklink }
+ if
+ }
+ if
+ end
+ SDict /pdf.outerbox undef
+ SDict /pdf.baselineskip undef
+ currentdict /pdf.pdfmark.dict undef
+ }
+ if
+ pdf.pdfmark.good
+ { pdfmark }
+ { cleartomark }
+ ifelse
+ }
+ def
+/pdf.pdfmark.store
+ {
+ /pdf.pdfmark.dict 65534 dict def
+ counttomark 1 add copy
+ pop
+ {
+ dup mark eq
+ {
+ pop
+ exit
+ }
+ {
+ pdf.pdfmark.dict
+ begin def end
+ }
+ ifelse
+ }
+ loop
+}
+ def
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</dvips&header>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex