17dd7cddfSDavid du Colombier /* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid 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.
97dd7cddfSDavid 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.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: zht2.c,v 1.14 2005/10/11 10:04:28 leonardo Exp $ */
187dd7cddfSDavid du Colombier /* Level 2 sethalftone operator */
197dd7cddfSDavid du Colombier #include "ghost.h"
207dd7cddfSDavid du Colombier #include "oper.h"
217dd7cddfSDavid du Colombier #include "gsstruct.h"
227dd7cddfSDavid du Colombier #include "gxdevice.h" /* for gzht.h */
237dd7cddfSDavid du Colombier #include "gzht.h"
247dd7cddfSDavid du Colombier #include "estack.h"
257dd7cddfSDavid du Colombier #include "ialloc.h"
267dd7cddfSDavid du Colombier #include "iddict.h"
277dd7cddfSDavid du Colombier #include "idparam.h"
287dd7cddfSDavid du Colombier #include "igstate.h"
297dd7cddfSDavid du Colombier #include "icolor.h"
307dd7cddfSDavid du Colombier #include "iht.h"
317dd7cddfSDavid du Colombier #include "store.h"
32*593dc095SDavid du Colombier #include "iname.h"
33*593dc095SDavid du Colombier #include "zht2.h"
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier /* Forward references */
36*593dc095SDavid du Colombier private int dict_spot_params(const ref *, gs_spot_halftone *, ref *, ref *);
37*593dc095SDavid du Colombier private int dict_spot_results(i_ctx_t *, ref *, const gs_spot_halftone *);
38*593dc095SDavid du Colombier private int dict_threshold_params(const ref *, gs_threshold_halftone *,
39*593dc095SDavid du Colombier ref *);
40*593dc095SDavid du Colombier private int dict_threshold2_params(const ref *, gs_threshold2_halftone *,
41*593dc095SDavid du Colombier ref *, gs_memory_t *);
42*593dc095SDavid du Colombier
43*593dc095SDavid du Colombier /*
44*593dc095SDavid du Colombier * This routine translates a gs_separation_name value into a character string
45*593dc095SDavid du Colombier * pointer and a string length.
46*593dc095SDavid du Colombier */
47*593dc095SDavid du Colombier int
gs_get_colorname_string(const gs_memory_t * mem,gs_separation_name colorname_index,unsigned char ** ppstr,unsigned int * pname_size)48*593dc095SDavid du Colombier gs_get_colorname_string(const gs_memory_t *mem, gs_separation_name colorname_index,
49*593dc095SDavid du Colombier unsigned char **ppstr, unsigned int *pname_size)
50*593dc095SDavid du Colombier {
51*593dc095SDavid du Colombier ref nref;
52*593dc095SDavid du Colombier
53*593dc095SDavid du Colombier name_index_ref(mem, colorname_index, &nref);
54*593dc095SDavid du Colombier name_string_ref(mem, &nref, &nref);
55*593dc095SDavid du Colombier return obj_string_data(mem, &nref, (const unsigned char**) ppstr, pname_size);
56*593dc095SDavid du Colombier }
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier /* Dummy spot function */
597dd7cddfSDavid du Colombier private float
spot1_dummy(floatp x,floatp y)607dd7cddfSDavid du Colombier spot1_dummy(floatp x, floatp y)
617dd7cddfSDavid du Colombier {
627dd7cddfSDavid du Colombier return (x + y) / 2;
637dd7cddfSDavid du Colombier }
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier /* <dict> <dict5> .sethalftone5 - */
66*593dc095SDavid du Colombier private int sethalftone_finish(i_ctx_t *);
67*593dc095SDavid du Colombier private int sethalftone_cleanup(i_ctx_t *);
687dd7cddfSDavid du Colombier private int
zsethalftone5(i_ctx_t * i_ctx_p)697dd7cddfSDavid du Colombier zsethalftone5(i_ctx_t *i_ctx_p)
707dd7cddfSDavid du Colombier {
717dd7cddfSDavid du Colombier os_ptr op = osp;
727dd7cddfSDavid du Colombier uint count;
737dd7cddfSDavid du Colombier gs_halftone_component *phtc;
747dd7cddfSDavid du Colombier gs_halftone_component *pc;
757dd7cddfSDavid du Colombier int code = 0;
76*593dc095SDavid du Colombier int j;
777dd7cddfSDavid du Colombier gs_halftone *pht;
787dd7cddfSDavid du Colombier gx_device_halftone *pdht;
79*593dc095SDavid du Colombier ref sprocs[GS_CLIENT_COLOR_MAX_COMPONENTS + 1];
80*593dc095SDavid du Colombier ref tprocs[GS_CLIENT_COLOR_MAX_COMPONENTS + 1];
817dd7cddfSDavid du Colombier gs_memory_t *mem;
827dd7cddfSDavid du Colombier uint edepth = ref_stack_count(&e_stack);
837dd7cddfSDavid du Colombier int npop = 2;
84*593dc095SDavid du Colombier int dict_enum = dict_first(op);
85*593dc095SDavid du Colombier ref rvalue[2];
86*593dc095SDavid du Colombier int cname, colorant_number;
87*593dc095SDavid du Colombier byte * pname;
88*593dc095SDavid du Colombier uint name_size;
89*593dc095SDavid du Colombier int halftonetype, type = 0;
90*593dc095SDavid du Colombier gs_state *pgs = igs;
91*593dc095SDavid du Colombier int space_index = r_space_index(op - 1);
92*593dc095SDavid du Colombier
93*593dc095SDavid du Colombier mem = (gs_memory_t *) idmemory->spaces_indexed[space_index];
947dd7cddfSDavid du Colombier
957dd7cddfSDavid du Colombier check_type(*op, t_dictionary);
967dd7cddfSDavid du Colombier check_dict_read(*op);
977dd7cddfSDavid du Colombier check_type(op[-1], t_dictionary);
987dd7cddfSDavid du Colombier check_dict_read(op[-1]);
997dd7cddfSDavid du Colombier
100*593dc095SDavid du Colombier /*
101*593dc095SDavid du Colombier * We think that Type 2 and Type 4 halftones, like
102*593dc095SDavid du Colombier * screens set by setcolorscreen, adapt automatically to
103*593dc095SDavid du Colombier * the device color space, so we need to mark them
104*593dc095SDavid du Colombier * with a different internal halftone type.
105*593dc095SDavid du Colombier */
106*593dc095SDavid du Colombier dict_int_param(op - 1, "HalftoneType", 1, 5, 0, &type);
107*593dc095SDavid du Colombier halftonetype = (type == 2 || type == 4)
108*593dc095SDavid du Colombier ? ht_type_multiple_colorscreen
109*593dc095SDavid du Colombier : ht_type_multiple;
110*593dc095SDavid du Colombier
111*593dc095SDavid du Colombier /* Count how many components that we will actually use. */
112*593dc095SDavid du Colombier
113*593dc095SDavid du Colombier for (count = 0; ;) {
114*593dc095SDavid du Colombier bool have_default = false;
115*593dc095SDavid du Colombier
116*593dc095SDavid du Colombier /* Move to next element in the dictionary */
117*593dc095SDavid du Colombier if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1)
118*593dc095SDavid du Colombier break;
119*593dc095SDavid du Colombier /*
120*593dc095SDavid du Colombier * Verify that we have a valid component. We may have a
121*593dc095SDavid du Colombier * /HalfToneType entry.
122*593dc095SDavid du Colombier */
123*593dc095SDavid du Colombier if (!r_has_type(&rvalue[1], t_dictionary))
124*593dc095SDavid du Colombier continue;
125*593dc095SDavid du Colombier
126*593dc095SDavid du Colombier /* Get the name of the component verify that we will use it. */
127*593dc095SDavid du Colombier cname = name_index(mem, &rvalue[0]);
128*593dc095SDavid du Colombier code = gs_get_colorname_string(mem, cname, &pname, &name_size);
129*593dc095SDavid du Colombier if (code < 0)
130*593dc095SDavid du Colombier break;
131*593dc095SDavid du Colombier colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size,
132*593dc095SDavid du Colombier halftonetype);
133*593dc095SDavid du Colombier if (colorant_number < 0)
134*593dc095SDavid du Colombier continue;
135*593dc095SDavid du Colombier else if (colorant_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
136*593dc095SDavid du Colombier /* If here then we have the "Default" component */
137*593dc095SDavid du Colombier if (have_default)
138*593dc095SDavid du Colombier return_error(e_rangecheck);
139*593dc095SDavid du Colombier have_default = true;
1407dd7cddfSDavid du Colombier }
141*593dc095SDavid du Colombier
142*593dc095SDavid du Colombier count++;
143*593dc095SDavid du Colombier /*
144*593dc095SDavid du Colombier * Check to see if we have already reached the legal number of
145*593dc095SDavid du Colombier * components.
146*593dc095SDavid du Colombier */
147*593dc095SDavid du Colombier if (count > GS_CLIENT_COLOR_MAX_COMPONENTS + 1) {
148*593dc095SDavid du Colombier code = gs_note_error(e_rangecheck);
149*593dc095SDavid du Colombier break;
150*593dc095SDavid du Colombier }
151*593dc095SDavid du Colombier }
152*593dc095SDavid du Colombier
1537dd7cddfSDavid du Colombier check_estack(5); /* for sampling Type 1 screens */
154*593dc095SDavid du Colombier refset_null(sprocs, count);
155*593dc095SDavid du Colombier refset_null(tprocs, count);
1567dd7cddfSDavid du Colombier rc_alloc_struct_0(pht, gs_halftone, &st_halftone,
1577dd7cddfSDavid du Colombier imemory, pht = 0, ".sethalftone5");
1587dd7cddfSDavid du Colombier phtc = gs_alloc_struct_array(mem, count, gs_halftone_component,
1597dd7cddfSDavid du Colombier &st_ht_component_element,
1607dd7cddfSDavid du Colombier ".sethalftone5");
1617dd7cddfSDavid du Colombier rc_alloc_struct_0(pdht, gx_device_halftone, &st_device_halftone,
1627dd7cddfSDavid du Colombier imemory, pdht = 0, ".sethalftone5");
163*593dc095SDavid du Colombier if (pht == 0 || phtc == 0 || pdht == 0) {
164*593dc095SDavid du Colombier j = 0; /* Quiet the compiler:
165*593dc095SDavid du Colombier gs_note_error isn't necessarily identity,
166*593dc095SDavid du Colombier so j could be left ununitialized. */
1677dd7cddfSDavid du Colombier code = gs_note_error(e_VMerror);
168*593dc095SDavid du Colombier } else {
169*593dc095SDavid du Colombier dict_enum = dict_first(op);
170*593dc095SDavid du Colombier for (j = 0, pc = phtc; ;) {
1717dd7cddfSDavid du Colombier int type;
1727dd7cddfSDavid du Colombier
173*593dc095SDavid du Colombier /* Move to next element in the dictionary */
174*593dc095SDavid du Colombier if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1)
175*593dc095SDavid du Colombier break;
176*593dc095SDavid du Colombier /*
177*593dc095SDavid du Colombier * Verify that we have a valid component. We may have a
178*593dc095SDavid du Colombier * /HalfToneType entry.
179*593dc095SDavid du Colombier */
180*593dc095SDavid du Colombier if (!r_has_type(&rvalue[1], t_dictionary))
181*593dc095SDavid du Colombier continue;
182*593dc095SDavid du Colombier
183*593dc095SDavid du Colombier /* Get the name of the component */
184*593dc095SDavid du Colombier cname = name_index(mem, &rvalue[0]);
185*593dc095SDavid du Colombier code = gs_get_colorname_string(mem, cname, &pname, &name_size);
186*593dc095SDavid du Colombier if (code < 0)
187*593dc095SDavid du Colombier break;
188*593dc095SDavid du Colombier colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size,
189*593dc095SDavid du Colombier halftonetype);
190*593dc095SDavid du Colombier if (colorant_number < 0)
191*593dc095SDavid du Colombier continue; /* Do not use this component */
192*593dc095SDavid du Colombier pc->cname = cname;
193*593dc095SDavid du Colombier pc->comp_number = colorant_number;
194*593dc095SDavid du Colombier
195*593dc095SDavid du Colombier /* Now process the component dictionary */
196*593dc095SDavid du Colombier check_dict_read(rvalue[1]);
197*593dc095SDavid du Colombier if (dict_int_param(&rvalue[1], "HalftoneType", 1, 7, 0, &type) < 0) {
1987dd7cddfSDavid du Colombier code = gs_note_error(e_typecheck);
1997dd7cddfSDavid du Colombier break;
2007dd7cddfSDavid du Colombier }
2017dd7cddfSDavid du Colombier switch (type) {
2027dd7cddfSDavid du Colombier default:
2037dd7cddfSDavid du Colombier code = gs_note_error(e_rangecheck);
2047dd7cddfSDavid du Colombier break;
2057dd7cddfSDavid du Colombier case 1:
206*593dc095SDavid du Colombier code = dict_spot_params(&rvalue[1], &pc->params.spot,
207*593dc095SDavid du Colombier sprocs + j, tprocs + j);
2087dd7cddfSDavid du Colombier pc->params.spot.screen.spot_function = spot1_dummy;
2097dd7cddfSDavid du Colombier pc->type = ht_type_spot;
2107dd7cddfSDavid du Colombier break;
2117dd7cddfSDavid du Colombier case 3:
212*593dc095SDavid du Colombier code = dict_threshold_params(&rvalue[1], &pc->params.threshold,
213*593dc095SDavid du Colombier tprocs + j);
2147dd7cddfSDavid du Colombier pc->type = ht_type_threshold;
2157dd7cddfSDavid du Colombier break;
2167dd7cddfSDavid du Colombier case 7:
217*593dc095SDavid du Colombier code = dict_threshold2_params(&rvalue[1], &pc->params.threshold2,
218*593dc095SDavid du Colombier tprocs + j, imemory);
2197dd7cddfSDavid du Colombier pc->type = ht_type_threshold2;
2207dd7cddfSDavid du Colombier break;
2217dd7cddfSDavid du Colombier }
2227dd7cddfSDavid du Colombier if (code < 0)
2237dd7cddfSDavid du Colombier break;
224*593dc095SDavid du Colombier pc++;
225*593dc095SDavid du Colombier j++;
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier }
2287dd7cddfSDavid du Colombier if (code >= 0) {
229*593dc095SDavid du Colombier pht->type = halftonetype;
2307dd7cddfSDavid du Colombier pht->params.multiple.components = phtc;
231*593dc095SDavid du Colombier pht->params.multiple.num_comp = j;
232*593dc095SDavid du Colombier pht->params.multiple.get_colorname_string = gs_get_colorname_string;
2337dd7cddfSDavid du Colombier code = gs_sethalftone_prepare(igs, pht, pdht);
2347dd7cddfSDavid du Colombier }
235*593dc095SDavid du Colombier if (code >= 0) {
236*593dc095SDavid du Colombier /*
237*593dc095SDavid du Colombier * Put the actual frequency and angle in the spot function component dictionaries.
238*593dc095SDavid du Colombier */
239*593dc095SDavid du Colombier dict_enum = dict_first(op);
240*593dc095SDavid du Colombier for (pc = phtc; ; ) {
241*593dc095SDavid du Colombier /* Move to next element in the dictionary */
242*593dc095SDavid du Colombier if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1)
243*593dc095SDavid du Colombier break;
2447dd7cddfSDavid du Colombier
245*593dc095SDavid du Colombier /* Verify that we have a valid component */
246*593dc095SDavid du Colombier if (!r_has_type(&rvalue[1], t_dictionary))
247*593dc095SDavid du Colombier continue;
248*593dc095SDavid du Colombier
249*593dc095SDavid du Colombier /* Get the name of the component and verify that we will use it. */
250*593dc095SDavid du Colombier cname = name_index(mem, &rvalue[0]);
251*593dc095SDavid du Colombier code = gs_get_colorname_string(mem, cname, &pname, &name_size);
2527dd7cddfSDavid du Colombier if (code < 0)
2537dd7cddfSDavid du Colombier break;
254*593dc095SDavid du Colombier colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size,
255*593dc095SDavid du Colombier halftonetype);
256*593dc095SDavid du Colombier if (colorant_number < 0)
257*593dc095SDavid du Colombier continue;
258*593dc095SDavid du Colombier
259*593dc095SDavid du Colombier if (pc->type == ht_type_spot) {
260*593dc095SDavid du Colombier code = dict_spot_results(i_ctx_p, &rvalue[1], &pc->params.spot);
261*593dc095SDavid du Colombier if (code < 0)
262*593dc095SDavid du Colombier break;
263*593dc095SDavid du Colombier }
264*593dc095SDavid du Colombier pc++;
2657dd7cddfSDavid du Colombier }
2667dd7cddfSDavid du Colombier }
2677dd7cddfSDavid du Colombier if (code >= 0) {
2687dd7cddfSDavid du Colombier /*
2697dd7cddfSDavid du Colombier * Schedule the sampling of any Type 1 screens,
2707dd7cddfSDavid du Colombier * and any (Type 1 or Type 3) TransferFunctions.
2717dd7cddfSDavid du Colombier * Save the stack depths in case we have to back out.
2727dd7cddfSDavid du Colombier */
2737dd7cddfSDavid du Colombier uint odepth = ref_stack_count(&o_stack);
2747dd7cddfSDavid du Colombier ref odict, odict5;
2757dd7cddfSDavid du Colombier
2767dd7cddfSDavid du Colombier odict = op[-1];
2777dd7cddfSDavid du Colombier odict5 = *op;
2787dd7cddfSDavid du Colombier pop(2);
2797dd7cddfSDavid du Colombier op = osp;
2807dd7cddfSDavid du Colombier esp += 5;
2817dd7cddfSDavid du Colombier make_mark_estack(esp - 4, es_other, sethalftone_cleanup);
2827dd7cddfSDavid du Colombier esp[-3] = odict;
2837dd7cddfSDavid du Colombier make_istruct(esp - 2, 0, pht);
2847dd7cddfSDavid du Colombier make_istruct(esp - 1, 0, pdht);
2857dd7cddfSDavid du Colombier make_op_estack(esp, sethalftone_finish);
2867dd7cddfSDavid du Colombier for (j = 0; j < count; j++) {
287*593dc095SDavid du Colombier gx_ht_order *porder = NULL;
2887dd7cddfSDavid du Colombier
289*593dc095SDavid du Colombier if (pdht->components == 0)
290*593dc095SDavid du Colombier porder = &pdht->order;
291*593dc095SDavid du Colombier else {
292*593dc095SDavid du Colombier /* Find the component in pdht that matches component j in
293*593dc095SDavid du Colombier the pht; gs_sethalftone_prepare() may permute these. */
294*593dc095SDavid du Colombier int k;
295*593dc095SDavid du Colombier int comp_number = phtc[j].comp_number;
296*593dc095SDavid du Colombier for (k = 0; k < count; k++) {
297*593dc095SDavid du Colombier if (pdht->components[k].comp_number == comp_number) {
298*593dc095SDavid du Colombier porder = &pdht->components[k].corder;
299*593dc095SDavid du Colombier break;
300*593dc095SDavid du Colombier }
301*593dc095SDavid du Colombier }
302*593dc095SDavid du Colombier }
3037dd7cddfSDavid du Colombier switch (phtc[j].type) {
3047dd7cddfSDavid du Colombier case ht_type_spot:
3057dd7cddfSDavid du Colombier code = zscreen_enum_init(i_ctx_p, porder,
3067dd7cddfSDavid du Colombier &phtc[j].params.spot.screen,
307*593dc095SDavid du Colombier &sprocs[j], 0, 0, space_index);
3087dd7cddfSDavid du Colombier if (code < 0)
3097dd7cddfSDavid du Colombier break;
3107dd7cddfSDavid du Colombier /* falls through */
3117dd7cddfSDavid du Colombier case ht_type_threshold:
3127dd7cddfSDavid du Colombier if (!r_has_type(tprocs + j, t__invalid)) {
3137dd7cddfSDavid du Colombier /* Schedule TransferFunction sampling. */
3147dd7cddfSDavid du Colombier /****** check_xstack IS WRONG ******/
3157dd7cddfSDavid du Colombier check_ostack(zcolor_remap_one_ostack);
3167dd7cddfSDavid du Colombier check_estack(zcolor_remap_one_estack);
3177dd7cddfSDavid du Colombier code = zcolor_remap_one(i_ctx_p, tprocs + j,
3187dd7cddfSDavid du Colombier porder->transfer, igs,
3197dd7cddfSDavid du Colombier zcolor_remap_one_finish);
3207dd7cddfSDavid du Colombier op = osp;
3217dd7cddfSDavid du Colombier }
3227dd7cddfSDavid du Colombier break;
3237dd7cddfSDavid du Colombier default: /* not possible here, but to keep */
3247dd7cddfSDavid du Colombier /* the compilers happy.... */
3257dd7cddfSDavid du Colombier ;
3267dd7cddfSDavid du Colombier }
3277dd7cddfSDavid du Colombier if (code < 0) { /* Restore the stack. */
3287dd7cddfSDavid du Colombier ref_stack_pop_to(&o_stack, odepth);
3297dd7cddfSDavid du Colombier ref_stack_pop_to(&e_stack, edepth);
3307dd7cddfSDavid du Colombier op = osp;
3317dd7cddfSDavid du Colombier op[-1] = odict;
3327dd7cddfSDavid du Colombier *op = odict5;
3337dd7cddfSDavid du Colombier break;
3347dd7cddfSDavid du Colombier }
3357dd7cddfSDavid du Colombier npop = 0;
3367dd7cddfSDavid du Colombier }
3377dd7cddfSDavid du Colombier }
3387dd7cddfSDavid du Colombier if (code < 0) {
3397dd7cddfSDavid du Colombier gs_free_object(mem, pdht, ".sethalftone5");
3407dd7cddfSDavid du Colombier gs_free_object(mem, phtc, ".sethalftone5");
3417dd7cddfSDavid du Colombier gs_free_object(mem, pht, ".sethalftone5");
3427dd7cddfSDavid du Colombier return code;
3437dd7cddfSDavid du Colombier }
3447dd7cddfSDavid du Colombier pop(npop);
3457dd7cddfSDavid du Colombier return (ref_stack_count(&e_stack) > edepth ? o_push_estack : 0);
3467dd7cddfSDavid du Colombier }
347*593dc095SDavid du Colombier
3487dd7cddfSDavid du Colombier /* Install the halftone after sampling. */
3497dd7cddfSDavid du Colombier private int
sethalftone_finish(i_ctx_t * i_ctx_p)3507dd7cddfSDavid du Colombier sethalftone_finish(i_ctx_t *i_ctx_p)
3517dd7cddfSDavid du Colombier {
3527dd7cddfSDavid du Colombier gx_device_halftone *pdht = r_ptr(esp, gx_device_halftone);
3537dd7cddfSDavid du Colombier int code;
3547dd7cddfSDavid du Colombier
3557dd7cddfSDavid du Colombier if (pdht->components)
3567dd7cddfSDavid du Colombier pdht->order = pdht->components[0].corder;
3577dd7cddfSDavid du Colombier code = gx_ht_install(igs, r_ptr(esp - 1, gs_halftone), pdht);
3587dd7cddfSDavid du Colombier if (code < 0)
3597dd7cddfSDavid du Colombier return code;
3607dd7cddfSDavid du Colombier istate->halftone = esp[-2];
3617dd7cddfSDavid du Colombier esp -= 4;
3627dd7cddfSDavid du Colombier sethalftone_cleanup(i_ctx_p);
3637dd7cddfSDavid du Colombier return o_pop_estack;
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier /* Clean up after installing the halftone. */
3667dd7cddfSDavid du Colombier private int
sethalftone_cleanup(i_ctx_t * i_ctx_p)3677dd7cddfSDavid du Colombier sethalftone_cleanup(i_ctx_t *i_ctx_p)
3687dd7cddfSDavid du Colombier {
3697dd7cddfSDavid du Colombier gx_device_halftone *pdht = r_ptr(&esp[4], gx_device_halftone);
3707dd7cddfSDavid du Colombier gs_halftone *pht = r_ptr(&esp[3], gs_halftone);
3717dd7cddfSDavid du Colombier
3727dd7cddfSDavid du Colombier gs_free_object(pdht->rc.memory, pdht,
3737dd7cddfSDavid du Colombier "sethalftone_cleanup(device halftone)");
3747dd7cddfSDavid du Colombier gs_free_object(pht->rc.memory, pht,
3757dd7cddfSDavid du Colombier "sethalftone_cleanup(halftone)");
3767dd7cddfSDavid du Colombier return 0;
3777dd7cddfSDavid du Colombier }
3787dd7cddfSDavid du Colombier
3797dd7cddfSDavid du Colombier /* ------ Initialization procedure ------ */
3807dd7cddfSDavid du Colombier
3817dd7cddfSDavid du Colombier const op_def zht2_l2_op_defs[] =
3827dd7cddfSDavid du Colombier {
3837dd7cddfSDavid du Colombier op_def_begin_level2(),
3847dd7cddfSDavid du Colombier {"2.sethalftone5", zsethalftone5},
3857dd7cddfSDavid du Colombier /* Internal operators */
3867dd7cddfSDavid du Colombier {"0%sethalftone_finish", sethalftone_finish},
3877dd7cddfSDavid du Colombier op_def_end(0)
3887dd7cddfSDavid du Colombier };
3897dd7cddfSDavid du Colombier
3907dd7cddfSDavid du Colombier /* ------ Internal routines ------ */
3917dd7cddfSDavid du Colombier
3927dd7cddfSDavid du Colombier /* Extract frequency, angle, spot function, and accurate screens flag */
3937dd7cddfSDavid du Colombier /* from a dictionary. */
3947dd7cddfSDavid du Colombier private int
dict_spot_params(const ref * pdict,gs_spot_halftone * psp,ref * psproc,ref * ptproc)3957dd7cddfSDavid du Colombier dict_spot_params(const ref * pdict, gs_spot_halftone * psp,
3967dd7cddfSDavid du Colombier ref * psproc, ref * ptproc)
3977dd7cddfSDavid du Colombier {
3987dd7cddfSDavid du Colombier int code;
3997dd7cddfSDavid du Colombier
4007dd7cddfSDavid du Colombier check_dict_read(*pdict);
4017dd7cddfSDavid du Colombier if ((code = dict_float_param(pdict, "Frequency", 0.0,
4027dd7cddfSDavid du Colombier &psp->screen.frequency)) != 0 ||
4037dd7cddfSDavid du Colombier (code = dict_float_param(pdict, "Angle", 0.0,
4047dd7cddfSDavid du Colombier &psp->screen.angle)) != 0 ||
4057dd7cddfSDavid du Colombier (code = dict_proc_param(pdict, "SpotFunction", psproc, false)) != 0 ||
4067dd7cddfSDavid du Colombier (code = dict_bool_param(pdict, "AccurateScreens",
4077dd7cddfSDavid du Colombier gs_currentaccuratescreens(),
4087dd7cddfSDavid du Colombier &psp->accurate_screens)) < 0 ||
4097dd7cddfSDavid du Colombier (code = dict_proc_param(pdict, "TransferFunction", ptproc, false)) < 0
4107dd7cddfSDavid du Colombier )
4117dd7cddfSDavid du Colombier return (code < 0 ? code : e_undefined);
4127dd7cddfSDavid du Colombier psp->transfer = (code > 0 ? (gs_mapping_proc) 0 : gs_mapped_transfer);
4137dd7cddfSDavid du Colombier psp->transfer_closure.proc = 0;
4147dd7cddfSDavid du Colombier psp->transfer_closure.data = 0;
4157dd7cddfSDavid du Colombier return 0;
4167dd7cddfSDavid du Colombier }
4177dd7cddfSDavid du Colombier
4187dd7cddfSDavid du Colombier /* Set actual frequency and angle in a dictionary. */
4197dd7cddfSDavid du Colombier private int
dict_real_result(i_ctx_t * i_ctx_p,ref * pdict,const char * kstr,floatp val)4207dd7cddfSDavid du Colombier dict_real_result(i_ctx_t *i_ctx_p, ref * pdict, const char *kstr, floatp val)
4217dd7cddfSDavid du Colombier {
4227dd7cddfSDavid du Colombier int code = 0;
4237dd7cddfSDavid du Colombier ref *ignore;
4247dd7cddfSDavid du Colombier
4257dd7cddfSDavid du Colombier if (dict_find_string(pdict, kstr, &ignore) > 0) {
4267dd7cddfSDavid du Colombier ref rval;
4277dd7cddfSDavid du Colombier
4287dd7cddfSDavid du Colombier check_dict_write(*pdict);
4297dd7cddfSDavid du Colombier make_real(&rval, val);
4307dd7cddfSDavid du Colombier code = idict_put_string(pdict, kstr, &rval);
4317dd7cddfSDavid du Colombier }
4327dd7cddfSDavid du Colombier return code;
4337dd7cddfSDavid du Colombier }
4347dd7cddfSDavid du Colombier private int
dict_spot_results(i_ctx_t * i_ctx_p,ref * pdict,const gs_spot_halftone * psp)4357dd7cddfSDavid du Colombier dict_spot_results(i_ctx_t *i_ctx_p, ref * pdict, const gs_spot_halftone * psp)
4367dd7cddfSDavid du Colombier {
4377dd7cddfSDavid du Colombier int code;
4387dd7cddfSDavid du Colombier
4397dd7cddfSDavid du Colombier code = dict_real_result(i_ctx_p, pdict, "ActualFrequency",
4407dd7cddfSDavid du Colombier psp->screen.actual_frequency);
4417dd7cddfSDavid du Colombier if (code < 0)
4427dd7cddfSDavid du Colombier return code;
4437dd7cddfSDavid du Colombier return dict_real_result(i_ctx_p, pdict, "ActualAngle",
4447dd7cddfSDavid du Colombier psp->screen.actual_angle);
4457dd7cddfSDavid du Colombier }
4467dd7cddfSDavid du Colombier
4477dd7cddfSDavid du Colombier /* Extract Width, Height, and TransferFunction from a dictionary. */
4487dd7cddfSDavid du Colombier private int
dict_threshold_common_params(const ref * pdict,gs_threshold_halftone_common * ptp,ref ** pptstring,ref * ptproc)4497dd7cddfSDavid du Colombier dict_threshold_common_params(const ref * pdict,
4507dd7cddfSDavid du Colombier gs_threshold_halftone_common * ptp,
4517dd7cddfSDavid du Colombier ref **pptstring, ref *ptproc)
4527dd7cddfSDavid du Colombier {
4537dd7cddfSDavid du Colombier int code;
4547dd7cddfSDavid du Colombier
4557dd7cddfSDavid du Colombier check_dict_read(*pdict);
4567dd7cddfSDavid du Colombier if ((code = dict_int_param(pdict, "Width", 1, 0x7fff, -1,
4577dd7cddfSDavid du Colombier &ptp->width)) < 0 ||
4587dd7cddfSDavid du Colombier (code = dict_int_param(pdict, "Height", 1, 0x7fff, -1,
4597dd7cddfSDavid du Colombier &ptp->height)) < 0 ||
4607dd7cddfSDavid du Colombier (code = dict_find_string(pdict, "Thresholds", pptstring)) <= 0 ||
4617dd7cddfSDavid du Colombier (code = dict_proc_param(pdict, "TransferFunction", ptproc, false)) < 0
4627dd7cddfSDavid du Colombier )
4637dd7cddfSDavid du Colombier return (code < 0 ? code : e_undefined);
4647dd7cddfSDavid du Colombier ptp->transfer_closure.proc = 0;
4657dd7cddfSDavid du Colombier ptp->transfer_closure.data = 0;
4667dd7cddfSDavid du Colombier return code;
4677dd7cddfSDavid du Colombier }
4687dd7cddfSDavid du Colombier
4697dd7cddfSDavid du Colombier /* Extract threshold common parameters + Thresholds. */
4707dd7cddfSDavid du Colombier private int
dict_threshold_params(const ref * pdict,gs_threshold_halftone * ptp,ref * ptproc)4717dd7cddfSDavid du Colombier dict_threshold_params(const ref * pdict, gs_threshold_halftone * ptp,
4727dd7cddfSDavid du Colombier ref * ptproc)
4737dd7cddfSDavid du Colombier {
4747dd7cddfSDavid du Colombier ref *tstring;
4757dd7cddfSDavid du Colombier int code =
4767dd7cddfSDavid du Colombier dict_threshold_common_params(pdict,
4777dd7cddfSDavid du Colombier (gs_threshold_halftone_common *)ptp,
4787dd7cddfSDavid du Colombier &tstring, ptproc);
4797dd7cddfSDavid du Colombier
4807dd7cddfSDavid du Colombier if (code < 0)
4817dd7cddfSDavid du Colombier return code;
4827dd7cddfSDavid du Colombier check_read_type_only(*tstring, t_string);
4837dd7cddfSDavid du Colombier if (r_size(tstring) != (long)ptp->width * ptp->height)
4847dd7cddfSDavid du Colombier return_error(e_rangecheck);
4857dd7cddfSDavid du Colombier ptp->thresholds.data = tstring->value.const_bytes;
4867dd7cddfSDavid du Colombier ptp->thresholds.size = r_size(tstring);
4877dd7cddfSDavid du Colombier ptp->transfer = (code > 0 ? (gs_mapping_proc) 0 : gs_mapped_transfer);
4887dd7cddfSDavid du Colombier return 0;
4897dd7cddfSDavid du Colombier }
4907dd7cddfSDavid du Colombier
4917dd7cddfSDavid du Colombier /* Extract threshold common parameters + Thresholds, Width2, Height2, */
4927dd7cddfSDavid du Colombier /* BitsPerSample. */
4937dd7cddfSDavid du Colombier private int
dict_threshold2_params(const ref * pdict,gs_threshold2_halftone * ptp,ref * ptproc,gs_memory_t * mem)4947dd7cddfSDavid du Colombier dict_threshold2_params(const ref * pdict, gs_threshold2_halftone * ptp,
4957dd7cddfSDavid du Colombier ref * ptproc, gs_memory_t *mem)
4967dd7cddfSDavid du Colombier {
4977dd7cddfSDavid du Colombier ref *tstring;
4987dd7cddfSDavid du Colombier int code =
4997dd7cddfSDavid du Colombier dict_threshold_common_params(pdict,
5007dd7cddfSDavid du Colombier (gs_threshold_halftone_common *)ptp,
5017dd7cddfSDavid du Colombier &tstring, ptproc);
5027dd7cddfSDavid du Colombier int bps;
5037dd7cddfSDavid du Colombier uint size;
5047dd7cddfSDavid du Colombier int cw2, ch2;
5057dd7cddfSDavid du Colombier
5067dd7cddfSDavid du Colombier if (code < 0 ||
5077dd7cddfSDavid du Colombier (code = cw2 = dict_int_param(pdict, "Width2", 0, 0x7fff, 0,
5087dd7cddfSDavid du Colombier &ptp->width2)) < 0 ||
5097dd7cddfSDavid du Colombier (code = ch2 = dict_int_param(pdict, "Height2", 0, 0x7fff, 0,
5107dd7cddfSDavid du Colombier &ptp->height2)) < 0 ||
5117dd7cddfSDavid du Colombier (code = dict_int_param(pdict, "BitsPerSample", 8, 16, -1, &bps)) < 0
5127dd7cddfSDavid du Colombier )
5137dd7cddfSDavid du Colombier return code;
5147dd7cddfSDavid du Colombier if ((bps != 8 && bps != 16) || cw2 != ch2 ||
5157dd7cddfSDavid du Colombier (!cw2 && (ptp->width2 == 0 || ptp->height2 == 0))
5167dd7cddfSDavid du Colombier )
5177dd7cddfSDavid du Colombier return_error(e_rangecheck);
5187dd7cddfSDavid du Colombier ptp->bytes_per_sample = bps / 8;
5197dd7cddfSDavid du Colombier switch (r_type(tstring)) {
5207dd7cddfSDavid du Colombier case t_string:
5217dd7cddfSDavid du Colombier size = r_size(tstring);
5227dd7cddfSDavid du Colombier gs_bytestring_from_string(&ptp->thresholds, tstring->value.const_bytes,
5237dd7cddfSDavid du Colombier size);
5247dd7cddfSDavid du Colombier break;
5257dd7cddfSDavid du Colombier case t_astruct:
5267dd7cddfSDavid du Colombier if (gs_object_type(mem, tstring->value.pstruct) != &st_bytes)
5277dd7cddfSDavid du Colombier return_error(e_typecheck);
5287dd7cddfSDavid du Colombier size = gs_object_size(mem, tstring->value.pstruct);
5297dd7cddfSDavid du Colombier gs_bytestring_from_bytes(&ptp->thresholds, r_ptr(tstring, byte),
5307dd7cddfSDavid du Colombier 0, size);
5317dd7cddfSDavid du Colombier break;
5327dd7cddfSDavid du Colombier default:
5337dd7cddfSDavid du Colombier return_error(e_typecheck);
5347dd7cddfSDavid du Colombier }
5357dd7cddfSDavid du Colombier check_read(*tstring);
5367dd7cddfSDavid du Colombier if (size != (ptp->width * ptp->height + ptp->width2 * ptp->height2) *
5377dd7cddfSDavid du Colombier ptp->bytes_per_sample)
5387dd7cddfSDavid du Colombier return_error(e_rangecheck);
5397dd7cddfSDavid du Colombier return 0;
5407dd7cddfSDavid du Colombier }
541