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