1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gspcolor.c 8250 2007-09-25 13:31:24Z giles $ */
15
/* Pattern color operators and procedures for Ghostscript library */
21
#include "gsutil.h" /* for gs_next_ids */
25
#include "gxcoord.h" /* for gs_concat, gx_tr'_to_fixed */
26
#include "gxcspace.h" /* for gscolor2.h */
41
public_st_pattern_template();
42
public_st_pattern_instance();
44
/* Define the Pattern color space. */
45
gs_private_st_composite(st_color_space_Pattern, gs_color_space,
46
"gs_color_space_Pattern", cs_Pattern_enum_ptrs, cs_Pattern_reloc_ptrs);
47
static cs_proc_num_components(gx_num_components_Pattern);
48
static cs_proc_remap_color(gx_remap_Pattern);
49
static cs_proc_init_color(gx_init_Pattern);
50
static cs_proc_restrict_color(gx_restrict_Pattern);
51
static cs_proc_install_cspace(gx_install_Pattern);
52
static cs_proc_set_overprint(gx_set_overprint_Pattern);
53
static cs_proc_final(gx_final_Pattern);
54
static cs_proc_adjust_color_count(gx_adjust_color_Pattern);
55
static cs_proc_serialize(gx_serialize_Pattern);
56
const gs_color_space_type gs_color_space_type_Pattern = {
57
gs_color_space_index_Pattern, false, false,
58
&st_color_space_Pattern, gx_num_components_Pattern,
59
gx_init_Pattern, gx_restrict_Pattern,
61
gx_no_concretize_color, NULL,
62
gx_remap_Pattern, gx_install_Pattern,
63
gx_set_overprint_Pattern,
64
gx_final_Pattern, gx_adjust_color_Pattern,
69
/* Initialize a generic pattern template. */
71
gs_pattern_common_init(gs_pattern_template_t * ppat,
72
const gs_pattern_type_t *type)
75
ppat->PatternType = type->PatternType;
76
uid_set_invalid(&ppat->uid);
77
ppat->client_data = 0; /* for GC */
80
/* Generic makepattern */
82
gs_make_pattern(gs_client_color * pcc, const gs_pattern_template_t * pcp,
83
const gs_matrix * pmat, gs_state * pgs, gs_memory_t * mem)
85
return pcp->type->procs.make_pattern(pcc, pcp, pmat, pgs, mem);
89
* Do the generic work for makepattern: allocate the instance and the
90
* saved graphics state, and fill in the common members.
93
gs_make_pattern_common(gs_client_color *pcc,
94
const gs_pattern_template_t *ptemp,
95
const gs_matrix *pmat, gs_state *pgs, gs_memory_t *mem,
96
gs_memory_type_ptr_t pstype)
98
gs_pattern_instance_t *pinst;
102
mem = gs_state_memory(pgs);
103
rc_alloc_struct_1(pinst, gs_pattern_instance_t, pstype, mem,
104
return_error(gs_error_VMerror),
105
"gs_make_pattern_common");
106
pinst->rc.free = rc_free_pattern_instance;
107
pinst->type = ptemp->type;
108
saved = gs_state_copy(pgs, mem);
110
gs_free_object(mem, pinst, "gs_make_pattern_common");
111
return_error(gs_error_VMerror);
113
gs_concat(saved, pmat);
115
pinst->saved = saved;
116
pcc->pattern = pinst;
117
pcc->pattern->pattern_id = gs_next_ids(mem, 1);
121
/* Free the saved gstate when freeing a Pattern instance. */
123
rc_free_pattern_instance(gs_memory_t * mem, void *pinst_void,
126
gs_pattern_instance_t *pinst = pinst_void;
128
gs_state_free(pinst->saved);
129
rc_free_struct_only(mem, pinst_void, cname);
134
gs_setpattern(gs_state * pgs, const gs_client_color * pcc)
136
int code = gs_setpatternspace(pgs);
140
return gs_setcolor(pgs, pcc);
143
/* setpatternspace */
144
/* This does all the work of setpattern except for the final setcolor. */
146
gs_setpatternspace(gs_state * pgs)
150
if (pgs->in_cachedevice)
151
return_error(gs_error_undefined);
152
if (pgs->color_space->type->index != gs_color_space_index_Pattern) {
155
pcs = gs_cspace_alloc(pgs->memory, &gs_color_space_type_Pattern);
157
return_error(gs_error_VMerror);
158
/* reference to base space shifts from pgs to pcs with no net change */
159
pcs->base_space = pgs->color_space;
160
pcs->params.pattern.has_base_space = true;
161
pgs->color_space = pcs;
162
cs_full_init_color(pgs->ccolor, pcs);
163
gx_unset_dev_color(pgs);
169
* Adjust the reference count of a pattern. This is intended to support
170
* applications (such as PCL) which maintain client colors outside of the
171
* graphic state. Since the pattern instance structure is opaque to these
172
* applications, they need some way to release or retain the instances as
176
gs_pattern_reference(gs_client_color * pcc, int delta)
178
if (pcc->pattern != 0)
179
rc_adjust(pcc->pattern, delta, "gs_pattern_reference");
183
/* This is only intended for the benefit of pattern PaintProcs. */
184
const gs_pattern_template_t *
185
gs_get_pattern(const gs_client_color * pcc)
187
const gs_pattern_instance_t *pinst = pcc->pattern;
189
return (pinst == 0 ? 0 : pinst->type->procs.get_pattern(pinst));
193
* Get the number of components in a Pattern color.
194
* For backward compatibility, and to distinguish Pattern color spaces
195
* from all others, we negate the result.
198
gx_num_components_Pattern(const gs_color_space * pcs)
201
(pcs->params.pattern.has_base_space ?
202
-1 - cs_num_components(pcs->base_space) :
203
-1 /* Pattern dictionary only */ );
206
/* Remap a Pattern color. */
208
gx_remap_Pattern(const gs_client_color * pc, const gs_color_space * pcs,
209
gx_device_color * pdc, const gs_imager_state * pis,
210
gx_device * dev, gs_color_select_t select)
212
if (pc->pattern == 0) {
213
pdc->ccolor_valid = false;
214
pdc->ccolor.pattern = 0; /* for GC */
215
color_set_null_pattern(pdc);
219
pc->pattern->type->procs.remap_color(pc, pcs, pdc, pis, dev, select);
222
/* Initialize a Pattern color. */
224
gx_init_Pattern(gs_client_color * pcc, const gs_color_space * pcs)
226
if (pcs->params.pattern.has_base_space) {
227
const gs_color_space *pbcs = pcs->base_space;
229
cs_init_color(pcc, pbcs);
231
/*pcc->pattern = 0; *//* cs_full_init_color handles this */
234
/* Force a Pattern color into legal range. */
235
/* Note that if the pattern is uncolored (PaintType = 2), */
236
/* the color space must have a base space: we check this here only */
237
/* to prevent accessing uninitialized data, but if there is no base space, */
238
/* it is an error that we count on being detected elsewhere. */
240
gx_restrict_Pattern(gs_client_color * pcc, const gs_color_space * pcs)
242
/* We need a special check for the null pattern. */
244
pcc->pattern->type->procs.uses_base_space(gs_get_pattern(pcc)) &&
245
pcs->params.pattern.has_base_space
247
const gs_color_space *pbcs = pcs->base_space;
249
(*pbcs->type->restrict_color) (pcc, pbcs);
253
/* Install a Pattern color space. */
255
gx_install_Pattern(gs_color_space * pcs, gs_state * pgs)
257
if (!pcs->params.pattern.has_base_space)
259
return (pcs->base_space->type->install_cspace)(pcs->base_space, pgs);
263
* Set the overprint compositor for a Pattern color space. This does nothing;
264
* for patterns the overprint compositor is set at set_device_color time.
267
gx_set_overprint_Pattern(const gs_color_space * pcs, gs_state * pgs)
272
/* Adjust the reference counts for Pattern color spaces or colors. */
274
gx_final_Pattern(const gs_color_space * pcs)
276
/* {csrc} really do nothing? */
280
gx_adjust_color_Pattern(const gs_client_color * pcc,
281
const gs_color_space * pcs, int delta)
283
gs_pattern_instance_t *pinst = pcc->pattern;
285
rc_adjust_only(pinst, delta, "gx_adjust_color_Pattern");
286
if (pcs && pcs->params.pattern.has_base_space)
287
(pcs->base_space->type->adjust_color_count)
288
(pcc, pcs->base_space, delta);
294
ENUM_PTRS_BEGIN_PROC(cs_Pattern_enum_ptrs)
297
/* {csrc} may change to st_base_color_space */
300
static RELOC_PTRS_BEGIN(cs_Pattern_reloc_ptrs)
306
/* ---------------- Serialization. -------------------------------- */
309
gx_serialize_Pattern(const gs_color_space * pcs, stream * s)
311
const gs_pattern_params * p = &pcs->params.pattern;
313
int code = gx_serialize_cspace_type(pcs, s);
317
code = sputs(s, (const byte *)&p->has_base_space, sizeof(p->has_base_space), &n);
320
if (!p->has_base_space)
322
return cs_serialize(pcs->base_space, s);