summaryrefslogtreecommitdiff
path: root/macros/optex/base/colors.opm
blob: 36afcb3862fc07dc70782de4355c100314be4af7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
%% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \colordef {Colors <2022-03-07>} % preloaded in format

   \_doc -----------------------------
   The basic colors in CMYK
   \`\Blue` \`\Red` \`\Brown` \`\Green` \`\Yellow` \`\Cyan` \`\Magenta`
   \`\Grey` \`\LightGrey` \`\White` and \`\Black`
   are declared here.
   \_cod -----------------------------

\_def\Blue      {\_setcmykcolor{1 1 0 0}}
\_def\Red       {\_setcmykcolor{0 1 1 0}}
\_def\Brown     {\_setcmykcolor{0 .67 .67 .5}}
\_def\Green     {\_setcmykcolor{1 0 1 0}}
\_def\Yellow    {\_setcmykcolor{0 0 1 0}}
\_def\Cyan      {\_setcmykcolor{1 0 0 0}}
\_def\Magenta   {\_setcmykcolor{0 1 0 0}}
\_def\Grey      {\_setcmykcolor{0 0 0 .5}}
\_def\LightGrey {\_setcmykcolor{0 0 0 .2}}
\_def\White     {\_setgreycolor{1}}
\_def\Black     {\_setgreycolor{0}}

   \_doc -----------------------------
   By default, the \`\setcmykcolor` \`\setrgbcolor` and \`\setgreycolor`
   macros with `{<componetns>}` parameter
   expand to \^`\_setcolor``{<color-data>}{<fill-op>}{<stroke-op>}` where
   <color-data> is <R> <G> <B> or <C> <M> <Y> <K> or <G> and
   <fill-op> is color operator for filling, <stroke-op> is color operator
   for stroking.
   \_cod -----------------------------

\_def\_setcmykcolor#1{\_setcolor{#1}kK}
\_def\_setrgbcolor#1{\_setcolor{#1}{rg}{RG}}
\_def\_setgreycolor#1{\_setcolor{#1}gG}
\_public \setcmykcolor \setrgbcolor \setgreycolor ;

   \_doc -----------------------------
   The \`\onlyrgb` declaration redefines \^`\setcmykcolor` to do conversion
   to RGB just before \^`\_setcolor` is used.
   The \`\onlycmyk` declaration redefines \^`\setrgbcolor` to do conversion
   to CMYK just before \^`\_setcolor` is used.
   Moreover, \^`\onlyrgb` re-defines three basic RGB
   colors for RGB color space and re-declares \^`\colordef` as \^`\rgbcolordef`.
   \_cod -----------------------------

\_def\_onlyrgb{\_def\Red{\_setrgbcolor{1 0 0}}%
   \_def\Green{\_setrgbcolor{0 1 0}}\_def\Blue{\_setrgbcolor{0 0 1}}%
   \_let\_colordef=\_rgbcolordef
   \_def\_setrgbcolor##1{\_setcolor{##1}{rg}{RG}}%
   \_def\_setcmykcolor##1{\_ea\_setcolor\_ea{\_expanded{\_cmyktorgb ##1 ;}}{rg}{RG}}%
   \_public \colordef \setrgbcolor \setcmykcolor ;}
\_def\_onlycmyk{%
   \_let\_colordef=\_cmykcolordef
   \_def\_setrgbcolor##1{\_ea\_setcolor\_ea{\_expanded{\_rgbtocmyk ##1 ;}}kK}%
   \_def\_setcmykcolor##1{\_setcolor{##1}kK}%
   \_public \colordef \setrgbcolor \setcmykcolor ;}
