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