/src/ghostpdl/base/gxclimag.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2024 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Higher-level image operations for band lists */ |
18 | | #include "math_.h" |
19 | | #include "memory_.h" |
20 | | #include "string_.h" /* for strcmp */ |
21 | | #include "gx.h" |
22 | | #include "gserrors.h" |
23 | | #include "gscspace.h" |
24 | | #include "gscdefs.h" /* for image type table */ |
25 | | #include "gxarith.h" |
26 | | #include "gxcspace.h" |
27 | | #include "gxpcolor.h" |
28 | | #include "gxdevice.h" |
29 | | #include "gxdevmem.h" /* must precede gxcldev.h */ |
30 | | #include "gxcldev.h" |
31 | | #include "gxclpath.h" |
32 | | #include "gxfmap.h" |
33 | | #include "gxiparam.h" |
34 | | #include "gxpath.h" |
35 | | #include "stream.h" |
36 | | #include "strimpl.h" /* for sisparam.h */ |
37 | | #include "sisparam.h" |
38 | | #include "gxcomp.h" |
39 | | #include "gsserial.h" |
40 | | #include "gxdhtserial.h" |
41 | | #include "gsptype1.h" |
42 | | #include "gsicc_manage.h" |
43 | | #include "gsicc_cache.h" |
44 | | #include "gxdevsop.h" |
45 | | #include "gscindex.h" |
46 | | #include "gsicc_cms.h" |
47 | | #include "gximdecode.h" |
48 | | |
49 | | extern_gx_image_type_table(); |
50 | | |
51 | | /* Define whether we should use high-level images. */ |
52 | | /* (See below for additional restrictions.) */ |
53 | | static const bool USE_HL_IMAGES = true; |
54 | | |
55 | | /* Forward references */ |
56 | | static int cmd_put_set_data_x(gx_device_clist_writer * cldev, |
57 | | gx_clist_state * pcls, int data_x); |
58 | | static bool check_rect_for_trivial_clip( |
59 | | const gx_clip_path *pcpath, /* May be NULL, clip to evaluate */ |
60 | | int px, int py, int qx, int qy /* corners of box to test */ |
61 | | ); |
62 | | |
63 | | static bool |
64 | | palette_has_color(const gs_color_space *pcs, const gs_pixel_image_t * const pim) |
65 | 0 | { |
66 | 0 | gs_color_space *pbcs = pcs->base_space; |
67 | 0 | gs_color_space_index base_type = gs_color_space_get_index(pbcs); |
68 | 0 | bool ((*is_neutral)(void*, int)); |
69 | 0 | int bps = pim->BitsPerComponent; |
70 | 0 | int num_entries = 1 << bps; |
71 | 0 | int k; |
72 | 0 | byte psrc[4]; |
73 | |
|
74 | 0 | switch(base_type) { |
75 | | |
76 | 0 | case gs_color_space_index_DeviceGray: |
77 | 0 | case gs_color_space_index_CIEA: |
78 | 0 | return false; |
79 | 0 | break; |
80 | | |
81 | 0 | case gs_color_space_index_DeviceRGB: |
82 | 0 | case gs_color_space_index_CIEABC: |
83 | 0 | case gs_color_space_index_CIEDEF: |
84 | 0 | is_neutral = &gsicc_mcm_monitor_rgb; |
85 | 0 | break; |
86 | | |
87 | 0 | case gs_color_space_index_DeviceCMYK: |
88 | 0 | case gs_color_space_index_CIEDEFG: |
89 | 0 | is_neutral = &gsicc_mcm_monitor_cmyk; |
90 | 0 | break; |
91 | | |
92 | 0 | case gs_color_space_index_DevicePixel: |
93 | 0 | case gs_color_space_index_DeviceN: |
94 | 0 | case gs_color_space_index_Separation: |
95 | 0 | case gs_color_space_index_Indexed: |
96 | 0 | case gs_color_space_index_Pattern: |
97 | 0 | return true; |
98 | 0 | break; |
99 | | |
100 | 0 | case gs_color_space_index_ICC: |
101 | 0 | switch(pbcs->cmm_icc_profile_data->data_cs) { |
102 | 0 | case gsRGB: |
103 | 0 | is_neutral = &gsicc_mcm_monitor_rgb; |
104 | 0 | break; |
105 | | |
106 | 0 | case gsCMYK: |
107 | 0 | is_neutral = &gsicc_mcm_monitor_cmyk; |
108 | 0 | break; |
109 | | |
110 | 0 | case gsCIELAB: |
111 | 0 | is_neutral = &gsicc_mcm_monitor_lab; |
112 | 0 | break; |
113 | | |
114 | 0 | default: |
115 | 0 | return true; |
116 | 0 | } |
117 | 0 | break; |
118 | 0 | default: |
119 | 0 | return true; |
120 | 0 | } |
121 | | /* Now go through the palette with the check color function */ |
122 | 0 | for (k = 0; k < num_entries; k++) { |
123 | 0 | (void)gs_cspace_indexed_lookup_bytes(pcs, (float) k, psrc); /* this always returns 0 */ |
124 | 0 | if (!is_neutral(psrc, 1)) { |
125 | | /* Has color end this now */ |
126 | 0 | return true; |
127 | 0 | } |
128 | 0 | } |
129 | | /* Must not have color */ |
130 | 0 | return false; |
131 | 0 | } |
132 | | |
133 | | |
134 | | /* ------ Driver procedures ------ */ |
135 | | |
136 | | int |
137 | | clist_fill_mask(gx_device * dev, |
138 | | const byte * data, int data_x, int raster, gx_bitmap_id id, |
139 | | int rx, int ry, int rwidth, int rheight, |
140 | | const gx_drawing_color * pdcolor, int depth, |
141 | | gs_logical_operation_t lop, const gx_clip_path * pcpath) |
142 | 1.35M | { |
143 | 1.35M | gx_device_clist_writer * const cdev = |
144 | 1.35M | &((gx_device_clist *)dev)->writer; |
145 | 1.35M | const byte *orig_data = data; /* for writing tile */ |
146 | 1.35M | int orig_data_x = data_x; /* ditto */ |
147 | 1.35M | int orig_x = rx; /* ditto */ |
148 | 1.35M | int orig_width = rwidth; /* ditto */ |
149 | 1.35M | int orig_height = rheight; /* ditto */ |
150 | 1.35M | int y0; |
151 | 1.35M | byte copy_op = |
152 | 1.35M | (depth > 1 ? cmd_op_copy_color_alpha : |
153 | 1.35M | cmd_op_copy_mono_planes); /* Plane not needed here */ |
154 | 1.35M | bool slow_rop = |
155 | 1.35M | cmd_slow_rop(dev, lop_know_S_0(lop), pdcolor) || |
156 | 1.35M | cmd_slow_rop(dev, lop_know_S_1(lop), pdcolor); |
157 | 1.35M | cmd_rects_enum_t re; |
158 | | |
159 | | /* If depth > 1, this call will be translated to a copy_alpha call. */ |
160 | | /* if the target device can't perform copy_alpha, exit now. */ |
161 | 1.35M | if (depth > 1 && (cdev->disable_mask & clist_disable_copy_alpha) != 0) |
162 | 0 | return_error(gs_error_unknownerror); |
163 | | |
164 | 1.35M | crop_copy(cdev, data, data_x, raster, id, rx, ry, rwidth, rheight); |
165 | 1.35M | if (rwidth <= 0 || rheight <= 0) |
166 | 185k | return 0; |
167 | 1.17M | y0 = ry; /* must do after fit_copy */ |
168 | | |
169 | | /* If non-trivial clipping & complex clipping disabled, default */ |
170 | | /* Also default for uncached bitmap or non-default lop; */ |
171 | | /* We could handle more RasterOp cases here directly, but it */ |
172 | | /* doesn't seem worth the trouble right now. */ |
173 | | /* Lastly, the command list will translate calls with depth > 1 to */ |
174 | | /* copy_alpha calls, so the device color must be pure */ |
175 | 1.17M | if (((cdev->disable_mask & clist_disable_complex_clip) && |
176 | 1.17M | !check_rect_for_trivial_clip(pcpath, rx, ry, rx + rwidth, ry + rheight)) || |
177 | 1.17M | gs_debug_c('`') || id == gx_no_bitmap_id || lop != lop_default || |
178 | 1.17M | (depth > 1 && !color_writes_pure(pdcolor, lop)) |
179 | 1.17M | ) |
180 | 2.43k | copy: |
181 | 2.43k | return gx_default_fill_mask(dev, data, data_x, raster, id, |
182 | 2.43k | rx, ry, rwidth, rheight, pdcolor, depth, |
183 | 2.43k | lop, pcpath); |
184 | | |
185 | 1.17M | if (cmd_check_clip_path(cdev, pcpath)) |
186 | 4.95k | cmd_clear_known(cdev, clip_path_known); |
187 | 1.17M | if (cdev->permanent_error < 0) |
188 | 0 | return (cdev->permanent_error); |
189 | | /* If needed, update the trans_bbox */ |
190 | 1.17M | if (cdev->pdf14_needed) { |
191 | 1.17M | gs_int_rect bbox; |
192 | | |
193 | 1.17M | bbox.p.x = rx; |
194 | 1.17M | bbox.q.x = rx + rwidth - 1; |
195 | 1.17M | bbox.p.y = ry; |
196 | 1.17M | bbox.q.y = ry + rheight - 1; |
197 | | |
198 | 1.17M | clist_update_trans_bbox(cdev, &bbox); |
199 | 1.17M | } |
200 | 1.17M | RECT_ENUM_INIT(re, ry, rheight); |
201 | 2.69M | do { |
202 | 2.69M | int code; |
203 | 2.69M | ulong offset_temp; |
204 | | |
205 | 2.69M | RECT_STEP_INIT(re); |
206 | 2.69M | code = cmd_update_lop(cdev, re.pcls, lop); |
207 | 2.69M | if (code < 0) |
208 | 0 | return code; |
209 | 2.69M | if (depth > 1 && !re.pcls->color_is_alpha) { |
210 | 0 | byte *dp; |
211 | |
|
212 | 0 | code = set_cmd_put_op(&dp, cdev, re.pcls, cmd_opv_set_copy_alpha, 1); |
213 | 0 | if (code < 0) |
214 | 0 | return code; |
215 | 0 | re.pcls->color_is_alpha = 1; |
216 | 0 | } |
217 | 2.69M | code = cmd_do_write_unknown(cdev, re.pcls, clip_path_known); |
218 | 2.69M | if (code >= 0) |
219 | 2.69M | code = cmd_do_enable_clip(cdev, re.pcls, pcpath != NULL); |
220 | 2.69M | if (code < 0) |
221 | 0 | return code; |
222 | 2.69M | code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, |
223 | 2.69M | devn_not_tile_fill); |
224 | 2.69M | if (code == gs_error_unregistered) |
225 | 0 | return code; |
226 | 2.69M | if (depth > 1 && code >= 0) |
227 | 0 | code = cmd_set_color1(cdev, re.pcls, pdcolor->colors.pure); |
228 | 2.69M | if (code < 0) |
229 | 0 | return code; |
230 | 2.69M | re.pcls->color_usage.slow_rop |= slow_rop; |
231 | | /* Put it in the cache if possible. */ |
232 | 2.69M | if (!cls_has_tile_id(cdev, re.pcls, id, offset_temp)) { |
233 | 2.58M | gx_strip_bitmap tile; |
234 | | |
235 | 2.58M | tile.data = (byte *) orig_data; /* actually const */ |
236 | 2.58M | tile.raster = raster; |
237 | 2.58M | tile.size.x = tile.rep_width = orig_width; |
238 | 2.58M | tile.size.y = tile.rep_height = orig_height; |
239 | 2.58M | tile.rep_shift = tile.shift = 0; |
240 | 2.58M | tile.id = id; |
241 | 2.58M | tile.num_planes = 1; |
242 | 2.58M | code = clist_change_bits(cdev, re.pcls, &tile, depth); |
243 | 2.58M | if (code < 0) { |
244 | | /* Something went wrong; just copy the bits. */ |
245 | 0 | goto copy; |
246 | 0 | } |
247 | 2.58M | } |
248 | 2.69M | { |
249 | 2.69M | gx_cmd_rect rect; |
250 | 2.69M | int rsize; |
251 | 2.69M | byte op = copy_op + cmd_copy_use_tile; |
252 | | |
253 | | /* Output a command to copy the entire character. */ |
254 | | /* It will be truncated properly per band. */ |
255 | 2.69M | rect.x = orig_x, rect.y = y0; |
256 | 2.69M | rect.width = orig_width, rect.height = re.yend - y0; |
257 | 2.69M | rsize = 1 + cmd_sizexy(rect); |
258 | 2.69M | if (depth == 1) rsize = rsize + cmd_sizew(0); /* need planar_height 0 setting */ |
259 | 2.69M | code = (orig_data_x ? |
260 | 2.69M | cmd_put_set_data_x(cdev, re.pcls, orig_data_x) : 0); |
261 | 2.69M | if (code >= 0) { |
262 | 2.69M | byte *dp; |
263 | | |
264 | 2.69M | code = set_cmd_put_op(&dp, cdev, re.pcls, op, rsize); |
265 | | /* |
266 | | * The following conditional is unnecessary: the two |
267 | | * statements inside it should go outside the |
268 | | * HANDLE_RECT. They are here solely to pacify |
269 | | * stupid compilers that don't understand that dp |
270 | | * will always be set if control gets past the |
271 | | * HANDLE_RECT. |
272 | | */ |
273 | 2.69M | if (code >= 0) { |
274 | 2.69M | dp++; |
275 | 2.69M | if (depth == 1) { |
276 | 2.69M | cmd_putw(0, &dp); |
277 | 2.69M | } |
278 | 2.69M | cmd_putxy(rect, &dp); |
279 | 2.69M | } |
280 | 2.69M | } |
281 | 2.69M | if (code < 0) |
282 | 0 | return code; |
283 | 2.69M | re.pcls->rect = rect; |
284 | 2.69M | } |
285 | 2.69M | } while ((re.y += re.height) < re.yend); |
286 | 1.17M | return 0; |
287 | 1.17M | } |
288 | | |
289 | | /* ------ Bitmap image driver procedures ------ */ |
290 | | |
291 | | /* Define the structure for keeping track of progress through an image. */ |
292 | | typedef struct clist_image_enum_s { |
293 | | gx_image_enum_common; |
294 | | /* Arguments of begin_image */ |
295 | | gs_pixel_image_t image; /* only uses Width, Height, Interpolate */ |
296 | | gx_drawing_color dcolor; /* only pure right now */ |
297 | | gs_int_rect rect; |
298 | | const gx_clip_path *pcpath; |
299 | | /* Set at creation time */ |
300 | | gs_image_format_t format; |
301 | | gs_int_point support; /* extra source pixels for interpolation */ |
302 | | int bits_per_plane; /* bits per pixel per plane */ |
303 | | gs_matrix matrix; /* image space -> device space */ |
304 | | bool uses_color; |
305 | | bool masked; |
306 | | clist_color_space_t color_space; |
307 | | int ymin, ymax; |
308 | | gx_color_usage_t color_usage; |
309 | | /* begin_image command prepared & ready to output */ |
310 | | /****** SIZE COMPUTATION IS WRONG, TIED TO gximage.c, gsmatrix.c ******/ |
311 | | byte begin_image_command[3 + |
312 | | /* Width, Height */ |
313 | | 2 * cmd_sizew_max + |
314 | | /* ImageMatrix */ |
315 | | 1 + 6 * sizeof(float) + |
316 | | /* Decode */ |
317 | | (GS_IMAGE_MAX_COMPONENTS + 3) / 4 + |
318 | | GS_IMAGE_MAX_COMPONENTS * 2 * sizeof(float) + |
319 | | /* MaskColors */ |
320 | | GS_IMAGE_MAX_COMPONENTS * cmd_sizew_max + |
321 | | /* rect */ |
322 | | 4 * cmd_sizew_max]; |
323 | | int begin_image_command_length; |
324 | | /* Updated dynamically */ |
325 | | int y; |
326 | | bool color_map_is_known; |
327 | | bool monitor_color; |
328 | | image_decode_t decode; |
329 | | byte *buffer; /* needed for unpacking during monitoring */ |
330 | | } clist_image_enum; |
331 | | gs_private_st_suffix_add3(st_clist_image_enum, clist_image_enum, |
332 | | "clist_image_enum", clist_image_enum_enum_ptrs, |
333 | | clist_image_enum_reloc_ptrs, st_gx_image_enum_common, |
334 | | pcpath, color_space.space, buffer); |
335 | | |
336 | | static image_enum_proc_plane_data(clist_image_plane_data); |
337 | | static image_enum_proc_end_image(clist_image_end_image); |
338 | | static const gx_image_enum_procs_t clist_image_enum_procs = |
339 | | { |
340 | | clist_image_plane_data, clist_image_end_image |
341 | | }; |
342 | | |
343 | | /* data_size is number of bytes per component, width is number of pixels in the row. */ |
344 | | static bool |
345 | | row_has_color(byte *data_ptr, clist_image_enum *pie_c, int data_size, int width) |
346 | 0 | { |
347 | 0 | clist_color_space_t pclcs = pie_c->color_space; |
348 | 0 | bool ((*is_neutral)(void*, int)); |
349 | 0 | int step_size = data_size * pie_c->decode.spp; |
350 | 0 | byte *ptr; |
351 | 0 | bool is_mono; |
352 | 0 | int k; |
353 | |
|
354 | 0 | if (pclcs.icc_info.is_lab) { |
355 | 0 | is_neutral = &gsicc_mcm_monitor_lab; |
356 | 0 | } else { |
357 | 0 | switch(pclcs.icc_info.icc_num_components) { |
358 | 0 | case 3: |
359 | 0 | is_neutral = &gsicc_mcm_monitor_rgb; |
360 | 0 | break; |
361 | 0 | case 4: |
362 | 0 | is_neutral = &gsicc_mcm_monitor_cmyk; |
363 | 0 | break; |
364 | 0 | default: |
365 | 0 | return true; |
366 | 0 | } |
367 | 0 | } |
368 | | /* Now go through the raster line and determine if we have any color. */ |
369 | 0 | ptr = data_ptr; |
370 | 0 | for (k = 0; k < width; k++) { |
371 | 0 | is_mono = is_neutral(ptr, data_size); |
372 | 0 | if (!is_mono) { |
373 | 0 | return true; |
374 | 0 | } |
375 | 0 | ptr += step_size; |
376 | 0 | } |
377 | 0 | return false; |
378 | 0 | } |
379 | | |
380 | | /* Forward declarations */ |
381 | | static bool image_band_box(gx_device * dev, const clist_image_enum * pie, |
382 | | int y, int h, gs_int_rect * pbox); |
383 | | static int begin_image_command(byte *buf, uint buf_size, |
384 | | const gs_image_common_t *pic); |
385 | | static int cmd_image_plane_data(gx_device_clist_writer * cldev, |
386 | | gx_clist_state * pcls, |
387 | | const gx_image_plane_t * planes, |
388 | | const gx_image_enum_common_t * pie, |
389 | | uint bytes_per_plane, |
390 | | const uint * offsets, int dx, int h); |
391 | | static int cmd_image_plane_data_mon(gx_device_clist_writer * cldev, |
392 | | gx_clist_state * pcls, |
393 | | const gx_image_plane_t * planes, |
394 | | const gx_image_enum_common_t * pie, |
395 | | uint bytes_per_plane, |
396 | | const uint * offsets, int dx, int h, |
397 | | bool *found_color); |
398 | | static uint clist_image_unknowns(gx_device *dev, |
399 | | const clist_image_enum *pie); |
400 | | static int write_image_end_all(gx_device *dev, |
401 | | const clist_image_enum *pie); |
402 | | |
403 | | /* |
404 | | * Since currently we are limited to writing a single subrectangle of the |
405 | | * image for each band, images that are rotated by angles other than |
406 | | * multiples of 90 degrees may wind up writing many copies of the data. |
407 | | * Eventually we will fix this by breaking up the image into multiple |
408 | | * subrectangles, but for now, don't use the high-level approach if it would |
409 | | * cause the data to explode because of this. |
410 | | */ |
411 | | static bool |
412 | | image_matrix_ok_to_band(const gs_matrix * pmat) |
413 | 4.70k | { |
414 | 4.70k | double t; |
415 | | /* Detecting a downscale when it's really noscale upsets some |
416 | | * customers code, so we add a fudge factor in here. This may |
417 | | * cause us to allow the use of high level images for some downscales |
418 | | * that are *nearly* noscales, but our code will cope with that. */ |
419 | 4.70k | float one = (float)(1.0 - 1e-5); |
420 | | |
421 | | /* Don't band if the matrix is (nearly) singular. */ |
422 | 4.70k | if (fabs(pmat->xx * pmat->yy - pmat->xy * pmat->yx) < 0.001) |
423 | 146 | return false; |
424 | | /* If it's portrait, then we encode it if not a downscale */ |
425 | 4.56k | if (is_xxyy(pmat)) |
426 | 4.54k | return (fabs(pmat->xx) >= one) && (fabs(pmat->yy) >= one); |
427 | | /* If it's landscape, then we encode it if not a downscale */ |
428 | 21 | if (is_xyyx(pmat)) |
429 | 1 | return (fabs(pmat->xy) >= one) && (fabs(pmat->yx) >= one); |
430 | | /* Skewed, so do more expensive downscale test */ |
431 | 20 | if ((pmat->xx * pmat->xx + pmat->xy * pmat->xy < one) || |
432 | 20 | (pmat->yx * pmat->yx + pmat->yy * pmat->yy < one)) |
433 | 9 | return false; |
434 | | /* Otherwise only encode it if it doesn't rotate too much */ |
435 | 11 | t = (fabs(pmat->xx) + fabs(pmat->yy)) / |
436 | 11 | (fabs(pmat->xy) + fabs(pmat->yx)); |
437 | 11 | return (t < 0.2 || t > 5); |
438 | 20 | } |
439 | | |
440 | | /* Start processing an image. */ |
441 | | int |
442 | | clist_begin_typed_image(gx_device * dev, const gs_gstate * pgs, |
443 | | const gs_matrix * pmat, const gs_image_common_t * pic, |
444 | | const gs_int_rect * prect, const gx_drawing_color * pdcolor, |
445 | | const gx_clip_path * pcpath, gs_memory_t * mem, |
446 | | gx_image_enum_common_t ** pinfo) |
447 | 4.72k | { |
448 | 4.72k | const gs_pixel_image_t * const pim = (const gs_pixel_image_t *)pic; |
449 | 4.72k | gx_device_clist_writer * const cdev = |
450 | 4.72k | &((gx_device_clist *)dev)->writer; |
451 | 4.72k | clist_image_enum *pie = 0; |
452 | 4.72k | int base_index; |
453 | 4.72k | bool indexed; |
454 | 4.72k | bool masked = false; |
455 | 4.72k | bool has_alpha = false; |
456 | 4.72k | int num_components; |
457 | 4.72k | int bits_per_pixel; |
458 | 4.72k | bool uses_color; |
459 | 4.72k | bool varying_depths = false; |
460 | 4.72k | gs_matrix mat; |
461 | 4.72k | gs_rect sbox, dbox; |
462 | 4.72k | gs_image_format_t format; |
463 | 4.72k | gx_color_usage_bits color_usage = 0; |
464 | 4.72k | int code; |
465 | 4.72k | bool mask_use_hl; |
466 | 4.72k | clist_icc_color_t icc_zero_init = { 0 }; |
467 | 4.72k | cmm_profile_t *src_profile; |
468 | 4.72k | cmm_srcgtag_profile_t *srcgtag_profile; |
469 | 4.72k | gsicc_rendering_intents_t renderingintent; |
470 | 4.72k | gsicc_blackptcomp_t blackptcomp; |
471 | 4.72k | gsicc_rendering_param_t stored_rendering_cond; |
472 | 4.72k | gsicc_rendering_param_t dev_render_cond; |
473 | 4.72k | gs_gstate *pgs_nonconst = (gs_gstate*) pgs; |
474 | 4.72k | bool intent_changed = false; |
475 | 4.72k | bool bp_changed = false; |
476 | 4.72k | cmm_dev_profile_t *dev_profile = NULL; |
477 | 4.72k | cmm_profile_t *gs_output_profile; |
478 | 4.72k | bool is_planar_dev = !!dev->num_planar_planes; |
479 | 4.72k | bool render_is_valid; |
480 | 4.72k | int csi; |
481 | 4.72k | gx_clip_path *lpcpath = NULL; |
482 | | |
483 | 4.72k | if (pgs == NULL) { |
484 | | /* At this time, this cannot/should not ever happen, |
485 | | so it's fatal if it does. |
486 | | */ |
487 | 0 | return_error(gs_error_Fatal); |
488 | 0 | } |
489 | 4.72k | renderingintent = pgs->renderingintent; |
490 | 4.72k | blackptcomp = pgs->blackptcomp; |
491 | | |
492 | | /* We can only handle a limited set of image types. */ |
493 | 4.72k | switch ((gs_debug_c('`') ? -1 : pic->type->index)) { |
494 | 4.72k | case 1: |
495 | 4.72k | masked = ((const gs_image1_t *)pim)->ImageMask; |
496 | 4.72k | has_alpha = ((const gs_image1_t *)pim)->Alpha != 0; |
497 | | /* fall through */ |
498 | 4.72k | case 4: |
499 | 4.72k | if (pmat == 0) |
500 | 4.72k | break; |
501 | 0 | default: |
502 | 0 | goto use_default; |
503 | 4.72k | } |
504 | 4.72k | format = pim->format; |
505 | | /* See above for why we allocate the enumerator as immovable. */ |
506 | 4.72k | pie = gs_alloc_struct_immovable(mem, clist_image_enum, |
507 | 4.72k | &st_clist_image_enum, |
508 | 4.72k | "clist_begin_typed_image"); |
509 | 4.72k | if (pie == 0) |
510 | 0 | return_error(gs_error_VMerror); |
511 | 4.72k | #ifdef PACIFY_VALGRIND |
512 | | /* The following memset is required to avoid a valgrind warning |
513 | | * in: |
514 | | * gs -I./gs/lib -sOutputFile=out.pgm -dMaxBitmap=10000 |
515 | | * -sDEVICE=pgmraw -r300 -Z: -sDEFAULTPAPERSIZE=letter |
516 | | * -dNOPAUSE -dBATCH -K2000000 -dClusterJob -dJOBSERVER |
517 | | * tests_private/ps/ps3cet/11-14.PS |
518 | | * Setting the individual elements of the structure directly is |
519 | | * not enough, which leads me to believe that we are writing the |
520 | | * entire struct out, padding and all. |
521 | | */ |
522 | 4.72k | memset(&pie->color_space.icc_info, 0, sizeof(pie->color_space.icc_info)); |
523 | 4.72k | #endif |
524 | 4.72k | pie->memory = mem; |
525 | 4.72k | pie->buffer = NULL; |
526 | 4.72k | pie->masked = masked; |
527 | 4.72k | *pinfo = (gx_image_enum_common_t *) pie; |
528 | | /* num_planes and plane_depths[] are set later, */ |
529 | | /* by gx_image_enum_common_init. */ |
530 | 4.72k | if (masked) { |
531 | 6 | base_index = gs_color_space_index_DeviceGray; /* arbitrary */ |
532 | 6 | indexed = false; |
533 | 6 | num_components = 1; |
534 | 6 | uses_color = true; |
535 | | /* cmd_put_drawing_color handles color_usage */ |
536 | 4.71k | } else { |
537 | 4.71k | const gs_color_space *pcs = pim->ColorSpace; |
538 | | |
539 | 4.71k | base_index = gs_color_space_get_index(pcs); |
540 | 4.71k | if (base_index == gs_color_space_index_Indexed) { |
541 | 124 | const gs_color_space *pbcs = |
542 | 124 | gs_color_space_indexed_base_space(pcs); |
543 | | |
544 | 124 | indexed = true; |
545 | 124 | base_index = gs_color_space_get_index(pbcs); |
546 | 124 | num_components = 1; |
547 | 4.59k | } else { |
548 | 4.59k | indexed = false; |
549 | 4.59k | num_components = gs_color_space_num_components(pcs); |
550 | 4.59k | } |
551 | 4.71k | uses_color = pim->CombineWithColor && |
552 | 4.71k | (rop3_uses_T(pgs->log_op) || rop3_uses_S(pgs->log_op)); |
553 | 4.71k | } |
554 | 4.72k | code = gx_image_enum_common_init((gx_image_enum_common_t *) pie, |
555 | 4.72k | (const gs_data_image_t *) pim, |
556 | 4.72k | &clist_image_enum_procs, dev, |
557 | 4.72k | num_components, format); |
558 | 4.72k | { |
559 | 4.72k | int i; |
560 | | |
561 | 4.72k | for (i = 1; i < pie->num_planes; ++i) |
562 | 0 | varying_depths |= pie->plane_depths[i] != pie->plane_depths[0]; |
563 | 4.72k | } |
564 | | |
565 | | /* Now, check to see if we can't handle this as a high level image. */ |
566 | 4.72k | if (code < 0) |
567 | 0 | goto use_default; |
568 | 4.72k | if (!USE_HL_IMAGES) /* Always use the default. */ |
569 | 0 | goto use_default; |
570 | 4.72k | if (cdev->disable_mask & clist_disable_hl_image) |
571 | 0 | goto use_default; |
572 | 4.72k | if (cdev->image_enum_id != gs_no_id) /* Can't handle nested images */ |
573 | 0 | goto use_default; |
574 | 4.72k | if (base_index > gs_color_space_index_DeviceCMYK && |
575 | 4.72k | base_index != gs_color_space_index_ICC) |
576 | | /****** Can only handle Gray, RGB, CMYK and ICC ******/ |
577 | 2 | goto use_default; |
578 | 4.72k | if (has_alpha) |
579 | | /****** CAN'T HANDLE IMAGES WITH ALPHA YET ******/ |
580 | 0 | goto use_default; |
581 | 4.72k | if (varying_depths) |
582 | | /****** CAN'T HANDLE IMAGES WITH IRREGULAR DEPTHS ******/ |
583 | 0 | goto use_default; |
584 | 4.72k | if ((code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 || |
585 | 4.72k | (code = gs_matrix_multiply(&mat, &ctm_only(pgs), &mat)) < 0 || |
586 | 4.72k | !(cdev->disable_mask & clist_disable_nonrect_hl_image ? |
587 | 0 | (is_xxyy(&mat) || is_xyyx(&mat)) : |
588 | 4.70k | image_matrix_ok_to_band(&mat))) |
589 | 1.05k | goto use_default; |
590 | | |
591 | 3.66k | mask_use_hl = |
592 | 3.66k | masked && ( gx_dc_is_pattern1_color(pdcolor) || gx_dc_is_pure(pdcolor) ); |
593 | 3.66k | if (!mask_use_hl && uses_color && !gx_dc_is_pure(pdcolor) && |
594 | 3.66k | !gx_dc_is_pattern1_color_clist_based(pdcolor)) |
595 | | /* Only add in masks that are pure or pattern or pattern trans types */ |
596 | 0 | goto use_default; |
597 | | |
598 | | /* We've passed the tests; code it as a high level image */ |
599 | 3.66k | { |
600 | 3.66k | int bytes_per_plane, bytes_per_row; |
601 | | |
602 | 3.66k | bits_per_pixel = pim->BitsPerComponent * num_components; |
603 | 3.66k | pie->decode.bps = bits_per_pixel/num_components; |
604 | 3.66k | pie->decode.spp = num_components; |
605 | 3.66k | pie->image = *pim; |
606 | 3.66k | pie->dcolor = *pdcolor; |
607 | 3.66k | if (prect) |
608 | 0 | pie->rect = *prect; |
609 | 3.66k | else { |
610 | 3.66k | pie->rect.p.x = 0, pie->rect.p.y = 0; |
611 | 3.66k | pie->rect.q.x = pim->Width, pie->rect.q.y = pim->Height; |
612 | 3.66k | } |
613 | 3.66k | pie->pgs = pgs; |
614 | 3.66k | pie->pgs_level = pgs->level; |
615 | | |
616 | 3.66k | if (pcpath) { |
617 | 3.66k | lpcpath = gx_cpath_alloc(mem, "clist_begin_typed_image(lpcpath)"); |
618 | 3.66k | if (!lpcpath) { |
619 | 0 | goto use_default; |
620 | 0 | } |
621 | 3.66k | code = gx_cpath_copy(pcpath, lpcpath); |
622 | 3.66k | if (code < 0) { |
623 | 0 | goto use_default; |
624 | 0 | } |
625 | 3.66k | } |
626 | 3.66k | pie->pcpath = lpcpath; |
627 | | |
628 | 3.66k | pie->buffer = NULL; |
629 | 3.66k | pie->format = format; |
630 | 3.66k | pie->bits_per_plane = bits_per_pixel / pie->num_planes; |
631 | 3.66k | pie->matrix = mat; |
632 | 3.66k | pie->uses_color = uses_color; |
633 | 3.66k | if (masked) { |
634 | 0 | pie->color_space.byte1 = 0; /* arbitrary */ |
635 | 0 | pie->color_space.icc_info = icc_zero_init; |
636 | 0 | pie->color_space.space = 0; |
637 | 0 | pie->color_space.id = gs_no_id; |
638 | 3.66k | } else { |
639 | | /* Check for presence of ICC profiles in standard Device Color Spaces |
640 | | This can happen if a default space was initialized. It should |
641 | | typically have assigned to it one of the default ICC profiles */ |
642 | 3.66k | if (indexed) { |
643 | 44 | if (pim->ColorSpace->base_space->cmm_icc_profile_data) { |
644 | 44 | base_index = gs_color_space_index_ICC; |
645 | 44 | } |
646 | 3.62k | } else { |
647 | 3.62k | if (pim->ColorSpace->cmm_icc_profile_data) { |
648 | 3.62k | base_index = gs_color_space_index_ICC; |
649 | 3.62k | } |
650 | 3.62k | } |
651 | 3.66k | pie->color_space.byte1 = (base_index << 4) | |
652 | 3.66k | (indexed ? (pim->ColorSpace->params.indexed.use_proc ? 12 : 8) : 0); |
653 | 3.66k | pie->color_space.id = |
654 | 3.66k | (pie->color_space.space = pim->ColorSpace)->id; |
655 | | /* Get the hash code of the ICC space */ |
656 | 3.66k | if ( base_index == gs_color_space_index_ICC ) { |
657 | 3.66k | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
658 | 3.66k | gsicc_extract_profile(dev->graphics_type_tag, dev_profile, |
659 | 3.66k | &(gs_output_profile), |
660 | 3.66k | (&(dev_render_cond))); |
661 | 3.66k | if (!indexed) { |
662 | 3.62k | src_profile = pim->ColorSpace->cmm_icc_profile_data; |
663 | 3.62k | } else { |
664 | 44 | src_profile = |
665 | 44 | pim->ColorSpace->base_space->cmm_icc_profile_data; |
666 | 44 | } |
667 | | /* Initialize the rendering conditions to what we currently |
668 | | have before we may blow them away with what is set in |
669 | | the srcgtag information */ |
670 | 3.66k | stored_rendering_cond.graphics_type_tag = GS_IMAGE_TAG; |
671 | 3.66k | stored_rendering_cond.override_icc = |
672 | 3.66k | dev_render_cond.override_icc; |
673 | 3.66k | stored_rendering_cond.preserve_black = |
674 | 3.66k | dev_render_cond.preserve_black; |
675 | 3.66k | stored_rendering_cond.cmm = gsCMM_DEFAULT; /* Unless spec. below */ |
676 | | /* We may need to do some substitions for the source profile */ |
677 | 3.66k | if (pgs->icc_manager->srcgtag_profile != NULL) { |
678 | 0 | srcgtag_profile = pgs->icc_manager->srcgtag_profile; |
679 | 0 | if (src_profile->data_cs == gsRGB) { |
680 | 0 | if (srcgtag_profile->rgb_profiles[gsSRC_IMAGPRO] != NULL) { |
681 | | /* We only do this replacement depending upon the |
682 | | ICC override setting for this object and the |
683 | | original color space of this object */ |
684 | 0 | csi = gsicc_get_default_type(src_profile); |
685 | 0 | if (srcgtag_profile->rgb_rend_cond[gsSRC_IMAGPRO].override_icc || |
686 | 0 | csi == gs_color_space_index_DeviceRGB) { |
687 | 0 | src_profile = |
688 | 0 | srcgtag_profile->rgb_profiles[gsSRC_IMAGPRO]; |
689 | 0 | pgs_nonconst->renderingintent = |
690 | 0 | srcgtag_profile->rgb_rend_cond[gsSRC_IMAGPRO].rendering_intent; |
691 | 0 | pgs_nonconst->blackptcomp = |
692 | 0 | srcgtag_profile->rgb_rend_cond[gsSRC_IMAGPRO].black_point_comp; |
693 | 0 | stored_rendering_cond = |
694 | 0 | srcgtag_profile->rgb_rend_cond[gsSRC_IMAGPRO]; |
695 | 0 | } |
696 | 0 | } else { |
697 | | /* A possible do not use CM case */ |
698 | 0 | stored_rendering_cond.cmm = |
699 | 0 | srcgtag_profile->rgb_rend_cond[gsSRC_IMAGPRO].cmm; |
700 | 0 | } |
701 | 0 | } else if (src_profile->data_cs == gsCMYK) { |
702 | 0 | if (srcgtag_profile->cmyk_profiles[gsSRC_IMAGPRO] != NULL) { |
703 | 0 | csi = gsicc_get_default_type(src_profile); |
704 | 0 | if (srcgtag_profile->cmyk_rend_cond[gsSRC_IMAGPRO].override_icc || |
705 | 0 | csi == gs_color_space_index_DeviceCMYK) { |
706 | 0 | src_profile = |
707 | 0 | srcgtag_profile->cmyk_profiles[gsSRC_IMAGPRO]; |
708 | 0 | pgs_nonconst->renderingintent = |
709 | 0 | srcgtag_profile->cmyk_rend_cond[gsSRC_IMAGPRO].rendering_intent; |
710 | 0 | pgs_nonconst->blackptcomp = |
711 | 0 | srcgtag_profile->cmyk_rend_cond[gsSRC_IMAGPRO].black_point_comp; |
712 | 0 | stored_rendering_cond = |
713 | 0 | srcgtag_profile->cmyk_rend_cond[gsSRC_IMAGPRO]; |
714 | 0 | } |
715 | 0 | } else { |
716 | | /* A possible do not use CM case */ |
717 | 0 | stored_rendering_cond.cmm = |
718 | 0 | srcgtag_profile->cmyk_rend_cond[gsSRC_IMAGPRO].cmm; |
719 | 0 | } |
720 | 0 | } |
721 | 0 | } |
722 | | /* If the device RI is set and we are not setting the RI from |
723 | | the source structure, then override any RI specified in the |
724 | | document by the RI specified in the device */ |
725 | 3.66k | if (!(pgs_nonconst->renderingintent & gsRI_OVERRIDE)) { /* was set by source? */ |
726 | | /* No it was not. See if we should override with the |
727 | | device setting */ |
728 | 3.66k | if (dev_render_cond.rendering_intent != gsRINOTSPECIFIED) { |
729 | 0 | pgs_nonconst->renderingintent = |
730 | 0 | dev_render_cond.rendering_intent; |
731 | 0 | } |
732 | 3.66k | } |
733 | | /* We have a similar issue to deal with with respect to the |
734 | | black point. */ |
735 | 3.66k | if (!(pgs_nonconst->blackptcomp & gsBP_OVERRIDE)) { |
736 | 3.66k | if (dev_render_cond.black_point_comp != gsBPNOTSPECIFIED) { |
737 | 0 | pgs_nonconst->blackptcomp = |
738 | 0 | dev_render_cond.black_point_comp; |
739 | 0 | } |
740 | 3.66k | } |
741 | 3.66k | if (renderingintent != pgs_nonconst->renderingintent) |
742 | 0 | intent_changed = true; |
743 | 3.66k | if (blackptcomp != pgs_nonconst->blackptcomp) |
744 | 0 | bp_changed = true; |
745 | | /* Set for the rendering param structure also */ |
746 | 3.66k | stored_rendering_cond.rendering_intent = |
747 | 3.66k | pgs_nonconst->renderingintent; |
748 | 3.66k | stored_rendering_cond.black_point_comp = |
749 | 3.66k | pgs_nonconst->blackptcomp; |
750 | 3.66k | stored_rendering_cond.graphics_type_tag = GS_IMAGE_TAG; |
751 | 3.66k | if (!(src_profile->hash_is_valid)) { |
752 | 0 | int64_t hash; |
753 | 0 | gsicc_get_icc_buff_hash(src_profile->buffer, &hash, |
754 | 0 | src_profile->buffer_size); |
755 | 0 | src_profile->hashcode = hash; |
756 | 0 | src_profile->hash_is_valid = true; |
757 | 0 | } |
758 | 3.66k | pie->color_space.icc_info.icc_hash = src_profile->hashcode; |
759 | 3.66k | pie->color_space.icc_info.icc_num_components = |
760 | 3.66k | src_profile->num_comps; |
761 | 3.66k | pie->color_space.icc_info.is_lab = src_profile->islab; |
762 | 3.66k | pie->color_space.icc_info.default_match = src_profile->default_match; |
763 | 3.66k | pie->color_space.icc_info.data_cs = src_profile->data_cs; |
764 | 3.66k | src_profile->rend_cond = stored_rendering_cond; |
765 | 3.66k | render_is_valid = src_profile->rend_is_valid; |
766 | 3.66k | src_profile->rend_is_valid = true; |
767 | 3.66k | clist_icc_addentry(cdev, src_profile->hashcode, src_profile); |
768 | 3.66k | src_profile->rend_is_valid = render_is_valid; |
769 | 3.66k | } else { |
770 | 0 | pie->color_space.icc_info = icc_zero_init; |
771 | 0 | } |
772 | 3.66k | } |
773 | 3.66k | pie->y = pie->rect.p.y; |
774 | | /* Image row has to fit in cmd writer's buffer */ |
775 | 3.66k | bytes_per_plane = |
776 | 3.66k | (pim->Width * pie->bits_per_plane + 7) >> 3; |
777 | 3.66k | bytes_per_row = bytes_per_plane * pie->num_planes; |
778 | 3.66k | bytes_per_row = max(bytes_per_row, 1); |
779 | 3.66k | if (cmd_largest_size + bytes_per_row > cdev->cend - cdev->cbuf) |
780 | 0 | goto use_default; |
781 | 3.66k | } |
782 | 3.66k | if (pim->Interpolate) { |
783 | 0 | pie->support.x = pie->support.y = MAX_ISCALE_SUPPORT + 1; |
784 | 3.66k | } else { |
785 | 3.66k | pie->support.x = pie->support.y = 0; |
786 | 3.66k | } |
787 | 3.66k | sbox.p.x = pie->rect.p.x - pie->support.x; |
788 | 3.66k | sbox.p.y = pie->rect.p.y - pie->support.y; |
789 | 3.66k | sbox.q.x = pie->rect.q.x + pie->support.x; |
790 | 3.66k | sbox.q.y = pie->rect.q.y + pie->support.y; |
791 | 3.66k | gs_bbox_transform(&sbox, &mat, &dbox); |
792 | | |
793 | 3.66k | if (cdev->disable_mask & clist_disable_complex_clip) |
794 | 0 | if (!check_rect_for_trivial_clip(lpcpath, |
795 | 0 | (int)floor(dbox.p.x), (int)floor(dbox.p.y), |
796 | 0 | (int)ceil(dbox.q.x), (int)ceil(dbox.q.y))) |
797 | 0 | goto use_default; |
798 | | |
799 | | /* If we are going out to a halftone device and the size of the stored |
800 | | image at device resolution and color space is going to be smaller, |
801 | | go ahead and do the default handler. This occurs only for planar |
802 | | devices where if we prerender we will end up doing the fast theshold |
803 | | halftone and going out as copy_planes commands into the clist. |
804 | | There is already a test above with regard to the posture so that |
805 | | we are only doing portrait or landscape cases if we are here. Only |
806 | | question is penum->image_parent_type == gs_image_type1 */ |
807 | 3.66k | if (dev_profile == NULL) { |
808 | 0 | gsicc_rendering_param_t temp_render_cond; |
809 | 0 | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
810 | 0 | if (code < 0) |
811 | 0 | return code; |
812 | 0 | gsicc_extract_profile(dev->graphics_type_tag, dev_profile, |
813 | 0 | &(gs_output_profile), |
814 | 0 | &(temp_render_cond)); |
815 | 0 | } |
816 | | /* Decide if we need to do any monitoring of the colors. Note that multiple source |
817 | | (planes) is treated as color */ |
818 | 3.66k | pie->decode.unpack = NULL; |
819 | 3.66k | if (dev_profile->pageneutralcolor && pie->color_space.icc_info.data_cs != gsGRAY) { |
820 | | /* If it is an index image, then check the pallete only */ |
821 | 0 | if (!indexed) { |
822 | 0 | pie->monitor_color = true; |
823 | | /* Set up the unpacking proc for monitoring */ |
824 | 0 | get_unpack_proc((gx_image_enum_common_t*) pie, &(pie->decode), |
825 | 0 | pim->format, pim->Decode); |
826 | 0 | get_map(&(pie->decode), pim->format, pim->Decode); |
827 | 0 | if (pie->decode.unpack == NULL) { |
828 | | /* If we cant unpack, then end monitoring now. Treat as has color */ |
829 | 0 | dev_profile->pageneutralcolor = false; |
830 | 0 | code = gsicc_mcm_end_monitor(pgs->icc_link_cache, dev); |
831 | 0 | if (code < 0) |
832 | 0 | return code; |
833 | 0 | } else { |
834 | | /* We need to allocate the buffer for unpacking during monitoring. |
835 | | This is mainly for the 12bit case */ |
836 | 0 | int bsize = ((pie->decode.bps > 8 ? (pim->Width) * 2 : pim->Width) + 15) * num_components; |
837 | 0 | pie->buffer = gs_alloc_bytes(mem, bsize, "image buffer"); |
838 | 0 | if (pie->buffer == 0) { |
839 | 0 | gs_free_object(mem, pie, "clist_begin_typed_image"); |
840 | 0 | *pinfo = NULL; |
841 | 0 | return_error(gs_error_VMerror); |
842 | 0 | } |
843 | 0 | } |
844 | 0 | } else { |
845 | 0 | pie->monitor_color = false; |
846 | | /* Check the Palette here */ |
847 | 0 | if (palette_has_color(pim->ColorSpace, pim)) { |
848 | | /* Has color. We are done monitoring */ |
849 | 0 | dev_profile->pageneutralcolor = false; |
850 | 0 | code = gsicc_mcm_end_monitor(pgs->icc_link_cache, dev); |
851 | 0 | if (code < 0) |
852 | 0 | return code; |
853 | 0 | } |
854 | 0 | } |
855 | 3.66k | } else { |
856 | 3.66k | pie->monitor_color = false; |
857 | 3.66k | } |
858 | 3.66k | if (gx_device_must_halftone(dev) && pim->BitsPerComponent == 8 && !masked && |
859 | 3.66k | (dev->color_info.num_components == 1 || is_planar_dev) && |
860 | 3.66k | dev_profile->prebandthreshold) { |
861 | 0 | int dev_width = (int)(ceil(dbox.q.x) - floor(dbox.p.x)); |
862 | 0 | int dev_height = (int)(ceil(dbox.q.y) - floor(dbox.p.y)); |
863 | |
|
864 | 0 | int src_size = pim->Height * |
865 | 0 | bitmap_raster(pim->Width * pim->BitsPerComponent * |
866 | 0 | num_components); |
867 | 0 | int des_size = dev_height * bitmap_raster(dev_width * |
868 | 0 | dev->color_info.depth); |
869 | 0 | if (src_size > des_size) |
870 | 0 | goto use_default; |
871 | 0 | } |
872 | | /* Create the begin_image command. */ |
873 | 3.66k | if ((pie->begin_image_command_length = |
874 | 3.66k | begin_image_command(pie->begin_image_command, |
875 | 3.66k | sizeof(pie->begin_image_command), pic)) < 0) |
876 | 0 | goto use_default; |
877 | 3.66k | if (!masked) { |
878 | | /* |
879 | | * Calculate (conservatively) the set of colors that this image |
880 | | * might generate. For single-component images we can sample |
881 | | * this. We generate all the possible colors now; otherwise, |
882 | | * we assume that any color might be generated. It is possible |
883 | | * to do better than this, but we won't bother unless there's |
884 | | * evidence that it's worthwhile. |
885 | | */ |
886 | 3.66k | gx_color_usage_bits all = gx_color_usage_all(cdev); |
887 | | |
888 | 3.66k | if (num_components > 1) |
889 | 1.98k | color_usage = all; |
890 | 1.67k | else { |
891 | 1.67k | const gs_color_space *pcs = pim->ColorSpace; |
892 | 1.67k | cs_proc_remap_color((*remap_color)) = pcs->type->remap_color; |
893 | 1.67k | gs_client_color cc; |
894 | 1.67k | gx_drawing_color dcolor; |
895 | 1.67k | int i; |
896 | 1.67k | int max_value = indexed ? pcs->params.indexed.hival : 1; |
897 | | |
898 | 5.03k | for (i = 0; i <= max_value; ++i) { |
899 | | /* Enumerate the indexed colors, or just Black (DeviceGray = 0) */ |
900 | 3.35k | cc.paint.values[0] = (double)i; |
901 | 3.35k | code = remap_color(&cc, pcs, &dcolor, pgs, dev, |
902 | 3.35k | gs_color_select_source); |
903 | 3.35k | if (code < 0) |
904 | 0 | break; |
905 | 3.35k | color_usage |= cmd_drawing_color_usage(cdev, &dcolor); |
906 | 3.35k | } |
907 | 1.67k | if (code < 0) |
908 | 0 | goto use_default; |
909 | 1.67k | } |
910 | 3.66k | } |
911 | 3.66k | pie->color_usage.or = color_usage; |
912 | 3.66k | pie->color_usage.slow_rop = |
913 | 3.66k | cmd_slow_rop(dev, pgs->log_op, (uses_color ? pdcolor : NULL)); |
914 | 3.66k | pie->color_map_is_known = false; |
915 | | /* |
916 | | * Calculate a (slightly conservative) Y bounding interval for the image |
917 | | * in device space. |
918 | | */ |
919 | 3.66k | { |
920 | 3.66k | int y0 = (int)floor(dbox.p.y - 0.51); /* adjust + rounding slop */ |
921 | 3.66k | int y1 = (int)ceil(dbox.q.y + 0.51); /* ditto */ |
922 | | |
923 | 3.66k | if (lpcpath) { |
924 | 3.66k | gs_fixed_rect obox; |
925 | 3.66k | gx_cpath_outer_box(lpcpath, &obox); |
926 | 3.66k | pie->ymin = max(0, max(y0, fixed2int(obox.p.y))); |
927 | 3.66k | pie->ymax = min(min(y1, fixed2int(obox.q.y)), dev->height); |
928 | 3.66k | } else { |
929 | 0 | pie->ymin = max(y0, 0); |
930 | 0 | pie->ymax = min(y1, dev->height); |
931 | 0 | } |
932 | 3.66k | } |
933 | | |
934 | | /* |
935 | | * Make sure the CTM, color space, and clipping region (and, for |
936 | | * masked images or images with CombineWithColor, the current color) |
937 | | * are known at the time of the begin_image command. |
938 | | */ |
939 | 3.66k | cmd_clear_known(cdev, clist_image_unknowns(dev, pie) | begin_image_known); |
940 | | /* Because the rendering intent may be driven by the source color |
941 | | settings we may have needed to overide the intent. Need to break the const |
942 | | on the pgs here for this and reset back */ |
943 | 3.66k | if (intent_changed) |
944 | 0 | pgs_nonconst->renderingintent = renderingintent; |
945 | 3.66k | if (bp_changed) |
946 | 0 | pgs_nonconst->blackptcomp = blackptcomp; |
947 | | |
948 | 3.66k | cdev->image_enum_id = pie->id; |
949 | 3.66k | return 0; |
950 | | /* |
951 | | * We couldn't handle the image. It is up to the caller to use the default |
952 | | * algorithms, which break the image up into rectangles or small pixmaps. |
953 | | * If we are doing the PDF14 transparency device then we want to make sure we do |
954 | | * NOT use the target device. In this case we return -1. |
955 | | */ |
956 | 1.06k | use_default: |
957 | 1.06k | if (pie != NULL) |
958 | 1.06k | gs_free_object(mem, pie->buffer, "clist_begin_typed_image"); |
959 | 1.06k | gs_free_object(mem, pie, "clist_begin_typed_image"); |
960 | 1.06k | *pinfo = NULL; |
961 | | |
962 | 1.06k | if (lpcpath != NULL) |
963 | 0 | gx_cpath_free(lpcpath, "clist_begin_typed_image(lpcpath)"); |
964 | | |
965 | 1.06k | if (pgs->has_transparency){ |
966 | 1.06k | return -1; |
967 | 1.06k | } else { |
968 | 0 | return gx_default_begin_typed_image(dev, pgs, pmat, pic, prect, |
969 | 0 | pdcolor, pcpath, mem, pinfo); |
970 | 0 | } |
971 | 1.06k | } |
972 | | |
973 | | /* Error cleanup for clist_image_plane_data. */ |
974 | | static inline int |
975 | | clist_image_plane_data_retry_cleanup(gx_device *dev, clist_image_enum *pie, int yh_used, int code) |
976 | 0 | { |
977 | 0 | gx_device_clist_writer * const cdev = |
978 | 0 | &((gx_device_clist *)dev)->writer; |
979 | 0 |
|
980 | 0 | ++cdev->ignore_lo_mem_warnings; |
981 | 0 | { |
982 | 0 | code = write_image_end_all(dev, pie); |
983 | 0 | } |
984 | 0 | --cdev->ignore_lo_mem_warnings; |
985 | 0 | /* Update sub-rect */ |
986 | 0 | if (!pie->image.Interpolate) |
987 | 0 | pie->rect.p.y += yh_used; /* interpolate & mem recovery currently incompat */ |
988 | 0 | return code; |
989 | 0 | } |
990 | | |
991 | | /* Process the next piece of an image. */ |
992 | | static int |
993 | | clist_image_plane_data(gx_image_enum_common_t * info, |
994 | | const gx_image_plane_t * planes, int yh, |
995 | | int *rows_used) |
996 | 160k | { |
997 | 160k | gx_device *dev = info->dev; |
998 | 160k | gx_device_clist_writer * const cdev = |
999 | 160k | &((gx_device_clist *)dev)->writer; |
1000 | 160k | clist_image_enum *pie = (clist_image_enum *) info; |
1001 | 160k | gs_rect sbox, dbox; |
1002 | 160k | int y_orig = pie->y; |
1003 | 160k | int yh_used = min(yh, pie->rect.q.y - y_orig); |
1004 | 160k | int y0, y1; |
1005 | 160k | int ry, rheight; |
1006 | 160k | int code; |
1007 | 160k | cmd_rects_enum_t re; |
1008 | 160k | bool found_color = false; |
1009 | | |
1010 | | #ifdef DEBUG |
1011 | | if (pie->id != cdev->image_enum_id) { |
1012 | | lprintf2("end_image id = %lu != clist image id = %lu!\n", |
1013 | | (ulong) pie->id, (ulong) cdev->image_enum_id); |
1014 | | *rows_used = 0; |
1015 | | return_error(gs_error_Fatal); |
1016 | | } |
1017 | | #endif |
1018 | | |
1019 | 160k | if (info->pgs != NULL && info->pgs->level < info->pgs_level) |
1020 | 0 | return_error(gs_error_undefinedresult); |
1021 | | |
1022 | | /****** CAN'T HANDLE VARYING data_x VALUES YET ******/ |
1023 | 160k | { |
1024 | 160k | int i; |
1025 | | |
1026 | 160k | for (i = 1; i < info->num_planes; ++i) |
1027 | 0 | if (planes[i].data_x != planes[0].data_x) { |
1028 | 0 | *rows_used = 0; |
1029 | 0 | return_error(gs_error_rangecheck); |
1030 | 0 | } |
1031 | 160k | } |
1032 | 160k | sbox.p.x = pie->rect.p.x - pie->support.x; |
1033 | 160k | sbox.p.y = (y0 = y_orig) - pie->support.y; |
1034 | 160k | sbox.q.x = pie->rect.q.x + pie->support.x; |
1035 | 160k | sbox.q.y = (y1 = pie->y += yh_used) + pie->support.y; |
1036 | 160k | code = gs_bbox_transform(&sbox, &pie->matrix, &dbox); |
1037 | 160k | if (code < 0) |
1038 | 0 | return code; |
1039 | | /* |
1040 | | * In order to keep the band list consistent, we must write out |
1041 | | * the image data in precisely those bands whose begin_image |
1042 | | * Y range includes the respective image scan lines. Because of |
1043 | | * rounding, we must expand the dbox by a little extra, and then |
1044 | | * use image_band_box to calculate the precise range for each band. |
1045 | | * This is slow, but we don't see any faster way to do it in the |
1046 | | * general case. |
1047 | | */ |
1048 | 160k | { |
1049 | 160k | int ry0 = (int)floor(dbox.p.y) - 2; |
1050 | 160k | int ry1 = (int)ceil(dbox.q.y) + 2; |
1051 | 160k | int band_height0 = cdev->page_info.band_params.BandHeight; |
1052 | | |
1053 | | /* |
1054 | | * Make sure we don't go into any bands beyond the Y range |
1055 | | * determined at begin_image time. |
1056 | | */ |
1057 | 160k | if (ry0 < pie->ymin) |
1058 | 2.67k | ry0 = pie->ymin; |
1059 | 160k | if (ry1 > pie->ymax) |
1060 | 3.68k | ry1 = pie->ymax; |
1061 | | /* |
1062 | | * If the image extends off the page in the Y direction, |
1063 | | * we may have ry0 > ry1. Check for this here. |
1064 | | */ |
1065 | 160k | if (ry0 >= ry1) |
1066 | 295 | goto done; |
1067 | | /* Expand the range out to band boundaries. */ |
1068 | 160k | ry = ry0 / band_height0 * band_height0; |
1069 | 160k | rheight = min(ROUND_UP(ry1, band_height0), dev->height) - ry; |
1070 | 160k | } |
1071 | | |
1072 | 160k | if (cdev->permanent_error < 0) |
1073 | 0 | return (cdev->permanent_error); |
1074 | | /* If needed, update the trans_bbox */ |
1075 | 160k | if (cdev->pdf14_needed) { |
1076 | 160k | gs_int_rect bbox; |
1077 | | |
1078 | 160k | bbox.p.x = (int)floor(dbox.p.x); |
1079 | 160k | bbox.q.x = (int)ceil(dbox.q.x); |
1080 | 160k | bbox.p.y = pie->ymin; |
1081 | 160k | bbox.q.y = pie->ymax; |
1082 | | |
1083 | 160k | clist_update_trans_bbox(cdev, &bbox); |
1084 | 160k | } |
1085 | | /* Make sure clip_path for the cdev is not stale -- update from image_enum */ |
1086 | 160k | cdev->clip_path = NULL; |
1087 | 160k | cmd_check_clip_path(cdev, pie->pcpath); |
1088 | | |
1089 | 160k | RECT_ENUM_INIT(re, ry, rheight); |
1090 | 268k | do { |
1091 | 268k | gs_int_rect ibox; |
1092 | 268k | gs_int_rect entire_box; |
1093 | | |
1094 | 268k | RECT_STEP_INIT(re); |
1095 | | /* |
1096 | | * Just transmit the subset of the data that intersects this band. |
1097 | | * Note that y and height always define a complete band. |
1098 | | */ |
1099 | | |
1100 | 268k | if (!image_band_box(dev, pie, re.y, re.height, &ibox)) |
1101 | 0 | continue; |
1102 | | /* |
1103 | | * The transmitted subrectangle has to be computed at the time |
1104 | | * we write the begin_image command; this in turn controls how |
1105 | | * much of each scan line we write out. |
1106 | | */ |
1107 | 268k | { |
1108 | 268k | int band_ymax = min(re.band_end, pie->ymax); |
1109 | 268k | int band_ymin = max(re.band_end - re.band_height, pie->ymin); |
1110 | | |
1111 | 268k | if (!image_band_box(dev, pie, band_ymin, |
1112 | 268k | band_ymax - band_ymin, &entire_box)) |
1113 | 0 | continue; |
1114 | 268k | } |
1115 | | |
1116 | 268k | re.pcls->color_usage.or |= pie->color_usage.or; |
1117 | 268k | re.pcls->color_usage.slow_rop |= pie->color_usage.slow_rop; |
1118 | | |
1119 | | /* Write out begin_image & its preamble for this band */ |
1120 | 268k | if (!(re.pcls->known & begin_image_known)) { |
1121 | 53.1k | gs_logical_operation_t lop = pie->pgs->log_op; |
1122 | 53.1k | byte *dp; |
1123 | 53.1k | byte *bp = pie->begin_image_command + |
1124 | 53.1k | pie->begin_image_command_length; |
1125 | 53.1k | uint len; |
1126 | 53.1k | byte image_op = cmd_opv_begin_image; |
1127 | | |
1128 | | /* Make sure the gs_gstate is up to date. */ |
1129 | 53.1k | code = (pie->color_map_is_known ? 0 : |
1130 | 53.1k | cmd_put_color_mapping(cdev, pie->pgs)); |
1131 | 53.1k | pie->color_map_is_known = true; |
1132 | 53.1k | if (code >= 0) { |
1133 | 53.1k | uint want_known = ctm_known | clip_path_known | |
1134 | 53.1k | op_bm_tk_known | ais_known | |
1135 | 53.1k | fill_alpha_known | stroke_alpha_known | fill_adjust_known | |
1136 | 53.1k | (pie->color_space.id == gs_no_id ? 0 : |
1137 | 53.1k | color_space_known); |
1138 | | |
1139 | 53.1k | code = cmd_do_write_unknown(cdev, re.pcls, want_known); |
1140 | 53.1k | } |
1141 | 53.1k | if (code >= 0) |
1142 | 53.1k | code = cmd_do_enable_clip(cdev, re.pcls, pie->pcpath != NULL); |
1143 | 53.1k | if (code >= 0) |
1144 | 53.1k | code = cmd_update_lop(cdev, re.pcls, lop); |
1145 | 53.1k | if (code < 0) |
1146 | 0 | return code; |
1147 | | /* Does the result of this image depend upon the current color in the |
1148 | | * graphics state? If so, we need to send it. */ |
1149 | 53.1k | if (pie->uses_color) { |
1150 | | /* We want to write the color taking into account the entire image so */ |
1151 | | /* we set re.rect_nbands from pie->ymin and pie->ymax so that we will */ |
1152 | | /* make the decision to write 'all_bands' the same for the whole image */ |
1153 | | /* This is slightly more efficient, and is required for patterns with */ |
1154 | | /* transparency that push the group at the begin_image step. */ |
1155 | 0 | re.rect_nbands = ((pie->ymax + re.band_height - 1) / re.band_height) - |
1156 | 0 | ((pie->ymin) / re.band_height); |
1157 | 0 | code = cmd_put_drawing_color(cdev, re.pcls, &pie->dcolor, |
1158 | 0 | &re, devn_not_tile_fill); |
1159 | 0 | if (code < 0) |
1160 | 0 | return code; |
1161 | 0 | if (!pie->masked) { |
1162 | | /* In PS and PDF, masked == uses_color. In PCL, due to rops, we can |
1163 | | * have a non-imagemask image that relies on the current graphics |
1164 | | * color. C303.BIN page 20 has an example of this. Normally the above |
1165 | | * call the cmd_put_drawing_color will have sent through the halftone |
1166 | | * phase, but we can be in the situation where the current drawing |
1167 | | * color is pure (so no phase is sent), but the colors in the image |
1168 | | * are not (so a phase must be sent). Accordingly, we catch that |
1169 | | * here. */ |
1170 | 0 | if (pie->pgs->screen_phase[gs_color_select_texture].x != re.pcls->screen_phase[gs_color_select_texture].x || |
1171 | 0 | pie->pgs->screen_phase[gs_color_select_texture].y != re.pcls->screen_phase[gs_color_select_texture].y) { |
1172 | 0 | code = cmd_set_screen_phase_generic(cdev, re.pcls, |
1173 | 0 | pie->pgs->screen_phase[gs_color_select_texture].x, |
1174 | 0 | pie->pgs->screen_phase[gs_color_select_texture].y, |
1175 | 0 | gs_color_select_texture, true); |
1176 | 0 | if (code < 0) |
1177 | 0 | return code; |
1178 | 0 | } |
1179 | 0 | if (pie->pgs->screen_phase[gs_color_select_source].x != re.pcls->screen_phase[gs_color_select_source].x || |
1180 | 0 | pie->pgs->screen_phase[gs_color_select_source].y != re.pcls->screen_phase[gs_color_select_source].y) { |
1181 | 0 | code = cmd_set_screen_phase_generic(cdev, re.pcls, |
1182 | 0 | pie->pgs->screen_phase[gs_color_select_source].x, |
1183 | 0 | pie->pgs->screen_phase[gs_color_select_source].y, |
1184 | 0 | gs_color_select_source, true); |
1185 | 0 | if (code < 0) |
1186 | 0 | return code; |
1187 | 0 | } |
1188 | 0 | } |
1189 | 53.1k | } else if (0 != re.pcls->tile_phase.x || 0 != re.pcls->tile_phase.y) { |
1190 | 0 | code = cmd_set_tile_phase(cdev, re.pcls, 0, 0); |
1191 | 0 | if (code < 0) |
1192 | 0 | return code; |
1193 | 0 | } |
1194 | 53.1k | if (entire_box.p.x != 0 || entire_box.p.y != 0 || |
1195 | 53.1k | entire_box.q.x != pie->image.Width || |
1196 | 53.1k | entire_box.q.y != pie->image.Height |
1197 | 53.1k | ) { |
1198 | 53.1k | image_op = cmd_opv_begin_image_rect; |
1199 | 53.1k | cmd_put2w(entire_box.p.x, entire_box.p.y, &bp); |
1200 | 53.1k | cmd_put2w(pie->image.Width - entire_box.q.x, |
1201 | 53.1k | pie->image.Height - entire_box.q.y, &bp); |
1202 | 53.1k | } |
1203 | 53.1k | len = bp - pie->begin_image_command; |
1204 | 53.1k | code = |
1205 | 53.1k | set_cmd_put_op(&dp, cdev, re.pcls, image_op, 1 + len); |
1206 | 53.1k | if (code < 0) |
1207 | 0 | return code; |
1208 | 53.1k | memcpy(dp + 1, pie->begin_image_command, len); |
1209 | | |
1210 | | /* Mark band's begin_image as known */ |
1211 | 53.1k | re.pcls->known |= begin_image_known; |
1212 | 53.1k | } |
1213 | | |
1214 | | /* |
1215 | | * The data that we write out must use the X values set by |
1216 | | * begin_image, which may cover a larger interval than the ones |
1217 | | * actually needed for these particular scan lines if the image is |
1218 | | * rotated. |
1219 | | */ |
1220 | 268k | { |
1221 | | /* |
1222 | | * image_band_box ensures that b{x,y}{0,1} fall within |
1223 | | * pie->rect. |
1224 | | */ |
1225 | 268k | int bx0 = entire_box.p.x, bx1 = entire_box.q.x; |
1226 | 268k | int by0 = ibox.p.y, by1 = ibox.q.y; |
1227 | 268k | int bpp = pie->bits_per_plane; |
1228 | 268k | int num_planes = pie->num_planes; |
1229 | 268k | uint offsets[GS_IMAGE_MAX_COMPONENTS]; |
1230 | 268k | int i, iy, ih, xskip, xoff, nrows; |
1231 | 268k | uint bytes_per_plane, bytes_per_row, rows_per_cmd; |
1232 | | |
1233 | 268k | if (by0 < y0) |
1234 | 193k | by0 = y0; |
1235 | 268k | if (by1 > y1) |
1236 | 194k | by1 = y1; |
1237 | | /* |
1238 | | * Make sure we're skipping an integral number of pixels, by |
1239 | | * truncating the initial X coordinate to the next lower |
1240 | | * value that is an exact multiple of a byte. |
1241 | | */ |
1242 | 268k | xoff = bx0 - pie->rect.p.x; |
1243 | 268k | xskip = xoff & -(int)"\001\010\004\010\002\010\004\010"[bpp & 7]; |
1244 | 537k | for (i = 0; i < num_planes; ++i) |
1245 | 268k | offsets[i] = |
1246 | 268k | (by0 - y0) * planes[i].raster + ((xskip * bpp) >> 3); |
1247 | 268k | bytes_per_plane = ((bx1 - (pie->rect.p.x + xskip)) * bpp + 7) >> 3; |
1248 | 268k | bytes_per_row = bytes_per_plane * pie->num_planes; |
1249 | 268k | rows_per_cmd = |
1250 | 268k | (data_bits_size - cmd_largest_size) / max(bytes_per_row, 1); |
1251 | | |
1252 | 268k | if (rows_per_cmd == 0) { |
1253 | | /* The reader will have to buffer a row separately. */ |
1254 | 0 | rows_per_cmd = 1; |
1255 | 0 | } |
1256 | 268k | if (pie->monitor_color) { |
1257 | 0 | for (iy = by0, ih = by1 - by0; ih > 0; iy += nrows, ih -= nrows) { |
1258 | 0 | nrows = min(ih, rows_per_cmd); |
1259 | 0 | if (!found_color) { |
1260 | 0 | code = cmd_image_plane_data_mon(cdev, re.pcls, planes, info, |
1261 | 0 | bytes_per_plane, offsets, |
1262 | 0 | xoff - xskip, nrows, |
1263 | 0 | &found_color); |
1264 | 0 | if (found_color) { |
1265 | | /* Has color. We are done monitoring */ |
1266 | 0 | cmm_dev_profile_t *dev_profile; |
1267 | 0 | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
1268 | 0 | dev_profile->pageneutralcolor = false; |
1269 | 0 | code |= gsicc_mcm_end_monitor(pie->pgs->icc_link_cache, dev); |
1270 | 0 | pie->monitor_color = false; |
1271 | 0 | } |
1272 | 0 | } else { |
1273 | 0 | code = cmd_image_plane_data(cdev, re.pcls, planes, info, |
1274 | 0 | bytes_per_plane, offsets, |
1275 | 0 | xoff - xskip, nrows); |
1276 | 0 | } |
1277 | 0 | if (code < 0) |
1278 | 0 | return code; |
1279 | 0 | for (i = 0; i < num_planes; ++i) |
1280 | 0 | offsets[i] += planes[i].raster * nrows; |
1281 | 0 | } |
1282 | 268k | } else { |
1283 | 493k | for (iy = by0, ih = by1 - by0; ih > 0; iy += nrows, ih -= nrows) { |
1284 | 224k | nrows = min(ih, rows_per_cmd); |
1285 | 224k | code = cmd_image_plane_data(cdev, re.pcls, planes, info, |
1286 | 224k | bytes_per_plane, offsets, |
1287 | 224k | xoff - xskip, nrows); |
1288 | 224k | if (code < 0) |
1289 | 0 | return code; |
1290 | 449k | for (i = 0; i < num_planes; ++i) |
1291 | 224k | offsets[i] += planes[i].raster * nrows; |
1292 | 224k | } |
1293 | 268k | } |
1294 | 268k | } |
1295 | 268k | } while ((re.y += re.height) < re.yend); |
1296 | 160k | done: |
1297 | 160k | *rows_used = pie->y - y_orig; |
1298 | 160k | return pie->y >= pie->rect.q.y; |
1299 | 160k | } |
1300 | | |
1301 | | /* Clean up by releasing the buffers. */ |
1302 | | static int |
1303 | | clist_image_end_image(gx_image_enum_common_t * info, bool draw_last) |
1304 | 3.66k | { |
1305 | 3.66k | gx_device *dev = info->dev; |
1306 | 3.66k | gx_device_clist_writer * const cdev = |
1307 | 3.66k | &((gx_device_clist *)dev)->writer; |
1308 | 3.66k | clist_image_enum *pie = (clist_image_enum *) info; |
1309 | 3.66k | int code; |
1310 | | |
1311 | | #ifdef DEBUG |
1312 | | if (pie->id != cdev->image_enum_id) { |
1313 | | lprintf2("end_image id = %lu != clist image id = %lu!\n", |
1314 | | (ulong) pie->id, (ulong) cdev->image_enum_id); |
1315 | | return_error(gs_error_Fatal); |
1316 | | } |
1317 | | #endif |
1318 | 3.66k | code = write_image_end_all(dev, pie); |
1319 | 3.66k | cdev->image_enum_id = gs_no_id; |
1320 | 3.66k | gx_cpath_free((gx_clip_path *)pie->pcpath, "clist_image_end_image(pie->pcpath)"); |
1321 | 3.66k | cdev->clip_path = NULL; |
1322 | 3.66k | cdev->clip_path_id = gs_no_id; |
1323 | 3.66k | gx_image_free_enum(&info); |
1324 | 3.66k | return code; |
1325 | 3.66k | } |
1326 | | |
1327 | | /* Create a compositor device. */ |
1328 | | int |
1329 | | clist_composite(gx_device * dev, |
1330 | | gx_device ** pcdev, const gs_composite_t * pcte, |
1331 | | gs_gstate * pgs, gs_memory_t * mem, gx_device *cldev) |
1332 | 169k | { |
1333 | 169k | byte * dp; |
1334 | 169k | uint size = 0, size_dummy; |
1335 | 169k | gx_device_clist_writer * const cdev = |
1336 | 169k | &((gx_device_clist *)dev)->writer; |
1337 | 169k | int ry, rheight, cropping_op; |
1338 | 169k | int band_height = cdev->page_info.band_params.BandHeight; |
1339 | 169k | int last_band = cdev->nbands - 1; |
1340 | 169k | int first_band = 0, no_of_bands = cdev->nbands; |
1341 | 169k | int code = pcte->type->procs.write(pcte, 0, &size, cdev); |
1342 | 169k | int temp_cropping_min, temp_cropping_max; |
1343 | 169k | int newdev; |
1344 | | |
1345 | 169k | CMD_CHECK_LAST_OP_BLOCK_DEFINED(cdev); |
1346 | | |
1347 | | /* determine the amount of space required */ |
1348 | 169k | if (code < 0 && code != gs_error_rangecheck) |
1349 | 0 | return code; |
1350 | 169k | size += 2 + 1; /* 2 bytes for the command code, one for the id */ |
1351 | | |
1352 | | /* Create a compositor device for clist writing (if needed) */ |
1353 | 169k | code = pcte->type->procs.clist_compositor_write_update(pcte, dev, |
1354 | 169k | pcdev, pgs, mem); |
1355 | 169k | if (code < 0) |
1356 | 0 | return code; |
1357 | 169k | newdev = code == 1; |
1358 | | |
1359 | 169k | CMD_CHECK_LAST_OP_BLOCK_DEFINED(cdev); |
1360 | | |
1361 | 169k | code = pcte->type->procs.get_cropping(pcte, &ry, &rheight, cdev->cropping_min, cdev->cropping_max); |
1362 | | |
1363 | 169k | CMD_CHECK_LAST_OP_BLOCK_DEFINED(cdev); |
1364 | | |
1365 | 169k | if (code < 0) |
1366 | 0 | return code; |
1367 | | |
1368 | 169k | cropping_op = code; |
1369 | 169k | code = 0; |
1370 | | |
1371 | 169k | if (cropping_op == PUSHCROP || cropping_op == SAMEAS_PUSHCROP_BUTNOPUSH) { |
1372 | 9.98k | first_band = ry / band_height; |
1373 | 9.98k | last_band = (ry + rheight - 1) / band_height; |
1374 | 159k | } else if (cropping_op == POPCROP || cropping_op == CURRBANDS) { |
1375 | 8.75k | first_band = cdev->cropping_min / band_height; |
1376 | 8.75k | last_band = (cdev->cropping_max - 1) / band_height; |
1377 | 8.75k | } |
1378 | | |
1379 | 169k | if (last_band - first_band > no_of_bands * 2 / 3) { |
1380 | | /* Covering many bands, so write "all bands" command for shorter clist. */ |
1381 | 159k | cropping_op = ALLBANDS; |
1382 | 159k | } |
1383 | | |
1384 | | /* Using 'v' here instead of 'L' since this is used almost exclusively with |
1385 | | the transparency code */ |
1386 | | |
1387 | | #ifdef DEBUG |
1388 | | if (gs_debug_c('v')) { |
1389 | | |
1390 | | if(cropping_op != 0) { |
1391 | | |
1392 | | dmprintf2(dev->memory, "[v] cropping_op = %d. Total number of bands is %d \n", |
1393 | | cropping_op, no_of_bands); |
1394 | | dmprintf2(dev->memory, "[v] Writing out from band %d through band %d \n", |
1395 | | first_band, last_band); |
1396 | | |
1397 | | } else { |
1398 | | |
1399 | | dmprintf1(dev->memory, "[v] cropping_op = %d. Writing out to all bands \n", |
1400 | | cropping_op); |
1401 | | |
1402 | | } |
1403 | | } |
1404 | | #endif |
1405 | | |
1406 | 169k | if (cropping_op == ALLBANDS) { |
1407 | | /* overprint applies to all bands */ |
1408 | 159k | size_dummy = size; |
1409 | 159k | code = set_cmd_put_all_extended_op(& dp, |
1410 | 159k | (gx_device_clist_writer *)dev, |
1411 | 159k | cmd_opv_ext_composite, |
1412 | 159k | size ); |
1413 | 159k | if (code < 0) |
1414 | 0 | return code; |
1415 | | |
1416 | | /* insert the compositor identifier */ |
1417 | 159k | dp[2] = pcte->type->comp_id; |
1418 | | |
1419 | | /* serialize the remainder of the compositor */ |
1420 | 159k | if ((code = pcte->type->procs.write(pcte, dp + 3, &size_dummy, cdev)) < 0) |
1421 | 0 | ((gx_device_clist_writer *)dev)->cnext = dp; |
1422 | | |
1423 | 159k | if (code >= 0 && newdev) |
1424 | 1.08k | code = 1; /* Return 1 to indicate we created a new device. */ |
1425 | 159k | return code; |
1426 | 159k | } |
1427 | 10.1k | if (cropping_op == PUSHCROP) { |
1428 | 5.07k | code = clist_writer_push_cropping(cdev, ry, rheight); |
1429 | 5.07k | if (code < 0) |
1430 | 0 | return code; |
1431 | 5.07k | } |
1432 | 10.1k | if (cropping_op == SAMEAS_PUSHCROP_BUTNOPUSH) { |
1433 | | /* Set the range even though it is not pushed until the group occurs |
1434 | | This occurs only when we had blend changes with a group push */ |
1435 | 10 | temp_cropping_min = max(cdev->cropping_min, ry); |
1436 | 10 | temp_cropping_max = min(cdev->cropping_max, ry + rheight); |
1437 | 10.1k | } else { |
1438 | 10.1k | temp_cropping_min = cdev->cropping_min; |
1439 | 10.1k | temp_cropping_max = cdev->cropping_max; |
1440 | 10.1k | } |
1441 | | /* Adjust the lower and upper bound to allow for image gridfitting changing boundaries */ |
1442 | 10.1k | if (temp_cropping_min > 0) |
1443 | 9.94k | temp_cropping_min--; |
1444 | 10.1k | if (temp_cropping_max < dev->height - 1) |
1445 | 10.1k | temp_cropping_max++; |
1446 | 10.1k | if (temp_cropping_min < temp_cropping_max) { |
1447 | | /* The pdf14 compositor could be applied |
1448 | | only to bands covered by the pcte->params.bbox. */ |
1449 | 10.1k | cmd_rects_enum_t re; |
1450 | | |
1451 | 10.1k | RECT_ENUM_INIT(re, temp_cropping_min, temp_cropping_max - temp_cropping_min); |
1452 | 140k | do { |
1453 | 140k | RECT_STEP_INIT(re); |
1454 | 140k | code = set_cmd_put_extended_op(&dp, cdev, re.pcls, cmd_opv_ext_composite, size); |
1455 | 140k | if (code >= 0) { |
1456 | 140k | size_dummy = size; |
1457 | 140k | dp[2] = pcte->type->comp_id; |
1458 | 140k | code = pcte->type->procs.write(pcte, dp + 3, &size_dummy, cdev); |
1459 | 140k | } |
1460 | 140k | if (code < 0) |
1461 | 0 | return code; |
1462 | 140k | } while ((re.y += re.height) < re.yend); |
1463 | 10.1k | } |
1464 | 10.1k | if (cropping_op == POPCROP) { |
1465 | 5.07k | code = clist_writer_pop_cropping(cdev); |
1466 | 5.07k | if (code < 0) |
1467 | 0 | return code; |
1468 | 5.07k | } |
1469 | | |
1470 | 10.1k | if (newdev) |
1471 | 0 | code = 1; /* Return 1 to indicate we created a new device. */ |
1472 | | |
1473 | 10.1k | return code; |
1474 | 10.1k | } |
1475 | | |
1476 | | /* ------ Utilities ------ */ |
1477 | | |
1478 | | /* Add a command to set data_x. */ |
1479 | | static int |
1480 | | cmd_put_set_data_x(gx_device_clist_writer * cldev, gx_clist_state * pcls, |
1481 | | int data_x) |
1482 | 0 | { |
1483 | 0 | byte *dp; |
1484 | 0 | int code; |
1485 | |
|
1486 | 0 | if (data_x > 0x1f) { |
1487 | 0 | int dx_msb = data_x >> 5; |
1488 | |
|
1489 | 0 | code = set_cmd_put_op(&dp, cldev, pcls, cmd_opv_set_misc, |
1490 | 0 | 2 + cmd_size_w(dx_msb)); |
1491 | 0 | if (code >= 0) { |
1492 | 0 | dp[1] = cmd_set_misc_data_x + 0x20 + (data_x & 0x1f); |
1493 | 0 | cmd_put_w(dx_msb, dp + 2); |
1494 | 0 | } |
1495 | 0 | } else { |
1496 | 0 | code = set_cmd_put_op(&dp, cldev, pcls, cmd_opv_set_misc, 2); |
1497 | 0 | if (code >= 0) |
1498 | 0 | dp[1] = cmd_set_misc_data_x + data_x; |
1499 | 0 | } |
1500 | 0 | return code; |
1501 | 0 | } |
1502 | | |
1503 | | /* Add commands to represent a full (device) halftone. */ |
1504 | | int |
1505 | | cmd_put_halftone(gx_device_clist_writer * cldev, const gx_device_halftone * pdht) |
1506 | 0 | { |
1507 | 0 | uint ht_size = 0, req_size; |
1508 | 0 | byte * dp; |
1509 | 0 | byte * dp0 = 0; |
1510 | 0 | byte * pht_buff = 0; |
1511 | 0 | int code = gx_ht_write(pdht, (gx_device *)cldev, 0, &ht_size); |
1512 | | |
1513 | | /* |
1514 | | * Determine the required size, and if necessary allocate a buffer. |
1515 | | * |
1516 | | * The full serialized representation consists of: |
1517 | | * command code (2 bytes) |
1518 | | * length of serialized halftone (enc_u_sizew(ht_size) |
1519 | | * one or more halfton segments, which consist of: |
1520 | | * command code (2 bytes) |
1521 | | * segment size (enc_u_sizew(seg_size) (seg_size < cbuf_ht_seg_max_size) |
1522 | | * the serialized halftone segment (seg_size) |
1523 | | * |
1524 | | * Serialized halftones may be larger than the command buffer, so it |
1525 | | * is sent in segments. The cmd_opv_extend/cmd_opv_ext_put_halftone |
1526 | | * combination indicates that a device halftone is being sent, and |
1527 | | * provides the length of the entire halftone. This is followed by |
1528 | | * one or more cmd_opv_extend/cmd_opv_ext_ht_seg commands, which |
1529 | | * convey the segments of the serialized hafltone. The reader can |
1530 | | * identify the final segment by adding segment lengths. |
1531 | | * |
1532 | | * This complexity is hidden from the serialization code. If the |
1533 | | * halftone is larger than a single halftone buffer, we allocate a |
1534 | | * buffer to hold the entire representation, and divided into |
1535 | | * segments in this routine. |
1536 | | */ |
1537 | 0 | if (code < 0 && code != gs_error_rangecheck) |
1538 | 0 | return code; |
1539 | 0 | req_size = 2 + enc_u_sizew(ht_size); |
1540 | | |
1541 | | /* output the "put halftone" command */ |
1542 | 0 | if ((code = set_cmd_put_all_extended_op(&dp, cldev, cmd_opv_ext_put_halftone, req_size)) < 0) |
1543 | 0 | return code; |
1544 | 0 | dp += 2; |
1545 | 0 | enc_u_putw(ht_size, dp); |
1546 | | |
1547 | | /* see if a separate allocated buffer is required */ |
1548 | 0 | if (ht_size > cbuf_ht_seg_max_size) { |
1549 | 0 | pht_buff = gs_alloc_bytes( cldev->bandlist_memory, |
1550 | 0 | ht_size, |
1551 | 0 | "cmd_put_halftone" ); |
1552 | 0 | if (pht_buff == 0) |
1553 | 0 | return_error(gs_error_VMerror); |
1554 | 0 | } else { |
1555 | | /* send the only segment command */ |
1556 | 0 | req_size += ht_size; |
1557 | 0 | code = set_cmd_put_all_extended_op(&dp, cldev, cmd_opv_ext_put_ht_seg, req_size); |
1558 | 0 | if (code < 0) |
1559 | 0 | return code; |
1560 | 0 | dp0 = dp; |
1561 | 0 | dp += 2; |
1562 | 0 | enc_u_putw(ht_size, dp); |
1563 | 0 | pht_buff = dp; |
1564 | 0 | } |
1565 | | |
1566 | | /* serialize the halftone */ |
1567 | 0 | code = gx_ht_write(pdht, (gx_device *)cldev, pht_buff, &ht_size); |
1568 | 0 | if (code < 0) { |
1569 | 0 | if (ht_size > cbuf_ht_seg_max_size) |
1570 | 0 | gs_free_object( cldev->bandlist_memory, |
1571 | 0 | pht_buff, |
1572 | 0 | "cmd_put_halftone" ); |
1573 | 0 | else |
1574 | 0 | cldev->cnext = dp0; |
1575 | 0 | return code; |
1576 | 0 | } |
1577 | | |
1578 | | /* |
1579 | | * If the halftone fit into a single command buffer, we are done. |
1580 | | * Otherwise, process the individual segments. |
1581 | | * |
1582 | | * If bandlist memory is exhausted while processing the segments, |
1583 | | * we do not make any attempt to recover the partially submitted |
1584 | | * halftone. The reader will discard any partially sent hafltone |
1585 | | * when it receives the next cmd_opv_extend/ |
1586 | | * cmd_opv_ext_put_halftone combination. |
1587 | | */ |
1588 | 0 | if (ht_size > cbuf_ht_seg_max_size) { |
1589 | 0 | byte * pbuff = pht_buff; |
1590 | |
|
1591 | 0 | while (ht_size > 0 && code >= 0) { |
1592 | 0 | int seg_size, tmp_size; |
1593 | |
|
1594 | 0 | seg_size = ( ht_size > cbuf_ht_seg_max_size ? cbuf_ht_seg_max_size |
1595 | 0 | : ht_size ); |
1596 | 0 | tmp_size = 2 + enc_u_sizew(seg_size) + seg_size; |
1597 | 0 | code = set_cmd_put_all_extended_op(&dp, cldev, cmd_opv_ext_put_ht_seg, tmp_size); |
1598 | 0 | if (code >= 0) { |
1599 | 0 | dp += 2; |
1600 | 0 | enc_u_putw(seg_size, dp); |
1601 | 0 | memcpy(dp, pbuff, seg_size); |
1602 | 0 | ht_size -= seg_size; |
1603 | 0 | pbuff += seg_size; |
1604 | 0 | } |
1605 | 0 | } |
1606 | 0 | gs_free_object( cldev->bandlist_memory, pht_buff, "cmd_put_halftone"); |
1607 | 0 | pht_buff = 0; |
1608 | 0 | } |
1609 | |
|
1610 | 0 | if (code >= 0) |
1611 | 0 | cldev->device_halftone_id = pdht->id; |
1612 | |
|
1613 | 0 | return code; |
1614 | 0 | } |
1615 | | |
1616 | | /* Write out any necessary color mapping data. */ |
1617 | | int |
1618 | | cmd_put_color_mapping(gx_device_clist_writer * cldev, |
1619 | | const gs_gstate * pgs) |
1620 | 4.34k | { |
1621 | 4.34k | int code; |
1622 | 4.34k | const gx_device_halftone *pdht = gx_select_dev_ht(pgs); |
1623 | | |
1624 | | /* Put out the halftone, if present, and target is not contone. */ |
1625 | 4.34k | if (pdht && pdht->id != cldev->device_halftone_id && !device_is_contone(cldev->target)) { |
1626 | 0 | code = cmd_put_halftone(cldev, pdht); |
1627 | 0 | if (code < 0) |
1628 | 0 | return code; |
1629 | 0 | cldev->device_halftone_id = pdht->id; |
1630 | 0 | } |
1631 | | /* Put the under color removal and black generation functions */ |
1632 | 4.34k | code = cmd_put_color_map(cldev, cmd_map_black_generation, |
1633 | 4.34k | 0, pgs->black_generation, |
1634 | 4.34k | &cldev->black_generation_id); |
1635 | 4.34k | if (code < 0) |
1636 | 0 | return code; |
1637 | 4.34k | code = cmd_put_color_map(cldev, cmd_map_undercolor_removal, |
1638 | 4.34k | 0, pgs->undercolor_removal, |
1639 | 4.34k | &cldev->undercolor_removal_id); |
1640 | 4.34k | if (code < 0) |
1641 | 0 | return code; |
1642 | | /* Now put out the transfer functions. */ |
1643 | 4.34k | { |
1644 | 4.34k | uint which = 0; |
1645 | 4.34k | bool send_default_comp = false; |
1646 | 4.34k | int i; |
1647 | 4.34k | gs_id default_comp_id, xfer_ids[4]; |
1648 | | |
1649 | | /* |
1650 | | * Determine the ids for the transfer functions that we currently |
1651 | | * have in the set_transfer structure. The halftone xfer funcs |
1652 | | * are sent in cmd_put_halftone. |
1653 | | */ |
1654 | 4.34k | #define get_id(pgs, color, color_num) \ |
1655 | 13.0k | ((pgs->set_transfer.color != NULL && pgs->set_transfer.color_num >= 0) \ |
1656 | 13.0k | ? pgs->set_transfer.color->id\ |
1657 | 13.0k | : pgs->set_transfer.gray->id) |
1658 | | |
1659 | 4.34k | xfer_ids[0] = get_id(pgs, red, red_component_num); |
1660 | 4.34k | xfer_ids[1] = get_id(pgs, green, green_component_num); |
1661 | 4.34k | xfer_ids[2] = get_id(pgs, blue, blue_component_num); |
1662 | 4.34k | xfer_ids[3] = default_comp_id = pgs->set_transfer.gray->id; |
1663 | 4.34k | #undef get_id |
1664 | | |
1665 | 21.7k | for (i = 0; i < countof(cldev->transfer_ids); ++i) { |
1666 | 17.3k | if (xfer_ids[i] != cldev->transfer_ids[i]) |
1667 | 4.34k | which |= 1 << i; |
1668 | 17.3k | if (xfer_ids[i] == default_comp_id && |
1669 | 17.3k | cldev->transfer_ids[i] != default_comp_id) |
1670 | 4.34k | send_default_comp = true; |
1671 | 17.3k | } |
1672 | | /* There are 3 cases for transfer functions: nothing to write, */ |
1673 | | /* a single function, and multiple functions. */ |
1674 | 4.34k | if (which == 0) |
1675 | 3.25k | return 0; |
1676 | | /* |
1677 | | * Send default transfer function if changed or we need it for a |
1678 | | * component |
1679 | | */ |
1680 | 1.08k | if (send_default_comp || cldev->transfer_ids[0] != default_comp_id) { |
1681 | 1.08k | gs_id dummy = gs_no_id; |
1682 | | |
1683 | 1.08k | code = cmd_put_color_map(cldev, cmd_map_transfer, 0, |
1684 | 1.08k | pgs->set_transfer.gray, &dummy); |
1685 | 1.08k | if (code < 0) |
1686 | 0 | return code; |
1687 | | /* Sending a default will force all xfers to default */ |
1688 | 5.43k | for (i = 0; i < countof(cldev->transfer_ids); ++i) |
1689 | 4.34k | cldev->transfer_ids[i] = default_comp_id; |
1690 | 1.08k | } |
1691 | | /* Send any transfer functions which have changed */ |
1692 | 1.08k | if (cldev->transfer_ids[0] != xfer_ids[0]) { |
1693 | 0 | code = cmd_put_color_map(cldev, cmd_map_transfer_0, |
1694 | 0 | pgs->set_transfer.red_component_num, |
1695 | 0 | pgs->set_transfer.red, &cldev->transfer_ids[0]); |
1696 | 0 | if (code < 0) |
1697 | 0 | return code; |
1698 | 0 | } |
1699 | 1.08k | if (cldev->transfer_ids[1] != xfer_ids[1]) { |
1700 | 0 | code = cmd_put_color_map(cldev, cmd_map_transfer_1, |
1701 | 0 | pgs->set_transfer.green_component_num, |
1702 | 0 | pgs->set_transfer.green, &cldev->transfer_ids[1]); |
1703 | 0 | if (code < 0) |
1704 | 0 | return code; |
1705 | 0 | } |
1706 | 1.08k | if (cldev->transfer_ids[2] != xfer_ids[2]) { |
1707 | 0 | code = cmd_put_color_map(cldev, cmd_map_transfer_2, |
1708 | 0 | pgs->set_transfer.blue_component_num, |
1709 | 0 | pgs->set_transfer.blue, &cldev->transfer_ids[2]); |
1710 | 0 | if (code < 0) |
1711 | 0 | return code; |
1712 | 0 | } |
1713 | 1.08k | } |
1714 | | |
1715 | 1.08k | return 0; |
1716 | 1.08k | } |
1717 | | |
1718 | | /* |
1719 | | * Compute the subrectangle of an image that intersects a band; |
1720 | | * return false if it is empty. |
1721 | | * It is OK for this to be too large; in fact, with the present |
1722 | | * algorithm, it will be quite a bit too large if the transformation isn't |
1723 | | * well-behaved ("well-behaved" meaning either xy = yx = 0 or xx = yy = 0). |
1724 | | */ |
1725 | 0 | #define I_FLOOR(x) ((int)floor(x)) |
1726 | 0 | #define I_CEIL(x) ((int)ceil(x)) |
1727 | | static void |
1728 | | box_merge_point(gs_int_rect * pbox, double x, double y) |
1729 | 0 | { |
1730 | 0 | int t; |
1731 | |
|
1732 | 0 | if ((t = I_FLOOR(x)) < pbox->p.x) |
1733 | 0 | pbox->p.x = t; |
1734 | 0 | if ((t = I_CEIL(x)) > pbox->q.x) |
1735 | 0 | pbox->q.x = t; |
1736 | 0 | if ((t = I_FLOOR(y)) < pbox->p.y) |
1737 | 0 | pbox->p.y = t; |
1738 | 0 | if ((t = I_CEIL(y)) > pbox->q.y) |
1739 | 0 | pbox->q.y = t; |
1740 | 0 | } |
1741 | | static bool |
1742 | | image_band_box(gx_device * dev, const clist_image_enum * pie, int y, int h, |
1743 | | gs_int_rect * pbox) |
1744 | 537k | { |
1745 | 537k | fixed by0 = int2fixed(y); |
1746 | 537k | fixed by1 = int2fixed(y + h); |
1747 | 537k | int |
1748 | 537k | px = pie->rect.p.x, py = pie->rect.p.y, |
1749 | 537k | qx = pie->rect.q.x, qy = pie->rect.q.y; |
1750 | 537k | gs_fixed_rect cbox; /* device clipping box */ |
1751 | 537k | gs_rect bbox; /* cbox intersected with band */ |
1752 | | |
1753 | | /* Intersect the device clipping box and the band. */ |
1754 | 537k | (*dev_proc(dev, get_clipping_box)) (dev, &cbox); |
1755 | | /* The fixed_half here is to allow for adjustment. */ |
1756 | 537k | bbox.p.x = fixed2float(cbox.p.x - fixed_half); |
1757 | 537k | bbox.q.x = fixed2float(cbox.q.x + fixed_half); |
1758 | 537k | bbox.p.y = fixed2float(max(cbox.p.y, by0) - fixed_half); |
1759 | 537k | bbox.q.y = fixed2float(min(cbox.q.y, by1) + fixed_half); |
1760 | | /* Limit the box further if possible (because of a clipping path) */ |
1761 | 537k | if (bbox.p.y < pie->ymin) |
1762 | 8.97k | bbox.p.y = pie->ymin; |
1763 | 537k | if (bbox.q.y > pie->ymax) |
1764 | 10.0k | bbox.q.y = pie->ymax; |
1765 | | #ifdef DEBUG |
1766 | | if (gs_debug_c('b')) { |
1767 | | dmlprintf6(dev->memory, "[b]band box for (%d,%d),(%d,%d), band (%d,%d) =>\n", |
1768 | | px, py, qx, qy, y, y + h); |
1769 | | dmlprintf10(dev->memory, " (%g,%g),(%g,%g), matrix=[%g %g %g %g %g %g]\n", |
1770 | | bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y, |
1771 | | pie->matrix.xx, pie->matrix.xy, pie->matrix.yx, |
1772 | | pie->matrix.yy, pie->matrix.tx, pie->matrix.ty); |
1773 | | } |
1774 | | #endif |
1775 | 537k | if (is_xxyy(&pie->matrix) || is_xyyx(&pie->matrix)) { |
1776 | | /* |
1777 | | * The inverse transform of the band is a rectangle aligned with |
1778 | | * the coordinate axes, so we can just intersect it with the |
1779 | | * image subrectangle. |
1780 | | */ |
1781 | 537k | gs_rect ibox; /* bbox transformed back to image space */ |
1782 | | |
1783 | 537k | if (gs_bbox_transform_inverse(&bbox, &pie->matrix, &ibox) < 0) |
1784 | 0 | return false; |
1785 | 537k | pbox->p.x = max(px, I_FLOOR(ibox.p.x)); |
1786 | 537k | pbox->q.x = min(qx, I_CEIL(ibox.q.x)); |
1787 | 537k | pbox->p.y = max(py, I_FLOOR(ibox.p.y)); |
1788 | 537k | pbox->q.y = min(qy, I_CEIL(ibox.q.y)); |
1789 | 537k | } else { |
1790 | | /* |
1791 | | * The inverse transform of the band is not aligned with the |
1792 | | * axes, i.e., is a general parallelogram. To compute an exact |
1793 | | * bounding box, we need to find the intersections of this |
1794 | | * parallelogram with the image subrectangle. |
1795 | | * |
1796 | | * There is probably a much more efficient way to do this |
1797 | | * computation, but we don't know what it is. |
1798 | | */ |
1799 | 0 | gs_point rect[4]; |
1800 | 0 | gs_point corners[5]; |
1801 | 0 | int i; |
1802 | | |
1803 | | /* Store the corners of the image rectangle. */ |
1804 | 0 | rect[0].x = rect[3].x = px; |
1805 | 0 | rect[1].x = rect[2].x = qx; |
1806 | 0 | rect[0].y = rect[1].y = py; |
1807 | 0 | rect[2].y = rect[3].y = qy; |
1808 | | /* |
1809 | | * Compute the corners of the clipped band in image space. If |
1810 | | * the matrix is singular or an overflow occurs, the result will |
1811 | | * be nonsense: in this case, there isn't anything useful we |
1812 | | * can do, so return an empty intersection. |
1813 | | */ |
1814 | 0 | if (gs_point_transform_inverse(bbox.p.x, bbox.p.y, &pie->matrix, |
1815 | 0 | &corners[0]) < 0 || |
1816 | 0 | gs_point_transform_inverse(bbox.q.x, bbox.p.y, &pie->matrix, |
1817 | 0 | &corners[1]) < 0 || |
1818 | 0 | gs_point_transform_inverse(bbox.q.x, bbox.q.y, &pie->matrix, |
1819 | 0 | &corners[2]) < 0 || |
1820 | 0 | gs_point_transform_inverse(bbox.p.x, bbox.q.y, &pie->matrix, |
1821 | 0 | &corners[3]) < 0 |
1822 | 0 | ) { |
1823 | 0 | if_debug0m('b', dev->memory, |
1824 | 0 | "[b]can't inverse-transform a band corner!\n"); |
1825 | 0 | return false; |
1826 | 0 | } |
1827 | 0 | corners[4] = corners[0]; |
1828 | 0 | pbox->p.x = qx, pbox->p.y = qy; |
1829 | 0 | pbox->q.x = px, pbox->q.y = py; |
1830 | | /* |
1831 | | * We iterate over both the image rectangle and the band |
1832 | | * parallelogram in a single loop for convenience, even though |
1833 | | * there is no coupling between the two. |
1834 | | */ |
1835 | 0 | for (i = 0; i < 4; ++i) { |
1836 | 0 | gs_point pa, pt; |
1837 | 0 | double dx, dy; |
1838 | | |
1839 | | /* Check the image corner for being inside the band. */ |
1840 | 0 | pa = rect[i]; |
1841 | 0 | gs_point_transform(pa.x, pa.y, &pie->matrix, &pt); |
1842 | 0 | if (pt.x >= bbox.p.x && pt.x <= bbox.q.x && |
1843 | 0 | pt.y >= bbox.p.y && pt.y <= bbox.q.y |
1844 | 0 | ) |
1845 | 0 | box_merge_point(pbox, pa.x, pa.y); |
1846 | | /* Check the band corner for being inside the image. */ |
1847 | 0 | pa = corners[i]; |
1848 | 0 | if (pa.x >= px && pa.x <= qx && pa.y >= py && pa.y <= qy) |
1849 | 0 | box_merge_point(pbox, pa.x, pa.y); |
1850 | | /* Check for intersections of band edges with image edges. */ |
1851 | 0 | dx = corners[i + 1].x - pa.x; |
1852 | 0 | dy = corners[i + 1].y - pa.y; |
1853 | 0 | #define in_range(t, tc, p, q)\ |
1854 | 0 | (0 <= t && t <= 1 && (t = tc) >= p && t <= q) |
1855 | 0 | if (dx != 0) { |
1856 | 0 | double t = (px - pa.x) / dx; |
1857 | |
|
1858 | 0 | if_debug3m('b', dev->memory, " (px) t=%g => (%d,%g)\n", |
1859 | 0 | t, px, pa.y + t * dy); |
1860 | 0 | if (in_range(t, pa.y + t * dy, py, qy)) |
1861 | 0 | box_merge_point(pbox, (double) px, t); |
1862 | 0 | t = (qx - pa.x) / dx; |
1863 | 0 | if_debug3m('b', dev->memory, " (qx) t=%g => (%d,%g)\n", |
1864 | 0 | t, qx, pa.y + t * dy); |
1865 | 0 | if (in_range(t, pa.y + t * dy, py, qy)) |
1866 | 0 | box_merge_point(pbox, (double) qx, t); |
1867 | 0 | } |
1868 | 0 | if (dy != 0) { |
1869 | 0 | double t = (py - pa.y) / dy; |
1870 | |
|
1871 | 0 | if_debug3m('b', dev->memory, " (py) t=%g => (%g,%d)\n", |
1872 | 0 | t, pa.x + t * dx, py); |
1873 | 0 | if (in_range(t, pa.x + t * dx, px, qx)) |
1874 | 0 | box_merge_point(pbox, t, (double) py); |
1875 | 0 | t = (qy - pa.y) / dy; |
1876 | 0 | if_debug3m('b', dev->memory, " (qy) t=%g => (%g,%d)\n", |
1877 | 0 | t, pa.x + t * dx, qy); |
1878 | 0 | if (in_range(t, pa.x + t * dx, px, qx)) |
1879 | 0 | box_merge_point(pbox, t, (double) qy); |
1880 | 0 | } |
1881 | 0 | #undef in_range |
1882 | 0 | } |
1883 | 0 | } |
1884 | 537k | if_debug4m('b', dev->memory, " => (%d,%d),(%d,%d)\n", |
1885 | 537k | pbox->p.x, pbox->p.y, pbox->q.x, pbox->q.y); |
1886 | | /* |
1887 | | * If necessary, add pixels around the edges so we will have |
1888 | | * enough information to do interpolation. |
1889 | | */ |
1890 | 537k | if ((pbox->p.x -= pie->support.x) < pie->rect.p.x) |
1891 | 0 | pbox->p.x = pie->rect.p.x; |
1892 | 537k | if ((pbox->p.y -= pie->support.y) < pie->rect.p.y) |
1893 | 0 | pbox->p.y = pie->rect.p.y; |
1894 | 537k | if ((pbox->q.x += pie->support.x) > pie->rect.q.x) |
1895 | 0 | pbox->q.x = pie->rect.q.x; |
1896 | 537k | if ((pbox->q.y += pie->support.y) > pie->rect.q.y) |
1897 | 0 | pbox->q.y = pie->rect.q.y; |
1898 | 537k | return (pbox->p.x < pbox->q.x && pbox->p.y < pbox->q.y); |
1899 | 537k | } |
1900 | | |
1901 | | inline static bool |
1902 | | icc_info_notequal(clist_icc_color_t info1, clist_icc_color_t info2) |
1903 | 399 | { |
1904 | 399 | if (info1.data_cs != info2.data_cs || info1.default_match != info2.default_match || |
1905 | 399 | info1.icc_num_components != info2.icc_num_components || info1.is_lab != info2.is_lab || |
1906 | 399 | info1.icc_hash != info2.icc_hash) |
1907 | 0 | return true; |
1908 | 399 | else |
1909 | 399 | return false; |
1910 | 399 | } |
1911 | | |
1912 | | /* Determine which image-related properties are unknown */ |
1913 | | static uint /* mask of unknown properties(see pcls->known) */ |
1914 | | clist_image_unknowns(gx_device *dev, const clist_image_enum *pie) |
1915 | 3.66k | { |
1916 | 3.66k | gx_device_clist_writer * const cdev = |
1917 | 3.66k | &((gx_device_clist *)dev)->writer; |
1918 | 3.66k | const gs_gstate *const pgs = pie->pgs; |
1919 | 3.66k | uint unknown = 0; |
1920 | | |
1921 | | /* |
1922 | | * Determine if the CTM, color space, fill_adjust and clipping region, |
1923 | | * (and, for masked images or images with CombineWithColor, the current |
1924 | | * color) are unknown. Set the device state in anticipation of the |
1925 | | * values becoming known. |
1926 | | */ |
1927 | 3.66k | if (cdev->gs_gstate.ctm.xx != pgs->ctm.xx || |
1928 | 3.66k | cdev->gs_gstate.ctm.xy != pgs->ctm.xy || |
1929 | 3.66k | cdev->gs_gstate.ctm.yx != pgs->ctm.yx || |
1930 | 3.66k | cdev->gs_gstate.ctm.yy != pgs->ctm.yy || |
1931 | 3.66k | cdev->gs_gstate.ctm.tx != pgs->ctm.tx || |
1932 | 3.66k | cdev->gs_gstate.ctm.ty != pgs->ctm.ty |
1933 | 3.66k | ) { |
1934 | 1.05k | unknown |= ctm_known; |
1935 | 1.05k | cdev->gs_gstate.ctm = pgs->ctm; |
1936 | 1.05k | } |
1937 | 3.66k | if (pie->color_space.id == gs_no_id) { /* masked image */ |
1938 | 0 | cdev->color_space.space = 0; /* for GC */ |
1939 | 3.66k | } else { /* not masked */ |
1940 | 3.66k | if (cdev->color_space.id != pie->color_space.id || |
1941 | 3.66k | cdev->color_space.space != pie->color_space.space || |
1942 | 3.66k | icc_info_notequal(cdev->color_space.icc_info, pie->color_space.icc_info)) { |
1943 | 3.26k | unknown |= color_space_known; |
1944 | 3.26k | cdev->color_space.space = pie->color_space.space; |
1945 | 3.26k | cdev->color_space = pie->color_space; |
1946 | 3.26k | memcpy(&(cdev->color_space.icc_info), &(pie->color_space.icc_info), sizeof(clist_icc_color_t)); |
1947 | 3.26k | } |
1948 | 3.66k | } |
1949 | 3.66k | if (cdev->gs_gstate.fill_adjust.x != pgs->fill_adjust.x || |
1950 | 3.66k | cdev->gs_gstate.fill_adjust.y != pgs->fill_adjust.y) { |
1951 | 0 | unknown |= fill_adjust_known; |
1952 | 0 | cdev->gs_gstate.fill_adjust = pgs->fill_adjust; |
1953 | 0 | } |
1954 | 3.66k | if (cmd_check_clip_path(cdev, pie->pcpath)) |
1955 | 3.66k | unknown |= clip_path_known; |
1956 | | /* |
1957 | | * Note: overprint and overprint_mode are implemented via a compositor |
1958 | | * device, which is passed separately through the command list. Hence, |
1959 | | * though both parameters are passed in the state as well, this usually |
1960 | | * has no effect. |
1961 | | */ |
1962 | 3.66k | if (cdev->gs_gstate.overprint != pgs->overprint || |
1963 | 3.66k | cdev->gs_gstate.overprint_mode != pgs->overprint_mode || |
1964 | 3.66k | cdev->gs_gstate.blend_mode != pgs->blend_mode || |
1965 | 3.66k | cdev->gs_gstate.text_knockout != pgs->text_knockout || |
1966 | 3.66k | cdev->gs_gstate.renderingintent != pgs->renderingintent) { |
1967 | 1.18k | unknown |= op_bm_tk_known; |
1968 | 1.18k | cdev->gs_gstate.overprint = pgs->overprint; |
1969 | 1.18k | cdev->gs_gstate.overprint_mode = pgs->overprint_mode; |
1970 | 1.18k | cdev->gs_gstate.blend_mode = pgs->blend_mode; |
1971 | 1.18k | cdev->gs_gstate.text_knockout = pgs->text_knockout; |
1972 | 1.18k | cdev->gs_gstate.renderingintent = pgs->renderingintent; |
1973 | 1.18k | } |
1974 | 3.66k | if (cdev->gs_gstate.alphaisshape != pgs->alphaisshape) { |
1975 | 31 | unknown |= ais_known; |
1976 | 31 | cdev->gs_gstate.alphaisshape = pgs->alphaisshape; |
1977 | 31 | } |
1978 | 3.66k | if (cdev->gs_gstate.strokeconstantalpha != pgs->strokeconstantalpha) { |
1979 | 5 | unknown |= stroke_alpha_known; |
1980 | 5 | cdev->gs_gstate.strokeconstantalpha = pgs->strokeconstantalpha; |
1981 | 5 | } |
1982 | 3.66k | if (cdev->gs_gstate.fillconstantalpha != pgs->fillconstantalpha) { |
1983 | 26 | unknown |= fill_alpha_known; |
1984 | 26 | cdev->gs_gstate.fillconstantalpha = pgs->fillconstantalpha; |
1985 | 26 | } |
1986 | 3.66k | return unknown; |
1987 | 3.66k | } |
1988 | | |
1989 | | /* Construct the begin_image command. */ |
1990 | | static int |
1991 | | begin_image_command(byte *buf, uint buf_size, const gs_image_common_t *pic) |
1992 | 3.66k | { |
1993 | 3.66k | int i; |
1994 | 3.66k | stream s; |
1995 | 3.66k | const gs_color_space *ignore_pcs; |
1996 | 3.66k | int code; |
1997 | | |
1998 | 14.6k | for (i = 0; i < gx_image_type_table_count; ++i) |
1999 | 14.6k | if (gx_image_type_table[i] == pic->type) |
2000 | 3.66k | break; |
2001 | 3.66k | if (i >= gx_image_type_table_count) |
2002 | 0 | return_error(gs_error_rangecheck); |
2003 | 3.66k | s_init(&s, NULL); |
2004 | 3.66k | swrite_string(&s, buf, buf_size); |
2005 | 3.66k | sputc(&s, (byte)i); |
2006 | 3.66k | code = pic->type->sput(pic, &s, &ignore_pcs); |
2007 | 3.66k | return (code < 0 ? code : stell(&s)); |
2008 | 3.66k | } |
2009 | | |
2010 | | /* Write data for a partial image. */ |
2011 | | static int |
2012 | | cmd_image_plane_data(gx_device_clist_writer * cldev, gx_clist_state * pcls, |
2013 | | const gx_image_plane_t * planes, |
2014 | | const gx_image_enum_common_t * pie, |
2015 | | uint bytes_per_plane, const uint * offsets, |
2016 | | int dx, int h) |
2017 | 224k | { |
2018 | 224k | int data_x = planes[0].data_x + dx; |
2019 | 224k | uint nbytes = bytes_per_plane * pie->num_planes * h; |
2020 | 224k | uint len = 1 + cmd_size2w(h, bytes_per_plane) + nbytes; |
2021 | 224k | byte *dp; |
2022 | 224k | uint offset = 0; |
2023 | 224k | int plane, i; |
2024 | 224k | int code; |
2025 | | |
2026 | 224k | if (data_x) { |
2027 | 0 | code = cmd_put_set_data_x(cldev, pcls, data_x); |
2028 | 0 | if (code < 0) |
2029 | 0 | return code; |
2030 | 0 | offset = ((data_x & ~7) * cldev->clist_color_info.depth) >> 3; |
2031 | 0 | } |
2032 | 224k | code = set_cmd_put_op(&dp, cldev, pcls, cmd_opv_image_data, len); |
2033 | 224k | if (code < 0) |
2034 | 0 | return code; |
2035 | 224k | dp++; |
2036 | 224k | cmd_put2w(h, bytes_per_plane, &dp); |
2037 | 449k | for (plane = 0; plane < pie->num_planes; ++plane) |
2038 | 608k | for (i = 0; i < h; ++i) { |
2039 | 383k | memcpy(dp, |
2040 | 383k | planes[plane].data + i * planes[plane].raster + |
2041 | 383k | offsets[plane] + offset, |
2042 | 383k | bytes_per_plane); |
2043 | 383k | dp += bytes_per_plane; |
2044 | 383k | } |
2045 | 224k | return 0; |
2046 | 224k | } |
2047 | | |
2048 | | /* Write data for a partial image with color monitor. */ |
2049 | | static int |
2050 | | cmd_image_plane_data_mon(gx_device_clist_writer * cldev, gx_clist_state * pcls, |
2051 | | const gx_image_plane_t * planes, |
2052 | | const gx_image_enum_common_t * pie, |
2053 | | uint bytes_per_plane, const uint * offsets, |
2054 | | int dx, int h, bool *found_color) |
2055 | 0 | { |
2056 | 0 | clist_image_enum *pie_c = (clist_image_enum *) pie; |
2057 | 0 | int data_x = planes[0].data_x + dx; |
2058 | 0 | uint nbytes = bytes_per_plane * pie->num_planes * h; |
2059 | 0 | uint len = 1 + cmd_size2w(h, bytes_per_plane) + nbytes; |
2060 | 0 | byte *dp; |
2061 | 0 | uint offset = 0; |
2062 | 0 | int plane, i; |
2063 | 0 | int code; |
2064 | 0 | int width = pie_c->rect.q.x - pie_c->rect.p.x; |
2065 | 0 | int dsize = (((width + (planes[0]).data_x) * pie_c->decode.spp * |
2066 | 0 | pie_c->decode.bps / pie->num_planes + 7) >> 3); |
2067 | 0 | int data_size = pie_c->decode.spread / pie->num_planes; |
2068 | |
|
2069 | 0 | *found_color = false; |
2070 | |
|
2071 | 0 | if (data_x) { |
2072 | 0 | code = cmd_put_set_data_x(cldev, pcls, data_x); |
2073 | 0 | if (code < 0) |
2074 | 0 | return code; |
2075 | 0 | offset = ((data_x & ~7) * cldev->clist_color_info.depth) >> 3; |
2076 | 0 | } |
2077 | 0 | code = set_cmd_put_op(&dp, cldev, pcls, cmd_opv_image_data, len); |
2078 | 0 | if (code < 0) |
2079 | 0 | return code; |
2080 | 0 | dp++; |
2081 | |
|
2082 | 0 | cmd_put2w(h, bytes_per_plane, &dp); |
2083 | |
|
2084 | 0 | for (i = 0; i < h; ++i) { |
2085 | 0 | if (!(*found_color)) { |
2086 | | /* Here we need to unpack and actually look at the image data |
2087 | | to see if we have any non-neutral colors */ |
2088 | 0 | int pdata_x; |
2089 | 0 | byte *data_ptr = (byte *)(planes[0].data + i * planes[0].raster + offsets[0] + offset); |
2090 | 0 | byte *buffer = (byte *)(*pie_c->decode.unpack)(pie_c->buffer, &pdata_x, |
2091 | 0 | data_ptr, 0, dsize, pie_c->decode.map, |
2092 | 0 | pie_c->decode.spread, pie_c->decode.spp); |
2093 | |
|
2094 | 0 | for (plane = 1; plane < pie->num_planes; ++plane) { |
2095 | | /* unpack planes after the first (if any), relying on spread to place the */ |
2096 | | /* data at the correct spacing, with the buffer start adjusted for each plane */ |
2097 | 0 | data_ptr = (byte *)(planes[plane].data + i * planes[plane].raster + offsets[plane] + offset); |
2098 | 0 | (*pie_c->decode.unpack)(pie_c->buffer + (data_size * plane), &pdata_x, data_ptr, 0, |
2099 | 0 | dsize, pie_c->decode.map, pie_c->decode.spread, pie_c->decode.spp); |
2100 | 0 | } |
2101 | 0 | if (row_has_color(buffer, pie_c, data_size, width)) { |
2102 | | /* Has color. We are done monitoring */ |
2103 | 0 | *found_color = true; |
2104 | 0 | } |
2105 | 0 | } |
2106 | | /* Now copy the plane data into the clist buffer */ |
2107 | 0 | for (plane = 0; plane < pie->num_planes; ++plane) { |
2108 | 0 | memcpy(dp, planes[plane].data + i * planes[plane].raster + |
2109 | 0 | offsets[plane] + offset, bytes_per_plane); |
2110 | 0 | dp += bytes_per_plane; |
2111 | 0 | } |
2112 | 0 | } |
2113 | 0 | return 0; |
2114 | 0 | } |
2115 | | |
2116 | | /* Write image_end commands into all bands */ |
2117 | | static int /* ret 0 ok, else -ve error status */ |
2118 | | write_image_end_all(gx_device *dev, const clist_image_enum *pie) |
2119 | 3.66k | { |
2120 | 3.66k | gx_device_clist_writer * const cdev = |
2121 | 3.66k | &((gx_device_clist *)dev)->writer; |
2122 | 3.66k | int code; |
2123 | 3.66k | int ry = pie->ymin; |
2124 | 3.66k | int rheight = pie->ymax - ry; |
2125 | 3.66k | cmd_rects_enum_t re; |
2126 | | |
2127 | | /* |
2128 | | * We need to check specially for images lying entirely outside the |
2129 | | * page, since the RECT writing logic doesn't do this. |
2130 | | */ |
2131 | 3.66k | if (pie->ymax < 0 || ry >= dev->height) |
2132 | 4 | return 0; |
2133 | 3.66k | if (cdev->permanent_error < 0) |
2134 | 0 | return (cdev->permanent_error); |
2135 | 3.66k | RECT_ENUM_INIT(re, ry, rheight); |
2136 | 81.5k | do { |
2137 | 81.5k | byte *dp; |
2138 | | |
2139 | 81.5k | RECT_STEP_INIT(re); |
2140 | 81.5k | if (re.pcls->known & begin_image_known) { |
2141 | 53.1k | if_debug1m('L', dev->memory, "[L]image_end for band %d\n", re.band); |
2142 | 53.1k | code = set_cmd_put_op(&dp, cdev, re.pcls, cmd_opv_image_data, 2); |
2143 | 53.1k | if (code < 0) |
2144 | 0 | return code; |
2145 | 53.1k | dp[1] = 0; /* EOD */ |
2146 | 53.1k | re.pcls->known ^= begin_image_known; |
2147 | 53.1k | } |
2148 | 81.5k | } while ((re.y += re.height) < re.yend); |
2149 | | /* Make sure to clean up the buffer if we were monitoring */ |
2150 | 3.66k | if (pie->buffer != NULL) { |
2151 | 0 | gs_free_object(pie->memory, pie->buffer, "write_image_end_all"); |
2152 | 0 | } |
2153 | 3.66k | return 0; |
2154 | 3.66k | } |
2155 | | |
2156 | | /* |
2157 | | * Compare a rectangle vs. clip path. Return true if there is no clipping |
2158 | | * path, if the rectangle is unclipped, or if the clipping path is a |
2159 | | * rectangle and intersects the given rectangle. |
2160 | | */ |
2161 | | static bool |
2162 | | check_rect_for_trivial_clip( |
2163 | | const gx_clip_path *pcpath, /* May be NULL, clip to evaluate */ |
2164 | | int px, int py, int qx, int qy /* corners of box to test */ |
2165 | | ) |
2166 | 0 | { |
2167 | 0 | gs_fixed_rect obox; |
2168 | 0 | gs_fixed_rect imgbox; |
2169 | |
|
2170 | 0 | if (!pcpath) |
2171 | 0 | return true; |
2172 | | |
2173 | 0 | imgbox.p.x = int2fixed(px); |
2174 | 0 | imgbox.p.y = int2fixed(py); |
2175 | 0 | imgbox.q.x = int2fixed(qx); |
2176 | 0 | imgbox.q.y = int2fixed(qy); |
2177 | 0 | if (gx_cpath_includes_rectangle(pcpath, |
2178 | 0 | imgbox.p.x, imgbox.p.y, |
2179 | 0 | imgbox.q.x, imgbox.q.y)) |
2180 | 0 | return true; |
2181 | | |
2182 | 0 | return (gx_cpath_outer_box(pcpath, &obox) /* cpath is rectangle */ && |
2183 | 0 | obox.p.x <= imgbox.q.x && obox.q.x >= imgbox.p.x && |
2184 | 0 | obox.p.y <= imgbox.q.y && obox.q.y >= imgbox.p.y ); |
2185 | 0 | } |