[latex3-commits] [l3svn] branch master updated: First steps for color functions
noreply at latex-project.org
noreply at latex-project.org
Tue Oct 10 22:58:08 CEST 2017
This is an automated email from the git hooks/post-receive script.
joseph pushed a commit to branch master
in repository l3svn.
The following commit(s) were added to refs/heads/master by this push:
new f6d5c66 First steps for color functions
f6d5c66 is described below
commit f6d5c669ade4c7c8d5bbdee1a8486f0d42c1c861
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date: Tue Oct 10 21:57:12 2017 +0100
First steps for color functions
---
l3trial/l3color-addn/l3color-addn.dtx | 567 +++++++++++++++++++++++++++++++++
1 file changed, 567 insertions(+)
diff --git a/l3trial/l3color-addn/l3color-addn.dtx b/l3trial/l3color-addn/l3color-addn.dtx
new file mode 100644
index 0000000..a127e23
--- /dev/null
+++ b/l3trial/l3color-addn/l3color-addn.dtx
@@ -0,0 +1,567 @@
+% \iffalse meta-comment
+%
+%% File: l3color-addn.dtx Copyright(C) 2017 The LaTeX3 Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3kernel 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>
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \textsf{l3color-addn} package\\ Experimental additions to color support^^A
+% }
+%
+% \author{^^A
+% The \LaTeX3 Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team at latex-project.org}
+% {latex-team at latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2017/09/18}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \section{Color expressions}
+%
+% \section{Named colors}
+%
+% \begin{function}{\color_set:nn}
+% \begin{syntax}
+% \cs{color_set:nn} \marg{name} \marg{color expression}
+% \end{syntax}
+% \end{function}
+%
+% \begin{function}{\color_set:nnn}
+% \begin{syntax}
+% \cs{color_set:nnn} \marg{name} \marg{model} \marg{value(s)}
+% \end{syntax}
+% \end{function}
+%
+% \begin{function}{\color_set_eq:nn}
+% \begin{syntax}
+% \cs{color_set_eq:nn} \meta{name1} \marg{name2}
+% \end{syntax}
+% \end{function}
+%
+% \section{Selecting colors}
+%
+% \begin{function}{\color_select:n}
+% \begin{syntax}
+% \cs{color_select:n} \meta{color expression}
+% \end{syntax}
+% \end{function}
+%
+% \begin{function}{\color_select:nn}
+% \begin{syntax}
+% \cs{color_select:nn} \meta{model} \meta{value(s)}
+% \end{syntax}
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3color-addn} Implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \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 separate token list variable, rather than the alternative of using a
+% single property list for all names.
+%
+% \subsection{Setup}
+%
+% \begin{variable}{\l_@@_tmp_tl}
+% \begin{macrocode}
+\tl_new:N \l_@@_tmp_tl
+% \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 }
+ {
+ \tl_if_exist:cTF { l_@@_named_ #1 _tl }
+ \prg_return_true:
+ \prg_return_false:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_extract:nNN}
+% \begin{macro}[aux]{\@@_extract:NNw}
+% Split the model and color from a named color, and store the two. No test
+% for the existence of the color: that is assumed to be the case (this
+% is internal only). Somewhat \enquote{old-fashioned} but should be quite
+% fast.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_extract:nNN #1#2#3
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \@@_extract:NNw
+ \exp_after:wN \exp_after:wN \exp_after:wN #2
+ \exp_after:wN \exp_after:wN \exp_after:wN #3
+ \cs:w l_@@_named_ #1 _tl \cs_end: \q_stop
+ }
+\cs_new_protected:Npn \@@_extract:NNw #1#2 #3 ~ #4 \q_stop
+ {
+ \tl_set:Nn #1 {#3}
+ \tl_set:Nn #2 {#4}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Model conversion}
+%
+% \begin{macro}[int]{\@@_convert:nnN, \@@_convert:VVN}
+% \begin{macro}[aux]{\@@_convert:nnnN}
+% \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:nnnnn}
+% 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
+ {
+ \str_if_eq_x:nnT {#1} { spot } % TO DO!!!
+ { }
+ \tl_set:Nx #4
+ { \use:c { @@_convert_ #1 _ #2 :w } #3 ~ 0 ~ 0 ~ 0 \q_stop }
+ }
+\cs_generate_variant:Nn \@@_convert:nnnN { nnV }
+\cs_new:Npn \@@_convert_gray_rgb:w #1 ~ #2 \q_stop
+ { #1 ~ #1 ~ #1 }
+\cs_new:Npn \@@_convert_gray_cmyk:w #1 ~ #2 \q_stop
+ { 0 ~ 0 ~ 0 ~ #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 \q_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 \q_stop
+ {
+ \exp_args:Nf \@@_convert_rgb_cmyk:nnnnn
+ { \fp_eval:n { min ( 1 - #1 , 1 - #2 , 1 - #3 ) } {#1} {#2} {#3}
+ }
+
+\cs_new:Npn \@@_convert_rgb_cmyk:nnnnn #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 \q_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 \q_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}[int]{\@@_parse:nn}
+% \begin{macro}[aux]{\@@_parse:n}
+% \begin{macro}[aux]{\@@_parse:w}
+% \begin{macro}[aux]{\@@_parse_loop_init:nn}
+% \begin{macro}[aux]{\@@_parse_loop:w}
+% \begin{macro}[aux]{\@@_parse_loop:nn}
+% \begin{macro}[aux]{\@@_parse_break:w}
+% \begin{macro}[aux]{\@@_parse_end:}
+% \begin{macro}[aux, EXP]{\@@_parse_mix:Nnnn}
+% \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:Npn \@@_parse:nn #1#2
+ {
+ \group_begin:
+ \seq_map_inline:Nn \l_char_active_seq
+ {
+ \tl_set:Nx \l_@@_tmp_tl { \cs_to_str:N ##1 }
+ \char_set_active_eq:NN ##1 \l_@@_tmp_tl
+ }
+ \tl_set:Nx \l_@@_tmp_tl {#2}
+ \exp_args:NNV \group_end:
+ \@@_parse:V \l_@@_tmp_tl
+ #1
+ }
+% \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:Nn \@@_parse:n #1
+ {
+ \tl_if_exist:cTF { l_@@_named_ #1 _tl }
+ { \tl_set_eq:Nc \l__color_current_tl { l_@@_named_ #1 _tl } }
+ { \@@_parse:w #1 ! \q_stop }
+ }
+\cs_new_protected:Npn \@@_parse:w #1 ! #2 \q_stop
+ {
+ \@@_if_defined:nTF {#1}
+ {
+ \tl_if_blank:nTF {#2}
+ { \tl_set_eq:Nc \l__color_current_tl { l_@@_named_ #1 _tl } }
+ { \@@_parse_loop_init:nn {#1} {#2} }
+ }
+ {
+ \msg_kernel_error:nnn { color } { unknown-color } {#2}
+ \tl_set_eq:NN \l__color_current_tl \l_@@_named_black_tl
+ }
+ }
+% \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:nn #1#2
+ {
+ \group_begin:
+ \@@_extract:nNN {#1} \l_@@_model_tl \l_@@_value_tl
+ \@@_parse_loop:w #2 ! ! ! ! \q_stop
+ \tl_set:Nx \l_@@_tmp_tl
+ { \l_@@_model_tl \c_space_tl \l_@@_value_tl }
+ \exp_args:NNNV \group_end:
+ \tl_set:Nn \l__color_current_tl \l_@@_tmp_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 \q_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 \q_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 {#1}
+ {
+ \@@_extract:nNN {#1} \l_@@_next_model_tl \l_@@_next_value_tl
+ \tl_if_eq:NNF \l_@@_model_tl \l_@@_next_model_tl
+ {
+ \str_if_eq_x:nnT { \l_@@_model_tl } { gray }
+ {
+ \use:x
+ {
+ \tl_set:Nn \exp_not:N \l_@@_model_tl
+ { \l_@@_next_model_tl }
+ \tl_set:Nn \exp_not:N \l_@@_value_tl
+ { \l_@@_next_value_tl }
+ \tl_set:Nn \exp_not:N \l_next_@@_model_tl
+ { \l_@@_model_tl }
+ \tl_set:Nn \exp_not:N \l_next_@@_value_tl
+ { \l_@@_value_tl }
+ }
+ }
+ \@@_convert:VVN
+ \l_@@_next_model_tl
+ \l_@@_model_tl
+ \l_@@_next_value_tl
+ }
+ \tl_set:Nx \l_@@_value_tl
+ {
+ \@@_parse_mix:NVVn
+ \l_@@_model_tl \l_@@_value_tl \l_@@_next_value_tl {#2}
+ }
+ }
+ {
+ \msg_kernel_error:nnn { color } { unknown-color } {#2}
+ \@@_extract:nNN { black } \l_@@_model_tl \l_@@_value_tl
+ \@@_parse_break:w
+ }
+ }
+\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_new:Npn \@@_parse_mix:nNnn #1#2#3#4
+ {
+ \use:c { @@_parse_mix_ #2 :nnw } {#1}
+ #3 \q_mark #4 \q_stop
+ }
+\cs_new:Npn \@@_parse_mix_gray:nw #1#2 \q_mark #3 \q_stop
+ { \fp_eval:n { #2 * #1 + #3 * ( 1 - #1 ) } }
+\cs_new:Npn \@@_parse_mix_rgb:nw
+ #1#2 ~ #3 ~ #4 \q_mark #5 ~ #6 ~ #7 \q_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 \q_mark #6 ~ #7 ~ #8 ~ #9 \q_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}
+%
+% \begin{macro}[EXP]
+% {\@@_parse_gray:w, \@@_parse_rgb:w, \@@_parse_cmyk:w, \@@_parse_spot:w}
+% \begin{macro}[EXP]{\@@_parse_spot_aux:w}
+% Turn the input into internal form.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_gray:w #1 , #2 \q_stop {#1}
+\cs_new:Npn \@@_parse_rgb:w #1 , #2 , #3 , #4 \q_stop { #1 ~ #2 ~ #3 }
+\cs_new:Npn \@@_parse_cmyk:w #1 , #2 , #3 , #4 , #5 \q_stop
+ { #1 ~ #2 ~ #3 ~ #4 }
+\cs_new:Npn \@@_parse_spot:w #1 , #2 \q_stop
+ { \@@_parse_spot_aux:w #1 ! 100 ! \q_stop }
+\cs_new:Npn \@@_parse_spot_aux:w #1 ! #2 ! #3 \q_stop
+ { #1 ~ \fp_eval:n { #2 / 100 } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Direct model use}
+%
+% \begin{macro}{\@@_use:nnn}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_use:nnn #1#2#3
+ {
+ \cs_if_exist:cTF { @@_parse_ #2 :w }
+ {
+ \tl_set:Nx \l__color_current_tl
+ { #2 ~ \use:c { @@_parse_ #2 :w } #3 , 0 , 0 , 0 , 0 \q_stop }
+ #1
+ }
+ {
+ \__msg_kernel_error:nnn { color } { invalid-model } {#2}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\color_set:nn}
+% \begin{macro}{\color_set:nnn}
+% \begin{macro}{\color_set_eq:nn}
+% Defining named colors has to include a step to force creation of the
+% underlying token list to avoid errors when checking is enabled.
+% \begin{macrocode}
+\cs_new_protected:Npn \color_set:nn #1
+ { \@@_parse:nn { \@@_store:n {#1} } }
+\cs_new_protected:Npn \color_set:nnn #1
+ { \@@_use:nnn { \@@_store:n {#1} } }
+\cs_new_protected:Npn \color_set_eq:nn #1#2
+ {
+ \@@_if_defined:nTF {#2}
+ {
+ \tl_clear_new:c { l_@@_named_ #1 _tl }
+ \str_if_eq:nnTF {#2} { . }
+ { \tl_et_eq:cN { l_@@_named_ #1 _tl } \l__color_current_tl }
+ { \tl_et_eq:cc { l_@@_named_ #1 _tl } { l_@@_named_ #2 _tl } }
+ }
+ {
+ \msg_kernel_error:nnn { color } { unknown-color } {#2}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\color_select:n}
+% \begin{macro}{\color_select:nn}
+% Parse the input expressions then get the driver to actually activate
+% them.
+% \begin{macrocode}
+\cs_new_protected:Npn \color_select:n
+ { \@@_parse:nn { \__driver_color_select: } }
+\cs_new_protected:Npn \color_select:nn
+ { \@@_use:nnn { \__driver_color_select: } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Pre-defined color names}
+%
+% \begin{macrocode}
+\color_set:nnn { black } { gray } { 0 }
+\color_set:nnn { white } { gray } { 0 }
+\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 { grenn } { rgb } { 0~1~0 }
+\color_set:nnn { blue } { rgb } { 0~0~1 }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\__msg_kernel_new:nnnn { color } { invalid-model }
+ { Invalid~color~model~'#1'. }
+ {
+ LaTeX~has~been~asked~to~use~a~color~model~called~'#1',~
+ but~this~model~is~not~set~up.
+ }
+\__msg_kernel_new:nnnn { color } { unknown-color }
+ { Unknown~color~'#1'. }
+ {
+ LaTeX~has~been~asked~to~use~a~color~named~'#1',~
+ but~this~has~never~been~defined.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the latex3-commits
mailing list