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