/src/ghostpdl/base/gdevdbit.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2026 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | /* Default device bitmap copying implementation */ |
17 | | #include "gx.h" |
18 | | #include "gpcheck.h" |
19 | | #include "gserrors.h" |
20 | | #include "gsbittab.h" |
21 | | #include "gsrect.h" |
22 | | #include "gsropt.h" |
23 | | #include "gxdcolor.h" |
24 | | #include "gxdevice.h" |
25 | | #include "gxdevmem.h" |
26 | | #include "gdevmem.h" |
27 | | #include "gxgetbit.h" |
28 | | #undef mdev |
29 | | #include "gxcpath.h" |
30 | | |
31 | | /* Implement copy_mono by filling lots of small rectangles. */ |
32 | | /* This is very inefficient, but it works as a default. */ |
33 | | int |
34 | | gx_default_copy_mono(gx_device * dev, const byte * data, |
35 | | int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h, |
36 | | gx_color_index zero, gx_color_index one) |
37 | 451k | { |
38 | 451k | bool invert; |
39 | 451k | gx_color_index color; |
40 | 451k | gx_device_color devc; |
41 | | |
42 | 451k | if (!data) |
43 | 0 | return gs_throw_code(gs_error_unknownerror); |
44 | 451k | fit_copy(dev, data, dx, raster, id, x, y, w, h); |
45 | 367k | if (!data) |
46 | 0 | return gs_throw_code(gs_error_unknownerror); |
47 | 367k | if (one != gx_no_color_index) { |
48 | 351k | invert = false; |
49 | 351k | color = one; |
50 | 351k | if (zero != gx_no_color_index) { |
51 | 53.3k | int code = (*dev_proc(dev, fill_rectangle)) |
52 | 53.3k | (dev, x, y, w, h, zero); |
53 | | |
54 | 53.3k | if (code < 0) |
55 | 0 | return code; |
56 | 53.3k | } |
57 | 351k | } else { |
58 | 16.8k | invert = true; |
59 | 16.8k | color = zero; |
60 | 16.8k | } |
61 | 367k | if (!data) |
62 | 0 | return gs_throw_code(gs_error_unknownerror); |
63 | 367k | set_nonclient_dev_color(&devc, color); |
64 | 367k | if (!data) |
65 | 0 | return gs_throw_code(gs_error_unknownerror); |
66 | 367k | return gx_dc_default_fill_masked |
67 | 367k | (&devc, data, dx, raster, id, x, y, w, h, dev, rop3_T, invert); |
68 | 367k | } |
69 | | |
70 | | /* Implement copy_color by filling lots of small rectangles. */ |
71 | | /* This is very inefficient, but it works as a default. */ |
72 | | int |
73 | | gx_default_copy_color(gx_device * dev, const byte * data, |
74 | | int dx, int raster, gx_bitmap_id id, |
75 | | int x, int y, int w, int h) |
76 | 1.75M | { |
77 | 1.75M | int depth = dev->color_info.depth; |
78 | 1.75M | byte mask; |
79 | | |
80 | 1.75M | dev_proc_fill_rectangle((*fill)); |
81 | 1.75M | const byte *row; |
82 | 1.75M | int iy; |
83 | | |
84 | 1.75M | if (depth == 1) |
85 | 792k | return (*dev_proc(dev, copy_mono)) (dev, data, dx, raster, id, |
86 | 792k | x, y, w, h, |
87 | 792k | (gx_color_index) 0, (gx_color_index) 1); |
88 | 1.75M | fit_copy(dev, data, dx, raster, id, x, y, w, h); |
89 | 958k | fill = dev_proc(dev, fill_rectangle); |
90 | 958k | mask = (byte) ((1 << depth) - 1); |
91 | 1.92M | for (row = data, iy = 0; iy < h; row += raster, ++iy) { |
92 | 965k | int ix; |
93 | 965k | gx_color_index c0 = gx_no_color_index; |
94 | 965k | const byte *ptr = row + ((dx * depth) >> 3); |
95 | 965k | int i0; |
96 | | |
97 | 34.7M | for (i0 = ix = 0; ix < w; ++ix) { |
98 | 33.8M | gx_color_index color; |
99 | | |
100 | 33.8M | if (depth >= 8) { |
101 | 33.0M | color = *ptr++; |
102 | 33.0M | switch (depth) { |
103 | 0 | case 64: |
104 | 0 | color = (color << 8) + *ptr++; |
105 | 0 | case 56: |
106 | 0 | color = (color << 8) + *ptr++; |
107 | 0 | case 48: |
108 | 0 | color = (color << 8) + *ptr++; |
109 | 0 | case 40: |
110 | 0 | color = (color << 8) + *ptr++; |
111 | 0 | case 32: |
112 | 0 | color = (color << 8) + *ptr++; |
113 | 18.4M | case 24: |
114 | 18.4M | color = (color << 8) + *ptr++; |
115 | 18.4M | case 16: |
116 | 18.4M | color = (color << 8) + *ptr++; |
117 | 33.0M | } |
118 | 33.0M | } else { |
119 | 808k | uint dbit = (-(ix + dx + 1) * depth) & 7; |
120 | | |
121 | 808k | color = (*ptr >> dbit) & mask; |
122 | 808k | if (dbit == 0) |
123 | 387k | ptr++; |
124 | 808k | } |
125 | 33.8M | if (color != c0) { |
126 | 1.94M | if (ix > i0) { |
127 | 984k | int code = (*fill) |
128 | 984k | (dev, i0 + x, iy + y, ix - i0, 1, c0); |
129 | | |
130 | 984k | if (code < 0) |
131 | 0 | return code; |
132 | 984k | } |
133 | 1.94M | c0 = color; |
134 | 1.94M | i0 = ix; |
135 | 1.94M | } |
136 | 33.8M | } |
137 | 965k | if (ix > i0) { |
138 | 965k | int code = (*fill) (dev, i0 + x, iy + y, ix - i0, 1, c0); |
139 | | |
140 | 965k | if (code < 0) |
141 | 0 | return code; |
142 | 965k | } |
143 | 965k | } |
144 | 958k | return 0; |
145 | 958k | } |
146 | | |
147 | | int |
148 | | gx_no_copy_alpha(gx_device * dev, const byte * data, int data_x, |
149 | | int raster, gx_bitmap_id id, int x, int y, int width, int height, |
150 | | gx_color_index color, int depth) |
151 | 0 | { |
152 | 0 | return_error(gs_error_unknownerror); |
153 | 0 | } |
154 | | |
155 | | /* Currently we really should only be here if the target device is planar |
156 | | AND it supports devn colors AND is 8 or 16 bit. For example tiffsep |
157 | | and psdcmyk may make use of this if AA is enabled. It is basically |
158 | | designed for devices that need more than 64 bits for color support |
159 | | |
160 | | So that I can follow things and make it readable for future generations, |
161 | | I am not using the macro nightmare that default_copy_alpha uses. */ |
162 | | int |
163 | | gx_default_copy_alpha_hl_color(gx_device * dev, const byte * data, int data_x, |
164 | | int raster, gx_bitmap_id id, int x, int y, int width, int height, |
165 | | const gx_drawing_color *pdcolor, int depth) |
166 | 0 | { |
167 | 0 | const byte *row_alpha; |
168 | 0 | gs_memory_t *mem = dev->memory; |
169 | 0 | int bpp = dev->color_info.depth; |
170 | 0 | uchar ncomps = dev->color_info.num_components; |
171 | 0 | uint64_t out_raster, product = 0; |
172 | 0 | int code = 0; |
173 | 0 | gx_color_value src_cv[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
174 | 0 | gx_color_value curr_cv[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
175 | 0 | gx_color_value blend_cv[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
176 | 0 | int ry; |
177 | 0 | uchar k, j; |
178 | 0 | gs_get_bits_params_t gb_params; |
179 | 0 | byte *src_planes[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
180 | 0 | gs_int_rect gb_rect; |
181 | 0 | int byte_depth; |
182 | 0 | int shift, word_width; |
183 | 0 | gx_color_value *composite; |
184 | 0 | byte *gb_buff; |
185 | 0 | int x_curr, w_curr, gb_buff_start; |
186 | 0 | int has_tags = device_encodes_tags(dev); |
187 | |
|
188 | 0 | byte_depth = bpp / ncomps; |
189 | 0 | shift = 16 - byte_depth; |
190 | 0 | word_width = byte_depth >> 3; |
191 | |
|
192 | 0 | fit_copy(dev, data, data_x, raster, id, x, y, width, height); |
193 | 0 | row_alpha = data; |
194 | 0 | out_raster = bitmap_raster(width * (size_t)byte_depth); |
195 | 0 | if (check_64bit_multiply(out_raster, ncomps, (int64_t *) &product) != 0) |
196 | 0 | return gs_note_error(gs_error_undefinedresult); |
197 | 0 | gb_buff = gs_alloc_bytes(mem, product, "copy_alpha_hl_color(gb_buff)"); |
198 | 0 | if (gb_buff == 0) { |
199 | 0 | code = gs_note_error(gs_error_VMerror); |
200 | 0 | return code; |
201 | 0 | } |
202 | 0 | for (k = 0; k < ncomps; k++) { |
203 | 0 | src_cv[k] = pdcolor->colors.devn.values[k]; |
204 | 0 | } |
205 | | /* Initialize the get_bits parameters. Here we just get a plane at a time. */ |
206 | 0 | gb_params.options = GB_COLORS_NATIVE |
207 | 0 | | GB_ALPHA_NONE |
208 | 0 | | GB_DEPTH_ALL |
209 | 0 | | GB_PACKING_PLANAR |
210 | 0 | | GB_RETURN_COPY |
211 | 0 | | GB_ALIGN_STANDARD |
212 | 0 | | GB_OFFSET_0 |
213 | 0 | | GB_RASTER_STANDARD |
214 | 0 | | GB_SELECT_PLANES; |
215 | 0 | gb_rect.p.x = x; |
216 | 0 | gb_rect.q.x = x + width; |
217 | 0 | for (ry = y; ry < y + height; row_alpha += raster, ++ry) { |
218 | 0 | int sx, rx; |
219 | |
|
220 | 0 | gb_rect.p.y = ry; |
221 | 0 | gb_rect.q.y = ry+1; |
222 | 0 | for (k = 0; k < ncomps; k++) { |
223 | | /* First set the params to zero for all planes except the one we want */ |
224 | | /* I am not sure why get_bits_rectangle for the planar device can |
225 | | not hand back the data in a proper planar form. To get the |
226 | | individual planes seems that I need to jump through some hoops |
227 | | here */ |
228 | 0 | for (j = 0; j < ncomps; j++) |
229 | 0 | gb_params.data[j] = 0; |
230 | 0 | gb_params.data[k] = gb_buff + k * out_raster; |
231 | 0 | code = dev_proc(dev, get_bits_rectangle) (dev, &gb_rect, |
232 | 0 | &gb_params); |
233 | 0 | src_planes[k] = gb_params.data[k]; |
234 | 0 | if (code < 0) { |
235 | 0 | gs_free_object(mem, gb_buff, "copy_alpha_hl_color"); |
236 | 0 | return code; |
237 | 0 | } |
238 | 0 | } |
239 | | /* At this point we have to carry around some additional variables |
240 | | so that we can handle any buffer flushes due to alpha == 0 values. |
241 | | See below why this is needed */ |
242 | 0 | x_curr = x; |
243 | 0 | w_curr = 0; |
244 | 0 | gb_buff_start = 0; |
245 | 0 | for (sx = data_x, rx = x; sx < data_x + width; ++sx, ++rx) { |
246 | 0 | int alpha2, alpha; |
247 | |
|
248 | 0 | w_curr += 1; |
249 | 0 | switch (depth) |
250 | 0 | { |
251 | 0 | case 2: |
252 | 0 | alpha = ((row_alpha[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 85; |
253 | 0 | break; |
254 | 0 | case 4: |
255 | 0 | alpha2 = row_alpha[sx >> 1]; |
256 | 0 | alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4) * 17; |
257 | 0 | break; |
258 | 0 | case 8: |
259 | 0 | alpha = row_alpha[sx]; |
260 | 0 | break; |
261 | 0 | default: |
262 | 0 | return_error(gs_error_rangecheck); |
263 | 0 | } |
264 | | |
265 | 0 | if (alpha == 0) { |
266 | | /* With alpha 0 we want to avoid writing out this value. |
267 | | * While it is true that writting it out leaves the color |
268 | | * unchanged, any device that's watching what pixels are |
269 | | * written (such as the pattern tile devices) may have problems. |
270 | | * As in gx_default_copy_alpha the right thing to do is to write |
271 | | * out what we have so far and then continue to collect when we |
272 | | * get back to non zero alpha. */ |
273 | 0 | code = dev_proc(dev, copy_planes)(dev, &(gb_buff[gb_buff_start]), |
274 | 0 | 0, out_raster, gs_no_bitmap_id, |
275 | 0 | x_curr, ry, w_curr-1, 1, 1); |
276 | 0 | if (code < 0) { |
277 | 0 | gs_free_object(mem, gb_buff, "copy_alpha_hl_color"); |
278 | 0 | return code; |
279 | 0 | } |
280 | | /* reset ourselves */ |
281 | 0 | gb_buff_start = gb_buff_start + w_curr * word_width; |
282 | 0 | w_curr = 0; |
283 | 0 | x_curr = rx + 1; |
284 | 0 | } else { |
285 | 0 | if (alpha == 255) { |
286 | | /* Just use the new color. */ |
287 | 0 | composite = &(src_cv[0]); |
288 | 0 | } else { |
289 | | /* We need to do the weighting by the alpha value */ |
290 | 0 | alpha += (alpha>>7); /* Expand from 0..255->0..256 */ |
291 | | /* First get the old color */ |
292 | 0 | for (k = 0; k < ncomps-has_tags; k++) { |
293 | | /* We only have 8 and 16 bit depth to worry about. |
294 | | However, this stuff should really be done with |
295 | | the device encode/decode procedure. */ |
296 | 0 | byte *ptr = ((src_planes[k]) + (sx - data_x) * word_width); |
297 | 0 | curr_cv[k] = 0; |
298 | 0 | switch (word_width) { |
299 | 0 | case 2: |
300 | 0 | curr_cv[k] += (*ptr++ << 8); |
301 | 0 | curr_cv[k] += *ptr; |
302 | 0 | break; |
303 | 0 | case 1: |
304 | 0 | curr_cv[k] += *ptr; |
305 | 0 | curr_cv[k] += curr_cv[k] << 8; |
306 | 0 | } |
307 | | /* Now compute the new color which is a blend of |
308 | | the old and the new */ |
309 | 0 | blend_cv[k] = ((curr_cv[k]<<8) + |
310 | 0 | (((long) src_cv[k] - (long) curr_cv[k]) * alpha))>>8; |
311 | 0 | } |
312 | | /* DO NOT BLEND TAGS. */ |
313 | 0 | if (has_tags) |
314 | 0 | { |
315 | 0 | byte *ptr = ((src_planes[k]) + (sx - data_x) * word_width); |
316 | 0 | curr_cv[k] = 0; |
317 | 0 | switch (word_width) { |
318 | 0 | case 2: |
319 | 0 | curr_cv[k] += (*ptr++ << 8); |
320 | 0 | case 1: |
321 | 0 | curr_cv[k] += *ptr; |
322 | 0 | } |
323 | 0 | blend_cv[k] = curr_cv[k] | src_cv[k]; |
324 | 0 | } |
325 | 0 | composite = &(blend_cv[0]); |
326 | 0 | } |
327 | | /* Update our plane data buffers. Just reuse the current one */ |
328 | 0 | for (k = 0; k < ncomps-has_tags; k++) { |
329 | 0 | byte *ptr = ((src_planes[k]) + (sx - data_x) * word_width); |
330 | 0 | switch (word_width) { |
331 | 0 | case 2: |
332 | 0 | *ptr++ = composite[k] >> 8; |
333 | 0 | case 1: |
334 | 0 | *ptr++ = composite[k] >> shift; |
335 | 0 | } |
336 | 0 | } |
337 | 0 | if (has_tags) |
338 | 0 | { |
339 | 0 | byte *ptr = ((src_planes[k]) + (sx - data_x) * word_width); |
340 | 0 | switch (word_width) { |
341 | 0 | case 2: |
342 | 0 | *ptr++ = composite[k] >> 8; |
343 | 0 | case 1: |
344 | 0 | *ptr++ = composite[k]; |
345 | 0 | } |
346 | 0 | } |
347 | 0 | } /* else on alpha != 0 */ |
348 | 0 | } /* loop on x */ |
349 | | /* Flush what ever we have left. We may only have a partial due to |
350 | | the presence of alpha = 0 values */ |
351 | 0 | code = dev_proc(dev, copy_planes)(dev, &(gb_buff[gb_buff_start]), |
352 | 0 | 0, out_raster, gs_no_bitmap_id, |
353 | 0 | x_curr, ry, w_curr, 1, 1); |
354 | 0 | } /* loop on y */ |
355 | 0 | gs_free_object(mem, gb_buff, "copy_alpha_hl_color"); |
356 | 0 | return code; |
357 | 0 | } |
358 | | |
359 | | int |
360 | | gx_default_copy_alpha(gx_device * dev, const byte * data, int data_x, |
361 | | int raster, gx_bitmap_id id, int x, int y, int width, int height, |
362 | | gx_color_index color, int depth) |
363 | 0 | { /* This might be called with depth = 1.... */ |
364 | 0 | if (depth == 1) |
365 | 0 | return (*dev_proc(dev, copy_mono)) (dev, data, data_x, raster, id, |
366 | 0 | x, y, width, height, |
367 | 0 | gx_no_color_index, color); |
368 | | /* |
369 | | * Simulate alpha by weighted averaging of RGB values. |
370 | | * This is very slow, but functionally correct. |
371 | | */ |
372 | 0 | { |
373 | 0 | const byte *row; |
374 | 0 | gs_memory_t *mem = dev->memory; |
375 | 0 | int bpp = dev->color_info.depth; |
376 | 0 | uchar ncomps = dev->color_info.num_components; |
377 | 0 | uint in_size = gx_device_raster_chunky(dev, false); |
378 | 0 | byte *lin; |
379 | 0 | uint out_size; |
380 | 0 | byte *lout; |
381 | 0 | int code = 0; |
382 | 0 | gx_color_value color_cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
383 | 0 | int ry, lx; |
384 | 0 | gs_int_rect rect; |
385 | |
|
386 | 0 | fit_copy(dev, data, data_x, raster, id, x, y, width, height); |
387 | 0 | row = data; |
388 | 0 | out_size = bitmap_raster(width * bpp); |
389 | 0 | lin = gs_alloc_bytes(mem, in_size, "copy_alpha(lin)"); |
390 | 0 | lout = gs_alloc_bytes(mem, out_size, "copy_alpha(lout)"); |
391 | 0 | if (lin == 0 || lout == 0) { |
392 | 0 | code = gs_note_error(gs_error_VMerror); |
393 | 0 | goto out; |
394 | 0 | } |
395 | 0 | (*dev_proc(dev, decode_color)) (dev, color, color_cv); |
396 | 0 | rect.p.x = 0; |
397 | 0 | rect.q.x = dev->width; |
398 | 0 | for (ry = y; ry < y + height; row += raster, ++ry) { |
399 | 0 | byte *line; |
400 | 0 | int sx, rx; |
401 | |
|
402 | 0 | byte *l_dptr = lout; |
403 | 0 | int l_dbit = 0; |
404 | 0 | byte l_dbyte = ((l_dbit) ? (byte)(*(l_dptr) & (0xff00 >> (l_dbit))) : 0); |
405 | 0 | int l_xprev = x; |
406 | 0 | gs_get_bits_params_t params; |
407 | |
|
408 | 0 | params.options = (GB_ALIGN_STANDARD | |
409 | 0 | (GB_RETURN_COPY | GB_RETURN_POINTER) | |
410 | 0 | GB_OFFSET_0 | |
411 | 0 | GB_RASTER_STANDARD | GB_PACKING_CHUNKY | |
412 | 0 | GB_COLORS_NATIVE | GB_ALPHA_NONE); |
413 | 0 | params.x_offset = 0; |
414 | 0 | params.raster = bitmap_raster(dev->width * (size_t)dev->color_info.depth); |
415 | 0 | params.data[0] = lin; |
416 | 0 | rect.p.y = ry; |
417 | 0 | rect.q.y = ry+1; |
418 | 0 | code = (*dev_proc(dev, get_bits_rectangle))(dev, &rect, |
419 | 0 | ¶ms); |
420 | 0 | if (code < 0) |
421 | 0 | break; |
422 | 0 | line = params.data[0]; |
423 | 0 | lx = x; |
424 | 0 | for (sx = data_x, rx = x; sx < data_x + width; ++sx, ++rx) { |
425 | 0 | gx_color_index previous = gx_no_color_index; |
426 | 0 | gx_color_index composite; |
427 | 0 | int alpha2, alpha; |
428 | |
|
429 | 0 | switch(depth) |
430 | 0 | { |
431 | 0 | case 2: |
432 | | /* map 0 - 3 to 0 - 15 */ |
433 | 0 | alpha = ((row[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 85; |
434 | 0 | break; |
435 | 0 | case 4: |
436 | 0 | alpha2 = row[sx >> 1], |
437 | 0 | alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4) * 17; |
438 | 0 | break; |
439 | 0 | case 8: |
440 | 0 | alpha = row[sx]; |
441 | 0 | break; |
442 | 0 | default: |
443 | 0 | return_error(gs_error_rangecheck); |
444 | 0 | } |
445 | 0 | blend: |
446 | 0 | if (alpha == 0) { |
447 | | /* Previously the code used to just write out the previous |
448 | | * colour when the alpha was 0, but that's wrong. It leaves |
449 | | * the underlying colour unchanged, but has the effect of |
450 | | * making this pixel appear solid in any device that's |
451 | | * watching what pixels are written (such as the pattern |
452 | | * tile devices). The right thing to do is to write out |
453 | | * the buffered accumulator, and skip over any pixels that |
454 | | * are completely clear. */ |
455 | 0 | if (rx > l_xprev ) { |
456 | 0 | sample_store_flush(l_dptr, l_dbit, l_dbyte); |
457 | 0 | code = (*dev_proc(dev, copy_color)) |
458 | 0 | (dev, lout, l_xprev - (lx), out_size, |
459 | 0 | gx_no_bitmap_id, l_xprev, ry, (rx) - l_xprev, 1); |
460 | 0 | if ( code < 0 ) |
461 | 0 | return code; |
462 | 0 | } |
463 | 0 | l_dptr = lout; |
464 | 0 | l_dbit = 0; |
465 | 0 | l_dbyte = (l_dbit ? (byte)(*l_dptr & (0xff00 >> l_dbit)) : 0); |
466 | 0 | l_xprev = rx+1; |
467 | 0 | lx = rx+1; |
468 | 0 | } else { |
469 | 0 | if (alpha == 255) { /* Just write the new color. */ |
470 | 0 | composite = color; |
471 | 0 | } else { |
472 | 0 | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
473 | 0 | uchar i; |
474 | 0 | int alpha2 = alpha + (alpha>>7); |
475 | |
|
476 | 0 | if (previous == gx_no_color_index) { /* Extract the old color. */ |
477 | 0 | if (bpp < 8) { |
478 | 0 | const uint bit = rx * bpp; |
479 | 0 | const byte *src = line + (bit >> 3); |
480 | |
|
481 | 0 | previous = |
482 | 0 | (*src >> (8 - ((bit & 7) + bpp))) & |
483 | 0 | ((1 << bpp) - 1); |
484 | 0 | } else { |
485 | 0 | const byte *src = line + (rx * (bpp >> 3)); |
486 | |
|
487 | 0 | previous = 0; |
488 | 0 | switch (bpp >> 3) { |
489 | 0 | case 8: |
490 | 0 | previous += (gx_color_index) * src++ |
491 | 0 | << SAMPLE_BOUND_SHIFT(previous, 56); |
492 | 0 | case 7: |
493 | 0 | previous += (gx_color_index) * src++ |
494 | 0 | << SAMPLE_BOUND_SHIFT(previous, 48); |
495 | 0 | case 6: |
496 | 0 | previous += (gx_color_index) * src++ |
497 | 0 | << SAMPLE_BOUND_SHIFT(previous, 40); |
498 | 0 | case 5: |
499 | 0 | previous += (gx_color_index) * src++ |
500 | 0 | << SAMPLE_BOUND_SHIFT(previous, 32); |
501 | 0 | case 4: |
502 | 0 | previous += (gx_color_index) * src++ << 24; |
503 | 0 | case 3: |
504 | 0 | previous += (gx_color_index) * src++ << 16; |
505 | 0 | case 2: |
506 | 0 | previous += (gx_color_index) * src++ << 8; |
507 | 0 | case 1: |
508 | 0 | previous += *src++; |
509 | 0 | } |
510 | 0 | } |
511 | 0 | } |
512 | 0 | (*dev_proc(dev, decode_color)) (dev, previous, cv); |
513 | | #if ARCH_INTS_ARE_SHORT |
514 | | # define b_int long |
515 | | #else |
516 | 0 | # define b_int int |
517 | 0 | #endif |
518 | 0 | #define make_shade(old, clr, alpha) \ |
519 | 0 | (((((b_int)(old))<<8) + (((b_int)(clr) - (b_int)(old)) * (alpha)))>>8) |
520 | 0 | for (i=0; i<ncomps; i++) |
521 | 0 | cv[i] = make_shade(cv[i], color_cv[i], alpha2); |
522 | 0 | #undef b_int |
523 | 0 | #undef make_shade |
524 | 0 | composite = |
525 | 0 | (*dev_proc(dev, encode_color)) (dev, cv); |
526 | 0 | if (composite == gx_no_color_index) { /* The device can't represent this color. */ |
527 | | /* Move the alpha value towards 0 or 1. */ |
528 | 0 | if (alpha == 127) /* move 1/2 towards 1 */ |
529 | 0 | ++alpha; |
530 | 0 | alpha = (alpha & 128) | (alpha >> 1); |
531 | 0 | goto blend; |
532 | 0 | } |
533 | 0 | } |
534 | 0 | if (sizeof(composite) > 4) { |
535 | 0 | if (sample_store_next64(composite, &l_dptr, &l_dbit, bpp, &l_dbyte) < 0) |
536 | 0 | return_error(gs_error_rangecheck); |
537 | 0 | } |
538 | 0 | else { |
539 | 0 | if (sample_store_next32(composite, &l_dptr, &l_dbit, bpp, &l_dbyte) < 0) |
540 | 0 | return_error(gs_error_rangecheck); |
541 | 0 | } |
542 | 0 | } |
543 | 0 | } |
544 | 0 | if ( rx > l_xprev ) { |
545 | 0 | sample_store_flush(l_dptr, l_dbit, l_dbyte); |
546 | 0 | code = (*dev_proc(dev, copy_color)) |
547 | 0 | (dev, lout, l_xprev - lx, out_size, |
548 | 0 | gx_no_bitmap_id, l_xprev, ry, rx - l_xprev, 1); |
549 | 0 | if (code < 0) |
550 | 0 | return code; |
551 | 0 | } |
552 | 0 | } |
553 | 0 | out:gs_free_object(mem, lout, "copy_alpha(lout)"); |
554 | 0 | gs_free_object(mem, lin, "copy_alpha(lin)"); |
555 | 0 | return code; |
556 | 0 | } |
557 | 0 | } |
558 | | |
559 | | int |
560 | | gx_default_fill_mask(gx_device * orig_dev, |
561 | | const byte * data, int dx, int raster, gx_bitmap_id id, |
562 | | int x, int y, int w, int h, |
563 | | const gx_drawing_color * pdcolor, int depth, |
564 | | gs_logical_operation_t lop, const gx_clip_path * pcpath) |
565 | 10.0M | { |
566 | 10.0M | gx_device *dev = orig_dev; |
567 | 10.0M | gx_device_clip cdev; |
568 | 10.0M | int code = 0; |
569 | | |
570 | 10.0M | if (w == 0 || h == 0) |
571 | 1.83k | return 0; |
572 | | |
573 | 10.0M | if (pcpath != 0) |
574 | 1.08M | { |
575 | 1.08M | gs_fixed_rect rect; |
576 | 1.08M | int tmp; |
577 | | |
578 | 1.08M | rect.p.x = int2fixed(x); |
579 | 1.08M | rect.p.y = int2fixed(y); |
580 | 1.08M | rect.q.x = int2fixed(x+w); |
581 | 1.08M | rect.q.y = int2fixed(y+h); |
582 | 1.08M | dev = gx_make_clip_device_on_stack_if_needed(&cdev, pcpath, dev, &rect); |
583 | 1.08M | if (dev == NULL) |
584 | 17.5k | return 0; |
585 | | /* Clip region if possible */ |
586 | 1.06M | tmp = fixed2int(rect.p.x); |
587 | 1.06M | if (tmp > x) |
588 | 2.01k | { |
589 | 2.01k | dx += tmp-x; |
590 | 2.01k | x = tmp; |
591 | 2.01k | } |
592 | 1.06M | tmp = fixed2int(rect.q.x); |
593 | 1.06M | if (tmp < x+w) |
594 | 3.57k | w = tmp-x; |
595 | 1.06M | tmp = fixed2int(rect.p.y); |
596 | 1.06M | if (tmp > y) |
597 | 37.0k | { |
598 | 37.0k | data += (tmp-y) * raster; |
599 | 37.0k | y = tmp; |
600 | 37.0k | } |
601 | 1.06M | tmp = fixed2int(rect.q.y); |
602 | 1.06M | if (tmp < y+h) |
603 | 73.7k | h = tmp-y; |
604 | 1.06M | } |
605 | 10.0M | if (depth > 1) { |
606 | | /****** CAN'T DO ROP OR HALFTONE WITH ALPHA ******/ |
607 | 0 | code = (*dev_proc(dev, copy_alpha)) |
608 | 0 | (dev, data, dx, raster, id, x, y, w, h, |
609 | 0 | gx_dc_pure_color(pdcolor), depth); |
610 | 0 | } else |
611 | 10.0M | code = pdcolor->type->fill_masked(pdcolor, data, dx, raster, id, |
612 | 10.0M | x, y, w, h, dev, lop, false); |
613 | 10.0M | if (dev != orig_dev) |
614 | 9.31k | gx_destroy_clip_device_on_stack(&cdev); |
615 | 10.0M | return code; |
616 | 10.0M | } |
617 | | |
618 | | /* Default implementation of strip_tile_rect_devn. With the current design |
619 | | only devices that support devn color will be making use of this |
620 | | procedure and those are planar devices. So we have an implemenation |
621 | | for planar devices and not a default implemenetation at this time. */ |
622 | | int |
623 | | gx_default_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles, |
624 | | int x, int y, int w, int h, const gx_drawing_color * pdcolor0, |
625 | | const gx_drawing_color * pdcolor1, int px, int py) |
626 | 0 | { |
627 | 0 | int width = tiles->size.x; |
628 | 0 | int height = tiles->size.y; |
629 | 0 | int raster = tiles->raster; |
630 | 0 | int rwidth = tiles->rep_width; |
631 | 0 | int rheight = tiles->rep_height; |
632 | 0 | int shift = tiles->shift; |
633 | 0 | int code; |
634 | |
|
635 | 0 | if (rwidth == 0 || rheight == 0) |
636 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
637 | 0 | fit_fill_xy(dev, x, y, w, h); |
638 | 0 | if (w == 0 || h == 0) |
639 | 0 | return 0; |
640 | | |
641 | | /* Loop over as many tiles as we need vertically */ |
642 | 0 | while (1) { |
643 | 0 | int xoff = (shift == 0 ? px : |
644 | 0 | px + (y + py) / rheight * tiles->rep_shift); |
645 | | /* irx = x offset within the tile to start copying from */ |
646 | 0 | int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */ |
647 | 0 | (x + xoff) & (rwidth - 1) : |
648 | 0 | (x + xoff) % rwidth); |
649 | | /* ry = y offset within the tile to start copying from */ |
650 | 0 | int ry = ((rheight & (rheight - 1)) == 0 ? /* power of 2 */ |
651 | 0 | (y + py) & (rheight - 1) : |
652 | 0 | (y + py) % rheight); |
653 | | /* icw = how many bits we can copy before we run out of tile and need to loop */ |
654 | 0 | int icw = width - irx; |
655 | | /* ch = how many rows we can copy before we run out of tile and need to loop */ |
656 | 0 | int ch = height - ry; |
657 | 0 | byte *row0 = tiles->data + ry * raster; |
658 | | |
659 | | /* Loop per line */ |
660 | 0 | do { |
661 | 0 | byte *row = row0; |
662 | 0 | int w2 = w; |
663 | 0 | int left_in_tile = icw; |
664 | 0 | int runlen = 0; |
665 | 0 | int bit = 1<<((7-irx) & 7); |
666 | 0 | int x2 = x; |
667 | 0 | if (left_in_tile > w2) |
668 | 0 | left_in_tile = w2; |
669 | | |
670 | | /* Loop per row */ |
671 | 0 | while (w2) { |
672 | 0 | while (left_in_tile && ((bit & *row) == 0)) { |
673 | 0 | bit >>= 1; |
674 | 0 | if (bit == 0) |
675 | 0 | bit = 128, row++; |
676 | 0 | left_in_tile--; |
677 | 0 | runlen++; |
678 | 0 | } |
679 | 0 | if (runlen) { |
680 | 0 | gs_fixed_rect rect; |
681 | 0 | rect.p.x = int2fixed(x2); |
682 | 0 | rect.p.y = int2fixed(y); |
683 | 0 | rect.q.x = rect.p.x + int2fixed(runlen); |
684 | 0 | rect.q.y = rect.p.y + int2fixed(1); |
685 | | /* Pure colours are only used to signal transparency */ |
686 | 0 | if (pdcolor0->type != gx_dc_type_pure) { |
687 | 0 | code = dev_proc(dev, fill_rectangle_hl_color)(dev, &rect, NULL, pdcolor0, NULL); |
688 | 0 | if (code < 0) |
689 | 0 | return code; |
690 | 0 | } |
691 | 0 | x2 += runlen; |
692 | 0 | w2 -= runlen; |
693 | 0 | runlen = 0; |
694 | 0 | } |
695 | 0 | while (left_in_tile && ((bit & *row) != 0)) { |
696 | 0 | bit >>= 1; |
697 | 0 | if (bit == 0) |
698 | 0 | bit = 128, row++; |
699 | 0 | left_in_tile--; |
700 | 0 | runlen++; |
701 | 0 | } |
702 | 0 | if (runlen) { |
703 | 0 | gs_fixed_rect rect; |
704 | 0 | rect.p.x = int2fixed(x2); |
705 | 0 | rect.p.y = int2fixed(y); |
706 | 0 | rect.q.x = rect.p.x + int2fixed(runlen); |
707 | 0 | rect.q.y = rect.p.y + int2fixed(1); |
708 | | /* Pure colours are only used to signal transparency */ |
709 | 0 | if (pdcolor1->type != gx_dc_type_pure) { |
710 | 0 | code = dev_proc(dev, fill_rectangle_hl_color)(dev, &rect, NULL, pdcolor1, NULL); |
711 | 0 | if (code < 0) |
712 | 0 | return code; |
713 | 0 | } |
714 | 0 | x2 += runlen; |
715 | 0 | w2 -= runlen; |
716 | 0 | runlen = 0; |
717 | 0 | } |
718 | 0 | if (left_in_tile == 0) { |
719 | 0 | left_in_tile = rwidth; |
720 | 0 | if (left_in_tile > w2) |
721 | 0 | left_in_tile = w2; |
722 | 0 | } |
723 | 0 | } |
724 | | |
725 | | /* That's a line complete. */ |
726 | 0 | y++; |
727 | 0 | if (--h == 0) |
728 | 0 | return 0; |
729 | 0 | row0 += raster; |
730 | 0 | } while (--ch != 0); /* Until we finish a tile vertically */ |
731 | 0 | } |
732 | 0 | } |
733 | | |
734 | | /* Default implementation of strip_tile_rectangle */ |
735 | | int |
736 | | gx_default_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles, |
737 | | int x, int y, int w, int h, gx_color_index color0, gx_color_index color1, |
738 | | int px, int py) |
739 | 38.2M | { /* Fill the rectangle in chunks. */ |
740 | 38.2M | int width = tiles->size.x; |
741 | 38.2M | int height = tiles->size.y; |
742 | 38.2M | int raster = tiles->raster; |
743 | 38.2M | int rwidth = tiles->rep_width; |
744 | 38.2M | int rheight = tiles->rep_height; |
745 | 38.2M | int shift = tiles->shift; |
746 | 38.2M | gs_id tile_id = tiles->id; |
747 | | |
748 | 38.2M | if (rwidth == 0 || rheight == 0) |
749 | 1 | return_error(gs_error_unregistered); /* Must not happen. */ |
750 | 38.2M | fit_fill_xy(dev, x, y, w, h); |
751 | | |
752 | | #ifdef DEBUG |
753 | | if (gs_debug_c('t')) { |
754 | | int ptx, pty; |
755 | | const byte *ptp = tiles->data; |
756 | | |
757 | | dmlprintf4(dev->memory, "[t]tile %dx%d raster=%d id=%lu;", |
758 | | tiles->size.x, tiles->size.y, tiles->raster, tiles->id); |
759 | | dmlprintf6(dev->memory, " x,y=%d,%d w,h=%d,%d p=%d,%d\n", |
760 | | x, y, w, h, px, py); |
761 | | dmlputs(dev->memory, ""); |
762 | | for (pty = 0; pty < tiles->size.y; pty++) { |
763 | | dmprintf(dev->memory, " "); |
764 | | for (ptx = 0; ptx < tiles->raster; ptx++) |
765 | | dmprintf1(dev->memory, "%3x", *ptp++); |
766 | | } |
767 | | dmputc(dev->memory, '\n'); |
768 | | } |
769 | | #endif |
770 | | |
771 | 38.2M | { /* |
772 | | * Note: we can't do the following computations until after |
773 | | * the fit_fill_xy. |
774 | | */ |
775 | 38.2M | int xoff = |
776 | 38.2M | (shift == 0 ? px : |
777 | 38.2M | px + (y + py) / rheight * tiles->rep_shift); |
778 | 38.2M | int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */ |
779 | 16.2M | (x + xoff) & (rwidth - 1) : |
780 | 38.2M | (x + xoff) % rwidth); |
781 | 38.2M | int ry = ((rheight & (rheight - 1)) == 0 ? /* power of 2 */ |
782 | 16.2M | (y + py) & (rheight - 1) : |
783 | 38.2M | (y + py) % rheight); |
784 | 38.2M | int icw = width - irx; |
785 | 38.2M | int ch = height - ry; |
786 | 38.2M | byte *row = tiles->data + ry * raster; |
787 | | |
788 | 38.2M | dev_proc_copy_mono((*proc_mono)); |
789 | 38.2M | dev_proc_copy_color((*proc_color)); |
790 | 38.2M | dev_proc_copy_planes((*proc_planes)); |
791 | 38.2M | int code = 0; |
792 | | |
793 | 38.2M | if (color0 == gx_no_color_index && color1 == gx_no_color_index) { |
794 | 6.83M | if (tiles->num_planes > 1) { |
795 | 24.4k | proc_mono = 0; |
796 | 24.4k | proc_color = 0; |
797 | 24.4k | proc_planes = dev_proc(dev, copy_planes); |
798 | 6.80M | } else { |
799 | 6.80M | proc_planes = 0; |
800 | 6.80M | proc_color = dev_proc(dev, copy_color); |
801 | 6.80M | proc_mono = 0; |
802 | 6.80M | } |
803 | 31.4M | } else { |
804 | 31.4M | proc_planes = 0; |
805 | 31.4M | proc_color = 0; |
806 | 31.4M | proc_mono = dev_proc(dev, copy_mono); |
807 | 31.4M | } |
808 | | |
809 | 95.5M | #define GX_DEFAULT_COPY_TILE(dev, srcx, tx, ty, tw, th, tid) do {\ |
810 | 95.5M | if_debug6m('t', (dev)->memory, " copy id=%lu sx=%d => x=%d y=%d w=%d h=%d\n", tid, srcx, tx, ty, tw, th);\ |
811 | 95.5M | if (tiles->num_planes > 1) {\ |
812 | 91.8k | if (proc_planes)\ |
813 | 91.8k | code = (*proc_planes)(dev, row, srcx, raster, tid, tx, ty, tw, th, height);\ |
814 | 95.4M | } else {\ |
815 | 95.4M | if (proc_color != 0) {\ |
816 | 61.6M | code = (*proc_color)(dev, row, srcx, raster, tid, tx, ty, tw, th);\ |
817 | 61.6M | } else {\ |
818 | 33.7M | if (proc_mono)\ |
819 | 94.4M | code = (*proc_mono)(dev, row, srcx, raster, tid, tx, ty, tw, th, color0, color1);\ |
820 | 33.7M | else code = 0;\ |
821 | 33.7M | }\ |
822 | 95.4M | }\ |
823 | 95.5M | if (code < 0) return_error(code);\ |
824 | 95.5M | } while (0); |
825 | | |
826 | | |
827 | 38.2M | if (ch >= h) { /* Shallow operation */ |
828 | 37.3M | if (icw >= w) { /* Just one (partial) tile to transfer. */ |
829 | 30.6M | GX_DEFAULT_COPY_TILE(dev, irx, x, y, w, h, (w == width && h == height ? tile_id : gs_no_bitmap_id)); |
830 | 30.6M | } else { |
831 | 6.68M | int ex = x + w; |
832 | 6.68M | int fex = ex - width; |
833 | 6.68M | int cx = x + icw; |
834 | 6.68M | ulong id = (h == height ? tile_id : gs_no_bitmap_id); |
835 | | |
836 | 6.68M | GX_DEFAULT_COPY_TILE(dev, irx, x, y, icw, h, gs_no_bitmap_id); |
837 | 51.6M | while (cx <= fex) { |
838 | 45.0M | GX_DEFAULT_COPY_TILE(dev, 0, cx, y, width, h, id); |
839 | 45.0M | cx += width; |
840 | 45.0M | } |
841 | 6.68M | if (cx < ex) { |
842 | 5.38M | GX_DEFAULT_COPY_TILE(dev, 0, cx, y, ex - cx, h, gs_no_bitmap_id); |
843 | 5.38M | } |
844 | 6.68M | } |
845 | 37.3M | } else if (icw >= w && shift == 0) { |
846 | | /* Narrow operation, no shift */ |
847 | 735k | int ey = y + h; |
848 | 735k | int fey = ey - height; |
849 | 735k | int cy = y + ch; |
850 | 735k | ulong id = (w == width ? tile_id : gs_no_bitmap_id); |
851 | | |
852 | 735k | GX_DEFAULT_COPY_TILE(dev, irx, x, y, w, ch, (ch == height ? id : gs_no_bitmap_id)); |
853 | 735k | row = tiles->data; |
854 | 1.05M | do { |
855 | 1.05M | ch = (cy > fey ? ey - cy : height); |
856 | 1.05M | GX_DEFAULT_COPY_TILE(dev, irx, x, cy, w, ch, |
857 | 1.05M | (ch == height ? id : gs_no_bitmap_id)); |
858 | 1.05M | } |
859 | 1.05M | while ((cy += ch) < ey); |
860 | 735k | } else { |
861 | | /* Full operation. If shift != 0, some scan lines */ |
862 | | /* may be narrow. We could test shift == 0 in advance */ |
863 | | /* and use a slightly faster loop, but right now */ |
864 | | /* we don't bother. */ |
865 | 153k | int ex = x + w, ey = y + h; |
866 | 153k | int fex = ex - width, fey = ey - height; |
867 | 153k | int cx, cy; |
868 | | |
869 | 504k | for (cy = y;;) { |
870 | 504k | ulong id = (ch == height ? tile_id : gs_no_bitmap_id); |
871 | | |
872 | 504k | if (icw >= w) { |
873 | 0 | GX_DEFAULT_COPY_TILE(dev, irx, x, cy, w, ch, |
874 | 0 | (w == width ? id : gs_no_bitmap_id)); |
875 | 504k | } else { |
876 | 504k | GX_DEFAULT_COPY_TILE(dev, irx, x, cy, icw, ch, gs_no_bitmap_id); |
877 | 504k | cx = x + icw; |
878 | 5.57M | while (cx <= fex) { |
879 | 5.06M | GX_DEFAULT_COPY_TILE(dev, 0, cx, cy, width, ch, id); |
880 | 5.06M | cx += width; |
881 | 5.06M | } |
882 | 504k | if (cx < ex) { |
883 | 413k | GX_DEFAULT_COPY_TILE(dev, 0, cx, cy, ex - cx, ch, gs_no_bitmap_id); |
884 | 413k | } |
885 | 504k | } |
886 | 504k | if ((cy += ch) >= ey) |
887 | 153k | break; |
888 | 351k | ch = (cy > fey ? ey - cy : height); |
889 | 351k | if ((irx += shift) >= rwidth) |
890 | 0 | irx -= rwidth; |
891 | 351k | icw = width - irx; |
892 | 351k | row = tiles->data; |
893 | 351k | } |
894 | 153k | } |
895 | 38.2M | #undef GX_DEFAULT_COPY_TILE |
896 | 38.2M | } |
897 | 38.2M | return 0; |
898 | 38.2M | } |
899 | | |
900 | | int |
901 | | gx_no_strip_copy_rop2(gx_device * dev, |
902 | | const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id, |
903 | | const gx_color_index * scolors, |
904 | | const gx_strip_bitmap * textures, const gx_color_index * tcolors, |
905 | | int x, int y, int width, int height, |
906 | | int phase_x, int phase_y, gs_logical_operation_t lop, |
907 | | uint planar_height) |
908 | 0 | { |
909 | 0 | return_error(gs_error_unknownerror); /* not implemented */ |
910 | 0 | } |
911 | | |
912 | | /* ---------------- Unaligned copy operations ---------------- */ |
913 | | |
914 | | /* |
915 | | * Implementing unaligned operations in terms of the standard aligned |
916 | | * operations requires adjusting the bitmap origin and/or the raster to be |
917 | | * aligned. Adjusting the origin is simple; adjusting the raster requires |
918 | | * doing the operation one scan line at a time. |
919 | | */ |
920 | | int |
921 | | gx_copy_mono_unaligned(gx_device * dev, const byte * data, |
922 | | int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h, |
923 | | gx_color_index zero, gx_color_index one) |
924 | 0 | { |
925 | 0 | dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono); |
926 | 0 | uint offset = ALIGNMENT_MOD(data, align_bitmap_mod); |
927 | 0 | int step = raster & (align_bitmap_mod - 1); |
928 | | |
929 | | /* Adjust the origin. */ |
930 | 0 | data -= offset; |
931 | 0 | dx += offset << 3; |
932 | | |
933 | | /* Adjust the raster. */ |
934 | 0 | if (!step) { /* No adjustment needed. */ |
935 | 0 | return (*copy_mono) (dev, data, dx, raster, id, |
936 | 0 | x, y, w, h, zero, one); |
937 | 0 | } |
938 | | /* Do the transfer one scan line at a time. */ |
939 | 0 | { |
940 | 0 | const byte *p = data; |
941 | 0 | int d = dx; |
942 | 0 | int code = 0; |
943 | 0 | int i; |
944 | |
|
945 | 0 | for (i = 0; i < h && code >= 0; |
946 | 0 | ++i, p += raster - step, d += step << 3 |
947 | 0 | ) |
948 | 0 | code = (*copy_mono) (dev, p, d, raster, gx_no_bitmap_id, |
949 | 0 | x, y + i, w, 1, zero, one); |
950 | 0 | return code; |
951 | 0 | } |
952 | 0 | } |
953 | | |
954 | | int |
955 | | gx_copy_color_unaligned(gx_device * dev, const byte * data, |
956 | | int data_x, int raster, gx_bitmap_id id, |
957 | | int x, int y, int width, int height) |
958 | 0 | { |
959 | 0 | dev_proc_copy_color((*copy_color)) = dev_proc(dev, copy_color); |
960 | 0 | int depth = dev->color_info.depth; |
961 | 0 | uint offset = (uint) (data - (const byte *)0) & (align_bitmap_mod - 1); |
962 | 0 | int step = raster & (align_bitmap_mod - 1); |
963 | | |
964 | | /* |
965 | | * Adjust the origin. |
966 | | * We have to do something very special for 24-bit data, |
967 | | * because that is the only depth that doesn't divide |
968 | | * align_bitmap_mod exactly. In particular, we need to find |
969 | | * M*B + R == 0 mod 3, where M is align_bitmap_mod, R is the |
970 | | * offset value just calculated, and B is an integer unknown; |
971 | | * the new value of offset will be M*B + R. |
972 | | */ |
973 | 0 | if (depth == 24) |
974 | 0 | offset += (offset % 3) * |
975 | 0 | (align_bitmap_mod * (3 - (align_bitmap_mod % 3))); |
976 | 0 | data -= offset; |
977 | 0 | data_x += (offset << 3) / depth; |
978 | | |
979 | | /* Adjust the raster. */ |
980 | 0 | if (!step) { /* No adjustment needed. */ |
981 | 0 | return (*copy_color) (dev, data, data_x, raster, id, |
982 | 0 | x, y, width, height); |
983 | 0 | } |
984 | | /* Do the transfer one scan line at a time. */ |
985 | 0 | { |
986 | 0 | const byte *p = data; |
987 | 0 | int d = data_x; |
988 | 0 | int dstep = (step << 3) / depth; |
989 | 0 | int code = 0; |
990 | 0 | int i; |
991 | |
|
992 | 0 | for (i = 0; i < height && code >= 0; |
993 | 0 | ++i, p += raster - step, d += dstep |
994 | 0 | ) |
995 | 0 | code = (*copy_color) (dev, p, d, raster, gx_no_bitmap_id, |
996 | 0 | x, y + i, width, 1); |
997 | 0 | return code; |
998 | 0 | } |
999 | 0 | } |
1000 | | |
1001 | | int |
1002 | | gx_copy_alpha_unaligned(gx_device * dev, const byte * data, int data_x, |
1003 | | int raster, gx_bitmap_id id, int x, int y, int width, int height, |
1004 | | gx_color_index color, int depth) |
1005 | 0 | { |
1006 | 0 | dev_proc_copy_alpha((*copy_alpha)) = dev_proc(dev, copy_alpha); |
1007 | 0 | uint offset = (uint) (data - (const byte *)0) & (align_bitmap_mod - 1); |
1008 | 0 | int step = raster & (align_bitmap_mod - 1); |
1009 | | |
1010 | | /* Adjust the origin. */ |
1011 | 0 | data -= offset; |
1012 | 0 | data_x += (offset << 3) / depth; |
1013 | | |
1014 | | /* Adjust the raster. */ |
1015 | 0 | if (!step) { /* No adjustment needed. */ |
1016 | 0 | return (*copy_alpha) (dev, data, data_x, raster, id, |
1017 | 0 | x, y, width, height, color, depth); |
1018 | 0 | } |
1019 | | /* Do the transfer one scan line at a time. */ |
1020 | 0 | { |
1021 | 0 | const byte *p = data; |
1022 | 0 | int d = data_x; |
1023 | 0 | int dstep = (step << 3) / depth; |
1024 | 0 | int code = 0; |
1025 | 0 | int i; |
1026 | |
|
1027 | 0 | for (i = 0; i < height && code >= 0; |
1028 | 0 | ++i, p += raster - step, d += dstep |
1029 | 0 | ) |
1030 | 0 | code = (*copy_alpha) (dev, p, d, raster, gx_no_bitmap_id, |
1031 | 0 | x, y + i, width, 1, color, depth); |
1032 | 0 | return code; |
1033 | 0 | } |
1034 | 0 | } |