123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- /* Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved.
-
- This file is part of AFPL Ghostscript.
-
- AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
- distributor accepts any responsibility for the consequences of using it, or
- for whether it serves any particular purpose or works at all, unless he or
- she says so in writing. Refer to the Aladdin Free Public License (the
- "License") for full details.
-
- Every copy of AFPL Ghostscript must include a copy of the License, normally
- in a plain ASCII text file named PUBLIC. The License grants you the right
- to copy, modify and redistribute AFPL Ghostscript, but only under certain
- conditions described in the License. Among other things, the License
- requires that the copyright notice and this notice be preserved on all
- copies.
- */
- /*$Id: gscdevn.c,v 1.6 2001/08/21 23:52:36 dancoby Exp $ */
- /* DeviceN color space and operation definition */
- #include "memory_.h"
- #include "gx.h"
- #include "gserrors.h"
- #include "gscdevn.h"
- #include "gsfunc.h"
- #include "gsrefct.h"
- #include "gsmatrix.h" /* for gscolor2.h */
- #include "gsstruct.h"
- #include "gxcspace.h"
- #include "gxcdevn.h"
- /* ---------------- Color space ---------------- */
- /* GC descriptors */
- gs_private_st_composite(st_color_space_DeviceN, gs_paint_color_space,
- "gs_color_space_DeviceN", cs_DeviceN_enum_ptrs, cs_DeviceN_reloc_ptrs);
- private_st_device_n_map();
- /* Define the DeviceN color space type. */
- private cs_proc_num_components(gx_num_components_DeviceN);
- private cs_proc_base_space(gx_alt_space_DeviceN);
- private cs_proc_equal(gx_equal_DeviceN);
- private cs_proc_init_color(gx_init_DeviceN);
- private cs_proc_restrict_color(gx_restrict_DeviceN);
- private cs_proc_concrete_space(gx_concrete_space_DeviceN);
- private cs_proc_concretize_color(gx_concretize_DeviceN);
- private cs_proc_remap_concrete_color(gx_remap_concrete_DeviceN);
- private cs_proc_install_cspace(gx_install_DeviceN);
- private cs_proc_adjust_cspace_count(gx_adjust_cspace_DeviceN);
- const gs_color_space_type gs_color_space_type_DeviceN = {
- gs_color_space_index_DeviceN, true, false,
- &st_color_space_DeviceN, gx_num_components_DeviceN,
- gx_alt_space_DeviceN, gx_equal_DeviceN,
- gx_init_DeviceN, gx_restrict_DeviceN,
- gx_concrete_space_DeviceN,
- gx_concretize_DeviceN, gx_remap_concrete_DeviceN,
- gx_default_remap_color, gx_install_DeviceN,
- gx_adjust_cspace_DeviceN, gx_no_adjust_color_count
- };
- /* GC procedures */
- private
- ENUM_PTRS_WITH(cs_DeviceN_enum_ptrs, gs_color_space *pcs)
- {
- return ENUM_USING(*pcs->params.device_n.alt_space.type->stype,
- &pcs->params.device_n.alt_space,
- sizeof(pcs->params.device_n.alt_space), index - 2);
- }
- ENUM_PTR(0, gs_color_space, params.device_n.names);
- ENUM_PTR(1, gs_color_space, params.device_n.map);
- ENUM_PTRS_END
- private RELOC_PTRS_WITH(cs_DeviceN_reloc_ptrs, gs_color_space *pcs)
- {
- RELOC_PTR(gs_color_space, params.device_n.names);
- RELOC_PTR(gs_color_space, params.device_n.map);
- RELOC_USING(*pcs->params.device_n.alt_space.type->stype,
- &pcs->params.device_n.alt_space,
- sizeof(gs_base_color_space));
- }
- RELOC_PTRS_END
- /* ------ Public procedures ------ */
- /*
- * Build a DeviceN color space.
- */
- int
- gs_cspace_build_DeviceN(
- gs_color_space **ppcspace,
- gs_separation_name *psnames,
- uint num_components,
- const gs_color_space *palt_cspace,
- gs_memory_t *pmem
- )
- {
- gs_color_space *pcspace = 0; /* bogus initialization */
- gs_device_n_params *pcsdevn = 0; /* bogus initialization */
- int code;
- if (palt_cspace == 0 || !palt_cspace->type->can_be_alt_space)
- return_error(gs_error_rangecheck);
- code = gs_cspace_alloc(&pcspace, &gs_color_space_type_DeviceN, pmem);
- if (code < 0)
- return code;
- pcsdevn = &pcspace->params.device_n;
- code = alloc_device_n_map(&pcsdevn->map, pmem, "gs_cspace_build_DeviceN");
- if (code < 0) {
- gs_free_object(pmem, pcspace, "gs_cspace_build_DeviceN");
- return code;
- }
- pcsdevn->names = psnames;
- pcsdevn->num_components = num_components;
- gs_cspace_init_from((gs_color_space *)&pcsdevn->alt_space, palt_cspace);
- *ppcspace = pcspace;
- return 0;
- }
- /* Allocate and initialize a DeviceN map. */
- int
- alloc_device_n_map(gs_device_n_map ** ppmap, gs_memory_t * mem,
- client_name_t cname)
- {
- gs_device_n_map *pimap;
- rc_alloc_struct_1(pimap, gs_device_n_map, &st_device_n_map, mem,
- return_error(gs_error_VMerror), cname);
- pimap->tint_transform = 0;
- pimap->tint_transform_data = 0;
- pimap->cache_valid = false;
- *ppmap = pimap;
- return 0;
- }
- /*
- * Set the DeviceN tint transformation procedure.
- */
- int
- gs_cspace_set_devn_proc(gs_color_space * pcspace,
- int (*proc)(P5(const gs_device_n_params *,
- const float *,
- float *,
- const gs_imager_state *,
- void *
- )),
- void *proc_data
- )
- {
- gs_device_n_map *pimap;
- if (gs_color_space_get_index(pcspace) != gs_color_space_index_DeviceN)
- return_error(gs_error_rangecheck);
- pimap = pcspace->params.device_n.map;
- pimap->tint_transform = proc;
- pimap->tint_transform_data = proc_data;
- pimap->cache_valid = false;
- return 0;
- }
- /* Map a DeviceN color using a Function. */
- private int
- map_devn_using_function(const gs_device_n_params *pcsdevn,
- const float *in, float *out,
- const gs_imager_state *pis, void *data)
- {
- gs_function_t *const pfn = data;
- return gs_function_evaluate(pfn, in, out);
- }
- /*
- * Set the DeviceN tint transformation procedure to a Function.
- */
- int
- gs_cspace_set_devn_function(gs_color_space *pcspace, gs_function_t *pfn)
- {
- gs_device_n_map *pimap;
- if (gs_color_space_get_index(pcspace) != gs_color_space_index_DeviceN ||
- pfn->params.m != pcspace->params.device_n.num_components ||
- pfn->params.n !=
- gs_color_space_num_components((gs_color_space *)
- &pcspace->params.device_n.alt_space)
- )
- return_error(gs_error_rangecheck);
- pimap = pcspace->params.device_n.map;
- pimap->tint_transform = map_devn_using_function;
- pimap->tint_transform_data = pfn;
- pimap->cache_valid = false;
- return 0;
- }
- /*
- * If the DeviceN tint transformation procedure is a Function,
- * return the function object, otherwise return 0.
- */
- gs_function_t *
- gs_cspace_get_devn_function(const gs_color_space *pcspace)
- {
- if (gs_color_space_get_index(pcspace) == gs_color_space_index_DeviceN &&
- pcspace->params.device_n.map->tint_transform ==
- map_devn_using_function)
- return pcspace->params.device_n.map->tint_transform_data;
- return 0;
- }
- /* ------ Color space implementation ------ */
- /* Return the number of components of a DeviceN space. */
- private int
- gx_num_components_DeviceN(const gs_color_space * pcs)
- {
- return pcs->params.device_n.num_components;
- }
- /* Return the alternate space of a DeviceN space. */
- private const gs_color_space *
- gx_alt_space_DeviceN(const gs_color_space * pcs)
- {
- return (const gs_color_space *)&(pcs->params.device_n.alt_space);
- }
- /* Test whether one DeviceN color space equals another. */
- private bool
- gx_equal_DeviceN(const gs_color_space *pcs1, const gs_color_space *pcs2)
- {
- return (gs_color_space_equal(gx_alt_space_DeviceN(pcs1),
- gx_alt_space_DeviceN(pcs2)) &&
- pcs1->params.device_n.num_components ==
- pcs2->params.device_n.num_components &&
- !memcmp(pcs1->params.device_n.names, pcs2->params.device_n.names,
- pcs1->params.device_n.num_components *
- sizeof(pcs1->params.device_n.names[0])) &&
- pcs1->params.device_n.map->tint_transform ==
- pcs2->params.device_n.map->tint_transform &&
- pcs1->params.device_n.map->tint_transform_data ==
- pcs2->params.device_n.map->tint_transform_data);
- }
- /* Initialize a DeviceN color. */
- private void
- gx_init_DeviceN(gs_client_color * pcc, const gs_color_space * pcs)
- {
- int i;
- for (i = 0; i < pcs->params.device_n.num_components; ++i)
- pcc->paint.values[i] = 1.0;
- }
- /* Force a DeviceN color into legal range. */
- private void
- gx_restrict_DeviceN(gs_client_color * pcc, const gs_color_space * pcs)
- {
- int i;
- for (i = 0; i < pcs->params.device_n.num_components; ++i) {
- floatp value = pcc->paint.values[i];
- pcc->paint.values[i] = (value <= 0 ? 0 : value >= 1 ? 1 : value);
- }
- }
- /* Remap a DeviceN color. */
- private const gs_color_space *
- gx_concrete_space_DeviceN(const gs_color_space * pcs,
- const gs_imager_state * pis)
- {
- /* We don't support concrete DeviceN spaces yet. */
- const gs_color_space *pacs =
- (const gs_color_space *)&pcs->params.device_n.alt_space;
- return cs_concrete_space(pacs, pis);
- }
- private int
- gx_concretize_DeviceN(const gs_client_color * pc, const gs_color_space * pcs,
- frac * pconc, const gs_imager_state * pis)
- {
- int code, tcode;
- gs_client_color cc;
- const gs_color_space *pacs =
- (const gs_color_space *)&pcs->params.device_n.alt_space;
- gs_device_n_map *map = pcs->params.device_n.map;
- /* Check the 1-element cache first. */
- if (map->cache_valid) {
- int i;
- for (i = pcs->params.device_n.num_components; --i >= 0;) {
- if (map->tint[i] != pc->paint.values[i])
- break;
- }
- if (i < 0) {
- int num_out = gs_color_space_num_components(pacs);
- for (i = 0; i < num_out; ++i)
- pconc[i] = map->conc[i];
- return 0;
- }
- }
- /*
- * We always map into the alternate color space. We must preserve
- * tcode for implementing a semi-hack in the interpreter.
- */
- tcode = (*pcs->params.device_n.map->tint_transform)
- (&pcs->params.device_n, pc->paint.values, &cc.paint.values[0],
- pis, pcs->params.device_n.map->tint_transform_data);
- if (tcode < 0)
- return tcode;
- code = (*pacs->type->concretize_color) (&cc, pacs, pconc, pis);
- return (code < 0 || tcode == 0 ? code : tcode);
- }
- private int
- gx_remap_concrete_DeviceN(const frac * pconc,
- gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
- gs_color_select_t select)
- {
- /* We don't support concrete DeviceN colors yet. */
- return_error(gs_error_rangecheck);
- }
- /* Install a DeviceN color space. */
- private int
- gx_install_DeviceN(const gs_color_space * pcs, gs_state * pgs)
- {
- const gs_separation_name *names = pcs->params.device_n.names;
- uint i, j;
- const char none_str[] = "None";
- const int none_size = strlen(none_str);
- /*
- * Postscript does not accept /None as a color component but it is
- * allowed in PDF so we accept it. Except for /None, no components
- * are allowed to have duplicated names.
- */
- for (i = 1; i < pcs->params.device_n.num_components; ++i) {
- byte *pname;
- uint name_size;
- pcs->params.device_n.get_colorname_string(names[i], &pname, &name_size);
- if (name_size != none_size ||
- (strncmp(none_str, (const char *) pname, name_size)!=0)) {
- for (j = 0; j < i; ++j) {
- if (names[i] == names[j])
- return_error(gs_error_rangecheck);
- }
- }
- }
- return (*pcs->params.device_n.alt_space.type->install_cspace)
- ((const gs_color_space *) & pcs->params.device_n.alt_space, pgs);
- }
- /* Adjust the reference count of a DeviceN color space. */
- private void
- gx_adjust_cspace_DeviceN(const gs_color_space * pcs, int delta)
- {
- rc_adjust_const(pcs->params.device_n.map, delta, "gx_adjust_DeviceN");
- (*pcs->params.device_n.alt_space.type->adjust_cspace_count)
- ((const gs_color_space *)&pcs->params.device_n.alt_space, delta);
- }
|