summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3experimental
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-02-19 03:01:02 +0000
committerNorbert Preining <norbert@preining.info>2021-02-19 03:01:02 +0000
commitf670508774c35b585b520fa9217d156664b4cb2a (patch)
treefcf8e0722878a1789f7a4200d247850c1a39a647 /macros/latex/contrib/l3experimental
parent154cba57ad7bf6df84889efda0fa5cd8b1e54828 (diff)
CTAN sync 202102190301
Diffstat (limited to 'macros/latex/contrib/l3experimental')
-rw-r--r--macros/latex/contrib/l3experimental/CHANGELOG.md9
-rw-r--r--macros/latex/contrib/l3experimental/README.md14
-rw-r--r--macros/latex/contrib/l3experimental/l3benchmark.dtx4
-rw-r--r--macros/latex/contrib/l3experimental/l3benchmark.pdfbin314447 -> 314359 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3bitset.dtx4
-rw-r--r--macros/latex/contrib/l3experimental/l3bitset.pdfbin382530 -> 382437 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3color.dtx2553
-rw-r--r--macros/latex/contrib/l3experimental/l3color.ins58
-rw-r--r--macros/latex/contrib/l3experimental/l3color.pdfbin369039 -> 0 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3draw-boxes.dtx2
-rw-r--r--macros/latex/contrib/l3experimental/l3draw-code.pdfbin606904 -> 607244 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3draw-layers.dtx2
-rw-r--r--macros/latex/contrib/l3experimental/l3draw-paths.dtx2
-rw-r--r--macros/latex/contrib/l3experimental/l3draw-points.dtx2
-rw-r--r--macros/latex/contrib/l3experimental/l3draw-scopes.dtx2
-rw-r--r--macros/latex/contrib/l3experimental/l3draw-softpath.dtx2
-rw-r--r--macros/latex/contrib/l3experimental/l3draw-state.dtx2
-rw-r--r--macros/latex/contrib/l3experimental/l3draw-transforms.dtx2
-rw-r--r--macros/latex/contrib/l3experimental/l3draw.dtx18
-rw-r--r--macros/latex/contrib/l3experimental/l3draw.pdfbin490075 -> 489992 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3galley.dtx4
-rw-r--r--macros/latex/contrib/l3experimental/l3galley.pdfbin386004 -> 385907 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3graphics.dtx4
-rw-r--r--macros/latex/contrib/l3experimental/l3graphics.pdfbin363302 -> 363213 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3pdf-code.pdfbin279001 -> 0 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3pdf-code.tex56
-rw-r--r--macros/latex/contrib/l3experimental/l3pdf.dtx442
-rw-r--r--macros/latex/contrib/l3experimental/l3pdf.ins60
-rw-r--r--macros/latex/contrib/l3experimental/l3pdf.pdfbin377364 -> 0 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3str-format.dtx4
-rw-r--r--macros/latex/contrib/l3experimental/l3str-format.pdfbin345158 -> 345067 bytes
-rw-r--r--macros/latex/contrib/l3experimental/l3sys-shell.dtx4
-rw-r--r--macros/latex/contrib/l3experimental/l3sys-shell.pdfbin311867 -> 311776 bytes
-rw-r--r--macros/latex/contrib/l3experimental/xcoffins.dtx4
-rw-r--r--macros/latex/contrib/l3experimental/xcoffins.pdfbin373136 -> 373064 bytes
-rw-r--r--macros/latex/contrib/l3experimental/xgalley.dtx4
-rw-r--r--macros/latex/contrib/l3experimental/xgalley.pdfbin285978 -> 285883 bytes
37 files changed, 41 insertions, 3217 deletions
diff --git a/macros/latex/contrib/l3experimental/CHANGELOG.md b/macros/latex/contrib/l3experimental/CHANGELOG.md
index 5c3d6b7d4a..2180a6864b 100644
--- a/macros/latex/contrib/l3experimental/CHANGELOG.md
+++ b/macros/latex/contrib/l3experimental/CHANGELOG.md
@@ -7,6 +7,12 @@ this project uses date-based 'snapshot' version identifiers.
## [Unreleased]
+## [2021-02-18]
+
+### Removed
+- `l3color`: moved to `l3kernel`
+- `l3pdf`: moved to `l3kernel`
+
## [2021-02-06]
### Changed
@@ -195,7 +201,8 @@ this project uses date-based 'snapshot' version identifiers.
- New `l3color` module using `xcolor`-like expression syntax
- New `l3draw` module, based on `pgf` layer of the TikZ system
-[Unreleased]: https://github.com/latex3/latex3/compare/2021-02-06...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2021-02-18...HEAD
+[2021-02-18]: https://github.com/latex3/latex3/compare/2021-02-06...2021-02-18
[2021-02-06]: https://github.com/latex3/latex3/compare/2021-01-29...2021-02-06
[2021-01-29]: https://github.com/latex3/latex3/compare/2021-10-27...2021-01-29
[2020-10-27]: https://github.com/latex3/latex3/compare/2020-09-24...2020-10-27
diff --git a/macros/latex/contrib/l3experimental/README.md b/macros/latex/contrib/l3experimental/README.md
index 417d53493e..110132faf0 100644
--- a/macros/latex/contrib/l3experimental/README.md
+++ b/macros/latex/contrib/l3experimental/README.md
@@ -1,7 +1,7 @@
Experimental LaTeX3 Concepts
============================
-Release 2021-02-06
+Release 2021-02-18
Overview
--------
@@ -22,7 +22,6 @@ updated at the same time.
Currently included in the CTAN release of l3experimental are the following
bundles:
* `l3benchmark`
-* `l3color`
* `l3draw`
* `l3graphics`
* `l3pdf`
@@ -36,15 +35,6 @@ bundles:
This module provides support for benchmarking the performance of code.
-
-`l3color`
----------
-
-This module provides support for setting colors using a range of color models.
-It also allows the construction of 'color expressions', in which multiple colors
-are mixed together at the macro level. There is also support for spot colors:
-the latter is highly experimental.
-
`l3draw`
--------
@@ -127,7 +117,7 @@ The LaTeX Project
------------------
Development of LaTeX3 is carried out by
-[The LaTeX Project](https://www.latex-project.org/latex3/).
+[The LaTeX Project](https://www.latex-project.org/latex3/).
The development team can be contacted
by e-mail: <latex-team@latex-project.org>; for general LaTeX3 discussion
diff --git a/macros/latex/contrib/l3experimental/l3benchmark.dtx b/macros/latex/contrib/l3experimental/l3benchmark.dtx
index 76f3677781..1771ac2666 100644
--- a/macros/latex/contrib/l3experimental/l3benchmark.dtx
+++ b/macros/latex/contrib/l3experimental/l3benchmark.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
@@ -129,7 +129,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3benchmark}{2021-02-06}{}
+\ProvidesExplPackage{l3benchmark}{2021-02-18}{}
{L3 Experimental benchmarking}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3experimental/l3benchmark.pdf b/macros/latex/contrib/l3experimental/l3benchmark.pdf
index a788198674..ee7144dba8 100644
--- a/macros/latex/contrib/l3experimental/l3benchmark.pdf
+++ b/macros/latex/contrib/l3experimental/l3benchmark.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3bitset.dtx b/macros/latex/contrib/l3experimental/l3bitset.dtx
index 7c61b81f83..686df60ccd 100644
--- a/macros/latex/contrib/l3experimental/l3bitset.dtx
+++ b/macros/latex/contrib/l3experimental/l3bitset.dtx
@@ -42,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
% \begin{documentation}
@@ -264,7 +264,7 @@
%<@@=bitset>
% \end{macrocode}
% \begin{macrocode}
-\ProvidesExplPackage{l3bitset}{2021-02-06}{}
+\ProvidesExplPackage{l3bitset}{2021-02-18}{}
{L3 Experimental bitset support}
% \end{macrocode}
% A bitset is a string variable.
diff --git a/macros/latex/contrib/l3experimental/l3bitset.pdf b/macros/latex/contrib/l3experimental/l3bitset.pdf
index 68490cb185..2c9b2877c2 100644
--- a/macros/latex/contrib/l3experimental/l3bitset.pdf
+++ b/macros/latex/contrib/l3experimental/l3bitset.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3color.dtx b/macros/latex/contrib/l3experimental/l3color.dtx
deleted file mode 100644
index 0f1b130da8..0000000000
--- a/macros/latex/contrib/l3experimental/l3color.dtx
+++ /dev/null
@@ -1,2553 +0,0 @@
-% \iffalse meta-comment
-%
-%% File: l3color.dtx
-%
-% Copyright (C) 2017-2021 The LaTeX 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|package>
-%<*driver>
-\documentclass[full]{l3doc}
-\begin{document}
- \DocInput{\jobname.dtx}
-\end{document}
-%</driver>
-% \fi
-%
-% \title{^^A
-% The \textsf{l3color} package\\ Experimental color support^^A
-% }
-%
-% \author{^^A
-% The \LaTeX{} Project\thanks
-% {^^A
-% E-mail:
-% \href{mailto:latex-team@latex-project.org}
-% {latex-team@latex-project.org}^^A
-% }^^A
-% }
-%
-% \date{Released 2021-02-06}
-%
-% \maketitle
-%
-% \begin{documentation}
-%
-% \section{Color models}
-%
-% A color \emph{model} is a way to represent sets of colors. Different models
-% are particularly suitable for different output methods, \emph{e.g.}~screen
-% or print. Parameter-based models can describe a very large number of unique
-% colors, and have a varying number of \emph{axes} which define a color
-% space. In contrast, various proprietary models are available which define
-% \emph{spot} colors (more formally separations).
-%
-% Core models are used to pass color information to output; these are
-% \enquote{native} to \pkg{l3color}. Core models use real numbers in the range
-% $[0,1]$ to represent values. The core models supported here are
-% \begin{itemize}
-% \item \texttt{gray} Grayscale color, with a single axis running from
-% $0$ (fully black) to $1$ (fully white)
-% \item \texttt{rgb} Red-green-blue color, with three axes, one for each of
-% the components
-% \item \texttt{cmyk} Cyan-magenta-yellow-black color, with four axes, one for
-% each of the components
-% \end{itemize}
-% There are also interface models: these are convenient for users but have
-% to be manipulated before storing/passing to the backend. Interface models
-% are primarily integer-based: see below for more detail. The supported
-% interface models are
-% \begin{itemize}
-% \item \texttt{Gray} Grayscale color, with a single axis running from
-% $0$ (fully black) to $15$ (fully white)
-% \item \texttt{hsb} Hue-saturation-brightness color, with three axes,all
-% real values in the range $[0,1]$ for hue saturation and brightness
-% \item \texttt{Hsb} Hue-saturation-brightness color, with three axes, integer
-% in the range $[0,360]$ for hue, real values in the range $[0,1]$ for
-% saturation and brightness
-% \item \texttt{HSB} Hue-saturation-brightness color, with three axes, integers
-% in the range $[0,240]$ for hue, saturation and brightness
-% \item \texttt{HTML} HTML format representation of RGB color given as a
-% single six-digit hexadecimal number
-% \item \texttt{RGB} Red-green-blue color, with three axes, one for each of
-% the components, values as integers from $0$ to $255$
-% \item \texttt{wave} Light wavelength, a real number in the range
-% $380$ to $780$ (nanometres)
-% \end{itemize}
-% All interface models are internally stored as |rgb|.
-%
-% To allow parsing of data from \pkg{xcolor}, any leading model up the first
-% \texttt{:} will be discarded; the approach of selecting an internal form
-% for data is \emph{not} used in \pkg{l3color}.
-%
-% Additional models may be created to allow mixing of separation colors
-% with each other or with those from other models. See
-% Section~\ref{l3color:sec:new-models} for more detail of color support
-% for additional models.
-%
-% When color is selected by model, the \meta{values} given are specified as
-% a comma-separated list. The length of the list will therefore be determined
-% by the detail of the model involved.
-%
-% Color models (and interconversion) are complex, and more details are given
-% in the manual to the \LaTeXe{} \pkg{xcolor} package and in the
-% \emph{PostScript Language Reference Manual}, published by Addison--Wesley.
-%
-% \section{Color expressions}
-%
-% In addition to allowing specification of color by model and values,
-% \pkg{l3color} also supports color expressions. These are created
-% by combining one or more color names, with the amount of each specified
-% as a percentage. The latter is given between |!| symbols in the expression.
-% Thus for example
-% \begin{verbatim}
-% red!50!green
-% \end{verbatim}
-% is a mixture of $50\,\%$ red and $50\,\%$ green. A trailing percentage is
-% interpreted as implicitly followed by |white|, and so
-% \begin{verbatim}
-% red!25
-% \end{verbatim}
-% specifies $25\,\%$ red mixed with $75\,\%$ white.
-%
-% Where the models for the mixed colors are different, the model of the first
-% color is used. Thus
-% \begin{verbatim}
-% red!50!cyan
-% \end{verbatim}
-% will result in a color specification using the |rgb| model, made up of
-% $50\,\%$ red and $50\,\%$ of cyan \emph{expressed in \texttt{rgb}}. As color
-% model interconversion is not exact.
-%
-% The one exception to the above is where the first model in an expression is
-% |gray|. In this case, the order of mixing is \enquote{swapped} internally, so
-% that for example
-% \begin{verbatim}
-% black!50!red
-% \end{verbatim}
-% has the same result as
-% \begin{verbatim}
-% red!50!black
-% \end{verbatim}
-% (the predefined colors |black| and |white| use the |gray| model).
-%
-% Where more than two colors are mixed in an expression, evaluation takes place
-% in a stepwise fashion. Thus in
-% \begin{verbatim}
-% cyan!50!magenta!10!yellow
-% \end{verbatim}
-% the sub-expression
-% \begin{verbatim}
-% cyan!50!magenta
-% \end{verbatim}
-% is first evaluated to give an intermediate color specification, before
-% the second step
-% \begin{verbatim}
-% <intermediate>!10!yellow
-% \end{verbatim}
-% where |<intermediate>| represents this transitory calculated value.
-%
-% Within a color expression, |.| may be used to represent the color active
-% for typesetting (the current color). This allows for example
-% \begin{verbatim}
-% .!50
-% \end{verbatim}
-% to mean a mixture of $50\,\%$ of current color with white.
-%
-% (Color expressions supported here are a subset of those provided by
-% the \LaTeXe{} \pkg{xcolor} package. At present, only such features as are
-% clearly useful have been added here.)
-%
-% \section{Named colors}
-%
-% Color names are stored in a single namespace, which makes them accessible
-% as part of color expressions. Whilst they are not reserved in a technical
-% sense, the names |black|, |white|, |red|, |green|, |blue|, |cyan|, |magenta|
-% and |yellow| have special meaning and should not be redefined. Color names
-% should be made up of letters, numbers and spaces only: other characters are
-% reserved for use in color expressions. In particular, |.| represents the
-% current color at the start of a color expression.
-%
-% \begin{function}{\color_set:nn}
-% \begin{syntax}
-% \cs{color_set:nn} \Arg{name} \Arg{color expression}
-% \end{syntax}
-% Evaluates the \meta{color expression} and stores the resulting
-% color specification as the \meta{name}.
-% \end{function}
-%
-% \begin{function}{\color_set:nnn}
-% \begin{syntax}
-% \cs{color_set:nnn} \Arg{name} \Arg{model(s)} \Arg{value(s)}
-% \end{syntax}
-% Stores the color specification equivalent to the \meta{model(s)} and
-% \meta{values} as the \meta{name}.
-% \end{function}
-%
-% \begin{function}{\color_set_eq:nn}
-% \begin{syntax}
-% \cs{color_set_eq:nn} \Arg{name1} \Arg{name2}
-% \end{syntax}
-% Copies the color specification in \meta{name2} to \meta{name1}. The
-% special name |.| may be used to represent the current color, allowing
-% it to be saved to a name.
-% \end{function}
-%
-% \begin{function}{\color_show:n}
-% \begin{syntax}
-% \cs{color_show:n} \Arg{name}
-% \end{syntax}
-% Displays the color specification stored in the \meta{name} on the
-% terminal.
-% \end{function}
-%
-% \section{Selecting colors}
-%
-% General selection of color is safe when split across pages: a stack is
-% used to ensure that the correct color is re-selected on the new page.
-%
-% \begin{function}{\color_select:n}
-% \begin{syntax}
-% \cs{color_select:n} \Arg{color expression}
-% \end{syntax}
-% Parses the \meta{color expression} and then activates the resulting
-% color specification for typeset material.
-% \end{function}
-%
-% \begin{function}{\color_select:nn}
-% \begin{syntax}
-% \cs{color_select:nn} \Arg{model(s)} \Arg{value(s)}
-% \end{syntax}
-% Activates the color specification equivalent to the \meta{model(s)} and
-% \meta{value(s)} for typeset material.
-% \end{function}
-%
-% \begin{variable}{\l_color_fixed_model_tl}
-% When this is set to a non-empty value, colors will be converted to
-% the specified model when they are selected. Note that included images
-% and similar are not influenced by this setting.
-% \end{variable}
-%
-% \section{Colors for fills and strokes}
-%
-% Colors for drawing operations and so forth are split into strokes and fills
-% (the latter may also be referred to as non-stroke color). The fill color is
-% used for text under normal circumstances. Depending on the backend, stroke
-% color may use a \emph{stack}, in which case it exhibits the same page breaking
-% behavior as general color. However, \texttt{dvips}/\texttt{dvisvgm} do not
-% support this, and so color will need to be contained within a scope, such
-% as \cs{draw_begin:}/\cs{draw_end:}.
-%
-% Note that the \emph{current color} is the fill color, as this is used for
-% running text.
-%
-% \begin{function}{\color_fill:n, \color_stroke:n}
-% \begin{syntax}
-% \cs{color_fill:n} \Arg{color expression}
-% \end{syntax}
-% Parses the \meta{color expression} and then activates the resulting
-% color specification for filling or stroking.
-% \end{function}
-%
-% \begin{function}{\color_fill:nn, \color_stroke:nn}
-% \begin{syntax}
-% \cs{color_fill:nn} \Arg{model(s)} \Arg{value(s)}
-% \end{syntax}
-% Activates the color specification equivalent to the \meta{model(s)} and
-% \meta{value(s)} for filling or stroking.
-% \end{function}
-%
-% \begin{variable}{color.sc}
-% When using \texttt{dvips}, this PostScript variables hold the stroke color.
-% \end{variable}
-%
-% \section{Multiple color models}
-%
-% When selecting or setting a color with an explicit model, it is possible
-% to give values for more than one model at one time. This is particularly
-% useful where automated conversion between models does not give the desired
-% outcome. To do this, the list of models and list of values are both subdivided
-% using |/| characters (as for the similar function in \pkg{xcolor}). For
-% example, to save a color with explicit |cmyk| and |rgb| values, one could
-% use
-% \begin{verbatim}
-% \color_set:nnn { foo } { cmyk / rgb }
-% { 0.1 , 0.2 , 0.3 , 0.4 / 0.1, 0.2 , 0.3 }
-% \end{verbatim}
-% The manually-specified conversion will be used in preference to automated
-% calculation whenever the model(s) listed are used: both in expressions and
-% when a fixed model is active.
-%
-% Similarly, the same syntax can be applied to directly selecting a color.
-% \begin{verbatim}
-% \color_select:nn { cmyk / rgb }
-% { 0.1 , 0.2 , 0.3 , 0.4 / 0.1, 0.2 , 0.3 }
-% \end{verbatim}
-% Again, this list is used when a fixed model is active: the first entry is used
-% unless there is a fixed model matching one of the other entries.
-%
-% \section{Exporting color specifications}
-%
-% The major use of color expressions is in setting typesetting output, but there
-% are other places in which some form of color information is required. These
-% may need data in a different format or using a different model to the internal
-% representation. Thus a set of functions are available to export colors in
-% different formats.
-%
-% Valid export targets are
-% \begin{itemize}
-% \item \texttt{backend} Two brace groups: the first containing the
-% model, the second containing space-separated values appropriate
-% for the model; this is the format required by backend functions
-% of \pkg{expl3}
-% \item \texttt{HTML} Uppercase two-digit hexadecimal values, expressing
-% a red-green-blue color; the digits are \emph{not} separated
-% \item \texttt{space-sep-cmyk} Space-separated cyan-magenta-yellow-black
-% values
-% \item \texttt{space-sep-rgb} Space-separated red-green-blue values
-% suitable for use as a PDF annotation color
-% \end{itemize}
-%
-% \begin{function}{\color_export:nnN}
-% \begin{syntax}
-% \cs{color_export:nnN} \Arg{color expression} \Arg{format} \Arg{tl}
-% \end{syntax}
-% Parses the \meta{color expression} as described earlier,
-% then converts to the \meta{format} specified and assigns the data to the
-% \meta{tl}.
-% \end{function}
-%
-% \begin{function}{\color_export:nnnN}
-% \begin{syntax}
-% \cs{color_export:nnnN} \Arg{model} \Arg{value(s)} \Arg{format} \Arg{tl}
-% \end{syntax}
-% Expresses the combination of \meta{model} and \meta{value(s)} in an
-% internal representation, then converts to the \meta{format} specified and
-% assigns the data to the \meta{tl}.
-% \end{function}
-%
-% \section{Creating new color models}
-% \label{l3color:sec:new-models}
-%
-% Additional color models are required to support specialist workflows, for
-% example those involving separations (see
-% \url{https://helpx.adobe.com/indesign/using/spot-process-colors.html}
-% for details of the use of separations in print). Color models may be split
-% into families; for the standard device-based color models (\texttt{DeviceCMYK},
-% \texttt{DeviceRGB}, \texttt{DeviceGray}), these are synonymous. This
-% is not generally the case: see the PDF reference for more details. (Note that
-% \pkg{l3color} uses the shorter names \texttt{cmyk}, etc.)
-%
-% \begin{function}{\color_model_new:nnn}
-% \begin{syntax}
-% \cs{color_model_new:nnn} \Arg{model} \Arg{family} \Arg{params}
-% \end{syntax}
-% Creates a new \meta{model} which is derived from the color model \meta{family}.
-% The latter should be one of
-% \begin{itemize}
-% \item \texttt{DeviceN}
-% \item \texttt{Separation}
-% \end{itemize}
-% (The \meta{family} may be given in mixed case as-in the PDF reference:
-% internally, case of these strings is folded.)
-% Depending on the \meta{family}, one or more \meta{params} are mandatory or
-% optional.
-% \end{function}
-%
-% For a \texttt{Separation} space, there are three \emph{compulsory} keys.
-% \begin{itemize}
-% \item \texttt{name} The name of the Separation, for example the formal
-% name of a spot color ink. Such a \meta{name} may contain spaces, etc.,
-% which are not permitted in the \meta{model}.
-% \item \texttt{alternative-model} An alternative device colorspace, one of
-% \texttt{cmyk}, \texttt{rgb}, \texttt{gray} or \texttt{CIELAB}. The three
-% parameter-based models work as described above; see below for
-% details of CIELAB colors.
-% \item \texttt{alternative-values} A comma-separated list of values
-% appropriate to the \texttt{alternative-model}. This information is used by
-% the PDF application if the \texttt{Separation} is not available.
-% \end{itemize}
-%
-% CIELAB color separations are created using the
-% \texttt{alternative-model = CIELAB} setting. These colors must also have an
-% \texttt{illuminant} key, one of \texttt{a}, \texttt{c}, \texttt{e},
-% \texttt{d50}, \texttt{d55}, \texttt{d65} or \texttt{d75}. The
-% \texttt{alternative-values} in this case are the three parameters $L*$, $a*$
-% and $b*$ of the CIELAB model. Full details of this device-independent color
-% approach are given in the documentation to the \pkg{colorspace} package.
-%
-% CIELAB colors \emph{cannot} be converted into other device-dependent color
-% spaces, and as such, mixing can only occur if colors set up using the CIELAB
-% model are also given with an alternative parameter-based model. If that is
-% not the case, \pkg{l3color} will fallback to using black as the colorant in
-% any mixing.
-%
-% For a \texttt{DeviceN} space, there is one \emph{compulsory} key.
-% \begin{itemize}
-% \item \texttt{names} The names of the components of the \texttt{DeviceN}
-% space. Each should be either the \meta{name} of a \texttt{Separation} model,
-% a process color name (\texttt{cyan}, etc.) or the special name \texttt{none}.
-% \end{itemize}
-%
-% \end{documentation}
-%
-% \begin{implementation}
-%
-% \section{\pkg{l3color} Implementation}
-%
-% \begin{macrocode}
-%<*package>
-% \end{macrocode}
-%
-% \begin{macrocode}
-%<@@=color>
-% \end{macrocode}
-%
-% \begin{macrocode}
-\ProvidesExplPackage{l3color}{2021-02-06}{}
- {L3 Experimental color support}
-% \end{macrocode}
-%
-% \subsection{Predefined color names}
-%
-% The ability to predefine colors with a name is a key part of this module and
-% means there has to be a method for storing the results. At first sight, it
-% seems natural to follow the usual \pkg{expl3} model and create a
-% \texttt{color} variable type for the process. That would then allow both
-% local and global colors, constant colors and the like. However, these names
-% need to be accessible in some form at the user level, for selection of colors
-% either simply by name or as part of a more complex expression. This does not
-% require that the full name is exposed but does require that they can be
-% looked up in a predictable way. As such, it is more useful to expose just the
-% color names as part of the interface, with the result that only local color
-% names can be created. (This is also seen for example in key creation in
-% \pkg{l3keys}.) As a result, color names are declarative (no \texttt{new}
-% functions).
-%
-% Since there is no need to manipulate colors \emph{en masse}, each is stored
-% in a two-part structure: a \texttt{prop} for the colors themselves, and a
-% \texttt{tl} for the default model for each color.
-%
-% \subsection{Setup}
-%
-% \begin{variable}{\l_@@_internal_int, \l_@@_internal_tl}
-% \begin{macrocode}
-\int_new:N \l_@@_internal_int
-\tl_new:N \l_@@_internal_tl
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\s_@@_mark}
-% Internal scan marks. \cs{s_@@_stop} is already defined in \pkg{l3color-base}.
-% \begin{macrocode}
-\scan_new:N \s_@@_mark
-% \end{macrocode}
-% \end{variable}
-%
-% \subsection{Utility functions}
-%
-% \begin{macro}[int, TF, EXP]{\@@_if_defined:n}
-% A simple wrapper to avoid needing to have the lookup repeated in too many
-% places.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \@@_if_defined:n #1 { T, F, TF }
- {
- \prop_if_exist:cTF { l_@@_named_ #1 _prop }
- \prg_return_true:
- \prg_return_false:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\@@_model:N, \@@_values:N}
-% Simple abstractions.
-% \begin{macrocode}
-\cs_new:Npn \@@_model:N #1 { \exp_after:wN \use_i:nn #1 }
-\cs_new:Npn \@@_values:N #1 { \exp_after:wN \use_ii:nn #1 }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_extract:nNN, \@@_extract:VNN}
-% Recover the values for the standard model for a color.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_extract:nNN #1#2#3
- {
- \tl_set_eq:Nc #2 { l_@@_named_ #1 _tl }
- \prop_get:cVN { l_@@_named_ #1 _prop } #2 #3
- }
-\cs_generate_variant:Nn \@@_extract:nNN { V }
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Model conversion}
-%
-% \begin{macro}{\@@_convert:nnN, \@@_convert:VVN}
-% \begin{macro}{\@@_convert:nnnN, \@@_convert:nVnN, \@@_convert:nnVN}
-% \begin{macro}[aux, EXP]
-% {
-% \@@_convert_gray_rgb:w
-% \@@_convert_gray_cmyk:w
-% \@@_convert_cmyk_gray:w
-% \@@_convert_cmyk_rgb:w
-% \@@_convert_rgb_gray:w
-% \@@_convert_rgb_cmyk:w
-% }
-% \begin{macro}[aux, EXP]{\@@_convert_rgb_cmyk:nnnn}
-% Model conversion is carried out using standard formulae, as described in
-% the manual for \pkg{xcolor} (see also the \emph{PostScript Language
-% Reference Manual}).
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_convert:nnN #1#2#3
- { \@@_convert:nnVN {#1} {#2} #3 #3 }
-\cs_generate_variant:Nn \@@_convert:nnN { VV }
-\cs_new_protected:Npn \@@_convert:nnnN #1#2#3#4
- {
- \tl_set:Nx #4
- {
- \cs_if_exist:cTF { @@_convert_ #1 _ #2 :w }
- { \use:c { @@_convert_ #1 _ #2 :w } #3 ~ 0 ~ 0 ~ 0 \s_@@_stop }
- { \use:c { c_@@_fallback_ #2 _tl } }
- }
- }
-\cs_generate_variant:Nn \@@_convert:nnnN { nV , nnV }
-\cs_new:Npn \@@_convert_gray_rgb:w #1 ~ #2 \s_@@_stop
- { #1 ~ #1 ~ #1 }
-\cs_new:Npn \@@_convert_gray_cmyk:w #1 ~ #2 \s_@@_stop
- { 0 ~ 0 ~ 0 ~ \fp_eval:n { 1 - #1 } }
-% \end{macrocode}
-% These rather odd values are based on \textsc{ntsc} television: the set are
-% used for the |cmyk| conversion.
-% \begin{macrocode}
-\cs_new:Npn \@@_convert_rgb_gray:w #1 ~ #2 ~ #3 ~ #4 \s_@@_stop
- { \fp_eval:n { 0.3 * #1 + 0.59 * #2 + 0.11 * #3 } }
-% \end{macrocode}
-% The conversion from |rgb| to |cmyk| is the most complex: a two-step
-% procedure which requires \emph{black generation} and \emph{undercolor
-% removal} functions. The PostScript reference describes them as
-% device-dependent, but following \pkg{xcolor} we assume they are linear.
-% Moreover, as the likelihood of anyone using a non-unitary matrix here is
-% tiny, we simplify and treat those two concepts as no-ops.
-% \begin{macrocode}
-\cs_new:Npn \@@_convert_rgb_cmyk:w #1 ~ #2 ~ #3 ~ #4 \s_@@_stop
- {
- \exp_args:Nf \@@_convert_rgb_cmyk:nnnn
- { \fp_eval:n { min ( 1 - #1 , 1 - #2 , 1 - #3 ) } } {#1} {#2} {#3}
- }
-\cs_new:Npn \@@_convert_rgb_cmyk:nnnn #1#2#3#4
- {
- \fp_eval:n { min ( 1 , max ( 0 , 1 - #2 - #1 ) ) } \c_space_tl
- \fp_eval:n { min ( 1 , max ( 0 , 1 - #3 - #1 ) ) } \c_space_tl
- \fp_eval:n { min ( 1 , max ( 0 , 1 - #4 - #1 ) ) } \c_space_tl
- #1
- }
-\cs_new:Npn \@@_convert_cmyk_gray:w #1 ~ #2 ~ #3 ~ #4 ~ #5 \s_@@_stop
- { \fp_eval:n { 1 - min ( 1 , 0.3 * #1 + 0.59 * #2 + 0.11 * #3 + #4 ) } }
-\cs_new:Npn \@@_convert_cmyk_rgb:w #1 ~ #2 ~ #3 ~ #4 ~ #5 \s_@@_stop
- {
- \fp_eval:n { 1 - min ( 1 , #1 + #4 ) } \c_space_tl
- \fp_eval:n { 1 - min ( 1 , #2 + #4 ) } \c_space_tl
- \fp_eval:n { 1 - min ( 1 , #3 + #4 ) }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Color expressions}
-%
-% \begin{variable}
-% {\l_@@_model_tl, \l_@@_value_tl, \l_@@_next_model_tl, \l_@@_next_value_tl}
-% Working space to store the color data whilst doing calculations: keeping
-% it on the stack is attractive but gets tricky (return is non-trivial).
-% \begin{macrocode}
-\tl_new:N \l_@@_model_tl
-\tl_new:N \l_@@_value_tl
-\tl_new:N \l_@@_next_model_tl
-\tl_new:N \l_@@_next_value_tl
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\@@_parse:nN}
-% \begin{macro}{\@@_parse_aux:nN}
-% \begin{macro}{\@@_parse_eq:Nn}
-% \begin{macro}{\@@_parse_eq:nNn}
-% \begin{macro}{\@@_parse:Nw}
-% \begin{macro}{\@@_parse_loop_init:Nnn}
-% \begin{macro}{\@@_parse_loop:w}
-% \begin{macro}{\@@_parse_loop:nn}
-% \begin{macro}{\@@_parse_gray:n, \@@_parse_std:n}
-% \begin{macro}{\@@_parse_break:w}
-% \begin{macro}{\@@_parse_end:}
-% \begin{macro}[aux, EXP]{\@@_parse_mix:Nnnn, \@@_parse_mix:NVVn}
-% \begin{macro}[aux, EXP]{\@@_parse_mix:nNnn}
-% \begin{macro}[aux, EXP]
-% {
-% \@@_parse_mix_gray:nw ,
-% \@@_parse_mix_rgb:nw ,
-% \@@_parse_mix_cmyk:nw
-% }
-% The main function for parsing color expressions removes actives but
-% otherwise expands, then starts working through the expression itself.
-% At the end, we apply the payload.
-% \begin{macrocode}
-\cs_new_protected:Npx \@@_parse:nN #1#2
- {
- \exp_not:N \@@_backend_pickup:N \exp_not:N \l_@@_current_tl
- \tl_set:Nx \exp_not:c { l_@@_named_ . _tl }
- { \exp_not:N \@@_model:N \exp_not:N \l_@@_current_tl }
- \prop_put:NVx \exp_not:c { l_@@_named_ . _prop }
- \exp_not:c { l_@@_named_ . _tl }
- { \exp_not:N \@@_values:N \exp_not:N \l_@@_current_tl }
- \exp_not:N \exp_args:Ne \exp_not:N \@@_parse_aux:nN
- { \exp_not:N \tl_to_str:n {#1} } #2
- }
-% \end{macrocode}
-% Before going to all of the effort of parsing an expression, these two
-% precursor functions look for a pre-defined name, either on its own or
-% with a trailing |!| (which is the same thing).
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_aux:nN #1#2
- {
- \tl_if_exist:cTF { l_@@_named_ #1 _prop }
- { \@@_parse_set_eq:Nn #2 {#1} }
- { \@@_parse:Nw #2#1 ! \s_@@_stop }
- \@@_check_model:N #2
- }
-\cs_new_protected:Npn \@@_parse_set_eq:Nn #1#2
- {
- \tl_if_empty:NTF \l_color_fixed_model_tl
- { \exp_args:Nv \@@_parse_set_eq:nNn { l_@@_named_ #2 _tl } }
- { \exp_args:NV \@@_parse_set_eq:nNn \l_color_fixed_model_tl }
- #1 {#2}
- }
-% \end{macrocode}
-% Here, we have to allow for the case where there is a fixed model:
-% that can't be swept up by generic conversion as we are dealing with a
-% named color.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_set_eq:nNn #1#2#3
- {
- \prop_get:cnNTF
- { l_@@_named_ #3 _prop } {#1}
- \l_@@_value_tl
- { \tl_set:Nx #2 { {#1} { \l_@@_value_tl } } }
- {
- \tl_set_eq:Nc \l_@@_model_tl { l_@@_named_ #3 _tl }
- \prop_get:cVN { l_@@_named_ #3 _prop } \l_@@_model_tl
- \l_@@_value_tl
- \@@_convert:nnN
- \l_@@_model_tl {#1} \l_@@_value_tl
- \tl_set:Nx #2
- {
- {#1}
- { \l_@@_value_tl }
- }
- }
- }
-\cs_new_protected:Npn \@@_parse:Nw #1#2 ! #3 \s_@@_stop
- {
- \@@_if_defined:nTF {#2}
- {
- \tl_if_blank:nTF {#3}
- { \@@_parse_set_eq:Nn #1 {#2} }
- { \@@_parse_loop_init:Nnn #1 {#2} {#3} }
- }
- {
- \__kernel_msg_error:nnn { color } { unknown-color } {#2}
- \tl_set:Nn \l_@@_current_tl { { gray } { 0 } }
- }
- }
-% \end{macrocode}
-% Once we establish that a full parse is needed, the next job is to get the
-% detail of the first color. That will determine the model we use for the
-% calculation: splitting here makes checking that a bit easier.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_loop_init:Nnn #1#2#3
- {
- \group_begin:
- \@@_extract:nNN {#2} \l_@@_model_tl \l_@@_value_tl
- \@@_parse_loop:w #3 ! ! ! ! \s_@@_stop
- \tl_set:Nx \l_@@_internal_tl
- { { \l_@@_model_tl } { \l_@@_value_tl } }
- \exp_args:NNNV \group_end:
- \tl_set:Nn #1 \l_@@_internal_tl
- }
-% \end{macrocode}
-% This is the loop proper: there can be an open-ended set of colors to parse,
-% separated by |!| tokens. There are a few cases to look out for. At the end
-% of the expression and with we find a mix of $100$ then we simply skip the
-% next color entirely (we can't stop the loop as there might be a further
-% valid color to mix in). On the other hand, if we get a mix of $0$ then
-% drop everything so far and start again. There is also a trailing
-% |white| to \enquote{read in} if the final explicit data is a mix.
-% Those conditions are separate from actually looping, which is therefore
-% sorted out by checking if we have further data to process: in contrast
-% to \pkg{xcolor}, we don't allow |!!| so the test can be simplified.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_loop:w #1 ! #2 ! #3 ! #4 ! #5 \s_@@_stop
- {
- \bool_lazy_or:nnF
- { \tl_if_blank_p:n {#1} }
- { \int_compare_p:nNn {#1} = { 100 } }
- {
- \int_compare:nNnTF {#1} = { 0 }
- {
- \tl_if_blank:nTF {#2}
- { \@@_extract:nNN { white } }
- { \@@_extract:nNN {#2} }
- \l_@@_model_tl \l_@@_value_tl
- }
- {
- \use:x
- {
- \@@_parse_loop:nn {#1}
- { \tl_if_blank:nTF {#2} { white } {#2} }
- }
- }
- }
- \tl_if_blank:nF {#3}
- { \@@_parse_loop:w #3 ! #4 ! #5 \s_@@_stop }
- \@@_parse_end:
- }
-% \end{macrocode}
-% The \enquote{payload} of calculation in the loop first. If the model for
-% the upcoming color is different from that of the existing (partial) color,
-% convert the model. For |gray| the two are flipped round so that the outcome
-% is something with \enquote{real} color. We are then in a position to do the
-% actual calculation itself. The two auxiliaries here give us a way to break
-% the loop should an invalid name be found.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_loop:nn #1#2
- {
- \@@_if_defined:nTF {#2}
- {
- \@@_extract:nNN {#2} \l_@@_next_model_tl \l_@@_next_value_tl
- \tl_if_eq:NNF \l_@@_model_tl \l_@@_next_model_tl
- {
- \str_if_eq:VnTF \l_@@_model_tl { gray }
- { \@@_parse_gray:n {#2} }
- { \@@_parse_std:n {#2} }
- }
- \tl_set:Nx \l_@@_value_tl
- {
- \@@_parse_mix:NVVn
- \l_@@_model_tl \l_@@_value_tl \l_@@_next_value_tl {#1}
- }
- }
- {
- \__kernel_msg_error:nnn { color } { unknown-color } {#2}
- \@@_extract:nNN { black } \l_@@_model_tl \l_@@_value_tl
- \@@_parse_break:w
- }
- }
-% \end{macrocode}
-% The \texttt{gray} model needs special handling: the models need to be
-% swapped: we do that using a dedicated function.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_parse_gray:n #1
- {
- \tl_set_eq:NN \l_@@_model_tl \l_@@_next_model_tl
- \tl_set:Nn \l_@@_next_model_tl { gray }
- \exp_args:NnV \@@_convert:nnN { gray } \l_@@_model_tl
- \l_@@_value_tl
- \prop_get:cVN { l_@@_named_ #1 _prop } \l_@@_model_tl
- \l_@@_next_value_tl
- }
-\cs_new_protected:Npn \@@_parse_std:n #1
- {
- \prop_get:cVNF { l_@@_named_ #1 _prop }
- \l_@@_model_tl
- \l_@@_next_value_tl
- {
- \@@_convert:VVN
- \l_@@_next_model_tl
- \l_@@_model_tl
- \l_@@_next_value_tl
- }
- }
-\cs_new_protected:Npn \@@_parse_break:w #1 \@@_parse_end: { }
-\cs_new_protected:Npn \@@_parse_end: { }
-% \end{macrocode}
-% Do the vector arithmetic: mainly a question of shuffling input, along
-% with one pre-calculation to keep down the use of division.
-% \begin{macrocode}
-\cs_new:Npn \@@_parse_mix:Nnnn #1#2#3#4
- {
- \exp_args:Nf \@@_parse_mix:nNnn
- { \fp_eval:n { #4 / 100 } }
- #1 {#2} {#3}
- }
-\cs_generate_variant:Nn \@@_parse_mix:Nnnn { NVV }
-\cs_new:Npn \@@_parse_mix:nNnn #1#2#3#4
- {
- \use:c { @@_parse_mix_ #2 :nw } {#1}
- #3 \s_@@_mark #4 \s_@@_stop
- }
-\cs_new:Npn \@@_parse_mix_gray:nw #1#2 \s_@@_mark #3 \s_@@_stop
- { \fp_eval:n { #2 * #1 + #3 * ( 1 - #1 ) } }
-\cs_new:Npn \@@_parse_mix_rgb:nw
- #1#2 ~ #3 ~ #4 \s_@@_mark #5 ~ #6 ~ #7 \s_@@_stop
- {
- \fp_eval:n { #2 * #1 + #5 * ( 1 - #1 ) } \c_space_tl
- \fp_eval:n { #3 * #1 + #6 * ( 1 - #1 ) } \c_space_tl
- \fp_eval:n { #4 * #1 + #7 * ( 1 - #1 ) }
- }
-\cs_new:Npn \@@_parse_mix_cmyk:nw
- #1#2 ~ #3 ~ #4 ~ #5 \s_@@_mark #6 ~ #7 ~ #8 ~ #9 \s_@@_stop
- {
- \fp_eval:n { #2 * #1 + #6 * ( 1 - #1 ) } \c_space_tl
- \fp_eval:n { #3 * #1 + #7 * ( 1 - #1 ) } \c_space_tl
- \fp_eval:n { #4 * #1 + #8 * ( 1 - #1 ) } \c_space_tl
- \fp_eval:n { #5 * #1 + #9 * ( 1 - #1 ) }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]
-% {
-% \@@_parse_model_gray:w, \@@_parse_model_rgb:w,
-% \@@_parse_model_cmyk:w
-% }
-% \begin{macro}[EXP]{\@@_parse_number:n}
-% \begin{macro}[EXP]{\@@_parse_number:w}
-% Turn the input into internal form, also tidying up the number quickly.
-% \begin{macrocode}
-\cs_new:Npn \@@_parse_model_gray:w #1 , #2 \s_@@_stop
- { { gray } { \@@_parse_number:n {#1} } }
-\cs_new:Npn \@@_parse_model_rgb:w #1 , #2 , #3 , #4 \s_@@_stop
- {
- { rgb }
- {
- \@@_parse_number:n {#1} ~
- \@@_parse_number:n {#2} ~
- \@@_parse_number:n {#3}
- }
- }
-\cs_new:Npn \@@_parse_model_cmyk:w #1 , #2 , #3 , #4 , #5 \s_@@_stop
- {
- { cmyk }
- {
- \@@_parse_number:n {#1} ~
- \@@_parse_number:n {#2} ~
- \@@_parse_number:n {#3} ~
- \@@_parse_number:n {#4}
- }
- }
-\cs_new:Npn \@@_parse_number:n #1
- { \@@_parse_number:w #1 . 0 . \s_@@_stop }
-\cs_new:Npn \@@_parse_number:w #1 . #2 . #3 \s_@@_stop
- { \tl_if_blank:nTF {#1} { 0 } {#1} . #2 }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]
-% {
-% \@@_parse_model_Gray:w, \@@_parse_model_hsb:w,
-% \@@_parse_model_Hsb:w, \@@_parse_model_HSB:w,
-% \@@_parse_model_HTML:w, \@@_parse_model_RGB:w
-% }
-% \begin{macro}[EXP]{\@@_parse_model_hsb:nnn, \@@_parse_model_hsb_aux:nnn}
-% \begin{macro}[EXP]{\@@_parse_model_hsb:nnnn}
-% \begin{macro}[EXP]{\@@_parse_model_hsb:nnnnn}
-% \begin{macro}[EXP]
-% {
-% \@@_parse_model_hsb_0:nnnn ,
-% \@@_parse_model_hsb_1:nnnn ,
-% \@@_parse_model_hsb_2:nnnn ,
-% \@@_parse_model_hsb_3:nnnn ,
-% \@@_parse_model_hsb_4:nnnn ,
-% \@@_parse_model_hsb_5:nnnn
-% }
-% \begin{macro}[EXP]{\@@_parse_model_wave:w}
-% \begin{macro}[EXP]
-% {\@@_parse_model_wave_auxi:nn, \@@_parse_model_wave_auxii:nn}
-% \begin{macro}[EXP]{\@@_parse_model_wave_rho:n}
-% \begin{macrocode}
-\cs_new:Npn \@@_parse_model_Gray:w #1 , #2 \s_@@_stop
- { { gray } { \fp_eval:n { #1 / 15 } } }
-\cs_new:Npn \@@_parse_model_hsb:w #1 , #2 , #3 , #4 \s_@@_stop
- { \@@_parse_model_hsb:nnn {#1} {#2} {#3} }
-\cs_new:Npn \@@_parse_model_Hsb:w #1 , #2 , #3 , #4 \s_@@_stop
- {
- \exp_args:Ne \@@_parse_model_hsb:nnn { \fp_eval:n { #1 / 360 } }
- {#2} {#3}
- }
-% \end{macrocode}
-% The conversion here is non-trivial but is described at length
-% in the \pkg{xcolor} manual. For ease, we calculate the integer
-% and fractional parts of the hue first, then use them to work out the
-% possible values for $r$, $g$ and $b$ before putting them in the correct
-% places.
-% \begin{macrocode}
-\cs_new:Npn \@@_parse_model_hsb:nnn #1#2#3
- {
- { rgb }
- {
- \exp_args:Ne \@@_parse_model_hsb_aux:nnn
- { \fp_eval:n { 6 * #1 } } {#2} {#3}
- }
- }
-\cs_new:Npn \@@_parse_model_hsb_aux:nnn #1#2#3
- {
- \exp_args:Nee \@@_parse_model_hsb_aux:nnnn
- { \fp_eval:n { floor(#1) } } { \fp_eval:n { #1 - floor(#1) } }
- {#2} {#3}
- }
-\cs_new:Npn \@@_parse_model_hsb_aux:nnnn #1#2#3#4
- {
- \use:e
- {
- \exp_not:N \@@_parse_model_hsb_aux:nnnnn
- { \@@_parse_number:n {#4} }
- { \fp_eval:n { round(#4 * (1 - #3) ,5) } }
- { \fp_eval:n { round(#4 * ( 1 - #3 * #2 ) ,5) } }
- { \fp_eval:n { round(#4 * ( 1 - #3 * (1 - #2) ) ,5) } }
- {#1}
- }
- }
-\cs_new:Npn \@@_parse_model_hsb_aux:nnnnn #1#2#3#4#5
- { \use:c { @@_parse_model_hsb_ #5 :nnnn } {#1} {#2} {#3} {#4} }
-\cs_new:cpn { @@_parse_model_hsb_0:nnnn } #1#2#3#4 { #1 ~ #4 ~ #2 }
-\cs_new:cpn { @@_parse_model_hsb_1:nnnn } #1#2#3#4 { #3 ~ #1 ~ #2 }
-\cs_new:cpn { @@_parse_model_hsb_2:nnnn } #1#2#3#4 { #2 ~ #1 ~ #4 }
-\cs_new:cpn { @@_parse_model_hsb_3:nnnn } #1#2#3#4 { #2 ~ #3 ~ #1 }
-\cs_new:cpn { @@_parse_model_hsb_4:nnnn } #1#2#3#4 { #4 ~ #2 ~ #1 }
-\cs_new:cpn { @@_parse_model_hsb_5:nnnn } #1#2#3#4 { #1 ~ #2 ~ #3 }
-\cs_new:cpn { @@_parse_model_hsb_6:nnnn } #1#2#3#4 { #1 ~ #2 ~ #2 }
-\cs_new:Npn \@@_parse_model_HSB:w #1 , #2 , #3 , #4 \s_@@_stop
- {
- \exp_args:Neee \@@_parse_model_hsb:nnn
- { \fp_eval:n {#1 / 240} }
- { \fp_eval:n {#2 / 240} }
- { \fp_eval:n {#3 / 240} }
- }
-\cs_new:Npn \@@_parse_model_HTML:w #1 , #2 \s_@@_stop
- { \@@_parse_model_HTML_aux:w #1 0 0 0 0 0 0 \s_@@_stop }
-\cs_new:Npn \@@_parse_model_HTML_aux:w #1#2#3#4#5#6#7 \s_@@_stop
- {
- { rgb }
- {
- \fp_eval:n { round(\int_from_hex:n {#1#2} / 255,5) } ~
- \fp_eval:n { round(\int_from_hex:n {#3#4} / 255,5) } ~
- \fp_eval:n { round(\int_from_hex:n {#5#6} / 255,5) }
- }
- }
-\cs_new:Npn \@@_parse_model_RGB:w #1 , #2 , #3 , #4 \s_@@_stop
- {
- { rgb }
- {
- \fp_eval:n { round(#1 / 255,5) } ~
- \fp_eval:n { round(#2 / 255,5) } ~
- \fp_eval:n { round(#3 / 255,5) }
- }
- }
-% \end{macrocode}
-% Following the description in the \pkg{xcolor} manual. As we always use |rgb|,
-% there is no need to find the sixth, we just pas the information straight
-% to the |hsb| auxiliary defined earlier.
-% \begin{macrocode}
-\cs_new:Npn \@@_parse_model_wave:w #1 , #2 \s_@@_stop
- {
- { rgb }
- {
- \fp_compare:nNnTF {#1} < { 420 }
- { \@@_parse_model_wave_auxi:nn {#1} { 0.3 + 0.7 * (#1 - 380) / 40 }
- }
- {
- \fp_compare:nNnTF {#1} > { 700 }
- { \@@_parse_model_wave_auxi:nn {#1} { 0.3 + 0.7 * (#1 - 780) / -80 } }
- { \@@_parse_model_wave_auxi:nn {#1} { 1 } }
- }
- }
- }
-\cs_new:Npn \@@_parse_model_wave_auxi:nn #1#2
- {
- \fp_compare:nNnTF {#1} < { 440 }
- {
- \@@_parse_model_wave_auxii:nn
- { 4 + \@@_parse_model_wave_rho:n { (#1 - 440) / -60 } }
- {#2}
- }
- {
- \fp_compare:nNnTF {#1} < { 490 }
- {
- \@@_parse_model_wave_auxii:nn
- { 4 - \@@_parse_model_wave_rho:n { (#1 - 440) / 50 } }
- {#2}
- }
- {
- \fp_compare:nNnTF {#1} < { 510 }
- {
- \@@_parse_model_wave_auxii:nn
- { 2 + \@@_parse_model_wave_rho:n { (#1 - 510) / -20 } }
- {#2}
- }
- {
- \fp_compare:nNnTF {#1} < { 580 }
- {
- \@@_parse_model_wave_auxii:nn
- { 2 - \@@_parse_model_wave_rho:n { (#1 - 510) / 70 } }
- {#2}
- }
- {
- \fp_compare:nNnTF {#1} < { 645 }
- {
- \@@_parse_model_wave_auxii:nn
- { \@@_parse_model_wave_rho:n { (#1 - 645) / -65 } }
- {#2}
- }
- { \@@_parse_model_wave_auxii:nn { 0 } {#2} }
- }
- }
- }
- }
- }
-\cs_new:Npn \@@_parse_model_wave_auxii:nn #1#2
- {
- \exp_args:Neee \@@_parse_model_hsb_aux:nnn
- { \fp_eval:n {#1} }
- { 1 }
- { \@@_parse_model_wave_rho:n {#2} }
- }
-\cs_new:Npn \@@_parse_model_wave_rho:n #1
- { \fp_eval:n { min(1, max(0,#1) ) } }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Selecting colors (and color models)}
-%
-% \begin{variable}{\l_color_fixed_model_tl}
-% For selecting a single fixed model.
-% \begin{macrocode}
-\tl_new:N \l_color_fixed_model_tl
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\@@_check_model:N}
-% \begin{macro}{\@@_check_model:nn}
-% Check that the model in use is the one required.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_check_model:N #1
- {
- \tl_if_empty:NF \l_color_fixed_model_tl
- {
- \exp_after:wN \@@_check_model:nn #1
- \tl_if_eq:NNF \l_@@_model_tl \l_color_fixed_model_tl
- {
- \@@_convert:VVN \l_@@_model_tl \l_color_fixed_model_tl
- \l_@@_value_tl
- }
- \tl_set:Nx #1
- { { \l_color_fixed_model_tl } { \l_@@_value_tl } }
- }
- }
-\cs_new_protected:Npn \@@_check_model:nn #1#2
- {
- \tl_set:Nn \l_@@_model_tl {#1}
- \tl_set:Nn \l_@@_value_tl {#2}
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@@_select:}
-% A backend-neutral location for \enquote{last minute} manipulations before
-% handing off to the backend code. We set the special |.| syntax here: this
-% will therefore always be available. The finalisation is separate from the
-% main function so it can also be applied to \emph{e.g.}~page color.
-% \begin{macrocode}
-\cs_new_protected:Npx \@@_select:
- {
- \tl_set:Nx \exp_not:c { l_@@_named_ . _tl }
- { \exp_not:N \@@_model:N \exp_not:N \l_@@_current_tl }
- \prop_clear:N \exp_not:c { l_@@_named_ . _prop }
- \prop_put:NVx \exp_not:c { l_@@_named_ . _prop }
- \exp_not:c { l_@@_named_ . _tl }
- { \exp_not:N \@@_values:N \exp_not:N \l_@@_current_tl }
- \@@_select:N \exp_not:N \l_@@_current_tl
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\color_select:n}
-% \begin{macro}{\color_select:nn}
-% \begin{macro}{\@@_select_main:Nw, \@@_select_loop:Nw}
-% \begin{macro}{\@@_select:nnN}
-% \begin{macro}{\@@_select_swap:Nnn}
-% Parse the input expressions then get the backend to actually activate
-% them. The main complexity here is the need to check through multiple models.
-% That is done \enquote{locally} here as the approach is subtly different to
-% when different models are being stored.
-% \begin{macrocode}
-\cs_new_protected:Npn \color_select:n #1
- {
- \@@_parse:nN {#1} \l_@@_current_tl
- \@@_select:
- }
-\cs_new_protected:Npn \color_select:nn #1#2
- {
- \@@_select_main:Nw \l_@@_current_tl
- #1 / / \s_@@_mark #2 / / \s_@@_stop
- \@@_select:
- }
-% \end{macrocode}
-% If the first color model is the fixed one, or if there is no fixed
-% model, we don't need most of the data: just set up and apply the backend
-% function.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_select_main:Nw
- #1 #2 / #3 / #4 \s_@@_mark #5 / #6 / #7 \s_@@_stop
- {
- \@@_select:nnN {#2} {#5} #1
- \bool_lazy_or:nnF
- { \tl_if_empty_p:N \l_color_fixed_model_tl }
- { \str_if_eq_p:nV {#2} \l_color_fixed_model_tl }
- { \@@_select_loop:Nw #1 #3 / #4 \s_@@_mark #6 / #7 \s_@@_stop }
- }
-% \end{macrocode}
-% If a fixed model applies, we need to check each possible value in order.
-% If there is no hit at all, fall back on the generic formula-based
-% interchange.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_select_loop:Nw
- #1 #2 / #3 \s_@@_mark #4 / #5 \s_@@_stop
- {
- \str_if_eq:nVTF {#2} \l_color_fixed_model_tl
- { \@@_select:nnN {#2} {#4} #1 }
- {
- \tl_if_blank:nTF {#2}
- { \exp_after:wN \@@_select_swap:Nnn \exp_after:wN #1 #1 }
- { \@@_select_loop:Nw #1 #3 \s_@@_mark #5 \s_@@_stop }
- }
- }
-\cs_new_protected:Npn \@@_select:nnN #1#2#3
- {
- \cs_if_exist:cTF { @@_parse_model_ #1 :w }
- {
- \tl_set:Nx #3
- { \use:c { @@_parse_model_ #1 :w } #2 , 0 , 0 , 0 , 0 \s_@@_stop }
- }
- { \__kernel_msg_error:nnn { color } { unknown-model } {#1} }
- }
-\cs_new_protected:Npn \@@_select_swap:Nnn #1#2#3
- {
- \@@_convert:nVnN {#2} \l_color_fixed_model_tl {#3} \l_@@_value_tl
- \tl_set:Nx #1
- { { \l_color_fixed_model_tl } { \l_@@_value_tl } }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Fill and stroke color}
-%
-% \begin{macro}{\color_fill:n, \color_stroke:n}
-% \begin{macro}{\color_fill:nn, \color_stroke:nn}
-% \begin{macro}{\@@_draw:nnn}
-% \begin{macrocode}
-\cs_new_protected:Npn \color_fill:n #1
- {
- \@@_parse:nN {#1} \l_@@_current_tl
- \exp_after:wN \@@_draw:nnn \l_@@_current_tl { fill }
- }
-\cs_new_protected:Npn \color_stroke:n #1
- {
- \@@_parse:nN {#1} \l_@@_current_tl
- \exp_after:wN \@@_draw:nnn \l_@@_current_tl { stroke }
- }
-\cs_new_protected:Npn \color_fill:nn #1#2
- {
- \@@_select_main:Nw \l_@@_current_tl
- #1 / / \s_@@_mark #2 / / \s_@@_stop
- \exp_after:wN \@@_draw:nnn \l_@@_current_tl { fill }
- }
-\cs_new_protected:Npn \color_stroke:nn #1#2
- {
- \@@_select_main:Nw \l_@@_current_tl
- #1 / / \s_@@_mark #2 / / \s_@@_stop
- \exp_after:wN \@@_draw:nnn \l_@@_current_tl { stroke }
- }
-\cs_new_protected:Npn \@@_draw:nnn #1#2#3
- { \use:c { @@_backend_ #3 _ #1 :n } {#2} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Defining named colors}
-%
-% \begin{variable}{\l_@@_named_tl}
-% Space to store the detail of the named color.
-% \begin{macrocode}
-\tl_new:N \l_@@_named_tl
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\color_set:nn}
-% \begin{macro}{\@@_set:nnn}
-% \begin{macro}{\@@_set:nn}
-% \begin{macro}{\@@_set:nnw}
-% \begin{macro}{\color_set:nnn}
-% \begin{macro}{\@@_set_colon:nnw}
-% \begin{macro}{\@@_set_loop:nw}
-% \begin{macro}{\color_set_eq:nn}
-% Defining named colors means working through the model list and saving
-% both the \enquote{main} color and any equivalents in other models. Even
-% if there is only one model, we store a |prop| as well as a |tl|, as there
-% could be grouping weirdness, etc. When setting using an expression,
-% we need to avoid any fixed model issues, which is done without a group as
-% in \pkg{l3keys}.
-% \begin{macrocode}
-\cs_new_protected:Npn \color_set:nn #1#2
- {
- \exp_args:NV \@@_set:nnn
- \l_color_fixed_model_tl {#1} {#2}
- }
-\cs_new_protected:Npn \@@_set:nnn #1#2#3
- {
- \tl_clear:N \l_color_fixed_model_tl
- \@@_set:nn {#2} {#3}
- \tl_set:Nn \l_color_fixed_model_tl {#1}
- }
-\cs_new_protected:Npn \@@_set:nn #1#2
- {
- \str_if_eq:nnF {#1} { . }
- {
- \@@_parse:nN {#2} \l_@@_named_tl
- \tl_clear_new:c { l_@@_named_ #1 _tl }
- \tl_set:cx { l_@@_named_ #1 _tl }
- { \@@_model:N \l_@@_named_tl }
- \prop_clear_new:c { l_@@_named_ #1 _prop }
- \prop_put:cvx { l_@@_named_ #1 _prop } { l_@@_named_ #1 _tl }
- { \@@_values:N \l_@@_named_tl }
- \@@_set:nnw {#1} {#2} #2 ! \s_@@_stop
- }
- }
-% \end{macrocode}
-% When setting an expression-based color, there could be multiple model
-% data available for one or more of the input colors. Where that is true for
-% the \emph{first} named color in an expression, we re-parse the expression
-% when they are also parameter-based: only |cmyk|, |gray| and |rgb| make
-% any sense here. There is a bit of a performance hit but this should be
-% rare and taking place during set-up.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_set:nnw #1#2#3 ! #4 \s_@@_stop
- {
- \clist_map_inline:nn { cmyk , gray , rgb }
- {
- \prop_get:cnNT { l_@@_named_ #3 _prop } {##1} \l_@@_internal_tl
- {
- \prop_if_in:cnF { l_@@_named_ #1 _prop } {##1}
- {
- \group_begin:
- \tl_set:cn { l_@@_named_ #3 _tl } {##1}
- \@@_parse:nN {#2} \l_@@_internal_tl
- \exp_args:NNNV \group_end:
- \tl_set:Nn \l_@@_internal_tl \l_@@_internal_tl
- \prop_put:cxx { l_@@_named_ #1 _prop }
- { \@@_model:N \l_@@_internal_tl }
- { \@@_values:N \l_@@_internal_tl }
- }
- }
- }
- }
-\cs_new_protected:Npx \color_set:nnn #1#2#3
- {
- \exp_not:N \str_if_eq:nnF {#1} { . }
- {
- \tl_clear_new:c { l_@@_named_ #1 _tl }
- \prop_clear_new:c { l_@@_named_ #1 _prop }
- \exp_not:N \@@_set_colon:nnw {#1} {#3}
- #2 \c_colon_str \c_colon_str \exp_not:N \s_@@_stop
- }
- }
-\use:x
- {
- \cs_new_protected:Npn \exp_not:N \@@_set_colon:nnw
- ##1##2 ##3 \c_colon_str ##4 \c_colon_str
- ##5 \exp_not:N \s_@@_stop
- }
- {
- \tl_if_blank:nTF {#4}
- { \@@_set_loop:nw {#1} #3 }
- { \@@_set_loop:nw {#1} #4 }
- / / \s_@@_mark #2 / / \s_@@_stop
- }
-\cs_new_protected:Npn \@@_set_loop:nw
- #1#2 / #3 \s_@@_mark #4 / #5 \s_@@_stop
- {
- \tl_if_blank:nF {#2}
- {
- \@@_select:nnN {#2} {#4} \l_@@_named_tl
- \tl_set:Nx \l_@@_internal_tl { \@@_model:N \l_@@_named_tl }
- \tl_if_empty:cT { l_@@_named_ #1 _tl }
- { \tl_set_eq:cN { l_@@_named_ #1 _tl } \l_@@_internal_tl }
- \prop_put:cVx { l_@@_named_ #1 _prop } \l_@@_internal_tl
- { \@@_values:N \l_@@_named_tl }
- \@@_set_loop:nw {#1} #3 \s_@@_mark #5 \s_@@_stop
- }
- }
-\cs_new_protected:Npn \color_set_eq:nn #1#2
- {
- \@@_if_defined:nTF {#2}
- {
- \tl_clear_new:c { l_@@_named_ #1 _tl }
- \prop_clear_new:c { l_@@_named_ #1 _prop }
- \str_if_eq:nnTF {#2} { . }
- {
- \tl_set:cx { l_@@_named_ #1 _tl }
- { \@@_model:N \l_@@_current_tl }
- \prop_put:cvx { l_@@_named_ #1 _prop } { l_@@_named_ #1 _tl }
- { \@@_values:N \l_@@_current_tl }
- }
- {
- \tl_set_eq:cc { l_@@_named_ #1 _tl } { l_@@_named_ #2 _tl }
- \prop_set_eq:cc { l_@@_named_ #1 _prop } { l_@@_named_ #2 _prop }
- }
- }
- {
- \__kernel_msg_error:nnn { color } { unknown-color } {#2}
- }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% A small set of colors are always defined.
-% \begin{macrocode}
-\color_set:nnn { black } { gray } { 0 }
-\color_set:nnn { white } { gray } { 1 }
-\color_set:nnn { cyan } { cmyk } { 1 , 0 , 0 , 0 }
-\color_set:nnn { magenta } { cmyk } { 0 , 1 , 0 , 0 }
-\color_set:nnn { yellow } { cmyk } { 0 , 0 , 1 , 0 }
-\color_set:nnn { red } { rgb } { 1 , 0 , 0 }
-\color_set:nnn { green } { rgb } { 0 , 1 , 0 }
-\color_set:nnn { blue } { rgb } { 0 , 0 , 1 }
-% \end{macrocode}
-%
-% \begin{variable}{\l_@@_named_._prop, \l_@@_named_._tl}
-% A special named color: this is always defined though not fixed in
-% definition.
-% \begin{macrocode}
-\prop_new:c { l_@@_named_._prop }
-\tl_new:c { l_@@_named_._tl }
-\tl_set:cx { l_@@_named_._tl } { \@@_model:N \l_@@_current_tl }
-% \end{macrocode}
-% \end{variable}
-%
-% \subsection{Exporting colors}
-%
-% \begin{macro}{\color_export:nnN}
-% \begin{macro}{\color_export:nnnN}
-% \begin{macro}{\@@_export:nN}
-% \begin{macro}{\@@_export:nnnN}
-% \begin{macrocode}
-\cs_new_protected:Npn \color_export:nnN #1#2#3
- {
- \group_begin:
- \tl_if_exist:cT { c_@@_export_ #2 _tl }
- { \tl_set_eq:Nc \l_color_fixed_model_tl { c_@@_export_ #2 _tl } }
- \@@_parse:nN {#1} #3
- \@@_export:nN {#2} #3
- \exp_args:NNNV \group_end:
- \tl_set:Nn #3 #3
- }
-\cs_new_protected:Npn \color_export:nnnN #1#2#3#4
- {
- \@@_select_main:Nw #4
- #1 / / \s_@@_mark #2 / / \s_@@_stop
- \@@_export:nN {#3} #4
- }
-\cs_new_protected:Npn \@@_export:nN #1#2
- { \exp_after:wN \@@_export:nnnN #2 {#1} #2 }
-\cs_new:Npn \@@_export:nnnN #1#2#3#4
- {
- \cs_if_exist_use:cF { @@_export_format_ #3 :nnN }
- {
- \__kernel_msg_error:nnn { color } { unknown-export-format } {#3}
- \use_none:nnn
- }
- {#1} {#2} #4
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@@_export_format_backend:nnN}
-% Simple.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_export_format_backend:nnN #1#2#3
- { \tl_set:Nn #3 { {#1} {#2} } }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_export:nnnNN}
-% A generic auxiliary for cases where only one model is appropriate.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_export:nnnNN #1#2#3#4#5
- {
- \str_if_eq:nnTF {#2} {#1}
- { #5 #4 #3 \s_@@_stop }
- {
- \@@_convert:nnnN {#2} {#1} {#3} #4
- \exp_after:wN #5 \exp_after:wN #4
- #4 \s_@@_stop
- }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{variable}
-% {
-% \c_@@_export_HTML_tl ,
-% \c_@@_export_space-sep-cmyk_tl ,
-% \c_@@_export_space-sep-rgb_tl
-% }
-% \begin{macrocode}
-\tl_const:Nn \c_@@_export_HTML_tl { rgb }
-\tl_const:cn { c_@@_export_space-sep-cmyk_tl } { cmyk }
-\tl_const:cn { c_@@_export_space-sep-rgb_tl } { rgb }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\@@_export_format_space-sep-cmyk:nnN}
-% \begin{macro}{\@@_export_space-sep-cmyk:Nw}
-% \begin{macrocode}
-\cs_new_protected:cpx { @@_export_format_space-sep-cmyk:nnN } #1#2#3
- {
- \exp_not:N \@@_export:nnnNN { cmyk } {#1} {#2} #3
- \exp_not:c { @@_export_space-sep-cmyk:Nw }
- }
-\cs_new_protected:cpn { @@_export_space-sep-cmyk:Nw } #1#2 \s_@@_stop
- { \tl_set:Nx #1 {#2} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}
-% {
-% \@@_export_format_HTML:nnN ,
-% \@@_export_format_space-sep-rgb:nnN
-% }
-% \begin{macro}
-% {
-% \@@_export_HTML:Nw ,
-% \@@_export_space-sep-rgb:Nw
-% }
-% \begin{macro}[EXP]{\@@_export_HTML:n}
-% \textsc{html} values must be given in |rgb|: we force conversion if
-% required, then do some simple maths.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_export_format_HTML:nnN #1#2#3
- { \@@_export:nnnNN { rgb } {#1} {#2}#3 \@@_export_HTML:Nw }
-\cs_new_protected:cpx { @@_export_format_space-sep-rgb:nnN } #1#2#3
- {
- \exp_not:N \@@_export:nnnNN { rgb } {#1} {#2} #3
- \exp_not:c { @@_export_space-sep-rgb:Nw }
- }
-\cs_new_protected:Npn \@@_export_HTML:Nw #1#2 ~ #3 ~ #4 \s_@@_stop
- {
- \tl_set:Nx #1
- {
- \@@_export_HTML:n {#2}
- \@@_export_HTML:n {#3}
- \@@_export_HTML:n {#4}
- }
- }
-\cs_new:Npn \@@_export_HTML:n #1
- {
- \fp_compare:nNnTF {#1} = { 0 }
- { 00 }
- { \int_to_Hex:n { \fp_to_int:n { #1 * 255 } } }
- }
-\cs_new_protected:cpn { @@_export_space-sep-rgb:Nw } #1#2 \s_@@_stop
- { \tl_set:Nx #1 {#2} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Additional color models}
-%
-% \begin{variable}{\l_@@_internal_prop}
-% \begin{macrocode}
-\prop_new:N \l_@@_internal_prop
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_model_int}
-% A tracker for the total number of new models.
-% \begin{macrocode}
-\int_new:N \g_@@_model_int
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}
-% {\c_@@_fallback_cmyk_tl, \c_@@_fallback_gray_tl, \c_@@_fallback_rgb_tl}
-% Conversion from Separation or DeviceN spaces may not be possible; have
-% a fallback to black.
-% \begin{macrocode}
-\tl_const:Nn \c_@@_fallback_cmyk_tl { 0 ~ 0 ~ 0 ~ 1 }
-\tl_const:Nn \c_@@_fallback_gray_tl { 1 }
-\tl_const:Nn \c_@@_fallback_rgb_tl { 1 ~ 1 ~ 1 }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_colorants_prop}
-% Mapping from names to colorants.
-% \begin{macrocode}
-\prop_new:N \g_@@_colorants_prop
-\prop_gput:Nnn \g_@@_colorants_prop { black } { Black }
-\prop_gput:Nnn \g_@@_colorants_prop { blue } { Blue }
-\prop_gput:Nnn \g_@@_colorants_prop { cyan } { Cyan }
-\prop_gput:Nnn \g_@@_colorants_prop { green } { Green }
-\prop_gput:Nnn \g_@@_colorants_prop { magenta } { Magenta }
-\prop_gput:Nnn \g_@@_colorants_prop { none } { None }
-\prop_gput:Nnn \g_@@_colorants_prop { red } { Red }
-\prop_gput:Nnn \g_@@_colorants_prop { yellow } { Yellow }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}
-% {
-% \c_@@_model_whitepoint_CIELAB_a_tl ,
-% \c_@@_model_whitepoint_CIELAB_b_tl ,
-% \c_@@_model_whitepoint_CIELAB_e_tl ,
-% \c_@@_model_whitepoint_CIELAB_d50_tl ,
-% \c_@@_model_whitepoint_CIELAB_d55_tl ,
-% \c_@@_model_whitepoint_CIELAB_d65_tl ,
-% \c_@@_model_whitepoint_CIELAB_d75_tl
-% }
-% Whitepoint data for the CIELAB profiles.
-% \begin{macrocode}
-\tl_const:Nn \c_@@_model_whitepoint_CIELAB_a_tl { 1.0985 ~ 1 ~ 0.3558 }
-\tl_const:Nn \c_@@_model_whitepoint_CIELAB_b_tl { 0.9807 ~ 1 ~ 1.1822 }
-\tl_const:Nn \c_@@_model_whitepoint_CIELAB_e_tl { 1 ~ 1 ~ 1 }
-\tl_const:cn { c_@@_model_whitepoint_CIELAB_d50_tl } { 0.9642 ~ 1 ~ 0.8251 }
-\tl_const:cn { c_@@_model_whitepoint_CIELAB_d55_tl } { 0.9568 ~ 1 ~ 0.9214 }
-\tl_const:cn { c_@@_model_whitepoint_CIELAB_d65_tl } { 0.9504 ~ 1 ~ 1.0888 }
-\tl_const:cn { c_@@_model_whitepoint_CIELAB_d75_tl } { 0.9497 ~ 1 ~ 1.2261 }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\c_@@_model_range_CIELAB_tl}
-% The range for CIELAB color spaces.
-% \begin{macrocode}
-\tl_const:Nn \c_@@_model_range_CIELAB_tl { 0 ~ 100 ~ -128 ~ 127 ~ -128 ~ 127 }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_alternative_model_prop}
-% For tracking the alternative model set up for separations, etc.
-% \begin{macrocode}
-\prop_new:N \g_@@_alternative_model_prop
-\clist_map_inline:nn { cyan , magenta , yellow , black }
- { \prop_gput:Nnn \g_@@_alternative_model_prop {#1} { cmyk } }
-\clist_map_inline:nn { red , green , blue }
- { \prop_gput:Nnn \g_@@_alternative_model_prop {#1} { rgb } }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_alternative_values_prop}
-% Same for the values: a bit more involved.
-% \begin{macrocode}
-\prop_new:N \g_@@_alternative_values_prop
-\prop_gput:Nnn \g_@@_alternative_values_prop { cyan } { 1 , 0 , 0 , 0 }
-\prop_gput:Nnn \g_@@_alternative_values_prop { magenta } { 0 , 1 , 0 , 0 }
-\prop_gput:Nnn \g_@@_alternative_values_prop { yellow } { 0 , 0 , 1 , 0 }
-\prop_gput:Nnn \g_@@_alternative_values_prop { black } { 0 , 0 , 0 , 1 }
-\prop_gput:Nnn \g_@@_alternative_values_prop { red } { 1 , 0 , 0 }
-\prop_gput:Nnn \g_@@_alternative_values_prop { green } { 0 , 1 , 0 }
-\prop_gput:Nnn \g_@@_alternative_values_prop { blue } { 0 , 0 , 1 }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\color_model_new:nnn, \@@_model_new:nnn}
-% Set up a new model: in general this has to be handled by a family-dependent
-% function. To avoid some \enquote{interesting} questions with casing, we
-% fold the case of the family name. The key--value list should always be
-% present, so we convert it up-front to a |prop|, then deal with the detail
-% on a per-family basis.
-% \begin{macrocode}
-\cs_new_protected:Npn \color_model_new:nnn #1#2#3
- {
- \exp_args:Nee \@@_model_new:nnn
- { \tl_to_str:n {#1} }
- { \str_foldcase:n {#2} } {#3}
- }
-\cs_new_protected:Npn \@@_model_new:nnn #1#2#3
- {
- \cs_if_exist:cTF { @@_parse_model_ #1 :w }
- {
- \__kernel_msg_error:nnn { color } { model-already-defined } {#1}
- }
- {
- \cs_if_exist:cTF { @@_model_ #2 :n }
- {
- \prop_set_from_keyval:Nn \l_@@_internal_prop {#3}
- \use:c { @@_model_ #2 :n } {#1}
- }
- {
- \__kernel_msg_error:nnn { color } { unknown-model-type } {#2}
- }
- }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@_model_separation:n}
-% \begin{macro}{\@@_model_separation:nn}
-% \begin{macro}{\@@_model_separation:nnn}
-% \begin{macro}{\@@_model_separation:w}
-% \begin{macro}
-% {
-% \@@_model_separation_cmyk:nnnnnn ,
-% \@@_model_separation_gray:nnnnnn ,
-% \@@_model_separation_rgb:nnnnnn
-% }
-% \begin{macro}{\@@_model_convert:nnn}
-% \begin{macro}{\@@_model_separation_CIELAB:nnnnnn}
-% \begin{macro}{\@@_model_separation_CIELAB:nnnnnnn}
-% Separations must have a \enquote{real} name, which is pretty easy to find.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_separation:n #1
- {
- \prop_get:NnNTF \l_@@_internal_prop { name }
- \l_@@_internal_tl
- {
- \exp_args:NV \@@_model_separation:nn
- \l_@@_internal_tl {#1}
- }
- {
- \__kernel_msg_error:nnn { color }
- { separation-requires-name } {#1}
- }
- }
-% \end{macrocode}
-% We have two keys to find at this stage: the alternative space model
-% and linked values.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_separation:nn #1#2
- {
- \prop_get:NnNTF \l_@@_internal_prop { alternative-model }
- \l_@@_internal_tl
- {
- \exp_args:NV \@@_model_separation:nnn
- \l_@@_internal_tl {#2} {#1}
- }
- {
- \__kernel_msg_error:nnn { color }
- { separation-alternative-model } {#2}
- }
- }
-\cs_new_protected:Npn \@@_model_separation:nnn #1#2#3
- {
- \cs_if_exist:cTF { @@_model_separation_ #1 :nnnnnn }
- {
- \prop_get:NnNTF \l_@@_internal_prop { alternative-values }
- \l_@@_internal_tl
- {
- \exp_after:wN \@@_model_separation:w \l_@@_internal_tl
- , 0 , 0 , 0 , 0 \s_@@_stop {#2} {#3} {#1}
- }
- {
- \__kernel_msg_error:nnn { color }
- { separation-alternative-values } {#2}
- }
- }
- {
- \__kernel_msg_error:nnn { color }
- { unknown-alternative-model } {#1}
- }
- }
-% \end{macrocode}
-% As each alternative space leads to a different requirement for conversion,
-% and as there are only a small number of choices, we manually split the data
-% and then set up. Notice that mixing tints is really just the same
-% as mixing \texttt{gray}. The \texttt{white} color is special, as it allows
-% tints to be adjusted without an additional color space. To make sure the
-% data is set for that at all group levels, we need to work on a per-level
-% basis. Within the output, only the set-up needs the \enquote{real} name
-% of the colorspace: we use a simple tracking number for general usage
-% as this is a clear namespace without issues of escaping chars.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_separation:w
- #1 , #2 , #3 , #4 , #5 \s_@@_stop #6#7#8
- {
- \int_gincr:N \g_@@_model_int
- \tl_const:cn { c_@@_fallback_ #6 _tl } { 1 }
- \cs_new_eq:cN { @@_parse_mix_ #6 :nw } \@@_parse_mix_gray:nw
- \cs_new:cpn { @@_parse_model_ #6 :w } ##1 , ##2 \s_@@_stop
- { {#6} { \@@_parse_number:n {##1} } }
- \clist_map_inline:nn { fill , stroke , select }
- {
- \cs_new_protected:cpx { @@_backend_ ##1 _ #6 :n } ####1
- {
- \exp_not:c { @@_backend_ ##1 _ separation:nn }
- { color \int_use:N \g_@@_model_int } {####1}
- }
- }
- \use:c { @@_model_separation_ #8 :nnnnnn }
- {#6} {#7} {#1} {#2} {#3} {#4}
- \prop_gput:Nnn \g_@@_alternative_model_prop {#6} {#8}
- \prop_gput:Nnx \g_@@_colorants_prop {#6}
- { \str_convert_pdfname:n {#7} }
- \cs_new_protected:cpx { @@_model_ #6 _white: }
- {
- \prop_put:Nnn \exp_not:N \l_@@_named_white_prop {#6} { 0 }
- \exp_not:N \int_compare:nNnF { \tex_currentgrouplevel:D } = 0
- { \group_insert_after:N \exp_not:c { @@_model_ #6 _ white: } }
- }
- \use:c { @@_model_ #6 _white: }
- }
-\cs_new_protected:Npn \@@_model_separation_cmyk:nnnnnn #1#2#3#4#5#6
- {
- \cs_new:cpn { @@_convert_ #1 _cmyk:w } ##1 ~ ##2 \s_@@_stop
- {
- \fp_eval:n {##1 * #3} ~
- \fp_eval:n {##1 * #4} ~
- \fp_eval:n {##1 * #5} ~
- \fp_eval:n {##1 * #6}
- }
- \@@_model_convert:nnn {#1} { cmyk } { rgb }
- \@@_model_convert:nnn {#1} { cmyk } { gray }
- \prop_gput:Nnn \g_@@_alternative_values_prop {#1} { #3 , #4 , #5 , #6 }
- \@@_backend_separation_init:nnnnn {#2} { /DeviceCMYK } { }
- { 0 ~ 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 ~ #6 }
- }
-\cs_new_protected:Npn \@@_model_separation_rgb:nnnnnn #1#2#3#4#5#6
- {
- \cs_new:cpn { @@_convert_ #1 _rgb:w } ##1 ~ ##2 \s_@@_stop
- {
- \fp_eval:n {##1 * #3} ~
- \fp_eval:n {##1 * #4} ~
- \fp_eval:n {##1 * #5}
- }
- \@@_model_convert:nnn {#1} { rgb } { cmyk }
- \@@_model_convert:nnn {#1} { rgb } { gray }
- \prop_gput:Nnn \g_@@_alternative_values_prop {#1} { #3 , #4 , #5 }
- \@@_backend_separation_init:nnnnn {#2} { /DeviceRGB } { }
- { 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 }
- }
-\cs_new_protected:Npn \@@_model_separation_gray:nnnnnn #1#2#3#4#5#6
- {
- \cs_new:cpn { @@_convert_ #1 _cmyk:w } ##1 ~ ##2 \s_@@_stop
- {
- \fp_eval:n {##1 * #3} ~
- \fp_eval:n {##1 * #3} ~
- \fp_eval:n {##1 * #3} ~
- \fp_eval:n {##1 * #3}
- }
- \cs_new:cpn { @@_convert_ #1 _gray:w } ##1 ~ ##2 \s_@@_stop
- { \fp_eval:n {##1 * #3} }
- \cs_new:cpn { @@_convert_ #1 _rgb:w } ##1 ~ ##2 \s_@@_stop
- {
- \fp_eval:n {##1 * #3} ~
- \fp_eval:n {##1 * #3} ~
- \fp_eval:n {##1 * #3}
- }
- \prop_gput:Nnn \g_@@_alternative_values_prop {#1} {#3}
- \@@_backend_separation_init:nnnnn {#2} { /DeviceGray } { } { 0 } {#3}
- }
-% \end{macrocode}
-% Generic model conversion \emph{via} an alternative intermediate.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_convert:nnn #1#2#3
- {
- \cs_new:cpx { @@_convert_ #1 _ #3 :w } ##1 ~ ##2 \s_@@_stop
- {
- \exp_not:N \exp_args:NNe \exp_not:N \use:nn
- \exp_not:c { @@_convert_ #2 _ #3 :w }
- { \exp_not:c { @@_convert_ #1 _ #2 :w } ##1 ~ ##2 \s_@@_stop }
- \c_space_tl \exp_not:N \s_@@_stop
- }
- }
-% \end{macrocode}
-% Setting up for CIELAB needs a bit more work: there is the illuminant and
-% the need for an appropriate object.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_separation_CIELAB:nnnnnn #1#2#3#4#5#6
- {
- \prop_get:NnNF \l_@@_internal_prop { illuminant }
- \l_@@_internal_tl
- {
- \__kernel_msg_error:nnn { color }
- { CIELAB-requires-illuminant } {#1}
- \tl_set:Nn \l_@@_internal_tl { d50 }
- }
- \exp_args:NV \@@_model_separation_CIELAB:nnnnnnn
- \l_@@_internal_tl {#1} {#2} {#3} {#4} {#5} {#6}
- }
-% \end{macrocode}
-% If a CIELAB space is being set up, we need the illuminant, then create
-% the appropriate set up. At present, this doesn't include \texttt{BlackPoint}
-% or \texttt{Range} data, but that may be added later. As CIELAB colors
-% cannot be converted to anything else, we fallback to producing black: the
-% user should set up a second model for colors set up this way.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_separation_CIELAB:nnnnnnn #1#2#3#4#5#6#7
- {
- \tl_if_exist:cTF { c_@@_model_whitepoint_CIELAB_ #1 _tl }
- {
- \@@_backend_separation_init_CIELAB:nnn {#1} {#3} { #4 ~ #5 ~ #6 }
- \cs_new:cpn { @@_convert_ #2 _cmyk:w } ##1 ~ ##2 \s_@@_stop
- { 0 ~ 0 ~ 0 ~ 1 }
- \cs_new:cpn { @@_convert_ #2 _rgb:w } ##1 ~ ##2 \s_@@_stop
- { 1 ~ 1 ~ 1 }
- \cs_new:cpn { @@_convert_ #2 _gray:w } ##1 ~ ##2 \s_@@_stop
- { 1 }
- }
- {
- \__kernel_msg_error:nnn { color }
- { unknown-CIELAB-illuminant } {#1}
- }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\@@_model_devicen:n}
-% \begin{macro}{\@@_model_devicen:nn}
-% \begin{macro}{\@@_model_devicen:nnn}
-% \begin{macro}{\@@_model_devicen:nnnn}
-% \begin{macro}
-% {
-% \@@_model_devicen_parse_1:nn ,
-% \@@_model_devicen_parse_2:nn ,
-% \@@_model_devicen_parse_3:nn ,
-% \@@_model_devicen_parse_4:nn ,
-% \@@_model_devicen_parse_generic:nn
-% }
-% \begin{macro}[EXP]{\@@_model_devicen_parse:nw}
-% \begin{macro}[EXP]{\@@_model_devicen_mix:nw}
-% \begin{macro}{\@@_model_devicen_init:nnn}
-% \begin{macro}{\@@_model_devicen_init:nnnn}
-% \begin{macro}{\@@_model_devicen_tranform:w}
-% \begin{macro}
-% {
-% \@@_model_devicen_tranform_1:nnnnn ,
-% \@@_model_devicen_tranform_3:nnnnn ,
-% \@@_model_devicen_tranform_4:nnnnn ,
-% }
-% \begin{macro}{\@@_model_devicen_tranform:nnn}
-% \begin{macro}[EXP]{\@@_model_devicen_colorant:n}
-% \begin{macro}{\@@_model_devicen_convert:nnn}
-% \begin{macro}
-% {
-% \@@_model_devicen_convert_cmyk:n ,
-% \@@_model_devicen_convert_gray:n ,
-% \@@_model_devicen_convert_rgb:n
-% }
-% \begin{macro}{\@@_model_devicen_convert:nnnn}
-% \begin{macro}[EXP]{\@@_model_devicen_convert:n, \@@_model_devicen_convert_aux:n}
-% \begin{macro}[EXP]{\@@_model_devicen_convert:w}
-% \begin{macro}[EXP]{\@@_convert_devicen_cmyk:nnnnw}
-% \begin{macro}[EXP]{\@@_convert_devicen_cmyk:nnnnnnnnn}
-% \begin{macro}[EXP]{\@@_convert_devicen_cmyk_aux:nnnnw}
-% \begin{macro}[EXP]{\@@_convert_devicen_gray:nw}
-% \begin{macro}[EXP]{\@@_convert_devicen_gray:nnn}
-% \begin{macro}[EXP]{\@@_convert_devicen_gray_aux:nw}
-% \begin{macro}[EXP]{\@@_convert_devicen_rgb:nnnw}
-% \begin{macro}[EXP]{\@@_convert_devicen_rgb:nnnnnnn}
-% \begin{macro}[EXP]{\@@_convert_devicen_rgb_aux:nnnw}
-% We require a list of component names here: one might call them colorants,
-% but it's convenient to use \TeX{} names instead so we slightly adjust the
-% terminology.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_devicen:n #1
- {
- \prop_get:NnNTF \l_@@_internal_prop { names }
- \l_@@_internal_tl
- {
- \exp_args:NV \@@_model_devicen:nn
- \l_@@_internal_tl {#1}
- }
- {
- \__kernel_msg_error:nnn { color }
- { DeviceN-requires-names } {#1}
- }
- }
-% \end{macrocode}
-% All valid models will have an alternative listed, either hard-coded for
-% the core device ones, or dynamically added for Separations, etc.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_devicen:nn #1#2
- {
- \tl_clear:N \l_@@_model_tl
- \clist_map_inline:nn {#1}
- {
- \prop_get:NnNTF \g_@@_alternative_model_prop {##1}
- \l_@@_internal_tl
- {
- \tl_if_empty:NTF \l_@@_model_tl
- { \tl_set_eq:NN \l_@@_model_tl \l_@@_internal_tl }
- {
- \str_if_eq:VVF \l_@@_model_tl \l_@@_internal_tl
- {
- \__kernel_msg_error:nnn { color }
- { DeviceN-inconsistent-alternative }
- {#2}
- \clist_map_break:n { \use_none:nnnn }
- }
- }
- }
- {
- \str_if_eq:nnF {##1} { none }
- {
- \__kernel_msg_error:nnn { color }
- { DeviceN-no-alternative }
- {#2}
- }
- }
- }
- \tl_if_empty:NTF \l_@@_model_tl
- {
- \__kernel_msg_error:nnn { color }
- { DeviceN-no-alternative } {#2}
- }
- { \exp_args:NV \@@_model_devicen:nnn \l_@@_model_tl {#1} {#2} }
- }
-% \end{macrocode}
-% We now complete the data we require by first finding out how many
-% colorants there are, then moving on to begin constructing the function
-% required to map to the alternative color space.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_devicen:nnn #1#2#3
- {
- \exp_args:Nx \@@_model_devicen:nnnn
- { \clist_count:n {#2} } {#1} {#2} {#3}
- }
-% \end{macrocode}
-% At this stage, we have checked everything is in place, so we can set up
-% the \TeX{} and backend data structures. As for separations, it's not really
-% possible in general to have a fallback, so we simply provide
-% \enquote{black} for each element.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_devicen:nnnn #1#2#3#4
- {
- \int_gincr:N \g_@@_model_int
- \tl_const:cx { c_@@_fallback_ #4 _tl }
- { \prg_replicate:nn {#1} { 1 ~ } }
- \cs_if_exist_use:cF { @@_model_devicen_parse_ #1 :nn }
- { \@@_model_devicen_parse_generic:nn }
- {#4} {#1}
- \clist_map_inline:nn { fill , stroke , select }
- {
- \cs_new_protected:cpx { @@_backend_ ##1 _ #4 :n } ####1
- {
- \exp_not:c { @@_backend_ ##1 _ devicen:nn }
- { color \int_use:N \g_@@_model_int } {####1}
- }
- }
- \cs_new_protected:cpx { @@_model_ #4 _white: }
- {
- \prop_put:Nnn \exp_not:N \l_@@_named_white_prop {#4}
- { \prg_replicate:nn {#1} { 0 ~ } }
- \exp_not:N \int_compare:nNnF { \tex_currentgrouplevel:D } = 0
- { \group_insert_after:N \exp_not:c { @@_model_ #4 _ white: } }
- }
- \use:c { @@_model_ #4 _white: }
- \@@_model_devicen_init:nnn {#1} {#2} {#3}
- \@@_model_devicen_convert:nnn {#4} {#2} {#3}
- }
-% \end{macrocode}
-% For short lists of DeviceN colors, wee can use hand-tuned parsing. This
-% lines up with other models, where we allow for up to four components. For
-% larger spaces,. rather than limit artificially, we use a somewhat slow
-% approach based on open-ended commas-lists.
-% \begin{macrocode}
-\cs_new_protected:cpn { @@_model_devicen_parse_1:nn } #1#2
- {
- \cs_new:cpn { @@_parse_model_ #1 :w } ##1 , ##2 \s_@@_stop
- { {#1} { \@@_parse_number:n {##1} } }
- \cs_new_eq:cN { @@_parse_mix_ #1 :nw } \@@_parse_mix_gray:nw
- }
-\cs_new_protected:cpn { @@_model_devicen_parse_2:nn } #1#2
- {
- \cs_new:cpn { @@_parse_model_ #1 :w } ##1 , ##2 , ##3 \s_@@_stop
- { {#1} { \@@_parse_number:n {##1} ~ \@@_parse_number:n {##2} } }
- \cs_new:cpn { @@_parse_mix_ #1 :nw }
- ##1##2 ~ ##3 \s_@@_mark ##4 ~ ##5 \s_@@_stop
- {
- \fp_eval:n { ##2 * ##1 + ##4 * ( 1 - ##1 ) } \c_space_tl
- \fp_eval:n { ##3 * ##1 + ##5 * ( 1 - ##1 ) }
- }
- }
-\cs_new_protected:cpn { @@_model_devicen_parse_3:nn } #1#2
- {
- \cs_new:cpn { @@_parse_model_ #1 :w } ##1 , ##2 , ##3 , ##4 \s_@@_stop
- {
- {#1}
- {
- \@@_parse_number:n {##1} ~
- \@@_parse_number:n {##2} ~
- \@@_parse_number:n {##3}
- }
- }
- \cs_new_eq:cN { @@_parse_mix_ #1 :nw } \@@_parse_mix_rgb:nw
- }
-\cs_new_protected:cpn { @@_model_devicen_parse_4:nn } #1#2
- {
- \cs_new:cpn { @@_parse_model_ #1 :w }
- ##1 , ##2 , ##3 , ##4 , ##5 \s_@@_stop
- {
- {#1}
- {
- \@@_parse_number:n {##1} ~
- \@@_parse_number:n {##2} ~
- \@@_parse_number:n {##3} ~
- \@@_parse_number:n {##4}
- }
- }
- \cs_new_eq:cN { @@_parse_mix_ #1 :nw } \@@_parse_mix_cmyk:nw
- }
-\cs_new_protected:Npn \@@_model_devicen_parse_generic:nn #1#2
- {
- \cs_new:cpn { @@_parse_model_ #1 :w } ##1 , ##2 \s_@@_stop
- {
- {#1}
- { \@@_model_devicen_parse:nw {#2} ##1 , ##2 , \q_nil , \s_@@_stop }
- }
- \cs_new:cpx { @@_parse_mix_ #1 :nw }
- ##1 ##2 \s_@@_mark ##3 \s_@@_stop
- {
- \exp_not:N \@@_model_devicen_mix:nw {##1}
- ##2 \c_space_tl \exp_not:N \q_nil \c_space_tl \exp_not:N \s_@@_mark
- ##3 \c_space_tl \exp_not:N \q_nil \c_space_tl \exp_not:N \s_@@_stop
- }
- }
-\cs_new:Npn \@@_model_devicen_parse:nw #1#2 , #3 \s_@@_stop
- {
- \int_compare:nNnT {#1} > 0
- {
- \quark_if_nil:nTF {#2}
- { \prg_replicate:nn {#1} { 0 ~ } }
- {
- \@@_parse_number:n {#2}
- \int_compare:nNnT {#1} > 1 { ~ }
- \exp_args:Nf \@@_model_devicen_parse:nw
- { \int_eval:n { #1 - 1 } } #3 \s_@@_stop
- }
- }
- }
-\cs_new:Npn \@@_model_devicen_mix:nw #1#2 ~ #3 \s_@@_mark #4 ~ #5 \s_@@_stop
- {
- \fp_eval:n { #2 * #1 + #4 * ( 1 - #1 ) }
- \quark_if_nil:oF { \tl_head:w #3 \q_stop }
- {
- \c_space_tl
- \@@_model_devicen_mix:nw {#1} #3 \s_@@_mark #5 \s_@@_stop
- }
- }
-% \end{macrocode}
-% To construct the tint transformation, we have to use PostScript. The
-% aim is to have the final tint for each device colorant as
-% \[
-% 1 - \prod_{n} (1 - X_{n} D_{X_{n}})
-% \]
-% where $X$ is a DeviceN colorant and $D$ is the amount of device colorant
-% that the DeviceN colorant maps to. At the start of the process, the
-% PostScript stack will contain the $X_{n}$ values, whilst we have the
-% $D$ values on a per-DeviceN colorant basis. The more convenient approach
-% for us is therefore to take each DeviceN colorant in turn and find the
-% value $1 - X_{n} D_{X_{n}}$, multiplying as we go, and finalise with the
-% subtraction. That contrasts to \pkg{colorspace}: it splits the process
-% up by process color, which works better when you have a fixed list
-% of colorants. (\pkg{colorspace} only supports up to $4$ DeviceN colors,
-% and only \texttt{cmyk} as the alternative space.) To set this up,
-% we first need to know the number of values in the target color space:
-% this is easily handled as there are a very small range of possibles.
-% Once we have that information, it's relatively easy to build the required
-% PostScript using some generic code.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_devicen_init:nnn #1#2#3
- {
- \exp_args:Ne \@@_model_devicen_init:nnnn
- {
- \str_case:nn {#2}
- {
- { cmyk } { 4 }
- { gray } { 1 }
- { rgb } { 3 }
- }
- }
- {#1} {#2} {#3}
- }
-% \end{macrocode}
-% As we always need to split the alternative values into parts, we use a
-% shared auxiliary and only use a minimal difference between code paths.
-% Construction of the tint transformation is as far as possible done using
-% loops, which means there are some inefficiencies for device colors in
-% the \texttt{DeviceN} space: we roll the stack one-at-a-time even if there
-% is a potential shortcut. However, that way there is nothing to special-case.
-% Once this is sorted, we can write the tint transform object, which will
-% remain as the last object until we sort out the final step: the colorant
-% list.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_devicen_init:nnnn #1#2#3#4
- {
- \tl_set:Nx \l_@@_internal_tl
- { \prg_replicate:nn {#1} { 1.0 ~ } }
- \int_zero:N \l_@@_internal_int
- \clist_map_inline:nn {#4}
- {
- \int_incr:N \l_@@_internal_int
- \prop_get:NnN \g_@@_alternative_values_prop {##1}
- \l_@@_value_tl
- \exp_after:wN \@@_model_devicen_transform:w
- \l_@@_value_tl , 0 , 0 , 0 \s_@@_stop {#1} {#2}
- }
- \tl_put_right:Nx \l_@@_internal_tl
- {
- \prg_replicate:nn {#1}
- { neg ~ 1.0 ~ add ~ #1 ~ -1 ~ roll ~ }
- \int_eval:n { #2 + 4 } ~ 4 ~ roll
- \prg_replicate:nn {#2} { ~ pop }
- }
- \use:x
- {
- \@@_backend_devicen_init:nnn
- {
- \clist_map_function:nN {#4}
- \@@_model_devicen_colorant:n
- }
- {
- \str_case:nn {#3}
- {
- { cmyk } { /DeviceCMYK }
- { gray } { /DeviceGray }
- { rgb } { /DeviceRGB }
- }
- }
- { \exp_not:V \l_@@_internal_tl }
- }
- }
-\cs_new_protected:Npn \@@_model_devicen_transform:w
- #1 , #2 , #3 , #4 , #5 \s_@@_stop #6#7
- {
- \use:c { @@_model_devicen_transform_ #6 :nnnnn }
- {#1} {#2} {#3} {#4} {#7}
- }
-\cs_new_protected:cpn { @@_model_devicen_transform_1:nnnnn } #1#2#3#4#5
- { \@@_model_devicen_transform:nnn {#5} { 1 } {#1} }
-\cs_new_protected:cpn { @@_model_devicen_transform_3:nnnnn } #1#2#3#4#5
- {
- \clist_map_inline { #1 , #2 , #3 }
- { \@@_model_devicen_transform:nnn {#5} { 3 } {##1} }
- }
-\cs_new_protected:cpn { @@_model_devicen_transform_4:nnnnn } #1#2#3#4#5
- {
- \clist_map_inline:nn { #1 , #2 , #3 , #4 }
- { \@@_model_devicen_transform:nnn {#5} { 4 } {##1} }
- }
-\cs_new_protected:Npn \@@_model_devicen_transform:nnn #1#2#3
- {
- \tl_put_right:Nx \l_@@_internal_tl
- {
- \fp_compare:nNnF {#3} = \c_zero_fp
- {
- \int_eval:n { #1 - \l_@@_internal_int + #2 } ~ index ~
- #3 ~ neg ~ mul ~ 1.0 ~ add ~ mul ~
- }
- #2 ~ -1 ~ roll ~
- }
- }
-\cs_new:Npn \@@_model_devicen_colorant:n #1
- {
- / \prop_item:Nn \g_@@_colorants_prop {#1} ~
- }
-% \end{macrocode}
-% Here we need to set up conversion from the DeviceN space to the alternative
-% at the \TeX{} level. This also means supplying methods for inter-converting
-% to other parameter-based spaces. Essentially the approach is exactly the same
-% as the PostScript, just expressed in \TeX{} terms.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_devicen_convert:nnn #1#2#3
- {
- \use:c { @@_model_devicen_convert_ #2 :nn } {#1} {#3}
- }
-\cs_new_protected:Npn \@@_model_devicen_convert_cmyk:nn #1#2
- {
- \@@_model_convert:nnn {#1} { cmyk } { gray }
- \@@_model_convert:nnn {#1} { cmyk } { rgb }
- \@@_model_devicen_convert:nnnn {#1} { cmyk } { 4 } {#2}
- }
-\cs_new_protected:Npn \@@_model_devicen_convert_gray:nn #1#2
- {
- \@@_model_convert:nnn {#1} { gray } { cmyk }
- \@@_model_convert:nnn {#1} { gray } { rgb }
- \@@_model_devicen_convert:nnnn {#1} { gray } { 1 } {#2}
- }
-\cs_new_protected:Npn \@@_model_devicen_convert_rgb:nn #1#2
- {
- \@@_model_convert:nnn {#1} { rgb } { cmyk }
- \@@_model_convert:nnn {#1} { rgb } { gray }
- \@@_model_devicen_convert:nnnn {#1} { rgb } { 3 } {#2}
- }
-\cs_new_protected:Npn \@@_model_devicen_convert:nnnn #1#2#3#4
- {
- \cs_new:cpx { @@_convert_ #1 _ #2 :w } ##1 \s_@@_stop
- {
- \exp_not:c { @@_convert_devicen_ #2 : \prg_replicate:nn {#3} { n } w }
- \prg_replicate:nn {#3} { { 1 } }
- ##1 \exp_not:N \s_@@_mark
- \clist_map_function:nN {#4} \@@_model_devicen_convert:n
- \exp_not:N \s_@@_stop
- }
- }
-\cs_new:Npn \@@_model_devicen_convert:n #1
- {
- {
- \exp_args:Ne \@@_model_devicen_convert_aux:n
- { \prop_item:Nn \g_@@_alternative_values_prop {#1} }
- }
- }
-\cs_new:Npn \@@_model_devicen_convert_aux:n #1
- { \@@_model_devicen_convert_aux:w #1 , , , , \s_@@_stop }
-\cs_new:Npn \@@_model_devicen_convert_aux:w #1 , #2 , #3 , #4 , #5 \s_@@_stop
- {
- {#1}
- \tl_if_blank:nF {#2}
- {
- {#2}
- \tl_if_blank:nF {#3}
- {
- {#3}
- \tl_if_blank:nF {#4} { {#4} }
- }
- }
- }
-\cs_new:Npn \@@_convert_devicen_cmyk:nnnnw
- #1#2#3#4#5 ~ #6 \s_@@_mark #7#8 \s_@@_stop
- {
- \@@_convert_devicen_cmyk:nnnnnnnnn {#5} {#1} {#2} {#3} {#4} #7
- #6 \s_@@_mark #8 \s_@@_stop
- }
-\cs_new:Npn \@@_convert_devicen_cmyk:nnnnnnnnn #1#2#3#4#5#6#7#8#9
- {
- \use:e
- {
- \exp_not:N \@@_convert_devicen_cmyk_aux:nnnnw
- { \fp_eval:n { #2 * (1 - (#1 * #6)) } }
- { \fp_eval:n { #3 * (1 - (#1 * #7)) } }
- { \fp_eval:n { #4 * (1 - (#1 * #8)) } }
- { \fp_eval:n { #5 * (1 - (#1 * #9)) } }
- }
- }
-\cs_new:Npn \@@_convert_devicen_cmyk_aux:nnnnw
- #1#2#3#4 #5 \s_@@_mark #6 \s_@@_stop
- {
- \tl_if_blank:nTF {#5}
- {
- \fp_eval:n { 1 - #1 } ~
- \fp_eval:n { 1 - #2 } ~
- \fp_eval:n { 1 - #3 } ~
- \fp_eval:n { 1 - #4 }
- }
- {
- \@@_convert_devicen_cmyk:nnnnw {#1} {#2} {#3} {#4}
- #5 \s_@@_mark #6 \s_@@_stop
- }
- }
-\cs_new:Npn \@@_convert_devicen_gray:nw
- #1#2 ~ #3 \s_@@_mark #4#5 \s_@@_stop
- {
- \@@_convert_devicen_gray:nnn {#2} {#1} #4
- #3 \s_@@_mark #5 \s_@@_stop
- }
-\cs_new:Npn \@@_convert_devicen_gray:nnn #1#2#3
- {
- \exp_arsgs:Ne \@@_convert_devicen_gray_aux:nw
- { \fp_eval:n { #2 * (1 - (#1 * #3)) } }
- }
-\cs_new:Npn \@@_convert_devicen_gray_aux:nw
- #1 #2 \s_@@_mark #3 \s_@@_stop
- {
- \tl_if_blank:nTF {#2}
- { \fp_eval:n { 1 - #1 } }
- {
- \@@_convert_devicen_gray:nw {#1}
- #2 \s_@@_mark #3 \s_@@_stop
- }
- }
-\cs_new:Npn \@@_convert_devicen_rgb:nnnw
- #1#2#3#4 ~ #5 \s_@@_mark #6#7 \s_@@_stop
- {
- \@@_convert_devicen_cmyk:nnnnnn {#4} {#1} {#2} {#3} #6
- #5 \s_@@_mark #7 \s_@@_stop
- }
-\cs_new:Npn \@@_convert_devicen_rgb:nnnnnnn #1#2#3#4#5#6#7
- {
- \use:e
- {
- \exp_not:N \@@_convert_devicen_rgb_aux:nnnw
- { \fp_eval:n { #2 * (1 - (#1 * #5)) } }
- { \fp_eval:n { #3 * (1 - (#1 * #6)) } }
- { \fp_eval:n { #4 * (1 - (#1 * #7)) } }
- }
- }
-\cs_new:Npn \@@_convert_devicen_rgb_aux:nnnw
- #1#2#3 #4 \s_@@_mark #5 \s_@@_stop
- {
- \tl_if_blank:nTF {#4}
- {
- \fp_eval:n { 1 - #1 } ~
- \fp_eval:n { 1 - #2 } ~
- \fp_eval:n { 1 - #3 }
- }
- {
- \@@_convert_devicen_rgb:nnnw {#1} {#2} {#3}
- #4 \s_@@_mark #5 \s_@@_stop
- }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Diagnostics}
-%
-% \begin{macro}{\color_show:n}
-% \begin{macro}{\@@_show:n}
-% Extract the information about a color and format for the user: the approach
-% is similar to the keys module here.
-% \begin{macrocode}
-\cs_new_protected:Npn \color_show:n #1
- {
- \msg_show:nnxxxx { LaTeX / color } { show }
- {#1}
- {
- \@@_if_defined:nT {#1}
- {
- \exp_args:Nv \@@_show:n { l_@@_named_ #1 _tl }
- \prop_map_function:cN
- { l_@@_named_ #1 _prop }
- \msg_show_item_unbraced:nn
- }
- }
- { }
- { }
- }
-\cs_new:Npn \@@_show:n #1
- {
- \msg_show_item_unbraced:nn { model } {#1}
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Messages}
-%
-% \begin{macrocode}
-\__kernel_msg_new:nnnn { color } { CIELAB-requires-illuminant }
- { CIELAB~color~space~'#1'~require~an~illuminant. }
- {
- LaTeX~has~been~asked~to~create~a~separation~color~space~using~
- CIELAB~specifications,~but~no~\\ \\
- \iow_indent:n { illuminant~=~<basis> }
- \\ \\
- key~was~given~with~the~correct~information.~LaTeX~will~use~illuminant~
- 'd50'~for~recovery.
- }
-\__kernel_msg_new:nnnn { color } { conversion-not-available }
- { No~model~conversion~available~from~'#1'~to~'#2'. }
- {
- LaTeX~has~been~asked~to~convert~a~color~from~model~'#1'~
- to~model'#2',~but~there~is~no~method~available~to~do~that.
- }
-\__kernel_msg_new:nnnn { color } { DeviceN-inconsistent-alternative }
- { DeviceN~color~spaces~require~a~single~alternative~space. }
- {
- LaTeX~has~been~asked~to~create~a~DeviceN~color~space~'#1',~
- but~the~constituent~colors~do~not~have~a~common~alternative~
- color.
- }
-\__kernel_msg_new:nnnn { color } { DeviceN-no-alternative }
- { DeviceN~color~spaces~require~an~alternative~space. }
- {
- LaTeX~has~been~asked~to~create~a~DeviceN~color~space~'#1',~
- but~the~constituent~colors~do~not~all~have~a~device-based~alternative.
- }
-\__kernel_msg_new:nnnn { color } { DeviceN-requires-names }
- { DeviceN~color~space~'#1'~require~a~list~of~names. }
- {
- LaTeX~has~been~asked~to~create~a~DeviceN~color~space,~
- but~no~\\ \\
- \iow_indent:n { names~=~<names> }
- \\ \\
- key~was~given~with~the~correct~information.
- }
-\__kernel_msg_new:nnnn { color } { model-already-defined }
- { Color~model~'#1'~already~defined. }
- {
- LaTeX~was~asked~to~define~a~new~color~model~called~'#1',~but~
- this~color~model~already~exists.
- }
-\__kernel_msg_new:nnnn { color } { separation-alternative-model }
- { Separation~color~space~'#1'~require~an~alternative~model. }
- {
- LaTeX~has~been~asked~to~create~a~separation~color~space,~
- but~no~\\ \\
- \iow_indent:n { alternative-model~=~<model> }
- \\ \\
- key~was~given~with~the~correct~information.
- }
-\__kernel_msg_new:nnnn { color } { separation-alternative-values }
- { Separation~color~space~'#1'~require~values~for~the~alternative~space. }
- {
- LaTeX~has~been~asked~to~create~a~separation~color~space,~
- but~no~\\ \\
- \iow_indent:n { alternative-values~=~<model> }
- \\ \\
- key~was~given~with~the~correct~information.
- }
-\__kernel_msg_new:nnnn { color } { separation-requires-name }
- { Separation~color~space~'#1'~require~a~formal~name. }
- {
- LaTeX~has~been~asked~to~create~a~separation~color~space,~
- but~no~\\ \\
- \iow_indent:n { name~=~<formal~name> }
- \\ \\
- key~was~given~with~the~correct~information.
- }
-\__kernel_msg_new:nnnn { color } { unknown-color }
- { Unknown~color~'#1'. }
- {
- LaTeX~has~been~asked~to~use~a~color~named~'#1',~
- but~this~has~never~been~defined.
- }
-\__kernel_msg_new:nnnn { color } { unknown-alternative-model }
- { Separation~color~space~'#1'~require~an~valid~alternative~space. }
- {
- LaTeX~has~been~asked~to~create~a~separation~color~space,~
- but~the~model~given~as\\ \\
- \iow_indent:n { alternative-model~=~<model> }
- \\ \\
- is~unknown.
- }
-\__kernel_msg_new:nnnn { color } { unknown-export-format }
- { Unknown~export~format~'#1'. }
- {
- LaTeX~has~been~asked~to~export~a~color~in~format~'#1',~
- but~this~has~never~been~defined.
- }
-\__kernel_msg_new:nnnn { color } { unknown-CIELAB-illuminant }
- { Unknown~illuminant~model~'#1'. }
- {
- LaTeX~has~been~asked~to~use~create~a~color~space~using~CIELAB~
- illuminant~'#1',~but~this~does~not~exist.
- }
-\__kernel_msg_new:nnnn { color } { unknown-model }
- { Unknown~color~model~'#1'. }
- {
- LaTeX~has~been~asked~to~use~a~color~model~called~'#1',~
- but~this~model~is~not~set~up.
- }
-\__kernel_msg_new:nnnn { color } { unknown-model-type }
- { Unknown~color~model~type~'#1'. }
- {
- LaTeX~has~been~asked~to~create~a~new~color~model~called~'#1',~
- but~this~type~of~model~was~never~set~up.
- }
-% \end{macrocode}
-%
-% \begin{macrocode}
-\__kernel_msg_new:nnn { color } { show }
- {
- The~color~#1~
- \tl_if_empty:nTF {#2}
- { is~undefined. }
- { has~the~properties: #2 }
- }
-% \end{macrocode}
-%
-% \begin{macrocode}
-%</package>
-% \end{macrocode}
-%
-% \end{implementation}
-%
-% \PrintIndex
diff --git a/macros/latex/contrib/l3experimental/l3color.ins b/macros/latex/contrib/l3experimental/l3color.ins
deleted file mode 100644
index e1704a9715..0000000000
--- a/macros/latex/contrib/l3experimental/l3color.ins
+++ /dev/null
@@ -1,58 +0,0 @@
-\iffalse meta-comment
-
-File: l3color.ins
-
-Copyright (C) 2017-2021 The LaTeX 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.
-
------------------------------------------------------------------------
-
-Any modification of this file should ensure that the copyright and
-license information is placed in the derived files.
-
-\fi
-
-\input l3docstrip.tex
-\askforoverwritefalse
-
-\preamble
-
-Copyright (C) 2017-2021 The LaTeX 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.
-
-\endpreamble
-% stop docstrip adding \endinput
-\postamble
-\endpostamble
-
-\keepsilent
-
-\generate{\file{l3color.sty}{\from{l3color.dtx}{package}}}
-
-\endbatchfile
diff --git a/macros/latex/contrib/l3experimental/l3color.pdf b/macros/latex/contrib/l3experimental/l3color.pdf
deleted file mode 100644
index aacda29a30..0000000000
--- a/macros/latex/contrib/l3experimental/l3color.pdf
+++ /dev/null
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3draw-boxes.dtx b/macros/latex/contrib/l3experimental/l3draw-boxes.dtx
index 29103416ee..64bc0cfa64 100644
--- a/macros/latex/contrib/l3experimental/l3draw-boxes.dtx
+++ b/macros/latex/contrib/l3experimental/l3draw-boxes.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3experimental/l3draw-code.pdf b/macros/latex/contrib/l3experimental/l3draw-code.pdf
index c52386b2b1..38889a0dc3 100644
--- a/macros/latex/contrib/l3experimental/l3draw-code.pdf
+++ b/macros/latex/contrib/l3experimental/l3draw-code.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3draw-layers.dtx b/macros/latex/contrib/l3experimental/l3draw-layers.dtx
index 0ed23162fd..f193ceb4d6 100644
--- a/macros/latex/contrib/l3experimental/l3draw-layers.dtx
+++ b/macros/latex/contrib/l3experimental/l3draw-layers.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3experimental/l3draw-paths.dtx b/macros/latex/contrib/l3experimental/l3draw-paths.dtx
index bfad9e14a3..a846d4046a 100644
--- a/macros/latex/contrib/l3experimental/l3draw-paths.dtx
+++ b/macros/latex/contrib/l3experimental/l3draw-paths.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3experimental/l3draw-points.dtx b/macros/latex/contrib/l3experimental/l3draw-points.dtx
index 8c170eeb27..70e088d0cf 100644
--- a/macros/latex/contrib/l3experimental/l3draw-points.dtx
+++ b/macros/latex/contrib/l3experimental/l3draw-points.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3experimental/l3draw-scopes.dtx b/macros/latex/contrib/l3experimental/l3draw-scopes.dtx
index 4b28b10397..60792f27ed 100644
--- a/macros/latex/contrib/l3experimental/l3draw-scopes.dtx
+++ b/macros/latex/contrib/l3experimental/l3draw-scopes.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3experimental/l3draw-softpath.dtx b/macros/latex/contrib/l3experimental/l3draw-softpath.dtx
index 2bda7e3c2d..9d70d5d7e2 100644
--- a/macros/latex/contrib/l3experimental/l3draw-softpath.dtx
+++ b/macros/latex/contrib/l3experimental/l3draw-softpath.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3experimental/l3draw-state.dtx b/macros/latex/contrib/l3experimental/l3draw-state.dtx
index 42709122b7..105120a391 100644
--- a/macros/latex/contrib/l3experimental/l3draw-state.dtx
+++ b/macros/latex/contrib/l3experimental/l3draw-state.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3experimental/l3draw-transforms.dtx b/macros/latex/contrib/l3experimental/l3draw-transforms.dtx
index 880fff8b1a..839fce91a6 100644
--- a/macros/latex/contrib/l3experimental/l3draw-transforms.dtx
+++ b/macros/latex/contrib/l3experimental/l3draw-transforms.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3experimental/l3draw.dtx b/macros/latex/contrib/l3experimental/l3draw.dtx
index 68f83903ec..1b6cdd8ab9 100644
--- a/macros/latex/contrib/l3experimental/l3draw.dtx
+++ b/macros/latex/contrib/l3experimental/l3draw.dtx
@@ -110,7 +110,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
@@ -231,7 +231,7 @@
% \begin{syntax}
% \cs{draw_linewidth:n} \Arg{width}
% \end{syntax}
-% Sets the width to be used for stroking to the \meta{width} (an
+% Sets the width to be used for stroking to the \meta{width} (an
% \meta{fp expr}).
% \end{function}
%
@@ -268,7 +268,7 @@
% \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}
@@ -410,7 +410,7 @@
% 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.
@@ -470,7 +470,7 @@
% \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.
@@ -795,7 +795,7 @@
% \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.
+% 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}
%
@@ -1136,14 +1136,10 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3draw}{2021-02-06}{}
+\ProvidesExplPackage{l3draw}{2021-02-18}{}
{L3 Experimental core drawing support}
% \end{macrocode}
%
-% \begin{macrocode}
-\RequirePackage { l3color }
-% \end{macrocode}
-%
% \subsection{Internal auxiliaries}
%
% \begin{variable}{\s_@@_mark,\s_@@_stop}
diff --git a/macros/latex/contrib/l3experimental/l3draw.pdf b/macros/latex/contrib/l3experimental/l3draw.pdf
index c93d56a3e6..d0eb491882 100644
--- a/macros/latex/contrib/l3experimental/l3draw.pdf
+++ b/macros/latex/contrib/l3experimental/l3draw.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3galley.dtx b/macros/latex/contrib/l3experimental/l3galley.dtx
index 2209ce8d9e..1c7c9bd941 100644
--- a/macros/latex/contrib/l3experimental/l3galley.dtx
+++ b/macros/latex/contrib/l3experimental/l3galley.dtx
@@ -61,7 +61,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
@@ -686,7 +686,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3galley}{2021-02-06}{}
+\ProvidesExplPackage{l3galley}{2021-02-18}{}
{L3 Experimental galley code}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3experimental/l3galley.pdf b/macros/latex/contrib/l3experimental/l3galley.pdf
index 4e836f86ad..743d8ac6f2 100644
--- a/macros/latex/contrib/l3experimental/l3galley.pdf
+++ b/macros/latex/contrib/l3experimental/l3galley.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3graphics.dtx b/macros/latex/contrib/l3experimental/l3graphics.dtx
index c244ad7258..5b4144c062 100644
--- a/macros/latex/contrib/l3experimental/l3graphics.dtx
+++ b/macros/latex/contrib/l3experimental/l3graphics.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
@@ -240,7 +240,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3graphics}{2021-02-06}{}
+\ProvidesExplPackage{l3graphics}{2021-02-18}{}
{L3 Experimental graphics inclusion support}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3experimental/l3graphics.pdf b/macros/latex/contrib/l3experimental/l3graphics.pdf
index 835fc34762..2ae274ac53 100644
--- a/macros/latex/contrib/l3experimental/l3graphics.pdf
+++ b/macros/latex/contrib/l3experimental/l3graphics.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3pdf-code.pdf b/macros/latex/contrib/l3experimental/l3pdf-code.pdf
deleted file mode 100644
index cc3e9f9c5e..0000000000
--- a/macros/latex/contrib/l3experimental/l3pdf-code.pdf
+++ /dev/null
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3pdf-code.tex b/macros/latex/contrib/l3experimental/l3pdf-code.tex
deleted file mode 100644
index db2a7d5bf0..0000000000
--- a/macros/latex/contrib/l3experimental/l3pdf-code.tex
+++ /dev/null
@@ -1,56 +0,0 @@
-\iffalse meta-comment
-
-File: l3pdf-code.tex
-
-Copyright (C) 2019,2021 The LaTeX 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
-
- https://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 released version of this bundle is available from CTAN.
-
------------------------------------------------------------------------
-
-The development version of the bundle can be found at
-
- https://github.com/latex3/latex3
-
-for those people who are interested.
-
-\fi
-
-\documentclass{l3doc}
-
-\begin{document}
-
-\makeatletter
-\let\DelayPrintIndex\PrintIndex
-\let\PrintIndex\@empty
-\makeatother
-
-\ExplSyntaxOn
-\clist_gput_right:Nn \g_docinput_clist
- {
- l3pdf.dtx ,
- }
-\ExplSyntaxOff
-
-\part{Implementation}
-
-\def\maketitle{}
-\EnableImplementation
-\DisableDocumentation
-\DocInputAgain
-
-\clearpage
-
-\DelayPrintIndex
-
-\end{document}
diff --git a/macros/latex/contrib/l3experimental/l3pdf.dtx b/macros/latex/contrib/l3experimental/l3pdf.dtx
deleted file mode 100644
index f5a5c72cfe..0000000000
--- a/macros/latex/contrib/l3experimental/l3pdf.dtx
+++ /dev/null
@@ -1,442 +0,0 @@
-% \iffalse meta-comment
-%
-%% File: l3pdf.dtx
-%
-% Copyright(C) 2019-2021 The LaTeX 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|package>
-%<*driver>
-\documentclass[full]{l3doc}
-\begin{document}
- \DocInput{\jobname.dtx}
-\end{document}
-%</driver>
-% \fi
-%
-% \title{^^A
-% The \pkg{l3pdf} package\\ Core PDF support^^A
-% }
-%
-% \author{^^A
-% The \LaTeX{} Project\thanks
-% {^^A
-% E-mail:
-% \href{mailto:latex-team@latex-project.org}
-% {latex-team@latex-project.org}^^A
-% }^^A
-% }
-%
-% \date{Released 2021-02-06}
-%
-% \maketitle
-%
-% \begin{documentation}
-%
-% \section{\pkg{l3pdf} documentation}
-%
-% \subsection{Objects}
-%
-% \begin{function}[added = 2019-06-02]{\pdf_object_new:nn}
-% \begin{syntax}
-% \cs{pdf_object_new:nn} \Arg{object} \Arg{type}
-% \end{syntax}
-% Declares \meta{object} as a PDF object of \meta{type}, which should be
-% one of
-% \begin{itemize}
-% \item \texttt{array}
-% \item \texttt{dict}
-% \item \texttt{fstream}
-% \item \texttt{stream}
-% \end{itemize}
-% The object may be referenced from this point on, and written later
-% using \cs{pdf_object_write:nn}.
-% \end{function}
-% \begin{function}[EXP, pTF, added=2020-05-15]{\pdf_object_if_exist:n}
-% \begin{syntax}
-% \cs{pdf_object_if_exist_p:n} \Arg{object}
-% \cs{pdf_object_if_exist:nTF} \Arg{object}
-% \end{syntax}
-% Tests whether an object with name \Arg{object} has been defined.
-% \end{function}
-% \begin{function}[added = 2019-06-02]
-% {\pdf_object_write:nn, \pdf_object_write:nx}
-% \begin{syntax}
-% \cs{pdf_object_write:nn} \Arg{object} \Arg{content}
-% \end{syntax}
-% Writes the \meta{content} as content of the \meta{object}. Depending on the
-% \meta{type} declared for the object, the format required for the
-% \meta{data} will vary
-% \begin{itemize}
-% \item[\texttt{array}] A space-separated list of values
-% \item[\texttt{dict}] Key--value pairs in the form
-% \texttt{/\meta{key} \meta{value}}
-% \item[\texttt{fstream}] Two brace groups: \meta{file name} and
-% \meta{file content}
-% \item[\texttt{stream}] Two brace groups: \meta{attributes (dictionary)}
-% and \meta{stream contents}
-% \end{itemize}
-% \end{function}
-%
-% \begin{function}[EXP, added = 2019-06-02]{\pdf_object_ref:n}
-% \begin{syntax}
-% \cs{pdf_object_ref:n} \Arg{object}
-% \end{syntax}
-% Inserts the appropriate information to reference the \meta{object}
-% in for example page resource allocation
-% \end{function}
-%
-% \begin{function}[added = 2019-06-02]
-% {\pdf_object_now:nn, \pdf_object_now:nx}
-% \begin{syntax}
-% \cs{pdf_object_now:nn} \Arg{type} \Arg{content}
-% \end{syntax}
-% Writes the \meta{content} as content of an anonymous object. Depending on the
-% \meta{type}, the format required for the \meta{data} will vary
-% \begin{itemize}
-% \item[\texttt{array}] A space-separated list of values
-% \item[\texttt{dict}] Key--value pairs in the form
-% \texttt{/\meta{key} \meta{value}}
-% \item[\texttt{fstream}] Two brace groups: \meta{file name} and
-% \meta{file content}
-% \item[\texttt{stream}] Two brace groups: \meta{attributes (dictionary)}
-% and \meta{stream contents}
-% \end{itemize}
-% \end{function}
-%
-% \begin{function}[EXP, added = 2019-06-02]{\pdf_object_last:}
-% \begin{syntax}
-% \cs{pdf_object_last:}
-% \end{syntax}
-% Inserts the appropriate information to reference the last \meta{object}
-% created. This is particularly useful for anonymous objects.
-% \end{function}
-%
-% \subsection{Version}
-%
-% \begin{function}[pTF, EXP, added = 2019-06-02]{\pdf_version_compare:Nn}
-% \begin{syntax}
-% \cs{pdf_version_compare:NnTF} \meta{comparator} \Arg{version} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Compares the version of the PDF being created with the \meta{version}
-% string specified, using the \meta{comparator}. Either the \meta{true code}
-% or \meta{false code} will be left in the output stream.
-% \end{function}
-%
-% \begin{function}[added = 2019-06-02]
-% {\pdf_version_gset:n, \pdf_version_min_gset:n}
-% \begin{syntax}
-% \cs{pdf_version_gset:n} \Arg{version}
-% \end{syntax}
-% Sets the \meta{version} of the PDF being created. The |min| version will
-% not alter the output version unless it is currently lower than the
-% \meta{version} requested.
-%
-% This function may only be used up to the point where the PDF file is
-% initialised.
-% \end{function}
-%
-% \begin{function}[EXP, added = 2019-06-02]
-% {\pdf_version:, \pdf_version_major:, \pdf_version_minor:}
-% \begin{syntax}
-% \cs{pdf_version:}
-% \end{syntax}
-% Expands to the currently-active PDF version.
-% \end{function}
-%
-% \subsection{Compression}
-%
-% \begin{function}[added = 2019-06-02]{\pdf_uncompress:}
-% \begin{syntax}
-% \cs{pdf_uncompress:}
-% \end{syntax}
-% Disables any compression of the PDF, where possible.
-%
-% This function may only be used up to the point where the PDF file is
-% initialised.
-% \end{function}
-%
-% \subsection{Destinations}
-%
-% Destinations are the places a link jumped too.
-% Unlike the name may suggest they don't described
-% an exact location in the PDF. Instead a destination contains a reference to
-% a page along with an instruction how to display this page.
-% The normally used \enquote{XYZ \textit{top left zoom}} for example instructs
-% the viewer to show the page with the given \textit{zoom} and
-% the top left corner at the \textit{top left} coordinates---which then gives
-% the impression that there is an anchor at this position.
-%
-% If an instruction takes a coordinate, it is calculated by the following
-% commands relative to the location the command is issued.
-% So to get a specific coordinate one has to move the command to the right place.
-%
-% \begin{function}[added = 2021-01-03]
-% {\pdf_destination:nn}
-% \begin{syntax}
-% \cs{pdf_destination:nn} \Arg{name} \Arg{type or integer}
-% \end{syntax}
-% This creates a destination. \Arg{type or integer} can be one of |fit|, |fith|,
-% |fitv|, |fitb|, |fitbh|, |fitbv|, |fitr|, |xyz|
-% or an integer representing a scale factor in percent.
-% |fitr| here gives only a lightweight version of |/FitR|:
-% The backend code defines |fitr| so that it will with pdf\LaTeX{} and
-% Lua\LaTeX{} use the coordinates of the surrounding box,
-% with \texttt{dvips} and \texttt{dvipdfmx} it falls back to |fit|.
-% For full control use \cs{pdf_destination:nnnn}.
-%
-% The keywords match to the PDF names as described in the following tabular.
-%
-% \medskip
-% \noindent\begin{tabular}{ll>{\raggedright\arraybackslash}p{6cm}}
-% \toprule
-% Keyword & PDF & Remarks \\ \midrule
-% |fit| & |/Fit|
-% & Fits the page to the window\\
-% |fith| & |/FitH| \textit{top}
-% & Fits the width of the page to the window \\
-% |fitv| & |/FitV| \textit{left}
-% & Fits the height of the page to the window \\
-% |fitb| & |/FitB|
-% & Fits the page bounding box to the window \\
-% |fitbh|& |/FitBH| \textit{top}
-% & Fits the width of the page bounding box to the window. \\
-% |fitbv|& |/FitBV| \textit{left}
-% & Fits the height of the page bounding box to the window. \\
-% |fitr| & |/FitR| \textit{left bottom right top}
-% & Fits the rectangle specified by the four coordinates to the window
-% (see above for the restrictions)\\
-% |xyz| & |/XYZ| \textit{left top} null
-% & Sets a coordinate but doesn't change the zoom.\\
-% \Arg{integer} & |/XYZ| \textit{left top zoom}
-% & Sets a coordinate and a zoom meaning \Arg{integer}\%.
-% \\\bottomrule
-% \end{tabular}
-%
-% \end{function}
-%
-% \begin{function}[added = 2021-01-17]
-% {\pdf_destination:nnnn}
-% \begin{syntax}
-% \cs{pdf_destination:nnnn} \Arg{name} \Arg{width} \Arg{height} \Arg{depth}
-% \end{syntax}
-% This creates a destination with |/FitR| type with the given dimensions relative
-% to the current location. The destination is in a box of size zero, but it doesn't
-% switch to horizontal mode.
-% \end{function}
-% \end{documentation}
-%
-% \begin{implementation}
-%
-% \section{\pkg{l3pdf} implementation}
-%
-% \begin{macrocode}
-%<*package>
-% \end{macrocode}
-%
-% \begin{macrocode}
-%<@@=pdf>
-% \end{macrocode}
-%
-% \begin{macrocode}
-\ProvidesExplPackage{l3pdf}{2021-02-06}{}
- {L3 Experimental core PDF support}
-% \end{macrocode}
-%
-% \begin{variable}{\s_@@_stop}
-% Internal scan marks.
-% \begin{macrocode}
-\scan_new:N \s_@@_stop
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\g_@@_init_bool}
-% A flag so we have some chance of avoiding setting things we are not
-% allowed to.
-% \begin{macrocode}
-\bool_new:N \g_@@_init_bool
-%<*package>
-\cs_if_exist:NT \documentclass
- {
- \AtBeginDocument
- { \bool_gset_true:N \g_@@_init_bool }
- }
-%</package>
-% \end{macrocode}
-% \end{variable}
-%
-% \subsection{Compression}
-%
-% \begin{macro}{\pdf_uncompress:}
-% Simple to do.
-% \begin{macrocode}
-\cs_new_protected:Npn \pdf_uncompress:
- {
- \bool_if:NF \g_@@_init_bool
- {
- \@@_backend_compresslevel:n { 0 }
- \@@_backend_compress_objects:n { \c_false_bool }
- }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Objects}
-%
-% \begin{macro}{\pdf_object_new:nn, \pdf_object_write:nn, \pdf_object_write:nx}
-% \begin{macro}[pTF]{\pdf_object_if_exist:n}
-% \begin{macro}{\pdf_object_ref:n}
-% \begin{macro}{\pdf_object_now:nn, \pdf_object_now:nx}
-% \begin{macro}{\pdf_object_last:}
-% Simple to do.
-% \begin{macrocode}
-\cs_new_protected:Npn \pdf_object_new:nn #1#2
- { \@@_backend_object_new:nn {#1} {#2} }
-\prg_new_conditional:Npnn \pdf_object_if_exist:n #1 { p , T , F , TF }
- {
- \int_if_exist:cTF { c__pdf_backend_object_ \tl_to_str:n {#1} _int }
- { \prg_return_true: }
- { \prg_return_false:}
- }
-\cs_new_protected:Npn \pdf_object_write:nn #1#2
- { \@@_backend_object_write:nn {#1} {#2} }
-\cs_generate_variant:Nn \pdf_object_write:nn { nx }
-\cs_new:Npn \pdf_object_ref:n #1 { \@@_backend_object_ref:n {#1} }
-\cs_new_protected:Npn \pdf_object_now:nn #1#2
- { \@@_backend_object_now:nn {#1} {#2} }
-\cs_generate_variant:Nn \pdf_object_now:nn { nx }
-\cs_new:Npn \pdf_object_last: { \@@_backend_object_last: }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Version}
-%
-% \begin{macro}{\pdf_version_compare:Nn}
-% \begin{macro}
-% {
-% @@_version_compare_=:w ,
-% @@_version_compare_<:w ,
-% @@_version_compare_>:w
-% }
-% \begin{macrocode}
-% To compare version, we need to split the given value then deal with both
-% major and minor version
-\prg_new_conditional:Npnn \pdf_version_compare:Nn #1#2 { p , T , F , TF }
- { \use:c { @@_version_compare_ #1 :w } #2 . . \s_@@_stop }
-\cs_new:cpn { @@_version_compare_=:w } #1 . #2 . #3 \s_@@_stop
- {
- \bool_lazy_and:nnTF
- { \int_compare_p:nNn \@@_backend_version_major: = {#1} }
- { \int_compare_p:nNn \@@_backend_version_minor: = {#2} }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_new:cpn { @@_version_compare_<:w } #1 . #2 . #3 \s_@@_stop
- {
- \bool_lazy_or:nnTF
- { \int_compare_p:nNn \@@_backend_version_major: < {#1} }
- {
- \bool_lazy_and_p:nn
- { \int_compare_p:nNn \@@_backend_version_major: = {#1} }
- { \int_compare_p:nNn \@@_backend_version_minor: < {#2} }
- }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_new:cpn { @@_version_compare_>:w } #1 . #2 . #3 \s_@@_stop
- {
- \bool_lazy_or:nnTF
- { \int_compare_p:nNn \@@_backend_version_major: > {#1} }
- {
- \bool_lazy_and_p:nn
- { \int_compare_p:nNn \@@_backend_version_major: = {#1} }
- { \int_compare_p:nNn \@@_backend_version_minor: > {#2} }
- }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\pdf_version_gset:n, \pdf_version_min_gset:n}
-% \begin{macro}{\@@_version_gset:w}
-% Split the version and set.
-% \begin{macrocode}
-\cs_new_protected:Npn \pdf_version_gset:n #1
- { \@@_version_gset:w #1 . . \s_@@_stop }
-\cs_new_protected:Npn \pdf_version_min_gset:n #1
- {
- \pdf_version_compare:NnT < {#1}
- { \@@_version_gset:w #1 . . \s_@@_stop }
- }
-\cs_new_protected:Npn \@@_version_gset:w #1 . #2 . #3\s_@@_stop
- {
- \bool_if:NF \g_@@_init_bool
- {
- \@@_backend_version_major_gset:n {#1}
- \@@_backend_version_minor_gset:n {#2}
- }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\pdf_version:, \pdf_version_major:, \pdf_version_minor:}
-% Wrappers.
-% \begin{macrocode}
-\cs_new:Npn \pdf_version:
- { \@@_backend_version_major: . \@@_backend_version_minor: }
-\cs_new:Npn \pdf_version_major: { \@@_backend_version_major: }
-\cs_new:Npn \pdf_version_minor: { \@@_backend_version_minor: }
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Destinations}
-%
-% \begin{macro}{\pdf_destination:nn}
-% \begin{macrocode}
-\cs_new_protected:Npn \pdf_destination:nn #1 #2
- { \@@_backend_destination:nn {#1}{#2} }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\pdf_destination:nnnn}
-% \begin{macrocode}
-\cs_new_protected:Npn \pdf_destination:nnnn #1 #2 #3 #4
- {
- \hbox_to_zero:n
- { \@@_backend_destination:nnnn {#1} {#2} {#3} {#4} }
- }
-% \end{macrocode}
-% \end{macro}
-% \begin{macrocode}
-%</package>
-% \end{macrocode}
-%
-% \end{implementation}
-%
-% \PrintIndex
diff --git a/macros/latex/contrib/l3experimental/l3pdf.ins b/macros/latex/contrib/l3experimental/l3pdf.ins
deleted file mode 100644
index e422ceb995..0000000000
--- a/macros/latex/contrib/l3experimental/l3pdf.ins
+++ /dev/null
@@ -1,60 +0,0 @@
-\iffalse meta-comment
-
-File: l3pdf.ins
-
-Copyright (C) 2019-2021 The LaTeX 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.
-
------------------------------------------------------------------------
-
-Any modification of this file should ensure that the copyright and
-license information is placed in the derived files.
-
-\fi
-
-\input l3docstrip.tex
-\askforoverwritefalse
-
-\preamble
-
-Copyright (C) 2019-2021 The LaTeX 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 "l3pdf bundle" (The Work in LPPL)
-and all files in that bundle must be distributed together.
-
-\endpreamble
-% stop docstrip adding \endinput
-\postamble
-\endpostamble
-
-\keepsilent
-
-\generate{\file{l3pdf.sty}
- {\from{l3pdf.dtx}{package}}
-}
-
-\endbatchfile
diff --git a/macros/latex/contrib/l3experimental/l3pdf.pdf b/macros/latex/contrib/l3experimental/l3pdf.pdf
deleted file mode 100644
index 38b9038f82..0000000000
--- a/macros/latex/contrib/l3experimental/l3pdf.pdf
+++ /dev/null
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3str-format.dtx b/macros/latex/contrib/l3experimental/l3str-format.dtx
index e39f2e7e03..9b0cf4a5a4 100644
--- a/macros/latex/contrib/l3experimental/l3str-format.dtx
+++ b/macros/latex/contrib/l3experimental/l3str-format.dtx
@@ -48,7 +48,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
@@ -166,7 +166,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3str-format}{2021-02-06}{}
+\ProvidesExplPackage{l3str-format}{2021-02-18}{}
{L3 Experimental string formatting}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3experimental/l3str-format.pdf b/macros/latex/contrib/l3experimental/l3str-format.pdf
index df1b4600dc..b0b07a632e 100644
--- a/macros/latex/contrib/l3experimental/l3str-format.pdf
+++ b/macros/latex/contrib/l3experimental/l3str-format.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/l3sys-shell.dtx b/macros/latex/contrib/l3experimental/l3sys-shell.dtx
index 2e1d15d8db..9a7920fe3f 100644
--- a/macros/latex/contrib/l3experimental/l3sys-shell.dtx
+++ b/macros/latex/contrib/l3experimental/l3sys-shell.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
@@ -135,7 +135,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3sys-shell}{2021-02-06}{}
+\ProvidesExplPackage{l3sys-shell}{2021-02-18}{}
{L3 Experimental system shell functions}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3experimental/l3sys-shell.pdf b/macros/latex/contrib/l3experimental/l3sys-shell.pdf
index a2de0baee3..44d84d1d9b 100644
--- a/macros/latex/contrib/l3experimental/l3sys-shell.pdf
+++ b/macros/latex/contrib/l3experimental/l3sys-shell.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/xcoffins.dtx b/macros/latex/contrib/l3experimental/xcoffins.dtx
index 37ef1c2cfe..86d3add8ae 100644
--- a/macros/latex/contrib/l3experimental/xcoffins.dtx
+++ b/macros/latex/contrib/l3experimental/xcoffins.dtx
@@ -53,7 +53,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
@@ -672,7 +672,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{xcoffins}{2021-02-06}{}
+\ProvidesExplPackage{xcoffins}{2021-02-18}{}
{L3 Experimental design level coffins}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3experimental/xcoffins.pdf b/macros/latex/contrib/l3experimental/xcoffins.pdf
index 6c76fdd7b2..cb1e4bd9ad 100644
--- a/macros/latex/contrib/l3experimental/xcoffins.pdf
+++ b/macros/latex/contrib/l3experimental/xcoffins.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3experimental/xgalley.dtx b/macros/latex/contrib/l3experimental/xgalley.dtx
index 9292de0889..680e288fe3 100644
--- a/macros/latex/contrib/l3experimental/xgalley.dtx
+++ b/macros/latex/contrib/l3experimental/xgalley.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2021-02-06}
+% \date{Released 2021-02-18}
%
% \maketitle
%
@@ -731,7 +731,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{xgalley}{2021-02-06}{}
+\ProvidesExplPackage{xgalley}{2021-02-18}{}
{L3 Experimental galley}
\RequirePackage{xtemplate,l3galley}
% \end{macrocode}
diff --git a/macros/latex/contrib/l3experimental/xgalley.pdf b/macros/latex/contrib/l3experimental/xgalley.pdf
index 3d8a23cec1..b882769cf5 100644
--- a/macros/latex/contrib/l3experimental/xgalley.pdf
+++ b/macros/latex/contrib/l3experimental/xgalley.pdf
Binary files differ