[INTL]
[reactos.git] / base / applications / mstsc / bitmap.c
1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Bitmap decompression routines
4 Copyright (C) Matthew Chapman 1999-2005
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 /* three seperate function for speed when decompressing the bitmaps */
22 /* when modifing one function make the change in the others */
23 /* comment out #define BITMAP_SPEED_OVER_SIZE below for one slower function */
24 /* j@american-data.com */
25
26 /* indent is confused by this file */
27 /* *INDENT-OFF* */
28
29 #include "precomp.h"
30
31 #define BITMAP_SPEED_OVER_SIZE
32
33 #define CVAL(p) (*(p++))
34 #ifdef NEED_ALIGN
35 #ifdef L_ENDIAN
36 #define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; }
37 #else
38 #define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); }
39 #endif /* L_ENDIAN */
40 #else
41 #define CVAL2(p, v) { v = (*((uint16*)p)); p += 2; }
42 #endif /* NEED_ALIGN */
43
44 #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
45
46 #define REPEAT(statement) \
47 { \
48 while((count & ~0x7) && ((x+8) < width)) \
49 UNROLL8( statement; count--; x++; ); \
50 \
51 while((count > 0) && (x < width)) \
52 { \
53 statement; \
54 count--; \
55 x++; \
56 } \
57 }
58
59 #define MASK_UPDATE() \
60 { \
61 mixmask <<= 1; \
62 if (mixmask == 0) \
63 { \
64 mask = fom_mask ? fom_mask : CVAL(input); \
65 mixmask = 1; \
66 } \
67 }
68
69 #ifdef BITMAP_SPEED_OVER_SIZE
70
71 /* 1 byte bitmap decompress */
72 static BOOL
73 bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
74 {
75 uint8 *end = input + size;
76 uint8 *prevline = NULL, *line = NULL;
77 int opcode, count, offset, isfillormix, x = width;
78 int lastopcode = -1, insertmix = False, bicolour = False;
79 uint8 code;
80 uint8 colour1 = 0, colour2 = 0;
81 uint8 mixmask, mask = 0;
82 uint8 mix = 0xff;
83 int fom_mask = 0;
84
85 while (input < end)
86 {
87 fom_mask = 0;
88 code = CVAL(input);
89 opcode = code >> 4;
90 /* Handle different opcode forms */
91 switch (opcode)
92 {
93 case 0xc:
94 case 0xd:
95 case 0xe:
96 opcode -= 6;
97 count = code & 0xf;
98 offset = 16;
99 break;
100 case 0xf:
101 opcode = code & 0xf;
102 if (opcode < 9)
103 {
104 count = CVAL(input);
105 count |= CVAL(input) << 8;
106 }
107 else
108 {
109 count = (opcode < 0xb) ? 8 : 1;
110 }
111 offset = 0;
112 break;
113 default:
114 opcode >>= 1;
115 count = code & 0x1f;
116 offset = 32;
117 break;
118 }
119 /* Handle strange cases for counts */
120 if (offset != 0)
121 {
122 isfillormix = ((opcode == 2) || (opcode == 7));
123 if (count == 0)
124 {
125 if (isfillormix)
126 count = CVAL(input) + 1;
127 else
128 count = CVAL(input) + offset;
129 }
130 else if (isfillormix)
131 {
132 count <<= 3;
133 }
134 }
135 /* Read preliminary data */
136 switch (opcode)
137 {
138 case 0: /* Fill */
139 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
140 insertmix = True;
141 break;
142 case 8: /* Bicolour */
143 colour1 = CVAL(input);
144 case 3: /* Colour */
145 colour2 = CVAL(input);
146 break;
147 case 6: /* SetMix/Mix */
148 case 7: /* SetMix/FillOrMix */
149 mix = CVAL(input);
150 opcode -= 5;
151 break;
152 case 9: /* FillOrMix_1 */
153 mask = 0x03;
154 opcode = 0x02;
155 fom_mask = 3;
156 break;
157 case 0x0a: /* FillOrMix_2 */
158 mask = 0x05;
159 opcode = 0x02;
160 fom_mask = 5;
161 break;
162 }
163 lastopcode = opcode;
164 mixmask = 0;
165 /* Output body */
166 while (count > 0)
167 {
168 if (x >= width)
169 {
170 if (height <= 0)
171 return False;
172 x = 0;
173 height--;
174 prevline = line;
175 line = output + height * width;
176 }
177 switch (opcode)
178 {
179 case 0: /* Fill */
180 if (insertmix)
181 {
182 if (prevline == NULL)
183 line[x] = mix;
184 else
185 line[x] = prevline[x] ^ mix;
186 insertmix = False;
187 count--;
188 x++;
189 }
190 if (prevline == NULL)
191 {
192 REPEAT(line[x] = 0)
193 }
194 else
195 {
196 REPEAT(line[x] = prevline[x])
197 }
198 break;
199 case 1: /* Mix */
200 if (prevline == NULL)
201 {
202 REPEAT(line[x] = mix)
203 }
204 else
205 {
206 REPEAT(line[x] = prevline[x] ^ mix)
207 }
208 break;
209 case 2: /* Fill or Mix */
210 if (prevline == NULL)
211 {
212 REPEAT
213 (
214 MASK_UPDATE();
215 if (mask & mixmask)
216 line[x] = mix;
217 else
218 line[x] = 0;
219 )
220 }
221 else
222 {
223 REPEAT
224 (
225 MASK_UPDATE();
226 if (mask & mixmask)
227 line[x] = prevline[x] ^ mix;
228 else
229 line[x] = prevline[x];
230 )
231 }
232 break;
233 case 3: /* Colour */
234 REPEAT(line[x] = colour2)
235 break;
236 case 4: /* Copy */
237 REPEAT(line[x] = CVAL(input))
238 break;
239 case 8: /* Bicolour */
240 REPEAT
241 (
242 if (bicolour)
243 {
244 line[x] = colour2;
245 bicolour = False;
246 }
247 else
248 {
249 line[x] = colour1;
250 bicolour = True; count++;
251 }
252 )
253 break;
254 case 0xd: /* White */
255 REPEAT(line[x] = 0xff)
256 break;
257 case 0xe: /* Black */
258 REPEAT(line[x] = 0)
259 break;
260 default:
261 unimpl("bitmap opcode 0x%x\n", opcode);
262 return False;
263 }
264 }
265 }
266 return True;
267 }
268
269 /* 2 byte bitmap decompress */
270 static BOOL
271 bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
272 {
273 uint8 *end = input + size;
274 uint16 *prevline = NULL, *line = NULL;
275 int opcode, count, offset, isfillormix, x = width;
276 int lastopcode = -1, insertmix = False, bicolour = False;
277 uint8 code;
278 uint16 colour1 = 0, colour2 = 0;
279 uint8 mixmask, mask = 0;
280 uint16 mix = 0xffff;
281 int fom_mask = 0;
282
283 while (input < end)
284 {
285 fom_mask = 0;
286 code = CVAL(input);
287 opcode = code >> 4;
288 /* Handle different opcode forms */
289 switch (opcode)
290 {
291 case 0xc:
292 case 0xd:
293 case 0xe:
294 opcode -= 6;
295 count = code & 0xf;
296 offset = 16;
297 break;
298 case 0xf:
299 opcode = code & 0xf;
300 if (opcode < 9)
301 {
302 count = CVAL(input);
303 count |= CVAL(input) << 8;
304 }
305 else
306 {
307 count = (opcode < 0xb) ? 8 : 1;
308 }
309 offset = 0;
310 break;
311 default:
312 opcode >>= 1;
313 count = code & 0x1f;
314 offset = 32;
315 break;
316 }
317 /* Handle strange cases for counts */
318 if (offset != 0)
319 {
320 isfillormix = ((opcode == 2) || (opcode == 7));
321 if (count == 0)
322 {
323 if (isfillormix)
324 count = CVAL(input) + 1;
325 else
326 count = CVAL(input) + offset;
327 }
328 else if (isfillormix)
329 {
330 count <<= 3;
331 }
332 }
333 /* Read preliminary data */
334 switch (opcode)
335 {
336 case 0: /* Fill */
337 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
338 insertmix = True;
339 break;
340 case 8: /* Bicolour */
341 CVAL2(input, colour1);
342 case 3: /* Colour */
343 CVAL2(input, colour2);
344 break;
345 case 6: /* SetMix/Mix */
346 case 7: /* SetMix/FillOrMix */
347 CVAL2(input, mix);
348 opcode -= 5;
349 break;
350 case 9: /* FillOrMix_1 */
351 mask = 0x03;
352 opcode = 0x02;
353 fom_mask = 3;
354 break;
355 case 0x0a: /* FillOrMix_2 */
356 mask = 0x05;
357 opcode = 0x02;
358 fom_mask = 5;
359 break;
360 }
361 lastopcode = opcode;
362 mixmask = 0;
363 /* Output body */
364 while (count > 0)
365 {
366 if (x >= width)
367 {
368 if (height <= 0)
369 return False;
370 x = 0;
371 height--;
372 prevline = line;
373 line = ((uint16 *) output) + height * width;
374 }
375 switch (opcode)
376 {
377 case 0: /* Fill */
378 if (insertmix)
379 {
380 if (prevline == NULL)
381 line[x] = mix;
382 else
383 line[x] = prevline[x] ^ mix;
384 insertmix = False;
385 count--;
386 x++;
387 }
388 if (prevline == NULL)
389 {
390 REPEAT(line[x] = 0)
391 }
392 else
393 {
394 REPEAT(line[x] = prevline[x])
395 }
396 break;
397 case 1: /* Mix */
398 if (prevline == NULL)
399 {
400 REPEAT(line[x] = mix)
401 }
402 else
403 {
404 REPEAT(line[x] = prevline[x] ^ mix)
405 }
406 break;
407 case 2: /* Fill or Mix */
408 if (prevline == NULL)
409 {
410 REPEAT
411 (
412 MASK_UPDATE();
413 if (mask & mixmask)
414 line[x] = mix;
415 else
416 line[x] = 0;
417 )
418 }
419 else
420 {
421 REPEAT
422 (
423 MASK_UPDATE();
424 if (mask & mixmask)
425 line[x] = prevline[x] ^ mix;
426 else
427 line[x] = prevline[x];
428 )
429 }
430 break;
431 case 3: /* Colour */
432 REPEAT(line[x] = colour2)
433 break;
434 case 4: /* Copy */
435 REPEAT(CVAL2(input, line[x]))
436 break;
437 case 8: /* Bicolour */
438 REPEAT
439 (
440 if (bicolour)
441 {
442 line[x] = colour2;
443 bicolour = False;
444 }
445 else
446 {
447 line[x] = colour1;
448 bicolour = True;
449 count++;
450 }
451 )
452 break;
453 case 0xd: /* White */
454 REPEAT(line[x] = 0xffff)
455 break;
456 case 0xe: /* Black */
457 REPEAT(line[x] = 0)
458 break;
459 default:
460 unimpl("bitmap opcode 0x%x\n", opcode);
461 return False;
462 }
463 }
464 }
465 return True;
466 }
467
468 /* 3 byte bitmap decompress */
469 static BOOL
470 bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
471 {
472 uint8 *end = input + size;
473 uint8 *prevline = NULL, *line = NULL;
474 int opcode, count, offset, isfillormix, x = width;
475 int lastopcode = -1, insertmix = False, bicolour = False;
476 uint8 code;
477 uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
478 uint8 mixmask, mask = 0;
479 uint8 mix[3] = {0xff, 0xff, 0xff};
480 int fom_mask = 0;
481
482 while (input < end)
483 {
484 fom_mask = 0;
485 code = CVAL(input);
486 opcode = code >> 4;
487 /* Handle different opcode forms */
488 switch (opcode)
489 {
490 case 0xc:
491 case 0xd:
492 case 0xe:
493 opcode -= 6;
494 count = code & 0xf;
495 offset = 16;
496 break;
497 case 0xf:
498 opcode = code & 0xf;
499 if (opcode < 9)
500 {
501 count = CVAL(input);
502 count |= CVAL(input) << 8;
503 }
504 else
505 {
506 count = (opcode <
507 0xb) ? 8 : 1;
508 }
509 offset = 0;
510 break;
511 default:
512 opcode >>= 1;
513 count = code & 0x1f;
514 offset = 32;
515 break;
516 }
517 /* Handle strange cases for counts */
518 if (offset != 0)
519 {
520 isfillormix = ((opcode == 2) || (opcode == 7));
521 if (count == 0)
522 {
523 if (isfillormix)
524 count = CVAL(input) + 1;
525 else
526 count = CVAL(input) + offset;
527 }
528 else if (isfillormix)
529 {
530 count <<= 3;
531 }
532 }
533 /* Read preliminary data */
534 switch (opcode)
535 {
536 case 0: /* Fill */
537 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
538 insertmix = True;
539 break;
540 case 8: /* Bicolour */
541 colour1[0] = CVAL(input);
542 colour1[1] = CVAL(input);
543 colour1[2] = CVAL(input);
544 case 3: /* Colour */
545 colour2[0] = CVAL(input);
546 colour2[1] = CVAL(input);
547 colour2[2] = CVAL(input);
548 break;
549 case 6: /* SetMix/Mix */
550 case 7: /* SetMix/FillOrMix */
551 mix[0] = CVAL(input);
552 mix[1] = CVAL(input);
553 mix[2] = CVAL(input);
554 opcode -= 5;
555 break;
556 case 9: /* FillOrMix_1 */
557 mask = 0x03;
558 opcode = 0x02;
559 fom_mask = 3;
560 break;
561 case 0x0a: /* FillOrMix_2 */
562 mask = 0x05;
563 opcode = 0x02;
564 fom_mask = 5;
565 break;
566 }
567 lastopcode = opcode;
568 mixmask = 0;
569 /* Output body */
570 while (count > 0)
571 {
572 if (x >= width)
573 {
574 if (height <= 0)
575 return False;
576 x = 0;
577 height--;
578 prevline = line;
579 line = output + height * (width * 3);
580 }
581 switch (opcode)
582 {
583 case 0: /* Fill */
584 if (insertmix)
585 {
586 if (prevline == NULL)
587 {
588 line[x * 3] = mix[0];
589 line[x * 3 + 1] = mix[1];
590 line[x * 3 + 2] = mix[2];
591 }
592 else
593 {
594 line[x * 3] =
595 prevline[x * 3] ^ mix[0];
596 line[x * 3 + 1] =
597 prevline[x * 3 + 1] ^ mix[1];
598 line[x * 3 + 2] =
599 prevline[x * 3 + 2] ^ mix[2];
600 }
601 insertmix = False;
602 count--;
603 x++;
604 }
605 if (prevline == NULL)
606 {
607 REPEAT
608 (
609 line[x * 3] = 0;
610 line[x * 3 + 1] = 0;
611 line[x * 3 + 2] = 0;
612 )
613 }
614 else
615 {
616 REPEAT
617 (
618 line[x * 3] = prevline[x * 3];
619 line[x * 3 + 1] = prevline[x * 3 + 1];
620 line[x * 3 + 2] = prevline[x * 3 + 2];
621 )
622 }
623 break;
624 case 1: /* Mix */
625 if (prevline == NULL)
626 {
627 REPEAT
628 (
629 line[x * 3] = mix[0];
630 line[x * 3 + 1] = mix[1];
631 line[x * 3 + 2] = mix[2];
632 )
633 }
634 else
635 {
636 REPEAT
637 (
638 line[x * 3] =
639 prevline[x * 3] ^ mix[0];
640 line[x * 3 + 1] =
641 prevline[x * 3 + 1] ^ mix[1];
642 line[x * 3 + 2] =
643 prevline[x * 3 + 2] ^ mix[2];
644 )
645 }
646 break;
647 case 2: /* Fill or Mix */
648 if (prevline == NULL)
649 {
650 REPEAT
651 (
652 MASK_UPDATE();
653 if (mask & mixmask)
654 {
655 line[x * 3] = mix[0];
656 line[x * 3 + 1] = mix[1];
657 line[x * 3 + 2] = mix[2];
658 }
659 else
660 {
661 line[x * 3] = 0;
662 line[x * 3 + 1] = 0;
663 line[x * 3 + 2] = 0;
664 }
665 )
666 }
667 else
668 {
669 REPEAT
670 (
671 MASK_UPDATE();
672 if (mask & mixmask)
673 {
674 line[x * 3] =
675 prevline[x * 3] ^ mix [0];
676 line[x * 3 + 1] =
677 prevline[x * 3 + 1] ^ mix [1];
678 line[x * 3 + 2] =
679 prevline[x * 3 + 2] ^ mix [2];
680 }
681 else
682 {
683 line[x * 3] =
684 prevline[x * 3];
685 line[x * 3 + 1] =
686 prevline[x * 3 + 1];
687 line[x * 3 + 2] =
688 prevline[x * 3 + 2];
689 }
690 )
691 }
692 break;
693 case 3: /* Colour */
694 REPEAT
695 (
696 line[x * 3] = colour2 [0];
697 line[x * 3 + 1] = colour2 [1];
698 line[x * 3 + 2] = colour2 [2];
699 )
700 break;
701 case 4: /* Copy */
702 REPEAT
703 (
704 line[x * 3] = CVAL(input);
705 line[x * 3 + 1] = CVAL(input);
706 line[x * 3 + 2] = CVAL(input);
707 )
708 break;
709 case 8: /* Bicolour */
710 REPEAT
711 (
712 if (bicolour)
713 {
714 line[x * 3] = colour2[0];
715 line[x * 3 + 1] = colour2[1];
716 line[x * 3 + 2] = colour2[2];
717 bicolour = False;
718 }
719 else
720 {
721 line[x * 3] = colour1[0];
722 line[x * 3 + 1] = colour1[1];
723 line[x * 3 + 2] = colour1[2];
724 bicolour = True;
725 count++;
726 }
727 )
728 break;
729 case 0xd: /* White */
730 REPEAT
731 (
732 line[x * 3] = 0xff;
733 line[x * 3 + 1] = 0xff;
734 line[x * 3 + 2] = 0xff;
735 )
736 break;
737 case 0xe: /* Black */
738 REPEAT
739 (
740 line[x * 3] = 0;
741 line[x * 3 + 1] = 0;
742 line[x * 3 + 2] = 0;
743 )
744 break;
745 default:
746 unimpl("bitmap opcode 0x%x\n", opcode);
747 return False;
748 }
749 }
750 }
751 return True;
752 }
753
754 #else
755
756 static uint32
757 cvalx(uint8 **input, int Bpp)
758 {
759 uint32 rv = 0;
760 memcpy(&rv, *input, Bpp);
761 *input += Bpp;
762 return rv;
763 }
764
765 static void
766 setli(uint8 *input, int offset, uint32 value, int Bpp)
767 {
768 input += offset * Bpp;
769 memcpy(input, &value, Bpp);
770 }
771
772 static uint32
773 getli(uint8 *input, int offset, int Bpp)
774 {
775 uint32 rv = 0;
776 input += offset * Bpp;
777 memcpy(&rv, input, Bpp);
778 return rv;
779 }
780
781 static BOOL
782 bitmap_decompressx(uint8 *output, int width, int height, uint8 *input, int size, int Bpp)
783 {
784 uint8 *end = input + size;
785 uint8 *prevline = NULL, *line = NULL;
786 int opcode, count, offset, isfillormix, x = width;
787 int lastopcode = -1, insertmix = False, bicolour = False;
788 uint8 code;
789 uint32 colour1 = 0, colour2 = 0;
790 uint8 mixmask, mask = 0;
791 uint32 mix = 0xffffffff;
792 int fom_mask = 0;
793
794 while (input < end)
795 {
796 fom_mask = 0;
797 code = CVAL(input);
798 opcode = code >> 4;
799
800 /* Handle different opcode forms */
801 switch (opcode)
802 {
803 case 0xc:
804 case 0xd:
805 case 0xe:
806 opcode -= 6;
807 count = code & 0xf;
808 offset = 16;
809 break;
810
811 case 0xf:
812 opcode = code & 0xf;
813 if (opcode < 9)
814 {
815 count = CVAL(input);
816 count |= CVAL(input) << 8;
817 }
818 else
819 {
820 count = (opcode < 0xb) ? 8 : 1;
821 }
822 offset = 0;
823 break;
824
825 default:
826 opcode >>= 1;
827 count = code & 0x1f;
828 offset = 32;
829 break;
830 }
831
832 /* Handle strange cases for counts */
833 if (offset != 0)
834 {
835 isfillormix = ((opcode == 2) || (opcode == 7));
836
837 if (count == 0)
838 {
839 if (isfillormix)
840 count = CVAL(input) + 1;
841 else
842 count = CVAL(input) + offset;
843 }
844 else if (isfillormix)
845 {
846 count <<= 3;
847 }
848 }
849
850 /* Read preliminary data */
851 switch (opcode)
852 {
853 case 0: /* Fill */
854 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
855 insertmix = True;
856 break;
857 case 8: /* Bicolour */
858 colour1 = cvalx(&input, Bpp);
859 case 3: /* Colour */
860 colour2 = cvalx(&input, Bpp);
861 break;
862 case 6: /* SetMix/Mix */
863 case 7: /* SetMix/FillOrMix */
864 mix = cvalx(&input, Bpp);
865 opcode -= 5;
866 break;
867 case 9: /* FillOrMix_1 */
868 mask = 0x03;
869 opcode = 0x02;
870 fom_mask = 3;
871 break;
872 case 0x0a: /* FillOrMix_2 */
873 mask = 0x05;
874 opcode = 0x02;
875 fom_mask = 5;
876 break;
877
878 }
879
880 lastopcode = opcode;
881 mixmask = 0;
882
883 /* Output body */
884 while (count > 0)
885 {
886 if (x >= width)
887 {
888 if (height <= 0)
889 return False;
890
891 x = 0;
892 height--;
893
894 prevline = line;
895 line = output + height * width * Bpp;
896 }
897
898 switch (opcode)
899 {
900 case 0: /* Fill */
901 if (insertmix)
902 {
903 if (prevline == NULL)
904 setli(line, x, mix, Bpp);
905 else
906 setli(line, x,
907 getli(prevline, x, Bpp) ^ mix, Bpp);
908
909 insertmix = False;
910 count--;
911 x++;
912 }
913
914 if (prevline == NULL)
915 {
916 REPEAT(setli(line, x, 0, Bpp))}
917 else
918 {
919 REPEAT(setli
920 (line, x, getli(prevline, x, Bpp), Bpp));
921 }
922 break;
923
924 case 1: /* Mix */
925 if (prevline == NULL)
926 {
927 REPEAT(setli(line, x, mix, Bpp));
928 }
929 else
930 {
931 REPEAT(setli
932 (line, x, getli(prevline, x, Bpp) ^ mix,
933 Bpp));
934 }
935 break;
936
937 case 2: /* Fill or Mix */
938 if (prevline == NULL)
939 {
940 REPEAT(MASK_UPDATE();
941 if (mask & mixmask) setli(line, x, mix, Bpp);
942 else
943 setli(line, x, 0, Bpp););
944 }
945 else
946 {
947 REPEAT(MASK_UPDATE();
948 if (mask & mixmask)
949 setli(line, x, getli(prevline, x, Bpp) ^ mix,
950 Bpp);
951 else
952 setli(line, x, getli(prevline, x, Bpp),
953 Bpp););
954 }
955 break;
956
957 case 3: /* Colour */
958 REPEAT(setli(line, x, colour2, Bpp));
959 break;
960
961 case 4: /* Copy */
962 REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp));
963 break;
964
965 case 8: /* Bicolour */
966 REPEAT(if (bicolour)
967 {
968 setli(line, x, colour2, Bpp); bicolour = False;}
969 else
970 {
971 setli(line, x, colour1, Bpp); bicolour = True;
972 count++;}
973 );
974 break;
975
976 case 0xd: /* White */
977 REPEAT(setli(line, x, 0xffffffff, Bpp));
978 break;
979
980 case 0xe: /* Black */
981 REPEAT(setli(line, x, 0, Bpp));
982 break;
983
984 default:
985 unimpl("bitmap opcode 0x%x\n", opcode);
986 return False;
987 }
988 }
989 }
990
991 return True;
992 }
993
994 #endif
995
996 /* main decompress function */
997 BOOL
998 bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
999 {
1000 #ifdef BITMAP_SPEED_OVER_SIZE
1001 BOOL rv = False;
1002 switch (Bpp)
1003 {
1004 case 1:
1005 rv = bitmap_decompress1(output, width, height, input, size);
1006 break;
1007 case 2:
1008 rv = bitmap_decompress2(output, width, height, input, size);
1009 break;
1010 case 3:
1011 rv = bitmap_decompress3(output, width, height, input, size);
1012 break;
1013 }
1014 #else
1015 BOOL rv;
1016 rv = bitmap_decompressx(output, width, height, input, size, Bpp);
1017 #endif
1018 return rv;
1019 }
1020
1021 /* *INDENT-ON* */