summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3experimental/l3color.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-09-03 03:01:14 +0000
committerNorbert Preining <norbert@preining.info>2020-09-03 03:01:14 +0000
commitfc732340b62b41cedbe82bcb3675a86c65343a21 (patch)
treec490d1d57d300b1024517118f6e494d68eae5bcd /macros/latex/contrib/l3experimental/l3color.dtx
parent66aedee32b96d68acc7b854602552c75ef261973 (diff)
CTAN sync 202009030301
Diffstat (limited to 'macros/latex/contrib/l3experimental/l3color.dtx')
-rw-r--r--macros/latex/contrib/l3experimental/l3color.dtx246
1 files changed, 146 insertions, 100 deletions
diff --git a/macros/latex/contrib/l3experimental/l3color.dtx b/macros/latex/contrib/l3experimental/l3color.dtx
index 42151e2a41..ec8266d06f 100644
--- a/macros/latex/contrib/l3experimental/l3color.dtx
+++ b/macros/latex/contrib/l3experimental/l3color.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Released 2020-08-07}
+% \date{Released 2020-09-01}
%
% \maketitle
%
@@ -59,7 +59,7 @@
% 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.
+% \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
@@ -71,31 +71,38 @@
% the components
% \item \texttt{cmyk} Cyan-magenta-yellow-black color, with four axes, one for
% each of the components
-% \item \texttt{spot} Spot color, with one value, the name of the color
-% (see \url{https://helpx.adobe.com/indesign/using/spot-process-colors.html}
-% for details of the use of spot colors in print)
% \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, integer
-% in the range $[0,360]$ for hue, integer values in the range $[0,255]$ 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|.
%
-% Additional models may be created to allow mixing of spot colors
+% 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 spot color support.
+% 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
@@ -327,7 +334,7 @@
% \meta{tl}.
% \end{function}
%
-% \begin{function}{\color_export:nnN}
+% \begin{function}{\color_export:nnnN}
% \begin{syntax}
% \cs{color_export:nnnN} \Arg{model} \Arg{value(s)} \Arg{format} \Arg{tl}
% \end{syntax}
@@ -405,7 +412,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3color}{2020-08-07}{}
+\ProvidesExplPackage{l3color}{2020-09-01}{}
{L3 Experimental color support}
% \end{macrocode}
%
@@ -593,14 +600,12 @@
% \begin{macrocode}
\cs_new_protected:Npx \@@_parse:nN #1#2
{
-%<*package>
\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 }
-%</package>
\exp_not:N \exp_args:Ne \exp_not:N \@@_parse_aux:nN
{ \exp_not:N \tl_to_str:n {#1} } #2
}
@@ -822,11 +827,10 @@
% \begin{macro}[EXP]
% {
% \@@_parse_model_gray:w, \@@_parse_model_rgb:w,
-% \@@_parse_model_cmyk:w, \@@_parse_model_spot:w
+% \@@_parse_model_cmyk:w
% }
% \begin{macro}[EXP]{\@@_parse_number:n}
% \begin{macro}[EXP]{\@@_parse_number:w}
-% \begin{macro}[EXP]{\@@_parse_spot_aux: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
@@ -850,13 +854,6 @@
\@@_parse_number:n {#4}
}
}
-\cs_new:Npn \@@_parse_model_spot:w #1 , #2 \s_@@_stop
- {
- { spot }
- { \@@_parse_spot_aux:w #1 ! 100 ! \s_@@_stop }
- }
-\cs_new:Npn \@@_parse_spot_aux:w #1 ! #2 ! #3 \s_@@_stop
- { #1 ~ \fp_eval:n { #2 / 100 } }
\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
@@ -865,14 +862,34 @@
% \end{macro}
% \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 } }
@@ -923,9 +940,9 @@
\cs_new:Npn \@@_parse_model_HSB:w #1 , #2 , #3 , #4 \s_@@_stop
{
\exp_args:Neee \@@_parse_model_hsb:nnn
- { \fp_eval:n {#1 / 360} }
- { \fp_eval:n {#2 / 255} }
- { \fp_eval:n {#3 / 255} }
+ { \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 }
@@ -948,6 +965,83 @@
}
}
% \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)}
@@ -1127,6 +1221,7 @@
% \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
@@ -1189,15 +1284,28 @@
}
}
}
-\cs_new_protected:Npn \color_set:nnn #1#2#3
+\cs_new_protected:Npx \color_set:nnn #1#2#3
{
- \str_if_eq:nnF {#1} { . }
+ \exp_not:N \str_if_eq:nnF {#1} { . }
{
\tl_clear_new:c { l_@@_named_ #1 _tl }
\prop_clear_new:c { l_@@_named_ #1 _prop }
- \@@_set_loop:nw {#1} #2 / / \s_@@_mark #3 / / \s_@@_stop
+ \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
{
@@ -1242,9 +1350,10 @@
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% A small set of colors are always defined.
-% \begin{macrocode}
+% \begin{macrocode}
\color_set:nnn { black } { gray } { 0 }
\color_set:nnn { white } { gray } { 1 }
\color_set:nnn { cyan } { cmyk } { 1 , 0 , 0 , 0 }
@@ -1253,7 +1362,7 @@
\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}
+% \end{macrocode}
%
% \begin{variable}{\l_@@_named_._prop, \l_@@_named_._tl}
% A special named color: this is always defined though not fixed in
@@ -1457,9 +1566,6 @@
% \begin{macro}{\@@_model_convert:nnn}
% \begin{macro}{\@@_model_separation_cielab:nnnnnn}
% \begin{macro}{\@@_model_separation_cielab:nnnnnnn}
-% \begin{macro}{\@@_model_separation_init:nnnnn}
-% \begin{macro}{\@@_model_separation_init_cielab:n}
-% \begin{macro}{\@@_model_separation_init_cielab:nnnnn}
% 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
@@ -1590,7 +1696,7 @@
}
\@@_model_convert:nnn {#1} { cmyk } { rgb }
\@@_model_convert:nnn {#1} { cmyk } { gray }
- \@@_model_separation_init:nnnnn {#2} { /DeviceCMYK } { }
+ \@@_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
@@ -1603,7 +1709,7 @@
}
\@@_model_convert:nnn {#1} { rgb } { cmyk }
\@@_model_convert:nnn {#1} { rgb } { gray }
- \@@_model_separation_init:nnnnn {#2} { /DeviceRGB } { }
+ \@@_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
@@ -1623,7 +1729,7 @@
\fp_eval:n {##1 * #3} ~
\fp_eval:n {##1 * #3}
}
- \@@_model_separation_init:nnnnn {#2} { /DeviceGray } { } { 0 } {#3}
+ \@@_backend_separation_init:nnnnn {#2} { /DeviceGray } { } { 0 } {#3}
}
% \end{macrocode}
% Generic model conversion \emph{via} an alternative intermediate.
@@ -1665,8 +1771,8 @@
{
\tl_if_exist:cTF { c_@@_model_whitepoint_cielab_ #1 _tl }
{
- \@@_model_separation_init_cielab:n {#1}
- \@@_model_separation_init_cielab:nnnnn {#2} {#3} {#4} {#5} {#6}
+ \@@_backend_separation_init_cielab:n {#1}
+ \@@_backend_separation_init_cielab:nnnnn {#2} {#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
@@ -1680,66 +1786,6 @@
}
}
% \end{macrocode}
-% Initialising the PDF structures needs two parts: creating an object
-% containing the \enquote{real} name of the Separation, then adding a reference
-% to that to each page. The latter uses the internal name of the \texttt{cs}.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_separation_init:nnnnn #1#2#3#4#5
- {
- \pdf_object_now:nx { array }
- {
- /Separation
- / \str_convert_pdfname:n {#1} ~ #2 ~
- <<
- /FunctionType ~ 2
- /Domain ~ [0 ~ 1]
- \tl_if_blank:nF {#3} { /Range ~ [#3] }
- /C0 ~ [#4] ~
- /C1 ~ [#5] /N ~ 1
- >>
- }
- \use:x
- {
- \pdfcoredict_gput:nnn
- { Page / Resources / ColorSpace }
- { color \int_use:N \g_@@_separation_int }
- { \pdf_object_last: }
- }
- }
-\cs_if_exist:NF \pdf_object_now:nn
- { \cs_gset_protected:Npn \@@_model_separation_init:nnnnn #1#2#3#4#5 { } }
-% \end{macrocode}
-% For CIELAB colors, we need one object per document for the illuminant,
-% plus initialisation of the color space referencing that object.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_separation_init_cielab:n #1
- {
- \pdf_object_new:nn { @@_illuminant_cielab_ #1 } { array }
- \pdf_object_write:nx { @@_illuminant_cielab_ #1 }
- {
- /Lab ~
- <<
- /WhitePoint ~
- [ \tl_use:c { c_@@_model_whitepoint_cielab_ #1 _tl } ]
- /Range ~ [ \c_@@_model_range_lab_tl ]
- >>
- }
- }
-\cs_if_exist:NF \pdf_object_new:nn
- { \cs_gset_protected:Npn \@@_model_separation_init_cielab:n #1 { } }
-\cs_new_protected:Npn \@@_model_separation_init_cielab:nnnnn #1#2#3#4#5
- {
- \@@_model_separation_init:nnnnn
- {#2}
- { \pdf_object_ref:n { @@_illuminant_cielab_ #1 } }
- { \c_@@_model_range_lab_tl }
- { 100 ~ 0 ~ 0 }
- { #3 ~ #4 ~ #5 }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}