From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/l3experimental/l3draw.dtx | 1166 ++++++++++++++++++++++++ 1 file changed, 1166 insertions(+) create mode 100644 macros/latex/contrib/l3experimental/l3draw.dtx (limited to 'macros/latex/contrib/l3experimental/l3draw.dtx') diff --git a/macros/latex/contrib/l3experimental/l3draw.dtx b/macros/latex/contrib/l3experimental/l3draw.dtx new file mode 100644 index 0000000000..971ebc6caa --- /dev/null +++ b/macros/latex/contrib/l3experimental/l3draw.dtx @@ -0,0 +1,1166 @@ +% \iffalse meta-comment +% +%% File: l3draw.dtx +% +% Copyright(C) 2018,2019 The LaTeX3 Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% http://www.latex-project.org/lppl.txt +% +% This file is part of the "l3experimental bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/latex3/latex3 +% +% for those people who are interested. +% +%<*driver|package> +\RequirePackage{expl3} +% +%<*driver> +\documentclass[full]{l3doc} +\usepackage{l3draw} +% For creating code demonstrations +% This needs access to some code-level interfaces in listings +\usepackage{listings} +\makeatletter +\lst@RequireAspects{writefile} +\newsavebox\demo@box +\lstnewenvironment{demo}[1][code and example] + {% + \global\let\lst@intname\@empty + \edef\demo@end{% + \expandafter\noexpand\csname demo@@#1@end\endcsname + }% + \@nameuse{demo@@#1}% + } + {\demo@end} +\newcommand\demo@new[3]{% + \@namedef{demo@@#1}{#2}% + \@namedef{demo@@#1@end}{#3}% +} +\newcommand*\demo@common{% + \setkeys{lst} + {% + basicstyle = \small\ttfamily, + basewidth = 0.51em, + gobble = 5, + language = [LaTeX]{TeX}, + }% +} +\newcommand*\demo@input{% + \ExplSyntaxOn + \catcode`\^^M = 10\relax + \catcode`\% = 14\relax + \input{\jobname.tmp}% + \ExplSyntaxOff +} +\demo@new{code and example}{% + \setbox\demo@box=\hbox\bgroup + \lst@BeginAlsoWriteFile{\jobname.tmp}% + \demo@common +}{% + \lst@EndWriteFile + \egroup + \begin{center} + \ifdim\wd\demo@box > 0.75\linewidth + \begin{minipage}{\linewidth} + \usebox\demo@box + \end{minipage}% + \par + \begin{minipage}{\linewidth} + \demo@input + \end{minipage} + \else + \begin{minipage}{0.25\linewidth} + \demo@input + \end{minipage}% + \hfil + \begin{minipage}{0.75\linewidth} + \usebox\demo@box + \end{minipage}% + \fi + \end{center} +} +\makeatother +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% \fi +% +% \title{^^A +% The \pkg{l3draw} package\\ Core drawing support^^A +% } +% +% \author{^^A +% The \LaTeX3 Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Released 2019-08-25} +% +% \maketitle +% +% \begin{documentation} +% +% \section{\pkg{l3draw} documentation} +% +% The \pkg{l3draw} package provides a set of tools for creating (vector) +% drawings in \pkg{expl3}. It is heavily inspired by the \pkg{pgf} layer of +% the Ti\textit{k}Z system, with many of the interfaces having the same form. +% However, the code provided here is build entirely on core \pkg{expl3} ideas +% and uses the \LaTeX3 FPU for numerical support. +% +% Numerical expressions in \pkg{l3draw} are handled as floating point +% expressions, unless otherwise noted. This means that they may contain or +% omit explicit units. Where units are omitted, they will automatically be +% taken as given in (\TeX{}) points. +% +% The code here is \emph{highly} experimental. +% +% \subsection{Drawings} +% +% \begin{function}{\draw_begin:, \draw_end:} +% \begin{syntax} +% \cs{draw_begin:} +% ... +% \cs{draw_end:} +% \end{syntax} +% Each drawing should be created within a \cs{draw_begin:}/\cs{draw_end:} +% function pair. The \texttt{begin} function sets up a number of key +% data structures for the rest of the functions here: unless otherwise +% specified, use of |\draw_...| functions outside of this +% \enquote{environment} is \emph{not supported}. +% +% The drawing created within the environment will be inserted into +% the typesetting stream by the \cs{draw_end:} function, which will +% switch out of vertical mode if required. +% \begin{demo} +% \dim_new:N \l_mypos_dim +% \draw_begin: +% \draw_path_moveto:n { 0cm , \l_mypos_dim } +% \draw_path_lineto:n { 1cm , \l_mypos_dim } +% \dim_set:Nn \l_mypos_dim { 1cm } +% \draw_path_lineto:n { 1cm , \l_mypos_dim } +% \draw_path_close: +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% +% Within a drawing, the only commands that should appear are those directly +% aimed at drawing (from \pkg{l3draw}) and those which produce \emph{no} +% typeset output. For example, it is possible to include loops inside a +% drawing using |\int_step_function:nnnn| or similar. On the other hand, +% text should not be included directly in drawings, but should rather be +% inserted using the appropriate \pkg{l3draw} command. +% +% The drawing environment sets the following standard behaviors +% \begin{itemize} +% \item Non-zero rule for fill overlaps +% \item Butt caps for lines +% \item Mitering for line joins with a miter factor of $10$ +% \item Solid line strokes +% \end{itemize} +% \end{function} +% +% Within a drawing, there are different ways of referring to a position. +% The co-ordinates of a point are given relative to the current +% \emph{drawing axes}. These can be manipulated and tracked at the code +% level. Underlying this is the \meta{canvas}, which is at the \pkg{draw} +% level essentially fixed and in line with the paper. Initially, the two +% sets of axes are coincident. (It is possible to manipulate the canvas +% axes at the driver level: this is then \enquote{transparent} to the +% \pkg{draw} level, and so should be used only when strictly required.) +% +% \begin{function}{\draw_suspend_begin:, \draw_suspend_end:} +% \begin{syntax} +% \cs{draw_suspend_begin:} +% ... +% \cs{draw_suspend_end:} +% \end{syntax} +% Suspends all of the drawing mechanisms to allow \enquote{normal} +% material to be created. Typically, this environment will be applied +% inside a box which may contain nested pictures. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \hbox_set:Nn \l_tmpa_box +% { +% \draw_suspend_begin: +% This~is~normal~text. +% \draw_begin: % A subpicture +% \draw_path_moveto:n { 1cm , 0cm } +% \draw_path_lineto:n { 1cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% More~text. +% \draw_suspend_end: +% } +% \draw_box_use:N \l_tmpa_box +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% \end{function} +% +% \subsection{Graphics state} +% +% Within the drawing environment, a number of functions control how drawings +% will appear. Note that these all apply \emph{globally}, though some are +% rest at the start of each drawing (\cs{draw_begin:}). +% +% \begin{variable}{\g_draw_linewidth_default_dim} +% The default value of the linewidth for stokes, set at the start +% of every drawing (\cs{draw_begin:}). +% \end{variable} +% +% \begin{function}{\draw_linewidth:n} +% \begin{syntax} +% \cs{draw_linewidth:n} \Arg{width} +% \end{syntax} +% Sets the width to be used for stroking to the \meta{width} (an +% \meta{fp expr}). +% \end{function} +% +% \begin{function}{\draw_dash_pattern:nn} +% \begin{syntax} +% \cs{draw_dash_pattern:nn} \Arg{pattern} \Arg{phase} +% \end{syntax} +% Specifies a dash pattern. The \meta{pattern} itself is a comma-separated +% list of entries which represent the \enquote{on} and \enquote{off} +% parts of the line. These are all \meta{fp expr} and repeat as required. +% Thus the \meta{pattern} may be of arbitrary length. The \meta{phase} +% specifies where during the first \enquote{on} line the pattern should +% start. +% \begin{demo} +% \draw_begin: +% \draw_dash_pattern:nn +% { 0.5cm , 0.5cm , 0.1cm , 0.2cm } +% { 0cm } +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 2cm , 0cm } +% \draw_path_use_clear:n { stroke } +% \draw_dash_pattern:nn +% { 0.5cm , 0.5cm , 0.1cm , 0.2cm } +% { 0.1cm } +% \draw_path_moveto:n { 0cm , 1mm } +% \draw_path_lineto:n { 2cm , 1mm } +% \draw_path_use_clear:n { stroke } +% \draw_dash_pattern:nn +% { 0.5cm , 0.5cm , 0.1cm , 0.2cm } +% { 0.2cm } +% \draw_path_moveto:n { 0cm , 2mm } +% \draw_path_lineto:n { 2cm , 2mm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% Setting an empty pattern will produce a solid line. +% +% Note the \meta{pattern} interface here is different from that in \pkg{pgf}: +% the list is comma-separated not given in brace groups. +% \end{function} +% +% \begin{function}{\draw_nonzero_rule:, \draw_evenodd_rule:} +% \begin{syntax} +% \cs{draw_nonzero_rule:} +% \end{syntax} +% Active either the non-zero winding number or the even-odd rule, +% respectively, for determining what is inside a fill or clip area. +% For technical reasons, these command are not influenced by scoping +% and apply on an ongoing basis. +% \end{function} +% +% \begin{function} +% { +% \draw_cap_butt: , +% \draw_cap_rectangle: , +% \draw_cap_round: +% } +% \begin{syntax} +% \cs{draw_cap_butt:} +% \end{syntax} +% Sets the style of terminal stroke position to one of butt, rectangle or +% round. +% \end{function} +% +% \begin{function} +% { +% \draw_join_bevel: , +% \draw_join_miter: , +% \draw_join_round: +% } +% \begin{syntax} +% \cs{draw_cap_butt:} +% \end{syntax} +% Sets the style of stroke joins to one of bevel, miter or round. +% \end{function} +% +% \begin{function}{\draw_miterlimit:n} +% \begin{syntax} +% \cs{draw_miterlimit:n} \Arg{factor} +% \end{syntax} +% Sets the miter \meta{factor} of lines joined as a miter, as described in the +% PDF and PostScript manuals. The \meta{factor} is an \meta{fp expr}. +% \end{function} +% +% \subsection{Scoping drawing elements} +% +% Scoping drawing elements is necessary to allowing nesting of subparts. +% These features have specific use requirements: the preconditions must be +% met. In particular, each type of drawing scope also constitutes a +% group (\cs{group_begin:}/\cs{group_end:} pair): as such, they must be +% nested correctly. +% +% \begin{function}{\draw_scope_begin:, \draw_scope_end:} +% \begin{syntax} +% \cs{draw_scope_begin:} +% ... +% \cs{draw_scope_end:} +% \end{syntax} +% Creates a scope for localisation of state settings within a drawing. +% A scope forms a \TeX{} group but will also localise global state +% variables (such as \cs{g_draw_linewidth_default_dim}), and driver-level +% concepts such as the termination of lines. +% \begin{demo} +% \draw_begin: +% \draw_scope_begin: +% \group_begin: +% \draw_linewidth:n { 2pt } +% \draw_path_rectangle:nn { 0 , 0 } { 2ex , 2ex } +% \draw_path_use:n { stroke } +% \group_end: +% \draw_path_rectangle:nn { 3ex , 0ex } { 2ex , 2ex } +% \draw_path_use:n { stroke } +% \draw_scope_end: +% \draw_path_rectangle:nn { 6ex , 0ex } { 2ex , 2ex } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% Global graphical concepts restricted by scope are +% \begin{itemize} +% \item Line width +% \item Stroke and fill color +% \item Dash pattern +% \item Line joining and capping, including the miter limit +% \item Clipping paths +% \item Canvas (driver) transformations +% \end{itemize} +% \end{function} +% +% \subsection{Points} +% +% Functions supporting the calculation of points (co-ordinates) are expandable +% and may be used outside of the drawing environment. When used in this +% way, they all yield a co-ordinate tuple, for example +% \begin{verbatim} +% \tl_set:Nx \l_tmpa_tl { \draw_point:nn { 1 } { 2 } } +% \tl_show:N \l_tmpa_tl +% \end{verbatim} +% gives +% \begin{verbatim} +% > \l_tmpa_tl=1pt,2pt. +% } +% \end{verbatim} +% +% This output form is then suitable as \emph{input} for subsequent point +% calculations, \emph{i.e.}~where a \meta{point} is required it may be +% given as a tuple. This \emph{may} include units and surrounding +% parentheses, for example +% \begin{verbatim} +% 1,2 +% (1,2) +% 1cm,3pt +% (1pt,2cm) +% 2 * sind(30), 2^4in +% \end{verbatim} +% are all valid input forms. Notice that each part of the tuple may itself +% be a float point expression. +% +% Point co-ordinates are relative to the canvas axes, but can be transformed +% by \cs{draw_point_transform:n}. These manipulation is applied by many +% higher-level functions, for example path construction, and allows parts of +% a drawing to be rotated, scaled or skewed. This occurs before writing any +% data to the driver, and so such manipulations are tracked by the drawing +% mechanisms. See \cs{@@_backend_cm:nnnn} for backend-level +% manipulation of the canvas axes themselves. +% +% Notice that in contrast to \pkg{pgf} it is possible to give the positions +% of points \emph{directly}. +% +% \subsubsection{Basic point functions} +% +% \begin{function}[EXP]{\draw_point_polar:nn, \draw_point_polar:nnn} +% \begin{syntax} +% \cs{draw_point_polar:nn} \Arg{radius} \Arg{angle} +% \cs{draw_point_polar:nnn} \Arg{radius-a} \Arg{radius-b} \Arg{angle} +% \end{syntax} +% Gives the co-ordinates of the point at \meta{angle} (an \meta{fp expr} in +% \emph{degrees}) and \meta{radius}. The three-argument version accepts +% two radii of different lengths. +% +% Note the interface here is somewhat different from that in \pkg{pgf}: +% the one- and two-radii versions in \pkg{l3draw} use separate functions, +% whilst in \pkg{pgf} they use the same function and a keyword. +% \end{function} +% +% \begin{function}[EXP]{\draw_point_unit_vector:n} +% \begin{syntax} +% \cs{draw_point_unit_vector:n} \Arg{point} +% \end{syntax} +% Expands to the co-ordinates of a unit vector in the direction of the +% \meta{point} from the origin. If the \meta{point} is at the origin, +% a vertical unit vector is returned +% \end{function} +% +% \begin{function}[EXP]{\draw_point_transform:n} +% \begin{syntax} +% \cs{draw_point_transform:n} \Arg{point} +% \end{syntax} +% Evaluates the position of the \meta{point} subject to the current +% transformation matrix. This operation is applied automatically by +% most higher-level functions (\emph{e.g.}~path manipulations). +% \end{function} +% +% \subsubsection{Points on a vector basis} +% +% As well as giving explicit values, it is possible to describe points +% in terms of underlying direction vectors. The latter are initially +% co-incident with the standard Cartesian axes, but may be altered by +% the user. +% +% \begin{function}{\draw_xvec:n, \draw_yvec:n, \draw_zvec:n} +% \begin{syntax} +% \cs{draw_xvec:n} \Arg{point} +% \end{syntax} +% Defines the appropriate base vector to point toward the \meta{point} +% on the canvas. The standard settings for the $x$- and $y$-vectors are +% $1\,\mathrm{cm}$ along the relevant canvas axis, whilst for the +% $z$-vector an appropriate direction is taken. +% \end{function} +% +% \begin{function}[EXP]{\draw_point_vec:nn, \draw_point_vec:nnn} +% \begin{syntax} +% \cs{draw_point_vec:nn} \Arg{xscale} \Arg{yscale} +% \cs{draw_point_vec:nnn} \Arg{xscale} \Arg{yscale} \Arg{zscale} +% \end{syntax} +% Expands to the co-ordinate of the point at \meta{xscale} times the +% $x$-vector and \meta{yscale} times the $y$-vector. The three-argument +% version extends this to include the $z$-vector. +% \end{function} +% +% \begin{function}[EXP]{\draw_point_vec_polar:nn, \draw_point_vec_polar:nnn} +% \begin{syntax} +% \cs{draw_point_vec_polar:nn} \Arg{radius} \Arg{angle} +% \cs{draw_point_vec_polar:nnn} \Arg{radius-a} \Arg{radius-b} \Arg{angle} +% \end{syntax} +% Gives the co-ordinates of the point at \meta{angle} (an \meta{fp expr} in +% \emph{degrees}) and \meta{radius}, relative to the prevailing +% $x$- and $y$-vectors. The three-argument version accepts two radii of +% different lengths. +% +% Note the interface here is somewhat different from that in \pkg{pgf}: +% the one- and two-radii versions in \pkg{l3draw} use separate functions, +% whilst in \pkg{pgf} they use the same function and a keyword. +% \end{function} +% +% \subsubsection{Intersections} +% +% \begin{function}[EXP]{\draw_point_intersect_lines:nnnn} +% \begin{syntax} +% \cs{draw_point_intersect_lines:nnnn} \Arg{point1} \Arg{point2} \Arg{point3} \Arg{point4} +% \end{syntax} +% Evaluates the point at the intersection of one line, joining +% \meta{point1} and \meta{point2}, and a second line joining \meta{point3} +% and \meta{point4}. If the lines do not intersect, or are coincident, and +% error will occur. +% \end{function} +% +% \begin{function}[EXP]{\draw_point_intersect_circles:nnnnn} +% \begin{syntax} +% \cs{draw_point_intersect_circles:nnnnn} +% \Arg{center1} \Arg{radius1} \Arg{center2} \Arg{radius2} \Arg{root} +% \end{syntax} +% Evaluates the point at the intersection of one circle with +% \meta{center1} and \meta{radius1}, and a second circle with \meta{center2} +% and \meta{radius2}. If the circles do not intersect, or are coincident, and +% error will occur. +% +% Note the interface here has a different argument ordering from that in +% \pkg{pgf}, which has the two centers then the two radii. +% \end{function} +% +% \subsubsection{Interpolations} +% +% \begin{function}[EXP]{\draw_point_interpolate_line:nnn} +% \begin{syntax} +% \cs{draw_point_interpolate_line:nnn} \Arg{part} \Arg{point1} \Arg{point2} +% \end{syntax} +% Expands to the point which is \meta{part} way along the line joining +% \meta{point1} and \meta{point2}. The \meta{part} may be an interpolation or +% an extrapolation, and is a floating point value expressing a percentage +% along the line, \emph{e.g.}~a value of \texttt{0.5} would be half-way +% between the two points. +% \end{function} +% +% \begin{function}[EXP]{\draw_point_interpolate_distance:nnn} +% \begin{syntax} +% \cs{draw_point_interpolate_distance:nnn} \Arg{distance} \Arg{point expr1} \Arg{point expr2} +% \end{syntax} +% Expands to the point which is \meta{distance} way along the line joining +% \meta{point1} and \meta{point2}. The \meta{distance} may be an interpolation +% or an extrapolation. +% \end{function} +% +% \begin{function}[EXP]{\draw_point_interpolate_curve:nnnnnn} +% \begin{syntax} +% \cs{draw_point_interpolate_curve:nnnnnn} \Arg{part} +% \Arg{start} \Arg{control1} \Arg{control2} \Arg{end} +% \end{syntax} +% Expands to the point which is \meta{part} way along the curve between +% \meta{start} and \meta{end} and defined by \meta{control1} and +% \meta{control2}. The \meta{part} may be an interpolation or +% an extrapolation, and is a floating point value expressing a percentage +% along the curve, \emph{e.g.}~a value of \texttt{0.5} would be half-way +% along the curve. +% \end{function} +% +% \subsection{Paths} +% +% Paths are constructed by combining one or more operations before applying +% one or more actions. Thus until a path is \enquote{used}, it may be +% manipulated or indeed discarded entirely. Only one path is active at +% any one time, and the path is \emph{not} affected by \TeX{} grouping. +% +% \begin{function}{\draw_path_corner_arc:nn} +% \begin{syntax} +% \cs{draw_path_corner_arc:n} \Arg{length1} \Arg{length2} +% \end{syntax} +% Sets the degree of rounding applied to corners in a path: the two +% \meta{length} values are the distances from the corner at which the curving +% should start. The first \meta{length} applies to the part of the path +% \enquote{leading in} to the corner (\emph{i.e.}~from the previous path +% operation), and the second to that \enquote{leading out}. If both +% values are \texttt{0pt} then corners will not be rounded. The values +% apply within the scope of the current \TeX{} group. +% \begin{demo} +% \draw_begin: +% \draw_path_corner_arc:nn { 5mm } { 5mm } +% \draw_path_rectangle_corners:nn +% { 0cm , 0cm } { 3cm , 2cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% \begin{demo} +% \draw_begin: +% \draw_path_corner_arc:nn { 10mm } { 5mm } +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 2cm } +% \draw_path_lineto:n { 3cm , 2cm } +% \draw_path_curveto:nnn +% { 3cm , 0cm } { 2cm , 0cm } { 1cm , 0cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% The corners created are quarter-circles for exact right-angles and +% close approximations otherwise. Closing a path will result in rounding +% correctly. +% \begin{demo} +% \draw_begin: +% \draw_path_corner_arc:nn { 4pt } { 4pt } +% \draw_path_moveto:n +% { \draw_point_polar:nn { 1cm } { 0 } } +% \int_step_inline:nnnn { 72 } { 72 } { 359 } +% { +% \draw_path_lineto:n +% { \draw_point_polar:nn { 1cm } { #1 } } +% } +% \draw_path_close: +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_path_close:} +% \begin{syntax} +% \cs{draw_path_close:} +% \end{syntax} +% Closes the current part of the path by appending a straight line from +% the current point to the starting point of the path. In general, any +% path to be \emph{filled} should include a close instructions. +% \end{function} +% +% \begin{function}{\draw_path_use:n, \draw_path_use_clear:n} +% \begin{syntax} +% \cs{draw_path_use:n} \Arg{action(s)} +% \end{syntax} +% Inserts the current path, carrying out one ore more possible \meta{actions} +% (a comma list): +% \begin{itemize} +% \item \texttt{stroke} Draws a line along the current path +% \item \texttt{draw} A synonym for \texttt{stroke} +% \item \texttt{fill} Fills the interior of the path with the current +% file color +% \item \texttt{clip} Clips any content outside of the path +% \end{itemize} +% Actions are applied in the order given irrespective of the input order. +% Note that whilst it is possible to use a path without clearing it, the +% normal use case would be to clear the path (this resets data structures +% at the macro level). +% \end{function} +% +% \subsubsection{Path operations on drawing axes} +% +% The standard path functions are all influenced by the active transformation +% matrix, \emph{i.e.}~the work relative to the drawing axes rather than +% the canvas. +% +% \begin{function}{\draw_path_moveto:n} +% \begin{syntax} +% \cs{draw_path_moveto:n} \Arg{point} +% \end{syntax} +% Moves the reference point of the path to the \meta{point}, but will +% not join this to any previous point. +% \end{function} +% +% \begin{function}{\draw_path_lineto:n} +% \begin{syntax} +% \cs{draw_path_lineto:n} \Arg{point} +% \end{syntax} +% Joins the current path to the \meta{point} with a straight line. +% In general, for reliable treatment by viewers, a \cs{draw_path_moveto:n} +% operation should precede the first use of a \cs{draw_path_lineto:n} +% on a path. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 1cm , 1cm } +% \draw_path_lineto:n { 2cm , 1cm } +% \draw_path_lineto:n { 3cm , 0.5cm } +% \draw_path_lineto:n { 3cm , 0cm } +% \draw_color_fill:n { yellow!80!black } +% \draw_path_use_clear:n { fill , stroke } +% \draw_end: +% \end{demo} +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 1cm , 1cm } +% \draw_path_lineto:n { 2cm , 1cm } +% \draw_path_moveto:n { 2cm , 1cm } % Begins a new part +% \draw_path_lineto:n { 3cm , 0.5cm } +% \draw_path_lineto:n { 3cm , 0cm } +% \draw_color_fill:n { yellow!80!black } +% \draw_path_use_clear:n { fill , stroke } +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_path_curveto:nnn} +% \begin{syntax} +% \cs{draw_path_curveto:nnn} \Arg{control1} \Arg{control2} \Arg{end} +% \end{syntax} +% Joins the current path to the \meta{end} with a curved line defined by +% cubic Bézier points \meta{control1} and \meta{control2}. The bounding box +% of the path (and image) will fully-contain the curve and control points, +% \emph{i.e.}~it may be bigger than strictly necessary to contain the curve +% \emph{alone}. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_curveto:nnn +% { 1cm , 1cm } % First control +% { 2cm , 1cm } % Second control +% { 3cm , 0cm } % End +% \draw_color_fill:n { yellow!80!black } +% \draw_path_use_clear:n { fill , stroke } +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_path_curveto:nn} +% \begin{syntax} +% \cs{draw_path_curveto:nn} \Arg{control} \Arg{end} +% \end{syntax} +% Joins the current path to the \meta{end} with a curved line defined by +% quadratic Bézier point \meta{control}. The bounding box +% of the path (and image) will fully-contain the curve and computed (cubic) +% control points, \emph{i.e.}~it may be bigger than strictly necessary to +% contain the curve \emph{alone}. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_curveto:nn +% { 1cm , 1cm } +% { 2cm , 0cm } +% \draw_color_fill:n { yellow!80!black } +% \draw_path_use_clear:n { fill , stroke } +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_path_arc:nnn, \draw_path_arc:nnnn} +% \begin{syntax} +% \cs{draw_path_arc:nnn} \Arg{angle1} \Arg{angle2} \Arg{radius} +% \cs{draw_path_arc:nnnn} \Arg{angle1} \Arg{angle2} \Arg{radius-a} \Arg{radius-b} +% \end{syntax} +% Joins the current path with an arc between \meta{angle1} and \meta{angle2} +% and of \meta{radius}. The four-argument version accepts two radii of +% different lengths. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_arc:nnn { 180 } { 90 } { 0.5cm } +% \draw_path_lineto:n { 3cm , 1.5cm } +% \draw_path_arc:nnn { 90 } { -45 } { 0.5cm } +% \draw_path_use_clear:n { fill } +% \draw_end: +% \end{demo} +% +% Note the interface here has a different argument ordering from that in +% \pkg{pgf}, which has the two centers then the two radii. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_arc:nnnn { 180 } { 45 } { 2cm } { 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_path_arc_axes:nnnn} +% \begin{syntax} +% \cs{draw_path_arc_axes:nnn} \Arg{angle1} \Arg{angle2} \Arg{vector1} \Arg{vector2} +% \end{syntax} +% Appends the portion of an ellipse from \meta{angle1} to \meta{angle2} of an +% ellipse with axes along \meta{vector1} and \meta{vector2} to the current +% path. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 2cm , 5mm } +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_moveto:n { 2cm , 5mm } +% \draw_path_arc_axes:nnnn { 0 } { 90 } +% { 2cm , 5mm } { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_path_ellipse:nnn} +% \begin{syntax} +% \cs{draw_path_ellipse:nnn} \Arg{center} \Arg{vector1} \Arg{vector2} +% \end{syntax} +% Appends an ellipse at \meta{center} with axes along \meta{vector1} and +% \meta{vector2} to the current path. A new part is started if the path +% is already non-empty. Notice that the underlying drawing is constructed +% from arcs with appropriate moves: the interfaces is a more efficient +% convenience. +% \begin{demo} +% \draw_begin: +% \draw_path_ellipse:nnn +% { 1cm , 0cm } +% { 1.5cm , 0cm } +% { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \draw_color:n { red } +% \draw_path_ellipse:nnn +% { 1cm , 0cm } +% { 1cm , 1cm } +% { -0.5cm , 0.5cm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% +% Note that any transformation is applied to the completed ellipse rather than +% to the axes. +% \end{function} +% +% \begin{function}{\draw_path_circle:nn} +% \begin{syntax} +% \cs{draw_path_circle:nn} \Arg{center} \Arg{radius} +% \end{syntax} +% Appends a circle of \meta{radius} at \meta{center} to the current path. +% This is a shortcut for \cs{draw_path_ellipse:nnn}. +% \end{function} +% +% \begin{function}{\draw_path_rectangle:nn, \draw_path_rectangle_corners:nn} +% \begin{syntax} +% \cs{draw_path_rectangle:nn} \Arg{lower-left} \Arg{displacement} +% \cs{draw_path_rectangle_corners:nn} \Arg{lower-left} \Arg{top-right} +% \end{syntax} +% Appends a rectangle starting at \meta{lower-left} to the current path, +% with the size of the rectangle determined either by a \meta{displacement} +% or the position of the \meta{top-right}. +% \begin{demo} +% \draw_begin: +% \draw_path_rectangle:nn +% { 1cm , 0cm } +% { 1.5cm , 1cm } +% \draw_path_rectangle:nn +% { 1.5cm , 0.25cm } +% { 1.5cm , 1cm } +% \draw_path_rectangle:nn +% { 2cm , 0.5cm } +% { 1.5cm , 1cm } +% \draw_path_use_clear:n { draw } +% \draw_end: +% \end{demo} +% \begin{demo} +% \draw_begin: +% \draw_path_rectangle_corners:nn +% { 1cm , 0cm } +% { 1.5cm , 1cm } +% \draw_path_use_clear:n { draw } +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_path_grid:nnnn} +% \begin{syntax} +% \cs{draw_path_grid:nnnn} \Arg{xstep} \Arg{ystep} \Arg{lower-left} \Arg{upper-right} +% \end{syntax} +% Constructs a grid of \meta{xstep} and \meta{ystep} inside the rectangle +% defined by the \meta{lower-left} and the \meta{upper-right}, and appends +% this to the current path. The grid will be aligned such that grid lines +% pass through the origin, which may result in \enquote{protruding} ends +% if the start/end positions do not fully align. +% \begin{demo} +% \draw_begin: +% \draw_linewidth:n { 0.8pt } +% \draw_path_grid:nnnn +% { 1cm } { 1cm } +% { -3mm , -3mm } +% { 33mm , 23mm } +% \draw_path_use_clear:n { stroke } +% \draw_linewidth:n { 0.4pt } +% \draw_path_grid:nnnn +% { 1mm } { 1mm } +% { -1.5mm , -1.5mm } +% { 31.5mm , 21.5mm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% +% Any transformation is applied to the finished grid. +% \begin{demo} +% \draw_begin: +% \draw_transform_rotate:n { 10 } +% \draw_path_grid:nnnn +% { 1mm } { 2mm } +% { 0mm , 0mm } +% { 30mm , 30mm } +% \draw_path_use_clear:n { stroke } +% \draw_end: +% \end{demo} +% \end{function} +% +% \subsubsection{Path scope} +% +% \begin{function}{\draw_path_scope_begin:, \draw_path_scope_end:} +% \begin{syntax} +% \cs{draw_path_scope_begin:} +% ... +% \cs{draw_path_scope_end:} +% \end{syntax} +% Suspends (and saves) the current (partial) path, initialising a new +% path within the scope. Path operations are written to output only when +% used, so the scoped path is stored at the \pkg{expl3} level, not +% in the output. +% \end{function} +% +% \subsubsection{Path operations on canvas axes} +% +% For \emph{specialist} work, a small number of functions are provided +% which work relative to the canvas axes, \emph{i.e.}~these functions +% ignore the transformation matrix. +% +% \begin{function}{\draw_path_canvas_moveto:n} +% \begin{syntax} +% \cs{draw_path_canvas_moveto:n} \Arg{canvas point} +% \end{syntax} +% Moves the reference point of the path to the \meta{canvas point}, but will +% not join this to any previous point. +% \end{function} +% +% \begin{function}{\draw_path_canvas_lineto:n} +% \begin{syntax} +% \cs{draw_path_canvas_lineto:n} \Arg{canvas point} +% \end{syntax} +% Joins the current path to the \meta{canvas point} with a straight line. +% \end{function} +% +% \begin{function}{\draw_path_canvas_curveto:nnn} +% \begin{syntax} +% \cs{draw_path_canvas_curveto:nnn} \Arg{control1} \Arg{control2} \Arg{end} +% \end{syntax} +% Joins the current path to the \meta{end} with a curved line defined by +% cubic Bézier points \meta{control1} and \meta{control2}. These positions +% are given as canvas points. +% \end{function} +% +% \subsection{Bounding box} +% +% \begin{variable}{\l_draw_bb_update_bool} +% All functions automatically update the bounding box of the image, unless +% specified otherwise. This behavior is selectable using the +% \cs{l_draw_bb_update_bool} boolean. +% \end{variable} +% +% \subsection{Boxes and coffins} +% +% \begin{function}{\draw_box_use:N} +% \begin{syntax} +% \cs{draw_box_use:N} \meta{box} +% \end{syntax} +% Inserts the \meta{box} into a drawing, taking account of the current +% transformation matrix and shift, and adjusting the drawing bounding +% box to contain the (apparent) size of the box if this is active +% (see \cs{l_draw_bb_update_bool}). +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \hbox_set:Nn \l_tmpa_box +% { This~is~text. } +% \draw_box_use:N \l_tmpa_box +% \draw_end: +% \end{demo} +% \begin{demo} +% \draw_begin: +% \draw_transform_matrix_absolute:nnnn { 2 } { 0 } { 1 } { 2 } +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \hbox_set:Nn \l_tmpa_box +% { This~is~text. } +% \draw_box_use:N \l_tmpa_box +% \draw_end: +% \end{demo} +% \end{function} +% +% \begin{function}{\draw_coffin_use:Nnn} +% \begin{syntax} +% \cs{draw_coffin_use:N} \meta{coffin} \Arg{hpole} \Arg{vpole} +% \end{syntax} +% Inserts the \meta{coffin} into a drawing, taking account of the current +% transformation matrix and shift, and adjusting the drawing bounding +% box to contain the (apparent) size of the box if this is active +% (see \cs{l_draw_bb_update_bool}). The alignment point of the coffin to +% the origin is specified by the intersection of the \meta{hpole} and the +% \meta{vpole}. +% \begin{demo} +% \draw_begin: +% \draw_path_moveto:n { 0cm , 0cm } +% \draw_path_lineto:n { 0cm , 1cm } +% \draw_path_use_clear:n { stroke } +% \hcoffin_set:Nn \l_tmpa_coffin +% { This~is~text. } +% \draw_coffin_use:Nnn \l_tmpa_coffin { hc } { vc } +% \draw_end: +% \end{demo} +% \end{function} +% +% \subsection{Color} +% +% \begin{function}{\draw_color:n, \draw_color_fill:n, \draw_color_stroke:n} +% \begin{syntax} +% \cs{draw_color:n} \Arg{color expression} +% \end{syntax} +% Evaluates the \meta{color expression} as described for \pkg{l3color}. +% \end{function} +% +% \subsection{Transformations} +% +% Points are normally used unchanged relative to the canvas axes. This can +% be modified by applying a transformation matrix. The canvas axes themselves +% may be adjusted using \cs{driver_draw_cm:nnnn}: note that this +% is transparent to the drawing code so is not tracked. +% +% \begin{function} +% {\draw_transform_matrix:nnnn, \draw_transform_matrix_absolute:nnnn} +% \begin{syntax} +% \cs{draw_transform_matrix:nnnn} +% \Arg{a} \Arg{b} \Arg{c} \Arg{d} +% \end{syntax} +% Applies the transformation matrix $[ \meta{a} \meta{b} \meta{c} \meta{d}]$. +% The basic applies the transformation in addition to those active; the +% |absolute| version overwrites any active transformation. +% This assignment is local. +% \end{function} +% +% \begin{function}{\draw_transform_shift:n, \draw_transform_shift_absolute:n} +% \begin{syntax} +% \cs{draw_transform_shift:n} \Arg{vector} +% \end{syntax} +% Applies the transformation \meta{vector} to points. +% The basic applies the vector in addition to those active; the +% |absolute| version overwrites any active vector. +% This assignment is local. +% \end{function} +% +% \begin{function}{\draw_transform_triangle:nnn} +% \begin{syntax} +% \cs{draw_transform_triangle:nnn} +% \Arg{origin} \Arg{point1} \Arg{point2} +% \end{syntax} +% Applies a transformation such that the co-ordinates $(0, 0)$, $(1, 0)$ +% and $(0, 1)$ are given by the \meta{origin}, \meta{point1} and +% \meta{point2}, respectively. +% This assignment is local. +% \end{function} +% +% \begin{function}{\draw_transform_rotate:n} +% \begin{syntax} +% \cs{draw_transform_rotate:n} \Arg{angle} +% \end{syntax} +% Applies a rotation by the \meta{angle}, measured anti-clockwise in degrees. +% This rotation is \emph{additional} to any prevailing transformation. +% This assignment is local. +% \end{function} +% +% \begin{function} +% { +% \draw_transform_scale:n, +% \draw_transform_xscale:n, +% \draw_transform_yscale:n +% } +% \begin{syntax} +% \cs{draw_transform_scale:n} \Arg{scale} +% \end{syntax} +% Applies the \meta{scale} in either $x$ or $y$ (or both). +% This scale is \emph{added} to any prevailing transformation. +% This assignment is local. +% \end{function} +% +% \begin{function} +% { +% \draw_transform_xshift:n, +% \draw_transform_yshift:n +% } +% \begin{syntax} +% \cs{draw_transform_xshift:n} \Arg{xshift} +% \end{syntax} +% Applies an \meta{xshift} or \meta{yshift}, as appropriate. This shift is +% \emph{added} to any prevailing one. +% This assignment is local. +% \end{function} +% +% \begin{function} +% { +% \draw_transform_xslant:n, +% \draw_transform_yslant:n +% } +% \begin{syntax} +% \cs{draw_transform_xslant:n} \Arg{slant} +% \end{syntax} +% Applies the \meta{slant} (a factor) in either $x$ or $y$. +% This slant is \emph{added} to any prevailing transformation. +% This assignment is local. +% \end{function} +% +% \begin{function} +% {\draw_transform_matrix_invert:, \draw_transform_shift_invert:} +% \begin{syntax} +% \cs{draw_transform_matrix_invert:} +% \end{syntax} +% Inverts the current transformation matrix or shift vector, as +% appropriate. +% This assignment is local. +% \end{function} +% +% \begin{function} +% {\draw_transform_matrix_reset:, \draw_transform_shift_reset:} +% \begin{syntax} +% \cs{draw_transform_matrix_reset:} +% \end{syntax} +% Resets the current transformation matrix or shift vector, as +% appropriate. +% This assignment is local. +% \end{function} +% +% \subsection{Layers} +% +% Drawing layers may be used to alter the way in which elements are stacked +% on top of one another. In particular, they are useful when the nature of +% an element depends on another, but where it needs to be behind it's +% \enquote{parent}. A classic example is a filled background: this needs to +% know the size of the material it is behind. +% +% All drawings feature a layer called |main|. This layer should always be +% present, and is the one which \enquote{non-layered} content is added to. +% +% \begin{function}{\draw_layer_new:n} +% \begin{syntax} +% \cs{draw_layer_new:n} \Arg{layer} +% \end{syntax} +% Creates a new \meta{layer} which can then be used in drawing. The layer +% |main| is pre-defined. +% \end{function} +% +% \begin{function}{\draw_layer_begin:n, \draw_layer_end:} +% \begin{syntax} +% \cs{draw_layer_begin:n} \Arg{layer} +% ... +% \cs{draw_layer_end:} +% \end{syntax} +% Begin and end collection of material for the \meta{layer}, which should +% previously have been created (and which cannot be |main|). Material +% collected for the layer is available globally within the current drawing. +% \end{function} +% +% \begin{variable}{\l_draw_layers_clist} +% The list of active layers: may be given anywhere before \cs{draw_end:}. +% The |main| layer should always be included. +% \end{variable} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3draw} implementation} +% +% \begin{macrocode} +%<*initex|package> +% \end{macrocode} +% +% \begin{macrocode} +%<@@=draw> +% \end{macrocode} +% +% \begin{macrocode} +%<*package> +\ProvidesExplPackage{l3draw}{2019-08-25}{} + {L3 Experimental core drawing support} +% +% \end{macrocode} +% +% \begin{macrocode} +\RequirePackage { l3color } +% \end{macrocode} +% +% Everything else is in the sub-files! +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex -- cgit v1.2.3