/[rdesktop]/sourceforge.net/trunk/rdesktop/bitmap.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/bitmap.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 19 by matty, Sun Oct 8 01:59:25 2000 UTC revision 693 by stargo, Fri May 7 04:57:39 2004 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Bitmap decompression routines     Bitmap decompression routines
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2002
5      
6     This program is free software; you can redistribute it and/or modify     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     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     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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    #define BITMAP_SPEED_OVER_SIZE
27    
28    /* indent is confused by this file */
29    /* *INDENT-OFF* */
30    
31  #include "rdesktop.h"  #include "rdesktop.h"
32    
33  #define CVAL(p)   (*(p++))  #define CVAL(p)   (*(p++))
34  #define SVAL(p)   ((*((p++) + 1) << 8) | CVAL(p))  #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)++));
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 REPEAT(statement) { while ((count > 0) && (x < width)) { statement; count--; x++; } }  #define MASK_UPDATE() \
60  #define MASK_UPDATE() { mixmask <<= 1; if (mixmask == 0) { mask = CVAL(input); mixmask = 1; } }  { \
61            mixmask <<= 1; \
62            if (mixmask == 0) \
63            { \
64                    mask = fom_mask ? fom_mask : CVAL(input); \
65                    mixmask = 1; \
66            } \
67    }
68    
69  BOOL bitmap_decompress(unsigned char *output, int width, int height,  #ifdef BITMAP_SPEED_OVER_SIZE
70                         unsigned char *input, int size)  
71    /* 1 byte bitmap decompress */
72    static BOOL
73    bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
74  {  {
75          unsigned char *end = input + size;          uint8 *end = input + size;
76          unsigned char *prevline = NULL, *line = NULL;          uint8 *prevline = NULL, *line = NULL;
77          int opcode, count, offset, isfillormix, x = width;          int opcode, count, offset, isfillormix, x = width;
78          int lastopcode = -1, insertmix = False, bicolour = False;          int lastopcode = -1, insertmix = False, bicolour = False;
79          uint8 code, colour1 = 0, colour2 = 0;          uint8 code;
80          uint8 mixmask, mask = 0, mix = 0xff;          uint8 colour1 = 0, colour2 = 0;
81            uint8 mixmask, mask = 0;
82            uint8 mix = 0xff;
83            int fom_mask = 0;
84    
85          while (input < end)          while (input < end)
86          {          {
87                    fom_mask = 0;
88                  code = CVAL(input);                  code = CVAL(input);
89                  opcode = code >> 4;                  opcode = code >> 4;
   
90                  /* Handle different opcode forms */                  /* Handle different opcode forms */
91                  switch (opcode)                  switch (opcode)
92                  {                  {
# Line 51  BOOL bitmap_decompress(unsigned char *ou Line 97  BOOL bitmap_decompress(unsigned char *ou
97                                  count = code & 0xf;                                  count = code & 0xf;
98                                  offset = 16;                                  offset = 16;
99                                  break;                                  break;
   
100                          case 0xf:                          case 0xf:
101                                  opcode = code & 0xf;                                  opcode = code & 0xf;
102                                  count = (opcode < 13) ? SVAL(input) : 1;                                  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;                                  offset = 0;
112                                  break;                                  break;
   
113                          default:                          default:
114                                  opcode >>= 1;                                  opcode >>= 1;
115                                  count = code & 0x1f;                                  count = code & 0x1f;
116                                  offset = 32;                                  offset = 32;
117                                  break;                                  break;
118                  }                  }
   
119                  /* Handle strange cases for counts */                  /* Handle strange cases for counts */
120                  if (offset != 0)                  if (offset != 0)
121                  {                  {
122                          isfillormix = ((opcode == 2) || (opcode == 7));                          isfillormix = ((opcode == 2) || (opcode == 7));
   
123                          if (count == 0)                          if (count == 0)
124                          {                          {
125                                  if (isfillormix)                                  if (isfillormix)
# Line 82  BOOL bitmap_decompress(unsigned char *ou Line 132  BOOL bitmap_decompress(unsigned char *ou
132                                  count <<= 3;                                  count <<= 3;
133                          }                          }
134                  }                  }
   
135                  /* Read preliminary data */                  /* Read preliminary data */
                 mixmask = 0;  
136                  switch (opcode)                  switch (opcode)
137                  {                  {
138                          case 0: /* Fill */                          case 0: /* Fill */
139                                  if ((lastopcode == opcode)                                  if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
                                     && !((x == width) && (prevline == NULL)))  
140                                          insertmix = True;                                          insertmix = True;
141                                  break;                                  break;
142                          case 8: /* Bicolour */                          case 8: /* Bicolour */
143                                  colour1 = CVAL(input);                                  colour1 = CVAL(input);
144                          case 3: /* Colour */                          case 3: /* Colour */
145                                  colour2 = CVAL(input);                                  colour2 = CVAL(input);
146                                  break;                                  break;
147                          case 6: /* SetMix/Mix */                          case 6: /* SetMix/Mix */
148                          case 7: /* SetMix/FillOrMix */                          case 7: /* SetMix/FillOrMix */
149                                  mix = CVAL(input);                                  mix = CVAL(input);
150                                  opcode -= 5;                                  opcode -= 5;
151                                  break;                                  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;                  lastopcode = opcode;
164                    mixmask = 0;
165                  /* Output body */                  /* Output body */
166                  while (count > 0)                  while (count > 0)
167                  {                  {
# Line 112  BOOL bitmap_decompress(unsigned char *ou Line 169  BOOL bitmap_decompress(unsigned char *ou
169                          {                          {
170                                  if (height <= 0)                                  if (height <= 0)
171                                          return False;                                          return False;
   
172                                  x = 0;                                  x = 0;
173                                  height--;                                  height--;
   
174                                  prevline = line;                                  prevline = line;
175                                  line = output + height * width;                                  line = output + height * width;
176                          }                          }
   
177                          switch (opcode)                          switch (opcode)
178                          {                          {
179                                  case 0: /* Fill */                                  case 0: /* Fill */
180                                          if (insertmix)                                          if (insertmix)
181                                          {                                          {
182                                                  if (prevline == NULL)                                                  if (prevline == NULL)
183                                                          line[x] = mix;                                                          line[x] = mix;
184                                                  else                                                  else
185                                                          line[x] = prevline[x] ^ mix;                                                          line[x] = prevline[x] ^ mix;
   
186                                                  insertmix = False;                                                  insertmix = False;
187                                                  count--;                                                  count--;
188                                                  x++;                                                  x++;
189                                          }                                          }
   
190                                          if (prevline == NULL)                                          if (prevline == NULL)
191                                            {
192                                                  REPEAT(line[x] = 0)                                                  REPEAT(line[x] = 0)
193                                            }
194                                          else                                          else
195                                            {
196                                                  REPEAT(line[x] = prevline[x])                                                  REPEAT(line[x] = prevline[x])
197                                            }
198                                          break;                                          break;
199                                    case 1: /* Mix */
                                 case 1: /* Mix */  
200                                          if (prevline == NULL)                                          if (prevline == NULL)
201                                            {
202                                                  REPEAT(line[x] = mix)                                                  REPEAT(line[x] = mix)
203                                            }
204                                          else                                          else
205                                            {
206                                                  REPEAT(line[x] = prevline[x] ^ mix)                                                  REPEAT(line[x] = prevline[x] ^ mix)
207                                            }
208                                          break;                                          break;
209                                    case 2: /* Fill or Mix */
                                 case 2: /* Fill or Mix */  
210                                          if (prevline == NULL)                                          if (prevline == NULL)
211                                              REPEAT(                                          {
212                                                     MASK_UPDATE();                                                  REPEAT
213                                                    (
214                                                     if (mask & mixmask)                                                          MASK_UPDATE();
215                                                          line[x] = mix;                                                          if (mask & mixmask)
216                                                     else                                                                  line[x] = mix;
217                                                          line[x] = 0;                                                          else
218                                              )                                                                  line[x] = 0;
219                                                    )
220                                            }
221                                          else                                          else
222                                              REPEAT(                                          {
223                                                     MASK_UPDATE();                                                  REPEAT
224                                                    (
225                                                     if (mask & mixmask)                                                          MASK_UPDATE();
226                                                          line[x] = prevline[x] ^ mix;                                                          if (mask & mixmask)
227                                                     else                                                                  line[x] = prevline[x] ^ mix;
228                                                          line[x] = prevline[x];                                                          else
229                                              )                                                                  line[x] = prevline[x];
230                                                    )
231                                            }
232                                          break;                                          break;
233                                    case 3: /* Colour */
                                 case 3: /* Colour */  
234                                          REPEAT(line[x] = colour2)                                          REPEAT(line[x] = colour2)
235                                          break;                                          break;
236                                    case 4: /* Copy */
                                 case 4: /* Copy */  
237                                          REPEAT(line[x] = CVAL(input))                                          REPEAT(line[x] = CVAL(input))
238                                          break;                                          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                                  case 8: /* Bicolour */  /* 2 byte bitmap decompress */
270                                          REPEAT(  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)                                                  if (bicolour)
441                                                  {                                                  {
442                                                          line[x] = colour2;                                                          line[x] = colour2;
# Line 192  BOOL bitmap_decompress(unsigned char *ou Line 450  BOOL bitmap_decompress(unsigned char *ou
450                                                  }                                                  }
451                                          )                                          )
452                                          break;                                          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                                  case 13: /* White */  /* 3 byte bitmap decompress */
469                                          REPEAT(line[x] = 0xff)  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;                                          break;
923    
924                                  case 14: /* Black */                                  case 1: /* Mix */
925                                          REPEAT(line[x] = 0x00)                                          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;                                          break;
983    
984                                  default:                                  default:
985                                          NOTIMP("bitmap opcode 0x%x\n", opcode);                                          unimpl("bitmap opcode 0x%x\n", opcode);
986                                          return False;                                          return False;
987                          }                          }
988                  }                  }
# Line 210  BOOL bitmap_decompress(unsigned char *ou Line 990  BOOL bitmap_decompress(unsigned char *ou
990    
991          return True;          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* */

Legend:
Removed from v.19  
changed lines
  Added in v.693

  ViewVC Help
Powered by ViewVC 1.1.26