diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx | 592 |
1 files changed, 586 insertions, 6 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx index 88ae571c742..48f4edbc6a3 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2019-02-15} +% \date{Released 2019-03-05} % % \maketitle % @@ -100,7 +100,7 @@ % % \section{Setting coffin content and poles} % -% \begin{function}[added = 2011-08-17, updated = 2011-09-03] +% \begin{function}[added = 2011-08-17, updated = 2019-01-21] % { % \hcoffin_set:Nn, \hcoffin_set:cn, % \hcoffin_gset:Nn, \hcoffin_gset:cn @@ -187,6 +187,47 @@ % \meta{offset} should be given as a dimension expression. % \end{function} % +% \section{Coffin affine transformations} +% +% \begin{function}[updated = 2019-01-23] +% { +% \coffin_resize:Nnn, \coffin_resize:cnn, +% \coffin_gresize:Nnn, \coffin_gresize:cnn +% } +% \begin{syntax} +% \cs{coffin_resize:Nnn} \meta{coffin} \Arg{width} \Arg{total-height} +% \end{syntax} +% Resized the \meta{coffin} to \meta{width} and \meta{total-height}, +% both of which should be given as dimension expressions. +% \end{function} +% +% \begin{function} +% { +% \coffin_rotate:Nn, \coffin_rotate:cn, +% \coffin_grotate:Nn, \coffin_grotate:cn +% } +% \begin{syntax} +% \cs{coffin_rotate:Nn} \meta{coffin} \Arg{angle} +% \end{syntax} +% Rotates the \meta{coffin} by the given \meta{angle} (given in +% degrees counter-clockwise). This process rotates both the +% coffin content and poles. Multiple rotations do not result in +% the bounding box of the coffin growing unnecessarily. +% \end{function} +% +% \begin{function}[updated = 2019-01-23] +% { +% \coffin_scale:Nnn, \coffin_scale:cnn, +% \coffin_gscale:Nnn, \coffin_gscale:cnn +% } +% \begin{syntax} +% \cs{coffin_scale:Nnn} \meta{coffin} \Arg{x-scale} \Arg{y-scale} +% \end{syntax} +% Scales the \meta{coffin} by a factors \meta{x-scale} and +% \meta{y-scale} in the horizontal and vertical directions, +% respectively. The two scale factors should be given as real numbers. +% \end{function} +% % \section{Joining and using coffins} % % \begin{function}[updated = 2019-01-22] @@ -1277,6 +1318,537 @@ % \end{macro} % \end{macro} % +% \subsection{Affine transformations} +% +% \begin{variable}{\l_@@_sin_fp} +% \begin{variable}{\l_@@_cos_fp} +% Used for rotations to get the sine and cosine values. +% \begin{macrocode} +\fp_new:N \l_@@_sin_fp +\fp_new:N \l_@@_cos_fp +% \end{macrocode} +% \end{variable} +% \end{variable} +% +% \begin{variable}{\l_@@_bounding_prop} +% A property list for the bounding box of a coffin. This is only needed +% during the rotation, so there is just the one. +% \begin{macrocode} +\prop_new:N \l_@@_bounding_prop +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_corners_prop, \l_@@_poles_prop} +% Used to avoid needing to track scope for intermediate steps. +% \begin{macrocode} +\prop_new:N \l_@@_corners_prop +\prop_new:N \l_@@_poles_prop +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_bounding_shift_dim} +% The shift of the bounding box of a coffin from the real content. +% \begin{macrocode} +\dim_new:N \l_@@_bounding_shift_dim +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_left_corner_dim} +% \begin{variable}{\l_@@_right_corner_dim} +% \begin{variable}{\l_@@_bottom_corner_dim} +% \begin{variable}{\l_@@_top_corner_dim} +% These are used to hold maxima for the various corner values: these +% thus define the minimum size of the bounding box after rotation. +% \begin{macrocode} +\dim_new:N \l_@@_left_corner_dim +\dim_new:N \l_@@_right_corner_dim +\dim_new:N \l_@@_bottom_corner_dim +\dim_new:N \l_@@_top_corner_dim +% \end{macrocode} +% \end{variable} +% \end{variable} +% \end{variable} +% \end{variable} +% +% \begin{macro} +% { +% \coffin_rotate:Nn, \coffin_rotate:cn, +% \coffin_grotate:Nn, \coffin_grotate:cn +% } +% \begin{macro}{\@@_rotate:NnNNN} +% Rotating a coffin requires several steps which can be conveniently +% run together. The sine and cosine of the angle in degrees are +% computed. This is then used to set \cs{l_@@_sin_fp} and +% \cs{l_@@_cos_fp}, which are carried through unchanged for the rest +% of the procedure. +% \begin{macrocode} +\cs_new_protected:Npn \coffin_rotate:Nn #1#2 + { \@@_rotate:NnNNN #1 {#2} \box_rotate:Nn \prop_set_eq:cN \hbox_set:Nn } +\cs_generate_variant:Nn \coffin_rotate:Nn { c } +\cs_new_protected:Npn \coffin_grotate:Nn #1#2 + { \@@_rotate:NnNNN #1 {#2} \box_grotate:Nn \prop_gset_eq:cN \hbox_gset:Nn } +\cs_generate_variant:Nn \coffin_grotate:Nn { c } +\cs_new_protected:Npn \@@_rotate:NnNNN #1#2#3#4#5 + { + \fp_set:Nn \l_@@_sin_fp { sind ( #2 ) } + \fp_set:Nn \l_@@_cos_fp { cosd ( #2 ) } +% \end{macrocode} +% Use a local copy of the property lists to avoid needing to pass the +% name and scope around. +% \begin{macrocode} + \prop_set_eq:Nc \l_@@_corners_prop + { coffin ~ \@@_to_value:N #1 ~ corners } + \prop_set_eq:Nc \l_@@_poles_prop + { coffin ~ \@@_to_value:N #1 ~ poles } +% \end{macrocode} +% The corners and poles of the coffin can now be rotated around the +% origin. This is best achieved using mapping functions. +% \begin{macrocode} + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_rotate_corner:Nnnn #1 {##1} ##2 } + \prop_map_inline:Nn \l_@@_poles_prop + { \@@_rotate_pole:Nnnnnn #1 {##1} ##2 } +% \end{macrocode} +% The bounding box of the coffin needs to be rotated, and to do this +% the corners have to be found first. They are then rotated in the same +% way as the corners of the coffin material itself. +% \begin{macrocode} + \@@_set_bounding:N #1 + \prop_map_inline:Nn \l_@@_bounding_prop + { \@@_rotate_bounding:nnn {##1} ##2 } +% \end{macrocode} +% At this stage, there needs to be a calculation to find where the +% corners of the content and the box itself will end up. +% \begin{macrocode} + \@@_find_corner_maxima:N #1 + \@@_find_bounding_shift: + #3 #1 {#2} +% \end{macrocode} +% The correction of the box position itself takes place here. The idea +% is that the bounding box for a coffin is tight up to the content, and +% has the reference point at the bottom-left. The $x$-direction is +% handled by moving the content by the difference in the positions of +% the bounding box and the content left edge. The $y$-direction is +% dealt with by moving the box down by any depth it has acquired. The +% internal box is used here to allow for the next step. +% \begin{macrocode} + \hbox_set:Nn \l_@@_internal_box + { + \tex_kern:D + \dim_eval:n + { \l_@@_bounding_shift_dim - \l_@@_left_corner_dim } + \exp_stop_f: + \box_move_down:nn { \l_@@_bottom_corner_dim } + { \box_use:N #1 } + } +% \end{macrocode} +% If there have been any previous rotations then the size of the +% bounding box will be bigger than the contents. This can be corrected +% easily by setting the size of the box to the height and width of the +% content. As this operation requires setting box dimensions and these +% transcend grouping, the safe way to do this is to use the internal box +% and to reset the result into the target box. +% \begin{macrocode} + \box_set_ht:Nn \l_@@_internal_box + { \l_@@_top_corner_dim - \l_@@_bottom_corner_dim } + \box_set_dp:Nn \l_@@_internal_box { 0pt } + \box_set_wd:Nn \l_@@_internal_box + { \l_@@_right_corner_dim - \l_@@_left_corner_dim } + #5 #1 { \box_use_drop:N \l_@@_internal_box } +% \end{macrocode} +% The final task is to move the poles and corners such that they are +% back in alignment with the box reference point. +% \begin{macrocode} + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_shift_corner:Nnnn #1 {##1} ##2 } + \prop_map_inline:Nn \l_@@_poles_prop + { \@@_shift_pole:Nnnnnn #1 {##1} ##2 } +% \end{macrocode} +% Update the coffin data. +% \begin{macrocode} + #4 { coffin ~ \@@_to_value:N #1 ~ corners } + \l_@@_corners_prop + #4 { coffin ~ \@@_to_value:N #1 ~ poles } + \l_@@_poles_prop + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_set_bounding:N} +% The bounding box corners for a coffin are easy enough to find: this +% is the same code as for the corners of the material itself, but +% using a dedicated property list. +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_bounding:N #1 + { + \prop_put:Nnx \l_@@_bounding_prop { tl } + { { 0pt } { \dim_eval:n { \box_ht:N #1 } } } + \prop_put:Nnx \l_@@_bounding_prop { tr } + { + { \dim_eval:n { \box_wd:N #1 } } + { \dim_eval:n { \box_ht:N #1 } } + } + \dim_set:Nn \l_@@_internal_dim { -\box_dp:N #1 } + \prop_put:Nnx \l_@@_bounding_prop { bl } + { { 0pt } { \dim_use:N \l_@@_internal_dim } } + \prop_put:Nnx \l_@@_bounding_prop { br } + { + { \dim_eval:n { \box_wd:N #1 } } + { \dim_use:N \l_@@_internal_dim } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_rotate_bounding:nnn} +% \begin{macro}{\@@_rotate_corner:Nnnn} +% Rotating the position of the corner of the coffin is just a case +% of treating this as a vector from the reference point. The same +% treatment is used for the corners of the material itself and the +% bounding box. +% \begin{macrocode} +\cs_new_protected:Npn \@@_rotate_bounding:nnn #1#2#3 + { + \@@_rotate_vector:nnNN {#2} {#3} \l_@@_x_dim \l_@@_y_dim + \prop_put:Nnx \l_@@_bounding_prop {#1} + { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } } + } +\cs_new_protected:Npn \@@_rotate_corner:Nnnn #1#2#3#4 + { + \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim + \prop_put:Nnx \l_@@_corners_prop {#2} + { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_rotate_pole:Nnnnnn} +% Rotating a single pole simply means shifting the co-ordinate of +% the pole and its direction. The rotation here is about the bottom-left +% corner of the coffin. +% \begin{macrocode} +\cs_new_protected:Npn \@@_rotate_pole:Nnnnnn #1#2#3#4#5#6 + { + \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim + \@@_rotate_vector:nnNN {#5} {#6} + \l_@@_x_prime_dim \l_@@_y_prime_dim + \prop_put:Nnx \l_@@_poles_prop {#2} + { + { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } + { \dim_use:N \l_@@_x_prime_dim } + { \dim_use:N \l_@@_y_prime_dim } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_rotate_vector:nnNN} +% A rotation function, which needs only an input vector (as dimensions) +% and an output space. The values \cs{l_@@_cos_fp} and +% \cs{l_@@_sin_fp} should previously have been set up correctly. +% Working this way means that the floating point work is kept to a +% minimum: for any given rotation the sin and cosine values do no +% change, after all. +% \begin{macrocode} +\cs_new_protected:Npn \@@_rotate_vector:nnNN #1#2#3#4 + { + \dim_set:Nn #3 + { + \fp_to_dim:n + { + \dim_to_fp:n {#1} * \l_@@_cos_fp + - \dim_to_fp:n {#2} * \l_@@_sin_fp + } + } + \dim_set:Nn #4 + { + \fp_to_dim:n + { + \dim_to_fp:n {#1} * \l_@@_sin_fp + + \dim_to_fp:n {#2} * \l_@@_cos_fp + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_find_corner_maxima:N} +% \begin{macro}{\@@_find_corner_maxima_aux:nn} +% The idea here is to find the extremities of the content of the +% coffin. This is done by looking for the smallest values for the bottom +% and left corners, and the largest values for the top and right +% corners. The values start at the maximum dimensions so that the +% case where all are positive or all are negative works out correctly. +% \begin{macrocode} +\cs_new_protected:Npn \@@_find_corner_maxima:N #1 + { + \dim_set:Nn \l_@@_top_corner_dim { -\c_max_dim } + \dim_set:Nn \l_@@_right_corner_dim { -\c_max_dim } + \dim_set:Nn \l_@@_bottom_corner_dim { \c_max_dim } + \dim_set:Nn \l_@@_left_corner_dim { \c_max_dim } + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_find_corner_maxima_aux:nn ##2 } + } +\cs_new_protected:Npn \@@_find_corner_maxima_aux:nn #1#2 + { + \dim_set:Nn \l_@@_left_corner_dim + { \dim_min:nn { \l_@@_left_corner_dim } {#1} } + \dim_set:Nn \l_@@_right_corner_dim + { \dim_max:nn { \l_@@_right_corner_dim } {#1} } + \dim_set:Nn \l_@@_bottom_corner_dim + { \dim_min:nn { \l_@@_bottom_corner_dim } {#2} } + \dim_set:Nn \l_@@_top_corner_dim + { \dim_max:nn { \l_@@_top_corner_dim } {#2} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_find_bounding_shift:} +% \begin{macro}{\@@_find_bounding_shift_aux:nn} +% The approach to finding the shift for the bounding box is similar to +% that for the corners. However, there is only one value needed here and +% a fixed input property list, so things are a bit clearer. +% \begin{macrocode} +\cs_new_protected:Npn \@@_find_bounding_shift: + { + \dim_set:Nn \l_@@_bounding_shift_dim { \c_max_dim } + \prop_map_inline:Nn \l_@@_bounding_prop + { \@@_find_bounding_shift_aux:nn ##2 } + } +\cs_new_protected:Npn \@@_find_bounding_shift_aux:nn #1#2 + { + \dim_set:Nn \l_@@_bounding_shift_dim + { \dim_min:nn { \l_@@_bounding_shift_dim } {#1} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_shift_corner:Nnnn} +% \begin{macro}{\@@_shift_pole:Nnnnnn} +% Shifting the corners and poles of a coffin means subtracting the +% appropriate values from the $x$- and $y$-components. For +% the poles, this means that the direction vector is unchanged. +% \begin{macrocode} +\cs_new_protected:Npn \@@_shift_corner:Nnnn #1#2#3#4 + { + \prop_put:Nnx \l_@@_corners_prop {#2} + { + { \dim_eval:n { #3 - \l_@@_left_corner_dim } } + { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } } + } + } +\cs_new_protected:Npn \@@_shift_pole:Nnnnnn #1#2#3#4#5#6 + { + \prop_put:Nnx \l_@@_poles_prop {#2} + { + { \dim_eval:n { #3 - \l_@@_left_corner_dim } } + { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } } + {#5} {#6} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{variable}{\l_@@_scale_x_fp} +% \begin{variable}{\l_@@_scale_y_fp} +% Storage for the scaling factors in $x$ and $y$, respectively. +% \begin{macrocode} +\fp_new:N \l_@@_scale_x_fp +\fp_new:N \l_@@_scale_y_fp +% \end{macrocode} +% \end{variable} +% \end{variable} +% +% \begin{variable}{\l_@@_scaled_total_height_dim} +% \begin{variable}{\l_@@_scaled_width_dim} +% When scaling, the values given have to be turned into absolute values. +% \begin{macrocode} +\dim_new:N \l_@@_scaled_total_height_dim +\dim_new:N \l_@@_scaled_width_dim +% \end{macrocode} +% \end{variable} +% \end{variable} +% +% \begin{macro} +% { +% \coffin_resize:Nnn, \coffin_resize:cnn, +% \coffin_gresize:Nnn, \coffin_gresize:cnn +% } +% \begin{macro}{\@@_resize:NnnNN} +% Resizing a coffin begins by setting up the user-friendly names for +% the dimensions of the coffin box. The new sizes are then turned into +% scale factor. This is the same operation as takes place for the +% underlying box, but that operation is grouped and so the same +% calculation is done here. +% \begin{macrocode} +\cs_new_protected:Npn \coffin_resize:Nnn #1#2#3 + { + \@@_resize:NnnNN #1 {#2} {#3} + \box_resize_to_wd_and_ht_plus_dp:Nnn + \prop_set_eq:cN + } +\cs_generate_variant:Nn \coffin_resize:Nnn { c } +\cs_new_protected:Npn \coffin_gresize:Nnn #1#2#3 + { + \@@_resize:NnnNN #1 {#2} {#3} + \box_gresize_to_wd_and_ht_plus_dp:Nnn + \prop_gset_eq:cN + } +\cs_generate_variant:Nn \coffin_gresize:Nnn { c } +\cs_new_protected:Npn \@@_resize:NnnNN #1#2#3#4#5 + { + \fp_set:Nn \l_@@_scale_x_fp + { \dim_to_fp:n {#2} / \dim_to_fp:n { \coffin_wd:N #1 } } + \fp_set:Nn \l_@@_scale_y_fp + { + \dim_to_fp:n {#3} + / \dim_to_fp:n { \coffin_ht:N #1 + \coffin_dp:N #1 } + } + #4 #1 {#2} {#3} + \@@_resize_common:NnnN #1 {#2} {#3} #5 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_resize_common:NnnN} +% The poles and corners of the coffin are scaled to the appropriate +% places before actually resizing the underlying box. +% \begin{macrocode} +\cs_new_protected:Npn \@@_resize_common:NnnN #1#2#3#4 + { + \prop_set_eq:Nc \l_@@_corners_prop + { coffin ~ \@@_to_value:N #1 ~ corners } + \prop_set_eq:Nc \l_@@_poles_prop + { coffin ~ \@@_to_value:N #1 ~ poles } + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_scale_corner:Nnnn #1 {##1} ##2 } + \prop_map_inline:Nn \l_@@_poles_prop + { \@@_scale_pole:Nnnnnn #1 {##1} ##2 } +% \end{macrocode} +% Negative $x$-scaling values place the poles in the wrong +% location: this is corrected here. +% \begin{macrocode} + \fp_compare:nNnT \l_@@_scale_x_fp < \c_zero_fp + { + \prop_map_inline:Nn \l_@@_corners_prop + { \@@_x_shift_corner:Nnnn #1 {##1} ##2 } + \prop_map_inline:Nn \l_@@_poles_prop + { \@@_x_shift_pole:Nnnnnn #1 {##1} ##2 } + } + #4 { coffin ~ \@@_to_value:N #1 ~ corners } + \l_@@_corners_prop + #4 { coffin ~ \@@_to_value:N #1 ~ poles } + \l_@@_poles_prop + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \coffin_scale:Nnn, \coffin_scale:cnn, +% \coffin_gscale:Nnn, \coffin_gscale:cnn +% } +% \begin{macro}{\coffin_scale:NnnNN} +% For scaling, the opposite calculation is done to find the new +% dimensions for the coffin. Only the total height is needed, as this +% is the shift required for corners and poles. The scaling is done +% the \TeX{} way as this works properly with floating point values +% without needing to use the \texttt{fp} module. +% \begin{macrocode} +\cs_new_protected:Npn \coffin_scale:Nnn #1#2#3 + { \@@_scale:NnnNN #1 {#2} {#3} \box_scale:Nnn \prop_set_eq:cN } +\cs_generate_variant:Nn \coffin_scale:Nnn { c } +\cs_new_protected:Npn \coffin_gscale:Nnn #1#2#3 + { \@@_scale:NnnNN #1 {#2} {#3} \box_gscale:Nnn \prop_gset_eq:cN } +\cs_generate_variant:Nn \coffin_gscale:Nnn { c } +\cs_new_protected:Npn \@@_scale:NnnNN #1#2#3#4#5 + { + \fp_set:Nn \l_@@_scale_x_fp {#2} + \fp_set:Nn \l_@@_scale_y_fp {#3} + #4 #1 { \l_@@_scale_x_fp } { \l_@@_scale_y_fp } + \dim_set:Nn \l_@@_internal_dim + { \coffin_ht:N #1 + \coffin_dp:N #1 } + \dim_set:Nn \l_@@_scaled_total_height_dim + { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_internal_dim } + \dim_set:Nn \l_@@_scaled_width_dim + { -\fp_abs:n { \l_@@_scale_x_fp } \coffin_wd:N #1 } + \@@_resize_common:NnnN #1 + { \l_@@_scaled_width_dim } { \l_@@_scaled_total_height_dim } + #5 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_scale_vector:nnNN} +% This functions scales a vector from the origin using the pre-set scale +% factors in $x$ and $y$. This is a much less complex operation +% than rotation, and as a result the code is a lot clearer. +% \begin{macrocode} +\cs_new_protected:Npn \@@_scale_vector:nnNN #1#2#3#4 + { + \dim_set:Nn #3 + { \fp_to_dim:n { \dim_to_fp:n {#1} * \l_@@_scale_x_fp } } + \dim_set:Nn #4 + { \fp_to_dim:n { \dim_to_fp:n {#2} * \l_@@_scale_y_fp } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_scale_corner:Nnnn} +% \begin{macro}{\@@_scale_pole:Nnnnnn} +% Scaling both corners and poles is a simple calculation using the +% preceding vector scaling. +% \begin{macrocode} +\cs_new_protected:Npn \@@_scale_corner:Nnnn #1#2#3#4 + { + \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim + \prop_put:Nnx \l_@@_corners_prop {#2} + { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } } + } +\cs_new_protected:Npn \@@_scale_pole:Nnnnnn #1#2#3#4#5#6 + { + \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim + \prop_put:Nnx \l_@@_poles_prop {#2} + { + { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } + {#5} {#6} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_x_shift_corner:Nnnn} +% \begin{macro}{\@@_x_shift_pole:Nnnnnn} +% These functions correct for the $x$ displacement that takes +% place with a negative horizontal scaling. +% \begin{macrocode} +\cs_new_protected:Npn \@@_x_shift_corner:Nnnn #1#2#3#4 + { + \prop_put:Nnx \l_@@_corners_prop {#2} + { + { \dim_eval:n { #3 + \box_wd:N #1 } } {#4} + } + } +\cs_new_protected:Npn \@@_x_shift_pole:Nnnnnn #1#2#3#4#5#6 + { + \prop_put:Nnx \l_@@_poles_prop {#2} + { + { \dim_eval:n { #3 + \box_wd:N #1 } } {#4} + {#5} {#6} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Aligning and typesetting of coffins} % % \begin{macro} @@ -1698,6 +2270,14 @@ % \end{macrocode} % \end{variable} % +% \begin{macro}{\@@_color:n} +% Calls \tn{color}, and otherwise does nothing if \tn{color} is not defined. +% \begin{macrocode} +\cs_new_protected:Npn \@@_color:n #1 + { \cs_if_exist:NT \color { \color {#1} } } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\coffin_mark_handle:Nnnn, \coffin_mark_handle:cnnn} % \begin{macro}{\@@_mark_handle_aux:nnnnNnn} % Marking a single handle is relatively easy. The standard attachment @@ -1714,7 +2294,7 @@ \hbox:n { \tex_vrule:D width 1pt height 1pt \scan_stop: } % TODO %</initex> %<*package> - \color {#4} + \@@_color:n {#4} \rule { 1pt } { 1pt } %</package> } @@ -1726,7 +2306,7 @@ % TODO %</initex> %<*package> - \color {#4} + \@@_color:n {#4} %</package> \l_@@_display_font_tl ( \tl_to_str:n { #2 , #3 } ) @@ -1783,7 +2363,7 @@ \hbox:n { \tex_vrule:D width 1pt height 1pt \scan_stop: } % TODO %</initex> %<*package> - \color {#2} + \@@_color:n {#2} \rule { 1pt } { 1pt } %</package> } @@ -1829,7 +2409,7 @@ % TODO %</initex> %<*package> - \color {#6} + \@@_color:n {#6} %</package> \l_@@_display_font_tl ( \tl_to_str:n { #1 , ##1 } ) |