Skip to content

Commit

Permalink
First steps in box inclusion in drawings
Browse files Browse the repository at this point in the history
In contrast to pgf, we want to do everything using driver-level specials
rather than raw PostScript/PDF. That means that the interfaces need to
be adjusted to avoid using translations at the driver level: these have
to be done in TeX.

There are various corrections to the driver code here.

At present, the SVG path may be completely out-of-line.

Note that some skews seem to mislead dvips/ps2pdf, resulting in entire
pages rotating. That does not seem to be due to 'leaking' rotations, and
is therefore likely down to some auto-detection somewhere.
  • Loading branch information
josephwright committed Mar 3, 2018
1 parent 646cab3 commit ec2925e
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 41 deletions.
76 changes: 76 additions & 0 deletions l3experimental/l3draw/l3draw-scopes.dtx
Expand Up @@ -234,6 +234,82 @@
% \end{macrocode}
% \end{macro}
%
% \subsection{Inserting boxes}
%
% Inserting boxes requires us to \enquote{interrupt} the drawing state,
% so is closely linked to scoping. At the same time, there are a few
% additional features required to make text work in a flexible way.
%
% \begin{variable}{\l_@@_tmp_box}
% \begin{macrocode}
\box_new:N \l_@@_tmp_box
% \end{macrocode}
% \end{variable}
%
% \begin{macro}{\draw_hbox_set:Nn}
% Collect up the input and box, reset all of the structures and typeset.
% Note that in \pkg{pgf} the various reset parts are set up in an auxiliary,
% but this is not done here at present as it is all done only once.
% \begin{macrocode}
\cs_new_protected:Npn \draw_hbox_set:Nn #1#2
{
\hbox_set:Nn #1
{
\color_ensure_current:
\@@_scope_bb_begin:
\draw_path_scope_begin:
\draw_transform_matrix_reset:
\draw_transform_shift_reset:
#2
\draw_path_scope_end:
\@@_scope_bb_end:
}
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\draw_hbox_use:N}
% Before inserting a box, we need to make sure that the bounding box is being
% updated correctly. As drawings track transformations as a whole, rather
% than as separate operations, we do the insertion using an almost-raw
% matrix.
% \begin{macrocode}
\cs_new_protected:Npn \draw_hbox_use:N #1
{
\@@_point_process:nn
{ \@@_path_update_limits:nn }
{ \draw_point_transform:n { 0pt , \box_dp:N #1 } }
\@@_point_process:nn
{ \@@_path_update_limits:nn }
{ \draw_point_transform:n { \box_wd:N #1 , \box_dp:N #1 } }
\@@_point_process:nn
{ \@@_path_update_limits:nn }
{ \draw_point_transform:n { 0pt , \box_ht:N #1 } }
\@@_point_process:nn
{ \@@_path_update_limits:nn }
{ \draw_point_transform:n { \box_wd:N #1 , \box_ht:N #1 } }
\group_begin:
\hbox_set:Nn \l_@@_tmp_box
{
\tex_kern:D \l_@@_xshift_dim
\box_move_up:nn { \l_@@_yshift_dim } { \box_use:N #1 }
}
\box_set_ht:Nn \l_@@_tmp_box { 0pt }
\box_set_dp:Nn \l_@@_tmp_box { 0pt }
\box_set_wd:Nn \l_@@_tmp_box { 0pt }
\use:x
{
\driver_draw_hbox_use:Nnnnn \l_@@_tmp_box
{ \fp_use:N \l_@@_matrix_a_fp }
{ \fp_use:N \l_@@_matrix_b_fp }
{ \fp_use:N \l_@@_matrix_c_fp }
{ \fp_use:N \l_@@_matrix_d_fp }
}
\group_end:
}
% \end{macrocode}
% \end{macro}
%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}
Expand Down
85 changes: 44 additions & 41 deletions l3kernel/l3drivers.dtx
Expand Up @@ -428,7 +428,7 @@
%
% \subsection{Inserting \TeX{} material}
%
% \begin{function}{\driver_draw_hbox:Nnnnnnn}
% \begin{function}{\driver_draw_hbox_use:Nnnnn}
% \begin{syntax}
% \cs{driver_draw_hbox:Nnnnnnn} \meta{box}
% \Arg{a} \Arg{b} \Arg{c} \Arg{d} \Arg{x} \Arg{y}
Expand Down Expand Up @@ -1179,7 +1179,7 @@
{
\fp_compare:nNnTF {#1} = \c_zero_fp
{ 0 }
{ \fp_eval:n { round ( -#1 , 5 ) } } ~
{ \fp_eval:n { round ( -#1, 5 ) } } ~
rotate
}
\@@_draw_literal:n
Expand All @@ -1192,15 +1192,15 @@
{
\fp_compare:nNnTF {#4} = \c_zero_fp
{ 0 }
{ \fp_eval:n { round ( -#1 , 5 ) } } ~
{ \fp_eval:n { round ( -#4 , 5 ) } } ~
rotate
}
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\driver_draw_hbox:Nnnnnnn}
% \begin{macro}{\driver_draw_hbox_use:Nnnnn}
% Inside a picture |@beginspecial|/|@endspecial| are active, which is
% normally a good thing but means that the position and scaling would be off
% if the box was inserted directly. Instead, we need to reverse the effect of
Expand All @@ -1210,18 +1210,15 @@
% drawing origin so has to be done purely in driver code not using \TeX{}
% offsets.
% \begin{macrocode}
\cs_new_protected:Npn \driver_draw_hbox:Nnnnnnn #1#2#3#4#5#6#7
\cs_new_protected:Npn \driver_draw_hbox_use:Nnnnn #1#2#3#4#5
{
\@@_scope_begin:
\@@_draw_literal:n { [end] }
\driver_draw_cm:nnnn {#2} {#3} {#4} {#5}
\@@_draw_literal:n { 72~Resolution~div~72~VResolution~div~neg~scale }
\@@_draw_literal:n { magscale~{1~DVImag~div~dup~scale}~if }
\@@_draw_literal:n { l3x~neg~l3y~neg~translate }
\box_set_wd:Nn #1 { 0pt }
\box_set_ht:Nn #1 { 0pt }
\box_set_dp:Nn #1 { 0pt }
\box_use:N #1
\hbox_overlap_right:n { \box_use:N #1 }
\@@_draw_literal:n { [begin] }
\@@_scope_end:
}
Expand Down Expand Up @@ -2091,33 +2088,33 @@
%<*dvipdfmx|xdvipdfmx>
\cs_new_protected:Npn \@@_draw_cm:nnnn #1#2#3#4
{
\@@_draw_literal:n
\tex_special:D
{
x:rotate~
\fp_compare:nNnTF {#1} = \c_zero_fp
{ 0 }
{ \fp_eval:n { round ( #1 , 5 ) } }
{ \fp_eval:n { round ( -#1 , 5 ) } }
}
\@@_draw_literal:n
\tex_special:D
{
x:scale~
\fp_eval:n { round ( #2 , 5 ) } ~
\fp_eval:n { round ( #3 , 5 ) }
}
\@@_draw_literal:n
\tex_special:D
{
x:rotate~
\fp_compare:nNnTF {#4} = \c_zero_fp
{ 0 }
{ \fp_eval:n { round ( -#1 , 5 ) } }
{ \fp_eval:n { round ( -#4 , 5 ) } }
}
}
%</dvipdfmx|xdvipdfmx>
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\driver_draw_hbox:Nnnnnnn}
% \begin{macro}{\driver_draw_hbox_use:Nnnnn}
% \begin{variable}{\l_@@_tmp_box}
% Inserting a \TeX{} box transformed to the requested position and using
% the current matrix is done using a mixture of \TeX{} and low-level
Expand All @@ -2126,19 +2123,12 @@
% operation can never be cached, the scope is set directly not using the
% \texttt{draw} version.
% \begin{macrocode}
\cs_new_protected:Npn \driver_draw_hbox:Nnnnnnn #1#2#3#4#5#6#7
\cs_new_protected:Npn \driver_draw_hbox_use:Nnnnn #1#2#3#4#5
{
\hbox_set_to_wd:Nnn \l_@@_tmp_box { 0pt }
{
\tex_kern:D \dim_eval:n {#6}
\driver_draw_scope_begin:
\driver_draw_cm:nnnn {#2} {#3} {#4} {#5}
\box_move_up:nn {#7} { \box_use:N #1 }
\driver_draw_scope_end:
}
\box_set_ht:Nn \l_@@_tmp_box { 0pt }
\box_set_dp:Nn \l_@@_tmp_box { 0pt }
\box_use:N \l_@@_tmp_box
\driver_draw_scope_begin:
\driver_draw_cm:nnnn {#2} {#3} {#4} {#5}
\hbox_overlap_right:n { \box_use:N #1 }
\driver_draw_scope_end:
}
\box_new:N \l_@@_tmp_box
% \end{macrocode}
Expand Down Expand Up @@ -2778,7 +2768,11 @@
%
% \begin{macro}{\@@_draw_cm_decompose:nnnnN}
% \begin{macro}
% {\@@_draw_cm_decompose_auxi:nnnnN, \@@_draw_cm_decompose_auxii:nnnnN}
% {
% \@@_draw_cm_decompose_auxi:nnnnN,
% \@@_draw_cm_decompose_auxii:nnnnN,
% \@@_draw_cm_decompose_auxiii:nnnnN,
% }
% Internally, transformations for drawing are tracked as a matrix. Not all
% engines provide a way of dealing with this: if we use a raw matrix, the
% engine looses track of positions (for example for hyperlinks), and this is
Expand Down Expand Up @@ -2816,24 +2810,26 @@
% \]
% From these, we can find that
% \begin{align*}
% \frac{w_{1} + w_{2}}{1} &= \sqrt{E^{2} + H^{2}} \\
% \frac{w_{1} - w_{2}}{1} &= \sqrt{F^{2} + G^{2}} \\
% \frac{w_{1} + w_{2}}{2} &= \sqrt{E^{2} + H^{2}} \\
% \frac{w_{1} - w_{2}}{2} &= \sqrt{F^{2} + G^{2}} \\
% \gamma - \beta &= \tan^{-1}(G/F) \\
% \gamma + \beta &= \tan^{-1}(H/E)
% \end{align*}
% at which point we just have to do various pieces of re-arrangement to
% get all of the values. (See J.~Blinn, \emph{IEEE Comput.\ Graph.\ Appl.},
% 1996, \textbf{16}, 82--88.)
% 1996, \textbf{16}, 82--88.) There is one wrinkle: the PostScript (and PDF)
% way of specifying a transformation matrix exchanges where one would
% normally expect $B$ and $C$ to be.
% \begin{macrocode}
\cs_new_protected:Npn \@@_draw_cm_decompose:nnnnN #1#2#3#4#5
{
\use:x
{
\@@_draw_cm_decompose_auxi:nnnnN
{ \fp_eval:n { (#1 + #4) / 2 } }
{ \fp_eval:n { #1 - (#1 + #4) / 2 } }
{ \fp_eval:n { (#2 + #3) / 2 } }
{ \fp_eval:n { #2 - (#2 + #3) / 2 } }
{ \fp_eval:n { (#1 - #4) / 2 } }
{ \fp_eval:n { (#3 + #2) / 2 } }
{ \fp_eval:n { (#3 - #2) / 2 } }
}
#5
}
Expand All @@ -2842,23 +2838,30 @@
\use:x
{
\@@_draw_cm_decompose_auxii:nnnnN
{ \fp_eval:n { sqrt ( #1 * #1 + #4 * #4 ) } }
{ \fp_eval:n { sqrt ( #2 * #2 + #3 * #3 ) } }
{ \fp_eval:n { atand ( #3 / #2 ) } }
{ \fp_eval:n { atand ( #4 / #1 ) } }
{ \fp_eval:n { 2 * sqrt ( #1 * #1 + #4 * #4 ) } }
{ \fp_eval:n { 2 * sqrt ( #2 * #2 + #3 * #3 ) } }
{ \fp_eval:n { atand ( #3 , #2 ) } }
{ \fp_eval:n { atand ( #4 , #1 ) } }
}
#5
}
\cs_new_protected:Npn \@@_draw_cm_decompose_auxii:nnnnN #1#2#3#4#5
{
\use:x
{
\exp_not:N #5
\@@_draw_cm_decompose_auxiii:nnnnN
{ \fp_eval:n { ( #4 - #3 ) / 2 } }
{ \fp_eval:n { #1 + #2 } }
{ \fp_eval:n { #1 - #2 } }
{ \fp_eval:n { ( #1 + #2 ) / 2 } }
{ \fp_eval:n { ( #1 - #2 ) / 2 } }
{ \fp_eval:n { ( #4 + #3 ) / 2 } }
}
#5
}
\cs_new_protected:Npn \@@_draw_cm_decompose_auxiii:nnnnN #1#2#3#4#5
{
\fp_compare:nNnTF { abs( #2 ) } > { abs ( #3 ) }
{ #5 {#1} {#2} {#3} {#4} }
{ #5 {#1} {#3} {#2} {#4} }
}
% \end{macrocode}
% \end{macro}
Expand Down

0 comments on commit ec2925e

Please sign in to comment.