diff options
Diffstat (limited to 'Master/texmf-dist/source/latex')
67 files changed, 2400 insertions, 1028 deletions
diff --git a/Master/texmf-dist/source/latex/l3experimental/l3color/l3color.dtx b/Master/texmf-dist/source/latex/l3experimental/l3color/l3color.dtx index f00c047afff..68eaa14452d 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3color/l3color.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3color/l3color.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -263,7 +263,7 @@ % % \begin{macrocode} %<*package> -\ProvidesExplPackage{l3color}{2018/02/21}{} +\ProvidesExplPackage{l3color}{2018/03/05}{} {L3 Experimental color support} %</package> % \end{macrocode} @@ -445,6 +445,10 @@ % \begin{macrocode} \cs_new_protected:Npn \color_parse:nN #1#2 { +%<*package> + \driver_color_pickup:N \l_@@_current_tl + \tl_set_eq:cN { l_@@_named_ . _tl } \l_@@_current_tl +%</package> \group_begin: \seq_map_inline:Nn \l_char_active_seq { @@ -465,6 +469,7 @@ \tl_if_exist:cTF { l_@@_named_ #1 _tl } { \tl_set_eq:Nc #2 { l_@@_named_ #1 _tl } } { \@@_parse:Nw #2#1 ! \q_stop } + \@@_check_model:N #2 } \cs_new_protected:Npn \@@_parse:Nw #1#2 ! #3 \q_stop { @@ -651,25 +656,15 @@ % \end{macrocode} % \end{variable} % -% \begin{macro}{\@@_select:} -% \begin{macro}{\@@_finalise:N} -% \begin{macro}{\@@_finalise:w} -% A driver-neutral location for \enquote{last minute} manipulations before -% handing off to the driver code. We set the special |.| syntax here: this -% will therefore always be available. The finalisation is separate from the -% main function so it can also be applied to \emph{e.g.}~page color. +% \begin{macro}{\@@_check_model:N} +% \begin{macro}{\@@_check_model:w} +% Check that the model in use is the one required. % \begin{macrocode} -\cs_new_protected:Npn \@@_select: - { - \@@_finalise:N \l_@@_current_tl - \tl_set_eq:cN { l_@@_named_ . _tl } \l_@@_current_tl - \@@_select:V \l_@@_current_tl - } -\cs_new_protected:Npn \@@_finalise:N #1 +\cs_new_protected:Npn \@@_check_model:N #1 { \tl_if_empty:NF \l_color_fixed_model_tl { - \exp_after:wN \@@_finalise:w #1 \q_stop + \exp_after:wN \@@_check_model:w #1 \q_stop \tl_if_eq:NNF \l_@@_model_tl \l_color_fixed_model_tl { \@@_convert:VVN \l_@@_model_tl \l_color_fixed_model_tl @@ -679,7 +674,7 @@ { \l_color_fixed_model_tl \c_space_tl \l_@@_value_tl } } } -\cs_new_protected:Npn \@@_finalise:w #1 ~ #2 \q_stop +\cs_new_protected:Npn \@@_check_model:w #1 ~ #2 \q_stop { \tl_set:Nn \l_@@_model_tl {#1} \tl_set:Nn \l_@@_value_tl {#2} @@ -688,6 +683,20 @@ % \end{macro} % \end{macro} % +% \begin{macro}{\@@_select:} +% A driver-neutral location for \enquote{last minute} manipulations before +% handing off to the driver code. We set the special |.| syntax here: this +% will therefore always be available. The finalisation is separate from the +% main function so it can also be applied to \emph{e.g.}~page color. +% \begin{macrocode} +\cs_new_protected:Npn \@@_select: + { + \tl_set_eq:cN { l_@@_named_ . _tl } \l_@@_current_tl + \@@_select:V \l_@@_current_tl + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\color_select:n} % \begin{macro}{\color_select:nn} % Parse the input expressions then get the driver to actually activate @@ -718,6 +727,7 @@ { \tl_set:Nx #3 { #1 ~ \use:c { @@_parse_ #1 :w } #2 , 0 , 0 , 0 , 0 \q_stop } + \@@_check_model:N #3 } { \__kernel_msg_error:nnn { color } { invalid-model } {#1} @@ -803,6 +813,7 @@ % definition. % \begin{macrocode} \tl_new:c { l_@@_named_._tl } +\tl_set_eq:cN { l_@@_named_._tl } \l_@@_current_tl % \end{macrocode} % \end{variable} % diff --git a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-boxes.dtx b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-boxes.dtx new file mode 100644 index 00000000000..0cfd7239da9 --- /dev/null +++ b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-boxes.dtx @@ -0,0 +1,153 @@ +% \iffalse meta-comment +% +%% File: l3draw-boxes.dtx Copyright(C) 2018 The LaTeX3 Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% http://www.latex-project.org/lppl.txt +% +% This file is part of the "l3experimental bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/latex3/latex3 +% +% for those people who are interested. +% +%<*driver> +\RequirePackage{expl3} +\documentclass[full]{l3doc} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{^^A +% The \pkg{l3draw} package\\ Boxes in drawings^^A +% } +% +% \author{^^A +% The \LaTeX3 Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Released 2018/03/05} +% +% \maketitle +% +% \begin{implementation} +% +% \section{\pkg{l3draw-boxes} implementation} +% +% \begin{macrocode} +%<*initex|package> +% \end{macrocode} +% +% \begin{macrocode} +%<@@=draw> +% \end{macrocode} +% +% 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_box_use:N} +% \begin{macro}{\@@_box_use:Nnnnn} +% 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. The process is split into two so that coffins are also supported. +% \begin{macrocode} +\cs_new_protected:Npn \draw_box_use:N #1 + { + \@@_box_use:Nnnnn #1 + { 0pt } { -\box_dp:N #1 } { \box_wd:N #1 } { \box_ht:N #1 } + } +\cs_new_protected:Npn \@@_box_use:Nnnnn #1#2#3#4#5 + { + \bool_if:NT \l_draw_bb_update_bool + { + \@@_point_process:nn + { \@@_path_update_limits:nn } + { \draw_point_transform:n { #2 , #3 } } + \@@_point_process:nn + { \@@_path_update_limits:nn } + { \draw_point_transform:n { #4 , #3 } } + \@@_point_process:nn + { \@@_path_update_limits:nn } + { \draw_point_transform:n { #4 , #5 } } + \@@_point_process:nn + { \@@_path_update_limits:nn } + { \draw_point_transform:n { #2 , #5 } } + } + \group_begin: + \hbox_set:Nn \l_@@_tmp_box + { + \use:x + { + \driver_draw_box_use:Nnnnn #1 + { \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 } + } + } + \hbox_set:Nn \l_@@_tmp_box + { + \tex_kern:D \l_@@_xshift_dim + \box_move_up:nn { \l_@@_yshift_dim } + { \box_use_drop:N \l_@@_tmp_box } + } + \box_set_ht:Nn \l_@@_tmp_box { 0pt } + \box_set_dp:Nn \l_@@_tmp_box { 0pt } + \box_set_wd:Nn \l_@@_tmp_box { 0pt } + \box_use_drop:N \l_@@_tmp_box + \group_end: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\draw_coffin_use:Nnn} +% Slightly more than a shortcut: we have to allow for the fact that coffins +% have no apparent width before the reference point. +% \begin{macrocode} +\cs_new_protected:Npn \draw_coffin_use:Nnn #1#2#3 + { + \group_begin: + \hbox_set:Nn \l_@@_tmp_box + { \coffin_typeset:Nnnnn #1 {#2} {#3} { 0pt } { 0pt } } + \@@_box_use:Nnnnn \l_@@_tmp_box + { \box_wd:N \l_@@_tmp_box - \coffin_wd:N #1 } + { -\box_dp:N \l_@@_tmp_box } + { \box_wd:N \l_@@_tmp_box } + { \box_ht:N \l_@@_tmp_box } + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</initex|package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-paths.dtx b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-paths.dtx index 2fa882e7f1a..09df8391d17 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-paths.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-paths.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -128,7 +128,7 @@ { \dim_max:nn \g_@@_path_ymax_dim {#2} } \dim_gset:Nn \g_@@_path_ymin_dim { \dim_min:nn \g_@@_path_ymin_dim {#2} } - \bool_if:NT \l_@@_update_bb_bool + \bool_if:NT \l_draw_bb_update_bool { \dim_gset:Nn \g_@@_xmax_dim { \dim_max:nn \g_@@_xmax_dim {#1} } @@ -185,15 +185,10 @@ % \end{macrocode} % \end{variable} % -% \begin{macro}{\draw_path_corner_arc:n} -% \begin{macro}{\@@_path_corner_arc:nn} +% \begin{macro}{\draw_path_corner_arc:nn} % Calculate the arcs, check they are non-zero. % \begin{macrocode} -\cs_new_protected:Npn \draw_path_corner_arc:n #1 - { - \@@_point_process:nn { \@@_path_corner_arc:nn } {#1} - } -\cs_new_protected:Npn \@@_path_corner_arc:nn #1#2 +\cs_new_protected:Npn \draw_path_corner_arc:nn #1#2 { \dim_set:Nn \l_@@_corner_xarc_dim {#1} \dim_set:Nn \l_@@_corner_yarc_dim {#2} @@ -205,7 +200,6 @@ } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro}{\@@_path_mark_corner:} % Mark up corners for arc post-processing. @@ -295,6 +289,33 @@ % \end{macrocode} % \end{macro} % +% \subsection{Canvas path constructions} +% +% \begin{macro}{\draw_path_canvas_moveto:n, \draw_path_canvas_lineto:n} +% \begin{macro}{\draw_path_canvas_curveto:nnn} +% Operations with no application of the transformation matrix. +% \begin{macrocode} +\cs_new_protected:Npn \draw_path_canvas_moveto:n #1 + { \@@_point_process:nn { \@@_path_moveto:nn } {#1} } +\cs_new_protected:Npn \draw_path_canvas_lineto:n #1 + { \@@_point_process:nn { \@@_path_lineto:nn } {#1} } +\cs_new_protected:Npn \draw_path_canvas_curveto:nnn #1#2#3 + { + \@@_point_process:nnn + { + \@@_point_process:nn + { + \@@_path_mark_corner: + \@@_path_curveto:nnnnnn + } + {#1} + } + {#2} {#3} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \subsection{Computed curves} % % More complex operations need some calculations. To assist with those, various @@ -690,7 +711,9 @@ { \@@_point_process:nnn { - \bool_if:NTF \l_@@_corner_arc_bool + \bool_lazy_or:nnTF + { \l_@@_corner_arc_bool } + { \l_@@_matrix_active_bool } { \@@_path_rectangle_rounded:nnnn } { \@@_path_rectangle:nnnn } } @@ -736,33 +759,71 @@ % \subsection{Grids} % % \begin{macro}{\draw_path_grid:nnnn} -% \begin{macro}{\@@_path_grid:nnnnnn} -% A simple set of loops. +% \begin{macro} +% { +% \@@_path_grid_auxi:nnnnnn, \@@_path_grid_auxi:ffnnnn, +% \@@_path_grid_auxii:nnnnnn, +% \@@_path_grid_auxiii:nnnnnn, \@@_path_grid_auxiiii:ffnnnn +% } +% \begin{macro} +% {\@@_path_grid_auxiv:nnnnnnnn, \@@_path_grid_auxiv:ffnnnnnn} +% The main complexity here is lining up the grid correctly. +% To keep it simple, we tidy up the argument ordering first. % \begin{macrocode} \cs_new_protected:Npn \draw_path_grid:nnnn #1#2#3#4 { \@@_point_process:nnn - { \@@_path_grid:nnnnnn {#1} {#2} } + { + \@@_path_grid_auxi:ffnnnn + { \dim_eval:n { \dim_abs:n {#1} } } + { \dim_eval:n { \dim_abs:n {#2} } } + } {#3} {#4} } -\cs_new_protected:Npn \@@_path_grid:nnnnnn #1#2#3#4#5#6 +\cs_new_protected:Npn \@@_path_grid_auxi:nnnnnn #1#2#3#4#5#6 + { + \dim_compare:nNnTF {#3} > {#5} + { \@@_path_grid_auxii:nnnnnn {#1} {#2} {#5} {#4} {#3} {#6} } + { \@@_path_grid_auxii:nnnnnn {#1} {#2} {#3} {#4} {#5} {#6} } + } +\cs_generate_variant:Nn \@@_path_grid_auxi:nnnnnn { ff } +\cs_new_protected:Npn \@@_path_grid_auxii:nnnnnn #1#2#3#4#5#6 + { + \dim_compare:nNnTF {#4} > {#6} + { \@@_path_grid_auxiii:nnnnnn {#1} {#2} {#3} {#6} {#5} {#4} } + { \@@_path_grid_auxiii:nnnnnn {#1} {#2} {#3} {#4} {#5} {#6} } + } +\cs_new_protected:Npn \@@_path_grid_auxiii:nnnnnn #1#2#3#4#5#6 + { + \@@_path_grid_auxiv:ffnnnnnn + { \fp_to_dim:n { #1 * trunc(#3/(#1)) } } + { \fp_to_dim:n { #2 * trunc(#4/(#2)) } } + {#1} {#2} {#3} {#4} {#5} {#6} + } +\cs_new_protected:Npn \@@_path_grid_auxiv:nnnnnnnn #1#2#3#4#5#6#7#8 { \dim_step_inline:nnnn - {#3} { \dim_compare:nNnF {#3} < {#5} { - } \dim_abs:n {#1} } {#5} + {#1} + {#3} + {#7} { - \draw_path_moveto:n { ##1 , #4 } - \draw_path_lineto:n { ##1 , #6 } + \draw_path_moveto:n { ##1 , #6 } + \draw_path_lineto:n { ##1 , #8 } } \dim_step_inline:nnnn - {#4} { \dim_compare:nNnF {#4} < {#6} { - } \dim_abs:n {#2} } {#6} + {#2} + {#4} + {#8} { - \draw_path_moveto:n { #3 , ##1 } - \draw_path_lineto:n { #5 , ##1 } + \draw_path_moveto:n { #5 , ##1 } + \draw_path_lineto:n { #7 , ##1 } } } +\cs_generate_variant:Nn \@@_path_grid_auxiv:nnnnnnnn { ff } % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % \subsection{Using paths} % @@ -790,7 +851,7 @@ % % \begin{macro}{\draw_path_use:n, \draw_path_use_clear:n} % \begin{macro}{\@@_path_use:n} -% \begin{macro}{\@@_path_use_action_draw:} +% \begin{macro}{\@@_path_use_action_draw:, \@@_path_use_action_fillstroke:} % \begin{macro}{\@@_path_use_stroke_bb:} % \begin{macro}{\@@_path_use_stroke_bb_aux:NnN} % There are a range of actions which can apply to a path: they are handled @@ -833,8 +894,9 @@ { \ERROR } } } + \@@_softpath_round_corners: \bool_lazy_and:nnT - { \l_@@_update_bb_bool } + { \l_draw_bb_update_bool } { \l_@@_path_use_stroke_bool } { \@@_path_use_stroke_bb: } \bool_if:NTF \l_@@_path_use_clear_bool @@ -859,6 +921,11 @@ { \bool_set_true:N \l_@@_path_use_stroke_bool } +\cs_new_protected:Npn \@@_path_use_action_fillstroke: + { + \bool_set_true:N \l_@@_path_use_fill_bool + \bool_set_true:N \l_@@_path_use_stroke_bool + } % \end{macrocode} % Where the path is relevant to size and is stroked, we need to allow for % the part which overlaps the edge of the bounding box. @@ -892,6 +959,75 @@ % \end{macro} % \end{macro} % +% \subsection{Scoping paths} +% +% \begin{variable} +% { +% \l_@@_path_lastx_dim, \l_@@_path_lasty_dim, +% \l_@@_path_xmax_dim, \l_@@_path_xmin_dim, +% \l_@@_path_ymax_dim, \l_@@_path_ymin_dim +% } +% \begin{variable}{\l_@@_softpath_corners_bool} +% Local storage for global data. There is already a +% \cs{l_@@_softpath_main_tl} for path manipulation, so we can reuse that +% (it is always grouped when the path is being reconstructed). +% \begin{macrocode} +\dim_new:N \l_@@_path_lastx_dim +\dim_new:N \l_@@_path_lasty_dim +\dim_new:N \l_@@_path_xmax_dim +\dim_new:N \l_@@_path_xmin_dim +\dim_new:N \l_@@_path_ymax_dim +\dim_new:N \l_@@_path_ymin_dim +\dim_new:N \l_@@_softpath_lastx_dim +\dim_new:N \l_@@_softpath_lasty_dim +\bool_new:N \l_@@_softpath_corners_bool +% \end{macrocode} +% \end{variable} +% \end{variable} +% +% \begin{macro}{\draw_path_scope_begin:, \draw_path_scope_end:} +% Scoping a path is a bit more involved, largely as there are a number +% of variables to keep hold of. +% \begin{macrocode} +\cs_new_protected:Npn \draw_path_scope_begin: + { + \group_begin: + \dim_set_eq:NN \l_@@_path_lastx_dim \g_@@_path_lastx_dim + \dim_set_eq:NN \l_@@_path_lasty_dim \g_@@_path_lasty_dim + \dim_set_eq:NN \l_@@_path_xmax_dim \g_@@_path_xmax_dim + \dim_set_eq:NN \l_@@_path_xmin_dim \g_@@_path_xmin_dim + \dim_set_eq:NN \l_@@_path_ymax_dim \g_@@_path_ymax_dim + \dim_set_eq:NN \l_@@_path_ymin_dim \g_@@_path_ymin_dim + \dim_set_eq:NN \l_@@_softpath_lastx_dim \g_@@_softpath_lastx_dim + \dim_set_eq:NN \l_@@_softpath_lasty_dim \g_@@_softpath_lasty_dim + \@@_path_reset_limits: + \@@_softpath_concat:n { } + \tl_set_eq:NN \l_@@_softpath_main_tl \g_@@_softpath_main_tl + \bool_set_eq:NN + \l_@@_softpath_corners_bool + \g_@@_softpath_corners_bool + \@@_softpath_clear: + } +\cs_new_protected:Npn \draw_path_scope_end: + { + \bool_gset_eq:NN + \g_@@_softpath_corners_bool + \l_@@_softpath_corners_bool + \@@_softpath_clear: + \tl_gset_eq:NN \g_@@_softpath_main_tl \l_@@_softpath_main_tl + \dim_gset_eq:NN \g_@@_softpath_lastx_dim \l_@@_softpath_lastx_dim + \dim_gset_eq:NN \g_@@_softpath_lasty_dim \l_@@_softpath_lasty_dim + \dim_gset_eq:NN \g_@@_path_xmax_dim \l_@@_path_xmax_dim + \dim_gset_eq:NN \g_@@_path_xmin_dim \l_@@_path_xmin_dim + \dim_gset_eq:NN \g_@@_path_ymax_dim \l_@@_path_ymax_dim + \dim_gset_eq:NN \g_@@_path_ymin_dim \l_@@_path_ymin_dim + \dim_gset_eq:NN \g_@@_path_lastx_dim \l_@@_path_lastx_dim + \dim_gset_eq:NN \g_@@_path_lasty_dim \l_@@_path_lasty_dim + \group_end: + } +% \end{macrocode} +% \end{macro} +% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-points.dtx b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-points.dtx index 01497992889..69ca8b6ae73 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-points.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-points.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -485,39 +485,31 @@ % \begin{macro}[EXP]{\@@_point_interpolate_distance:nnnnn} % \begin{macro}[EXP] % { -% \@@_point_interpolate_distance_aux:nnnnnnn, -% \@@_point_interpolate_distance_aux:nnnnnnn, -% } -% \begin{macro}[EXP] -% { -% \@@_point_interpolate_distance_aux:nnnnnn, -% \@@_point_interpolate_distance_aux:fnnnnn, +% \@@_point_interpolate_distance:nnnnnn, +% \@@_point_interpolate_distance:fnnnnn, % } % Same idea but using the normalised length to obtain the scale factor. +% The start point is needed twice, so we force evaluation, but the end +% point is needed only the once. % \begin{macrocode} \cs_new:Npn \draw_point_interpolate_distance:nnn #1#2#3 { - \@@_point_process:nnn - { \@@_point_interpolate_distance:nnnnn {#1} } - {#2} {#3} - } -\cs_new:Npn \@@_point_interpolate_distance:nnnnn #1#2#3#4#5 - { - \@@_point_interpolate_distance_aux:nnnnnnn - { \fp_eval:n { #4 - #2 } } - { \fp_eval:n { #5 - #3 } } - {#2} {#3} {#4} {#5} {#1} + \@@_point_process:nn + { \@@_point_interpolate_distance:nnnn {#1} {#3} } + {#2} } -\cs_new:Npn \@@_point_interpolate_distance_aux:nnnnnnn #1#2#3#4#5#6#7 +\cs_new:Npn \@@_point_interpolate_distance:nnnn #1#2#3#4 { - \@@_point_interpolate_distance_aux:fnnnn - { \fp_eval:n { (#7) / (sqrt ( #1 * #1 + #2 * #2 )) } } - {#3} {#4} {#5} {#6} + \@@_point_process:nn + { + \@@_point_interpolate_distance:fnnnn + { \fp_eval:n {#1} } {#3} {#4} + } + { \draw_point_unit_vector:n { ( #2 ) - ( #3 , #4 ) } } } -\cs_generate_variant:Nn \@@_point_interpolate_distance_aux:nnnnnnn { ff } -\cs_new:Npn \@@_point_interpolate_distance_aux:nnnnn #1#2#3#4#5 +\cs_new:Npn \@@_point_interpolate_distance:nnnnn #1#2#3#4#5 { \@@_point_to_dim:n { #2 + #1 * #4 , #3 + #1 * #5 } } -\cs_generate_variant:Nn \@@_point_interpolate_distance_aux:nnnnn { f } +\cs_generate_variant:Nn \@@_point_interpolate_distance:nnnnn { f } % \end{macrocode} % \end{macro} % \end{macro} @@ -605,7 +597,6 @@ % \end{macro} % \end{macro} % \end{macro} -% \end{macro} % % \begin{macro}[EXP]{\draw_point_interpolate_curve:nnnnn} % \begin{macro}[EXP]{\draw_point_interpolate_curve_auxi:nnnnnnnnn} @@ -889,20 +880,20 @@ } \cs_new:Npn \@@_point_transform:nn #1#2 { - \bool_if:NTF \l_@@_transformcm_active_bool + \bool_if:NTF \l_@@_matrix_active_bool { \@@_point_to_dim:n { ( - \l_@@_transformcm_aa_fp * #1 - + \l_@@_transformcm_ba_fp * #2 - + \l_@@_transformcm_xshift_dim + \l_@@_matrix_a_fp * #1 + + \l_@@_matrix_c_fp * #2 + + \l_@@_xshift_dim ) , ( - \l_@@_transformcm_ab_fp * #1 - + \l_@@_transformcm_bb_fp * #2 - + \l_@@_transformcm_yshift_dim + \l_@@_matrix_b_fp * #1 + + \l_@@_matrix_d_fp * #2 + + \l_@@_yshift_dim ) } } @@ -910,8 +901,7 @@ \@@_point_to_dim:n { (#1, #2) - + ( \l_@@_transformcm_xshift_dim , - \l_@@_transformcm_yshift_dim ) + + ( \l_@@_xshift_dim , \l_@@_yshift_dim ) } } } @@ -930,18 +920,18 @@ } \cs_new:Npn \@@_point_transform_noshift:nn #1#2 { - \bool_if:NTF \l_@@_transformcm_active_bool + \bool_if:NTF \l_@@_matrix_active_bool { \@@_point_to_dim:n { ( - \l_@@_transformcm_aa_fp * #1 - + \l_@@_transformcm_ba_fp * #2 + \l_@@_matrix_a_fp * #1 + + \l_@@_matrix_c_fp * #2 ) , ( - \l_@@_transformcm_ab_fp * #1 - + \l_@@_transformcm_bb_fp * #2 + \l_@@_matrix_b_fp * #1 + + \l_@@_matrix_d_fp * #2 ) } } diff --git a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-scopes.dtx b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-scopes.dtx index b87a6a152b7..451226ccdef 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-scopes.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-scopes.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -72,11 +72,11 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_update_bb_bool} +% \begin{variable}{\l_draw_bb_update_bool} % Flag to indicate that a path (or similar) should update the bounding box % of the drawing. % \begin{macrocode} -\bool_new:N \l_@@_update_bb_bool +\bool_new:N \l_draw_bb_update_bool % \end{macrocode} % \end{variable} % @@ -87,47 +87,161 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\g_@@_id_int} +% The drawing number. +% \begin{macrocode} +\int_new:N \g_@@_id_int +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_reset_bb:} +% A simple auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_reset_bb: + { + \dim_gset:Nn \g_@@_xmax_dim { -\c_max_dim } + \dim_gset:Nn \g_@@_xmin_dim { \c_max_dim } + \dim_gset:Nn \g_@@_ymax_dim { -\c_max_dim } + \dim_gset:Nn \g_@@_ymin_dim { \c_max_dim } + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\draw_begin:, \draw_end:} % Drawings are created by setting them into a box, then adjusting the box -% before inserting into the surroundings. At present the content is simply -% collected then dumped: work will be required to manipulate the size as -% this data becomes more defined. It may be that a coffin construct is -% better here in the longer term: that may become clearer as the code is -% completed. Another obvious question is whether/where vertical mode should -% be ended (\emph{i.e.}~should this behave like a raw |\vbox| or like -% a coffin). In contrast to \pkg{pgf}, we use a vertical box here: material -% between explicit instructions should not be present anyway. (Consider -% adding an |\everypar| hook as done for the \LaTeXe{} preamble.) +% before inserting into the surroundings. Color is set here using the drawing +% mechanism largely as it then sets up the internal data structures. It may be +% that a coffin construct is better here in the longer term: that may become +% clearer as the code is completed. As we need to avoid any insertion of +% baseline skips, the outer box here has to be an |hbox|. % \begin{macrocode} \cs_new_protected:Npn \draw_begin: { - \vbox_set:Nw \l_@@_main_box - \driver_draw_begin: - \dim_gset:Nn \g_@@_xmax_dim { -\c_max_dim } - \dim_gset:Nn \g_@@_xmin_dim { \c_max_dim } - \dim_gset:Nn \g_@@_ymax_dim { -\c_max_dim } - \dim_gset:Nn \g_@@_ymin_dim { \c_max_dim } - \bool_set_true:N \l_@@_update_bb_bool - \draw_transform_reset: - \draw_linewidth:n { \l_draw_default_linewidth_dim } + \group_begin: + \int_gincr:N \g_@@_id_int + \hbox_set:Nw \l_@@_main_box + \driver_draw_begin: + \@@_reset_bb: + \@@_path_reset_limits: + \bool_set_true:N \l_draw_bb_update_bool + \draw_transform_matrix_reset: + \draw_transform_shift_reset: + \@@_softpath_clear: + \draw_linewidth:n { \l_draw_default_linewidth_dim } + \draw_color:n { . } } \cs_new_protected:Npn \draw_end: { - \driver_draw_end: - \vbox_set_end: - \hbox_set:Nn \l_@@_main_box - { - \skip_horizontal:n { -\g_@@_xmin_dim } - \box_move_down:nn { \g_@@_ymin_dim } - { \box_use_drop:N \l_@@_main_box } - } - \box_set_ht:Nn \l_@@_main_box - { \g_@@_ymax_dim - \g_@@_ymin_dim } - \box_set_dp:Nn \l_@@_main_box { 0pt } - \box_set_wd:Nn \l_@@_main_box - { \g_@@_xmax_dim - \g_@@_xmin_dim } - \mode_leave_vertical: - \box_use_drop:N \l_@@_main_box + \driver_draw_end: + \hbox_set_end: + \dim_compare:nNnT \g_@@_xmin_dim = \c_max_dim + { + \dim_gzero:N \g_@@_xmax_dim + \dim_gzero:N \g_@@_xmin_dim + \dim_gzero:N \g_@@_ymax_dim + \dim_gzero:N \g_@@_ymin_dim + } + \hbox_set:Nn \l_@@_main_box + { + \skip_horizontal:n { -\g_@@_xmin_dim } + \box_move_down:nn { \g_@@_ymin_dim } + { \box_use_drop:N \l_@@_main_box } + } + \box_set_ht:Nn \l_@@_main_box + { \g_@@_ymax_dim - \g_@@_ymin_dim } + \box_set_dp:Nn \l_@@_main_box { 0pt } + \box_set_wd:Nn \l_@@_main_box + { \g_@@_xmax_dim - \g_@@_xmin_dim } + \mode_leave_vertical: + \box_use_drop:N \l_@@_main_box + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Scopes} +% +% \begin{variable}{\l_@@_linewidth_dim} +% \begin{variable}{\l_@@_fill_color_tl, \l_@@_stroke_color_tl} +% Storage for local variables. +% \begin{macrocode} +\dim_new:N \l_@@_linewidth_dim +\tl_new:N \l_@@_fill_color_tl +\tl_new:N \l_@@_stroke_color_tl +% \end{macrocode} +% \end{variable} +% \end{variable} +% +% \begin{macro}{\draw_scope_begin:, \draw_scope_begin:} +% As well as the graphics (and \TeX{}) scope, also deal with global +% data structures. +% \begin{macrocode} +\cs_new_protected:Npn \draw_scope_begin: + { + \driver_draw_scope_begin: + \group_begin: + \dim_set_eq:NN \l_@@_linewidth_dim \g_@@_linewidth_dim + \draw_path_scope_begin: + } +\cs_new_protected:Npn \draw_scope_end: + { + \draw_path_scope_end: + \dim_gset_eq:NN \g_@@_linewidth_dim \l_@@_linewidth_dim + \group_end: + \driver_draw_scope_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{variable} +% {\l_@@_xmax_dim, \l_@@_xmin_dim, \l_@@_ymax_dim, \l_@@_ymin_dim} +% Storage for the bounding box. +% \begin{macrocode} +\dim_new:N \l_@@_xmax_dim +\dim_new:N \l_@@_xmin_dim +\dim_new:N \l_@@_ymax_dim +\dim_new:N \l_@@_ymin_dim +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_scope_bb_begin:, \@@_scope_bb_end:} +% The bounding box is simple: a straight group-based save and restore +% approach. +% \begin{macrocode} +\cs_new_protected:Npn \@@_scope_bb_begin: + { + \group_begin: + \dim_set_eq:NN \l_@@_xmax_dim \g_@@_xmax_dim + \dim_set_eq:NN \l_@@_xmin_dim \g_@@_xmin_dim + \dim_set_eq:NN \l_@@_ymax_dim \g_@@_ymax_dim + \dim_set_eq:NN \l_@@_ymin_dim \g_@@_ymin_dim + \@@_reset_bb: + } +\cs_new_protected:Npn \@@_scope_bb_end: + { + \dim_gset_eq:NN \g_@@_xmax_dim \l_@@_xmax_dim + \dim_gset_eq:NN \g_@@_xmin_dim \l_@@_xmin_dim + \dim_gset_eq:NN \g_@@_ymax_dim \l_@@_ymax_dim + \dim_gset_eq:NN \g_@@_ymin_dim \l_@@_ymin_dim + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\draw_suspend_begin:, \draw_suspend_end:} +% Suspend all parts of a drawing. +% \begin{macrocode} +\cs_new_protected:Npn \draw_suspend_begin: + { + \@@_scope_bb_begin: + \draw_path_scope_begin: + \draw_transform_matrix_reset: + \draw_transform_shift_reset: + } +\cs_new_protected:Npn \draw_suspend_end: + { + \draw_path_scope_end: + \@@_scope_bb_end: } % \end{macrocode} % \end{macro} diff --git a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-softpath.dtx b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-softpath.dtx index f10d7928082..f98083584bd 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-softpath.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-softpath.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -58,6 +58,8 @@ %<@@=draw> % \end{macrocode} % +% \subsection{Managing soft paths} +% % There are two linked aims in the code here. The most significant is to % provide a way to modify paths, for example to shorten the ends or round % the corners. This means that the path cannot be written piecemeal as @@ -100,6 +102,13 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\g_@@_softpath_corners_bool} +% Allow for optimised path use. +% \begin{macrocode} +\bool_new:N \g_@@_softpath_corners_bool +% \end{macrocode} +% \end{variable} +% % \begin{macro}{\@@_softpath_add:n, \@@_softpath_add:x} % \begin{macro}{\@@_softpath_concat:n} % \begin{macro}{\@@_softpath_reset_buffers:} @@ -155,22 +164,6 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\@@_softpath_get:N, \@@_softpath_set_eq:N} -% Save and restore functions. -% \begin{macrocode} -\cs_new_protected:Npn \@@_softpath_get:N #1 - { - \@@_softpath_concat:n { } - \tl_set_eq:NN #1 \g_@@_softpath_main_tl - } -\cs_new_protected:Npn \@@_softpath_set_eq:N #1 - { - \tl_gset_eq:NN \g_@@_softpath_main_tl #1 - \@@_softpath_reset_buffers: - } -% \end{macrocode} -% \end{macro} -% % \begin{macro} % {\@@_softpath_use:, \@@_softpath_clear:, \@@_softpath_use_clear:} % Using and clearing is trivial. @@ -186,6 +179,7 @@ \tl_gclear:N \g_@@_softpath_main_tl \tl_gclear:N \g_@@_softpath_buffer_a_tl \tl_gclear:N \g_@@_softpath_buffer_b_tl + \bool_gset_false:N \g_@@_softpath_corners_bool } \cs_new_protected:Npn \@@_softpath_use_clear: { @@ -267,6 +261,7 @@ { \@@_softpath_add:n { \@@_softpath_roundpoint_op:nn {#1} {#2} } + \bool_gset_true:N \g_@@_softpath_corners_bool } \cs_generate_variant:Nn \@@_softpath_roundpoint:nn { VV } % \end{macrocode} @@ -290,6 +285,8 @@ % \begin{macro}{\@@_softpath_curveto_opi:nnNnnNnn} % \begin{macro}{\@@_softpath_rectangle_opi:nnNnn} % The markers for operations: all the top-level ones take two arguments. +% The support tokens for curves have to be different in meaning to a +% round point, hence being quark-like. % \begin{macrocode} \cs_new_protected:Npn \@@_softpath_close_op:nn #1#2 { \driver_draw_closepath: } @@ -297,8 +294,10 @@ { \@@_softpath_curveto_opi:nnNnnNnn {#1} {#2} } \cs_new_protected:Npn \@@_softpath_curveto_opi:nnNnnNnn #1#2#3#4#5#6#7#8 { \driver_draw_curveto:nnnnnn {#1} {#2} {#4} {#5} {#7} {#8} } -\cs_new_protected:Npn \@@_softpath_curveto_opii:nn #1#2 { } -\cs_new_protected:Npn \@@_softpath_curveto_opiii:nn #1#2 { } +\cs_new_protected:Npn \@@_softpath_curveto_opii:nn #1#2 + { \@@_softpath_curveto_opii:nn } +\cs_new_protected:Npn \@@_softpath_curveto_opiii:nn #1#2 + { \@@_softpath_curveto_opiii:nn } \cs_new_protected:Npn \@@_softpath_lineto_op:nn #1#2 { \driver_draw_lineto:nn {#1} {#2} } \cs_new_protected:Npn \@@_softpath_moveto_op:nn #1#2 @@ -314,6 +313,364 @@ % \end{macro} % \end{macro} % +% \subsection{Rounding soft path corners} +% +% The aim here is to find corner rounding points and to replace them with +% arcs of appropriate length. The approach is exactly that in \pkg{pgf}: +% step through, find the corners, find the supporting data, do the rounding. +% +% \begin{variable}{\l_@@_softpath_main_tl} +% For constructing the updated path. +% \begin{macrocode} +\tl_new:N \l_@@_softpath_main_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_softpath_part_tl} +% Data structures. +% \begin{macrocode} +\tl_new:N \l_@@_softpath_part_tl +\tl_new:N \l_@@_softpath_curve_end_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% {\l_@@_softpath_lastx_fp, \l_@@_softpath_lasty_fp} +% \begin{variable} +% {\l_@@_softpath_corneri_dim, \l_@@_softpath_cornerii_dim} +% \begin{variable}{\l_@@_softpath_first_tl, \l_@@_softpath_move_tl} +% Position tracking: the token list data may be entirely empty or set to +% a co-ordinate. +% \begin{macrocode} +\fp_new:N \l_@@_softpath_lastx_fp +\fp_new:N \l_@@_softpath_lasty_fp +\dim_new:N \l_@@_softpath_corneri_dim +\dim_new:N \l_@@_softpath_cornerii_dim +\tl_new:N \l_@@_softpath_first_tl +\tl_new:N \l_@@_softpath_move_tl +% \end{macrocode} +% \end{variable} +% \end{variable} +% \end{variable} +% +% \begin{variable}{\c_@@_softpath_arc_fp} +% The magic constant. +% \begin{macrocode} +\fp_const:Nn \c_@@_softpath_arc_fp { 4/3 * (sqrt(2) - 1) } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_softpath_round_corners:} +% \begin{macro}{\@@_softpath_round_loop:Nnn} +% \begin{macro}{\@@_softpath_round_action:nn} +% \begin{macro}{\@@_softpath_round_action:Nnn} +% \begin{macro}{\@@_softpath_round_action_curveto:NnnNnn} +% \begin{macro}{\@@_softpath_round_action_close:} +% \begin{macro}{\@@_softpath_round_lookahead:NnnNnn} +% \begin{macro}{\@@_softpath_round_roundpoint:NnnNnnNnn} +% \begin{macro}{\@@_softpath_round_calc:nnnNnn} +% \begin{macro}[EXP] +% {\@@_softpath_round_calc:nnnnnn, \@@_softpath_round_calc:fVnnnn} +% \begin{macro}[EXP]{\@@_softpath_round_calc:nnnnw} +% \begin{macro}{\@@_softpath_round_close:nn} +% \begin{macro}[EXP]{\@@_softpath_round_close:w} +% \begin{macro}{\@@_softpath_round_end:} +% Rounding corners on a path means going through the entire path and +% adjusting it. As such, we avoid this entirely if we know there are no +% corners to deal with. Assuming there is work to do, we recover the existing +% path and start a loop. +% \begin{macrocode} +\cs_new_protected:Npn \@@_softpath_round_corners: + { + \bool_if:NT \g_@@_softpath_corners_bool + { + \group_begin: + \tl_clear:N \l_@@_softpath_main_tl + \tl_clear:N \l_@@_softpath_part_tl + \fp_zero:N \l_@@_softpath_lastx_fp + \fp_zero:N \l_@@_softpath_lasty_fp + \tl_clear:N \l_@@_softpath_first_tl + \tl_clear:N \l_@@_softpath_move_tl + \@@_softpath_concat:n { } + \exp_after:wN \@@_softpath_round_loop:Nnn + \g_@@_softpath_main_tl + \q_recursion_tail ? ? + \q_recursion_stop + \group_end: + } + \bool_gset_false:N \g_@@_softpath_corners_bool + } +% \end{macrocode} +% The loop can take advantage of the fact that all soft path operations are +% made up of a token followed by two arguments. At this stage, there is +% a simple split: have we round a round point. If so, is there any actual +% rounding to be done: if the arcs have come through zero, just ignore it. +% In cases where we are not at a corner, we simply move along the path, +% allowing for any new part starting due to a \texttt{moveto}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_softpath_round_loop:Nnn #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #1 { \@@_softpath_round_end: } + \token_if_eq_meaning:NNTF #1 \@@_softpath_roundpoint_op:nn + { \@@_softpath_round_action:nn {#2} {#3} } + { + \tl_if_empty:NT \l_@@_softpath_first_tl + { \tl_set:Nn \l_@@_softpath_first_tl { {#2} {#3} } } + \fp_set:Nn \l_@@_softpath_lastx_fp {#2} + \fp_set:Nn \l_@@_softpath_lasty_fp {#3} + \token_if_eq_meaning:NNTF #1 \@@_softpath_moveto_op:nn + { + \tl_put_right:No \l_@@_softpath_main_tl + \l_@@_softpath_move_tl + \tl_put_right:No \l_@@_softpath_main_tl + \l_@@_softpath_part_tl + \tl_set:Nn \l_@@_softpath_move_tl { #1 {#2} {#3} } + \tl_clear:N \l_@@_softpath_first_tl + \tl_clear:N \l_@@_softpath_part_tl + } + { \tl_put_right:Nn \l_@@_softpath_part_tl { #1 {#2} {#3} } } + \@@_softpath_round_loop:Nnn + } + } +\cs_new_protected:Npn \@@_softpath_round_action:nn #1#2 + { + \dim_set:Nn \l_@@_softpath_corneri_dim {#1} + \dim_set:Nn \l_@@_softpath_cornerii_dim {#2} + \bool_lazy_and:nnTF + { \dim_compare_p:nNn \l_@@_softpath_corneri_dim = { 0pt } } + { \dim_compare_p:nNn \l_@@_softpath_cornerii_dim = { 0pt } } + { \@@_softpath_round_loop:Nnn } + { \@@_softpath_round_action:Nnn } + } +% \end{macrocode} +% We now have a round point to work on and have grabbed the next item in +% the path. There are only a few cases where we have to do anything. Each of +% them is picked up by looking for the appropriate action. +% \begin{macrocode} +\cs_new_protected:Npn \@@_softpath_round_action:Nnn #1#2#3 + { + \tl_if_empty:NT \l_@@_softpath_first_tl + { \tl_set:Nn \l_@@_softpath_first_tl { {#2} {#3} } } + \token_if_eq_meaning:NNTF #1 \@@_softpath_curveto_opi:nn + { \@@_softpath_round_action_curveto:NnnNnn } + { + \token_if_eq_meaning:NNTF #1 \@@_softpath_close_op:nn + { \@@_softpath_round_action_close: } + { + \token_if_eq_meaning:NNTF #1 \@@_softpath_lineto_op:nn + { \@@_softpath_round_lookahead:NnnNnn } + { \@@_softpath_round_loop:Nnn } + } + } + #1 {#2} {#3} + } +% \end{macrocode} +% For a curve, we collect the two control points then move on to grab the +% end point and add the curve there: the second control point becomes our +% starter. +% \begin{macrocode} +\cs_new_protected:Npn \@@_softpath_round_action_curveto:NnnNnn + #1#2#3#4#5#6 + { + \tl_put_right:Nn \l_@@_softpath_part_tl + { #1 {#2} {#3} #4 {#5} {#6} } + \fp_set:Nn \l_@@_softpath_lastx_fp {#5} + \fp_set:Nn \l_@@_softpath_lasty_fp {#6} + \@@_softpath_round_lookahead:NnnNnn + } +\cs_new_protected:Npn \@@_softpath_round_action_close: + { + \bool_lazy_and:nnTF + { ! \tl_if_empty_p:N \l_@@_softpath_first_tl } + { ! \tl_if_empty_p:N \l_@@_softpath_move_tl } + { + \exp_after:wN \@@_softpath_round_close:nn + \l_@@_softpath_first_tl + } + { \@@_softpath_round_loop:Nnn } + } +% \end{macrocode} +% At this stage we have a current (sub)operation (|#1|) and the next +% operation (|#4|), and can therefore decide whether to round or not. +% In the case of yet another rounding marker, we have to look a bit +% further ahead. +% \begin{macrocode} +\cs_new_protected:Npn \@@_softpath_round_lookahead:NnnNnn #1#2#3#4#5#6 + { + \bool_lazy_any:nTF + { + { \token_if_eq_meaning_p:NN #4 \@@_softpath_lineto_op:nn } + { \token_if_eq_meaning_p:NN #4 \@@_softpath_curveto_opi:nn } + { \token_if_eq_meaning_p:NN #4 \@@_softpath_close_op:nn } + } + { + \@@_softpath_round_calc:nnnNnn + \@@_softpath_round_loop:Nnn {#5} {#6} + } + { + \token_if_eq_meaning:NNTF #4 \@@_softpath_roundpoint_op:nn + { \@@_softpath_round_roundpoint:NnnNnnNnn } + { \@@_softpath_round_loop:Nnn } + } + #1 {#2} {#3} + #4 {#5} {#6} + } +\cs_new_protected:Npn \@@_softpath_round_roundpoint:NnnNnnNnn + #1#2#3#4#5#6#7#8#9 + { + \@@_softpath_round_calc:nnnNnn + \@@_softpath_round_loop:Nnn + {#8} {#9} #1 {#2} {#3} + #4 {#5} {#6} #7 {#8} {#9} + } +% \end{macrocode} +% We now have all of the data needed to construct a rounded corner: all that +% is left to do is to work out the detail! At this stage, we have details +% of where the corner itself is (|#4|, |#5|), and where the next point is +% (|#1|, |#2|). There are two types of calculations to do. First, we +% need to interpolate from those two points in the direction of the +% corner, in order to work out where the curve we are adding will start +% and end. From those, plus the points we already have, we work out where +% the control points will lie. All of this is done in an expansion to +% avoid multiple calls to |\tl_put_right:Nx|. The end point of the line +% is worked out up-front and saved: we need that if dealing with a +% close-path operation. +% \begin{macrocode} +\cs_new_protected:Npn \@@_softpath_round_calc:nnnNnn #1#2#3#4#5#6 + { + \tl_set:Nx \l_@@_softpath_curve_end_tl + { + \draw_point_interpolate_distance:nnn + \l_@@_softpath_cornerii_dim + { #5 , #6 } { #2 , #3 } + } + \tl_put_right:Nx \l_@@_softpath_part_tl + { + \exp_not:N #4 + \@@_softpath_round_calc:fVnnnn + { + \draw_point_interpolate_distance:nnn + \l_@@_softpath_corneri_dim + { #5 , #6 } + { + \l_@@_softpath_lastx_fp , + \l_@@_softpath_lasty_fp + } + } + \l_@@_softpath_curve_end_tl + {#5} {#6} {#2} {#3} + } + \fp_set:Nn \l_@@_softpath_lastx_fp {#5} + \fp_set:Nn \l_@@_softpath_lasty_fp {#6} + #1 + } +% \end{macrocode} +% At this stage we have the two curve end points, but they are in +% co-ordinate form. So we split them up (with some more reordering). +% \begin{macrocode} +\cs_new:Npn \@@_softpath_round_calc:nnnnnn #1#2#3#4#5#6 + { + \@@_softpath_round_calc:nnnnw {#3} {#4} {#5} {#6} + #1 \q_mark #2 \q_stop + } +\cs_generate_variant:Nn \@@_softpath_round_calc:nnnnnn { fV } +% \end{macrocode} +% The calculations themselves are relatively straight-forward, as we use a +% quadratic Bézier curve. +% \begin{macrocode} +\cs_new:Npn \@@_softpath_round_calc:nnnnw + #1#2#3#4 #5 , #6 \q_mark #7 , #8 \q_stop + { + {#5} {#6} + \exp_not:N \@@_softpath_curveto_opi:nn + { + \fp_to_dim:n + { #5 + \c_@@_softpath_arc_fp * ( #1 - #5 ) } + } + { + \fp_to_dim:n + { #6 + \c_@@_softpath_arc_fp * ( #2 - #6 ) } + } + \exp_not:N \@@_softpath_curveto_opii:nn + { + \fp_to_dim:n + { #7 + \c_@@_softpath_arc_fp * ( #1 - #7 ) } + } + { + \fp_to_dim:n + { #8 + \c_@@_softpath_arc_fp* ( #2 - #8 ) } + } + \exp_not:N \@@_softpath_curveto_opiii:nn + {#7} {#8} + } +% \end{macrocode} +% To deal with a close-path operation, we need to do some manipulation. +% It needs to be treated as a line operation for rounding, and then +% have the close path operation re-added at the point where the curve +% ends. That means saving the end point in the calculation step (see +% earlier), and shuffling a lot. +% \begin{macrocode} +\cs_new_protected:Npn \@@_softpath_round_close:nn #1#2 + { + \use:x + { + \@@_softpath_round_calc:nnnNnn + { + \tl_set:Nx \exp_not:N \l_@@_softpath_move_tl + { + \@@_softpath_moveto_op:nn + \exp_not:N \exp_after:wN + \exp_not:N \@@_softpath_round_close:w + \exp_not:N \l_@@_softpath_curve_end_tl + \exp_not:N \q_stop + } + \use:x + { + \exp_not:N \exp_not:N \exp_not:N \use_i:nnnn + { + \@@_softpath_round_loop:Nnn + \@@_softpath_close_op:nn + \exp_not:N \exp_after:wN + \exp_not:N \@@_softpath_round_close:w + \exp_not:N \l_@@_softpath_curve_end_tl + \exp_not:N \q_stop + } + } + } + {#1} {#2} + \@@_softpath_lineto_op:nn + \exp_after:wN \use_none:n \l_@@_softpath_move_tl + } + } +\cs_new:Npn \@@_softpath_round_close:w #1 , #2 \q_stop { {#1} {#2} } +% \end{macrocode} +% Tidy up the parts of the path, complete the built token list and put +% it back into action. +% \begin{macrocode} +\cs_new_protected:Npn \@@_softpath_round_end: + { + \tl_put_right:No \l_@@_softpath_main_tl + \l_@@_softpath_move_tl + \tl_put_right:No \l_@@_softpath_main_tl + \l_@@_softpath_part_tl + \tl_gset_eq:NN \g_@@_softpath_main_tl \l_@@_softpath_main_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-state.dtx b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-state.dtx index 5e6eb424d05..4c6bade4569 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-state.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-state.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -94,7 +94,7 @@ % Pass through to the driver layer. % \begin{macrocode} \cs_new_protected:Npn \draw_miterlimit:n #1 - { \driver_draw_miterlimit:n { \fp_to_dim:n {#1} } } + { \driver_draw_miterlimit:n { \fp_eval:n {#1} } } % \end{macrocode} % \end{macro} % @@ -124,14 +124,6 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\g_@@_fill_color_tl, \g_@@_stroke_color_tl} -% For tracking. -% \begin{macrocode} -\tl_new:N \g_@@_fill_color_tl -\tl_new:N \g_@@_stroke_color_tl -% \end{macrocode} -% \end{variable} -% % \begin{macro}{\draw_color:n, \draw_color_fill:n, \draw_color_stroke:n} % \begin{macro}{\@@_color:nn} % \begin{macro}{\@@_color_aux:nn, \@@_color_aux:Vn} @@ -144,8 +136,7 @@ % Much the same as for core color support but calling the relevant % driver-level function. % \begin{macrocode} -\cs_new_protected:Npn \draw_color:n #1 - { \@@_color:nn { } {#1} } +\cs_new_eq:NN \draw_color:n \color_select:n \cs_new_protected:Npn \draw_color_fill:n #1 { \@@_color:nn { fill } {#1} } \cs_new_protected:Npn \draw_color_stroke:n #1 @@ -153,16 +144,7 @@ \cs_new_protected:Npn \@@_color:nn #1#2 { \color_parse:nN {#2} \l_@@_color_tmp_tl - \tl_if_blank:nTF {#1} - { - \tl_gset_eq:NN \g_@@_fill_color_tl \l_@@_color_tmp_tl - \tl_gset_eq:NN \g_@@_stroke_color_tl \l_@@_color_tmp_tl - \@@_color_aux:Vn \l_@@_color_tmp_tl { color } - } - { - \tl_gset_eq:cN { g_@@_ #1 _color_tl } \l_@@_color_tmp_tl - \@@_color_aux:Vn \l_@@_color_tmp_tl { #1 } - } + \@@_color_aux:Vn \l_@@_color_tmp_tl {#1} } \cs_new_protected:Npn \@@_color_aux:nn #1#2 { \@@_color:nw {#2} #1 \q_stop } @@ -170,13 +152,13 @@ \cs_new_protected:Npn \@@_color:nw #1#2 ~ #3 \q_stop { \use:c { @@_color_ #2 :nw } {#1} #3 \q_stop } \cs_new_protected:Npn \@@_color_cmyk:nw #1#2 ~ #3 ~ #4 ~ #5 \q_stop - { \use:c { driver_draw_ #1 _cmyk:nnnn } {#2} {#3} {#4} {#5} } + { \use:c { driver_draw_color_ #1 _cmyk:nnnn } {#2} {#3} {#4} {#5} } \cs_new_protected:Npn \@@_color_gray:nw #1#2 \q_stop - { \use:c { driver_draw_ #1 _gray:n } {#2} } + { \use:c { driver_draw_color_ #1 _gray:n } {#2} } \cs_new_protected:Npn \@@_color_rgb:nw #1#2 ~ #3 ~ #4 \q_stop - { \use:c { driver_draw_ #1 _rgb:nnn } {#2} {#3} {#4} } + { \use:c { driver_draw_color_ #1 _rgb:nnn } {#2} {#3} {#4} } \cs_new_protected:Npn \@@_color_spot:nw #1#2 ~ #3 \q_stop - { \use:c { driver_draw_ #1 _spot:nn } {#2} {#3} } + { \use:c { driver_draw_color_ #1 _spot:nn } {#2} {#3} } % \end{macrocode} % \end{macro} % \end{macro} diff --git a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-transforms.dtx b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-transforms.dtx index 4f325f01092..9b1478b48b7 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-transforms.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-transforms.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -58,149 +58,159 @@ %<@@=draw> % \end{macrocode} % -% \begin{variable}{\l_@@_transformcm_active_bool} +% This sub-module covers more-or-less the same ideas as +% \texttt{pgfcoretransformations.code.tex}. At present, equivalents of the +% following are currently absent: +% \begin{itemize} +% \item \cs{pgfgettransform}, \cs{pgfgettransformentries}: Awaiting use cases. +% \item \cs{pgftransformlineattime}, \cs{pgftransformarcaxesattime}, +% \cs{pgftransformcurveattime}: Need to look at the use cases for +% these to fully understand them. +% \item \cs{pgftransformarrow}: Likely to be done when other arrow functions +% are added. +% \item \cs{pgflowlevelsynccm}, \cs{pgflowlevel}: Likely to be added when +% use cases are encountered in other parts of the code. +% \end{itemize} +% +% \begin{variable}{\l_@@_matrix_active_bool} % An internal flag to avoid redundant calculations. % \begin{macrocode} -\bool_new:N \l_@@_transformcm_active_bool +\bool_new:N \l_@@_matrix_active_bool % \end{macrocode} % \end{variable} % % \begin{variable} % { -% \l_@@_transformcm_aa_fp, \l_@@_transformcm_ab_fp, -% \l_@@_transformcm_ba_fp, \l_@@_transformcm_aa_fp, -% \l_@@_transformcm_xshift_dim, -% \l_@@_transformcm_yshift_dim +% \l_@@_matrix_a_fp, +% \l_@@_matrix_b_fp, +% \l_@@_matrix_c_fp, +% \l_@@_matrix_a_fp, +% \l_@@_xshift_dim, +% \l_@@_yshift_dim % } -% The active matrix itself. +% The active matrix and shifts. % \begin{macrocode} -\fp_new:N \l_@@_transformcm_aa_fp -\fp_new:N \l_@@_transformcm_ab_fp -\fp_new:N \l_@@_transformcm_ba_fp -\fp_new:N \l_@@_transformcm_bb_fp -\dim_new:N \l_@@_transformcm_xshift_dim -\dim_new:N \l_@@_transformcm_yshift_dim +\fp_new:N \l_@@_matrix_a_fp +\fp_new:N \l_@@_matrix_b_fp +\fp_new:N \l_@@_matrix_c_fp +\fp_new:N \l_@@_matrix_d_fp +\dim_new:N \l_@@_xshift_dim +\dim_new:N \l_@@_yshift_dim % \end{macrocode} % \end{variable} % -% \begin{macro}{\draw_transform_reset:} +% \begin{macro}{\draw_transform_matrix_reset:, \draw_transform_shift_reset:} % Fast resetting. % \begin{macrocode} -\cs_new_protected:Npn \draw_transform_reset: +\cs_new_protected:Npn \draw_transform_matrix_reset: + { + \fp_set:Nn \l_@@_matrix_a_fp { 1 } + \fp_zero:N \l_@@_matrix_b_fp + \fp_zero:N \l_@@_matrix_c_fp + \fp_set:Nn \l_@@_matrix_d_fp { 1 } + } +\cs_new_protected:Npn \draw_transform_shift_reset: { - \fp_set:Nn \l_@@_transformcm_aa_fp { 1} - \fp_zero:N \l_@@_transformcm_ab_fp - \fp_zero:N \l_@@_transformcm_ba_fp - \fp_set:Nn \l_@@_transformcm_bb_fp { 1 } - \dim_zero:N \l_@@_transformcm_xshift_dim - \dim_zero:N \l_@@_transformcm_yshift_dim + \dim_zero:N \l_@@_xshift_dim + \dim_zero:N \l_@@_yshift_dim } -\draw_transform_reset: +\draw_transform_matrix_reset: +\draw_transform_shift_reset: % \end{macrocode} % \end{macro} % -% \begin{macro}{\draw_transform:nnnnn} -% \begin{macro}{\@@_transform:nnnnnnn} +% \begin{macro}{\draw_transform_matrix:nnnn} +% \begin{macro}{\draw_transform_shift:n} +% \begin{macro}{\@@_transform_shift:nn} % Setting the transform matrix is straight-forward, with just a bit % of expansion to sort out. With the mechanism active, the identity % matrix is set. % \begin{macrocode} -\cs_new_protected:Npn \draw_transform:nnnnn #1#2#3#4#5 +\cs_new_protected:Npn \draw_transform_matrix:nnnn #1#2#3#4 { - \@@_point_process:nn - { \@@_transform:nnnnnnn {#1} {#2} {#3} {#4} } - {#5} - } -\cs_new_protected:Npn \@@_transform:nnnnnnn #1#2#3#4#5#6 - { - \fp_set:Nn \l_@@_transformcm_aa_fp {#1} - \fp_set:Nn \l_@@_transformcm_ab_fp {#2} - \fp_set:Nn \l_@@_transformcm_ba_fp {#3} - \fp_set:Nn \l_@@_transformcm_bb_fp {#4} - \dim_set:Nn \l_@@_transformcm_xshift_dim {#5} - \dim_set:Nn \l_@@_transformcm_yshift_dim {#6} + \fp_set:Nn \l_@@_matrix_a_fp {#1} + \fp_set:Nn \l_@@_matrix_b_fp {#2} + \fp_set:Nn \l_@@_matrix_c_fp {#3} + \fp_set:Nn \l_@@_matrix_d_fp {#4} \bool_lazy_all:nTF { - { \fp_compare_p:nNn \l_@@_transformcm_aa_fp = \c_one_fp } - { \fp_compare_p:nNn \l_@@_transformcm_ab_fp = \c_zero_fp } - { \fp_compare_p:nNn \l_@@_transformcm_ba_fp = \c_zero_fp } - { \fp_compare_p:nNn \l_@@_transformcm_bb_fp = \c_one_fp } + { \fp_compare_p:nNn \l_@@_matrix_a_fp = \c_one_fp } + { \fp_compare_p:nNn \l_@@_matrix_b_fp = \c_zero_fp } + { \fp_compare_p:nNn \l_@@_matrix_c_fp = \c_zero_fp } + { \fp_compare_p:nNn \l_@@_matrix_d_fp = \c_one_fp } } - { \bool_set_false:N \l_@@_transformcm_active_bool } - { \bool_set_true:N \l_@@_transformcm_active_bool } + { \bool_set_false:N \l_@@_matrix_active_bool } + { \bool_set_true:N \l_@@_matrix_active_bool } + } +\cs_new_protected:Npn \draw_transform_shift:n #1 + { + \@@_point_process:nn + { \@@_transform_shift:nn } {#1} + } +\cs_new_protected:Npn \@@_transform_shift:nn #1#2 + { + \dim_set:Nn \l_@@_xshift_dim {#1} + \dim_set:Nn \l_@@_yshift_dim {#2} } % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % -% \begin{macro}{\draw_transform_concat:nnnnn} -% \begin{macro}{\@@_transform_concat:nnnnnn} -% \begin{macro}{\@@_transform_concat_aux:nnnnnn} -% Much the same story for adding to an existing matrix. The part that is more -% complex is the calculations required: everything gets passed back to -% \cs{@@_transform_set:nnnnnn}, with pre-expansion just in case there are -% \emph{e.g}~random values. The final step is \texttt{x}-type expanded as -% otherwise later values affect earlier ones. +% \begin{macro}{\draw_transform_matrix_concat:nnnn} +% \begin{macro}{\@@_transform_concat:nnnn} +% \begin{macro}{\draw_transform_shift_concat:n} +% \begin{macro}{\@@_transform_shift_concat:nn} +% Much the same story for adding to an existing matrix, with a bit of +% pre-expansion so that the calculation uses \enquote{frozen} values. % \begin{macrocode} -\cs_new_protected:Npn \draw_transform_concat:nnnnn #1#2#3#4#5 - { - \@@_point_process:nn - { \@@_transform_concat:nnnnnn {#1} {#2} {#3} {#4} } - {#5} - } -\cs_new_protected:Npn \@@_transform_concat:nnnnnn #1#2#3#4#5#6 +\cs_new_protected:Npn \draw_transform_matrix_concat:nnnn #1#2#3#4 { \use:x { - \@@_transform_concat_aux:nnnnnn + \@@_transform_concat:nnnn { \fp_eval:n {#1} } { \fp_eval:n {#2} } { \fp_eval:n {#3} } { \fp_eval:n {#4} } - {#5} - {#6} } } -\cs_new_protected:Npn \@@_transform_concat_aux:nnnnnn #1#2#3#4#5#6 +\cs_new_protected:Npn \@@_transform_concat:nnnn #1#2#3#4 { \use:x { - \@@_transform:nnnnnnn - { #1 * \l_@@_transformcm_aa_fp + #2 * \l_@@_transformcm_ba_fp } - { #1 * \l_@@_transformcm_ab_fp + #2 * \l_@@_transformcm_bb_fp } - { #3 * \l_@@_transformcm_aa_fp + #4 * \l_@@_transformcm_ba_fp } - { #3 * \l_@@_transformcm_ab_fp + #4 * \l_@@_transformcm_bb_fp } - { - \fp_to_dim:n - { - \l_@@_transformcm_xshift_dim - + \l_@@_transformcm_aa_fp * #5 - + \l_@@_transformcm_ba_fp * #6 - } - } - { - \fp_to_dim:n - { - \l_@@_transformcm_yshift_dim - + \l_@@_transformcm_ab_fp * #5 - + \l_@@_transformcm_bb_fp * #6 - } - } + \draw_transform_matrix:nnnn + { #1 * \l_@@_matrix_a_fp + #2 * \l_@@_matrix_c_fp } + { #1 * \l_@@_matrix_b_fp + #2 * \l_@@_matrix_d_fp } + { #3 * \l_@@_matrix_a_fp + #4 * \l_@@_matrix_c_fp } + { #3 * \l_@@_matrix_b_fp + #4 * \l_@@_matrix_d_fp } } } +\cs_new_protected:Npn \draw_transform_shift_concat:n #1 + { + \@@_point_process:nn + { \@@_transform_shift_concat:nn } {#1} + } +\cs_new_protected:Npn \@@_transform_shift_concat:nn #1#2 + { + \dim_set:Nn \l_@@_xshift_dim { \l_@@_xshift_dim + #1 } + \dim_set:Nn \l_@@_yshift_dim { \l_@@_yshift_dim + #2 } + } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % -% \begin{macro}{\draw_transform_invert:} +% \begin{macro}{\draw_transform_matrix_invert:} % \begin{macro}{\@@_transform_invert:n, \@@_transform_invert:f} +% \begin{macro}{\draw_transform_shift_invert:} % Standard mathematics: calculate the inverse matrix and use that, then % undo the shifts. % \begin{macrocode} -\cs_new_protected:Npn \draw_transform_invert: +\cs_new_protected:Npn \draw_transform_matrix_invert: { - \bool_if:NT \l_@@_transformcm_active_bool + \bool_if:NT \l_@@_matrix_active_bool { \@@_transform_invert:f { @@ -208,44 +218,34 @@ { 1 / ( - \l_@@_transformcm_aa_fp * \l_@@_transformcm_bb_fp - - \l_@@_transformcm_ab_fp * \l_@@_transformcm_ba_fp + \l_@@_matrix_a_fp * \l_@@_matrix_d_fp + - \l_@@_matrix_b_fp * \l_@@_matrix_c_fp ) } } } - \dim_set:Nn \l_@@_transformcm_xshift_dim - { - \fp_to_dim:n - { - -\l_@@_transformcm_xshift_dim * \l_@@_transformcm_aa_fp - -\l_@@_transformcm_yshift_dim * \l_@@_transformcm_ba_fp - } - } - \dim_set:Nn \l_@@_transformcm_yshift_dim - { - \fp_to_dim:n - { - -\l_@@_transformcm_xshift_dim * \l_@@_transformcm_ab_fp - -\l_@@_transformcm_yshift_dim * \l_@@_transformcm_bb_fp - } - } } \cs_new_protected:Npn \@@_transform_invert:n #1 { - \fp_set:Nn \l_@@_transformcm_aa_fp - { \l_@@_transformcm_bb_fp * #1 } - \fp_set:Nn \l_@@_transformcm_ab_fp - { -\l_@@_transformcm_ab_fp * #1 } - \fp_set:Nn \l_@@_transformcm_ba_fp - { -\l_@@_transformcm_ba_fp * #1 } - \fp_set:Nn \l_@@_transformcm_bb_fp - { \l_@@_transformcm_aa_fp * #1 } + \fp_set:Nn \l_@@_matrix_a_fp + { \l_@@_matrix_d_fp * #1 } + \fp_set:Nn \l_@@_matrix_b_fp + { -\l_@@_matrix_b_fp * #1 } + \fp_set:Nn \l_@@_matrix_c_fp + { -\l_@@_matrix_c_fp * #1 } + \fp_set:Nn \l_@@_matrix_d_fp + { \l_@@_matrix_a_fp * #1 } } \cs_generate_variant:Nn \@@_transform_invert:n { f } +\cs_new_protected:Npn \draw_transform_shift_invert: + { + \dim_set:Nn \l_@@_xshift_dim { -\l_@@_xshift_dim } + \dim_set:Nn \l_@@_yshift_dim { -\l_@@_yshift_dim } + } % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}{\draw_transform_triangle:nnn} % Simple maths to move the canvas origin to |#1| and the two axes to @@ -265,18 +265,69 @@ { \use:x { - \@@_transform:nnnnnnn + \draw_transform_matrix:nnnn { #3 - #1 } { #4 - #2 } { #5 - #1 } { #6 - #2 } - {#1} - {#2} + \draw_transform_shift:n { #1 , #2 } } } % \end{macrocode} % \end{macro} % +% \begin{macro} +% {\draw_transform_scale:n, \draw_transform_xscale:n, \draw_transform_yscale:n} +% \begin{macro} +% {\draw_transform_xshift:n, \draw_transform_yshift:n} +% \begin{macro} +% {\draw_transform_xslant:n, \draw_transform_yslant:n} +% Lots of shortcuts. +% \begin{macrocode} +\cs_new_protected:Npn \draw_transform_scale:n #1 + { \draw_transform_matrix_concat:nnnn { #1 } { 0 } { 0 } { #1 } } +\cs_new_protected:Npn \draw_transform_xscale:n #1 + { \draw_transform_matrix_concat:nnnn { #1 } { 0 } { 0 } { 1 } } +\cs_new_protected:Npn \draw_transform_yscale:n #1 + { \draw_transform_matrix_concat:nnnn { 1 } { 0 } { 0 } { #1 } } +\cs_new_protected:Npn \draw_transform_xshift:n #1 + { \draw_transform_shift_concat:n { #1 , 0 } } +\cs_new_protected:Npn \draw_transform_yshift:n #1 + { \draw_transform_shift_concat:n { 0 , #1 } } +\cs_new_protected:Npn \draw_transform_xslant:n #1 + { \draw_transform_matrix_concat:nnnn { 1 } { 0 } { #1 } { 1 } } +\cs_new_protected:Npn \draw_transform_yslant:n #1 + { \draw_transform_matrix_concat:nnnn { 1 } { #1 } { 0 } { 1 } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\draw_transform_rotate:n} +% \begin{macro} +% { +% \@@_transform_rotate:n, \@@_transform_rotate:f, +% \@@_transform_rotate:nn, \@@_transform_rotate:ff +% } +% Slightly more involved: evaluate the angle only once, and the sine and +% cosine only once. +% \begin{macrocode} +\cs_new_protected:Npn \draw_transform_rotate:n #1 + { \@@_transform_rotate:f { \fp_eval:n {#1} } } +\cs_new_protected:Npn \@@_transform_rotate:n #1 + { + \@@_transform_rotate:ff + { \fp_eval:n { cosd(#1) } } + { \fp_eval:n { sind(#1) } } + } +\cs_generate_variant:Nn \@@_transform_rotate:n { f } +\cs_new_protected:Npn \@@_transform_rotate:nn #1#2 + { \draw_transform_matrix_concat:nnnn {#1} {#2} { -#2 } { #1 } } +\cs_generate_variant:Nn \@@_transform_rotate:nn { ff } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.dtx b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.dtx index 9b7c04d5e54..7cefc6d837d 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.dtx @@ -25,6 +25,71 @@ %</driver|package> %<*driver> \documentclass[full]{l3doc} +\usepackage[utf8]{inputenc} +\usepackage{l3draw} +% For creating code demonstrations +% This needs access to some code-level interfaces in listings +\usepackage{listings} +\makeatletter +\lst@RequireAspects{writefile} +\newsavebox\demo@box +\lstnewenvironment{demo}[1][code and example] + {% + \global\let\lst@intname\@empty + \edef\demo@end{% + \expandafter\noexpand\csname demo@@#1@end\endcsname + }% + \@nameuse{demo@@#1}% + } + {\demo@end} +\newcommand\demo@new[3]{% + \@namedef{demo@@#1}{#2}% + \@namedef{demo@@#1@end}{#3}% +} +\newcommand*\demo@common{% + \setkeys{lst} + {% + basicstyle = \small\ttfamily, + basewidth = 0.51em, + gobble = 5, + language = [LaTeX]{TeX}, + }% +} +\newcommand*\demo@input{% + \ExplSyntaxOn + \catcode`\^^M = 10\relax + \catcode`\% = 14\relax + \input{\jobname.tmp}% + \ExplSyntaxOff +} +\demo@new{code and example}{% + \setbox\demo@box=\hbox\bgroup + \lst@BeginAlsoWriteFile{\jobname.tmp}% + \demo@common +}{% + \lst@EndWriteFile + \egroup + \begin{center} + \ifdim\wd\demo@box > 0.75\linewidth + \begin{minipage}{\linewidth} + \usebox\demo@box + \end{minipage}% + \par + \begin{minipage}{\linewidth} + \demo@input + \end{minipage} + \else + \begin{minipage}{0.25\linewidth} + \demo@input + \end{minipage}% + \hfil + \begin{minipage}{0.75\linewidth} + \usebox\demo@box + \end{minipage}% + \fi + \end{center} +} +\makeatother \begin{document} \DocInput{\jobname.dtx} \end{document} @@ -44,7 +109,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -82,6 +147,64 @@ % The drawing created within the environment will be inserted into % the typesetting stream by the \cs{draw_end:} function, which will % switch out of vertical mode if required. +% \begin{demo} +% \dim_new:N \l_mypos_dim +% \draw_begin: +% \draw_path_moveto:n { 0cm , \l_mypos_dim } +% \draw_path_lineto:n { 1cm , \l_mypos_dim } +% \dim_set:Nn \l_mypos_dim { 1cm } +% \draw_path_lineto:n { 1cm , \l_mypos_dim } +% \draw_path_close: +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% +% Within a drawing, the only commands that should appear are those directly +% aimed at drawing (from \pkg{l3draw}) and those which produce \emph{no} +% typeset output. For example, it is possible to include loops inside a +% drawing using |\int_step_function:nnnn| or similar. On the other hand, +% text should not be included directly in drawings, but should rather be +% inserted using the appropriate \pkg{l3draw} command. +% \end{function} +% +% Within a drawing, there are different ways of referring to a position. +% The co-ordinates of a point are given relative to the current +% \emph{drawing axes}. These can be manipulated and tracked at the code +% level. Underlying this is the \meta{canvas}, which is at the \pkg{draw} +% level essentially fixed and in line with the paper. Initially, the two +% sets of axes are coincident. (It is possible to manipulate the canvas +% axes at the driver level: this is then \enquote{transparent} to the +% \pkg{draw} level, and so should be used only when strictly required.) +% +% \begin{function}{\draw_suspend_begin:, \draw_suspend_end:} +% \begin{syntax} +% \cs{draw_suspend_begin:} +% ... +% \cs{draw_suspend_end:} +% \end{syntax} +% Suspends all of the drawing mechanisms to allow \enquote{normal} +% material to be created. Typically, this environment will be applied +% inside a box which may contain nested pictures. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \hbox_set:Nn \l_tmpa_box +% { +% \draw_suspend_begin: +% This~is~normal~text. +% \draw_begin: % A subpicture +% \draw_path_moveto:n { 1cm , 0cm } +% \draw_path_lineto:n { 1cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% More~text. +% \draw_suspend_end: +% } +% \draw_box_use:N \l_tmpa_box +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} % \end{function} % % \subsection{Graphics state} @@ -90,10 +213,10 @@ % will appear. Note that these all apply \emph{globally}, though some are % rest at the start of each drawing (\cs{draw_begin:}). % -% \begin{function}{\g_draw_linewidth_default_dim} +% \begin{variable}{\g_draw_linewidth_default_dim} % The default value of the linewidth for stokes, set at the start % of every drawing (\cs{draw_begin:}). -% \end{function} +% \end{variable} % % \begin{function}{\draw_linewidth:n, \draw_inner_linewidth:n} % \begin{syntax} @@ -140,10 +263,54 @@ % % \begin{function}{\draw_miterlimit:n} % \begin{syntax} -% \cs{draw_miterlimit:n} \Arg{limit} +% \cs{draw_miterlimit:n} \Arg{factor} % \end{syntax} -% Sets the miter \meta{limit} of lines joined as a miter, as described in the -% PDF and PostScript manuals. The \meta{limit} is an \meta{fp expr}. +% Sets the miter \meta{factor} of lines joined as a miter, as described in the +% PDF and PostScript manuals. The \meta{factor} is an \meta{fp expr}. +% \end{function} +% +% \subsection{Scoping drawing elements} +% +% Scoping drawing elements is necessary to allowing nesting of subparts. +% These features have specific use requirements: the preconditions must be +% met. In particular, each type of drawing scope also constitutes a +% group (\cs{groupd_being:}/\cs{group_end:} pair): as such, they must be +% nested correctly. +% +% \begin{function}{\draw_scope_begin:, \draw_scope_end:} +% \begin{syntax} +% \cs{draw_scope_begin:} +% ... +% \cs{draw_scope_end:} +% \end{syntax} +% Creates a scope for localisation of state settings within a drawing. +% A scope forms a \TeX{} group but will also localise global state +% variables (such as \cs{g_draw_linewidth_default_dim}), and driver-level +% concepts such as the termination of lines. +% \begin{demo} +% \draw_begin: +% \draw_scope_begin: +% \group_begin: +% \draw_linewidth:n { 2pt } +% \draw_path_rectangle:nn { 0 , 0 } { 2ex , 2ex } +% \draw_path_use:n { stroke } +% \group_end: +% \draw_path_rectangle:nn { 3ex , 0ex } { 2ex , 2ex } +% \draw_path_use:n { stroke } +% \draw_scope_end: +% \draw_path_rectangle:nn { 6ex , 0ex } { 2ex , 2ex } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% Global graphical concepts restricted by scope are +% \begin{itemize} +% \item Line width +% \item Stroke and fill color +% \item Dash pattern +% \item Line joining and capping, including the miter limit +% \item Clipping paths +% \item Canvas (driver) transformations +% \end{itemize} % \end{function} % % \subsection{Points} @@ -180,7 +347,7 @@ % higher-level functions, for example path construction, and allows parts of % a drawing to be rotated, scaled or skewed. This occurs before writing any % data to the driver, and so such manipulations are tracked by the drawing -% mechanisms. See \cs{driver_draw_transformcm:nnnnnn} for driver-level +% mechanisms. See \cs{driver_draw_cm:nnnn} for driver-level % manipulation of the canvas axes themselves. % % Notice that in contrast to \pkg{pgf} it is possible to give the positions @@ -235,8 +402,8 @@ % \begin{syntax} % \cs{draw_point_unit_vector:n} \Arg{point} % \end{syntax} -% Expands to the co-ordinates of a unit vector joining the \meta{point} -% with the origin. +% Expands to the co-ordinates of a unit vector in the direction of the +% \meta{point} from the origin. % \end{function} % % \begin{function}[EXP]{\draw_point_transform:n} @@ -255,9 +422,9 @@ % co-incident with the standard Cartesian axes, but may be altered by % the user. % -% \begin{function}{\draw_xvec_set:n, \draw_yvec_set:n, \draw_zvec_set:n} +% \begin{function}{\draw_xvec:n, \draw_yvec:n, \draw_zvec:n} % \begin{syntax} -% \cs{draw_xvec_set:n} \Arg{point} +% \cs{draw_xvec:n} \Arg{point} % \end{syntax} % Defines the appropriate base vector to point toward the \meta{point} % on the canvas. The standard settings for the $x$- and $y$-vectors are @@ -358,16 +525,86 @@ % manipulated or indeed discarded entirely. Only one path is active at % any one time, and the path is \emph{not} affected by \TeX{} grouping. % -% \begin{function}{\draw_path_corner_arc:n} +% \begin{function}{\draw_path_corner_arc:nn} +% \begin{syntax} +% \cs{draw_path_corner_arc:n} \Arg{length1} \Arg{length2} +% \end{syntax} +% Sets the degree of rounding applied to corners in a path: the two +% \meta{length} values are the distances from the corner at which the curving +% should start. The first \meta{length} applies to the part of the path +% \enquote{leading in} to the corner (\emph{i.e.}~from the previous path +% operation), and the second to that \enquote{leading out}. If both +% values are \texttt{0pt} then corners will not be rounded. The values +% apply within the scope of the current \TeX{} group. +% \begin{demo} +% \draw_begin: +% \draw_path_corner_arc:nn { 5mm } { 5mm } +% \draw_path_rectangle_corners:nn +% { 0cm , 0cm } { 3cm , 2cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% \begin{demo} +% \draw_begin: +% \draw_path_corner_arc:nn { 10mm } { 5mm } +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 2cm } +% \draw_path_lineto:n { 3cm , 2cm } +% \draw_path_curveto:nnn +% { 3cm , 0cm } { 2cm , 0cm } { 1cm , 0 cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% The corners created are quarter-circles for exact right-angles and +% close approximations otherwise. Closing a path will result in rounding +% correctly. +% \begin{demo} +% \draw_begin: +% \draw_path_corner_arc:nn { 4pt } { 4pt } +% \draw_path_moveto:n +% { \draw_point_polar:nn { 0 } { 1cm } } +% \int_step_inline:nnnn { 72 } { 72 } { 359 } +% { +% \draw_path_lineto:n +% { \draw_point_polar:nn { #1 } { 1cm } } +% } +% \draw_path_close: +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_path_close:} % \begin{syntax} -% \cs{draw_path_corner_arc:n} \Arg{length} +% \cs{draw_path_close:} % \end{syntax} -% Sets the degree of rounding applied to corners in a path: if the -% \meta{length} is \texttt{0pt} then no rounding applies. The value of the -% \meta{length} is local to the current \TeX{} group. \emph{At present, -% corner arcs are not activated in the code.} +% Closes the current part of the path by appending a straight line from +% the current point to the starting point of the path. In general, any +% path to be \emph{filled} should include a close instructions. % \end{function} % +% \begin{function}{\draw_path_use:n, \draw_path_use_clear:n} +% \begin{syntax} +% \cs{draw_path_use:n} \Arg{action(s)} +% \end{syntax} +% Inserts the current path, carrying out one ore more possible \meta{actions} +% (a comma list): +% \begin{itemize} +% \item \texttt{clear} Resets the path to empty +% \item \texttt{clip} Clips any content outside of the path +% \item \texttt{draw} +% \item \texttt{fill} Fills the interior of the path with the current +% file color +% \item \texttt{stroke} Draws a line along the current path +% \end{itemize} +% \end{function} +% +% \subsubsection{Path operations on drawing axes} +% +% The standard path functions are all influenced by the active transformation +% matrix, \emph{i.e.}~the work relative to the drawing axes rather than +% the canvas. +% % \begin{function}{\draw_path_moveto:n} % \begin{syntax} % \cs{draw_path_moveto:n} \Arg{point} @@ -381,6 +618,32 @@ % \cs{draw_path_lineto:n} \Arg{point} % \end{syntax} % Joins the current path to the \meta{point} with a straight line. +% In general, for reliable treatment by viewers, a \cs{draw_path_moveto:n} +% operation should precede the first use of a \cs{draw_path_lineto:n} +% on a path. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 1cm , 1cm } +% \draw_path_lineto:n { 2cm , 1cm } +% \draw_path_lineto:n { 3cm , 0.5cm } +% \draw_path_lineto:n { 3cm , 0cm } +% \draw_color_fill:n { yellow!80!black } +% \draw_path_use_clear:n { fill , stroke } +% \draw_end: +% \end{demo} +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 1cm , 1cm } +% \draw_path_lineto:n { 2cm , 1cm } +% \draw_path_moveto:n { 2cm , 1cm } % Begins a new part +% \draw_path_lineto:n { 3cm , 0.5cm } +% \draw_path_lineto:n { 3cm , 0cm } +% \draw_color_fill:n { yellow!80!black } +% \draw_path_use_clear:n { fill , stroke } +% \draw_end: +% \end{demo} % \end{function} % % \begin{function}{\draw_path_curveto:nnn} @@ -388,7 +651,21 @@ % \cs{draw_path_curveto:nnn} \Arg{control1} \Arg{control2} \Arg{end} % \end{syntax} % Joins the current path to the \meta{end} with a curved line defined by -% cubic Bézier points \meta{control1} and \meta{control2}. +% cubic Bézier points \meta{control1} and \meta{control2}. The bounding box +% of the path (and image) will fully-contain the curve and control points, +% \emph{i.e.}~it may be bigger than strictly necessary to contain the curve +% \emph{alone}. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_curveto:nnn +% { 1cm , 1cm } % First control +% { 2cm , 1cm } % Second control +% { 3cm , 0cm } % End +% \draw_color_fill:n { yellow!80!black } +% \draw_path_use_clear:n { fill , stroke } +% \draw_end: +% \end{demo} % \end{function} % % \begin{function}{\draw_path_curveto:nn} @@ -396,7 +673,20 @@ % \cs{draw_path_curveto:nn} \Arg{control} \Arg{end} % \end{syntax} % Joins the current path to the \meta{end} with a curved line defined by -% quadratic Bézier point \meta{control}. +% quadratic Bézier point \meta{control}. The bounding box +% of the path (and image) will fully-contain the curve and computed (cubic) +% control points, \emph{i.e.}~it may be bigger than strictly necessary to +% contain the curve \emph{alone}. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_curveto:nn +% { 1cm , 1cm } +% { 2cm , 0cm } +% \draw_color_fill:n { yellow!80!black } +% \draw_path_use_clear:n { fill , stroke } +% \draw_end: +% \end{demo} % \end{function} % % \begin{function}{\draw_path_arc:nnn, \draw_path_arc:nnnn} @@ -407,9 +697,26 @@ % Joins the current path with an arc between \meta{angle1} and \meta{angle2} % and of \meta{radius}. The four-argument version accepts two radii of % different lengths. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_arc:nnn { 180 } { 90 } { 0.5cm } +% \draw_path_lineto:n { 3cm , 1.5cm } +% \draw_path_arc:nnn { 90 } { -45 } { 0.5cm } +% \draw_path_use_clear:n { fill } +% \draw_end: +% \end{demo} % % Note the interface here has a different argument ordering from that in % \pkg{pgf}, which has the two centers then the two radii. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_arc:nnnn { 180 } { 45 } { 2cm } { 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} % \end{function} % % \begin{function}{\draw_path_arc_axes:nnnn} @@ -417,15 +724,49 @@ % \cs{draw_path_arc_axes:nnn} \Arg{angle1} \Arg{angle2} \Arg{vector1} \Arg{vector2} % \end{syntax} % Appends the portion of an ellipse from \meta{angle1} to \meta{angle2} of an -% ellipse with axes along \meta{vector1} and \meta{vector2} to the current path. +% ellipse with axes along \meta{vector1} and \meta{vector2} to the current +% path. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 2cm , 5mm } +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_moveto:n { 2cm , 5mm } +% \draw_path_arc_axes:nnnn { 0 } { 90 } +% { 2cm , 5mm } { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} % \end{function} % -% \begin{function}{\draw_path_ellipse:nnnn} +% \begin{function}{\draw_path_ellipse:nnn} % \begin{syntax} % \cs{draw_path_ellipse:nnn} \Arg{center} \Arg{vector1} \Arg{vector2} % \end{syntax} % Appends an ellipse at \meta{center} with axes along \meta{vector1} and -% \meta{vector2} to the current path. +% \meta{vector2} to the current path. A new part is started if the path +% is already non-empty. Notice that the underlying drawing is constructed +% from arcs with appropriate moves: the interfaces is a more efficient +% convenience. +% \begin{demo} +% \draw_begin: +% \draw_path_ellipse:nnn +% { 1cm , 0cm } +% { 1.5cm , 0cm } +% { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_color:n { red } +% \draw_path_ellipse:nnn +% { 1cm , 0cm } +% { 1cm , 1cm } +% { -0.5cm , 0.5cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% +% Note that any transformation is applied to the completed ellipse rather than +% to the axes. % \end{function} % % \begin{function}{\draw_path_circle:nn} @@ -433,6 +774,7 @@ % \cs{draw_path_circle:nn} \Arg{center} \Arg{radius} % \end{syntax} % Appends a circle of \meta{radius} at \meta{center} to the current path. +% This is a shortcut for \cs{draw_path_ellipse:nnn}. % \end{function} % % \begin{function}{\draw_path_rectangle:nn, \draw_path_rectangle_corners:nn} @@ -443,44 +785,179 @@ % Appends a rectangle starting at \meta{lower-left} to the current path, % with the size of the rectangle determined either by a \meta{displacement} % or the position of the \meta{top-right}. +% \begin{demo} +% \draw_begin: +% \draw_path_rectangle:nn +% { 1cm , 0cm } +% { 1.5cm , 1cm } +% \draw_path_rectangle:nn +% { 1.5cm , 0.25cm } +% { 1.5cm , 1cm } +% \draw_path_rectangle:nn +% { 2cm , 0.5cm } +% { 1.5cm , 1cm } +% \draw_path_use_clear:n { draw } +% \draw_end: +% \end{demo} +% \begin{demo} +% \draw_begin: +% \draw_path_rectangle_corners:nn +% { 1cm , 0cm } +% { 1.5cm , 1cm } +% \draw_path_use_clear:n { draw } +% \draw_end: +% \end{demo} % \end{function} % % \begin{function}{\draw_path_grid:nnnn} % \begin{syntax} -% \cs{draw_path_grid:nnnn} \Arg{xspace} \Arg{yspace} \Arg{lower-left} \Arg{upper-right} +% \cs{draw_path_grid:nnnn} \Arg{xstep} \Arg{ystep} \Arg{lower-left} \Arg{upper-right} % \end{syntax} -% Constructs a grid of \meta{xspace} and \meta{yspace} from the -% \meta{lower-left} to the \meta{upper-right}, and appends this to the -% current path. +% Constructs a grid of \meta{xstep} and \meta{ystep} inside the rectangle +% defined by the \meta{lower-left} and the \meta{upper-right}, and appends +% this to the current path. The grid will be aligned such that grid lines +% pass through the origin, which may result in \enquote{protruding} ends +% if the start/end positions do not fully align. +% \begin{demo} +% \draw_begin: +% \draw_linewidth:n { 0.8pt } +% \draw_path_grid:nnnn +% { 1cm } { 1cm } +% { -3mm , -3mm } +% { 33mm , 23mm } +% \draw_path_use_clear:n { stroke } +% \draw_linewidth:n { 0.4pt } +% \draw_path_grid:nnnn +% { 1mm } { 1mm } +% { -1.5mm , -1.5mm } +% { 31.5mm , 21.5mm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% +% Any transformation is applied to the finished grid. +% \begin{demo} +% \draw_begin: +% \draw_transform_rotate:n { 10 } +% \draw_path_grid:nnnn +% { 1mm } { 2mm } +% { 0mm , 0mm } +% { 30mm , 30mm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} % \end{function} % -% \begin{function}{\draw_path_close:} +% \subsubsection{Path scope} +% +% \begin{function}{\draw_path_scope_begin:, \draw_path_scope_end:} % \begin{syntax} -% \cs{draw_path_close:} +% \cs{draw_path_scope_begin:} +% ... +% \cs{draw_path_scope_end:} % \end{syntax} -% Closes the current part of the path by appending a straight line from -% the current point to the starting point of the path. +% Suspends (and saves) the current (partial) path, initialising a new +% path within the scope. Path operations are written to output only when +% used, so the scoped path is stored at the \pkg{expl3} level, not +% in the output. % \end{function} % -% \begin{function}{\draw_path_use:n, \draw_path_use_clear:n} +% \subsubsection{Path operations on canvas axes} +% +% For \emph{specialist} work, a small number of functions are provided +% which work relative to the canvas axes, \emph{i.e.}~these functions +% ignore the transformation matrix. +% +% \begin{function}{\draw_path_canvas_moveto:n} % \begin{syntax} -% \cs{draw_path_use:n} \Arg{action(s)} +% \cs{draw_path_canvas_moveto:n} \Arg{canvas point} % \end{syntax} -% Inserts the current path, carrying out one ore more possible \meta{actions} -% (a comma list): -% \begin{itemize} -% \item \texttt{clear} Resets the path to empty -% \item \texttt{clip} Clips any content outside of the path -% \item \texttt{draw} -% \item \texttt{fill} Fills the interior of the path with the current -% file color -% \item \texttt{stroke} Draws a line along the current path -% \end{itemize} +% Moves the reference point of the path to the \meta{canvas point}, but will +% not join this to any previous point. +% \end{function} +% +% \begin{function}{\draw_path_canvas_lineto:n} +% \begin{syntax} +% \cs{draw_path_canvas_lineto:n} \Arg{canvas point} +% \end{syntax} +% Joins the current path to the \meta{canvas point} with a straight line. +% \end{function} +% +% \begin{function}{\draw_path_canvas_curveto:nnn} +% \begin{syntax} +% \cs{draw_path_canvas_curveto:nnn} \Arg{control1} \Arg{control2} \Arg{end} +% \end{syntax} +% Joins the current path to the \meta{end} with a curved line defined by +% cubic Bézier points \meta{control1} and \meta{control2}. These positions +% are given as canvas points. +% \end{function} +% +% \subsection{Bounding box} +% +% \begin{variable}{\l_draw_bb_update_bool} +% All functions automatically update the bounding box of the image, unless +% specified otherwise. This behavior is selectable using the +% \cs{l_draw_bb_update_bool} boolean. +% \end{variable} +% +% \subsection{Boxes and coffins} +% +% \begin{function}{\draw_box_use:N} +% \begin{syntax} +% \cs{draw_box_use:N} \meta{box} +% \end{syntax} +% Inserts the \meta{box} into a drawing, taking account of the current +% transformation matrix and shift, and adjusting the drawing bounding +% box to contain the (apparent) size of the box if this is active +% (see \cs{l_draw_bb_update_bool}). +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \hbox_set:Nn \l_tmpa_box +% { This~is~text. } +% \draw_box_use:N \l_tmpa_box +% \draw_end: +% \end{demo} +% \begin{demo} +% \draw_begin: +% \draw_transform_matrix:nnnn { 2 } { 0 } { 1 } { 2 } +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \hbox_set:Nn \l_tmpa_box +% { This~is~text. } +% \draw_box_use:N \l_tmpa_box +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_coffin_use:Nnn} +% \begin{syntax} +% \cs{draw_coffin_use:N} \meta{coffin} \Arg{hpole} \Arg{vpole} +% \end{syntax} +% Inserts the \meta{coffin} into a drawing, taking account of the current +% transformation matrix and shift, and adjusting the drawing bounding +% box to contain the (apparent) size of the box if this is active +% (see \cs{l_draw_bb_update_bool}). The alignment point of the coffin to +% the origin is specified by the intersection of the \meta{hpole} and the +% \meta{vpole}. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \hcoffin_set:Nn \l_tmpa_coffin +% { This~is~text. } +% \draw_coffin_use:Nnn \l_tmpa_coffin { hc } { vc } +% \draw_end: +% \end{demo} % \end{function} % % \subsection{Color} % -% \begin{function}{\draw_color:n, \draw_fill:n, \draw_stroke:n} +% \begin{function}{\draw_color:n, \draw_color_fill:n, \draw_color_stroke:n} % \begin{syntax} % \cs{draw_color:n} \Arg{color expression} % \end{syntax} @@ -491,34 +968,28 @@ % % Points are normally used unchanged relative to the canvas axes. This can % be modified by applying a transformation matrix. The canvas axes themselves -% may be adjusted using \cs{driver_draw_transformcm:nnnnnn}: note that this +% may be adjusted using \cs{driver_draw_cm:nnnn}: note that this % is transparent to the drawing code so is not tracked. % -% \begin{function}{\draw_transform_reset:} -% \begin{syntax} -% \cs{draw_transform_reset:} -% \end{syntax} -% Resets the matrix to the identity. -% \end{function} -% -% \begin{function}{\draw_transform_concat:nnnnn} +% \begin{function} +% {\draw_transform_matrix:nnnn, \draw_transform_matrix_concat:nnnn} % \begin{syntax} -% \cs{draw_transform_concat:nnnnn} -% \Arg{a} \Arg{b} \Arg{c} \Arg{d} \Arg{vector} +% \cs{draw_transform_matrix:nnnnn} +% \Arg{a} \Arg{b} \Arg{c} \Arg{d} % \end{syntax} -% Appends the given transformation to the currently-active one. The -% transformation is made up of a matrix \meta{a}, \meta{b}, \meta{c} and -% \meta{d}, and a shift by the \meta{vector}. +% Applies the transformation matrix $[ \meta{a} \meta{b} \meta{c} \meta{d}]$. +% The basic version over-writes the current matrix, the |concat| version +% concatenates. +% This assignment is local. % \end{function} % -% \begin{function}{\draw_transform:nnnnn} +% \begin{function}{\draw_transform_shift:n, \draw_transform_shift_concat:n} % \begin{syntax} -% \cs{draw_transform:nnnnn} -% \Arg{a} \Arg{b} \Arg{c} \Arg{d} \Arg{vector} +% \cs{draw_transform_shift:n} \Arg{vector} % \end{syntax} -% Applies the transformation matrix specified, over-writing any existing -% matrix. The transformation is made up of a matrix \meta{a}, \meta{b}, -% \meta{c} and \meta{d}, and a shift by the \meta{vector}. +% Applies the transformation \meta{vector} to points. The basic version +% over-writes the current vector, the |concat| version concatenates. +% This assignment is local. % \end{function} % % \begin{function}{\draw_transform_triangle:nnn} @@ -529,14 +1000,77 @@ % Applies a transformation such that the co-ordinates $(0, 0)$, $(1, 0)$ % and $(0, 1)$ are given by the \meta{origin}, \meta{point1} and % \meta{point2}, respectively. +% This assignment is local. +% \end{function} +% +% \begin{function}{\draw_transform_rotate:n} +% \begin{syntax} +% \cs{draw_transform_rotate:n} \Arg{angle} +% \end{syntax} +% Applies a rotation by the \meta{angle}, measured anti-clockwise in degrees. +% This rotation is \emph{additional} to any prevailing transformation. +% This assignment is local. % \end{function} % -% \begin{function}{\draw_transform_invert:} +% \begin{function} +% { +% \draw_transform_scale:n, +% \draw_transform_xscale:n, +% \draw_transform_xscale:n +% } +% \begin{syntax} +% \cs{draw_transform_scale:n} \Arg{scale} +% \end{syntax} +% Applies the \meta{scale} in either $x$ or $y$ (or both). +% This scale is \emph{added} to any prevailing transformation. +% This assignment is local. +% \end{function} +% +% \begin{function} +% { +% \draw_transform_xshift:n, +% \draw_transform_yshift:n +% } +% \begin{syntax} +% \cs{draw_transform_shift:n} \Arg{vector} +% \cs{draw_transform_xshift:n} \Arg{xshift} +% \end{syntax} +% Applies an \meta{xshift} or \meta{yshift}, as appropriate. This shift is +% \emph{added} to any prevailing one. +% This assignment is local. +% \end{function} +% +% \begin{function} +% { +% \draw_transform_xslant:n, +% \draw_transform_yslant:n +% } +% \begin{syntax} +% \cs{draw_transform_xslant:n} \Arg{slant} +% \end{syntax} +% Applies the \meta{slant} (a factor) in either $x$ or $y$. +% This slant is \emph{added} to any prevailing transformation. +% This assignment is local. +% \end{function} +% +% \begin{function} +% {\draw_transform_matrix_invert:, \draw_transform_shift_invert:} +% \begin{syntax} +% \cs{draw_transform_matrix_invert:} +% \end{syntax} +% Inverts the current transformation matrix or shift vector, as +% appropriate. +% This assignment is local. +% \end{function} +% +% \begin{function} +% {\draw_transform_matrix_reset, \draw_transform_shift_reset:} % \begin{syntax} -% \cs{draw_transform_invert:} +% \cs{draw_transform_matrix_reset:} % \end{syntax} -% Inverts the current transformation matrix and reverses the current -% shift vector. +% Resets the current transformation matrix or shift vector, as +% appropriate. +% This assignment is local. % \end{function} % % \end{documentation} @@ -555,7 +1089,7 @@ % % \begin{macrocode} %<*package> -\ProvidesExplPackage{l3draw}{2018/02/21}{} +\ProvidesExplPackage{l3draw}{2018/03/05}{} {L3 Experimental core drawing support} %</package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.ins b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.ins index d7c3616c607..e91015c2ba1 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.ins +++ b/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.ins @@ -54,6 +54,7 @@ and all files in that bundle must be distributed together. \generate{\file{l3draw.sty} { \from{l3draw.dtx} {package} + \from{l3draw-boxes.dtx} {package} \from{l3draw-paths.dtx} {package} \from{l3draw-points.dtx} {package} \from{l3draw-scopes.dtx} {package} diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-convert.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-convert.dtx index 5691eb65ec9..66a01368167 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-convert.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-convert.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: l3str-convert.dtx Copyright (C) 2013-2017 The LaTeX3 Project +%% File: l3str-convert.dtx Copyright (C) 2013-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -47,7 +47,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -252,7 +252,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{l3str-convert}{2018/02/21}{} +\ProvidesExplPackage{l3str-convert}{2018/03/05}{} {L3 Experimental string encoding conversions} % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx index 14f6874216c..8075162f725 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: l3str-format.dtx Copyright (C) 2012-2017 The LaTeX3 Project +%% File: l3str-format.dtx Copyright (C) 2012-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -47,7 +47,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -163,7 +163,7 @@ % % \begin{macrocode} %<*package> -\ProvidesExplPackage{l3str-format}{2018/02/21}{} +\ProvidesExplPackage{l3str-format}{2018/03/05}{} {L3 Experimental string formatting} %</package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx b/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx index dd801e51ae0..e4a7b5b12ea 100644 --- a/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx @@ -54,7 +54,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -673,7 +673,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xcoffins}{2018/02/21}{} +\ProvidesExplPackage{xcoffins}{2018/03/05}{} {L3 Experimental design level coffins} % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx b/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx index 7533b90e087..f0ff78ee457 100644 --- a/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx @@ -1,7 +1,7 @@ % \iffalse % %% File: l3galley.dtx Copyright (C) 1999-2001, 2004-2009 Frank Mittelbach -%% (C) 2010-2017 The LaTeX3 Project +%% (C) 2010-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -59,7 +59,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -685,7 +685,7 @@ % % \begin{macrocode} %<*package> -\ProvidesExplPackage{l3galley}{2018/02/21}{} +\ProvidesExplPackage{l3galley}{2018/03/05}{} {L3 Experimental galley code} %</package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx index d0e62a385c5..7c6dd9656a4 100644 --- a/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx @@ -1,7 +1,7 @@ % \iffalse % %% File: xgalley.dtx Copyright (C) 1999-2001, 2004-2009 Frank Mittelbach -%% (C) 2010-2012,2014,2016-2017 The LaTeX3 Project +%% (C) 2010-2012,2014,2016-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -45,7 +45,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -732,7 +732,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xgalley}{2018/02/21}{} +\ProvidesExplPackage{xgalley}{2018/03/05}{} {L3 Experimental galley} \RequirePackage{xparse,xtemplate,l3galley} % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx index 67af1e5da46..f001b8c12c1 100644 --- a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: expl3.dtx Copyright (C) 1990-2017 The LaTeX3 Project +%% File: expl3.dtx Copyright (C) 1990-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -21,7 +21,7 @@ % for those people who are interested. % %<*driver|generic|package> -\def\ExplFileDate{2018/02/21}% +\def\ExplFileDate{2018/03/05}% %</driver|generic|package> %<*driver> \documentclass[full]{l3doc} @@ -49,7 +49,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3.ins b/Master/texmf-dist/source/latex/l3kernel/l3.ins index e2db89df344..244c385eca5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3.ins +++ b/Master/texmf-dist/source/latex/l3kernel/l3.ins @@ -96,8 +96,8 @@ and all files in that bundle must be distributed together. \from{l3tl-analysis.dtx}{package} \from{l3regex.dtx} {package} \from{l3box.dtx} {package} - \from{l3coffins.dtx} {package} \from{l3color-base.dtx} {package} + \from{l3coffins.dtx} {package} \from{l3sys.dtx} {package} \from{l3deprecation.dtx}{package} \from{l3candidates.dtx} {package} @@ -125,31 +125,11 @@ and all files in that bundle must be distributed together. % old modules generating a usage error: -\generate{\file{l3basics.sty} {\from{l3oldmodules.dtx} {l3basics,oldmodules}}} -\generate{\file{l3bootstrap.sty} {\from{l3oldmodules.dtx} {l3bootstrap,oldmodules}}} -\generate{\file{l3box.sty} {\from{l3oldmodules.dtx} {l3box,oldmodules}}} -\generate{\file{l3candidates.sty} {\from{l3oldmodules.dtx} {l3candidates,oldmodules}}} -\generate{\file{l3clist.sty} {\from{l3oldmodules.dtx} {l3clist,oldmodules}}} -\generate{\file{l3coffins.sty} {\from{l3oldmodules.dtx} {l3coffins,oldmodules}}} -\generate{\file{l3expan.sty} {\from{l3oldmodules.dtx} {l3expan,oldmodules}}} -\generate{\file{l3file.sty} {\from{l3oldmodules.dtx} {l3file,oldmodules}}} -\generate{\file{l3fp.sty} {\from{l3oldmodules.dtx} {l3fp,oldmodules}}} -\generate{\file{l3int.sty} {\from{l3oldmodules.dtx} {l3int,oldmodules}}} -\generate{\file{l3keys.sty} {\from{l3oldmodules.dtx} {l3keys,oldmodules}}} -\generate{\file{l3msg.sty} {\from{l3oldmodules.dtx} {l3msg,oldmodules}}} -\generate{\file{l3names.sty} {\from{l3oldmodules.dtx} {l3names,oldmodules}}} -\generate{\file{l3prg.sty} {\from{l3oldmodules.dtx} {l3prg,oldmodules}}} -\generate{\file{l3prop.sty} {\from{l3oldmodules.dtx} {l3prop,oldmodules}}} -\generate{\file{l3quark.sty} {\from{l3oldmodules.dtx} {l3quark,oldmodules}}} \generate{\file{l3regex.sty} {\from{l3oldmodules.dtx} {l3regex,oldmodules}}} -\generate{\file{l3seq.sty} {\from{l3oldmodules.dtx} {l3seq,oldmodules}}} -\generate{\file{l3skip.sty} {\from{l3oldmodules.dtx} {l3skip,oldmodules}}} \generate{\file{l3sort.sty} {\from{l3oldmodules.dtx} {l3sort,oldmodules}}} \generate{\file{l3str.sty} {\from{l3oldmodules.dtx} {l3str,oldmodules}}} -\generate{\file{l3tl.sty} {\from{l3oldmodules.dtx} {l3tl,oldmodules}}} \generate{\file{l3tl-analysis.sty}{\from{l3oldmodules.dtx} {l3tl-analysis,oldmodules}}} \generate{\file{l3tl-build.sty} {\from{l3oldmodules.dtx} {l3tl-build,oldmodules}}} -\generate{\file{l3token.sty} {\from{l3oldmodules.dtx} {l3token,oldmodules}}} % Lua code diff --git a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx index 3edc736eeb9..e4928419daa 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx index 7b2b8bb3948..a1743469432 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx index f4c05b9ab39..63e80a95630 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx @@ -138,7 +138,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx index d214f8551e0..0ae3b450f40 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -1190,7 +1190,7 @@ % Put a horizontal box directly into the input stream. % \begin{macrocode} \cs_new_protected:Npn \hbox:n #1 - { \tex_hbox:D \scan_stop: { \group_begin: #1 \group_end: } } + { \tex_hbox:D \scan_stop: { \color_group_begin: #1 \color_group_end: } } % \end{macrocode} % \end{macro} % @@ -1200,10 +1200,13 @@ % \begin{macrocode} \__kernel_patch:nnNNpn { \__kernel_chk_var_local:N #1 } { } \cs_new_protected:Npn \hbox_set:Nn #1#2 - { \tex_setbox:D #1 \tex_hbox:D { \group_begin: #2 \group_end: } } + { \tex_setbox:D #1 \tex_hbox:D { \color_group_begin: #2 \color_group_end: } } \__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { } \cs_new_protected:Npn \hbox_gset:Nn #1#2 - { \tex_global:D \tex_setbox:D #1 \tex_hbox:D { \group_begin: #2 \group_end: } } + { + \tex_global:D \tex_setbox:D #1 \tex_hbox:D + { \color_group_begin: #2 \color_group_end: } + } \cs_generate_variant:Nn \hbox_set:Nn { c } \cs_generate_variant:Nn \hbox_gset:Nn { c } % \end{macrocode} @@ -1220,13 +1223,13 @@ \cs_new_protected:Npn \hbox_set_to_wd:Nnn #1#2#3 { \tex_setbox:D #1 \tex_hbox:D to \__dim_eval:n {#2} - { \group_begin: #3 \group_end: } + { \color_group_begin: #3 \color_group_end: } } \__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { } \cs_new_protected:Npn \hbox_gset_to_wd:Nnn #1#2#3 { \tex_global:D \tex_setbox:D #1 \tex_hbox:D to \__dim_eval:n {#2} - { \group_begin: #3 \group_end: } + { \color_group_begin: #3 \color_group_end: } } \cs_generate_variant:Nn \hbox_set_to_wd:Nnn { c } \cs_generate_variant:Nn \hbox_gset_to_wd:Nnn { c } @@ -1246,20 +1249,20 @@ { \tex_setbox:D #1 \tex_hbox:D \c_group_begin_token - \group_begin: + \color_group_begin: } \__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { } \cs_new_protected:Npn \hbox_gset:Nw #1 { \tex_global:D \tex_setbox:D #1 \tex_hbox:D \c_group_begin_token - \group_begin: + \color_group_begin: } \cs_generate_variant:Nn \hbox_set:Nw { c } \cs_generate_variant:Nn \hbox_gset:Nw { c } \cs_new_protected:Npn \hbox_set_end: { - \group_end: + \color_group_end: \c_group_end_token } \cs_new_eq:NN \hbox_gset_end: \hbox_set_end: @@ -1277,14 +1280,14 @@ { \tex_setbox:D #1 \tex_hbox:D to \__dim_eval:n {#2} \c_group_begin_token - \group_begin: + \color_group_begin: } \__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { } \cs_new_protected:Npn \hbox_gset_to_wd:Nnw #1#2 { \tex_global:D \tex_setbox:D #1 \tex_hbox:D to \__dim_eval:n {#2} \c_group_begin_token - \group_begin: + \color_group_begin: } \cs_generate_variant:Nn \hbox_set_to_wd:Nnw { c } \cs_generate_variant:Nn \hbox_gset_to_wd:Nnw { c } @@ -1300,10 +1303,10 @@ \cs_new_protected:Npn \hbox_to_wd:nn #1#2 { \tex_hbox:D to \__dim_eval:n {#1} - { \group_begin: #2 \group_end: } + { \color_group_begin: #2 \color_group_end: } } \cs_new_protected:Npn \hbox_to_zero:n #1 - { \tex_hbox:D to \c_zero_dim { \group_begin: #1 \group_end: } } + { \tex_hbox:D to \c_zero_dim { \color_group_begin: #1 \color_group_end: } } % \end{macrocode} % \end{macro} % \end{macro} @@ -1345,9 +1348,9 @@ % Put a vertical box directly into the input stream. % \begin{macrocode} \cs_new_protected:Npn \vbox:n #1 - { \tex_vbox:D { \group_begin: #1 \par \group_end: } } + { \tex_vbox:D { \color_group_begin: #1 \color_group_end: } } \cs_new_protected:Npn \vbox_top:n #1 - { \tex_vtop:D { \group_begin: #1 \par \group_end: } } + { \tex_vtop:D { \color_group_begin: #1 \color_group_end: } } % \end{macrocode} % \end{macro} % \end{macro} @@ -1360,12 +1363,12 @@ \cs_new_protected:Npn \vbox_to_ht:nn #1#2 { \tex_vbox:D to \__dim_eval:n {#1} - { \group_begin: #2 \par \group_end: } + { \color_group_begin: #2 \color_group_end: } } \cs_new_protected:Npn \vbox_to_zero:n #1 { \tex_vbox:D to \c_zero_dim - { \group_begin: #1 \par \group_end: } + { \color_group_begin: #1 \color_group_end: } } % \end{macrocode} % \end{macro} @@ -1380,13 +1383,13 @@ \cs_new_protected:Npn \vbox_set:Nn #1#2 { \tex_setbox:D #1 \tex_vbox:D - { \group_begin: #2 \par \group_end: } + { \color_group_begin: #2 \color_group_end: } } \__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { } \cs_new_protected:Npn \vbox_gset:Nn #1#2 { \tex_global:D \tex_setbox:D #1 \tex_vbox:D - { \group_begin: #2 \par \group_end: } + { \color_group_begin: #2 \color_group_end: } } \cs_generate_variant:Nn \vbox_set:Nn { c } \cs_generate_variant:Nn \vbox_gset:Nn { c } @@ -1404,13 +1407,13 @@ \cs_new_protected:Npn \vbox_set_top:Nn #1#2 { \tex_setbox:D #1 \tex_vtop:D - { \group_begin: #2 \par \group_end: } + { \color_group_begin: #2 \color_group_end: } } \__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { } \cs_new_protected:Npn \vbox_gset_top:Nn #1#2 { \tex_global:D \tex_setbox:D #1 \tex_vtop:D - { \group_begin: #2 \par \group_end: } + { \color_group_begin: #2 \color_group_end: } } \cs_generate_variant:Nn \vbox_set_top:Nn { c } \cs_generate_variant:Nn \vbox_gset_top:Nn { c } @@ -1427,13 +1430,13 @@ \cs_new_protected:Npn \vbox_set_to_ht:Nnn #1#2#3 { \tex_setbox:D #1 \tex_vbox:D to \__dim_eval:n {#2} - { \group_begin: #3 \par \group_end: } + { \color_group_begin: #3 \color_group_end: } } \__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { } \cs_new_protected:Npn \vbox_gset_to_ht:Nnn #1#2#3 { \tex_global:D \tex_setbox:D #1 \tex_vbox:D to \__dim_eval:n {#2} - { \group_begin: #3 \par \group_end: } + { \color_group_begin: #3 \color_group_end: } } \cs_generate_variant:Nn \vbox_set_to_ht:Nnn { c } \cs_generate_variant:Nn \vbox_gset_to_ht:Nnn { c } @@ -1453,21 +1456,20 @@ { \tex_setbox:D #1 \tex_vbox:D \c_group_begin_token - \group_begin: + \color_group_begin: } \__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { } \cs_new_protected:Npn \vbox_gset:Nw #1 { \tex_global:D \tex_setbox:D #1 \tex_vbox:D \c_group_begin_token - \group_begin: + \color_group_begin: } \cs_generate_variant:Nn \vbox_set:Nw { c } \cs_generate_variant:Nn \vbox_gset:Nw { c } \cs_new_protected:Npn \vbox_set_end: { - \par - \group_end: + \color_group_end: \c_group_end_token } \cs_new_eq:NN \vbox_gset_end: \vbox_set_end: @@ -1485,14 +1487,14 @@ { \tex_setbox:D #1 \tex_vbox:D to \__dim_eval:n {#2} \c_group_begin_token - \group_begin: + \color_group_begin: } \__kernel_patch:nnNNpn { \__kernel_chk_var_global:N #1 } { } \cs_new_protected:Npn \vbox_gset_to_ht:Nnw #1#2 { \tex_global:D \tex_setbox:D #1 \tex_vbox:D to \__dim_eval:n {#2} \c_group_begin_token - \group_begin: + \color_group_begin: } \cs_generate_variant:Nn \vbox_set_to_ht:Nnw { c } \cs_generate_variant:Nn \vbox_gset_to_ht:Nnw { c } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx index e8d226189ac..3208f1ec9bb 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -1862,28 +1862,6 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[deprecated = 2017-12-31]{\file_if_exist_input:nT, \file_if_exist_input:nTF} -% For removal after 2017-12-31. -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2017-12-31 } - { \file_if_exist:nTF and~ \file_input:n } -\cs_new_protected:Npn \file_if_exist_input:nTF #1#2#3 - { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NTF \l_@@_full_name_str - {#3} { #2 \@@_input:V \l_@@_full_name_str } - } -\__kernel_patch_deprecation:nnNNpn { 2017-12-31 } - { \file_if_exist:nT and~ \file_input:n } -\cs_new_protected:Npn \file_if_exist_input:nT #1#2 - { - \file_get_full_name:nN {#1} \l_@@_full_name_str - \str_if_empty:NF \l_@@_full_name_str - { #2 \@@_input:V \l_@@_full_name_str } - } -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\file_input_stop:} % A simple rename. % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx index 431df952a3c..a11c54cb818 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx index db42fb4981b..42b8793c0d5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: l3coffins.dtx Copyright(C) 2010-2017 The LaTeX3 Project +%% File: l3coffins.dtx Copyright(C) 2010-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -175,7 +175,7 @@ % ~~\meta{coffin_2} \Arg{coffin_2-pole_1} \Arg{coffin_2-pole_2} % ~~\Arg{x-offset} \Arg{y-offset} % \end{syntax} -% This function attaches <coffin_2> to <coffin_1> such that the bounding box +% This function attaches \meta{coffin_2} to \meta{coffin_1} such that the bounding box % of \meta{coffin_1} is not altered, \emph{i.e.}~\meta{coffin_2} can % protrude outside of the bounding box of the coffin. The alignment % is carried out by first calculating \meta{handle_1}, the @@ -199,7 +199,7 @@ % ~~\meta{coffin_2} \Arg{coffin_2-pole_1} \Arg{coffin_2-pole_2} % ~~\Arg{x-offset} \Arg{y-offset} % \end{syntax} -% This function joins <coffin_2> to <coffin_1> such that the bounding box +% This function joins \meta{coffin_2} to \meta{coffin_1} such that the bounding box % of \meta{coffin_1} may expand. The new bounding % box covers the area containing the bounding boxes of the two % original coffins. The alignment is carried out by first calculating @@ -684,12 +684,11 @@ % Special coffins: these cannot be set up earlier as they need % \cs{coffin_new:N}. The empty coffin is set as a box as the full % coffin-setting system needs some material which is not yet available. -% Debugging must be suspended as we are assigning to a constant coffin. +% The empty coffin is creted entirely by hand: not everything is in place +% yet. % \begin{macrocode} \coffin_new:N \c_empty_coffin -\debug_suspend: -\hbox_set:Nn \c_empty_coffin { } -\debug_resume: +\tex_setbox:D \c_empty_coffin = \tex_hbox:D { } \coffin_new:N \l_@@_aligned_coffin \coffin_new:N \l_@@_aligned_internal_coffin % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx b/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx index b3e88c1a7ee..8e294d166ab 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -147,7 +147,6 @@ \driver_color_pickup:N \l_@@_current_tl %</package> \@@_select:V \l_@@_current_tl - \group_insert_after:N \driver_color_reset: } % \end{macrocode} % \end{macro} @@ -161,7 +160,7 @@ % higher-level experimental material. % \begin{macrocode} \cs_new_protected:Npn \@@_select:n #1 - { \@@_select:w #1 \q_stop } + { \@@_select:w #1 \q_stop } \cs_generate_variant:Nn \@@_select:n { V } \cs_new_protected:Npn \@@_select:w #1 ~ #2 \q_stop { \use:c { @@_select_ #1 :w } #2 \q_stop } @@ -181,9 +180,7 @@ % \begin{variable}{\l_@@_current_tl} % As the setting data is used only % for specials, and those are always space-separated, it makes most sense to -% hold the internal information in that form. Any splitting is done by a -% delimited function but often the entire \texttt{tl} can be used as-is: -% see \texttt{l3drivers.dtx}. +% hold the internal information in that form. % \begin{macrocode} \tl_new:N \l_@@_current_tl \tl_set:Nn \l_@@_current_tl { gray~0 } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx index 1ab74d3b67b..95664eb799d 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -83,6 +83,8 @@ { \tl_to_str:n {#3} } { \token_to_str:N #1 } { \tl_to_str:n {#2} } } } +\@@_error:Nnn \file_if_exist_input:nT { \file_if_exist:nT and~ \file_input:n } { 2018-03-05 } +\@@_error:Nnn \file_if_exist_input:nTF { \file_if_exist:nT and~ \file_input:n } { 2018-03-05 } \@@_error:Nnn \c_job_name_tl { \c_sys_jobname_str } { 2017-01-01 } \@@_error:Nnn \dim_case:nnn { \dim_case:nnF } { 2015-07-14 } \@@_error:Nnn \int_case:nnn { \int_case:nnF } { 2015-07-14 } @@ -92,6 +94,7 @@ \@@_error:Nnn \int_to_binary:n { \int_to_bin:n } { 2016-01-05 } \@@_error:Nnn \int_to_hexadecimal:n { \int_to_hex:n } { 2016-01-05 } \@@_error:Nnn \int_to_octal:n { \int_to_oct:n } { 2016-01-05 } +\@@_error:Nnn \ior_get_str:NN { \ior_str_get:NN } { 2018-03-05 } \@@_error:Nnn \luatex_if_engine_p: { \sys_if_engine_luatex_p: } { 2017-01-01 } \@@_error:Nnn \luatex_if_engine:F { \sys_if_engine_luatex:F } { 2017-01-01 } \@@_error:Nnn \luatex_if_engine:T { \sys_if_engine_luatex:T } { 2017-01-01 } @@ -110,6 +113,8 @@ \@@_error:Nnn \str_case_x:nnn { \str_case_x:nnF } { 2015-07-14 } \@@_error:Nnn \tl_case:cnn { \tl_case:cnF } { 2015-07-14 } \@@_error:Nnn \tl_case:Nnn { \tl_case:NnF } { 2015-07-14 } +\@@_error:Nnn \tl_to_lowercase:n { \tex_lowercase:D } { 2018-03-05 } +\@@_error:Nnn \tl_to_uppercase:n { \tex_uppercase:D } { 2018-03-05 } \@@_error:Nnn \xetex_if_engine_p: { \sys_if_engine_xetex_p: } { 2017-01-01 } \@@_error:Nnn \xetex_if_engine:F { \sys_if_engine_xetex:F } { 2017-01-01 } \@@_error:Nnn \xetex_if_engine:T { \sys_if_engine_xetex:T } { 2017-01-01 } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx index 4341ff018a1..711873fe192 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx @@ -70,14 +70,14 @@ and all files in that bundle must be distributed together. % This isn't included in the typeset documentation because it's a bit % ugly: %<*class> -\ProvidesExplClass{l3doc}{2018/02/21}{} +\ProvidesExplClass{l3doc}{2018/03/05}{} {L3 Experimental documentation class} %</class> % \fi % % \title{The \cls{l3doc} class} % \author{\Team} -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % \maketitle % \tableofcontents % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx index 5295a5553fd..d52e130284f 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx @@ -61,7 +61,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx index 8b5aa7d53c1..242bc86790c 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: l3drivers.dtx Copyright(C) 2011-2017 The LaTeX3 Project +%% File: l3drivers.dtx Copyright(C) 2011-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -129,7 +129,7 @@ % \end{syntax} % Sets the color to the CMYK values specified, all of which are % fp denotations in the range $0$ and $1$. For drawing colors, see -% \cs{driver_draw_color_cmyk:nnnn}, \emph{etc.} +% \cs{driver_draw_stroke_cmyk:nnnn}, \emph{etc.} % \end{function} % % \begin{function}[added = 2018-02-20]{\driver_color_gray:n} @@ -138,7 +138,7 @@ % \end{syntax} % Sets the color to the grayscale value specified, which is % fp denotations in the range $0$ and $1$. For drawing colors, see -% \cs{driver_draw_color_gray:n}, \emph{etc.} +% \cs{driver_draw_stroke_gray:n}, \emph{etc.} % \end{function} % % \begin{function}[added = 2018-02-20]{\driver_color_rgb:nnn} @@ -147,20 +147,7 @@ % \end{syntax} % Sets the color to the RGB values specified, all of which are % fp denotations in the range $0$ and $1$. For drawing colors, see -% \cs{driver_draw_color_rgb:nnn}, \emph{etc.} -% \end{function} -% -% \begin{function}[added = 2018-02-20]{\driver_color_reset:} -% \begin{syntax} -% \cs{driver_color_reset:} -% \end{syntax} -% Resets the active color to that before a call to -% \cs{driver_color_\meta{model}:n(nnn)}. This function should be inserted -% after the \TeX{} group setting a color, \emph{i.e.}~normally -% \begin{verbatim} -% % Use of \driver_color_rgb:nnn, etc. -% \group_insert_after:N \driver_color_reset: -% \end{verbatim} +% \cs{driver_draw_stroke_rgb:nnn}, \emph{etc.} % \end{function} % % \begin{function}[added = 2018-02-20]{\driver_color_pickup:N} @@ -404,58 +391,46 @@ % % \begin{function} % { -% \driver_draw_color_cmyk:nnnn , -% \driver_draw_fill_cmyk:nnnn , -% \driver_draw_stroke_cmyk:nnnn +% \driver_draw_color_fill_cmyk:nnnn , +% \driver_draw_color_stroke_cmyk:nnnn % } % \begin{syntax} -% \cs{driver_draw_color_cmyk:nnnn} \Arg{cyan} \Arg{magenta} \Arg{yellow} +% \cs{driver_draw_color_fill_cmyk:nnnn} \Arg{cyan} \Arg{magenta} \Arg{yellow} % \Arg{black} % \end{syntax} % Sets the color for drawing to the CMYK values specified, all of which are -% fp denotations in the range $0$ and $1$. The -% \texttt{fill} and \texttt{stroke} versions set only the color for those -% operations. Note that the general setting is more efficient with some -% drivers so should in most cases be preferred. +% fp denotations in the range $0$ and $1$. % \end{function} % % \begin{function} % { -% \driver_draw_color_gray:n , -% \driver_draw_fill_gray:n , -% \driver_draw_stroke_gray:n +% \driver_draw_color_fill_gray:n , +% \driver_draw_color_stroke_gray:n % } % \begin{syntax} -% \cs{driver_draw_color_gray:n} \Arg{gray} +% \cs{driver_draw_color_fill_gray:n} \Arg{gray} % \end{syntax} % Sets the color for drawing to the grayscale value specified, which is -% fp denotations in the range $0$ and $1$. The -% \texttt{fill} and \texttt{stroke} versions set only the color for those -% operations. Note that the general setting is more efficient with some -% drivers so should in most cases be preferred. +% fp denotations in the range $0$ and $1$. % \end{function} % % \begin{function} % { -% \driver_draw_color_rgb:nnn , -% \driver_draw_fill_rgb:nnn , -% \driver_draw_stroke_rgb:nnn +% \driver_draw_color_fill_rgb:nnn , +% \driver_draw_color_stroke_rgb:nnn % } % \begin{syntax} -% \cs{driver_draw_color_rgb:nnn} \Arg{red} \Arg{green} \Arg{blue} +% \cs{driver_draw_color_fill_rgb:nnn} \Arg{red} \Arg{green} \Arg{blue} % \end{syntax} % Sets the color for drawing to the RGB values specified, all of which are -% fp denotations in the range $0$ and $1$. The -% \texttt{fill} and \texttt{stroke} versions set only the color for those -% operations. Note that the general setting is more efficient with some -% drivers so should in most cases be preferred. +% fp denotations in the range $0$ and $1$. % \end{function} % % \subsection{Inserting \TeX{} material} % -% \begin{function}{\driver_draw_hbox:Nnnnnnn} +% \begin{function}{\driver_draw_box_use:Nnnnn} % \begin{syntax} -% \cs{driver_draw_hbox:Nnnnnnn} \meta{box} +% \cs{driver_draw_box:Nnnnnnn} \meta{box} % \Arg{a} \Arg{b} \Arg{c} \Arg{d} \Arg{x} \Arg{y} % \end{syntax} % Inserts the \meta{box} as an hbox with the box reference point placed @@ -469,14 +444,13 @@ % % \subsection{Coordinate system transformations} % -% \begin{function}{\driver_draw_transformcm:nnnnnn} +% \begin{function}{\driver_draw_cm:nnnn} % \begin{syntax} -% \cs{driver_draw_transformcm:nnnnnn} \Arg{a} \Arg{b} \Arg{c} \Arg{d} -% \Arg{x} \Arg{y} +% \cs{driver_draw_cm:nnnn} \Arg{a} \Arg{b} \Arg{c} \Arg{d} % \end{syntax} -% Applies the transformation matrix $[a b c d]$ and offset vector -% ($x$, $y$) to the current graphic state. This affects any subsequent -% items in the same scope but not those already given. +% Applies the transformation matrix $[a b c d]$ to the current graphic state. +% This affects any subsequent items in the same scope but not those already +% given. % \end{function} % % \end{documentation} @@ -537,9 +511,13 @@ % % \subsection{Color support} % +% Color support is split into two parts: a \enquote{general} concept and +% one directly linked to drawings (or rather the split between filling +% and stroking). General color is relatively easy to handle: we have a color +% stack available with all modern drivers, and can use that.% % Whilst \texttt{(x)dvipdfmx} does have its own approach to color specials, % it is easier to use \texttt{dvips}-like ones for all cases except direct -% PDF output. As such the color code is collected here in two blocks. +% PDF output. % % \subsubsection{\texttt{dvips}-style} % @@ -586,8 +564,9 @@ % \begin{macro}{\driver_color_rgb:nnn} % \begin{macro}{\driver_color_spot:nn} % \begin{macro}{\@@_color_select:n} -% \begin{macro}{\driver_color_reset:} -% Simply dump the data. +% \begin{macro}{\@@_color_reset:} +% Push the data to the stack. In the case of \texttt{dvips} also reset the +% drawing fill color in raw PostScript. % \begin{macrocode} \cs_new_protected:Npn \driver_color_cmyk:nnnn #1#2#3#4 { \@@_color_select:n { cmyk~ #1 ~ #2 ~ #3 ~ #4 } } @@ -596,10 +575,16 @@ \cs_new_protected:Npn \driver_color_rgb:nnn #1#2#3 { \@@_color_select:n { rgb~ #1 ~ #2 ~ #3 } } \cs_new_protected:Npn \driver_color_spot:nn #1#2 - { \@@_color_select:n { color~push~\c_space_tl #1 } } + { \@@_color_select:n { \c_space_tl #1 } } \cs_new_protected:Npn \@@_color_select:n #1 - { \tex_special:D { color~push~ #1 } } -\cs_new_protected:Npn \driver_color_reset: + { + \tex_special:D { color~push~ #1 } +%<*dvips> + \tex_special:D { ps::/l3fc~{ }~def } +%</dvips> + \group_insert_after:N \@@_color_reset: + } +\cs_new_protected:Npn \@@_color_reset: { \tex_special:D { color~pop } } % \end{macrocode} % \end{macro} @@ -683,7 +668,7 @@ % \begin{macro}{\driver_color_rgb:nnn} % \begin{macro}{\driver_color_spot:nn} % \begin{macro}{\@@_color_select:n} -% \begin{macro}{\driver_color_reset:} +% \begin{macro}{\@@_color_reset:} % Simply dump the data, but allowing for \LuaTeX{}. % \begin{macrocode} \cs_new_protected:Npn \driver_color_cmyk:nnnn #1#2#3#4 @@ -700,8 +685,9 @@ { \luatex_pdfextension:D colorstack } { \pdftex_pdfcolorstack:D } \exp_not:N \l_@@_color_stack_int push {#1} + \group_insert_after:N \exp_not:N \@@_color_reset: } -\cs_new_protected:Npx \driver_color_reset: +\cs_new_protected:Npx \@@_color_reset: { \cs_if_exist:NTF \luatex_pdfextension:D { \luatex_pdfextension:D colorstack } @@ -877,7 +863,7 @@ % here). % \begin{macrocode} \cs_new_protected:Npn \@@_draw_literal:n #1 - { \tex_special:D { ps:: ~ #1 } } + { \tex_special:D { ps:: #1 } } \cs_generate_variant:Nn \@@_draw_literal:n { x } % \end{macrocode} % \end{macro} @@ -892,16 +878,17 @@ % \begin{macrocode} \cs_new_protected:Npn \driver_draw_begin: { - \tex_special:D { ps::[begin] } - \tex_special:D { ps::~save } - \tex_special:D { ps::~/l3x~currentpoint~/l3y~exch~def~def } - \tex_special:D { ps::~@beginspecial } + \@@_draw_literal:n { [begin] } + \@@_draw_literal:n { save } + \@@_draw_literal:n { /l3x~currentpoint~/l3y~exch~def~def } + \@@_draw_literal:n { @beginspecial } + \@@_draw_literal:n { /l3fc~{ }~def } } \cs_new_protected:Npn \driver_draw_end: { - \tex_special:D { ps::~@endspecial } - \tex_special:D { ps::~restore } - \tex_special:D { ps::[end] } + \@@_draw_literal:n { @endspecial } + \@@_draw_literal:n { restore } + \@@_draw_literal:n { [end] } } % \end{macrocode} % \end{macro} @@ -987,21 +974,17 @@ % \begin{variable}{\g_@@_draw_clip_bool} % Unlike PDF, PostScript doesn't track separate colors for strokes and other % elements. It is also desirable to have the |clip| keyword after a stroke or -% fill. To achieve those outcomes, there is some work to do. For color, if a -% stroke or fill color is defined it is used for the relevant operation, with -% a graphic scope inserted as required. That does mean that once such a color -% is set all further uses inside the same scope have to use scoping: see also -% the color set up functions. For clipping, the required ordering is achieved -% using a \TeX{} switch. All of the operations end with a new path instruction -% as they do not terminate (again in contrast to PDF). +% fill. To achieve those outcomes, there is some work to do. For color, the +% stoke color is simple but the fill one has to be inserted by hand. For +% clipping, the required ordering is achieved using a \TeX{} switch. All of +% the operations end with a new path instruction as they do not terminate +% (again in contrast to PDF). % \begin{macrocode} \cs_new_protected:Npn \driver_draw_closepath: { \@@_draw_literal:n { closepath } } \cs_new_protected:Npn \driver_draw_stroke: { - \@@_draw_literal:n { currentdict~/l3sc~known~{gsave~l3sc}~if } - \@@_draw_literal:n { stroke } - \@@_draw_literal:n { currentdict~/l3sc~known~{grestore}~if } + \@@_draw_literal:n { stroke } \bool_if:NT \g_@@_draw_clip_bool { \@@_draw_literal:x @@ -1020,13 +1003,14 @@ } \cs_new_protected:Npn \driver_draw_fill: { - \@@_draw_literal:n { currentdict~/l3fc~known~{gsave~l3fc}~if } + \@@_draw_literal:n { gsave } + \@@_draw_literal:n { l3fc } \@@_draw_literal:x { \bool_if:NT \g_@@_draw_eor_bool { eo } fill } - \@@_draw_literal:n { currentdict~/l3fc~known~{grestore}~if } + \@@_draw_literal:n { grestore } \bool_if:NT \g_@@_draw_clip_bool { \@@_draw_literal:x @@ -1040,16 +1024,15 @@ } \cs_new_protected:Npn \driver_draw_fillstroke: { - \@@_draw_literal:n { currentdict~/l3fc~known~{gsave~l3fc}~if } + \@@_draw_literal:n { gsave } + \@@_draw_literal:n { l3fc } \@@_draw_literal:x { \bool_if:NT \g_@@_draw_eor_bool { eo } fill } - \@@_draw_literal:n { currentdict~/l3fc~known~{grestore}~if } - \@@_draw_literal:n { currentdict~/l3sc~known~{gsave~l3sc}~if } + \@@_draw_literal:n { grestore } \@@_draw_literal:n { stroke } - \@@_draw_literal:n { currentdict~/l3sc~known~{grestore}~if } \bool_if:NT \g_@@_draw_clip_bool { \@@_draw_literal:x @@ -1131,73 +1114,46 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\_@@_draw_color_reset:} +% % \begin{macro} % { -% \driver_draw_color_cmyk:nnnn , -% \driver_draw_fill_cmyk:nnnn , -% \driver_draw_stroke_cmyk:nnnn +% \driver_draw_color_fill_cmyk:nnnn , +% \driver_draw_color_stroke_cmyk:nnnn % } % \begin{macro} % { -% \driver_draw_color_gray:n , -% \driver_draw_fill_gray:n , -% \driver_draw_stroke_gray:n +% \driver_draw_color_fill_gray:n , +% \driver_draw_color_stroke_gray:n % } % \begin{macro} % { -% \driver_draw_color_rgb:nnn , -% \driver_draw_fill_rgb:nnn , -% \driver_draw_stroke_rgb:nnn +% \driver_draw_color_fill_rgb:nnn , +% \driver_draw_color_stroke_rgb:nnn % } -% To allow color to be defined for strokes and fills separately and to -% respect scoping, the data needs to be stored at the PostScript level. -% We cannot undefine (local) fill/stroke colors once set up but we can -% set them blank to improve performance slightly. +% \begin{macro}{\@@_draw_color_fill:n, \@@_draw_color_stroke:n} +% For \texttt{dvips}, we can use the standard color stack to deal with +% stroke color, but for fills have to switch to raw PostScript. This is +% thus not handled by the stack, but the context is very restricted. See +% also how fills are implemented. % \begin{macrocode} -\cs_new_protected:Npn \@@_draw_color_reset: - { - \@@_draw_literal:n { currentdic~/l3fc~known~{ /l3fc~ { } ~def }~if } - \@@_draw_literal:n { currentdic~/l3sc~known~{ /l3sc~ { } ~def }~if } - } -\cs_new_protected:Npn \driver_draw_color_cmyk:nnnn #1#2#3#4 - { - \@@_draw_literal:n { #1 ~ #2 ~ #3 ~ #4 ~ setcmykcolor } - \@@_draw_color_reset: - } -\cs_new_protected:Npn \driver_draw_fill_cmyk:nnnn #1#2#3#4 - { - \@@_draw_literal:n - { /l3fc ~ { #1 ~ #2 ~ #3 ~ #4 ~ setcmykcolor ~ } ~ def } - } -\cs_new_protected:Npn \driver_draw_stroke_cmyk:nnnn #1#2#3#4 +\cs_new_protected:Npn \driver_draw_color_fill_cmyk:nnnn #1#2#3#4 + { \@@_draw_fill:n { #1 ~ #2 ~ #3 ~ #4 ~ setcmykcolor } } +\cs_new_protected:Npn \driver_draw_color_stroke_cmyk:nnnn #1#2#3#4 + { \@@_draw_stroke:n { cmyk ~ #1 ~ #2 ~ #3 ~ #4 } } +\cs_new_protected:Npn \driver_draw_color_fill_gray:n #1 + { \@@_draw_fill:n { #1 ~ setgray } } +\cs_new_protected:Npn \driver_draw_color_stroke_gray:n #1 + { \@@_draw_stroke:n { gray ~ #1 } } +\cs_new_protected:Npn \driver_draw_color_fill_rgb:nnn #1#2#3 + { \@@_draw_fill:n { #1 ~ #2 ~ #3 ~ setrgbcolor } } +\cs_new_protected:Npn \driver_draw_color_stroke_rgb:nnn #1#2#3 + { \@@_draw_stroke:n { rgb ~ #1 ~ #2 ~ #3 } } +\cs_new_protected:Npn \@@_draw_color_fill:n #1 + { \@@_draw_literal:n { /l3fc ~ { #1 } ~ def } } +\cs_new_protected:Npn \@@_draw_color_stroke:n #1 { - \@@_draw_literal:n - { /l3sc ~ { #1 ~ #2 ~ #3 ~ #4 ~ setcmykcolor ~ } ~ def } - } -\cs_new_protected:Npn \driver_draw_color_gray:n #1 - { - \@@_draw_literal:n { #1 ~ setgray } - \@@_draw_color_reset: - } -\cs_new_protected:Npn \driver_draw_fill_gray:n #1 - { \@@_draw_literal:n { /l3fc ~ { #1 ~ setgray } ~ def } } -\cs_new_protected:Npn \driver_draw_stroke_gray:n #1 - { \@@_draw_literal:n { /l3sc ~ { #1 ~ setgray } ~ def } } -\cs_new_protected:Npn \driver_draw_color_rgb:nnn #1#2#3 - { - \@@_draw_literal:n { #1 ~ #2 ~ #3 ~ setrgbcolor } - \@@_draw_color_reset: - } -\cs_new_protected:Npn \driver_draw_fill_rgb:nnn #1#2#3 - { - \@@_draw_literal:n - { /l3fc ~ { #1 ~ #2 ~ #3 ~ setrgbcolor } ~ def } - } -\cs_new_protected:Npn \driver_draw_stroke_rgb:nnn #1#2#3 - { - \@@_draw_literal:n - { /l3sc ~ { #1 ~ #2 ~ #3 ~ setrgbcolor } ~ def } + \tex_special:D { color~push~#1 } + \group_insert_after:N \@@_color_reset: } % \end{macrocode} % \end{macro} @@ -1205,26 +1161,19 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\driver_draw_transformcm:nnnnnn} -% The first four arguments here are floats (the affine matrix), the last -% two are a displacement vector. Once again, force evaluation to allow for -% caching. +% \begin{macro}{\driver_draw_cm:nnnn} +% In \texttt{dvips}, keeping the transformations in line with the engine +% is unfortunately not possible for scaling and rotations: even if we +% decompose the matrix into those operations, there is still no driver +% tracking (\emph{cf.}~\texttt{(x)dvipdfmx}). Thus we take the shortest +% path available and simply dump the matrix as given. % \begin{macrocode} -\cs_new_protected:Npn \driver_draw_transformcm:nnnnnn #1#2#3#4#5#6 - { - \@@_draw_literal:x - { - [ - #1 ~ #2 ~ #3 ~ #4 ~ - \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~ - ] ~ - concat - } - } +\cs_new_protected:Npn \driver_draw_cm:nnnn #1#2#3#4 + { \@@_draw_literal:n { [#1 ~ #2 ~ #3 ~ #4 ~ 0 ~ 0 ] ~ concat } } % \end{macrocode} % \end{macro} % -% \begin{macro}{\driver_draw_hbox:Nnnnnnn} +% \begin{macro}{\driver_draw_box_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 @@ -1234,19 +1183,16 @@ % 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_box_use:Nnnnn #1#2#3#4#5 { \@@_scope_begin: - \tex_special:D { ps::[end] } - \driver_draw_transformcm:nnnnnn {#2} {#3} {#4} {#5} {#6} {#7} - \tex_special:D { ps::~72~Resolution~div~72~VResolution~div~neg~scale } - \tex_special:D { ps::~magscale~{1~DVImag~div~dup~scale}~if } - \tex_special:D { ps::~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 - \tex_special:D { ps::[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 } + \hbox_overlap_right:n { \box_use:N #1 } + \@@_draw_literal:n { [begin] } \@@_scope_end: } % \end{macrocode} @@ -2053,75 +1999,200 @@ % % \begin{macro} % { -% \driver_draw_color_cmyk:nnnn , -% \driver_draw_fill_cmyk:nnnn , -% \driver_draw_stroke_cmyk:nnnn +% \driver_draw_color_fill_cmyk:nnnn , +% \driver_draw_color_stroke_cmyk:nnnn % } % \begin{macro} % { -% \driver_draw_color_gray:n , -% \driver_draw_fill_gray:n , -% \driver_draw_stroke_gray:n +% \driver_draw_color_fill_gray:n , +% \driver_draw_color_stroke_gray:n % } % \begin{macro} % { -% \driver_draw_color_rgb:nnn , -% \driver_draw_fill_rgb:nnn , -% \driver_draw_stroke_rgb:nnn +% \driver_draw_color_fill_rgb:nnn , +% \driver_draw_color_stroke_rgb:nnn % } -% Yet more fast conversion, all using the FPU to allow for expressions -% in numerical input. +% For the stroke color, all engines here can use the color stack to handle +% the setting. However, that is not the case for fill color: the stack in +% \texttt{(x)dvipdfmx} only covers one type of color. So we have to use +% different approaches for the two sets of engines. +% \begin{macrocode} +\cs_new_protected:Npn \driver_draw_color_fill_cmyk:nnnn #1#2#3#4 + { \@@_color_fill_select:n { #1 ~ #2 ~ #3 ~ #4 ~ k } } +\cs_new_protected:Npn \driver_draw_color_stroke_cmyk:nnnn #1#2#3#4 + { \@@_color_select:n { #1 ~ #2 ~ #3 ~ #4 ~ K } } +\cs_new_protected:Npn \driver_draw_color_fill_gray:n #1 + { \@@_color_fill_select:n { #1 ~ g } } +\cs_new_protected:Npn \driver_draw_color_stroke_gray:n #1 + { \@@_color_select:n { #1 ~ G } } +\cs_new_protected:Npn \driver_draw_color_fill_rgb:nnn #1#2#3 + { \@@_color_fill_select:n { #1 ~ #2 ~ #3 ~ rg } } +\cs_new_protected:Npn \driver_draw_color_stroke_rgb:nnn #1#2#3 + { \@@_color_select:n { #1 ~ #2 ~ #3 ~ RG } } +%<*pdfmode> +\cs_new_eq:NN \@@_color_fill_select:n \@@_color_select:n +%</pdfmode> +%<*dvipdfmx|xdvipdfmx> +\cs_new_eq:NN \@@_color_fill_select:n \@@_draw_literal:n +%</dvipdfmx|xdvipdfmx> +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\driver_draw_cm:nnnn} +% \begin{macro}{\@@_draw_cm:nnnn} +% Another split here between \texttt{pdfmode} and \texttt{(x)dvipdfmx}. +% In the former, we have a direct method to maintain alignment: the driver +% can use a matrix itself. For \texttt{(x)dvipdfmx}, we can to decompose the +% matrix into rotations and a scaling, then use those operations as they +% are handled by the driver. (There is driver support for matrix operations in +% \texttt{(x)dvipdfmx}, but as a matched pair so not suitable for the +% \enquote{stand alone} transformation set up here.) % \begin{macrocode} -\cs_new_protected:Npn \driver_draw_color_cmyk:nnnn #1#2#3#4 +\cs_new_protected:Npn \driver_draw_cm:nnnn #1#2#3#4 { - \@@_draw_literal:n - { #1 ~ #2 ~ #3 ~ #4 ~ k ~ #1 ~ #2 ~ #3 ~ #4 ~ K } - } -\cs_new_protected:Npn \driver_draw_fill_cmyk:nnnn #1#2#3#4 - { - \@@_draw_literal:n { #1 ~ #2 ~ #3 ~ #4 ~ k } +%<*pdfmode> + \@@_matrix:n { #1 ~ #2 ~ #3 ~ #4 } +%</pdfmode> +%<*dvipdfmx|xdvipdfmx> + \@@_draw_cm_decompose:nnnnN {#1} {#2} {#3} {#4} + \@@_draw_cm:nnnn +%</dvipdfmx|xdvipdfmx> } -\cs_new_protected:Npn \driver_draw_stroke_cmyk:nnnn #1#2#3#4 - { \@@_draw_literal:n { #1 ~ #2 ~ #3 ~ #4 ~ K } } -\cs_new_protected:Npn \driver_draw_color_gray:n #1 - { \@@_draw_literal:n { #1 ~ g ~ #1 ~ G } } -\cs_new_protected:Npn \driver_draw_fill_gray:n #1 - { \@@_draw_literal:n { #1 ~ g } } -\cs_new_protected:Npn \driver_draw_stroke_gray:n #1 - { \@@_draw_literal:n { #1 ~ G } } -\cs_new_protected:Npn \driver_draw_color_rgb:nnn #1#2#3 +%<*dvipdfmx|xdvipdfmx> +\cs_new_protected:Npn \@@_draw_cm:nnnn #1#2#3#4 { - \@@_draw_literal:n - { #1 ~ #2 ~ #3 ~ rg ~ #1 ~ #2 ~ #3 ~ RG } + \tex_special:D + { + x:rotate~ + \fp_compare:nNnTF {#1} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -#1 , 5 ) } } + } + \tex_special:D + { + x:scale~ + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } + } + \tex_special:D + { + x:rotate~ + \fp_compare:nNnTF {#4} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( -#4 , 5 ) } } + } } -\cs_new_protected:Npn \driver_draw_fill_rgb:nnn #1#2#3 - { \@@_draw_literal:n { #1 ~ #2 ~ #3 ~ rg } } -\cs_new_protected:Npn \driver_draw_stroke_rgb:nnn #1#2#3 - { \@@_draw_literal:n { #1 ~ #2 ~ #3 ~ RG } } +%</dvipdfmx|xdvipdfmx> % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} % -% \begin{macro}{\driver_draw_transformcm:nnnnnn} -% The first four arguments here are floats (the affine matrix), the last -% two are a displacement vector. Once again, force evaluation to allow for -% caching. +% \begin{macro}{\@@_draw_cm_decompose:nnnnN} +% \begin{macro} +% { +% \@@_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 +% not desirable. They do, however, allow us to track rotations and scalings. +% Luckily, we can decompose any (two-dimensional) matrix into two rotations +% and a single scaling: +% \[ +% \begin{bmatrix} +% A & B \\ C & D +% \end{bmatrix} +% = +% \begin{bmatrix} +% \cos\beta & \sin\beta \\ -\sin\beta & \cos\beta +% \end{bmatrix} +% \begin{bmatrix} +% w_{1} & 0 \\ 0 & w_{2} +% \end{bmatrix} +% \begin{bmatrix} +% \cos\gamma & \sin\gamma \\ -\sin\gamma & \cos\gamma +% \end{bmatrix} +% \] +% The parent matrix can be converted to +% \[ +% \begin{bmatrix} +% A & B \\ C & D +% \end{bmatrix} +% = +% \begin{bmatrix} +% E & H \\-H & E +% \end{bmatrix} +% + +% \begin{bmatrix} +% F & G \\ G & -F +% \end{bmatrix} +% \] +% From these, we can find that +% \begin{align*} +% \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.) 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 \driver_draw_transformcm:nnnnnn #1#2#3#4#5#6 +%<*dvipdfmx|xdvipdfmx> +\cs_new_protected:Npn \@@_draw_cm_decompose:nnnnN #1#2#3#4#5 { - \@@_draw_literal:x + \use:x { - #1 ~ #2 ~ #3 ~ #4 ~ - \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~ - cm + \@@_draw_cm_decompose_auxi:nnnnN + { \fp_eval:n { (#1 + #4) / 2 } } + { \fp_eval:n { (#1 - #4) / 2 } } + { \fp_eval:n { (#3 + #2) / 2 } } + { \fp_eval:n { (#3 - #2) / 2 } } + } + #5 + } +\cs_new_protected:Npn \@@_draw_cm_decompose_auxi:nnnnN #1#2#3#4#5 + { + \use:x + { + \@@_draw_cm_decompose_auxii:nnnnN + { \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 + { + \@@_draw_cm_decompose_auxiii:nnnnN + { \fp_eval:n { ( #4 - #3 ) / 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} } } +%</dvipdfmx|xdvipdfmx> % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\driver_draw_hbox:Nnnnnnn} -% \begin{variable}{\l_@@_tmp_box} +% \begin{macro}{\driver_draw_box_use:Nnnnn} % Inserting a \TeX{} box transformed to the requested position and using % the current matrix is done using a mixture of \TeX{} and low-level % manipulation. The offset can be handled by \TeX{}, so only any rotation/^^A @@ -2129,25 +2200,22 @@ % 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_box_use:Nnnnn #1#2#3#4#5 { - \hbox_set:Nn \l_@@_tmp_box - { - \tex_kern:D \__dim_eval:n {#6} - \@@_scope_begin: - \driver_draw_transformcm:nnnnnn {#2} {#3} {#4} {#5} - { 0pt } { 0pt } - \box_move_up:nn {#7} { \box_use:N #1 } - \@@_scope_end: - } - \box_set_wd:Nn \l_@@_tmp_box { 0pt } - \box_set_ht:Nn \l_@@_tmp_box { 0pt } - \box_set_dp:Nn \l_@@_tmp_box { 0pt } - \box_use:N \l_@@_tmp_box + \@@_scope_begin: +%<*pdfmode> + \driver_draw_cm:nnnn {#2} {#3} {#4} {#5} +%</pdfmode> +%<*dvipdfmx|xdvipdfmx> + \tex_special:D { pdf:btrans~matrix~ #2 ~ #3 ~ #4 ~ #5 ~ 0 ~ 0 } +%</dvipdfmx|xdvipdfmx> + \hbox_overlap_right:n { \box_use:N #1 } +%<*dvipdfmx|xdvipdfmx> + \tex_special:D { pdf:etrans } +%</dvipdfmx|xdvipdfmx> + \@@_scope_end: } -\box_new:N \l_@@_tmp_box % \end{macrocode} -% \end{variable} % \end{macro} % % \begin{macrocode} @@ -2651,122 +2719,85 @@ % % \begin{macro} % { -% \driver_draw_color_cmyk:nnnn , -% \driver_draw_fill_cmyk:nnnn , -% \driver_draw_stroke_cmyk:nnnn +% \driver_draw_color_fill_cmyk:nnnn , +% \driver_draw_color_stroke_cmyk:nnnn % } % \begin{macro} % { -% \driver_draw_color_gray:n , -% \driver_draw_fill_gray:n , -% \driver_draw_stroke_gray:n +% \driver_draw_color_fill_gray:n , +% \driver_draw_color_stroke_gray:n % } % \begin{macro} % { -% \driver_draw_color_rgb:nnn , -% \driver_draw_fill_rgb:nnn , -% \driver_draw_stroke_rgb:nnn +% \driver_draw_color_fill_rgb:nnn , +% \driver_draw_color_stroke_rgb:nnn % } -% SVG only works with RGB colors, so there is some conversion to -% do. The values also need to be given as percentages, which means a -% little more maths. +% \begin{macro}{\@@_draw_color_fill:nnn} +% SVG fill color has to be covered outside of the stack, as for +% \texttt{dvips}. Here, we are only allowed RGB colors so there is some +% conversion to do. % \begin{macrocode} -\cs_new_protected:Npn \@@_draw_color_cmyk_aux:NNnnnnn #1#2#3#4#5#6 +\cs_new_protected:Npn \driver_draw_color_stroke_cmyk:nnnn #1#2#3#4 { \use:x { - \@@_draw_color_rgb_auxii:nnn - { \fp_eval:n { -100 * ( (#3) * ( 1 - (#6) ) - 1 ) } } - { \fp_eval:n { -100 * ( (#4) * ( 1 - (#6) ) + #6 - 1 ) } } - { \fp_eval:n { -100 * ( (#5) * ( 1 - (#6) ) + #6 - 1 ) } } + \@@_draw_color_fill:nnn + { \fp_eval:n { -100 * ( (#1) * ( 1 - (#4) ) - 1 ) } } + { \fp_eval:n { -100 * ( (#2) * ( 1 - (#4) ) + #4 - 1 ) } } + { \fp_eval:n { -100 * ( (#3) * ( 1 - (#4) ) + #4 - 1 ) } } } - #1 #2 } -\cs_new_protected:Npn \driver_draw_color_cmyk:nnnn - { \@@_draw_color_cmyk_aux:NNnnnnn \c_true_bool \c_true_bool } -\cs_new_protected:Npn \driver_draw_fill_cmyk:nnnn - { \@@_draw_color_cmyk_aux:NNnnnnn \c_false_bool \c_true_bool } -\cs_new_protected:Npn \driver_draw_stroke_cmyk:nnnn - { \@@_draw_color_cmyk_aux:NNnnnnn \c_true_bool \c_false_bool } -\cs_new_protected:Npn \@@_draw_color_gray_aux:NNn #1#2#3 +\cs_new_eq:NN \driver_draw_color_stroke_cmyk:nnnn \driver_color_cmyk:nnnn +\cs_new_protected:Npn \driver_draw_color_gray:n #1 { \use:x { - \@@_draw_color_gray_aux:nNN - { \fp_eval:n { 100 * (#3)} } + \@@_draw_color_gray_aux:n + { \fp_eval:n { 100 * (#3) } } } - #1 #2 - } -\cs_new_protected:Npn \@@_draw_color_gray_aux:nNN #1 - { \@@_draw_color_rgb_auxii:nnnNN {#1} {#1} {#1} } -\cs_generate_variant:Nn \@@_draw_color_gray_aux:nNN { x } -\cs_new_protected:Npn \driver_draw_color_gray:n - { \@@_draw_color_gray_aux:NNn \c_true_bool \c_true_bool } -\cs_new_protected:Npn \driver_draw_fill_gray:n - { \@@_draw_color_gray_aux:NNn \c_false_bool \c_true_bool } -\cs_new_protected:Npn \driver_draw_stroke_gray:n - { \@@_draw_color_gray_aux:NNn \c_true_bool \c_false_bool } -\cs_new_protected:Npn \@@_draw_color_rgb_auxi:NNnnn #1#2#3#4#5 + } +\cs_new_protected:Npn \@@_draw_color_gray_aux:n #1 + { \@@_draw_color_fill:nnn {#1} {#1} {#1} } +\cs_new_eq:NN \driver_draw_color_stroke_gray:n \driver_color_gray:n +\cs_new_protected:Npn \driver_draw_color_rgb:nnn #1#2#3 { \use:x { - \@@_draw_color_rgb_auxii:nnnNN + \@@_draw_color_fill:nnn + { \fp_eval:n { 100 * (#1) } } + { \fp_eval:n { 100 * (#2) } } { \fp_eval:n { 100 * (#3) } } - { \fp_eval:n { 100 * (#4) } } - { \fp_eval:n { 100 * (#5) } } } - #1 #2 } -\cs_new_protected:Npn \@@_draw_color_rgb_auxii:nnnNN #1#2#3#4#5 +\cs_new_protected:Npn \@@_draw_color_fill:nnn #1#2#3 { \@@_draw_scope:x { - \bool_if:NT #4 - { - fill = - " - rgb - ( - #1 \c_percent_str , - #2 \c_percent_str , - #3 \c_percent_str - ) - " - \bool_if:NT #5 { ~ } - } - \bool_if:NT #5 - { - stroke = - " - rgb - ( - #1 \c_percent_str , - #2 \c_percent_str , - #3 \c_percent_str - ) - " - } + fill = + " + rgb + ( + #1 \c_percent_str , + #2 \c_percent_str , + #3 \c_percent_str + ) + " } } -\cs_new_protected:Npn \driver_draw_color_rgb:nnn - { \@@_draw_color_rgb_auxi:NNnnn \c_true_bool \c_true_bool } -\cs_new_protected:Npn \driver_draw_fill_rgb:nnn - { \@@_draw_color_rgb_auxi:NNnnn \c_false_bool \c_true_bool } -\cs_new_protected:Npn \driver_draw_stroke_rgb:nnn - { \@@_draw_color_rgb_auxi:NNnnn \c_true_bool \c_false_bool } +\cs_new_eq:NN \driver_draw_color_stroke_rgb:nnn \driver_color_rgb:nnn % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % -% \begin{macro}{\driver_draw_transformcm:nnnnnn} -% The first four arguments here are floats (the affine matrix), the last -% two are a displacement vector. Once again, force evaluation to allow for -% caching. +% \begin{macro}{\driver_draw_cm:nnnn} +% The four arguments here are floats (the affine matrix), the last +% two are a displacement vector. % \begin{macrocode} -\cs_new_protected:Npn \driver_draw_transformcm:nnnnnn #1#2#3#4#5#6 +\cs_new_protected:Npn \driver_draw_cm:nnnn #1#2#3#4 { - \@@_draw_scope:x + \@@_draw_scope:n { transform = " @@ -2774,7 +2805,7 @@ ( \fp_eval:n {#1} , \fp_eval:n {#2} , \fp_eval:n {#3} , \fp_eval:n {#4} , - \dim_to_decimal:n {#5} , \dim_to_decimal:n {#6} + 0pt , 0pt ) " } @@ -2790,7 +2821,7 @@ \cs_new_protected:Npn \driver_draw_hbox:Nnnnnnn #1#2#3#4#5#6#7 { \@@_scope_begin: - \driver_draw_transformcm:nnnnnn {#2} {#3} {#4} {#5} {#6} {#7} + \driver_draw_cm:nnnn {#2} {#3} {#4} {#5} \@@_literal:n { < g~ diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx index bd8f69d6f16..871763ed5fe 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx index 4b89d01c5d1..76a88d152d4 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -2442,14 +2442,6 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[added = 2012-06-24, updated = 2012-07-31, deprecated=2017-12-31]{\ior_get_str:NN} -% For removal after 2017-12-31. -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2017-12-31 } { \ior_str_get:NN } -\cs_new_protected:Npn \ior_get_str:NN { \ior_str_get:NN } -% \end{macrocode} -% \end{macro} -% % \begin{macro}[deprecated = 2018-12-31]{\file_list:} % Renamed to \cs{file_log_list:}. For removal after 2018-12-31. % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx index 96a497d7492..b0e54d8aa65 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx index 29ffae5d507..4fd4d1e35dc 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3format.ins b/Master/texmf-dist/source/latex/l3kernel/l3format.ins index 6aa7727df4f..472df57f282 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3format.ins +++ b/Master/texmf-dist/source/latex/l3kernel/l3format.ins @@ -96,8 +96,8 @@ and all files in that bundle must be distributed together. \from{l3tl-analysis.dtx}{initex} \from{l3regex.dtx} {initex} \from{l3box.dtx} {initex} - \from{l3coffins.dtx} {initex} \from{l3color-base.dtx} {initex} + \from{l3coffins.dtx} {initex} \from{l3sys.dtx} {initex} \from{l3deprecation.dtx}{initex} \from{l3candidates.dtx} {initex} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx index d4dfd6d5c41..295748ef5d5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % \maketitle % % \begin{documentation} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx index 2c63887e4f0..6acdf09e1af 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -630,6 +630,7 @@ % \end{macro} % \end{macro} % +% \begin{macro}[EXP]{\@@_exp_after_tuple_o:w} % \begin{macro}[EXP]{\@@_exp_after_tuple_f:nw, \@@_exp_after_array_f:w} % The loop works by using the |n| argument of % \cs{@@_exp_after_any_f:nw} to place the loop macro after the next @@ -642,6 +643,8 @@ % \cs{s_@@_stop} % \end{quote} % \begin{macrocode} +\cs_new:Npn \@@_exp_after_tuple_o:w + { \@@_exp_after_tuple_f:nw { \exp_after:wN \exp_stop_f: } } \cs_new:Npn \@@_exp_after_tuple_f:nw #1 \s_@@_tuple \@@_tuple_chk:w #2 ; { \exp_after:wN \s_@@_tuple @@ -657,6 +660,7 @@ { \@@_exp_after_any_f:nw { \@@_exp_after_array_f:w } } % \end{macrocode} % \end{macro} +% \end{macro} % % \subsection{Packing digits} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx index 8a0f18da382..347172c2a1f 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx index abf02162559..18253136f24 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx index c705c4c47f1..aa85f1584f5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx index 9172db30bc5..f0716dd0f15 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx index 678c76cdf7c..77a092f8f00 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -96,16 +96,20 @@ % \begin{macro}[pTF, EXP]{\fp_compare:n} % \begin{macro}[EXP]{\@@_compare_return:w} % Within floating point expressions, comparison operators are treated -% as operations, so we evaluate |#1|, then compare with $0$. +% as operations, so we evaluate |#1|, then compare with $\pm 0$. +% Tuples are \texttt{true}. % \begin{macrocode} \prg_new_conditional:Npnn \fp_compare:n #1 { p , T , F , TF } { \exp_after:wN \@@_compare_return:w \exp:w \exp_end_continue_f:w \@@_parse:n {#1} } -\cs_new:Npn \@@_compare_return:w \s_@@ \@@_chk:w #1#2; +\cs_new:Npn \@@_compare_return:w #1#2#3; { - \if_meaning:w 0 #1 + \if_charcode:w 0 + \@@_if_type_fp:NTwFw + #1 { \use_i_delimit_by_q_stop:nw #3 \q_stop } + \s_@@ 1 \q_stop \prg_return_false: \else: \prg_return_true: @@ -118,7 +122,7 @@ % \begin{macro}[pTF, EXP]{\fp_compare:nNn} % \begin{macro}[EXP]{\@@_compare_aux:wn} % Evaluate |#1| and |#3|, using an auxiliary to expand both, and feed -% the two floating point numbers swapped to \cs{@@_compare_back:ww}, +% the two floating point numbers swapped to \cs{@@_compare_back_any:ww}, % defined below. Compare the result with |`#2-`=|, which is $-1$ for % |<|, $0$ for |=|, $1$ for |>| and $2$ for |?|. % \begin{macrocode} @@ -135,16 +139,16 @@ } \cs_new:Npn \@@_compare_aux:wn #1; #2 { - \exp_after:wN \@@_compare_back:ww + \exp_after:wN \@@_compare_back_any:ww \exp:w \exp_end_continue_f:w \@@_parse:n {#2} #1; } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}[EXP]{\@@_compare_back:ww, \@@_compare_nan:w} +% \begin{macro}[EXP]{\@@_compare_back_any:ww, \@@_compare_back:ww, \@@_compare_nan:w} % \begin{quote} -% \cs{@@_compare_back:ww} \meta{y} |;| \meta{x} |;| +% \cs{@@_compare_back_any:ww} \meta{y} |;| \meta{x} |;| % \end{quote} % Expands (in the same way as \cs{int_eval:n}) to $-1$ if $x<y$, $0$ % if $x=y$, $1$ if $x>y$, and $2$ otherwise (denoted as $x?y$). If @@ -157,6 +161,23 @@ % a different type, the highest type is a larger number. Finally, if % $y\leq 0$, then $x>y$, unless both are zero. % \begin{macrocode} +\cs_new:Npn \@@_compare_back_any:ww #1#2; #3 + { + \@@_if_type_fp:NTwFw + #1 { \@@_if_type_fp:NTwFw #3 \use_i:nn \s_@@ \use_ii:nn \q_stop } + \s_@@ \use_ii:nn \q_stop + \@@_compare_back:ww + { + \cs:w + @@ + \@@_type_from_scan:N #1 + _compare_back + \@@_type_from_scan:N #3 + :ww + \cs_end: + } + #1#2 ; #3 + } \cs_new:Npn \@@_compare_back:ww \s_@@ \@@_chk:w #1 #2 #3; \s_@@ \@@_chk:w #4 #5 #6; @@ -188,6 +209,46 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[EXP]{\@@_compare_back_tuple:ww, \@@_tuple_compare_back:ww, \@@_tuple_compare_back_tuple:ww} +% \begin{macro}[EXP]{\@@_tuple_compare_back_loop:w} +% Tuple and floating point numbers are not comparable so return $2$ in +% mixed cases or when tuples have a different number of items. +% Otherwise compare pairs of items with \cs{@@_compare_back_any:ww} +% and if any don't match return~$2$ (as \cs{__int_value:w} |02| +% \cs{exp_stop_f:}). +% \begin{macrocode} +\cs_new:Npn \@@_compare_back_tuple:ww #1; #2; { 2 } +\cs_new:Npn \@@_tuple_compare_back:ww #1; #2; { 2 } +\cs_new:Npn \@@_tuple_compare_back_tuple:ww + \s_@@_tuple \@@_tuple_chk:w #1; + \s_@@_tuple \@@_tuple_chk:w #2; + { + \int_compare:nNnTF { \@@_array_count:n {#1} } = { \@@_array_count:n {#2} } + { + \__int_value:w 0 + \@@_tuple_compare_back_loop:w + #1 { \s_@@ \__prg_break: } ; @ + #2 { \s_@@ \__prg_break: } ; + \__prg_break_point: + \exp_stop_f: + } + { 2 } + } +\cs_new:Npn \@@_tuple_compare_back_loop:w #1#2 ; #3 @ #4#5 ; + { + \use_none:n #1 + \use_none:n #4 + \if_int_compare:w + \@@_compare_back_any:ww #1 #2 ; #4 #5 ; = 0 \exp_stop_f: + \else: + 2 \exp_after:wN \__prg_break: + \fi: + \@@_tuple_compare_back_loop:w #3 @ + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macro}[EXP]{\@@_compare_npos:nwnw} % \begin{macro}[EXP]{\@@_compare_significand:nnnnnnnn} % \begin{quote} @@ -309,7 +370,7 @@ % \end{macro} % % \begin{macro}[EXP]{\fp_step_function:nnnN, \fp_step_function:nnnc} -% \begin{macro}[EXP]{\@@_step:wwwN} +% \begin{macro}[EXP]{\@@_step:wwwN, \@@_step_fp:wwwN} % \begin{macro}[EXP]{\@@_step:NnnnnN, \@@_step:NfnnnN} % The approach here is somewhat similar to % \cs{int_step_function:nnnN}. There are two subtleties: we use the @@ -326,6 +387,7 @@ } \cs_generate_variant:Nn \fp_step_function:nnnN { nnnc } % \end{macrocode} +% Only floating point numbers (not tuples) are allowed arguments. % Only \enquote{normal} floating points (not $\pm 0$, % $\pm\texttt{inf}$, \texttt{nan}) can be used as step; if positive, % call \cs{@@_step:NnnnnN} with argument |>| otherwise~|<|. This @@ -334,7 +396,20 @@ % progress. Conversion to decimal is done just before calling the % user's function. % \begin{macrocode} -\cs_new:Npn \@@_step:wwwN #1 ; \s_@@ \@@_chk:w #2#3#4 ; #5; #6 +\cs_new:Npn \@@_step:wwwN #1#2; #3#4; #5#6; #7 + { + \@@_if_type_fp:NTwFw #1 { } \s_@@ \__prg_break: \q_stop + \@@_if_type_fp:NTwFw #3 { } \s_@@ \__prg_break: \q_stop + \@@_if_type_fp:NTwFw #5 { } \s_@@ \__prg_break: \q_stop + \use_i:nnnn { \@@_step_fp:wwwN #1#2; #3#4; #5#6; #7 } + \__prg_break_point: + \use:n + { + \@@_error:nfff { fp-step-tuple } { \fp_to_tl:n { #1#2 ; } } + { \fp_to_tl:n { #3#4 ; } } { \fp_to_tl:n { #5#6 ; } } + } + } +\cs_new:Npn \@@_step_fp:wwwN #1 ; \s_@@ \@@_chk:w #2#3#4 ; #5; #6 { \token_if_eq_meaning:NNTF #2 1 { @@ -410,6 +485,8 @@ % \end{macro} % % \begin{macrocode} +\__kernel_msg_new:nnn { kernel } { fp-step-tuple } + { Tuple~argument~in~fp_step_...~{#1}{#2}{#3}. } \__kernel_msg_new:nnn { kernel } { fp-bad-step } { Invalid~step~size~#2~in~step~function~#3. } \__kernel_msg_new:nnn { kernel } { fp-tiny-step } @@ -511,12 +588,12 @@ % % \subsection{Boolean operations} % -% \begin{macro}[EXP]{\@@_not_o:w} +% \begin{macro}[EXP]{\@@_not_o:w, \@@_tuple_not_o:w} % Return \texttt{true} or \texttt{false}, with two expansions, one to % exit the conditional, and one to please \pkg{l3fp-parse}. The first % argument is provided by \pkg{l3fp-parse} and is ignored. % \begin{macrocode} -\cs_new:cpn { @@_not_o:w } #1 \s_@@ \@@_chk:w #2#3; @ +\cs_new:Npn \@@_not_o:w #1 \s_@@ \@@_chk:w #2#3; @ { \if_meaning:w 0 #2 \exp_after:wN \exp_after:wN \exp_after:wN \c_one_fp @@ -524,11 +601,12 @@ \exp_after:wN \exp_after:wN \exp_after:wN \c_zero_fp \fi: } +\cs_new:Npn \@@_tuple_not_o:w #1 @ { \exp_after:wN \c_zero_fp } % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]+\@@_&_o:ww+ -% \begin{macro}[EXP]+\@@_|_o:ww+ +% \begin{macro}[EXP]{\@@_&_o:ww, \@@_tuple_&_o:ww, \@@_&_tuple_o:ww, \@@_tuple_&_tuple_o:ww} +% \begin{macro}[EXP]{\@@_|_o:ww, \@@_tuple_|_o:ww, \@@_|_tuple_o:ww, \@@_tuple_|_tuple_o:ww} % \begin{macro}[EXP]{\@@_and_return:wNw} % For \texttt{and}, if the first number is zero, return it (with the % same sign). Otherwise, return the second one. For \texttt{or}, the @@ -547,9 +625,22 @@ \fi: \@@_exp_after_o:w } + \cs_new:Npn \@@_&_tuple_o:ww #1 \s_@@ \@@_chk:w #2#3; + { + \if_meaning:w 0 #2 #1 + \@@_and_return:wNw \s_@@ \@@_chk:w #2#3; + \fi: + \@@_exp_after_tuple_o:w + } + \cs_new:Npn \@@_tuple_&_o:ww #1; { \@@_exp_after_o:w } + \cs_new:Npn \@@_tuple_&_tuple_o:ww #1; { \@@_exp_after_tuple_o:w } \cs_new:Npn \@@_|_o:ww { \@@_&_o:ww \else: } + \cs_new:Npn \@@_|_tuple_o:ww { \@@_&_tuple_o:ww \else: } + \cs_new:Npn \@@_tuple_|_o:ww #1; #2; { \@@_exp_after_tuple_o:w #1; } + \cs_new:Npn \@@_tuple_|_tuple_o:ww #1; #2; { \@@_exp_after_tuple_o:w #1; } \group_end: -\cs_new:Npn \@@_and_return:wNw #1; \fi: #2#3; { \fi: #2 #1; } +\cs_new:Npn \@@_and_return:wNw #1; \fi: #2; + { \fi: \@@_exp_after_o:w #1; } % \end{macrocode} % \end{macro} % \end{macro} @@ -557,32 +648,28 @@ % % \subsection{Ternary operator} % -%^^A todo: understand and optimize. % \begin{macro}[EXP] % {\@@_ternary:NwwN, \@@_ternary_auxi:NwwN, \@@_ternary_auxii:NwwN} -% \begin{macro}[EXP] -% { -% \@@_ternary_loop_break:w, \@@_ternary_loop:Nw, -% \@@_ternary_map_break:, \@@_ternary_break_point:n -% } % The first function receives the test and the true branch of the |?:| -% ternary operator. It returns the true branch, unless the test -% branch is zero. In that case, the function returns a very specific -% \texttt{nan}. The second function receives the output of the first -% function, and the false branch. It returns the previous input, -% unless that is the special \texttt{nan}, in which case we return the -% false branch. +% ternary operator. It calls \cs{@@_ternary_auxii:NwwN} if the test +% branch is a floating point number $\pm 0$, and otherwise calls +% \cs{@@_ternary_auxi:NwwN}. These functions select one of their two +% arguments. % \begin{macrocode} -\cs_new:Npn \@@_ternary:NwwN #1 #2@ #3@ #4 +\cs_new:Npn \@@_ternary:NwwN #1 #2#3@ #4@ #5 { - \if_meaning:w \@@_parse_infix_::N #4 - \@@_ternary_loop:Nw - #2 - \s_@@ \@@_chk:w { \@@_ternary_loop_break:w } ; - \@@_ternary_break_point:n { \exp_after:wN \@@_ternary_auxi:NwwN } + \if_meaning:w \@@_parse_infix_::N #5 + \if_charcode:w 0 + \@@_if_type_fp:NTwFw + #2 { \use_i:nn \use_i_delimit_by_q_stop:nw #3 \q_stop } + \s_@@ 1 \q_stop + \exp_after:wN \exp_after:wN \exp_after:wN \@@_ternary_auxii:NwwN + \else: + \exp_after:wN \exp_after:wN \exp_after:wN \@@_ternary_auxi:NwwN + \fi: \exp_after:wN #1 \exp:w \exp_end_continue_f:w - \@@_exp_after_array_f:w #3 \s_@@_stop + \@@_exp_after_array_f:w #4 \s_@@_stop \exp_after:wN @ \exp:w \@@_parse_operand:Nw \c_@@_prec_colon_int @@ -593,25 +680,11 @@ \exp_after:wN \@@_parse_continue:NwN \exp_after:wN #1 \exp:w \exp_end_continue_f:w - \@@_exp_after_array_f:w #3 \s_@@_stop - \exp_after:wN #4 + \@@_exp_after_array_f:w #4 \s_@@_stop + \exp_after:wN #5 \exp_after:wN #1 \fi: } -\cs_new:Npn \@@_ternary_loop_break:w - #1 \fi: #2 \@@_ternary_break_point:n #3 - { - 0 = 0 \exp_stop_f: \fi: - \exp_after:wN \@@_ternary_auxii:NwwN - } -\cs_new:Npn \@@_ternary_loop:Nw \s_@@ \@@_chk:w #1#2; - { - \if_int_compare:w #1 > 0 \exp_stop_f: - \exp_after:wN \@@_ternary_map_break: - \fi: - \@@_ternary_loop:Nw - } -\cs_new:Npn \@@_ternary_map_break: #1 \@@_ternary_break_point:n #2 {#2} \cs_new:Npn \@@_ternary_auxi:NwwN #1#2@#3@#4 { \exp_after:wN \@@_parse_continue:NwN @@ -630,7 +703,6 @@ } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macrocode} %</initex|package> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx index 541d8f14ab6..41c22e977c7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -2069,7 +2069,7 @@ % % \subsection{Main functions} % -% \begin{macro}[EXP]{\@@_parse:n} +% \begin{macro}[EXP]{\@@_parse:n, \@@_parse_o:n} % \begin{macro}[EXP]{\@@_parse_after:ww} % Start an \cs{exp:w} expansion so that \cs{@@_parse:n} expands % in two steps. The \cs{@@_parse_operand:Nw} function performs @@ -2090,25 +2090,27 @@ \@@_parse_expand:w #1 \s_@@_mark \@@_parse_infix_end:N \s_@@_stop + \exp_end: } \cs_new:Npn \@@_parse_after:ww - #1@ \@@_parse_infix_end:N \s_@@_stop - { \exp_end: #1 } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_parse_o:n} -% ^^A todo: optimize, comment, make it work for arrays. -% \begin{macrocode} + #1@ \@@_parse_infix_end:N \s_@@_stop #2 { #2 #1 } \cs_new:Npn \@@_parse_o:n #1 { - \exp_after:wN \exp_after:wN - \exp_after:wN \@@_exp_after_o:w - \@@_parse:n {#1} + \exp:w + \exp_after:wN \@@_parse_after:ww + \exp:w + \@@_parse_operand:Nw \c_@@_prec_end_int + \@@_parse_expand:w #1 + \s_@@_mark \@@_parse_infix_end:N + \s_@@_stop + { + \exp_end_continue_f:w + \@@_exp_after_any_f:nw { \exp_after:wN \exp_stop_f: } + } } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}[EXP]{\@@_parse_operand:Nw} % \begin{macro}[EXP]{\@@_parse_continue:NwN} @@ -2600,7 +2602,7 @@ \if_meaning:w \c_zero_fp #3 0 \else: - \if_case:w \@@_compare_back:ww #8 #2 \exp_stop_f: + \if_case:w \@@_compare_back_any:ww #8 #2 \exp_stop_f: #5 \or: #6 \or: #7 \else: #4 \fi: \fi: diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx index f8ca2c4a81e..565c61dbcc8 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx index 10bc2370e7b..5636ff51d8a 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -86,68 +86,19 @@ % \begin{macro}[EXP] % { % \@@_parse_word_round:N, \@@_parse_round:Nw, -% \@@_parse_round_no_error:Nw, -% \@@_parse_round_deprecation_error:Nw % } -% \begin{macro}[deprecated = 2017-12-31]{round+, round0, round-} -% This looks for |+|, |-|, |0| after |round|. That syntax was -% deprecated in 2013 but the system to tell users about deprecated -% syntax was not really available then, so we did not have anything -% set up. When \pkg{l3doc} complains, remove the syntax by -% removing everything until the last \cs{fi:} in -% \cs{@@_parse_word_round:N} (and getting rid of the unused -% definitions of \cs{@@_parse_round:Nw} and so on, as well as the -% |fp-deprecated| error in \pkg{l3fp-parse}). % \begin{macrocode} \cs_new:Npn \@@_parse_word_round:N #1#2 { - \if_meaning:w + #2 - \@@_parse_round:Nw \@@_round_to_pinf:NNN - \else: - \if_meaning:w 0 #2 - \@@_parse_round:Nw \@@_round_to_zero:NNN - \else: - \if_meaning:w - #2 - \@@_parse_round:Nw \@@_round_to_ninf:NNN - \fi: - \fi: - \fi: \@@_parse_function:NNN \@@_round_o:Nw \@@_round_to_nearest:NNN #1 #2 } -\__kernel_debug:TF - { - \__kernel_deprecation_code:nn - { - \cs_set_eq:NN \@@_parse_round:Nw - \@@_parse_round_deprecation_error:Nw - } - { - \cs_set_eq:NN \@@_parse_round:Nw - \@@_parse_round_no_error:Nw - } - \cs_new:Npn \@@_parse_round_deprecation_error:Nw - #1 #2 \@@_round_to_nearest:NNN #3#4 - { - \@@_error:nnfn { fp-deprecated } { round#4() } - { - \str_case:nn {#2} - { { + } { ceil } { 0 } { trunc } { - } { floor } } - } { } - #2 #1 #3 - } - \cs_new:Npn \@@_parse_round_no_error:Nw - #1 #2 \@@_round_to_nearest:NNN #3#4 { #2 #1 #3 } - \cs_new_eq:NN \@@_parse_round:Nw \@@_parse_round_no_error:Nw - } - { - \cs_new:Npn \@@_parse_round:Nw - #1 #2 \@@_round_to_nearest:NNN #3#4 { #2 #1 #3 } - } +\cs_new:Npn \@@_parse_round:Nw #1 #2 \@@_round_to_nearest:NNN #3#4 + { #2 #1 #3 } + % \end{macrocode} % \end{macro} -% \end{macro} % % \subsection{Rounding tools} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx index 02b769a1691..8548fa1654a 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % \maketitle % % \begin{documentation} @@ -333,11 +333,11 @@ % % \subsection{Errors} % -% \begin{macro}[EXP]{\@@_error:nnnn, \@@_error:nnfn, \@@_error:nffn} +% \begin{macro}[EXP]{\@@_error:nnnn, \@@_error:nnfn, \@@_error:nffn, \@@_error:nfff} % \begin{macrocode} \cs_new:Npn \@@_error:nnnn { \__kernel_msg_expandable_error:nnnnn { kernel } } -\cs_generate_variant:Nn \@@_error:nnnn { nnf, nff } +\cs_generate_variant:Nn \@@_error:nnnn { nnf, nff , nfff } % \end{macrocode} % \end{macro} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx index 2bccf65847a..8d1d38f0180 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx index 1558b86d6f8..b02f20ae962 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: l3fp.dtx Copyright (C) 2011-2017 The LaTeX3 Project +%% File: l3fp.dtx Copyright (C) 2011-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -47,7 +47,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -107,13 +107,17 @@ % \item Dimensions, automatically expressed in points, \emph{e.g.}, % \texttt{pc} is~$12$. % \item Automatic conversion (no need for \cs[no-index]{\meta{type}_use:N}) of -% integer, dimension, and skip variables to floating points, +% integer, dimension, and skip variables to floating point numbers, % expressing dimensions in points and ignoring the stretch and % shrink components of skips. +% \item Tuples: $(x_1,\ldots{},x_n)$ that can be stored in variables, +% added together, multiplied or divided by a floating point number, +% and nested. % \end{itemize} % Floating point numbers can be given either explicitly (in a form such % as |1.234e-34|, or |-.0001|), or as a stored floating point variable, -% which is automatically replaced by its current value. See +% which is automatically replaced by its current value. +% A \enquote{floating point} is a floating point number or a tuple thereof. See % section~\ref{sec:l3fp:fp-floats} for a description of what a floating point is, % section~\ref{sec:l3fp:fp-precedence} for details about how an expression is % parsed, and section~\ref{sec:l3fp:fp-operations} to know what the various @@ -123,7 +127,7 @@ % An example of use could be the following. % \begin{verbatim} % \LaTeX{} can now compute: $ \frac{\sin (3.5)}{2} + 2\cdot 10^{-3} -% = \ExplSyntaxOn \fp_to_decimal:n {sin 3.5 /2 + 2e-3} $. +% = \ExplSyntaxOn \fp_to_decimal:n {sin(3.5)/2 + 2e-3} $. % \end{verbatim} % But in all fairness, this module is mostly meant as an underlying tool % for higher-level commands. For example, one could provide a function @@ -210,6 +214,8 @@ % \end{syntax} % Adds the result of computing the \meta{floating point expression} to % the \meta{fp~var}. +% This also applies if \meta{fp~var} and \meta{floating point +% expression} evaluate to tuples of the same size. % \end{function} % % \begin{function}[updated = 2012-05-08, tested = m3fp002] @@ -219,9 +225,11 @@ % \end{syntax} % Subtracts the result of computing the \meta{floating point % expression} from the \meta{fp~var}. +% This also applies if \meta{fp~var} and \meta{floating point +% expression} evaluate to tuples of the same size. % \end{function} % -% \section{Using floating point numbers} +% \section{Using floating points} % % \begin{function}[EXP, added = 2012-05-08, updated = 2012-07-08, % tested = m3fp-convert003]{\fp_eval:n} @@ -234,7 +242,11 @@ % for the exponent. Non-significant trailing zeros are trimmed, and % integers are expressed without a decimal separator. The values % $\pm\infty$ and \nan{} trigger an \enquote{invalid operation} -% exception. This function is identical to \cs{fp_to_decimal:n}. +% exception. +% For a tuple, each item is converted using \cs{fp_eval:n} and they are combined as +% |(|\meta{fp_1}\verb*|, |\meta{fp_2}\verb*|, |\ldots{}\meta{fp_n}|)| +% if $n>1$ and |(|\meta{fp_1}|,)| or |()| for fewer items. +% This function is identical to \cs{fp_to_decimal:n}. % \end{function} % % \begin{function}[EXP, added = 2012-05-08, updated = 2012-07-08] @@ -250,6 +262,9 @@ % integers are expressed without a decimal separator. The values % $\pm\infty$ and~\nan{} trigger an \enquote{invalid operation} % exception. +% For a tuple, each item is converted using \cs{fp_to_decimal:n} and they are combined as +% |(|\meta{fp_1}\verb*|, |\meta{fp_2}\verb*|, |\ldots{}\meta{fp_n}|)| +% if $n>1$ and |(|\meta{fp_1}|,)| or |()| for fewer items. % \end{function} % % \begin{function}[EXP, updated = 2016-03-22] @@ -265,8 +280,8 @@ % In particular, the result may % be outside the range $[- 2^{14} + 2^{-17}, 2^{14} - 2^{-17}]$ of % valid \TeX{} dimensions, leading to overflow errors if used as a -% dimension. The values $\pm\infty$ and~\nan{} trigger an -% \enquote{invalid operation} exception. +% dimension. Tuples, as well as the values $\pm\infty$ and~\nan{}, +% trigger an \enquote{invalid operation} exception. % \end{function} % % \begin{function}[EXP, updated = 2012-07-08] @@ -280,8 +295,8 @@ % integer. % The result may be outside the range $[- 2^{31} + 1, 2^{31} - 1]$ of % valid \TeX{}~integers, leading to overflow errors if used in an -% integer expression. The values $\pm\infty$ and~\nan{} trigger -% an \enquote{invalid operation} exception. +% integer expression. Tuples, as well as the values $\pm\infty$ +% and~\nan{}, trigger an \enquote{invalid operation} exception. % \end{function} % % \begin{function}[EXP, added = 2012-05-08, updated = 2016-03-22] @@ -299,6 +314,9 @@ % The values $\pm\infty$ and~\nan{} trigger an \enquote{invalid % operation} exception. Normal category codes apply: thus the |e| is % category code~$11$ (a letter). +% For a tuple, each item is converted using \cs{fp_to_scientific:n} and they are combined as +% |(|\meta{fp_1}\verb*|, |\meta{fp_2}\verb*|, |\ldots{}\meta{fp_n}|)| +% if $n>1$ and |(|\meta{fp_1}|,)| or |()| for fewer items. % \end{function} % % \begin{function}[EXP, updated = 2016-03-22] @@ -320,6 +338,9 @@ % |0|, |-0|, \texttt{inf}, \texttt{-inf}, and~\texttt{nan} % respectively. Normal category codes apply and thus \texttt{inf} or % \texttt{nan}, if produced, are made up of letters. +% For a tuple, each item is converted using \cs{fp_to_tl:n} and they are combined as +% |(|\meta{fp_1}\verb*|, |\meta{fp_2}\verb*|, |\ldots{}\meta{fp_n}|)| +% if $n>1$ and |(|\meta{fp_1}|,)| or |()| for fewer items. % \end{function} % % \begin{function}[EXP, updated = 2012-07-08] @@ -332,8 +353,11 @@ % Leading or trailing zeros may be inserted to compensate for the % exponent. Non-significant trailing zeros are trimmed. Integers are % expressed without a decimal separator. The values $\pm\infty$ -% and~\nan{} trigger an \enquote{invalid operation} exception. This -% function is identical to \cs{fp_to_decimal:N}. +% and~\nan{} trigger an \enquote{invalid operation} exception. +% For a tuple, each item is converted using \cs{fp_to_decimal:n} and they are combined as +% |(|\meta{fp_1}\verb*|, |\meta{fp_2}\verb*|, |\ldots{}\meta{fp_n}|)| +% if $n>1$ and |(|\meta{fp_1}|,)| or |()| for fewer items. +% This function is identical to \cs{fp_to_decimal:N}. % \end{function} % % \section{Floating point conditionals} @@ -355,11 +379,11 @@ % \cs{fp_compare:nNnTF} \Arg{fpexpr_1} \meta{relation} \Arg{fpexpr_2} \Arg{true code} \Arg{false code} % \end{syntax} % Compares the \meta{fpexpr_1} and the \meta{fpexpr_2}, and returns -% \texttt{true} if the \meta{relation} is obeyed. Two floating point -% numbers $x$ and~$y$ may obey four mutually exclusive relations: -% $x<y$, $x=y$, $x>y$, or $x$ and~$y$ are not ordered. The latter -% case occurs exactly when one or both operands is~\nan{}, and this relation -% is denoted by the symbol~|?|. Note that a~\nan{} is distinct from +% \texttt{true} if the \meta{relation} is obeyed. Two floating points +% $x$ and~$y$ may obey four mutually exclusive relations: +% $x<y$, $x=y$, $x>y$, or $x?y$ (\enquote{not ordered}). The last +% case occurs exactly if one or both operands is~\nan{} or is a tuple, +% unless they are equal tuples. Note that a~\nan{} is distinct from % any value, even another~\nan{}, hence $x=x$ is not true for % a~\nan{}. To test if a value is~\nan{}, compare it to an arbitrary % number with the \enquote{not ordered} relation. @@ -368,6 +392,10 @@ % { } % <value> is nan % { } % <value> is not nan % \end{verbatim} +% Tuples are equal if they have the same number of items and items +% compare equal (in particular there must be no~\nan{}). +% At present any other comparison with tuples yields |?| (not ordered). +% This is experimental. % \end{function} % % \begin{function}[EXP, pTF, updated = 2012-12-14, @@ -400,10 +428,10 @@ % expression} is evaluated only once. Contrarily to % \cs{int_compare:nTF}, all \meta{floating point expressions} are % computed, even if one comparison is \texttt{false}. Two floating -% point numbers $x$ and~$y$ may obey four mutually exclusive -% relations: $x<y$, $x=y$, $x>y$, or $x$ and~$y$ are not ordered. The -% latter case occurs exactly when one or both operands is~\nan{}, and -% this relation is denoted by the symbol~|?|. Each \meta{relation} +% points $x$ and~$y$ may obey four mutually exclusive +% relations: $x<y$, $x=y$, $x>y$, or $x?y$ (\enquote{not ordered}). +% The last case occurs exactly if one or both operands is~\nan{} or is +% a tuple, unless they are equal tuples. Each \meta{relation} % can be any (non-empty) combination of |<|, |=|, |>|, and~|?|, plus % an optional leading~|!| (which negates the \meta{relation}), with % the restriction that the \meta{relation} may not start with~|?|, as @@ -530,7 +558,8 @@ % \cs{fp_step_function:nnnN} \Arg{initial value} \Arg{step} \Arg{final value} \meta{function} % \end{syntax} % This function first evaluates the \meta{initial value}, \meta{step} -% and \meta{final value}, all of which should be floating point expressions. +% and \meta{final value}, each of which should be a floating point +% expression evaluating to a floating point number, not a tuple. % The \meta{function} is then placed in front of each \meta{value} % from the \meta{initial value} to the \meta{final value} in turn % (using \meta{step} between each \meta{value}). The \meta{step} must @@ -565,7 +594,8 @@ % \cs{fp_step_inline:nnnn} \Arg{initial value} \Arg{step} \Arg{final value} \Arg{code} % \end{syntax} % This function first evaluates the \meta{initial value}, \meta{step} -% and \meta{final value}, all of which should be floating point expressions. +% and \meta{final value}, all of which should be floating point +% expressions evaluating to a floating point number, not a tuple. % Then for each \meta{value} from the \meta{initial value} to the % \meta{final value} in turn (using \meta{step} between each % \meta{value}), the \meta{code} is inserted into the input stream @@ -579,7 +609,8 @@ % ~~\Arg{initial value} \Arg{step} \Arg{final value} \meta{tl~var} \Arg{code} % \end{syntax} % This function first evaluates the \meta{initial value}, \meta{step} -% and \meta{final value}, all of which should be floating point expressions. +% and \meta{final value}, all of which should be floating point +% expressions evaluating to a floating point number, not a tuple. % Then for each \meta{value} from the \meta{initial value} to the % \meta{final value} in turn (using \meta{step} between each % \meta{value}), the \meta{code} is inserted into the input stream, @@ -811,12 +842,13 @@ % \item Logical \texttt{and}, denoted by |&&|. % \item Logical \texttt{or}, denoted by \verb+||+. % \item Ternary operator |?:| (right associative). +% \item Comma (to build tuples). % \end{itemize} % The precedence of operations can be overridden using parentheses. % In particular, those precedences imply that % \begin{align*} -% \mathtt{sin 2pi} & = \sin(2\pi) = 0, \\ -% \mathtt{2\char`\^2max(3,4)} & = 2^{2 \max(3,4)} = 256. +% \mathtt{sin 2pi} & = \sin(2)\pi != 0, \\ +% \mathtt{2\char`\^2max(3,5)} & = 2^2 \max(3,5) = 20. % \end{align*} % Functions are called on the value of their argument, contrarily to % \TeX{} macros. @@ -826,16 +858,21 @@ % We now present the various operations allowed in floating point % expressions, from the lowest precedence to the highest. When used as % a truth value, a floating point expression is \texttt{false} if it is -% $\pm 0$, and \texttt{true} otherwise, including when it is \nan{}. +% $\pm 0$, and \texttt{true} otherwise, including when it is \nan{} or a +% tuple such as $(0,0)$. Tuples are only supported to some extent by +% operations that work with truth values (|?:|, \verb"||", |&&|, |!|), +% by comparisons (|!<=>?|), and by |+|, |-|, |*|, |/|. Unless otherwise +% specified, providing a tuple as an argument of any other operation +% yields the \enquote{invalid operation} exception and a \nan{} result. % % \begin{function}[tested = m3fp-logic002, module = ]{?:} % \begin{syntax} % \cs{fp_eval:n} \{ \meta{operand_1} |?| \meta{operand_2} |:| \meta{operand_3} \} % \end{syntax} % The ternary operator |?:| results in \meta{operand_2} if -% \meta{operand_1} is true, and \meta{operand_3} if it is false (equal to -% $\pm 0$). All three \meta{operands} are evaluated in all cases. The -% operator is right associative, hence +% \meta{operand_1} is true (not $\pm 0$), and \meta{operand_3} if \meta{operand_1} +% is false ($\pm 0$). All three \meta{operands} are evaluated in all +% cases; they may be tuples. The operator is right associative, hence % \begin{verbatim} % \fp_eval:n % { @@ -856,9 +893,12 @@ % \begin{syntax} % \cs{fp_eval:n} \{ \meta{operand_1} \verb"||" \meta{operand_2} \} % \end{syntax} -% If \meta{operand_1} is true (non-zero), use that value, otherwise the +% If \meta{operand_1} is true (not $\pm 0$), use that value, otherwise the % value of \meta{operand_2}. Both \meta{operands} are evaluated in all -% cases. +% cases; they may be tuples. In \meta{operand_1} \verb"||" +% \meta{operand_2} \verb"||" \ldots{} \verb"||" \meta{operands_n}, the +% first true (nonzero) \meta{operand} is used and if all are zero the +% last one ($\pm 0$) is used. % \end{function} % % \begin{function}[tested = m3fp-logic002]{&&} @@ -867,7 +907,10 @@ % \end{syntax} % If \meta{operand_1} is false (equal to~$\pm 0$), use that value, % otherwise the value of \meta{operand_2}. Both \meta{operands} are -% evaluated in all cases. +% evaluated in all cases; they may be tuples. In \meta{operand_1} +% |&&| \meta{operand_2} |&&| \ldots{} |&&| \meta{operands_n}, the +% first false ($\pm 0$) \meta{operand} is used and if none is zero the +% last one is used. % \end{function} % % \begin{function}[tested = m3fp-logic001, updated = 2013-12-14] @@ -885,7 +928,7 @@ % |>|, and~|?|, optionally preceded by~|!|, and may not start % with~|?|. This evaluates to $+1$ if all comparisons % \meta{operand_i} \meta{relation_i} \meta{operand_{i+1}} are true, and -% $+0$ otherwise. All \meta{operands} are evaluated in all cases. +% $+0$ otherwise. All \meta{operands} are evaluated (once) in all cases. % See \cs{fp_compare:nTF} for details. % \end{function} % @@ -897,6 +940,9 @@ % Computes the sum or the difference of its two \meta{operands}. The % \enquote{invalid operation} exception occurs for $\infty-\infty$. % \enquote{Underflow} and \enquote{overflow} occur when appropriate. +% These operations supports the itemwise addition or subtraction of +% two tuples, but if they have a different number of items the +% \enquote{invalid operation} exception occurs and the result is \nan{}. % \end{function} % % \begin{function}[tested = {m3fp-basics002, m3fp-basics003}]{*, /} @@ -909,6 +955,12 @@ % $0/0$, or $0*\infty$. \enquote{Division by zero} occurs when % dividing a finite non-zero number by $\pm 0$. \enquote{Underflow} % and \enquote{overflow} occur when appropriate. +% When \meta{operand_1} is a tuple and \meta{operand_2} is a floating +% point number, each item of \meta{operand_1} is multiplied or divided +% by \meta{operand_2}. Multiplication also supports the case where +% \meta{operand_1} is a floating point number and \meta{operand_2} a +% tuple. Other combinations yield an \enquote{invalid operation} +% exception and a \nan{} result. % \end{function} % % \begin{function}[tested = m3fp-basics004, label = !]{+, -, !} @@ -918,8 +970,9 @@ % \cs{fp_eval:n} \{ |!| \meta{operand} \} % \end{syntax} % The unary |+| does nothing, the unary |-| changes the sign of the -% \meta{operand}, and |!| \meta{operand} evaluates to $1$ if -% \meta{operand} is false and $0$ otherwise (this is the \texttt{not} +% \meta{operand} (for a tuple, of all its components), and +% |!| \meta{operand} evaluates to $1$ if \meta{operand} is false +% (is $\pm 0$) and $0$ otherwise (this is the \texttt{not} % boolean function). Those operations never raise exceptions. % \end{function} % @@ -939,15 +992,16 @@ % the sign cannot be determined. \enquote{Division by zero} occurs % when raising $\pm 0$ to a finite strictly negative power. % \enquote{Underflow} and \enquote{overflow} occur when appropriate. +% If either operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % % \begin{function}[tested = m3fp-basics004]{abs} % \begin{syntax} % \cs{fp_eval:n} \{ |abs(| \meta{fpexpr} |)| \} % \end{syntax} -% Computes the absolute value of the \meta{fpexpr}. This function -% does not raise any exception beyond those raised when computing its -% operand \meta{fpexpr}. See also \cs{fp_abs:n}. +% Computes the absolute value of the \meta{fpexpr}. If the operand is +% a tuple, \enquote{invalid operation} occurs. This operation does +% not raise exceptions in other cases. See also \cs{fp_abs:n}. % \end{function} % % \begin{function}[tested = m3fp-expo001]{exp} @@ -956,6 +1010,7 @@ % \end{syntax} % Computes the exponential of the \meta{fpexpr}. \enquote{Underflow} % and \enquote{overflow} occur when appropriate. +% If the operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % % \begin{function}[tested = m3fp-expo001]{ln} @@ -964,10 +1019,11 @@ % \end{syntax} % Computes the natural logarithm of the \meta{fpexpr}. Negative % numbers have no (real) logarithm, hence the \enquote{invalid -% operation} is raised in that case, including for $\ln(-0)$. -% \enquote{Division by zero} occurs when evaluating $\ln(+0) = -% -\infty$. \enquote{Underflow} and \enquote{overflow} occur when -% appropriate. +% operation} is raised in that case, including for $\ln(-0)$. +% \enquote{Division by zero} occurs when evaluating +% $\ln(+0) = -\infty$. \enquote{Underflow} and \enquote{overflow} +% occur when appropriate. If the operand is a tuple, \enquote{invalid +% operation} occurs. % \end{function} % % \begin{function}[tested = m3fp-logic002]{max, min} @@ -976,8 +1032,9 @@ % \cs{fp_eval:n} \{ |min(| \meta{fpexpr_1} |,| \meta{fpexpr_2} |,| \ldots{} |)| \} % \end{syntax} % Evaluates each \meta{fpexpr} and computes the largest (smallest) of -% those. If any of the \meta{fpexpr} is a \nan{}, the result is -% \nan{}. Those operations do not raise exceptions. +% those. If any of the \meta{fpexpr} is a \nan{} or tuple, the result +% is \nan{}. If any operand is a tuple, \enquote{invalid operation} +% occurs; these operations do not raise exceptions in other cases. % \end{function} % % \begin{function} @@ -1018,6 +1075,7 @@ % \end{itemize} % \enquote{Overflow} occurs if $x$~is finite and the result is % infinite (this can only happen if $\meta{fpexpr_2}\string<-9984$). +% If any operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % % \begin{function}[tested = m3fp-logic002]{sign} @@ -1026,8 +1084,9 @@ % \end{syntax} % Evaluates the \meta{fpexpr} and determines its sign: $+1$ for % positive numbers and for $+\infty$, $-1$ for negative numbers and -% for $-\infty$, $\pm 0$ for $\pm 0$, and \nan{} for \nan{}. This -% operation does not raise exceptions. +% for $-\infty$, $\pm 0$ for $\pm 0$, and \nan{} for \nan{}. +% If the operand is a tuple, \enquote{invalid operation} occurs. +% This operation does not raise exceptions in other cases. % \end{function} % % \begin{function}[updated = 2013-11-17, tested = m3fp-trig001] @@ -1051,6 +1110,7 @@ % cotangent, cosecant, or secant at one of their poles leads to a % \enquote{division by zero} exception. \enquote{Underflow} and % \enquote{overflow} occur when appropriate. +% If the operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % % \begin{function}[added = 2013-11-02, tested = m3fp-trig003] @@ -1074,6 +1134,7 @@ % cotangent, cosecant, or secant at one of their poles leads to a % \enquote{division by zero} exception. \enquote{Underflow} and % \enquote{overflow} occur when appropriate. +% If the operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % % \begin{function}[added = 2013-11-02, tested = m3fp-trig002] @@ -1093,6 +1154,7 @@ % inside the range $(-1,1)$, an \enquote{invalid operation} exception % is raised. \enquote{Underflow} and \enquote{overflow} occur when % appropriate. +% If the operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % % \begin{function}[added = 2013-11-02, tested = m3fp-trig004] @@ -1112,6 +1174,7 @@ % inside the range $(-1,1)$, an \enquote{invalid operation} exception % is raised. \enquote{Underflow} and \enquote{overflow} occur when % appropriate. +% If the operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % % \begin{function}[added = 2013-11-02, tested = m3fp-trig002] @@ -1140,7 +1203,8 @@ % need not be defined for the two-argument arctangent: when both % expressions yield~$\pm 0$, or when both yield~$\pm\infty$, the % resulting angle is one of $\{\pm\pi/4,\pm 3\pi/4\}$ depending on -% signs. Only the \enquote{underflow} exception can occur. +% signs. The \enquote{underflow} exception can occur. +% If any operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % % \begin{function}[added = 2013-11-02, tested = m3fp-trig004] @@ -1168,8 +1232,9 @@ % The ratio $\meta{fpexpr_1}/\meta{fpexpr_2}$ need not be defined for % the two-argument arctangent: when both expressions yield~$\pm 0$, or % when both yield~$\pm\infty$, the resulting angle is one of $\{\pm -% 45,\pm 135\}$ depending on signs. Only the \enquote{underflow} +% 45,\pm 135\}$ depending on signs. The \enquote{underflow} % exception can occur. +% If any operand is a tuple, \enquote{invalid operation} occurs. % \end{function} % % \begin{function}[added = 2013-12-14, tested = m3fp-basics005]{sqrt} @@ -1177,7 +1242,7 @@ % \cs{fp_eval:n} \{ |sqrt(| \meta{fpexpr} |)| \} % \end{syntax} % Computes the square root of the \meta{fpexpr}. The \enquote{invalid -% operation} is raised when the \meta{fpexpr} is negative; no other +% operation} is raised when the \meta{fpexpr} is negative or is a tuple; no other % exception can occur. Special values yield $\sqrt{-0} = -0$, % $\sqrt{+0} = +0$, $\sqrt{+\infty} = +\infty$ and % $\sqrt{\text{\nan{}}}=\text{\nan{}}$. @@ -1272,9 +1337,9 @@ % \end{syntax} % Evaluates the \meta{floating point expression} as described for % \cs{fp_eval:n} and leaves the absolute value of the result in the -% input stream. This function does not raise any exception beyond -% those raised when evaluating its argument. Within floating point -% expressions, |abs()| can be used. +% input stream. If the argument is a tuple, \enquote{invalid +% operation} occurs, but no other case raises exceptions. Within +% floating point expressions, |abs()| can be used. % \end{function} % % \begin{function}[EXP, added = 2012-09-26, tested = m3fp-convert003] @@ -1283,10 +1348,11 @@ % \cs{fp_max:nn} \Arg{fp expression 1} \Arg{fp expression 2} % \end{syntax} % Evaluates the \meta{floating point expressions} as described for -% \cs{fp_eval:n} and leaves the resulting larger (\texttt{max}) or smaller -% (\texttt{min}) value in the input stream. This function does not raise any -% exception beyond those raised when evaluating its argument. Within -% floating point expressions, |max()| and |min()| can be used. +% \cs{fp_eval:n} and leaves the resulting larger (\texttt{max}) or +% smaller (\texttt{min}) value in the input stream. If the argument +% is a tuple, \enquote{invalid operation} occurs, but no other case +% raises exceptions. Within floating point expressions, |max()| and +% |min()| can be used. % \end{function} % % \section{Disclaimer and roadmap} @@ -1297,6 +1363,7 @@ % % The following need to be done. I'll try to time-order the items. % \begin{itemize} +% \item Function to count items in a tuple (and to determine if something is a tuple). % \item Decide what exponent range to consider. % \item Support signalling \texttt{nan}. % \item Modulo and remainder, and rounding functions |quantize|, @@ -1326,7 +1393,7 @@ % \pkg{Pgfmath} also provides box-measurements (depth, height, width), but % boxes are not possible expandably. % -% Bugs. +% Bugs, and tests to add. % \begin{itemize} % \item Check that functions are monotonic when they should. % \item Add exceptions to |?:|, |!<=>?|, |&&|, \verb"||", and |!|. diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx index 732c2b7b968..2d9deaf1210 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx b/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx index a9af6f8f40d..56128aa8e1c 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx index 5e5a5399d42..75dcff129dd 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx index 2cf851e9184..d5179a174ce 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx index a18c7b553ff..2314178cf11 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx index 0e9d5d082c6..80e862d5d2f 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3oldmodules.dtx b/Master/texmf-dist/source/latex/l3kernel/l3oldmodules.dtx index 3577138d59f..169ee512dd8 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3oldmodules.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3oldmodules.dtx @@ -42,7 +42,7 @@ % } % % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -86,31 +86,11 @@ % \begin{macrocode} %<*oldmodules> \def\old@liii@module@name -%<l3basics>{l3basics} -%<l3bootstrap>{l3bootstrap} -%<l3box>{l3box} -%<l3candidates>{l3candidates} -%<l3clist>{l3clist} -%<l3coffins>{l3coffins} -%<l3expan>{l3expan} -%<l3file>{l3file} -%<l3fp>{l3fp} -%<l3int>{l3int} -%<l3keys>{l3keys} -%<l3msg>{l3msg} -%<l3names>{l3names} -%<l3prg>{l3prg} -%<l3prop>{l3prop} -%<l3quark>{l3quark} %<l3regex>{l3regex} -%<l3seq>{l3seq} -%<l3skip>{l3skip} %<l3sort>{l3sort} %<l3str>{l3str} -%<l3tl>{l3tl} %<l3tl-analysis>{l3tl-analysis} %<l3tl-build>{l3tl-build} -%<l3token>{l3token} % \end{macrocode} % % Then identify the current package: @@ -129,20 +109,15 @@ \typeout{** } \typeout{** Its functionality is now only provided as part of the expl3 package.} \typeout{** } -%<!l3regex&!l3sort&!l3tl-analysis&!l3tl-build>\typeout{** After showing you an error message you can hit <return> we will continue} -%<!l3regex&!l3sort&!l3tl-analysis&!l3tl-build>\typeout{** for now by loading expl3 for you. However, the old packages will be} -%<!l3regex&!l3sort&!l3tl-analysis&!l3tl-build>\typeout{** removed entirely at the end of 2017.} -%<l3regex|l3sort|l3tl-analysis|l3tl-build>\typeout{** The old packages will be removed entirely at the end of 2018.} +\typeout{** The old packages will be removed entirely at the end of 2018.} \typeout{** } \typeout{** Therefore, please replace '\string\usepackage{\old@liii@module@name}'} \typeout{** with '\string\usepackage{expl3}' in your documents as soon as possible.} \typeout{** } \typeout{*******************************************************************} -%<!l3regex&!l3sort&!l3tl-analysis&!l3tl-build>\PackageError -%<l3regex|l3sort|l3tl-analysis|l3tl-build>\PackageWarning +\PackageWarning \old@liii@module@name{This package is obsolete --- use 'expl3' instead} -%<!l3regex&!l3sort&!l3tl-analysis&!l3tl-build> \@ehc % \end{macrocode} % Finally load \texttt{expl3} so that the user can continue for now. % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx index a8318bcaf42..73a8774db53 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx index 2657404a11a..edbb4ce3815 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx index b3afc35b97d..f4ee8b13118 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx index e811b8c4db4..c693af6f7d2 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx index 69a8db98fcc..95dddce8afa 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx index ed740f3a2f0..250f71b65ce 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx index 31eba1be4f9..10569020f22 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx index bcf24c33bc5..245be5a85ce 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx index a3314333f0a..01842fa73f4 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx index 0e3a85e268e..60cd85b5478 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl-build.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl-build.dtx index 00a4308c2e7..15cc7029cc3 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl-build.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl-build.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx index ef429b9d7dd..a655fe18ea3 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % @@ -3036,18 +3036,6 @@ % \end{macrocode} % \end{variable} % -% \subsection{Deprecated functions} -% -% \begin{macro}[deprecated=2017-12-31]{\tl_to_lowercase:n, \tl_to_uppercase:n} -% For removal after 2017-12-31. -% \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2017-12-31 } { \tex_lowercase:D } -\cs_new_protected:Npn \tl_to_lowercase:n #1 { \tex_lowercase:D {#1} } -\__kernel_patch_deprecation:nnNNpn { 2017-12-31 } { \tex_uppercase:D } -\cs_new_protected:Npn \tl_to_uppercase:n #1 { \tex_uppercase:D {#1} } -% \end{macrocode} -% \end{macro} -% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx index b6d06510a9a..5bf97da8f8a 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2018/02/21} +% \date{Released 2018/03/05} % % \maketitle % |