[XeTeX] XeTeX : request for enhancement

Philip Taylor Philip.Taylor at Hellenic-Institute.Uk
Thu Apr 4 22:49:45 CEST 2024


On 15/10/2023, 15:17, I wrote :
> At the moment, one can include a PDF file using the following syntax :
>
>     \XeTeXpdffile ⟨filename⟩ [ page ⟨int⟩ ] [ crop | media | bleed |
>     trim | art ]
>     [ scaled ⟨int⟩ | xscaled ⟨int⟩ | yscaled ⟨int⟩ | width ⟨dimen⟩ |
>     height ⟨dimen⟩ | rotated ⟨decimal⟩ ]
>     Insert (pages of) a PDF. See below for explanation
>
> where [ crop | media | bleed | trim | art ] specify to which of the 
> four boxes known to PDF the inserted file is to be cropped.  I 
> frequently have the need to crop a PDF file during inclusion to 
> arbitrary dimensions, but at the moment that would appear to be 
> impossible (short of pre-massaging the PDF to be inserted).  Would it 
> be possible to enhance XeTeX to recognise and honour the following (or 
> similar) syntax :
>
>     \XeTeXpdffile ⟨filename⟩ [ page ⟨int⟩ ] [ crop | media | bleed |
>     trim | art | custom [xmin ymin xmax ymax]]
>     [ scaled ⟨int⟩ | xscaled ⟨int⟩ | yscaled ⟨int⟩ | width ⟨dimen⟩ |
>     height ⟨dimen⟩ | rotated ⟨decimal⟩ ]
>     Insert (pages of) a PDF. See below for explanation
>
to which David Carlisle kindly replied :

> You can clip an arbitrary box so no need to have this as an image 
> inclusion feature.
>
> \input{graphicx}
> \includegraphics{example-image.pdf}
> \bigskip
> \includegraphics[trim=20pt 50pt 50pt 100pt, clip]{example-image.pdf}
> \bye
The need for this feature disappeared, so I did not pursue David’s 
suggestion at the time, but the need returned yesterday so I gave 
David's suggestion a try, and although it took me several attempts to 
work out the correct dimensions to pass as parameter to \includegraphics 
(in part because the PostScript/PDF bounding box is bottom-up, while TeX 
assembles boxes top down (and the TeXworks ruler also increases as one 
goes downwards)) I eventually managed to make it work.  However, while 
graphicx.tex is only 40 or so lines long, graphicx.sty (which 
graphicx.tex slaves) is over 250 lines, miniltx.tex is almost 600 lines, 
and then there are the driver files (xetex.def is over 500 lines in 
itself).  In total, maybe 1500 lines of code or so.  This seemed 
somewhat excessive to me, so I set about finding out how graphicx.tex 
achieved my goal.  It turned out that the key part was less than 20 
lines in length, and "hidden" in xetex.def :

