1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 /* High level device color save/compare procedures */
17 
18 #ifndef gxhldevc_INCLUDED
19 #  define gxhldevc_INCLUDED
20 
21 #include "gsdcolor.h"
22 #include "gsgstate.h"
23 
24 /*
25  * Most high level devices want more information about the color spaces
26  * which were used to create color values.
27  *
28  * There are some added complications:
29  *
30  * 1. Ghostscript has many dozens, if not hundreds, of device drivers which
31  * have been written for it.  Many of these devices are outside of our
32  * control.  (However we do receive questions and complaints when they no
33  * longer work.)  Thus we also want to avoid making changes in the device
34  * interface which would require changes to the code in these devices.
35  *
36  * 2. We also desire to not save pointers to color space structures, etc.
37  * within the high level device.  Many of these structures are temporary,
38  * stack based, or are deleted outside of the control of the device.  Thus
39  * it becomes almost impossible to prevent pointers to deleted objects.
40  *
41  * 3. Both color spaces and device colors are passed to devices via pointers
42  * to objects.  These objects, in turn, often contain pointers to other
43  * objects.
44  *
45  * These constraints imply the need within the device to save color spaces
46  * and colors in some form which will allows us to detect color space or
47  * color changes when a new color space and a color is compared to the old
48  * saved color space and color.  These 'saved' forms should not include
49  * pointers to objects outside of the control of the device.
50  *
51  * The functions below are desiged to assist the high level device in the
52  * saving, comparing, and getting high level color information.
53  */
54 
55 /*
56  * A structure for saving high level color information for high level devices.
57  */
58 typedef struct gx_hl_saved_color_s {
59     gs_id color_space_id;
60     gs_id pattern_id;
61     bool ccolor_valid;
62     gs_client_color ccolor;
63     gx_device_color_saved saved_dev_color;
64 } gx_hl_saved_color;
65 
66 /*
67  * Initiailze a high level saved color to null
68  */
69 void gx_hld_saved_color_init(gx_hl_saved_color * psc);
70 
71 /*
72  * Save the device color information including the color space id and
73  * client color data (if available).  The pattern id is also saved for
74  * detection of changes in the pattern.
75  *
76  * This routine returns 'true' if sufficient information was provided
77  * to completely describe a full high level (non process color model)
78  * color.  Otherwise 'false' is returned.  Thus the return does both
79  * a save and test on the given color.
80  *
81  * If the device can't handle high level colors, it must pass NULL to
82  * the 'pgs' argument.
83  */
84 bool gx_hld_save_color(const gs_gstate * pgs,
85         const gx_device_color * pdevc, gx_hl_saved_color * psc);
86 
87 /*
88  * Compare two saved colors to check if match.  Note this routine assumes
89  * unused parts of the saved color have been zeroed.  See gx_hld_save_color()
90  * for what is actually being compared.
91  */
92 bool gx_hld_saved_color_equal(const gx_hl_saved_color * psc1,
93                            const gx_hl_saved_color * psc2);
94 
95 /*
96  * Check whether two saved colors have same color space.
97  */
98 bool gx_hld_saved_color_same_cspace(const gx_hl_saved_color * psc1,
99                            const gx_hl_saved_color * psc2);
100 
101 /*
102  * Check if a high level color is availavble.
103  */
104 bool
105 gx_hld_is_hl_color_available(const gs_gstate * pgs,
106                 const gx_device_color * pdevc);
107 
108 /*
109  * Return status from get_color_space_and_ccolor.  See that routine for
110  * more information.
111  *
112  * Hopefully I will be given more information to allow the choice of
113  * better names.
114  */
115 typedef enum {
116         non_pattern_color_space,
117         pattern_color_space,
118         use_process_color
119 } gx_hld_get_color_space_and_ccolor_status;
120 
121 /*
122  * Get pointers to the current color space and client color.
123  *
124  * There are four possible cases:
125  * 1.  Either the device color or gs_gstate pointer is NULL.  If so then
126  *     we do not have enough information.  Thus we need to fall back to the
127  *     process color model color.  Return NULL for both pointers.
128  * 2.  The device color was not created from a color space and a client color.
129  *     (See the set_non_client_color() macro.)  In this case NULL is returned
130  *     for both pointers.  (Use process color model color.)
131  * 3.  The device color is a 'pattern'.  Return pointers to both the current
132  *     color space and the ccolor (client color) field in the device color
133  *     structure.  Note:  For the shfill opeartor, a pattern color space will
134  *     be used to build the device color.  However the current color space
135  *     will not be the pattern color space.
136  * 4.  All other cases: the current color space is the color space used to
137  *     build the device color.  A pointer to the current color space is
138  *     returned.  The client color pointer will be NULL.
139  *
140  * The status returned indicates if the color space information is valid
141  * (non valid --> use_process_color) and whether the color space is
142  * a pattern or non pattern).
143  */
144 gx_hld_get_color_space_and_ccolor_status gx_hld_get_color_space_and_ccolor(
145                 const gs_gstate * pgs, const gx_device_color * pdevc,
146                 const gs_color_space ** ppcs, const gs_client_color ** ppcc);
147 
148 /*
149  * This routine will return the number of components in the current color
150  * space.
151  *
152  * The routine will return -1 if the gs_gstate does not point to a
153  * graphics state (and thus we cannot get the current color space).
154  */
155 int gx_hld_get_number_color_components(const gs_gstate * pgs);
156 
157 /*
158  * This defines sthe possible status to be returned from get_color_component.
159  */
160 typedef enum {
161     valid_result = 1,
162     invalid_color_info = 2,
163     invalid_component_requested = 3
164 } gx_hld_get_color_component_status;
165 
166 /*
167  * Get the requested high level color value.
168  *
169  * This routine will get the specified high level color if it is available.
170  * If the value is not available (status equal either invalid_color_info or
171  * invalid_component_requested).  In this case, it is suggested that the
172  * device fall back to using the process color model.
173  */
174 gx_hld_get_color_component_status gx_hld_get_color_component(
175                 const gs_gstate * pgs, const gx_device_color * pdevc,
176                 int comp_numi, float * output);
177 
178 #endif
179