Commit | Line | Data |
---|---|---|
5ae70ead WJ |
1 | /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* zpaint.c */ | |
21 | /* Painting operators for Ghostscript */ | |
22 | #include "ghost.h" | |
23 | #include "errors.h" | |
24 | #include "oper.h" | |
25 | #include "alloc.h" | |
26 | #include "estack.h" /* for image[mask] */ | |
27 | #include "store.h" | |
28 | #include "gsmatrix.h" | |
29 | #include "gspaint.h" | |
30 | #include "state.h" | |
31 | ||
32 | /* Forward references */ | |
33 | private int image_opaque_setup(P2(os_ptr, int)); | |
34 | private int image_setup(P3(os_ptr, int, int)); | |
35 | private int image_continue(P1(os_ptr)); | |
36 | private int i_image_continue; | |
37 | ||
38 | /* erasepage */ | |
39 | int | |
40 | zerasepage(register os_ptr op) | |
41 | { return gs_erasepage(igs); | |
42 | } | |
43 | ||
44 | /* fill */ | |
45 | int | |
46 | zfill(register os_ptr op) | |
47 | { return gs_fill(igs); | |
48 | } | |
49 | ||
50 | /* eofill */ | |
51 | int | |
52 | zeofill(register os_ptr op) | |
53 | { return gs_eofill(igs); | |
54 | } | |
55 | ||
56 | /* stroke */ | |
57 | int | |
58 | zstroke(register os_ptr op) | |
59 | { return gs_stroke(igs); | |
60 | } | |
61 | ||
62 | /* colorimage */ | |
63 | int | |
64 | zcolorimage(register os_ptr op) | |
65 | { int spp; /* samples per pixel */ | |
66 | int npop = 7; | |
67 | os_ptr procp = op - 2; | |
68 | int code; | |
69 | check_type(*op, t_integer); /* ncolors */ | |
70 | check_type(op[-1], t_boolean); /* multiproc */ | |
71 | if ( (ulong)(op->value.intval) > 4 ) return e_rangecheck; | |
72 | switch ( (spp = (int)(op->value.intval)) ) | |
73 | { | |
74 | case 1: | |
75 | break; | |
76 | case 3: case 4: | |
77 | if ( op[-1].value.index ) /* planar format */ | |
78 | npop += spp - 1, | |
79 | procp -= spp - 1, | |
80 | spp = - spp; | |
81 | break; | |
82 | default: | |
83 | return e_rangecheck; | |
84 | } | |
85 | code = image_opaque_setup(procp, spp); | |
86 | if ( code >= 0 ) pop(npop); | |
87 | return code; | |
88 | } | |
89 | ||
90 | /* image */ | |
91 | int | |
92 | zimage(register os_ptr op) | |
93 | { int code = image_opaque_setup(op, 1); | |
94 | if ( code >= 0 ) pop(5); | |
95 | return code; | |
96 | } | |
97 | ||
98 | /* imagemask */ | |
99 | int | |
100 | zimagemask(register os_ptr op) | |
101 | { int code; | |
102 | check_type(op[-2], t_boolean); | |
103 | code = image_setup(op, !op[-2].value.index, 0); | |
104 | if ( code >= 0 ) pop(5); | |
105 | return code; | |
106 | } | |
107 | ||
108 | /* Common setup for image and colorimage. */ | |
109 | private int | |
110 | image_opaque_setup(register os_ptr op, int spp) | |
111 | { check_type(op[-2], t_integer); /* bits/sample */ | |
112 | if ( (ulong)(op[-2].value.intval) > 8 ) return e_rangecheck; | |
113 | return image_setup(op, (int)op[-2].value.intval, spp); | |
114 | } | |
115 | ||
116 | /* Common setup for [color]image and imagemask. */ | |
117 | /* spp is 0 for imagemask, 1 for image, and [-]3 or [-]4 for colorimage. */ | |
118 | private int | |
119 | image_setup(register os_ptr op, int param3 /* bits/sample or invert */, int spp) | |
120 | { int code; | |
121 | gs_image_enum *penum; | |
122 | gs_matrix mat; | |
123 | int px; | |
124 | int pmax = (spp < 0 ? ~ spp : 0); | |
125 | /* We push on the estack: */ | |
126 | /* Control mark, 4 procs, last plane index, */ | |
127 | /* enumeration structure (as bytes). */ | |
128 | #define inumpush 7 | |
129 | check_estack(inumpush + 2); /* stuff above, + continuation + proc */ | |
130 | check_type(op[-4], t_integer); /* width */ | |
131 | check_type(op[-3], t_integer); /* height */ | |
132 | /* Note that the "procedures" might not be procedures, */ | |
133 | /* but might be literal strings. */ | |
134 | for ( px = 0; px <= pmax; px++ ) | |
135 | if ( !r_has_type(op + px, t_string) ) | |
136 | { check_proc(op[px]); /* proc(s) */ | |
137 | } | |
138 | if ( op[-4].value.intval <= 0 || op[-3].value.intval < 0 ) | |
139 | return e_undefinedresult; | |
140 | if ( op[-3].value.intval == 0 ) return 0; /* empty image */ | |
141 | if ( (code = read_matrix(op - 1, &mat)) < 0 ) | |
142 | return code; | |
143 | if ( (penum = (gs_image_enum *)alloc(1, gs_image_enum_sizeof, "image_setup")) == 0 ) | |
144 | return e_VMerror; | |
145 | code = (spp == 0 ? | |
146 | gs_imagemask_init(penum, igs, (int)op[-4].value.intval, | |
147 | (int)op[-3].value.intval, param3, &mat, 1) : | |
148 | gs_image_init(penum, igs, (int)op[-4].value.intval, | |
149 | (int)op[-3].value.intval, param3, spp, &mat) ); | |
150 | if ( code < 0 ) return code; | |
151 | mark_estack(es_other); | |
152 | ++esp; | |
153 | for ( px = 0; px < 4; esp++, px++ ) | |
154 | if ( px <= pmax ) | |
155 | *esp = op[px]; | |
156 | else | |
157 | make_null(esp); | |
158 | make_int(esp, 0); /* current plane */ | |
159 | r_set_size(esp, pmax); | |
160 | ++esp; | |
161 | make_tasv(esp, t_string, 0, gs_image_enum_sizeof, bytes, (byte *)penum); | |
162 | push_op_estack(image_continue, i_image_continue); | |
163 | *++esp = *op; /* run the (first) procedure */ | |
164 | return o_push_estack; | |
165 | } | |
166 | /* Continuation procedure. Hand the string to the enumerator. */ | |
167 | private int | |
168 | image_continue(register os_ptr op) | |
169 | { gs_image_enum *penum = (gs_image_enum *)esp->value.bytes; | |
170 | int code; | |
171 | if ( !r_has_type(op, t_string) ) | |
172 | { /* Procedure didn't return a string. Quit. */ | |
173 | esp -= inumpush; | |
174 | alloc_free((char *)penum, 1, gs_image_enum_sizeof, | |
175 | "image_continue(quit)"); | |
176 | return e_typecheck; | |
177 | } | |
178 | code = gs_image_next(penum, op->value.bytes, r_size(op)); | |
179 | if ( r_size(op) == 0 || code != 0 ) /* stop now */ | |
180 | { esp -= inumpush; | |
181 | alloc_free((char *)penum, 1, gs_image_enum_sizeof, | |
182 | "image_continue(finished)"); | |
183 | if ( code < 0 ) return code; | |
184 | code = o_pop_estack; | |
185 | } | |
186 | else | |
187 | { int px = (int)++(esp[-1].value.intval); | |
188 | es_ptr pproc = esp - 5; | |
189 | if ( px > r_size(esp - 1) ) | |
190 | esp[-1].value.intval = px = 0; | |
191 | push_op_estack(image_continue, i_image_continue); | |
192 | *++esp = pproc[px]; | |
193 | code = o_push_estack; | |
194 | } | |
195 | pop(1); | |
196 | return code; | |
197 | } | |
198 | ||
199 | /* ------ Initialization procedure ------ */ | |
200 | ||
201 | op_def zpaint_op_defs[] = { | |
202 | {"0eofill", zeofill}, | |
203 | {"0erasepage", zerasepage}, | |
204 | {"0fill", zfill}, | |
205 | {"7colorimage", zcolorimage}, | |
206 | {"5image", zimage}, | |
207 | {"5imagemask", zimagemask}, | |
208 | {"0stroke", zstroke}, | |
209 | /* Internal operators */ | |
210 | {"0%image_continue", image_continue, &i_image_continue}, | |
211 | op_def_end(0) | |
212 | }; |