\_public \onlyrgb \onlycmyk ;

   \_doc -----------------------------
   The \`\_colorattr` for coloring is allocated and
   \`\_setcolor``{<color-data>}{<fill-op>}{<stroke-op>}` is defined here.
   This macro does `\_colorattr=`\`\_colorcnt` if the <color data> was not used
   before and prepare mapping from this integer value to the <color data>
   and increments \^`\_colorcnt`.
   If the <color data> were used already, then \^`\_setcolor`
   does `\_colorattr=<stored-value>`.
   This work is done by the \`\_translatecolor` macro. The following mapping
   macros are created:
   \begtt \catcode`<=13
   \_color::<data> <fill-op>    ... expands to used <attribute-value>
   \_color:<attribute-value>    ... expands to <data> <fill-op>
   \_color-s:<attribute-value>  ... expands to <data> <stroke-op>
   \endtt
   \_cod -----------------------------

\_newattribute \_colorattr
\_newcount \_colorcnt \_colorcnt=1 % allocations start at 1
\_protected\_def\_setcolor{\_colorprefix\_colorattr=\_translatecolor}
\_def\_translatecolor#1#2#3{\_ifcsname _color::#1 #2\_endcsname\_lastnamedcs\_relax
   \_else
      \_colorcnt
      \_sxdef{_color::#1 #2}{\_the\_colorcnt}%
      \_sxdef{_color:\_the\_colorcnt}{#1 #2}%
      \_sxdef{_color-s:\_the\_colorcnt}{#1 #3}%
      \_incr \_colorcnt
   \_fi
}
% Black is the default color.
\_sdef{_color::0 g}{0}
\_sdef{_color:0}{0 g}
\_sdef{_color-s:0}{0 G}

   \_doc -----------------------------
   We support concept of non-local color, i.e. all changes of the color
   attribute are global by setting \`\_colorprefix` to `\global`.
   \`\localcolor` is the default, i.e.\ \^`\_colorprefix` is `\relax`.\nl
   You can write `\global\Red` if you want to have global setting of the
   color.
   \_cod -----------------------------

\_protected\_def \_localcolor   {\_let\_colorprefix=\_relax}
\_protected\_def \_nolocalcolor {\_let\_colorprefix=\_global}
\_public \localcolor \nolocalcolor ;
\_localcolor

   \_doc -----------------------------
   The attribute \`\_transpattr` is allocated and set by the
   \`\transparency``<number>` macro. If such level of the tranparency was
   never used in the document then
   \^`\addextgstate{tr<number>}`\code{\{<</ca X /CA X>>\}} is applied
   (where `X` is `(255-<number>)/255`).
   This information is used when shipout is processed (similarly as colors).
   It means `/tr<number> gs` is inserted when the attribute is changed.\nl
   \`\_resetattrs` resets the \^`\_colorattr` and \^`\_transpattr`
   to their initial value `-"7FFFFFFF`.
   \_cod -----------------------------

