Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2024 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* setcolorscreen operator */ |
18 | | #include "ghost.h" |
19 | | #include "memory_.h" |
20 | | #include "oper.h" |
21 | | #include "estack.h" |
22 | | #include "gsstruct.h" /* must precede igstate.h, */ |
23 | | /* because of #ifdef in gsht.h */ |
24 | | #include "ialloc.h" |
25 | | #include "igstate.h" |
26 | | #include "gsmatrix.h" |
27 | | #include "gxdevice.h" /* for gzht.h */ |
28 | | #include "gzht.h" |
29 | | #include "gsstate.h" |
30 | | #include "iht.h" |
31 | | #include "store.h" |
32 | | |
33 | | /* Dummy spot function */ |
34 | | static float |
35 | | spot_dummy(double x, double y) |
36 | 22.2M | { |
37 | 22.2M | return (x + y) / 2; |
38 | 22.2M | } |
39 | | |
40 | | /* <red_freq> ... <gray_proc> setcolorscreen - */ |
41 | | static int setcolorscreen_finish(i_ctx_t *); |
42 | | static int setcolorscreen_cleanup(i_ctx_t *); |
43 | | static int |
44 | | zsetcolorscreen(i_ctx_t *i_ctx_p) |
45 | 326k | { |
46 | 326k | os_ptr op = osp; |
47 | 326k | gs_colorscreen_halftone cscreen; |
48 | 326k | ref sprocs[4]; |
49 | 326k | gs_halftone *pht; |
50 | 326k | gx_device_halftone *pdht; |
51 | 326k | int i; |
52 | 326k | int code = 0; |
53 | 326k | int space = 0; |
54 | 326k | gs_memory_t *mem; |
55 | 326k | gs_memory_t *currmem = (gs_memory_t *)idmemory->current; |
56 | | |
57 | 1.63M | for (i = 0; i < 4; i++) { |
58 | 1.30M | os_ptr op1 = op - 9 + i * 3; |
59 | 1.30M | int code = zscreen_params(op1, &cscreen.screens.indexed[i]); |
60 | | |
61 | 1.30M | if (code < 0) |
62 | 0 | return code; |
63 | 1.30M | cscreen.screens.indexed[i].spot_function = spot_dummy; |
64 | 1.30M | sprocs[i] = *op1; |
65 | 1.30M | space = max(space, r_space_index(op1)); |
66 | 1.30M | } |
67 | 326k | mem = (gs_memory_t *)idmemory->spaces_indexed[space]; |
68 | | /* We must have the currentglobal consistent through the sampling process */ |
69 | 326k | ialloc_set_space(idmemory, (mem == (gs_memory_t *)idmemory->spaces.memories.named.global ? avm_global : avm_local)); |
70 | 326k | check_estack(9); /* for sampling screens */ |
71 | 326k | rc_alloc_struct_0(pht, gs_halftone, &st_halftone, |
72 | 326k | mem, pht = 0, "setcolorscreen(halftone)"); |
73 | 326k | rc_alloc_struct_0(pdht, gx_device_halftone, &st_device_halftone, |
74 | 326k | mem, pdht = 0, "setcolorscreen(device halftone)"); |
75 | 326k | if (pht == 0 || pdht == 0) |
76 | 0 | code = gs_note_error(gs_error_VMerror); |
77 | 326k | else { |
78 | 326k | pht->type = ht_type_colorscreen; |
79 | 326k | pht->objtype = HT_OBJTYPE_DEFAULT; |
80 | 326k | pht->params.colorscreen = cscreen; |
81 | 326k | code = gs_sethalftone_prepare(igs, pht, pdht); |
82 | 326k | } |
83 | 326k | if (code >= 0) { /* Schedule the sampling of the screens. */ |
84 | 326k | es_ptr esp0 = esp; /* for backing out */ |
85 | | |
86 | 326k | esp += 9; |
87 | 326k | make_mark_estack(esp - 8, es_other, setcolorscreen_cleanup); |
88 | 326k | make_bool(esp - 7, (currmem == (gs_memory_t *)idmemory->spaces.memories.named.global)); |
89 | 326k | memcpy(esp - 6, sprocs, sizeof(ref) * 4); /* procs */ |
90 | 326k | make_istruct(esp - 2, 0, pht); |
91 | 326k | make_istruct(esp - 1, 0, pdht); |
92 | 326k | make_op_estack(esp, setcolorscreen_finish); |
93 | 1.63M | for (i = 0; i < 4; i++) { |
94 | | /* Shuffle the indices to correspond to */ |
95 | | /* the component order. */ |
96 | 1.30M | code = zscreen_enum_init(i_ctx_p, |
97 | 1.30M | &pdht->components[(i + 1) & 3].corder, |
98 | 1.30M | &pht->params.colorscreen.screens.indexed[i], |
99 | 1.30M | &sprocs[i], 0, 0, space); |
100 | 1.30M | if (code < 0) { |
101 | 0 | esp = esp0; |
102 | 0 | break; |
103 | 0 | } |
104 | 1.30M | } |
105 | 326k | } |
106 | 326k | if (code < 0) { |
107 | 0 | gs_free_object(mem, pdht, "setcolorscreen(device halftone)"); |
108 | 0 | gs_free_object(mem, pht, "setcolorscreen(halftone)"); |
109 | 0 | return code; |
110 | 0 | } |
111 | 326k | pop(12); |
112 | 326k | return o_push_estack; |
113 | 326k | } |
114 | | /* Install the color screen after sampling. */ |
115 | | static int |
116 | | setcolorscreen_finish(i_ctx_t *i_ctx_p) |
117 | 326k | { |
118 | 326k | gx_device_halftone *pdht = r_ptr(esp, gx_device_halftone); |
119 | 326k | int code; |
120 | | |
121 | 326k | pdht->order = pdht->components[0].corder; |
122 | 326k | code = gx_ht_install(igs, r_ptr(esp - 1, gs_halftone), pdht); |
123 | 326k | if (code < 0) { |
124 | | /* We need the stack correct for setcolorscreen_cleanup() but we need it back |
125 | | where we started before we return the error. |
126 | | */ |
127 | 0 | es_ptr esp0 = esp; |
128 | 0 | esp -= 8; |
129 | 0 | setcolorscreen_cleanup(i_ctx_p); |
130 | 0 | esp = esp0; |
131 | 0 | return code; |
132 | 0 | } |
133 | 326k | istate->screen_procs.red = esp[-5]; |
134 | 326k | istate->screen_procs.green = esp[-4]; |
135 | 326k | istate->screen_procs.blue = esp[-3]; |
136 | 326k | istate->screen_procs.gray = esp[-2]; |
137 | 326k | make_null(&istate->halftone); |
138 | 326k | esp -= 8; |
139 | 326k | setcolorscreen_cleanup(i_ctx_p); |
140 | 326k | return o_pop_estack; |
141 | 326k | } |
142 | | /* Clean up after installing the color screen. */ |
143 | | static int |
144 | | setcolorscreen_cleanup(i_ctx_t *i_ctx_p) |
145 | 326k | { |
146 | 326k | gs_halftone *pht = r_ptr(esp + 7, gs_halftone); |
147 | 326k | gx_device_halftone *pdht = r_ptr(esp + 8, gx_device_halftone); |
148 | 326k | bool global = (esp + 2)->value.boolval; |
149 | | |
150 | 326k | gs_free_object(pdht->rc.memory, pdht, |
151 | 326k | "setcolorscreen_cleanup(device halftone)"); |
152 | 326k | gs_free_object(pht->rc.memory, pht, |
153 | 326k | "setcolorscreen_cleanup(halftone)"); |
154 | | /* See bug #707007, explicitly freed structures on the stacks need to be made NULL */ |
155 | 326k | make_null(esp + 6); |
156 | 326k | make_null(esp + 7); |
157 | 326k | ialloc_set_space(idmemory, (global ? avm_global : avm_local)); |
158 | 326k | return 0; |
159 | 326k | } |
160 | | |
161 | | /* ------ Initialization procedure ------ */ |
162 | | |
163 | | const op_def zht1_op_defs[] = |
164 | | { |
165 | | {"<setcolorscreen", zsetcolorscreen}, |
166 | | /* Internal operators */ |
167 | | {"0%setcolorscreen_finish", setcolorscreen_finish}, |
168 | | op_def_end(0) |
169 | | }; |