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