diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx | 291 |
1 files changed, 235 insertions, 56 deletions
diff --git a/Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx b/Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx index 165313c04b8..a9a86daebb1 100644 --- a/Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx +++ b/Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2020-09-01} +% \date{Released 2020-09-11} % % \maketitle % @@ -311,57 +311,223 @@ % \begin{macro}{\@@_backend_select_separation:nn} % \begin{macrocode} \cs_new_protected:Npn \@@_backend_select_separation:nn #1#2 - { \@@_backend_select:n { setspotcolor ~ #1 ~ #2 } } + { \@@_backend_select:n { separation ~ #1 ~ #2 } } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_backend_separation_init:nnnnn} -% \begin{macro}{\@@_backend_separation_init:nnn} -% \begin{macro}[EXP]{\@@_backend_separation_init:n} +% \begin{macro} +% { +% \@@_backend_separation_init:nnnnn, +% \@@_backend_separation_init:nxxnn, +% \@@_backend_separation_init_aux:nnnnn +% } +% \begin{macro}[EXP] +% { +% \@@_backend_separation_init_/DeviceCMYK:nnn , +% \@@_backend_separation_init_/DeviceGray:nnn , +% \@@_backend_separation_init_/DeviceRGB:nnn +% } +% \begin{macro}[EXP]{\@@_backend_separation_init_Device:Nn} +% \begin{macro}[EXP]{\@@_backend_separation_init:nnn} +% \begin{macro}[EXP]{\@@_backend_separation_init_count:n} +% \begin{macro}[EXP]{\@@_backend_separation_init_count:w} +% \begin{macro}[EXP]{\@@_backend_separation_init:nnnn} % \begin{macro}[EXP]{\@@_backend_separation_init:w} -% \begin{macro}{\@@_backend_separation_init_cielab:nnnnn} -% \begin{macro}{\@@_backend_separation_init_cielab:n} +% \begin{macro}[EXP]{\@@_backend_separation_init:n} +% \begin{macro}[EXP]{\@@_backend_separation_init:nw} +% \begin{macro}{\@@_backend_separation_init_CIELAB:nnn} % Initialising here means creating a small header set up plus massaging % some data. This comes about as we have to deal with PDF-focussed data, % which makes most sense \enquote{higher-up}. The approach is based on -% ideas from \url{https://tex.stackexchange.com/q/560093}. +% ideas from \url{https://tex.stackexchange.com/q/560093} plus using +% the PostScript manual for other aspects. % \begin{macrocode} \cs_new_protected:Npx \@@_backend_separation_init:nnnnn #1#2#3#4#5 { \bool_if:NT \g__kernel_backend_header_bool { \cs_if_exist:NTF \AtBeginDvi - { \AtBeginDvi } + { \exp_not:N \AtBeginDvi } { \use:n } { - \exp_not:N \@@_backend_separation_init:nnn - {#1} {#2} {#5} + \exp_not:N \@@_backend_separation_init_aux:nnnnn + {#1} {#2} {#3} {#4} {#5} } } } -\cs_new_protected:Npn \@@_backend_separation_init:nnn #1#2#3 +\cs_generate_variant:Nn \@@_backend_separation_init:nnnnn { nxx } +\cs_new_protected:Npn \@@_backend_separation_init_aux:nnnnn #1#2#3#4#5 { \__kernel_backend_literal:e { ! TeXDict ~ begin ~ - /color \int_use:N \g_@@_separation_int \c_space_tl - [#3] ~ aload ~ pop ~ ( \str_convert_pdfname:n {#1} ) ~ - find \@@_backend_separation_init:n {#2} customcolor ~ def ~ + /color \int_use:N \g_@@_separation_int + { + [ ~ + /Separation ~ ( \str_convert_pdfname:n {#1} ) ~ + [ ~ #2 ~ ] ~ + { + \cs_if_exist_use:cF { @@_backend_separation_init_ #2 :nnn } + { \@@_backend_separation_init:nnn } + {#3} {#4} {#5} + } + ] ~ setcolorspace + } ~ def ~ end } } +\cs_new:cpn { @@_backend_separation_init_ /DeviceCMYK :nnn } #1#2#3 + { \@@_backend_separation_init_Device:Nn 4 {#3} } +\cs_new:cpn { @@_backend_separation_init_ /DeviceGray :nnn } #1#2#3 + { \@@_backend_separation_init_Device:Nn 1 {#3} } +\cs_new:cpn { @@_backend_separation_init_ /DeviceRGB :nnn } #1#2#3 + { \@@_backend_separation_init_Device:Nn 2 {#3} } +\cs_new:Npn \@@_backend_separation_init_Device:Nn #1#2 + { + #2 ~ + \prg_replicate:nn {#1} + { #1 ~ index ~ mul ~ #1 ~ 1 ~ roll ~ } + \int_eval:n { #1 + 1 } ~ -1 ~ roll ~ pop + } +% \end{macrocode} +% For the generic case, we cannot use |/FunctionType 2| unfortunately, so +% we have to code that idea up in PostScript. Here, we will therefore assume +% that a range is \emph{always} given. First, we count values in each argument: +% at the backend level, we can assume there are always well-behaved with +% spaces present. +% \begin{macrocode} +\cs_new:Npn \@@_backend_separation_init:nnn #1#2#3 + { + \exp_args:Ne \@@_backend_separation_init:nnnn + { \@@_backend_separation_init_count:n {#2} } + {#1} {#2} {#3} + } +\cs_new:Npn \@@_backend_separation_init_count:n #1 + { \int_eval:n { 0 \@@_backend_separation_init_count:w #1 ~ \s_@@_stop } } +\cs_new:Npn \@@_backend_separation_init_count:w #1 ~ #2 \s_@@_stop + { + +1 + \tl_if_blank:nF {#2} + { \@@_backend_separation_init_count:w #2 \s_@@_stop } + } +% \end{macrocode} +% Now we implement the algorithm. In the terms in the PostScript manual, +% we have $\mathbf{N} = 1$ and $\mathbf{Domain} = [0~1]$, with +% $\mathbf{Range}$ as |#2|, $\mathbf{C0}$ as |#3| and $\mathbf{C1}$ +% as |#4|, with the number of output components in |#1|. So all we have +% to do is implement $y_{i} = \mathbf{C0}_{i} + x(\mathbf{C1}_{i} - +% \mathbf{C0}_{i})$ with lots of stack manipulation, then check the +% ranges. That's done by adding everything to the stack first, then using +% the fact we know all of the offsets. As manipulating the stack is tricky, +% we start by re-formatting the $\mathbf{C0}$ and $\mathbf{C1}$ arrays to +% be interleaved, and add a \texttt{0} to each pair: this is used +% to keep the stack of constant length while we are doing the first pass of +% mathematics. We then working through that list, calculating from the +% last to the first value before tidying up by removing all of the input +% values. We do that by first copying all of the final $y$ values to the +% end of the stack, then rolling everything so we can pop the now-unneeded +% material. +% \begin{macrocode} +\cs_new:Npn \@@_backend_separation_init:nnnn #1#2#3#4 + { + \@@_backend_separation_init:w #3 ~ \s_@@_stop #4 ~ \s_@@_stop + \prg_replicate:nn {#1} + { + pop ~ 1 ~ index ~ neg ~ 1 ~ index ~ add ~ + \int_eval:n { 3 * #1 } ~ index ~ mul ~ + 2 ~ index ~ add ~ + \int_eval:n { 3 * #1 } ~ #1 ~ roll ~ + } + \int_step_function:nnnN {#1} { -1 } { 1 } + \@@_backend_separation_init:n + \int_eval:n { 4 * #1 + 1 } ~ #1 ~ roll ~ + \prg_replicate:nn { 3 * #1 + 1 } { pop ~ } + \tl_if_blank:nF {#2} + { \@@_backend_separation_init:nw {#1} #2 ~ \s_@@_stop } + } +\cs_new:Npn \@@_backend_separation_init:w + #1 ~ #2 \s_@@_stop #3 ~ #4 \s_@@_stop + { + #1 ~ #3 ~ 0 ~ + \tl_if_blank:nF {#2} + { \@@_backend_separation_init:w #2 \s_@@_stop #4 \s_@@_stop } + } \cs_new:Npn \@@_backend_separation_init:n #1 + { \int_eval:n { #1 * 2 } ~ index ~ } +% \end{macrocode} +% Finally, we deal with the range limit if required. This is handled +% by splitting the range into pairs. It's then just a question of doing +% the comparisons, this time dropping everything except the desired +% result. +% \begin{macrocode} +\cs_new:Npn \@@_backend_separation_init:nw #1#2 ~ #3 ~ #4 \s_@@_stop { - \@@_backend_separation_init:w #1 /Device #1 /Device \s_@@_stop + #2 ~ #3 ~ + 2 ~ index ~ 2 ~ index ~ lt ~ + { ~ pop ~ exch ~ pop ~ } ~ + { ~ + 2 ~ index ~ 1 ~ index ~ gt ~ + { ~ exch ~ pop ~ exch ~ pop ~ } ~ + { ~ pop ~ pop ~ } ~ + ifelse ~ + } + ifelse ~ + #1 ~ 1 ~ roll ~ + \tl_if_blank:nF {#4} + { \@@_backend_separation_init:nw {#1} #4 \s_@@_stop } } -\cs_new:Npn \@@_backend_separation_init:w #1 /Device #2 /Device #3 \s_@@_stop - { \str_lowercase:n {#2} } % \end{macrocode} -% Currently no CIELAB support. +% CIELAB support uses the detail from the PostScript reference, page 227; +% other than that block of PostScript, this is the same as for PDF-based +% routes. % \begin{macrocode} -\cs_new_protected:Npn \@@_backend_separation_init_cielab:nnnnn #1#2#3#4#5 { } -\cs_new_protected:Npn \@@_backend_separation_init_cielab:n #1 { } +\cs_new_protected:Npn \@@_backend_separation_init_CIELAB:nnn #1#2#3 + { + \@@_backend_separation_init:nxxnn + {#2} + { + /CIEBasedABC ~ + << ~ + /RangeABC ~ [ ~ \c_@@_model_range_CIELAB_tl \c_space_tl ] ~ + /DecodeABC ~ + [ ~ + { ~ 16 ~ add ~ 116 ~ div ~ } ~ bind ~ + { ~ 500 ~ div ~ } ~ bind ~ + { ~ 200 ~ div ~ } ~ bind ~ + ] ~ + /MatrixABC ~ [ ~ 1 ~ 1 ~ 1 ~ 1 ~ 0 ~ 0 ~ 0 ~ 0 ~ -1 ~ ] ~ + /DecodeLMN ~ + [ ~ + { ~ + dup ~ 6 ~ 29 ~ div ~ ge ~ + { ~ dup ~ dup ~ mul ~ mul ~ ~ } ~ + { ~ 4 ~ 29 ~ div ~ sub ~ 108 ~ 841 ~ div ~ mul ~ } ~ + ifelse ~ + 0.9505 ~ mul ~ + } ~ bind ~ + { ~ + dup ~ 6 ~ 29 ~ div ~ ge ~ + { ~ dup ~ dup ~ mul ~ mul ~ } ~ + { ~ 4 ~ 29 ~ div ~ sub ~ 108 ~ 841 ~ div ~ mul ~ } ~ + ifelse ~ + } ~ bind ~ + { ~ + dup ~ 6 ~ 29 ~ div ~ ge ~ + { ~ dup ~ dup ~ mul ~ mul ~ } ~ + { ~ 4 ~ 29 ~ div ~ sub ~ 108 ~ 841 ~ div ~ mul ~ } ~ + ifelse ~ + 1.0890 ~ mul ~ + } ~ bind + ] ~ + /WhitePoint ~ + [ ~ \tl_use:c { c_@@_model_whitepoint_CIELAB_ #1 _tl } ~ ] ~ + >> + } + { \c_@@_model_range_CIELAB_tl } + { 100 ~ 0 ~ 0 } + {#3} + } % \end{macrocode} % \end{macro} % \end{macro} @@ -369,6 +535,11 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % \begin{macrocode} %</dvips> @@ -386,16 +557,13 @@ % \end{macro} % % \begin{macro} -% {\@@_backend_separation_init:nnnnn, \@@_backend_separation_init_cielab:nnnnn} -% \begin{macro}{\@@_backend_separation_init_cielab:n} +% {\@@_backend_separation_init:nnnnn, \@@_backend_separation_init_CIELAB:nnn} % No support at present. % \begin{macrocode} \cs_new_protected:Npn \@@_backend_separation_init:nnnnn #1#2#3#4#5 { } -\cs_new_protected:Npn \@@_backend_separation_init_cielab:nnnnn #1#2#3#4#5 { } -\cs_new_protected:Npn \@@_backend_separation_init_cielab:n #1 { } +\cs_new_protected:Npn \@@_backend_separation_init_CIELAB:nnnnnn #1#2#3 { } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macrocode} %</dvisvgm> @@ -406,6 +574,7 @@ % \end{macrocode} % % \begin{macro}{\@@_backend_select_separation:nn} +% \begin{macro}{\@@_backend_select:n} % Different syntaxes here as the stacks are accessed very differently. % \begin{macrocode} \cs_new_protected:Npn \@@_backend_select_separation:nn #1#2 @@ -415,32 +584,42 @@ %<*luatex|pdftex> { \@@_backend_select:n { /#1 ~ cs ~ /#1 ~ CS ~ #2 ~ scn ~ #2 ~ SCN } } %</luatex|pdftex> +%<*dvipdfmx|xetex> +\cs_new_protected:Npn \@@_backend_select:n #1 + { + \__kernel_backend_literal:n { pdf: bc ~ #1 } + \group_insert_after:N \@@_backend_reset: + } +%</dvipdfmx|xetex> % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}{\@@_backend_separation_init:nnnnn} % \begin{macro}{\@@_backend_separation_init:n} -% \begin{macro}{\@@_backend_separation_init_cielab:nnnnn} -% \begin{macro}{\@@_backend_separation_init_cielab:n} +% \begin{macro}{\@@_backend_separation_init_CIELAB:nnn} % 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}. % For \texttt{dvipdfmx}/\XeTeX{}, the backend does most of the work so we need a -% simplified version. +% simplified version. We use a separate object for the tint transformation +% following the model in the PDF reference. % \begin{macrocode} \cs_new_protected:Npn \@@_backend_separation_init:nnnnn #1#2#3#4#5 { + \pdf_object_now:nx { dict } + { + /FunctionType ~ 2 + /Domain ~ [0 ~ 1] + \tl_if_blank:nF {#3} { /Range ~ [#3] } + /C0 ~ [#4] ~ + /C1 ~ [#5] /N ~ 1 + } \@@_backend_separation_init:n { /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 - >> + \pdf_object_last: } %<*luatex|pdftex> \use:x @@ -459,7 +638,7 @@ %<*dvipdfmx|xetex> \__kernel_backend_literal:x { - pdf:obj ~ @ color \int_use:N \g_@@_separation_int \c_space_tl + pdf:obj ~ @color \int_use:N \g_@@_separation_int \c_space_tl [#1] } %</dvipdfmx|xetex> @@ -471,37 +650,37 @@ % 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 \@@_backend_separation_init_cielab:nnnnn #1#2#3#4#5 +\cs_new_protected:Npn \@@_backend_separation_init_CIELAB:nnn #1#2#3 { + \pdf_object_if_exist:nF { @@_illuminant_CIELAB_ #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_CIELAB_tl ] + >> + } + } \@@_backend_separation_init:nnnnn {#2} - { \pdf_object_ref:n { @@_illuminant_cielab_ #1 } } - { \c_@@_model_range_lab_tl } + { \pdf_object_ref:n { @@_illuminant_CIELAB_ #1 } } + { \c_@@_model_range_CIELAB_tl } { 100 ~ 0 ~ 0 } - { #3 ~ #4 ~ #5 } + {#3} } \cs_if_exist:NF \pdf_object_now:nn - { \cs_gset_protected:Npn \@@_backend_separation_init_cielab:nnnnn #1#2#3#4#5 { } } -\cs_new_protected:Npn \@@_backend_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_gset_protected:Npn \@@_backend_separation_init_CIELAB:nnn #1#2#3 + { } } -\cs_if_exist:NF \pdf_object_new:nn - { \cs_gset_protected:Npn \@@_backend_separation_init_cielab:n #1 { } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} % % \begin{macrocode} %</dvipdfmx|luatex|pdftex|xetex> |