/src/ghostpdl/base/gxclrast.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2022 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., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Command list interpreter/rasterizer */ |
18 | | #include "memory_.h" |
19 | | #include "gx.h" |
20 | | #include "gp.h" /* for gp_fmode_rb */ |
21 | | #include "gpcheck.h" |
22 | | #include "gserrors.h" |
23 | | #include "gscdefs.h" /* for image type table */ |
24 | | #include "gsbitops.h" |
25 | | #include "gsparams.h" |
26 | | #include "gsstate.h" /* (should only be gs_gstate) */ |
27 | | #include "gstrans.h" /* for gs_is_pdf14trans_compositor */ |
28 | | #include "gxdcolor.h" |
29 | | #include "gxdevice.h" |
30 | | #include "gscoord.h" /* requires gsmatrix.h */ |
31 | | #include "gsdevice.h" /* for gs_deviceinitialmatrix */ |
32 | | #include "gsiparm4.h" |
33 | | #include "gxdevmem.h" /* must precede gxcldev.h */ |
34 | | #include "gxcldev.h" |
35 | | #include "gxclpath.h" |
36 | | #include "gxcmap.h" |
37 | | #include "gxcolor2.h" |
38 | | #include "gxcspace.h" /* for gs_color_space_type */ |
39 | | #include "gxdhtres.h" |
40 | | #include "gxgetbit.h" |
41 | | #include "gxpaint.h" /* for gx_fill/stroke_params */ |
42 | | #include "gxpcolor.h" |
43 | | #include "gxhttile.h" |
44 | | #include "gxiparam.h" |
45 | | #include "gximask.h" |
46 | | #include "gzpath.h" |
47 | | #include "gzcpath.h" |
48 | | #include "gzacpath.h" |
49 | | #include "stream.h" |
50 | | #include "strimpl.h" |
51 | | #include "gxcomp.h" |
52 | | #include "gsserial.h" |
53 | | #include "gxdhtserial.h" |
54 | | #include "gzht.h" |
55 | | #include "gxshade.h" |
56 | | #include "gxshade4.h" |
57 | | #include "gsicc_manage.h" |
58 | | #include "gsicc.h" |
59 | | |
60 | | extern_gx_device_halftone_list(); |
61 | | extern_gx_image_type_table(); |
62 | | |
63 | | /* We need color space types for constructing temporary color spaces. */ |
64 | | extern const gs_color_space_type gs_color_space_type_Indexed; |
65 | | |
66 | | /* Print a bitmap for tracing */ |
67 | | #ifdef DEBUG |
68 | | static void |
69 | | cmd_print_bits(gs_memory_t *mem, const byte * data, int width, int height, int raster) |
70 | | { |
71 | | int i, j; |
72 | | |
73 | | dmlprintf3(mem, "[L]width=%d, height=%d, raster=%d\n", |
74 | | width, height, raster); |
75 | | for (i = 0; i < height; i++) { |
76 | | const byte *row = data + i * raster; |
77 | | |
78 | | dmlprintf(mem, "[L]"); |
79 | | for (j = 0; j < raster; j++) |
80 | | dmprintf1(mem, " %02x", row[j]); |
81 | | dmputc(mem, '\n'); |
82 | | } |
83 | | } |
84 | | #else |
85 | | # define cmd_print_bits(mem, data, width, height, raster) DO_NOTHING |
86 | | #endif |
87 | | |
88 | | /* Get a variable-length integer operand. */ |
89 | | #define cmd_getw(var, p)\ |
90 | 503M | BEGIN\ |
91 | 503M | if ( *p < 0x80 ) var = *p++;\ |
92 | 503M | else { const byte *_cbp; var = cmd_get_w(p, &_cbp); p = _cbp; }\ |
93 | 503M | END |
94 | | |
95 | | static long |
96 | | cmd_get_w(const byte * p, const byte ** rp) |
97 | 433M | { |
98 | 433M | int val = *p++ & 0x7f; |
99 | 433M | int shift = 7; |
100 | | |
101 | 860M | for (; val |= (int)(*p & 0x7f) << shift, *p++ > 0x7f; shift += 7); |
102 | 433M | *rp = p; |
103 | 433M | return val; |
104 | 433M | } |
105 | | |
106 | | /* Get a variable-length fractional operand. */ |
107 | | #define cmd_getfrac(var, p)\ |
108 | 72.6k | BEGIN\ |
109 | 72.6k | if ( !(*p & 1) ) var = (*p++) << 24;\ |
110 | 72.6k | else { const byte *_cbp; var = cmd_get_frac31(p, &_cbp); p = _cbp; }\ |
111 | 72.6k | END |
112 | | static frac31 |
113 | | cmd_get_frac31(const byte * p, const byte ** rp) |
114 | 19.4k | { |
115 | 19.4k | frac31 val = (*p++ & 0xFE) << 24; |
116 | 19.4k | int shift = 24 - 7; |
117 | | |
118 | 34.8k | for (; val |= (frac31)(*p & 0xFE) << shift, *p++ & 1; shift -= 7); |
119 | 19.4k | *rp = p; |
120 | 19.4k | return val; |
121 | 19.4k | } |
122 | | |
123 | | /* |
124 | | * Define the structure for keeping track of the command reading buffer. |
125 | | * |
126 | | * The ptr member is only used for passing the current pointer to, and |
127 | | * receiving an updated pointer from, commands implemented as separate |
128 | | * procedures: normally it is kept in a register. |
129 | | */ |
130 | | typedef struct command_buf_s { |
131 | | byte *data; /* actual buffer, guaranteed aligned */ |
132 | | uint size; |
133 | | const byte *ptr; /* next byte to be read (see above) */ |
134 | | const byte *warn_limit; /* refill warning point */ |
135 | | const byte *end; /* byte just beyond valid data */ |
136 | | stream *s; /* for refilling buffer */ |
137 | | int end_status; |
138 | | } command_buf_t; |
139 | | |
140 | | /* Set the end of a command buffer. */ |
141 | | static void |
142 | | set_cb_end(command_buf_t *pcb, const byte *end) |
143 | 6.86M | { |
144 | 6.86M | pcb->end = end; |
145 | 6.86M | pcb->warn_limit = pcb->data + (pcb->size - cmd_largest_size + 1); |
146 | 6.86M | if ( pcb->warn_limit > pcb->end ) |
147 | 645k | pcb->warn_limit = pcb->end; /**** This is dangerous. Other places ****/ |
148 | | /**** assume that the limit is a soft ****/ |
149 | | /**** limit and should check 'end' ****/ |
150 | 6.86M | } |
151 | | |
152 | | static inline void |
153 | | advance_buffer(command_buf_t *pcb, const byte *cbp) |
154 | 6.21M | { |
155 | | #ifdef DEBUG |
156 | | stream_state *st = pcb->s->state; |
157 | | |
158 | | top_up_offset_map(st, pcb->data, cbp, pcb->end); |
159 | | #endif |
160 | 6.21M | memmove(pcb->data, cbp, pcb->end - cbp); |
161 | 6.21M | } |
162 | | |
163 | | static inline void |
164 | | next_is_skip(command_buf_t *pcb) |
165 | 16.4k | { |
166 | | #ifdef DEBUG |
167 | | stream_state *st = pcb->s->state; |
168 | | |
169 | | offset_map_next_data_out_of_band(st); |
170 | | #endif |
171 | 16.4k | } |
172 | | |
173 | | /* Read more data into a command buffer. */ |
174 | | static int |
175 | | top_up_cbuf(command_buf_t *pcb, const byte **pcbp) |
176 | 8.15M | { |
177 | 8.15M | uint nread; |
178 | 8.15M | const byte *cbp = *pcbp; |
179 | 8.15M | byte *cb_top = pcb->data + (pcb->end - cbp); |
180 | | |
181 | 8.15M | if (cbp < pcb->data || cbp > pcb->end) { |
182 | 0 | errprintf(pcb->s->memory, "Clist I/O error: cbp outside of buffer\n"); |
183 | 0 | return (gs_error_ioerror); |
184 | 0 | } |
185 | | |
186 | 8.15M | if (seofp(pcb->s)) { |
187 | | /* Can't use offset_map, because s_close resets s->state. Don't top up. */ |
188 | 1.93M | pcb->end_status = pcb->s->end_status; |
189 | 1.93M | return 0; |
190 | 1.93M | } |
191 | 6.21M | advance_buffer(pcb, cbp); |
192 | 6.21M | nread = pcb->end - cb_top; |
193 | 6.21M | pcb->end_status = sgets(pcb->s, cb_top, nread, &nread); |
194 | 6.21M | if ( nread == 0 ) { |
195 | | /* No data for this band at all. */ |
196 | 14 | if (cb_top >= pcb->end) { |
197 | | /* should not happen */ |
198 | 0 | *pcbp = pcb->data; |
199 | 0 | pcb->data[0] = cmd_opv_end_run; |
200 | 0 | return_error(gs_error_ioerror); |
201 | 0 | } |
202 | 14 | *cb_top = cmd_opv_end_run; |
203 | 14 | nread = 1; |
204 | 14 | } |
205 | 6.21M | set_cb_end(pcb, cb_top + nread); |
206 | 6.21M | process_interrupts(pcb->s->memory); |
207 | 6.21M | *pcbp = pcb->data; |
208 | 6.21M | return 0; |
209 | 6.21M | } |
210 | | |
211 | | /* Read data from the command buffer and stream. */ |
212 | | /* From the command_buffer pcb, read rsize bytes to ptr, starting from cbp. |
213 | | * Return the new value for pcb->ptr. */ |
214 | | static const byte * |
215 | | cmd_read_data(command_buf_t *pcb, byte *ptr, uint rsize, const byte *cbp) |
216 | 4.89M | { |
217 | 4.89M | if (pcb->end - cbp >= rsize) { |
218 | 4.87M | memmove(ptr, cbp, rsize); |
219 | 4.87M | return cbp + rsize; |
220 | 4.87M | } else { |
221 | 18.1k | uint cleft = pcb->end - cbp; |
222 | 18.1k | uint rleft = rsize - cleft; |
223 | | |
224 | 18.1k | memmove(ptr, cbp, cleft); |
225 | 18.1k | sgets(pcb->s, ptr + cleft, rleft, &rleft); |
226 | | #ifdef DEBUG |
227 | | { |
228 | | stream_state *st = pcb->s->state; |
229 | | |
230 | | adjust_offset_map_for_skipped_data(st, (uint)(pcb->end - pcb->data), rleft); |
231 | | } |
232 | | #endif |
233 | 18.1k | return pcb->end; |
234 | 18.1k | } |
235 | 4.89M | } |
236 | | |
237 | | /* Read a fixed-size value from the command buffer. */ |
238 | | static inline const byte * |
239 | | cmd_copy_value(void *pvar, int var_size, const byte *cbp) |
240 | 714k | { |
241 | 714k | memcpy(pvar, cbp, var_size); |
242 | 714k | return cbp + var_size; |
243 | 714k | } |
244 | | #define cmd_get_value(var, cbp)\ |
245 | 714k | cbp = cmd_copy_value(&var, sizeof(var), cbp) |
246 | | |
247 | | /* |
248 | | * Define a buffer structure to hold a serialized halftone. This is |
249 | | * used only if the serialized halftone is too large to fit into |
250 | | * the command buffer. |
251 | | */ |
252 | | typedef struct ht_buff_s { |
253 | | uint ht_size, read_size; |
254 | | byte * pcurr; |
255 | | byte * pbuff; |
256 | | } ht_buff_t; |
257 | | |
258 | | /* |
259 | | * Render one band to a specified target device. Note that if |
260 | | * action == setup, target may be 0. |
261 | | */ |
262 | | static int read_set_tile_size(command_buf_t *pcb, tile_slot *bits, bool for_pattern); |
263 | | static int read_set_bits(command_buf_t *pcb, tile_slot *bits, |
264 | | int compress, gx_clist_state *pcls, |
265 | | gx_strip_bitmap *tile, tile_slot **pslot, |
266 | | gx_device_clist_reader *cdev, gs_memory_t *mem); |
267 | | static int read_set_misc2(command_buf_t *pcb, gs_gstate *pgs, |
268 | | segment_notes *pnotes); |
269 | | static int read_set_color_space(command_buf_t *pcb, gs_gstate *pgs, |
270 | | gx_device_clist_reader *cdev, gs_memory_t *mem); |
271 | | static int read_begin_image(command_buf_t *pcb, gs_image_common_t *pic, |
272 | | gs_color_space *pcs); |
273 | | static int read_put_params(command_buf_t *pcb, gs_gstate *pgs, |
274 | | gx_device_clist_reader *cdev, |
275 | | gs_memory_t *mem); |
276 | | static int read_composite(command_buf_t *pcb, gs_memory_t *mem, gs_composite_t **ppcomp); |
277 | | static int apply_composite(gx_device_clist_reader *cdev, gs_gstate *pgs, |
278 | | gs_memory_t *mem, gs_composite_t *pcomp, |
279 | | int x0, int y0, gx_device **ptarget); |
280 | | static int read_alloc_ht_buff(ht_buff_t *, uint, gs_memory_t *); |
281 | | static int read_ht_segment(ht_buff_t *, command_buf_t *, gs_gstate *, |
282 | | gx_device *, gs_memory_t *); |
283 | | |
284 | | static const byte *cmd_read_rect(int, gx_cmd_rect *, const byte *); |
285 | | static const byte *cmd_read_short_bits(command_buf_t *pcb, byte *data, int tot_bytes, |
286 | | int width_bytes, int height, |
287 | | uint raster, const byte *cbp); |
288 | | static int cmd_select_map(cmd_map_index, cmd_map_contents, |
289 | | gs_gstate *, int **, |
290 | | frac **, uint *, gs_memory_t *); |
291 | | static int cmd_create_dev_ht(gx_device_halftone **, gs_memory_t *); |
292 | | static int cmd_resize_halftone(gx_device_halftone **, uint, |
293 | | gs_memory_t *); |
294 | | static int clist_decode_segment(gx_path *, int, fixed[6], |
295 | | gs_fixed_point *, int, int, |
296 | | segment_notes); |
297 | | static int clist_do_polyfill(gx_device *, gx_path *, |
298 | | const gx_drawing_color *, |
299 | | gs_logical_operation_t); |
300 | | |
301 | | static inline void |
302 | | enqueue_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last, gs_composite_t *pcomp) |
303 | 20.5M | { |
304 | 20.5M | if (*ppcomp_last == NULL) { |
305 | 3.18M | pcomp->prev = pcomp->next = NULL; |
306 | 3.18M | *ppcomp_last = *ppcomp_first = pcomp; |
307 | 17.3M | } else { |
308 | 17.3M | (*ppcomp_last)->next = pcomp; |
309 | 17.3M | pcomp->prev = *ppcomp_last; |
310 | 17.3M | pcomp->next = NULL; |
311 | 17.3M | *ppcomp_last = pcomp; |
312 | 17.3M | } |
313 | 20.5M | } |
314 | | |
315 | | #if 0 /* Appears unused - keep for a while. */ |
316 | | static inline gs_composite_t * |
317 | | dequeue_last_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last) |
318 | | { |
319 | | gs_composite_t *pcomp = *ppcomp_last; |
320 | | |
321 | | if (*ppcomp_first == *ppcomp_last) |
322 | | *ppcomp_first = *ppcomp_last = NULL; |
323 | | else { |
324 | | *ppcomp_last = (*ppcomp_last)->prev; |
325 | | pcomp->prev = NULL; |
326 | | (*ppcomp_last)->next = NULL; |
327 | | } |
328 | | return pcomp; |
329 | | } |
330 | | |
331 | | static inline gs_composite_t * |
332 | | dequeue_first_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last) |
333 | | { |
334 | | gs_composite_t *pcomp = *ppcomp_first; |
335 | | |
336 | | if (*ppcomp_first == *ppcomp_last) |
337 | | *ppcomp_first = *ppcomp_last = NULL; |
338 | | else { |
339 | | *ppcomp_first = (*ppcomp_first)->next; |
340 | | pcomp->next = NULL; |
341 | | (*ppcomp_last)->prev = NULL; |
342 | | } |
343 | | return pcomp; |
344 | | } |
345 | | #endif |
346 | | |
347 | | static inline int |
348 | | dequeue_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last, gs_composite_t *pcomp) |
349 | 20.5M | { |
350 | 20.5M | if (*ppcomp_last == *ppcomp_first) { |
351 | 3.18M | if (*ppcomp_last == pcomp) { |
352 | 3.18M | *ppcomp_last = *ppcomp_first = NULL; |
353 | 3.18M | return 0; |
354 | 3.18M | } else |
355 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
356 | 17.3M | } else { |
357 | 17.3M | gs_composite_t *pcomp_next = pcomp->next, *pcomp_prev = pcomp->prev; |
358 | | |
359 | 17.3M | if (*ppcomp_last == pcomp) |
360 | 3.90M | *ppcomp_last = pcomp->prev; |
361 | 13.4M | else |
362 | 13.4M | pcomp_next->prev = pcomp_prev; |
363 | 17.3M | if (*ppcomp_first == pcomp) |
364 | 13.4M | *ppcomp_first = pcomp->next; |
365 | 3.90M | else |
366 | 3.90M | pcomp_prev->next = pcomp_next; |
367 | 17.3M | pcomp->next = pcomp->prev = NULL; |
368 | 17.3M | return 0; |
369 | 17.3M | } |
370 | 20.5M | } |
371 | | |
372 | | static inline void |
373 | | free_compositor(gs_composite_t *pcomp, gs_memory_t *mem) |
374 | 5.61M | { |
375 | 5.61M | gs_free_object(mem, pcomp, "free_compositor"); |
376 | 5.61M | } |
377 | | |
378 | | static inline bool |
379 | | is_null_compositor_op(const byte *cbp, int *length) |
380 | 16.4M | { |
381 | 16.4M | if (cbp[0] == cmd_opv_end_run) { |
382 | 14.6M | *length = 1; |
383 | 14.6M | return true; |
384 | 14.6M | } |
385 | 1.79M | return false; |
386 | 16.4M | } |
387 | | |
388 | | static int |
389 | | execute_compositor_queue(gx_device_clist_reader *cdev, gx_device **target, gx_device **tdev, gs_gstate *pgs, |
390 | | gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last, gs_composite_t *pcomp_from, |
391 | | int x0, int y0, gs_memory_t *mem, bool idle) |
392 | 1.71M | { |
393 | 16.6M | while (pcomp_from != NULL) { |
394 | 14.9M | gs_composite_t *pcomp = pcomp_from; |
395 | 14.9M | int code; |
396 | | |
397 | 14.9M | pcomp_from = pcomp->next; |
398 | 14.9M | code = dequeue_compositor(ppcomp_first, ppcomp_last, pcomp); |
399 | 14.9M | if (code < 0) |
400 | 0 | return code; |
401 | 14.9M | pcomp->idle |= idle; |
402 | 14.9M | code = apply_composite(cdev, pgs, mem, pcomp, x0, y0, target); /* Releases the compositor. */ |
403 | 14.9M | if (code < 0) |
404 | 3 | return code; |
405 | 14.9M | *tdev = *target; |
406 | 14.9M | } |
407 | 1.71M | return 0; |
408 | 1.71M | } |
409 | | |
410 | | static void |
411 | | mark_as_idle(gs_composite_t *pcomp_start, gs_composite_t *pcomp_end) |
412 | 370k | { |
413 | 370k | gs_composite_t *pcomp = pcomp_start; |
414 | | |
415 | 805k | while (pcomp != NULL) { |
416 | 805k | pcomp->idle = true; |
417 | 805k | if (pcomp == pcomp_end) |
418 | 370k | break; |
419 | 434k | pcomp = pcomp->next; |
420 | 434k | } |
421 | 370k | } |
422 | | |
423 | | static inline int |
424 | | drop_compositor_queue(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last, |
425 | | gs_composite_t *pcomp_from, gs_memory_t *mem, int x0, int y0, |
426 | | gs_gstate *pgs) |
427 | 30.0k | { |
428 | 30.0k | gs_composite_t *pcomp; |
429 | | |
430 | 174k | do { |
431 | 174k | int code; |
432 | | |
433 | 174k | pcomp = *ppcomp_last; |
434 | 174k | if (pcomp == NULL) |
435 | 0 | return 0; |
436 | 174k | dequeue_compositor(ppcomp_first, ppcomp_last, *ppcomp_last); |
437 | 174k | code = pcomp->type->procs.adjust_ctm(pcomp, x0, y0, pgs); |
438 | 174k | if (code < 0) |
439 | 0 | return code; |
440 | 174k | free_compositor(pcomp, mem); |
441 | 174k | } while (pcomp != pcomp_from); |
442 | 30.0k | return 0; |
443 | 30.0k | } |
444 | | |
445 | | static int |
446 | | read_set_misc_map(byte cb, command_buf_t *pcb, gs_gstate *pgs, gs_memory_t *mem) |
447 | 1.18M | { |
448 | 1.18M | const byte *cbp = pcb->ptr; |
449 | 1.18M | frac *mdata; |
450 | 1.18M | int *pcomp_num; |
451 | 1.18M | uint count = 0; /* quiet compiler */ |
452 | 1.18M | cmd_map_contents cont = |
453 | 1.18M | (cmd_map_contents)(cb & 0x30) >> 4; |
454 | 1.18M | int code; |
455 | | |
456 | 1.18M | code = cmd_select_map(cb & 0xf, cont, |
457 | 1.18M | pgs, |
458 | 1.18M | &pcomp_num, |
459 | 1.18M | &mdata, &count, mem); |
460 | | |
461 | 1.18M | if (code < 0) |
462 | 0 | return code; |
463 | | /* Get component number if relevant */ |
464 | 1.18M | if (pcomp_num == NULL) |
465 | 1.18M | cbp++; |
466 | 60 | else { |
467 | 60 | *pcomp_num = (int) *cbp++; |
468 | 60 | if_debug1m('L', mem, " comp_num=%d", *pcomp_num); |
469 | 60 | } |
470 | 1.18M | if (cont == cmd_map_other) { |
471 | 1.00M | cbp = cmd_read_data(pcb, (byte *)mdata, count, cbp); |
472 | | |
473 | | #ifdef DEBUG |
474 | | if (gs_debug_c('L')) { |
475 | | uint i; |
476 | | |
477 | | for (i = 0; i < count / sizeof(*mdata); ++i) |
478 | | dmprintf1(mem, " 0x%04x", mdata[i]); |
479 | | dmputc(mem, '\n'); |
480 | | } |
481 | | } else { |
482 | | if_debug0m('L', mem, " none\n"); |
483 | | #endif |
484 | 1.00M | } |
485 | | /* Recompute the effective transfer, */ |
486 | | /* in case this was a transfer map. */ |
487 | 1.18M | gx_gstate_set_effective_xfer(pgs); |
488 | 1.18M | pcb->ptr = cbp; |
489 | 1.18M | return 0; |
490 | 1.18M | } |
491 | | |
492 | | #ifdef DEBUG |
493 | | void clist_debug_op(gs_memory_t *mem, const unsigned char *cbp) |
494 | | { |
495 | | unsigned char op = *cbp++; |
496 | | const char *const *sub = cmd_sub_op_names[op >> 4]; |
497 | | if (op == cmd_opv_extend) { |
498 | | unsigned char op2 = *cbp; |
499 | | if (cmd_extend_op_names[op2]) |
500 | | dmlprintf1(mem, " %s", cmd_extend_op_names[op2]); |
501 | | else |
502 | | dmlprintf1(mem, " ?0x%02x?", (int)op2); |
503 | | } else if (sub) |
504 | | dmlprintf1(mem, " %s", sub[op & 0xf]); |
505 | | else |
506 | | dmlprintf2(mem, " %s %d", cmd_op_names[op >> 4], op & 0xf); |
507 | | } |
508 | | #endif |
509 | | |
510 | | int |
511 | | clist_playback_band(clist_playback_action playback_action, /* lgtm [cpp/use-of-goto] */ |
512 | | gx_device_clist_reader *cdev, stream *s, |
513 | | gx_device *target, int x0, int y0, |
514 | | gs_memory_t * mem) |
515 | 650k | { |
516 | 650k | byte *cbuf_storage; |
517 | 650k | command_buf_t cbuf; |
518 | | /* data_bits is for short copy_* bits and copy_* compressed, */ |
519 | | /* must be aligned */ |
520 | 650k | byte *data_bits = 0; |
521 | 650k | const byte *cbp; |
522 | 650k | int dev_depth; /* May vary due to compositing devices */ |
523 | 650k | int dev_depth_bytes; |
524 | 650k | int odd_delta_shift; |
525 | 650k | int num_zero_bytes; |
526 | 650k | gx_device *tdev; |
527 | 650k | gx_clist_state state; |
528 | 650k | gx_color_index *set_colors; |
529 | 650k | gx_device_color *set_dev_colors; |
530 | 650k | tile_slot *state_slot; |
531 | 650k | gx_strip_bitmap state_tile; /* parameters for reading tiles */ |
532 | 650k | tile_slot tile_bits; /* parameters of current tile */ |
533 | 650k | gs_int_point tile_phase; |
534 | 650k | gx_path path; |
535 | 650k | bool in_path; |
536 | 650k | gs_fixed_point ppos; |
537 | 650k | gx_clip_path clip_path; |
538 | 650k | bool use_clip; |
539 | 650k | gx_clip_path *pcpath; |
540 | 650k | gx_device_cpath_accum clip_accum; |
541 | 650k | gs_fixed_rect target_box; |
542 | 650k | struct _cas { |
543 | 650k | bool lop_enabled; |
544 | 650k | gx_device_color dcolor; |
545 | 650k | gs_fixed_point fa_save; |
546 | 650k | } clip_save; |
547 | 650k | bool in_clip = false; |
548 | 650k | gs_gstate gs_gstate; |
549 | 650k | gx_device_color fill_color = { 0 }; |
550 | 650k | gx_device_color stroke_color = { 0 }; |
551 | 650k | float dash_pattern[cmd_max_dash]; |
552 | 650k | gx_fill_params fill_params; |
553 | 650k | gx_stroke_params stroke_params; |
554 | | #ifdef DEBUG |
555 | | gs_halftone_type halftone_type; |
556 | | #endif |
557 | 650k | union im_ { |
558 | 650k | gs_image_common_t c; |
559 | 650k | gs_data_image_t d; |
560 | 650k | gs_image1_t i1; |
561 | 650k | gs_image4_t i4; |
562 | 650k | } image; |
563 | 650k | gs_int_rect image_rect; |
564 | 650k | gs_color_space *pcs = NULL; |
565 | 650k | gx_image_enum_common_t *image_info; |
566 | 650k | gx_image_plane_t planes[32]; |
567 | 650k | uint data_height; |
568 | 650k | uint data_size; |
569 | 650k | byte *data_on_heap; |
570 | 650k | fixed vs[6]; |
571 | 650k | segment_notes notes; |
572 | 650k | int data_x; |
573 | 650k | int code = 0; |
574 | 650k | ht_buff_t ht_buff; |
575 | 650k | gx_device *const orig_target = target; |
576 | 650k | gx_device_clip clipper_dev; |
577 | 650k | bool clipper_dev_open; |
578 | 650k | patch_fill_state_t pfs; |
579 | 650k | int op = 0; |
580 | 650k | int plane_height = 0; |
581 | | |
582 | | #ifdef DEBUG |
583 | | stream_state *st = s->state; /* Save because s_close resets s->state. */ |
584 | | #endif |
585 | 650k | gs_composite_t *pcomp_first = NULL, *pcomp_last = NULL; |
586 | 650k | tile_slot bits; /* parameters for reading bits */ |
587 | | |
588 | | /* pad the cbuf data area a bit (just in case) */ |
589 | 650k | if ((cbuf_storage = gs_alloc_bytes(mem, cbuf_size + sizeof(double), |
590 | 650k | "clist_playback_band(cbuf_storage)")) == NULL) { |
591 | 0 | return_error(gs_error_VMerror); |
592 | 0 | } |
593 | 650k | cbuf.data = (byte *)cbuf_storage; |
594 | 650k | cbuf.size = cbuf_size; |
595 | 650k | cbuf.s = s; |
596 | 650k | cbuf.end_status = 0; |
597 | 650k | set_cb_end(&cbuf, cbuf.data + cbuf.size); |
598 | 650k | cbp = cbuf.end; |
599 | | |
600 | 650k | pfs.dev = NULL; /* Indicate "not initialized". */ |
601 | 650k | memset(&ht_buff, 0, sizeof(ht_buff)); |
602 | | |
603 | | /* The following initializations are to quiet gcc warnings. */ |
604 | 650k | memset(&bits, 0, sizeof(bits)); |
605 | 650k | memset(&tile_bits, 0, sizeof(tile_bits)); |
606 | 650k | memset(&clip_save, 0, sizeof(clip_save)); |
607 | 650k | memset(&state_slot, 0, sizeof(state_slot)); |
608 | 650k | ppos.x = ppos.y = 0; |
609 | | |
610 | 650k | in: /* Initialize for a new page. */ |
611 | 650k | tdev = target; |
612 | 650k | set_colors = state.colors; |
613 | 650k | set_dev_colors = state.tile_color_devn; |
614 | 650k | use_clip = false; |
615 | 650k | pcpath = NULL; |
616 | 650k | clipper_dev_open = false; |
617 | 650k | notes = sn_none; |
618 | 650k | data_x = 0; |
619 | 650k | { |
620 | 650k | static const gx_clist_state cls_initial = { cls_initial_values }; |
621 | | |
622 | 650k | state = cls_initial; |
623 | 650k | } |
624 | 650k | state_tile.id = gx_no_bitmap_id; |
625 | 650k | state_tile.shift = state_tile.rep_shift = 0; |
626 | 650k | state_tile.size.x = state_tile.size.y = 0; |
627 | 650k | state_tile.num_planes = 1; |
628 | 650k | tile_phase.x = x0; |
629 | 650k | tile_phase.y = y0; |
630 | 650k | gx_path_init_local(&path, mem); |
631 | 650k | in_path = false; |
632 | | /* |
633 | | * Initialize the clipping region to the full page. |
634 | | * (Since we also initialize use_clip to false, this is arbitrary.) |
635 | | */ |
636 | 650k | { |
637 | 650k | gs_fixed_rect cbox; |
638 | | |
639 | 650k | gx_cpath_init_local(&clip_path, mem); |
640 | 650k | cbox.p.x = 0; |
641 | 650k | cbox.p.y = 0; |
642 | 650k | cbox.q.x = cdev->width; |
643 | 650k | cbox.q.y = cdev->height; |
644 | 650k | gx_cpath_from_rectangle(&clip_path, &cbox); |
645 | 650k | } |
646 | 650k | if (target != 0) |
647 | 650k | (*dev_proc(target, get_clipping_box))(target, &target_box); |
648 | 650k | memset(&gs_gstate, 0, sizeof(gs_gstate)); |
649 | 650k | GS_STATE_INIT_VALUES_CLIST((&gs_gstate)); |
650 | 650k | code = gs_gstate_initialize(&gs_gstate, mem); |
651 | 650k | if (code < 0) |
652 | 1 | goto out; |
653 | 650k | gs_gstate.device = tdev; |
654 | 650k | gs_gstate.view_clip = NULL; /* Avoid issues in pdf14 fill stroke */ |
655 | 650k | gs_gstate.clip_path = &clip_path; |
656 | 650k | pcs = gs_cspace_new_DeviceGray(mem); |
657 | 650k | if (pcs == NULL) { |
658 | 0 | code = gs_note_error(gs_error_VMerror); |
659 | 0 | goto out; |
660 | 0 | } |
661 | 650k | code = pcs->type->install_cspace(pcs, &gs_gstate); |
662 | 650k | if (code < 0) { |
663 | 7 | rc_decrement(pcs, "clist_playback_band"); |
664 | 7 | goto out; |
665 | 7 | } |
666 | 650k | gs_gstate.color[0].color_space = pcs; /* we already have one ref */ |
667 | 650k | gs_gstate.color[1].color_space = pcs; |
668 | 650k | rc_increment_cs(pcs); /* increment for second ref */ |
669 | | /* Initialize client color and device color */ |
670 | 650k | gs_gstate.color[0].ccolor = |
671 | 650k | gs_alloc_struct(mem, gs_client_color, &st_client_color, "clist_playback_band"); |
672 | 650k | gs_gstate.color[1].ccolor = |
673 | 650k | gs_alloc_struct(mem, gs_client_color, &st_client_color, "clist_playback_band"); |
674 | 650k | gs_gstate.color[0].dev_color = |
675 | 650k | gs_alloc_struct(mem, gx_device_color, &st_device_color, "clist_playback_band"); |
676 | 650k | gs_gstate.color[1].dev_color = |
677 | 650k | gs_alloc_struct(mem, gx_device_color, &st_device_color, "clist_playback_band"); |
678 | 650k | if (gs_gstate.color[0].ccolor == 0 || gs_gstate.color[0].dev_color == 0 || |
679 | 650k | gs_gstate.color[1].ccolor == 0 || gs_gstate.color[1].dev_color == 0 |
680 | 650k | ) { |
681 | 0 | gs_free_object(mem, gs_gstate.color[1].ccolor, "clist_playback_band"); |
682 | 0 | gs_free_object(mem, gs_gstate.color[0].dev_color, "clist_playback_band"); |
683 | 0 | gs_free_object(mem, gs_gstate.color[1].dev_color, "clist_playback_band"); |
684 | 0 | return_error(gs_error_VMerror); |
685 | 0 | } |
686 | 650k | gs_gstate.color[0].color_space->pclient_color_space_data = |
687 | 650k | pcs->pclient_color_space_data; |
688 | 650k | cs_full_init_color(gs_gstate.color[0].ccolor, pcs); |
689 | 650k | gx_unset_dev_color(&gs_gstate); |
690 | | |
691 | 650k | gs_gstate.color[1].color_space->pclient_color_space_data = |
692 | 650k | pcs->pclient_color_space_data; |
693 | 650k | cs_full_init_color(gs_gstate.color[1].ccolor, pcs); |
694 | 650k | gx_unset_dev_color(&gs_gstate); |
695 | | |
696 | | /* Remove the ICC link cache and replace with the device link cache |
697 | | so that we share the cache across bands */ |
698 | 650k | rc_decrement(gs_gstate.icc_link_cache,"clist_playback_band"); |
699 | 650k | gs_gstate.icc_link_cache = cdev->icc_cache_cl; |
700 | | /* Need to lock during the increment of the link cache */ |
701 | 650k | gx_monitor_enter(cdev->icc_cache_cl->lock); |
702 | 650k | rc_increment(cdev->icc_cache_cl); |
703 | 650k | gx_monitor_leave(cdev->icc_cache_cl->lock); /* let everyone run */ |
704 | 650k | if (code < 0) |
705 | 0 | goto out; |
706 | | |
707 | 650k | gs_gstate.line_params.dash.pattern = dash_pattern; |
708 | 650k | if (tdev != 0) { |
709 | 650k | gx_set_cmap_procs(&gs_gstate, tdev); |
710 | 650k | } |
711 | 650k | gx_gstate_setscreenphase(&gs_gstate, -x0, -y0, gs_color_select_all); |
712 | | #ifdef DEBUG |
713 | | halftone_type = ht_type_none; |
714 | | #endif |
715 | 650k | fill_color.ccolor_valid = false; |
716 | 650k | color_unset(&fill_color); |
717 | 650k | data_bits = gs_alloc_bytes(mem, data_bits_size, |
718 | 650k | "clist_playback_band(data_bits)"); |
719 | 650k | if (data_bits == 0) { |
720 | 0 | code = gs_note_error(gs_error_VMerror); |
721 | 0 | goto out; |
722 | 0 | } |
723 | 140M | while (code >= 0) { |
724 | 140M | int compress; |
725 | 140M | int depth = 0x7badf00d; /* Initialize against indeterminizm. */ |
726 | 140M | int raster = 0x7badf00d; /* Initialize against indeterminizm. */ |
727 | 140M | byte *source = NULL; /* Initialize against indeterminizm. */ |
728 | 140M | gx_color_index colors[2]; |
729 | 140M | gx_color_index *pcolor; |
730 | 140M | gx_device_color *pdcolor = NULL; |
731 | 140M | gs_logical_operation_t log_op; |
732 | | |
733 | | /* Make sure the buffer contains a full command. */ |
734 | 140M | if (cbp >= cbuf.warn_limit) { |
735 | 1.22M | if (cbuf.end_status < 0) { /* End of file or error. */ |
736 | 4.59k | if (cbp >= cbuf.end) { |
737 | 0 | code = (cbuf.end_status == EOFC ? 0 : |
738 | 0 | gs_note_error(gs_error_ioerror)); |
739 | 0 | break; |
740 | 0 | } |
741 | 1.21M | } else { |
742 | 1.21M | code = top_up_cbuf(&cbuf, &cbp); |
743 | 1.21M | if (code < 0) |
744 | 0 | goto top_up_failed; |
745 | 1.21M | } |
746 | 1.22M | } |
747 | 140M | op = *cbp++; |
748 | | #ifdef DEBUG |
749 | | if (gs_debug_c('L')) { |
750 | | int64_t offset = clist_file_offset(st, cbp - 1 - cbuf.data); |
751 | | |
752 | | dmlprintf1(mem, "[L] %"PRIu64":", offset); |
753 | | clist_debug_op(mem, cbp-1); |
754 | | } |
755 | | #endif |
756 | 140M | switch (op >> 4) { |
757 | 17.6M | case cmd_op_misc >> 4: |
758 | 17.6M | switch (op) { |
759 | 1.73M | case cmd_opv_end_run: |
760 | 1.73M | if_debug0m('L', mem, "\n"); |
761 | 1.73M | continue; |
762 | 1.24k | case cmd_opv_set_tile_size: |
763 | 1.24k | cbuf.ptr = cbp; |
764 | 1.24k | code = read_set_tile_size(&cbuf, &tile_bits, |
765 | 1.24k | gx_device_is_pattern_clist((gx_device *)cdev)); |
766 | 1.24k | cbp = cbuf.ptr; |
767 | 1.24k | if (code < 0) |
768 | 0 | goto out; |
769 | 1.24k | continue; |
770 | 5.63k | case cmd_opv_set_tile_phase: |
771 | 5.63k | cmd_getw(state.tile_phase.x, cbp); |
772 | 5.63k | cmd_getw(state.tile_phase.y, cbp); |
773 | 5.63k | if_debug2m('L', mem, " (%d,%d)\n", |
774 | 5.63k | state.tile_phase.x, |
775 | 5.63k | state.tile_phase.y); |
776 | 5.63k | goto set_tile_phase; |
777 | 7.94k | case cmd_opv_set_screen_phaseT: |
778 | 7.94k | cmd_getw(state.screen_phase[gs_color_select_texture].x, cbp); |
779 | 7.94k | cmd_getw(state.screen_phase[gs_color_select_texture].y, cbp); |
780 | 7.94k | if_debug2m('L', mem, " (%d,%d)\n", |
781 | 7.94k | state.screen_phase[0].x, |
782 | 7.94k | state.screen_phase[gs_color_select_texture].y); |
783 | 7.94k | gx_gstate_setscreenphase(&gs_gstate, |
784 | 7.94k | state.screen_phase[gs_color_select_texture].x - x0, |
785 | 7.94k | state.screen_phase[gs_color_select_texture].y - y0, |
786 | 7.94k | gs_color_select_texture); |
787 | 7.94k | continue; |
788 | 0 | case cmd_opv_set_screen_phaseS: |
789 | 0 | cmd_getw(state.screen_phase[gs_color_select_source].x, cbp); |
790 | 0 | cmd_getw(state.screen_phase[gs_color_select_source].y, cbp); |
791 | 0 | if_debug2m('L', mem, " (%d,%d)\n", |
792 | 0 | state.screen_phase[gs_color_select_source].x, |
793 | 0 | state.screen_phase[gs_color_select_source].y); |
794 | 0 | gx_gstate_setscreenphase(&gs_gstate, |
795 | 0 | state.screen_phase[gs_color_select_source].x - x0, |
796 | 0 | state.screen_phase[gs_color_select_source].y - y0, |
797 | 0 | gs_color_select_source); |
798 | 0 | continue; |
799 | 4.79k | case cmd_opv_set_tile_bits: |
800 | 4.79k | bits = tile_bits; |
801 | 4.79k | compress = 0; |
802 | 3.03M | stb: |
803 | 3.03M | cbuf.ptr = cbp; |
804 | 3.03M | code = read_set_bits(&cbuf, &bits, compress, |
805 | 3.03M | &state, &state_tile, &state_slot, |
806 | 3.03M | cdev, mem); |
807 | 3.03M | cbp = cbuf.ptr; |
808 | 3.03M | if (code < 0) |
809 | 0 | goto out; |
810 | 3.03M | goto stp; |
811 | 3.03M | case cmd_opv_set_bits: |
812 | 3.02M | do_opv_set_bits: |
813 | 3.02M | compress = *cbp & 3; |
814 | 3.02M | bits.head.depth = *cbp++ >> 2; |
815 | 3.02M | cmd_getw(bits.width, cbp); |
816 | 3.02M | cmd_getw(bits.height, cbp); |
817 | 3.02M | if (op == cmd_opv_set_bits_planar) |
818 | 3.02M | cmd_getw(bits.num_planes, cbp); |
819 | 3.02M | else |
820 | 3.02M | bits.num_planes = 1; |
821 | 3.02M | if_debug5m('L', mem, " compress=%d depth=%d size=(%d,%d) planes=%d", |
822 | 3.02M | compress, bits.head.depth, |
823 | 3.02M | bits.width, bits.height, bits.num_planes); |
824 | 3.02M | bits.raster = |
825 | 3.02M | bitmap_raster(bits.width * bits.head.depth); |
826 | 3.02M | bits.x_reps = bits.y_reps = 1; |
827 | 3.02M | bits.shift = bits.rep_shift = 0; |
828 | 3.02M | goto stb; |
829 | 76.8k | case cmd_opv_set_tile_color: |
830 | 76.8k | set_colors = state.tile_colors; |
831 | 76.8k | if_debug0m('L', mem, "\n"); |
832 | 76.8k | continue; |
833 | 1.44M | case cmd_opv_set_misc: |
834 | 1.44M | { |
835 | 1.44M | uint cb = *cbp++; |
836 | | |
837 | 1.44M | switch (cb >> 6) { |
838 | 302k | case cmd_set_misc_lop >> 6: |
839 | 302k | cmd_getw(state.lop, cbp); |
840 | 302k | state.lop = (state.lop << 6) + (cb & 0x3f); |
841 | 302k | if_debug1m('L', mem, " lop=0x%x\n", state.lop); |
842 | 302k | if (state.lop_enabled) |
843 | 207k | gs_gstate.log_op = state.lop; |
844 | 302k | break; |
845 | 94.9k | case cmd_set_misc_data_x >> 6: |
846 | 94.9k | if (cb & 0x20) |
847 | 94.9k | cmd_getw(data_x, cbp); |
848 | 94.9k | else |
849 | 94.9k | data_x = 0; |
850 | 94.9k | data_x = (data_x << 5) + (cb & 0x1f); |
851 | 94.9k | if_debug1m('L', mem, " data_x=%d\n", data_x); |
852 | 94.9k | break; |
853 | 1.04M | case cmd_set_misc_map >> 6: |
854 | 1.04M | cbuf.ptr = cbp; |
855 | 1.04M | code = read_set_misc_map(cb, &cbuf, &gs_gstate, mem); |
856 | 1.04M | if (code < 0) |
857 | 0 | goto out; |
858 | 1.04M | cbp = cbuf.ptr; |
859 | 1.04M | break; |
860 | 0 | case cmd_set_misc_halftone >> 6: { |
861 | 0 | uint num_comp; |
862 | | #ifdef DEBUG |
863 | | halftone_type = cb & 0x3f; |
864 | | #endif |
865 | 0 | cmd_getw(num_comp, cbp); |
866 | | #ifdef DEBUG |
867 | | if_debug2m('L', mem, " halftone type=%d num_comp=%u\n", |
868 | | halftone_type, num_comp); |
869 | | #endif |
870 | 0 | code = cmd_resize_halftone( |
871 | 0 | &gs_gstate.dev_ht[HT_OBJTYPE_DEFAULT], |
872 | 0 | num_comp, mem); |
873 | 0 | if (code < 0) |
874 | 0 | goto out; |
875 | 0 | break; |
876 | 0 | } |
877 | 0 | default: |
878 | 0 | goto bad_op; |
879 | 1.44M | } |
880 | 1.44M | } |
881 | 1.44M | continue; |
882 | 1.44M | case cmd_opv_enable_lop: |
883 | 95.5k | state.lop_enabled = true; |
884 | 95.5k | gs_gstate.log_op = state.lop; |
885 | 95.5k | if_debug0m('L', mem, "\n"); |
886 | 95.5k | continue; |
887 | 80.8k | case cmd_opv_disable_lop: |
888 | 80.8k | state.lop_enabled = false; |
889 | 80.8k | gs_gstate.log_op = lop_default; |
890 | 80.8k | if_debug0m('L', mem, "\n"); |
891 | 80.8k | continue; |
892 | 650k | case cmd_opv_end_page: |
893 | 650k | if_debug0m('L', mem, "\n"); |
894 | | /* |
895 | | * Do end-of-page cleanup, then reinitialize if |
896 | | * there are more pages to come. |
897 | | */ |
898 | 650k | goto out; |
899 | 0 | case cmd_opv_delta_color0: |
900 | 0 | pcolor = &set_colors[0]; |
901 | 0 | goto delta2_c; |
902 | 10.4M | case cmd_opv_delta_color1: |
903 | 10.4M | pcolor = &set_colors[1]; |
904 | 10.4M | delta2_c:set_colors = state.colors; |
905 | | /* See comments for cmd_put_color() in gxclutil.c. */ |
906 | 10.4M | { |
907 | 10.4M | gx_color_index delta = 0; |
908 | 10.4M | uint data; |
909 | | |
910 | 10.4M | dev_depth = (tdev->color_info.depth <= 8*sizeof(gx_color_index) ? |
911 | 10.4M | tdev->color_info.depth : 8*sizeof(gx_color_index)); |
912 | 10.4M | dev_depth_bytes = (dev_depth + 7) >> 3; |
913 | 10.4M | switch (dev_depth_bytes) { |
914 | | /* For cases with an even number of bytes */ |
915 | 0 | case 8: |
916 | 0 | data = *cbp++; |
917 | 0 | delta = (((gx_color_index) |
918 | 0 | ((data & 0xf0) << 4) + (data & 0x0f)) << 24) << 24; |
919 | | /* fall through */ |
920 | 0 | case 6: |
921 | 0 | data = *cbp++; |
922 | 0 | delta |= (((gx_color_index) |
923 | 0 | ((data & 0xf0) << 4) + (data & 0x0f)) << 16) << 16; |
924 | | /* fall through */ |
925 | 7.18M | case 4: |
926 | 7.18M | data = *cbp++; |
927 | 7.18M | delta |= ((gx_color_index) |
928 | 7.18M | ((data & 0xf0) << 4) + (data & 0x0f)) << 16; |
929 | | /* fall through */ |
930 | 7.18M | case 2: |
931 | 7.18M | data = *cbp++; |
932 | 7.18M | delta |= ((gx_color_index) |
933 | 7.18M | ((data & 0xf0) << 4) + (data & 0x0f)); |
934 | 7.18M | break; |
935 | | /* For cases with an odd number of bytes */ |
936 | 0 | case 7: |
937 | 0 | data = *cbp++; |
938 | 0 | delta = ((gx_color_index) |
939 | 0 | ((data & 0xf0) << 4) + (data & 0x0f)) << 16; |
940 | | /* fall through */ |
941 | 0 | case 5: |
942 | 0 | data = *cbp++; |
943 | 0 | delta |= ((gx_color_index) |
944 | 0 | ((data & 0xf0) << 4) + (data & 0x0f)); |
945 | | /* fall through */ |
946 | 3.30M | case 3: |
947 | 3.30M | data = *cbp++; |
948 | 3.30M | odd_delta_shift = (dev_depth_bytes - 3) * 8; |
949 | 3.30M | delta |= ((gx_color_index) |
950 | 3.30M | ((data & 0xe0) << 3) + (data & 0x1f)) << odd_delta_shift; |
951 | 3.30M | data = *cbp++; |
952 | 3.30M | delta |= ((gx_color_index) ((data & 0xf8) << 2) + (data & 0x07)) |
953 | 3.30M | << (odd_delta_shift + 11); |
954 | 10.4M | } |
955 | 10.4M | *pcolor += delta - cmd_delta_offsets[dev_depth_bytes]; |
956 | 10.4M | } |
957 | 10.4M | if (sizeof(*pcolor) <= sizeof(ulong)) |
958 | 10.4M | if_debug1m('L', mem, " 0x%lx\n", (ulong)*pcolor); |
959 | 0 | else |
960 | 10.4M | if_debug2m('L', mem, " 0x%8lx%08lx\n", |
961 | 10.4M | (ulong)(*pcolor >> 8*(sizeof(*pcolor) - sizeof(ulong))), (ulong)*pcolor); |
962 | 10.4M | continue; |
963 | 0 | case cmd_opv_set_copy_color: |
964 | 0 | state.color_is_alpha = 0; |
965 | 0 | if_debug0m('L', mem, "\n"); |
966 | 0 | continue; |
967 | 0 | case cmd_opv_set_copy_alpha: |
968 | 0 | state.color_is_alpha = 1; |
969 | 0 | if_debug0m('L', mem, "\n"); |
970 | 0 | continue; |
971 | 0 | default: |
972 | 0 | goto bad_op; |
973 | 17.6M | } |
974 | | /*NOTREACHED */ |
975 | 38.0k | case cmd_op_set_color0 >> 4: |
976 | 38.0k | pcolor = &set_colors[0]; |
977 | 38.0k | goto set_color; |
978 | 7.48M | case cmd_op_set_color1 >> 4: |
979 | 7.48M | pcolor = &set_colors[1]; |
980 | 7.51M | set_color:set_colors = state.colors; |
981 | | /* |
982 | | * We have a special case for gx_no_color_index. If the low |
983 | | * order 4 bits are "cmd_no_color_index" then we really |
984 | | * have a value of gx_no_color_index. Otherwise the these |
985 | | * bits indicate the number of low order zero bytes in the |
986 | | * value. See comments for cmd_put_color() in gxclutil.c. |
987 | | */ |
988 | 7.51M | num_zero_bytes = op & 0x0f; |
989 | | |
990 | 7.51M | if (num_zero_bytes == cmd_no_color_index) |
991 | 0 | *pcolor = gx_no_color_index; |
992 | 7.51M | else { |
993 | 7.51M | gx_color_index color = 0; |
994 | | |
995 | 7.51M | dev_depth = (tdev->color_info.depth < 8*sizeof(gx_color_index) ? |
996 | 7.51M | tdev->color_info.depth : 8*sizeof(gx_color_index)); |
997 | 7.51M | dev_depth_bytes = (dev_depth + 7) >> 3; |
998 | 7.51M | switch (dev_depth_bytes - num_zero_bytes) { |
999 | 0 | case 8: |
1000 | 0 | color = (gx_color_index) * cbp++; |
1001 | 0 | case 7: |
1002 | 0 | color = (color << 8) | (gx_color_index) * cbp++; |
1003 | 0 | case 6: |
1004 | 0 | color = (color << 8) | (gx_color_index) * cbp++; |
1005 | 0 | case 5: |
1006 | 0 | color = (color << 8) | (gx_color_index) * cbp++; |
1007 | 679k | case 4: |
1008 | 679k | color = (color << 8) | (gx_color_index) * cbp++; |
1009 | 1.66M | case 3: |
1010 | 1.66M | color = (color << 8) | (gx_color_index) * cbp++; |
1011 | 1.76M | case 2: |
1012 | 1.76M | color = (color << 8) | (gx_color_index) * cbp++; |
1013 | 7.10M | case 1: |
1014 | 7.10M | color = (color << 8) | (gx_color_index) * cbp++; |
1015 | 7.51M | default: |
1016 | 7.51M | break; |
1017 | 7.51M | } |
1018 | 7.51M | color <<= num_zero_bytes * 8; |
1019 | 7.51M | *pcolor = color; |
1020 | 7.51M | } |
1021 | 7.51M | if (sizeof(*pcolor) <= sizeof(ulong)) |
1022 | 7.51M | if_debug1m('L', mem, " 0x%lx\n", (ulong)*pcolor); |
1023 | 0 | else |
1024 | 7.51M | if_debug2m('L', mem, " 0x%8lx%08lx\n", |
1025 | 7.51M | (ulong)(*pcolor >> 8*(sizeof(*pcolor) - sizeof(ulong))), (ulong)*pcolor); |
1026 | 7.51M | continue; |
1027 | 1.49M | case cmd_op_fill_rect >> 4: |
1028 | 1.52M | case cmd_op_tile_rect >> 4: |
1029 | 1.52M | cbp = cmd_read_rect(op, &state.rect, cbp); |
1030 | 1.52M | break; |
1031 | 2.41M | case cmd_op_fill_rect_short >> 4: |
1032 | 2.60M | case cmd_op_tile_rect_short >> 4: |
1033 | 2.60M | state.rect.x += *cbp + cmd_min_short; |
1034 | 2.60M | state.rect.width += cbp[1] + cmd_min_short; |
1035 | 2.60M | if (op & 0xf) { |
1036 | 1.44M | state.rect.height += (op & 0xf) + cmd_min_dxy_tiny; |
1037 | 1.44M | cbp += 2; |
1038 | 1.44M | } else { |
1039 | 1.15M | state.rect.y += cbp[2] + cmd_min_short; |
1040 | 1.15M | state.rect.height += cbp[3] + cmd_min_short; |
1041 | 1.15M | cbp += 4; |
1042 | 1.15M | } |
1043 | 2.60M | break; |
1044 | 20.4M | case cmd_op_fill_rect_tiny >> 4: |
1045 | 20.7M | case cmd_op_tile_rect_tiny >> 4: |
1046 | 20.7M | if (op & 8) |
1047 | 15.7M | state.rect.x += state.rect.width; |
1048 | 5.04M | else { |
1049 | 5.04M | int txy = *cbp++; |
1050 | | |
1051 | 5.04M | state.rect.x += (txy >> 4) + cmd_min_dxy_tiny; |
1052 | 5.04M | state.rect.y += (txy & 0xf) + cmd_min_dxy_tiny; |
1053 | 5.04M | } |
1054 | 20.7M | state.rect.width += (op & 7) + cmd_min_dw_tiny; |
1055 | 20.7M | break; |
1056 | 9.20M | case cmd_op_copy_mono_planes >> 4: |
1057 | 9.20M | cmd_getw(plane_height, cbp); |
1058 | 9.20M | if (plane_height == 0) { |
1059 | | /* We are doing a copy mono */ |
1060 | 9.20M | depth = 1; |
1061 | 9.20M | } else { |
1062 | 0 | depth = tdev->color_info.depth; |
1063 | 0 | } |
1064 | 9.20M | if_debug1m('L', mem, " plane_height=0x%x", plane_height); |
1065 | 9.20M | goto copy; |
1066 | 1.13M | case cmd_op_copy_color_alpha >> 4: |
1067 | 1.13M | if (state.color_is_alpha) { |
1068 | 0 | if (!(op & 8)) |
1069 | 0 | depth = *cbp++; |
1070 | 0 | } else |
1071 | 1.13M | depth = tdev->color_info.depth; |
1072 | 1.13M | plane_height = 0; |
1073 | 10.3M | copy:cmd_getw(state.rect.x, cbp); |
1074 | 10.3M | cmd_getw(state.rect.y, cbp); |
1075 | 10.3M | if (op & cmd_copy_use_tile) { /* Use the current "tile". */ |
1076 | | #ifdef DEBUG |
1077 | | if (state_slot->index != state.tile_index) { |
1078 | | mlprintf2(mem, "state_slot->index = %d, state.tile_index = %d!\n", |
1079 | | state_slot->index, |
1080 | | state.tile_index); |
1081 | | code = gs_note_error(gs_error_ioerror); |
1082 | | goto out; |
1083 | | } |
1084 | | #endif |
1085 | 9.11M | depth = state_slot->head.depth; |
1086 | 9.11M | state.rect.width = state_slot->width; |
1087 | 9.11M | state.rect.height = state_slot->height; |
1088 | 9.11M | if (state.rect.y + state.rect.height > cdev->height) |
1089 | 9.50k | state.rect.height = cdev->height - state.rect.y; /* clamp as writer did */ |
1090 | 9.11M | raster = state_slot->raster; |
1091 | 9.11M | source = (byte *) (state_slot + 1); |
1092 | 9.11M | } else { /* Read width, height, bits. */ |
1093 | | /* depth was set already. */ |
1094 | 1.21M | uint width_bits, width_bytes; |
1095 | 1.21M | uint bytes; |
1096 | 1.21M | uchar planes = 1; |
1097 | 1.21M | uint plane_depth = depth; |
1098 | 1.21M | uint pln; |
1099 | 1.21M | byte compression = op & 3; |
1100 | 1.21M | uint out_bytes; |
1101 | | |
1102 | 1.21M | cmd_getw(state.rect.width, cbp); |
1103 | 1.21M | cmd_getw(state.rect.height, cbp); |
1104 | 1.21M | if (plane_height != 0) { |
1105 | 0 | planes = tdev->color_info.num_components; |
1106 | 0 | plane_depth /= planes; |
1107 | 0 | } |
1108 | 1.21M | width_bits = state.rect.width * plane_depth; |
1109 | 1.21M | bytes = clist_bitmap_bytes(width_bits, |
1110 | 1.21M | state.rect.height, |
1111 | 1.21M | op & 3, &width_bytes, |
1112 | 1.21M | (uint *)&raster); |
1113 | 1.21M | if (planes > 1) { |
1114 | 0 | out_bytes = raster * state.rect.height; |
1115 | 0 | plane_height = state.rect.height; |
1116 | 1.21M | } else { |
1117 | 1.21M | out_bytes = bytes; |
1118 | 1.21M | } |
1119 | | /* copy_mono and copy_color/alpha */ |
1120 | | /* ensure that the bits will fit in a single buffer, */ |
1121 | | /* even after decompression if compressed. */ |
1122 | | #ifdef DEBUG |
1123 | | if (planes * out_bytes > data_bits_size) { |
1124 | | mlprintf6(mem, "bitmap size exceeds buffer! width=%d raster=%d height=%d\n file pos %"PRId64" buf pos %d/%d\n", |
1125 | | state.rect.width, raster, |
1126 | | state.rect.height, |
1127 | | stell(s), (int)(cbp - cbuf.data), |
1128 | | (int)(cbuf.end - cbuf.data)); |
1129 | | code = gs_note_error(gs_error_ioerror); |
1130 | | goto out; |
1131 | | } |
1132 | | #endif |
1133 | 2.42M | for (pln = 0; pln < planes; pln++) { |
1134 | 1.21M | byte *plane_bits = data_bits + pln * plane_height * raster; |
1135 | | |
1136 | | /* Fill the cbuf if needed to get the data for the plane */ |
1137 | 1.21M | if (cbp + out_bytes >= cbuf.warn_limit) { |
1138 | 9.19k | code = top_up_cbuf(&cbuf, &cbp); |
1139 | 9.19k | if (code < 0) |
1140 | 0 | goto top_up_failed; |
1141 | 9.19k | } |
1142 | 1.21M | if (pln) |
1143 | 0 | compression = *cbp++; |
1144 | | |
1145 | 1.21M | if (compression == cmd_compress_const) { |
1146 | 690 | cbp = cmd_read_data(&cbuf, plane_bits, 1, cbp); |
1147 | 690 | if (width_bytes > 0 && state.rect.height > 0) |
1148 | 690 | memset(plane_bits+1, *plane_bits, width_bytes * state.rect.height - 1); |
1149 | 690 | if (pln == 0) |
1150 | 690 | source = data_bits; |
1151 | | |
1152 | 1.21M | } else if (compression) { /* Decompress the image data. */ |
1153 | 2.14k | stream_cursor_read r; |
1154 | 2.14k | stream_cursor_write w; |
1155 | | |
1156 | | /* We don't know the data length a priori, */ |
1157 | | /* so to be conservative, we read */ |
1158 | | /* the uncompressed size. */ |
1159 | 2.14k | uint cleft = cbuf.end - cbp; |
1160 | | |
1161 | 2.14k | if (cleft < bytes && !cbuf.end_status) { |
1162 | 0 | uint nread = cbuf_size - cleft; |
1163 | |
|
1164 | 0 | advance_buffer(&cbuf, cbp); |
1165 | 0 | cbuf.end_status = sgets(s, cbuf.data + cleft, nread, &nread); |
1166 | 0 | set_cb_end(&cbuf, cbuf.data + cleft + nread); |
1167 | 0 | cbp = cbuf.data; |
1168 | 0 | } |
1169 | 2.14k | r.ptr = cbp - 1; |
1170 | 2.14k | r.limit = cbuf.end - 1; |
1171 | 2.14k | w.ptr = plane_bits - 1; |
1172 | 2.14k | w.limit = w.ptr + data_bits_size; |
1173 | 2.14k | switch (compression) { |
1174 | 0 | case cmd_compress_rle: |
1175 | 0 | { |
1176 | 0 | stream_RLD_state sstate; |
1177 | |
|
1178 | 0 | clist_rld_init(&sstate); |
1179 | | /* The process procedure can't fail. */ |
1180 | 0 | (*s_RLD_template.process) |
1181 | 0 | ((stream_state *)&sstate, &r, &w, true); |
1182 | 0 | } |
1183 | 0 | break; |
1184 | 2.14k | case cmd_compress_cfe: |
1185 | 2.14k | { |
1186 | 2.14k | stream_CFD_state sstate; |
1187 | | |
1188 | 2.14k | clist_cfd_init(&sstate, |
1189 | 2.14k | width_bytes << 3 /*state.rect.width */ , |
1190 | 2.14k | state.rect.height, mem); |
1191 | | /* The process procedure can't fail. */ |
1192 | 2.14k | (*s_CFD_template.process) |
1193 | 2.14k | ((stream_state *)&sstate, &r, &w, true); |
1194 | 2.14k | (*s_CFD_template.release) |
1195 | 2.14k | ((stream_state *)&sstate); |
1196 | 2.14k | } |
1197 | 2.14k | break; |
1198 | 0 | default: |
1199 | 0 | goto bad_op; |
1200 | 2.14k | } |
1201 | 2.14k | cbp = r.ptr + 1; |
1202 | 2.14k | if (pln == 0) |
1203 | 2.14k | source = data_bits; |
1204 | 1.21M | } else if ((state.rect.height > 1 && width_bytes != raster) || |
1205 | 1.21M | (plane_height != 0)) { |
1206 | 10.2k | cbp = cmd_read_short_bits(&cbuf, plane_bits, bytes, width_bytes, |
1207 | 10.2k | state.rect.height, raster, cbp); |
1208 | 10.2k | if (pln == 0) |
1209 | 10.2k | source = data_bits; |
1210 | 1.20M | } else { |
1211 | | /* Never used for planar data */ |
1212 | 1.20M | cbp = cmd_read_data(&cbuf, cbuf.data, bytes, cbp); |
1213 | 1.20M | source = cbuf.data; |
1214 | 1.20M | } |
1215 | 1.21M | } |
1216 | | #ifdef DEBUG |
1217 | | if (gs_debug_c('L')) { |
1218 | | dmprintf2(mem, " depth=%d, data_x=%d\n", |
1219 | | depth, data_x); |
1220 | | cmd_print_bits(mem, source, state.rect.width, |
1221 | | state.rect.height, raster); |
1222 | | } |
1223 | | #endif |
1224 | 1.21M | } |
1225 | 10.3M | break; |
1226 | 10.3M | case cmd_op_delta_tile_index >> 4: |
1227 | 2.03M | state.tile_index += (int)(op & 0xf) - 8; |
1228 | 2.03M | goto sti; |
1229 | 3.95M | case cmd_op_set_tile_index >> 4: |
1230 | 3.95M | state.tile_index = |
1231 | 3.95M | ((op & 0xf) << 8) + *cbp++; |
1232 | 5.99M | sti:state_slot = |
1233 | 5.99M | (tile_slot *) (cdev->cache_chunk->data + |
1234 | 5.99M | cdev->tile_table[state.tile_index].offset); |
1235 | 5.99M | if_debug2m('L', mem, " index=%u offset=%lu\n", |
1236 | 5.99M | state.tile_index, |
1237 | 5.99M | cdev->tile_table[state.tile_index].offset); |
1238 | 5.99M | state_tile.data = (byte *) (state_slot + 1); |
1239 | 9.02M | stp:state_tile.size.x = state_slot->width; |
1240 | 9.02M | state_tile.size.y = state_slot->height; |
1241 | 9.02M | state_tile.raster = state_slot->raster; |
1242 | 9.02M | state_tile.rep_width = state_tile.size.x / |
1243 | 9.02M | state_slot->x_reps; |
1244 | 9.02M | state_tile.rep_height = state_tile.size.y / |
1245 | 9.02M | state_slot->y_reps; |
1246 | 9.02M | state_tile.rep_shift = state_slot->rep_shift; |
1247 | 9.02M | state_tile.shift = state_slot->shift; |
1248 | 9.02M | state_tile.id = state_slot->id; |
1249 | 9.02M | state_tile.num_planes = state_slot->num_planes; |
1250 | 9.02M | set_tile_phase: |
1251 | 9.02M | if (state_tile.size.x) |
1252 | 9.02M | tile_phase.x = |
1253 | 9.02M | (state.tile_phase.x + x0) % state_tile.size.x; |
1254 | | /* |
1255 | | * The true tile height for shifted tiles is not |
1256 | | * size.y: see gxbitmap.h for the computation. |
1257 | | */ |
1258 | 9.02M | if (state_tile.size.y) { |
1259 | 9.02M | int full_height; |
1260 | | |
1261 | 9.02M | if (state_tile.shift == 0) |
1262 | 9.02M | full_height = state_tile.size.y; |
1263 | 0 | else |
1264 | 0 | full_height = state_tile.rep_height * |
1265 | 0 | (state_tile.rep_width / |
1266 | 0 | igcd(state_tile.rep_shift, |
1267 | 0 | state_tile.rep_width)); |
1268 | 9.02M | tile_phase.y = (state.tile_phase.y + y0) % full_height; |
1269 | 9.02M | } |
1270 | 9.02M | continue; |
1271 | 15.6M | case cmd_op_misc2 >> 4: |
1272 | 15.6M | switch (op) { |
1273 | 0 | case cmd_opv_set_bits_planar: |
1274 | 0 | goto do_opv_set_bits; |
1275 | 26.7k | case cmd_opv_set_fill_adjust: |
1276 | 26.7k | cmd_get_value(gs_gstate.fill_adjust.x, cbp); |
1277 | 26.7k | cmd_get_value(gs_gstate.fill_adjust.y, cbp); |
1278 | 26.7k | if_debug2m('L', mem, " (%g,%g)\n", |
1279 | 26.7k | fixed2float(gs_gstate.fill_adjust.x), |
1280 | 26.7k | fixed2float(gs_gstate.fill_adjust.y)); |
1281 | 26.7k | continue; |
1282 | 472k | case cmd_opv_set_ctm: |
1283 | 472k | { |
1284 | 472k | gs_matrix mat; |
1285 | | |
1286 | 472k | cbp = cmd_read_matrix(&mat, cbp); |
1287 | 472k | if_debug6m('L', mem, " [%g %g %g %g %g %g]\n", |
1288 | 472k | mat.xx, mat.xy, mat.yx, mat.yy, |
1289 | 472k | mat.tx, mat.ty); |
1290 | 472k | mat.tx -= x0; |
1291 | 472k | mat.ty -= y0; |
1292 | 472k | gs_gstate_setmatrix(&gs_gstate, &mat); |
1293 | 472k | } |
1294 | 472k | continue; |
1295 | 531k | case cmd_opv_set_misc2: |
1296 | 531k | cbuf.ptr = cbp; |
1297 | 531k | code = read_set_misc2(&cbuf, &gs_gstate, ¬es); |
1298 | 531k | cbp = cbuf.ptr; |
1299 | 531k | if (code < 0) |
1300 | 0 | goto out; |
1301 | 531k | continue; |
1302 | 531k | case cmd_opv_set_dash: |
1303 | 21.5k | { |
1304 | 21.5k | int nb = *cbp++; |
1305 | 21.5k | int n = nb & 0x3f; |
1306 | 21.5k | float dot_length, offset; |
1307 | | |
1308 | 21.5k | cmd_get_value(dot_length, cbp); |
1309 | 21.5k | cmd_get_value(offset, cbp); |
1310 | 21.5k | memcpy(dash_pattern, cbp, n * sizeof(float)); |
1311 | | |
1312 | 21.5k | gx_set_dash(&gs_gstate.line_params.dash, |
1313 | 21.5k | dash_pattern, n, offset, |
1314 | 21.5k | NULL); |
1315 | 21.5k | gx_set_dash_adapt(&gs_gstate.line_params.dash, |
1316 | 21.5k | (nb & 0x80) != 0); |
1317 | 21.5k | gx_set_dot_length(&gs_gstate.line_params, |
1318 | 21.5k | dot_length, |
1319 | 21.5k | (nb & 0x40) != 0); |
1320 | | #ifdef DEBUG |
1321 | | if (gs_debug_c('L')) { |
1322 | | int i; |
1323 | | |
1324 | | dmprintf4(mem, " dot=%g(mode %d) adapt=%d offset=%g [", |
1325 | | dot_length, |
1326 | | (nb & 0x40) != 0, |
1327 | | (nb & 0x80) != 0, offset); |
1328 | | for (i = 0; i < n; ++i) |
1329 | | dmprintf1(mem, "%g ", dash_pattern[i]); |
1330 | | dmputs(mem, "]\n"); |
1331 | | } |
1332 | | #endif |
1333 | 21.5k | cbp += n * sizeof(float); |
1334 | 21.5k | } |
1335 | 21.5k | break; |
1336 | 799 | case cmd_opv_enable_clip: |
1337 | 799 | pcpath = (use_clip ? &clip_path : NULL); |
1338 | 799 | if (pcpath) { |
1339 | 422 | code = gx_cpath_ensure_path_list(pcpath); |
1340 | 422 | if (code < 0) |
1341 | 0 | goto out; |
1342 | 422 | } |
1343 | 799 | clipper_dev_open = false; |
1344 | 799 | if_debug0m('L', mem, "\n"); |
1345 | 799 | break; |
1346 | 1.39k | case cmd_opv_disable_clip: |
1347 | 1.39k | pcpath = NULL; |
1348 | 1.39k | clipper_dev_open = false; |
1349 | 1.39k | if_debug0m('L', mem, "\n"); |
1350 | 1.39k | break; |
1351 | 815k | case cmd_opv_begin_clip: |
1352 | 815k | pcpath = NULL; |
1353 | 815k | clipper_dev_open = false; |
1354 | 815k | in_clip = true; |
1355 | 815k | if_debug0m('L', mem, "\n"); |
1356 | 815k | code = gx_cpath_reset(&clip_path); |
1357 | 815k | if (code < 0) |
1358 | 0 | goto out; |
1359 | 815k | gx_cpath_accum_begin(&clip_accum, mem, false); |
1360 | 815k | gx_cpath_accum_set_cbox(&clip_accum, |
1361 | 815k | &target_box); |
1362 | 815k | tdev = (gx_device *)&clip_accum; |
1363 | 815k | clip_save.lop_enabled = state.lop_enabled; |
1364 | 815k | clip_save.dcolor = fill_color; |
1365 | 815k | clip_save.fa_save.x = gs_gstate.fill_adjust.x; |
1366 | 815k | clip_save.fa_save.y = gs_gstate.fill_adjust.y; |
1367 | 815k | cmd_getw(gs_gstate.fill_adjust.x, cbp); |
1368 | 815k | cmd_getw(gs_gstate.fill_adjust.y, cbp); |
1369 | | /* temporarily set a solid color */ |
1370 | 815k | color_set_pure(&fill_color, (gx_color_index)1); |
1371 | 815k | state.lop_enabled = false; |
1372 | 815k | gs_gstate.log_op = lop_default; |
1373 | 815k | break; |
1374 | 815k | case cmd_opv_end_clip: |
1375 | 815k | if_debug0m('L', mem, "\n"); |
1376 | 815k | gx_cpath_accum_end(&clip_accum, &clip_path); |
1377 | 815k | tdev = target; |
1378 | | /* |
1379 | | * If the entire band falls within the clip |
1380 | | * path, no clipping is needed. |
1381 | | */ |
1382 | 815k | { |
1383 | 815k | gs_fixed_rect cbox; |
1384 | | |
1385 | 815k | gx_cpath_inner_box(&clip_path, &cbox); |
1386 | 815k | use_clip = |
1387 | 815k | !(cbox.p.x <= target_box.p.x && |
1388 | 815k | cbox.q.x >= target_box.q.x && |
1389 | 815k | cbox.p.y <= target_box.p.y && |
1390 | 815k | cbox.q.y >= target_box.q.y); |
1391 | 815k | } |
1392 | 815k | pcpath = (use_clip ? &clip_path : NULL); |
1393 | 815k | if (pcpath) { |
1394 | 407k | code = gx_cpath_ensure_path_list(pcpath); |
1395 | 407k | if (code < 0) |
1396 | 0 | goto out; |
1397 | 407k | } |
1398 | 815k | clipper_dev_open = false; |
1399 | 815k | state.lop_enabled = clip_save.lop_enabled; |
1400 | 815k | gs_gstate.log_op = |
1401 | 815k | (state.lop_enabled ? state.lop : |
1402 | 815k | lop_default); |
1403 | 815k | fill_color = clip_save.dcolor; |
1404 | | /* restore the fill_adjust if it was changed by begin_clip */ |
1405 | 815k | gs_gstate.fill_adjust.x = clip_save.fa_save.x; |
1406 | 815k | gs_gstate.fill_adjust.y = clip_save.fa_save.y; |
1407 | 815k | in_clip = false; |
1408 | 815k | break; |
1409 | 114k | case cmd_opv_set_color_space: |
1410 | 114k | cbuf.ptr = cbp; |
1411 | 114k | code = read_set_color_space(&cbuf, &gs_gstate, cdev, mem); |
1412 | 114k | pcs = gs_gstate.color[0].color_space; |
1413 | 114k | cbp = cbuf.ptr; |
1414 | 114k | if (code < 0) { |
1415 | 0 | if (code == gs_error_rangecheck) |
1416 | 0 | goto bad_op; |
1417 | 0 | goto out; |
1418 | 0 | } |
1419 | 114k | break; |
1420 | 1.81M | case cmd_op_fill_rect_hl: |
1421 | 1.81M | { |
1422 | 1.81M | gs_fixed_rect rect_hl; |
1423 | | |
1424 | 1.81M | cbp = cmd_read_rect(op & 0xf0, &state.rect, cbp); |
1425 | 1.81M | if (fill_color.type != gx_dc_type_devn) { |
1426 | 0 | if_debug0m('L', mem, "hl rect fill without devn color\n"); |
1427 | 0 | code = gs_note_error(gs_error_typecheck); |
1428 | 0 | goto out; |
1429 | 0 | } |
1430 | 1.81M | if_debug4m('L', mem, " x=%d y=%d w=%d h=%d\n", |
1431 | 1.81M | state.rect.x, state.rect.y, |
1432 | 1.81M | state.rect.width,state.rect.height); |
1433 | 1.81M | rect_hl.p.x = int2fixed(state.rect.x - x0); |
1434 | 1.81M | rect_hl.p.y = int2fixed(state.rect.y - y0); |
1435 | 1.81M | rect_hl.q.x = int2fixed(state.rect.width) + rect_hl.p.x; |
1436 | 1.81M | rect_hl.q.y = int2fixed(state.rect.height) + rect_hl.p.y; |
1437 | 1.81M | code = dev_proc(tdev, fill_rectangle_hl_color) (tdev, |
1438 | 1.81M | &rect_hl, NULL, |
1439 | 1.81M | &fill_color, NULL); |
1440 | 1.81M | } |
1441 | 0 | continue; |
1442 | 113k | case cmd_opv_begin_image_rect: |
1443 | 113k | cbuf.ptr = cbp; |
1444 | 113k | code = read_begin_image(&cbuf, &image.c, pcs); |
1445 | 113k | cbp = cbuf.ptr; |
1446 | 113k | if (code < 0) |
1447 | 0 | goto out; |
1448 | 113k | { |
1449 | 113k | uint diff; |
1450 | | |
1451 | 113k | cmd_getw(image_rect.p.x, cbp); |
1452 | 113k | cmd_getw(image_rect.p.y, cbp); |
1453 | 113k | cmd_getw(diff, cbp); |
1454 | 113k | image_rect.q.x = image.d.Width - diff; |
1455 | 113k | cmd_getw(diff, cbp); |
1456 | 113k | image_rect.q.y = image.d.Height - diff; |
1457 | 113k | if_debug4m('L', mem, " rect=(%d,%d),(%d,%d)", |
1458 | 113k | image_rect.p.x, image_rect.p.y, |
1459 | 113k | image_rect.q.x, image_rect.q.y); |
1460 | 113k | } |
1461 | 113k | goto ibegin; |
1462 | 1.77k | case cmd_opv_begin_image: |
1463 | 1.77k | cbuf.ptr = cbp; |
1464 | 1.77k | code = read_begin_image(&cbuf, &image.c, pcs); |
1465 | 1.77k | cbp = cbuf.ptr; |
1466 | 1.77k | if (code < 0) |
1467 | 0 | goto out; |
1468 | 1.77k | image_rect.p.x = 0; |
1469 | 1.77k | image_rect.p.y = 0; |
1470 | 1.77k | image_rect.q.x = image.d.Width; |
1471 | 1.77k | image_rect.q.y = image.d.Height; |
1472 | 1.77k | if_debug2m('L', mem, " size=(%d,%d)", |
1473 | 1.77k | image.d.Width, image.d.Height); |
1474 | 114k | ibegin: if_debug0m('L', mem, "\n"); |
1475 | 114k | { |
1476 | | /* Processing an image operation */ |
1477 | 114k | dev_proc(tdev, set_graphics_type_tag)(tdev, GS_IMAGE_TAG);/* FIXME: what about text bitmaps? */ |
1478 | 114k | image.i4.override_in_smask = 0; |
1479 | 114k | code = (*dev_proc(tdev, begin_typed_image)) |
1480 | 114k | (tdev, &gs_gstate, NULL, |
1481 | 114k | (const gs_image_common_t *)&image, |
1482 | 114k | &image_rect, &fill_color, pcpath, mem, |
1483 | 114k | &image_info); |
1484 | 114k | } |
1485 | 114k | if (code < 0) |
1486 | 0 | goto out; |
1487 | 114k | break; |
1488 | 114k | case cmd_opv_image_plane_data: |
1489 | 0 | cmd_getw(data_height, cbp); |
1490 | 0 | if (data_height == 0) { |
1491 | 0 | if_debug0m('L', mem, " done image\n"); |
1492 | 0 | code = gx_image_end(image_info, true); |
1493 | 0 | if (code < 0) |
1494 | 0 | goto out; |
1495 | 0 | continue; |
1496 | 0 | } |
1497 | 0 | { |
1498 | 0 | uint flags; |
1499 | 0 | int plane; |
1500 | 0 | uint raster1 = 0xbaadf00d; /* Initialize against indeterminizm. */ |
1501 | |
|
1502 | 0 | cmd_getw(flags, cbp); |
1503 | 0 | for (plane = 0; |
1504 | 0 | plane < image_info->num_planes; |
1505 | 0 | ++plane, flags >>= 1) { |
1506 | 0 | if (flags & 1) { |
1507 | 0 | if (cbuf.end - cbp < |
1508 | 0 | 2 * cmd_max_intsize(sizeof(uint))) { |
1509 | 0 | code = top_up_cbuf(&cbuf, &cbp); |
1510 | 0 | if (code < 0) |
1511 | 0 | goto top_up_failed; |
1512 | 0 | } |
1513 | 0 | cmd_getw(planes[plane].raster, cbp); |
1514 | 0 | if ((raster1 = planes[plane].raster) != 0) |
1515 | 0 | cmd_getw(data_x, cbp); |
1516 | 0 | } else { |
1517 | 0 | planes[plane].raster = raster1; |
1518 | 0 | } |
1519 | 0 | planes[plane].data_x = data_x; |
1520 | 0 | } |
1521 | 0 | } |
1522 | 0 | goto idata; |
1523 | 752k | case cmd_opv_image_data: |
1524 | 752k | cmd_getw(data_height, cbp); |
1525 | 752k | if (data_height == 0) { |
1526 | 114k | if_debug0m('L', mem, " done image\n"); |
1527 | 114k | code = gx_image_end(image_info, true); |
1528 | 114k | if (code < 0) |
1529 | 0 | goto out; |
1530 | 114k | continue; |
1531 | 114k | } |
1532 | 637k | { |
1533 | 637k | uint bytes_per_plane; |
1534 | 637k | int plane; |
1535 | | |
1536 | 637k | cmd_getw(bytes_per_plane, cbp); |
1537 | 637k | if_debug2m('L', mem, " height=%u raster=%u\n", |
1538 | 637k | data_height, bytes_per_plane); |
1539 | 637k | for (plane = 0; |
1540 | 1.27M | plane < image_info->num_planes; |
1541 | 639k | ++plane |
1542 | 639k | ) { |
1543 | 639k | planes[plane].data_x = data_x; |
1544 | 639k | planes[plane].raster = bytes_per_plane; |
1545 | 639k | } |
1546 | 637k | } |
1547 | 637k | idata: data_size = 0; |
1548 | 637k | { |
1549 | 637k | int plane; |
1550 | | |
1551 | 1.27M | for (plane = 0; plane < image_info->num_planes; |
1552 | 639k | ++plane) |
1553 | 639k | data_size += planes[plane].raster; |
1554 | 637k | } |
1555 | 637k | data_size *= data_height; |
1556 | 637k | data_on_heap = 0; |
1557 | 637k | if (cbuf.end - cbp < data_size) { |
1558 | 232k | code = top_up_cbuf(&cbuf, &cbp); |
1559 | 232k | if (code < 0) |
1560 | 0 | goto top_up_failed; |
1561 | 232k | } |
1562 | 637k | if (cbuf.end - cbp >= data_size) { |
1563 | 621k | planes[0].data = cbp; |
1564 | 621k | cbp += data_size; |
1565 | 621k | } else { |
1566 | 16.4k | uint cleft = cbuf.end - cbp; |
1567 | 16.4k | uint rleft = data_size - cleft; |
1568 | 16.4k | byte *rdata; |
1569 | | |
1570 | 16.4k | if (data_size > cbuf.end - cbuf.data) { |
1571 | | /* Allocate a separate buffer. */ |
1572 | 16.4k | rdata = data_on_heap = |
1573 | 16.4k | gs_alloc_bytes(mem, data_size, |
1574 | 16.4k | "clist image_data"); |
1575 | 16.4k | if (rdata == 0) { |
1576 | 0 | code = gs_note_error(gs_error_VMerror); |
1577 | 0 | goto out; |
1578 | 0 | } |
1579 | 16.4k | } else |
1580 | 0 | rdata = cbuf.data; |
1581 | 16.4k | memmove(rdata, cbp, cleft); |
1582 | 16.4k | if (data_on_heap) |
1583 | 16.4k | next_is_skip(&cbuf); |
1584 | 16.4k | if (sgets(s, rdata + cleft, rleft, &rleft) < 0) { |
1585 | 0 | code = gs_note_error(gs_error_unregistered); /* Must not happen. */ |
1586 | 0 | goto out; |
1587 | 0 | } |
1588 | 16.4k | planes[0].data = rdata; |
1589 | 16.4k | cbp = cbuf.end; /* force refill */ |
1590 | 16.4k | } |
1591 | 637k | { |
1592 | 637k | int plane; |
1593 | 637k | const byte *data = planes[0].data; |
1594 | | |
1595 | 637k | for (plane = 0; |
1596 | 1.27M | plane < image_info->num_planes; |
1597 | 639k | ++plane |
1598 | 639k | ) { |
1599 | 639k | if (planes[plane].raster == 0) |
1600 | 0 | planes[plane].data = 0; |
1601 | 639k | else { |
1602 | 639k | planes[plane].data = data; |
1603 | 639k | data += planes[plane].raster * |
1604 | 639k | data_height; |
1605 | 639k | } |
1606 | 639k | } |
1607 | 637k | } |
1608 | | #ifdef DEBUG |
1609 | | if (gs_debug_c('L')) { |
1610 | | int plane; |
1611 | | |
1612 | | for (plane = 0; plane < image_info->num_planes; |
1613 | | ++plane) |
1614 | | if (planes[plane].data != 0) |
1615 | | cmd_print_bits(mem, |
1616 | | planes[plane].data, |
1617 | | image_rect.q.x - |
1618 | | image_rect.p.x, |
1619 | | data_height, |
1620 | | planes[plane].raster); |
1621 | | } |
1622 | | #endif |
1623 | 637k | code = gx_image_plane_data(image_info, planes, |
1624 | 637k | data_height); |
1625 | 637k | if (code < 0) |
1626 | 0 | gx_image_end(image_info, false); |
1627 | 637k | if (data_on_heap) |
1628 | 16.4k | gs_free_object(mem, data_on_heap, |
1629 | 637k | "clist image_data"); |
1630 | 637k | data_x = 0; |
1631 | 637k | if (code < 0) |
1632 | 0 | goto out; |
1633 | 637k | continue; |
1634 | 10.1M | case cmd_opv_extend: |
1635 | 10.1M | switch (*cbp++) { |
1636 | 0 | case cmd_opv_ext_put_params: |
1637 | 0 | if_debug0m('L', mem, "put_params\n"); |
1638 | 0 | cbuf.ptr = cbp; |
1639 | 0 | code = read_put_params(&cbuf, &gs_gstate, |
1640 | 0 | cdev, mem); |
1641 | 0 | cbp = cbuf.ptr; |
1642 | 0 | if (code > 0) |
1643 | 0 | break; /* empty list */ |
1644 | 0 | if (code < 0) |
1645 | 0 | goto out; |
1646 | 0 | if (playback_action == playback_action_setup) |
1647 | 0 | goto out; |
1648 | 0 | break; |
1649 | 1.48M | case cmd_opv_ext_composite: |
1650 | 1.48M | if_debug0m('L', mem, " ext_composite\n"); |
1651 | 1.48M | cbuf.ptr = cbp; |
1652 | | /* |
1653 | | * The screen phase may have been changed during |
1654 | | * the processing of masked images. |
1655 | | */ |
1656 | 1.48M | gx_gstate_setscreenphase(&gs_gstate, |
1657 | 1.48M | -x0, -y0, gs_color_select_all); |
1658 | 1.48M | cbp -= 2; /* Step back to simplify the cycle invariant below. */ |
1659 | 38.2M | for (;;) { |
1660 | | /* This internal loop looks ahead for compositor commands and |
1661 | | copies them into a temporary queue. Compositors, which do not paint something, |
1662 | | are marked as idle and later executed with a reduced functionality |
1663 | | for reducing time and memory expense. */ |
1664 | 38.2M | int len; |
1665 | | |
1666 | 38.2M | if (cbp >= cbuf.warn_limit) { |
1667 | 60.3k | code = top_up_cbuf(&cbuf, &cbp); |
1668 | 60.3k | if (code < 0) |
1669 | 0 | goto out; |
1670 | 60.3k | } |
1671 | | #ifdef DEBUG |
1672 | | if (gs_debug_c('L')) { |
1673 | | long offset = (long)clist_file_offset(st, cbp - cbuf.data); |
1674 | | |
1675 | | dmlprintf1(mem, "[L] %ld:", offset); |
1676 | | clist_debug_op(mem, cbp); |
1677 | | dmlprintf(mem, "\n"); |
1678 | | } |
1679 | | #endif |
1680 | 38.2M | if (cbp[0] == cmd_opv_extend && cbp[1] == cmd_opv_ext_composite) { |
1681 | 21.8M | gs_composite_t *pcomp, *pcomp_opening; |
1682 | 21.8M | gs_compositor_closing_state closing_state; |
1683 | | |
1684 | 21.8M | cbuf.ptr = cbp += 2; |
1685 | 21.8M | code = read_composite(&cbuf, mem, &pcomp); |
1686 | 21.8M | if (code < 0) |
1687 | 0 | goto out; |
1688 | 21.8M | cbp = cbuf.ptr; |
1689 | 21.8M | if (pcomp == NULL) |
1690 | 0 | continue; |
1691 | 21.8M | if (gs_is_pdf14trans_compositor(pcomp) && |
1692 | 21.8M | playback_action == playback_action_render_no_pdf14) { |
1693 | | /* free the compositor object */ |
1694 | 1.25M | gs_free_object(mem, pcomp, "read_composite"); |
1695 | 1.25M | pcomp = NULL; |
1696 | 1.25M | continue; |
1697 | 1.25M | } |
1698 | 20.5M | pcomp_opening = pcomp_last; |
1699 | 20.5M | closing_state = pcomp->type->procs.is_closing(pcomp, &pcomp_opening, tdev); |
1700 | 20.5M | switch(closing_state) |
1701 | 20.5M | { |
1702 | 0 | default: |
1703 | 0 | code = (int)closing_state; |
1704 | 0 | if (code >= 0) |
1705 | 0 | code = gs_note_error(gs_error_unregistered); /* Must not happen. */ |
1706 | 0 | goto out; |
1707 | 14.4M | case COMP_ENQUEUE: |
1708 | | /* Enqueue. */ |
1709 | 14.4M | enqueue_compositor(&pcomp_first, &pcomp_last, pcomp); |
1710 | 14.4M | break; |
1711 | 0 | case COMP_EXEC_IDLE: |
1712 | | /* Execute idle. */ |
1713 | 0 | enqueue_compositor(&pcomp_first, &pcomp_last, pcomp); |
1714 | 0 | code = execute_compositor_queue(cdev, &target, &tdev, |
1715 | 0 | &gs_gstate, &pcomp_first, &pcomp_last, pcomp_opening, x0, y0, mem, true); |
1716 | 0 | if (code < 0) |
1717 | 0 | goto out; |
1718 | 0 | break; |
1719 | 228k | case COMP_EXEC_QUEUE: |
1720 | | /* The opening command was executed. Execute the queue. */ |
1721 | 228k | enqueue_compositor(&pcomp_first, &pcomp_last, pcomp); |
1722 | 228k | code = execute_compositor_queue(cdev, &target, &tdev, |
1723 | 228k | &gs_gstate, &pcomp_first, &pcomp_last, pcomp_first, x0, y0, mem, false); |
1724 | 228k | if (code < 0) |
1725 | 0 | goto out; |
1726 | 228k | break; |
1727 | 228k | case COMP_REPLACE_PREV: |
1728 | | /* Replace last compositors. */ |
1729 | 0 | code = execute_compositor_queue(cdev, &target, &tdev, |
1730 | 0 | &gs_gstate, &pcomp_first, &pcomp_last, pcomp_opening, x0, y0, mem, true); |
1731 | 0 | if (code < 0) |
1732 | 0 | goto out; |
1733 | 0 | enqueue_compositor(&pcomp_first, &pcomp_last, pcomp); |
1734 | 0 | break; |
1735 | 5.44M | case COMP_REPLACE_CURR: |
1736 | | /* Replace specific compositor. */ |
1737 | 5.44M | code = dequeue_compositor(&pcomp_first, &pcomp_last, pcomp_opening); |
1738 | 5.44M | if (code < 0) |
1739 | 0 | goto out; |
1740 | 5.44M | enqueue_compositor(&pcomp_first, &pcomp_last, pcomp); |
1741 | 5.44M | free_compositor(pcomp_opening, mem); |
1742 | 5.44M | break; |
1743 | 30.0k | case COMP_DROP_QUEUE: |
1744 | | /* Annihilate the last compositors. */ |
1745 | 30.0k | enqueue_compositor(&pcomp_first, &pcomp_last, pcomp); |
1746 | 30.0k | code = drop_compositor_queue(&pcomp_first, &pcomp_last, pcomp_opening, mem, x0, y0, &gs_gstate); |
1747 | 30.0k | if (code < 0) |
1748 | 0 | goto out; |
1749 | 30.0k | break; |
1750 | 370k | case COMP_MARK_IDLE: |
1751 | | /* Mark as idle. */ |
1752 | 370k | enqueue_compositor(&pcomp_first, &pcomp_last, pcomp); |
1753 | 370k | mark_as_idle(pcomp_opening, pcomp); |
1754 | 20.5M | } |
1755 | 20.5M | } else if (is_null_compositor_op(cbp, &len)) { |
1756 | 14.6M | cbuf.ptr = cbp += len; |
1757 | 14.6M | } else if (cbp[0] == cmd_opv_end_page) { |
1758 | | /* End page, drop the queue. */ |
1759 | 357k | code = execute_compositor_queue(cdev, &target, &tdev, |
1760 | 357k | &gs_gstate, &pcomp_first, &pcomp_last, pcomp_first, x0, y0, mem, true); |
1761 | 357k | if (code < 0) |
1762 | 3 | goto out; |
1763 | 357k | break; |
1764 | 1.43M | } else if (pcomp_last != NULL && |
1765 | 1.43M | pcomp_last->type->procs.is_friendly(pcomp_last, cbp[0], cbp[1])) { |
1766 | | /* Immediately execute friendly commands |
1767 | | inside the compositor lookahead loop. |
1768 | | Currently there are few friendly commands for the pdf14 compositor only |
1769 | | due to the logic defined in c_pdf14trans_is_friendly. |
1770 | | This code duplicates some code portions from the main loop, |
1771 | | but we have no better idea with no slowdown to the main loop. |
1772 | | */ |
1773 | 313k | uint cb; |
1774 | | |
1775 | 313k | switch (*cbp++) { |
1776 | 171k | case cmd_opv_extend: |
1777 | 171k | switch (*cbp++) { |
1778 | 59.1k | case cmd_opv_ext_put_halftone: |
1779 | 59.1k | { |
1780 | 59.1k | uint ht_size; |
1781 | | |
1782 | 59.1k | enc_u_getw(ht_size, cbp); |
1783 | 59.1k | code = read_alloc_ht_buff(&ht_buff, ht_size, mem); |
1784 | 59.1k | if (code < 0) |
1785 | 0 | goto out; |
1786 | 59.1k | } |
1787 | 59.1k | break; |
1788 | 112k | case cmd_opv_ext_put_ht_seg: |
1789 | 112k | cbuf.ptr = cbp; |
1790 | 112k | code = read_ht_segment(&ht_buff, &cbuf, |
1791 | 112k | &gs_gstate, tdev, |
1792 | 112k | mem); |
1793 | 112k | cbp = cbuf.ptr; |
1794 | 112k | if (code < 0) |
1795 | 0 | goto out; |
1796 | 112k | break; |
1797 | 112k | default: |
1798 | 0 | code = gs_note_error(gs_error_unregistered); /* Must not happen. */ |
1799 | 0 | goto out; |
1800 | 171k | } |
1801 | 171k | break; |
1802 | 171k | case cmd_opv_set_misc: |
1803 | 141k | cb = *cbp++; |
1804 | 141k | switch (cb >> 6) { |
1805 | 141k | case cmd_set_misc_map >> 6: |
1806 | 141k | cbuf.ptr = cbp; |
1807 | 141k | code = read_set_misc_map(cb, &cbuf, &gs_gstate, mem); |
1808 | 141k | if (code < 0) |
1809 | 0 | goto out; |
1810 | 141k | cbp = cbuf.ptr; |
1811 | 141k | break; |
1812 | 0 | default: |
1813 | 0 | code = gs_note_error(gs_error_unregistered); /* Must not happen. */ |
1814 | 0 | goto out; |
1815 | 141k | } |
1816 | 141k | break; |
1817 | 141k | default: |
1818 | 0 | code = gs_note_error(gs_error_unregistered); /* Must not happen. */ |
1819 | 0 | goto out; |
1820 | 313k | } |
1821 | 1.12M | } else { |
1822 | | /* A drawing command, execute entire queue. */ |
1823 | 1.12M | code = execute_compositor_queue(cdev, &target, &tdev, |
1824 | 1.12M | &gs_gstate, &pcomp_first, &pcomp_last, pcomp_first, x0, y0, mem, false); |
1825 | 1.12M | if (code < 0) |
1826 | 0 | goto out; |
1827 | 1.12M | break; |
1828 | 1.12M | } |
1829 | 38.2M | } |
1830 | 1.48M | if (pcomp_last != NULL) { |
1831 | 0 | code = gs_note_error(gs_error_unregistered); |
1832 | 0 | goto out; |
1833 | 0 | } |
1834 | 1.48M | break; |
1835 | 1.48M | case cmd_opv_ext_put_halftone: |
1836 | 170k | { |
1837 | 170k | uint ht_size; |
1838 | | |
1839 | 170k | if_debug0m('L', mem, " ext_put_halftone\n"); |
1840 | 170k | enc_u_getw(ht_size, cbp); |
1841 | 170k | code = read_alloc_ht_buff(&ht_buff, ht_size, mem); |
1842 | 170k | if (code < 0) |
1843 | 0 | goto out; |
1844 | 170k | } |
1845 | 170k | break; |
1846 | 321k | case cmd_opv_ext_put_ht_seg: |
1847 | 321k | if_debug0m('L', mem, " ext_put_ht_seg\n"); |
1848 | 321k | cbuf.ptr = cbp; |
1849 | 321k | code = read_ht_segment(&ht_buff, &cbuf, |
1850 | 321k | &gs_gstate, tdev, |
1851 | 321k | mem); |
1852 | 321k | cbp = cbuf.ptr; |
1853 | 321k | if (code < 0) |
1854 | 0 | goto out; |
1855 | 321k | break; |
1856 | 321k | case cmd_opv_ext_set_color_is_devn: |
1857 | 0 | state.color_is_devn = true; |
1858 | 0 | if_debug0m('L', mem, " ext_set_color_is_devn\n"); |
1859 | 0 | break; |
1860 | 0 | case cmd_opv_ext_unset_color_is_devn: |
1861 | 0 | state.color_is_devn = false; |
1862 | 0 | if_debug0m('L', mem, " ext_unset_color_is_devn\n"); |
1863 | 0 | break; |
1864 | 0 | case cmd_opv_ext_tile_rect_hl: |
1865 | | /* Strip tile with devn colors */ |
1866 | 0 | cbp = cmd_read_rect(op & 0xf0, &state.rect, cbp); |
1867 | 0 | if_debug4m('L', mem, " x=%d y=%d w=%d h=%d\n", |
1868 | 0 | state.rect.x, state.rect.y, |
1869 | 0 | state.rect.width,state.rect.height); |
1870 | 0 | code = (*dev_proc(tdev, strip_tile_rect_devn)) |
1871 | 0 | (tdev, &state_tile, |
1872 | 0 | state.rect.x - x0, state.rect.y - y0, |
1873 | 0 | state.rect.width, state.rect.height, |
1874 | 0 | &(state.tile_color_devn[0]), |
1875 | 0 | &(state.tile_color_devn[1]), |
1876 | 0 | tile_phase.x, tile_phase.y); |
1877 | 0 | break; |
1878 | 7.83M | case cmd_opv_ext_put_fill_dcolor: |
1879 | 7.83M | pdcolor = &fill_color; |
1880 | 7.83M | goto load_dcolor; |
1881 | 326k | case cmd_opv_ext_put_stroke_dcolor: |
1882 | 326k | pdcolor = &stroke_color; |
1883 | 326k | goto load_dcolor; |
1884 | 0 | case cmd_opv_ext_put_tile_devn_color0: |
1885 | 0 | pdcolor = &set_dev_colors[0]; |
1886 | 0 | goto load_dcolor; |
1887 | 0 | case cmd_opv_ext_put_tile_devn_color1: |
1888 | 0 | pdcolor = &set_dev_colors[1]; |
1889 | 8.15M | load_dcolor:{ |
1890 | 8.15M | uint color_size; |
1891 | 8.15M | int left, offset, l; |
1892 | 8.15M | const gx_device_color_type_t * pdct; |
1893 | 8.15M | byte type_and_flag = *cbp++; |
1894 | 8.15M | byte is_continuation = type_and_flag & 0x80; |
1895 | | |
1896 | 8.15M | if_debug0m('L', mem, " cmd_opv_ext_put_drawing_color\n"); |
1897 | 8.15M | pdct = gx_get_dc_type_from_index(type_and_flag & 0x7F); |
1898 | 8.15M | if (pdct == 0) { |
1899 | 0 | code = gs_note_error(gs_error_rangecheck); |
1900 | 0 | goto out; |
1901 | 0 | } |
1902 | 8.15M | offset = 0; |
1903 | 8.15M | if (is_continuation) |
1904 | 8.15M | enc_u_getw(offset, cbp); |
1905 | 8.15M | enc_u_getw(color_size, cbp); |
1906 | 8.15M | left = color_size; |
1907 | 8.15M | if (!left) { |
1908 | | /* We still need to call pdct->read because it may change dev_color.type - |
1909 | | see gx_dc_null_read.*/ |
1910 | 44.4k | code = pdct->read(pdcolor, &gs_gstate, |
1911 | 44.4k | pdcolor, tdev, offset, |
1912 | 44.4k | cbp, 0, mem, x0, y0); |
1913 | 44.4k | if (code < 0) |
1914 | 0 | goto out; |
1915 | 44.4k | } |
1916 | 20.3M | while (left) { |
1917 | 12.1M | if (cbuf.warn_limit - cbp < (int)left) { /* cbp can be past warn_limit */ |
1918 | 4.28M | code = top_up_cbuf(&cbuf, &cbp); |
1919 | 4.28M | if (code < 0) |
1920 | 0 | goto top_up_failed; |
1921 | 4.28M | } |
1922 | 12.1M | l = min(left, cbuf.end - cbp); |
1923 | 12.1M | code = pdct->read(pdcolor, &gs_gstate, |
1924 | 12.1M | pdcolor, tdev, offset, |
1925 | 12.1M | cbp, l, mem, x0, y0); |
1926 | 12.1M | if (code < 0) |
1927 | 0 | goto out; |
1928 | 12.1M | l = code; |
1929 | 12.1M | cbp += l; |
1930 | 12.1M | offset += l; |
1931 | 12.1M | left -= l; |
1932 | 12.1M | } |
1933 | 8.15M | code = gx_color_load(pdcolor, &gs_gstate, |
1934 | 8.15M | tdev); |
1935 | 8.15M | if (code < 0) |
1936 | 0 | goto out; |
1937 | 8.15M | } |
1938 | 8.15M | break; |
1939 | 8.15M | default: |
1940 | 0 | goto bad_op; |
1941 | 10.1M | } |
1942 | 10.1M | break; |
1943 | 10.1M | default: |
1944 | 0 | goto bad_op; |
1945 | 15.6M | } |
1946 | 12.0M | continue; |
1947 | 15.3M | case cmd_op_segment >> 4: |
1948 | 15.3M | { |
1949 | 15.3M | int i; |
1950 | 15.3M | static const byte op_num_operands[] = { |
1951 | 15.3M | cmd_segment_op_num_operands_values |
1952 | 15.3M | }; |
1953 | 15.3M | rgapto: |
1954 | 15.3M | if (!in_path) { |
1955 | 2.34M | ppos.x = int2fixed(state.rect.x); |
1956 | 2.34M | ppos.y = int2fixed(state.rect.y); |
1957 | 2.34M | if_debug2m('L', mem, " (%d,%d)", state.rect.x, |
1958 | 2.34M | state.rect.y); |
1959 | 2.34M | notes = sn_none; |
1960 | 2.34M | in_path = true; |
1961 | 2.34M | } |
1962 | 40.5M | for (i = 0; i < op_num_operands[op & 0xf]; ++i) { |
1963 | 25.1M | fixed v; |
1964 | 25.1M | int b = *cbp; |
1965 | | |
1966 | 25.1M | switch (b >> 5) { |
1967 | 7.81M | case 0: |
1968 | 14.5M | case 1: |
1969 | 14.5M | vs[i++] = |
1970 | 14.5M | ((fixed) ((b ^ 0x20) - 0x20) << 13) + |
1971 | 14.5M | ((int)cbp[1] << 5) + (cbp[2] >> 3); |
1972 | 14.5M | if_debug1m('L', mem, " %g", fixed2float(vs[i - 1])); |
1973 | 14.5M | cbp += 2; |
1974 | 14.5M | v = (int)((*cbp & 7) ^ 4) - 4; |
1975 | 14.5M | break; |
1976 | 3.76M | case 2: |
1977 | 7.44M | case 3: |
1978 | 7.44M | v = (b ^ 0x60) - 0x20; |
1979 | 7.44M | break; |
1980 | 674k | case 4: |
1981 | 1.10M | case 5: |
1982 | | /* |
1983 | | * Without the following cast, C's |
1984 | | * brain-damaged coercion rules cause the |
1985 | | * result to be considered unsigned, and not |
1986 | | * sign-extended on machines where |
1987 | | * sizeof(long) > sizeof(int). |
1988 | | */ |
1989 | 1.10M | v = (((b ^ 0xa0) - 0x20) << 8) + (int)*++cbp; |
1990 | 1.10M | break; |
1991 | 1.55M | case 6: |
1992 | 1.55M | v = (b ^ 0xd0) - 0x10; |
1993 | 1.55M | vs[i] = |
1994 | 1.55M | ((v << 8) + cbp[1]) << (_fixed_shift - 2); |
1995 | 1.55M | if_debug1m('L', mem, " %g", fixed2float(vs[i])); |
1996 | 1.55M | cbp += 2; |
1997 | 1.55M | continue; |
1998 | 462k | default /*case 7 */ : |
1999 | 462k | v = (int)(*++cbp ^ 0x80) - 0x80; |
2000 | 925k | for (b = 0; b < sizeof(fixed) - 3; ++b) |
2001 | 462k | v = (v << 8) + *++cbp; |
2002 | 462k | break; |
2003 | 25.1M | } |
2004 | 23.6M | cbp += 3; |
2005 | | /* Absent the cast in the next statement, */ |
2006 | | /* the Borland C++ 4.5 compiler incorrectly */ |
2007 | | /* sign-extends the result of the shift. */ |
2008 | 23.6M | vs[i] = (v << 16) + (uint) (cbp[-2] << 8) + cbp[-1]; |
2009 | 23.6M | if_debug1m('L', mem, " %g", fixed2float(vs[i])); |
2010 | 23.6M | } |
2011 | 15.3M | if_debug0m('L', mem, "\n"); |
2012 | 15.3M | code = clist_decode_segment(&path, op, vs, &ppos, |
2013 | 15.3M | x0, y0, notes); |
2014 | 15.3M | if (code < 0) |
2015 | 0 | goto out; |
2016 | 15.3M | } |
2017 | 15.3M | continue; |
2018 | 42.8M | case cmd_op_path >> 4: |
2019 | 42.8M | if (op == cmd_opv_rgapto) |
2020 | 0 | goto rgapto; |
2021 | 42.8M | else if (op == cmd_opv_lock_pattern) { |
2022 | 719 | gs_id id; |
2023 | 719 | int lock = *cbp++; |
2024 | 719 | cmd_get_value(id, cbp); |
2025 | 719 | if_debug2m('L', mem, "id=0x%lx, lock=%d\n", id, lock); |
2026 | | /* We currently lock the pattern in all the bands, even in ones |
2027 | | * where we haven't used the pattern. This can cause the following |
2028 | | * call to return with 'undefined' because the pattern is not |
2029 | | * found. Just swallow this error and continue. */ |
2030 | 719 | code = gx_pattern_cache_entry_set_lock(&gs_gstate, id, lock); |
2031 | 719 | if (code == gs_error_undefined) |
2032 | 0 | code = 0; |
2033 | 719 | if (code < 0) |
2034 | 0 | goto out; |
2035 | 719 | continue; |
2036 | 42.8M | } else { |
2037 | 42.8M | gx_path fpath; |
2038 | 42.8M | gx_path *ppath = &path; |
2039 | | |
2040 | 42.8M | if_debug0m('L', mem, "\n"); |
2041 | | /* if in clip, flatten path first */ |
2042 | 42.8M | if (in_clip) { |
2043 | 257k | gx_path_init_local(&fpath, mem); |
2044 | 257k | code = gx_path_add_flattened_accurate(&path, &fpath, |
2045 | 257k | gs_currentflat_inline(&gs_gstate), |
2046 | 257k | gs_gstate.accurate_curves); |
2047 | 257k | if (code < 0) |
2048 | 0 | goto out; |
2049 | 257k | ppath = &fpath; |
2050 | 257k | } |
2051 | 42.8M | switch (op) { |
2052 | 1.76M | case cmd_opv_fill: |
2053 | 1.76M | fill_params.rule = gx_rule_winding_number; |
2054 | 1.76M | goto fill; |
2055 | 52.6k | case cmd_opv_eofill: |
2056 | 52.6k | fill_params.rule = gx_rule_even_odd; |
2057 | 1.82M | fill: |
2058 | 1.82M | fill_params.adjust = gs_gstate.fill_adjust; |
2059 | 1.82M | fill_params.flatness = gs_gstate.flatness; |
2060 | 1.82M | code = (*dev_proc(tdev, fill_path))(tdev, &gs_gstate, ppath, |
2061 | 1.82M | &fill_params, &fill_color, pcpath); |
2062 | 1.82M | break; |
2063 | 35.2k | case cmd_opv_fill_stroke: |
2064 | 35.2k | fill_params.rule = gx_rule_winding_number; |
2065 | 35.2k | goto fill_stroke; |
2066 | 2.25k | case cmd_opv_eofill_stroke: |
2067 | 2.25k | fill_params.rule = gx_rule_even_odd; |
2068 | 37.4k | fill_stroke: |
2069 | 37.4k | fill_params.adjust = gs_gstate.fill_adjust; |
2070 | 37.4k | fill_params.flatness = gs_gstate.flatness; |
2071 | 37.4k | stroke_params.flatness = gs_gstate.flatness; |
2072 | 37.4k | stroke_params.traditional = false; |
2073 | 37.4k | code = (*dev_proc(tdev, fill_stroke_path))(tdev, &gs_gstate, ppath, |
2074 | 37.4k | &fill_params, &fill_color, |
2075 | 37.4k | &stroke_params, &stroke_color, pcpath); |
2076 | 37.4k | break; |
2077 | 734k | case cmd_opv_stroke: |
2078 | 734k | stroke_params.flatness = gs_gstate.flatness; |
2079 | 734k | stroke_params.traditional = false; |
2080 | 734k | code = (*dev_proc(tdev, stroke_path)) |
2081 | 734k | (tdev, &gs_gstate, |
2082 | 734k | ppath, &stroke_params, |
2083 | 734k | &stroke_color, pcpath); |
2084 | 734k | break; |
2085 | 144k | case cmd_opv_polyfill: |
2086 | 144k | code = clist_do_polyfill(tdev, ppath, &fill_color, |
2087 | 144k | gs_gstate.log_op); |
2088 | 144k | break; |
2089 | 40.1M | case cmd_opv_fill_trapezoid: |
2090 | 40.1M | { |
2091 | 40.1M | gs_fixed_edge left, right; |
2092 | 40.1M | fixed ybot, ytop; |
2093 | 40.1M | int options, swap_axes, wh; |
2094 | 40.1M | fixed x0f; |
2095 | 40.1M | fixed y0f; |
2096 | 40.1M | gx_device *ttdev = tdev; |
2097 | | |
2098 | 40.1M | if (pcpath != NULL && !clipper_dev_open) { |
2099 | 463 | gx_make_clip_device_on_stack(&clipper_dev, pcpath, tdev); |
2100 | 463 | clipper_dev_open = true; |
2101 | 463 | } |
2102 | 40.1M | if (clipper_dev_open) |
2103 | 39.0M | ttdev = (gx_device *)&clipper_dev; |
2104 | | /* Note that if we have transparency present, the clipper device may need to have |
2105 | | its color information updated to be synced up with the target device. |
2106 | | This can occur if we had fills of a path first with a transparency mask to get |
2107 | | an XPS opacity followed by a fill with a transparency group. This occurs in |
2108 | | the XPS gradient code */ |
2109 | 40.1M | if (tdev->color_info.num_components != ttdev->color_info.num_components){ |
2110 | | /* Reset the clipper device color information. Only worry about |
2111 | | the information that is used in the trap code */ |
2112 | 0 | ttdev->color_info.num_components = tdev->color_info.num_components; |
2113 | 0 | ttdev->color_info.depth = tdev->color_info.depth; |
2114 | 0 | ttdev->color_info.polarity = tdev->color_info.polarity; |
2115 | 0 | memcpy(&(ttdev->color_info.comp_bits),&(tdev->color_info.comp_bits),GX_DEVICE_COLOR_MAX_COMPONENTS); |
2116 | 0 | memcpy(&(ttdev->color_info.comp_shift),&(tdev->color_info.comp_shift),GX_DEVICE_COLOR_MAX_COMPONENTS); |
2117 | 0 | } |
2118 | 40.1M | cmd_getw(left.start.x, cbp); |
2119 | 40.1M | cmd_getw(left.start.y, cbp); |
2120 | 40.1M | cmd_getw(left.end.x, cbp); |
2121 | 40.1M | cmd_getw(left.end.y, cbp); |
2122 | 40.1M | cmd_getw(right.start.x, cbp); |
2123 | 40.1M | cmd_getw(right.start.y, cbp); |
2124 | 40.1M | cmd_getw(right.end.x, cbp); |
2125 | 40.1M | cmd_getw(right.end.y, cbp); |
2126 | 40.1M | cmd_getw(options, cbp); |
2127 | 40.1M | if (!(options & 4)) { |
2128 | 40.1M | cmd_getw(ybot, cbp); |
2129 | 40.1M | cmd_getw(ytop, cbp); |
2130 | 40.1M | } else |
2131 | 1.16k | ytop = ybot = 0; /* Unused, but quiet gcc warning. */ |
2132 | 40.1M | swap_axes = options & 1; |
2133 | 40.1M | wh = swap_axes ? tdev->width : tdev->height; |
2134 | 40.1M | x0f = int2fixed(swap_axes ? y0 : x0); |
2135 | 40.1M | y0f = int2fixed(swap_axes ? x0 : y0); |
2136 | 40.1M | left.start.x -= x0f; |
2137 | 40.1M | left.start.y -= y0f; |
2138 | 40.1M | left.end.x -= x0f; |
2139 | 40.1M | left.end.y -= y0f; |
2140 | 40.1M | right.start.x -= x0f; |
2141 | 40.1M | right.start.y -= y0f; |
2142 | 40.1M | right.end.x -= x0f; |
2143 | 40.1M | right.end.y -= y0f; |
2144 | 40.1M | if (options & 2) { |
2145 | 3.96k | uchar num_components = tdev->color_info.num_components; |
2146 | 3.96k | frac31 c[4][GX_DEVICE_COLOR_MAX_COMPONENTS], *cc[4]; |
2147 | 3.96k | byte colors_mask, i, j, m = 1; |
2148 | 3.96k | gs_fill_attributes fa; |
2149 | 3.96k | gs_fixed_rect clip; |
2150 | 3.96k | fixed hh = int2fixed(swap_axes ? target->width : target->height); |
2151 | | |
2152 | 3.96k | if (cbuf.end - cbp < 5 * cmd_max_intsize(sizeof(frac31))) { |
2153 | 5 | code = top_up_cbuf(&cbuf, &cbp); |
2154 | 5 | if (code < 0) |
2155 | 0 | goto top_up_failed; |
2156 | 5 | } |
2157 | 3.96k | cmd_getw(clip.p.x, cbp); |
2158 | 3.96k | cmd_getw(clip.p.y, cbp); |
2159 | 3.96k | cmd_getw(clip.q.x, cbp); |
2160 | 3.96k | cmd_getw(clip.q.y, cbp); |
2161 | 3.96k | clip.p.x -= x0f; |
2162 | 3.96k | clip.p.y -= y0f; |
2163 | 3.96k | clip.q.x -= x0f; |
2164 | 3.96k | clip.q.y -= y0f; |
2165 | 3.96k | if (clip.p.y < 0) |
2166 | 5 | clip.p.y = 0; |
2167 | 3.96k | if (clip.q.y > hh) |
2168 | 140 | clip.q.y = hh; |
2169 | 3.96k | fa.clip = &clip; |
2170 | 3.96k | fa.swap_axes = swap_axes; |
2171 | 3.96k | fa.ht = NULL; |
2172 | 3.96k | fa.lop = lop_default; /* fgixme: gs_gstate.log_op; */ |
2173 | 3.96k | fa.ystart = ybot - y0f; |
2174 | 3.96k | fa.yend = ytop - y0f; |
2175 | 3.96k | cmd_getw(colors_mask, cbp); |
2176 | 19.8k | for (i = 0; i < 4; i++, m <<= 1) { |
2177 | 15.8k | if (colors_mask & m) { |
2178 | 9.10k | if (cbuf.end - cbp < num_components * cmd_max_intsize(sizeof(frac31))) { |
2179 | 18 | code = top_up_cbuf(&cbuf, &cbp); |
2180 | 18 | if (code < 0) |
2181 | 0 | goto top_up_failed; |
2182 | 18 | } |
2183 | 9.10k | cc[i] = c[i]; |
2184 | 45.4k | for (j = 0; j < num_components; j++) |
2185 | 36.3k | cmd_getfrac(c[i][j], cbp); |
2186 | 9.10k | } else |
2187 | 6.77k | cc[i] = NULL; |
2188 | 15.8k | } |
2189 | 3.96k | if (options & 4) { |
2190 | 1.16k | # if 1 /* Disable to debug gx_fill_triangle_small. */ |
2191 | 1.16k | code = dev_proc(ttdev, fill_linear_color_triangle)(ttdev, &fa, |
2192 | 1.16k | &left.start, &left.end, &right.start, |
2193 | 1.16k | cc[0], cc[1], cc[2]); |
2194 | | # else |
2195 | | code = 0; |
2196 | | # endif |
2197 | 1.16k | if (code == 0) { |
2198 | | /* The target device didn't fill the trapezoid and |
2199 | | requests a decomposition. Subdivide into smaller triangles : */ |
2200 | 0 | if (pfs.dev == NULL) |
2201 | 0 | code = gx_init_patch_fill_state_for_clist(tdev, &pfs, mem); |
2202 | 0 | if (code >= 0) { |
2203 | 0 | pfs.dev = ttdev; |
2204 | 0 | pfs.rect = clip; /* fixme: eliminate 'clip'. */ |
2205 | 0 | fa.pfs = &pfs; |
2206 | 0 | code = gx_fill_triangle_small(ttdev, &fa, |
2207 | 0 | &left.start, &left.end, &right.start, |
2208 | 0 | cc[0], cc[1], cc[2]); |
2209 | 0 | } |
2210 | 0 | } |
2211 | 2.80k | } else { |
2212 | 2.80k | code = dev_proc(ttdev, fill_linear_color_trapezoid)(ttdev, &fa, |
2213 | 2.80k | &left.start, &left.end, &right.start, &right.end, |
2214 | 2.80k | cc[0], cc[1], cc[2], cc[3]); |
2215 | 2.80k | if (code == 0) { |
2216 | | /* Fixme : The target device didn't fill the trapezoid and |
2217 | | requests a decomposition. |
2218 | | Currently we never call it with 4 colors (see gxshade6.c) |
2219 | | and 2 colors must not return 0 - see comment to |
2220 | | dev_t_proc_fill_linear_color_trapezoid in gxdevcli.c . |
2221 | | Must not happen. */ |
2222 | 0 | code = gs_note_error(gs_error_unregistered); |
2223 | 0 | } |
2224 | 2.80k | } |
2225 | 3.96k | } else |
2226 | 40.1M | code = gx_default_fill_trapezoid(ttdev, &left, &right, |
2227 | 40.1M | max(ybot - y0f, fixed_half), |
2228 | 40.1M | min(ytop - y0f, int2fixed(wh)), swap_axes, |
2229 | 40.1M | &fill_color, gs_gstate.log_op); |
2230 | 40.1M | } |
2231 | 40.1M | break; |
2232 | 40.1M | default: |
2233 | 0 | goto bad_op; |
2234 | 42.8M | } |
2235 | 42.8M | if (ppath != &path) |
2236 | 257k | gx_path_free(ppath, "clist_render_band"); |
2237 | 42.8M | } |
2238 | 42.8M | if (in_path) { /* path might be empty! */ |
2239 | 2.34M | state.rect.x = fixed2int_var(ppos.x); |
2240 | 2.34M | state.rect.y = fixed2int_var(ppos.y); |
2241 | 2.34M | in_path = false; |
2242 | 2.34M | } |
2243 | 42.8M | gx_path_free(&path, "clist_render_band"); |
2244 | 42.8M | gx_path_init_local(&path, mem); |
2245 | 42.8M | if (code < 0) |
2246 | 0 | goto out; |
2247 | 42.8M | continue; |
2248 | 42.8M | default: |
2249 | 0 | bad_op:mlprintf5(mem, "Bad op %02x band y0 = %d file pos %"PRId64" buf pos %d/%d\n", |
2250 | 0 | op, y0, stell(s), (int)(cbp - cbuf.data), (int)(cbuf.end - cbuf.data)); |
2251 | 0 | { |
2252 | 0 | const byte *pp; |
2253 | |
|
2254 | 0 | for (pp = cbuf.data; pp < cbuf.end; pp += 10) { |
2255 | 0 | dmlprintf1(mem, "%4d:", (int)(pp - cbuf.data)); |
2256 | 0 | dmprintf10(mem, " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", |
2257 | 0 | pp[0], pp[1], pp[2], pp[3], pp[4], |
2258 | 0 | pp[5], pp[6], pp[7], pp[8], pp[9]); |
2259 | 0 | } |
2260 | 0 | } |
2261 | 0 | code = gs_note_error(gs_error_Fatal); |
2262 | 0 | goto out; |
2263 | 140M | } |
2264 | 140M | if_debug4m('L', mem, " x=%d y=%d w=%d h=%d\n", |
2265 | 35.2M | state.rect.x, state.rect.y, state.rect.width, |
2266 | 35.2M | state.rect.height); |
2267 | 35.2M | switch (op >> 4) { |
2268 | 1.49M | case cmd_op_fill_rect >> 4: |
2269 | 1.49M | if (state.rect.width == 0 && state.rect.height == 0 && |
2270 | 1.49M | state.rect.x == 0 && state.rect.y == 0) { |
2271 | | /* FIXME: This test should be unnecessary. Bug 692076 |
2272 | | * is open pending a proper fix. */ |
2273 | 641k | code = (dev_proc(tdev, fillpage) == NULL ? 0 : |
2274 | 641k | (*dev_proc(tdev, fillpage))(tdev, &gs_gstate, |
2275 | 641k | &fill_color)); |
2276 | 641k | break; |
2277 | 641k | } |
2278 | 3.25M | case cmd_op_fill_rect_short >> 4: |
2279 | 23.7M | case cmd_op_fill_rect_tiny >> 4: |
2280 | 23.7M | if (!state.lop_enabled) { |
2281 | 23.7M | code = (*dev_proc(tdev, fill_rectangle)) |
2282 | 23.7M | (tdev, state.rect.x - x0, state.rect.y - y0, |
2283 | 23.7M | state.rect.width, state.rect.height, |
2284 | 23.7M | state.colors[1]); |
2285 | 23.7M | break; |
2286 | 23.7M | } |
2287 | 0 | source = NULL; |
2288 | 0 | data_x = 0; |
2289 | 0 | raster = 0; |
2290 | 0 | colors[0] = colors[1] = state.colors[1]; |
2291 | 0 | log_op = state.lop; |
2292 | 0 | pcolor = colors; |
2293 | 0 | do_rop:code = (*dev_proc(tdev, strip_copy_rop2)) |
2294 | 0 | (tdev, source, data_x, raster, gx_no_bitmap_id, |
2295 | 0 | pcolor, &state_tile, |
2296 | 0 | (state.tile_colors[0] == gx_no_color_index && |
2297 | 0 | state.tile_colors[1] == gx_no_color_index ? |
2298 | 0 | NULL : state.tile_colors), |
2299 | 0 | state.rect.x - x0, state.rect.y - y0, |
2300 | 0 | state.rect.width - data_x, state.rect.height, |
2301 | 0 | tile_phase.x, tile_phase.y, log_op, |
2302 | 0 | plane_height); |
2303 | 0 | plane_height = 0; |
2304 | 0 | data_x = 0; |
2305 | 0 | break; |
2306 | 37.4k | case cmd_op_tile_rect >> 4: |
2307 | 37.4k | if (state.rect.width == 0 && state.rect.height == 0 && |
2308 | 37.4k | state.rect.x == 0 && state.rect.y == 0) { |
2309 | 0 | code = (*dev_proc(tdev, fillpage))(tdev, &gs_gstate, &fill_color); |
2310 | 0 | break; |
2311 | 0 | } |
2312 | 232k | case cmd_op_tile_rect_short >> 4: |
2313 | 567k | case cmd_op_tile_rect_tiny >> 4: |
2314 | | /* Currently we don't use lop with strip_tile_rectangle. */ |
2315 | 567k | code = (*dev_proc(tdev, strip_tile_rectangle)) |
2316 | 567k | (tdev, &state_tile, |
2317 | 567k | state.rect.x - x0, state.rect.y - y0, |
2318 | 567k | state.rect.width, state.rect.height, |
2319 | 567k | state.tile_colors[0], state.tile_colors[1], |
2320 | 567k | tile_phase.x, tile_phase.y); |
2321 | 567k | break; |
2322 | 9.20M | case cmd_op_copy_mono_planes >> 4: |
2323 | 9.20M | if (state.lop_enabled) { |
2324 | 0 | pcolor = state.colors; |
2325 | 0 | log_op = state.lop; |
2326 | 0 | goto do_rop; |
2327 | 0 | } |
2328 | 9.20M | if ((op & cmd_copy_use_tile) || pcpath != NULL) { /* |
2329 | | * This call of copy_mono originated as a call |
2330 | | * of fill_mask. |
2331 | | */ |
2332 | 9.11M | code = gx_image_fill_masked |
2333 | 9.11M | (tdev, source, data_x, raster, gx_no_bitmap_id, |
2334 | 9.11M | state.rect.x - x0, state.rect.y - y0, |
2335 | 9.11M | state.rect.width - data_x, state.rect.height, |
2336 | 9.11M | &fill_color, 1, gs_gstate.log_op, pcpath); |
2337 | 9.11M | } else { |
2338 | 83.7k | if (plane_height == 0) { |
2339 | 83.7k | code = (*dev_proc(tdev, copy_mono)) |
2340 | 83.7k | (tdev, source, data_x, raster, gx_no_bitmap_id, |
2341 | 83.7k | state.rect.x - x0, state.rect.y - y0, |
2342 | 83.7k | state.rect.width - data_x, state.rect.height, |
2343 | 83.7k | state.colors[0], state.colors[1]); |
2344 | 83.7k | } else { |
2345 | 0 | code = (*dev_proc(tdev, copy_planes)) |
2346 | 0 | (tdev, source, data_x, raster, gx_no_bitmap_id, |
2347 | 0 | state.rect.x - x0, state.rect.y - y0, |
2348 | 0 | state.rect.width - data_x, state.rect.height, |
2349 | 0 | plane_height); |
2350 | 0 | } |
2351 | 83.7k | } |
2352 | 9.20M | plane_height = 0; |
2353 | 9.20M | data_x = 0; |
2354 | 9.20M | break; |
2355 | 1.13M | case cmd_op_copy_color_alpha >> 4: |
2356 | 1.13M | if (state.color_is_alpha) { |
2357 | | /****** CAN'T DO ROP WITH ALPHA ******/ |
2358 | 0 | if (state.color_is_devn && |
2359 | 0 | dev_proc(tdev, copy_alpha_hl_color) != gx_default_no_copy_alpha_hl_color) { /* FIXME */ |
2360 | 0 | code = (*dev_proc(tdev, copy_alpha_hl_color)) |
2361 | 0 | (tdev, source, data_x, raster, gx_no_bitmap_id, |
2362 | 0 | state.rect.x - x0, state.rect.y - y0, |
2363 | 0 | state.rect.width - data_x, state.rect.height, |
2364 | 0 | &fill_color, depth); |
2365 | 0 | } else { |
2366 | 0 | code = (*dev_proc(tdev, copy_alpha)) |
2367 | 0 | (tdev, source, data_x, raster, gx_no_bitmap_id, |
2368 | 0 | state.rect.x - x0, state.rect.y - y0, |
2369 | 0 | state.rect.width - data_x, state.rect.height, |
2370 | 0 | state.colors[1], depth); |
2371 | 0 | } |
2372 | 1.13M | } else { |
2373 | 1.13M | if (state.lop_enabled) { |
2374 | 0 | pcolor = NULL; |
2375 | 0 | log_op = state.lop; |
2376 | 0 | goto do_rop; |
2377 | 0 | } |
2378 | 1.13M | code = (*dev_proc(tdev, copy_color)) |
2379 | 1.13M | (tdev, source, data_x, raster, gx_no_bitmap_id, |
2380 | 1.13M | state.rect.x - x0, state.rect.y - y0, |
2381 | 1.13M | state.rect.width - data_x, state.rect.height); |
2382 | 1.13M | } |
2383 | 1.13M | data_x = 0; |
2384 | 1.13M | break; |
2385 | 0 | default: /* can't happen */ |
2386 | 0 | goto bad_op; |
2387 | 35.2M | } |
2388 | 35.2M | } |
2389 | | /* Clean up before we exit. */ |
2390 | 650k | out: |
2391 | 650k | if (ht_buff.pbuff != 0) { |
2392 | 0 | gs_free_object(mem, ht_buff.pbuff, "clist_playback_band(ht_buff)"); |
2393 | 0 | ht_buff.pbuff = 0; |
2394 | 0 | ht_buff.pcurr = 0; |
2395 | 0 | } |
2396 | 650k | ht_buff.ht_size = 0; |
2397 | 650k | ht_buff.read_size = 0; |
2398 | | |
2399 | 650k | if (pcomp_last != NULL) { |
2400 | 0 | int code1 = drop_compositor_queue(&pcomp_first, &pcomp_last, NULL, mem, x0, y0, &gs_gstate); |
2401 | |
|
2402 | 0 | if (code == 0) |
2403 | 0 | code = code1; |
2404 | 0 | } |
2405 | 650k | gx_cpath_free(&clip_path, "clist_render_band exit"); |
2406 | 650k | gx_path_free(&path, "clist_render_band exit"); |
2407 | 650k | if (gs_gstate.pattern_cache != NULL) { |
2408 | 9.78k | gx_pattern_cache_free(gs_gstate.pattern_cache); |
2409 | 9.78k | gs_gstate.pattern_cache = NULL; |
2410 | 9.78k | } |
2411 | | /* Free the client color and device colors allocated upon entry */ |
2412 | 650k | gs_free_object(mem, gs_gstate.color[0].ccolor, "clist_playback_band"); |
2413 | 650k | gs_free_object(mem, gs_gstate.color[1].ccolor, "clist_playback_band"); |
2414 | 650k | gs_free_object(mem, gs_gstate.color[0].dev_color, "clist_playback_band"); |
2415 | 650k | gs_free_object(mem, gs_gstate.color[1].dev_color, "clist_playback_band"); |
2416 | 650k | gs_gstate.color[0].ccolor = gs_gstate.color[1].ccolor = NULL; |
2417 | 650k | gs_gstate.color[0].dev_color = gs_gstate.color[1].dev_color = NULL; |
2418 | | |
2419 | | /* The imager state release will decrement the icc link cache. To avoid |
2420 | | race conditions lock the cache */ |
2421 | 650k | gx_monitor_enter(cdev->icc_cache_cl->lock); |
2422 | 650k | gs_gstate_release(&gs_gstate); |
2423 | 650k | gx_monitor_leave(cdev->icc_cache_cl->lock); /* done with increment, let everyone run */ |
2424 | 650k | gs_free_object(mem, data_bits, "clist_playback_band(data_bits)"); |
2425 | 650k | if (target != orig_target) { |
2426 | 253k | if (target->rc.ref_count != 1) { |
2427 | | /* This can occur if we are coming from a pattern clist that |
2428 | | includes transparency. In this case, we do not want to |
2429 | | free the compositor since it is really the main target that |
2430 | | we are tiling into. i.e. the tile itself does not have |
2431 | | a pdf14 device, but rather we push a trans group, draw and |
2432 | | then pop the group to properly blend */ |
2433 | 0 | rc_decrement(target, "gxclrast(target compositor)"); |
2434 | 253k | } else { |
2435 | | /* Ref count was 1. close the device and then free it */ |
2436 | 253k | if (target->is_open) |
2437 | 46 | dev_proc(target, close_device)(target); |
2438 | 253k | gs_free_object(target->memory, target, "gxclrast discard compositor"); |
2439 | 253k | } |
2440 | 253k | target = orig_target; |
2441 | 253k | } |
2442 | 650k | if (code < 0) { |
2443 | 11 | if (pfs.dev != NULL) |
2444 | 0 | term_patch_fill_state(&pfs); |
2445 | 11 | rc_decrement(gs_gstate.color[0].color_space, "clist_playback_band"); |
2446 | 11 | rc_decrement(gs_gstate.color[1].color_space, "clist_playback_band"); |
2447 | 11 | gs_free_object(mem, cbuf_storage, "clist_playback_band(cbuf_storage)"); |
2448 | 11 | gx_cpath_free(&clip_path, "clist_playback_band"); |
2449 | 11 | if (pcpath != &clip_path) |
2450 | 10 | gx_cpath_free(pcpath, "clist_playback_band"); |
2451 | 11 | return_error(code); |
2452 | 11 | } |
2453 | | /* Check whether we have more pages to process. */ |
2454 | 650k | if ((playback_action != playback_action_setup && |
2455 | 650k | (cbp < cbuf.end || !seofp(s)) && (op != cmd_opv_end_page) ) |
2456 | 650k | ) |
2457 | 0 | goto in; |
2458 | 650k | if (pfs.dev != NULL) |
2459 | 0 | term_patch_fill_state(&pfs); |
2460 | 650k | rc_decrement(gs_gstate.color[0].color_space, "clist_playback_band"); |
2461 | 650k | rc_decrement(gs_gstate.color[1].color_space, "clist_playback_band"); |
2462 | 650k | gs_free_object(mem, cbuf_storage, "clist_playback_band(cbuf_storage)"); |
2463 | 650k | gx_cpath_free(&clip_path, "clist_playback_band"); |
2464 | 650k | if (pcpath != &clip_path) |
2465 | 567k | gx_cpath_free(pcpath, "clist_playback_band"); |
2466 | 650k | return code; |
2467 | 0 | top_up_failed: |
2468 | 0 | gx_cpath_free(&clip_path, "clist_playback_band"); |
2469 | 0 | if (pcpath != &clip_path) |
2470 | 0 | gx_cpath_free(pcpath, "clist_playback_band"); |
2471 | 0 | return code; |
2472 | 650k | } |
2473 | | |
2474 | | /* ---------------- Individual commands ---------------- */ |
2475 | | |
2476 | | /* |
2477 | | * These single-use procedures implement a few large individual commands, |
2478 | | * primarily for readability but also to avoid overflowing compilers' |
2479 | | * optimization limits. They all take the command buffer as their first |
2480 | | * parameter (pcb), assume that the current buffer pointer is in pcb->ptr, |
2481 | | * and update it there. |
2482 | | */ |
2483 | | |
2484 | | static int |
2485 | | read_set_tile_size(command_buf_t *pcb, tile_slot *bits, bool for_pattern) |
2486 | 1.24k | { |
2487 | 1.24k | const byte *cbp = pcb->ptr; |
2488 | 1.24k | uint rep_width, rep_height; |
2489 | 1.24k | uint pdepth; |
2490 | 1.24k | byte bd = *cbp++; |
2491 | | |
2492 | 1.24k | bits->head.depth = cmd_code_to_depth(bd); |
2493 | 1.24k | if (for_pattern) |
2494 | 1.24k | cmd_getw(bits->id, cbp); |
2495 | 1.24k | cmd_getw(rep_width, cbp); |
2496 | 1.24k | cmd_getw(rep_height, cbp); |
2497 | 1.24k | if (bd & 0x20) { |
2498 | 1.24k | cmd_getw(bits->x_reps, cbp); |
2499 | 1.24k | bits->width = rep_width * bits->x_reps; |
2500 | 1.24k | } else { |
2501 | 0 | bits->x_reps = 1; |
2502 | 0 | bits->width = rep_width; |
2503 | 0 | } |
2504 | 1.24k | if (bd & 0x40) { |
2505 | 472 | cmd_getw(bits->y_reps, cbp); |
2506 | 472 | bits->height = rep_height * bits->y_reps; |
2507 | 768 | } else { |
2508 | 768 | bits->y_reps = 1; |
2509 | 768 | bits->height = rep_height; |
2510 | 768 | } |
2511 | 1.24k | if (bd & 0x80) |
2512 | 1.24k | cmd_getw(bits->rep_shift, cbp); |
2513 | 1.24k | else |
2514 | 1.24k | bits->rep_shift = 0; |
2515 | 1.24k | if (bd & 0x10) |
2516 | 0 | bits->num_planes = *cbp++; |
2517 | 1.24k | else |
2518 | 1.24k | bits->num_planes = 1; |
2519 | 1.24k | if_debug7('L', " depth=%d size=(%d,%d), rep_size=(%d,%d), rep_shift=%d, num_planes=%d\n", |
2520 | 1.24k | bits->head.depth, bits->width, |
2521 | 1.24k | bits->height, rep_width, |
2522 | 1.24k | rep_height, bits->rep_shift, bits->num_planes); |
2523 | 1.24k | bits->shift = |
2524 | 1.24k | (bits->rep_shift == 0 ? 0 : |
2525 | 1.24k | (bits->rep_shift * (bits->height / rep_height)) % rep_width); |
2526 | 1.24k | pdepth = bits->head.depth; |
2527 | 1.24k | if (bits->num_planes != 1) |
2528 | 0 | pdepth /= bits->num_planes; |
2529 | 1.24k | bits->raster = bitmap_raster(bits->width * pdepth); |
2530 | 1.24k | pcb->ptr = cbp; |
2531 | 1.24k | return 0; |
2532 | 1.24k | } |
2533 | | |
2534 | | static int |
2535 | | read_set_bits(command_buf_t *pcb, tile_slot *bits, int compress, |
2536 | | gx_clist_state *pcls, gx_strip_bitmap *tile, tile_slot **pslot, |
2537 | | gx_device_clist_reader *cdev, gs_memory_t *mem) |
2538 | 3.03M | { |
2539 | 3.03M | const byte *cbp = pcb->ptr; |
2540 | 3.03M | uint rep_width = bits->width / bits->x_reps; |
2541 | 3.03M | uint rep_height = bits->height / bits->y_reps; |
2542 | 3.03M | uint index; |
2543 | 3.03M | ulong offset; |
2544 | 3.03M | uint width_bits; |
2545 | 3.03M | uint width_bytes; |
2546 | 3.03M | uint raster; |
2547 | 3.03M | uint bytes; |
2548 | 3.03M | byte *data; |
2549 | 3.03M | tile_slot *slot; |
2550 | 3.03M | uint depth = bits->head.depth; |
2551 | | |
2552 | 3.03M | if (bits->num_planes != 1) |
2553 | 0 | depth /= bits->num_planes; |
2554 | 3.03M | width_bits = rep_width * depth; |
2555 | | |
2556 | 3.03M | bytes = clist_bitmap_bytes(width_bits, rep_height * bits->num_planes, |
2557 | 3.03M | compress | |
2558 | 3.03M | (rep_width < bits->width ? |
2559 | 3.02M | decompress_spread : 0) | |
2560 | 3.03M | decompress_elsewhere, |
2561 | 3.03M | &width_bytes, |
2562 | 3.03M | (uint *)&raster); |
2563 | | |
2564 | 3.03M | cmd_getw(index, cbp); |
2565 | 3.03M | cmd_getw(offset, cbp); |
2566 | 3.03M | if_debug2m('L', mem, " index=%d offset=%lu\n", index, offset); |
2567 | 3.03M | pcls->tile_index = index; |
2568 | 3.03M | cdev->tile_table[pcls->tile_index].offset = offset; |
2569 | 3.03M | slot = (tile_slot *)(cdev->cache_chunk->data + offset); |
2570 | 3.03M | *pslot = slot; |
2571 | 3.03M | *slot = *bits; |
2572 | 3.03M | tile->data = data = (byte *)(slot + 1); |
2573 | | #ifdef DEBUG |
2574 | | slot->index = pcls->tile_index; |
2575 | | #endif |
2576 | 3.03M | if (compress == cmd_compress_const) { |
2577 | 0 | cbp = cmd_read_data(pcb, data, 1, cbp); |
2578 | 0 | if (width_bytes > 0 && rep_height > 0) |
2579 | 0 | memset(data+1, *data, width_bytes * rep_height - 1); |
2580 | 3.03M | } else if (compress) { |
2581 | | /* |
2582 | | * Decompress the image data. We'd like to share this code with the |
2583 | | * similar code in copy_*, but right now we don't see how. |
2584 | | */ |
2585 | 355k | stream_cursor_read r; |
2586 | 355k | stream_cursor_write w; |
2587 | | /* |
2588 | | * We don't know the data length a priori, so to be conservative, we |
2589 | | * read the uncompressed size. |
2590 | | */ |
2591 | 355k | uint cleft = pcb->end - cbp; |
2592 | | |
2593 | 355k | if (cleft < bytes && !pcb->end_status) { |
2594 | 6.90k | uint nread = cbuf_size - cleft; |
2595 | | |
2596 | 6.90k | advance_buffer(pcb, cbp); |
2597 | 6.90k | pcb->end_status = sgets(pcb->s, pcb->data + cleft, nread, &nread); |
2598 | 6.90k | set_cb_end(pcb, pcb->data + cleft + nread); |
2599 | 6.90k | cbp = pcb->data; |
2600 | 6.90k | } |
2601 | 355k | r.ptr = cbp - 1; |
2602 | 355k | r.limit = pcb->end - 1; |
2603 | 355k | w.ptr = data - 1; |
2604 | 355k | w.limit = w.ptr + bytes; |
2605 | 355k | switch (compress) { |
2606 | 0 | case cmd_compress_rle: |
2607 | 0 | { |
2608 | 0 | stream_RLD_state sstate; |
2609 | |
|
2610 | 0 | clist_rld_init(&sstate); |
2611 | 0 | (*s_RLD_template.process) |
2612 | 0 | ((stream_state *)&sstate, &r, &w, true); |
2613 | 0 | } |
2614 | 0 | break; |
2615 | 355k | case cmd_compress_cfe: |
2616 | 355k | { |
2617 | 355k | stream_CFD_state sstate; |
2618 | | |
2619 | 355k | clist_cfd_init(&sstate, |
2620 | 355k | width_bytes << 3 /*width_bits */ , |
2621 | 355k | rep_height, mem); |
2622 | 355k | (*s_CFD_template.process) |
2623 | 355k | ((stream_state *)&sstate, &r, &w, true); |
2624 | 355k | (*s_CFD_template.release) |
2625 | 355k | ((stream_state *)&sstate); |
2626 | 355k | } |
2627 | 355k | break; |
2628 | 0 | default: |
2629 | 0 | return_error(gs_error_unregistered); |
2630 | 355k | } |
2631 | 355k | cbp = r.ptr + 1; |
2632 | 2.67M | } else if (rep_height * bits->num_planes > 1 && width_bytes != bits->raster) { |
2633 | 2.65M | cbp = cmd_read_short_bits(pcb, data, bytes, |
2634 | 2.65M | width_bytes, rep_height * bits->num_planes, |
2635 | 2.65M | bits->raster, cbp); |
2636 | 2.65M | } else { |
2637 | 22.5k | cbp = cmd_read_data(pcb, data, bytes, cbp); |
2638 | 22.5k | } |
2639 | 3.03M | if (bits->width > rep_width) |
2640 | 4.79k | bits_replicate_horizontally(data, |
2641 | 4.79k | rep_width * depth, rep_height * bits->num_planes, |
2642 | 4.79k | bits->raster, |
2643 | 4.79k | bits->width * depth, |
2644 | 4.79k | bits->raster); |
2645 | 3.03M | if (bits->height > rep_height) |
2646 | 693 | bits_replicate_vertically(data, |
2647 | 693 | rep_height, bits->raster, |
2648 | 693 | bits->height); |
2649 | | #ifdef DEBUG |
2650 | | if (gs_debug_c('L')) |
2651 | | cmd_print_bits(mem, data, bits->width, bits->height, bits->raster); |
2652 | | #endif |
2653 | 3.03M | pcb->ptr = cbp; |
2654 | 3.03M | return 0; |
2655 | 3.03M | } |
2656 | | |
2657 | | /* if necessary, allocate a buffer to hold a serialized halftone */ |
2658 | | static int |
2659 | | read_alloc_ht_buff(ht_buff_t * pht_buff, uint ht_size, gs_memory_t * mem) |
2660 | 229k | { |
2661 | | /* free the existing buffer, if any (usually none) */ |
2662 | 229k | if (pht_buff->pbuff != 0) { |
2663 | 0 | gs_free_object(mem, pht_buff->pbuff, "read_alloc_ht_buff"); |
2664 | 0 | pht_buff->pbuff = 0; |
2665 | 0 | } |
2666 | | |
2667 | | /* |
2668 | | * If the serialized halftone fits in the command buffer, no |
2669 | | * additional buffer is required. |
2670 | | */ |
2671 | 229k | if (ht_size > cbuf_ht_seg_max_size) { |
2672 | 200k | pht_buff->pbuff = gs_alloc_bytes(mem, ht_size, "read_alloc_ht_buff"); |
2673 | 200k | if (pht_buff->pbuff == 0) |
2674 | 0 | return_error(gs_error_VMerror); |
2675 | 200k | } |
2676 | 229k | pht_buff->ht_size = ht_size; |
2677 | 229k | pht_buff->read_size = 0; |
2678 | 229k | pht_buff->pcurr = pht_buff->pbuff; |
2679 | 229k | return 0; |
2680 | 229k | } |
2681 | | |
2682 | | /* read a halftone segment; if it is the final segment, build the halftone */ |
2683 | | static int |
2684 | | read_ht_segment( |
2685 | | ht_buff_t * pht_buff, |
2686 | | command_buf_t * pcb, |
2687 | | gs_gstate * pgs, |
2688 | | gx_device * dev, |
2689 | | gs_memory_t * mem ) |
2690 | 433k | { |
2691 | 433k | const byte * cbp = pcb->ptr; |
2692 | 433k | const byte * pbuff = 0; |
2693 | 433k | uint ht_size = pht_buff->ht_size, seg_size; |
2694 | 433k | int code = 0; |
2695 | | |
2696 | | /* get the segment size; refill command buffer if necessary */ |
2697 | 433k | enc_u_getw(seg_size, cbp); |
2698 | 433k | if (pcb->warn_limit - cbp < (int)seg_size) { /* cbp can be past warn_limit */ |
2699 | 203k | code = top_up_cbuf(pcb, &cbp); |
2700 | 203k | if (code < 0) |
2701 | 0 | return code; |
2702 | 203k | if (pcb->end - cbp < (int)seg_size) { |
2703 | 0 | emprintf(mem, " *** ht segment size doesn't fit in buffer ***\n"); |
2704 | 0 | return_error(gs_error_unknownerror); |
2705 | 0 | } |
2706 | 203k | } |
2707 | | |
2708 | 433k | if (pht_buff->pbuff == 0) { |
2709 | | /* if not separate buffer, must be only one segment */ |
2710 | 29.1k | if (seg_size != ht_size) |
2711 | 0 | return_error(gs_error_unknownerror); |
2712 | 29.1k | pbuff = cbp; |
2713 | 404k | } else { |
2714 | 404k | if (seg_size + pht_buff->read_size > pht_buff->ht_size) |
2715 | 0 | return_error(gs_error_unknownerror); |
2716 | 404k | memcpy(pht_buff->pcurr, cbp, seg_size); |
2717 | 404k | pht_buff->pcurr += seg_size; |
2718 | 404k | if ((pht_buff->read_size += seg_size) == ht_size) |
2719 | 200k | pbuff = pht_buff->pbuff; |
2720 | 404k | } |
2721 | | |
2722 | | /* if everything has been read, convert back to a halftone */ |
2723 | 433k | if (pbuff != 0) { |
2724 | 229k | code = gx_ht_read_and_install(pgs, dev, pbuff, ht_size, mem); |
2725 | | |
2726 | | /* release any buffered information */ |
2727 | 229k | if (pht_buff->pbuff != 0) { |
2728 | 200k | gs_free_object(mem, pht_buff->pbuff, "read_alloc_ht_buff"); |
2729 | 200k | pht_buff->pbuff = 0; |
2730 | 200k | pht_buff->pcurr = 0; |
2731 | 200k | } |
2732 | 229k | pht_buff->ht_size = 0; |
2733 | 229k | pht_buff->read_size = 0; |
2734 | 229k | } |
2735 | | |
2736 | | /* update the command buffer ponter */ |
2737 | 433k | pcb->ptr = cbp + seg_size; |
2738 | | |
2739 | 433k | return code; |
2740 | 433k | } |
2741 | | |
2742 | | static int |
2743 | | read_set_misc2(command_buf_t *pcb, gs_gstate *pgs, segment_notes *pnotes) |
2744 | 531k | { |
2745 | 531k | const byte *cbp = pcb->ptr; |
2746 | 531k | uint mask, cb; |
2747 | | |
2748 | 531k | if_debug0m('L', pgs->memory, "\n"); |
2749 | 531k | cmd_getw(mask, cbp); |
2750 | 531k | if (mask & cap_join_known) { |
2751 | 72.6k | cb = *cbp++; |
2752 | 72.6k | pgs->line_params.start_cap = (gs_line_cap)((cb >> 3) & 7); |
2753 | 72.6k | pgs->line_params.join = (gs_line_join)(cb & 7); |
2754 | 72.6k | if_debug2m('L', pgs->memory, "[L] start_cap=%d join=%d\n", |
2755 | 72.6k | pgs->line_params.start_cap, pgs->line_params.join); |
2756 | 72.6k | cb = *cbp++; |
2757 | 72.6k | pgs->line_params.end_cap = (gs_line_cap)((cb >> 3) & 7); |
2758 | 72.6k | pgs->line_params.dash_cap = (gs_line_cap)(cb & 7); |
2759 | 72.6k | if_debug2m('L', pgs->memory, "[L] end_cap=%d dash_cap=%d\n", |
2760 | 72.6k | pgs->line_params.end_cap, pgs->line_params.dash_cap); |
2761 | 72.6k | } |
2762 | 531k | if (mask & cj_ac_sa_known) { |
2763 | 20.4k | cb = *cbp++; |
2764 | 20.4k | pgs->line_params.curve_join = ((cb >> 2) & 7) - 1; |
2765 | 20.4k | pgs->accurate_curves = (cb & 2) != 0; |
2766 | 20.4k | pgs->stroke_adjust = cb & 1; |
2767 | 20.4k | if_debug3m('L', pgs->memory, "[L] CJ=%d AC=%d SA=%d\n", |
2768 | 20.4k | pgs->line_params.curve_join, pgs->accurate_curves, |
2769 | 20.4k | pgs->stroke_adjust); |
2770 | 20.4k | } |
2771 | 531k | if (mask & flatness_known) { |
2772 | 38.9k | cmd_get_value(pgs->flatness, cbp); |
2773 | 38.9k | if_debug1m('L', pgs->memory, "[L] flatness=%g\n", pgs->flatness); |
2774 | 38.9k | } |
2775 | 531k | if (mask & line_width_known) { |
2776 | 193k | float width; |
2777 | | |
2778 | 193k | cmd_get_value(width, cbp); |
2779 | 193k | if_debug1m('L', pgs->memory, "[L] line_width=%g\n", width); |
2780 | 193k | gx_set_line_width(&pgs->line_params, width); |
2781 | 193k | } |
2782 | 531k | if (mask & miter_limit_known) { |
2783 | 6.30k | float limit; |
2784 | | |
2785 | 6.30k | cmd_get_value(limit, cbp); |
2786 | 6.30k | if_debug1m('L', pgs->memory, "[L] miter_limit=%g\n", limit); |
2787 | 6.30k | gx_set_miter_limit(&pgs->line_params, limit); |
2788 | 6.30k | } |
2789 | 531k | if (mask & op_bm_tk_known) { |
2790 | 235k | cb = *cbp++; |
2791 | 235k | pgs->blend_mode = cb >> 3; |
2792 | 235k | pgs->text_knockout = cb & 1; |
2793 | | /* the following usually have no effect; see gxclpath.c */ |
2794 | 235k | cb = *cbp++; |
2795 | 235k | pgs->overprint_mode = (cb >> 2) & 1; |
2796 | 235k | pgs->stroke_overprint = (cb >> 1) & 1; |
2797 | 235k | pgs->overprint = cb & 1; |
2798 | 235k | cb = *cbp++; |
2799 | 235k | pgs->renderingintent = cb; |
2800 | 235k | if_debug6m('L', pgs->memory, "[L] BM=%d TK=%d OPM=%d OP=%d op=%d RI=%d\n", |
2801 | 235k | pgs->blend_mode, pgs->text_knockout, pgs->overprint_mode, |
2802 | 235k | pgs->stroke_overprint, pgs->overprint, pgs->renderingintent); |
2803 | 235k | } |
2804 | 531k | if (mask & segment_notes_known) { |
2805 | 552 | cb = *cbp++; |
2806 | 552 | *pnotes = (segment_notes)(cb & 0x3f); |
2807 | 552 | if_debug1m('L', pgs->memory, "[L] notes=%d\n", *pnotes); |
2808 | 552 | } |
2809 | 531k | if (mask & ais_known) { |
2810 | 8.88k | cmd_get_value(pgs->alphaisshape, cbp); |
2811 | 8.88k | if_debug1m('L', pgs->memory, "[L] alphaisshape=%d\n", pgs->alphaisshape); |
2812 | 8.88k | } |
2813 | 531k | if (mask & stroke_alpha_known) { |
2814 | 182k | cmd_get_value(pgs->strokeconstantalpha, cbp); |
2815 | 182k | if_debug1m('L', pgs->memory, "[L] strokeconstantalpha=%g\n", pgs->strokeconstantalpha); |
2816 | 182k | } |
2817 | 531k | if (mask & fill_alpha_known) { |
2818 | 187k | cmd_get_value(pgs->fillconstantalpha, cbp); |
2819 | 187k | if_debug1m('L', pgs->memory, "[L] fillconstantalpha=%u\n", (uint)(pgs->fillconstantalpha)); |
2820 | 187k | } |
2821 | 531k | pcb->ptr = cbp; |
2822 | 531k | return 0; |
2823 | 531k | } |
2824 | | |
2825 | | static int |
2826 | | read_set_color_space(command_buf_t *pcb, gs_gstate *pgs, |
2827 | | gx_device_clist_reader *cdev, gs_memory_t *mem) |
2828 | 114k | { |
2829 | 114k | const byte *cbp = pcb->ptr; |
2830 | 114k | byte b = *cbp++; |
2831 | 114k | int index = b >> 4; |
2832 | 114k | gs_color_space *pcs; |
2833 | 114k | int code = 0; |
2834 | 114k | cmm_profile_t *picc_profile; |
2835 | 114k | clist_icc_color_t icc_information; |
2836 | | |
2837 | 114k | if_debug3m('L', mem, " %d%s%s\n", index, |
2838 | 114k | (b & 8 ? " (indexed)" : ""), |
2839 | 114k | (b & 4 ? "(proc)" : "")); |
2840 | | /* They all store the ICC information. Even if it is NULL |
2841 | | it is used in the ICC case to avoid reading from the |
2842 | | serialized profile data which is stored elsewhere in the |
2843 | | clist. Hence we avoid jumping around in the file. */ |
2844 | 114k | memcpy(&icc_information, cbp, sizeof(clist_icc_color_t)); |
2845 | 114k | cbp = cbp + sizeof(clist_icc_color_t); |
2846 | 114k | switch (index) { |
2847 | 0 | case gs_color_space_index_DeviceGray: |
2848 | 0 | pcs = gs_cspace_new_DeviceGray(mem); |
2849 | 0 | break; |
2850 | 0 | case gs_color_space_index_DeviceRGB: |
2851 | 0 | pcs = gs_cspace_new_DeviceRGB(mem); |
2852 | 0 | break; |
2853 | 0 | case gs_color_space_index_DeviceCMYK: |
2854 | 0 | pcs = gs_cspace_new_DeviceCMYK(mem); |
2855 | 0 | break; |
2856 | 114k | case gs_color_space_index_ICC: |
2857 | | /* build the color space object */ |
2858 | 114k | code = gs_cspace_build_ICC(&pcs, NULL, mem); |
2859 | | /* Don't bother getting the ICC stuff from the clist yet */ |
2860 | 114k | picc_profile = gsicc_profile_new(NULL, cdev->memory, NULL, 0); |
2861 | 114k | if (picc_profile == NULL) |
2862 | 0 | return gs_rethrow(-1, "Failed to find ICC profile during clist read"); |
2863 | 114k | picc_profile->num_comps = icc_information.icc_num_components; |
2864 | 114k | picc_profile->hashcode = icc_information.icc_hash; |
2865 | 114k | picc_profile->hash_is_valid = true; |
2866 | 114k | picc_profile->islab = icc_information.is_lab; |
2867 | 114k | picc_profile->default_match = icc_information.default_match; |
2868 | 114k | picc_profile->data_cs = icc_information.data_cs; |
2869 | | /* Store the clist reader address in the profile |
2870 | | structure so that we can get to the buffer |
2871 | | data if we really neeed it. Ideally, we |
2872 | | will use a cached link and only access this once. */ |
2873 | 114k | picc_profile->dev = (gx_device*) cdev; |
2874 | | /* Assign it to the colorspace */ |
2875 | 114k | code = gsicc_set_gscs_profile(pcs, picc_profile, mem); |
2876 | | /* And we no longer need our reference to the profile */ |
2877 | 114k | gsicc_adjust_profile_rc(picc_profile, -1, "read_set_color_space"); |
2878 | 114k | break; |
2879 | 0 | default: |
2880 | 0 | code = gs_note_error(gs_error_rangecheck); /* others are NYI */ |
2881 | 0 | goto out; |
2882 | 114k | } |
2883 | | |
2884 | 114k | if (pcs == NULL) { |
2885 | 0 | code = gs_note_error(gs_error_VMerror); |
2886 | 0 | goto out; |
2887 | 0 | } |
2888 | | |
2889 | 114k | if (b & 8) { |
2890 | 948 | bool use_proc = (b & 4) != 0; |
2891 | 948 | int hival; |
2892 | 948 | int num_values; |
2893 | 948 | byte *data; |
2894 | 948 | uint data_size; |
2895 | 948 | gs_color_space *pcs_indexed; |
2896 | | |
2897 | 948 | pcs_indexed = gs_cspace_alloc(mem, &gs_color_space_type_Indexed); |
2898 | 948 | if (pcs_indexed == 0) { |
2899 | 0 | rc_decrement_cs(pcs, "read_set_color_space"); |
2900 | 0 | code = gs_note_error(gs_error_VMerror); |
2901 | 0 | goto out; |
2902 | 0 | } |
2903 | 948 | pcs_indexed->base_space = pcs; |
2904 | 948 | pcs = pcs_indexed; |
2905 | 948 | pcs->params.indexed.use_proc = 0; |
2906 | 948 | pcs->params.indexed.lookup.table.data = 0; |
2907 | 948 | pcs->params.indexed.lookup.table.size = 0; |
2908 | 948 | cmd_getw(hival, cbp); |
2909 | 948 | pcs->params.indexed.n_comps = gs_color_space_num_components(pcs->base_space); |
2910 | 948 | num_values = (hival + 1) * pcs->params.indexed.n_comps; |
2911 | 948 | if (use_proc) { |
2912 | 0 | gs_indexed_map *map; |
2913 | |
|
2914 | 0 | code = alloc_indexed_map(&map, num_values, mem, "indexed map"); |
2915 | 0 | if (code < 0) { |
2916 | 0 | rc_decrement_cs(pcs, "read_set_color_space"); |
2917 | 0 | goto out; |
2918 | 0 | } |
2919 | 0 | map->proc.lookup_index = lookup_indexed_map; |
2920 | 0 | pcs->params.indexed.lookup.map = map; |
2921 | 0 | data = (byte *)map->values; |
2922 | 0 | data_size = num_values * sizeof(map->values[0]); |
2923 | 948 | } else { |
2924 | 948 | byte *table = gs_alloc_string(mem, num_values, "color_space indexed table"); |
2925 | | |
2926 | 948 | if (table == 0) { |
2927 | 0 | code = gs_note_error(gs_error_VMerror); |
2928 | 0 | rc_decrement_cs(pcs, "read_set_color_space"); |
2929 | 0 | goto out; |
2930 | 0 | } |
2931 | 948 | pcs->params.indexed.lookup.table.data = table; |
2932 | 948 | pcs->params.indexed.lookup.table.size = num_values; |
2933 | 948 | data = table; |
2934 | 948 | data_size = num_values; |
2935 | 948 | } |
2936 | 948 | cbp = cmd_read_data(pcb, data, data_size, cbp); |
2937 | 948 | pcs->params.indexed.hival = hival; |
2938 | 948 | pcs->params.indexed.use_proc = use_proc; |
2939 | 948 | } |
2940 | | |
2941 | | /* Release reference to old color space before installing new one. */ |
2942 | 114k | if (pgs->color[0].color_space != NULL) |
2943 | 114k | rc_decrement_only_cs(pgs->color[0].color_space, "read_set_color_space"); |
2944 | 114k | pgs->color[0].color_space = pcs; |
2945 | 114k | out: |
2946 | 114k | pcb->ptr = cbp; |
2947 | 114k | return code; |
2948 | 114k | } |
2949 | | |
2950 | | static int |
2951 | | read_begin_image(command_buf_t *pcb, gs_image_common_t *pic, |
2952 | | gs_color_space *pcs) |
2953 | 114k | { |
2954 | 114k | uint index = *(pcb->ptr)++; |
2955 | 114k | const gx_image_type_t *image_type = gx_image_type_table[index]; |
2956 | 114k | stream s; |
2957 | 114k | int code; |
2958 | | |
2959 | | /* This is sloppy, but we don't have enough information to do better. */ |
2960 | 114k | code = top_up_cbuf(pcb, &pcb->ptr); |
2961 | 114k | if (code < 0) |
2962 | 0 | return code; |
2963 | 114k | s_init(&s, NULL); |
2964 | 114k | sread_string(&s, pcb->ptr, pcb->end - pcb->ptr); |
2965 | 114k | code = image_type->sget(pic, &s, pcs); |
2966 | 114k | pcb->ptr = sbufptr(&s); |
2967 | 114k | return code; |
2968 | 114k | } |
2969 | | |
2970 | | static int |
2971 | | read_put_params(command_buf_t *pcb, gs_gstate *pgs, |
2972 | | gx_device_clist_reader *cdev, gs_memory_t *mem) |
2973 | 0 | { |
2974 | 0 | const byte *cbp = pcb->ptr; |
2975 | 0 | gs_c_param_list param_list; |
2976 | 0 | uint cleft; |
2977 | 0 | uint rleft; |
2978 | 0 | bool alloc_data_on_heap = false; |
2979 | 0 | byte *param_buf; |
2980 | 0 | uint param_length; |
2981 | 0 | int code; |
2982 | |
|
2983 | 0 | cmd_get_value(param_length, cbp); |
2984 | 0 | if_debug1m('L', mem, " length=%d\n", param_length); |
2985 | 0 | if (param_length == 0) { |
2986 | 0 | code = 1; /* empty list */ |
2987 | 0 | goto out; |
2988 | 0 | } |
2989 | | |
2990 | | /* Make sure entire serialized param list is in cbuf */ |
2991 | | /* + force void* alignment */ |
2992 | 0 | code = top_up_cbuf(pcb, &cbp); |
2993 | 0 | if (code < 0) |
2994 | 0 | return code; |
2995 | 0 | if (pcb->end - cbp >= param_length) { |
2996 | 0 | param_buf = (byte *)cbp; |
2997 | 0 | cbp += param_length; |
2998 | 0 | } else { |
2999 | | /* NOTE: param_buf must be maximally aligned */ |
3000 | 0 | param_buf = gs_alloc_bytes(mem, param_length, |
3001 | 0 | "clist put_params"); |
3002 | 0 | if (param_buf == 0) { |
3003 | 0 | code = gs_note_error(gs_error_VMerror); |
3004 | 0 | goto out; |
3005 | 0 | } |
3006 | 0 | alloc_data_on_heap = true; |
3007 | 0 | cleft = pcb->end - cbp; |
3008 | 0 | rleft = param_length - cleft; |
3009 | 0 | memmove(param_buf, cbp, cleft); |
3010 | 0 | next_is_skip(pcb); |
3011 | 0 | pcb->end_status = sgets(pcb->s, param_buf + cleft, rleft, &rleft); |
3012 | 0 | cbp = pcb->end; /* force refill */ |
3013 | 0 | } |
3014 | | |
3015 | | /* |
3016 | | * Create a gs_c_param_list & expand into it. |
3017 | | * NB that gs_c_param_list doesn't copy objects into |
3018 | | * it, but rather keeps *pointers* to what's passed. |
3019 | | * That's OK because the serialized format keeps enough |
3020 | | * space to hold expanded versions of the structures, |
3021 | | * but this means we cannot deallocate source buffer |
3022 | | * until the gs_c_param_list is deleted. |
3023 | | */ |
3024 | 0 | gs_c_param_list_write(¶m_list, mem); |
3025 | 0 | code = gs_param_list_unserialize |
3026 | 0 | ( (gs_param_list *)¶m_list, param_buf ); |
3027 | 0 | if (code >= 0 && code != param_length) |
3028 | 0 | code = gs_error_unknownerror; /* must match */ |
3029 | 0 | if (code >= 0) { |
3030 | 0 | gs_c_param_list_read(¶m_list); |
3031 | 0 | code = gs_gstate_putdeviceparams(pgs, (gx_device *)cdev, |
3032 | 0 | (gs_param_list *)¶m_list); |
3033 | 0 | } |
3034 | 0 | gs_c_param_list_release(¶m_list); |
3035 | 0 | if (alloc_data_on_heap) |
3036 | 0 | gs_free_object(mem, param_buf, "clist put_params"); |
3037 | |
|
3038 | 0 | out: |
3039 | 0 | pcb->ptr = cbp; |
3040 | 0 | return code; |
3041 | 0 | } |
3042 | | |
3043 | | /* |
3044 | | * Read a "composite" command, and execute the command. |
3045 | | * |
3046 | | * This code assumes that a the largest create compositor command, |
3047 | | * including the compositor name size, is smaller than the data buffer |
3048 | | * size. This assumption is inherent in the basic design of the coding |
3049 | | * and the de-serializer interface, as no length field is provided. |
3050 | | * |
3051 | | * At the time of this writing, no compositor violates this assumption. |
3052 | | * The largest composite is currently 1275 bytes, while the command |
3053 | | * data buffer is 4096 bytes. |
3054 | | * |
3055 | | * In the event that this assumption is violated, a change in the encoding |
3056 | | * would be called for. |
3057 | | * |
3058 | | * See comment in gdevp14.c c_pdf14trans_read PDF14_BEGIN_TRANS_MASK case. |
3059 | | */ |
3060 | | extern_gs_find_compositor(); |
3061 | | |
3062 | | static int |
3063 | | read_composite( |
3064 | | command_buf_t *pcb, gs_memory_t *mem, gs_composite_t **ppcomp) |
3065 | 21.8M | { |
3066 | 21.8M | const byte * cbp = pcb->ptr; |
3067 | 21.8M | int comp_id = 0, code = 0; |
3068 | 21.8M | const gs_composite_type_t * pcomp_type = 0; |
3069 | | |
3070 | | /* fill the command buffer (see comment above) */ |
3071 | 21.8M | if (pcb->end - cbp < MAX_CLIST_COMPOSITOR_SIZE + sizeof(comp_id)) { |
3072 | 2.02M | code = top_up_cbuf(pcb, &cbp); |
3073 | 2.02M | if (code < 0) |
3074 | 0 | return code; |
3075 | 2.02M | } |
3076 | | |
3077 | | /* find the appropriate compositor method vector */ |
3078 | 21.8M | comp_id = *cbp++; |
3079 | 21.8M | if ((pcomp_type = gs_find_compositor(comp_id)) == 0) |
3080 | 0 | return_error(gs_error_unknownerror); |
3081 | | |
3082 | | /* de-serialize the compositor */ |
3083 | 21.8M | code = pcomp_type->procs.read(ppcomp, cbp, pcb->end - cbp, mem); |
3084 | | |
3085 | | /* If we read more than the maximum expected, return a rangecheck error */ |
3086 | 21.8M | if ( code > MAX_CLIST_COMPOSITOR_SIZE ) |
3087 | 0 | return_error(gs_error_rangecheck); |
3088 | | |
3089 | 21.8M | if (code > 0) |
3090 | 21.8M | cbp += code; |
3091 | 21.8M | pcb->ptr = cbp; |
3092 | 21.8M | return code; |
3093 | 21.8M | } |
3094 | | |
3095 | | static int apply_composite(gx_device_clist_reader *cdev, gs_gstate *pgs, |
3096 | | gs_memory_t *mem, gs_composite_t *pcomp, |
3097 | | int x0, int y0, gx_device **ptarget) |
3098 | 14.9M | { |
3099 | 14.9M | gx_device *tdev = *ptarget; |
3100 | 14.9M | int code; |
3101 | | |
3102 | 14.9M | code = pcomp->type->procs.adjust_ctm(pcomp, x0, y0, pgs); |
3103 | 14.9M | if (code < 0) |
3104 | 0 | goto exit; |
3105 | | /* |
3106 | | * Apply the compositor to the target device; note that this may |
3107 | | * change the target device. |
3108 | | */ |
3109 | 14.9M | code = dev_proc(tdev, composite)(tdev, &tdev, pcomp, pgs, mem, (gx_device*) cdev); |
3110 | 14.9M | if (code == 1) { |
3111 | | /* A new compositor was created that wrapped tdev. This should |
3112 | | * be our new target. */ |
3113 | 253k | *ptarget = tdev; |
3114 | 253k | code = 0; |
3115 | 253k | } |
3116 | 14.9M | if (code < 0) |
3117 | 3 | goto exit; |
3118 | | |
3119 | | /* Perform any updates for the clist device required */ |
3120 | 14.9M | code = pcomp->type->procs.clist_compositor_read_update(pcomp, |
3121 | 14.9M | (gx_device *)cdev, tdev, pgs, mem); |
3122 | 14.9M | exit: |
3123 | | /* free the compositor object */ |
3124 | 14.9M | gs_free_object(mem, pcomp, "read_composite"); |
3125 | | |
3126 | 14.9M | return code; |
3127 | 14.9M | } |
3128 | | |
3129 | | /* ---------------- Utilities ---------------- */ |
3130 | | |
3131 | | /* Read and unpack a short bitmap */ |
3132 | | /* |
3133 | | * The 'raster' in the dest buffer may be larger than the 'width_bytes' |
3134 | | * in the src, so after reading we memmove data down to the proper |
3135 | | * alignment from the last line backwards. |
3136 | | * THIS RELIES on width_bytes <= raster to work. |
3137 | | */ |
3138 | | static const byte * |
3139 | | cmd_read_short_bits(command_buf_t *pcb, byte *data, int tot_bytes, |
3140 | | int width_bytes, int height, uint raster, const byte *cbp) |
3141 | 2.66M | { |
3142 | | /* Note the following may read from the file past the end of the buffer */ |
3143 | | /* leaving cbp at pcb->end. No further reading using cbp can be done */ |
3144 | | /* without top_up_cbuf to reload the buffer. */ |
3145 | 2.66M | cbp = cmd_read_data(pcb, data, tot_bytes, cbp); |
3146 | | |
3147 | | /* if needed, adjust buffer contents for dest raster > width_bytes */ |
3148 | 2.66M | if (width_bytes < raster) { |
3149 | 2.66M | const byte *pdata = data /*src*/ + width_bytes * height; |
3150 | 2.66M | byte *udata = data /*dest*/ + height * raster; |
3151 | | |
3152 | 41.1M | while (--height > 0) { /* don't need to move the first line to itself */ |
3153 | 38.4M | udata -= raster, pdata -= width_bytes; |
3154 | 38.4M | switch (width_bytes) { |
3155 | 0 | default: |
3156 | 0 | memmove(udata, pdata, width_bytes); |
3157 | 0 | break; |
3158 | 64.2k | case 6: |
3159 | 64.2k | udata[5] = pdata[5]; |
3160 | 206k | case 5: |
3161 | 206k | udata[4] = pdata[4]; |
3162 | 1.11M | case 4: |
3163 | 1.11M | udata[3] = pdata[3]; |
3164 | 9.82M | case 3: |
3165 | 9.82M | udata[2] = pdata[2]; |
3166 | 31.1M | case 2: |
3167 | 31.1M | udata[1] = pdata[1]; |
3168 | 38.4M | case 1: |
3169 | 38.4M | udata[0] = pdata[0]; |
3170 | 38.4M | case 0:; /* shouldn't happen */ |
3171 | 38.4M | } |
3172 | 38.4M | } |
3173 | 2.66M | } |
3174 | 2.66M | return cbp; |
3175 | 2.66M | } |
3176 | | |
3177 | | /* Read a rectangle. */ |
3178 | | static const byte * |
3179 | | cmd_read_rect(int op, gx_cmd_rect * prect, const byte * cbp) |
3180 | 3.34M | { |
3181 | 3.34M | cmd_getw(prect->x, cbp); |
3182 | 3.34M | if (op & 0xf) |
3183 | 385k | prect->y += ((op >> 2) & 3) - 2; |
3184 | 2.95M | else { |
3185 | 2.95M | cmd_getw(prect->y, cbp); |
3186 | 2.95M | } |
3187 | 3.34M | cmd_getw(prect->width, cbp); |
3188 | 3.34M | if (op & 0xf) |
3189 | 385k | prect->height += (op & 3) - 2; |
3190 | 2.95M | else { |
3191 | 2.95M | cmd_getw(prect->height, cbp); |
3192 | 2.95M | } |
3193 | 3.34M | return cbp; |
3194 | 3.34M | } |
3195 | | |
3196 | | /* |
3197 | | * Select a map for loading with data. |
3198 | | * |
3199 | | * This routine has three outputs: |
3200 | | * *pmdata - points to the map data. |
3201 | | * *pcomp_num - points to a component number if the map is a transfer |
3202 | | * map which has been set via the setcolortransfer operator. |
3203 | | * A. value of NULL indicates that no component number is to |
3204 | | * be sent for this map. |
3205 | | * *pcount - the size of the map (in bytes). |
3206 | | */ |
3207 | | static int |
3208 | | cmd_select_map(cmd_map_index map_index, cmd_map_contents cont, |
3209 | | gs_gstate * pgs, int ** pcomp_num, frac ** pmdata, |
3210 | | uint * pcount, gs_memory_t * mem) |
3211 | 1.18M | { |
3212 | 1.18M | gx_transfer_map *map; |
3213 | 1.18M | gx_transfer_map **pmap; |
3214 | 1.18M | const char *cname; |
3215 | | |
3216 | 1.18M | *pcomp_num = NULL; /* Only used for color transfer maps */ |
3217 | 1.18M | switch (map_index) { |
3218 | 369k | case cmd_map_transfer: |
3219 | 369k | if_debug0m('L', mem, " transfer"); |
3220 | 369k | rc_unshare_struct(pgs->set_transfer.gray, gx_transfer_map, |
3221 | 369k | &st_transfer_map, mem, return_error(gs_error_VMerror), |
3222 | 369k | "cmd_select_map(default_transfer)"); |
3223 | 369k | map = pgs->set_transfer.gray; |
3224 | | /* Release all current maps */ |
3225 | 369k | rc_decrement(pgs->set_transfer.red, "cmd_select_map(red)"); |
3226 | 369k | pgs->set_transfer.red = NULL; |
3227 | 369k | pgs->set_transfer.red_component_num = -1; |
3228 | 369k | rc_decrement(pgs->set_transfer.green, "cmd_select_map(green)"); |
3229 | 369k | pgs->set_transfer.green = NULL; |
3230 | 369k | pgs->set_transfer.green_component_num = -1; |
3231 | 369k | rc_decrement(pgs->set_transfer.blue, "cmd_select_map(blue)"); |
3232 | 369k | pgs->set_transfer.blue = NULL; |
3233 | 369k | pgs->set_transfer.blue_component_num = -1; |
3234 | 369k | goto transfer2; |
3235 | 20 | case cmd_map_transfer_0: |
3236 | 20 | pmap = &pgs->set_transfer.red; |
3237 | 20 | *pcomp_num = &pgs->set_transfer.red_component_num; |
3238 | 20 | goto transfer1; |
3239 | 20 | case cmd_map_transfer_1: |
3240 | 20 | pmap = &pgs->set_transfer.green; |
3241 | 20 | *pcomp_num = &pgs->set_transfer.green_component_num; |
3242 | 20 | goto transfer1; |
3243 | 20 | case cmd_map_transfer_2: |
3244 | 20 | pmap = &pgs->set_transfer.blue; |
3245 | 20 | *pcomp_num = &pgs->set_transfer.blue_component_num; |
3246 | 20 | goto transfer1; |
3247 | 0 | case cmd_map_transfer_3: |
3248 | 0 | pmap = &pgs->set_transfer.gray; |
3249 | 0 | *pcomp_num = &pgs->set_transfer.gray_component_num; |
3250 | 60 | transfer1: if_debug1m('L', mem, " transfer[%d]", (int)(map_index - cmd_map_transfer_0)); |
3251 | 60 | rc_unshare_struct(*pmap, gx_transfer_map, &st_transfer_map, mem, |
3252 | 60 | return_error(gs_error_VMerror), "cmd_select_map(transfer)"); |
3253 | 60 | map = *pmap; |
3254 | | |
3255 | 370k | transfer2: if (cont != cmd_map_other) { |
3256 | 185k | gx_set_identity_transfer(map); |
3257 | 185k | *pmdata = 0; |
3258 | 185k | *pcount = 0; |
3259 | 185k | return 0; |
3260 | 185k | } |
3261 | 184k | break; |
3262 | 408k | case cmd_map_black_generation: |
3263 | 408k | if_debug0m('L', mem, " black generation"); |
3264 | 408k | pmap = &pgs->black_generation; |
3265 | 408k | cname = "cmd_select_map(black generation)"; |
3266 | 408k | goto alloc; |
3267 | 408k | case cmd_map_undercolor_removal: |
3268 | 408k | if_debug0m('L', mem, " undercolor removal"); |
3269 | 408k | pmap = &pgs->undercolor_removal; |
3270 | 408k | cname = "cmd_select_map(undercolor removal)"; |
3271 | 817k | alloc: if (cont == cmd_map_none) { |
3272 | 0 | rc_decrement(*pmap, cname); |
3273 | 0 | *pmap = 0; |
3274 | 0 | *pmdata = 0; |
3275 | 0 | *pcount = 0; |
3276 | 0 | return 0; |
3277 | 0 | } |
3278 | 817k | rc_unshare_struct(*pmap, gx_transfer_map, &st_transfer_map, |
3279 | 817k | mem, return_error(gs_error_VMerror), cname); |
3280 | 817k | map = *pmap; |
3281 | 817k | if (cont == cmd_map_identity) { |
3282 | 0 | gx_set_identity_transfer(map); |
3283 | 0 | *pmdata = 0; |
3284 | 0 | *pcount = 0; |
3285 | 0 | return 0; |
3286 | 0 | } |
3287 | 817k | break; |
3288 | 817k | default: |
3289 | 0 | *pmdata = 0; |
3290 | 0 | return 0; |
3291 | 1.18M | } |
3292 | 1.00M | map->proc = gs_mapped_transfer; |
3293 | 1.00M | *pmdata = map->values; |
3294 | 1.00M | *pcount = sizeof(map->values); |
3295 | 1.00M | return 0; |
3296 | 1.18M | } |
3297 | | |
3298 | | /* Create a device halftone for the imager if necessary. */ |
3299 | | static int |
3300 | | cmd_create_dev_ht(gx_device_halftone **ppdht, gs_memory_t *mem) |
3301 | 0 | { |
3302 | 0 | gx_device_halftone *pdht = *ppdht; |
3303 | |
|
3304 | 0 | if (pdht == 0) { |
3305 | 0 | rc_header rc; |
3306 | |
|
3307 | 0 | rc_alloc_struct_1(pdht, gx_device_halftone, &st_device_halftone, mem, |
3308 | 0 | return_error(gs_error_VMerror), |
3309 | 0 | "cmd_create_dev_ht"); |
3310 | 0 | rc = pdht->rc; |
3311 | 0 | memset(pdht, 0, sizeof(*pdht)); |
3312 | 0 | pdht->rc = rc; |
3313 | 0 | *ppdht = pdht; |
3314 | 0 | } |
3315 | 0 | return 0; |
3316 | 0 | } |
3317 | | |
3318 | | /* Resize the halftone components array if necessary. */ |
3319 | | static int |
3320 | | cmd_resize_halftone(gx_device_halftone **ppdht, uint num_comp, |
3321 | | gs_memory_t * mem) |
3322 | 0 | { |
3323 | 0 | int code = cmd_create_dev_ht(ppdht, mem); |
3324 | 0 | gx_device_halftone *pdht = *ppdht; |
3325 | |
|
3326 | 0 | if (code < 0) |
3327 | 0 | return code; |
3328 | 0 | if (num_comp != pdht->num_comp) { |
3329 | 0 | gx_ht_order_component *pcomp; |
3330 | | |
3331 | | /* |
3332 | | * We must be careful not to shrink or free the components array |
3333 | | * before releasing any relevant elements. |
3334 | | */ |
3335 | 0 | if (num_comp < pdht->num_comp) { |
3336 | 0 | uint i; |
3337 | | |
3338 | | /* Don't release the default order. */ |
3339 | 0 | for (i = pdht->num_comp; i-- > num_comp;) |
3340 | 0 | if (pdht->components[i].corder.bit_data != pdht->order.bit_data) |
3341 | 0 | gx_ht_order_release(&pdht->components[i].corder, mem, true); |
3342 | 0 | if (num_comp == 0) { |
3343 | 0 | gs_free_object(mem, pdht->components, "cmd_resize_halftone"); |
3344 | 0 | pcomp = 0; |
3345 | 0 | } else { |
3346 | 0 | pcomp = gs_resize_object(mem, pdht->components, num_comp, |
3347 | 0 | "cmd_resize_halftone"); |
3348 | 0 | if (pcomp == 0) { |
3349 | 0 | pdht->num_comp = num_comp; /* attempt consistency */ |
3350 | 0 | return_error(gs_error_VMerror); |
3351 | 0 | } |
3352 | 0 | } |
3353 | 0 | } else { |
3354 | | /* num_comp > pdht->num_comp */ |
3355 | 0 | if (pdht->num_comp == 0) |
3356 | 0 | pcomp = gs_alloc_struct_array(mem, num_comp, |
3357 | 0 | gx_ht_order_component, |
3358 | 0 | &st_ht_order_component_element, |
3359 | 0 | "cmd_resize_halftone"); |
3360 | 0 | else |
3361 | 0 | pcomp = gs_resize_object(mem, pdht->components, num_comp, |
3362 | 0 | "cmd_resize_halftone"); |
3363 | 0 | if (pcomp == 0) |
3364 | 0 | return_error(gs_error_VMerror); |
3365 | 0 | memset(&pcomp[pdht->num_comp], 0, |
3366 | 0 | sizeof(*pcomp) * (num_comp - pdht->num_comp)); |
3367 | 0 | } |
3368 | 0 | pdht->num_comp = num_comp; |
3369 | 0 | pdht->components = pcomp; |
3370 | 0 | } |
3371 | 0 | return 0; |
3372 | 0 | } |
3373 | | |
3374 | | /* ------ Path operations ------ */ |
3375 | | |
3376 | | /* Decode a path segment. */ |
3377 | | static int |
3378 | | clist_decode_segment(gx_path * ppath, int op, fixed vs[6], |
3379 | | gs_fixed_point * ppos, int x0, int y0, segment_notes notes) |
3380 | 15.3M | { |
3381 | 15.3M | fixed px = ppos->x - int2fixed(x0); |
3382 | 15.3M | fixed py = ppos->y - int2fixed(y0); |
3383 | 15.3M | int code; |
3384 | | |
3385 | 20.3M | #define A vs[0] |
3386 | 15.3M | #define B vs[1] |
3387 | 15.3M | #define C vs[2] |
3388 | 15.3M | #define D vs[3] |
3389 | 15.3M | #define E vs[4] |
3390 | 15.3M | #define F vs[5] |
3391 | | |
3392 | 15.3M | switch (op) { |
3393 | 2.25M | case cmd_opv_rmoveto: |
3394 | 2.25M | code = gx_path_add_point(ppath, px += A, py += B); |
3395 | 2.25M | break; |
3396 | 1.53M | case cmd_opv_rlineto: |
3397 | 1.53M | code = gx_path_add_line_notes(ppath, px += A, py += B, notes); |
3398 | 1.53M | break; |
3399 | 0 | case cmd_opv_rgapto: |
3400 | 0 | code = gx_path_add_gap_notes(ppath, px += A, py += B, notes); |
3401 | 0 | break; |
3402 | 2.62M | case cmd_opv_hlineto: |
3403 | 2.62M | code = gx_path_add_line_notes(ppath, px += A, py, notes); |
3404 | 2.62M | break; |
3405 | 2.84M | case cmd_opv_vlineto: |
3406 | 2.84M | code = gx_path_add_line_notes(ppath, px, py += A, notes); |
3407 | 2.84M | break; |
3408 | 255k | case cmd_opv_rmlineto: |
3409 | 255k | if ((code = gx_path_add_point(ppath, px += A, py += B)) < 0) |
3410 | 0 | break; |
3411 | 255k | code = gx_path_add_line_notes(ppath, px += C, py += D, notes); |
3412 | 255k | break; |
3413 | 225k | case cmd_opv_rm2lineto: |
3414 | 225k | if ((code = gx_path_add_point(ppath, px += A, py += B)) < 0 || |
3415 | 225k | (code = gx_path_add_line_notes(ppath, px += C, py += D, |
3416 | 225k | notes)) < 0 |
3417 | 225k | ) |
3418 | 0 | break; |
3419 | 225k | code = gx_path_add_line_notes(ppath, px += E, py += F, notes); |
3420 | 225k | break; |
3421 | 54.4k | case cmd_opv_rm3lineto: |
3422 | 54.4k | if ((code = gx_path_add_point(ppath, px += A, py += B)) < 0 || |
3423 | 54.4k | (code = gx_path_add_line_notes(ppath, px += C, py += D, |
3424 | 54.4k | notes)) < 0 || |
3425 | 54.4k | (code = gx_path_add_line_notes(ppath, px += E, py += F, |
3426 | 54.4k | notes)) < 0 |
3427 | 54.4k | ) |
3428 | 0 | break; |
3429 | 54.4k | code = gx_path_add_line_notes(ppath, px -= C, py -= D, notes); |
3430 | 54.4k | break; |
3431 | 3.56M | case cmd_opv_rrcurveto: /* a b c d e f => a b a+c b+d a+c+e b+d+f */ |
3432 | 3.57M | rrc: E += (C += A); |
3433 | 3.57M | F += (D += B); |
3434 | 4.24M | curve: code = gx_path_add_curve_notes(ppath, px + A, py + B, |
3435 | 4.24M | px + C, py + D, |
3436 | 4.24M | px + E, py + F, notes); |
3437 | 4.24M | px += E, py += F; |
3438 | 4.24M | break; |
3439 | 269k | case cmd_opv_hvcurveto: /* a b c d => a 0 a+b c a+b c+d */ |
3440 | 273k | hvc: F = C + D, D = C, E = C = A + B, B = 0; |
3441 | 273k | goto curve; |
3442 | 269k | case cmd_opv_vhcurveto: /* a b c d => 0 a b a+c b+d a+c */ |
3443 | 282k | vhc: E = B + D, F = D = A + C, C = B, B = A, A = 0; |
3444 | 282k | goto curve; |
3445 | 48.5k | case cmd_opv_nrcurveto: /* a b c d => 0 0 a b a+c b+d */ |
3446 | 48.5k | F = B + D, E = A + C, D = B, C = A, B = A = 0; |
3447 | 48.5k | goto curve; |
3448 | 63.0k | case cmd_opv_rncurveto: /* a b c d => a b a+c b+d a+c b+d */ |
3449 | 63.0k | F = D += B, E = C += A; |
3450 | 63.0k | goto curve; |
3451 | 13.6k | case cmd_opv_vqcurveto: /* a b => VH a b TS(a,b) TS(b,a) */ |
3452 | 13.6k | if ((A ^ B) < 0) |
3453 | 3.69k | C = -B, D = -A; |
3454 | 9.94k | else |
3455 | 9.94k | C = B, D = A; |
3456 | 13.6k | goto vhc; |
3457 | 4.64k | case cmd_opv_hqcurveto: /* a b => HV a TS(a,b) b TS(b,a) */ |
3458 | 4.64k | if ((A ^ B) < 0) |
3459 | 1.49k | D = -A, C = B, B = -B; |
3460 | 3.15k | else |
3461 | 3.15k | D = A, C = B; |
3462 | 4.64k | goto hvc; |
3463 | 9.77k | case cmd_opv_scurveto: /* (a b c d e f) => */ |
3464 | 9.77k | { |
3465 | 9.77k | fixed a = A, b = B; |
3466 | | |
3467 | | /* See gxclpath.h for details on the following. */ |
3468 | 9.77k | if (A == 0) { |
3469 | | /* Previous curve was vh or vv */ |
3470 | 9.08k | A = E - C, B = D - F, C = C - a, D = b - D, E = a, F = -b; |
3471 | 9.08k | } else { |
3472 | | /* Previous curve was hv or hh */ |
3473 | 690 | A = C - E, B = F - D, C = a - C, D = D - b, E = -a, F = b; |
3474 | 690 | } |
3475 | 9.77k | } |
3476 | 9.77k | goto rrc; |
3477 | 1.35M | case cmd_opv_closepath: |
3478 | 1.35M | if ((code = gx_path_close_subpath(ppath)) < 0) |
3479 | 1.35M | return code;; |
3480 | 1.35M | if ((code = gx_path_current_point(ppath, (gs_fixed_point *) vs)) < 0) |
3481 | 1.35M | return code;; |
3482 | 1.35M | px = A, py = B; |
3483 | 1.35M | break; |
3484 | 0 | default: |
3485 | 0 | return_error(gs_error_rangecheck); |
3486 | 15.3M | } |
3487 | 15.3M | #undef A |
3488 | 15.3M | #undef B |
3489 | 15.3M | #undef C |
3490 | 15.3M | #undef D |
3491 | 15.3M | #undef E |
3492 | 15.3M | #undef F |
3493 | 15.3M | ppos->x = px + int2fixed(x0); |
3494 | 15.3M | ppos->y = py + int2fixed(y0); |
3495 | 15.3M | return code; |
3496 | 15.3M | } |
3497 | | |
3498 | | /* |
3499 | | * Execute a polyfill -- either a fill_parallelogram or a fill_triangle. |
3500 | | * |
3501 | | * Note that degenerate parallelograms or triangles may collapse into |
3502 | | * a single line or point. We must check for this so we don't try to |
3503 | | * access non-existent segments. |
3504 | | */ |
3505 | | static int |
3506 | | clist_do_polyfill(gx_device *dev, gx_path *ppath, |
3507 | | const gx_drawing_color *pdcolor, |
3508 | | gs_logical_operation_t lop) |
3509 | 144k | { |
3510 | 144k | const subpath *psub = ppath->first_subpath; |
3511 | 144k | const segment *pseg1; |
3512 | 144k | const segment *pseg2; |
3513 | 144k | int code; |
3514 | | |
3515 | 144k | if (psub && (pseg1 = psub->next) != 0 && (pseg2 = pseg1->next) != 0) { |
3516 | 144k | fixed px = psub->pt.x, py = psub->pt.y; |
3517 | 144k | fixed ax = pseg1->pt.x - px, ay = pseg1->pt.y - py; |
3518 | 144k | fixed bx, by; |
3519 | | /* |
3520 | | * We take advantage of the fact that the parameter lists for |
3521 | | * fill_parallelogram and fill_triangle are identical. |
3522 | | */ |
3523 | 144k | dev_proc_fill_parallelogram((*fill)); |
3524 | | |
3525 | | /* close_path of 3 point triangle adds 4th point, detected here.*/ |
3526 | | /* close_path on parallelogram adds 5th point also ignored. */ |
3527 | 144k | if (pseg2->next && !(px == pseg2->next->pt.x && py == pseg2->next->pt.y)) { |
3528 | | /* Parallelogram */ |
3529 | 67.0k | fill = dev_proc(dev, fill_parallelogram); |
3530 | 67.0k | bx = pseg2->pt.x - pseg1->pt.x; |
3531 | 67.0k | by = pseg2->pt.y - pseg1->pt.y; |
3532 | 77.2k | } else { |
3533 | | /* Triangle */ |
3534 | 77.2k | fill = dev_proc(dev, fill_triangle); |
3535 | 77.2k | bx = pseg2->pt.x - px; |
3536 | 77.2k | by = pseg2->pt.y - py; |
3537 | 77.2k | } |
3538 | 144k | code = fill(dev, px, py, ax, ay, bx, by, pdcolor, lop); |
3539 | 144k | } else |
3540 | 0 | code = 0; |
3541 | 144k | gx_path_new(ppath); |
3542 | 144k | return code; |
3543 | 144k | } |