[latex3-commits] [git/LaTeX3-latex3-latex3] master: l3draw: Softpath support (1d814c3)
Joseph Wright
joseph.wright at morningstar2.co.uk
Wed Feb 14 15:20:57 CET 2018
Repository : https://github.com/latex3/latex3
On branch : master
Link : https://github.com/latex3/latex3/commit/1d814c33f98a4d633291f594c88390814237cf35
>---------------------------------------------------------------
commit 1d814c33f98a4d633291f594c88390814237cf35
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date: Wed Feb 14 08:50:13 2018 +0000
l3draw: Softpath support
This should cover everything required:
may yet want to think about how many paths!
>---------------------------------------------------------------
1d814c33f98a4d633291f594c88390814237cf35
l3trial/l3draw/l3draw-softpath.dtx | 316 ++++++++++++++++++++++++++++++++
l3trial/l3draw/l3draw.ins | 1 +
l3trial/l3draw/testfiles/m3draw000.tlg | 4 +
3 files changed, 321 insertions(+)
diff --git a/l3trial/l3draw/l3draw-softpath.dtx b/l3trial/l3draw/l3draw-softpath.dtx
new file mode 100644
index 0000000..d411c7e
--- /dev/null
+++ b/l3trial/l3draw/l3draw-softpath.dtx
@@ -0,0 +1,316 @@
+% \iffalse meta-comment
+%
+%% File: l3draw-softpath.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 "l3trial 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-softpath} package\\ Soft paths^^A
+% }
+%
+% \author{^^A
+% The \LaTeX3 Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team at latex-project.org}
+% {latex-team at latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2018/02/05}
+%
+% \maketitle
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3draw-softpath} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=draw>
+% \end{macrocode}
+%
+% 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
+% specials, but rather needs to be held in macros. The second aspect that
+% follows from this is performance: simply adding to a single macro a piece
+% at a time will have poor performance as the list gets long. Paths need to
+% be global (as specials are), so we cannot use \pkg{l3tl-build} or a similar
+% approach. Instead, we use the same idea as \pkg{pgf}: use a series of buffer
+% macros such that in most cases we don't add tokens to the main list. This
+% will get slow only for \emph{enormous} paths.
+%
+% Each marker (operation) token takes two arguments, which makes processing
+% more straight-forward. As such, some operations have dummy arguments, whilst
+% others have to be split over several tokens.
+%
+% \begin{variable}
+% {
+% \g_@@_softpath_main_tl ,
+% \g_@@_softpath_buffer_a_tl ,
+% \g_@@_softpath_buffer_b_tl
+% }
+% The soft path itself.
+% \begin{macrocode}
+\tl_new:N \g_@@_softpath_main_tl
+\tl_new:N \g_@@_softpath_buffer_a_tl
+\tl_new:N \g_@@_softpath_buffer_b_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {
+% \g_@@_softpath_buffer_a_int ,
+% \g_@@_softpath_buffer_b_int
+% }
+% Tracking data.
+% \begin{macrocode}
+\int_new:N \g_@@_softpath_buffer_a_int
+\int_new:N \g_@@_softpath_buffer_b_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_softpath_add:n, \@@_softpath_add:x}
+% \begin{macro}{\@@_softpath_concat:n}
+% \begin{macro}{\@@_softpath_reset_buffers:}
+% The softpath itself is quite simple. We use three token lists to hold the
+% data: two buffers of limited length, and the main list of arbitrary size.
+% Most of the time this will mean that we don't add to the full list, so
+% performance will be acceptable.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_softpath_add:n #1
+ {
+ \int_compare:nNnTF \g_@@_softpath_buffer_a_int < { 40 }
+ {
+ \int_gincr:N \g_@@_softpath_buffer_a_int
+ \tl_gput_right:Nn \g_@@_softpath_buffer_a_tl {#1}
+ }
+ {
+ \int_compare:nNnTF \g_@@_softpath_buffer_b_int < { 40 }
+ {
+ \int_gincr:N \g_@@_softpath_buffer_b_int
+ \tl_gset:Nx \g_@@_softpath_buffer_b_tl
+ {
+ \exp_not:V \g_@@_softpath_buffer_b_tl
+ \exp_not:V \g_@@_softpath_buffer_a_tl
+ \exp_not:n {#1}
+ }
+ \int_gzero:N \g_@@_softpath_buffer_a_int
+ \tl_gclear:N \g_@@_softpath_buffer_a_tl
+ }
+ { \@@_softpath_concat:n {#1} }
+ }
+ }
+\cs_generate_variant:Nn \@@_softpath_add:n { x }
+\cs_new_protected:Npn \@@_softpath_concat:n #1
+ {
+ \tl_gset:Nx \g_@@_softpath_main_tl
+ {
+ \exp_not:V \g_@@_softpath_main_tl
+ \exp_not:V \g_@@_softpath_buffer_b_tl
+ \exp_not:V \g_@@_softpath_buffer_a_tl
+ \exp_not:n {#1}
+ }
+ \@@_softpath_reset_buffers:
+ }
+\cs_new_protected:Npn \@@_softpath_reset_buffers:
+ {
+ \int_gzero:N \g_@@_softpath_buffer_a_int
+ \tl_gclear:N \g_@@_softpath_buffer_a_tl
+ \int_gzero:N \g_@@_softpath_buffer_b_int
+ \tl_gclear:N \g_@@_softpath_buffer_b_tl
+ }
+% \end{macrocode}
+% \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.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_softpath_use:
+ {
+ \g_@@_softpath_main_tl
+ \g_@@_softpath_buffer_b_tl
+ \g_@@_softpath_buffer_a_tl
+ }
+\cs_new_protected:Npn \@@_softpath_clear:
+ {
+ \tl_gclear:N \g_@@_softpath_main_tl
+ \tl_gclear:N \g_@@_softpath_buffer_a_tl
+ \tl_gclear:N \g_@@_softpath_buffer_b_tl
+ }
+\cs_new_protected:Npn \@@_softpath_use_clear:
+ {
+ \@@_softpath_use:
+ \@@_softpath_clear:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\g_@@_softpath_lastx_dim, \g_@@_softpath_lasty_dim}
+% For tracking the end of the path (to close it).
+% \begin{macrocode}
+\dim_new:N \g_@@_softpath_lastx_dim
+\dim_new:N \g_@@_softpath_lasty_dim
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_softpath_move_bool}
+% Track if moving a point should update the close position.
+% \begin{macrocode}
+\bool_new:N \g_@@_softpath_move_bool
+\bool_gset_true:N \g_@@_softpath_move_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_softpath_curveto:nnnnnn}
+% \begin{macro}
+% {
+% \@@_softpath_lineto:nn,
+% \@@_softpath_moveto:nn
+% }
+% \begin{macro}{\@@_softpath_rectangle:nnnn}
+% \begin{macro}{\@@_softpath_roundpoint:nn}
+% The various parts of a path expressed as the appropriate soft path
+% functions.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_softpath_closepath:
+ {
+ \@@_softpath_add:x
+ {
+ \@@_softpath_close_op:nn
+ { \dim_use:N \g_@@_softpath_lastx_dim }
+ { \dim_use:N \g_@@_softpath_lasty_dim }
+ }
+ }
+\cs_new_protected:Npn \@@_softpath_curveto:nnnnnn #1#2#3#4#5#6
+ {
+ \@@_softpath_add:n
+ {
+ \@@_softpath_curveto_opi:nn {#1} {#2}
+ \@@_softpath_curveto_opii:nn {#3} {#4}
+ \@@_softpath_curveto_opiii:nn {#5} {#6}
+ }
+ }
+\cs_new_protected:Npn \@@_softpath_lineto:nn #1#2
+ {
+ \@@_softpath_add:n
+ { \@@_softpath_lineto_op:nn {#1} {#2} }
+ }
+\cs_new_protected:Npn \@@_softpath_moveto:nn #1#2
+ {
+ \@@_softpath_add:n
+ { \@@_softpath_moveto_op:nn {#1} {#2} }
+ \bool_if:NT \g_@@_softpath_move_bool
+ {
+ \dim_gset:Nn \g_@@_softpath_lastx_dim {#1}
+ \dim_gset:Nn \g_@@_softpath_lasty_dim {#2}
+ }
+ }
+\cs_new_protected:Npn \@@_softpath_rectangle:nn #1#2#3#4
+ {
+ \@@_softpath_add:n
+ {
+ \@@_softpath_rectangle_opi:nn {#1} {#2}
+ \@@_softpath_rectangle_opii:nn {#3} {#4}
+ }
+ }
+\cs_new_protected:Npn \@@_softpath_roundpoint:nn #1#2
+ {
+ \@@_softpath_add:n
+ { \@@_softpath_round_op:nn {#1} {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_softpath_close_op:nn ,
+% \@@_softpath_curveto_opi:nn ,
+% \@@_softpath_curveto_opii:nn ,
+% \@@_softpath_curveto_opiii:nn ,
+% \@@_softpath_lineto_op:nn ,
+% \@@_softpath_moveto_op:nn ,
+% \@@_softpath_roundpoint_op:nn ,
+% \@@_softpath_rectangle_opi:nn ,
+% \@@_softpath_rectangle_opii:nn
+% }
+% \begin{macro}{\@@_softpath_curveto_opi:nnNnnNnn}
+% \begin{macro}{\@@_softpath_curveto_opi:nnNnn}
+% The markers for operations: all the top-level ones take two arguments.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_softpath_close_op:nn #1#2
+ { \driver_draw_closepath: }
+\cs_new_protected:Npn \@@_softpath_curveto_opi:nn #1#2
+ { \@@_softpath_curveto_opi:nnNnnNnn {#1} {#2} }
+\cs_new_protected:Npn \@@_softpath_curveto_opi:nnNnnNnn #1#2#3#4#5#6#7#8
+ { \driver_draw_curevto: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_lineto_op:nn #1#2
+ { \driver_draw_lineto:nn {#1} {#2} }
+\cs_new_protected:Npn \@@_softpath_moveto_op:nn #1#2
+ { \driver_draw_moveto:nn {#1} {#2} }
+\cs_new_protected:Npn \@@_softpath_roundpoint_op:nn #1#2 { }
+\cs_new_protected:Npn \@@_softpath_rectangle_opi:nn #1#2
+ { \@@_softpath_rectangle_opi:nnNnn{#1} {#2} }
+\cs_new_protected:Npn \@@_softpath_rectangle_opi:nnNnnNnn #1#2#3#4#5
+ { \driver_draw_rectangle:nnnn {#1} {#2} {#4} {#5} }
+ \cs_new_protected:Npn \@@_softpath_rectangle_opii:nn #1#2 { }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
diff --git a/l3trial/l3draw/l3draw.ins b/l3trial/l3draw/l3draw.ins
index 76739c8..330a6a5 100644
--- a/l3trial/l3draw/l3draw.ins
+++ b/l3trial/l3draw/l3draw.ins
@@ -57,6 +57,7 @@ and all files in that bundle must be distributed together.
\from{l3draw-paths.dtx} {package}
\from{l3draw-points.dtx} {package}
\from{l3draw-scopes.dtx} {package}
+ \from{l3draw-softpath.dtx} {package}
\from{l3draw-state.dtx} {package}
\from{l3draw-transforms.dtx} {package}
}
diff --git a/l3trial/l3draw/testfiles/m3draw000.tlg b/l3trial/l3draw/testfiles/m3draw000.tlg
index 90838e7..7ea0839 100644
--- a/l3trial/l3draw/testfiles/m3draw000.tlg
+++ b/l3trial/l3draw/testfiles/m3draw000.tlg
@@ -19,6 +19,10 @@ Author: Joseph Wright
\g__draw_ymax_dim=\dimen...
\g__draw_ymin_dim=\dimen...
\l__draw_main_box=\box...
+\g__draw_softpath_buffer_a_int=\count...
+\g__draw_softpath_buffer_b_int=\count...
+\g__draw_softpath_lastx_dim=\dimen...
+\g__draw_softpath_lasty_dim=\dimen...
\g__draw_linewidth_dim=\dimen...
\g__draw_inner_linewidth_dim=\dimen...
\l_draw_default_linewidth_dim=\dimen...
More information about the latex3-commits
mailing list