1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Blitting functions.
12 *
13 * By Shawn Hargreaves.
14 *
15 * Dithering code by James Hyman.
16 *
17 * Transparency preserving code by Elias Pschernig.
18 *
19 * See readme.txt for copyright information.
20 */
21
22
23 #include <string.h>
24 #include "allegro.h"
25 #include "allegro/internal/aintern.h"
26
27
28
29 /* get_replacement_mask_color:
30 * Helper function to get a replacement color for the bitmap's mask color.
31 */
get_replacement_mask_color(BITMAP * bmp)32 static int get_replacement_mask_color(BITMAP *bmp)
33 {
34 int depth, c, g = 0;
35
36 depth = bitmap_color_depth(bmp);
37
38 if (depth == 8) {
39 if (rgb_map)
40 return rgb_map->data[31][1][31];
41 else
42 return bestfit_color(_current_palette, 63, 1, 63);
43 }
44 else {
45 do
46 c = makecol_depth(depth, 255, ++g, 255);
47 while (c == bitmap_mask_color(bmp));
48
49 return c;
50 }
51 }
52
53
54
55 /* blit_from_256:
56 * Expands 256 color images onto a truecolor destination.
57 */
blit_from_256(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)58 static void blit_from_256(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
59 {
60 #ifdef ALLEGRO_COLOR8
61
62 int *dest_palette_color;
63 uintptr_t s, d;
64 unsigned char *ss;
65 int x, y, c, rc;
66
67 /* lookup table avoids repeated color format conversions */
68 if (_color_conv & COLORCONV_KEEP_TRANS) {
69 dest_palette_color = _AL_MALLOC_ATOMIC(256*sizeof(int));
70 memcpy(dest_palette_color, _palette_expansion_table(bitmap_color_depth(dest)), 256*sizeof(int));
71
72 rc = get_replacement_mask_color(dest);
73
74 dest_palette_color[MASK_COLOR_8] = bitmap_mask_color(dest);
75
76 for (c=0; c<256; c++) {
77 if ((c != MASK_COLOR_8) &&
78 (dest_palette_color[c] == bitmap_mask_color(dest)))
79 dest_palette_color[c] = rc;
80 }
81 }
82 else
83 dest_palette_color = _palette_expansion_table(bitmap_color_depth(dest));
84
85 /* worker macro */
86 #define EXPAND_BLIT(bits, dsize) \
87 { \
88 if (is_memory_bitmap(src)) { \
89 /* fast version when reading from memory bitmap */ \
90 bmp_select(dest); \
91 \
92 for (y=0; y<h; y++) { \
93 ss = src->line[s_y+y] + s_x; \
94 d = bmp_write_line(dest, d_y+y) + d_x*dsize; \
95 \
96 for (x=0; x<w; x++) { \
97 bmp_write##bits(d, dest_palette_color[*ss]); \
98 ss++; \
99 d += dsize; \
100 } \
101 } \
102 \
103 bmp_unwrite_line(dest); \
104 } \
105 else { \
106 /* slower version when reading from the screen */ \
107 for (y=0; y<h; y++) { \
108 s = bmp_read_line(src, s_y+y) + s_x; \
109 d = bmp_write_line(dest, d_y+y) + d_x*dsize; \
110 \
111 for (x=0; x<w; x++) { \
112 bmp_select(src); \
113 c = bmp_read8(s); \
114 \
115 bmp_select(dest); \
116 bmp_write##bits(d, dest_palette_color[c]); \
117 \
118 s++; \
119 d += dsize; \
120 } \
121 } \
122 \
123 bmp_unwrite_line(src); \
124 bmp_unwrite_line(dest); \
125 } \
126 }
127
128 /* expand the above macro for each possible output depth */
129 switch (bitmap_color_depth(dest)) {
130
131 #ifdef ALLEGRO_COLOR16
132 case 15:
133 case 16:
134 EXPAND_BLIT(16, sizeof(int16_t));
135 break;
136 #endif
137
138 #ifdef ALLEGRO_COLOR24
139 case 24:
140 EXPAND_BLIT(24, 3);
141 break;
142 #endif
143
144 #ifdef ALLEGRO_COLOR32
145 case 32:
146 EXPAND_BLIT(32, sizeof(int32_t));
147 break;
148 #endif
149 }
150
151 if (_color_conv & COLORCONV_KEEP_TRANS)
152 _AL_FREE(dest_palette_color);
153
154 #endif
155 }
156
157
158
159 /* worker macro for converting between two color formats, possibly with dithering */
160 #define CONVERT_BLIT_EX(sbits, ssize, dbits, dsize, MAKECOL) \
161 { \
162 if (_color_conv & COLORCONV_KEEP_TRANS) { \
163 int rc = get_replacement_mask_color(dest); \
164 int src_mask = bitmap_mask_color(src); \
165 int dest_mask = bitmap_mask_color(dest); \
166 \
167 for (y=0; y<h; y++) { \
168 s = bmp_read_line(src, s_y+y) + s_x*ssize; \
169 d = bmp_write_line(dest, d_y+y) + d_x*dsize; \
170 \
171 for (x=0; x<w; x++) { \
172 bmp_select(src); \
173 c = bmp_read##sbits(s); \
174 \
175 if (c == src_mask) \
176 c = dest_mask; \
177 else { \
178 r = getr##sbits(c); \
179 g = getg##sbits(c); \
180 b = getb##sbits(c); \
181 c = MAKECOL; \
182 if (c == dest_mask) \
183 c = rc; \
184 } \
185 \
186 bmp_select(dest); \
187 bmp_write##dbits(d, c); \
188 \
189 s += ssize; \
190 d += dsize; \
191 } \
192 } \
193 } \
194 else { \
195 for (y=0; y<h; y++) { \
196 s = bmp_read_line(src, s_y+y) + s_x*ssize; \
197 d = bmp_write_line(dest, d_y+y) + d_x*dsize; \
198 \
199 for (x=0; x<w; x++) { \
200 bmp_select(src); \
201 c = bmp_read##sbits(s); \
202 \
203 r = getr##sbits(c); \
204 g = getg##sbits(c); \
205 b = getb##sbits(c); \
206 \
207 bmp_select(dest); \
208 bmp_write##dbits(d, MAKECOL); \
209 \
210 s += ssize; \
211 d += dsize; \
212 } \
213 } \
214 } \
215 \
216 bmp_unwrite_line(src); \
217 bmp_unwrite_line(dest); \
218 }
219
220 #define CONVERT_BLIT(sbits, ssize, dbits, dsize) \
221 CONVERT_BLIT_EX(sbits, ssize, dbits, dsize, makecol##dbits(r, g, b))
222 #define CONVERT_DITHER_BLIT(sbits, ssize, dbits, dsize) \
223 CONVERT_BLIT_EX(sbits, ssize, dbits, dsize, \
224 makecol##dbits##_dither(r, g, b, x, y))
225
226
227
228 #if (defined ALLEGRO_COLOR8) || (defined ALLEGRO_GFX_HAS_VGA)
229
230 /* dither_blit:
231 * Blits with Floyd-Steinberg error diffusion.
232 */
dither_blit(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)233 static void dither_blit(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
234 {
235 int prev_drawmode = _drawing_mode;
236 int *errline[3];
237 int *errnextline[3];
238 int errpixel[3];
239 int v[3], e[3], n[3];
240 int x, y, i;
241 int c, nc, rc;
242
243 /* allocate memory for the error buffers */
244 for (i=0; i<3; i++) {
245 errline[i] = _AL_MALLOC_ATOMIC(sizeof(int) * w);
246 errnextline[i] = _AL_MALLOC_ATOMIC(sizeof(int) * w);
247 }
248
249 /* free the buffers if there was an error allocating one */
250 for (i=0; i<3; i++) {
251 if ((!errline[i]) || (!errnextline[i]))
252 goto getout;
253 }
254
255 /* initialize the error buffers */
256 for (i=0; i<3; i++) {
257 memset(errline[i], 0, sizeof(int) * w);
258 memset(errnextline[i], 0, sizeof(int) * w);
259 errpixel[i] = 0;
260 }
261
262 /* get the replacement color */
263 rc = get_replacement_mask_color(dest);
264
265 _drawing_mode = DRAW_MODE_SOLID;
266
267 /* dither!!! */
268 for (y =0; y<h; y++) {
269 for (x =0; x<w; x++) {
270 /* get the colour from the source bitmap */
271 c = getpixel(src, s_x+x, s_y+y);
272 v[0] = getr_depth(bitmap_color_depth(src), c);
273 v[1] = getg_depth(bitmap_color_depth(src), c);
274 v[2] = getb_depth(bitmap_color_depth(src), c);
275
276 /* add the error from previous pixels */
277 for (i=0; i<3; i++) {
278 n[i] = v[i] + errline[i][x] + errpixel[i];
279
280 if (n[i] > 255)
281 n[i] = 255;
282
283 if (n[i] < 0)
284 n[i] = 0;
285 }
286
287 /* find the nearest matching colour */
288 nc = makecol8(n[0], n[1], n[2]);
289 if (_color_conv & COLORCONV_KEEP_TRANS) {
290 if (c == bitmap_mask_color(src))
291 putpixel(dest, d_x+x, d_y+y, bitmap_mask_color(dest));
292 else if (nc == bitmap_mask_color(dest))
293 putpixel(dest, d_x+x, d_y+y, rc);
294 else
295 putpixel(dest, d_x+x, d_y+y, nc);
296 }
297 else {
298 putpixel(dest, d_x+x, d_y+y, nc);
299 }
300 v[0] = getr8(nc);
301 v[1] = getg8(nc);
302 v[2] = getb8(nc);
303
304 /* calculate the error and store it */
305 for (i=0; i<3; i++) {
306 e[i] = n[i] - v[i];
307 errpixel[i] = (int)((e[i] * 3)/8);
308 errnextline[i][x] += errpixel[i];
309
310 if (x != w-1)
311 errnextline[i][x+1] = (int)(e[i]/4);
312 }
313 }
314
315 /* update error buffers */
316 for (i=0; i<3; i++) {
317 memcpy(errline[i], errnextline[i], sizeof(int) * w);
318 memset(errnextline[i], 0, sizeof(int) * w);
319 }
320 }
321
322 _drawing_mode = prev_drawmode;
323
324 getout:
325
326 for (i=0; i<3; i++) {
327 if (errline[i])
328 _AL_FREE(errline[i]);
329
330 if (errnextline[i])
331 _AL_FREE(errnextline[i]);
332 }
333 }
334
335 #endif
336
337
338
339 /* blit_from_15:
340 * Converts 15 bpp images onto some other destination format.
341 */
blit_from_15(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)342 static void blit_from_15(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
343 {
344 #ifdef ALLEGRO_COLOR16
345
346 int x, y, c, r, g, b;
347 uintptr_t s, d;
348
349 switch (bitmap_color_depth(dest)) {
350
351 #ifdef ALLEGRO_COLOR8
352 case 8:
353 if (_color_conv & COLORCONV_DITHER_PAL)
354 dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h);
355 else
356 CONVERT_BLIT(15, sizeof(int16_t), 8, 1)
357 break;
358 #endif
359
360 case 16:
361 CONVERT_BLIT(15, sizeof(int16_t), 16, sizeof(int16_t))
362 break;
363
364 #ifdef ALLEGRO_COLOR24
365 case 24:
366 CONVERT_BLIT(15, sizeof(int16_t), 24, 3)
367 break;
368 #endif
369
370 #ifdef ALLEGRO_COLOR32
371 case 32:
372 CONVERT_BLIT(15, sizeof(int16_t), 32, sizeof(int32_t))
373 break;
374 #endif
375 }
376
377 #endif
378 }
379
380
381
382 /* blit_from_16:
383 * Converts 16 bpp images onto some other destination format.
384 */
blit_from_16(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)385 static void blit_from_16(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
386 {
387 #ifdef ALLEGRO_COLOR16
388
389 int x, y, c, r, g, b;
390 uintptr_t s, d;
391
392 switch (bitmap_color_depth(dest)) {
393
394 #ifdef ALLEGRO_COLOR8
395 case 8:
396 if (_color_conv & COLORCONV_DITHER_PAL)
397 dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h);
398 else
399 CONVERT_BLIT(16, sizeof(int16_t), 8, 1)
400 break;
401 #endif
402
403 case 15:
404 CONVERT_BLIT(16, sizeof(int16_t), 15, sizeof(int16_t))
405 break;
406
407 #ifdef ALLEGRO_COLOR24
408 case 24:
409 CONVERT_BLIT(16, sizeof(int16_t), 24, 3)
410 break;
411 #endif
412
413 #ifdef ALLEGRO_COLOR32
414 case 32:
415 CONVERT_BLIT(16, sizeof(int16_t), 32, sizeof(int32_t))
416 break;
417 #endif
418 }
419
420 #endif
421 }
422
423
424
425 /* blit_from_24:
426 * Converts 24 bpp images onto some other destination format.
427 */
blit_from_24(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)428 static void blit_from_24(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
429 {
430 #ifdef ALLEGRO_COLOR24
431
432 int x, y, c, r, g, b;
433 uintptr_t s, d;
434
435 switch (bitmap_color_depth(dest)) {
436
437 #ifdef ALLEGRO_COLOR8
438 case 8:
439 if (_color_conv & COLORCONV_DITHER_PAL)
440 dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h);
441 else
442 CONVERT_BLIT(24, 3, 8, 1);
443 break;
444 #endif
445
446 #ifdef ALLEGRO_COLOR16
447 case 15:
448 if (_color_conv & COLORCONV_DITHER_HI)
449 CONVERT_DITHER_BLIT(24, 3, 15, sizeof(int16_t))
450 else
451 CONVERT_BLIT(24, 3, 15, sizeof(int16_t))
452 break;
453
454 case 16:
455 if (_color_conv & COLORCONV_DITHER_HI)
456 CONVERT_DITHER_BLIT(24, 3, 16, sizeof(int16_t))
457 else
458 CONVERT_BLIT(24, 3, 16, sizeof(int16_t))
459 break;
460 #endif
461
462 #ifdef ALLEGRO_COLOR32
463 case 32:
464 CONVERT_BLIT(24, 3, 32, sizeof(int32_t))
465 break;
466 #endif
467 }
468
469 #endif
470 }
471
472
473
474 /* blit_from_32:
475 * Converts 32 bpp images onto some other destination format.
476 */
blit_from_32(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)477 static void blit_from_32(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
478 {
479 #ifdef ALLEGRO_COLOR32
480
481 int x, y, c, r, g, b;
482 uintptr_t s, d;
483
484 switch (bitmap_color_depth(dest)) {
485
486 #ifdef ALLEGRO_COLOR8
487 case 8:
488 if (_color_conv & COLORCONV_DITHER_PAL)
489 dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h);
490 else
491 CONVERT_BLIT(32, sizeof(int32_t), 8, 1)
492 break;
493 #endif
494
495 #ifdef ALLEGRO_COLOR16
496 case 15:
497 if (_color_conv & COLORCONV_DITHER_HI)
498 CONVERT_DITHER_BLIT(32, sizeof(int32_t), 15, sizeof(int16_t))
499 else
500 CONVERT_BLIT(32, sizeof(int32_t), 15, sizeof(int16_t))
501 break;
502
503 case 16:
504 if (_color_conv & COLORCONV_DITHER_HI)
505 CONVERT_DITHER_BLIT(32, sizeof(int32_t), 16, sizeof(int16_t))
506 else
507 CONVERT_BLIT(32, sizeof(int32_t), 16, sizeof(int16_t))
508 break;
509 #endif
510
511 #ifdef ALLEGRO_COLOR24
512 case 24:
513 CONVERT_BLIT(32, sizeof(int32_t), 24, 3)
514 break;
515 #endif
516 }
517
518 #endif
519 }
520
521
522
523 /* blit_to_or_from_modex:
524 * Converts between truecolor and planar mode-X bitmaps. This function is
525 * painfully slow, but I don't think it is something that people will need
526 * to do very often...
527 */
blit_to_or_from_modex(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)528 static void blit_to_or_from_modex(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
529 {
530 #ifdef ALLEGRO_GFX_HAS_VGA
531
532 int x, y, c, r, g, b;
533 int src_depth = bitmap_color_depth(src);
534 int dest_depth = bitmap_color_depth(dest);
535
536 int prev_drawmode = _drawing_mode;
537 _drawing_mode = DRAW_MODE_SOLID;
538
539 if ((src_depth != 8) && (_color_conv & COLORCONV_DITHER_PAL))
540 dither_blit(src, dest, s_x, s_y, d_x, d_y, w, h);
541 else {
542 for (y=0; y<h; y++) {
543 for (x=0; x<w; x++) {
544 c = getpixel(src, s_x+x, s_y+y);
545 r = getr_depth(src_depth, c);
546 g = getg_depth(src_depth, c);
547 b = getb_depth(src_depth, c);
548 c = makecol_depth(dest_depth, r, g, b);
549 putpixel(dest, d_x+x, d_y+y, c);
550 }
551 }
552 }
553
554 _drawing_mode = prev_drawmode;
555
556 #endif
557 }
558
559
560
561 /* blit_between_formats:
562 * Blits an (already clipped) region between two bitmaps of different
563 * color depths, doing the appopriate format conversions.
564 */
_blit_between_formats(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)565 void _blit_between_formats(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
566 {
567 if ((is_planar_bitmap(src)) || (is_planar_bitmap(dest))) {
568 blit_to_or_from_modex(src, dest, s_x, s_y, d_x, d_y, w, h);
569 }
570 else {
571 switch (bitmap_color_depth(src)) {
572
573 case 8:
574 blit_from_256(src, dest, s_x, s_y, d_x, d_y, w, h);
575 break;
576
577 case 15:
578 blit_from_15(src, dest, s_x, s_y, d_x, d_y, w, h);
579 break;
580
581 case 16:
582 blit_from_16(src, dest, s_x, s_y, d_x, d_y, w, h);
583 break;
584
585 case 24:
586 blit_from_24(src, dest, s_x, s_y, d_x, d_y, w, h);
587 break;
588
589 case 32:
590 blit_from_32(src, dest, s_x, s_y, d_x, d_y, w, h);
591 break;
592 }
593 }
594 }
595
596
597
598 /* blit_to_self:
599 * Blits an (already clipped) region between two areas of the same bitmap,
600 * checking which way around to do the blit.
601 */
blit_to_self(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)602 static void blit_to_self(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
603 {
604 unsigned long sx, sy, dx, dy;
605 BITMAP *tmp;
606
607 if (dest->id & BMP_ID_NOBLIT) {
608 /* with single-banked cards we have to use a temporary bitmap */
609 tmp = create_bitmap(w, h);
610 if (tmp) {
611 src->vtable->blit_to_memory(src, tmp, s_x, s_y, 0, 0, w, h);
612 dest->vtable->blit_from_memory(tmp, dest, 0, 0, d_x, d_y, w, h);
613 destroy_bitmap(tmp);
614 }
615 }
616 else {
617 /* check which way round to do the blit */
618 sx = s_x + src->x_ofs;
619 sy = s_y + src->y_ofs;
620
621 dx = d_x + dest->x_ofs;
622 dy = d_y + dest->y_ofs;
623
624 if ((sx+w <= dx) || (dx+w <= sx) || (sy+h <= dy) || (dy+h <= sy))
625 dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h);
626 else if ((sy > dy) || ((sy == dy) && (sx > dx)))
627 dest->vtable->blit_to_self_forward(src, dest, s_x, s_y, d_x, d_y, w, h);
628 else if ((sx != dx) || (sy != dy))
629 dest->vtable->blit_to_self_backward(src, dest, s_x, s_y, d_x, d_y, w, h);
630 }
631 }
632
633
634
635 /* helper for clipping a blit rectangle */
636 #define BLIT_CLIP() \
637 /* check for ridiculous cases */ \
638 if ((s_x >= src->w) || (s_y >= src->h) || \
639 (d_x >= dest->cr) || (d_y >= dest->cb)) \
640 return; \
641 \
642 /* clip src left */ \
643 if (s_x < 0) { \
644 w += s_x; \
645 d_x -= s_x; \
646 s_x = 0; \
647 } \
648 \
649 /* clip src top */ \
650 if (s_y < 0) { \
651 h += s_y; \
652 d_y -= s_y; \
653 s_y = 0; \
654 } \
655 \
656 /* clip src right */ \
657 if (s_x+w > src->w) \
658 w = src->w - s_x; \
659 \
660 /* clip src bottom */ \
661 if (s_y+h > src->h) \
662 h = src->h - s_y; \
663 \
664 /* clip dest left */ \
665 if (d_x < dest->cl) { \
666 d_x -= dest->cl; \
667 w += d_x; \
668 s_x -= d_x; \
669 d_x = dest->cl; \
670 } \
671 \
672 /* clip dest top */ \
673 if (d_y < dest->ct) { \
674 d_y -= dest->ct; \
675 h += d_y; \
676 s_y -= d_y; \
677 d_y = dest->ct; \
678 } \
679 \
680 /* clip dest right */ \
681 if (d_x+w > dest->cr) \
682 w = dest->cr - d_x; \
683 \
684 /* clip dest bottom */ \
685 if (d_y+h > dest->cb) \
686 h = dest->cb - d_y; \
687 \
688 /* bottle out if zero size */ \
689 if ((w <= 0) || (h <= 0)) \
690 return;
691
692
693
694 /* blit:
695 * Copies an area of the source bitmap to the destination bitmap. s_x and
696 * s_y give the top left corner of the area of the source bitmap to copy,
697 * and d_x and d_y give the position in the destination bitmap. w and h
698 * give the size of the area to blit. This routine respects the clipping
699 * rectangle of the destination bitmap, and will work correctly even when
700 * the two memory areas overlap (ie. src and dest are the same).
701 */
blit(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)702 void blit(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
703 {
704 ASSERT(src);
705 ASSERT(dest);
706 BLIT_CLIP();
707
708 if (src->vtable->color_depth != dest->vtable->color_depth) {
709 /* need to do a color conversion */
710 dest->vtable->blit_between_formats(src, dest, s_x, s_y, d_x, d_y, w, h);
711 }
712 else if (is_same_bitmap(src, dest)) {
713 /* special handling for overlapping regions */
714 blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h);
715 }
716 else if (is_video_bitmap(dest)) {
717 /* drawing onto video bitmaps */
718 if (is_video_bitmap(src))
719 dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h);
720 else if (is_system_bitmap(src))
721 dest->vtable->blit_from_system(src, dest, s_x, s_y, d_x, d_y, w, h);
722 else
723 dest->vtable->blit_from_memory(src, dest, s_x, s_y, d_x, d_y, w, h);
724 }
725 else if (is_system_bitmap(dest)) {
726 /* drawing onto system bitmaps */
727 if (is_video_bitmap(src))
728 src->vtable->blit_to_system(src, dest, s_x, s_y, d_x, d_y, w, h);
729 else if (is_system_bitmap(src))
730 dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h);
731 else
732 dest->vtable->blit_from_memory(src, dest, s_x, s_y, d_x, d_y, w, h);
733 }
734 else {
735 /* drawing onto memory bitmaps */
736 if ((is_video_bitmap(src)) || (is_system_bitmap(src)))
737 src->vtable->blit_to_memory(src, dest, s_x, s_y, d_x, d_y, w, h);
738 else
739 dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h);
740 }
741 }
742
743 END_OF_FUNCTION(blit);
744
745
746
747 /* masked_blit:
748 * Version of blit() that skips zero pixels. The source must be a memory
749 * bitmap, and the source and dest regions must not overlap.
750 */
masked_blit(BITMAP * src,BITMAP * dest,int s_x,int s_y,int d_x,int d_y,int w,int h)751 void masked_blit(BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)
752 {
753 ASSERT(src);
754 ASSERT(dest);
755 ASSERT(src->vtable->color_depth == dest->vtable->color_depth);
756
757 BLIT_CLIP();
758
759 dest->vtable->masked_blit(src, dest, s_x, s_y, d_x, d_y, w, h);
760 }
761