summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/mk/mk-colors.tex
blob: 0d12c976e8db76a4ef60b1c1c30feafeb551b3a4 (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
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
% language=uk

\startcomponent mk-colors

\environment mk-environment

\chapter{Colors redone}

\subject{introduction}

Color support has been present in \CONTEXT\ right from the start and
support has been gradualy extended, for instance with transparency
and spot colors. About 10 years later we have the first major rewrite
of this mechanism using attributes as implemented in \LUATEX.

Because I needed a test file to check if all things still work as
expected, I decided to recap the most important commands in this
chapter.

\subject{color support}

The core command is \type {\definecolor}, so let's define a few
colors:

\startbuffer
\definecolor [red]     [r=1]
\definecolor [green]   [g=1]
\definecolor [blue]    [b=1]
\definecolor [yellow]  [y=1]
\definecolor [magenta] [m=1]
\definecolor [cyan]    [c=1]
\stopbuffer

\typebuffer \getbuffer

This gives us the following colors:

\showcolorcomponents[red,green,blue,,yellow,magenta,cyan]

As you can see in this table, transparency is part of a color
specification, so let's define a few transparent colors:

\startbuffer
\definecolor [t-red]   [r=1,a=1,t=.5]
\definecolor [t-green] [g=1,a=1,t=.5]
\definecolor [t-blue]  [b=1,a=1,t=.5]
\stopbuffer

\typebuffer \getbuffer

\showcolorcomponents[t-red,t-green,t-blue]

Because transparency is now separated from color, we can define
transparent behaviour as follows:

\startbuffer
\definecolor[half-transparent] [a=1,t=.5]
\stopbuffer

\typebuffer \getbuffer

Implementing process color spaces was not that complex, but spot and multitone
colors took a bit more code.

\startbuffer
\definecolor     [parentspot]               [r=.5,g=.2,b=.8]
\definespotcolor [childspot-1] [parentspot] [p=.7]
\definespotcolor [childspot-2] [parentspot] [p=.4]
\stopbuffer

\typebuffer \getbuffer

The three colors, two of them are spot colors, show up as follows:

\showcolorcomponents[parentspot,childspot-1,childspot-2]

Multitone colors can also be defined:

\startbuffer
\definespotcolor [spotone]   [red]   [p=1]
\definespotcolor [spottwo]   [green] [p=1]

\definespotcolor [spotone-t] [red]   [a=1,t=.5]
\definespotcolor [spottwo-t] [green] [a=1,t=.5]

\definemultitonecolor
    [whatever]
    [spotone=.5,spottwo=.5]
    [b=.5]
\definemultitonecolor
    [whatever-t]
    [spotone=.5,spottwo=.5]
    [b=.5]
    [a=1,t=.5]
\stopbuffer

\typebuffer \getbuffer

Transparencies don't carry over:

\showcolorcomponents[spotone,spottwo,spotone-t,spottwo-t,whatever,whatever-t]

Transparencies combine as follows:

\startbuffer
\blackrule[width=3cm,height=1cm,color=spotone-t]\hskip-1.5cm
\blackrule[width=3cm,height=1cm,color=spotone-t]
\stopbuffer

\typebuffer

\startlinecorrection
\dontleavehmode\getbuffer
\stoplinecorrection

We can still clone colors and overload color dynamically. I used the following
test code for the \MKIV\ code:

\startbuffer
{\green green->red}
\definecolor[green] [g=1]
{\green green->green}
\definecolor[green] [blue]
{\green green->blue}
\definecolor[blue] [red]
{\green green->red}
\setupcolors[expansion=yes]%
\definecolor[blue] [red]
\definecolor[green] [blue]
\definecolor[blue] [r=1]
{\green green->blue}
\stopbuffer

\typebuffer \getbuffer

Of course palets and color groups are supported too. We seldom use
colorgroups, but here is an example:

\startbuffer
\definecolorgroup
  [redish]
  [1.00:0.90:0.90,1.00:0.80:0.80,1.00:0.70:0.70,1.00:0.55:0.55,
   1.00:0.40:0.40,1.00:0.25:0.25,1.00:0.15:0.15,0.90:0.00:0.00]
\stopbuffer

\typebuffer \getbuffer

The redish color is called by number:

\startbuffer
\blackrule[width=3cm,height=1cm,depth=0pt,color=redish:1]\quad
\blackrule[width=3cm,height=1cm,depth=0pt,color=redish:2]\quad
\blackrule[width=3cm,height=1cm,depth=0pt,color=redish:3]
\stopbuffer

\typebuffer

\startlinecorrection
\dontleavehmode\getbuffer
\stoplinecorrection

Palets work with names:

\startbuffer
\definepalet
  [complement]
  [red=cyan,green=magenta,blue=yellow]
\stopbuffer

\typebuffer \getbuffer

This is used as:

\startbuffer
\blackrule[width=1cm,height=1cm,depth=0pt,color=red]\quad
\blackrule[width=1cm,height=1cm,depth=0pt,color=green]\quad
\blackrule[width=1cm,height=1cm,depth=0pt,color=blue]\quad
\setuppalet[complement]%
\blackrule[width=1cm,height=1cm,depth=0pt,color=red]\quad
\blackrule[width=1cm,height=1cm,depth=0pt,color=green]\quad
\blackrule[width=1cm,height=1cm,depth=0pt,color=blue]
\stopbuffer

\typebuffer

\startlinecorrection
\dontleavehmode\getbuffer
\stoplinecorrection

% Rasters are still supported but normally one will use colors:
%
% \startbuffer
% \raster[.5]{\blackrule[width=3cm,height=1cm]}\quad
% \raster[.8]{\blackrule[width=3cm,height=1cm]}
% \stopbuffer
%
% \typebuffer
%
% \startlinecorrection
% \dontleavehmode\getbuffer
% \stoplinecorrection

Of course the real torture test is \METAPOST\ inclusion:

\startbuffer
\startMPcode
    path p ; p := fullcircle scaled 4cm ;
    fill p                  withcolor \MPcolor{spotone-t} ;
    fill p shifted(2cm,0cm) withcolor \MPcolor{spottwo-t} ;
\stopMPcode
\stopbuffer

\typebuffer

These transparent color circles up as:

\startlinecorrection
\dontleavehmode\getbuffer
\stoplinecorrection

Multitone colors also work:

\startbuffer
\startMPcode
    path p ; p := fullcircle scaled 2cm ;
    fill p                  withcolor \MPcolor{spotone} ;
    fill p shifted(2cm,0cm) withcolor \MPcolor{spottwo} ;
    fill p shifted(4cm,0cm) withcolor \MPcolor{whatever} ;
\stopMPcode
\stopbuffer

\typebuffer

This gives:

\startlinecorrection
\dontleavehmode\getbuffer
\stoplinecorrection

\subject{implementation}

The implementation of colors using attributes if quite different
from the traditional method. In \MKII\ color support works okay but
the associated code is not that clean, if only because:

\startitemize[packed]
\item we need to keep track of grouped color usage
\item and we do that using dedicated marks (using \TEX's mark mechanism)
\item since this has limitations, we have quite some optimizations
\item like local (no marks) and global colors (marks)
\item and real dirty code to push and pop color states around pages
\item and some messy code to deal with document colors
\item and quite some conversion macros (think of \TEX\ not having floats)
\stopitemize

Although recent versions of \PDFTEX\ have a color stack mechanism, this
is not adequate for our usage, if only because we support more colorspaces
than this mechanism is supposed to deal with. (The color stack mechanism is
written with a particular macro packag ein mind.)

In \MKIV\ attributes behave like colors and therefore we no longer
need to care about what happens at pageboundaries. Also, we no
longer have to deal with the limitations of marks. Here:

\startitemize[packed]
\item we have distributed color spaces, color itself and transparency
\item all injection of backend code is postponed to shipout time
\item definition and conversion is delegated to \LUA
\stopitemize

Of course the current implementation is not as nice as we would like it
to be. This because:

\startitemize[packed]
\item support mechanism are under construction
\item we need to support both \MKII\ and \MKIV\ in one interface
\item backend support is yet limited
\stopitemize

Although in principle a mechanism based on attributes is much faster than
using marks cum suis, the new implementation is slower. The main reason is
that we need to finalize the to be shipped out box. However, since this
task involved more than just color, we will gain back some runtime when other
mechanisms also use attributes.

\subject{complications}

This paragraph is somewhat complex, so skip it when you don't feel comfortable with
the subject of when you've never seen low level \CONTEXT\ code.

Attributes behave like fonts. This means that they are kind of frozen once
material is boxed. Consider that we define a box as follows:

\starttyping
\setbox0\hbox{default {\red red \green green} default}
\stoptyping

What do you expect to come out the next code? In \MKII\ the \quote
{default} inside the box will be colored yellow but the internal
red and and green words will keep their color.

\starttyping
default {\yellow yellow \box0\ yellow} default
\stoptyping

When we use fonts switches we don't expect the content of the
box to change. So, in the following the \quote {default} texts will
{\em not} become bold.

\starttyping
\setbox0\hbox{default {\sl slanted \bi bold italic} default}
default {\bf bold \box0\ bold} default
\stoptyping

Future versions of \LUATEX\ will provide more control over how attributes
are applied to boxes, but for the moment we need to fallback on a solution
built in \MKIV:

\starttyping
default {\yellow yellow \attributedbox0\ yellow} default
\stoptyping

There is also a \type {\attributedcopy} macro. These macros signal the
attribute resolver (that kicks in just before shipout) that this box is to
be treated special.

In \MKII\ we had a similar situation which is why we had the option (only used
deep down in \CONTEXT) to encapsulate a bunch of code with

\starttyping
\startregistercolor[foregroundcolor]
some macro code ... here foregroundcolor is applied ... more code
\stopregisteringcode
\stoptyping

This is for instance used in the \type {\framed} macro. First we package the content,
foregroundcolor is not yet applied because the injected  specials of literals can interfere
badly, but by registering the colors the nested color calls are tricked into thinking that
preceding and following content is colored. When packaged, we apply backgrounds, frames,
and foregroundcolor to the whole result. Because nested colors were aware of the
foregroundcolor they have properly reverted to this color when needed.

In \MKIV\ the situation is reversed. Here we definitely need to set the foregroundcolor
because otherwise attributes are not set and here they don't interfere at all (no extra nodes).
For this we use the same registration macros. When the lot is packaged, applying foregroundcolor
is ineffective because the attributes are already applied. Instead of registering we could
have flushed the framed content using \type {\attributedbox}, but this way we can keep the
\MKII\ and \MKIV\ code base the same.

To summarize, first the na\"ive approach. Here the nested colors know how to revert, but
the color switch can interfere with the content (since color commands inject nodes).

\starttyping
\setbox\framed\vbox
  {\color[foregroundcolor]{packaged framed content, can have color switches}}
\stoptyping

The \MKII\ approach registers the foreground color so the nested colors
know what to do. There is no interfering code:

\starttyping
\startregistercolor[foregroundcolor]
\setbox\framed
\stopregisteringcode
\setbox\framed{\color[foregroundcolor]{\box\framed}}
\stoptyping

The registration actually sets the color, so in fact the final coloring is not
needed (does nothing). An alternative \MKIV\ approach is the following:

\starttyping
\color
  [foregroundcolor]
  {\setbox\framed{packaged framed content, can have color switches}}
\stoptyping

This works ok because attributes are applied to the whole content, i.e.\
the box. In \MKII\ this would be quite ineffective and actually result
in weird side effects.

\starttyping
< color stack is pushed and marks are set (unless local) >
< color special or literal sets color to foregroundcolor >
\setbox\framed{packaged framed content, can have color switches}
< color special or literal sets color to foregroundcolor >
< color stack is popped and marks are set (unless local) >
\stoptyping

So, effectively we set a box, and end up with:

\starttyping
< whatsits (special, literal and.or mark) >
< whatsits (special, literal and.or mark) >
\stoptyping

in the main vertical lost and that will interfere badly with spacing
and friends.

In \MKIV\ however, a color switch, like a font switch does not leave any
traces, it just sets a state. Anyway, keep in mind that there are some
rather fundamental conceptual differences between the two appoaches.

Let's end with an example that demonstrates the problem. We fill two boxes:

% in previous examples we may have messed up colors

\definecolor[red]   [darkred]
\definecolor[green] [darkgreen]
\definecolor[blue]  [darkblue]
\definecolor[yellow][darkyellow]

\startbuffer
\setbox0\hbox{RED {\blue blue} RED}
\setbox2\hbox{RED {\blue blue} {\attributedcopy0} RED}
\stopbuffer

\typebuffer \getbuffer

We will flush these in the following lines:

\startbuffer
{unset \color[red]{red \CopyMe} unset
    \color[red]{red \hbox{red \CopyMe}} unset}
{unset \color[red]{red \CopyMe} unset
    {\red red \hbox{red \CopyMe}} unset}
{unset \color[red]{red \CopyMe} unset
    {\red red \setbox0\hbox{red \CopyMe}\box0} unset}
{unset \color[red]{red \CopyMe} unset
    {\hbox{\red red \CopyMe}} unset}
{\blue blue \color[red]{red \CopyMe} blue
    \color[red]{red \hbox{red \CopyMe}} blue}
\stopbuffer

\typebuffer

\startbuffer[yes]
\def\CopyMe{\attributedcopy2\ \copy4}
\stopbuffer

\startbuffer[no]
\def\CopyMe{\copy2\ \copy4}
\stopbuffer

First we define \type {\CopyMe} as follows:

\typebuffer[yes]

This gives:

\start \enableattributeinheritance \getbuffer[yes] \getbuffer \stop

Compare this with:

\typebuffer[no]

This gives:

\getbuffer[no] \getbuffer

You get the picture? At least in early version of \MKIV\ you need to
enable support for inheritance with:

\starttyping
\enableattributeinheritance
\stoptyping

\stopcomponent