summaryrefslogtreecommitdiff
path: root/base/gsdcolor.h
blob: 0aacc21632687daeeede5c937c0b6dedcbca5a0d (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
/* Copyright (C) 2001-2023 Artifex Software, Inc.
   All Rights Reserved.

   This software is provided AS-IS with no warranty, either express or
   implied.

   This software is distributed under license and may not be copied,
   modified or distributed except as expressly authorized under the terms
   of the license contained in the file LICENSE in this distribution.

   Refer to licensing information at http://www.artifex.com or contact
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
   CA 94129, USA, for further information.
*/


/* Device color representation for drivers */

#ifndef gsdcolor_INCLUDED
#  define gsdcolor_INCLUDED

#include "gsccolor.h"
#include "gscms.h"		/* for gs_graphics_type_tag_t */
#include "gxarith.h"		/* for imod */
#include "gxbitmap.h"
#include "gxhttile.h"
#include "gxcindex.h"

typedef struct gx_device_color_s gx_device_color;

typedef struct gx_device_color_saved_s  gx_device_color_saved;

typedef struct gx_device_halftone_s gx_device_halftone;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * The definitions in the following section of the file are the only
 * ones that should be used by read-only clients such as implementors
 * of high-level driver functions.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
 * A device color consists of a base color and an optional (tiled) mask.
 * The base color may be a pure color, a devn color, a binary halftone,
 * or a colored bitmap (color halftone or colored Pattern).  The mask is
 * used for both colored and uncolored Patterns.
 */

/* Accessing a pure color. */
#define gx_dc_is_pure(pdc)\
  ((pdc)->type == gx_dc_type_pure)
#define gx_dc_writes_pure(pdc, lop)\
  (gx_dc_is_pure(pdc) && lop_no_S_is_T(lop))
#define gx_dc_pure_color(pdc)\
  ((pdc)->colors.pure)

/* Accessing a devn color. */
#define gx_dc_is_devn(pdc)\
  ((pdc)->type == gx_dc_type_devn)

/* Accessing the phase of a halftone. */
#define gx_dc_phase(pdc)\
  ((pdc)->phase)

/* Accessing a binary halftone. */
#define gx_dc_is_binary_halftone(pdc)\
  ((pdc)->type == gx_dc_type_ht_binary)
#define gx_dc_binary_tile(pdc)\
  (&(pdc)->colors.binary.b_tile->tiles)
#define gx_dc_binary_color0(pdc)\
  ((pdc)->colors.binary.color[0])
#define gx_dc_binary_color1(pdc)\
  ((pdc)->colors.binary.color[1])

/* Accessing a colored halftone. */
#define gx_dc_is_colored_halftone(pdc)\
  ((pdc)->type == gx_dc_type_ht_colored)

/*
 * Test device colors for equality.  Testing for equality is done
 * for determining when cache values, etc. can be used.  Thus these
 * routines should err toward false responses if there is any question
 * about the equality of the two device colors.
 */
bool gx_device_color_equal(const gx_device_color *pdevc1,
                           const gx_device_color *pdevc2);

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * The definitions in the following section of the file, plus the ones
 * just above, are the only ones that should be used by clients that
 * set as well as read device colors.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#define color_is_set(pdc)\
  ((pdc)->type != gx_dc_type_none)
#define color_unset(pdc)\
  (((pdc)->type = gx_dc_type_none), ((pdc)->tag = 0))

#define gx_dc_is_null(pdc)\
  ((pdc)->type == gx_dc_type_null)
#define color_is_null(pdc) gx_dc_is_null(pdc)
#define color_set_null(pdc)\
  ((pdc)->type = gx_dc_type_null)

#define color_is_pure(pdc) gx_dc_is_pure(pdc)
#define color_writes_pure(pdc, lop) gx_dc_writes_pure(pdc, lop)

#define color_is_devn(pdc) gx_dc_is_devn(pdc)
/*
 * Used to define 'pure' (solid - without halftoning or patterns) colors.
 * This macro assumes the colorspace and client color information is already
 * defined in the device color strucTure.  If not then see the next macro.
 */
#define color_set_pure(pdc, color)\
  ((pdc)->colors.pure = (color),\
   (pdc)->type = gx_dc_type_pure)
/*
 * Used to create special case device colors for which the colorspace
 * and client colors are not already contained in the device color.
 */
#define set_nonclient_dev_color(pdc, color)\
    color_set_pure(pdc, color);\
    (pdc)->ccolor_valid = false

/* Set the phase to an offset from the tile origin. */
#define color_set_phase(pdc, px, py)\
  ((pdc)->phase.x = (px),\
   (pdc)->phase.y = (py))
/* Set the phase from the halftone phase in a graphics state. */
#define color_set_phase_mod(pdc, px, py, tw, th)\
  color_set_phase(pdc, imod(-(px), tw), imod(-(py), th))

#define color_is_binary_halftone(pdc) gx_dc_is_binary_halftone(pdc)
#define color_set_binary_halftone_component(pdc, ht, index, color0, color1, level)\
  ((pdc)->colors.binary.b_ht = (ht),\
   (pdc)->colors.binary.b_index = (index),\
   (pdc)->colors.binary.color[0] = (color0),\
   (pdc)->colors.binary.color[1] = (color1),\
   (pdc)->colors.binary.b_level = (level),\
   (pdc)->type = gx_dc_type_ht_binary)
#define color_set_binary_halftone(pdc, ht, color0, color1, level)\
  color_set_binary_halftone_component(pdc, ht, -1, color0, color1, level)
#define color_set_binary_tile(pdc, color0, color1, tile)\
  ((pdc)->colors.binary.b_ht = 0,\
   (pdc)->colors.binary.color[0] = (color0),\
   (pdc)->colors.binary.color[1] = (color1),\
   (pdc)->colors.binary.b_index = -1, /* irrelevant */\
   (pdc)->colors.binary.b_tile = (tile),\
   (pdc)->type = gx_dc_type_ht_binary)

#define color_is_colored_halftone(pdc) gx_dc_is_colored_halftone(pdc)
#define _color_set_c(pdc, i, b, l)\
  ((pdc)->colors.colored.c_base[i] = (b),\
   (pdc)->colors.colored.c_level[i] = (l))

/* Some special clients set the individual components separately. */
void gx_complete_halftone(gx_device_color *pdevc, int num_comps,
                          gx_device_halftone *pdht);

/* Note that color_set_null_pattern doesn't set mask.ccolor. */
#define color_set_null_pattern(pdc)\
 ((pdc)->mask.id = gx_no_bitmap_id,\
  (pdc)->mask.m_tile = 0,\
  (pdc)->colors.pattern.p_tile = 0,\
  (pdc)->type = gx_dc_type_pattern)

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * The remaining definitions are internal ones that are included in this
 * file only because C's abstraction mechanisms aren't strong enough to
 * allow us to keep them separate and still have in-line access to the
 * commonly used members.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/* Define opaque types for objects referenced by device colors. */

typedef struct gx_color_tile_s gx_color_tile;

/*
 * The device color in the graphics state is computed from client color
 * specifications, and kept current through changes in transfer function,
 * device, and (if relevant) halftone phase.
 * (gx_set_dev_color sets the device color if needed.)
 * For binary halftones (and eventually colored halftones as well),
 * the bitmaps are only cached, so internal clients (the painting operators)
 * must call gx_color_load to ensure that the bitmap is available.
 * Device color elements set by gx_color_load are marked with @ below.
 *
 * Base colors are represented as follows:
 *
 *      Pure color (gx_dc_pure):
 *              colors.pure = the color;
 *      Binary halftone (gx_dc_ht_binary):
 *              colors.binary.b_ht = the device halftone;
 *		colors.binary.b_index = -1 if b_ht is the halftone,
 *		  otherwise an index in b_ht.components
 *              colors.binary.color[0] = the color for 0s (darker);
 *              colors.binary.color[1] = the color for 1s (lighter);
 *              colors.binary.b_level = the number of pixels to lighten,
 *                0 < halftone_level < P, the number of pixels in the tile;
 *      @       colors.binary.b_tile points to an entry in the binary
 *                tile cache.
 *      Colored halftone (gx_dc_ht_colored):
 *              colors.colored.c_ht = the device halftone;
 *              colors.colored.c_level[0..N-1] = the halftone levels,
 *                like b_level;
 *              colors.colored.c_base[0..N-1] = the base colors;
 *                N = the device color_info.num_components
 *		    (3 for RGB devices, 4 for CMYK devices, ? for DeviceN);
 *                0 <= c_level[i] < P;
 *                0 <= c_base[i] <= dither_rgb;
 *              colors.colored.alpha = the opacity.
 *		colors.colored.plane_mask: bit 2^i = 1 iff c_level[i] != 0
 *      Colored PatternType 1 pattern (gx_dc_pattern):
 *              (mask is also set, see below)
 *      @       colors.pattern.p_tile points to a gx_color_tile in
 *                the pattern cache, or is NULL for a null pattern.
 *
 * The phase element is used for all colors except pure ones.  It holds the
 * negative of the graphics state halftone phase, modulo the halftone tile
 * size.
 *
 * The ccolor element is used for all kinds of patterns.  It is needed for
 * rendering the pattern.
 *
 * The mask elements of a device color are only used for PatternType 1
 * patterns:
 *      Non-pattern:
 *              mask is unused.
 *      Pattern:
 *              mask.id gives the ID of the pattern (and its mask);
 *              mask.m_phase holds the negative of the graphics state
 *                halftone phase;
 *      @       mask.m_tile points to a gx_color_tile in the pattern cache,
 *                or is NULL for a pattern that doesn't require a mask.
 *                (The 'bits' of the tile are not accessed.)
 *                For colored patterns requiring a mask, p_tile and
 *                mask.m_tile point to the same cache entry.
 * For masked colors, gx_set_dev_color replaces the type with a different
 * type that applies the mask when painting.  These types are not defined
 * here, because they are only used in Level 2.
 */

/* Define the (opaque) type for device color types. */
/* The name is an unfortunate anachronism. */
typedef struct gx_device_color_type_s gx_device_color_type_t;
typedef const gx_device_color_type_t *gx_device_color_type;

struct gx_device_color_s {
    /*
     * Since some compilers don't allow static initialization of a
     * union, we put the type first.
     */
    gx_device_color_type type;
    gs_graphics_type_tag_t tag;	/* value used to set dev_color */
    /*
     * See the comment above for descriptions of the members.  We use
     * b_, c_, and p_ member names because some old compilers don't
     * allow the same name to be used for two different structure
     * members even when it's unambiguous.
     */
    union _c {
        gx_color_index pure;
        struct _bin {
            const gx_device_halftone *b_ht;
            gx_color_index color[2];
            uint b_level;
            int b_index;
            gx_ht_tile *b_tile;
        } binary;
        struct _col {
            gx_device_halftone *c_ht; /* non-const for setting cache ptr */
            ushort num_components;
            byte c_base[GX_DEVICE_COLOR_MAX_COMPONENTS];
            uint c_level[GX_DEVICE_COLOR_MAX_COMPONENTS];
#if GX_DEVICE_COLOR_MAX_COMPONENTS <= ARCH_SIZEOF_SHORT * 8
            ushort plane_mask;
#else
#if GX_DEVICE_COLOR_MAX_COMPONENTS <= ARCH_SIZEOF_INT * 8
            uint plane_mask;
#else
            gx_color_index plane_mask;
#endif
#endif
        } colored;
        struct _pat {
            gx_color_tile *p_tile;
        } /*(colored) */ pattern;
        struct _devn {
            ushort values[GS_CLIENT_COLOR_MAX_COMPONENTS];
        } devn;
    } colors;
    gs_int_point phase;
    /*
     * This flag indicates if the paint values in ccolor are valid.  They
     * are valid for most cases.  However there are some special cases
     * in which a device color is initialized to specific values (usually
     * black or white) instead of being created from a color space and
     * color values.
     */
    bool ccolor_valid;
    /*
     * 'ccolor' (a "client color") is valid iff 'ccolor_valid' is true.
     * For non-pattern colors, it contains the original paint values.
     * For pattern colors, it contains information required for remapping
     * the pattern.
     */
    gs_client_color ccolor;

    struct _mask {
        struct mp_ {
            int x, y;
        } m_phase;
        gx_bitmap_id id;
        gx_color_tile *m_tile;
    } mask;
};

/*extern_st(st_device_color); *//* in gxdcolor.h */
#define public_st_device_color() /* in gxcmap.c */\
  gs_public_st_composite(st_device_color, gx_device_color, "gx_device_color",\
    device_color_enum_ptrs, device_color_reloc_ptrs)
#define st_device_color_max_ptrs (st_client_color_max_ptrs + 2)

/*
 * For the command list, it is useful to record the most recent device
 * color placed in a band, so as to avoid sending unnecessary
 * information. The following structure is used for that purpose. It is
 * created by the save_dc method, and can be utilized by the write
 * method. It should otherwise be considered opaque, though it is
 * guarranteed not to contain pointers to allocated memory (and thus does
 * not interact with the GC code for containing structures).
 *
 * The reason a structure distinct from the device color itself is used
 * for this purpose is related to an anomally involving reference to
 * device halftones. The gx_device_halftone structure is reference
 * counted, but a long standing (and not easily removable) convention
 * in the code states that only reference from imager (graphic) states
 * to halftones are counted; reference from device colors are not. The
 * pointer to a halftone in a saved device color may, therefore,
 * become a dangling pointer. This does not occur in other uses of a
 * device color, because a color can only be usable when the hafltone
 * it references is the current halftone in some imager state.
 *
 * Because halftones are large and seldom changed, they are always sent
 * as "all bands" commands. Individual device colors, by contrast, are
 * usually written just for the bands that make use of them. The
 * distinction between these two cases can only be handled by command
 * list writer code itself, so this structure does not involve the
 * halftone. If the halftone changes, however, the write method should
 * be passed a null pointer for the saved color operand; this will
 * ensure the the full device color information is written.
 *
 * Currently patterns cannot be passed through the command list,
 * however vector devices need to save a color for comparing
 * it with another color, which appears later.
 * We provide a minimal support, which is necessary
 * for the current implementation of pdfwrite.
 * It is not sufficient for restoring the pattern from the saved color.
 */

struct gx_device_color_saved_s {
    gx_device_color_type    type;
    int                     devn_type;		/* for fill / stroke */
    union _svc {
        gx_color_index  pure;
        struct _svbin {
            gx_color_index  b_color[2];
            uint            b_level;
            int             b_index;
        }               binary;
        struct _svcol {
            byte    c_base[GX_DEVICE_COLOR_MAX_COMPONENTS];
            uint    c_level[GX_DEVICE_COLOR_MAX_COMPONENTS];
        }               colored;
        struct _svdevn {
            ushort values[GX_DEVICE_COLOR_MAX_COMPONENTS];
        } devn;
        struct _pattern {
            gs_id id;
        }		pattern;
        struct _pattern2 {
            gs_id id;
            bool shfill;
        }		pattern2;
    }                       colors;
    gs_int_point            phase;
};

/*
 * Define the standard device color types.
 * We define them here as pointers to the real types only because a few
 * C compilers don't allow declaring externs with abstract struct types;
 * we redefine them as macros in gxdcolor.h where the concrete type for
 * gx_device_color_procs is available.
 * We spell out the definition of gx_device_color type because some
 * C compilers can't handle the typedef correctly.
 */
#ifndef gx_dc_type_none
extern const gx_device_color_type_t *const gx_dc_type_none;	/* gxdcolor.c */
#endif
#ifndef gx_dc_type_null
extern const gx_device_color_type_t *const gx_dc_type_null;	/* gxdcolor.c */
#endif
#ifndef gx_dc_type_pure
extern const gx_device_color_type_t *const gx_dc_type_pure;	/* gxdcolor.c */
#endif
#ifndef gx_dc_type_devn
extern const gx_device_color_type_t *const gx_dc_type_devn;	/* gxdcolor.c */
#endif
                /*
                 * We don't declare gx_dc_pattern here, so as not to create
                 * a spurious external reference in Level 1 systems.
                 */
#ifndef gx_dc_type_pattern
/*extern const gx_device_color_type_t * const gx_dc_type_pattern; *//* gspcolor.c */
#endif
#ifndef gx_dc_type_ht_binary
extern const gx_device_color_type_t *const gx_dc_type_ht_binary;	/* gxht.c */
#endif
#ifndef gx_dc_type_ht_colored
extern const gx_device_color_type_t *const gx_dc_type_ht_colored;	/* gxcht.c */
#endif

#endif /* gsdcolor_INCLUDED */