1 /* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /*$Id: gdevdbit.c,v 1.11 2004/08/05 17:02:36 stefan Exp $ */
18 /* Default device bitmap copying implementation */
19 #include "gx.h"
20 #include "gpcheck.h"
21 #include "gserrors.h"
22 #include "gsbittab.h"
23 #include "gsrect.h"
24 #include "gsropt.h"
25 #include "gxdcolor.h"
26 #include "gxdevice.h"
27 #include "gxdevmem.h"
28 #include "gdevmem.h"
29 #undef mdev
30 #include "gxcpath.h"
31
32 /* By default, implement tile_rectangle using strip_tile_rectangle. */
33 int
gx_default_tile_rectangle(gx_device * dev,const gx_tile_bitmap * tile,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int px,int py)34 gx_default_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
35 int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
36 int px, int py)
37 {
38 gx_strip_bitmap tiles;
39
40 *(gx_tile_bitmap *) & tiles = *tile;
41 tiles.shift = tiles.rep_shift = 0;
42 return (*dev_proc(dev, strip_tile_rectangle))
43 (dev, &tiles, x, y, w, h, color0, color1, px, py);
44 }
45
46 /* Implement copy_mono by filling lots of small rectangles. */
47 /* This is very inefficient, but it works as a default. */
48 int
gx_default_copy_mono(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)49 gx_default_copy_mono(gx_device * dev, const byte * data,
50 int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h,
51 gx_color_index zero, gx_color_index one)
52 {
53 bool invert;
54 gx_color_index color;
55 gx_device_color devc;
56
57 fit_copy(dev, data, dx, raster, id, x, y, w, h);
58 if (one != gx_no_color_index) {
59 invert = false;
60 color = one;
61 if (zero != gx_no_color_index) {
62 int code = (*dev_proc(dev, fill_rectangle))
63 (dev, x, y, w, h, zero);
64
65 if (code < 0)
66 return code;
67 }
68 } else {
69 invert = true;
70 color = zero;
71 }
72 set_nonclient_dev_color(&devc, color);
73 return gx_dc_default_fill_masked
74 (&devc, data, dx, raster, id, x, y, w, h, dev, rop3_T, invert);
75 }
76
77 /* Implement copy_color by filling lots of small rectangles. */
78 /* This is very inefficient, but it works as a default. */
79 int
gx_default_copy_color(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h)80 gx_default_copy_color(gx_device * dev, const byte * data,
81 int dx, int raster, gx_bitmap_id id,
82 int x, int y, int w, int h)
83 {
84 int depth = dev->color_info.depth;
85 byte mask;
86
87 dev_proc_fill_rectangle((*fill));
88 const byte *row;
89 int iy;
90
91 if (depth == 1)
92 return (*dev_proc(dev, copy_mono)) (dev, data, dx, raster, id,
93 x, y, w, h,
94 (gx_color_index) 0, (gx_color_index) 1);
95 fit_copy(dev, data, dx, raster, id, x, y, w, h);
96 fill = dev_proc(dev, fill_rectangle);
97 mask = (byte) ((1 << depth) - 1);
98 for (row = data, iy = 0; iy < h; row += raster, ++iy) {
99 int ix;
100 gx_color_index c0 = gx_no_color_index;
101 const byte *ptr = row + ((dx * depth) >> 3);
102 int i0;
103
104 for (i0 = ix = 0; ix < w; ++ix) {
105 gx_color_index color;
106
107 if (depth >= 8) {
108 color = *ptr++;
109 switch (depth) {
110 case 64:
111 color = (color << 8) + *ptr++;
112 case 56:
113 color = (color << 8) + *ptr++;
114 case 48:
115 color = (color << 8) + *ptr++;
116 case 40:
117 color = (color << 8) + *ptr++;
118 case 32:
119 color = (color << 8) + *ptr++;
120 case 24:
121 color = (color << 8) + *ptr++;
122 case 16:
123 color = (color << 8) + *ptr++;
124 }
125 } else {
126 uint dbit = (-(ix + dx + 1) * depth) & 7;
127
128 color = (*ptr >> dbit) & mask;
129 if (dbit == 0)
130 ptr++;
131 }
132 if (color != c0) {
133 if (ix > i0) {
134 int code = (*fill)
135 (dev, i0 + x, iy + y, ix - i0, 1, c0);
136
137 if (code < 0)
138 return code;
139 }
140 c0 = color;
141 i0 = ix;
142 }
143 }
144 if (ix > i0) {
145 int code = (*fill) (dev, i0 + x, iy + y, ix - i0, 1, c0);
146
147 if (code < 0)
148 return code;
149 }
150 }
151 return 0;
152 }
153
154 int
gx_no_copy_alpha(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color,int depth)155 gx_no_copy_alpha(gx_device * dev, const byte * data, int data_x,
156 int raster, gx_bitmap_id id, int x, int y, int width, int height,
157 gx_color_index color, int depth)
158 {
159 return_error(gs_error_unknownerror);
160 }
161
162 int
gx_default_copy_alpha(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color,int depth)163 gx_default_copy_alpha(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 gx_color_index color, int depth)
166 { /* This might be called with depth = 1.... */
167 if (depth == 1)
168 return (*dev_proc(dev, copy_mono)) (dev, data, data_x, raster, id,
169 x, y, width, height,
170 gx_no_color_index, color);
171 /*
172 * Simulate alpha by weighted averaging of RGB values.
173 * This is very slow, but functionally correct.
174 */
175 {
176 const byte *row;
177 gs_memory_t *mem = dev->memory;
178 int bpp = dev->color_info.depth;
179 int ncomps = dev->color_info.num_components;
180 uint in_size = gx_device_raster(dev, false);
181 byte *lin;
182 uint out_size;
183 byte *lout;
184 int code = 0;
185 gx_color_value color_cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
186 int ry;
187
188 fit_copy(dev, data, data_x, raster, id, x, y, width, height);
189 row = data;
190 out_size = bitmap_raster(width * bpp);
191 lin = gs_alloc_bytes(mem, in_size, "copy_alpha(lin)");
192 lout = gs_alloc_bytes(mem, out_size, "copy_alpha(lout)");
193 if (lin == 0 || lout == 0) {
194 code = gs_note_error(gs_error_VMerror);
195 goto out;
196 }
197 (*dev_proc(dev, decode_color)) (dev, color, color_cv);
198 for (ry = y; ry < y + height; row += raster, ++ry) {
199 byte *line;
200 int sx, rx;
201
202 DECLARE_LINE_ACCUM_COPY(lout, bpp, x);
203
204 code = (*dev_proc(dev, get_bits)) (dev, ry, lin, &line);
205 if (code < 0)
206 break;
207 for (sx = data_x, rx = x; sx < data_x + width; ++sx, ++rx) {
208 gx_color_index previous = gx_no_color_index;
209 gx_color_index composite;
210 int alpha2, alpha;
211
212 if (depth == 2) /* map 0 - 3 to 0 - 15 */
213 alpha = ((row[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 5;
214 else
215 alpha2 = row[sx >> 1],
216 alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4);
217 blend:if (alpha == 15) { /* Just write the new color. */
218 composite = color;
219 } else {
220 if (previous == gx_no_color_index) { /* Extract the old color. */
221 if (bpp < 8) {
222 const uint bit = rx * bpp;
223 const byte *src = line + (bit >> 3);
224
225 previous =
226 (*src >> (8 - ((bit & 7) + bpp))) &
227 ((1 << bpp) - 1);
228 } else {
229 const byte *src = line + (rx * (bpp >> 3));
230
231 previous = 0;
232 switch (bpp >> 3) {
233 case 8:
234 previous += (gx_color_index) * src++
235 << sample_bound_shift(previous, 56);
236 case 7:
237 previous += (gx_color_index) * src++
238 << sample_bound_shift(previous, 48);
239 case 6:
240 previous += (gx_color_index) * src++
241 << sample_bound_shift(previous, 40);
242 case 5:
243 previous += (gx_color_index) * src++
244 << sample_bound_shift(previous, 32);
245 case 4:
246 previous += (gx_color_index) * src++ << 24;
247 case 3:
248 previous += (gx_color_index) * src++ << 16;
249 case 2:
250 previous += (gx_color_index) * src++ << 8;
251 case 1:
252 previous += *src++;
253 }
254 }
255 }
256 if (alpha == 0) { /* Just write the old color. */
257 composite = previous;
258 } else { /* Blend values. */
259 gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
260 int i;
261
262 (*dev_proc(dev, decode_color)) (dev, previous, cv);
263 #if arch_ints_are_short
264 # define b_int long
265 #else
266 # define b_int int
267 #endif
268 #define make_shade(old, clr, alpha, amax) \
269 (old) + (((b_int)(clr) - (b_int)(old)) * (alpha) / (amax))
270 for (i=0; i<ncomps; i++)
271 cv[i] = make_shade(cv[i], color_cv[i], alpha, 15);
272 #undef b_int
273 #undef make_shade
274 composite =
275 (*dev_proc(dev, encode_color)) (dev, cv);
276 if (composite == gx_no_color_index) { /* The device can't represent this color. */
277 /* Move the alpha value towards 0 or 1. */
278 if (alpha == 7) /* move 1/2 towards 1 */
279 ++alpha;
280 alpha = (alpha & 8) | (alpha >> 1);
281 goto blend;
282 }
283 }
284 }
285 LINE_ACCUM(composite, bpp);
286 }
287 LINE_ACCUM_COPY(dev, lout, bpp, x, rx, raster, ry);
288 }
289 out:gs_free_object(mem, lout, "copy_alpha(lout)");
290 gs_free_object(mem, lin, "copy_alpha(lin)");
291 return code;
292 }
293 }
294
295 int
gx_no_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_tile_bitmap * texture,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)296 gx_no_copy_rop(gx_device * dev,
297 const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
298 const gx_color_index * scolors,
299 const gx_tile_bitmap * texture, const gx_color_index * tcolors,
300 int x, int y, int width, int height,
301 int phase_x, int phase_y, gs_logical_operation_t lop)
302 {
303 return_error(gs_error_unknownerror); /* not implemented */
304 }
305
306 int
gx_default_fill_mask(gx_device * orig_dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,const gx_drawing_color * pdcolor,int depth,gs_logical_operation_t lop,const gx_clip_path * pcpath)307 gx_default_fill_mask(gx_device * orig_dev,
308 const byte * data, int dx, int raster, gx_bitmap_id id,
309 int x, int y, int w, int h,
310 const gx_drawing_color * pdcolor, int depth,
311 gs_logical_operation_t lop, const gx_clip_path * pcpath)
312 {
313 gx_device *dev;
314 gx_device_clip cdev;
315
316 if (pcpath != 0) {
317 gx_make_clip_path_device(&cdev, pcpath);
318 cdev.target = orig_dev;
319 dev = (gx_device *) & cdev;
320 (*dev_proc(dev, open_device)) (dev);
321 } else
322 dev = orig_dev;
323 if (depth > 1) {
324 /****** CAN'T DO ROP OR HALFTONE WITH ALPHA ******/
325 return (*dev_proc(dev, copy_alpha))
326 (dev, data, dx, raster, id, x, y, w, h,
327 gx_dc_pure_color(pdcolor), depth);
328 } else
329 return pdcolor->type->fill_masked(pdcolor, data, dx, raster, id,
330 x, y, w, h, dev, lop, false);
331 }
332
333 /* Default implementation of strip_tile_rectangle */
334 int
gx_default_strip_tile_rectangle(gx_device * dev,const gx_strip_bitmap * tiles,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int px,int py)335 gx_default_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
336 int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
337 int px, int py)
338 { /* Fill the rectangle in chunks. */
339 int width = tiles->size.x;
340 int height = tiles->size.y;
341 int raster = tiles->raster;
342 int rwidth = tiles->rep_width;
343 int rheight = tiles->rep_height;
344 int shift = tiles->shift;
345 gs_id tile_id = tiles->id;
346
347 fit_fill_xy(dev, x, y, w, h);
348
349 #ifdef DEBUG
350 if (gs_debug_c('t')) {
351 int ptx, pty;
352 const byte *ptp = tiles->data;
353
354 dlprintf4("[t]tile %dx%d raster=%d id=%lu;",
355 tiles->size.x, tiles->size.y, tiles->raster, tiles->id);
356 dlprintf6(" x,y=%d,%d w,h=%d,%d p=%d,%d\n",
357 x, y, w, h, px, py);
358 dlputs("");
359 for (pty = 0; pty < tiles->size.y; pty++) {
360 dprintf(" ");
361 for (ptx = 0; ptx < tiles->raster; ptx++)
362 dprintf1("%3x", *ptp++);
363 }
364 dputc('\n');
365 }
366 #endif
367
368 if (dev_proc(dev, tile_rectangle) != gx_default_tile_rectangle) {
369 if (shift == 0) { /*
370 * Temporarily patch the tile_rectangle procedure in the
371 * device so we don't get into a recursion loop if the
372 * device has a tile_rectangle procedure that conditionally
373 * calls the strip_tile_rectangle procedure.
374 */
375 dev_proc_tile_rectangle((*tile_proc)) =
376 dev_proc(dev, tile_rectangle);
377 int code;
378
379 set_dev_proc(dev, tile_rectangle, gx_default_tile_rectangle);
380 code = (*tile_proc)
381 (dev, (const gx_tile_bitmap *)tiles, x, y, w, h,
382 color0, color1, px, py);
383 set_dev_proc(dev, tile_rectangle, tile_proc);
384 return code;
385 }
386 /* We should probably optimize this case too, for the benefit */
387 /* of window systems, but we don't yet. */
388 } { /*
389 * Note: we can't do the following computations until after
390 * the fit_fill_xy.
391 */
392 int xoff =
393 (shift == 0 ? px :
394 px + (y + py) / rheight * tiles->rep_shift);
395 int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */
396 (x + xoff) & (rwidth - 1) :
397 (x + xoff) % rwidth);
398 int ry = ((rheight & (rheight - 1)) == 0 ? /* power of 2 */
399 (y + py) & (rheight - 1) :
400 (y + py) % rheight);
401 int icw = width - irx;
402 int ch = height - ry;
403 byte *row = tiles->data + ry * raster;
404
405 dev_proc_copy_mono((*proc_mono));
406 dev_proc_copy_color((*proc_color));
407 int code;
408
409 if (color0 == gx_no_color_index && color1 == gx_no_color_index)
410 proc_color = dev_proc(dev, copy_color), proc_mono = 0;
411 else
412 proc_color = 0, proc_mono = dev_proc(dev, copy_mono);
413
414 #define real_copy_tile(srcx, tx, ty, tw, th, id)\
415 code =\
416 (proc_color != 0 ?\
417 (*proc_color)(dev, row, srcx, raster, id, tx, ty, tw, th) :\
418 (*proc_mono)(dev, row, srcx, raster, id, tx, ty, tw, th, color0, color1));\
419 if (code < 0) return_error(code);\
420 return_if_interrupt(dev->memory)
421 #ifdef DEBUG
422 #define copy_tile(srcx, tx, ty, tw, th, tid)\
423 if_debug6('t', " copy id=%lu sx=%d => x=%d y=%d w=%d h=%d\n",\
424 tid, srcx, tx, ty, tw, th);\
425 real_copy_tile(srcx, tx, ty, tw, th, tid)
426 #else
427 #define copy_tile(srcx, tx, ty, tw, th, id)\
428 real_copy_tile(srcx, tx, ty, tw, th, id)
429 #endif
430 if (ch >= h) { /* Shallow operation */
431 if (icw >= w) { /* Just one (partial) tile to transfer. */
432 copy_tile(irx, x, y, w, h,
433 (w == width && h == height ? tile_id :
434 gs_no_bitmap_id));
435 } else {
436 int ex = x + w;
437 int fex = ex - width;
438 int cx = x + icw;
439 ulong id = (h == height ? tile_id : gs_no_bitmap_id);
440
441 copy_tile(irx, x, y, icw, h, gs_no_bitmap_id);
442 while (cx <= fex) {
443 copy_tile(0, cx, y, width, h, id);
444 cx += width;
445 }
446 if (cx < ex) {
447 copy_tile(0, cx, y, ex - cx, h, gs_no_bitmap_id);
448 }
449 }
450 } else if (icw >= w && shift == 0) {
451 /* Narrow operation, no shift */
452 int ey = y + h;
453 int fey = ey - height;
454 int cy = y + ch;
455 ulong id = (w == width ? tile_id : gs_no_bitmap_id);
456
457 copy_tile(irx, x, y, w, ch, (ch == height ? id : gs_no_bitmap_id));
458 row = tiles->data;
459 do {
460 ch = (cy > fey ? ey - cy : height);
461 copy_tile(irx, x, cy, w, ch,
462 (ch == height ? id : gs_no_bitmap_id));
463 }
464 while ((cy += ch) < ey);
465 } else {
466 /* Full operation. If shift != 0, some scan lines */
467 /* may be narrow. We could test shift == 0 in advance */
468 /* and use a slightly faster loop, but right now */
469 /* we don't bother. */
470 int ex = x + w, ey = y + h;
471 int fex = ex - width, fey = ey - height;
472 int cx, cy;
473
474 for (cy = y;;) {
475 ulong id = (ch == height ? tile_id : gs_no_bitmap_id);
476
477 if (icw >= w) {
478 copy_tile(irx, x, cy, w, ch,
479 (w == width ? id : gs_no_bitmap_id));
480 } else {
481 copy_tile(irx, x, cy, icw, ch, gs_no_bitmap_id);
482 cx = x + icw;
483 while (cx <= fex) {
484 copy_tile(0, cx, cy, width, ch, id);
485 cx += width;
486 }
487 if (cx < ex) {
488 copy_tile(0, cx, cy, ex - cx, ch, gs_no_bitmap_id);
489 }
490 }
491 if ((cy += ch) >= ey)
492 break;
493 ch = (cy > fey ? ey - cy : height);
494 if ((irx += shift) >= rwidth)
495 irx -= rwidth;
496 icw = width - irx;
497 row = tiles->data;
498 }
499 }
500 #undef copy_tile
501 #undef real_copy_tile
502 }
503 return 0;
504 }
505
506 int
gx_no_strip_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)507 gx_no_strip_copy_rop(gx_device * dev,
508 const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
509 const gx_color_index * scolors,
510 const gx_strip_bitmap * textures, const gx_color_index * tcolors,
511 int x, int y, int width, int height,
512 int phase_x, int phase_y, gs_logical_operation_t lop)
513 {
514 return_error(gs_error_unknownerror); /* not implemented */
515 }
516
517 /* ---------------- Unaligned copy operations ---------------- */
518
519 /*
520 * Implementing unaligned operations in terms of the standard aligned
521 * operations requires adjusting the bitmap origin and/or the raster to be
522 * aligned. Adjusting the origin is simple; adjusting the raster requires
523 * doing the operation one scan line at a time.
524 */
525 int
gx_copy_mono_unaligned(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)526 gx_copy_mono_unaligned(gx_device * dev, const byte * data,
527 int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h,
528 gx_color_index zero, gx_color_index one)
529 {
530 dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono);
531 uint offset = ALIGNMENT_MOD(data, align_bitmap_mod);
532 int step = raster & (align_bitmap_mod - 1);
533
534 /* Adjust the origin. */
535 data -= offset;
536 dx += offset << 3;
537
538 /* Adjust the raster. */
539 if (!step) { /* No adjustment needed. */
540 return (*copy_mono) (dev, data, dx, raster, id,
541 x, y, w, h, zero, one);
542 }
543 /* Do the transfer one scan line at a time. */
544 {
545 const byte *p = data;
546 int d = dx;
547 int code = 0;
548 int i;
549
550 for (i = 0; i < h && code >= 0;
551 ++i, p += raster - step, d += step << 3
552 )
553 code = (*copy_mono) (dev, p, d, raster, gx_no_bitmap_id,
554 x, y + i, w, 1, zero, one);
555 return code;
556 }
557 }
558
559 int
gx_copy_color_unaligned(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height)560 gx_copy_color_unaligned(gx_device * dev, const byte * data,
561 int data_x, int raster, gx_bitmap_id id,
562 int x, int y, int width, int height)
563 {
564 dev_proc_copy_color((*copy_color)) = dev_proc(dev, copy_color);
565 int depth = dev->color_info.depth;
566 uint offset = (uint) (data - (const byte *)0) & (align_bitmap_mod - 1);
567 int step = raster & (align_bitmap_mod - 1);
568
569 /*
570 * Adjust the origin.
571 * We have to do something very special for 24-bit data,
572 * because that is the only depth that doesn't divide
573 * align_bitmap_mod exactly. In particular, we need to find
574 * M*B + R == 0 mod 3, where M is align_bitmap_mod, R is the
575 * offset value just calculated, and B is an integer unknown;
576 * the new value of offset will be M*B + R.
577 */
578 if (depth == 24)
579 offset += (offset % 3) *
580 (align_bitmap_mod * (3 - (align_bitmap_mod % 3)));
581 data -= offset;
582 data_x += (offset << 3) / depth;
583
584 /* Adjust the raster. */
585 if (!step) { /* No adjustment needed. */
586 return (*copy_color) (dev, data, data_x, raster, id,
587 x, y, width, height);
588 }
589 /* Do the transfer one scan line at a time. */
590 {
591 const byte *p = data;
592 int d = data_x;
593 int dstep = (step << 3) / depth;
594 int code = 0;
595 int i;
596
597 for (i = 0; i < height && code >= 0;
598 ++i, p += raster - step, d += dstep
599 )
600 code = (*copy_color) (dev, p, d, raster, gx_no_bitmap_id,
601 x, y + i, width, 1);
602 return code;
603 }
604 }
605
606 int
gx_copy_alpha_unaligned(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color,int depth)607 gx_copy_alpha_unaligned(gx_device * dev, const byte * data, int data_x,
608 int raster, gx_bitmap_id id, int x, int y, int width, int height,
609 gx_color_index color, int depth)
610 {
611 dev_proc_copy_alpha((*copy_alpha)) = dev_proc(dev, copy_alpha);
612 uint offset = (uint) (data - (const byte *)0) & (align_bitmap_mod - 1);
613 int step = raster & (align_bitmap_mod - 1);
614
615 /* Adjust the origin. */
616 data -= offset;
617 data_x += (offset << 3) / depth;
618
619 /* Adjust the raster. */
620 if (!step) { /* No adjustment needed. */
621 return (*copy_alpha) (dev, data, data_x, raster, id,
622 x, y, width, height, color, depth);
623 }
624 /* Do the transfer one scan line at a time. */
625 {
626 const byte *p = data;
627 int d = data_x;
628 int dstep = (step << 3) / depth;
629 int code = 0;
630 int i;
631
632 for (i = 0; i < height && code >= 0;
633 ++i, p += raster - step, d += dstep
634 )
635 code = (*copy_alpha) (dev, p, d, raster, gx_no_bitmap_id,
636 x, y + i, width, 1, color, depth);
637 return code;
638 }
639 }
640