[latex3-commits] [git/LaTeX3-latex3-latex3] master: First steps in box inclusion in drawings (ec2925e)
Joseph Wright
joseph.wright at morningstar2.co.uk
Sat Mar 3 21:11:39 CET 2018
Repository : https://github.com/latex3/latex3
On branch : master
Link : https://github.com/latex3/latex3/commit/ec2925efd179405fe5a979cd7fb26cc23aba3376
>---------------------------------------------------------------
commit ec2925efd179405fe5a979cd7fb26cc23aba3376
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date: Sat Mar 3 20:11:39 2018 +0000
First steps in box inclusion in drawings
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.
>---------------------------------------------------------------
ec2925efd179405fe5a979cd7fb26cc23aba3376
l3experimental/l3draw/l3draw-scopes.dtx | 76 +++++++++++++++++++++++++++
l3kernel/l3drivers.dtx | 85 ++++++++++++++++---------------
2 files changed, 120 insertions(+), 41 deletions(-)
diff --git a/l3experimental/l3draw/l3draw-scopes.dtx b/l3experimental/l3draw/l3draw-scopes.dtx
index 8e8f949..6cff720 100644
--- a/l3experimental/l3draw/l3draw-scopes.dtx
+++ b/l3experimental/l3draw/l3draw-scopes.dtx
@@ -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}
diff --git a/l3kernel/l3drivers.dtx b/l3kernel/l3drivers.dtx
index b283ff0..fcccf31 100644
--- a/l3kernel/l3drivers.dtx
+++ b/l3kernel/l3drivers.dtx
@@ -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}
@@ -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
@@ -1192,7 +1192,7 @@
{
\fp_compare:nNnTF {#4} = \c_zero_fp
{ 0 }
- { \fp_eval:n { round ( -#1 , 5 ) } } ~
+ { \fp_eval:n { round ( -#4 , 5 ) } } ~
rotate
}
}
@@ -1200,7 +1200,7 @@
% \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
@@ -1210,7 +1210,7 @@
% 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] }
@@ -1218,10 +1218,7 @@
\@@_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:
}
@@ -2091,25 +2088,25 @@
%<*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>
@@ -2117,7 +2114,7 @@
% \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
@@ -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}
@@ -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
@@ -2816,14 +2810,16 @@
% \]
% 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
{
@@ -2831,9 +2827,9 @@
{
\@@_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
}
@@ -2842,10 +2838,10 @@
\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
}
@@ -2853,12 +2849,19 @@
{
\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}
More information about the latex3-commits
mailing list