xcoffins.pdf. - CTAN
xcoffins.pdf. - CTAN
xcoffins.pdf. - CTAN
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
The <strong>xcoffins</strong> package<br />
Design-level coffins ∗<br />
The L ATEX3 Project †<br />
Released 2012/07/29<br />
1 Introduction: the coffin concept<br />
In L ATEX3 terminology, a “coffin” is a box containing typeset material. Along with the<br />
box itself, the coffin structure includes information on the size and shape of the box,<br />
which makes it possible to align two or more coffins easily. This is achieved by providing<br />
a series of ‘poles’ for each coffin. These are horizontal and vertical lines through the coffin<br />
at defined positions, for example the top or horizontal centre. The points where these<br />
poles intersect are called “handles”. Two coffins can then be aligned by describing the<br />
relationship between a handle on one coffin with a handle on the second. In words, an<br />
example might then read<br />
Align the top-left handle of coffin A with the bottom-right handle of coffin B.<br />
The locations of coffin handles are much easier to understand visually. Figure 1<br />
shows the standard handle positions for a coffin typeset in horizontal mode (left) and in<br />
vertical mode (right). Notice that the later case results in a greater number of handles<br />
being available. As illustrated, each handle results from the intersection of two poles.<br />
For example, the centre of the coffin is marked (hc,vc), i.e. it is the point of intersection<br />
of the horizontal centre pole with the vertical centre pole. New handles are generated<br />
automatically when poles are added to a coffin: handles are “dynamic” entities.<br />
∗ This file describes v4029, last revised 2012/07/29.<br />
† E-mail: latex-team@latex-project.org<br />
(l,t)<br />
(l,vc)<br />
(l,H)<br />
(l,b)<br />
(hc,t)<br />
(hc,vc)<br />
(hc,H)<br />
(hc,b)<br />
(r,t)<br />
(r,vc)<br />
(r,H)<br />
(r,b)<br />
(l,t)<br />
(l,T)<br />
(l,vc)<br />
(l,H)<br />
(l,b)<br />
(hc,t)<br />
(hc,T)<br />
(hc,vc)<br />
(hc,H)<br />
(hc,b)<br />
Figure 1: Standard coffin handles: left, horizontal coffin; right, vertical coffin<br />
1<br />
(r,t)<br />
(r,T)<br />
(r,vc)<br />
(r,H)<br />
(r,b)
\NewCoffin<br />
\SetHorizontalCoffin<br />
\SetVerticalCoffin<br />
2 Creating and setting coffins<br />
Before any alignment can take place, coffins must be created and their contents must<br />
be created. All coffin operations are local to the current TEX group with the exception<br />
of coffin creation. Coffins are also “colour safe”: in contrast to the code-level \box_...<br />
functions there is no need to add additional grouping to coffins when dealing with colour.<br />
\NewCoffin 〈coffin〉<br />
Before a 〈coffin〉 can be used, it must be allocated using \NewCoffin. The name of the<br />
〈coffin〉 should be a control sequence (starting with the escape character, usually \), for<br />
example<br />
\NewCoffin\MyCoffin<br />
Coffins are allocated globally, and an error will be raised if the name of the 〈coffin〉 is<br />
not globally-unique.<br />
\SetHorizontalCoffin 〈coffin〉 {〈material〉}<br />
Typesets the 〈material〉 in horizontal mode, storing the result in the 〈coffin〉. The standard<br />
poles for the 〈coffin〉 are then set up based on the size of the typeset material.<br />
\SetVerticalCoffin 〈coffin〉 {〈width〉} {〈material〉}<br />
Typesets the 〈material〉 in vertical mode constrained to the given 〈width〉 and stores the<br />
result in the 〈coffin〉. The standard poles for the 〈coffin〉 are then set up based on the<br />
size of the typeset material.<br />
3 Controlling coffin poles<br />
A number of standard poles are automatically generated when the coffin is set or an<br />
alignment takes place. The standard poles for all coffins are:<br />
l a pole running along the left-hand edge of the bounding box of the coffin;<br />
hc a pole running vertically through the centre of the coffin half-way between the leftand<br />
right-hand edges of the bounding box (i.e. the “horizontal centre”);<br />
r a pole running along the right-hand edge of the bounding box of the coffin;<br />
b a pole running along the bottom edge of the bounding box of the coffin;<br />
vc a pole running horizontally through the centre of the coffin half-way between the<br />
bottom and top edges of the bounding box (i.e. the “vertical centre”);<br />
t a pole running along the top edge of the bounding box of the coffin;<br />
H a pole running along the baseline of the typeset material contained in the coffin.<br />
2
\SetHorizontalPole<br />
\SetVerticalPole<br />
\TotalHeight<br />
\Height<br />
In addition, coffins containing vertical-mode material also feature poles which reflect the<br />
richer nature of these systems:<br />
B a pole running along the baseline of the material at the bottom of the coffin.<br />
T a pole running along the baseline of the material at the top of the coffin.<br />
\SetHorizontalPole 〈coffin〉 {〈pole〉} {〈offset〉}<br />
Sets the 〈pole〉 to run horizontally through the 〈coffin〉. The 〈pole〉 will be located at the<br />
〈offset〉 from the bottom edge of the bounding box of the 〈coffin〉. The 〈offset〉 should<br />
be given as a dimension expression; this may include the terms \TotalHeight, \Height,<br />
\Depth and \Width, which will evaluate to the appropriate dimensions of the 〈coffin〉.<br />
For example, to create a pole running horizontally through the coffin at one third of the<br />
distance from the base of the coffin to the top, the appropriate instruction would be<br />
\SetHorizontalPole \MyCoffin {height/3} {\TotalHeight/3}<br />
Note that poles which run horizontally are described in terms of their vertical location<br />
in the coffin. Also notice that the total height of the coffin is described by the sum<br />
of \Height and \Depth: these are both measured from the horizontal baseline of the<br />
material in the coffin.<br />
\SetVerticalPole 〈coffin〉 {〈pole〉} {〈offset〉}<br />
Sets the 〈pole〉 to run vertically through the 〈coffin〉. The 〈pole〉 will be located at the<br />
〈offset〉 from the left-hand edge of the bounding box of the 〈coffin〉. The 〈offset〉 should<br />
be given as a dimension expression; this may include the terms \TotalHeight, \Height,<br />
\Depth and \Width, which will evaluate to the appropriate dimensions of the 〈coffin〉.<br />
For example, to create a pole running vertically through the coffin at one third of the<br />
distance from the left-hand edge, the appropriate instruction would be<br />
\SetVerticalPole \MyCoffin {width/3} {\Width/3}<br />
Note that poles which run vertically are described in terms of their horizontal location<br />
in the coffin.<br />
\TotalHeight<br />
Within the 〈offset〉 argument of \SetHorizontalPole and \SetVerticalPole, \TotalHeight<br />
will give the distance from the base to the top of the bounding box of the relevant coffin.<br />
\Height<br />
Within the 〈offset〉 argument of \SetHorizontalPole and \SetVerticalPole, \Height<br />
will give the distance from the baseline to the top of the bounding box of the relevant<br />
coffin.<br />
3
\Depth<br />
\Width<br />
\RotateCoffin<br />
\ResizeCoffin<br />
\ScaleCoffin<br />
\Depth<br />
(l,t)<br />
(l,vc)<br />
(l,H)<br />
(l,b)<br />
(hc,t)<br />
(hc,vc)<br />
(hc,H)<br />
(hc,b)<br />
(r,t)<br />
(r,vc)<br />
(r,H)<br />
(r,b)<br />
(l,t)<br />
(l,vc)<br />
(hc,t)<br />
(hc,vc)<br />
(l,H)<br />
(l,b)<br />
(r,t)<br />
(r,vc)<br />
(hc,H)<br />
(hc,b)<br />
(r,H)<br />
(r,b)<br />
Figure 2: Coffin rotation: left, unrotated; right, rotated by 45°.<br />
Within the 〈offset〉 argument of \SetHorizontalPole and \SetVerticalPole, \Depth<br />
will give the distance from the baseline to the bottom of the bounding box of the relevant<br />
coffin.<br />
\Width<br />
Within the 〈offset〉 argument of \SetHorizontalPole and \SetVerticalPole, \Width<br />
will give the distance from the right edge to the left edge of the bounding box of the<br />
relevant coffin.<br />
4 Rotating coffins<br />
\RotateCoffin 〈coffin〉 {〈angle〉}<br />
Rotates the 〈coffin〉 by the given 〈angle〉 about its reference point (given in degrees<br />
counter-clockwise) . This process will rotate both the coffin content and poles. Multiple<br />
rotations will not result in the bounding box of the coffin growing unnecessarily.<br />
The effect of rotation on a coffin is illustrated in Figure 2. As is shown, the coffin<br />
handles will remain correctly positioned relative to the content of the coffin. The “top”<br />
of a rotated coffin may of course no longer be the edge closest to the top of the physical<br />
page.<br />
5 Resizing coffins<br />
\ResizeCoffin 〈coffin〉 {〈width〉} {〈total-height〉}<br />
Resized the 〈coffin〉 to 〈width〉 and 〈total-height〉, both of which should be given as dimension<br />
expressions.<br />
\ScaleCoffin 〈coffin〉 {〈x-scale〉} {〈y-scale〉}<br />
Scales the 〈coffin〉 by a factors 〈x-scale〉 and 〈y-scale〉 in the horizontal and vertical<br />
directions, respectively. The two scale factors should be given as real numbers.<br />
4
\JoinCoffins<br />
(l,t)<br />
(l,vc)<br />
(l,H)<br />
(l,b)<br />
(hc,t)<br />
(hc,vc)<br />
(hc,H)<br />
(hc,b)<br />
(r,t)<br />
(r,vc)<br />
(r,H)<br />
(r,b)<br />
(l,t)<br />
(l,vc)<br />
(l,H)<br />
(l,b)<br />
Figure 3: Coffin resizing: left, resized to exactly 4 cm by 6 cm; right, scaled a factors of<br />
2 and 0.5 in x and y, respectively (example coffin as in Figure 2).<br />
\ResizeCoffin and \ScaleCoffin can be used interchangeably: whether scale factors<br />
or absolute values are the best form for the resizing will depend upon the context<br />
(Figure 3).<br />
6 Joining coffins<br />
The key operation for coffins is joining coffins to each other. This is always carried out<br />
such that the first coffin is the “parent”, and is updated by the alignment. The second<br />
“child” coffin is not altered by the alignment process.<br />
\JoinCoffins *<br />
〈coffin1〉 [ 〈coffin1-pole1〉 , 〈coffin1-pole2〉 ]<br />
〈coffin2〉 [ 〈coffin2-pole1〉 , 〈coffin2-pole2〉 ]<br />
( 〈x-offset〉 , 〈y-offset〉 )<br />
Joining of two coffins is carried out by the \JoinCoffins function, which takes two<br />
mandatory arguments: the “parent” 〈coffin1 〉 and the “child” 〈coffin2 〉. All of the other<br />
arguments shown are optional.<br />
The standard \JoinCoffins functions joins 〈coffin2 〉 to 〈coffin1 〉 such that the<br />
bounding box of 〈coffin1 〉 after the process will expand. The new bounding box will<br />
be the smallest rectangle covering the bounding boxes of the two input coffins. When the<br />
starred variant of \JoinCoffins is used, the bounding box of 〈coffin1 〉 is not altered,<br />
i.e. 〈coffin2 〉 may protrude outside of the bounding box of the updated 〈coffin1 〉. The<br />
difference between the two forms of alignment is best illustrated using a visual example.<br />
In Figure 4, the two processes are contrasted. In both cases, the small red coffin has<br />
been aligned with the large grey coffin. In the left-hand illustration, the \JoinCoffins<br />
function was used, resulting in an expanded bounding box. In contrast, on the right<br />
\AttachCoffin was used, meaning that the bounding box does not include the area of<br />
the smaller coffin.<br />
The alignment is carried out by first calculating 〈handle1 〉, the point of intersection<br />
of 〈coffin1-pole1 〉 and 〈coffin1-pole2 〉, and 〈handle2 〉, the point of intersection of<br />
〈coffin2-pole1 〉 and 〈coffin2-pole2 〉. If the two 〈poles〉 are not specified, \JoinCoffins<br />
will use the default value (H,l), i.e. the reference point used by TEX for the underlying<br />
box. Once the two 〈handles〉 have been located, 〈coffin2 〉 is then attached to<br />
〈coffin1 〉 such that the relationship between 〈handle1 〉 and 〈handle2 〉 is described by the<br />
5<br />
(hc,t)<br />
(hc,vc)<br />
(hc,H)<br />
(hc,b)<br />
(r,t)<br />
(r,vc)<br />
(r,H)<br />
(r,b)
Figure 4: Contrast between \JoinCoffins (left) and \JoinCoffins* (right); the bounding<br />
box of the coffin is show in black.<br />
Figure 5: The effect of rotation of a joined coffin: the black line shows the coffin bounding<br />
box.<br />
〈x-offset〉 and 〈y-offset〉. This 〈offset〉 is an optional argument, and if it is not given then<br />
(0 pt, 0 pt) is used.<br />
Notice that when \JoinCoffins is used the new bounding box is the smallest rectangle<br />
containing the bounding boxes of the two input coffins. As a result, it will include<br />
additional white space unless one coffin entirely overlaps the other (Figure 5, left).<br />
Rotation of coffins will take account of the extent of the material after rotation when<br />
re-calculating the bounding box. This means that no unnecessary white space will be<br />
added on rotation (Figure 5, right).<br />
As part of the joining procedure, the poles of the two input coffins are preserved<br />
within the structure of the updated coffin. In this way it is possible to carry out complex<br />
alignment procedures. The poles of a coffin after alignment may therefore be divided into<br />
three groups:<br />
1. The “native” poles of the updated coffin, such as l, r, hc, etc.<br />
2. Poles derived from 〈coffin1 〉, such as 〈coffin1〉-l, 〈coffin1〉-r, 〈coffin1〉-hc,<br />
etc.<br />
3. Poles derived from 〈coffin2 〉, such as 〈coffin2〉-l, 〈coffin2〉-r, 〈coffin2〉-hc,<br />
etc.<br />
Applying this ability allows a series of joining operations to take place, as illustrated<br />
in Figure 6. In this example, the scheme used for alignment was as follows:<br />
6
Figure 6: Aligning coffins using poles from previous operations.<br />
\SetHorizontalCoffin\OutputCoffin{}<br />
\SetHorizontalCoffin\RedCoffin<br />
{\color{red!20!white}\rule{0.2 in}{0.2 in}}<br />
\JoinCoffins\OutputCoffin[vc,hc]\RedCoffin[vc,hc]<br />
\SetHorizontalCoffin\BlueCoffin<br />
{\color{blue!20!white}\rule{0.2 in}{0.2 in}}<br />
\JoinCoffins\OutputCoffin[\RedCoffin-vc,\RedCoffin-hc]<br />
\BlueCoffin[b,l]<br />
\SetHorizontalCoffin\GreenCoffin<br />
{\color{green!20!white}\rule{0.2 in}{0.2 in}}<br />
\JoinCoffins\OutputCoffin[\BlueCoffin-vc,\BlueCoffin-hc]<br />
\GreenCoffin[b,l]<br />
\SetHorizontalCoffin\YellowCoffin<br />
{\color{yellow!20!white}\rule{0.2 in}{0.2 in}}<br />
\JoinCoffins\OutputCoffin[\GreenCoffin-vc,\GreenCoffin-hc]<br />
\YellowCoffin[b,l]<br />
\SetHorizontalCoffin \OrangeCoffin<br />
{\color{orange!20!white}\rule{0.2 in}{0.2 in}}<br />
\JoinCoffins\OutputCoffin[\BlueCoffin-t,\BlueCoffin-l]<br />
\OrangeCoffin[b,r]<br />
\TypesetCoffin\OutputCoffin<br />
This process begins by setting up \OutputCoffin to hold the joined output. Each join<br />
then takes place placing the new addition relative to the previous one. As each coffin<br />
joined has a unique name it is possible to align relative to each one of the component<br />
parts of the assembly. This is illustrated by the addition of the final \OrangeCoffin<br />
based on the earlier placement of the \BlueCoffin.<br />
7
\TypesetCoffin<br />
\CoffinDepth<br />
\CoffinHeight<br />
\CoffinTotalHeight<br />
\CoffinWidth<br />
7 Typesetting coffins<br />
\TypesetCoffin<br />
〈coffin〉 [ 〈pole1〉 , 〈pole2〉 ]<br />
( 〈x-offset〉 , 〈y-offset〉 )<br />
Typesetting is carried out by first calculating 〈handle〉, the point of intersection of 〈pole1 〉<br />
and 〈pole2 〉. This is an optional argument, and if not given then (H,l), the TEX reference<br />
point of the underlying box, is used. The coffin is then typeset such that the relationship<br />
between the current reference point in the document and the 〈handle〉 is described by<br />
the 〈x-offset〉 and 〈y-offset〉. This 〈offset〉 is optional, and if not given (0 pt, 0 pt) is<br />
used. Typesetting a coffin is therefore analogous to carrying out an alignment where the<br />
“parent” coffin is the current insertion point.<br />
8 Measuring coffins<br />
There are places in the design process where it is useful to be able to measure coffins<br />
outside of pole-setting procedures.<br />
\CoffinDepth 〈coffin〉<br />
Calculates the depth (below the baseline) of the 〈coffin〉 in a form suitable for use in a<br />
〈dimension expression〉, for example \setlength{\mylength}{\CoffinDepth\ExampleCoffin}.<br />
\CoffinHeight 〈coffin〉<br />
Calculates the height (above the baseline) of the 〈coffin〉 in a form suitable for use in a<br />
〈dimension expression〉, for example \setlength{\mylength}{\CoffinHeight\ExampleCoffin}.<br />
\CoffinTotalHeight 〈coffin〉<br />
Calculates the total height of the 〈coffin〉 in a form suitable for use in a 〈dimension<br />
expression〉, for example \setlength{\mylength}{\CoffinTotalHeight\ExampleCoffin}.<br />
\CoffinWidth 〈coffin〉<br />
Calculates the width of the 〈coffin〉 in a form suitable for use in a 〈dimension expression〉,<br />
for example \setlength{\mylength}{\CoffinWidth\ExampleCoffin}.<br />
9 Diagnostic functions<br />
Diagnostic data for following the coffin-building process is available both graphically and<br />
at the terminal. This reflects the fact that coffins are visual constructs.<br />
8
\DisplayCoffinHandles<br />
\MarkCoffinHandle<br />
\ShowCoffinStructure<br />
\DisplayCoffinHandles 〈coffin〉 {〈colour〉}<br />
This function first calculates the intersections between all of the 〈poles〉 of the 〈coffin〉 to<br />
give a set of 〈handles〉. It then prints the 〈coffin〉 at the current location in the source,<br />
with the position of the 〈handles〉 marked on the coffin. The 〈handles〉 will be labelled<br />
as part of this process: the locations of the 〈handles〉 and the labels are both printed in<br />
the 〈colour〉 specified.<br />
\MarkCoffinHandle 〈coffin〉<br />
[ 〈pole1〉 , 〈pole2〉 ] {〈colour〉}<br />
This function first calculates the 〈handle〉 for the 〈coffin〉 as defined by the intersection<br />
of 〈pole1 〉 and 〈pole2 〉. It then marks the position of the 〈handle〉 on the 〈coffin〉. The<br />
〈handle〉 will be labelled as part of this process: the location of the 〈handle〉 and the<br />
label are both printed in the 〈colour〉 specified. If no 〈poles〉 are give, the default (H,l)<br />
is used.<br />
\ShowCoffinStructure 〈coffin〉<br />
This function shows the structural information about the 〈coffin〉 in the terminal. The<br />
width, height and depth of the typeset material are given, along with the location of all<br />
of the poles of the coffin. For example, for the rotated coffin in Figure 2, the output of<br />
\ShowCoffinStructure is:<br />
Size of coffin \ExampleCoffin:<br />
> ht = 72.26999pt<br />
> dp = 0.0pt<br />
> wd = 72.26999pt<br />
Poles of coffin \ExampleCoffin:<br />
> l => {0pt}{0pt}{0pt}{1000pt}<br />
> B => {0pt}{0pt}{1000pt}{0pt}<br />
> H => {0pt}{0pt}{1000pt}{0pt}<br />
> T => {0pt}{0pt}{1000pt}{0pt}<br />
> hc => {36.135pt}{0pt}{0pt}{1000pt}<br />
> r => {72.26999pt}{0pt}{0pt}{1000pt}<br />
> vc => {0pt}{36.135pt}{1000pt}{0pt}<br />
> t => {0pt}{72.26999pt}{1000pt}{0pt}<br />
> b => {0pt}{0.0pt}{1000pt}{0pt}.<br />
}<br />
Notice that the poles of a coffin are defined by four values: the x and y co-ordinates of a<br />
point that the pole passes through and the x- and y-components of a vector denoting the<br />
direction of the pole. It is the ratio between the later, rather than the absolute values,<br />
which determines the direction of the pole.<br />
10 Implementation<br />
1 〈*package〉<br />
9
\l__coffin_A_hpole_tl<br />
\l__coffin_A_vpole_tl<br />
\l__coffin_B_hpole_tl<br />
\l__coffin_B_vpole_tl<br />
\l__coffin_bound_box_grow_bool<br />
\l__coffin_hoffset_dim<br />
\l__coffin_voffset_dim<br />
\__coffin_design_names:N<br />
\Height<br />
\Depth<br />
\Width<br />
\TotalHeight<br />
\l__coffin_height_dim<br />
\l__coffin_depth_dim<br />
\l__coffin_width_dim<br />
\l__coffin_totalheight_dim<br />
2 〈@@=coffin〉<br />
3 \ProvidesExplPackage<br />
4 {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}<br />
Key–value definitions for the alignment system. With the exception of grow-bounding-box,<br />
all of these have to be given with a value.<br />
5 \keys_define:nn { coffin }<br />
6 {<br />
7 coffin1-hpole .tl_set:N = \l__coffin_A_hpole_tl ,<br />
8 coffin1-hpole .value_required: ,<br />
9 coffin1-vpole .tl_set:N = \l__coffin_A_vpole_tl ,<br />
10 coffin1-vpole .value_required: ,<br />
11 coffin2-hpole .tl_set:N = \l__coffin_B_hpole_tl ,<br />
12 coffin2-hpole .value_required: ,<br />
13 coffin2-vpole .tl_set:N = \l__coffin_B_vpole_tl ,<br />
14 coffin2-vpole .value_required: ,<br />
15 grow-bounding-box .bool_set:N = \l__coffin_bound_box_grow_bool ,<br />
16 grow-bounding-box .default:n = true ,<br />
17 hoffset .dim_set:N = \l__coffin_hoffset_dim ,<br />
18 hoffset .value_required: ,<br />
19 voffset .dim_set:N = \l__coffin_voffset_dim ,<br />
20 voffset .value_required:<br />
21 }<br />
22 \keys_set:nn { coffin }<br />
23 {<br />
24 coffin1-hpole = H ,<br />
25 coffin1-vpole = l ,<br />
26 coffin2-hpole = H ,<br />
27 coffin2-vpole = l ,<br />
28 grow-bounding-box = true ,<br />
29 hoffset = 0 pt ,<br />
30 voffset = 0 pt<br />
31 }<br />
(End definition for \l__coffin_A_hpole_tl and others. These variables are documented on page ??.)<br />
Sets up design-level names for the various coffin dimensions. These are not defined<br />
outside of this scope, and are dimensions so that they work correctly inside for example<br />
\fp_eval:n.<br />
32 \cs_new_protected:Npn \__coffin_design_names:N #1<br />
33 {<br />
34 \dim_set:Nn \l__coffin_height_dim { \coffin_ht:N #1 }<br />
35 \dim_set:Nn \l__coffin_depth_dim { \coffin_dp:N #1 }<br />
36 \dim_set:Nn \l__coffin_width_dim { \coffin_wd:N #1 }<br />
37 \dim_set:Nn \l__coffin_totalheight_dim<br />
38 { \l__coffin_height_dim + \l__coffin_depth_dim }<br />
39 \cs_set_eq:NN \Height \l__coffin_height_dim<br />
40 \cs_set_eq:NN \Depth \l__coffin_depth_dim<br />
41 \cs_set_eq:NN \Width \l__coffin_width_dim<br />
42 \cs_set_eq:NN \TotalHeight \l__coffin_totalheight_dim<br />
10
43 }<br />
44 \dim_new:N \l__coffin_height_dim<br />
45 \dim_new:N \l__coffin_depth_dim<br />
46 \dim_new:N \l__coffin_width_dim<br />
47 \dim_new:N \l__coffin_totalheight_dim<br />
(End definition for \__coffin_design_names:N. This function is documented on page ??.)<br />
A lot of this is more-or-less just passing data straight through.<br />
\NewCoffin This is a very easy conversion.<br />
\SetHorizontalCoffin<br />
\SetVerticalCoffin<br />
\SetHorizontalPole<br />
\SetVerticalPole<br />
48 \NewDocumentCommand \NewCoffin { m }<br />
49 { \coffin_new:N #1 }<br />
(End definition for \NewCoffin. This function is documented on page 2.)<br />
These are again straight-forward translations.<br />
50 \NewDocumentCommand \SetHorizontalCoffin { m +m }<br />
51 { \hcoffin_set:Nn #1 {#2} }<br />
52 \NewDocumentCommand \SetVerticalCoffin { m m +m }<br />
53 { \vcoffin_set:Nnn #1 {#2} {#3} }<br />
(End definition for \SetHorizontalCoffin. This function is documented on page 2.)<br />
Here, there is a need to set up the design-level names for coffin dimensions. This requires<br />
grouping, but the coffin work has to occur outside of the group. Hence there is a bit of<br />
expansion trickery.<br />
54 \NewDocumentCommand \SetHorizontalPole { m m m }<br />
55 {<br />
56 \group_begin:<br />
57 \__coffin_design_names:N #1<br />
58 \use:x<br />
59 {<br />
60 \group_end:<br />
61 \coffin_set_horizontal_pole:Nnn #1<br />
62 { \exp_not:n {#2} } { \dim_eval:n {#3} }<br />
63 }<br />
64 }<br />
65 \NewDocumentCommand \SetVerticalPole { m m m }<br />
66 {<br />
67 \group_begin:<br />
68 \__coffin_design_names:N #1<br />
69 \use:x<br />
70 {<br />
71 \group_end:<br />
72 \coffin_set_vertical_pole:Nnn #1<br />
73 { \exp_not:n {#2} } { \dim_eval:n {#3} }<br />
74 }<br />
75 }<br />
(End definition for \SetHorizontalPole. This function is documented on page 3.)<br />
11
\JoinCoffins The \JoinCoffins function needs to do a bit of work on the input syntax, as there are<br />
a number of optional arguments to worry about. The idea here is that \JoinCoffins<br />
can be used to either expand the bounding box of 〈coffin1 〉 or add 〈coffin2 〉 without any<br />
expansion of the bounding box. There are also the two handle positions and the offset<br />
to sort out.<br />
76 \NewDocumentCommand \JoinCoffins<br />
77 {<br />
78 o<br />
79 s<br />
80 m<br />
81 > { \SplitArgument { 1 } { , } } O { H , l }<br />
82 m<br />
83 > { \SplitArgument { 1 } { , } } O { H , l }<br />
84 > { \SplitArgument { 1 } { , } } D ( ) { 0 pt , 0 pt }<br />
85 }<br />
86 {<br />
87 \IfNoValueTF {#1}<br />
88 {<br />
89 \IfBooleanTF #2<br />
90 { \coffin_attach:NnnNnnnn #3 #4 #5 #6 #7 }<br />
91 { \coffin_join:NnnNnnnn #3 #4 #5 #6 #7 }<br />
92 }<br />
93 {<br />
94 \group_begin:<br />
95 \keys_set:nn { coffin } {#1}<br />
96 \tl_set:Nx \l__coffin_tmp_tl<br />
97 {<br />
98 \group_end:<br />
99 \bool_if:NTF \l__coffin_bound_box_grow_bool<br />
100 { \coffin_join:NnnNnnnn }<br />
101 { \coffin_attach:NnnNnnnn }<br />
102 \exp_not:N #3<br />
103 { \exp_not:o { \l__coffin_A_hpole_tl } }<br />
104 { \exp_not:o { \l__coffin_A_vpole_tl } }<br />
105 \exp_not:N #5<br />
106 { \exp_not:o { \l__coffin_B_hpole_tl } }<br />
107 { \exp_not:o { \l__coffin_B_vpole_tl } }<br />
108 { \dim_use:N \l__coffin_hoffset_dim }<br />
109 { \dim_use:N \l__coffin_voffset_dim }<br />
110 }<br />
111 \l__coffin_tmp_tl<br />
112 }<br />
113 }<br />
(End definition for \JoinCoffins. This function is documented on page 5.)<br />
\TypesetCoffin For typesetting coffins there are two optional arguments, both of which need to be split.<br />
This is a simpler case of the code needed for \JoinCoffins.<br />
114 \NewDocumentCommand \TypesetCoffin<br />
115 {<br />
12
\RotateCoffin<br />
\ResizeCoffin<br />
\ScaleCoffin<br />
\CoffinDepth<br />
\CoffinHeight<br />
\CoffinTotalHeigth<br />
\CoffinWidth<br />
116 m<br />
117 > { \SplitArgument { 1 } { , } } O { H , l }<br />
118 > { \SplitArgument { 1 } { , } } D ( ) { 0 pt , 0 pt }<br />
119 }<br />
120 { \coffin_typeset:Nnnnn #1 #2 #3 }<br />
(End definition for \TypesetCoffin. This function is documented on page 8.)<br />
Mores straight-forward copies.<br />
121 \NewDocumentCommand \RotateCoffin { m m }<br />
122 { \coffin_rotate:Nn #1 {#2} }<br />
123 \NewDocumentCommand \ResizeCoffin { m m m }<br />
124 { \coffin_resize:Nnn #1 {#2} {#3} }<br />
125 \NewDocumentCommand \ScaleCoffin { m m m }<br />
126 { \coffin_scale:Nnn #1 {#2} {#3} }<br />
(End definition for \RotateCoffin. This function is documented on page 4.)<br />
Nothing too complex, except that the total height is set up as an expression so that it<br />
will act correctly if prefixed with a negative sign, etc.<br />
127 \NewDocumentCommand \CoffinDepth { m }<br />
128 { \coffin_dp:N #1 }<br />
129 \NewDocumentCommand \CoffinHeight { m }<br />
130 { \coffin_ht:N #1 }<br />
131 \NewDocumentCommand \CoffinTotalHeight { m }<br />
132 { \__dim_eval:w \coffin_ht:N #1 + \coffin_dp:N #1 \__dim_eval_end: }<br />
133 \NewDocumentCommand \CoffinWidth { m }<br />
134 { \coffin_wd:N #1 }<br />
(End definition for \CoffinDepth and others. These functions are documented on page 8.)<br />
\DisplayCoffinHandles Displaying all of the handles is a bit easier, as there is no need to worry about the handle.<br />
135 \NewDocumentCommand \DisplayCoffinHandles { m m }<br />
136 { \coffin_if_exist:NT #1 { \coffin_display_handles:Nn #1 {#2} } }<br />
(End definition for \DisplayCoffinHandles. This function is documented on page 9.)<br />
\MarkCoffinHandle Marking a handle requires a bit of work with the input, so that the design-level interface<br />
is “nice”.<br />
137 \NewDocumentCommand \MarkCoffinHandle<br />
138 { m > { \SplitArgument { 1 } { , } } O { H , l } m }<br />
139 { \coffin_if_exist:NT #1 { \coffin_mark_handle:Nnnn #1 #2 {#3} } }<br />
(End definition for \MarkCoffinHandle. This function is documented on page 9.)<br />
\ShowCoffinStructure Back again to easy-to-implement functions.<br />
140 \NewDocumentCommand \ShowCoffinStructure { m }<br />
141 { \coffin_show_structure:N #1 }<br />
(End definition for \ShowCoffinStructure. This function is documented on page 9.)<br />
142 〈/package〉<br />
13
Index<br />
The italic numbers denote the pages where the corresponding entry is described, numbers<br />
underlined point to the definition, all others indicate the places where it is used.<br />
Symbols<br />
\__coffin_design_names:N . . 32, 32, 57, 68<br />
\__dim_eval:w . . . . . . . . . . . . . . . . . . 132<br />
\__dim_eval_end: . . . . . . . . . . . . . . . 132<br />
B<br />
\bool_if:NTF . . . . . . . . . . . . . . . . . . . . 99<br />
C<br />
\coffin_attach:NnnNnnnn . . . . . . . 90, 101<br />
\coffin_display_handles:Nn . . . . . . . 136<br />
\coffin_dp:N . . . . . . . . . . . . . 35, 128, 132<br />
\coffin_ht:N . . . . . . . . . . . . . 34, 130, 132<br />
\coffin_if_exist:NT . . . . . . . . . . 136, 139<br />
\coffin_join:NnnNnnnn . . . . . . . . . 91, 100<br />
\coffin_mark_handle:Nnnn . . . . . . . . . 139<br />
\coffin_new:N . . . . . . . . . . . . . . . . . . . 49<br />
\coffin_resize:Nnn . . . . . . . . . . . . . . 124<br />
\coffin_rotate:Nn . . . . . . . . . . . . . . 122<br />
\coffin_scale:Nnn . . . . . . . . . . . . . . 126<br />
\coffin_set_horizontal_pole:Nnn . . . . 61<br />
\coffin_set_vertical_pole:Nnn . . . . . 72<br />
\coffin_show_structure:N . . . . . . . . . 141<br />
\coffin_typeset:Nnnnn . . . . . . . . . . . 120<br />
\coffin_wd:N . . . . . . . . . . . . . . . . . 36, 134<br />
\CoffinDepth . . . . . . . . . . . . . . 8, 127, 127<br />
\CoffinHeight . . . . . . . . . . . . . 8, 127, 129<br />
\CoffinTotalHeight . . . . . . . . . . . . 8, 131<br />
\CoffinTotalHeigth . . . . . . . . . . . . . . 127<br />
\CoffinWidth . . . . . . . . . . . . . . 8, 127, 133<br />
\cs_new_protected:Npn . . . . . . . . . . . . 32<br />
\cs_set_eq:NN . . . . . . . . . . . 39, 40, 41, 42<br />
D<br />
\Depth . . . . . . . . . . . . . . . . . . . . . 4, 32, 40<br />
\dim_eval:n . . . . . . . . . . . . . . . . . . 62, 73<br />
\dim_new:N . . . . . . . . . . . . . 44, 45, 46, 47<br />
\dim_set:Nn . . . . . . . . . . . . . 34, 35, 36, 37<br />
\dim_use:N . . . . . . . . . . . . . . . . . 108, 109<br />
\DisplayCoffinHandles . . . . . . 9, 135, 135<br />
E<br />
\exp_not:N . . . . . . . . . . . . . . . . . 102, 105<br />
\exp_not:n . . . . . . . . . . . . . . . . . . 62, 73<br />
14<br />
\exp_not:o . . . . . . . . . . 103, 104, 106, 107<br />
\ExplFileDate . . . . . . . . . . . . . . . . . . . . 4<br />
\ExplFileDescription . . . . . . . . . . . . . . 4<br />
\ExplFileName . . . . . . . . . . . . . . . . . . . . 4<br />
\ExplFileVersion . . . . . . . . . . . . . . . . . 4<br />
G<br />
\group_begin: . . . . . . . . . . . . . . 56, 67, 94<br />
\group_end: . . . . . . . . . . . . . . . . 60, 71, 98<br />
H<br />
\hcoffin_set:Nn . . . . . . . . . . . . . . . . . 51<br />
\Height . . . . . . . . . . . . . . . . . . . . 3, 32, 39<br />
I<br />
\IfBooleanTF . . . . . . . . . . . . . . . . . . . . 89<br />
\IfNoValueTF . . . . . . . . . . . . . . . . . . . . 87<br />
J<br />
\JoinCoffins . . . . . . . . . . . . . . . . 5, 76, 76<br />
K<br />
\keys_define:nn . . . . . . . . . . . . . . . . . . 5<br />
\keys_set:nn . . . . . . . . . . . . . . . . . 22, 95<br />
L<br />
\l__coffin_A_hpole_tl . . . . . . . . 5, 7, 103<br />
\l__coffin_A_vpole_tl . . . . . . . . 5, 9, 104<br />
\l__coffin_B_hpole_tl . . . . . . . 5, 11, 106<br />
\l__coffin_B_vpole_tl . . . . . . . 5, 13, 107<br />
\l__coffin_bound_box_grow_bool 5, 15, 99<br />
\l__coffin_depth_dim . . 32, 35, 38, 40, 45<br />
\l__coffin_height_dim . 32, 34, 38, 39, 44<br />
\l__coffin_hoffset_dim . . . . . . 5, 17, 108<br />
\l__coffin_tmp_tl . . . . . . . . . . . . 96, 111<br />
\l__coffin_totalheight_dim 32, 37, 42, 47<br />
\l__coffin_voffset_dim . . . . . . 5, 19, 109<br />
\l__coffin_width_dim . . . . . 32, 36, 41, 46<br />
M<br />
\MarkCoffinHandle . . . . . . . . . 9, 137, 137<br />
N<br />
\NewCoffin . . . . . . . . . . . . . . . . . 2, 48, 48<br />
\NewDocumentCommand . . . . . . . . . . . 48,<br />
50, 52, 54, 65, 76, 114, 121, 123,<br />
125, 127, 129, 131, 133, 135, 137, 140
P<br />
\ProvidesExplPackage . . . . . . . . . . . . . . 3<br />
R<br />
\ResizeCoffin . . . . . . . . . . . . . 4, 121, 123<br />
\RotateCoffin . . . . . . . . . . . . . 4, 121, 121<br />
S<br />
\ScaleCoffin . . . . . . . . . . . . . . 4, 121, 125<br />
\SetHorizontalCoffin . . . . . . . . . 2, 50, 50<br />
\SetHorizontalPole . . . . . . . . . . . 3, 54, 54<br />
\SetVerticalCoffin . . . . . . . . . . . 2, 50, 52<br />
\SetVerticalPole . . . . . . . . . . . . 3, 54, 65<br />
\ShowCoffinStructure . . . . . . . 9, 140, 140<br />
\SplitArgument . . 81, 83, 84, 117, 118, 138<br />
15<br />
T<br />
\tl_set:Nx . . . . . . . . . . . . . . . . . . . . . 96<br />
\TotalHeight . . . . . . . . . . . . . . . . 3, 32, 42<br />
\TypesetCoffin . . . . . . . . . . . . 8, 114, 114<br />
U<br />
\use:x . . . . . . . . . . . . . . . . . . . . . . 58, 69<br />
V<br />
\vcoffin_set:Nnn . . . . . . . . . . . . . . . . 53<br />
W<br />
\Width . . . . . . . . . . . . . . . . . . . . . 4, 32, 41