1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Sprite drawing functions.
12  *
13  *      By Michael Bukin.
14  *
15  *      See readme.txt for copyright information.
16  */
17 
18 #ifndef __bma_cspr_h
19 #define __bma_cspr_h
20 
21 
22 /* _linear_draw_sprite_ex:
23  *  Draws a masked sprite onto a linear bitmap at the specified dx, dy position,
24  *  using drawing mode specified by 'mode' and flipping mode specified by
25  *  'flip'.
26  */
FUNC_LINEAR_DRAW_SPRITE_EX(BITMAP * dst,BITMAP * src,int dx,int dy,int mode,int flip)27 void FUNC_LINEAR_DRAW_SPRITE_EX(BITMAP * dst, BITMAP * src, int dx, int dy,
28                                 int mode, int flip)
29 {
30    int x, y, w, h;
31    int x_dir = 1, y_dir = 1;
32    int dxbeg, dybeg;
33    int sxbeg, sybeg;
34    DLS_BLENDER lit_blender;
35    DTS_BLENDER trans_blender;
36 
37    ASSERT(dst);
38    ASSERT(src);
39 
40    if (flip == DRAW_SPRITE_V_FLIP) {
41       y_dir = -1;
42    }
43    if (flip == DRAW_SPRITE_H_FLIP) {
44       x_dir = -1;
45    }
46    if (flip == DRAW_SPRITE_VH_FLIP) {
47       y_dir = -1;
48       x_dir = -1;
49    }
50 
51    if (dst->clip) {
52       int tmp;
53 
54       tmp = dst->cl - dx;
55       sxbeg = MAX(0, tmp);
56       dxbeg = sxbeg + dx;
57 
58       tmp = dst->cr - dx;
59       w = MIN(src->w, tmp) - sxbeg;
60       if (w <= 0)
61          return;
62 
63       if (flip == DRAW_SPRITE_H_FLIP || flip == DRAW_SPRITE_VH_FLIP) {
64          /* use backward drawing onto dst */
65          sxbeg = src->w - (sxbeg + w);
66          dxbeg += w - 1;
67       }
68 
69       tmp = dst->ct - dy;
70       sybeg = MAX(0, tmp);
71       dybeg = sybeg + dy;
72 
73       tmp = dst->cb - dy;
74       h = MIN(src->h, tmp) - sybeg;
75       if (h <= 0)
76          return;
77 
78       if (flip == DRAW_SPRITE_V_FLIP || flip == DRAW_SPRITE_VH_FLIP) {
79          /* use backward drawing onto dst */
80          sybeg = src->h - (sybeg + h);
81          dybeg += h - 1;
82       }
83    }
84    else {
85       w = src->w;
86       h = src->h;
87       sxbeg = 0;
88       sybeg = 0;
89       dxbeg = dx;
90       if (flip == DRAW_SPRITE_H_FLIP || flip == DRAW_SPRITE_VH_FLIP) {
91          dxbeg = dx + w - 1;
92       }
93       dybeg = dy;
94       if (flip == DRAW_SPRITE_V_FLIP || flip == DRAW_SPRITE_VH_FLIP) {
95          dybeg = dy + h - 1;
96       }
97    }
98 
99    lit_blender = MAKE_DLS_BLENDER(0);
100    trans_blender = MAKE_DTS_BLENDER();
101 
102    if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
103       bmp_select(dst);
104 
105       for (y = 0; y < h; y++) {
106          PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
107 
108          /* flipped if y_dir is -1 */
109          PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
110 
111          /* d is incremented by x_dir, -1 if flipped */
112          for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR_N(d,x_dir), x--) {
113             unsigned long c = GET_MEMORY_PIXEL(s);
114             if (!IS_SPRITE_MASK(src, c)) {
115                switch (mode) {
116                   case DRAW_SPRITE_NORMAL:
117                      break;
118 
119                   case DRAW_SPRITE_LIT:
120                      c = DLSX_BLEND(lit_blender, c);
121                      break;
122 
123                   case DRAW_SPRITE_TRANS:
124                      c = DTS_BLEND(trans_blender, GET_PIXEL(d), c);
125                      break;
126                }
127                PUT_PIXEL(d, c);
128             }
129          }
130       }
131 
132       bmp_unwrite_line(dst);
133    }
134    else {
135       for (y = 0; y < h; y++) {
136          PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
137          PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
138 
139          for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR_N(d,x_dir), x--) {
140             unsigned long c = GET_MEMORY_PIXEL(s);
141             if (!IS_SPRITE_MASK(src, c)) {
142                switch (mode) {
143                   case DRAW_SPRITE_NORMAL:
144                      break;
145 
146                   case DRAW_SPRITE_LIT:
147                      c = DLSX_BLEND(lit_blender, c);
148                      break;
149 
150                   case DRAW_SPRITE_TRANS:
151                      c = DTS_BLEND(trans_blender, GET_PIXEL(d), c);
152                      break;
153                }
154                PUT_MEMORY_PIXEL(d, c);
155             }
156          }
157       }
158    }
159 }
160 
161 
162 
163 /* _linear_draw_sprite:
164  *  Draws a sprite onto a linear bitmap at the specified x, y position,
165  *  using a masked drawing mode where zero pixels are not output.
166  */
FUNC_LINEAR_DRAW_SPRITE(BITMAP * dst,BITMAP * src,int dx,int dy)167 void FUNC_LINEAR_DRAW_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy)
168 {
169    int x, y, w, h;
170    int dxbeg, dybeg;
171    int sxbeg, sybeg;
172 
173    ASSERT(dst);
174    ASSERT(src);
175 
176    if (dst->clip) {
177       int tmp;
178 
179       tmp = dst->cl - dx;
180       sxbeg = ((tmp < 0) ? 0 : tmp);
181       dxbeg = sxbeg + dx;
182 
183       tmp = dst->cr - dx;
184       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
185       if (w <= 0)
186 	 return;
187 
188       tmp = dst->ct - dy;
189       sybeg = ((tmp < 0) ? 0 : tmp);
190       dybeg = sybeg + dy;
191 
192       tmp = dst->cb - dy;
193       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
194       if (h <= 0)
195 	 return;
196    }
197    else {
198       w = src->w;
199       h = src->h;
200       sxbeg = 0;
201       sybeg = 0;
202       dxbeg = dx;
203       dybeg = dy;
204    }
205 
206    if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
207       bmp_select(dst);
208 
209       for (y = 0; y < h; y++) {
210 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
211 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
212 
213 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) {
214 	    unsigned long c = GET_MEMORY_PIXEL(s);
215 	    if (!IS_SPRITE_MASK(src, c)) {
216 	       PUT_PIXEL(d, c);
217 	    }
218 	 }
219       }
220 
221       bmp_unwrite_line(dst);
222    }
223    else {
224       for (y = 0; y < h; y++) {
225 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
226 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg);
227 
228 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) {
229 	    unsigned long c = GET_MEMORY_PIXEL(s);
230 	    if (!IS_SPRITE_MASK(src, c)) {
231 	       PUT_MEMORY_PIXEL(d, c);
232 	    }
233 	 }
234       }
235    }
236 }
237 
FUNC_LINEAR_DRAW_SPRITE_END(void)238 void FUNC_LINEAR_DRAW_SPRITE_END(void) { }
239 
240 
241 
242 /* _linear_draw_256_sprite:
243  *  Draws a 256 coor sprite onto a linear bitmap at the specified x, y
244  *  position, using a masked drawing mode where zero pixels are not output.
245  */
FUNC_LINEAR_DRAW_256_SPRITE(BITMAP * dst,BITMAP * src,int dx,int dy)246 void FUNC_LINEAR_DRAW_256_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy)
247 {
248    int x, y, w, h;
249    int dxbeg, dybeg;
250    int sxbeg, sybeg;
251    int *table;
252 
253    ASSERT(dst);
254    ASSERT(src);
255 
256    if (dst->clip) {
257       int tmp;
258 
259       tmp = dst->cl - dx;
260       sxbeg = ((tmp < 0) ? 0 : tmp);
261       dxbeg = sxbeg + dx;
262 
263       tmp = dst->cr - dx;
264       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
265       if (w <= 0)
266 	 return;
267 
268       tmp = dst->ct - dy;
269       sybeg = ((tmp < 0) ? 0 : tmp);
270       dybeg = sybeg + dy;
271 
272       tmp = dst->cb - dy;
273       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
274       if (h <= 0)
275 	 return;
276    }
277    else {
278       w = src->w;
279       h = src->h;
280       sxbeg = 0;
281       sybeg = 0;
282       dxbeg = dx;
283       dybeg = dy;
284    }
285 
286    table = _palette_expansion_table(bitmap_color_depth(dst));
287    ASSERT(table);
288 
289    if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
290       bmp_select(dst);
291 
292       for (y = 0; y < h; y++) {
293 	 unsigned char *s = src->line[sybeg + y] + sxbeg;
294 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
295 
296 	 for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(d), x--) {
297 	    unsigned long c = *s;
298 	    if (c != 0) {
299 	       c = table[c];
300 	       PUT_PIXEL(d, c);
301 	    }
302 	 }
303       }
304 
305       bmp_unwrite_line(dst);
306    }
307    else {
308       for (y = 0; y < h; y++) {
309 	 unsigned char *s = src->line[sybeg + y] + sxbeg;
310 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg);
311 
312 	 for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(d), x--) {
313 	    unsigned long c = *s;
314 	    if (c != 0) {
315 	       c = table[c];
316 	       PUT_MEMORY_PIXEL(d, c);
317 	    }
318 	 }
319       }
320    }
321 }
322 
323 
324 
325 /* _linear_draw_sprite_v_flip:
326  *  Draws a sprite to a linear bitmap, flipping vertically.
327  */
FUNC_LINEAR_DRAW_SPRITE_V_FLIP(BITMAP * dst,BITMAP * src,int dx,int dy)328 void FUNC_LINEAR_DRAW_SPRITE_V_FLIP(BITMAP *dst, BITMAP *src, int dx, int dy)
329 {
330    int x, y, w, h;
331    int dxbeg, dybeg;
332    int sxbeg, sybeg;
333 
334    ASSERT(dst);
335    ASSERT(src);
336 
337    if (dst->clip) {
338       int tmp;
339 
340       tmp = dst->cl - dx;
341       sxbeg = ((tmp < 0) ? 0 : tmp);
342       dxbeg = sxbeg + dx;
343 
344       tmp = dst->cr - dx;
345       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
346       if (w <= 0)
347 	 return;
348 
349       tmp = dst->ct - dy;
350       sybeg = ((tmp < 0) ? 0 : tmp);
351       dybeg = sybeg + dy;
352 
353       tmp = dst->cb - dy;
354       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
355       if (h <= 0)
356 	 return;
357 
358       /* use backward drawing onto dst */
359       sybeg = src->h - (sybeg + h);
360       dybeg += h - 1;
361    }
362    else {
363       w = src->w;
364       h = src->h;
365       sxbeg = 0;
366       sybeg = 0;
367       dxbeg = dx;
368       dybeg = dy + h - 1;
369    }
370 
371    if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
372       bmp_select(dst);
373 
374       for (y = 0; y < h; y++) {
375 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
376 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg - y), dxbeg);
377 
378 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) {
379 	    unsigned long c = GET_MEMORY_PIXEL(s);
380 	    if (!IS_SPRITE_MASK(src, c)) {
381 	       PUT_PIXEL(d, c);
382 	    }
383 	 }
384       }
385 
386       bmp_unwrite_line(dst);
387    }
388    else {
389       for (y = 0; y < h; y++) {
390 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
391 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg - y], dxbeg);
392 
393 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) {
394 	    unsigned long c = GET_MEMORY_PIXEL(s);
395 	    if (!IS_SPRITE_MASK(src, c)) {
396 	       PUT_MEMORY_PIXEL(d, c);
397 	    }
398 	 }
399       }
400    }
401 }
402 
403 
404 
405 /* _linear_draw_sprite_h_flip:
406  *  Draws a sprite to a linear bitmap, flipping horizontally.
407  */
FUNC_LINEAR_DRAW_SPRITE_H_FLIP(BITMAP * dst,BITMAP * src,int dx,int dy)408 void FUNC_LINEAR_DRAW_SPRITE_H_FLIP(BITMAP *dst, BITMAP *src, int dx, int dy)
409 {
410    int x, y, w, h;
411    int dxbeg, dybeg;
412    int sxbeg, sybeg;
413 
414    ASSERT(dst);
415    ASSERT(src);
416 
417    if (dst->clip) {
418       int tmp;
419 
420       tmp = dst->cl - dx;
421       sxbeg = ((tmp < 0) ? 0 : tmp);
422       dxbeg = sxbeg + dx;
423 
424       tmp = dst->cr - dx;
425       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
426       if (w <= 0)
427 	 return;
428 
429       /* use backward drawing onto dst */
430       sxbeg = src->w - (sxbeg + w);
431       dxbeg += w - 1;
432 
433       tmp = dst->ct - dy;
434       sybeg = ((tmp < 0) ? 0 : tmp);
435       dybeg = sybeg + dy;
436 
437       tmp = dst->cb - dy;
438       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
439       if (h <= 0)
440 	 return;
441    }
442    else {
443       w = src->w;
444       h = src->h;
445       sxbeg = 0;
446       sybeg = 0;
447       dxbeg = dx + w - 1;
448       dybeg = dy;
449    }
450 
451    if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
452       bmp_select(dst);
453 
454       for (y = 0; y < h; y++) {
455 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
456 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
457 
458 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) {
459 	    unsigned long c = GET_MEMORY_PIXEL(s);
460 	    if (!IS_SPRITE_MASK(src, c)) {
461 	       PUT_PIXEL(d, c);
462 	    }
463 	 }
464       }
465 
466       bmp_unwrite_line(dst);
467    }
468    else {
469       for (y = 0; y < h; y++) {
470 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
471 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg);
472 
473 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) {
474 	    unsigned long c = GET_MEMORY_PIXEL(s);
475 	    if (!IS_SPRITE_MASK(src, c)) {
476 	       PUT_MEMORY_PIXEL(d, c);
477 	    }
478 	 }
479       }
480    }
481 }
482 
483 
484 
485 /* _linear_draw_sprite_vh_flip:
486  *  Draws a sprite to a linear bitmap, flipping both vertically and horizontally.
487  */
FUNC_LINEAR_DRAW_SPRITE_VH_FLIP(BITMAP * dst,BITMAP * src,int dx,int dy)488 void FUNC_LINEAR_DRAW_SPRITE_VH_FLIP(BITMAP *dst, BITMAP *src, int dx, int dy)
489 {
490    int x, y, w, h;
491    int dxbeg, dybeg;
492    int sxbeg, sybeg;
493 
494    ASSERT(dst);
495    ASSERT(src);
496 
497    if (dst->clip) {
498       int tmp;
499 
500       tmp = dst->cl - dx;
501       sxbeg = ((tmp < 0) ? 0 : tmp);
502       dxbeg = sxbeg + dx;
503 
504       tmp = dst->cr - dx;
505       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
506       if (w <= 0)
507 	 return;
508 
509       /* use backward drawing onto dst */
510       sxbeg = src->w - (sxbeg + w);
511       dxbeg += w - 1;
512 
513       tmp = dst->ct - dy;
514       sybeg = ((tmp < 0) ? 0 : tmp);
515       dybeg = sybeg + dy;
516 
517       tmp = dst->cb - dy;
518       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
519       if (h <= 0)
520 	 return;
521 
522       /* use backward drawing onto dst */
523       sybeg = src->h - (sybeg + h);
524       dybeg += h - 1;
525    }
526    else {
527       w = src->w;
528       h = src->h;
529       sxbeg = 0;
530       sybeg = 0;
531       dxbeg = dx + w - 1;
532       dybeg = dy + h - 1;
533    }
534 
535    if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
536       bmp_select(dst);
537 
538       for (y = 0; y < h; y++) {
539 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
540 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg - y), dxbeg);
541 
542 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) {
543 	    unsigned long c = GET_MEMORY_PIXEL(s);
544 	    if (!IS_SPRITE_MASK(src, c)) {
545 	       PUT_PIXEL(d, c);
546 	    }
547 	 }
548       }
549 
550       bmp_unwrite_line(dst);
551    }
552    else {
553       for (y = 0; y < h; y++) {
554 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
555 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg - y], dxbeg);
556 
557 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), DEC_PIXEL_PTR(d), x--) {
558 	    unsigned long c = GET_MEMORY_PIXEL(s);
559 	    if (!IS_SPRITE_MASK(src, c)) {
560 	       PUT_MEMORY_PIXEL(d, c);
561 	    }
562 	 }
563       }
564    }
565 }
566 
567 
568 
569 /* _linear_draw_trans_sprite:
570  *  Draws a translucent sprite onto a linear bitmap.
571  */
FUNC_LINEAR_DRAW_TRANS_SPRITE(BITMAP * dst,BITMAP * src,int dx,int dy)572 void FUNC_LINEAR_DRAW_TRANS_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy)
573 {
574    int x, y, w, h;
575    int dxbeg, dybeg;
576    int sxbeg, sybeg;
577    DTS_BLENDER blender;
578 
579    ASSERT(dst);
580    ASSERT(src);
581 
582    if (dst->clip) {
583       int tmp;
584 
585       tmp = dst->cl - dx;
586       sxbeg = ((tmp < 0) ? 0 : tmp);
587       dxbeg = sxbeg + dx;
588 
589       tmp = dst->cr - dx;
590       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
591       if (w <= 0)
592 	 return;
593 
594       tmp = dst->ct - dy;
595       sybeg = ((tmp < 0) ? 0 : tmp);
596       dybeg = sybeg + dy;
597 
598       tmp = dst->cb - dy;
599       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
600       if (h <= 0)
601 	 return;
602    }
603    else {
604       w = src->w;
605       h = src->h;
606       sxbeg = 0;
607       sybeg = 0;
608       dxbeg = dx;
609       dybeg = dy;
610    }
611 
612    blender = MAKE_DTS_BLENDER();
613 
614    if ((src->vtable->color_depth == 8) && (dst->vtable->color_depth != 8)) {
615       bmp_select(dst);
616 
617       for (y = 0; y < h; y++) {
618 	 unsigned char *s = src->line[sybeg + y] + sxbeg;
619 	 PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg);
620 	 PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
621 
622 	 for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) {
623 	    unsigned long c = *s;
624 #if PP_DEPTH == 8
625 	    c = DTS_BLEND(blender, GET_PIXEL(ds), c);
626 	    PUT_PIXEL(dd, c);
627 #else
628             if (!IS_SPRITE_MASK(src, c)) {
629 	       c = DTS_BLEND(blender, GET_PIXEL(ds), c);
630 	       PUT_PIXEL(dd, c);
631 	    }
632 #endif
633 	 }
634       }
635 
636       bmp_unwrite_line(dst);
637    }
638    else if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
639       bmp_select(dst);
640 
641       for (y = 0; y < h; y++) {
642 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
643 	 PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg);
644 	 PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
645 
646 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) {
647 	    unsigned long c = GET_MEMORY_PIXEL(s);
648 #if PP_DEPTH == 8
649 	    c = DTS_BLEND(blender, GET_PIXEL(ds), c);
650 	    PUT_PIXEL(dd, c);
651 #else
652 	    if (!IS_SPRITE_MASK(src, c)) {
653 	       c = DTS_BLEND(blender, GET_PIXEL(ds), c);
654 	       PUT_PIXEL(dd, c);
655 	    }
656 #endif
657 	 }
658       }
659 
660       bmp_unwrite_line(dst);
661    }
662    else {
663       for (y = 0; y < h; y++) {
664 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
665 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg);
666 
667 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) {
668 	    unsigned long c = GET_MEMORY_PIXEL(s);
669 #if PP_DEPTH == 8
670 	    c = DTS_BLEND(blender, GET_MEMORY_PIXEL(d), c);
671 	    PUT_MEMORY_PIXEL(d, c);
672 #else
673 	    if (!IS_SPRITE_MASK(src, c)) {
674 	       c = DTS_BLEND(blender, GET_MEMORY_PIXEL(d), c);
675 	       PUT_MEMORY_PIXEL(d, c);
676 	    }
677 #endif
678 	 }
679       }
680    }
681 }
682 
683 
684 
685 #if (PP_DEPTH != 8) && (PP_DEPTH != 32)
686 
687 /* _linear_draw_trans_rgba_sprite:
688  *  Draws a translucent RGBA sprite onto a linear bitmap.
689  */
FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE(BITMAP * dst,BITMAP * src,int dx,int dy)690 void FUNC_LINEAR_DRAW_TRANS_RGBA_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy)
691 {
692    int x, y, w, h;
693    int dxbeg, dybeg;
694    int sxbeg, sybeg;
695    RGBA_BLENDER blender;
696 
697    ASSERT(dst);
698    ASSERT(src);
699 
700    if (dst->clip) {
701       int tmp;
702 
703       tmp = dst->cl - dx;
704       sxbeg = ((tmp < 0) ? 0 : tmp);
705       dxbeg = sxbeg + dx;
706 
707       tmp = dst->cr - dx;
708       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
709       if (w <= 0)
710 	 return;
711 
712       tmp = dst->ct - dy;
713       sybeg = ((tmp < 0) ? 0 : tmp);
714       dybeg = sybeg + dy;
715 
716       tmp = dst->cb - dy;
717       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
718       if (h <= 0)
719 	 return;
720    }
721    else {
722       w = src->w;
723       h = src->h;
724       sxbeg = 0;
725       sybeg = 0;
726       dxbeg = dx;
727       dybeg = dy;
728    }
729 
730    blender = MAKE_RGBA_BLENDER();
731 
732    bmp_select(dst);
733 
734    for (y = 0; y < h; y++) {
735       uint32_t *s = (uint32_t *)src->line[sybeg + y] + sxbeg;
736       PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg);
737       PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
738 
739       for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) {
740 	 unsigned long c = *s;
741 
742 	 if (c != MASK_COLOR_32) {
743 	    c = RGBA_BLEND(blender, GET_PIXEL(ds), c);
744 	    PUT_PIXEL(dd, c);
745 	 }
746       }
747    }
748 
749    bmp_unwrite_line(dst);
750 }
751 
752 #endif
753 
754 
755 
756 /* _linear_draw_lit_sprite:
757  *  Draws a lit sprite onto a linear bitmap.
758  */
FUNC_LINEAR_DRAW_LIT_SPRITE(BITMAP * dst,BITMAP * src,int dx,int dy,int color)759 void FUNC_LINEAR_DRAW_LIT_SPRITE(BITMAP *dst, BITMAP *src, int dx, int dy, int color)
760 {
761    int x, y, w, h;
762    int dxbeg, dybeg;
763    int sxbeg, sybeg;
764    DLS_BLENDER blender;
765 
766    ASSERT(dst);
767    ASSERT(src);
768 
769    if (dst->clip) {
770       int tmp;
771 
772       tmp = dst->cl - dx;
773       sxbeg = ((tmp < 0) ? 0 : tmp);
774       dxbeg = sxbeg + dx;
775 
776       tmp = dst->cr - dx;
777       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
778       if (w <= 0)
779 	 return;
780 
781       tmp = dst->ct - dy;
782       sybeg = ((tmp < 0) ? 0 : tmp);
783       dybeg = sybeg + dy;
784 
785       tmp = dst->cb - dy;
786       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
787       if (h <= 0)
788 	 return;
789    }
790    else {
791       w = src->w;
792       h = src->h;
793       sxbeg = 0;
794       sybeg = 0;
795       dxbeg = dx;
796       dybeg = dy;
797    }
798 
799    blender = MAKE_DLS_BLENDER(color);
800 
801    if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
802       bmp_select(dst);
803 
804       for (y = 0; y < h; y++) {
805 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
806 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
807 
808 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) {
809 	    unsigned long c = GET_MEMORY_PIXEL(s);
810 
811 	    if (!IS_MASK(c)) {
812 	       c = DLS_BLEND(blender, color, c);
813 	       PUT_PIXEL(d, c);
814 	    }
815 	 }
816       }
817 
818       bmp_unwrite_line(dst);
819    }
820    else {
821       for (y = 0; y < h; y++) {
822 	 PIXEL_PTR s = OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
823 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(dst->line[dybeg + y], dxbeg);
824 
825 	 for (x = w - 1; x >= 0; INC_PIXEL_PTR(s), INC_PIXEL_PTR(d), x--) {
826 	    unsigned long c = GET_MEMORY_PIXEL(s);
827 
828 	    if (!IS_MASK(c)) {
829 	       c = DLS_BLEND(blender, color, c);
830 	       PUT_MEMORY_PIXEL(d, c);
831 	    }
832 	 }
833       }
834    }
835 }
836 
837 
838 
839 /* _linear_draw_character:
840  *  For proportional font output onto a linear bitmap: uses the sprite as
841  *  a mask, replacing all set pixels with the specified color.
842  */
FUNC_LINEAR_DRAW_CHARACTER(BITMAP * dst,BITMAP * src,int dx,int dy,int color,int bg)843 void FUNC_LINEAR_DRAW_CHARACTER(BITMAP *dst, BITMAP *src, int dx, int dy, int color, int bg)
844 {
845    int x, y, w, h;
846    int dxbeg, dybeg;
847    int sxbeg, sybeg;
848 
849    ASSERT(dst);
850    ASSERT(src);
851 
852    if (dst->clip) {
853       int tmp;
854 
855       tmp = dst->cl - dx;
856       sxbeg = ((tmp < 0) ? 0 : tmp);
857       dxbeg = sxbeg + dx;
858 
859       tmp = dst->cr - dx;
860       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
861       if (w <= 0)
862 	 return;
863 
864       tmp = dst->ct - dy;
865       sybeg = ((tmp < 0) ? 0 : tmp);
866       dybeg = sybeg + dy;
867 
868       tmp = dst->cb - dy;
869       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
870       if (h <= 0)
871 	 return;
872    }
873    else {
874       w = src->w;
875       h = src->h;
876       sxbeg = 0;
877       sybeg = 0;
878       dxbeg = dx;
879       dybeg = dy;
880    }
881 
882    bmp_select(dst);
883 
884    if (bg < 0) {
885       /* Masked character.  */
886       for (y = 0; y < h; y++) {
887 	 unsigned char *s = src->line[sybeg + y] + sxbeg;
888 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
889 
890 	 for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(d), x--) {
891 	    unsigned long c = *s;
892 
893 	    if (c != 0) {
894 	       PUT_PIXEL(d, color);
895 	    }
896 	 }
897       }
898    }
899    else {
900       /* Opaque character.  */
901       for (y = 0; y < h; y++) {
902 	 unsigned char *s = src->line[sybeg + y] + sxbeg;
903 	 PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
904 
905 	 for (x = w - 1; x >= 0; s++, INC_PIXEL_PTR(d), x--) {
906 	    unsigned long c = *s;
907 
908 	    if (c != 0) {
909 	       PUT_PIXEL(d, color);
910 	    }
911 	    else {
912 	       PUT_PIXEL(d, bg);
913 	    }
914 	 }
915       }
916    }
917 
918    bmp_unwrite_line(dst);
919 }
920 
921 
922 
923 /* _linear_draw_rle_sprite:
924  *  Draws an RLE sprite onto a linear bitmap at the specified position.
925  */
FUNC_LINEAR_DRAW_RLE_SPRITE(BITMAP * dst,AL_CONST RLE_SPRITE * src,int dx,int dy)926 void FUNC_LINEAR_DRAW_RLE_SPRITE(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy)
927 {
928    int x, y, w, h;
929    int dxbeg, dybeg;
930    int sxbeg, sybeg;
931    RLE_PTR s;
932 
933    ASSERT(dst);
934    ASSERT(src);
935 
936    if (dst->clip) {
937       int tmp;
938 
939       tmp = dst->cl - dx;
940       sxbeg = ((tmp < 0) ? 0 : tmp);
941       dxbeg = sxbeg + dx;
942 
943       tmp = dst->cr - dx;
944       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
945       if (w <= 0)
946 	 return;
947 
948       tmp = dst->ct - dy;
949       sybeg = ((tmp < 0) ? 0 : tmp);
950       dybeg = sybeg + dy;
951 
952       tmp = dst->cb - dy;
953       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
954       if (h <= 0)
955 	 return;
956    }
957    else {
958       w = src->w;
959       h = src->h;
960       sxbeg = 0;
961       sybeg = 0;
962       dxbeg = dx;
963       dybeg = dy;
964    }
965 
966    s = (RLE_PTR) (src->dat);
967 
968    /* Clip top.  */
969    for (y = sybeg - 1; y >= 0; y--) {
970       long c = *s++;
971 
972       while (!RLE_IS_EOL(c)) {
973 	 if (c > 0)
974 	    s += c;
975 	 c = *s++;
976       }
977    }
978 
979    bmp_select(dst);
980 
981    /* Visible part.  */
982    if (sxbeg || dx+src->w >= dst->cr) {
983       for (y = 0; y < h; y++) {
984          PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
985          long c = *s++;
986 
987          /* Clip left.  */
988          for (x = sxbeg; x > 0; ) {
989 	    if (RLE_IS_EOL(c))
990 	       goto next_line;
991 	    else if (c > 0) {
992 	       /* Run of solid pixels.  */
993 	       if ((x - c) >= 0) {
994 	          /* Fully clipped.  */
995 	          x -= c;
996 	          s += c;
997 	       }
998 	       else {
999 	          /* Visible on the right.  */
1000 	          c -= x;
1001 	          s += x;
1002 	          break;
1003 	       }
1004 	    }
1005 	    else {
1006 	       /* Run of transparent pixels.  */
1007 	       if ((x + c) >= 0) {
1008 	          /* Fully clipped.  */
1009 	          x += c;
1010 	       }
1011 	       else {
1012 	          /* Visible on the right.  */
1013 	          c += x;
1014 	          break;
1015 	       }
1016 	    }
1017 
1018 	    c = *s++;
1019          }
1020 
1021          /* Visible part.  */
1022          for (x = w; x > 0; ) {
1023 	    if (RLE_IS_EOL(c))
1024 	       goto next_line;
1025 	    else if (c > 0) {
1026 	       /* Run of solid pixels.  */
1027 	       if ((x - c) >= 0) {
1028 	          /* Fully visible.  */
1029 	          x -= c;
1030 	          for (c--; c >= 0; s++, INC_PIXEL_PTR(d), c--) {
1031 		     unsigned long col = *s;
1032 		     PUT_PIXEL(d, col);
1033 	          }
1034 	       }
1035 	       else {
1036 	          /* Clipped on the right.  */
1037 	          c -= x;
1038 	          for (x--; x >= 0; s++, INC_PIXEL_PTR(d), x--) {
1039 		     unsigned long col = *s;
1040 		     PUT_PIXEL(d, col);
1041 	          }
1042 	          break;
1043 	       }
1044 	    }
1045 	    else {
1046 	       /* Run of transparent pixels.  */
1047 	       x += c;
1048 	       d = OFFSET_PIXEL_PTR(d, -c);
1049 	    }
1050 
1051 	    c = *s++;
1052          }
1053 
1054          /* Clip right.  */
1055          while (!RLE_IS_EOL(c)) {
1056 	    if (c > 0)
1057 	       s += c;
1058 	    c = *s++;
1059          }
1060 
1061 	 next_line: ;
1062       }
1063    }
1064    else {
1065       for (y = 0; y < h; y++) {
1066          PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
1067          long c = *s++;
1068 
1069          /* Visible part.  */
1070          for (x = w; x > 0; ) {
1071 	    if (RLE_IS_EOL(c))
1072 	       goto next_line2;
1073 	    else if (c > 0) {
1074 	       /* Run of solid pixels.  */
1075 	       if ((x - c) >= 0) {
1076 	          /* Fully visible.  */
1077 	          x -= c;
1078 	          for (c--; c >= 0; s++, INC_PIXEL_PTR(d), c--) {
1079 		     unsigned long col = *s;
1080 		     PUT_PIXEL(d, col);
1081 	          }
1082 	       }
1083 	       else {
1084 	          /* Clipped on the right.  */
1085 	          c -= x;
1086 	          for (x--; x >= 0; s++, INC_PIXEL_PTR(d), x--) {
1087 		     unsigned long col = *s;
1088 		     PUT_PIXEL(d, col);
1089 	          }
1090 	          break;
1091 	       }
1092 	    }
1093 	    else {
1094 	       /* Run of transparent pixels.  */
1095 	       x += c;
1096 	       d = OFFSET_PIXEL_PTR(d, -c);
1097 	    }
1098 
1099 	    c = *s++;
1100          }
1101 
1102 	 next_line2: ;
1103       }
1104    }
1105 
1106    bmp_unwrite_line(dst);
1107 }
1108 
1109 
1110 
1111 /* _linear_draw_trans_rle_sprite:
1112  *  Draws a translucent RLE sprite onto a linear bitmap.
1113  */
FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE(BITMAP * dst,AL_CONST RLE_SPRITE * src,int dx,int dy)1114 void FUNC_LINEAR_DRAW_TRANS_RLE_SPRITE(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy)
1115 {
1116    int x, y, w, h;
1117    int dxbeg, dybeg;
1118    int sxbeg, sybeg;
1119    RLE_PTR s;
1120    DTS_BLENDER blender;
1121 
1122    ASSERT(dst);
1123    ASSERT(src);
1124 
1125    if (dst->clip) {
1126       int tmp;
1127 
1128       tmp = dst->cl - dx;
1129       sxbeg = ((tmp < 0) ? 0 : tmp);
1130       dxbeg = sxbeg + dx;
1131 
1132       tmp = dst->cr - dx;
1133       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
1134       if (w <= 0)
1135 	 return;
1136 
1137       tmp = dst->ct - dy;
1138       sybeg = ((tmp < 0) ? 0 : tmp);
1139       dybeg = sybeg + dy;
1140 
1141       tmp = dst->cb - dy;
1142       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
1143       if (h <= 0)
1144 	 return;
1145    }
1146    else {
1147       w = src->w;
1148       h = src->h;
1149       sxbeg = 0;
1150       sybeg = 0;
1151       dxbeg = dx;
1152       dybeg = dy;
1153    }
1154 
1155    blender = MAKE_DTS_BLENDER();
1156    s = (RLE_PTR) (src->dat);
1157 
1158    /* Clip top.  */
1159    for (y = sybeg - 1; y >= 0; y--) {
1160       long c = *s++;
1161 
1162       while (!RLE_IS_EOL(c)) {
1163 	 if (c > 0)
1164 	    s += c;
1165 	 c = *s++;
1166       }
1167    }
1168 
1169    bmp_select(dst);
1170 
1171    /* Visible part.  */
1172    if (sxbeg || dx+src->w >= dst->cr) {
1173       for (y = 0; y < h; y++) {
1174          PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg);
1175          PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
1176          long c = *s++;
1177 
1178          /* Clip left.  */
1179          for (x = sxbeg; x > 0; ) {
1180 	    if (RLE_IS_EOL(c))
1181 	       goto next_line;
1182 	    else if (c > 0) {
1183 	       /* Run of solid pixels.  */
1184 	       if ((x - c) >= 0) {
1185 	          /* Fully clipped.  */
1186 	          x -= c;
1187 	          s += c;
1188 	       }
1189 	       else {
1190 	          /* Visible on the right.  */
1191 	          c -= x;
1192 	          s += x;
1193 	          break;
1194 	       }
1195 	    }
1196 	    else {
1197 	       /* Run of transparent pixels.  */
1198 	       if ((x + c) >= 0) {
1199 	          /* Fully clipped.  */
1200 	          x += c;
1201 	       }
1202 	       else {
1203 	          /* Visible on the right.  */
1204 	          c += x;
1205 	          break;
1206 	       }
1207 	    }
1208 
1209 	    c = *s++;
1210          }
1211 
1212          /* Visible part.  */
1213          for (x = w; x > 0; ) {
1214 	    if (RLE_IS_EOL(c))
1215 	       goto next_line;
1216 	    else if (c > 0) {
1217 	       /* Run of solid pixels.  */
1218 	       if ((x - c) >= 0) {
1219 	          /* Fully visible.  */
1220 	          x -= c;
1221 	          for (c--; c >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), c--) {
1222 		     unsigned long col = DTS_BLEND(blender, GET_PIXEL(ds), *s);
1223 		     PUT_PIXEL(dd, col);
1224 	          }
1225 	       }
1226 	       else {
1227 	          /* Clipped on the right.  */
1228 	          c -= x;
1229 	          for (x--; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) {
1230 		     unsigned long col = DTS_BLEND(blender, GET_PIXEL(ds), *s);
1231 		     PUT_PIXEL(dd, col);
1232 	          }
1233 	          break;
1234 	       }
1235 	    }
1236 	    else {
1237 	       /* Run of transparent pixels.  */
1238 	       x += c;
1239 	       ds = OFFSET_PIXEL_PTR(ds, -c);
1240 	       dd = OFFSET_PIXEL_PTR(dd, -c);
1241 	    }
1242 
1243 	    c = *s++;
1244          }
1245 
1246          /* Clip right.  */
1247          while (!RLE_IS_EOL(c)) {
1248 	    if (c > 0)
1249 	       s += c;
1250 	    c = *s++;
1251          }
1252 
1253 next_line:{}
1254       }
1255    }
1256    else {
1257       for (y = 0; y < h; y++) {
1258          PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg);
1259          PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
1260          long c = *s++;
1261 
1262          /* Visible part.  */
1263          for (x = w; x > 0; ) {
1264 	    if (RLE_IS_EOL(c))
1265 	       goto next_line2;
1266 	    else if (c > 0) {
1267 	       /* Run of solid pixels.  */
1268 	       if ((x - c) >= 0) {
1269 	          /* Fully visible.  */
1270 	          x -= c;
1271 	          for (c--; c >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), c--) {
1272 		     unsigned long col = DTS_BLEND(blender, GET_PIXEL(ds), *s);
1273 		     PUT_PIXEL(dd, col);
1274 	          }
1275 	       }
1276 	       else {
1277 	          /* Clipped on the right.  */
1278 	          c -= x;
1279 	          for (x--; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) {
1280 		     unsigned long col = DTS_BLEND(blender, GET_PIXEL(ds), *s);
1281 		     PUT_PIXEL(dd, col);
1282 	          }
1283 	          break;
1284 	       }
1285 	    }
1286 	    else {
1287 	       /* Run of transparent pixels.  */
1288 	       x += c;
1289 	       ds = OFFSET_PIXEL_PTR(ds, -c);
1290 	       dd = OFFSET_PIXEL_PTR(dd, -c);
1291 	    }
1292 
1293 	    c = *s++;
1294          }
1295 
1296          /* Clip right.  */
1297          while (!RLE_IS_EOL(c)) {
1298 	    if (c > 0)
1299 	       s += c;
1300 	    c = *s++;
1301          }
1302 
1303 next_line2:{}
1304       }
1305    }
1306 
1307    bmp_unwrite_line(dst);
1308 }
1309 
1310 
1311 
1312 #if (PP_DEPTH != 8) && (PP_DEPTH != 32)
1313 
1314 /* _linear_draw_trans_rgba_rle_sprite:
1315  *  Draws a translucent RGBA RLE sprite onto a linear bitmap.
1316  */
FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE(BITMAP * dst,AL_CONST RLE_SPRITE * src,int dx,int dy)1317 void FUNC_LINEAR_DRAW_TRANS_RGBA_RLE_SPRITE(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy)
1318 {
1319    int x, y, w, h;
1320    int dxbeg, dybeg;
1321    int sxbeg, sybeg;
1322    uint32_t *s;
1323    RGBA_BLENDER blender;
1324 
1325    ASSERT(dst);
1326    ASSERT(src);
1327 
1328    if (dst->clip) {
1329       int tmp;
1330 
1331       tmp = dst->cl - dx;
1332       sxbeg = ((tmp < 0) ? 0 : tmp);
1333       dxbeg = sxbeg + dx;
1334 
1335       tmp = dst->cr - dx;
1336       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
1337       if (w <= 0)
1338 	 return;
1339 
1340       tmp = dst->ct - dy;
1341       sybeg = ((tmp < 0) ? 0 : tmp);
1342       dybeg = sybeg + dy;
1343 
1344       tmp = dst->cb - dy;
1345       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
1346       if (h <= 0)
1347 	 return;
1348    }
1349    else {
1350       w = src->w;
1351       h = src->h;
1352       sxbeg = 0;
1353       sybeg = 0;
1354       dxbeg = dx;
1355       dybeg = dy;
1356    }
1357 
1358    blender = MAKE_RGBA_BLENDER();
1359    s = (uint32_t *) (src->dat);
1360 
1361    /* Clip top.  */
1362    for (y = sybeg - 1; y >= 0; y--) {
1363       long c = *s++;
1364 
1365       while (c != MASK_COLOR_32) {
1366 	 if (c > 0)
1367 	    s += c;
1368 	 c = *s++;
1369       }
1370    }
1371 
1372    bmp_select(dst);
1373 
1374    /* Visible part.  */
1375    if (sxbeg || dx+src->w >= dst->cr) {
1376       for (y = 0; y < h; y++) {
1377          PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg);
1378          PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
1379          long c = *s++;
1380 
1381          /* Clip left.  */
1382          for (x = sxbeg; x > 0; ) {
1383 	    if (c == MASK_COLOR_32)
1384 	       goto next_line;
1385 	    else if (c > 0) {
1386 	       /* Run of solid pixels.  */
1387 	       if ((x - c) >= 0) {
1388 	          /* Fully clipped.  */
1389 	          x -= c;
1390 	          s += c;
1391 	       }
1392 	       else {
1393 	          /* Visible on the right.  */
1394 	          c -= x;
1395 	          s += x;
1396 	          break;
1397 	       }
1398 	    }
1399 	    else {
1400 	       /* Run of transparent pixels.  */
1401 	       if ((x + c) >= 0) {
1402 	          /* Fully clipped.  */
1403 	          x += c;
1404 	       }
1405 	       else {
1406 	          /* Visible on the right.  */
1407 	          c += x;
1408 	          break;
1409 	       }
1410 	    }
1411 
1412 	    c = *s++;
1413          }
1414 
1415          /* Visible part.  */
1416          for (x = w; x > 0; ) {
1417 	    if (c == MASK_COLOR_32)
1418 	       goto next_line;
1419 	    else if (c > 0) {
1420 	       /* Run of solid pixels.  */
1421 	       if ((x - c) >= 0) {
1422 	          /* Fully visible.  */
1423 	          x -= c;
1424 	          for (c--; c >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), c--) {
1425 		     unsigned long col = RGBA_BLEND(blender, GET_PIXEL(ds), *s);
1426 		     PUT_PIXEL(dd, col);
1427 	          }
1428 	       }
1429 	       else {
1430 	          /* Clipped on the right.  */
1431 	          c -= x;
1432 	          for (x--; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) {
1433 		     unsigned long col = RGBA_BLEND(blender, GET_PIXEL(ds), *s);
1434 		     PUT_PIXEL(dd, col);
1435 	          }
1436 	          break;
1437 	       }
1438 	    }
1439 	    else {
1440 	       /* Run of transparent pixels.  */
1441 	       x += c;
1442 	       ds = OFFSET_PIXEL_PTR(ds, -c);
1443 	       dd = OFFSET_PIXEL_PTR(dd, -c);
1444 	    }
1445 
1446 	    c = *s++;
1447          }
1448 
1449          /* Clip right.  */
1450          while (c != MASK_COLOR_32) {
1451 	    if (c > 0)
1452 	       s += c;
1453 	    c = *s++;
1454          }
1455 
1456       next_line:{}
1457       }
1458    }
1459    else {
1460       for (y = 0; y < h; y++) {
1461          PIXEL_PTR ds = OFFSET_PIXEL_PTR(bmp_read_line(dst, dybeg + y), dxbeg);
1462          PIXEL_PTR dd = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
1463          long c = *s++;
1464 
1465          /* Visible part.  */
1466          for (x = w; x > 0; ) {
1467 	    if (c == MASK_COLOR_32)
1468 	       goto next_line2;
1469 	    else if (c > 0) {
1470 	       /* Run of solid pixels.  */
1471 	       if ((x - c) >= 0) {
1472 	          /* Fully visible.  */
1473 	          x -= c;
1474 	          for (c--; c >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), c--) {
1475 		     unsigned long col = RGBA_BLEND(blender, GET_PIXEL(ds), *s);
1476 		     PUT_PIXEL(dd, col);
1477 	          }
1478 	       }
1479 	       else {
1480 	          /* Clipped on the right.  */
1481 	          c -= x;
1482 	          for (x--; x >= 0; s++, INC_PIXEL_PTR(ds), INC_PIXEL_PTR(dd), x--) {
1483 		     unsigned long col = RGBA_BLEND(blender, GET_PIXEL(ds), *s);
1484 		     PUT_PIXEL(dd, col);
1485 	          }
1486 	          break;
1487 	       }
1488 	    }
1489 	    else {
1490 	       /* Run of transparent pixels.  */
1491 	       x += c;
1492 	       ds = OFFSET_PIXEL_PTR(ds, -c);
1493 	       dd = OFFSET_PIXEL_PTR(dd, -c);
1494 	    }
1495 
1496 	    c = *s++;
1497          }
1498 
1499       next_line2:{}
1500       }
1501    }
1502 
1503    bmp_unwrite_line(dst);
1504 }
1505 
1506 #endif
1507 
1508 
1509 
1510 /* _linear_draw_lit_rle_sprite:
1511  *  Draws a tinted RLE sprite onto a linear bitmap.
1512  */
FUNC_LINEAR_DRAW_LIT_RLE_SPRITE(BITMAP * dst,AL_CONST RLE_SPRITE * src,int dx,int dy,int color)1513 void FUNC_LINEAR_DRAW_LIT_RLE_SPRITE(BITMAP *dst, AL_CONST RLE_SPRITE *src, int dx, int dy, int color)
1514 {
1515    int x, y, w, h;
1516    int dxbeg, dybeg;
1517    int sxbeg, sybeg;
1518    RLE_PTR s;
1519    DLS_BLENDER blender;
1520 
1521    ASSERT(dst);
1522    ASSERT(src);
1523 
1524    if (dst->clip) {
1525       int tmp;
1526 
1527       tmp = dst->cl - dx;
1528       sxbeg = ((tmp < 0) ? 0 : tmp);
1529       dxbeg = sxbeg + dx;
1530 
1531       tmp = dst->cr - dx;
1532       w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
1533       if (w <= 0)
1534 	 return;
1535 
1536       tmp = dst->ct - dy;
1537       sybeg = ((tmp < 0) ? 0 : tmp);
1538       dybeg = sybeg + dy;
1539 
1540       tmp = dst->cb - dy;
1541       h = ((tmp > src->h) ? src->h : tmp) - sybeg;
1542       if (h <= 0)
1543 	 return;
1544    }
1545    else {
1546       w = src->w;
1547       h = src->h;
1548       sxbeg = 0;
1549       sybeg = 0;
1550       dxbeg = dx;
1551       dybeg = dy;
1552    }
1553 
1554    blender = MAKE_DLS_BLENDER(color);
1555    s = (RLE_PTR) (src->dat);
1556 
1557    /* Clip top.  */
1558    for (y = sybeg - 1; y >= 0; y--) {
1559       long c = *s++;
1560 
1561       while (!RLE_IS_EOL(c)) {
1562 	 if (c > 0)
1563 	    s += c;
1564 	 c = *s++;
1565       }
1566    }
1567 
1568    bmp_select(dst);
1569 
1570    /* Visible part.  */
1571    if (sxbeg || dx+src->w >= dst->cr) {
1572       for (y = 0; y < h; y++) {
1573          PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
1574          long c = *s++;
1575 
1576          /* Clip left.  */
1577          for (x = sxbeg; x > 0; ) {
1578 	    if (RLE_IS_EOL(c))
1579 	       goto next_line;
1580 	    else if (c > 0) {
1581 	       /* Run of solid pixels.  */
1582 	       if ((x - c) >= 0) {
1583 	          /* Fully clipped.  */
1584 	          x -= c;
1585 	          s += c;
1586 	       }
1587 	       else {
1588 	          /* Visible on the right.  */
1589 	          c -= x;
1590 	          s += x;
1591 	          break;
1592 	       }
1593 	    }
1594 	    else {
1595 	       /* Run of transparent pixels.  */
1596 	       if ((x + c) >= 0) {
1597 	          /* Fully clipped.  */
1598 	          x += c;
1599 	       }
1600 	       else {
1601 	          /* Visible on the right.  */
1602 	          c += x;
1603 	          break;
1604 	       }
1605 	    }
1606 
1607 	    c = *s++;
1608          }
1609 
1610          /* Visible part.  */
1611          for (x = w; x > 0; ) {
1612 	    if (RLE_IS_EOL(c))
1613 	       goto next_line;
1614 	    else if (c > 0) {
1615 	       /* Run of solid pixels.  */
1616 	       if ((x - c) >= 0) {
1617 	          /* Fully visible.  */
1618 	          x -= c;
1619 	          for (c--; c >= 0; s++, INC_PIXEL_PTR(d), c--) {
1620 		     unsigned long col = DLS_BLEND(blender, color, *s);
1621 		     PUT_PIXEL(d, col);
1622 	          }
1623 	       }
1624 	       else {
1625 	          /* Clipped on the right.  */
1626 	          c -= x;
1627 	          for (x--; x >= 0; s++, INC_PIXEL_PTR(d), x--) {
1628 		     unsigned long col = DLS_BLEND(blender, color, *s);
1629 		     PUT_PIXEL(d, col);
1630 	          }
1631 	          break;
1632 	       }
1633 	    }
1634 	    else {
1635 	       /* Run of transparent pixels.  */
1636 	       x += c;
1637 	       d = OFFSET_PIXEL_PTR(d, -c);
1638 	    }
1639 
1640 	    c = *s++;
1641          }
1642 
1643          /* Clip right.  */
1644          while (!RLE_IS_EOL(c)) {
1645 	    if (c > 0)
1646 	       s += c;
1647 	    c = *s++;
1648          }
1649 
1650 next_line:{}
1651 
1652       }
1653    }
1654    else {
1655       for (y = 0; y < h; y++) {
1656          PIXEL_PTR d = OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y), dxbeg);
1657          long c = *s++;
1658 
1659          /* Visible part.  */
1660          for (x = w; x > 0; ) {
1661 	    if (RLE_IS_EOL(c))
1662 	       goto next_line2;
1663 	    else if (c > 0) {
1664 	       /* Run of solid pixels.  */
1665 	       if ((x - c) >= 0) {
1666 	          /* Fully visible.  */
1667 	          x -= c;
1668 	          for (c--; c >= 0; s++, INC_PIXEL_PTR(d), c--) {
1669 		     unsigned long col = DLS_BLEND(blender, color, *s);
1670 		     PUT_PIXEL(d, col);
1671 	          }
1672 	       }
1673 	       else {
1674 	          /* Clipped on the right.  */
1675 	          c -= x;
1676 	          for (x--; x >= 0; s++, INC_PIXEL_PTR(d), x--) {
1677 		     unsigned long col = DLS_BLEND(blender, color, *s);
1678 		     PUT_PIXEL(d, col);
1679 	          }
1680 	          break;
1681 	       }
1682 	    }
1683 	    else {
1684 	       /* Run of transparent pixels.  */
1685 	       x += c;
1686 	       d = OFFSET_PIXEL_PTR(d, -c);
1687 	    }
1688 
1689 	    c = *s++;
1690          }
1691 
1692       next_line2:{}
1693       }
1694    }
1695 
1696    bmp_unwrite_line(dst);
1697 }
1698 
1699 #endif /* !__bma_cspr_h */
1700 
1701