\def\GPT at clipbox#1{%
   \setbox#1=\hbox{%
     \Gin at defaultbp\WIDTH{\wd#1}%
     \Gin at defaultbp\DEPTH{\dp#1}%
     \@tempdima\ht#1%
     \advance\@tempdima\dp#1%
     \Gin at defaultbp\TOTALHEIGHT{\@tempdima}%
     \special{x:gsave}%
     \special{%
       pdf:literal
       0 -\DEPTH\GPT at space \WIDTH\GPT at space \TOTALHEIGHT\GPT at space re  W n
     }%
     \rlap{\box#1}%
     \special{x:grestore}%
     \special{pdfcolorstack \@pdfcolorstack current}%
     \hskip\wd#1%
   }%
}

or in a somewhat more readable form (and omitting the commercial-ats and 
most eol percent comments)

\def \GPTclipbox #1%
     {%
       \setbox #1 = \hbox
           {%
             \Gindefaultbp \WIDTH = \wd#1
             \Gindefaultbp \DEPTH = \dp#1
             \tempdima = \ht #1
             \advance \tempdima by \dp #1
             \Gindefaultbp \TOTALHEIGHT = \tempdima
             \special {x:gsave}
             \special {pdf:literal 0 -\DEPTH \space \WIDTH \space 
\TOTALHEIGHT \space re W n}
             \rlap {\box#1}
             \special {x:grestore}
             \special {pdfcolorstack \pdfcolorstack current}
             \hskip \wd #1
           }%
     }

As the depth of most boxes is normally small, we can approximate the key 
line as follows, omitting the \spaces for readability :

    \special {pdf:literal 0 0 \WIDTH \TOTALHEIGHT re W n}

where :
/
/
> /The //|re|//operator constructs a rectangle. It takes four parameters 
> (the values preceding the operator) that define a rectangle: the x 
> co-ordinate of the lower-left corner, the y co-ordinate of the 
> lower-left corner, the width and the height. /
>
> /The //|W|//operator sets the clipping path, which in this case is the 
> rectangle just drawn, for the content that follows./
>
> //
>
> /The //|n|//operator starts a new path. It discards the paths 
> constructed so far. It thus prevents the rectangle just drawn (used as 
> clipping path) from being drawn/.
>
Now as both co-ordinates of the lower left corner are (or almost are) 
zero, the effect of the \special {pdf:literal  ... re W n} will be to 
clip the contents of the box passed as parameter to a rectangle with 
lower-left corner  approximately (0,0).  But what if we want a rectangle 
of the same size, but /not /with origin (0, 0) ?  Well, clearly, before 
this code is called, we mus massage the contents of the box to be passed 
as parameter such that our /intended/ origin has been mapped to the (0, 
0) point. Once we realise this, we are in a position to write the code :

    % !TeX Program=XeTeX

    \pdfpageheight = 210 mm
    \pdfpagewidth = 297 mm

    \hsize = \pdfpagewidth
    \vsize = \pdfpageheight

    \parindent = 1 cm

    \output = {\advance \hoffset by -1 in \advance \voffset by -1 in
    \shipout \box 255 }

    \newcount \xmin
    \newcount \ymin
    \newcount \xmax
    \newcount \ymax
    \newcount \height
    \newcount \width

    \xmin = 1900
    \ymin = 300

    \width = 700
    \height = 70

    \xmax = \numexpr \xmin + \width \relax
    \ymax = \numexpr \ymin + \height \relax

    \setbox 0 = \vbox {\XeTeXpdffile Example-image-3.pdf }
    \setbox 0 = \hbox to \width bp {\kern - \xmin bp \box 0 \hss}
    \setbox 0 = \vbox to \height bp {\kern \dimexpr \ymax bp - (\ht 0 +
    \dp 0) \box 0 \vss}

    \setbox 0 = \hbox
         \bgroup
             \special {x:gsave}
             \special {pdf:literal 0 0 \number \width \space \number
    \height \space re W n }
             \box 0
             \special {x:grestore}
         \egroup

    \topglue 1 cm
    \leavevmode \box 0

    \end

Just over 40 lines in total.  The file that I was seeking to clip, 
renamed as Example-image-3.pdf, is attached.  It is 100 cm wide by 20 cm 
tall (plus bleed and trim marks), or about 2800 x 600 bp, so I would 
normally want to express \xmin, \ymin, ..., \width in cm rather than in 
bp, as is implied in the code above, but that would just be syntactic 
sugar so I leave the code as I initially wrote it.  Note that my code 
does not correctly handle non-zero box depths as it stands.

My sincere thanks to David Carlisle for his suggestion which led to my 
being able to develop this code.
-- 
/Philip Taylor/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://tug.org/pipermail/xetex/attachments/20240404/7e333601/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Example-image-3.pdf
Type: application/pdf
Size: 5182 bytes
Desc: not available
URL: <https://tug.org/pipermail/xetex/attachments/20240404/7e333601/attachment.pdf>


More information about the XeTeX mailing list.