diff options
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3color.dtx')
-rw-r--r-- | macros/latex/contrib/l3kernel/l3color.dtx | 142 |
1 files changed, 122 insertions, 20 deletions
diff --git a/macros/latex/contrib/l3kernel/l3color.dtx b/macros/latex/contrib/l3kernel/l3color.dtx index 8fc7268cdb..33b28721ed 100644 --- a/macros/latex/contrib/l3kernel/l3color.dtx +++ b/macros/latex/contrib/l3kernel/l3color.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-08-05} +% \date{Released 2022-08-23} % % \maketitle % @@ -95,6 +95,7 @@ % \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 @@ -118,6 +119,20 @@ % \end{itemize} % All interface models are internally stored as |rgb|. % +% Finally, there are a small number of models which are parsed to allow +% data transfer from \pkg{xcolor} but which should not be used by end-users. +% These are +% \begin{itemize} +% \item \texttt{cmy} Cyan-magenta-yellow color with three axes, one for +% each of the components; converted to |cmyk| +% \item \texttt{tHsb} \enquote{Tuned} 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; converted to |rgb| using the +% standard tuning map defined by \pkg{xcolor} +% \item \texttt{\&spot} Spot color tint with one value; treated as a gray +% tint as spot color data is not available for extraction +% \end{itemize} +% % 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}. @@ -235,6 +250,15 @@ % it to be saved to a name. % \end{function} % +% \begin{function}[EXP, pTF, added = 2022-08-12]{\color_if_exist:n} +% \begin{syntax} +% \cs{color_if_exist:n} \Arg{name} +% \cs{color_if_exist:n} \Arg{name} \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests whether \meta{name} is currently defined to provide a color +% specification. +% \end{function} +% % \begin{function}[added = 2021-05-11]{\color_show:n, \color_log:n} % \begin{syntax} % \cs{color_show:n} \Arg{name} @@ -545,10 +569,7 @@ % current color \enquote{now}. % \begin{macrocode} \cs_new_protected:Npn \color_ensure_current: - { - \@@_backend_pickup:N \l_@@_current_tl - \@@_select:N \l_@@_current_tl - } + { \@@_select:N \l_@@_current_tl } % \end{macrocode} % \end{macro} % @@ -625,12 +646,12 @@ % % \subsection{Utility functions} % -% \begin{macro}[TF, EXP]{\@@_if_defined:n} +% \begin{macro}[pTF, EXP]{\color_if_exist:n} % A simple wrapper to avoid needing to have the lookup repeated in too many % places.To guard against a color created in a group, we need to test for % entries in the |prop|. % \begin{macrocode} -\prg_new_conditional:Npnn \@@_if_defined:n #1 { T, F, TF } +\prg_new_conditional:Npnn \color_if_exist:n #1 { p , T, F, TF } { \prop_if_exist:cTF { l_@@_named_ #1 _prop } { @@ -679,6 +700,7 @@ % \@@_convert_rgb_rgb:w % \@@_convert_rgb_cmyk:w % } +% \begin{macro}[EXP]{\@@_convert_rgb_cmyk:nnn} % \begin{macro}[EXP]{\@@_convert_rgb_cmyk:nnnn} % Model conversion is carried out using standard formulae for base models, % as described in the manual for \pkg{xcolor} (see also the \emph{PostScript @@ -742,18 +764,28 @@ % 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. +% tiny, we simplify and treat those two concepts as no-ops. To allow code +% sharing with parsing of |cmy| values, we have an intermediate function +% here (\cs{@@_convert_rgb_cmyk:nnn}) which actually takes |cmy| values +% as input. % \begin{macrocode} \cs_new:Npn \@@_convert_rgb_cmyk:w #1 ~ #2 ~ #3 \s_@@_stop { - \exp_args:Nf \@@_convert_rgb_cmyk:nnnn - { \fp_eval:n { min ( 1 - #1 , 1 - #2 , 1 - #3 ) } } {#1} {#2} {#3} + \exp_args:Neee \@@_convert_rgb_cmyk:nnn + { \fp_eval:n { 1 - #1 } } + { \fp_eval:n { 1 - #2 } } + { \fp_eval:n { 1 - #3 } } + } +\cs_new:Npn \@@_convert_rgb_cmyk:nnn #1#2#3 + { + \exp_args:Ne \@@_convert_rgb_cmyk:nnnn + { \fp_eval:n { min( #1, #2 , #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 + \fp_eval:n { min ( 1 , max ( 0 , #2 - #1 ) ) } \c_space_tl + \fp_eval:n { min ( 1 , max ( 0 , #3 - #1 ) ) } \c_space_tl + \fp_eval:n { min ( 1 , max ( 0 , #4 - #1 ) ) } \c_space_tl #1 } \cs_new:Npn \@@_convert_cmyk_gray:w #1 ~ #2 ~ #3 ~ #4 \s_@@_stop @@ -771,6 +803,7 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % % \subsection{Color expressions} % @@ -811,7 +844,6 @@ % \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 } @@ -827,7 +859,7 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_parse_aux:nN #1#2 { - \@@_if_defined:nTF {#1} + \color_if_exist:nTF {#1} { \@@_parse_set_eq:Nn #2 {#1} } { \@@_parse:Nw #2#1 ! \s_@@_stop } \@@_check_model:N #2 @@ -865,7 +897,7 @@ } \cs_new_protected:Npn \@@_parse:Nw #1#2 ! #3 \s_@@_stop { - \@@_if_defined:nTF {#2} + \color_if_exist:nTF {#2} { \tl_if_blank:nTF {#3} { \@@_parse_set_eq:Nn #1 {#2} } @@ -938,7 +970,7 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_parse_loop:nn #1#2 { - \@@_if_defined:nTF {#2} + \color_if_exist:nTF {#2} { \@@_extract:nNN {#2} \l_@@_next_model_tl \l_@@_next_value_tl \tl_if_eq:NNF \l_@@_model_tl \l_@@_next_model_tl @@ -1255,6 +1287,70 @@ % \end{macro} % \end{macro} % +% \begin{macro}{\@@_parse_model_cmy:w} +% Simply pass data to the conversion functions. +% \begin{macrocode} +\cs_new:Npn \@@_parse_model_cmy:w #1 , #2 , #3 , #4 \s_@@_stop + { + { cmyk } + { \@@_convert_rgb_cmyk:nnn {#1} {#2} {#3} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_model_tHsb:w} +% \begin{macro}{\@@_parse_model_tHsb:n} +% \begin{macro}{\@@_parse_model_tHsb:nw} +% There are three stages to the process here: bring the |tH| argument into +% the normal range, divide through to get to |hsb| and finally convert that +% to |rgb|. The final stage can be delegated to the parsing function for +% |hsb|, and the conversion from |Hsb| to |hsb| is trivial, so the main focus +% here is the first stage. We use a simple expandable loop to do the work, +% and we implement the equation given in the \pkg{xcolor} manual +% (number~85 there) as a simple expression. +% \begin{macrocode} +\cs_new:Npn \@@_parse_model_tHsb:w #1 , #2 , #3 , #4 \s_@@_stop + { + \exp_args:Ne \@@_parse_model_hsb:nnn + { \@@_parse_model_tHsb:n {#1} } {#2} {#3} + } +\cs_new:Npn \@@_parse_model_tHsb:n #1 + { + \@@_parse_model_tHsb:nw {#1} + 0 , 0 ; + 60 , 30 ; + 120 , 60 ; + 180 , 120 ; + 210 , 180 ; + 240 , 240 ; + 360 , 360 ; + \q_recursion_tail , ; + \q_recursion_stop + } +\cs_new:Npn \@@_parse_model_tHsb:nw #1 #2 , #3 ; #4 , #5 ; + { + \quark_if_recursion_tail_stop_do:nn {#4} { 0 } + \fp_compare:nNnTF {#1} > {#4} + { \@@_parse_model_tHsb:nw {#1} #4 , #5 ; } + { + \use_i_delimit_by_q_recursion_stop:nw + { \fp_eval:n { ((#1 - #2) / (#4 - #2) * (#5 - #3) + #3) / 360 } } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_model_&spot:w} +% We cannot extract data here from that passed by \pkg{xcolor}, so +% we fall back on a black tint. +% \begin{macrocode} +\cs_new:cpn { @@_parse_model_&spot:w } #1 , #2 \s_@@_stop + { { gray } { #1 } } +% \end{macrocode} +% \end{macro} +% % \subsection{Selecting colors (and color models)} % % \begin{variable}{\l_color_fixed_model_tl} @@ -1738,7 +1834,7 @@ } \cs_new_protected:Npn \color_set_eq:nn #1#2 { - \@@_if_defined:nTF {#2} + \color_if_exist:nTF {#2} { \tl_clear_new:c { l_@@_named_ #1 _tl } \prop_clear_new:c { l_@@_named_ #1 _prop } @@ -2932,7 +3028,7 @@ #1 { color } { show } {#2} { - \@@_if_defined:nT {#2} + \color_if_exist:nT {#2} { \exp_args:Nv \@@_show:n { l_@@_named_ #2 _tl } \prop_map_function:cN @@ -3048,6 +3144,12 @@ \\ \\ key~was~given~with~the~correct~information. } +\msg_new:nnn { color } { unhandled-model } + { + Unhandled~color~model~in~LaTeX2e~value~"#1": + \\ \\ + falling~back~on~grayscale. + } \msg_new:nnnn { color } { unknown-color } { Unknown~color~'#1'. } { @@ -3087,7 +3189,7 @@ LaTeX~has~been~asked~to~create~a~new~color~model~called~'#1',~ but~this~type~of~model~was~never~set~up. } -\prop_gput:Nnn \g_msg_module_name_prop { color } { LaTeX3 } +\prop_gput:Nnn \g_msg_module_name_prop { color } { LaTeX } \prop_gput:Nnn \g_msg_module_type_prop { color } { } % \end{macrocode} % |