\_newattribute\_transpattr
\_def\_transparency {\_afterassignment\_transparencyA \_transpattr}
\_def\_transparencyA{%
   \_ifnum\_transpattr<1 \_transpattr=\_noattr \_fi
   \_ifnum\_transpattr>255 \_opwarning{\_noexpand\transparency > 255 not allowed}%
       \_transpattr=\_noattr
   \_else
      \_ifcsname _transp:\_the\_transpattr\_endcsname \_else
         \_edef\_transpv{\_expr{(255-\_the\_transpattr)/255}}%
         \_addextgstate{tr\_the\_transpattr}{<</ca \_transpv\_space /CA \_transpv>>}%
         \_sxdef{_transp:\_the\_transpattr}{}%
         \_ifcsname _transp:0\_endcsname \_else
            \_addextgstate{tr0}{<</ca 1 /CA 1>>}%
            \_sxdef{_transp:0}{}%
         \_fi
      \_fi
   \_fi
}
\_def\_thetransparency{\_ifnum \_transpattr=-"7FFFFFFF 0\_else \_the\_transpattr \_fi}
\_def\_resetattrs{\_colorattr=\_noattr \_transpattr=\_noattr}

\_public \transparency \thetransparency ;

   \_doc -----------------------------
   We use Lua codes for RGB to CMYK or CMYK to RGB conversions and for
   addition color components in the \^`\colordef` macro.
   The \`\_rgbtocmyk` `<R> <G> <B> ;` expands to `<C> <M> <Y> <K>` and
   the \`\_cmyktorgb` `<C> <M> <Y> <K> ;` expands to `<R> <G> <B>`.
   The \`\_colorcrop`, \`\_colordefFin` and \`\_douseK` are auxiliary macros
   used in the \^`\colordef`. The `\_colorcrop` rescales color components in order
   to they are in $[0,1]$ interval. The `\colordefFin` expands to the values
   accumulated in Lua code `color_C`, `color_M`, `color_Y` and `color_K`.
   The `\_douseK` applies \^`\useK` to CMYK components.
   \nl
   The `\_tocmyk:<rgb>` or `\_torgb:<cmyk>` control sequences (given by
   \^`\rgbcmykmap`) have precedence.
   \_cod -----------------------------

\_def\_rgbtocmyk #1 #2 #3 ;{\_trycs{_tocmyk:#1 #2 #3}{%
   \_ea \_stripzeros \_detokenize \_ea{\_directlua{
      local kr = math.max(#1,#2,#3)
      if (kr==0) then
         tex.print('0. 0. 0. 1 ;')
      else
         tex.print(string.format('\_pcent.3f \_pcent.3f \_pcent.3f \_pcent.3f ;',
            (kr-#1)/kr, (kr-#2)/kr, (kr-#3)/kr, 1-kr))
      end
}}}}
\_def\_cmyktorgb #1 #2 #3 #4 ;{\_trycs{_torgb:#1 #2 #3 #4}{%
   \_ea \_stripzeros \_detokenize \_ea{\_directlua{
      local kr = 1-#4
      tex.print(string.format('\_pcent.3f \_pcent.3f \_pcent.3f ;',
         (1-#1)*kr, (1-#2)*kr, (1-#3)*kr))
}}}}
\_def\_colorcrop{\_directlua{
   local m=math.max(color_C, color_M, color_Y, color_K)
   if (m>1) then
      color_C=color_C/m  color_M=color_M/m  color_Y=color_Y/m color_K=color_K/m
   end
}}
\_def\_colordefFin{\_colorcrop \_ea \_stripzeros \_detokenize \_ea{\_directlua{
   tex.print(string.format('\_pcent.3f \_pcent.3f \_pcent.3f \_pcent.3f ;',
      color_C, color_M, color_Y, color_K))
}}}
\_def\_douseK{\_colorcrop \_directlua{
   kr=math.min(color_C, color_M, color_Y)
   if (kr>=1) then
      color_C=0  color_M=0  color_Y=0  color_K=1
   else
      color_C=(color_C-kr)/(1-kr)  color_M=(color_M-kr)/(1-kr)
      color_Y=(color_Y-kr)/(1-kr)  color_K=math.min(color_K+kr,1)
   end
}}

   \_doc -----------------------------
   We have a problem with the `%.3f` directive in Lua code. It prints trailed
   zeros: (0.300 instead desired 0.3) but we want to save PDF file space. The macro
   \`\_stripzeros` removes these trailing zeros at the expand processor
   level. So `\_stripzeros 0.300 0.400 0.560 ;` expands to `.3 .4 .56`.
   \_cod -----------------------------

\_def\_stripzeros #1.#2 #3{\_ifx0#1\_else#1\_fi.\_stripzeroA #2 0 :%
    \_ifx;#3\_else \_space \_ea\_stripzeros\_ea#3\_fi}
\_def\_stripzeroA #10 #2:{\_ifx^#2^\_stripzeroC#1:\_else \_stripzeroB#1 0 :\_fi}
\_def\_stripzeroB #10 #2:{\_ifx^#2^\_stripzeroC#1:\_else #1\_fi}
\_def\_stripzeroC #1 #2:{#1}

   \_doc -----------------------------
   \`\rgbcmykmap` `{<R> <G> <B>}`\,`{<C> <M> <Y> <K>}` declares mapping from
   RGB to CMYK and from CMYK to RGB for given color. It has precedence
   before general formulae used in the \^`\_rgbtocmyk` and \^`\_cmyktorgb`
   macros. Note, that the values <R> <G> <B> <C> <M> <Y> <K> must be given
   exacly in the same format as in \^`\setcmykcolor` and \^`\setrgbcolor`
   parameters. For example, `0.5` or `.5` or `.50` are different values from
   point of view of this mapping.
   \_cod -----------------------------

\_def\_rgbcmykmap#1#2{\_sxdef{_torgb:#2}{#1}\_sxdef{_tocmyk:#1}{#2}}
\_public \rgbcmykmap ;

   \_doc -----------------------------
   The \`\rgbcolordef` and \`\cmykcolordef` use common macro
   \`\_commoncolordef` with different first four parameters.
   The `\_commoncolordef <selector><K><R><G><what-define>{<data>}` does the
   real work. It initializes the Lua variables for summation.
   It expands <data> in the group where color selectors have
   special meaning, then it adjusts the resulting string by \^`\replstring`
   and runs it. Example shows how the <data> are processed:
   \begtt \catcode`\<=13
   input <data>:  ".3\Blue + .6^\KhakiC \useK -\Black"
   expanded to:  ".3 !=K 1 1 0 0 +.6^!=R .804 .776 .45 \_useK -!=G 0"
   adjusted to:  "\_addcolor .3!=K 1 1 0 0 \_addcolor .6!^R .804 .776 .45
                  \_useK \_addcolor -1!=G 0"
   and this is processed.
   \endtt
   \`\_addcolor` `<coef.>!<mod><type>` expands to `\_addcolor:<mod><type> <coef>`
   for example it expands to `\_addcolor:=K <coef>` followed by one or three or four
   numbers (depending on <type>). <mod> is `=` (use as is) or `^` (use
   complementary color). <type> is `K` for CMYK, `R` for RGB and `G` for
   GREY color space. Uppercase <type> informs that `\cmykcolordef` is
   processed and lowercase <type> informs that `\rgbcolordef` is processed.
   All variants of commands `\_addcolor:<mod><type>` are defined. All of
   them expand to `\_addcolorA <v1> <v2> <v3> <v4>` which adds the values of Lua
   variables. The `\rgbcolordef` uses `\_addcolorA <R> <G> <B> 0` and
   `\cmkykcolordef` uses `\_addcolorA <C> <M> <Y> <K>`. So the Lua variable
   names are a little confusing when `\rgbcolordef` is processed.

   Next, `\_commoncolordef` saves resulting values from Lua to `\_tmpb`
   using `\_colordefFin`. If `\rgbcolordef` is processed, then we must to
   remove the last <K> component which is in the format `.0` in such case.
   The `\_stripK` macro does it.
   Finally, the `<what-define>` is defined as `<selector>{<expanded _tmpb>}`,
   for example `\_setcmykclor{1 0 .5 .3}`.
   \_cod -----------------------------

\_def\_rgbcolordef  {\_commoncolordef \_setrgbcolor  krg}
\_def\_cmykcolordef {\_commoncolordef \_setcmykcolor KRG}
\_def\_commoncolordef#1#2#3#4#5#6{%
  \_begingroup
     \_directlua{color_C=0 color_M=0 color_Y=0 color_K=0}%
     \_def\_setcmykcolor##1{!=#2 ##1 }%
     \_def\_setrgbcolor ##1{!=#3 ##1 }%
     \_def\_setgreycolor##1{!=#4 ##1 }%
     \_let\_useK=\_relax
     \_edef\_tmpb{+#6}%
     \_replstring\_tmpb{+ }{+}\_replstring\_tmpb{- }{-}%
     \_replstring\_tmpb{+}{\_addcolor}\_replstring\_tmpb{-}{\_addcolor-}%
     \_replstring\_tmpb{^!=}{!^}\_replstring\_tmpb{-!}{-1!}%
     \_ifx K#2\_let\_useK=\_douseK \_fi
     \_tmpb
     \_edef\_tmpb{\_colordefFin}%
     \_ifx k#2\_edef\_tmpb{\_ea\_stripK \_tmpb;}\_fi
  \_ea\_endgroup
  \_ea\_def\_ea#5\_ea{\_ea#1\_ea{\_tmpb}}%
}
\_def\_addcolor#1!#2#3{\_cs{addcolor:#2#3}#1}
\_def\_addcolorA #1 #2 #3 #4 #5 {%
   \_def\_tmpa{#1}\_ifx\_tmpa\_empty \_else \_edef\_tmpa{\_tmpa*}\_fi
   \_directlua{color_C=math.max(color_C+\_tmpa#2,0)
               color_M=math.max(color_M+\_tmpa#3,0)
               color_Y=math.max(color_Y+\_tmpa#4,0)
               color_K=math.max(color_K+\_tmpa#5,0)
}}
\_sdef{addcolor:=K}#1 #2 #3 #4 #5 {\_addcolorA #1 #2 #3 #4 #5 }
\_sdef{addcolor:^K}#1 #2 #3 #4 #5 {\_addcolorA #1 (1-#2) (1-#3) (1-#4) #5 }
\_sdef{addcolor:^G}#1 #2 {\_addcolorA #1 0 0 0 #2 }
\_sdef{addcolor:=G}#1 #2 {\_addcolorA #1 0 0 0 (1-#2) }
\_sdef{addcolor:=R}#1 #2 #3 #4 {%
   \_edef\_tmpa{\_noexpand\_addcolorA #1 \_rgbtocmyk #2 #3 #4 ; }\_tmpa
}
\_sdef{addcolor:^R}#1 #2 #3 #4 {\_cs{addcolor:=R}#1 (1-#2) (1-#3) (1-#4) }

\_sdef{addcolor:=k}#1 #2 #3 #4 #5 {%
   \_edef\_tmpa{\_noexpand\_addcolorA #1 \_cmyktorgb #2 #3 #4 #5 ; 0 }\_tmpa
}
\_sdef{addcolor:^k}#1 #2 #3 #4 #5 {\_cs{addcolor:=k}#1 (1-#2) (1-#3) (1-#4) #5 }
\_sdef{addcolor:^g}#1 #2 {\_addcolorA #1 (1-#2) (1-#2) (1-#2) 0 }
\_sdef{addcolor:=g}#1 #2 {\_addcolorA #1 #2 #2 #2 0 }
\_sdef{addcolor:=r}#1 #2 #3 #4 {\_addcolorA #1 #2 #3 #4 0 }
\_sdef{addcolor:^r}#1 #2 #3 #4 {\_addcolorA #1 (1-#2) (1-#3) (1-#4) 0 }
\_def\_stripK#1 .0;{#1}
\_let\_colordef=\_cmykcolordef  % default \_colordef is \_cmykcolordef

   \_doc -----------------------------
   Public versions of \`\colordef` and \`\useK` macros are declared using
   `\_def`, because the internal versions `\_colordef` and `\_useK` are
   changed during processing.
   \_cod -----------------------------

\_def \useK{\_useK}
\_def \colordef {\_colordef}
\_public \cmykcolordef \rgbcolordef ;

   \_doc -----------------------------
   The \LaTeX/ file `x11nam.def` is read by \`\morecolors`. The numbers
   0,1,2,3,4 are transformed to letters O, <none>, B, C, D in the name of the
   color. Colors defined already are not re-defined. The empty \`\_showcolor`
   macro should be re-defined for color catalog printing. For example:
   \begtt
   \def\vr{\vrule height10pt depth2pt width20pt}
   \def\_showcolor{\hbox{\tt\_bslash\_tmpb: \csname\_tmpb\endcsname \vr}\space\space}
   \begmulti 4 \typosize[10/14]
   \morecolors
   \endmulti
   \endtt
   \_cod -----------------------------

\_def\_morecolors{%
   \_long\_def\_tmp##1\preparecolorset##2##3##4##5{\_tmpa ##5;,,,;}
   \_def\_tmpa##1,##2,##3,##4;{\_ifx,##1,\_else
      \_def\_tmpb{##1}\_replstring\_tmpb{1}{}\_replstring\_tmpb{2}{B}%
      \_replstring\_tmpb{3}{C}\_replstring\_tmpb{4}{D}\_replstring\_tmpb{0}{O}%
      \_ifcsname \_tmpb\_endcsname \_else
          \_sdef{\_tmpb}{\_setrgbcolor{##2 ##3 ##4}}\_showcolor\_fi
      \_ea\_tmpa\_fi
   }
   \_ea\_tmp\_input x11nam.def
}
\_let\_showcolor=\_relax % re-define it if you want to print a color catalog
\_public \morecolors ;

\_endcode % -------------------------------------

\secc Basic concept

Setting of color in PDF is handled by graphics operators which change the
graphics context. Colors for fills/strokes are distinguished, but apart from
that, only one color is active at time and is used for all material drawn by
following graphics operators, until next color is set. Each PDF content (e.g.
page or form XObject) has its own graphics context, that is initialized from
zero. Hence we have different concept of selecting fonts in \TeX/ (it
depends on \TeX/ groups but does not depends on pages) and color handling in
PDF.

\TeX/ itself has no concept of colors. Colors have always been handled by
inserting whatsits (either using `\special` for DVI or using
`\pdfliteral`/`\pdfcolorstack` for PDF). It is very efficient and \TeX/ doesn't
even have to know anything about colors, but it is also problematic in many
ways.

That is the reason why we decided to change color handling from
`\pdfcolorstack` to \LuaTeX/ attributes in version 1.04 of \OpTeX. Using
attributes, the color setting behaves exactly like font selection from \TeX/
point of view: it respects \TeX/ groups, colors can span more pages,
independent colors can be set for `\insert`s, etc. Moreover, once a material is
created (using `\setbox` for example) then it has its fonts and its colors
frozen and you can rely on it when you are using e.g. `\unhbox`. There are no
internal whatsits for colors which can interfere with other typesetting
material. In the end something like setting text to red (`{\Red text}`) should
have the same nice behavior like setting text to bold (`{\bf text}`).

\LuaTeX/ attributes can be set like count register -- one attribute holds one
number at a time. But the value of attribute is propagated to each created
typesetting element until the attribute is unset or set to another value. Very
much like the font property. We use one attribute \^`\_colorattr` for storing
the currently selected color (in number form).

Macros \^`\setcmykcolor``{<C> <M> <Y> <K>}` or \^`\setrgbcolor``{<R> <G> <B>}`
or\nl \^`\setgreycolor``{<Grey>}` are used in color selectors. These
macros expand to internal \^`\_setcolor` macro which sets the \^`\_colorattr`
attribute to an integer value and prepares mapping between this value and the real
color data. This mapping is used just before each `\shipout` in output routine.
The \^`\_preshipout` pseudo-primitive is used here, it converts attribute
values to internal PDF commands for selecting colors.

\secc Color mixing

The color mixing processed by the \^`\colordef` is done in the subtractive color
model CMYK. If the result has a component greater than 1 then all
components are multiplied by a coefficient in order to the maximal component is
equal to 1.

You can move a shared amount of CMY components (i.e. their minimum) to the
$K$ component. This saves the color tonners and the result is more true.
This should be done by \^`\useK` command at the end of a linear combination
used in `\colordef`. For example
\begtt
\colordef \myColor {.3\Green + .4\Blue \useK}
\endtt
The `\useK` command exactly does:
$$
  \displaylines{
  k' =\min(C,M,Y), \cr \ C=(C-k')/(1-k'), \ M=(M-k')/(1-k'), \ Y=(Y-k')/(1-k'), \cr
  K = \min(1,K+k').
}
$$

You can use minus instead of plus in the linear combination in `\colordef`. The
given color is substracted in such case and the negative components are
rounded to zero immediately. For example
\begtt
\colordef \Color {\Brown-\Black}
\endtt
can be used for removing the black component from the color. You can use
the `-\Black` trick after `\useK` command to remove grey components
occurred during color mixing.

Finally, you can use `^` immediately preceded before the macro name of the
color. Then the complementary color is used here.
\begtt
\colordef\mycolor{\Grey+.6^\Blue} % the same as \colordef\mycolor{\Grey+.6\Yellow}
\endtt

The \^`\rgbcolordef` can be used to mix colors in additive color model RGB.
If \^`\onlyrgb` is declared, then \^`\colordef` works as \^`\rgbcolordef`.

If a CMYK to RGB or RGB to CMYK conversion is needed then
direct conversion of given color is used (if declared using
\^`\rgbcmykmap``{<rgb>}{<cmyk>}`) or the following simple formulae are used
(ICC profiles are not supported):
$$
\displaylines{
   \hbox{CMYK to RGB:}\cr
   R = (1-C)(1-K), \ G = (1-M)(1-K), \ B = (1-Y)(1-K). \cr
   \hbox{RGB to CMYK:}\cr
   K'=\max(R,G,B), \ C=(K'-R)/K', \ M=(K'-G)/K', \ Y=(K'-B)/K', \ K=1-K'.
}
$$
The RGB to CMYK conversion is invoked when a color is declared using `\setrgbcolor`
and it is used in \^`\colordef` or if it is printed when \^`\onlycmyk` is declared.
The CMYK to RGB conversion is invoked when a color is declared using \^`\setcmykcolor`
and it is used in \^`\rgbcolordef` or if it is printed when \^`\onlyrgb` is declared.

\secc Implementation

\_endinput

2022-03-07 \_resetattrs instead \_resetcolor
2022-03-05 \transparency added
2021-07-16 colors reimplemented, now they are based on attributes
2021-05-28 \rgbcmykmap introduced
2020-04-22 \replstring\tmpb{+ }{+}, {- }{-} added in \colordef, bug fixed
2020-03-18 introduced