xref: /plan9/sys/src/cmd/gs/src/gxhldevc.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 2003 Artifex Software Inc, artofcode llc.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 /* $Id: gxhldevc.c,v 1.4 2005/05/31 10:56:57 igor Exp $ */
17 /* High level device color save/compare procedures */
18 
19 /*
20  * See comments at the start of gxhldevc.h for more explanation of the
21  * purpose and operation of these procedures.
22  */
23 #include "gx.h"
24 #include "gzstate.h"
25 #include "gscspace.h"
26 #include "gxcspace.h"
27 #include "gxhldevc.h"
28 #include "memory_.h"
29 #include "gxpcolor.h"
30 #include "gsptype2.h"
31 
32 /*
33  * Initiailze a high level saved color to null
34  */
gx_hld_saved_color_init(gx_hl_saved_color * psc)35 void gx_hld_saved_color_init(gx_hl_saved_color * psc)
36 {
37     gx_device_color temp_devc;
38 
39     memset(psc, 0, sizeof(*psc));	/* clear the entire structure */
40     psc->color_space_id = psc->pattern_id = gs_no_id;
41     color_set_null(&temp_devc);
42     temp_devc.type->save_dc(&temp_devc, &(psc->saved_dev_color));
43 }
44 
45 /*
46  * Get graphics state pointer (from imager state pointer)
47  */
gx_hld_get_gstate_ptr(const gs_imager_state * pis)48 const gs_state * gx_hld_get_gstate_ptr(const gs_imager_state * pis)
49 {
50     extern_st(st_gs_state);		/* only for testing */
51 
52     /* Check to verify the structure type is really st_gs_state */
53     if (pis == NULL || gs_object_type(pis->memory, pis) != &st_gs_state)
54 	return NULL;
55 
56     return (const gs_state *) pis;
57 }
58 
59 /*
60  * Save the device color information including the color space id and
61  * client color data (if available).
62  *
63  * More description in src/gxhldevc.h
64  */
65 bool
gx_hld_save_color(const gs_imager_state * pis,const gx_device_color * pdevc,gx_hl_saved_color * psc)66 gx_hld_save_color(const gs_imager_state * pis, const gx_device_color * pdevc,
67 		gx_hl_saved_color * psc)
68 {
69     const gs_state * pgs = gx_hld_get_gstate_ptr(pis);
70     memset(psc, 0, sizeof(*psc));	/* clear the entire structure */
71 
72     if (pdevc == NULL) {
73         /* No device color given, should not happen */
74         gx_hld_saved_color_init(psc);	/* revert to unknown color */
75 	return false;
76     } else if (pgs == NULL) {
77         /* No color space, simply save device color specific info */
78         psc->color_space_id = psc->pattern_id = gs_no_id;
79         pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
80 	return false;
81     } else {
82         /*
83 	 * Have color space, save id,  ccolor, & device color specific info.
84 	 * Also save the high level colors since two gx_color_index values
85 	 * may be the same but for differing high level colors (due to the
86 	 * usual lower resolution of the gx_color_index values.
87 	 */
88         const gs_color_space * pcs = pgs->color_space;
89         int i = gs_color_space_num_components(pcs);
90 
91         psc->color_space_id = pcs->id;
92         pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
93         i = any_abs(i);
94         for (i--; i >= 0; i--)
95 	    psc->ccolor.paint.values[i] = pdevc->ccolor.paint.values[i];
96 
97 	/* Save the pattern id - if present */
98 	if ((pdevc->type == gx_dc_type_pattern
99 	   || pdevc->type == gx_dc_type_pattern2) && pdevc->ccolor_valid)
100             psc->pattern_id = pdevc->ccolor.pattern->pattern_id;
101 	else
102             psc->pattern_id = gs_no_id;
103 	return true;
104     }
105 }
106 
107 /*
108  * Compare two saved colors to check if match.  Note this routine assumes
109  * unused parts of the saved color have been zeroed.  See gx_hld_save_color()
110  * for what is actually being compared.
111  */
gx_hld_saved_color_equal(const gx_hl_saved_color * psc1,const gx_hl_saved_color * psc2)112 bool gx_hld_saved_color_equal(const gx_hl_saved_color * psc1,
113 			   const gx_hl_saved_color * psc2)
114 {
115     return (memcmp(psc1, psc2, sizeof(*psc1)) == 0);
116 }
117 
118 /*
119  * Check whether two saved colors have same color space.
120  */
gx_hld_saved_color_same_cspace(const gx_hl_saved_color * psc1,const gx_hl_saved_color * psc2)121 bool gx_hld_saved_color_same_cspace(const gx_hl_saved_color * psc1,
122 			   const gx_hl_saved_color * psc2)
123 {
124     if (psc1->color_space_id != psc2->color_space_id)
125 	return false;
126     if (psc1->pattern_id != psc2->pattern_id)
127 	return false;
128     if (psc1->ccolor_valid != psc2->ccolor_valid)
129 	return false;
130     if (psc1->color_space_id != psc2->color_space_id)
131 	return false;
132     return true;
133 }
134 
135 /*
136  * Check if a high level color is availavble.
137  */
138 bool
gx_hld_is_hl_color_available(const gs_imager_state * pis,const gx_device_color * pdevc)139 gx_hld_is_hl_color_available(const gs_imager_state * pis,
140 		const gx_device_color * pdevc)
141 {
142     const gs_state * pgs = gx_hld_get_gstate_ptr(pis);
143 
144     if (pgs != NULL && pdevc != NULL && pdevc->ccolor_valid)
145 	return true;
146     return false;
147 }
148 
149 /*
150  * Get pointers to the current color space and client color.
151  *
152  * More description in src/gxhldevc.h
153  */
154 gx_hld_get_color_space_and_ccolor_status
gx_hld_get_color_space_and_ccolor(const gs_imager_state * pis,const gx_device_color * pdevc,const gs_color_space ** ppcs,const gs_client_color ** ppcc)155 gx_hld_get_color_space_and_ccolor(const gs_imager_state * pis,
156 		const gx_device_color * pdevc, const gs_color_space ** ppcs,
157 		const gs_client_color ** ppcc)
158 {
159     /* Check if the current color space was used to build the device color */
160     if (gx_hld_is_hl_color_available(pis, pdevc)) {
161 	const gs_state * pgs = gx_hld_get_gstate_ptr(pis);
162         const gs_color_space * pcs = pgs->color_space;
163 
164 	*ppcs = pcs;
165 	*ppcc = &(pdevc->ccolor);
166 	if (pdevc->type == gx_dc_type_pattern
167 	   || pdevc->type == &gx_dc_pure_masked
168 	   || pdevc->type == gx_dc_type_pattern2)
169             return pattern_color_sapce;
170 	else {
171             return non_pattern_color_space;
172 	}
173     }
174     /* No color space */
175     *ppcs = NULL;
176     *ppcc = NULL;
177     return use_process_color;
178 }
179 
180 /*
181  * Get the number of components in the current color space.
182  *
183  * More description in src/gxhldevc.h
184  */
185 int
gx_hld_get_number_color_components(const gs_imager_state * pis)186 gx_hld_get_number_color_components(const gs_imager_state * pis)
187 {
188     const gs_state * pgs = gx_hld_get_gstate_ptr(pis);
189 
190     if (pgs != NULL) {
191         const gs_color_space * pcs = pgs->color_space;
192 	int n = gs_color_space_num_components(pcs);
193 
194 	return (n >= 0 ? n : -n - 1);
195     } else
196 	return -1;
197 }
198 
199 /*
200  * Get the requested high level color value.
201  *
202  * More description in src/gxhldevc.h
203  */
204 gx_hld_get_color_component_status
gx_hld_get_color_component(const gs_imager_state * pis,const gx_device_color * pdevc,int comp_num,float * output)205 gx_hld_get_color_component(const gs_imager_state * pis,
206 			  const gx_device_color * pdevc,
207 			  int comp_num, float * output)
208 {
209     if (pdevc != NULL && pdevc->ccolor_valid) {
210 	int ncomp = gx_hld_get_number_color_components(pis);
211 
212 	if (ncomp < 0)
213 	    return invalid_color_info;
214 	if (comp_num < 0 || comp_num >= ncomp)
215 	    return invalid_component_requested;
216 	*output = pdevc->ccolor.paint.values[comp_num];
217         return valid_result;
218     }
219     return invalid_color_info;
220 }
221 
222