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

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

  ViewVC Help
Powered by ViewVC 1.1.26