summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx479
1 files changed, 468 insertions, 11 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
index 24252e7ae45..cfbcb9bdce3 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
@@ -38,7 +38,7 @@
\documentclass[full]{l3doc}
%</driver>
%<*driver|package>
-\GetIdInfo$Id: l3drivers.dtx 6494 2016-05-14 21:10:56Z joseph $
+\GetIdInfo$Id: l3drivers.dtx 6511 2016-05-17 20:20:23Z joseph $
{L3 Experimental drivers}
%</driver|package>
%<*driver>
@@ -153,6 +153,214 @@
% while preserving the color used in the box.
% \end{function}
%
+% \section{Drawing}
+%
+% The drawing functions provided here are \emph{highly} experimental. They
+% are inspired heavily by the system layer of \pkg{pgf} (most have the
+% same interface as the same functions in the latter's \cs{pgfsys@\ldots}
+% namespace). They are intended to form the basis for higher level drawing
+% interfaces, which themselves are likely to be further abstracted for user
+% access. Again, this model is heavily inspired by \pkg{pgf} and
+% Ti\textit{k}z.
+%
+% These low level drawing interfaces abstract from the driver raw requirements
+% but still require an appreciation of the concepts of PostScript/PDF/SVG
+% graphic creation.
+%
+% At present \emph{not all drivers are covered} by the following.
+%
+% \begin{function}
+% { \__driver_draw_begin:, \__driver_draw_end:}
+% \begin{syntax}
+% \cs{__driver_draw_begin:}
+% \meta{content}
+% \cs{__driver_draw_end:}
+% \end{syntax}
+% Defines a drawing environment. This will be a scope for the purposes of
+% the graphics state. Depending on the driver, other set up may or may not
+% take place here. The natural size of the \meta{content} should be zero
+% from the \TeX{} perspective: allowance for the size of the content must
+% be made at a higher level (or indeed this can be skipped if the content is
+% to overlap other material).
+% \end{function}
+%
+% \begin{function}
+% {\__driver_draw_scope_begin:, \__driver_draw_scope_end:}
+% \begin{syntax}
+% \cs{__driver_draw_scope_begin:}
+% \meta{content}
+% \cs{__driver_draw_scope_end:}
+% \end{syntax}
+% Defines a scope for drawing settings and so on. Changes to the graphic
+% state and concepts such as color or linewidth are localised to a scope.
+% This function pair must never be used if an partial path is under
+% construction: such paths must be entirely contained at one unbroken
+% scope level.
+% \end{function}
+%
+% \subsection{Path construction}
+%
+% \begin{function}{\__driver_draw_moveto:nn}
+% \begin{syntax}
+% \cs{__driver_draw_move:nn} \Arg{x} \Arg{y}
+% \end{syntax}
+% Moves the current drawing reference point to (\meta{x}, \meta{y});
+% any active transformation matrix will apply.
+% \end{function}
+%
+% \begin{function}{\__driver_draw_lineto:nn}
+% \begin{syntax}
+% \cs{__driver_draw_lineto:nn} \Arg{x} \Arg{y}
+% \end{syntax}
+% Adds a path from the current drawing reference point to
+% (\meta{x}, \meta{y}); any active transformation matrix will apply. Note
+% that nothing is drawn until a fill or stroke operation is applied, and that
+% the path may be discarded or used as a clip without appearing itself.
+% \end{function}
+%
+% \begin{function}{\__driver_draw_curveto:nnnnnn}
+% \begin{syntax}
+% \cs{__driver_draw_curveto:nnnnnn} \Arg{x_1} \Arg{y_1}
+% \Arg{x_2} \Arg{y_2} \Arg{x_3} \Arg{y_3}
+% \end{syntax}
+% Adds a Bezier curve path from the current drawing reference point to
+% (\meta{x_3}, \meta{y_3}), using (\meta{x_1}, \meta{y_1}) and
+% (\meta{x_2}, \meta{y_2}) as control points; any active transformation
+% matrix will apply. Note that nothing is drawn until a fill or stroke
+% operation is applied, and that the path may be discarded or used as a clip
+% without appearing itself.
+% \end{function}
+%
+% \begin{function}{\__driver_draw_closepath:}
+% \begin{syntax}
+% \cs{__driver_draw_closepath:}
+% \end{syntax}
+% Closes an existing path, adding a line from the current point to the
+% start of path. Note that nothing is drawn until a fill or stroke
+% operation is applied, and that the path may be discarded or used as a clip
+% without appearing itself.
+% \end{function}
+%
+% \subsection{Stroking and filling}
+%
+% \begin{function}{\__driver_draw_stroke:, \__driver_draw_closestroke:}
+% \begin{syntax}
+% \meta{path construction}
+% \cs{__driver_draw_stroke:}
+% \end{syntax}
+% Draws a line alone the current path, which will also be closed when
+% \cs{__driver_draw_closestroke:} is used. The nature of the line drawn
+% is influenced by settings for
+% \begin{itemize}
+% \item Line thickness
+% \item Stroke color (or the current color if no specific stroke color
+% is set)
+% \item Line capping (how non-closed line ends should look)
+% \item Join style (how a bend in the path should be rendered)
+% \item Dash pattern
+% \end{itemize}
+% The path may also be used for clipping.
+% \end{function}
+%
+% \begin{function}{\__driver_draw_fill:, \__driver_draw_fillstroke:}
+% \begin{syntax}
+% \meta{path construction}
+% \cs{__driver_draw_fill:}
+% \end{syntax}
+% Fills the area surrounded by the current path: this will be closed prior
+% to filling if it is not already. The \texttt{fillstroke} version will also
+% stroke the path as described for \cs{__driver_draw_stroke:}. The fill is
+% influenced by the setting for fill color (or the current color if no
+% specific stroke color is set). The path may also be used for clipping.
+% For paths which are self-intersecting or comprising multiple parts, the
+% determination of which areas are inside the path is made using the nonzero
+% winding rule number unless \cs{__driver_draw_eor_bool} is \texttt{true},
+% in which case the even-odd rule is used.
+% \end{function}
+%
+% \begin{function}{\__driver_draw_clip:}
+% \begin{syntax}
+% \meta{path construction}
+% \cs{__driver_draw_clip:}
+% \end{syntax}
+% Indicates that the current path should be used for clipping, such that
+% any subsequent material outside of the path (but within the current
+% scope) will not be shown. This command should be given once a path is
+% complete but before it is stroked or filled (if appropriate).
+% \end{function}
+%
+% \begin{function}{\__driver_draw_discardpath:}
+% \begin{syntax}
+% \meta{path construction}
+% \cs{__driver_draw_discardpath:}
+% \end{syntax}
+% Discards the current path without stroking or filling. This is primarily
+% useful for paths constructed purely for clipping, as this alone does not
+% end the paths existence.
+% \end{function}
+%
+% \subsection{Stroke options}
+%
+% \begin{function}{\__driver_draw_linewidth:n}
+% \begin{syntax}
+% \cs{__driver_draw_linewidth:n} \Arg{dimexpr}
+% \end{syntax}
+% Sets the width to be used for stroking to \meta{dimexpr}.
+% \end{function}
+%
+% \begin{function}{\__driver_draw_dash:nn}
+% \begin{syntax}
+% \cs{__driver_draw_dash:nn} \Arg{dash pattern} \Arg{phase}
+% \end{syntax}
+% Sets the pattern of dashing to be used when stroking a line. The
+% \meta{dash pattern} should be a comma-separated list of dimension
+% expressions. This is then interpreted as a series of pairs of line-on
+% and line-off lengths. For example \texttt{3pt, 4pt} means that $3$\,pt on,
+% $4$\,pt off, $3$\,pt on, and so on. A more complex pattern will also
+% repeat: \texttt{3pt, 4pt, 1pt, 2pt} results in $3$\,pt on, $4$\,pt off,
+% $1$\,pt on, $2$\,pt off, $3$\,pt on, and so on. An odd number of entries
+% means that the last is repeated, for example \texttt{3pt} is equal to
+% \texttt{3pt, 3pt}. An empty pattern yields a solid line.
+%
+% The \meta{phase} specifies an offset at the start of the cycle. For
+% example, with a pattern \texttt{3pt} a phase of \texttt{1pt} will mean
+% that the output is $2$\,pt on, $3$\,pt off, $3$\,pt on, $3$\,pt on,
+% \emph{etc.}
+% \end{function}
+%
+% \begin{function}
+% {
+% \__driver_draw_cap_butt: ,
+% \__driver_draw_cap_rectangle: ,
+% \__driver_draw_cap_round:
+% }
+% \begin{syntax}
+% \cs{__driver_draw_cap_butt:}
+% \end{syntax}
+% Sets the style of terminal stroke position to one of butt, rectangle or
+% round.
+% \end{function}
+%
+% \begin{function}
+% {
+% \__driver_draw_join_bevel: ,
+% \__driver_draw_join_miter: ,
+% \__driver_draw_join_round:
+% }
+% \begin{syntax}
+% \cs{__driver_draw_cap_butt:}
+% \end{syntax}
+% Sets the style of stroke joins to one of bevel, miter or round.
+% \end{function}
+%
+% \begin{function}{\__driver_draw_miterlimit:n}
+% \begin{syntax}
+% \cs{__driver_draw_miterlimit:n} \Arg{dimexpr}
+% \end{syntax}
+% Sets the miter limit of lines joined as a miter, as described in the
+% PDF and PostScript manuals.
+% \end{function}
+%
% \end{documentation}
%
% \begin{implementation}
@@ -383,12 +591,12 @@
% \begin{macro}[aux]{\@@_color_reset:}
% Directly set the color using the specials with optimisation support.
% \begin{macrocode}
-\cs_new_protected_nopar:Npx \@@_color_ensure_current:
+\cs_new_protected_nopar:Npn \@@_color_ensure_current:
{
\tex_special:D { pdf:bcolor~\l_@@_current_color_tl }
- \group_insert_after:N \exp_not:N \@@_color_reset:
+ \group_insert_after:N \@@_color_reset:
}
-\cs_new_protected_nopar:Npx \@@_color_reset:
+\cs_new_protected_nopar:Npn \@@_color_reset:
{ \tex_special:D { pdf:ecolor } }
% \end{macrocode}
% \end{macro}
@@ -419,9 +627,8 @@
\cs_set_protected_nopar:Npn \@@_color_ensure_current:
{
\tex_special:D { color~push~\l_@@_current_color_tl }
- \group_insert_after:N \exp_not:N \@@_color_reset:
+ \group_insert_after:N \@@_color_reset:
}
-
\cs_set_protected_nopar:Npn \@@_color_reset:
{ \tex_special:D { color~pop } }
}
@@ -533,6 +740,258 @@
% \end{macrocode}
% \end{macro}
%
+% \subsection{Drawing}
+%
+% \begin{macro}[aux]{\@@_draw_literal:n, \@@_draw_literal:x}
+% Pass data through using a dedicated interface.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_draw_literal:n \@@_literal:n
+\cs_generate_variant:Nn \@@_draw_literal:n { x }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_draw_begin:, \@@_draw_end:}
+% No special requirements here, so simply set up a drawing scope.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_draw_begin:
+ { \@@_draw_scope_begin: }
+\cs_new_protected_nopar:Npn \@@_draw_end:
+ { \@@_draw_scope_end: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_draw_scope_begin:, \@@_draw_scope_end:}
+% In contrast to a general scope, a drawing scope is always done using
+% the PDF operators so is the same for all relevant drivers.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_draw_scope_begin:
+ { \@@_draw_literal:n { q } }
+\cs_new_protected_nopar:Npn \@@_draw_scope_end:
+ { \@@_draw_literal:n { Q } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_draw_moveto:nn, \@@_draw_lineto:nn}
+% \begin{macro}[int]{\@@_draw_curveto:nnnnnn}
+% Path creation operations all resolve directly to PDF primitive steps, with
+% only the need to convert to \texttt{bp}. Notice that \texttt{x}-type
+% expansion is included here to ensure that any variable values are
+% forced to literals before any possible caching.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_draw_moveto:nn #1#2
+ {
+ \@@_draw_literal:x
+ { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ m }
+ }
+\cs_new_protected:Npn \@@_draw_lineto:nn #1#2
+ {
+ \@@_draw_literal:x
+ { \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~ l }
+ }
+\cs_new_protected:Npn \@@_draw_curveto:nnnnnn #1#2#3#4#5#6
+ {
+ \@@_draw_literal:x
+ {
+ \dim_to_decimal_in_bp:n {#1} ~ \dim_to_decimal_in_bp:n {#2} ~
+ \dim_to_decimal_in_bp:n {#3} ~ \dim_to_decimal_in_bp:n {#4} ~
+ \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~
+ c
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}[int]{\@@_draw_eor_bool}
+% The even-odd rule here can be implemented as a simply switch.
+% \begin{macrocode}
+\bool_new:N \@@_draw_eor_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[int]
+% {
+% \@@_draw_closepath: ,
+% \@@_draw_stroke: ,
+% \@@_draw_closestroke: ,
+% \@@_draw_fill: ,
+% \@@_draw_fillstroke: ,
+% \@@_draw_clip: ,
+% \@@_draw_discardpath:
+% }
+% Converting paths to output is again a case of mapping directly to
+% PDF operations.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_draw_closepath:
+ { \@@_draw_literal:n { h } }
+\cs_new_protected_nopar:Npn \@@_draw_stroke:
+ { \@@_draw_literal:n { S } }
+\cs_new_protected_nopar:Npn \@@_draw_closestroke:
+ { \@@_draw_literal:n { s } }
+\cs_new_protected_nopar:Npn \@@_draw_fill:
+ {
+ \@@_draw_literal:x
+ { f \bool_if:NT \@@_draw_eor_bool * }
+ }
+\cs_new_protected_nopar:Npn \@@_draw_fillstroke:
+ {
+ \@@_draw_literal:x
+ { B \bool_if:NT \@@_draw_eor_bool * }
+ }
+\cs_new_protected_nopar:Npn \@@_draw_clip:
+ {
+ \@@_draw_literal:x
+ { W \bool_if:NT \@@_draw_eor_bool * }
+ }
+\cs_new_protected_nopar:Npn \@@_draw_discardpath:
+ { \@@_draw_literal:n { n } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_draw_dash:nn}
+% \begin{macro}[aux]{\@@_draw_dash:n}
+% \begin{macro}[int]{\@@_draw_linewidth:n}
+% \begin{macro}[int]{\@@_draw_miterlimit:n}
+% \begin{macro}[int]^^A
+% {
+% \@@_draw_cap_butt:, \@@_draw_cap_round:, \@@_draw_cap_rectangle:,
+% \@@_draw_join_miter:, \@@_draw_join_round:, \@@_draw_join_bevel:
+% }
+% Converting paths to output is again a case of mapping directly to
+% PDF operations.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_draw_dash:nn #1#2
+ {
+ \@@_draw_literal:x
+ {
+ [ ~
+ \clist_map_function:nN {#1} \@@_draw_dash:n
+ ] ~
+ \dim_to_decimal_in_bp:n {#2} ~ d
+ }
+ }
+\cs_new:Npn \@@_draw_dash:n #1
+ { \dim_to_decimal_in_bp:n {#1} ~ }
+\cs_new_protected:Npn \@@_draw_linewidth:n #1
+ {
+ \@@_draw_literal:x
+ { \dim_to_decimal_in_bp:n {#1} ~ w }
+ }
+\cs_new_protected:Npn \@@_draw_miterlimit:n #1
+ { \@@_draw_literal:x { \fp_eval:n {#1} ~ M } }
+\cs_new_protected_nopar:Npn \@@_draw_cap_butt:
+ { \@@_draw_literal:n { 0 ~ J } }
+\cs_new_protected_nopar:Npn \@@_draw_cap_round:
+ { \@@_draw_literal:n { 1 ~ J } }
+\cs_new_protected_nopar:Npn \@@_draw_cap_rectangle:
+ { \@@_draw_literal:n { 2 ~ J } }
+\cs_new_protected_nopar:Npn \@@_draw_join_miter:
+ { \@@_draw_literal:n { 0 ~ j } }
+\cs_new_protected_nopar:Npn \@@_draw_join_round:
+ { \@@_draw_literal:n { 1 ~ j } }
+\cs_new_protected_nopar:Npn \@@_draw_join_bevel:
+ { \@@_draw_literal:n { 2 ~ j } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]
+% {\@@_draw_color_cmyk_fill:nnnn, \@@_draw_color_cmyk_stroke:nnnn}
+% \begin{macro}[int]
+% {\@@_draw_color_gray_fill:n, \@@_draw_color_gray_stroke:n}
+% \begin{macro}[int]
+% {\@@_draw_color_rgb_fill:nnn, \@@_draw_color_rgb_stroke:nnn}
+% Yet more fast conversion, all using the FPU to allow for expressions
+% in numerical input.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_draw_color_cmyk_fill:nnnn #1#2#3#4
+ {
+ \@@_draw_literal:x
+ {
+ \fp_eval:n {#1} ~ \fp_eval:n {#2} ~
+ \fp_eval:n {#3} ~ \fp_eval:n {#4} ~
+ k
+ }
+ }
+\cs_new_protected:Npn \@@_draw_color_cmyk_stroke:nnnn #1#2#3#4
+ {
+ \@@_draw_literal:x
+ {
+ \fp_eval:n {#1} ~ \fp_eval:n {#2} ~
+ \fp_eval:n {#3} ~ \fp_eval:n {#4} ~
+ K
+ }
+ }
+\cs_new_protected:Npn \@@_draw_color_gray_fill:n #1
+ { \@@_draw_literal:x { \fp_eval:n {#1} ~ g } }
+\cs_new_protected:Npn \@@_draw_color_gray_stroke:n #1
+ { \@@_draw_literal:x { \fp_eval:n {#1} ~ G } }
+\cs_new_protected:Npn \@@_draw_color_rgb_fill:nnn #1#2#3
+ {
+ \@@_draw_literal:x
+ { \fp_eval:n {#1} ~ \fp_eval:n {#2} ~ \fp_eval:n {#3} ~ rg }
+ }
+\cs_new_protected:Npn \@@_draw_color_rgb_stroke:nnn #1#2#3
+ {
+ \@@_draw_literal:x
+ { \fp_eval:n {#1} ~ \fp_eval:n {#2} ~ \fp_eval:n {#3} ~ RG }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_draw_transformcm:nnnnnn}
+% The first four arguments here are floats (the affine matrix), the last
+% two are a displacement vector. Once again, force evaluation to allow for
+% caching.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_draw_transformcm:nnnnnn #1#2#3#4#5#6
+ {
+ \@@_draw_literal:x
+ {
+ \fp_eval:n {#1} ~ \fp_eval:n {#2} ~
+ \fp_eval:n {#3} ~ \fp_eval:n {#4} ~
+ \dim_to_decimal_in_bp:n {#5} ~ \dim_to_decimal_in_bp:n {#6} ~
+ cm
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_draw_hbox:Nnnnnnn}
+% \begin{variable}[aux]{\l_@@_tmp_box}
+% Inserting a \TeX{} box transformed to the requested position and using
+% the current matrix is done using a mixture of \TeX{} and low-level
+% manipulation. The offset can be handled by \TeX{}, so only any rotation/^^A
+% skew/scaling component needs to be done using the matrix operation. As this
+% operation can never be cached, the scope is set directly not using the
+% \texttt{draw} version.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_draw_hbox:Nnnnnnn #1#2#3#4#5#6#7
+ {
+ \hbox_set:Nn \l_@@_tmp_box
+ {
+ \tex_kern:D \__dim_eval:w #6 \__dim_eval_end:
+ \@@_scope_begin:
+ \@@_draw_transformcm:nnnnnn {#2} {#3} {#4} {#5}
+ { 0pt } { 0pt }
+ \box_move_up:nn {#7} { \box_use:N #1 }
+ \@@_scope_end:
+ }
+ \box_set_wd:Nn \l_@@_tmp_box { 0pt }
+ \box_set_ht:Nn \l_@@_tmp_box { 0pt }
+ \box_set_dp:Nn \l_@@_tmp_box { 0pt }
+ \box_use:N \l_@@_tmp_box
+ }
+\box_new:N \l_@@_tmp_box
+% \end{macrocode}
+% \end{variable}
+% \end{macro}
+%
% \begin{macrocode}
%</dvipdfmx|pdfmode|xdvipdfmx>
% \end{macrocode}
@@ -552,7 +1011,7 @@
% of the stack to save the current position \enquote{up front} and to
% move back to it at the end of the process.
% \begin{macrocode}
-\cs_new_protected:Npx \@@_literal:n #1
+\cs_new_protected:Npn \@@_literal:n #1
{
\tex_special:D
{
@@ -691,7 +1150,6 @@
\tex_special:D { color~push~\l_@@_current_color_tl }
\group_insert_after:N \@@_color_reset:
}
-
\cs_new_protected_nopar:Npn \@@_color_reset:
{ \tex_special:D { color~pop } }
% \end{macrocode}
@@ -897,9 +1355,8 @@
\cs_new_protected_nopar:Npn \@@_color_ensure_current:
{
\tex_special:D { color~push~\l_@@_current_color_tl }
- \group_insert_after:N \exp_not:N \@@_color_reset:
+ \group_insert_after:N \@@_color_reset:
}
-
\cs_new_protected_nopar:Npn \@@_color_reset:
{ \tex_special:D { color~pop } }
% \end{macrocode}
@@ -916,4 +1373,4 @@
%
% \end{implementation}
%
-% \PrintIndex \ No newline at end of file
+% \PrintIndex