15.07.2013 Views

xcoffins.pdf. - CTAN

xcoffins.pdf. - CTAN

xcoffins.pdf. - CTAN

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!