/src/ghostpdl/base/gdevmpla.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 | | /* Any-depth planar "memory" (stored bitmap) device */ |
17 | | #include "memory_.h" |
18 | | #include "gx.h" |
19 | | #include "gserrors.h" |
20 | | #include "gsbitops.h" |
21 | | #include "gxdevice.h" |
22 | | #include "gxdcolor.h" /* for gx_fill_rectangle_device_rop */ |
23 | | #include "gxpcolor.h" /* for gx_dc_devn_masked */ |
24 | | #include "gxdevmem.h" /* semi-public definitions */ |
25 | | #include "gxgetbit.h" |
26 | | #include "gdevmem.h" /* private definitions */ |
27 | | #include "gdevmpla.h" /* interface */ |
28 | | #include "gxdevsop.h" |
29 | | |
30 | | /* procedures */ |
31 | | static dev_proc_open_device(mem_planar_open); |
32 | | static dev_proc_open_device(mem_planar_open_interleaved); |
33 | | declare_mem_procs(mem_planar_copy_mono, mem_planar_copy_color, mem_planar_fill_rectangle); |
34 | | static dev_proc_copy_color(mem_planar_copy_color_24to8); |
35 | | static dev_proc_copy_color(mem_planar_copy_color_4to1); |
36 | | static dev_proc_copy_planes(mem_planar_copy_planes); |
37 | | /* Not static due to an optimized case in tile_clip_fill_rectangle_hl_color*/ |
38 | | static dev_proc_strip_tile_rectangle(mem_planar_strip_tile_rectangle); |
39 | | static dev_proc_strip_tile_rect_devn(mem_planar_strip_tile_rect_devn); |
40 | | static dev_proc_strip_copy_rop2(mem_planar_strip_copy_rop2); |
41 | | static dev_proc_get_bits_rectangle(mem_planar_get_bits_rectangle); |
42 | | static dev_proc_fill_rectangle_hl_color(mem_planar_fill_rectangle_hl_color); |
43 | | static dev_proc_put_image(mem_planar_put_image); |
44 | | |
45 | | int |
46 | | mem_spec_op(gx_device *pdev, int dev_spec_op, |
47 | | void *data, int size) |
48 | 436M | { |
49 | 436M | cmm_dev_profile_t *dev_profile; |
50 | 436M | gx_device_memory *mdev = (gx_device_memory *)pdev; |
51 | | |
52 | 436M | if (pdev->num_planar_planes && |
53 | 436M | (dev_spec_op == gxdso_supports_devn || |
54 | 33.0M | dev_spec_op == gxdso_skip_icc_component_validation)) { |
55 | 954k | dev_proc(pdev, get_profile)(pdev, &dev_profile); |
56 | 954k | if (dev_profile != NULL && dev_profile->supports_devn && |
57 | 954k | dev_proc(pdev, fill_rectangle_hl_color) == mem_planar_fill_rectangle_hl_color) |
58 | 954k | return 1; |
59 | 954k | } |
60 | 435M | if (dev_spec_op == gxdso_is_std_cmyk_1bit) |
61 | 386M | return dev_proc(pdev, copy_color) == mem_planar_copy_color_4to1; |
62 | 49.5M | if (dev_spec_op == gxdso_is_pdf14_device || dev_spec_op == gxdso_pattern_handles_clip_path) |
63 | 4.10k | return 0; |
64 | 49.5M | if (mdev->owner) |
65 | 49.5M | return dev_proc(mdev->owner, dev_spec_op)(mdev->owner, dev_spec_op, data, size); |
66 | 19.4k | return gx_default_dev_spec_op(pdev, dev_spec_op, data, size); |
67 | 49.5M | } |
68 | | |
69 | | /* |
70 | | * Set up a planar memory device, after calling gs_make_mem_device but |
71 | | * before opening the device. The pre-existing device provides the color |
72 | | * mapping procedures, but not the drawing procedures. Requires: num_planes |
73 | | * > 0, plane_depths[0 .. num_planes - 1] > 0, sum of plane depths = |
74 | | * mdev->color_info.depth. |
75 | | * |
76 | | * Note that this is the only public procedure in this file, and the only |
77 | | * sanctioned way to set up a planar memory device. |
78 | | */ |
79 | | int |
80 | | gdev_mem_set_planar(gx_device_memory * mdev, int num_planes, |
81 | | const gx_render_plane_t *planes /*[num_planes]*/) |
82 | 7.70M | { |
83 | 7.70M | return gdev_mem_set_planar_interleaved(mdev, num_planes, planes, 0); |
84 | 7.70M | } |
85 | | |
86 | | int |
87 | | gdev_mem_set_planar_interleaved(gx_device_memory * mdev, int num_planes, |
88 | | const gx_render_plane_t *planes /*[num_planes]*/, |
89 | | int interleaved) |
90 | 7.70M | { |
91 | 7.70M | int total_depth; |
92 | 7.70M | int same_depth = planes[0].depth; |
93 | 7.70M | gx_color_index covered = 0; |
94 | 7.70M | int pi; |
95 | 7.70M | const gdev_mem_functions *fns = |
96 | 7.70M | gdev_mem_functions_for_bits(mdev->color_info.depth); |
97 | | |
98 | 7.70M | if (num_planes < 1 || num_planes > GX_DEVICE_COLOR_MAX_COMPONENTS || num_planes < mdev->color_info.num_components) |
99 | 0 | return_error(gs_error_rangecheck); |
100 | 48.2M | for (pi = 0, total_depth = 0; pi < num_planes; ++pi) { |
101 | 40.5M | int shift = planes[pi].shift; |
102 | 40.5M | int plane_depth = planes[pi].depth; |
103 | 40.5M | gx_color_index mask; |
104 | | |
105 | 40.5M | if (shift < 0 || plane_depth > 16 || |
106 | 40.5M | !gdev_mem_device_for_bits(plane_depth)) |
107 | 0 | return_error(gs_error_rangecheck); |
108 | | /* Don't test overlap if shift is too large to fit in the variable */ |
109 | 40.5M | if (shift < 8*sizeof(gx_color_index)) |
110 | 39.6M | { |
111 | 39.6M | mask = (((gx_color_index)1 << plane_depth) - 1) << shift; |
112 | 39.6M | if (covered & mask) |
113 | 0 | return_error(gs_error_rangecheck); |
114 | 39.6M | covered |= mask; |
115 | 39.6M | } |
116 | 40.5M | if (plane_depth != same_depth) |
117 | 0 | same_depth = 0; |
118 | 40.5M | total_depth += plane_depth; |
119 | 40.5M | } |
120 | 7.70M | if (total_depth > mdev->color_info.depth) |
121 | 0 | return_error(gs_error_rangecheck); |
122 | 7.70M | mdev->num_planar_planes = num_planes; |
123 | 7.70M | memcpy(mdev->planes, planes, num_planes * sizeof(planes[0])); |
124 | 7.70M | mdev->plane_depth = same_depth; |
125 | | /* Change the drawing procedures. */ |
126 | 7.70M | if (interleaved) |
127 | 0 | set_dev_proc(mdev, open_device, mem_planar_open_interleaved); |
128 | 7.70M | else |
129 | 7.70M | set_dev_proc(mdev, open_device, mem_planar_open); |
130 | | /* Regardless of how many planes we are using, always let the |
131 | | * device know how to handle hl_color. Even if we spot that we |
132 | | * can get away with a normal device, our callers may want to |
133 | | * feed us single component devn data. */ |
134 | 7.70M | set_dev_proc(mdev, fill_rectangle_hl_color, |
135 | 7.70M | mem_planar_fill_rectangle_hl_color); |
136 | 7.70M | if (num_planes == 1) { |
137 | | /* For 1 plane, just use a normal device */ |
138 | 0 | set_dev_proc(mdev, fill_rectangle, fns->fill_rectangle); |
139 | 0 | set_dev_proc(mdev, copy_mono, fns->copy_mono); |
140 | 0 | set_dev_proc(mdev, copy_color, fns->copy_color); |
141 | 0 | set_dev_proc(mdev, copy_alpha, fns->copy_alpha); |
142 | 0 | set_dev_proc(mdev, strip_tile_rectangle, fns->strip_tile_rectangle); |
143 | 0 | set_dev_proc(mdev, strip_copy_rop2, fns->strip_copy_rop2); |
144 | 0 | set_dev_proc(mdev, get_bits_rectangle, fns->get_bits_rectangle); |
145 | 7.70M | } else { |
146 | | /* If we are going out to a separation device or one that has more than |
147 | | four planes then use the high level color filling procedure. Also |
148 | | make use of the put_image operation to go from the pdf14 device |
149 | | directly to the planar buffer. */ |
150 | 7.70M | if (num_planes >= 4) { |
151 | | /* put_image always gives us our data in bytes (or 16bits) per |
152 | | * component. When we have a suitably deep device we can assume |
153 | | * that this will match our own representation, and use a fast |
154 | | * copy_planes based implementation. If not, we have to use the |
155 | | * default's copy-via-image implementation. */ |
156 | 7.70M | if (mdev->color_info.depth / num_planes >= 8) |
157 | 219k | set_dev_proc(mdev, put_image, mem_planar_put_image); |
158 | 7.70M | } |
159 | 7.70M | set_dev_proc(mdev, fill_rectangle, mem_planar_fill_rectangle); |
160 | 7.70M | set_dev_proc(mdev, copy_alpha_hl_color, gx_default_copy_alpha_hl_color); |
161 | 7.70M | set_dev_proc(mdev, copy_mono, mem_planar_copy_mono); |
162 | 7.70M | if ((mdev->color_info.depth == 24) && |
163 | 7.70M | (num_planes == 3) && |
164 | 7.70M | (mdev->planes[0].depth == 8) && (mdev->planes[0].shift == 16) && |
165 | 7.70M | (mdev->planes[1].depth == 8) && (mdev->planes[1].shift == 8) && |
166 | 7.70M | (mdev->planes[2].depth == 8) && (mdev->planes[2].shift == 0)) |
167 | 161 | set_dev_proc(mdev, copy_color, mem_planar_copy_color_24to8); |
168 | 7.70M | else if ((mdev->color_info.depth == 4) && |
169 | 7.70M | (num_planes == 4) && |
170 | 7.70M | (mdev->planes[0].depth == 1) && (mdev->planes[0].shift == 3) && |
171 | 7.70M | (mdev->planes[1].depth == 1) && (mdev->planes[1].shift == 2) && |
172 | 7.70M | (mdev->planes[2].depth == 1) && (mdev->planes[2].shift == 1) && |
173 | 7.70M | (mdev->planes[3].depth == 1) && (mdev->planes[3].shift == 0)) { |
174 | 6.57M | set_dev_proc(mdev, copy_color, mem_planar_copy_color_4to1); |
175 | 6.57M | } else |
176 | 1.13M | set_dev_proc(mdev, copy_color, mem_planar_copy_color); |
177 | 7.70M | set_dev_proc(mdev, copy_alpha, gx_default_copy_alpha); |
178 | 7.70M | set_dev_proc(mdev, strip_tile_rectangle, mem_planar_strip_tile_rectangle); |
179 | 7.70M | set_dev_proc(mdev, strip_tile_rect_devn, mem_planar_strip_tile_rect_devn); |
180 | 7.70M | set_dev_proc(mdev, strip_copy_rop2, mem_planar_strip_copy_rop2); |
181 | 7.70M | set_dev_proc(mdev, get_bits_rectangle, mem_planar_get_bits_rectangle); |
182 | 7.70M | } |
183 | 7.70M | fill_dev_proc(mdev, dev_spec_op, mem_spec_op); |
184 | 7.70M | set_dev_proc(mdev, copy_planes, mem_planar_copy_planes); |
185 | 7.70M | return 0; |
186 | 7.70M | } |
187 | | |
188 | | /* Open a planar memory device. */ |
189 | | static int |
190 | | mem_planar_open(gx_device * dev) |
191 | 504 | { |
192 | 504 | gx_device_memory *const mdev = (gx_device_memory *)dev; |
193 | | |
194 | | /* Check that we aren't trying to open a chunky device as planar. */ |
195 | 504 | if (!dev->num_planar_planes) |
196 | 0 | return_error(gs_error_rangecheck); |
197 | 504 | return gdev_mem_open_scan_lines(mdev, dev->height); |
198 | 504 | } |
199 | | |
200 | | static int |
201 | | mem_planar_open_interleaved(gx_device * dev) |
202 | 0 | { |
203 | 0 | gx_device_memory *const mdev = (gx_device_memory *)dev; |
204 | | |
205 | | /* Check that we aren't trying to open a chunky device as planar. */ |
206 | 0 | if (!dev->num_planar_planes) |
207 | 0 | return_error(gs_error_rangecheck); |
208 | 0 | return gdev_mem_open_scan_lines_interleaved(mdev, dev->height, 1); |
209 | 0 | } |
210 | | |
211 | | /* |
212 | | * We execute drawing operations by patching a few parameters in the |
213 | | * device structure and then calling the procedure appropriate to the |
214 | | * plane depth. |
215 | | */ |
216 | | typedef struct mem_save_params_s { |
217 | | int depth; /* color_info.depth */ |
218 | | byte *base; |
219 | | byte **line_ptrs; |
220 | | } mem_save_params_t; |
221 | | #define MEM_SAVE_PARAMS(mdev, msp)\ |
222 | 54.7M | (msp.depth = mdev->color_info.depth,\ |
223 | 54.7M | msp.base = mdev->base,\ |
224 | 54.7M | msp.line_ptrs = mdev->line_ptrs) |
225 | | /* Previous versions of MEM_SET_PARAMS calculated raster as |
226 | | * bitmap_raster(mdev->width * plane_depth), but this restricts us to |
227 | | * non interleaved frame buffers. Now we calculate it from the difference |
228 | | * between the first 2 line pointers; this clearly only works if there are |
229 | | * at least 2 line pointers to use. Otherwise, we fall back to the old |
230 | | * method. |
231 | | */ |
232 | | /* FIXME: Find a nicer way of calculating raster. This is only required if |
233 | | * we allow the plane_depth to vary per plane, and the rest of the code |
234 | | * assumes that it never does. This can probably be simplified now. */ |
235 | | #define MEM_SET_PARAMS(mdev, plane_depth)\ |
236 | 160M | (mdev->color_info.depth = plane_depth, /* maybe not needed */\ |
237 | 160M | mdev->base = mdev->line_ptrs[0],\ |
238 | 160M | mdev->raster = (mdev->height > 1 ? mdev->line_ptrs[1]-mdev->line_ptrs[0] : bitmap_raster(mdev->width * plane_depth))) |
239 | | #define MEM_RESTORE_PARAMS(mdev, msp)\ |
240 | 54.7M | (mdev->color_info.depth = msp.depth,\ |
241 | 54.7M | mdev->base = msp.base,\ |
242 | 54.7M | mdev->line_ptrs = msp.line_ptrs) |
243 | | |
244 | | /* Note tag_offset == 0 if there is no tag plane. Tags always follow the |
245 | | color data, but not neccessarily right after. */ |
246 | | static int |
247 | | put_image_copy_planes(gx_device * dev, const byte **base_ptr, int sourcex, |
248 | | int sraster, gx_bitmap_id id, |
249 | | int x, int y, int w, int h, int tag_offset) |
250 | 158 | { |
251 | 158 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
252 | 158 | int plane_depth; |
253 | 158 | mem_save_params_t save; |
254 | 158 | const gdev_mem_functions *fns; |
255 | 158 | int code = 0; |
256 | 158 | int plane; |
257 | 158 | const byte *base; |
258 | 158 | int last_plane = mdev->num_planar_planes - 1; |
259 | | |
260 | 158 | MEM_SAVE_PARAMS(mdev, save); |
261 | 804 | for (plane = 0; plane < mdev->num_planar_planes; plane++) |
262 | 646 | { |
263 | 646 | if (tag_offset && plane == last_plane) |
264 | 0 | base = base_ptr[tag_offset]; |
265 | 646 | else |
266 | 646 | base = base_ptr[plane]; |
267 | 646 | plane_depth = mdev->planes[plane].depth; |
268 | 646 | fns = gdev_mem_functions_for_bits(plane_depth); |
269 | 646 | if (base == NULL) { |
270 | | /* Blank the plane */ |
271 | 0 | code = fns->fill_rectangle(dev, x, y, w, h, |
272 | 0 | (gx_color_index)(dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE ? 0 : -1)); |
273 | 646 | } else if (plane_depth == 1) |
274 | 0 | code = fns->copy_mono(dev, base, sourcex, sraster, id, |
275 | 0 | x, y, w, h, |
276 | 0 | (gx_color_index)0, (gx_color_index)1); |
277 | 646 | else |
278 | 646 | fns->copy_color(dev, base, sourcex, sraster, id, x, y, w, h); |
279 | 646 | mdev->line_ptrs += mdev->height; |
280 | 646 | } |
281 | 158 | MEM_RESTORE_PARAMS(mdev, save); |
282 | 158 | return code; |
283 | 158 | } |
284 | | |
285 | | /* Put image command for copying the planar image buffers with or without |
286 | | alpha directly to the device buffer */ |
287 | | static int |
288 | | mem_planar_put_image(gx_device *pdev, gx_device *pmdev, const byte **buffers, int num_chan, int xstart, |
289 | | int ystart, int width, int height, int row_stride, |
290 | | int alpha_plane_index, int tag_plane_index) |
291 | 158 | { |
292 | | /* We don't want alpha, return 0 to ask for the pdf14 device to do the |
293 | | alpha composition. We also do not want chunky data coming in */ |
294 | 158 | if (alpha_plane_index != 0) |
295 | 0 | return 0; |
296 | | |
297 | 158 | put_image_copy_planes(pdev, buffers, 0, row_stride, |
298 | 158 | gx_no_bitmap_id, xstart, ystart, |
299 | 158 | width, height, tag_plane_index); |
300 | | |
301 | | /* we used all of the data */ |
302 | 158 | return height; |
303 | 158 | } |
304 | | |
305 | | /* Fill a rectangle with a high level color. This is used for separation |
306 | | devices. (e.g. tiffsep, psdcmyk) */ |
307 | | static int |
308 | | mem_planar_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, |
309 | | const gs_gstate *pgs, const gx_drawing_color *pdcolor, |
310 | | const gx_clip_path *pcpath) |
311 | 2.55M | { |
312 | 2.55M | gx_device_memory * const mdev = (gx_device_memory *)dev; |
313 | 2.55M | mem_save_params_t save; |
314 | 2.55M | int pi; |
315 | 2.55M | int x = fixed2int(rect->p.x); |
316 | 2.55M | int y = fixed2int(rect->p.y); |
317 | 2.55M | int w = fixed2int(rect->q.x) - x; |
318 | 2.55M | int h = fixed2int(rect->q.y) - y; |
319 | 2.55M | int has_tags = device_encodes_tags(dev); |
320 | 2.55M | int npp = mdev->num_planar_planes - has_tags; |
321 | | |
322 | | /* We can only handle devn cases, so use the default if not */ |
323 | | /* We can get called here from gx_dc_devn_masked_fill_rectangle */ |
324 | 2.55M | if (pdcolor->type != gx_dc_type_devn && pdcolor->type != &gx_dc_devn_masked) { |
325 | 0 | return gx_fill_rectangle_device_rop( x, y, w, h, pdcolor, dev, lop_default); |
326 | 0 | } |
327 | 2.55M | MEM_SAVE_PARAMS(mdev, save); |
328 | 12.7M | for (pi = 0; pi < npp; ++pi) { |
329 | 10.1M | int plane_depth = mdev->planes[pi].depth; |
330 | 10.1M | gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1; |
331 | 10.1M | int shift = 16 - plane_depth; |
332 | 10.1M | const gdev_mem_functions *fns = |
333 | 10.1M | gdev_mem_functions_for_bits(plane_depth); |
334 | | |
335 | 10.1M | MEM_SET_PARAMS(mdev, plane_depth); |
336 | 10.1M | fns->fill_rectangle(dev, x, y, w, h, |
337 | 10.1M | (pdcolor->colors.devn.values[pi]) >> shift & mask); |
338 | 10.1M | mdev->line_ptrs += mdev->height; |
339 | 10.1M | } |
340 | 2.55M | if (has_tags) { |
341 | 0 | int plane_depth = mdev->planes[pi].depth; |
342 | 0 | gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1; |
343 | 0 | const gdev_mem_functions *fns = |
344 | 0 | gdev_mem_functions_for_bits(plane_depth); |
345 | |
|
346 | 0 | MEM_SET_PARAMS(mdev, plane_depth); |
347 | 0 | fns->fill_rectangle(dev, x, y, w, h, |
348 | 0 | (pdcolor->colors.devn.values[pi]) & mask); |
349 | 0 | mdev->line_ptrs += mdev->height; |
350 | 0 | } |
351 | 2.55M | MEM_RESTORE_PARAMS(mdev, save); |
352 | 2.55M | return 0; |
353 | 2.55M | } |
354 | | |
355 | | /* Fill a rectangle with a color. */ |
356 | | static int |
357 | | mem_planar_fill_rectangle(gx_device * dev, int x, int y, int w, int h, |
358 | | gx_color_index color) |
359 | 24.3M | { |
360 | 24.3M | gx_device_memory * const mdev = (gx_device_memory *)dev; |
361 | 24.3M | mem_save_params_t save; |
362 | 24.3M | int pi; |
363 | | |
364 | 24.3M | MEM_SAVE_PARAMS(mdev, save); |
365 | 121M | for (pi = 0; pi < mdev->num_planar_planes; ++pi) { |
366 | 97.5M | int plane_depth = mdev->planes[pi].depth; |
367 | 97.5M | gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1; |
368 | 97.5M | const gdev_mem_functions *fns = |
369 | 97.5M | gdev_mem_functions_for_bits(plane_depth); |
370 | | |
371 | 97.5M | MEM_SET_PARAMS(mdev, plane_depth); |
372 | 97.5M | fns->fill_rectangle(dev, x, y, w, h, |
373 | 97.5M | (color >> mdev->planes[pi].shift) & mask); |
374 | 97.5M | mdev->line_ptrs += mdev->height; |
375 | 97.5M | } |
376 | 24.3M | MEM_RESTORE_PARAMS(mdev, save); |
377 | 24.3M | return 0; |
378 | 24.3M | } |
379 | | |
380 | | /* Copy a bitmap. */ |
381 | | static int |
382 | | mem_planar_copy_mono(gx_device * dev, const byte * base, int sourcex, |
383 | | int sraster, gx_bitmap_id id, int x, int y, int w, int h, |
384 | | gx_color_index color0, gx_color_index color1) |
385 | 580k | { |
386 | 580k | gx_device_memory * const mdev = (gx_device_memory *)dev; |
387 | 580k | mem_save_params_t save; |
388 | 580k | int pi; |
389 | | |
390 | 580k | MEM_SAVE_PARAMS(mdev, save); |
391 | 2.97M | for (pi = 0; pi < mdev->num_planar_planes; ++pi) { |
392 | 2.39M | int plane_depth = mdev->planes[pi].depth; |
393 | 2.39M | int shift = mdev->planes[pi].shift; |
394 | 2.39M | gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1; |
395 | 2.39M | const gdev_mem_functions *fns = |
396 | 2.39M | gdev_mem_functions_for_bits(plane_depth); |
397 | 2.39M | gx_color_index c0 = |
398 | 2.39M | (color0 == gx_no_color_index ? gx_no_color_index : |
399 | 2.39M | (color0 >> shift) & mask); |
400 | 2.39M | gx_color_index c1 = |
401 | 2.39M | (color1 == gx_no_color_index ? gx_no_color_index : |
402 | 2.39M | (color1 >> shift) & mask); |
403 | | |
404 | 2.39M | MEM_SET_PARAMS(mdev, plane_depth); |
405 | 2.39M | if (c0 == c1) |
406 | 66.6k | fns->fill_rectangle(dev, x, y, w, h, c0); |
407 | 2.32M | else |
408 | 2.32M | fns->copy_mono(dev, base, sourcex, sraster, id, |
409 | 2.32M | x, y, w, h, c0, c1); |
410 | 2.39M | mdev->line_ptrs += mdev->height; |
411 | 2.39M | } |
412 | 580k | MEM_RESTORE_PARAMS(mdev, save); |
413 | 580k | return 0; |
414 | 580k | } |
415 | | |
416 | | /* Copy color: Special case the 24 -> 8+8+8 case. */ |
417 | | static int |
418 | | mem_planar_copy_color_24to8(gx_device * dev, const byte * base, int sourcex, |
419 | | int sraster, gx_bitmap_id id, |
420 | | int x, int y, int w, int h) |
421 | 0 | { |
422 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
423 | 0 | #define BUF_LONGS 100 /* arbitrary, >= 1 */ |
424 | 0 | #define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG) |
425 | 0 | union b_ { |
426 | 0 | ulong l[BUF_LONGS]; |
427 | 0 | byte b[BUF_BYTES]; |
428 | 0 | } buf, buf1, buf2; |
429 | 0 | mem_save_params_t save; |
430 | 0 | dev_proc_copy_color((*copy_color)) = |
431 | 0 | gdev_mem_functions_for_bits(8)->copy_color; |
432 | 0 | uint plane_raster = bitmap_raster(w<<3); |
433 | 0 | int br, bw, bh, cx, cy, cw, ch, ix, iy; |
434 | |
|
435 | 0 | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
436 | 0 | MEM_SAVE_PARAMS(mdev, save); |
437 | 0 | MEM_SET_PARAMS(mdev, 8); |
438 | 0 | if (plane_raster > BUF_BYTES) { |
439 | 0 | br = BUF_BYTES; |
440 | 0 | bw = BUF_BYTES; |
441 | 0 | bh = 1; |
442 | 0 | } else { |
443 | 0 | br = plane_raster; |
444 | 0 | bw = w; |
445 | 0 | bh = BUF_BYTES / plane_raster; |
446 | 0 | } |
447 | 0 | for (cy = y; cy < y + h; cy += ch) { |
448 | 0 | ch = min(bh, y + h - cy); |
449 | 0 | for (cx = x; cx < x + w; cx += cw) { |
450 | 0 | int sx = sourcex + cx - x; |
451 | 0 | const byte *source_base = base + sraster * (cy - y); |
452 | |
|
453 | 0 | cw = min(bw, x + w - cx); |
454 | 0 | source_base += sx * 3; |
455 | 0 | for (iy = 0; iy < ch; ++iy) { |
456 | 0 | const byte *sptr = source_base; |
457 | 0 | byte *dptr0 = buf.b + br * iy; |
458 | 0 | byte *dptr1 = buf1.b + br * iy; |
459 | 0 | byte *dptr2 = buf2.b + br * iy; |
460 | 0 | ix = cw; |
461 | 0 | do { |
462 | | /* Use the temporary variables below to free the C compiler |
463 | | * to interleave load/stores for latencies sake despite the |
464 | | * pointer aliasing rules. */ |
465 | 0 | byte r = *sptr++; |
466 | 0 | byte g = *sptr++; |
467 | 0 | byte b = *sptr++; |
468 | 0 | *dptr0++ = r; |
469 | 0 | *dptr1++ = g; |
470 | 0 | *dptr2++ = b; |
471 | 0 | } while (--ix); |
472 | 0 | source_base += sraster; |
473 | 0 | } |
474 | 0 | copy_color(dev, buf.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch); |
475 | 0 | mdev->line_ptrs += mdev->height; |
476 | 0 | copy_color(dev, buf1.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch); |
477 | 0 | mdev->line_ptrs += mdev->height; |
478 | 0 | copy_color(dev, buf2.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch); |
479 | 0 | mdev->line_ptrs -= 2*mdev->height; |
480 | 0 | } |
481 | 0 | } |
482 | 0 | MEM_RESTORE_PARAMS(mdev, save); |
483 | 0 | return 0; |
484 | 0 | } |
485 | | |
486 | | /* Copy color: Special case the 4 -> 1+1+1+1 case. */ |
487 | | /* Two versions of this routine; the first does bit comparisons. This should |
488 | | * work well on architectures with small cache and conditional execution |
489 | | * (such as ARM). Hurts on x86 due to the ifs in the loop all causing small |
490 | | * skips ahead that defeat the branch predictor. |
491 | | * Second version uses a table lookup; 1K of table is nothing on x86, and |
492 | | * so this runs much faster. */ |
493 | | #ifdef PREFER_ALTERNATIION_TO_TABLES |
494 | | static int |
495 | | mem_planar_copy_color_4to1(gx_device * dev, const byte * base, int sourcex, |
496 | | int sraster, gx_bitmap_id id, |
497 | | int x, int y, int w, int h) |
498 | | { |
499 | | gx_device_memory * const mdev = (gx_device_memory *)dev; |
500 | | #define BUF_LONGS 100 /* arbitrary, >= 1 */ |
501 | | #define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG) |
502 | | union b_ { |
503 | | ulong l[BUF_LONGS]; |
504 | | byte b[BUF_BYTES]; |
505 | | } buf0, buf1, buf2, buf3; |
506 | | mem_save_params_t save; |
507 | | dev_proc_copy_mono((*copy_mono)) = |
508 | | gdev_mem_fill_functions_for_bits(1)->copy_mono; |
509 | | uint plane_raster = bitmap_raster(w); |
510 | | int br, bw, bh, cx, cy, cw, ch, ix, iy; |
511 | | |
512 | | #ifdef MEMENTO |
513 | | /* Pacify valgrind */ |
514 | | memset(buf0.l, 0, sizeof(ulong) * BUF_LONGS); |
515 | | memset(buf1.l, 0, sizeof(ulong) * BUF_LONGS); |
516 | | memset(buf2.l, 0, sizeof(ulong) * BUF_LONGS); |
517 | | memset(buf3.l, 0, sizeof(ulong) * BUF_LONGS); |
518 | | #endif |
519 | | |
520 | | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
521 | | MEM_SAVE_PARAMS(mdev, save); |
522 | | MEM_SET_PARAMS(mdev, 1); |
523 | | if (plane_raster > BUF_BYTES) { |
524 | | br = BUF_BYTES; |
525 | | bw = BUF_BYTES<<3; |
526 | | bh = 1; |
527 | | } else { |
528 | | br = plane_raster; |
529 | | bw = w; |
530 | | bh = BUF_BYTES / plane_raster; |
531 | | } |
532 | | for (cy = y; cy < y + h; cy += ch) { |
533 | | ch = min(bh, y + h - cy); |
534 | | for (cx = x; cx < x + w; cx += cw) { |
535 | | int sx = sourcex + cx - x; |
536 | | const byte *source_base = base + sraster * (cy - y) + (sx>>1); |
537 | | |
538 | | cw = min(bw, x + w - cx); |
539 | | if ((sx & 1) == 0) { |
540 | | for (iy = 0; iy < ch; ++iy) { |
541 | | const byte *sptr = source_base; |
542 | | byte *dptr0 = buf0.b + br * iy; |
543 | | byte *dptr1 = buf1.b + br * iy; |
544 | | byte *dptr2 = buf2.b + br * iy; |
545 | | byte *dptr3 = buf3.b + br * iy; |
546 | | byte roll = 0x80; |
547 | | byte bc = 0; |
548 | | byte bm = 0; |
549 | | byte by = 0; |
550 | | byte bk = 0; |
551 | | ix = cw; |
552 | | do { |
553 | | byte b = *sptr++; |
554 | | if (b & 0x80) |
555 | | bc |= roll; |
556 | | if (b & 0x40) |
557 | | bm |= roll; |
558 | | if (b & 0x20) |
559 | | by |= roll; |
560 | | if (b & 0x10) |
561 | | bk |= roll; |
562 | | roll >>= 1; |
563 | | if (b & 0x08) |
564 | | bc |= roll; |
565 | | if (b & 0x04) |
566 | | bm |= roll; |
567 | | if (b & 0x02) |
568 | | by |= roll; |
569 | | if (b & 0x01) |
570 | | bk |= roll; |
571 | | roll >>= 1; |
572 | | if (roll == 0) { |
573 | | *dptr0++ = bc; |
574 | | *dptr1++ = bm; |
575 | | *dptr2++ = by; |
576 | | *dptr3++ = bk; |
577 | | bc = 0; |
578 | | bm = 0; |
579 | | by = 0; |
580 | | bk = 0; |
581 | | roll = 0x80; |
582 | | } |
583 | | ix -= 2; |
584 | | } while (ix > 0); |
585 | | if (roll != 0x80) { |
586 | | *dptr0++ = bc; |
587 | | *dptr1++ = bm; |
588 | | *dptr2++ = by; |
589 | | *dptr3++ = bk; |
590 | | } |
591 | | source_base += sraster; |
592 | | } |
593 | | } else { |
594 | | for (iy = 0; iy < ch; ++iy) { |
595 | | const byte *sptr = source_base; |
596 | | byte *dptr0 = buf0.b + br * iy; |
597 | | byte *dptr1 = buf1.b + br * iy; |
598 | | byte *dptr2 = buf2.b + br * iy; |
599 | | byte *dptr3 = buf3.b + br * iy; |
600 | | byte roll = 0x80; |
601 | | byte bc = 0; |
602 | | byte bm = 0; |
603 | | byte by = 0; |
604 | | byte bk = 0; |
605 | | byte b = *sptr++; |
606 | | ix = cw; |
607 | | goto loop_entry; |
608 | | do { |
609 | | b = *sptr++; |
610 | | if (b & 0x80) |
611 | | bc |= roll; |
612 | | if (b & 0x40) |
613 | | bm |= roll; |
614 | | if (b & 0x20) |
615 | | by |= roll; |
616 | | if (b & 0x10) |
617 | | bk |= roll; |
618 | | roll >>= 1; |
619 | | if (roll == 0) { |
620 | | *dptr0++ = bc; |
621 | | *dptr1++ = bm; |
622 | | *dptr2++ = by; |
623 | | *dptr3++ = bk; |
624 | | bc = 0; |
625 | | bm = 0; |
626 | | by = 0; |
627 | | bk = 0; |
628 | | roll = 0x80; |
629 | | } |
630 | | loop_entry: |
631 | | if (b & 0x08) |
632 | | bc |= roll; |
633 | | if (b & 0x04) |
634 | | bm |= roll; |
635 | | if (b & 0x02) |
636 | | by |= roll; |
637 | | if (b & 0x01) |
638 | | bk |= roll; |
639 | | roll >>= 1; |
640 | | ix -= 2; |
641 | | } while (ix >= 0); /* ix == -2 means 1 extra done */ |
642 | | if ((ix == -2) && (roll == 0x40)) { |
643 | | /* We did an extra one, and it was the last thing |
644 | | * we did. Nothing to store. */ |
645 | | } else { |
646 | | /* Flush the stored bytes */ |
647 | | *dptr0++ = bc; |
648 | | *dptr1++ = bm; |
649 | | *dptr2++ = by; |
650 | | *dptr3++ = bk; |
651 | | } |
652 | | source_base += sraster; |
653 | | } |
654 | | } |
655 | | copy_mono(dev, buf0.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch, |
656 | | (gx_color_index)0, (gx_color_index)1); |
657 | | mdev->line_ptrs += mdev->height; |
658 | | copy_mono(dev, buf1.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch, |
659 | | (gx_color_index)0, (gx_color_index)1); |
660 | | mdev->line_ptrs += mdev->height; |
661 | | copy_mono(dev, buf2.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch, |
662 | | (gx_color_index)0, (gx_color_index)1); |
663 | | mdev->line_ptrs += mdev->height; |
664 | | copy_mono(dev, buf3.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch, |
665 | | (gx_color_index)0, (gx_color_index)1); |
666 | | mdev->line_ptrs -= 3*mdev->height; |
667 | | } |
668 | | } |
669 | | MEM_RESTORE_PARAMS(mdev, save); |
670 | | return 0; |
671 | | } |
672 | | #else |
673 | | |
674 | | static bits32 expand_4to1[256] = |
675 | | { |
676 | | 0x00000000,0x00000001,0x00000100,0x00000101, |
677 | | 0x00010000,0x00010001,0x00010100,0x00010101, |
678 | | 0x01000000,0x01000001,0x01000100,0x01000101, |
679 | | 0x01010000,0x01010001,0x01010100,0x01010101, |
680 | | 0x00000002,0x00000003,0x00000102,0x00000103, |
681 | | 0x00010002,0x00010003,0x00010102,0x00010103, |
682 | | 0x01000002,0x01000003,0x01000102,0x01000103, |
683 | | 0x01010002,0x01010003,0x01010102,0x01010103, |
684 | | 0x00000200,0x00000201,0x00000300,0x00000301, |
685 | | 0x00010200,0x00010201,0x00010300,0x00010301, |
686 | | 0x01000200,0x01000201,0x01000300,0x01000301, |
687 | | 0x01010200,0x01010201,0x01010300,0x01010301, |
688 | | 0x00000202,0x00000203,0x00000302,0x00000303, |
689 | | 0x00010202,0x00010203,0x00010302,0x00010303, |
690 | | 0x01000202,0x01000203,0x01000302,0x01000303, |
691 | | 0x01010202,0x01010203,0x01010302,0x01010303, |
692 | | 0x00020000,0x00020001,0x00020100,0x00020101, |
693 | | 0x00030000,0x00030001,0x00030100,0x00030101, |
694 | | 0x01020000,0x01020001,0x01020100,0x01020101, |
695 | | 0x01030000,0x01030001,0x01030100,0x01030101, |
696 | | 0x00020002,0x00020003,0x00020102,0x00020103, |
697 | | 0x00030002,0x00030003,0x00030102,0x00030103, |
698 | | 0x01020002,0x01020003,0x01020102,0x01020103, |
699 | | 0x01030002,0x01030003,0x01030102,0x01030103, |
700 | | 0x00020200,0x00020201,0x00020300,0x00020301, |
701 | | 0x00030200,0x00030201,0x00030300,0x00030301, |
702 | | 0x01020200,0x01020201,0x01020300,0x01020301, |
703 | | 0x01030200,0x01030201,0x01030300,0x01030301, |
704 | | 0x00020202,0x00020203,0x00020302,0x00020303, |
705 | | 0x00030202,0x00030203,0x00030302,0x00030303, |
706 | | 0x01020202,0x01020203,0x01020302,0x01020303, |
707 | | 0x01030202,0x01030203,0x01030302,0x01030303, |
708 | | 0x02000000,0x02000001,0x02000100,0x02000101, |
709 | | 0x02010000,0x02010001,0x02010100,0x02010101, |
710 | | 0x03000000,0x03000001,0x03000100,0x03000101, |
711 | | 0x03010000,0x03010001,0x03010100,0x03010101, |
712 | | 0x02000002,0x02000003,0x02000102,0x02000103, |
713 | | 0x02010002,0x02010003,0x02010102,0x02010103, |
714 | | 0x03000002,0x03000003,0x03000102,0x03000103, |
715 | | 0x03010002,0x03010003,0x03010102,0x03010103, |
716 | | 0x02000200,0x02000201,0x02000300,0x02000301, |
717 | | 0x02010200,0x02010201,0x02010300,0x02010301, |
718 | | 0x03000200,0x03000201,0x03000300,0x03000301, |
719 | | 0x03010200,0x03010201,0x03010300,0x03010301, |
720 | | 0x02000202,0x02000203,0x02000302,0x02000303, |
721 | | 0x02010202,0x02010203,0x02010302,0x02010303, |
722 | | 0x03000202,0x03000203,0x03000302,0x03000303, |
723 | | 0x03010202,0x03010203,0x03010302,0x03010303, |
724 | | 0x02020000,0x02020001,0x02020100,0x02020101, |
725 | | 0x02030000,0x02030001,0x02030100,0x02030101, |
726 | | 0x03020000,0x03020001,0x03020100,0x03020101, |
727 | | 0x03030000,0x03030001,0x03030100,0x03030101, |
728 | | 0x02020002,0x02020003,0x02020102,0x02020103, |
729 | | 0x02030002,0x02030003,0x02030102,0x02030103, |
730 | | 0x03020002,0x03020003,0x03020102,0x03020103, |
731 | | 0x03030002,0x03030003,0x03030102,0x03030103, |
732 | | 0x02020200,0x02020201,0x02020300,0x02020301, |
733 | | 0x02030200,0x02030201,0x02030300,0x02030301, |
734 | | 0x03020200,0x03020201,0x03020300,0x03020301, |
735 | | 0x03030200,0x03030201,0x03030300,0x03030301, |
736 | | 0x02020202,0x02020203,0x02020302,0x02020303, |
737 | | 0x02030202,0x02030203,0x02030302,0x02030303, |
738 | | 0x03020202,0x03020203,0x03020302,0x03020303, |
739 | | 0x03030202,0x03030203,0x03030302,0x03030303 |
740 | | }; |
741 | | |
742 | | static int |
743 | | mem_planar_copy_color_4to1(gx_device * dev, const byte * base, int sourcex, |
744 | | int sraster, gx_bitmap_id id, |
745 | | int x, int y, int w, int h) |
746 | 19.1M | { |
747 | 19.1M | gx_device_memory * const mdev = (gx_device_memory *)dev; |
748 | 37.8M | #define BUF_LONGS 100 /* arbitrary, >= 1 */ |
749 | 37.8M | #define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG) |
750 | 19.1M | union b_ { |
751 | 19.1M | ulong l[BUF_LONGS]; |
752 | 19.1M | byte b[BUF_BYTES]; |
753 | 19.1M | } buf0, buf1, buf2, buf3; |
754 | 19.1M | mem_save_params_t save; |
755 | 19.1M | dev_proc_copy_mono((*copy_mono)) = |
756 | 19.1M | gdev_mem_functions_for_bits(1)->copy_mono; |
757 | 19.1M | uint plane_raster = bitmap_raster(w); |
758 | 19.1M | int br, bw, bh, cx, cy, cw, ch, ix, iy; |
759 | | |
760 | 19.1M | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
761 | 18.9M | MEM_SAVE_PARAMS(mdev, save); |
762 | 18.9M | MEM_SET_PARAMS(mdev, 1); |
763 | 18.9M | if (plane_raster > BUF_BYTES) { |
764 | 0 | br = BUF_BYTES; |
765 | 0 | bw = BUF_BYTES<<3; |
766 | 0 | bh = 1; |
767 | 18.9M | } else { |
768 | 18.9M | br = plane_raster; |
769 | 18.9M | bw = w; |
770 | 18.9M | bh = BUF_BYTES / plane_raster; |
771 | 18.9M | } |
772 | 37.8M | for (cy = y; cy < y + h; cy += ch) { |
773 | 18.9M | ch = min(bh, y + h - cy); |
774 | 37.8M | for (cx = x; cx < x + w; cx += cw) { |
775 | 18.9M | int sx = sourcex + cx - x; |
776 | 18.9M | const byte *source_base = base + sraster * (cy - y) + (sx>>1); |
777 | | |
778 | 18.9M | cw = min(bw, x + w - cx); |
779 | 18.9M | if ((sx & 1) == 0) { |
780 | 39.8M | for (iy = 0; iy < ch; ++iy) { |
781 | 21.2M | const byte *sptr = source_base; |
782 | 21.2M | byte *dptr0 = buf0.b + br * iy; |
783 | 21.2M | byte *dptr1 = buf1.b + br * iy; |
784 | 21.2M | byte *dptr2 = buf2.b + br * iy; |
785 | 21.2M | byte *dptr3 = buf3.b + br * iy; |
786 | 21.2M | int roll = 6; |
787 | 21.2M | int cmyk = 0; |
788 | 21.2M | ix = cw; |
789 | 348M | do { |
790 | 348M | cmyk |= expand_4to1[*sptr++]<<roll; |
791 | 348M | roll -= 2; |
792 | 348M | if (roll < 0) { |
793 | 79.1M | *dptr0++ = cmyk>>24; |
794 | 79.1M | *dptr1++ = cmyk>>16; |
795 | 79.1M | *dptr2++ = cmyk>>8; |
796 | 79.1M | *dptr3++ = cmyk; |
797 | 79.1M | cmyk = 0; |
798 | 79.1M | roll = 6; |
799 | 79.1M | } |
800 | 348M | ix -= 2; |
801 | 348M | } while (ix > 0); |
802 | 21.2M | if (roll != 6) { |
803 | 19.2M | *dptr0++ = cmyk>>24; |
804 | 19.2M | *dptr1++ = cmyk>>16; |
805 | 19.2M | *dptr2++ = cmyk>>8; |
806 | 19.2M | *dptr3++ = cmyk; |
807 | 19.2M | } |
808 | 21.2M | source_base += sraster; |
809 | 21.2M | } |
810 | 18.6M | } else { |
811 | 750k | for (iy = 0; iy < ch; ++iy) { |
812 | 450k | const byte *sptr = source_base; |
813 | 450k | byte *dptr0 = buf0.b + br * iy; |
814 | 450k | byte *dptr1 = buf1.b + br * iy; |
815 | 450k | byte *dptr2 = buf2.b + br * iy; |
816 | 450k | byte *dptr3 = buf3.b + br * iy; |
817 | 450k | int roll = 7; |
818 | 450k | int cmyk = 0; |
819 | 450k | byte b = *sptr++ & 0x0f; |
820 | 450k | ix = cw; |
821 | 450k | goto loop_entry; |
822 | 8.82M | do { |
823 | 8.82M | b = *sptr++; |
824 | 8.82M | roll -= 2; |
825 | 8.82M | if (roll < 0) |
826 | 2.06M | { |
827 | 2.06M | cmyk |= expand_4to1[b & 0xf0]>>1; |
828 | 2.06M | *dptr0++ = cmyk>>24; |
829 | 2.06M | *dptr1++ = cmyk>>16; |
830 | 2.06M | *dptr2++ = cmyk>>8; |
831 | 2.06M | *dptr3++ = cmyk; |
832 | 2.06M | cmyk = 0; |
833 | 2.06M | roll = 7; |
834 | 2.06M | b &= 0x0f; |
835 | 2.06M | } |
836 | 9.27M | loop_entry: |
837 | 9.27M | cmyk |= expand_4to1[b]<<roll; |
838 | 9.27M | ix -= 2; |
839 | 9.27M | } while (ix >= 0); /* ix == -2 means 1 extra done */ |
840 | 450k | if ((ix == -2) && (roll == 7)) { |
841 | | /* We did an extra one, and it was the last thing |
842 | | * we did. Nothing to store. */ |
843 | 435k | } else { |
844 | | /* Flush the stored bytes */ |
845 | 435k | *dptr0++ = cmyk>>24; |
846 | 435k | *dptr1++ = cmyk>>16; |
847 | 435k | *dptr2++ = cmyk>>8; |
848 | 435k | *dptr3++ = cmyk; |
849 | 435k | } |
850 | 450k | source_base += sraster; |
851 | 450k | } |
852 | 299k | } |
853 | 18.9M | copy_mono(dev, buf0.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch, |
854 | 18.9M | (gx_color_index)0, (gx_color_index)1); |
855 | 18.9M | mdev->line_ptrs += mdev->height; |
856 | 18.9M | copy_mono(dev, buf1.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch, |
857 | 18.9M | (gx_color_index)0, (gx_color_index)1); |
858 | 18.9M | mdev->line_ptrs += mdev->height; |
859 | 18.9M | copy_mono(dev, buf2.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch, |
860 | 18.9M | (gx_color_index)0, (gx_color_index)1); |
861 | 18.9M | mdev->line_ptrs += mdev->height; |
862 | 18.9M | copy_mono(dev, buf3.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch, |
863 | 18.9M | (gx_color_index)0, (gx_color_index)1); |
864 | 18.9M | mdev->line_ptrs -= 3*mdev->height; |
865 | 18.9M | } |
866 | 18.9M | } |
867 | 18.9M | MEM_RESTORE_PARAMS(mdev, save); |
868 | 18.9M | return 0; |
869 | 18.9M | } |
870 | | #endif |
871 | | |
872 | | /* Copy a color bitmap. */ |
873 | | /* This is slow and messy. */ |
874 | | static int |
875 | | mem_planar_copy_color(gx_device * dev, const byte * base, int sourcex, |
876 | | int sraster, gx_bitmap_id id, |
877 | | int x, int y, int w, int h) |
878 | 38.1k | { |
879 | 38.1k | gx_device_memory * const mdev = (gx_device_memory *)dev; |
880 | 513k | #define BUF_LONGS 100 /* arbitrary, >= 1 */ |
881 | 513k | #define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG) |
882 | 38.1k | union b_ { |
883 | 38.1k | ulong l[BUF_LONGS]; |
884 | 38.1k | byte b[BUF_BYTES]; |
885 | 38.1k | } buf; |
886 | 38.1k | int source_depth = dev->color_info.depth; |
887 | 38.1k | mem_save_params_t save; |
888 | 38.1k | int pi; |
889 | | |
890 | | /* This routine cannot copy from 3bit chunky data, as 3 bit |
891 | | * things don't pack nicely into bytes or words. Accordingly |
892 | | * treat 3 bit things as 4 bit things. This is appropriate as |
893 | | * 3 bit data will generally have been passed to us as 4bit |
894 | | * data - such as halftones. */ |
895 | 38.1k | if (source_depth == 3) |
896 | 0 | source_depth = 4; |
897 | | |
898 | 38.1k | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
899 | 38.1k | MEM_SAVE_PARAMS(mdev, save); |
900 | 294k | for (pi = 0; pi < mdev->num_planar_planes; ++pi) { |
901 | 256k | int plane_depth = mdev->planes[pi].depth; |
902 | 256k | int shift = mdev->planes[pi].shift; |
903 | 256k | gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1; |
904 | 256k | const gdev_mem_functions *fns = |
905 | 256k | gdev_mem_functions_for_bits(plane_depth); |
906 | | /* |
907 | | * Divide up the transfer into chunks that can be assembled |
908 | | * within the fixed-size buffer. This code can be simplified |
909 | | * a lot if all planes have the same depth, by simply using |
910 | | * copy_color to transfer one column at a time, but it might |
911 | | * be very inefficient. |
912 | | */ |
913 | 256k | uint plane_raster = bitmap_raster(plane_depth * w); |
914 | 256k | int br, bw, bh, cx, cy, cw, ch, ix, iy; |
915 | | |
916 | 256k | MEM_SET_PARAMS(mdev, plane_depth); |
917 | 256k | if (plane_raster > BUF_BYTES) { |
918 | 0 | br = BUF_BYTES; |
919 | 0 | bw = BUF_BYTES * 8 / plane_depth; |
920 | 0 | bh = 1; |
921 | 256k | } else { |
922 | 256k | br = plane_raster; |
923 | 256k | bw = w; |
924 | 256k | bh = BUF_BYTES / plane_raster; |
925 | 256k | } |
926 | | /* |
927 | | * We could do the extraction with get_bits_rectangle |
928 | | * selecting a single plane, but this is critical enough |
929 | | * code that we more or less replicate it here. |
930 | | */ |
931 | 514k | for (cy = y; cy < y + h; cy += ch) { |
932 | 257k | ch = min(bh, y + h - cy); |
933 | 515k | for (cx = x; cx < x + w; cx += cw) { |
934 | 257k | int sx = sourcex + cx - x; |
935 | 257k | const byte *source_base = base + sraster * (cy - y); |
936 | 257k | int source_bit = 0; |
937 | | |
938 | 257k | cw = min(bw, x + w - cx); |
939 | 257k | if (sx) { |
940 | 5.69k | int xbit = sx * source_depth; |
941 | | |
942 | 5.69k | source_base += xbit >> 3; |
943 | 5.69k | source_bit = xbit & 7; |
944 | 5.69k | } |
945 | 1.08M | for (iy = 0; iy < ch; ++iy) { |
946 | 829k | const byte *sptr =source_base; |
947 | 829k | int sbit = source_bit; |
948 | 829k | byte *dptr = buf.b + br * iy; |
949 | 829k | int dbit = 0; |
950 | 829k | byte dbbyte = (dbit ? (byte)(*dptr & (0xff00 >> dbit)) : 0); |
951 | | |
952 | 17.3M | for (ix = 0; ix < cw; ++ix) { |
953 | 16.4M | gx_color_index value; |
954 | | |
955 | 16.4M | if (sizeof(value) > 4){ |
956 | 16.4M | if (sample_load_next64((uint64_t *)&value, &sptr, &sbit, source_depth) < 0) |
957 | 0 | return_error(gs_error_rangecheck); |
958 | 16.4M | } |
959 | 0 | else { |
960 | 0 | if (sample_load_next32((uint32_t *)&value, &sptr, &sbit, source_depth) < 0) |
961 | 0 | return_error(gs_error_rangecheck); |
962 | 0 | } |
963 | 16.4M | value = (value >> shift) & mask; |
964 | 16.4M | if (sample_store_next16(value, &dptr, &dbit, plane_depth, |
965 | 16.4M | &dbbyte) < 0) |
966 | 0 | return_error(gs_error_rangecheck); |
967 | 16.4M | } |
968 | 829k | sample_store_flush(dptr, dbit, dbbyte); |
969 | 829k | source_base += sraster; |
970 | 829k | } |
971 | | /* |
972 | | * Detect and bypass the possibility that copy_color is |
973 | | * defined in terms of copy_mono. |
974 | | */ |
975 | 257k | if (plane_depth == 1) |
976 | 257k | fns->copy_mono |
977 | 257k | (dev, buf.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch, |
978 | 257k | (gx_color_index)0, (gx_color_index)1); |
979 | 0 | else |
980 | 0 | fns->copy_color |
981 | 0 | (dev, buf.b, 0, br, gx_no_bitmap_id, cx, cy, cw, ch); |
982 | 257k | } |
983 | 257k | } |
984 | 256k | mdev->line_ptrs += mdev->height; |
985 | 256k | } |
986 | 38.1k | MEM_RESTORE_PARAMS(mdev, save); |
987 | 38.1k | return 0; |
988 | 38.1k | #undef BUF_BYTES |
989 | 38.1k | #undef BUF_LONGS |
990 | 38.1k | } |
991 | | |
992 | | /* Copy a given bitmap into a bitmap. */ |
993 | | static int |
994 | | mem_planar_copy_planes(gx_device * dev, const byte * base, int sourcex, |
995 | | int sraster, gx_bitmap_id id, |
996 | | int x, int y, int w, int h, int plane_height) |
997 | 474k | { |
998 | 474k | gx_device_memory * const mdev = (gx_device_memory *)dev; |
999 | 474k | mem_save_params_t save; |
1000 | 474k | int code = 0; |
1001 | 474k | int plane; |
1002 | | |
1003 | 474k | MEM_SAVE_PARAMS(mdev, save); |
1004 | 2.37M | for (plane = 0; plane < mdev->num_planar_planes; plane++) |
1005 | 1.89M | { |
1006 | 1.89M | int plane_depth = mdev->planes[plane].depth; |
1007 | 1.89M | const gdev_mem_functions *fns = |
1008 | 1.89M | gdev_mem_functions_for_bits(plane_depth); |
1009 | 1.89M | if (plane_depth == 1) |
1010 | 1.89M | code = fns->copy_mono(dev, base, sourcex, sraster, id, |
1011 | 1.89M | x, y, w, h, |
1012 | 1.89M | (gx_color_index)0, (gx_color_index)1); |
1013 | 2.73k | else |
1014 | 2.73k | code = fns->copy_color(dev, base, sourcex, sraster, |
1015 | 2.73k | id, x, y, w, h); |
1016 | 1.89M | base += sraster * plane_height; |
1017 | 1.89M | mdev->line_ptrs += mdev->height; |
1018 | 1.89M | } |
1019 | 474k | MEM_RESTORE_PARAMS(mdev, save); |
1020 | 474k | return code; |
1021 | 474k | } |
1022 | | |
1023 | | int |
1024 | | mem_planar_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles, |
1025 | | int x, int y, int w, int h, |
1026 | | const gx_drawing_color *pdcolor0, |
1027 | | const gx_drawing_color *pdcolor1, int px, int py) |
1028 | 0 | { |
1029 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
1030 | 0 | mem_save_params_t save; |
1031 | 0 | int pi; |
1032 | |
|
1033 | 0 | MEM_SAVE_PARAMS(mdev, save); |
1034 | 0 | for (pi = 0; pi < mdev->num_planar_planes; ++pi) { |
1035 | 0 | int plane_depth = mdev->planes[pi].depth; |
1036 | 0 | gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1; |
1037 | 0 | int shift = 16 - plane_depth; |
1038 | 0 | const gdev_mem_functions *fns = |
1039 | 0 | gdev_mem_functions_for_bits(plane_depth); |
1040 | 0 | gx_color_index c1, c0; |
1041 | |
|
1042 | 0 | if (pdcolor0->type == gx_dc_type_devn) { |
1043 | 0 | c0 = (pdcolor0->colors.devn.values[pi]) >> shift & mask; |
1044 | 0 | } else { |
1045 | 0 | c0 = gx_no_color_index; |
1046 | 0 | } |
1047 | 0 | if (pdcolor1->type == gx_dc_type_devn) { |
1048 | 0 | c1 = (pdcolor1->colors.devn.values[pi]) >> shift & mask; |
1049 | 0 | } else { |
1050 | 0 | c1 = gx_no_color_index; |
1051 | 0 | } |
1052 | | #ifdef DEBUG |
1053 | | if (c0 == gx_no_color_index && c1 == gx_no_color_index) { |
1054 | | dprintf("mem_planar_strip_tile_rect_dev called with two non-devn colors\n"); |
1055 | | } |
1056 | | #endif |
1057 | 0 | MEM_SET_PARAMS(mdev, plane_depth); |
1058 | 0 | if (c0 == c1) |
1059 | 0 | fns->fill_rectangle(dev, x, y, w, h, c0); |
1060 | 0 | else { |
1061 | | /* |
1062 | | * Temporarily replace copy_mono in case strip_tile_rectangle is |
1063 | | * defined in terms of it. |
1064 | | */ |
1065 | 0 | set_dev_proc(dev, copy_mono, fns->copy_mono); |
1066 | 0 | fns->strip_tile_rectangle(dev, tiles, x, y, w, h, c0, c1, px, py); |
1067 | 0 | } |
1068 | 0 | mdev->line_ptrs += mdev->height; |
1069 | 0 | } |
1070 | 0 | MEM_RESTORE_PARAMS(mdev, save); |
1071 | 0 | set_dev_proc(dev, copy_mono, mem_planar_copy_mono); |
1072 | 0 | return 0; |
1073 | 0 | } |
1074 | | |
1075 | | int |
1076 | | mem_planar_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles, |
1077 | | int x, int y, int w, int h, |
1078 | | gx_color_index color0, gx_color_index color1, |
1079 | | int px, int py) |
1080 | 7.86M | { |
1081 | 7.86M | gx_device_memory * const mdev = (gx_device_memory *)dev; |
1082 | 7.86M | mem_save_params_t save; |
1083 | 7.86M | int pi; |
1084 | | |
1085 | | /* We can't split up the transfer if the tile is colored. */ |
1086 | 7.86M | if (color0 == gx_no_color_index && color1 == gx_no_color_index) |
1087 | 22.9k | return gx_default_strip_tile_rectangle |
1088 | 22.9k | (dev, tiles, x, y, w, h, color0, color1, px, py); |
1089 | 7.84M | MEM_SAVE_PARAMS(mdev, save); |
1090 | 39.2M | for (pi = 0; pi < mdev->num_planar_planes; ++pi) { |
1091 | 31.4M | int plane_depth = mdev->planes[pi].depth; |
1092 | 31.4M | int shift = mdev->planes[pi].shift; |
1093 | 31.4M | gx_color_index mask = ((gx_color_index)1 << plane_depth) - 1; |
1094 | 31.4M | const gdev_mem_functions *fns = |
1095 | 31.4M | gdev_mem_functions_for_bits(plane_depth); |
1096 | 31.4M | gx_color_index c0 = |
1097 | 31.4M | (color0 == gx_no_color_index ? gx_no_color_index : |
1098 | 31.4M | (color0 >> shift) & mask); |
1099 | 31.4M | gx_color_index c1 = |
1100 | 31.4M | (color1 == gx_no_color_index ? gx_no_color_index : |
1101 | 31.4M | (color1 >> shift) & mask); |
1102 | | |
1103 | 31.4M | MEM_SET_PARAMS(mdev, plane_depth); |
1104 | 31.4M | if (c0 == c1) |
1105 | 23.5M | fns->fill_rectangle(dev, x, y, w, h, c0); |
1106 | 7.84M | else { |
1107 | | /* |
1108 | | * Temporarily replace copy_mono in case strip_tile_rectangle is |
1109 | | * defined in terms of it. |
1110 | | */ |
1111 | 7.84M | set_dev_proc(dev, copy_mono, fns->copy_mono); |
1112 | 7.84M | fns->strip_tile_rectangle(dev, tiles, x, y, w, h, c0, c1, px, py); |
1113 | 7.84M | } |
1114 | 31.4M | mdev->line_ptrs += mdev->height; |
1115 | 31.4M | } |
1116 | 7.84M | MEM_RESTORE_PARAMS(mdev, save); |
1117 | 7.84M | set_dev_proc(dev, copy_mono, mem_planar_copy_mono); |
1118 | 7.84M | return 0; |
1119 | 7.86M | } |
1120 | | |
1121 | | static int |
1122 | | planar_cmyk4bit_strip_copy_rop2(gx_device_memory * mdev, |
1123 | | const byte * srow, int sourcex, uint sraster, |
1124 | | gx_bitmap_id id, const gx_color_index * scolors, |
1125 | | const gx_strip_bitmap * textures, |
1126 | | const gx_color_index * tcolors, |
1127 | | int x, int y, int width, int height, |
1128 | | int phase_x, int phase_y, |
1129 | | gs_logical_operation_t lop, |
1130 | | uint planar_height) |
1131 | 0 | { |
1132 | 0 | gs_rop3_t rop = (gs_rop3_t)lop; |
1133 | 0 | uint draster = mdev->raster; |
1134 | 0 | int line_count; |
1135 | 0 | byte *cdrow, *mdrow, *ydrow, *kdrow; |
1136 | 0 | byte lmask, rmask; |
1137 | 0 | rop_proc cproc = NULL, mproc = NULL, yproc = NULL; |
1138 | 0 | int dbit; |
1139 | 0 | int cscolor = 0, mscolor = 0, yscolor = 0, kscolor = 0; |
1140 | 0 | int ctcolor = 0, mtcolor = 0, ytcolor = 0, ktcolor = 0; |
1141 | 0 | int constant_s = 0; |
1142 | | |
1143 | | /* assert(planar_height == 0) */ |
1144 | | |
1145 | | /* Modify the raster operation according to the source palette. */ |
1146 | 0 | fit_copy(mdev, srow, sourcex, sraster, id, x, y, width, height); |
1147 | | |
1148 | | /* This function assumes constant (or unused) scolors and tcolors */ |
1149 | 0 | if (scolors) |
1150 | 0 | { |
1151 | 0 | if (scolors[0] == scolors[1]) { |
1152 | 0 | kscolor = ((scolors[0] & 1) ? -1 : 0); |
1153 | 0 | cscolor = ((scolors[0] & 8) ? -1 : 0) | kscolor; |
1154 | 0 | mscolor = ((scolors[0] & 4) ? -1 : 0) | kscolor; |
1155 | 0 | yscolor = ((scolors[0] & 2) ? -1 : 0) | kscolor; |
1156 | 0 | constant_s = 1; |
1157 | 0 | } else { |
1158 | 0 | kscolor = (scolors[0] & 1) | ((scolors[1] & 1)<<1); |
1159 | 0 | cscolor = ((scolors[0] & 8)>>3) | ((scolors[1] & 8)>>2) | kscolor; |
1160 | 0 | mscolor = ((scolors[0] & 4)>>2) | ((scolors[1] & 4)>>1) | kscolor; |
1161 | 0 | yscolor = ((scolors[0] & 2)>>1) | (scolors[1] & 2) | kscolor; |
1162 | 0 | switch (cscolor) { |
1163 | 0 | case 0: |
1164 | 0 | cproc = rop_proc_table[rop3_know_S_0(rop)]; |
1165 | 0 | break; |
1166 | 0 | case 1: |
1167 | 0 | cproc = rop_proc_table[rop3_invert_S(rop)]; |
1168 | 0 | break; |
1169 | 0 | case 2: |
1170 | 0 | cproc = rop_proc_table[rop]; |
1171 | 0 | break; |
1172 | 0 | default: /* 3 */ |
1173 | 0 | cproc = rop_proc_table[rop3_know_S_1(rop)]; |
1174 | 0 | break; |
1175 | 0 | } |
1176 | 0 | switch (mscolor) { |
1177 | 0 | case 0: |
1178 | 0 | mproc = rop_proc_table[rop3_know_S_0(rop)]; |
1179 | 0 | break; |
1180 | 0 | case 1: |
1181 | 0 | mproc = rop_proc_table[rop3_invert_S(rop)]; |
1182 | 0 | break; |
1183 | 0 | case 2: |
1184 | 0 | mproc = rop_proc_table[rop]; |
1185 | 0 | break; |
1186 | 0 | default: /* 3 */ |
1187 | 0 | mproc = rop_proc_table[rop3_know_S_1(rop)]; |
1188 | 0 | break; |
1189 | 0 | } |
1190 | 0 | switch (yscolor) { |
1191 | 0 | case 0: |
1192 | 0 | yproc = rop_proc_table[rop3_know_S_0(rop)]; |
1193 | 0 | break; |
1194 | 0 | case 1: |
1195 | 0 | yproc = rop_proc_table[rop3_invert_S(rop)]; |
1196 | 0 | break; |
1197 | 0 | case 2: |
1198 | 0 | yproc = rop_proc_table[rop]; |
1199 | 0 | break; |
1200 | 0 | default: /* 3 */ |
1201 | 0 | yproc = rop_proc_table[rop3_know_S_1(rop)]; |
1202 | 0 | break; |
1203 | 0 | } |
1204 | 0 | } |
1205 | 0 | } |
1206 | 0 | if (tcolors) |
1207 | 0 | { |
1208 | 0 | ktcolor = ((tcolors[0] & 1) ? -1 : 0); |
1209 | 0 | ctcolor = ((tcolors[0] & 8) ? -1 : 0) | ktcolor; |
1210 | 0 | mtcolor = ((tcolors[0] & 4) ? -1 : 0) | ktcolor; |
1211 | 0 | ytcolor = ((tcolors[0] & 2) ? -1 : 0) | ktcolor; |
1212 | 0 | } |
1213 | | |
1214 | | /* Set up transfer parameters. */ |
1215 | 0 | line_count = height; |
1216 | 0 | if (lop_uses_T(lop) && (tcolors == NULL)) { /* && (textures != NULL) */ |
1217 | | /* Pixmap textures. For now we'll only get into this routine if |
1218 | | * textures is a pixmap (or constant, in which case we'll do it |
1219 | | * below). */ |
1220 | 0 | int ty; |
1221 | 0 | uint traster; |
1222 | | |
1223 | | /* Calculate the X offset for a given Y value, */ |
1224 | | /* taking shift into account if necessary. */ |
1225 | 0 | #define x_offset(px, ty, textures)\ |
1226 | 0 | ((textures)->shift == 0 ? (px) :\ |
1227 | 0 | (px) + (ty) / (textures)->rep_height * (textures)->rep_shift) |
1228 | |
|
1229 | 0 | cdrow = scan_line_base(mdev, y); |
1230 | 0 | mdrow = cdrow + mdev->height * draster; |
1231 | 0 | ydrow = mdrow + mdev->height * draster; |
1232 | 0 | kdrow = ydrow + mdev->height * draster; |
1233 | 0 | if (!textures) |
1234 | 0 | return 0; |
1235 | 0 | traster = textures->raster; |
1236 | 0 | ty = y + phase_y; |
1237 | 0 | for (; line_count-- > 0; cdrow += draster, mdrow += draster, ydrow += draster, kdrow += draster, srow += sraster, ++ty) { |
1238 | 0 | int sx = sourcex; |
1239 | 0 | int dx = x; |
1240 | 0 | int w = width; |
1241 | 0 | const byte *trow = textures->data + (ty % textures->rep_height) * traster; |
1242 | 0 | int xoff = x_offset(phase_x, ty, textures); |
1243 | 0 | int nw; |
1244 | 0 | int tx = (dx + xoff) % textures->rep_width; |
1245 | | |
1246 | | /* Loop over (horizontal) copies of the tile. */ |
1247 | 0 | for (; w > 0; sx += nw, dx += nw, w -= nw, tx = 0) { |
1248 | | /* sptr and tptr point to bytes of cmykcmyk. Need to convert |
1249 | | * these to planar format. */ |
1250 | 0 | int dbit = dx & 7; |
1251 | 0 | int tbit = tx & 1; |
1252 | 0 | int tskew = tbit - dbit; /* -7 >= tskew >= 1 */ |
1253 | 0 | int left = (nw = min(w, textures->size.x - tx))-8+dbit; |
1254 | 0 | int sbit = sx & 1; |
1255 | 0 | int sskew = sbit - dbit; /* -7 >= sskew >= 1 */ |
1256 | 0 | byte lmask = 0xff >> dbit; |
1257 | 0 | byte rmask = 0xff << (~(dbit + nw - 1) & 7); |
1258 | 0 | byte *cdptr = cdrow + (dx>>3); |
1259 | 0 | byte *mdptr = mdrow + (dx>>3); |
1260 | 0 | byte *ydptr = ydrow + (dx>>3); |
1261 | 0 | byte *kdptr = kdrow + (dx>>3); |
1262 | 0 | const byte *tptr = trow; |
1263 | 0 | const rop_proc proc = rop_proc_table[rop]; |
1264 | 0 | const byte *sptr = srow; |
1265 | 0 | sptr += (sskew>>1); /* Backtrack sptr if required. */ |
1266 | 0 | sptr += (sx>>1); |
1267 | 0 | tptr += (tskew>>1); /* Backtrack tptr if required. */ |
1268 | 0 | tptr += (tx>>1); |
1269 | 0 | if (left < 0) |
1270 | 0 | lmask &= rmask; |
1271 | 0 | { |
1272 | | /* Left hand bytes */ |
1273 | 0 | byte kdbyte = *kdptr; |
1274 | 0 | byte cdbyte = *cdptr; |
1275 | 0 | byte mdbyte = *mdptr; |
1276 | 0 | byte ydbyte = *ydptr; |
1277 | 0 | byte cresult, mresult, yresult, kresult; |
1278 | 0 | bits32 scol = 0, tcol = 0; |
1279 | 0 | if ((sskew & 1) == 0) { |
1280 | 0 | if (sskew >= 0) |
1281 | 0 | scol = expand_4to1[sptr[0]]<<6; |
1282 | 0 | if ((sskew >= -2) && (left > -6)) |
1283 | 0 | scol |= expand_4to1[sptr[1]]<<4; |
1284 | 0 | if ((sskew >= -4) && (left > -4)) |
1285 | 0 | scol |= expand_4to1[sptr[2]]<<2; |
1286 | 0 | if (left > -2) |
1287 | 0 | scol |= expand_4to1[sptr[3]]; |
1288 | 0 | } else { |
1289 | 0 | if (sskew >= 0) |
1290 | 0 | scol = expand_4to1[sptr[0] & 0x0f]<<7; |
1291 | 0 | if ((sskew >= -2) && (left > -7)) |
1292 | 0 | scol |= expand_4to1[sptr[1]]<<5; |
1293 | 0 | if ((sskew >= -4) && (left > -5)) |
1294 | 0 | scol |= expand_4to1[sptr[2]]<<3; |
1295 | 0 | if ((sskew >= -6) && (left > -3)) |
1296 | 0 | scol |= expand_4to1[sptr[3]]<<1; |
1297 | 0 | if (left > -1) |
1298 | 0 | scol |= expand_4to1[sptr[4] & 0xf0]>>1; |
1299 | 0 | } |
1300 | 0 | if ((tskew & 1) == 0) { |
1301 | 0 | if (tskew >= 0) |
1302 | 0 | tcol = expand_4to1[tptr[0]]<<6; |
1303 | 0 | if ((tskew >= -2) && (left > -6)) |
1304 | 0 | tcol |= expand_4to1[tptr[1]]<<4; |
1305 | 0 | if ((tskew >= -4) && (left > -4)) |
1306 | 0 | tcol |= expand_4to1[tptr[2]]<<2; |
1307 | 0 | if (left > -2) |
1308 | 0 | tcol |= expand_4to1[tptr[3]]; |
1309 | 0 | } else { |
1310 | 0 | if (tskew >= 0) |
1311 | 0 | tcol = expand_4to1[tptr[0] & 0x0f]<<7; |
1312 | 0 | if ((tskew >= -2) && (left > -7)) |
1313 | 0 | tcol |= expand_4to1[tptr[1]]<<5; |
1314 | 0 | if ((tskew >= -4) && (left > -5)) |
1315 | 0 | tcol |= expand_4to1[tptr[2]]<<3; |
1316 | 0 | if ((tskew >= -6) && (left > -3)) |
1317 | 0 | tcol |= expand_4to1[tptr[3]]<<1; |
1318 | 0 | if (left > -1) |
1319 | 0 | tcol |= expand_4to1[tptr[4] & 0xf0]>>1; |
1320 | 0 | } |
1321 | 0 | cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),tcol|(tcol>>24)); |
1322 | 0 | mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),tcol|(tcol>>16)); |
1323 | 0 | yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),tcol|(tcol>> 8)); |
1324 | 0 | kresult = cresult & mresult & yresult; |
1325 | 0 | cresult &= ~kresult; |
1326 | 0 | mresult &= ~kresult; |
1327 | 0 | yresult &= ~kresult; |
1328 | 0 | *cdptr++ = (cresult & lmask) | (cdbyte & ~lmask); |
1329 | 0 | *mdptr++ = (mresult & lmask) | (mdbyte & ~lmask); |
1330 | 0 | *ydptr++ = (yresult & lmask) | (ydbyte & ~lmask); |
1331 | 0 | *kdptr++ = (kresult & lmask) | (kdbyte & ~lmask); |
1332 | 0 | } |
1333 | 0 | if (left <= 0) /* if (width <= 8) we're done */ |
1334 | 0 | continue; |
1335 | 0 | sptr += 4; |
1336 | 0 | tptr += 4; |
1337 | 0 | left -= 8; /* left = bits to go - 8 */ |
1338 | 0 | while (left > 0) |
1339 | 0 | { |
1340 | 0 | byte kdbyte = *kdptr; |
1341 | 0 | byte cdbyte = *cdptr | kdbyte; |
1342 | 0 | byte mdbyte = *mdptr | kdbyte; |
1343 | 0 | byte ydbyte = *ydptr | kdbyte; |
1344 | 0 | byte cresult, mresult, yresult, kresult; |
1345 | 0 | bits32 scol, tcol; |
1346 | 0 | if ((sskew & 1) == 0) { |
1347 | 0 | scol = expand_4to1[sptr[0]]<<6; |
1348 | 0 | scol |= expand_4to1[sptr[1]]<<4; |
1349 | 0 | scol |= expand_4to1[sptr[2]]<<2; |
1350 | 0 | scol |= expand_4to1[sptr[3]]; |
1351 | 0 | } else { |
1352 | 0 | scol = expand_4to1[sptr[0] & 0x0f]<<7; |
1353 | 0 | scol |= expand_4to1[sptr[1]]<<5; |
1354 | 0 | scol |= expand_4to1[sptr[2]]<<3; |
1355 | 0 | scol |= expand_4to1[sptr[3]]<<1; |
1356 | 0 | scol |= expand_4to1[sptr[4] & 0xf0]>>1; |
1357 | 0 | } |
1358 | 0 | if ((tskew & 1) == 0) { |
1359 | 0 | tcol = expand_4to1[tptr[0]]<<6; |
1360 | 0 | tcol |= expand_4to1[tptr[1]]<<4; |
1361 | 0 | tcol |= expand_4to1[tptr[2]]<<2; |
1362 | 0 | tcol |= expand_4to1[tptr[3]]; |
1363 | 0 | } else { |
1364 | 0 | tcol = expand_4to1[tptr[0] & 0x0f]<<7; |
1365 | 0 | tcol |= expand_4to1[tptr[1]]<<5; |
1366 | 0 | tcol |= expand_4to1[tptr[2]]<<3; |
1367 | 0 | tcol |= expand_4to1[tptr[3]]<<1; |
1368 | 0 | tcol |= expand_4to1[tptr[4] & 0xf0]>>1; |
1369 | 0 | } |
1370 | 0 | cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),tcol|(tcol>>24)); |
1371 | 0 | mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),tcol|(tcol>>16)); |
1372 | 0 | yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),tcol|(tcol>> 8)); |
1373 | 0 | kresult = cresult & mresult & yresult; |
1374 | 0 | cresult &= ~kresult; |
1375 | 0 | mresult &= ~kresult; |
1376 | 0 | yresult &= ~kresult; |
1377 | 0 | *cdptr++ = cresult & ~kresult; |
1378 | 0 | *mdptr++ = mresult & ~kresult; |
1379 | 0 | *ydptr++ = yresult & ~kresult; |
1380 | 0 | *kdptr++ = kresult; |
1381 | 0 | sptr += 4; |
1382 | 0 | tptr += 4; |
1383 | 0 | left -= 8; |
1384 | 0 | } |
1385 | 0 | { |
1386 | 0 | byte kdbyte = *kdptr; |
1387 | 0 | byte cdbyte = *cdptr; |
1388 | 0 | byte mdbyte = *mdptr; |
1389 | 0 | byte ydbyte = *ydptr; |
1390 | 0 | byte cresult, mresult, yresult, kresult; |
1391 | 0 | bits32 scol, tcol; |
1392 | 0 | if ((sskew & 1) == 0) { |
1393 | 0 | scol = expand_4to1[sptr[0]]<<6; |
1394 | 0 | if (left > -6) |
1395 | 0 | scol |= expand_4to1[sptr[1]]<<4; |
1396 | 0 | if (left > -4) |
1397 | 0 | scol |= expand_4to1[sptr[2]]<<2; |
1398 | 0 | if (left > -2) |
1399 | 0 | scol |= expand_4to1[sptr[3]]; |
1400 | 0 | } else { |
1401 | 0 | scol = expand_4to1[sptr[0] & 0x0f]<<7; |
1402 | 0 | if (left > -7) |
1403 | 0 | scol |= expand_4to1[sptr[1]]<<5; |
1404 | 0 | if (left > -5) |
1405 | 0 | scol |= expand_4to1[sptr[2]]<<3; |
1406 | 0 | if (left > -3) |
1407 | 0 | scol |= expand_4to1[sptr[3]]<<1; |
1408 | 0 | if (left > -1) |
1409 | 0 | scol |= expand_4to1[sptr[4] & 0xf0]>>1; |
1410 | 0 | } |
1411 | 0 | if ((tskew & 1) == 0) { |
1412 | 0 | tcol = expand_4to1[tptr[0]]<<6; |
1413 | 0 | if (left > -6) |
1414 | 0 | tcol |= expand_4to1[tptr[1]]<<4; |
1415 | 0 | if (left > -4) |
1416 | 0 | tcol |= expand_4to1[tptr[2]]<<2; |
1417 | 0 | if (left > -2) |
1418 | 0 | tcol |= expand_4to1[tptr[3]]; |
1419 | 0 | } else { |
1420 | 0 | tcol = expand_4to1[tptr[0] & 0x0f]<<7; |
1421 | 0 | if (left > -7) |
1422 | 0 | tcol |= expand_4to1[tptr[1]]<<5; |
1423 | 0 | if (left > -5) |
1424 | 0 | tcol |= expand_4to1[tptr[2]]<<3; |
1425 | 0 | if (left > -3) |
1426 | 0 | tcol |= expand_4to1[tptr[3]]<<1; |
1427 | 0 | if (left > -1) |
1428 | 0 | tcol |= expand_4to1[tptr[4] & 0xf0]>>1; |
1429 | 0 | } |
1430 | 0 | cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),tcol|(tcol>>24)); |
1431 | 0 | mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),tcol|(tcol>>16)); |
1432 | 0 | yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),tcol|(tcol>> 8)); |
1433 | 0 | kresult = cresult & mresult & yresult; |
1434 | 0 | cresult &= ~kresult; |
1435 | 0 | mresult &= ~kresult; |
1436 | 0 | yresult &= ~kresult; |
1437 | 0 | *cdptr++ = (cresult & rmask) | (cdbyte & ~rmask); |
1438 | 0 | *mdptr++ = (mresult & rmask) | (mdbyte & ~rmask); |
1439 | 0 | *ydptr++ = (yresult & rmask) | (ydbyte & ~rmask); |
1440 | 0 | *kdptr++ = (kresult & rmask) | (kdbyte & ~rmask); |
1441 | 0 | } |
1442 | 0 | } |
1443 | 0 | } |
1444 | 0 | return 0; |
1445 | 0 | } |
1446 | | /* Texture constant (or unimportant) cases */ |
1447 | 0 | dbit = x & 7; |
1448 | 0 | cdrow = scan_line_base(mdev, y) + (x>>3); |
1449 | 0 | mdrow = cdrow + mdev->height * draster; |
1450 | 0 | ydrow = mdrow + mdev->height * draster; |
1451 | 0 | kdrow = ydrow + mdev->height * draster; |
1452 | 0 | lmask = 0xff >> dbit; |
1453 | 0 | width += dbit; |
1454 | 0 | rmask = 0xff << (~(width - 1) & 7); |
1455 | 0 | if (width < 8) |
1456 | 0 | lmask &= rmask; |
1457 | 0 | if (scolors == NULL) { |
1458 | | /* sptr points to bytes of cmykcmyk. Need to convert these to |
1459 | | * planar format. */ |
1460 | 0 | const rop_proc proc = rop_proc_table[rop]; |
1461 | 0 | int sbit = sourcex & 1; |
1462 | 0 | int sskew = sbit - dbit; /* -7 >= sskew >= 1 */ |
1463 | 0 | srow += (sskew>>1); /* Backtrack srow if required. */ |
1464 | 0 | srow += (sourcex>>1); |
1465 | 0 | for (; line_count-- > 0; cdrow += draster, mdrow += draster, ydrow += draster, kdrow += draster, srow += sraster) { |
1466 | 0 | byte *cdptr = cdrow; |
1467 | 0 | byte *mdptr = mdrow; |
1468 | 0 | byte *ydptr = ydrow; |
1469 | 0 | byte *kdptr = kdrow; |
1470 | 0 | const byte *sptr = srow; |
1471 | 0 | int left = width-8; |
1472 | 0 | { |
1473 | | /* Left hand bytes */ |
1474 | 0 | byte kdbyte = *kdptr; |
1475 | 0 | byte cdbyte = *cdptr; |
1476 | 0 | byte mdbyte = *mdptr; |
1477 | 0 | byte ydbyte = *ydptr; |
1478 | 0 | byte cresult, mresult, yresult, kresult; |
1479 | 0 | bits32 scol = 0; |
1480 | 0 | if ((sskew & 1) == 0) { |
1481 | 0 | if (sskew >= 0) |
1482 | 0 | scol = expand_4to1[sptr[0]]<<6; |
1483 | 0 | if ((sskew >= -2) && (left > -6)) |
1484 | 0 | scol |= expand_4to1[sptr[1]]<<4; |
1485 | 0 | if ((sskew >= -4) && (left > -4)) |
1486 | 0 | scol |= expand_4to1[sptr[2]]<<2; |
1487 | 0 | if (left > -2) |
1488 | 0 | scol |= expand_4to1[sptr[3]]; |
1489 | 0 | } else { |
1490 | 0 | if (sskew >= 0) |
1491 | 0 | scol = expand_4to1[sptr[0] & 0x0f]<<7; |
1492 | 0 | if ((sskew >= -2) && (left > -7)) |
1493 | 0 | scol |= expand_4to1[sptr[1]]<<5; |
1494 | 0 | if ((sskew >= -4) && (left > -5)) |
1495 | 0 | scol |= expand_4to1[sptr[2]]<<3; |
1496 | 0 | if ((sskew >= -6) && (left > -3)) |
1497 | 0 | scol |= expand_4to1[sptr[3]]<<1; |
1498 | 0 | if (left > -1) |
1499 | 0 | scol |= expand_4to1[sptr[4] & 0xf0]>>1; |
1500 | 0 | } |
1501 | 0 | cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),ctcolor); |
1502 | 0 | mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),mtcolor); |
1503 | 0 | yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),ytcolor); |
1504 | 0 | kresult = cresult & mresult & yresult; |
1505 | 0 | cresult &= ~kresult; |
1506 | 0 | mresult &= ~kresult; |
1507 | 0 | yresult &= ~kresult; |
1508 | 0 | *cdptr++ = (cresult & lmask) | (cdbyte & ~lmask); |
1509 | 0 | *mdptr++ = (mresult & lmask) | (mdbyte & ~lmask); |
1510 | 0 | *ydptr++ = (yresult & lmask) | (ydbyte & ~lmask); |
1511 | 0 | *kdptr++ = (kresult & lmask) | (kdbyte & ~lmask); |
1512 | 0 | } |
1513 | 0 | if (left <= 0) /* if (width <= 8) we're done */ |
1514 | 0 | continue; |
1515 | 0 | sptr += 4; |
1516 | 0 | left -= 8; /* left = bits to go - 8 */ |
1517 | 0 | while (left > 0) |
1518 | 0 | { |
1519 | 0 | byte kdbyte = *kdptr; |
1520 | 0 | byte cdbyte = *cdptr | kdbyte; |
1521 | 0 | byte mdbyte = *mdptr | kdbyte; |
1522 | 0 | byte ydbyte = *ydptr | kdbyte; |
1523 | 0 | byte cresult, mresult, yresult, kresult; |
1524 | 0 | bits32 scol; |
1525 | 0 | if ((sskew & 1) == 0) { |
1526 | 0 | scol = expand_4to1[sptr[0]]<<6; |
1527 | 0 | scol |= expand_4to1[sptr[1]]<<4; |
1528 | 0 | scol |= expand_4to1[sptr[2]]<<2; |
1529 | 0 | scol |= expand_4to1[sptr[3]]; |
1530 | 0 | } else { |
1531 | 0 | scol = expand_4to1[sptr[0] & 0x0f]<<7; |
1532 | 0 | scol |= expand_4to1[sptr[1]]<<5; |
1533 | 0 | scol |= expand_4to1[sptr[2]]<<3; |
1534 | 0 | scol |= expand_4to1[sptr[3]]<<1; |
1535 | 0 | scol |= expand_4to1[sptr[4] & 0xf0]>>1; |
1536 | 0 | } |
1537 | 0 | cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),ctcolor); |
1538 | 0 | mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),mtcolor); |
1539 | 0 | yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),ytcolor); |
1540 | 0 | kresult = cresult & mresult & yresult; |
1541 | 0 | cresult &= ~kresult; |
1542 | 0 | mresult &= ~kresult; |
1543 | 0 | yresult &= ~kresult; |
1544 | 0 | *cdptr++ = cresult & ~kresult; |
1545 | 0 | *mdptr++ = mresult & ~kresult; |
1546 | 0 | *ydptr++ = yresult & ~kresult; |
1547 | 0 | *kdptr++ = kresult; |
1548 | 0 | sptr += 4; |
1549 | 0 | left -= 8; |
1550 | 0 | } |
1551 | 0 | { |
1552 | 0 | byte kdbyte = *kdptr; |
1553 | 0 | byte cdbyte = *cdptr; |
1554 | 0 | byte mdbyte = *mdptr; |
1555 | 0 | byte ydbyte = *ydptr; |
1556 | 0 | byte cresult, mresult, yresult, kresult; |
1557 | 0 | bits32 scol; |
1558 | 0 | if ((sskew & 1) == 0) { |
1559 | 0 | scol = expand_4to1[sptr[0]]<<6; |
1560 | 0 | if (left > -6) |
1561 | 0 | scol |= expand_4to1[sptr[1]]<<4; |
1562 | 0 | if (left > -4) |
1563 | 0 | scol |= expand_4to1[sptr[2]]<<2; |
1564 | 0 | if (left > -2) |
1565 | 0 | scol |= expand_4to1[sptr[3]]; |
1566 | 0 | } else { |
1567 | 0 | scol = expand_4to1[sptr[0] & 0x0f]<<7; |
1568 | 0 | if (left > -7) |
1569 | 0 | scol |= expand_4to1[sptr[1]]<<5; |
1570 | 0 | if (left > -5) |
1571 | 0 | scol |= expand_4to1[sptr[2]]<<3; |
1572 | 0 | if (left > -3) |
1573 | 0 | scol |= expand_4to1[sptr[3]]<<1; |
1574 | 0 | if (left > -1) |
1575 | 0 | scol |= expand_4to1[sptr[4] & 0xf0]>>1; |
1576 | 0 | } |
1577 | 0 | cresult = (*proc)(cdbyte | kdbyte,scol|(scol>>24),ctcolor); |
1578 | 0 | mresult = (*proc)(mdbyte | kdbyte,scol|(scol>>16),mtcolor); |
1579 | 0 | yresult = (*proc)(ydbyte | kdbyte,scol|(scol>> 8),ytcolor); |
1580 | 0 | kresult = cresult & mresult & yresult; |
1581 | 0 | cresult &= ~kresult; |
1582 | 0 | mresult &= ~kresult; |
1583 | 0 | yresult &= ~kresult; |
1584 | 0 | *cdptr++ = (cresult & rmask) | (cdbyte & ~rmask); |
1585 | 0 | *mdptr++ = (mresult & rmask) | (mdbyte & ~rmask); |
1586 | 0 | *ydptr++ = (yresult & rmask) | (ydbyte & ~rmask); |
1587 | 0 | *kdptr++ = (kresult & rmask) | (kdbyte & ~rmask); |
1588 | 0 | } |
1589 | 0 | } |
1590 | 0 | } else if (constant_s) { |
1591 | 0 | const rop_proc proc = rop_proc_table[rop]; |
1592 | 0 | for (; line_count-- > 0; cdrow += draster, mdrow += draster, ydrow += draster, kdrow += draster) { |
1593 | 0 | byte *cdptr = cdrow; |
1594 | 0 | byte *mdptr = mdrow; |
1595 | 0 | byte *ydptr = ydrow; |
1596 | 0 | byte *kdptr = kdrow; |
1597 | 0 | int left = width-8; |
1598 | 0 | { |
1599 | | /* Left hand bytes */ |
1600 | 0 | byte kdbyte = *kdptr; |
1601 | 0 | byte cdbyte = *cdptr; |
1602 | 0 | byte mdbyte = *mdptr; |
1603 | 0 | byte ydbyte = *ydptr; |
1604 | 0 | byte cresult = (*proc)(cdbyte | kdbyte,cscolor,ctcolor); |
1605 | 0 | byte mresult = (*proc)(mdbyte | kdbyte,mscolor,mtcolor); |
1606 | 0 | byte yresult = (*proc)(ydbyte | kdbyte,yscolor,ytcolor); |
1607 | 0 | byte kresult = cresult & mresult & yresult; |
1608 | 0 | cresult &= ~kresult; |
1609 | 0 | mresult &= ~kresult; |
1610 | 0 | yresult &= ~kresult; |
1611 | 0 | *cdptr++ = (cresult & lmask) | (cdbyte & ~lmask); |
1612 | 0 | *mdptr++ = (mresult & lmask) | (mdbyte & ~lmask); |
1613 | 0 | *ydptr++ = (yresult & lmask) | (ydbyte & ~lmask); |
1614 | 0 | *kdptr++ = (kresult & lmask) | (kdbyte & ~lmask); |
1615 | 0 | } |
1616 | 0 | if (left <= 0) /* if (width <= 8) we're done */ |
1617 | 0 | continue; |
1618 | 0 | left -= 8; /* left = bits to go - 8 */ |
1619 | 0 | while (left > 0) |
1620 | 0 | { |
1621 | 0 | byte kdbyte = *kdptr; |
1622 | 0 | byte cdbyte = *cdptr | kdbyte; |
1623 | 0 | byte mdbyte = *mdptr | kdbyte; |
1624 | 0 | byte ydbyte = *ydptr | kdbyte; |
1625 | 0 | byte cresult = (*proc)(cdbyte,cscolor,ctcolor); |
1626 | 0 | byte mresult = (*proc)(mdbyte,mscolor,mtcolor); |
1627 | 0 | byte yresult = (*proc)(ydbyte,yscolor,ytcolor); |
1628 | 0 | byte kresult = cresult & mresult & yresult; |
1629 | 0 | cresult &= ~kresult; |
1630 | 0 | mresult &= ~kresult; |
1631 | 0 | yresult &= ~kresult; |
1632 | 0 | *cdptr++ = cresult & ~kresult; |
1633 | 0 | *mdptr++ = mresult & ~kresult; |
1634 | 0 | *ydptr++ = yresult & ~kresult; |
1635 | 0 | *kdptr++ = kresult; |
1636 | 0 | left -= 8; |
1637 | 0 | } |
1638 | 0 | { |
1639 | 0 | byte kdbyte = *kdptr; |
1640 | 0 | byte cdbyte = *cdptr; |
1641 | 0 | byte mdbyte = *mdptr; |
1642 | 0 | byte ydbyte = *ydptr; |
1643 | 0 | byte cresult = (*proc)(cdbyte | kdbyte,cscolor,ctcolor); |
1644 | 0 | byte mresult = (*proc)(mdbyte | kdbyte,mscolor,mtcolor); |
1645 | 0 | byte yresult = (*proc)(ydbyte | kdbyte,yscolor,ytcolor); |
1646 | 0 | byte kresult = cresult & mresult & yresult; |
1647 | 0 | cresult &= ~kresult; |
1648 | 0 | mresult &= ~kresult; |
1649 | 0 | yresult &= ~kresult; |
1650 | 0 | *cdptr++ = (cresult & rmask) | (cdbyte & ~rmask); |
1651 | 0 | *mdptr++ = (mresult & rmask) | (mdbyte & ~rmask); |
1652 | 0 | *ydptr++ = (yresult & rmask) | (ydbyte & ~rmask); |
1653 | 0 | *kdptr++ = (kresult & rmask) | (kdbyte & ~rmask); |
1654 | 0 | } |
1655 | 0 | } |
1656 | 0 | } else { |
1657 | | /* Constant T, bitmap S */ |
1658 | 0 | int sbit = sourcex & 7; |
1659 | 0 | int sskew = sbit - dbit; |
1660 | 0 | if (sskew < 0) |
1661 | 0 | --srow, sskew += 8; |
1662 | 0 | srow += (sourcex>>3); |
1663 | 0 | for (; line_count-- > 0; cdrow += draster, mdrow += draster, ydrow += draster, kdrow += draster, srow += sraster) { |
1664 | 0 | const byte *sptr = srow; |
1665 | 0 | byte *cdptr = cdrow; |
1666 | 0 | byte *mdptr = mdrow; |
1667 | 0 | byte *ydptr = ydrow; |
1668 | 0 | byte *kdptr = kdrow; |
1669 | 0 | int left = width-8; |
1670 | 0 | { |
1671 | | /* Left hand byte (maybe the only one) */ |
1672 | 0 | byte kdbyte = *kdptr; |
1673 | 0 | byte cdbyte = *cdptr; |
1674 | 0 | byte mdbyte = *mdptr; |
1675 | 0 | byte ydbyte = *ydptr; |
1676 | 0 | #define fetch1(ptr, skew)\ |
1677 | 0 | (skew ? (ptr[0] << skew) + (ptr[1] >> (8 - skew)) : *ptr) |
1678 | 0 | byte sbyte = fetch1(sptr, sskew); |
1679 | 0 | byte cresult = (*cproc)(cdbyte|kdbyte,sbyte,ctcolor); |
1680 | 0 | byte mresult = (*mproc)(mdbyte|kdbyte,sbyte,mtcolor); |
1681 | 0 | byte yresult = (*yproc)(ydbyte|kdbyte,sbyte,ytcolor); |
1682 | 0 | byte kresult = cresult & mresult & yresult; |
1683 | 0 | cresult &= ~kresult; |
1684 | 0 | mresult &= ~kresult; |
1685 | 0 | yresult &= ~kresult; |
1686 | 0 | *cdptr++ = (cresult & lmask) | (cdbyte & ~lmask); |
1687 | 0 | *mdptr++ = (mresult & lmask) | (mdbyte & ~lmask); |
1688 | 0 | *ydptr++ = (yresult & lmask) | (ydbyte & ~lmask); |
1689 | 0 | *kdptr++ = (kresult & lmask) | (kdbyte & ~lmask); |
1690 | 0 | sptr++; |
1691 | 0 | left -= 8; |
1692 | 0 | } |
1693 | 0 | while (left > 0) { |
1694 | | /* Bytes where all 8 bits of S are needed */ |
1695 | 0 | byte kdbyte = *kdptr; |
1696 | 0 | byte cdbyte = *cdptr | kdbyte; |
1697 | 0 | byte mdbyte = *mdptr | kdbyte; |
1698 | 0 | byte ydbyte = *ydptr | kdbyte; |
1699 | 0 | byte sbyte = fetch1(sptr, sskew); |
1700 | 0 | byte cresult = (*cproc)(cdbyte,sbyte,ctcolor); |
1701 | 0 | byte mresult = (*mproc)(mdbyte,sbyte,mtcolor); |
1702 | 0 | byte yresult = (*yproc)(ydbyte,sbyte,ytcolor); |
1703 | 0 | byte kresult = cresult & mresult & yresult; |
1704 | 0 | *cdptr++ = cresult & ~kresult; |
1705 | 0 | *mdptr++ = mresult & ~kresult; |
1706 | 0 | *ydptr++ = yresult & ~kresult; |
1707 | 0 | *kdptr++ = kresult; |
1708 | 0 | sptr++; |
1709 | 0 | left -= 8; |
1710 | 0 | } |
1711 | | /* Final byte */ |
1712 | 0 | if (left > -8) { |
1713 | 0 | byte kdbyte = *kdptr; |
1714 | 0 | byte cdbyte = *cdptr; |
1715 | 0 | byte mdbyte = *mdptr; |
1716 | 0 | byte ydbyte = *ydptr; |
1717 | 0 | byte sbyte = fetch1(sptr, sskew); |
1718 | 0 | #undef fetch1 |
1719 | 0 | byte cresult = (*cproc)(cdbyte | kdbyte,sbyte,ctcolor); |
1720 | 0 | byte mresult = (*mproc)(mdbyte | kdbyte,sbyte,mtcolor); |
1721 | 0 | byte yresult = (*yproc)(ydbyte | kdbyte,sbyte,ytcolor); |
1722 | 0 | byte kresult = cresult & mresult & yresult; |
1723 | 0 | cresult &= ~kresult; |
1724 | 0 | mresult &= ~kresult; |
1725 | 0 | yresult &= ~kresult; |
1726 | 0 | *cdptr++ = (cresult & rmask) | (cdbyte & ~rmask); |
1727 | 0 | *mdptr++ = (mresult & rmask) | (mdbyte & ~rmask); |
1728 | 0 | *ydptr++ = (yresult & rmask) | (ydbyte & ~rmask); |
1729 | 0 | *kdptr++ = (kresult & rmask) | (kdbyte & ~rmask); |
1730 | 0 | } |
1731 | 0 | } |
1732 | 0 | } |
1733 | 0 | return 0; |
1734 | 0 | } |
1735 | | |
1736 | | static int |
1737 | | plane_strip_copy_rop2(gx_device_memory * mdev, |
1738 | | const byte * sdata, int sourcex, uint sraster, |
1739 | | gx_bitmap_id id, const gx_color_index * scolors, |
1740 | | const gx_strip_bitmap * textures, |
1741 | | const gx_color_index * tcolors, |
1742 | | int x, int y, int width, int height, |
1743 | | int phase_x, int phase_y, |
1744 | | gs_logical_operation_t lop, int plane, |
1745 | | uint planar_height) |
1746 | 0 | { |
1747 | 0 | mem_save_params_t save; |
1748 | 0 | int code; |
1749 | 0 | const gdev_mem_functions *fns; |
1750 | 0 | int n, m; |
1751 | 0 | dev_proc_encode_color(*save_encode); |
1752 | 0 | dev_proc_get_color_mapping_procs(*save_gcmp); |
1753 | 0 | gx_color_index save_black, save_white; |
1754 | | |
1755 | | /* assert(planar_height == 0); */ |
1756 | |
|
1757 | 0 | MEM_SAVE_PARAMS(mdev, save); |
1758 | 0 | mdev->line_ptrs += mdev->height * plane; |
1759 | 0 | fns = gdev_mem_functions_for_bits(mdev->planes[plane].depth); |
1760 | | /* strip_copy_rop2 might end up calling get_bits_rectangle or fill_rectangle, |
1761 | | * so ensure we have the right ones in there. */ |
1762 | 0 | set_dev_proc(mdev, get_bits_rectangle, fns->get_bits_rectangle); |
1763 | 0 | set_dev_proc(mdev, fill_rectangle, fns->fill_rectangle); |
1764 | | /* We are about to change the number of components, so the cached black |
1765 | | * and white values are no longer correct. */ |
1766 | 0 | save_black = mdev->cached_colors.black; |
1767 | 0 | save_white = mdev->cached_colors.white; |
1768 | 0 | mdev->cached_colors.black = gx_no_color_index; |
1769 | 0 | mdev->cached_colors.white = gx_no_color_index; |
1770 | | /* The strip_copy_rop2 routine can end up trying to calculate black |
1771 | | * and white values. For this it will call 'get_color_mapping_procs' |
1772 | | * and encode_color. We can't have it calling the devices own ones |
1773 | | * because they assume multiple planes, not just one. Store the |
1774 | | * originals, and swap them out for sane ones. It's possible that |
1775 | | * for some crazy devices, these choices might not be perfect, |
1776 | | * but it's hard to see what we could do better, so those devices |
1777 | | * might need to implement their own strip_copy_rop2. */ |
1778 | 0 | save_encode = dev_proc(mdev, encode_color); |
1779 | 0 | save_gcmp = dev_proc(mdev, get_color_mapping_procs); |
1780 | 0 | set_dev_proc(mdev, get_color_mapping_procs, gx_default_DevGray_get_color_mapping_procs); |
1781 | 0 | set_dev_proc(mdev, encode_color, gx_default_gray_encode_color); |
1782 | | /* mdev->color_info.depth is restored by MEM_RESTORE_PARAMS below. */ |
1783 | 0 | mdev->color_info.depth = mdev->planes[plane].depth; |
1784 | 0 | n = mdev->color_info.num_components; |
1785 | 0 | mdev->color_info.num_components = 1; |
1786 | 0 | m = mdev->num_planar_planes; |
1787 | 0 | mdev->num_planar_planes = 1; |
1788 | 0 | code = fns->strip_copy_rop2((gx_device *)mdev, sdata, sourcex, sraster, |
1789 | 0 | id, scolors, textures, tcolors, |
1790 | 0 | x, y, width, height, |
1791 | 0 | phase_x, phase_y, lop, planar_height); |
1792 | | /* Restore color details. */ |
1793 | 0 | mdev->color_info.num_components = n; |
1794 | 0 | mdev->num_planar_planes = m; |
1795 | 0 | set_dev_proc(mdev, get_bits_rectangle, mem_planar_get_bits_rectangle); |
1796 | 0 | set_dev_proc(mdev, fill_rectangle, mem_planar_fill_rectangle); |
1797 | 0 | set_dev_proc(mdev, encode_color, save_encode); |
1798 | 0 | set_dev_proc(mdev, get_color_mapping_procs, save_gcmp); |
1799 | 0 | mdev->cached_colors.black = save_black; |
1800 | 0 | mdev->cached_colors.white = save_white; |
1801 | | /* The following effectively does: mdev->line_ptrs -= mdev->height * plane; */ |
1802 | 0 | MEM_RESTORE_PARAMS(mdev, save); |
1803 | 0 | return code; |
1804 | 0 | } |
1805 | | |
1806 | | /* |
1807 | | * Repack planar into chunky format. This is an internal procedure that |
1808 | | * implements the straightforward chunky case of get_bits_rectangle, and |
1809 | | * is also used for the general cases. |
1810 | | */ |
1811 | | static int |
1812 | | planar_to_chunky(gx_device_memory *mdev, int x, int y, int w, int h, |
1813 | | int offset, uint draster, byte *dest, byte **line_ptrs, |
1814 | | int plane_height) |
1815 | 474k | { |
1816 | 474k | int num_planes = mdev->num_planar_planes; |
1817 | 474k | const byte *sptr[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1818 | 474k | int sbit[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
1819 | 474k | byte *dptr; |
1820 | 474k | int dbit; |
1821 | 474k | byte dbbyte; |
1822 | 474k | int ddepth = mdev->color_info.depth; |
1823 | 474k | int direct = |
1824 | 474k | (mdev->color_info.depth != num_planes * mdev->plane_depth ? 0 : |
1825 | 474k | mdev->planes[0].shift == 0 ? -mdev->plane_depth : mdev->plane_depth); |
1826 | 474k | int pi, ix, iy; |
1827 | | |
1828 | | /* Check whether the planes are of equal size and sequential. */ |
1829 | | /* If direct != 0, we already know they exactly fill the depth. */ |
1830 | 474k | if (direct < 0) { |
1831 | 0 | for (pi = 0; pi < num_planes; ++pi) |
1832 | 0 | if (mdev->planes[pi].shift != pi * -direct) { |
1833 | 0 | direct = 0; break; |
1834 | 0 | } |
1835 | 474k | } else if (direct > 0) { |
1836 | 2.37M | for (pi = 0; pi < num_planes; ++pi) |
1837 | 1.89M | if (mdev->planes[num_planes - 1 - pi].shift != pi * direct) { |
1838 | 0 | direct = 0; break; |
1839 | 0 | } |
1840 | 474k | } |
1841 | 948k | for (iy = y; iy < y + h; ++iy) { |
1842 | 474k | byte **line_ptr = line_ptrs + iy; |
1843 | | |
1844 | 2.37M | for (pi = 0; pi < num_planes; ++pi, line_ptr += plane_height) { |
1845 | 1.89M | int plane_depth = mdev->planes[pi].depth; |
1846 | 1.89M | int xbit = x * plane_depth; |
1847 | | |
1848 | 1.89M | sptr[pi] = *line_ptr + (xbit >> 3); |
1849 | 1.89M | sbit[pi] = xbit & 7; |
1850 | 1.89M | } |
1851 | 474k | { |
1852 | 474k | int xbit = offset * ddepth; |
1853 | | |
1854 | 474k | dptr = dest + (iy - y) * draster + (xbit >> 3); |
1855 | 474k | dbit = xbit & 7; |
1856 | 474k | } |
1857 | 474k | if (direct == -8) { |
1858 | | /* 1 byte per component, lsb first. */ |
1859 | 0 | switch (num_planes) { |
1860 | 0 | case 3: { |
1861 | 0 | const byte *p0 = sptr[2]; |
1862 | 0 | const byte *p1 = sptr[1]; |
1863 | 0 | const byte *p2 = sptr[0]; |
1864 | |
|
1865 | 0 | for (ix = w; ix > 0; --ix, dptr += 3) { |
1866 | 0 | dptr[0] = *p0++; |
1867 | 0 | dptr[1] = *p1++; |
1868 | 0 | dptr[2] = *p2++; |
1869 | 0 | } |
1870 | 0 | } |
1871 | 0 | continue; |
1872 | 0 | case 4: |
1873 | 0 | for (ix = w; ix > 0; --ix, dptr += 4) { |
1874 | 0 | dptr[0] = *sptr[3]++; |
1875 | 0 | dptr[1] = *sptr[2]++; |
1876 | 0 | dptr[2] = *sptr[1]++; |
1877 | 0 | dptr[3] = *sptr[0]++; |
1878 | 0 | } |
1879 | 0 | continue; |
1880 | 0 | default: |
1881 | 0 | break; |
1882 | 0 | } |
1883 | 0 | } |
1884 | 474k | dbbyte = (dbit ? (byte)(*dptr & (0xff00 >> dbit)) : 0); |
1885 | | /* sample_store_preload(dbbyte, dptr, dbit, ddepth);*/ |
1886 | 21.6M | for (ix = w; ix > 0; --ix) { |
1887 | 21.1M | gx_color_index color = 0; |
1888 | | |
1889 | 105M | for (pi = 0; pi < num_planes; ++pi) { |
1890 | 84.6M | int plane_depth = mdev->planes[pi].depth; |
1891 | 84.6M | ushort value; |
1892 | | |
1893 | 84.6M | if (sample_load_next16(&value, &sptr[pi], &sbit[pi], plane_depth) < 0) |
1894 | 0 | return_error(gs_error_rangecheck); |
1895 | 84.6M | color |= (gx_color_index)value << mdev->planes[pi].shift; |
1896 | 84.6M | } |
1897 | 21.1M | if (sizeof(color) > 4) { |
1898 | 21.1M | if (sample_store_next64(color, &dptr, &dbit, ddepth, &dbbyte) < 0) |
1899 | 0 | return_error(gs_error_rangecheck); |
1900 | 21.1M | } |
1901 | 0 | else { |
1902 | 0 | if (sample_store_next32(color, &dptr, &dbit, ddepth, &dbbyte) < 0) |
1903 | 0 | return_error(gs_error_rangecheck); |
1904 | 0 | } |
1905 | 21.1M | } |
1906 | 474k | sample_store_flush(dptr, dbit, dbbyte); |
1907 | 474k | } |
1908 | 474k | return 0; |
1909 | 474k | } |
1910 | | |
1911 | | static byte cmykrop[256] = |
1912 | | { |
1913 | | 255,127,191,63,223,95,159,31,239,111,175,47,207,79,143,15, |
1914 | | 247,119,183,55,215,87,151,23,231,103,167,39,199,71,135,7, |
1915 | | 251,123,187,59,219,91,155,27,235,107,171,43,203,75,139,11, |
1916 | | 243,115,179,51,211,83,147,19,227,99,163,35,195,67,131,3, |
1917 | | 253,125,189,61,221,93,157,29,237,109,173,45,205,77,141,13, |
1918 | | 245,117,181,53,213,85,149,21,229,101,165,37,197,69,133,5, |
1919 | | 249,121,185,57,217,89,153,25,233,105,169,41,201,73,137,9, |
1920 | | 241,113,177,49,209,81,145,17,225,97,161,33,193,65,129,1, |
1921 | | 254,126,190,62,222,94,158,30,238,110,174,46,206,78,142,14, |
1922 | | 246,118,182,54,214,86,150,22,230,102,166,38,198,70,134,6, |
1923 | | 250,122,186,58,218,90,154,26,234,106,170,42,202,74,138,10, |
1924 | | 242,114,178,50,210,82,146,18,226,98,162,34,194,66,130,2, |
1925 | | 252,124,188,60,220,92,156,28,236,108,172,44,204,76,140,12, |
1926 | | 244,116,180,52,212,84,148,20,228,100,164,36,196,68,132,4, |
1927 | | 248,120,184,56,216,88,152,24,232,104,168,40,200,72,136,8, |
1928 | | 240,112,176,48,208,80,144,16,224,96,160,32,192,64,128,0 |
1929 | | }; |
1930 | | |
1931 | | static int |
1932 | | mem_planar_strip_copy_rop2(gx_device * dev, |
1933 | | const byte * sdata, int sourcex, uint sraster, |
1934 | | gx_bitmap_id id, const gx_color_index * scolors, |
1935 | | const gx_strip_bitmap * textures, |
1936 | | const gx_color_index * tcolors, |
1937 | | int x, int y, int width, int height, |
1938 | | int phase_x, int phase_y, |
1939 | | gs_logical_operation_t lop, |
1940 | | uint planar_height) |
1941 | 0 | { |
1942 | 0 | gx_device_memory * const mdev = (gx_device_memory *)dev; |
1943 | 0 | int code; |
1944 | |
|
1945 | 0 | lop = lop_sanitize(lop); |
1946 | 0 | if (planar_height != 0) { |
1947 | | /* S is in planar format; expand it to a temporary buffer, then |
1948 | | * call ourselves back with a modified rop to use it, then free |
1949 | | * the temporary buffer, and return. */ |
1950 | | /* Make a temporary buffer that contains both the raster and the line |
1951 | | * pointers for the buffer. For now, for the sake of sanity, we |
1952 | | * convert whole lines of s, but only as many lines as we have to. */ |
1953 | | /* We assume that scolors == NULL here */ |
1954 | 0 | int i; |
1955 | 0 | int j; |
1956 | 0 | uint chunky_sraster; |
1957 | 0 | uint nbytes; |
1958 | 0 | byte **line_ptrs; |
1959 | 0 | byte *sbuf, *buf; |
1960 | |
|
1961 | 0 | chunky_sraster = sraster * mdev->num_planar_planes; |
1962 | 0 | nbytes = height * chunky_sraster; |
1963 | 0 | buf = gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(buf)"); |
1964 | 0 | if (buf == NULL) { |
1965 | 0 | return gs_note_error(gs_error_VMerror); |
1966 | 0 | } |
1967 | 0 | nbytes = sizeof(byte *) * mdev->num_planar_planes * height; |
1968 | 0 | line_ptrs = (byte **)gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(line_ptrs)"); |
1969 | 0 | if (line_ptrs == NULL) { |
1970 | 0 | gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)"); |
1971 | 0 | return gs_note_error(gs_error_VMerror); |
1972 | 0 | } |
1973 | 0 | for (j = 0; j < mdev->color_info.num_components; j++) { |
1974 | 0 | sbuf = (byte *)sdata + j * sraster * planar_height; |
1975 | 0 | for (i = height; i > 0; i--) { |
1976 | 0 | *line_ptrs++ = sbuf; |
1977 | 0 | sbuf += sraster; |
1978 | 0 | } |
1979 | 0 | } |
1980 | 0 | line_ptrs -= height * mdev->num_planar_planes; |
1981 | 0 | planar_to_chunky(mdev, sourcex, 0, width, height, |
1982 | 0 | 0, chunky_sraster, buf, line_ptrs, height); |
1983 | 0 | gs_free_object(mdev->memory, line_ptrs, "mem_planar_strip_copy_rop(line_ptrs)"); |
1984 | 0 | code = mem_planar_strip_copy_rop2(dev, buf, 0, chunky_sraster, |
1985 | 0 | id, scolors, textures, tcolors, |
1986 | 0 | x, y, width, height, phase_x, phase_y, |
1987 | 0 | lop, 0); |
1988 | 0 | gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)"); |
1989 | 0 | return code; |
1990 | 0 | } |
1991 | | |
1992 | 0 | if (textures && textures->num_planes > 1) { |
1993 | | /* T is in planar format; expand it to a temporary buffer, then |
1994 | | * call ourselves back with a modified rop to use it, then free |
1995 | | * the temporary buffer, and return. */ |
1996 | | /* Make a temporary buffer that contains both the raster and the line |
1997 | | * pointers for the buffer. For now, for the sake of sanity, we |
1998 | | * convert whole lines of t, but only as many lines as we have to |
1999 | | * (unless it loops). */ |
2000 | | /* We assume that tcolors == NULL here */ |
2001 | 0 | int ty, i; |
2002 | 0 | uint chunky_t_raster; |
2003 | 0 | uint chunky_t_height; |
2004 | 0 | uint nbytes; |
2005 | 0 | byte **line_ptrs; |
2006 | 0 | byte *tbuf, *buf; |
2007 | 0 | gx_strip_bitmap newtex; |
2008 | |
|
2009 | 0 | ty = (y + phase_y) % textures->rep_height; |
2010 | 0 | if (ty < 0) |
2011 | 0 | ty += textures->rep_height; |
2012 | 0 | chunky_t_raster = bitmap_raster(textures->rep_width * mdev->color_info.depth); |
2013 | 0 | if (ty + height <= textures->rep_height) { |
2014 | 0 | chunky_t_height = height; |
2015 | 0 | phase_y = -y; |
2016 | 0 | } else { |
2017 | 0 | ty = 0; |
2018 | 0 | chunky_t_height = textures->rep_height; |
2019 | 0 | } |
2020 | 0 | nbytes = chunky_t_height * chunky_t_raster; |
2021 | 0 | buf = gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(buf)"); |
2022 | 0 | if (buf == NULL) { |
2023 | 0 | return gs_note_error(gs_error_VMerror); |
2024 | 0 | } |
2025 | 0 | nbytes = sizeof(byte *) * mdev->num_planar_planes * textures->rep_height; |
2026 | 0 | line_ptrs = (byte **)gs_alloc_bytes(mdev->memory, nbytes, "mem_planar_strip_copy_rop(line_ptrs)"); |
2027 | 0 | if (line_ptrs == NULL) { |
2028 | 0 | gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)"); |
2029 | 0 | return gs_note_error(gs_error_VMerror); |
2030 | 0 | } |
2031 | 0 | tbuf = textures->data; |
2032 | 0 | for (i = textures->rep_height * mdev->num_planar_planes; i > 0; i--) { |
2033 | 0 | *line_ptrs++ = tbuf; |
2034 | 0 | tbuf += textures->raster; |
2035 | 0 | } |
2036 | 0 | line_ptrs -= textures->rep_height * mdev->num_planar_planes; |
2037 | 0 | planar_to_chunky(mdev, 0, ty, textures->rep_width, chunky_t_height, |
2038 | 0 | 0, chunky_t_raster, buf, line_ptrs, textures->rep_height); |
2039 | 0 | gs_free_object(mdev->memory, line_ptrs, "mem_planar_strip_copy_rop(line_ptrs)"); |
2040 | 0 | newtex = *textures; |
2041 | 0 | newtex.data = buf; |
2042 | 0 | newtex.raster = chunky_t_raster; |
2043 | 0 | newtex.num_planes = 1; |
2044 | 0 | newtex.size.x = textures->rep_width; |
2045 | 0 | newtex.size.y = textures->rep_height; |
2046 | 0 | code = mem_planar_strip_copy_rop2(dev, sdata, sourcex, sraster, |
2047 | 0 | id, scolors, &newtex, tcolors, |
2048 | 0 | x, y, width, height, phase_x, phase_y, |
2049 | 0 | lop, planar_height); |
2050 | 0 | gs_free_object(mdev->memory, buf, "mem_planar_strip_copy_rop(buf)"); |
2051 | 0 | return code; |
2052 | 0 | } |
2053 | | |
2054 | | /* Not doing a planar lop. If we carry on down the default path here, |
2055 | | * we'll end up doing a planar_to_chunky; we may be able to sidestep |
2056 | | * that by spotting cases where we can operate directly. */ |
2057 | 0 | if ((!lop_uses_T(lop) || (tcolors && (tcolors[0] == tcolors[1]))) && |
2058 | 0 | (mdev->color_info.num_components == mdev->num_planar_planes)) { |
2059 | | /* No T in use, or constant T. */ |
2060 | 0 | if ((!lop_uses_S(lop) || (scolors && (scolors[0] == scolors[1]))) && |
2061 | 0 | ((mdev->color_info.num_components == 1) || (mdev->color_info.num_components == 3))) { |
2062 | 0 | int plane; |
2063 | | /* No S in use, or constant S. And either greyscale or rgb, |
2064 | | * so we can just do the rop on each plane in turn. */ |
2065 | 0 | for (plane=0; plane < mdev->color_info.num_components; plane++) |
2066 | 0 | { |
2067 | 0 | gx_color_index tcolors2[2], scolors2[2]; |
2068 | 0 | int shift = mdev->planes[plane].shift; |
2069 | 0 | int mask = (1<<mdev->planes[plane].depth)-1; |
2070 | |
|
2071 | 0 | if (tcolors) { |
2072 | 0 | tcolors2[0] = (tcolors[0] >> shift) & mask; |
2073 | 0 | tcolors2[1] = (tcolors[1] >> shift) & mask; |
2074 | 0 | } |
2075 | 0 | if (scolors) { |
2076 | 0 | scolors2[0] = (scolors[0] >> shift) & mask; |
2077 | 0 | scolors2[1] = (scolors[1] >> shift) & mask; |
2078 | 0 | } |
2079 | 0 | code = plane_strip_copy_rop2(mdev, sdata, sourcex, sraster, |
2080 | 0 | id, (scolors ? scolors2 : NULL), |
2081 | 0 | textures, (tcolors ? tcolors2 : NULL), |
2082 | 0 | x, y, width, height, |
2083 | 0 | phase_x, phase_y, lop, plane, 0); |
2084 | 0 | if (code < 0) |
2085 | 0 | return code; |
2086 | 0 | } |
2087 | 0 | return 0; |
2088 | 0 | } |
2089 | 0 | if ((mdev->color_info.num_components == 4) && (mdev->plane_depth == 1)) |
2090 | 0 | { |
2091 | 0 | lop = cmykrop[lop & 0xff] | (lop & ~0xff); |
2092 | 0 | return planar_cmyk4bit_strip_copy_rop2(mdev, sdata, sourcex, |
2093 | 0 | sraster, id, scolors, |
2094 | 0 | textures, tcolors, |
2095 | 0 | x, y, width, height, |
2096 | 0 | phase_x, phase_y, |
2097 | 0 | lop, 0); |
2098 | 0 | } |
2099 | 0 | } |
2100 | 0 | if (!tcolors && !scolors && |
2101 | 0 | (mdev->color_info.num_components == 4) && (mdev->plane_depth == 1)) { |
2102 | 0 | lop = cmykrop[lop & 0xff] | (lop & ~0xff); |
2103 | 0 | return planar_cmyk4bit_strip_copy_rop2(mdev, sdata, sourcex, |
2104 | 0 | sraster, id, scolors, |
2105 | 0 | textures, tcolors, |
2106 | 0 | x, y, width, height, |
2107 | 0 | phase_x, phase_y, |
2108 | 0 | lop, 0); |
2109 | 0 | } |
2110 | | /* Fall back to the default implementation (the only one that |
2111 | | * guarantees to properly cope with D being planar). */ |
2112 | 0 | return mem_default_strip_copy_rop2(dev, sdata, sourcex, sraster, |
2113 | 0 | id, scolors, textures, tcolors, |
2114 | 0 | x, y, width, height, |
2115 | 0 | phase_x, phase_y, lop, 0); |
2116 | 0 | } |
2117 | | |
2118 | | /* Copy bits back from a planar memory device. */ |
2119 | | static int |
2120 | | mem_planar_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect, |
2121 | | gs_get_bits_params_t * params) |
2122 | 7.85M | { |
2123 | | /* This duplicates most of mem_get_bits_rectangle. Tant pgs. */ |
2124 | 7.85M | gx_device_memory * const mdev = (gx_device_memory *)dev; |
2125 | 7.85M | gs_get_bits_options_t options = params->options; |
2126 | 7.85M | int x = prect->p.x, w = prect->q.x - x, y = prect->p.y, h = prect->q.y - y; |
2127 | 7.85M | int num_planes = mdev->num_planar_planes; |
2128 | 7.85M | gs_get_bits_params_t copy_params; |
2129 | 7.85M | int code; |
2130 | | |
2131 | 7.85M | if (options == 0) { |
2132 | | /* |
2133 | | * Unfortunately, as things stand, we have to support |
2134 | | * GB_PACKING_CHUNKY. In fact, we can't even claim to support |
2135 | | * GB_PACKING_PLANAR, because there is currently no way to |
2136 | | * describe the particular planar packing format that the device |
2137 | | * actually stores. |
2138 | | */ |
2139 | 0 | params->options = |
2140 | 0 | (GB_ALIGN_STANDARD | GB_ALIGN_ANY) | |
2141 | 0 | (GB_RETURN_COPY | GB_RETURN_POINTER) | |
2142 | 0 | (GB_OFFSET_0 | GB_OFFSET_SPECIFIED | GB_OFFSET_ANY) | |
2143 | 0 | (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED | GB_RASTER_ANY) | |
2144 | | /* |
2145 | | (mdev->num_planes == mdev->color_info.depth ? |
2146 | | GB_PACKING_CHUNKY | GB_PACKING_PLANAR | GB_PACKING_BIT_PLANAR : |
2147 | | GB_PACKING_CHUNKY | GB_PACKING_PLANAR) |
2148 | | */ |
2149 | 0 | GB_PACKING_CHUNKY | |
2150 | 0 | GB_COLORS_NATIVE | GB_ALPHA_NONE; |
2151 | 0 | return_error(gs_error_rangecheck); |
2152 | 0 | } |
2153 | | |
2154 | 7.85M | if (mdev->line_ptrs == 0x00) |
2155 | 0 | return_error(gs_error_rangecheck); |
2156 | | |
2157 | 7.85M | if ((w <= 0) | (h <= 0)) { |
2158 | 0 | if ((w | h) < 0) |
2159 | 0 | return_error(gs_error_rangecheck); |
2160 | 0 | return 0; |
2161 | 0 | } |
2162 | 7.85M | if (x < 0 || w > dev->width - x || |
2163 | 7.85M | y < 0 || h > dev->height - y |
2164 | 7.85M | ) |
2165 | 0 | return_error(gs_error_rangecheck); |
2166 | | |
2167 | | /* First off, see if we can satisfy get_bits_rectangle with just returning |
2168 | | * pointers to the existing data. */ |
2169 | 7.85M | if (params->options & GB_RETURN_POINTER) |
2170 | 7.38M | { |
2171 | 7.38M | gs_get_bits_params_t copy_params; |
2172 | 7.38M | byte **base = &scan_line_base(mdev, y); |
2173 | 7.38M | int code; |
2174 | | |
2175 | 7.38M | copy_params.options = |
2176 | 7.38M | GB_COLORS_NATIVE | GB_PACKING_PLANAR | GB_ALPHA_NONE | |
2177 | 7.38M | (mdev->raster == |
2178 | 7.38M | bitmap_raster(mdev->width * mdev->color_info.depth) ? |
2179 | 7.38M | GB_RASTER_STANDARD : GB_RASTER_SPECIFIED); |
2180 | 7.38M | copy_params.raster = mdev->raster; |
2181 | 7.38M | code = gx_get_bits_return_pointer(dev, x, h, params, |
2182 | 7.38M | ©_params, base); |
2183 | 7.38M | if (code >= 0) |
2184 | 7.38M | return code; |
2185 | 7.38M | } |
2186 | | |
2187 | | /* |
2188 | | * If the request is for exactly one plane, hand it off to a device |
2189 | | * temporarily tweaked to return just that plane. |
2190 | | */ |
2191 | 476k | if (!(~options & (GB_PACKING_PLANAR | GB_SELECT_PLANES))) { |
2192 | | /* Check that only a single plane is being requested. */ |
2193 | 2.29k | int pi; |
2194 | | |
2195 | 5.77k | for (pi = 0; pi < num_planes; ++pi) |
2196 | 5.77k | if (params->data[pi] != 0) |
2197 | 2.29k | break; |
2198 | 2.29k | if (pi < num_planes) { |
2199 | 2.29k | int plane = pi++; |
2200 | | |
2201 | 5.77k | for (; pi < num_planes; ++pi) |
2202 | 3.48k | if (params->data[pi] != 0) |
2203 | 0 | break; |
2204 | 2.29k | if (pi == num_planes) { |
2205 | 2.29k | mem_save_params_t save; |
2206 | | |
2207 | 2.29k | copy_params = *params; |
2208 | 2.29k | copy_params.options = |
2209 | 2.29k | (options & ~(GB_PACKING_ALL | GB_SELECT_PLANES)) | |
2210 | 2.29k | GB_PACKING_CHUNKY; |
2211 | 2.29k | copy_params.data[0] = copy_params.data[plane]; |
2212 | 2.29k | MEM_SAVE_PARAMS(mdev, save); |
2213 | 2.29k | mdev->line_ptrs += mdev->height * plane; |
2214 | 2.29k | MEM_SET_PARAMS(mdev, mdev->planes[plane].depth); |
2215 | 2.29k | code = mem_get_bits_rectangle(dev, prect, ©_params); |
2216 | 2.29k | MEM_RESTORE_PARAMS(mdev, save); |
2217 | 2.29k | if (code >= 0) { |
2218 | 2.29k | params->data[plane] = copy_params.data[0]; |
2219 | 2.29k | return code; |
2220 | 2.29k | } |
2221 | 2.29k | } |
2222 | 2.29k | } |
2223 | 2.29k | } |
2224 | | |
2225 | 474k | if ((params->options & GB_RETURN_POINTER) == 0) { |
2226 | | /* Can we do the fetch using a faked GB_RETURN_POINTER request |
2227 | | * and then copy the data? */ |
2228 | 474k | gs_get_bits_params_t params2 = *params; |
2229 | 474k | gs_get_bits_params_t copy_params; |
2230 | 474k | byte **base = &scan_line_base(mdev, y); |
2231 | 474k | int code; |
2232 | | |
2233 | 474k | params2.options &= ~GB_RETURN_COPY; |
2234 | 474k | params2.options |= GB_RETURN_POINTER; |
2235 | | |
2236 | 474k | copy_params.options = |
2237 | 474k | GB_COLORS_NATIVE | GB_PACKING_PLANAR | GB_ALPHA_NONE | |
2238 | 474k | (mdev->raster == |
2239 | 474k | bitmap_raster(mdev->width * mdev->color_info.depth) ? |
2240 | 474k | GB_RASTER_STANDARD : GB_RASTER_SPECIFIED); |
2241 | 474k | params2.raster = mdev->raster; |
2242 | 474k | copy_params.raster = mdev->raster; |
2243 | 474k | code = gx_get_bits_return_pointer(dev, x, h, ¶ms2, |
2244 | 474k | ©_params, base); |
2245 | 474k | if (code >= 0) { |
2246 | | /* get_bits worked. Let's copy the data out. */ |
2247 | 0 | int bpc = mdev->color_info.depth / mdev->num_planar_planes; |
2248 | 0 | int left = x; |
2249 | 0 | int right = x+w; |
2250 | 0 | int i, j; |
2251 | 0 | switch (bpc) { |
2252 | 0 | case 1: left >>= 3; right = (right+7)>>3; break; |
2253 | 0 | case 2: left >>= 2; right = (right+3)>>2; break; |
2254 | 0 | case 4: left >>= 1; right = (right+1)>>1; break; |
2255 | 0 | case 8: break; |
2256 | 0 | case 12: left = (left&~1); left += left>>1; |
2257 | 0 | right = right+(right>>1)+(right&1); break; |
2258 | 0 | case 16: left *= 2; right *= 2; break; |
2259 | 0 | default: return_error(gs_error_rangecheck); |
2260 | 0 | } |
2261 | 0 | right -= left; |
2262 | 0 | for (i = 0; i < mdev->num_planar_planes; i++) { |
2263 | 0 | byte *d = params->data[i]; |
2264 | 0 | const byte *s = params2.data[i]; |
2265 | 0 | for (j = 0; j < h; j++) { |
2266 | 0 | memcpy(d, s, right); |
2267 | 0 | d += params->raster; |
2268 | 0 | s += params2.raster; |
2269 | 0 | } |
2270 | 0 | } |
2271 | 0 | return code; |
2272 | 0 | } |
2273 | 474k | } |
2274 | | |
2275 | | /* |
2276 | | * We can't return the requested plane by itself. Fall back to |
2277 | | * chunky format. This is somewhat painful. |
2278 | | * |
2279 | | * The code here knows how to produce just one chunky format: |
2280 | | * GB_COLORS_NATIVE, GB_ALPHA_NONE, GB_RETURN_COPY. |
2281 | | * For any other format, we generate this one in a buffer and |
2282 | | * hand it off to gx_get_bits_copy. This is *really* painful. |
2283 | | */ |
2284 | 474k | if (!(~options & (GB_COLORS_NATIVE | GB_ALPHA_NONE | |
2285 | 474k | GB_PACKING_CHUNKY | GB_RETURN_COPY))) { |
2286 | 474k | int offset = (options & GB_OFFSET_SPECIFIED ? params->x_offset : 0); |
2287 | 474k | uint draster = |
2288 | 474k | (options & GB_RASTER_SPECIFIED ? params->raster : |
2289 | 474k | bitmap_raster((offset + w) * mdev->color_info.depth)); |
2290 | | |
2291 | 474k | planar_to_chunky(mdev, x, y, w, h, offset, draster, params->data[0], |
2292 | 474k | mdev->line_ptrs, mdev->height); |
2293 | 474k | } else { |
2294 | | /* |
2295 | | * Do the transfer through an intermediate buffer. |
2296 | | * The buffer must be large enough to hold at least one pixel, |
2297 | | * i.e., GX_DEVICE_COLOR_MAX_COMPONENTS 16-bit values. |
2298 | | * The algorithms are very similar to those in copy_color. |
2299 | | */ |
2300 | 0 | #define BUF_LONGS\ |
2301 | 0 | max(100, (GX_DEVICE_COLOR_MAX_COMPONENTS * 2 + sizeof(long) - 1) /\ |
2302 | 0 | sizeof(long)) |
2303 | 0 | #define BUF_BYTES (BUF_LONGS * ARCH_SIZEOF_LONG) |
2304 | 0 | union b_ { |
2305 | 0 | ulong l[BUF_LONGS]; |
2306 | 0 | byte b[BUF_BYTES]; |
2307 | 0 | } buf; |
2308 | 0 | int br, bw, bh, cx, cy, cw, ch; |
2309 | 0 | int ddepth = mdev->color_info.depth; |
2310 | 0 | uint raster = bitmap_raster(ddepth * mdev->width); |
2311 | 0 | gs_get_bits_params_t dest_params; |
2312 | 0 | int dest_bytes; |
2313 | |
|
2314 | 0 | if (raster > BUF_BYTES) { |
2315 | 0 | br = BUF_BYTES; |
2316 | 0 | bw = BUF_BYTES * 8 / ddepth; |
2317 | 0 | bh = 1; |
2318 | 0 | } else { |
2319 | 0 | br = raster; |
2320 | 0 | bw = w; |
2321 | 0 | bh = BUF_BYTES / raster; |
2322 | 0 | } |
2323 | 0 | copy_params.options = |
2324 | 0 | GB_COLORS_NATIVE | GB_PACKING_CHUNKY | GB_ALPHA_NONE | |
2325 | 0 | GB_RASTER_STANDARD; |
2326 | 0 | copy_params.raster = raster; |
2327 | | /* The options passed in from above may have GB_OFFSET_0, and what's |
2328 | | * more, the code below may insist on GB_OFFSET_0 being set. Hence we |
2329 | | * can't rely on x_offset to allow for the block size we are using. |
2330 | | * We'll have to adjust the pointer by steam. */ |
2331 | 0 | dest_params = *params; |
2332 | 0 | dest_params.x_offset = params->x_offset; |
2333 | 0 | if (options & GB_COLORS_RGB) |
2334 | 0 | dest_bytes = 3; |
2335 | 0 | else if (options & GB_COLORS_CMYK) |
2336 | 0 | dest_bytes = 4; |
2337 | 0 | else if (options & GB_COLORS_GRAY) |
2338 | 0 | dest_bytes = 1; |
2339 | 0 | else |
2340 | 0 | dest_bytes = mdev->color_info.depth / mdev->plane_depth; |
2341 | | /* We assume options & GB_DEPTH_8 */ |
2342 | 0 | for (cy = y; cy < y + h; cy += ch) { |
2343 | 0 | ch = min(bh, y + h - cy); |
2344 | 0 | for (cx = x; cx < x + w; cx += cw) { |
2345 | 0 | cw = min(bw, x + w - cx); |
2346 | 0 | planar_to_chunky(mdev, cx, cy, cw, ch, 0, br, buf.b, |
2347 | 0 | mdev->line_ptrs, mdev->height); |
2348 | 0 | code = gx_get_bits_copy(dev, 0, cw, ch, &dest_params, |
2349 | 0 | ©_params, buf.b, br); |
2350 | 0 | if (code < 0) |
2351 | 0 | return code; |
2352 | 0 | dest_params.data[0] += cw * dest_bytes; |
2353 | 0 | } |
2354 | 0 | dest_params.data[0] += ch * dest_params.raster - (w*dest_bytes); |
2355 | 0 | } |
2356 | 0 | #undef BUF_BYTES |
2357 | 0 | #undef BUF_LONGS |
2358 | 0 | } |
2359 | 474k | return 0; |
2360 | 474k | } |