summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/spath3/spath3.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/spath3/spath3.dtx')
-rw-r--r--Master/texmf-dist/source/latex/spath3/spath3.dtx4228
1 files changed, 0 insertions, 4228 deletions
diff --git a/Master/texmf-dist/source/latex/spath3/spath3.dtx b/Master/texmf-dist/source/latex/spath3/spath3.dtx
deleted file mode 100644
index 9d6ae2825df..00000000000
--- a/Master/texmf-dist/source/latex/spath3/spath3.dtx
+++ /dev/null
@@ -1,4228 +0,0 @@
-% \iffalse meta-comment
-%<*internal>
-\iffalse
-%</internal>
-%<*readme>
-----------------------------------------------------------------
-spath3 --- LaTeX3 functions for manipulating PGF soft paths
-E-mail: stacey@math.ntnu.no
-Released under the LaTeX Project Public License v1.3c or later
-See http://www.latex-project.org/lppl.txt
-----------------------------------------------------------------
-
-This package defines some functions used to manipulate PGFs soft paths.
-As applications of its use, included are a package for drawing calligraphic paths and a package for drawing knot diagrams.
-%</readme>
-%<*internal>
-\fi
-\def\nameofplainTeX{plain}
-\ifx\fmtname\nameofplainTeX\else
- \expandafter\begingroup
-\fi
-%</internal>
-%<*install>
-\input docstrip.tex
-\keepsilent
-\askforoverwritefalse
-\preamble
-----------------------------------------------------------------
-spath3 --- Functions for manipulating PGF soft paths
-E-mail: stacey@math.ntnu.no
-Released under the LaTeX Project Public License v1.3c or later
-See http://www.latex-project.org/lppl.txt
-----------------------------------------------------------------
-
-\endpreamble
-\postamble
-
-Copyright (C) 2011-2019 by Andrew Stacey <stacey@math.ntnu.no>
-
-This work 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 work is "maintained" (as per LPPL maintenance status) by
-Andrew Stacey.
-
-This work consists of the files spath3.dtx
- calligraphy_doc.tex
- knots_doc.tex
-and the derived files spath3.ins,
- spath3_code.pdf,
- spath3.sty,
- tikzlibrarycalligraphy.code.tex
- tikzlibraryknots.code.tex
- calligraphy.pdf
- knots.pdf
- README
-
-\endpostamble
-\usedir{tex/latex/spath3}
-\generate{
- \file{\jobname.sty}{\from{\jobname.dtx}{spath3}}
-}
-\generate{
- \file{tikzlibrarycalligraphy.code.tex}{\from{\jobname.dtx}{calligraphy}}
-}
-\generate{
- \file{tikzlibraryknots.code.tex}{\from{\jobname.dtx}{knots}}
-}
-%</install>
-%<install>\endbatchfile
-%<*internal>
-\usedir{source/latex/spath3}
-\generate{
- \file{\jobname.ins}{\from{\jobname.dtx}{install}}
-}
-\nopreamble\nopostamble
-\usedir{doc/latex/demopkg}
-\generate{
- \file{README.txt}{\from{\jobname.dtx}{readme}}
-}
-\ifx\fmtname\nameofplainTeX
- \expandafter\endbatchfile
-\else
- \expandafter\endgroup
-\fi
-%</internal>
-%<*driver>
-\documentclass[full]{l3doc}
-\usepackage[T1]{fontenc}
-\usepackage{lmodern}
-%\usepackage{morefloats}
-\usepackage{tikz}
-\usepackage{trace}
-\usepackage{spath3}
-%\traceoff
-%\usepackage[numbered]{hypdoc}
-\definecolor{lstbgcolor}{rgb}{0.9,0.9,0.9}
-
-\usepackage{listings}
-\lstloadlanguages{[LaTeX]TeX}
-\lstset{breakatwhitespace=true,breaklines=true,language=TeX}
-
-\usepackage{fancyvrb}
-
-\newenvironment{example}
- {\VerbatimEnvironment
- \begin{VerbatimOut}[gobble=2]{example.out}}
- {\end{VerbatimOut}
- \begin{center}
-% \setlength{\parindent}{0pt}
- \fbox{\begin{minipage}{.9\linewidth}
- \lstset{breakatwhitespace=true,breaklines=true,language=TeX,basicstyle=\small}
- \lstinputlisting[]{example.out}
- \end{minipage}}
-
- \fbox{\begin{minipage}{.9\linewidth}
- \input{example.out}
- \end{minipage}}
-\end{center}
-}
-\EnableCrossrefs
-\CodelineIndex
-\RecordChanges
-\begin{document}
- \DocInput{\jobname.dtx}
-\end{document}
-%</driver>
-% \fi
-%
-% \CheckSum{4488}
-%
-% \CharacterTable
-% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
-% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
-% Digits \0\1\2\3\4\5\6\7\8\9
-% Exclamation \! Double quote \" Hash (number) \#
-% Dollar \$ Percent \% Ampersand \&
-% Acute accent \' Left paren \( Right paren \)
-% Asterisk \* Plus \+ Comma \,
-% Minus \- Point \. Solidus \/
-% Colon \: Semicolon \; Less than \<
-% Equals \= Greater than \> Question mark \?
-% Commercial at \@ Left bracket \[ Backslash \\
-% Right bracket \] Circumflex \^ Underscore \_
-% Grave accent \` Left brace \{ Vertical bar \|
-% Right brace \} Tilde \~}
-%
-%
-% \changes{1.0}{2011/05/03}{Converted to DTX file}
-% \changes{1.1}{2016/02/19}{Fixes due to changes in LaTeX3}
-% \changes{1.2}{2019/02/12}{More fixes due to changes in LaTeX3}
-%
-% \DoNotIndex{\newcommand,\newenvironment}
-%
-% \providecommand*{\url}{\texttt}
-% \GetFileInfo{spath3.sty}
-% \title{The \textsf{spath3} package}
-% \author{Andrew Stacey \\ \url{stacey@math.ntnu.no}}
-% \date{\fileversion~from \filedate}
-%
-%
-% \maketitle
-%
-%
-% \section{Introduction}
-%
-% The \Verb+spath3+ package is intended as a library for manipulating PGF's \emph{soft paths}.
-% In between defining a path and using it, PGF stores a path as a \emph{soft path} where all the defining structure has been resolved into the basic operations but these have not yet been written to the output file.
-% They can therefore still be manipulated by \TeX, and as they have a very rigid form (and limited vocabulary), they are relatively easy to modify.
-% This package provides some methods for working with these paths.
-% It is not really intended for use by end users but as a foundation on which other packages can be built.
-% As examples, the \Verb+calligraphy+ package and the \Verb+knot+ package are included.
-% The first of these simulates a calligraphic pen stroking a path.
-% The second can be used to draw knot (and similar) diagrams.
-%
-% The format of a soft path is a sequence of triples of the form \Verb+\macro {dimension}{dimension}+.
-% The macro is one of a short list, the dimensions are coordinates in points.
-% There are certain further restrictions, particularly that every path must begin with a \Verb+move to+, and B\'ezier curves consist of three triples.
-%
-% \StopEventually{}
-%
-% \section{Implementation}
-%
-% \iffalse
-%<*spath3>
-% \fi
-% \subsection{Initialisation}
-%
-% Load the \LaTeX3 foundation and register us as a \LaTeX3\ package.
-% \begin{macrocode}
-\NeedsTeXFormat{LaTeX2e}
-\RequirePackage{expl3}
-\RequirePackage{pgf}
-\ProvidesExplPackage {spath3} {2019/02/12} {1.2} {Functions for
-manipulating PGF soft paths}
-\RequirePackage{xparse}
-% \end{macrocode}
-%
-% We need a slew of temporary variables.
-% \begin{macrocode}
-\tl_new:N \l__spath_tmpa_tl
-\tl_new:N \l__spath_tmpb_tl
-\tl_new:N \l__spath_tmpc_tl
-\tl_new:N \l__spath_tmpd_tl
-\tl_new:N \l__spath_smuggle_tl
-\dim_new:N \l__spath_tmpa_dim
-\dim_new:N \l__spath_tmpb_dim
-\fp_new:N \l__spath_tmpa_fp
-\fp_new:N \l__spath_tmpb_fp
-\int_new:N \l__spath_tmpa_int
-\int_new:N \g__spath_map_int
-% \end{macrocode}
-%
-% We need to be able to compare against the macros that can occur in a soft path so these token lists contain them.
-% \begin{macrocode}
-\tl_new:N \g__spath_moveto_tl
-\tl_new:N \g__spath_lineto_tl
-\tl_new:N \g__spath_curveto_tl
-\tl_new:N \g__spath_curvetoa_tl
-\tl_new:N \g__spath_curvetob_tl
-\tl_new:N \g__spath_closepath_tl
-\tl_set:Nn \g__spath_moveto_tl {\pgfsyssoftpath@movetotoken}
-\tl_set:Nn \g__spath_lineto_tl {\pgfsyssoftpath@linetotoken}
-\tl_set:Nn \g__spath_curveto_tl {\pgfsyssoftpath@curvetotoken}
-\tl_set:Nn \g__spath_curvetoa_tl {\pgfsyssoftpath@curvetosupportatoken}
-\tl_set:Nn \g__spath_curvetob_tl {\pgfsyssoftpath@curvetosupportbtoken}
-\tl_set:Nn \g__spath_closepath_tl {\pgfsyssoftpath@closepathtoken}
-% \end{macrocode}
-%
-% \subsection{Basic Structure and Methods}
-%
-% A soft path is a \Verb+prop+.
-% These are lists of the attributes that we define.
-% The first consists of all attributes, the second of those that are ``moveable'' in the sense that they change if we transform the path, the third are the ones that contain actual paths.
-%
-% Note that if using these attributes outside an \Verb+expl3+ context, the spaces should be omitted.
-% \begin{macrocode}
-\tl_new:N \g__spath_attributes
-\tl_new:N \g__spath_moveable_attributes
-\tl_new:N \g__spath_path_attributes
-\tl_set:Nn \g__spath_attributes {
- {path}
- {reverse path}
- {length}
- {real length}
- {number of components}
- {initial point}
- {final point}
- {initial action}
- {final action}
- {min bb}
- {max bb}
-}
-\tl_set:Nn \g__spath_moveable_attributes {
- {initial point}
- {final point}
- {min bb}
- {max bb}
-}
-\tl_set:Nn \g__spath_path_attributes {
- {path}
- {reverse path}
-}
-% \end{macrocode}
-%
-% An \Verb+spath+ object is actually a \Verb+prop+.
-% The following functions are wrappers around the underlying \Verb+prop+ functions.
-% We prefix the names to avoid clashing with other \Verb+prop+s that might be lying around, this is why all the \Verb+spath+ methods take argument \Verb+:n+ and not \Verb+:N+.
-% Given that \Verb+spath+ objects might be created inside a group but used outside it, we work globally throughout.
-% \begin{macro}{\spath_new:n}
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_new:n #1
-{
- \prop_new:c {l__spath_#1}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_clear:n}
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_clear:n #1
-{
- \prop_gclear:c {l__spath_#1}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_clear_new:n}
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_clear_new:n #1
-{
- \prop_gclear_new:c {l__spath_#1}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_show:n}
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_show:n #1
-{
- \prop_show:c {l__spath_#1}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_put:nnn}
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_put:nnn #1#2#3
-{
- \prop_gput:cnn {l__spath_#1} {#2} {#3}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_remove:nn}
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_remove:nn #1#2
-{
- \prop_gremove:cn {l__spath_#1} {#2}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\__spath_get:nn}
-% This function is an internal one since the real \Verb+get+ function will generate its data if it does not already exist.
-% \begin{macrocode}
-\cs_new_nopar:Npn \__spath_get:nn #1#2
-{
- \prop_item:cn {l__spath_#1} {#2}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\__spath_get:nnN}
-% \begin{macrocode}
-\cs_new_nopar:Npn \__spath_get:nnN #1#2#3
-{
- \prop_get:cnN {l__spath_#1} {#2} #3
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_if_in:nn}
-% \begin{macrocode}
-\prg_new_conditional:Npnn \spath_if_in:nn #1#2 {p, T, F, TF}
-{
- \prop_if_in:cnTF {l__spath_#1} {#2}
- { \prg_return_true: }
- { \prg_return_false: }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\__spath_get:nnN}
-% \begin{macrocode}
-\cs_generate_variant:Nn \__prop_split:NnTF {cnTF}
-\prg_new_protected_conditional:Npnn \__spath_get:nnN #1#2#3 {T, F, TF}
-{
- \__prop_split:cnTF {l__spath_#1} {#2}
- {
- \tl_set:Nn #3 {##2}
- \prg_return_true:
- }
- { \prg_return_false: }
-}
-\cs_generate_variant:Nn \spath_put:nnn {nnV, nnx, nno}
-\cs_generate_variant:Nn \__spath_get:nn {Vn}
-\cs_generate_variant:Nn \__spath_get:nnN {VnN}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_if_exist:n}
-% \begin{macrocode}
-\prg_new_conditional:Npnn \spath_if_exist:n #1 {p,T,F,TF}
-{
- \prop_if_exist:cTF {l__spath_#1}
- {
- \prg_return_true:
- }
- {
- \prg_return_false:
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_clone:nn}
-% Clones an \Verb+spath+.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_clone:nn #1 #2
-{
- \spath_clear_new:n {#2}
- \tl_map_inline:Nn \g__spath_attributes
- {
- \spath_if_in:nnT {#1} {##1}
- {
- \__spath_get:nnN {#1} {##1} \l__spath_tmpa_tl
- \spath_put:nnV {#2} {##1} \l__spath_tmpa_tl
- }
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_get_current_path:n}
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \spath_get_current_path:n #1
-{
- \pgfsyssoftpath@getcurrentpath\l__spath_tmpa_tl
- \spath_clear_new:n {#1}
- \spath_put:nnV {#1} {path} \l__spath_tmpa_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_set_current_path:n}
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \spath_set_current_path:n #1
-{
- \spath_get:nnN {#1} {min bb} \l__spath_tmpa_tl
- \exp_last_unbraced:NV \pgf@protocolsizes\l__spath_tmpa_tl
-
- \spath_get:nnN {#1} {max bb} \l__spath_tmpa_tl
- \exp_last_unbraced:NV \pgf@protocolsizes\l__spath_tmpa_tl
-
- \spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \pgfsyssoftpath@setcurrentpath\l__spath_tmpa_tl
- \pgfsyssoftpath@flushcurrentpath
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_use_path:nn}
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \spath_use_path:nn #1#2
-{
- \spath_set_current_path:n {#1}
- \pgfusepath{#2}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_protocol_path:n}
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \spath_protocol_path:n #1
-{
- \spath_get:nnN {#1} {min bb} \l__spath_tmpa_tl
- \exp_last_unbraced:NV \pgf@protocolsizes\l__spath_tmpa_tl
-
- \spath_get:nnN {#1} {max bb} \l__spath_tmpa_tl
- \exp_last_unbraced:NV \pgf@protocolsizes\l__spath_tmpa_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_tikz_path:nn}
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \spath_tikz_path:nn #1#2
-{
- \path[#1] \pgfextra{
- \spath_get:nnN {#2} {path} \l__spath_tmpa_tl
- \pgfsyssoftpath@setcurrentpath \l__spath_tmpa_tl
- };
-}
-\cs_generate_variant:Nn \spath_tikz_path:nn {Vn}
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Computing Information}
-%
-% \begin{macro}{\spath_get:nn}
-% The information that we store along with a soft path can be computed from it, but computing it every time is wasteful.
-% So this is the real \Verb+\spath_get:nn+ function which checks to see if we have already computed it and then either retrieves it or computes it.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_get:nn #1#2
-{
- \spath_if_in:nnF {#1} {#2}
- {
- \cs_if_exist_use:cT {spath_generate_#2:n} {{#1}}
- }
- \__spath_get:nn {#1} {#2}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_get:nnN}
-% As above but leaves the result in a token list rather than in the stream.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_get:nnN #1#2#3
-{
- \spath_if_in:nnF {#1} {#2}
- {
- \cs_if_exist_use:cT {spath_generate_#2:n} {{#1}}
- }
- \__spath_get:nnN {#1} {#2} #3
-}
-\cs_generate_variant:Nn \spath_get:nnN {VnN}
-% \end{macrocode}
-% \end{macro}
-%
-% The next slew of functions generate data from the original path, storing it in the \Verb+prop+ for further retrieval.
-% \begin{macro}{\spath_generate_length:n}
-% Counts the number of triples in the path.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_length:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \spath_put:nnx {#1} {length} {\int_eval:n {\tl_count:N \l__spath_tmpa_tl /3 }}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_reallength:n}
-% The real length of a path is the number of triples that actually draw something (that is, the number of lines and curves).
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_reallength:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \int_set:Nn \l__spath_tmpa_int {0}
- \tl_map_inline:Nn \l__spath_tmpa_tl {
- \tl_if_eq:nnT {##1} {\pgfsyssoftpath@linetotoken}
- {
- \int_incr:N \l__spath_tmpa_int
- }
- \tl_if_eq:nnT {##1} {\pgfsyssoftpath@curvetotoken}
- {
- \int_incr:N \l__spath_tmpa_int
- }
- }
- \spath_put:nnx {#1} {real length} {\int_use:N \l__spath_tmpa_int}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_numberofcomponents:n}
-% A component is a continuous segment of the path, separated by moves.
-% Successive moves are not collapsed, and zero length moves count.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_numberofcomponents:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \int_set:Nn \l__spath_tmpa_int {0}
- \tl_map_inline:Nn \l__spath_tmpa_tl {
- \tl_if_eq:nnT {##1} {\pgfsyssoftpath@movetotoken}
- {
- \int_incr:N \l__spath_tmpa_int
- }
- }
- \spath_put:nnx {#1} {number of components} {\int_use:N \l__spath_tmpa_int}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_initialpoint:n}
-% The starting point of the path.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_initialpoint:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \tl_clear:N \l__spath_tmpb_tl
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \spath_put:nnV {#1} {initial point} \l__spath_tmpb_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_finalpoint:n}
-% The final point of the path.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_finalpoint:n #1
-{
- \tl_clear:N \l__spath_tmpb_tl
- \spath_if_in:nnTF {#1} {reverse path}
- {
- \__spath_get:nnN {#1} {reverse path} \l__spath_tmpa_tl
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- }
- {
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \tl_reverse:N \l__spath_tmpa_tl
- \tl_put_left:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_left:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- }
- \spath_put:nnV {#1} {final point} \l__spath_tmpb_tl
-}
-\cs_generate_variant:Nn \spath_generate_finalpoint:n {V}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_reversepath:n}
-% This computes the reverse of the path.
-% TODO: handle closed paths, possibly rectangles.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_reversepath:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \tl_clear:N \l__spath_tmpb_tl
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_left:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- \bool_until_do:nn {
- \tl_if_empty_p:N \l__spath_tmpa_tl
- }
- {
- \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nn \l__spath_tmpd_tl {}
- \tl_case:NnF \l__spath_tmpc_tl
- {
- \g__spath_moveto_tl {\tl_set_eq:NN \l__spath_tmpd_tl \g__spath_moveto_tl }
- \g__spath_lineto_tl {\tl_set_eq:NN \l__spath_tmpd_tl \g__spath_lineto_tl }
- \g__spath_curveto_tl {\tl_set_eq:NN \l__spath_tmpd_tl \g__spath_curvetoa_tl }
- \g__spath_curvetoa_tl {\tl_set_eq:NN \l__spath_tmpd_tl \g__spath_curveto_tl }
- \g__spath_curvetob_tl {\tl_set_eq:NN \l__spath_tmpd_tl \g__spath_curvetob_tl }
- }
- {
- \tl_show:N \l__spath_tmpc_tl
- }
- \tl_put_left:NV \l__spath_tmpb_tl \l__spath_tmpd_tl
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_left:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- }
- \tl_put_left:NV \l__spath_tmpb_tl \g__spath_moveto_tl
- \spath_put:nnV {#1} {reverse path} \l__spath_tmpb_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_initialaction:n}
-% This is the first thing that the path does (after the initial move).
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_initialaction:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \tl_clear:N \l__spath_tmpb_tl
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_if_empty:NF \l__spath_tmpa_tl {
- \tl_set:Nx \l__spath_tmpb_tl {\tl_head:N \l__spath_tmpa_tl}
- }
- \spath_put:nnV {#1} {initial action} \l__spath_tmpb_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_final action:n}
-% This is the last thing that the path does.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_finalaction:n #1
-{
- \tl_clear:N \l__spath_tmpb_tl
- \spath_if_in:nnTF {#1} {reverse path}
- {
- \__spath_get:nnN {#1} {reverse path} \l__spath_tmpa_tl
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- }
- {
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \tl_reverse:N \l__spath_tmpa_tl
- }
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_if_empty:NF \l__spath_tmpa_tl {
- \tl_set:Nx \l__spath_tmpb_tl {\tl_head:N \l__spath_tmpa_tl}
- }
- \tl_if_eq:NNT \l__spath_tmpa_tl \g__spath_curvetoa_tl
- {
- \tl_set_eq:NN \l__spath_tmpa_tl \g__spath_curveto_tl
- }
- \spath_put:nnV {#1} {final action} \l__spath_tmpb_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_minbb:n}
-% This computes the minimum (bottom left) of the bounding box of the path.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_minbb:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \bool_until_do:nn {
- \tl_if_empty_p:N \l__spath_tmpa_tl
- }
- {
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpa_dim {\dim_min:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpa_dim}}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\dim_min:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpb_dim}}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- }
- \tl_clear:N \l__spath_tmpb_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- \spath_put:nnV {#1} {min bb} \l__spath_tmpb_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_max bb:n}
-% This computes the maximum (top right) of the bounding box of the path.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_generate_maxbb:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \bool_until_do:nn {
- \tl_if_empty_p:N \l__spath_tmpa_tl
- }
- {
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpa_dim {\dim_max:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpa_dim}}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\dim_max:nn {\tl_head:N \l__spath_tmpa_tl} {\l__spath_tmpb_dim}}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- }
- \tl_clear:N \l__spath_tmpb_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- \spath_put:nnV {#1} {max bb} \l__spath_tmpb_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_generate_all:n}
-% This function generates all of the data in one fell swoop.
-% By traversing the path just once it is quicker than doing each one individually.
-% However, it does need to store a lot of data as it goes.
-% \begin{itemize}
-% \item \Verb+\l__spath_rp_tl+ will hold the reversed path
-% \item \Verb+\l__spath_l_int+ will hold the length
-% \item \Verb+\l__spath_rl_int+ will hold the real length
-% \item \Verb+\l__spath_nc_int+ will hold the number of components
-% \item \Verb+\l__spath_ip_tl+ will hold the initial point
-% \item \Verb+\l__spath_fp_tl+ will hold the final point
-% \item \Verb+\l__spath_ia_tl+ will hold the initial action
-% \item \Verb+\l__spath_fa_tl+ will hold the final action
-% \item \Verb+\l__spath_minx_dim+ will hold the min x bb
-% \item \Verb+\l__spath_miny_dim+ will hold the min y bb
-% \item \Verb+\l__spath_maxx_dim+ will hold the max x bb
-% \item \Verb+\l__spath_maxy_dim+ will hold the max y bb
-% \end{itemize}
-% \begin{macrocode}
-\tl_new:N \l__spath_rp_tl
-\int_new:N \l__spath_l_int
-\int_new:N \l__spath_rl_int
-\int_new:N \l__spath_nc_int
-\tl_new:N \l__spath_ip_tl
-\tl_new:N \l__spath_fp_tl
-\tl_new:N \l__spath_ia_tl
-\tl_new:N \l__spath_fa_tl
-\dim_new:N \l__spath_minx_dim
-\dim_new:N \l__spath_miny_dim
-\dim_new:N \l__spath_maxx_dim
-\dim_new:N \l__spath_maxy_dim
-
-\cs_new_nopar:Npn \spath_generate_all:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
-
- \tl_clear:N \l__spath_rp_tl
- \int_set:Nn \l__spath_l_int {1}
- \int_zero:N \l__spath_rl_int
- \int_set:Nn \l__spath_nc_int {1}
- \tl_clear:N \l__spath_ip_tl
- \tl_clear:N \l__spath_fp_tl
- \tl_clear:N \l__spath_ia_tl
- \tl_clear:N \l__spath_fa_tl
- \dim_zero:N \l__spath_minx_dim
- \dim_zero:N \l__spath_miny_dim
- \dim_zero:N \l__spath_maxx_dim
- \dim_zero:N \l__spath_maxy_dim
-
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \tl_clear:N \l__spath_ip_tl
- \tl_put_right:Nx \l__spath_ip_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
-
- \dim_set_eq:NN \l__spath_minx_dim \l__spath_tmpa_dim
- \dim_set_eq:NN \l__spath_miny_dim \l__spath_tmpb_dim
- \dim_set_eq:NN \l__spath_maxx_dim \l__spath_tmpa_dim
- \dim_set_eq:NN \l__spath_maxy_dim \l__spath_tmpb_dim
-
- \tl_put_left:Nx \l__spath_rp_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
-
- \tl_set:Nx \l__spath_ia_tl {\tl_head:N \l__spath_tmpa_tl}
-
- \bool_until_do:nn {
- \tl_if_empty_p:N \l__spath_tmpa_tl
- }
- {
- \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nn \l__spath_tmpd_tl {}
- \tl_set_eq:NN \l__spath_fa_tl \l__spath_tmpc_tl
- \int_incr:N \l__spath_l_int
-
- \tl_case:NnF \l__spath_tmpc_tl
- {
- \g__spath_moveto_tl {
- \tl_set_eq:NN \l__spath_tmpd_tl \g__spath_moveto_tl
- \int_incr:N \l__spath_nc_int
- }
- \g__spath_lineto_tl {
- \tl_set_eq:NN \l__spath_tmpd_tl \g__spath_lineto_tl
- \int_incr:N \l__spath_rl_int
- }
- \g__spath_curveto_tl {
- \tl_set_eq:NN \l__spath_tmpd_tl \g__spath_curvetoa_tl
- \int_incr:N \l__spath_rl_int
- }
- \g__spath_curvetoa_tl {
- \tl_set_eq:NN \l__spath_tmpd_tl \g__spath_curveto_tl
- }
- \g__spath_curvetob_tl {
- \tl_set_eq:NN \l__spath_tmpd_tl \g__spath_curvetob_tl
- }
- }
- {
- \tl_show:N \l__spath_tmpc_tl
- }
- \tl_put_left:NV \l__spath_rp_tl \l__spath_tmpd_tl
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \dim_set:Nn \l__spath_minx_dim {\dim_min:nn { \l__spath_minx_dim} {\l__spath_tmpa_dim}}
- \dim_set:Nn \l__spath_miny_dim {\dim_min:nn { \l__spath_miny_dim} {\l__spath_tmpb_dim}}
- \dim_set:Nn \l__spath_maxx_dim {\dim_max:nn { \l__spath_maxx_dim} {\l__spath_tmpa_dim}}
- \dim_set:Nn \l__spath_maxy_dim {\dim_max:nn { \l__spath_maxy_dim} {\l__spath_tmpb_dim}}
-
- \tl_put_left:Nx \l__spath_rp_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
-
- \tl_set:Nx \l__spath_fp_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
-
- }
-
- \tl_put_left:NV \l__spath_rp_tl \g__spath_moveto_tl
-
- \spath_put:nnV {#1} {reverse path} \l__spath_rp_tl
- \spath_put:nnV {#1} {length} \l__spath_l_int
- \spath_put:nnV {#1} {real length} \l__spath_rl_int
- \spath_put:nnV {#1} {number of components} \l__spath_nc_int
- \spath_put:nnV {#1} {initial point} \l__spath_ip_tl
- \spath_put:nnV {#1} {final point} \l__spath_fp_tl
- \spath_put:nnV {#1} {initial action} \l__spath_ia_tl
- \spath_put:nnV {#1} {final action} \l__spath_fa_tl
-
- \tl_clear:N \l__spath_tmpb_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_minx_dim}
- {\dim_use:N \l__spath_miny_dim}
- }
- \spath_put:nnV {#1} {min bb} \l__spath_tmpb_tl
-
- \tl_clear:N \l__spath_tmpb_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_maxx_dim}
- {\dim_use:N \l__spath_maxy_dim}
- }
- \spath_put:nnV {#1} {max bb} \l__spath_tmpb_tl
-
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Path Manipulation}
-%
-% \begin{macro}{\spath_translate:nnn}
-% Translates a path.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_translate:nnn #1#2#3
-{
- \tl_map_inline:Nn \g__spath_moveable_attributes
- {
- \spath_if_in:nnT {#1} {##1}
- {
- \__spath_get:nnN {#1} {##1} \l__spath_tmpa_tl
-
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl + #2}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl + #3}
- \tl_clear:N \l__spath_tmpb_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- \spath_put:nnV {#1} {##1} \l__spath_tmpb_tl
- }
- }
- \tl_map_inline:Nn \g__spath_path_attributes
- {
- \spath_if_in:nnT {#1} {##1}
- {
- \__spath_get:nnN {#1} {##1} \l__spath_tmpa_tl
- \tl_clear:N \l__spath_tmpb_tl
- \bool_until_do:nn {
- \tl_if_empty_p:N \l__spath_tmpa_tl
- }
- {
- \tl_put_right:Nx \l__spath_tmpb_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl + #2}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl + #3}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- }
- \spath_put:nnV {#1} {##1} \l__spath_tmpb_tl
- }
- }
-}
-
-\cs_generate_variant:Nn \spath_translate:nnn {nxx}
-% \end{macrocode}
-%
-% This variant allows for passing the coordinates as a single braced group as it strips off the outer braces of the second argument.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_translate:nn #1#2
-{
- \spath_translate:nnn {#1} #2
-}
-
-\cs_generate_variant:Nn \spath_translate:nn {nV}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_scale:nnn}
-% Scale a path.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_scale:nnn #1#2#3
-{
- \tl_map_inline:Nn \g__spath_moveable_attributes
- {
- \spath_if_in:nnT {#1} {##1}
- {
- \__spath_get:nnN {#1} {##1} \l__spath_tmpa_tl
-
- \fp_set:Nn \l__spath_tmpa_fp {\tl_head:N \l__spath_tmpa_tl * #2}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \fp_set:Nn \l__spath_tmpb_fp {\tl_head:N \l__spath_tmpa_tl * #3}
- \tl_clear:N \l__spath_tmpb_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\fp_to_dim:N \l__spath_tmpa_fp}
- {\fp_to_dim:N \l__spath_tmpb_fp}
- }
- \spath_put:nnV {#1} {##1} \l__spath_tmpb_tl
- }
- }
- \tl_map_inline:Nn \g__spath_path_attributes
- {
- \spath_if_in:nnT {#1} {##1}
- {
- \__spath_get:nnN {#1} {##1} \l__spath_tmpa_tl
- \tl_clear:N \l__spath_tmpb_tl
- \bool_until_do:nn {
- \tl_if_empty_p:N \l__spath_tmpa_tl
- }
- {
- \tl_put_right:Nx \l__spath_tmpb_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \fp_set:Nn \l__spath_tmpa_fp {\tl_head:N \l__spath_tmpa_tl * #2}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \fp_set:Nn \l__spath_tmpb_fp {\tl_head:N \l__spath_tmpa_tl * #3}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\fp_to_dim:N \l__spath_tmpa_fp}
- {\fp_to_dim:N \l__spath_tmpb_fp}
- }
- }
- \spath_put:nnV {#1} {##1} \l__spath_tmpb_tl
- }
- }
-}
-\cs_generate_variant:Nn \spath_scale:nnn {nxx}
-% \end{macrocode}
-%
-% This variant allows for passing the coordinates as a single braced group as it strips off the outer braces of the second argument.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_scale:nn #1#2
-{
- \spath_scale:nnn {#1} #2
-}
-
-\cs_generate_variant:Nn \spath_scale:nn {nV}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_transform:nnnnnnn}
-% Applies an affine (matrix and vector) transformation to path.
-% The matrix is specified in rows first.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_transform:nnnnnnn #1#2#3#4#5#6#7
-{
- \tl_map_inline:Nn \g__spath_moveable_attributes
- {
- \spath_if_in:nnT {#1} {##1}
- {
- \__spath_get:nnN {#1} {##1} \l__spath_tmpa_tl
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_head:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_head:N \l__spath_tmpa_tl}
- \fp_set:Nn \l__spath_tmpa_fp {\l__spath_tmpa_tl * #2 + \l__spath_tmpb_tl * #3 + #6}
- \fp_set:Nn \l__spath_tmpb_fp {\l__spath_tmpa_tl * #4 + \l__spath_tmpb_tl * #5 + #7}
- \tl_clear:N \l__spath_tmpb_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\fp_to_dim:N \l__spath_tmpa_fp}
- {\fp_to_dim:N \l__spath_tmpb_fp}
- }
- \spath_put:nnV {#1} {##1} \l__spath_tmpb_tl
- }
- }
- \tl_map_inline:Nn \g__spath_path_attributes
- {
- \spath_if_in:nnT {#1} {##1}
- {
- \__spath_get:nnN {#1} {##1} \l__spath_tmpa_tl
- \tl_clear:N \l__spath_tmpb_tl
- \bool_until_do:nn {
- \tl_if_empty_p:N \l__spath_tmpa_tl
- }
- {
- \tl_put_right:Nx \l__spath_tmpb_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \fp_set:Nn \l__spath_tmpa_fp {\l_tmpa_tl * #2 + \l_tmpb_tl * #3 + #6}
- \fp_set:Nn \l__spath_tmpb_fp {\l_tmpa_tl * #4 + \l_tmpb_tl * #5 + #7}
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\fp_to_dim:N \l__spath_tmpa_fp}
- {\fp_to_dim:N \l__spath_tmpb_fp}
- }
- }
- \spath_put:nnV {#1} {##1} \l__spath_tmpb_tl
- }
- }
-}
-
-\cs_generate_variant:Nn \spath_transform:nnnnnnn {nxxxxxx}
-% \end{macrocode}
-%
-% This variant allows for passing the coordinates as a single braced group as it strips off the outer braces of the second argument.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_transform:nn #1#2
-{
- \spath_transform:nnnnnnn {#1} #2
-}
-
-\cs_generate_variant:Nn \spath_transform:nn {nV}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_reverse:n}
-% This reverses a path.
-% As a lot of the data is invariant under reversing, there isn't a lot to do.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_reverse:n #1
-{
- \spath_if_in:nnF {#1} {reverse path} {
- \use:c {spath_generate_reverse path:n} {#1}
- }
- \spath_swap:nnn {#1} {path} {reverse path}
- \spath_swap:nnn {#1} {initial point} {final point}
- \spath_swap:nnn {#1} {initial action} {final action}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_swap:nnn}
-% Swaps two entries, being careful to ensure that their existence (or otherwise) is preserved.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_swap:nnn #1#2#3
-{
- \__spath_get:nnNF {#1} {#2} \l__spath_tmpa_tl {\tl_clear:N \l__spath_tmpa_tl}
- \__spath_get:nnNF {#1} {#3} \l__spath_tmpb_tl {\tl_clear:N \l__spath_tmpb_tl}
- \tl_if_empty:NTF \l__spath_tmpb_tl
- {\spath_remove:nn {#1} {#2}}
- {\spath_put:nnV {#1} {#2} \l__spath_tmpb_tl}
- \tl_if_empty:NTF \l__spath_tmpa_tl
- {\spath_remove:nn {#1} {#3}}
- {\spath_put:nnV {#1} {#3} \l__spath_tmpa_tl}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_weld:nn}
-% This welds one path to another, moving the second so that it's initial point coincides with the first's final point.
-% It is called a \emph{weld} because the initial move of the second path is removed.
-% The first path is updated, the second is not modified.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_weld:nn #1#2
-{
- \spath_clone:nn {#2} {tmp_path}
- \spath_get:nnN {#1} {final point} \l__spath_tmpa_tl
-
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
-
- \spath_get:nnN {#2} {initial point} \l__spath_tmpa_tl
-
- \dim_sub:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_sub:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
-
- \spath_translate:nxx {tmp_path} {\dim_use:N \l__spath_tmpa_dim} {\dim_use:N \l__spath_tmpb_dim}
-
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \__spath_get:nnN {tmp_path} {path} \l__spath_tmpb_tl
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
-
- \spath_put:nnV {#1} {path} \l__spath_tmpa_tl
-
- \__spath_get:nnNTF {tmp_path} {final point} \l__spath_tmpa_tl
- {
- \spath_put:nnV {#1} {final point} \l__spath_tmpa_tl
- }
- {
- \spath_remove:nn {#1} {final point}
- }
-
- \__spath_get:nnNTF {tmp_path} {final action} \l__spath_tmpa_tl
- {
- \spath_put:nnV {#1} {final action} \l__spath_tmpa_tl
- }
- {
- \spath_remove:nn {#1} {final action}
- }
-
- \__spath_get:nnNT {tmp_path} {min bb} \l__spath_tmpa_tl
- {
- \__spath_get:nnNT {#1} {min bb} \l__spath_tmpb_tl
- {
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
-
- \dim_set:Nn \l__spath_tmpa_dim {\dim_min:nn {\l__spath_tmpa_dim} {\tl_head:N \l__spath_tmpb_tl}}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\dim_min:nn {\l__spath_tmpb_dim} {\tl_head:N \l__spath_tmpb_tl}}
-
- \tl_clear:N \l__spath_tmpb_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- \spath_put:nnV {#1} {min bb} \l__spath_tmpb_tl
- }
- }
-
- \__spath_get:nnNT {tmp_path} {max bb} \l__spath_tmpa_tl
- {
- \__spath_get:nnNT {#1} {max bb} \l__spath_tmpb_tl
- {
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
-
- \dim_set:Nn \l__spath_tmpa_dim {\dim_max:nn {\l__spath_tmpa_dim} {\tl_head:N \l__spath_tmpb_tl}}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \dim_set:Nn \l__spath_tmpb_dim {\dim_max:nn {\l__spath_tmpb_dim} {\tl_head:N \l__spath_tmpb_tl}}
-
- \tl_clear:N \l__spath_tmpb_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- \spath_put:nnV {#1} {max bb} \l__spath_tmpb_tl
- }
- }
-
- \__spath_get:nnNT {tmp_path} {reverse path} \l__spath_tmpa_tl
- {
- \__spath_get:nnNT {#1} {reverse path} \l__spath_tmpb_tl
- {
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
-
- \spath_put:nnV {#1} {reverse path} \l__spath_tmpa_tl
- }
- }
-
- \__spath_get:nnNT {tmp_path} {length} \l__spath_tmpa_tl
- {
- \__spath_get:nnNT {#1} {length} \l__spath_tmpb_tl
- {
- \int_set:Nn \l__spath_tmpa_int {\l__spath_tmpa_tl + \l__spath_tmpb_tl - 1}
- \spath_put:nnV {#1} {length} \l__spath_tmpa_int
- }
- }
-
- \__spath_get:nnNT {tmp_path} {real length} \l__spath_tmpa_tl
- {
- \__spath_get:nnNT {#1} {real length} \l__spath_tmpb_tl
- {
- \int_set:Nn \l__spath_tmpa_int {\l__spath_tmpa_tl + \l__spath_tmpb_tl}
- \spath_put:nnV {#1} {real length} \l__spath_tmpa_int
- }
- }
-
- \__spath_get:nnNT {tmp_path} {number of components} \l__spath_tmpa_tl
- {
- \__spath_get:nnNT {#1} {number of components} \l__spath_tmpb_tl
- {
- \int_set:Nn \l__spath_tmpa_int {\l__spath_tmpa_tl + \l__spath_tmpb_tl - 1}
- \spath_put:nnV {#1} {number of components} \l__spath_tmpa_int
- }
- }
-
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_prepend_no_move:nn}
-% Prepend the path from the second \Verb+spath+ to the first, removing
-% the adjoining move.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_prepend_no_move:nn #1#2
-{
- \spath_if_exist:nT {#2}
- {
- \__spath_get:nnN {#2} {path} \l__spath_tmpa_tl
- \__spath_get:nnN {#1} {path} \l__spath_tmpb_tl
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
- \spath_put:nnV {#1} {path} \l__spath_tmpa_tl
-
- \spath_if_in:nnTF {#2} {initial point}
- {
- \__spath_get:nnN {#2} {initial point} \l__spath_tmpa_tl
- \spath_put:nnV {#1} {initial point} \l__spath_tmpa_tl
- }
- {
- \spath_remove:nn {#1} {initial point}
- }
-
- \spath_if_in:nnTF {#2} {initial action}
- {
- \__spath_get:nnN {#2} {initial action} \l__spath_tmpa_tl
- \spath_put:nnV {#1} {initial action} \l__spath_tmpa_tl
- }
- {
- \spath_remove:nn {#1} {initial action}
- }
-
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {length}
- &&
- \spath_if_in_p:nn {#2} {length}
- }
- {
- \__spath_get:nnN {#1} {length} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {length} \l__spath_tmpb_tl
- \spath_put:nnx {#1} {length} {\int_eval:n {\l__spath_tmpa_tl +
- \l__spath_tmpb_tl - 1}}
- }
- {
- \spath_remove:nn {#1} {length}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {real length}
- &&
- \spath_if_in_p:nn {#2} {real length}
- }
- {
- \__spath_get:nnN {#1} {real length} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {real length} \l__spath_tmpb_tl
- \spath_put:nnx {#1} {real length} {\int_eval:n {\l__spath_tmpa_tl +
- \l__spath_tmpb_tl }}
- }
- {
- \spath_remove:nn {#1} {real length}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {number of components}
- &&
- \spath_if_in_p:nn {#2} {number of components}
- }
- {
- \__spath_get:nnN {#1} {number of components} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {number of components} \l__spath_tmpb_tl
- \spath_put:nnx {#1} {number of components} {\int_eval:n {\l__spath_tmpa_tl +
- \l__spath_tmpb_tl - 1}}
- }
- {
- \spath_remove:nn {#1} {number of components}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {min bb}
- &&
- \spath_if_in_p:nn {#2} {min bb}
- }
- {
- \__spath_get:nnN {#1} {min bb} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {min bb} \l__spath_tmpb_tl
- \dim_set:Nn \l__spath_tmpa_dim {\dim_min:nn {\tl_item:Nn
- \l__spath_tmpa_tl {1}} {\tl_item:Nn
- \l__spath_tmpb_tl {1}}}
- \dim_set:Nn \l__spath_tmpb_dim {\dim_min:nn {\tl_item:Nn
- \l__spath_tmpa_tl {2}} {\tl_item:Nn
- \l__spath_tmpb_tl {2}}}
- \spath_put:nnx {#1} {min bb} {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- }
- {
- \spath_remove:nn {#1} {min bb}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {max bb}
- &&
- \spath_if_in_p:nn {#2} {max bb}
- }
- {
- \__spath_get:nnN {#1} {max bb} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {max bb} \l__spath_tmpb_tl
- \dim_set:Nn \l__spath_tmpa_dim {\dim_min:nn {\tl_item:Nn
- \l__spath_tmpa_tl {1}} {\tl_item:Nn
- \l__spath_tmpb_tl {1}}}
- \dim_set:Nn \l__spath_tmpb_dim {\dim_min:nn {\tl_item:Nn
- \l__spath_tmpa_tl {2}} {\tl_item:Nn
- \l__spath_tmpb_tl {2}}}
- \spath_put:nnx {#1} {max bb} {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- }
- {
- \spath_remove:nn {#1} {max bb}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {reverse path}
- &&
- \spath_if_in_p:nn {#2} {reverse path}
- }
- {
- \__spath_get:nnN {#1} {reverse path} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {reverse path} \l__spath_tmpb_tl
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
- \spath_put:nnV {#1} {reverse path} \l__spath_tmpb_tl
- }
- {
- \spath_remove:nn {#1} {reverse path}
- }
-
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_append_no_move:nn}
-% Append the path from the second \Verb+spath+ to the first, removing
-% the adjoining move.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_append_no_move:nn #1#2
-{
- \spath_if_exist:nT {#2}
- {
- \spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \spath_get:nnN {#2} {path} \l__spath_tmpb_tl
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
- \spath_put:nnV {#1} {path} \l__spath_tmpa_tl
- \spath_if_in:nnTF {#2} {final point}
- {
- \__spath_get:nnN {#2} {final point} \l__spath_tmpa_tl
- \spath_put:nnV {#1} {final point} \l__spath_tmpa_tl
- }
- {
- \spath_remove:nn {#1} {final point}
- }
- \spath_if_in:nnTF {#2} {final action}
- {
- \__spath_get:nnN {#2} {final action} \l__spath_tmpa_tl
- \spath_put:nnV {#1} {final action} \l__spath_tmpa_tl
- }
- {
- \spath_remove:nn {#1} {final action}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {length}
- &&
- \spath_if_in_p:nn {#2} {length}
- }
- {
- \__spath_get:nnN {#1} {length} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {length} \l__spath_tmpb_tl
- \spath_put:nnx {#1} {length} {\int_eval:n {\l__spath_tmpa_tl +
- \l__spath_tmpb_tl - 1}}
- }
- {
- \spath_remove:nn {#1} {length}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {real length}
- &&
- \spath_if_in_p:nn {#2} {real length}
- }
- {
- \__spath_get:nnN {#1} {real length} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {real length} \l__spath_tmpb_tl
- \spath_put:nnx {#1} {real length} {\int_eval:n {\l__spath_tmpa_tl +
- \l__spath_tmpb_tl }}
- }
- {
- \spath_remove:nn {#1} {real length}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {number of components}
- &&
- \spath_if_in_p:nn {#2} {number of components}
- }
- {
- \__spath_get:nnN {#1} {number of components} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {number of components} \l__spath_tmpb_tl
- \spath_put:nnx {#1} {number of components} {\int_eval:n {\l__spath_tmpa_tl +
- \l__spath_tmpb_tl - 1}}
- }
- {
- \spath_remove:nn {#1} {number of components}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {min bb}
- &&
- \spath_if_in_p:nn {#2} {min bb}
- }
- {
- \__spath_get:nnN {#1} {min bb} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {min bb} \l__spath_tmpb_tl
- \dim_set:Nn \l__spath_tmpa_dim {\dim_min:nn {\tl_item:Nn
- \l__spath_tmpa_tl {1}} {\tl_item:Nn
- \l__spath_tmpb_tl {1}}}
- \dim_set:Nn \l__spath_tmpb_dim {\dim_min:nn {\tl_item:Nn
- \l__spath_tmpa_tl {2}} {\tl_item:Nn
- \l__spath_tmpb_tl {2}}}
- \spath_put:nnx {#1} {min bb} {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- }
- {
- \spath_remove:nn {#1} {min bb}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {max bb}
- &&
- \spath_if_in_p:nn {#2} {max bb}
- }
- {
- \__spath_get:nnN {#1} {max bb} \l__spath_tmpa_tl
- \__spath_get:nnN {#2} {max bb} \l__spath_tmpb_tl
- \dim_set:Nn \l__spath_tmpa_dim {\dim_min:nn {\tl_item:Nn
- \l__spath_tmpa_tl {1}} {\tl_item:Nn
- \l__spath_tmpb_tl {1}}}
- \dim_set:Nn \l__spath_tmpb_dim {\dim_min:nn {\tl_item:Nn
- \l__spath_tmpa_tl {2}} {\tl_item:Nn
- \l__spath_tmpb_tl {2}}}
- \spath_put:nnx {#1} {max bb} {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- }
- {
- \spath_remove:nn {#1} {max bb}
- }
- \bool_if:nTF
- {
- \spath_if_in_p:nn {#1} {reverse path}
- &&
- \spath_if_in_p:nn {#2} {reverse path}
- }
- {
- \__spath_get:nnN {#2} {reverse path} \l__spath_tmpa_tl
- \__spath_get:nnN {#1} {reverse path} \l__spath_tmpb_tl
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_set:Nx \l__spath_tmpb_tl {\tl_tail:N \l__spath_tmpb_tl}
- \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
- \spath_put:nnV {#1} {reverse path} \l__spath_tmpb_tl
- }
- {
- \spath_remove:nn {#1} {reverse path}
- }
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_bake_round:n}
-% Ought to clear the reverse path, if set.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_bake_round:n #1
-{
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \pgf@@processround\l__spath_tmpa_tl\l__spath_tmpb_tl
- \spath_put:nnV {#1} {path} \l__spath_tmpb_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_close_path:n}
-% Appends a close path to the end of the path, and to the end of the reverse path.
-% For now, the point is the initial or final point (respectively).
-% To be future proof, it ought to be the point of the adjacent move to.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_close_path:n #1
-{
- \spath_get:nnN {#1} {initial point} \l__spath_tmpb_tl
- \__spath_get:nnN {#1} {path} \l__spath_tmpa_tl
- \tl_put_right:NV \l__spath_tmpa_tl \g__spath_closepath_tl
- \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
- \spath_put:nnV {#1} {path} \l__spath_tmpa_tl
- \spath_if_in:nnT {#1} {reverse path}
- {
- \spath_get:nnN {#1} {final point} \l__spath_tmpb_tl
- \__spath_get:nnN {#1} {reverse path} \l__spath_tmpa_tl
- \tl_put_right:NV \l__spath_tmpa_tl \g__spath_closepath_tl
- \tl_put_right:NV \l__spath_tmpa_tl \l__spath_tmpb_tl
- \spath_put:nnV {#1} {reverse path} \l__spath_tmpa_tl
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Iteration Functions}
-%
-% \begin{macro}{\spath_map_component:Nn}
-% This iterates through the components of a path, applying the inline function to each.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_map_component:Nn #1#2
-{
- \int_gincr:N \g__spath_map_int
- \cs_gset:cpn { __spath_map_ \int_use:N \g__spath_map_int :w } ##1 {#2}
- \tl_set:NV \l__spath_tmpa_tl #1
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_right:NV \l__spath_tmpa_tl \g__spath_moveto_tl
- \tl_set_eq:NN \l__spath_tmpb_tl \g__spath_moveto_tl
- \bool_until_do:nn {
- \tl_if_empty_p:N \l__spath_tmpa_tl
- }
- {
- \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_if_eq:NNT \l__spath_tmpc_tl \g__spath_moveto_tl
- {
- \exp_args:NnV \use:c { __spath_map_ \int_use:N \g__spath_map_int :w } \l__spath_tmpb_tl
-\tl_clear:N \l__spath_tmpb_tl
- }
- \tl_if_single:NTF \l__spath_tmpc_tl
- {
- \tl_put_right:NV \l__spath_tmpb_tl \l__spath_tmpc_tl
- }
- {
- \tl_put_right:Nx \l__spath_tmpb_tl {{\l__spath_tmpc_tl}}
- }
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_map_segment_inline:Nn}
-% This iterates through the segments of the path, applying the inline function to each.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_map_segment_inline:Nn #1#2
-{
- \int_gincr:N \g__spath_map_int
- \cs_gset:cpn { __spath_map_ \int_use:N \g__spath_map_int :w } ##1 ##2 {#2}
- \spath_map_segment_function:Nc #1 { __spath_map_ \int_use:N \g__spath_map_int :w }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_map_segment_inline:nn}
-% This iterates through the segments of the path of the \Verb+spath+ object, applying the inline function to each.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_map_segment_inline:nn #1#2
-{
- \int_gincr:N \g__spath_map_int
- \cs_gset:cpn { __spath_map_ \int_use:N \g__spath_map_int :w } ##1 ##2 {#2}
- \spath_get:nnN {#1} {path} \l__spath_tmpd_tl
- \spath_map_segment_function:Nc \l__spath_tmpd_tl { __spath_map_ \int_use:N \g__spath_map_int :w }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\spath_map_segment_function:nN}
-% This iterates through the segments of the path of the \Verb+spath+ object, applying the specified function to each.
-% The specified function should take two \Verb+N+ type arguments.
-% The first is a token representing the type of path segment, the second is the path segment itself.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_map_segment_function:nN #1#2
-{
- \spath_get:nnN {#1} {path} \l__spath_tmpd_tl
- \spath_map_segment_function:NN \l__spath_tmpd_tl #2
-}
-% \end{macrocode}
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_map_segment_function:NN #1#2
-{
- \tl_set_eq:NN \l__spath_tmpa_tl #1
- \tl_clear:N \l__spath_tmpb_tl
- \dim_zero:N \l__spath_tmpa_dim
- \dim_zero:N \l__spath_tmpb_dim
-
- \bool_until_do:nn {
- \tl_if_empty_p:N \l__spath_tmpa_tl
- }
- {
- \tl_set:Nx \l__spath_tmpc_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_case:NnF \l__spath_tmpc_tl
- {
- \g__spath_lineto_tl
- {
- \tl_set_eq:NN \l__spath_tmpb_tl \g__spath_moveto_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- \tl_put_right:NV \l__spath_tmpb_tl \g__spath_lineto_tl
-
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- }
-
- \g__spath_curvetoa_tl
- {
- \tl_set_eq:NN \l__spath_tmpb_tl \g__spath_moveto_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- \tl_put_right:NV \l__spath_tmpb_tl \g__spath_curvetoa_tl
-
- \prg_replicate:nn {2} {
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- \tl_put_right:Nx \l__spath_tmpb_tl {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
- }
-
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- }
-
- \g__spath_closepath_tl
- {
- \tl_set_eq:NN \l__spath_tmpb_tl \g__spath_moveto_tl
- \tl_put_right:Nx \l__spath_tmpb_tl
- {
- {\dim_use:N \l__spath_tmpa_dim}
- {\dim_use:N \l__spath_tmpb_dim}
- }
- \tl_put_right:NV \l__spath_tmpb_tl \g__spath_lineto_tl
-
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- }
-
- }
- {
-
- \tl_set_eq:NN \l__spath_tmpb_tl \l__spath_tmpc_tl
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \dim_set:Nn \l__spath_tmpa_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- \tl_put_right:Nx \l__spath_tmpb_tl {{\tl_head:N \l__spath_tmpa_tl}}
- \dim_set:Nn \l__spath_tmpb_dim {\tl_head:N \l__spath_tmpa_tl}
- \tl_set:Nx \l__spath_tmpa_tl {\tl_tail:N \l__spath_tmpa_tl}
-
- }
-
- #2 \l__spath_tmpc_tl \l__spath_tmpb_tl
- \tl_clear:N \l__spath_tmpb_tl
-
- }
-}
-\cs_generate_variant:Nn \spath_map_segment_function:NN {Nc}
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Public Commands}
-%
-% The next functions are more ``public'' than the previous lot.
-% That said, they aren't intended for direct use in a normal document.
-%
-% Most are just wrappers around internal functions.
-%
-% \begin{macro}{\MakeSPath}
-% Constructs an \Verb+spath+ object out of the given name and path.
-% \begin{macrocode}
-\NewDocumentCommand \MakeSPath { m m }
-{
- \spath_clear_new:n {#1}
- \spath_put:nno {#1} {path} {#2}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\MakeSPathList}
-% This constructs a list of \Verb+spath+ objects from a single path by splitting it into components.
-% \begin{macrocode}
-\NewDocumentCommand \MakeSPathList { m m }
-{
- \tl_gclear_new:c {l__spath_list_#1}
- \int_zero:N \l__spath_tmpa_int
- \spath_map_component:Nn #2 {
- \spath_clear_new:n {#1 _ \int_use:N \l__spath_tmpa_int}
- \spath_put:nnn {#1 _ \int_use:N \l__spath_tmpa_int} {path} {##1}
- \tl_gput_right:cx {l__spath_list_#1} {{#1 _ \int_use:N \l__spath_tmpa_int}}
- \int_incr:N \l__spath_tmpa_int
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\CloneSPath}
-% \begin{macrocode}
-\NewDocumentCommand \CloneSPath { m m }
-{
- \spath_clone:nn {#1} {#2}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathInfo}
-% \begin{macrocode}
-\NewDocumentCommand \SPathInfo { m m }
-{
- \spath_get:nn {#1} {#2}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathPrepare}
-% \begin{macrocode}
-\NewDocumentCommand \SPathPrepare { m }
-{
- \spath_generate_all:n {#1}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathListPrepare}
-% \begin{macrocode}
-\NewDocumentCommand \SPathListPrepare { m }
-{
- \tl_map_inline:cn {l__spath_list_#1}
- {
- \spath_generate_all:n {##1}
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathInfoInto}
-% \begin{macrocode}
-\NewDocumentCommand \SPathInfoInto { m m m }
-{
- \tl_clear_new:N #3
- \spath_get:nnN {#1} {#2} #3
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathShow}
-% \begin{macrocode}
-\NewDocumentCommand \SPathShow { m }
-{
- \spath_show:n {#1}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathTranslate}
-% \begin{macrocode}
-\NewDocumentCommand \SPathTranslate { m m m }
-{
- \spath_translate:nnn {#1} {#2} {#3}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathTranslateInto}
-% Clones the path before translating it.
-% \begin{macrocode}
-\NewDocumentCommand \SPathTranslateInto { m m m m }
-{
- \spath_clone:nn {#1} {#2}
- \spath_translate:nnn {#2} {#3} {#4}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathScale}
-% \begin{macrocode}
-\NewDocumentCommand \SPathScale { m m m }
-{
- \spath_scale:nnn {#1} {#2} {#3}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathScaleInto}
-% Clones the path first.
-% \begin{macrocode}
-\NewDocumentCommand \SPathScaleInto { m m m m }
-{
- \spath_clone:nn {#1} {#2}
- \spath_scale:nnn {#2} {#3} {#4}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathWeld}
-% \begin{macrocode}
-\NewDocumentCommand \SPathWeld { m m }
-{
- \spath_weld:nn {#1} {#2}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\SPathWeldInto}
-% \begin{macrocode}
-\NewDocumentCommand \SPathWeldInto { m m m }
-{
- \spath_clone:nn {#1} {#2}
- \spath_weld:nn {#2} {#3}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% Interfaces via TikZ keys.
-% \begin{macrocode}
-\tikzset{
- save~spath/.code={
- \tikz@addmode{
- \spath_get_current_path:n {#1}
- }
- },
- restore~spath/.code={
- \spath_set_current_path:n {#1}
- }
-}
-% \end{macrocode}
-% \subsection{Miscellaneous Commands}
-%
-% \begin{macro}{\spath_split_curve:nnNN}
-% Splits a Bezier cubic into pieces.
-% \begin{macrocode}
-\cs_new_nopar:Npn \spath_split_curve:nnNN #1#2#3#4
-{
- \group_begin:
- \tl_gclear:N \l__spath_smuggle_tl
- \tl_set_eq:NN \l__spath_tmpa_tl \g__spath_moveto_tl
- \tl_put_right:Nx \l__spath_tmpa_tl {
- {\tl_item:nn {#2} {2}}
- {\tl_item:nn {#2} {3}}
- }
- \tl_put_right:NV \l__spath_tmpa_tl \g__spath_curvetoa_tl
- \tl_put_right:Nx \l__spath_tmpa_tl
- {
- {\fp_to_dim:n
- {
- (1 - #1) * \tl_item:nn {#2} {2} + (#1) * \tl_item:nn {#2} {5}
- }}
- {\fp_to_dim:n
- {
- (1 - #1) * \tl_item:nn {#2} {3} + (#1) * \tl_item:nn {#2} {6}
- }}
- }
- \tl_put_right:NV \l__spath_tmpa_tl \g__spath_curvetob_tl
- \tl_put_right:Nx \l__spath_tmpa_tl
- {
- {\fp_to_dim:n
- {
- (1 - #1)^2 * \tl_item:nn {#2} {2} + 2 * (1 - #1) * (#1) * \tl_item:nn {#2} {5} + (#1)^2 * \tl_item:nn {#2} {8}
- }}
- {\fp_to_dim:n
- {
- (1 - #1)^2 * \tl_item:nn {#2} {3} + 2 * (1 - #1) * (#1) * \tl_item:nn {#2} {6} + (#1)^2 * \tl_item:nn {#2} {9}
- }}
- }
- \tl_put_right:NV \l__spath_tmpa_tl \g__spath_curveto_tl
- \tl_put_right:Nx \l__spath_tmpa_tl
- {
- {\fp_to_dim:n
- {
- (1 - #1)^3 * \tl_item:nn {#2} {2} + 3 * (1 - #1)^2 * (#1) * \tl_item:nn {#2} {5} + 3 * (1 - #1) * (#1)^2 * \tl_item:nn {#2} {8} + (#1)^3 * \tl_item:nn {#2} {11}
- }}
- {\fp_to_dim:n
- {
- (1 - #1)^3 * \tl_item:nn {#2} {3} + 3 * (1 - #1)^2 * (#1) * \tl_item:nn {#2} {6} + 3 * (1 - #1) * (#1)^2 * \tl_item:nn {#2} {9} + (#1)^3 * \tl_item:nn {#2} {12}
- }}
- }
- \tl_gset_eq:NN \l__spath_smuggle_tl \l__spath_tmpa_tl
- \group_end:
- \tl_set_eq:NN #3 \l__spath_smuggle_tl
- \group_begin:
- \tl_set_eq:NN \l__spath_tmpa_tl \g__spath_moveto_tl
- \tl_put_right:Nx \l__spath_tmpa_tl
- {
- {\fp_to_dim:n
- {
- (1 - #1)^3 * \tl_item:nn {#2} {2} + 3 * (1 - #1)^2 * (#1) * \tl_item:nn {#2} {5} + 3 * (1 - #1) * (#1)^2 * \tl_item:nn {#2} {8} + (#1)^3 * \tl_item:nn {#2} {11}
- }}
- {\fp_to_dim:n
- {
- (1 - #1)^3 * \tl_item:nn {#2} {3} + 3 * (1 - #1)^2 * (#1) * \tl_item:nn {#2} {6} + 3 * (1 - #1) * (#1)^2 * \tl_item:nn {#2} {9} + (#1)^3 * \tl_item:nn {#2} {12}
- }}
- }
- \tl_put_right:NV \l__spath_tmpa_tl \g__spath_curvetoa_tl
- \tl_put_right:Nx \l__spath_tmpa_tl
- {
- {\fp_to_dim:n
- {
- (1 - #1)^2 * \tl_item:nn {#2} {5} + 2 * (1 - #1) * (#1) * \tl_item:nn {#2} {8} + (#1)^2 * \tl_item:nn {#2} {11}
- }}
- {\fp_to_dim:n
- {
- (1 - #1)^2 * \tl_item:nn {#2} {6} + 2 * (1 - #1) * (#1) * \tl_item:nn {#2} {9} + (#1)^2 * \tl_item:nn {#2} {12}
- }}
- }
- \tl_put_right:NV \l__spath_tmpa_tl \g__spath_curvetob_tl
- \tl_put_right:Nx \l__spath_tmpa_tl
- {
- {\fp_to_dim:n
- {
- (1 - #1) * \tl_item:nn {#2} {8} + (#1) * \tl_item:nn {#2} {11}
- }}
- {\fp_to_dim:n
- {
- (1 - #1) * \tl_item:nn {#2} {9} + (#1) * \tl_item:nn {#2} {12}
- }}
- }
- \tl_put_right:NV \l__spath_tmpa_tl \g__spath_curveto_tl
- \tl_put_right:Nx \l__spath_tmpa_tl {
- {\tl_item:nn {#2} {11}}
- {\tl_item:nn {#2} {12}}
- }
- \tl_gset_eq:NN \l__spath_smuggle_tl \l__spath_tmpa_tl
- \group_end:
- \tl_set_eq:NN #4 \l__spath_smuggle_tl
-}
-
-\cs_generate_variant:Nn \spath_split_curve:nnNN {nVNN, VVNN}
-% \end{macrocode}
-% \end{macro}
-% \iffalse
-%</spath3>
-% \fi
-%
-% \iffalse
-%<*calligraphy>
-% \fi
-%
-% \section{The Calligraphy Package}
-%
-% \subsection{Initialisation}
-% \begin{macrocode}
-\RequirePackage{spath3}
-\ExplSyntaxOn
-
-\tl_new:N \l__cal_tmpa_tl
-\tl_new:N \l__cal_tmpb_tl
-\int_new:N \l__cal_tmpa_int
-\int_new:N \l__cal_tmpb_int
-\int_new:N \l__cal_path_component_int
-\int_new:N \l__cal_label_int
-\dim_new:N \l__cal_tmpa_dim
-\dim_new:N \l__cal_tmpb_dim
-\dim_new:N \l__cal_tmpc_dim
-\dim_new:N \l__cal_tmpd_dim
-\dim_new:N \l__cal_tmpe_dim
-\dim_new:N \l__cal_tmpf_dim
-\dim_new:N \l__cal_tmpg_dim
-\dim_new:N \l__cal_tmph_dim
-\bool_new:N \l__cal_annotate_bool
-\bool_new:N \l__cal_taper_start_bool
-\bool_new:N \l__cal_taper_end_bool
-\bool_new:N \l__cal_taperable_bool
-\dim_new:N \l__cal_taper_width_dim
-\dim_new:N \l__cal_line_width_dim
-
-\bool_set_true:N \l__cal_taper_start_bool
-\bool_set_true:N \l__cal_taper_end_bool
-
-\cs_generate_variant:Nn \tl_put_right:Nn {Nv}
-% \end{macrocode}
-%
-% \subsection{TikZ Keys}
-%
-% The public interface to this package is through TikZ keys and styles.
-% \begin{macrocode}
-\tikzset{
- define~pen/.code={
- \tikzset{pen~name=#1}
- \pgf@relevantforpicturesizefalse
- \tikz@addmode{
- \pgfsyssoftpath@getcurrentpath\l__cal_tmpa_tl
- \MakeSPathList{calligraphy pen \pgfkeysvalueof{/tikz/pen~name}}{\l__cal_tmpa_tl}
- \SPathListPrepare{calligraphy pen \pgfkeysvalueof{/tikz/pen~name}}
- \pgfusepath{discard}%
- }
- },
- define~pen/.default={default},
- use~pen/.code={
- \tikzset{pen~name=#1}
- \int_gzero:N \l__cal_path_component_int
- \cs_set_eq:NN \pgfpathmoveto \cal_moveto:n
- \tikz@addmode{
- \pgfsyssoftpath@getcurrentpath\l__cal_tmpa_tl
- \MakeSPathList{calligraphy path}{\l__cal_tmpa_tl}
- \SPathListPrepare{calligraphy path}
- \CalligraphyPathCreate{calligraphy path}{\pgfkeysvalueof{/tikz/pen~name}}
- }
- },
- use~pen/.default={default},
- pen~name/.initial={default},
- copperplate/.style={pen~name=copperplate},
- pen~colour/.initial={black},
- weight/.is~choice,
- weight/heavy/.style={
- line~width=\pgfkeysvalueof{/tikz/heavy~line~width},
- taper~width=\pgfkeysvalueof{/tikz/light~line~width},
- },
- weight/light/.style={
- line~width=\pgfkeysvalueof{/tikz/light~line~width},
- taper~width=0pt,
- },
- heavy/.style={
- weight=heavy
- },
- light/.style={
- weight=light
- },
- heavy~line~width/.initial=2pt,
- light~line~width/.initial=1pt,
- taper/.is~choice,
- taper/.default=both,
- taper/none/.style={
- taper~start=false,
- taper~end=false,
- },
- taper/both/.style={
- taper~start=true,
- taper~end=true,
- },
- taper/start/.style={
- taper~start=true,
- taper~end=false,
- },
- taper/end/.style={
- taper~start=false,
- taper~end=true,
- },
- taper~start/.code={
- \tl_if_eq:nnTF {#1} {true}
- {
- \bool_set_true:N \l__cal_taper_start_bool
- }
- {
- \bool_set_false:N \l__cal_taper_start_bool
- }
- },
- taper~start/.default={true},
- taper~end/.code={
- \tl_if_eq:nnTF {#1} {true}
- {
- \bool_set_true:N \l__cal_taper_end_bool
- }
- {
- \bool_set_false:N \l__cal_taper_end_bool
- }
- },
- taper~end/.default={true},
- taper~width/.code={\dim_set:Nn \l__cal_taper_width_dim {#1}},
- nib~style/.code~2~args={
- \tl_clear_new:c {l__cal_nib_style_#1}
- \tl_set:cn {l__cal_nib_style_#1} {#2}
- },
- stroke~style/.code~2~args={
- \tl_clear_new:c {l__cal_stroke_style_#1}
- \tl_set:cn {l__cal_stroke_style_#1} {#2}
- },
- this~stroke~style/.code={
- \tl_clear_new:c {l__cal_stroke_inline_style_ \int_use:N \l__cal_path_component_int}
- \tl_set:cn {l__cal_stroke_inline_style_ \int_use:N \l__cal_path_component_int} {#1}
- },
- annotate/.style={
- annotate~if,
- annotate~reset,
- annotation~style/.update~value={#1},
- },
- annotate~if/.default={true},
- annotate~if/.code={
- \tl_if_eq:nnTF {#1} {true}
- {
- \bool_set_true:N \l__cal_annotate_bool
- }
- {
- \bool_set_false:N \l__cal_annotate_bool
- }
- },
- annotate~reset/.code={
- \int_gzero:N \l__cal_label_int
- },
- annotation~style/.initial={draw,->},
- annotation~shift/.initial={(0,1ex)},
- every~annotation~node/.initial={anchor=south~west},
- annotation~node~style/.code~2~args={
- \tl_set:cn {l__cal_annotation_style_ #1 _tl}{#2}
- },
- tl~use:N/.code={
- \exp_args:NV \pgfkeysalso #1
- },
- tl~use:c/.code={
- \tl_if_exist:cT {#1}
- {
- \exp_args:Nv \pgfkeysalso {#1}
- }
- },
- /handlers/.update~style/.code={
- \tl_if_eq:nnF {#1} {\pgfkeysnovalue}
- {
- \pgfkeys{\pgfkeyscurrentpath/.code=\pgfkeysalso{#1}}
- }
- },
- /handlers/.update~value/.code={
- \tl_if_eq:nnF {#1} {\pgfkeysnovalue}
- {
- \pgfkeyssetvalue{\pgfkeyscurrentpath}{#1}
- }
- }
-}
-% \end{macrocode}
-%
-% Some wrappers around the TikZ keys.
-% \begin{macrocode}
-\NewDocumentCommand \pen { O{} }
-{
- \path[define~ pen,every~ calligraphy~ pen/.try,#1]
-}
-
-\NewDocumentCommand \definepen { O{} }
-{
- \tikz \path[define~ pen,every~ calligraphy~ pen/.try,#1]
-}
-
-\NewDocumentCommand \calligraphy { O{} }
-{
- \path[use~ pen,every~ calligraphy/.try,#1]
-}
-% \end{macrocode}
-%
-% \subsection{The Path Creation}
-%
-% \begin{macro}{\CalligraphyPathCreate}
-% This is the main command for creating the calligraphic paths.
-% \begin{macrocode}
-\NewDocumentCommand \CalligraphyPathCreate { m m }
-{
- \int_zero:N \l__cal_tmpa_int
- \tl_map_inline:cn {l__spath_list_#1}
- {
- \int_incr:N \l__cal_tmpa_int
- \int_zero:N \l__cal_tmpb_int
- \tl_map_inline:cn {l__spath_list_calligraphy pen #2}
- {
- \int_incr:N \l__cal_tmpb_int
- \group_begin:
- \pgfsys@beginscope
-
- \cal_apply_style:c {l__cal_stroke_style_ \int_use:N \l__cal_tmpa_int}
- \cal_apply_style:c {l__cal_stroke_inline_style_ \int_use:N \l__cal_tmpa_int}
- \cal_apply_style:c {l__cal_nib_style_ \int_use:N \l__cal_tmpb_int}
-
- \spath_clone:nn {##1} {calligraphy temp path}
-
- \__spath_get:nnN {####1} {initial point} \l__cal_tmpa_tl
- \spath_translate:nV {calligraphy temp path} \l__cal_tmpa_tl
-
- \__spath_get:nnN {####1} {length} \l__cal_tmpa_tl
-
- \int_compare:nTF {\l__cal_tmpa_tl = 1}
- {
- \cal_at_least_three:n {calligraphy temp path}
-
- \spath_protocol_path:n {calligraphy temp path}
-
- \__spath_get:nnN {calligraphy temp path} {path} \l__cal_tmpa_tl
-
- \tikz@options
- \dim_set:Nn \l__cal_line_width_dim {\pgflinewidth}
- \cal_maybe_taper:N \l__cal_tmpa_tl
- }
- {
-
- \spath_weld:nn {calligraphy temp path} {####1}
- \spath_reverse:n {##1}
- \spath_reverse:n {####1}
- \spath_weld:nn {calligraphy temp path} {##1}
- \spath_weld:nn {calligraphy temp path} {####1}
- \spath_reverse:n {##1}
- \spath_reverse:n {####1}
-
- \tl_clear:N \l__cal_tmpa_tl
- \tl_set:Nn \l__cal_tmpa_tl {fill=\pgfkeysvalueof{/tikz/pen~colour},draw=none}
- \tl_if_exist:cT {l__cal_stroke_style_ \int_use:N \l__cal_tmpa_int}
- {
- \tl_put_right:Nv \l__cal_tmpa_tl {l__cal_stroke_style_ \int_use:N \l__cal_tmpa_int}
- }
- \tl_if_exist:cT {l__cal_stroke_inline_style_ \int_use:N \l__cal_tmpa_int}
- {
- \tl_put_right:Nn \l__cal_tmpa_tl {,}
- \tl_put_right:Nv \l__cal_tmpa_tl {l__cal_stroke_inline_style_ \int_use:N \l__cal_tmpa_int}
- }
- \tl_if_exist:cT {l__cal_nib_style_ \int_use:N \l__cal_tmpb_int}
- {
- \tl_put_right:Nn \l__cal_tmpa_tl {,}
- \tl_put_right:Nv \l__cal_tmpa_tl {l__cal_nib_style_ \int_use:N \l__cal_tmpb_int}
- }
- \spath_tikz_path:Vn \l__cal_tmpa_tl {calligraphy temp path}
-
- }
- \pgfsys@endscope
- \group_end:
- }
- \bool_if:NT \l__cal_annotate_bool
- {
- \spath_clone:nn {##1} {calligraphy temp path}
- \tl_set_eq:Nc \l_tmpa_tl {l__spath_list_calligraphy pen #2}
- \tl_reverse:N \l_tmpa_tl
- \tl_set:Nx \l_tmpa_tl {\tl_head:N \l_tmpa_tl}
- \spath_generate_finalpoint:V \l_tmpa_tl
- \spath_get:VnN \l_tmpa_tl {final point} \l_tmpa_tl
- \spath_translate:nV {calligraphy temp path} \l_tmpa_tl
- \tikz@scan@one@point\pgfutil@firstofone\pgfkeysvalueof{/tikz/annotation~shift}
- \spath_translate:nnn {calligraphy temp path} {\pgf@x} {\pgf@y}
-
- \pgfkeysgetvalue{/tikz/annotation~style}{\l_tmpa_tl}
- \spath_tikz_path:Vn \l_tmpa_tl {calligraphy temp path}
- \spath_get:nnN {calligraphy temp path} {final point} \l_tmpa_tl
- \exp_last_unbraced:NV \pgfqpoint \l_tmpa_tl
- \begin{scope}[reset~ cm]
- \node[every~annotation~node/.try,tl~use:c = {l__cal_annotation_style_ \int_use:N \l__cal_tmpa_int _tl}] at (\pgf@x,\pgf@y) {\int_use:N \l__cal_tmpa_int};
- \end{scope}
- }
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\cal_moveto:n}
-% When creating the path, we need to keep track of the number of components so that we can apply styles accordingly.
-% \begin{macrocode}
-\cs_new_eq:NN \cal_orig_moveto:n \pgfpathmoveto
-\cs_new_nopar:Npn \cal_moveto:n #1
-{
- \int_gincr:N \l__cal_path_component_int
- \cal_orig_moveto:n {#1}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\cal_apply_style:N}
-% Interface for applying \Verb+\tikzset+ to a token list.
-% \begin{macrocode}
-\cs_new_nopar:Npn \cal_apply_style:N #1
-{
- \tl_if_exist:NT #1 {
- \exp_args:NV \tikzset #1
- }
-}
-\cs_generate_variant:Nn \cal_apply_style:N {c}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\cal_at_least_three:n}
-% A tapered path has to have at least three components.
-% This figures out if it is necessary and sets up the splitting.
-% \begin{macrocode}
-\cs_new_nopar:Npn \cal_at_least_three:n #1
-{
- \spath_get:nnN {#1} {real length} \l__cal_tmpa_tl
- \tl_clear:N \l__cal_tmpb_tl
- \int_compare:nTF {\l__cal_tmpa_tl = 1}
- {
- \spath_get:nnN {#1} {path} \l__cal_tmpa_tl
- \spath_map_segment_inline:Nn \l__cal_tmpa_tl
- {
- \tl_case:NnF ##1 {
- \g__spath_lineto_tl {
- \cal_split_line_in_three:NN \l__cal_tmpb_tl ##2
- }
- \g__spath_curvetoa_tl {
- \cal_split_curve_in_three:NN \l__cal_tmpb_tl ##2
- }
- }
- {
- \tl_put_right:NV \l__cal_tmpb_tl ##2
- }
- }
- \spath_put:nnV {#1} {path} \l__cal_tmpb_tl
- }
- {
- \int_compare:nT {\l__cal_tmpa_tl = 2}
- {
- \spath_get:nnN {#1} {path} \l__cal_tmpa_tl
- \spath_map_segment_inline:Nn \l__cal_tmpa_tl
- {
- \tl_case:NnF ##1 {
- \g__spath_lineto_tl {
- \cal_split_line_in_two:NN \l__cal_tmpb_tl ##2
- }
- \g__spath_curvetoa_tl {
- \cal_split_curve_in_two:NN \l__cal_tmpb_tl ##2
- }
- }
- {
- \tl_put_right:NV \l__cal_tmpb_tl ##2
- }
- }
- \spath_put:nnV {#1} {path} \l__cal_tmpb_tl
- }
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\cal_split_line_in_two:NN}
-% Splits a line in two, adding the splits to the first token list.
-% \begin{macrocode}
-\cs_new_nopar:Npn \cal_split_line_in_two:NN #1#2
-{
- \tl_set_eq:NN \l__cal_tmpc_tl #2
-
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \dim_set:Nn \l__cal_tmpa_dim {\tl_head:N \l__cal_tmpc_tl}
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \dim_set:Nn \l__cal_tmpb_dim {\tl_head:N \l__cal_tmpc_tl}
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \dim_set:Nn \l__cal_tmpc_dim {\tl_head:N \l__cal_tmpc_tl}
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
- \dim_set:Nn \l__cal_tmpd_dim {\tl_head:N \l__cal_tmpc_tl}
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \tl_put_right:NV #1 \g__spath_lineto_tl
-
- \tl_put_right:Nx #1 {
- {\dim_eval:n {(\l__cal_tmpa_dim + \l__cal_tmpc_dim)/2}}
- {\dim_eval:n {(\l__cal_tmpb_dim + \l__cal_tmpd_dim)/2}}
- }
-
- \tl_put_right:NV #1 \g__spath_lineto_tl
- \tl_put_right:Nx #1 {
- {\dim_use:N \l__cal_tmpc_dim}
- {\dim_use:N \l__cal_tmpd_dim}
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\cal_split_line_in_three:NN}
-% Splits a line in three, adding the splits to the first token list.
-% \begin{macrocode}
-\cs_new_nopar:Npn \cal_split_line_in_three:NN #1#2
-{
- \tl_set_eq:NN \l__cal_tmpc_tl #2
-
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \dim_set:Nn \l__cal_tmpa_dim {\tl_head:N \l__cal_tmpc_tl}
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \dim_set:Nn \l__cal_tmpb_dim {\tl_head:N \l__cal_tmpc_tl}
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \dim_set:Nn \l__cal_tmpc_dim {\tl_head:N \l__cal_tmpc_tl}
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
- \dim_set:Nn \l__cal_tmpd_dim {\tl_head:N \l__cal_tmpc_tl}
- \tl_set:Nx \l__cal_tmpc_tl {\tl_tail:N \l__cal_tmpc_tl}
-
- \tl_put_right:NV #1 \g__spath_lineto_tl
-
- \tl_put_right:Nx #1 {
- {\dim_eval:n {(2\l__cal_tmpa_dim + \l__cal_tmpc_dim)/3}}
- {\dim_eval:n {(2\l__cal_tmpb_dim + \l__cal_tmpd_dim)/3}}
- }
-
- \tl_put_right:NV #1 \g__spath_lineto_tl
-
- \tl_put_right:Nx #1 {
- {\dim_eval:n {(\l__cal_tmpa_dim + 2\l__cal_tmpc_dim)/3}}
- {\dim_eval:n {(\l__cal_tmpb_dim + 2\l__cal_tmpd_dim)/3}}
- }
-
- \tl_put_right:NV #1 \g__spath_lineto_tl
- \tl_put_right:Nx #1 {
- {\dim_use:N \l__cal_tmpc_dim}
- {\dim_use:N \l__cal_tmpd_dim}
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\cal_split_curve_in_two:NN}
-% Splits a curve in two, adding the splits to the first token list.
-% \begin{macrocode}
-\cs_new_nopar:Npn \cal_split_curve_in_two:NN #1#2
-{
- \spath_split_curve:nVNN {.5} #2 \l_tmpa_tl \l_tmpb_tl
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_tail:N \l_tmpb_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_tail:N \l_tmpb_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_tail:N \l_tmpb_tl}
- \tl_put_right:NV #1 \l_tmpa_tl
- \tl_put_right:NV #1 \l_tmpb_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\cal_split_curve_in_three:NN}
-% Splits a curve in three, adding the splits to the first token list.
-% \begin{macrocode}
-\cs_new_nopar:Npn \cal_split_curve_in_three:NN #1#2
-{
- \spath_split_curve:nVNN {1/3} #2 \l_tmpa_tl \l_tmpb_tl
-
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_put_right:NV #1 \l_tmpa_tl
-
- \spath_split_curve:nVNN {.5} \l_tmpb_tl \l_tmpa_tl \l_tmpb_tl
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_tail:N \l_tmpb_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_tail:N \l_tmpb_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_tail:N \l_tmpb_tl}
- \tl_put_right:NV #1 \l_tmpa_tl
- \tl_put_right:NV #1 \l_tmpb_tl
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\cal_maybe_taper:N}
-% Possibly tapers the path, depending on the booleans.
-% \begin{macrocode}
-\cs_new_nopar:Npn \cal_maybe_taper:N #1
-{
- \tl_set_eq:NN \l__cal_tmpa_tl #1
-
- \bool_if:NT \l__cal_taper_start_bool
- {
-
- \dim_set:Nn \l__cal_tmpa_dim {\tl_item:Nn \l__cal_tmpa_tl {2}}
- \dim_set:Nn \l__cal_tmpb_dim {\tl_item:Nn \l__cal_tmpa_tl {3}}
- \tl_set:Nx \l__cal_tmpb_tl {\tl_item:Nn \l__cal_tmpa_tl {4}}
-
- \tl_case:NnF \l__cal_tmpb_tl
- {
- \g__spath_lineto_tl
- {
-
- \bool_set_true:N \l__cal_taperable_bool
- \dim_set:Nn \l__cal_tmpg_dim {\tl_item:Nn \l__cal_tmpa_tl {5}}
- \dim_set:Nn \l__cal_tmph_dim {\tl_item:Nn \l__cal_tmpa_tl {6}}
- \dim_set:Nn \l__cal_tmpc_dim {(2\l__cal_tmpa_dim + \l__cal_tmpg_dim)/3}
- \dim_set:Nn \l__cal_tmpd_dim {(2\l__cal_tmpb_dim + \l__cal_tmph_dim)/3}
- \dim_set:Nn \l__cal_tmpe_dim {(\l__cal_tmpa_dim + 2\l__cal_tmpg_dim)/3}
- \dim_set:Nn \l__cal_tmpf_dim {(\l__cal_tmpb_dim + 2\l__cal_tmph_dim)/3}
- \prg_replicate:nn {4}
- {
- \tl_set:Nx \l__cal_tmpa_tl {\tl_tail:N \l__cal_tmpa_tl}
- }
- \tl_put_left:NV \l__cal_tmpa_tl \g__spath_moveto_tl
- }
- \g__spath_curvetoa_tl
- {
- \bool_set_true:N \l__cal_taperable_bool
- \dim_set:Nn \l__cal_tmpc_dim {\tl_item:Nn \l__cal_tmpa_tl {5}}
- \dim_set:Nn \l__cal_tmpd_dim {\tl_item:Nn \l__cal_tmpa_tl {6}}
- \dim_set:Nn \l__cal_tmpe_dim {\tl_item:Nn \l__cal_tmpa_tl {8}}
- \dim_set:Nn \l__cal_tmpf_dim {\tl_item:Nn \l__cal_tmpa_tl {9}}
- \dim_set:Nn \l__cal_tmpg_dim {\tl_item:Nn \l__cal_tmpa_tl {11}}
- \dim_set:Nn \l__cal_tmph_dim {\tl_item:Nn \l__cal_tmpa_tl {12}}
- \prg_replicate:nn {10}
- {
- \tl_set:Nx \l__cal_tmpa_tl {\tl_tail:N \l__cal_tmpa_tl}
- }
- \tl_put_left:NV \l__cal_tmpa_tl \g__spath_moveto_tl
- }
- }
- {
- \bool_set_false:N \l__cal_taperable_bool
- }
-
- \bool_if:NT \l__cal_taperable_bool
- {
- \__cal_taper_aux:
- }
-
- }
-
- \bool_if:NT \l__cal_taper_end_bool
- {
-
- \dim_set:Nn \l__cal_tmpa_dim {\tl_item:Nn \l__cal_tmpa_tl {-2}}
- \dim_set:Nn \l__cal_tmpb_dim {\tl_item:Nn \l__cal_tmpa_tl {-1}}
- \tl_set:Nx \l__cal_tmpb_tl {\tl_item:Nn \l__cal_tmpa_tl {-3}}
-
- \tl_case:NnF \l__cal_tmpb_tl
- {
- \g__spath_lineto_tl
- {
-
- \bool_set_true:N \l__cal_taperable_bool
- \dim_set:Nn \l__cal_tmpg_dim {\tl_item:Nn \l__cal_tmpa_tl {-5}}
- \dim_set:Nn \l__cal_tmph_dim {\tl_item:Nn \l__cal_tmpa_tl {-4}}
- \dim_set:Nn \l__cal_tmpc_dim {(2\l__cal_tmpa_dim + \l__cal_tmpg_dim)/3}
- \dim_set:Nn \l__cal_tmpd_dim {(2\l__cal_tmpb_dim + \l__cal_tmph_dim)/3}
- \dim_set:Nn \l__cal_tmpe_dim {(\l__cal_tmpa_dim + 2\l__cal_tmpg_dim)/3}
- \dim_set:Nn \l__cal_tmpf_dim {(\l__cal_tmpb_dim + 2\l__cal_tmph_dim)/3}
- \tl_reverse:N \l__cal_tmpa_tl
- \prg_replicate:nn {3}
- {
- \tl_set:Nx \l__cal_tmpa_tl {\tl_tail:N \l__cal_tmpa_tl}
- }
- \tl_reverse:N \l__cal_tmpa_tl
- }
- \g__spath_curveto_tl
- {
- \bool_set_true:N \l__cal_taperable_bool
- \dim_set:Nn \l__cal_tmpc_dim {\tl_item:Nn \l__cal_tmpa_tl {-5}}
- \dim_set:Nn \l__cal_tmpd_dim {\tl_item:Nn \l__cal_tmpa_tl {-4}}
- \dim_set:Nn \l__cal_tmpe_dim {\tl_item:Nn \l__cal_tmpa_tl {-8}}
- \dim_set:Nn \l__cal_tmpf_dim {\tl_item:Nn \l__cal_tmpa_tl {-7}}
- \dim_set:Nn \l__cal_tmpg_dim {\tl_item:Nn \l__cal_tmpa_tl {-11}}
- \dim_set:Nn \l__cal_tmph_dim {\tl_item:Nn \l__cal_tmpa_tl {-10}}
- \tl_reverse:N \l__cal_tmpa_tl
- \prg_replicate:nn {9}
- {
- \tl_set:Nx \l__cal_tmpa_tl {\tl_tail:N \l__cal_tmpa_tl}
- }
- \tl_reverse:N \l__cal_tmpa_tl
- }
- }
- {
- \bool_set_false:N \l__cal_taperable_bool
- }
-
- \bool_if:NT \l__cal_taperable_bool
- {
- \__cal_taper_aux:
- }
-
- }
-
- \pgfsyssoftpath@setcurrentpath\l__cal_tmpa_tl
- \pgfsetstrokecolor{\pgfkeysvalueof{/tikz/pen~colour}}
- \pgfusepath{stroke}
-
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\__cal_taper_aux:}
-% Auxiliary macro to avoid unnecessary code duplication.
-% \begin{macrocode}
-\cs_new_nopar:Npn \__cal_taper_aux:
-{
- \tl_clear:N \l__cal_tmpb_tl
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_moveto_tl
-
- \fp_set:Nn \l__cal_tmpa_fp
- {
- \l__cal_tmpd_dim - \l__cal_tmpb_dim
- }
- \fp_set:Nn \l__cal_tmpb_fp
- {
- \l__cal_tmpa_dim - \l__cal_tmpc_dim
- }
- \fp_set:Nn \l__cal_tmpe_fp
- {
- (\l__cal_tmpa_fp^2 + \l__cal_tmpb_fp^2)^.5
- }
-
- \fp_set:Nn \l__cal_tmpa_fp {.5*\l__cal_taper_width_dim * \l__cal_tmpa_fp / \l__cal_tmpe_fp}
- \fp_set:Nn \l__cal_tmpb_fp {.5*\l__cal_taper_width_dim * \l__cal_tmpb_fp / \l__cal_tmpe_fp}
-
- \fp_set:Nn \l__cal_tmpc_fp
- {
- \l__cal_tmph_dim - \l__cal_tmpf_dim
- }
- \fp_set:Nn \l__cal_tmpd_fp
- {
- \l__cal_tmpe_dim - \l__cal_tmpg_dim
- }
- \fp_set:Nn \l__cal_tmpe_fp
- {
- (\l__cal_tmpc_fp^2 + \l__cal_tmpd_fp^2)^.5
- }
-
- \fp_set:Nn \l__cal_tmpc_fp {.5*\l__cal_line_width_dim * \l__cal_tmpc_fp / \l__cal_tmpe_fp}
- \fp_set:Nn \l__cal_tmpd_fp {.5*\l__cal_line_width_dim * \l__cal_tmpd_fp / \l__cal_tmpe_fp}
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim}}
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curvetoa_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpc_dim}}
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpd_dim}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curvetob_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpe_dim}}
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmpf_dim}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curveto_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpg_dim}}
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmph_dim}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curvetoa_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpg_dim - \fp_to_dim:n{ 1.32 * \l__cal_tmpd_fp}}}
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmph_dim + \fp_to_dim:n {1.32* \l__cal_tmpc_fp}}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curvetob_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpg_dim - \fp_to_dim:n {1.32 * \l__cal_tmpd_fp}}}
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmph_dim + \fp_to_dim:n {1.32 * \l__cal_tmpc_fp}}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curveto_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpg_dim}}
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmph_dim}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curvetoa_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpc_fp + \l__cal_tmpe_dim}}
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpd_fp + \l__cal_tmpf_dim}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curvetob_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpc_dim}}
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpd_dim}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curveto_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim}}
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curvetoa_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim + \fp_to_dim:n{ 1.32 * \l__cal_tmpb_fp}}}
- {\dim_eval:n { -\fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim - \fp_to_dim:n {1.32* \l__cal_tmpa_fp}}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curvetob_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim + \fp_to_dim:n {1.32 * \l__cal_tmpb_fp}}}
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim - \fp_to_dim:n {1.32 * \l__cal_tmpa_fp}}}
- }
-
- \tl_put_right:NV \l__cal_tmpb_tl \g__spath_curveto_tl
-
- \tl_put_right:Nx \l__cal_tmpb_tl
- {
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpa_fp + \l__cal_tmpa_dim}}
- {\dim_eval:n { \fp_to_dim:N \l__cal_tmpb_fp + \l__cal_tmpb_dim}}
- }
-
- \pgfsyssoftpath@setcurrentpath\l__cal_tmpb_tl
- \pgfsetfillcolor{\pgfkeysvalueof{/tikz/pen~colour}}
- \pgfusepath{fill}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% Defines a copperplate pen.
-% \begin{macrocode}
-\tl_set:Nn \l__cal_tmpa_tl {\pgfsyssoftpath@movetotoken{0pt}{0pt}}
-\MakeSPathList{calligraphy pen copperplate}{\l__cal_tmpa_tl}
-\SPathListPrepare{calligraphy pen copperplate}
-% \end{macrocode}
-%
-% \begin{macrocode}
-\ExplSyntaxOff
-% \end{macrocode}
-%
-% \subsection{Decorations}
-%
-% If a decoration library is loaded we define some decorations that use the calligraphy library, specifically the copperplate pen with its tapering.
-%
-% First, a brace decoration.
-% \begin{macrocode}
-\expandafter\ifx\csname pgfdeclaredecoration\endcsname\relax
-\else
-\pgfdeclaredecoration{calligraphic brace}{brace}
-{
- \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]
- {
- \pgfsyssoftpath@setcurrentpath{\pgfutil@empty}
- \pgfpathmoveto{\pgfpointorigin}
- \pgfpathcurveto
- {\pgfqpoint{.15\pgfdecorationsegmentamplitude}{.3\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
- {
- \pgftransformxshift{+\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance}
- \pgfpathlineto{\pgfqpoint{-\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
- \pgfpathcurveto
- {\pgfqpoint{-.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{-.15\pgfdecorationsegmentamplitude}{.7\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{0\pgfdecorationsegmentamplitude}{1\pgfdecorationsegmentamplitude}}
- \pgfpathmoveto{\pgfqpoint{0\pgfdecorationsegmentamplitude}{1\pgfdecorationsegmentamplitude}}
- \pgfpathcurveto
- {\pgfqpoint{.15\pgfdecorationsegmentamplitude}{.7\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
- }
- {
- \pgftransformxshift{+\pgfdecoratedremainingdistance}
- \pgfpathlineto{\pgfqpoint{-\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
- \pgfpathcurveto
- {\pgfqpoint{-.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{-.15\pgfdecorationsegmentamplitude}{.3\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{0pt}{0pt}}
- }
- \tikzset{
- taper width=.5\pgflinewidth,
- taper
- }%
- \pgfsyssoftpath@getcurrentpath\cal@tmp@path
- \MakeSPathList{calligraphy path}{\cal@tmp@path}%
- \SPathListPrepare{calligraphy path}%
- \CalligraphyPathCreate{calligraphy path}{copperplate}%
- }
- \state{final}{}
-}
-% \end{macrocode}
-%
-% The second is a straightened parenthesis (so that when very large it doesn't bow out too far).
-% \begin{macrocode}
-\pgfdeclaredecoration{calligraphic straight parenthesis}{brace}
-{
- \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]
- {
- \pgfsyssoftpath@setcurrentpath{\pgfutil@empty}
- \pgfpathmoveto{\pgfpointorigin}
- \pgfpathcurveto
- {\pgfqpoint{.76604\pgfdecorationsegmentamplitude}{.64279\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{2.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{3.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
- {
- \pgftransformxshift{+\pgfdecoratedremainingdistance}
- \pgfpathlineto{\pgfqpoint{-3.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
- \pgfpathcurveto
- {\pgfqpoint{-2.3333\pgfdecorationsegmentamplitude}{\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{-.76604\pgfdecorationsegmentamplitude}{.64279\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{0pt}{0pt}}
- }
- \tikzset{
- taper width=.5\pgflinewidth,
- taper
- }%
- \pgfsyssoftpath@getcurrentpath\cal@tmp@path
- \MakeSPathList{calligraphy path}{\cal@tmp@path}%
- \SPathListPrepare{calligraphy path}%
- \CalligraphyPathCreate{calligraphy path}{copperplate}%
- }
- \state{final}{}%
-}
-% \end{macrocode}
-%
-% The third is a curved parenthesis.
-% \begin{macrocode}
-\pgfdeclaredecoration{calligraphic curved parenthesis}{brace}
-{
- \state{brace}[width=+\pgfdecoratedremainingdistance,next state=final]
- {
- \pgfsyssoftpath@setcurrentpath{\pgfutil@empty}
- \pgfpathmoveto{\pgfpointorigin}
- \pgf@xa=\pgfdecoratedremainingdistance\relax
- \advance\pgf@xa by -1.5890\pgfdecorationsegmentamplitude\relax
- \edef\cgrphy@xa{\the\pgf@xa}
- \pgfpathcurveto
- {\pgfqpoint{1.5890\pgfdecorationsegmentamplitude}{1.3333\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{\cgrphy@xa}{1.3333\pgfdecorationsegmentamplitude}}
- {\pgfqpoint{\pgfdecoratedremainingdistance}{0pt}}
- \tikzset{
- taper width=.5\pgflinewidth,
- taper
- }%
- \pgfsyssoftpath@getcurrentpath\cal@tmp@path
- \MakeSPathList{calligraphy path}{\cal@tmp@path}%
- \SPathListPrepare{calligraphy path}%
- \CalligraphyPathCreate{calligraphy path}{copperplate}%
- }
- \state{final}{}%
-}
-% \end{macrocode}
-% End the conditional for if pgfdecoration module is loaded
-% \begin{macrocode}
-\fi
-% \end{macrocode}
-% \iffalse
-%</calligraphy>
-% \fi
-%
-%
-% \iffalse
-%<*knots>
-% \fi
-%%
-% \section{Drawing Knots}
-%
-%
-% \subsection{Initialisation}
-%
-% We load the \Verb+spath3+ library and the \Verb+intersections+ TikZ library.
-% Then we get going.
-% \begin{macrocode}
-\RequirePackage{spath3}
-\usetikzlibrary{intersections}
-
-\ExplSyntaxOn
-
-\tl_new:N \l__knot_tmpa_tl
-\tl_new:N \l__knot_tmpb_tl
-\tl_new:N \l__knot_tmpc_tl
-\tl_new:N \l__knot_tmpd_tl
-\tl_new:N \l__knot_tmpe_tl
-\tl_new:N \l__knot_tmpf_tl
-\tl_new:N \l__knot_tmpg_tl
-\tl_new:N \l__knot_redraws_tl
-\tl_new:N \l__knot_clip_width_tl
-\tl_new:N \l__knot_name_tl
-\tl_new:N \l__knot_node_tl
-\tl_new:N \l__knot_aux_tl
-\tl_new:N \l__knot_auxa_tl
-
-\int_new:N \l__knot_tmpa_int
-\int_new:N \l__knot_strands_int
-\int_new:N \l__knot_intersections_int
-\int_new:N \l__knot_filaments_int
-\int_new:N \l__knot_component_start_int
-
-\dim_new:N \l__knot_tmpa_dim
-\dim_new:N \l__knot_tmpb_dim
-\dim_new:N \l__knot_tmpc_dim
-\dim_new:N \l__knot_tolerance_dim
-\dim_new:N \l__knot_clip_bg_radius_dim
-\dim_new:N \l__knot_clip_draw_radius_dim
-
-\bool_new:N \l__knot_draft_bool
-\bool_new:N \l__knot_ignore_ends_bool
-\bool_new:N \l__knot_self_intersections_bool
-\bool_new:N \l__knot_splits_bool
-\bool_new:N \l__knot_super_draft_bool
-
-\bool_new:N \l__knot_prepend_prev_bool
-\bool_new:N \l__knot_append_next_bool
-\bool_new:N \l__knot_skip_bool
-\bool_new:N \l__knot_save_bool
-
-\seq_new:N \l__knot_nodes_seq
-
-\bool_set_true:N \l__knot_ignore_ends_bool
-% \end{macrocode}
-%
-% Configuration is via TikZ keys and styles.
-% \begin{macrocode}
-\tikzset{
- knot/.code={
- \tl_if_eq:nnTF {#1} {none}
- {
- \tikz@addmode{\tikz@mode@doublefalse}
- }
- {
- \tikz@addmode{\tikz@mode@doubletrue}
- \tl_if_eq:nnTF {\pgfkeysnovalue} {#1}
- {
- \tikz@addoption{\pgfsetinnerstrokecolor{.}}
- }
- {
- \pgfsetinnerstrokecolor{#1}
- }
- \tikz@addoption{
- \pgfsetstrokecolor{knotbg}
- }
- \tl_set:Nn \tikz@double@setup{
- \pgfsetinnerlinewidth{\pgflinewidth}
- \pgfsetlinewidth{\dim_eval:n {\tl_use:N \l__knot_gap_tl \pgflinewidth}}
- }
- }
- },
- knot~ gap/.store~ in=\l__knot_gap_tl,
- knot~ gap=3,
- knot~ diagram/.is~family,
- knot~ diagram/.unknown/.code={
- \tl_set_eq:NN \l__knot_tmpa_tl \pgfkeyscurrentname
- \pgfkeysalso{
- /tikz/\l__knot_tmpa_tl=#1
- }
- },
- background~ colour/.code={%
- \colorlet{knotbg}{#1}%
- },
- background~ color/.code={%
- \colorlet{knotbg}{#1}%
- },
- background~ colour=white,
- knot~ diagram,
- name/.store~ in=\l__knot_name_tl,
- name={knot},
- save~ intersections/.is~ choice,
- save~ intersections/.default=true,
- save~ intersections/true/.code={
- \bool_set_true:N \l__knot_save_bool
- },
- save~ intersections/false/.code={
- \bool_set_false:N \l__knot_save_bool
- },
- every~ strand/.style={draw},
- ignore~ endpoint~ intersections/.code={
- \tl_if_eq:nnTF {#1} {true}
- {
- \bool_set_true:N \l__knot_ignore_ends_bool
- }
- {
- \bool_set_false:N \l__knot_ignore_ends_bool
- }
- },
- ignore~ endpoint~ intersections/.default=true,
- consider~ self~ intersections/.is~choice,
- consider~ self~ intersections/true/.code={
- \bool_set_true:N \l__knot_self_intersections_bool
- \bool_set_true:N \l__knot_splits_bool
- },
- consider~ self~ intersections/false/.code={
- \bool_set_false:N \l__knot_self_intersections_bool
- \bool_set_false:N \l__knot_splits_bool
- },
- consider~ self~ intersections/no~ splits/.code={
- \bool_set_true:N \l__knot_self_intersections_bool
- \bool_set_false:N \l__knot_splits_bool
- },
- consider~ self~ intersections/.default={true},
- clip~ radius/.code={
- \dim_set:Nn \l__knot_clip_bg_radius_dim {#1}
- \dim_set:Nn \l__knot_clip_draw_radius_dim {#1+2pt}
- },
- clip~ draw~ radius/.code={
- \dim_set:Nn \l__knot_clip_draw_radius_dim {#1}
- },
- clip~ background~ radius/.code={
- \dim_set:Nn \l__knot_clip_bg_radius_dim {#1}
- },
- clip~ radius=10pt,
- end~ tolerance/.code={
- \dim_set:Nn \l__knot_tolerance_dim {#1}
- },
- end~ tolerance=14pt,
- clip/.style={
- clip
- },
- background~ clip/.style={
- clip
- },
- clip~ width/.code={
- \tl_set:Nn \l__knot_clip_width_tl {#1}
- },
- clip~ width=3,
- flip~ crossing/.code={%
- \tl_clear_new:c {l__knot_crossing_#1}
- \tl_set:cn {l__knot_crossing_#1} {x}
- },
- ignore~ crossing/.code={%
- \tl_clear_new:c {l__knot_ignore_crossing_#1}
- \tl_set:cn {l__knot_ignore_crossing_#1} {x}
- },
- draft~ mode/.is~ choice,
- draft~ mode/off/.code={%
- \bool_set_false:N \l__knot_draft_bool
- \bool_set_false:N \l__knot_super_draft_bool
- },
- draft~ mode/crossings/.code={%
- \bool_set_true:N \l__knot_draft_bool
- \bool_set_false:N \l__knot_super_draft_bool
- },
- draft~ mode/strands/.code={%
- \bool_set_true:N \l__knot_draft_bool
- \bool_set_true:N \l__knot_super_draft_bool
- },
- draft/.is~ family,
- draft,
- crossing~ label/.style={
- overlay,
- fill=white,
- fill~ opacity=.5,
- text~ opacity=1,
- text=blue,
- pin~ edge={blue,<-}
- },
- strand~ label/.style={
- overlay,
- circle,
- draw=purple,
- fill=white,
- fill~ opacity=.5,
- text~ opacity=1,
- text=purple,
- inner~ sep=0pt
- },
-}
-% \end{macrocode}
-%
-% Wrapper around \Verb+\tikzset+ for applying keys from a token list, checking for if the given token list exists.
-% \begin{macrocode}
-\cs_new_nopar:Npn \knot_apply_style:N #1
-{
- \tl_if_exist:NT #1 {
- \exp_args:NV \tikzset #1
- }
-}
-\cs_generate_variant:Nn \knot_apply_style:N {c}
-% \end{macrocode}
-%
-%\begin{macro}{\flipcrossings}
-% The user can specify a comma separated list of crossings to flip.
-% \begin{macrocode}
-\NewDocumentCommand \flipcrossings {m}
-{
- \tikzset{knot~ diagram/flip~ crossing/.list={#1}}%
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\strand}
-% This is how the user specifies a strand of the knot.
-% \begin{macrocode}
-\NewDocumentCommand \strand { O{} }
-{
- \int_incr:N \l__knot_strands_int
- \tl_clear_new:c {l__knot_options_strand \int_use:N \l__knot_strands_int}
- \tl_set:cn {l__knot_options_strand \int_use:N \l__knot_strands_int} {#1}
- \path[#1,save~ spath=knot strand \int_use:N \l__knot_strands_int]
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{knot}
-% This is the wrapper environment that calls the knot generation code.
-% \begin{macrocode}
-\NewDocumentEnvironment{knot} { O{} }
-{
- \knot_initialise:n {#1}
-}
-{
- \knot_render:
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_initialise:n}
-% Set up some stuff before loading in the strands.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_initialise:n #1
-{
- \tikzset{knot~ diagram/.cd,every~ knot~ diagram/.try,#1}
- \int_zero:N \l__knot_strands_int
- \tl_clear:N \l__knot_redraws_tl
- \seq_gclear:N \l__knot_nodes_seq
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_render:}
-% This is the code that starts the work of rendering the knot.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_render:
-{
-% \end{macrocode}
-% Start a scope and reset the transformation (since all transformations have already been taken into account when defining the strands).
-% \begin{macrocode}
- \pgfscope
- \pgftransformreset
-% \end{macrocode}
-% Loop through the strands drawing each one for the first time.
-% \begin{macrocode}
- \int_step_function:nnnN {1} {1} {\l__knot_strands_int} \knot_draw_strand:n
-% \end{macrocode}
-% In super draft mode we don't do anything else.
-% \begin{macrocode}
- \bool_if:NF \l__knot_super_draft_bool
- {
-% \end{macrocode}
-% In draft mode we draw labels at the ends of the strands; this also handles splitting curves to avoid self-intersections of Bezier curves if that's requested.
-% \begin{macrocode}
- \int_step_function:nnnN {1} {1} {\l__knot_strands_int} \knot_draw_labels:n
-% \end{macrocode}
-% If we're considering self intersections we need to split the strands into filaments.
-% \begin{macrocode}
- \bool_if:NTF \l__knot_self_intersections_bool
- {
- \knot_split_strands:
- \int_set_eq:NN \l__knot_tmpa_int \l__knot_filaments_int
- \tl_set:Nn \l__knot_prefix_tl {filament}
- }
- {
- \int_set_eq:NN \l__knot_tmpa_int \l__knot_strands_int
- \tl_set:Nn \l__knot_prefix_tl {strand}
- }
-% \end{macrocode}
-% Initialise the intersection count.
-% \begin{macrocode}
- \int_gzero:N \l__knot_intersections_int
-% \end{macrocode}
-% If in draft mode we label the intersections, otherwise we just stick a coordinate at each one.
-% \begin{macrocode}
- \bool_if:NTF \l__knot_draft_bool
- {
- \tl_set:Nn \l__knot_node_tl {
- \exp_not:N \node[coordinate,
- pin={[node~ contents={\int_use:N \l__knot_intersections_int},knot~ diagram/draft/crossing~ label, knot~ diagram/draft/crossing~ \int_use:N \l__knot_intersections_int \c_space_tl label/.try]
- }]
- }
- }
- {
- \tl_set:Nn \l__knot_node_tl {\exp_not:N \node[coordinate]}
- }
-% \end{macrocode}
-% This double loop steps through the pieces (strands or filaments) and computes the intersections and does stuff with those.
-% \begin{macrocode}
- \int_step_variable:nnnNn {1} {1} {\l__knot_tmpa_int - 1} \l__knot_tmpa_tl
- {
- \int_step_variable:nnnNn {\tl_use:N \l__knot_tmpa_tl + 1} {1} {\l__knot_tmpa_int} \l__knot_tmpb_tl
- {
- \knot_intersections:VV \l__knot_tmpa_tl \l__knot_tmpb_tl
- }
- }
-% \end{macrocode}
-% If any redraws were requested, do them here.
-% \begin{macrocode}
- \tl_use:N \l__knot_redraws_tl
-% \end{macrocode}
-% Draw the crossing nodes
-% \begin{macrocode}
- \seq_use:Nn \l__knot_nodes_seq {}
- }
-% \end{macrocode}
-% Close the scope
-% \begin{macrocode}
- \endpgfscope
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_draw_strand:n}
-% This renders a strand using the options originally specified.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_draw_strand:n #1
-{
- \pgfscope
- \group_begin:
- \tl_set:Nn \l_tmpa_tl {knot~ diagram/every~ strand/.try,}
- \tl_put_right:Nv \l_tmpa_tl {l__knot_options_strand #1}
- \tl_put_right:Nn \l_tmpa_tl {,knot~ diagram/only~ when~ rendering/.try,only~ when~ rendering/.try}
- \spath_bake_round:n {knot strand #1}
- \spath_tikz_path:Vn \l_tmpa_tl {knot strand #1}
- \group_end:
- \endpgfscope
-}
-\cs_generate_variant:Nn \tl_put_right:Nn {Nv}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_draw_labels:n}
-% Draw a label at each end of each strand, if in draft mode.
-% Also, if requested, split potentially self intersecting Bezier curves.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_draw_labels:n #1
-{
- \bool_if:NT \l__knot_draft_bool
- {
- \spath_get:nnN {knot strand #1} {final point} \l__knot_tmpb_tl
- \dim_set:Nn \l__knot_tmpa_dim {\tl_item:Nn \l__knot_tmpb_tl {1}}
- \dim_set:Nn \l__knot_tmpb_dim {\tl_item:Nn \l__knot_tmpb_tl {2}}
- \node[knot~ diagram/draft/strand~label] at (\l__knot_tmpa_dim,\l__knot_tmpb_dim) {#1};
- \spath_get:nnN {knot strand #1} {initial point} \l__knot_tmpb_tl
- \dim_set:Nn \l__knot_tmpa_dim {\tl_item:Nn \l__knot_tmpb_tl {1}}
- \dim_set:Nn \l__knot_tmpb_dim {\tl_item:Nn \l__knot_tmpb_tl {2}}
- \node[knot~ diagram/draft/strand~label] at (\l__knot_tmpa_dim,\l__knot_tmpb_dim) {#1};
- }
- \bool_if:nT {
- \l__knot_self_intersections_bool
- &&
- \l__knot_splits_bool
- }
- {
- \tl_clear:N \l__knot_tmpa_tl
- \spath_map_segment_function:nN {knot strand #1} \knot_split_self_intersects:NN
- \spath_put:nnV {knot strand #1} {path} \l__knot_tmpa_tl
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_split_self_intersects:NN}
-% This is the macro that does the split.
-% Figuring out whether a Bezier cubic self intersects is apparently a difficult problem so we don't bother.
-% We compute a point such that if there is an intersection then it lies on either side of the point.
-% I don't recall where the formula came from!
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_split_self_intersects:NN #1#2
-{
- \tl_case:NnF #1
- {
- \g__spath_curvetoa_tl
- {
- \fp_set:Nn \l_tmpa_fp
- {
- (\tl_item:Nn #2 {3} - 3 * \tl_item:Nn #2 {6} + 3 * \tl_item:Nn #2 {9} - \tl_item:Nn #2 {12})
- *
- (3 * \tl_item:Nn #2 {8} - 3 * \tl_item:Nn #2 {11})
- -
- (\tl_item:Nn #2 {2} - 3 * \tl_item:Nn #2 {5} + 3 * \tl_item:Nn #2 {8} - \tl_item:Nn #2 {11})
- *
- (3 * \tl_item:Nn #2 {9} - 3 * \tl_item:Nn #2 {12})
- }
- \fp_set:Nn \l_tmpb_fp
- {
- (\tl_item:Nn #2 {2} - 3 * \tl_item:Nn #2 {5} + 3 * \tl_item:Nn #2 {8} - \tl_item:Nn #2 {11})
- *
- (3 * \tl_item:Nn #2 {6} - 6 * \tl_item:Nn #2 {9} + 3 * \tl_item:Nn #2 {12})
- -
- (\tl_item:Nn #2 {3} - 3 * \tl_item:Nn #2 {6} + 3 * \tl_item:Nn #2 {9} - \tl_item:Nn #2 {12})
- *
- (3 * \tl_item:Nn #2 {5} - 6 * \tl_item:Nn #2 {8} + 3 * \tl_item:Nn #2 {11})
- }
- \fp_compare:nTF
- {
- \l_tmpb_fp != 0
- }
- {
- \fp_set:Nn \l_tmpa_fp {.5 * \l_tmpa_fp / \l_tmpb_fp}
- \fp_compare:nTF
- {
- 0 < \l_tmpa_fp && \l_tmpa_fp < 1
- }
- {
- \spath_split_curve:VVNN \l_tmpa_fp #2 \l_tmpa_tl \l_tmpb_tl
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_tail:N \l_tmpb_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_tail:N \l_tmpb_tl}
- \tl_set:Nx \l_tmpb_tl {\tl_tail:N \l_tmpb_tl}
- \tl_put_right:NV \l__knot_tmpa_tl \l_tmpa_tl
- \tl_put_right:NV \l__knot_tmpa_tl \l_tmpb_tl
- }
- {
- \tl_set_eq:NN \l_tmpa_tl #2
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_put_right:NV \l__knot_tmpa_tl \l_tmpa_tl
- }
- }
- {
- \tl_set_eq:NN \l_tmpa_tl #2
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_put_right:NV \l__knot_tmpa_tl \l_tmpa_tl
- }
- }
- \g__spath_lineto_tl
- {
- \tl_set_eq:NN \l_tmpa_tl #2
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_set:Nx \l_tmpa_tl {\tl_tail:N \l_tmpa_tl}
- \tl_put_right:NV \l__knot_tmpa_tl \l_tmpa_tl
- }
- }
- {
- \tl_put_right:NV \l__knot_tmpa_tl #2
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_intersections:nn}
-% This computes the intersections of two pieces and steps through them.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_intersections:nn #1#2
-{
- \group_begin:
- \tl_set_eq:NN \l__knot_tmpa_tl \l__knot_prefix_tl
- \tl_put_right:Nn \l__knot_tmpa_tl {#1}
- \tl_set_eq:NN \l__knot_tmpb_tl \l__knot_prefix_tl
- \tl_put_right:Nn \l__knot_tmpb_tl {#2}
- \spath_get:nnN {knot \tl_use:N \l__knot_tmpa_tl} {path} \l__knot_tmpc_tl
- \spath_get:nnN {knot \tl_use:N \l__knot_tmpb_tl} {path} \l__knot_tmpd_tl
-
- \bool_if:nTF {
- \l__knot_save_bool
- &&
- \tl_if_exist_p:c {knot~ intersections~ \tl_use:N \l__knot_name_tl - \tl_use:N \l__knot_tmpa_tl - \tl_use:N \l__knot_tmpb_tl}
- }
- {
- \tl_use:c {knot~ intersections~ \tl_use:N \l__knot_name_tl - \tl_use:N \l__knot_tmpa_tl - \tl_use:N \l__knot_tmpb_tl}
- }
- {
-\pgfintersectionofpaths{\pgfsetpath\l__knot_tmpc_tl}{\pgfsetpath\l__knot_tmpd_tl}
-
- }
- \int_compare:nT {\pgfintersectionsolutions > 0}
- {
- \int_step_function:nnnN {1} {1} {\pgfintersectionsolutions} \knot_do_intersection:n
- }
- \knot_save_intersections:VV \l__knot_tmpa_tl \l__knot_tmpb_tl
- \group_end:
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_save_intersections:nn}
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_save_intersections:nn #1#2
-{
- \bool_if:NT \l__knot_save_bool
- {
- \tl_clear:N \l__knot_aux_tl
- \tl_put_right:Nn \l__knot_aux_tl
- {
- \def\pgfintersectionsolutions
- }
- \tl_put_right:Nx \l__knot_aux_tl
- {
- {\int_eval:n {\pgfintersectionsolutions}}
- }
- \int_compare:nT {\pgfintersectionsolutions > 0}
- {
- \int_step_inline:nnnn {1} {1} {\pgfintersectionsolutions}
- {
- \pgfpointintersectionsolution{##1}
- \dim_set:Nn \l__knot_tmpa_dim {\pgf@x}
- \dim_set:Nn \l__knot_tmpb_dim {\pgf@y}
- \tl_put_right:Nn \l__knot_aux_tl
- {
- \expandafter\def\csname pgfpoint@intersect@solution@##1\endcsname
- }
- \tl_put_right:Nx \l__knot_aux_tl
- {
- {\exp_not:N \pgf@x=\dim_use:N \l__knot_tmpa_dim\exp_not:N\relax\exp_not:N \pgf@y =\dim_use:N \l__knot_tmpb_dim\relax}
- }
- }
- \tl_set:Nn \l__knot_auxa_tl {\expandafter \gdef \csname knot~ intersections~}
- \tl_put_right:Nx \l__knot_auxa_tl {\tl_use:N \l__knot_name_tl - #1 - #2}
- \tl_put_right:Nn \l__knot_auxa_tl {\endcsname}
- \tl_put_right:Nx \l__knot_auxa_tl {{\tl_to_str:N \l__knot_aux_tl}}
- \protected@write\@auxout{}{\tl_to_str:N \l__knot_auxa_tl}
- }
- }
-}
-\cs_generate_variant:Nn \knot_save_intersections:nn {VV}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_do_intersection:n}
-% This handles a specific intersection.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_do_intersection:n #1
-{
-% \end{macrocode}
-% Get the intersection coordinates.
-% \begin{macrocode}
- \pgfpointintersectionsolution{#1}
- \dim_set:Nn \l__knot_tmpa_dim {\pgf@x}
- \dim_set:Nn \l__knot_tmpb_dim {\pgf@y}
-% \end{macrocode}
-% If we're dealing with filaments, we can get false positives from the end points.
-% \begin{macrocode}
- \bool_set_false:N \l__knot_skip_bool
- \bool_if:NT \l__knot_self_intersections_bool
- {
-% \end{macrocode}
-% If one filament preceded the other, test for the intersection being at the relevant end point.
-% \begin{macrocode}
- \tl_set:Nn \l_tmpa_tl {knot previous}
- \tl_put_right:NV \l_tmpa_tl \l__knot_tmpa_tl
- \tl_set:Nv \l_tmpa_tl \l_tmpa_tl
- \tl_if_eq:NNT \l_tmpa_tl \l__knot_tmpb_tl
- {
- \knot_test_endpoint:VnT \l__knot_tmpb_tl {final point}
- {
- \bool_set_true:N \l__knot_skip_bool
- }
- }
-
- \tl_set:Nn \l_tmpa_tl {knot previous}
- \tl_put_right:NV \l_tmpa_tl \l__knot_tmpb_tl
- \tl_set:Nv \l_tmpa_tl \l_tmpa_tl
- \tl_if_eq:NNT \l_tmpa_tl \l__knot_tmpa_tl
- {
- \knot_test_endpoint:VnT \l__knot_tmpa_tl {final point}
- {
- \bool_set_true:N \l__knot_skip_bool
- }
- }
- }
-% \end{macrocode}
-% The user can also say that end points of filaments (or strands) should simply be ignored anyway.
-% \begin{macrocode}
- \bool_if:NT \l__knot_ignore_ends_bool
- {
- \knot_test_endpoint:VnT \l__knot_tmpa_tl {initial point}
- {
- \bool_set_true:N \l__knot_skip_bool
- }
- \knot_test_endpoint:VnT \l__knot_tmpa_tl {final point}
- {
- \bool_set_true:N \l__knot_skip_bool
- }
- \knot_test_endpoint:VnT \l__knot_tmpb_tl {initial point}
- {
- \bool_set_true:N \l__knot_skip_bool
- }
- \knot_test_endpoint:VnT \l__knot_tmpb_tl {final point}
- {
- \bool_set_true:N \l__knot_skip_bool
- }
- }
-% \end{macrocode}
-% Assuming that we passed all the above tests, we render the crossing.
-% \begin{macrocode}
- \bool_if:NF \l__knot_skip_bool
- {
-
- \int_gincr:N \l__knot_intersections_int
-% \end{macrocode}
-% This is the intersection test.
-% If the intersection finder finds too many, it might be useful to ignore some.
-% \begin{macrocode}
- \bool_if:nF
- {
- \tl_if_exist_p:c {l__knot_ignore_crossing_ \int_use:N
- \l__knot_intersections_int}
- &&
- ! \tl_if_empty_p:c {l__knot_ignore_crossing_ \int_use:N
- \l__knot_intersections_int}
- }
- {
-% \end{macrocode}
-% This is the flip test.
-% We only render one of the paths.
-% The ``flip'' swaps which one we render.
-% \begin{macrocode}
- \bool_if:nTF
- {
- \tl_if_exist_p:c {l__knot_crossing_ \int_use:N
- \l__knot_intersections_int}
- &&
- ! \tl_if_empty_p:c {l__knot_crossing_ \int_use:N
- \l__knot_intersections_int}
- }
- {
- \tl_set_eq:NN \l__knot_tmpg_tl \l__knot_tmpb_tl
- }
- {
- \tl_set_eq:NN \l__knot_tmpg_tl \l__knot_tmpa_tl
- }
-% \end{macrocode}
-% Now we know which one we're rendering, we test to see if we should also render its predecessor or successor to ensure that we render a path through the entire crossing region.
-% \begin{macrocode}
- \bool_if:NT \l__knot_self_intersections_bool
- {
- \knot_test_endpoint:VnT \l__knot_tmpg_tl {initial point}
- {
- \bool_set_true:N \l__knot_prepend_prev_bool
- }
- {
- \bool_set_false:N \l__knot_prepend_prev_bool
- }
- \knot_test_endpoint:VnT \l__knot_tmpg_tl {final point}
- {
- \bool_set_true:N \l__knot_append_next_bool
- }
- {
- \bool_set_false:N \l__knot_append_next_bool
- }
-% \end{macrocode}
-% If either of those tests succeeded, do the appending or prepending.
-% \begin{macrocode}
- \bool_if:nT
- {
- \l__knot_prepend_prev_bool || \l__knot_append_next_bool
- }
- {
- \spath_clone:nn {knot \tl_use:N \l__knot_tmpg_tl}
- {knot \tl_use:N \l__knot_prefix_tl -1}
-
- \tl_set_eq:cc {l__knot_options_ \tl_use:N \l__knot_prefix_tl -1} {l__knot_options_ \tl_use:N \l__knot_tmpg_tl}
-
- \bool_if:nT
- {
- \l__knot_prepend_prev_bool
- &&
- \tl_if_exist_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
- &&
- !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
- }
- {
- \spath_prepend_no_move:nn {knot \tl_use:N \l__knot_prefix_tl -1} {knot \tl_use:c {knot previous \tl_use:N \l__knot_tmpg_tl}}
-% \end{macrocode}
-% If we split potentially self intersecting curves, we test to see if we should prepend yet another segment.
-% \begin{macrocode}
- \bool_if:nT
- {
- \l__knot_splits_bool
- &&
- \tl_if_exist_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
- &&
- !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
- }
- {
- \knot_test_endpoint:vnT {knot previous \tl_use:N \l__knot_tmpg_tl} {initial point}
- {
- \spath_get:nnN {knot \tl_use:N \l__knot_prefix_tl -1} {path} \l_tmpa_tl
- \spath_prepend_no_move:nn {knot \tl_use:N \l__knot_prefix_tl -1} {knot \tl_use:c {knot previous \tl_use:c {knot previous \tl_use:N \l__knot_tmpg_tl}}}
- \spath_get:nnN {knot \tl_use:N \l__knot_prefix_tl -1} {path} \l_tmpa_tl
-
- }
- }
- }
-% \end{macrocode}
-% Now the same for appending.
-% \begin{macrocode}
- \bool_if:nT
- {
- \l__knot_append_next_bool
- &&
- \tl_if_exist_p:c {knot next \tl_use:N \l__knot_tmpg_tl}
- &&
- !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
- }
- {
- \spath_append_no_move:nn {knot \tl_use:N \l__knot_prefix_tl -1} {knot \tl_use:c {knot next \tl_use:N \l__knot_tmpg_tl}}
- \bool_if:nT
- {
- \l__knot_splits_bool
- &&
- \tl_if_exist_p:c {knot previous \tl_use:N
- \l__knot_tmpg_tl}
- &&
- !\tl_if_empty_p:c {knot previous \tl_use:N \l__knot_tmpg_tl}
- }
- {
- \knot_test_endpoint:vnT {knot previous \tl_use:N \l__knot_tmpg_tl} {final point}
- {
- \spath_append_no_move:nn {knot \tl_use:N \l__knot_prefix_tl -1} {knot \tl_use:c {knot next \tl_use:c {knot next \tl_use:N \l__knot_tmpg_tl}}}
-
- }
- }
- }
-
- \tl_set:Nn \l__knot_tmpg_tl {\tl_use:N \l__knot_prefix_tl -1}
- }
- }
-% \end{macrocode}
-% Now we render the crossing.
-% \begin{macrocode}
- \pgfscope
- \group_begin:
- \tikzset{knot~ diagram/every~ intersection/.try, every~ intersection/.try, knot~ diagram/intersection~ \int_use:N \l__knot_intersections_int/.try}
- \knot_draw_crossing:nVV {\tl_use:N \l__knot_tmpg_tl} \l__knot_tmpa_dim \l__knot_tmpb_dim
- \group_end:
- \endpgfscope
-% \end{macrocode}
-% This ends the boolean as to whether to consider the intersection at all
-% \begin{macrocode}
- }
-% \end{macrocode}
-% And stick a coordinate possibly with a label at the crossing.
-% \begin{macrocode}
- \seq_gpush:Nx \l__knot_nodes_seq { \l__knot_node_tl (\l__knot_name_tl \c_space_tl \int_use:N \l__knot_intersections_int) at (\dim_use:N \l__knot_tmpa_dim, \dim_use:N \l__knot_tmpb_dim) {};}
-
- }
-}
-
-\cs_generate_variant:Nn \knot_intersections:nn {VV}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_test_endpoint:N}
-% Test whether the point is near the intersection point.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \knot_test_endpoint:N #1 {p,T,F,TF}
-{
- \dim_compare:nTF
- {
- \dim_abs:n { \l__knot_tmpa_dim - \tl_item:Nn #1 {1}}
- +
- \dim_abs:n { \l__knot_tmpb_dim - \tl_item:Nn #1 {2}}
- <
- \l__knot_tolerance_dim
- }
- {
- \prg_return_true:
- }
- {
- \prg_return_false:
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_test_endpoint:nn}
-% Wrapper around the above.
-% \begin{macrocode}
-\prg_new_protected_conditional:Npnn \knot_test_endpoint:nn #1#2 {T,F,TF}
-{
- \spath_get:nnN {knot #1} {#2} \l__knot_tmpd_tl
- \knot_test_endpoint:NTF \l__knot_tmpd_tl
- {
- \prg_return_true:
- }
- {
- \prg_return_false:
- }
-}
-
-\cs_generate_variant:Nn \knot_test_endpoint:nnT {VnT,vnT}
-\cs_generate_variant:Nn \knot_test_endpoint:nnF {VnF,vnF}
-\cs_generate_variant:Nn \knot_test_endpoint:nnTF {VnTF,vnTF}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_draw_crossing:nnn}
-% This is the code that actually renders a crossing.
-% \begin{macrocode}
-\cs_new_nopar:Npn \knot_draw_crossing:nnn #1#2#3
-{
- \group_begin:
- \pgfscope
- \path[knot~ diagram/background~ clip] (#2, #3) circle[radius=\l__knot_clip_bg_radius_dim];
-
- \tl_set:Nn \l_tmpa_tl {knot~ diagram/every~ strand/.try,}
- \tl_if_exist:cT {l__knot_options_ #1}
- {
- \tl_put_right:Nv \l_tmpa_tl {l__knot_options_ #1}
- }
- \tl_put_right:Nn \l_tmpa_tl {,knotbg,line~ width= \tl_use:N \l__knot_clip_width_tl * \pgflinewidth}
- \spath_tikz_path:Vn \l_tmpa_tl {knot #1}
-
- \endpgfscope
-
- \pgfscope
- \path[knot~ diagram/clip] (#2, #3) circle[radius=\l__knot_clip_draw_radius_dim];
-
- \tl_set:Nn \l_tmpa_tl {knot~ diagram/every~ strand/.try,}
- \tl_if_exist:cT {l__knot_options_ #1}
- {
- \tl_put_right:Nv \l_tmpa_tl {l__knot_options_ #1}
- }
- \tl_put_right:Nn \l_tmpa_tl {,knot~ diagram/only~ when~ rendering/.try,only~ when~ rendering/.try}
- \spath_tikz_path:Vn \l_tmpa_tl {knot #1}
-
- \endpgfscope
- \group_end:
-}
-
-\cs_generate_variant:Nn \knot_draw_crossing:nnn {nVV}
-
-\cs_new_nopar:Npn \knot_draw_crossing:nn #1#2
-{
- \tikz@scan@one@point\pgfutil@firstofone #2 \relax
- \knot_draw_crossing:nVV {#1} \pgf@x \pgf@y
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_split_strands:}
-% This, and the following macros, are for splitting strands into filaments.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_split_strands:
-{
- \int_gzero:N \l__knot_filaments_int
- \int_step_function:nnnN {1} {1} {\l__knot_strands_int} \knot_split_strand:n
- \int_step_function:nnnN {1} {1} {\l__knot_filaments_int} \knot_compute_nexts:n
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_compute_nexts:n}
-% Each filament needs to know its predecessor and successor.
-% We work out the predecessors as we go along, this fills in the successors.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_compute_nexts:n #1
-{
- \tl_clear_new:c {knot next \tl_use:c {knot previous filament #1}}
- \tl_set:cn {knot next \tl_use:c {knot previous filament #1}} {filament #1}
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_split_strand:n}
-% Sets up the split for a single strand.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_split_strand:n #1
-{
- \int_set_eq:NN \l__knot_component_start_int \l__knot_filaments_int
- \int_incr:N \l__knot_component_start_int
- \tl_set_eq:Nc \l__knot_tmpa_tl {l__knot_options_strand #1}
- \spath_map_segment_function:nN {knot strand #1} \knot_save_filament:NN
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\knot_save_filament:NN}
-% Saves a filament as a new \Verb+spath+ object.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \knot_save_filament:NN #1#2
-{
- \tl_case:NnF #1
- {
- \g__spath_moveto_tl
- {
- \int_compare:nT {\l__knot_component_start_int < \l__knot_filaments_int}
- {
- \int_set_eq:NN \l__knot_component_start_int \l__knot_filaments_int
- }
- }
- \g__spath_lineto_tl
- {
- \int_gincr:N \l__knot_filaments_int
- \spath_clear_new:n {knot filament \int_use:N \l__knot_filaments_int}
- \spath_put:nnV {knot filament \int_use:N \l__knot_filaments_int} {path} #2
- \tl_set_eq:cN {l__knot_options_filament \int_use:N \l__knot_filaments_int} \l__knot_tmpa_tl
-
- \tl_clear_new:c {knot previous filament \int_use:N \l__knot_filaments_int}
- \int_compare:nF {\l__knot_component_start_int == \l__knot_filaments_int}
- {
- \tl_set:cx {knot previous filament \int_use:N \l__knot_filaments_int} {filament \int_eval:n {\l__knot_filaments_int - 1}}
- }
- }
- \g__spath_curvetoa_tl
- {
- \int_gincr:N \l__knot_filaments_int
- \spath_clear_new:n {knot filament \int_use:N \l__knot_filaments_int}
- \spath_put:nnV {knot filament \int_use:N \l__knot_filaments_int} {path} #2
- \tl_set_eq:cN {l__knot_options_filament \int_use:N \l__knot_filaments_int} \l__knot_tmpa_tl
-
- \tl_clear_new:c {knot previous filament \int_use:N \l__knot_filaments_int}
- \int_compare:nF {\l__knot_component_start_int == \l__knot_filaments_int}
- {
- \tl_set:cx {knot previous filament \int_use:N \l__knot_filaments_int} {filament \int_eval:n {\l__knot_filaments_int - 1}}
- }
- }
- \g__spath_closepath_tl
- {
- \tl_show:N #2
- \int_gincr:N \l__knot_filaments_int
- \spath_clear_new:n {knot filament \int_use:N \l__knot_filaments_int}
- \tl_clear:N \l_tmpa_tl
- \tl_put_right:Nx {\tl_item:Nn #2 {1}\tl_item:Nn #2 {2}\tl_item:Nn #2 {3}}
- \tl_put_right:NV \l_tmpa_tl \g__spath_lineto_tl
- \tl_put_right:Nx {\tl_item:Nn #2 {5}\tl_item:Nn #2 {6}}
- \tl_show:N \l_tmpa_tl
- \spath_put:nnV {knot filament \int_use:N \l__knot_filaments_int} {path} \l_tmpa_tl
- \tl_set_eq:cN {l__knot_options_filament \int_use:N \l__knot_filaments_int} \l__knot_tmpa_tl
- \tl_clear_new:c {knot previous filament \int_use:N \l__knot_filaments_int}
- \int_compare:nF {\l__knot_component_start_int == \l__knot_filaments_int}
- {
- \tl_set:cx {knot previous filament \int_use:N \l__knot_filaments_int} {filament \int_eval:n {\l__knot_filaments_int - 1}}
- }
- \tl_set:cx {knot previous filament \int_use:N \l__knot_component_start_int} {filament \int_use:N \l__knot_filaments_int}
- }
- }
- {
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\redraw}
-% The user can redraw segments of the strands at specific locations.
-% \begin{macrocode}
-\NewDocumentCommand \redraw { m m }
-{
-% \tikz@scan@one@point\pgfutil@firstofone #2 \relax
- \tl_put_right:Nn \l__knot_redraws_tl {\knot_draw_crossing:nn}
- \tl_put_right:Nx \l__knot_redraws_tl {
- {strand #1} {#2}% {\dim_use:N \pgf@x} {\dim_use:N \pgf@y}
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macrocode}
-\ExplSyntaxOff
-% \end{macrocode}
-%
-% \begin{macro}{\pgf@sh@@knotanchor}
-% Add the extra anchors for the knot crossing nodes.
-% \begin{macrocode}
-\def\pgf@sh@@knotanchor#1#2{%
- \anchor{#2 north west}{%
- \csname pgf@anchor@knot #1@north west\endcsname%
- \pgf@x=#2\pgf@x%
- \pgf@y=#2\pgf@y%
- }%
- \anchor{#2 north east}{%
- \csname pgf@anchor@knot #1@north east\endcsname%
- \pgf@x=#2\pgf@x%
- \pgf@y=#2\pgf@y%
- }%
- \anchor{#2 south west}{%
- \csname pgf@anchor@knot #1@south west\endcsname%
- \pgf@x=#2\pgf@x%
- \pgf@y=#2\pgf@y%
- }%
- \anchor{#2 south east}{%
- \csname pgf@anchor@knot #1@south east\endcsname%
- \pgf@x=#2\pgf@x%
- \pgf@y=#2\pgf@y%
- }%
- \anchor{#2 north}{%
- \csname pgf@anchor@knot #1@north\endcsname%
- \pgf@x=#2\pgf@x%
- \pgf@y=#2\pgf@y%
- }%
- \anchor{#2 east}{%
- \csname pgf@anchor@knot #1@east\endcsname%
- \pgf@x=#2\pgf@x%
- \pgf@y=#2\pgf@y%
- }%
- \anchor{#2 west}{%
- \csname pgf@anchor@knot #1@west\endcsname%
- \pgf@x=#2\pgf@x%
- \pgf@y=#2\pgf@y%
- }%
- \anchor{#2 south}{%
- \csname pgf@anchor@knot #1@south\endcsname%
- \pgf@x=#2\pgf@x%
- \pgf@y=#2\pgf@y%
- }%
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{knot crossing}
-% \begin{macrocode}
-\pgfdeclareshape{knot crossing}
-{
- \inheritsavedanchors[from=circle] % this is nearly a circle
- \inheritanchorborder[from=circle]
- \inheritanchor[from=circle]{north}
- \inheritanchor[from=circle]{north west}
- \inheritanchor[from=circle]{north east}
- \inheritanchor[from=circle]{center}
- \inheritanchor[from=circle]{west}
- \inheritanchor[from=circle]{east}
- \inheritanchor[from=circle]{mid}
- \inheritanchor[from=circle]{mid west}
- \inheritanchor[from=circle]{mid east}
- \inheritanchor[from=circle]{base}
- \inheritanchor[from=circle]{base west}
- \inheritanchor[from=circle]{base east}
- \inheritanchor[from=circle]{south}
- \inheritanchor[from=circle]{south west}
- \inheritanchor[from=circle]{south east}
- \inheritanchorborder[from=circle]
- \pgf@sh@@knotanchor{crossing}{2}
- \pgf@sh@@knotanchor{crossing}{3}
- \pgf@sh@@knotanchor{crossing}{4}
- \pgf@sh@@knotanchor{crossing}{8}
- \pgf@sh@@knotanchor{crossing}{16}
- \pgf@sh@@knotanchor{crossing}{32}
- \backgroundpath{
- \pgfutil@tempdima=\radius%
- \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%
- \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%
- \ifdim\pgf@xb<\pgf@yb%
- \advance\pgfutil@tempdima by-\pgf@yb%
- \else%
- \advance\pgfutil@tempdima by-\pgf@xb%
- \fi%
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{knot over cross}
-% \begin{macrocode}
-\pgfdeclareshape{knot over cross}
-{
- \inheritsavedanchors[from=rectangle] % this is nearly a circle
- \inheritanchorborder[from=rectangle]
- \inheritanchor[from=rectangle]{north}
- \inheritanchor[from=rectangle]{north west}
- \inheritanchor[from=rectangle]{north east}
- \inheritanchor[from=rectangle]{center}
- \inheritanchor[from=rectangle]{west}
- \inheritanchor[from=rectangle]{east}
- \inheritanchor[from=rectangle]{mid}
- \inheritanchor[from=rectangle]{mid west}
- \inheritanchor[from=rectangle]{mid east}
- \inheritanchor[from=rectangle]{base}
- \inheritanchor[from=rectangle]{base west}
- \inheritanchor[from=rectangle]{base east}
- \inheritanchor[from=rectangle]{south}
- \inheritanchor[from=rectangle]{south west}
- \inheritanchor[from=rectangle]{south east}
- \inheritanchorborder[from=rectangle]
- \backgroundpath{
- \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
- \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
- \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
- \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
- }
- \foregroundpath{
-% store lower right in xa/ya and upper right in xb/yb
- \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
- \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
- \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
- \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{knot under cross}
-% \begin{macrocode}
-\pgfdeclareshape{knot under cross}
-{
- \inheritsavedanchors[from=rectangle] % this is nearly a circle
- \inheritanchorborder[from=rectangle]
- \inheritanchor[from=rectangle]{north}
- \inheritanchor[from=rectangle]{north west}
- \inheritanchor[from=rectangle]{north east}
- \inheritanchor[from=rectangle]{center}
- \inheritanchor[from=rectangle]{west}
- \inheritanchor[from=rectangle]{east}
- \inheritanchor[from=rectangle]{mid}
- \inheritanchor[from=rectangle]{mid west}
- \inheritanchor[from=rectangle]{mid east}
- \inheritanchor[from=rectangle]{base}
- \inheritanchor[from=rectangle]{base west}
- \inheritanchor[from=rectangle]{base east}
- \inheritanchor[from=rectangle]{south}
- \inheritanchor[from=rectangle]{south west}
- \inheritanchor[from=rectangle]{south east}
- \inheritanchorborder[from=rectangle]
- \backgroundpath{
- \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
- \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
- \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
- \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
- }
- \foregroundpath{
-% store lower right in xa/ya and upper right in xb/yb
- \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
- \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
- \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
- \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{knot vert}
-% \begin{macrocode}
-\pgfdeclareshape{knot vert}
-{
- \inheritsavedanchors[from=rectangle] % this is nearly a circle
- \inheritanchorborder[from=rectangle]
- \inheritanchor[from=rectangle]{north}
- \inheritanchor[from=rectangle]{north west}
- \inheritanchor[from=rectangle]{north east}
- \inheritanchor[from=rectangle]{center}
- \inheritanchor[from=rectangle]{west}
- \inheritanchor[from=rectangle]{east}
- \inheritanchor[from=rectangle]{mid}
- \inheritanchor[from=rectangle]{mid west}
- \inheritanchor[from=rectangle]{mid east}
- \inheritanchor[from=rectangle]{base}
- \inheritanchor[from=rectangle]{base west}
- \inheritanchor[from=rectangle]{base east}
- \inheritanchor[from=rectangle]{south}
- \inheritanchor[from=rectangle]{south west}
- \inheritanchor[from=rectangle]{south east}
- \inheritanchorborder[from=rectangle]
- \backgroundpath{
-% store lower right in xa/ya and upper right in xb/yb
- \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
- \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
- \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
- \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
- \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
- \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{knot horiz}
-% \begin{macrocode}
-\pgfdeclareshape{knot horiz}
-{
- \inheritsavedanchors[from=rectangle] % this is nearly a circle
- \inheritanchorborder[from=rectangle]
- \inheritanchor[from=rectangle]{north}
- \inheritanchor[from=rectangle]{north west}
- \inheritanchor[from=rectangle]{north east}
- \inheritanchor[from=rectangle]{center}
- \inheritanchor[from=rectangle]{west}
- \inheritanchor[from=rectangle]{east}
- \inheritanchor[from=rectangle]{mid}
- \inheritanchor[from=rectangle]{mid west}
- \inheritanchor[from=rectangle]{mid east}
- \inheritanchor[from=rectangle]{base}
- \inheritanchor[from=rectangle]{base west}
- \inheritanchor[from=rectangle]{base east}
- \inheritanchor[from=rectangle]{south}
- \inheritanchor[from=rectangle]{south west}
- \inheritanchor[from=rectangle]{south east}
- \inheritanchorborder[from=rectangle]
- \foregroundpath{
-% store lower right in xa/ya and upper right in xb/yb
- \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
- \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
- \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
- \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
- \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
- \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-% \iffalse
-%</knots>
-% \fi
-%\Finale
-\endinput