11
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gscdevn.c 11937 2010-12-06 20:30:42Z mvrhel $ */
15
15
/* DeviceN color space and operation definition */
17
17
#include "memory_.h"
74
74
/* GC procedures */
77
77
ENUM_PTRS_BEGIN(cs_DeviceN_enum_ptrs) return 0;
78
78
ENUM_PTR(0, gs_color_space, params.device_n.names);
79
79
ENUM_PTR(1, gs_color_space, params.device_n.map);
108
108
if (palt_cspace == 0 || !palt_cspace->type->can_be_alt_space)
109
return_error(gs_error_rangecheck);
109
return_error(gs_error_rangecheck);
111
111
pcs = gs_cspace_alloc(pmem, &gs_color_space_type_DeviceN);
113
return_error(gs_error_VMerror);
113
return_error(gs_error_VMerror);
114
114
pcsdevn = &pcs->params.device_n;
115
115
pcsdevn->names = NULL;
116
116
pcsdevn->map = NULL;
119
119
/* Allocate space for color names list. */
120
120
code = alloc_device_n_map(&pcsdevn->map, pmem, "gs_cspace_build_DeviceN");
122
gs_free_object(pmem, pcs, "gs_cspace_new_DeviceN");
122
gs_free_object(pmem, pcs, "gs_cspace_new_DeviceN");
125
125
/* Allocate space for color names list. */
126
126
pnames = (gs_separation_name *)
127
gs_alloc_byte_array(pmem, num_components, sizeof(gs_separation_name),
128
".gs_cspace_build_DeviceN(names)");
127
gs_alloc_byte_array(pmem, num_components, sizeof(gs_separation_name),
128
".gs_cspace_build_DeviceN(names)");
129
129
if (pnames == 0) {
130
gs_free_object(pmem, pcsdevn->map, ".gs_cspace_build_DeviceN(map)");
131
gs_free_object(pmem, pcs, "gs_cspace_new_DeviceN");
132
return_error(gs_error_VMerror);
130
gs_free_object(pmem, pcsdevn->map, ".gs_cspace_build_DeviceN(map)");
131
gs_free_object(pmem, pcs, "gs_cspace_new_DeviceN");
132
return_error(gs_error_VMerror);
134
134
pcs->base_space = palt_cspace;
135
135
rc_increment_cs(palt_cspace);
142
142
/* Allocate and initialize a DeviceN map. */
144
144
alloc_device_n_map(gs_device_n_map ** ppmap, gs_memory_t * mem,
147
147
gs_device_n_map *pimap;
149
149
rc_alloc_struct_1(pimap, gs_device_n_map, &st_device_n_map, mem,
150
return_error(gs_error_VMerror), cname);
150
return_error(gs_error_VMerror), cname);
151
151
pimap->tint_transform = 0;
152
152
pimap->tint_transform_data = 0;
153
153
pimap->cache_valid = false;
174
174
/* Verify that we have a DeviceN color space */
176
return_error(gs_error_rangecheck);
176
return_error(gs_error_rangecheck);
177
177
pdevncs = gs_currentcolorspace_inline(pgs->saved);
178
178
if (pdevncs->type != &gs_color_space_type_DeviceN)
179
return_error(gs_error_rangecheck);
179
return_error(gs_error_rangecheck);
181
181
/* Allocate an attribute list element for our linked list of attributes */
182
182
rc_alloc_struct_1(patt, gs_device_n_attributes, &st_device_n_attributes,
183
pgs->memory, return_error(gs_error_VMerror),
184
"gs_attachattributrescolorspace");
183
pgs->memory, return_error(gs_error_VMerror),
184
"gs_attachattributrescolorspace");
186
186
/* Point our attribute list entry to the attribute color space */
187
187
patt->colorant_name = sep_name;
203
203
gs_cspace_set_devn_proc(gs_color_space * pcspace,
204
int (*proc)(const float *,
204
int (*proc)(const float *,
206
206
const gs_imager_state *,
212
212
gs_device_n_map *pimap;
214
214
if (gs_color_space_get_index(pcspace) != gs_color_space_index_DeviceN)
215
return_error(gs_error_rangecheck);
215
return_error(gs_error_rangecheck);
216
216
pimap = pcspace->params.device_n.map;
217
217
pimap->tint_transform = proc;
218
218
pimap->tint_transform_data = proc_data;
233
233
/* Map a DeviceN color using a Function. */
235
235
map_devn_using_function(const float *in, float *out,
236
const gs_imager_state *pis, void *data)
236
const gs_imager_state *pis, void *data)
239
239
gs_function_t *const pfn = data;
250
250
gs_device_n_map *pimap;
252
252
if (gs_color_space_get_index(pcspace) != gs_color_space_index_DeviceN ||
253
pfn->params.m != pcspace->params.device_n.num_components ||
254
pfn->params.n != gs_color_space_num_components(pcspace->base_space)
256
return_error(gs_error_rangecheck);
253
pfn->params.m != pcspace->params.device_n.num_components ||
254
pfn->params.n != gs_color_space_num_components(pcspace->base_space)
256
return_error(gs_error_rangecheck);
257
257
pimap = pcspace->params.device_n.map;
258
258
pimap->tint_transform = map_devn_using_function;
259
259
pimap->tint_transform_data = pfn;
269
269
gs_cspace_get_devn_function(const gs_color_space *pcspace)
271
271
if (gs_color_space_get_index(pcspace) == gs_color_space_index_DeviceN &&
272
pcspace->params.device_n.map->tint_transform ==
273
map_devn_using_function)
274
return pcspace->params.device_n.map->tint_transform_data;
272
pcspace->params.device_n.map->tint_transform ==
273
map_devn_using_function)
274
return pcspace->params.device_n.map->tint_transform_data;
303
303
for (i = 0; i < pcs->params.device_n.num_components; ++i) {
304
floatp value = pcc->paint.values[i];
305
pcc->paint.values[i] = (value <= 0 ? 0 : value >= 1 ? 1 : value);
304
floatp value = pcc->paint.values[i];
305
pcc->paint.values[i] = (value <= 0 ? 0 : value >= 1 ? 1 : value);
309
309
/* Remap a DeviceN color. */
310
310
static const gs_color_space *
311
311
gx_concrete_space_DeviceN(const gs_color_space * pcs,
312
const gs_imager_state * pis)
312
const gs_imager_state * pis)
314
314
bool is_lab = false;
317
317
* Verify that the color space and imager state info match.
319
319
if (pcs->id != pis->color_component_map.cspace_id)
320
dprintf("gx_concrete_space_DeviceN: color space id mismatch");
320
dprintf("gx_concrete_space_DeviceN: color space id mismatch");
323
323
* Check if we are using the alternate color space.
326
326
/* Need to handle PS CIE space */
327
327
if (gs_color_space_is_PSCIE(pcs->base_space)) {
328
328
if (pcs->base_space->icc_equivalent == NULL) {
329
gs_colorspace_set_icc_equivalent(pcs->base_space,
329
gs_colorspace_set_icc_equivalent(pcs->base_space,
330
330
&is_lab, pis->memory);
332
332
return (pcs->base_space->icc_equivalent);
334
334
return cs_concrete_space(pcs->base_space, pis);
343
343
gx_remap_DeviceN(const gs_client_color * pcc, const gs_color_space * pcs,
344
gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
345
gs_color_select_t select)
344
gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
345
gs_color_select_t select)
347
347
frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
348
348
const gs_color_space *pconcs;
352
352
gs_client_color temp;
354
354
if ( pcs->cmm_icc_profile_data != NULL && pis->color_component_map.use_alt_cspace) {
355
/* If needed, reorganize the data. The ICC colorants tag drives the
355
/* If needed, reorganize the data. The ICC colorants tag drives the
356
356
the laydown order */
357
357
if (pcs->cmm_icc_profile_data->devicen_permute_needed) {
358
358
for ( k = 0; k < i; k++) {
367
367
code = (*pcs->type->concretize_color)(pcc, pcs, conc, pis, dev);
370
370
pconcs = cs_concrete_space(pcs, pis);
371
371
code = (*pconcs->type->remap_concrete_color)(conc, pconcs, pdc, pis, dev, select);
372
372
/* Save original color space and color info into dev color */
374
374
for (i--; i >= 0; i--)
375
pdc->ccolor.paint.values[i] = pcc->paint.values[i];
375
pdc->ccolor.paint.values[i] = pcc->paint.values[i];
376
376
pdc->ccolor_valid = true;
382
382
gx_concretize_DeviceN(const gs_client_color * pc, const gs_color_space * pcs,
383
frac * pconc, const gs_imager_state * pis, gx_device *dev)
383
frac * pconc, const gs_imager_state * pis, gx_device *dev)
385
385
int code, tcode = 0;
386
386
gs_client_color cc;
404
404
if (pis->color_component_map.use_alt_cspace) {
406
/* Check the 1-element cache first. */
407
if (map->cache_valid) {
410
for (i = pcs->params.device_n.num_components; --i >= 0;) {
411
if (map->tint[i] != pc->paint.values[i])
415
int num_out = gs_color_space_num_components(pacs);
417
for (i = 0; i < num_out; ++i)
418
pconc[i] = map->conc[i];
406
/* Check the 1-element cache first. */
407
if (map->cache_valid) {
410
for (i = pcs->params.device_n.num_components; --i >= 0;) {
411
if (map->tint[i] != pc->paint.values[i])
415
int num_out = gs_color_space_num_components(pacs);
417
for (i = 0; i < num_out; ++i)
418
pconc[i] = map->conc[i];
422
422
tcode = (*pcs->params.device_n.map->tint_transform)
423
(pc->paint.values, &cc.paint.values[0],
424
pis, pcs->params.device_n.map->tint_transform_data);
423
(pc->paint.values, &cc.paint.values[0],
424
pis, pcs->params.device_n.map->tint_transform_data);
425
(*pacs->type->restrict_color)(&cc, pacs);
427
428
/* First check if this was PS based. */
428
429
if (gs_color_space_is_PSCIE(pacs)) {
429
430
/* If we have not yet create the profile do that now */
438
439
cc.paint.values[0] /= 100.0;
439
440
cc.paint.values[1] = (cc.paint.values[1]+128)/255.0;
440
441
cc.paint.values[2] = (cc.paint.values[2]+128)/255.0;
442
443
code = cs_concretize_color(&cc, pacs, pconc, pis, dev);
447
for (i = pcs->params.device_n.num_components; --i >= 0;)
448
pconc[i] = gx_unit_frac(pc->paint.values[i]);
448
for (i = pcs->params.device_n.num_components; --i >= 0;)
449
pconc[i] = gx_unit_frac(pc->paint.values[i]);
451
452
return (code < 0 || tcode == 0 ? code : tcode);
455
456
gx_remap_concrete_DeviceN(const frac * pconc, const gs_color_space * pcs,
456
gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
457
gs_color_select_t select)
457
gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
458
gs_color_select_t select)
461
462
* Verify that the color space and imager state info match.
463
464
if (pcs->id != pis->color_component_map.cspace_id)
464
dprintf("gx_remap_concrete_DeviceN: color space id mismatch");
465
dprintf("gx_remap_concrete_DeviceN: color space id mismatch");
466
467
if (pis->color_component_map.use_alt_cspace) {
467
468
const gs_color_space *pacs = pcs->base_space;
469
return (*pacs->type->remap_concrete_color)
470
(pconc, pacs, pdc, pis, dev, select);
470
return (*pacs->type->remap_concrete_color)
471
(pconc, pacs, pdc, pis, dev, select);
473
gx_remap_concrete_devicen(pconc, pdc, pis, dev, select);
474
gx_remap_concrete_devicen(pconc, pdc, pis, dev, select);
503
504
* using an additive color model.
505
506
if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) {
506
pcolor_component_map->use_alt_cspace = true;
507
pcolor_component_map->use_alt_cspace = true;
510
511
* Now check the names of the color components.
512
513
non_match = false;
513
514
for(i = 0; i < num_comp; i++ ) {
515
* Get the character string and length for the component name.
517
pcs->params.device_n.get_colorname_string(dev->memory, names[i], &pname, &name_size);
519
* Compare the colorant name to the device's. If the device's
520
* compare routine returns GX_DEVICE_COLOR_MAX_COMPONENTS then the
521
* colorant is in the SeparationNames list but not in the
522
* SeparationOrder list.
524
colorant_number = (*dev_proc(dev, get_color_comp_index))
525
(dev, (const char *)pname, name_size, SEPARATION_NAME);
526
if (colorant_number >= 0) { /* If valid colorant name */
527
pcolor_component_map->color_map[i] =
528
(colorant_number == GX_DEVICE_COLOR_MAX_COMPONENTS) ? -1
516
* Get the character string and length for the component name.
518
pcs->params.device_n.get_colorname_string(dev->memory, names[i], &pname, &name_size);
520
* Compare the colorant name to the device's. If the device's
521
* compare routine returns GX_DEVICE_COLOR_MAX_COMPONENTS then the
522
* colorant is in the SeparationNames list but not in the
523
* SeparationOrder list.
525
colorant_number = (*dev_proc(dev, get_color_comp_index))
526
(dev, (const char *)pname, name_size, SEPARATION_NAME);
527
if (colorant_number >= 0) { /* If valid colorant name */
528
pcolor_component_map->color_map[i] =
529
(colorant_number == GX_DEVICE_COLOR_MAX_COMPONENTS) ? -1
534
535
pcolor_component_map->use_alt_cspace = non_match;
546
547
/* See if we have an ICC profile that we can associate with
547
548
this DeviceN color space */
548
549
if (pgs->icc_manager->device_n != NULL) {
549
/* An nclr profile is in the manager. Grab one
551
pcs->cmm_icc_profile_data = gsicc_finddevicen(pcs, pgs->icc_manager);
550
/* An nclr profile is in the manager. Grab one that matches. */
551
cmm_profile_t *profdata = gsicc_finddevicen(pcs, pgs->icc_manager);
552
if (profdata != NULL)
553
rc_increment(profdata);
552
554
if (pcs->cmm_icc_profile_data != NULL)
553
rc_adjust(pcs->cmm_icc_profile_data, pcs->rc.ref_count, "gs_install_DeviceN");
555
rc_decrement(pcs->cmm_icc_profile_data, "gx_install_DeviceN");
556
pcs->cmm_icc_profile_data = profdata;
555
558
/* {csrc} was pgs->color_space->params.device_n.use_alt_cspace */
556
559
((gs_color_space *)pcs)->params.device_n.use_alt_cspace =
557
using_alt_color_space(pgs);
560
using_alt_color_space(pgs);
558
561
if (pcs->params.device_n.use_alt_cspace && pcs->cmm_icc_profile_data == NULL ) {
559
562
/* No nclr ICC profile */
560
563
code = (pcs->base_space->type->install_cspace)
561
(pcs->base_space, pgs);
564
(pcs->base_space, pgs);
562
565
} else if (pcs->params.device_n.use_alt_cspace) {
563
566
gs_color_space *nclr_pcs;
564
567
/* Need to install the nclr cspace */
565
568
code = gs_cspace_build_ICC(&nclr_pcs, NULL, pgs->memory);
566
569
nclr_pcs->cmm_icc_profile_data = pcs->cmm_icc_profile_data;
567
rc_increment_cs(nclr_pcs);
570
rc_increment(pcs->cmm_icc_profile_data);
571
rc_increment_cs(nclr_pcs); // Suspicious - RJW
568
572
rc_decrement_cs(pcs->base_space, "gx_install_DeviceN");
569
573
pcs->base_space = nclr_pcs;
585
589
gs_devicen_color_map * pcmap = &pgs->color_component_map;
587
591
if (pcmap->use_alt_cspace) {
588
const gs_color_space_type* base_type = pcs->base_space->type;
590
/* If the base space is DeviceCMYK, handle overprint as DeviceCMYK */
591
if ( base_type->index == gs_color_space_index_DeviceCMYK )
592
return base_type->set_overprint( pcs->base_space, pgs );
594
return gx_spot_colors_set_overprint( pcs->base_space, pgs);
592
const gs_color_space_type* base_type = pcs->base_space->type;
594
/* If the base space is DeviceCMYK, handle overprint as DeviceCMYK */
595
if ( base_type->index == gs_color_space_index_DeviceCMYK )
596
return base_type->set_overprint( pcs->base_space, pgs );
598
return gx_spot_colors_set_overprint( pcs->base_space, pgs);
597
601
gs_overprint_params_t params;
623
627
rc_decrement_only(pcs->params.device_n.map, "gx_adjust_DeviceN");
624
628
while (patt != NULL) {
625
pnextatt = patt->next;
626
rc_decrement_cs(patt->cspace, "gx_final_DeviceN");
629
pnextatt = patt->next;
630
rc_decrement_cs(patt->cspace, "gx_final_DeviceN");
627
631
rc_decrement(patt, "gx_adjust_DeviceN");
632
636
/* ---------------- Serialization. -------------------------------- */
635
639
gx_serialize_device_n_map(const gs_color_space * pcs, gs_device_n_map * m, stream * s)
637
641
const gs_function_t *pfn;
639
643
if (m->tint_transform != map_devn_using_function)
640
return_error(gs_error_unregistered); /* Unimplemented. */
644
return_error(gs_error_unregistered); /* Unimplemented. */
641
645
pfn = (const gs_function_t *)m->tint_transform_data;
642
646
return gs_function_serialize(pfn, s);
646
650
gx_serialize_DeviceN(const gs_color_space * pcs, stream * s)
648
652
const gs_device_n_params * p = &pcs->params.device_n;
650
654
int code = gx_serialize_cspace_type(pcs, s);
654
658
code = sputs(s, (const byte *)&p->num_components, sizeof(p->num_components), &n);
657
661
code = sputs(s, (const byte *)&p->names[0], sizeof(p->names[0]) * p->num_components, &n);
660
664
code = cs_serialize(pcs->base_space, s);
663
667
return gx_serialize_device_n_map(pcs, p->map, s);
664
668
/* p->use_alt_cspace isn't a property of the space. */