summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2018-03-07 21:50:56 +0000
committerKarl Berry <karl@freefriends.org>2018-03-07 21:50:56 +0000
commitf11f49763fc33ac8427d8c175d98a8d1275e4c5c (patch)
tree79aacd4b6ab168db69112977f42c2c99204e1621 /Master/texmf-dist/source
parentfb72b3560bdc8a98d78bf919da56c3316fa7723d (diff)
l3 (6mar18)
git-svn-id: svn://tug.org/texlive/trunk@46875 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3color/l3color.dtx47
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-boxes.dtx153
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-paths.dtx182
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-points.dtx70
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-scopes.dtx186
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-softpath.dtx395
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-state.dtx34
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-transforms.dtx283
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.dtx670
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.ins1
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3str/l3str-convert.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/expl3.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3.ins22
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3basics.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3box.dtx60
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx24
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3clist.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx15
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx9
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx7
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3doc.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx649
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3expan.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3file.dtx10
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3final.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3flag.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3format.ins2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx174
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx32
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx57
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp.dtx185
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3int.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3keys.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3msg.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3names.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3oldmodules.dtx31
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prg.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prop.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3quark.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3regex.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3seq.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3skip.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3sort.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3str.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3sys.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3tl-build.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3tl.dtx14
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3token.dtx2
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
%