summaryrefslogtreecommitdiff
path: root/base/gscspace.h
blob: 589c5a6912799a3179f3d384c855537c2c1852cc (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
/* 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.
*/


/* Client interface to color spaces */

#ifndef gscspace_INCLUDED
#  define gscspace_INCLUDED

#include "gsmemory.h"
#include "gsiparam.h"
#include "gsrefct.h"
#include "gsgstate.h"
#include "gsccolor.h"

/*
 * Previous versions had a complicated lifecycle discipline for
 * colorspaces. All that is now replaced with a simple allocation and
 * reference counting discipline. All colorspace objects are allocated
 * on the heap and reference counted. References to colorspace objects
 * are pointers. There is no stack allocation, inline allocation inside
 * structs, or copying of contents.
 */

/*
 * Here is the information associated with the various color space
 * structures.  Note that DevicePixel, DeviceN, and the ability to use
 * Separation or DeviceN spaces as the base space of an Indexed space
 * are LanguageLevel 3 additions.  Unfortunately, the terminology for the
 * different levels of generality is confusing and inconsistent for
 * historical reasons.
 *
 * For base spaces:
 *
 * Space        Space parameters                Color parameters
 * -----        ----------------                ----------------
 * DeviceGray   (none)                          1 real [0-1]
 * DeviceRGB    (none)                          3 reals [0-1]
 * DeviceCMYK   (none)                          4 reals [0-1]
 * DevicePixel  depth                           1 int [up to depth bits]
 * CIEBasedDEFG dictionary                      4 reals
 * CIEBasedDEF  dictionary                      3 reals
 * CIEBasedABC  dictionary                      3 reals
 * CIEBasedA    dictionary                      1 real
 *
 * For non-base direct spaces:
 *
 * Space        Space parameters                Color parameters
 * -----        ----------------                ----------------
 *
 * Separation   name, alt_space, tint_xform     1 real [0-1]
 * DeviceN      names, alt_space, tint_xform    N reals
 *
 * For non-direct paint spaces:
 *
 * Space        Space parameters                Color parameters
 * -----        ----------------                ----------------
 * Indexed      base_space, hival, lookup       1 int [0-hival]
 * ICCBased     dictionary, alt_space           1, 3, or 4 reals
 *
 * For non-paint spaces:
 *
 * Space        Space parameters                Color parameters
 * -----        ----------------                ----------------
 * Pattern      colored: (none)                 dictionary
 *              uncolored: base_space dictionary + base space params
 */

/* In moving to a pure ICC based color management every color space
   (or its base space) will be defined by an ICC profile.  All modern
   CMMs provide a handle to a profile structure when handed an
   ICC profile.  This handle will become a new member variable for
   ghostscripts color space structure.  When that profile is initialized
   depends upon the color space type.

   a) If the color space is defined to be ICC based, then the profile handle
      will be obtained during the installation of this space.

   b) If the color space is a defined as deviceRGB, CMYK or Gray color space, then
      the profile handle  will be populated with the handle for the ICC profile that
      is in the ICC manager for that color space type.

   c) If the color space is defined as one of the Postscript or PDF CIE (nonICC)
      color spaces, then the profile handle will only be obtained once a request is made
      to obtain a link that includes this color space.  At that point
      we will convert the nonICC colorspace to an ICC color space.

   d) DevicePixel color space appears to only be used by the image3x code
      for the softmask.  Really this should be a Gray color space that is
      never really linked as we do not want a pure alpha image to be
      colorimetrically managed.  Need to do a bit of code/history review to
      understand what this space is.  It may need to be specially managed.  It never
      is used in a linked transformation.

   e) DeviceN is related somewhat to the colorspaces in b) but a bit different.
      PDF does not provide the capability for definining DeviceN source colors
      with an ICC profile.  XPS and OpenXPS do, and it is likely that SVG will
      do so too.  Also, it may become possible in future PDF versions to define
      DeviceN source colors with and ICC profile.
      To support these cases when creating a deviceN color space, it
      will need to be possible to include the ICC information related to that
      color space.  When it is provided, the handle for that color space will
      be obtained from the CMM similar to the ICC spaces in a) .  Note that the
      output device can effectively be DeviceN, which is the process colorants.
      In this case, we will have the CMM handle for the profile in the ICC manager
      and that will be used for the device's color space.

   f) Indexed and Pattern.  These will not have an ICC CMM handle.  Their base
      space will however.

   g) Separation.  These can have an ICC CMM handle.  The exact capabilities
      depend upon the form of the Named color structure that the CMM is going
      to use.  If it is using a traditional ICC named color profile and the entry
      for the color name is there, then we will have a handle to the named
      color profile.  If the color is not there and the device does not have
      this color in its list of colors that it "understands", then we have
      to use the alternate tint transform.  At the extreme end, we could have
      a named color structure that includes for each named color a 1CLR ICC profile.
      Such a profile maps the tint values to CIELAB values.  In this case,
      the ICC CMM handle for the Separation space would be this profile.  Note that
      XPS has to have an ICC profile for a "Named" Color Space.

*/

/* Opaque types for a graphics state stuff */
typedef struct gsicc_link_s gsicc_link_t;

/* Define ICC profile structure type */
typedef struct cmm_profile_s cmm_profile_t;

typedef struct cmm_dev_profile_s cmm_dev_profile_t;

/*
 * Define color space type indices.  NOTE: PostScript code (gs_res.ps,
 * gs_ll3.ps) and the color space substitution code (gscssub.[hc] and its
 * clients) assumes values 0-2 for DeviceGray/RGB/CMYK respectively.
 */
typedef enum {

    /* Supported in all configurations */
    gs_color_space_index_DeviceGray = 0,
    gs_color_space_index_DeviceRGB,

    /* Supported in extended Level 1, and in Level 2 and above */
    gs_color_space_index_DeviceCMYK,

    /* Supported in LanguageLevel 3 only */
    gs_color_space_index_DevicePixel,
    gs_color_space_index_DeviceN,

    /* Supported in Level 2 and above only */
    /* DEC C truncates identifiers at 32 characters, so.... */
    gs_color_space_index_CIEDEFG,
    gs_color_space_index_CIEDEF,
    gs_color_space_index_CIEABC,
    gs_color_space_index_CIEA,
    gs_color_space_index_Separation,
    gs_color_space_index_Indexed,
    gs_color_space_index_Pattern,

    /* Supported in PDF 1.3 and later only */
    gs_color_space_index_ICC

} gs_color_space_index;

/* We define the names only for debugging printout. */
#define GS_COLOR_SPACE_TYPE_NAMES\
  "DeviceGray", "DeviceRGB", "DeviceCMYK", "DevicePixel", "DeviceN",\
  "CIEBasedDEFG", "CIEBasedDEF", "CIEBasedABC", "CIEBasedA",\
  "Separation", "Indexed", "Pattern", "ICCBased"

/* Define an abstract type for color space types (method structures). */
typedef struct gs_color_space_type_s gs_color_space_type;

/*
 * Parameters for "small" base color spaces. Of the small base color spaces,
 * only DevicePixel and CIE spaces have parameters: see gscie.h for the
 * structure definitions for CIE space parameters.
 *
 * It would be possible to save an allocation by placing the CIE
 * params inside the colorspace struct, rather than a pointer to a
 * separate struct, but we'll keep it the way it is for now.
 */
typedef struct gs_device_pixel_params_s {
    int depth;
} gs_device_pixel_params;
typedef struct gs_cie_a_s gs_cie_a;
typedef struct gs_cie_abc_s gs_cie_abc;
typedef struct gs_cie_def_s gs_cie_def;
typedef struct gs_cie_defg_s gs_cie_defg;

typedef struct gs_device_n_map_s gs_device_n_map;
typedef struct gs_device_n_colorant_s gs_device_n_colorant;

/*
 * Non-base direct color spaces: Separation and DeviceN.
 * These include a base alternative color space.
 */
typedef ulong gs_separation_name;	/* BOGUS */

/*
 * Define callback function for graphics library to ask
 * interpreter about character string representation of
 * component names.  This is used for comparison of component
 * names with similar objects like ProcessColorModel colorant
 * names.
 */
typedef int (gs_callback_func_get_colorname_string)
     (gs_gstate *pgs, gs_separation_name colorname, unsigned char **ppstr, unsigned int *plen);

typedef enum { SEP_NONE, SEP_ALL, SEP_OTHER } separation_type;
typedef enum { SEP_ENUM, SEP_MIX, SEP_PURE_RGB, SEP_PURE_CMYK, SEP_PURE_SPOT} separation_colors;

typedef struct gs_separation_params_s {
    gs_memory_t *mem;
    char *sep_name;
    gs_device_n_map *map;
    separation_type sep_type;
    bool use_alt_cspace;
    bool named_color_supported;
    separation_colors color_type;
} gs_separation_params;

typedef enum {
    gs_devicen_DeviceN,
    gs_devicen_NChannel
} gs_devicen_subtype;

typedef struct gs_device_n_params_s {
    gs_memory_t *mem;
    uint num_components;
    char **names;
    gs_device_n_map *map;
    bool use_alt_cspace;
    bool named_color_supported;
    separation_colors color_type;
    gs_devicen_subtype subtype;
    gs_device_n_colorant *colorants;
    gs_color_space       *devn_process_space;
    uint num_process_names;
    char **process_names;
    bool all_none;
} gs_device_n_params;

/* Define an abstract type for the client color space data */
typedef struct client_color_space_data_s client_color_space_data_t;

/*
 * Non-direct paint space: Indexed space.
 *
 * Note that for indexed color spaces, hival is the highest support index,
 * which is one less than the number of entries in the palette (as defined
 * in PostScript).
 */

typedef struct gs_indexed_map_s gs_indexed_map;

typedef struct gs_indexed_params_s {
    int hival;			/* num_entries - 1 */
    int n_comps;
    union {
        gs_const_string table;	/* size is implicit */
        gs_indexed_map *map;
    } lookup;
    bool use_proc;		/* 0 = use table, 1 = use proc & map */
} gs_indexed_params;

/*
 * Pattern parameter set. This may contain an instances of a paintable
 * color space. The boolean indicates if this is the case.
 */
typedef struct gs_pattern_params_s {
    bool has_base_space; /* {csrc} can't we just NULL-check the base_space? */
} gs_pattern_params;

typedef struct gs_calgray_params_s {
    float WhitePoint[3];
    float BlackPoint[3];
    float Gamma;
} gs_calgray_params;

typedef struct gs_calrgb_params_s {
    float WhitePoint[3];
    float BlackPoint[3];
    float Gamma[3];
    float Matrix[9];
} gs_calrgb_params;

typedef struct gs_lab_params_s {
    float WhitePoint[3];
    float BlackPoint[3];
    float Range[4];
} gs_lab_params;

/* id's 1 through 4 are reserved for static colorspaces; thus, dynamically
   assigned id's must begin at 5. */
#define cs_DeviceGray_id 1
#define cs_DeviceRGB_id 3
#define cs_DeviceCMYK_id 4

typedef void (*gs_cspace_free_proc_t) (gs_memory_t * mem, void *pcs);

typedef enum {
    gs_ICC_Alternate_None,
    gs_ICC_Alternate_DeviceGray,
    gs_ICC_Alternate_DeviceRGB,
    gs_ICC_Alternate_DeviceCMYK,
    gs_ICC_Alternate_CalGray,
    gs_ICC_Alternate_CalRGB,
    gs_ICC_Alternate_Lab,
} gs_ICC_Alternate_space;

/*
 * The colorspace object. For pattern and indexed colorspaces, the
 * base_space refers to the underlying colorspace. For separation,
 * deviceN, and icc colorspaces, base_space refers to the alternate
 * colorspace (referred to as alt_space in previous versions of the
 * code).
 */
struct gs_color_space_s {
    const gs_color_space_type *type;
    rc_header                  rc;
    gs_id                      id;
    gs_color_space             *base_space;
    gs_color_space             *icc_equivalent;
    gs_ICC_Alternate_space     ICC_Alternate_space;
    client_color_space_data_t  *pclient_color_space_data;
    void                       *interpreter_data;
    gs_cspace_free_proc_t      interpreter_free_cspace_proc;
    cmm_profile_t              *cmm_icc_profile_data;
    union {
        gs_device_pixel_params   pixel;
        gs_cie_defg *            defg;
        gs_cie_def *             def;
        gs_cie_abc *             abc;
        gs_cie_a *               a;
        gs_separation_params     separation;
        gs_device_n_params       device_n;
        gs_indexed_params        indexed;
        gs_pattern_params        pattern;
        /* These are only used for the Alternate space of an ICCBased
         * space, for the benefit of pdfwrite. For rendering, these
         * spaces are converted into ICCBased spaces.
         */
        gs_calgray_params        calgray;
        gs_calrgb_params         calrgb;
        gs_lab_params            lab;
    } params;
};

                                        /*extern_st(st_color_space); *//* in gxcspace.h */
#define public_st_color_space()	/* in gscspace.c */  \
    gs_public_st_composite_final( st_color_space,         \
                                  gs_color_space,         \
                                  "gs_color_space",       \
                                  color_space_enum_ptrs,  \
                                  color_space_reloc_ptrs, \
                                  gs_cspace_final         \
                            )

/* ---------------- Procedures ---------------- */

/* Constructors for simple device color spaces. These return NULL on
   VMerror. */

gs_color_space *gs_cspace_new_DeviceGray(gs_memory_t *mem);
gs_color_space *gs_cspace_new_DeviceRGB(gs_memory_t *mem);
gs_color_space *gs_cspace_new_DeviceCMYK(gs_memory_t *mem);
gs_color_space *gs_cspace_new_ICC(gs_memory_t *pmem, gs_gstate * pgs,
                                  int components);
gs_color_space *gs_cspace_new_scrgb(gs_memory_t *pmem, gs_gstate * pgs);

/* ------ Accessors ------ */

/* Get the index of a color space. */
gs_color_space_index gs_color_space_get_index(const gs_color_space *);

/* Tell if the space is CIE or ICC based */
bool gs_color_space_is_CIE(const gs_color_space * pcs);
bool gs_color_space_is_ICC(const gs_color_space * pcs);
bool gs_color_space_is_PSCIE(const gs_color_space * pcs);
int gs_colorspace_set_icc_equivalent(gs_color_space *pcs, bool *islab,
                                     gs_memory_t *memory);

/* Get the number of components in a color space. */
int gs_color_space_num_components(const gs_color_space *);

/*
 * Test whether two color spaces are equal.  Note that this test is
 * conservative: if it returns true, the color spaces are definitely
 * equal, while if it returns false, they might still be equivalent.
 */
bool gs_color_space_equal(const gs_color_space *pcs1,
                          const gs_color_space *pcs2);

/* Restrict a color to its legal range. */
void gs_color_space_restrict_color(gs_client_color *, const gs_color_space *);

/* Communicate to overprint compositor that overprint is not to be used */
int gx_set_no_overprint(gs_gstate* pgs);

/* Communicate to overprint compositor that only spot colors are to be preserved */
int gx_set_spot_only_overprint(gs_gstate* pgs);

/*
 * Get the base space of an Indexed or uncolored Pattern color space, or the
 * alternate space of a Separation or DeviceN space.  Return NULL if the
 * color space does not have a base/alternative color space.
 */
const gs_color_space *gs_cspace_base_space(const gs_color_space * pcspace);

const gs_color_space *gs_cspace_devn_process_space(const gs_color_space * pcspace);

/* Abstract the rc_increment and rc_decrement for color spaces so that we also rc_increment
   the ICC profile if there is one associated with the color space */

void rc_increment_cs(gs_color_space *pcs);

void rc_decrement_cs(gs_color_space *pcs, const char *cname);

void rc_decrement_only_cs(gs_color_space *pcs, const char *cname);

void cs_adjust_counts_icc(gs_gstate *pgs, int delta);

void cs_adjust_swappedcounts_icc(gs_gstate *pgs, int delta);

/* backwards compatibility */
#define gs_color_space_indexed_base_space(pcspace)\
    gs_cspace_base_space(pcspace)

#endif /* gscspace_INCLUDED */