/[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 655 by stargo, Fri Apr 16 09:11:03 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                                    memcpy(&colour1,&CVAL2(input),2);
334                            case 3: /* Colour */
335                                    memcpy(&colour2,&CVAL2(input),2);
336                                    break;
337                            case 6: /* SetMix/Mix */
338                            case 7: /* SetMix/FillOrMix */
339                                    memcpy(&mix,&CVAL2(input),2);
340                                    opcode -= 5;
341                                    break;
342                            case 9: /* FillOrMix_1 */
343                                    mask = 0x03;
344                                    opcode = 0x02;
345                                    fom_mask = 3;
346                                    break;
347                            case 0x0a:      /* FillOrMix_2 */
348                                    mask = 0x05;
349                                    opcode = 0x02;
350                                    fom_mask = 5;
351                                    break;
352                    }
353                    lastopcode = opcode;
354                    mixmask = 0;
355                    /* Output body */
356                    while (count > 0)
357                    {
358                            if (x >= width)
359                            {
360                                    if (height <= 0)
361                                            return False;
362                                    x = 0;
363                                    height--;
364                                    prevline = line;
365                                    line = ((uint16 *) output) + height * width;
366                            }
367                            switch (opcode)
368                            {
369                                    case 0: /* Fill */
370                                            if (insertmix)
371                                            {
372                                                    if (prevline == NULL)
373                                                            line[x] = mix;
374                                                    else
375                                                            line[x] = prevline[x] ^ mix;
376                                                    insertmix = False;
377                                                    count--;
378                                                    x++;
379                                            }
380                                            if (prevline == NULL)
381                                            {
382                                                    REPEAT(line[x] = 0)
383                                            }
384                                            else
385                                            {
386                                                    REPEAT(line[x] = prevline[x])
387                                            }
388                                            break;
389                                    case 1: /* Mix */
390                                            if (prevline == NULL)
391                                            {
392                                                    REPEAT(line[x] = mix)
393                                            }
394                                            else
395                                            {
396                                                    REPEAT(line[x] = prevline[x] ^ mix)
397                                            }
398                                            break;
399                                    case 2: /* Fill or Mix */
400                                            if (prevline == NULL)
401                                            {
402                                                    REPEAT
403                                                    (
404                                                            MASK_UPDATE();
405                                                            if (mask & mixmask)
406                                                                    line[x] = mix;
407                                                            else
408                                                                    line[x] = 0;
409                                                    )
410                                            }
411                                            else
412                                            {
413                                                    REPEAT
414                                                    (
415                                                            MASK_UPDATE();
416                                                            if (mask & mixmask)
417                                                                    line[x] = prevline[x] ^ mix;
418                                                            else
419                                                                    line[x] = prevline[x];
420                                                    )
421                                            }
422                                            break;
423                                    case 3: /* Colour */
424                                            REPEAT(line[x] = colour2)
425                                            break;
426                                    case 4: /* Copy */
427                                            REPEAT(memcpy(&line[x],&CVAL2(input),2))
428                                            break;
429                                    case 8: /* Bicolour */
430                                            REPEAT
431                                            (
432                                                  if (bicolour)                                                  if (bicolour)
433                                                  {                                                  {
434                                                          line[x] = colour2;                                                          line[x] = colour2;
# Line 192  BOOL bitmap_decompress(unsigned char *ou Line 442  BOOL bitmap_decompress(unsigned char *ou
442                                                  }                                                  }
443                                          )                                          )
444                                          break;                                          break;
445                                    case 0xd:       /* White */
446                                            REPEAT(line[x] = 0xffff)
447                                            break;
448                                    case 0xe:       /* Black */
449                                            REPEAT(line[x] = 0)
450                                            break;
451                                    default:
452                                            unimpl("bitmap opcode 0x%x\n", opcode);
453                                            return False;
454                            }
455                    }
456            }
457            return True;
458    }
459    
460                                  case 13: /* White */  /* 3 byte bitmap decompress */
461                                          REPEAT(line[x] = 0xff)  static BOOL
462    bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
463    {
464            uint8 *end = input + size;
465            uint8 *prevline = NULL, *line = NULL;
466            int opcode, count, offset, isfillormix, x = width;
467            int lastopcode = -1, insertmix = False, bicolour = False;
468            uint8 code;
469            uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
470            uint8 mixmask, mask = 0;
471            uint8 mix[3] = {0xff, 0xff, 0xff};
472            int fom_mask = 0;
473    
474            while (input < end)
475            {
476                    fom_mask = 0;
477                    code = CVAL(input);
478                    opcode = code >> 4;
479                    /* Handle different opcode forms */
480                    switch (opcode)
481                    {
482                            case 0xc:
483                            case 0xd:
484                            case 0xe:
485                                    opcode -= 6;
486                                    count = code & 0xf;
487                                    offset = 16;
488                                    break;
489                            case 0xf:
490                                    opcode = code & 0xf;
491                                    if (opcode < 9)
492                                    {
493                                            count = CVAL(input);
494                                            count |= CVAL(input) << 8;
495                                    }
496                                    else
497                                    {
498                                            count = (opcode <
499                                                     0xb) ? 8 : 1;
500                                    }
501                                    offset = 0;
502                                    break;
503                            default:
504                                    opcode >>= 1;
505                                    count = code & 0x1f;
506                                    offset = 32;
507                                    break;
508                    }
509                    /* Handle strange cases for counts */
510                    if (offset != 0)
511                    {
512                            isfillormix = ((opcode == 2) || (opcode == 7));
513                            if (count == 0)
514                            {
515                                    if (isfillormix)
516                                            count = CVAL(input) + 1;
517                                    else
518                                            count = CVAL(input) + offset;
519                            }
520                            else if (isfillormix)
521                            {
522                                    count <<= 3;
523                            }
524                    }
525                    /* Read preliminary data */
526                    switch (opcode)
527                    {
528                            case 0: /* Fill */
529                                    if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
530                                            insertmix = True;
531                                    break;
532                            case 8: /* Bicolour */
533                                    colour1[0] = CVAL(input);
534                                    colour1[1] = CVAL(input);
535                                    colour1[2] = CVAL(input);
536                            case 3: /* Colour */
537                                    colour2[0] = CVAL(input);
538                                    colour2[1] = CVAL(input);
539                                    colour2[2] = CVAL(input);
540                                    break;
541                            case 6: /* SetMix/Mix */
542                            case 7: /* SetMix/FillOrMix */
543                                    mix[0] = CVAL(input);
544                                    mix[1] = CVAL(input);
545                                    mix[2] = CVAL(input);
546                                    opcode -= 5;
547                                    break;
548                            case 9: /* FillOrMix_1 */
549                                    mask = 0x03;
550                                    opcode = 0x02;
551                                    fom_mask = 3;
552                                    break;
553                            case 0x0a:      /* FillOrMix_2 */
554                                    mask = 0x05;
555                                    opcode = 0x02;
556                                    fom_mask = 5;
557                                    break;
558                    }
559                    lastopcode = opcode;
560                    mixmask = 0;
561                    /* Output body */
562                    while (count > 0)
563                    {
564                            if (x >= width)
565                            {
566                                    if (height <= 0)
567                                            return False;
568                                    x = 0;
569                                    height--;
570                                    prevline = line;
571                                    line = output + height * (width * 3);
572                            }
573                            switch (opcode)
574                            {
575                                    case 0: /* Fill */
576                                            if (insertmix)
577                                            {
578                                                    if (prevline == NULL)
579                                                    {
580                                                            line[x * 3] = mix[0];
581                                                            line[x * 3 + 1] = mix[1];
582                                                            line[x * 3 + 2] = mix[2];
583                                                    }
584                                                    else
585                                                    {
586                                                            line[x * 3] =
587                                                             prevline[x * 3] ^ mix[0];
588                                                            line[x * 3 + 1] =
589                                                             prevline[x * 3 + 1] ^ mix[1];
590                                                            line[x * 3 + 2] =
591                                                             prevline[x * 3 + 2] ^ mix[2];
592                                                    }
593                                                    insertmix = False;
594                                                    count--;
595                                                    x++;
596                                            }
597                                            if (prevline == NULL)
598                                            {
599                                                    REPEAT
600                                                    (
601                                                            line[x * 3] = 0;
602                                                            line[x * 3 + 1] = 0;
603                                                            line[x * 3 + 2] = 0;
604                                                    )
605                                            }
606                                            else
607                                            {
608                                                    REPEAT
609                                                    (
610                                                            line[x * 3] = prevline[x * 3];
611                                                            line[x * 3 + 1] = prevline[x * 3 + 1];
612                                                            line[x * 3 + 2] = prevline[x * 3 + 2];
613                                                    )
614                                            }
615                                            break;
616                                    case 1: /* Mix */
617                                            if (prevline == NULL)
618                                            {
619                                                    REPEAT
620                                                    (
621                                                            line[x * 3] = mix[0];
622                                                            line[x * 3 + 1] = mix[1];
623                                                            line[x * 3 + 2] = mix[2];
624                                                    )
625                                            }
626                                            else
627                                            {
628                                                    REPEAT
629                                                    (
630                                                            line[x * 3] =
631                                                             prevline[x * 3] ^ mix[0];
632                                                            line[x * 3 + 1] =
633                                                             prevline[x * 3 + 1] ^ mix[1];
634                                                            line[x * 3 + 2] =
635                                                             prevline[x * 3 + 2] ^ mix[2];
636                                                    )
637                                            }
638                                          break;                                          break;
639                                    case 2: /* Fill or Mix */
640                                            if (prevline == NULL)
641                                            {
642                                                    REPEAT
643                                                    (
644                                                            MASK_UPDATE();
645                                                            if (mask & mixmask)
646                                                            {
647                                                                    line[x * 3] = mix[0];
648                                                                    line[x * 3 + 1] = mix[1];
649                                                                    line[x * 3 + 2] = mix[2];
650                                                            }
651                                                            else
652                                                            {
653                                                                    line[x * 3] = 0;
654                                                                    line[x * 3 + 1] = 0;
655                                                                    line[x * 3 + 2] = 0;
656                                                            }
657                                                    )
658                                            }
659                                            else
660                                            {
661                                                    REPEAT
662                                                    (
663                                                            MASK_UPDATE();
664                                                            if (mask & mixmask)
665                                                            {
666                                                                    line[x * 3] =
667                                                                     prevline[x * 3] ^ mix [0];
668                                                                    line[x * 3 + 1] =
669                                                                     prevline[x * 3 + 1] ^ mix [1];
670                                                                    line[x * 3 + 2] =
671                                                                     prevline[x * 3 + 2] ^ mix [2];
672                                                            }
673                                                            else
674                                                            {
675                                                                    line[x * 3] =
676                                                                     prevline[x * 3];
677                                                                    line[x * 3 + 1] =
678                                                                     prevline[x * 3 + 1];
679                                                                    line[x * 3 + 2] =
680                                                                     prevline[x * 3 + 2];
681                                                            }
682                                                    )
683                                            }
684                                            break;
685                                    case 3: /* Colour */
686                                            REPEAT
687                                            (
688                                                    line[x * 3] = colour2 [0];
689                                                    line[x * 3 + 1] = colour2 [1];
690                                                    line[x * 3 + 2] = colour2 [2];
691                                            )
692                                            break;
693                                    case 4: /* Copy */
694                                            REPEAT
695                                            (
696                                                    line[x * 3] = CVAL(input);
697                                                    line[x * 3 + 1] = CVAL(input);
698                                                    line[x * 3 + 2] = CVAL(input);
699                                            )
700                                            break;
701                                    case 8: /* Bicolour */
702                                            REPEAT
703                                            (
704                                                    if (bicolour)
705                                                    {
706                                                            line[x * 3] = colour2[0];
707                                                            line[x * 3 + 1] = colour2[1];
708                                                            line[x * 3 + 2] = colour2[2];
709                                                            bicolour = False;
710                                                    }
711                                                    else
712                                                    {
713                                                            line[x * 3] = colour1[0];
714                                                            line[x * 3 + 1] = colour1[1];
715                                                            line[x * 3 + 2] = colour1[2];
716                                                            bicolour = True;
717                                                            count++;
718                                                    }
719                                            )
720                                            break;
721                                    case 0xd:       /* White */
722                                            REPEAT
723                                            (
724                                                    line[x * 3] = 0xff;
725                                                    line[x * 3 + 1] = 0xff;
726                                                    line[x * 3 + 2] = 0xff;
727                                            )
728                                            break;
729                                    case 0xe:       /* Black */
730                                            REPEAT
731                                            (
732                                                    line[x * 3] = 0;
733                                                    line[x * 3 + 1] = 0;
734                                                    line[x * 3 + 2] = 0;
735                                            )
736                                            break;
737                                    default:
738                                            unimpl("bitmap opcode 0x%x\n", opcode);
739                                            return False;
740                            }
741                    }
742            }
743            return True;
744    }
745    
746    #else
747    
748    static uint32
749    cvalx(uint8 **input, int Bpp)
750    {
751            uint32 rv = 0;
752            memcpy(&rv, *input, Bpp);
753            *input += Bpp;
754            return rv;
755    }
756    
757    static void
758    setli(uint8 *input, int offset, uint32 value, int Bpp)
759    {
760            input += offset * Bpp;
761            memcpy(input, &value, Bpp);
762    }
763    
764    static uint32
765    getli(uint8 *input, int offset, int Bpp)
766    {
767            uint32 rv = 0;
768            input += offset * Bpp;
769            memcpy(&rv, input, Bpp);
770            return rv;
771    }
772    
773    static BOOL
774    bitmap_decompressx(uint8 *output, int width, int height, uint8 *input, int size, int Bpp)
775    {
776            uint8 *end = input + size;
777            uint8 *prevline = NULL, *line = NULL;
778            int opcode, count, offset, isfillormix, x = width;
779            int lastopcode = -1, insertmix = False, bicolour = False;
780            uint8 code;
781            uint32 colour1 = 0, colour2 = 0;
782            uint8 mixmask, mask = 0;
783            uint32 mix = 0xffffffff;
784            int fom_mask = 0;
785    
786                                  case 14: /* Black */          while (input < end)
787                                          REPEAT(line[x] = 0x00)          {
788                    fom_mask = 0;
789                    code = CVAL(input);
790                    opcode = code >> 4;
791    
792                    /* Handle different opcode forms */
793                    switch (opcode)
794                    {
795                            case 0xc:
796                            case 0xd:
797                            case 0xe:
798                                    opcode -= 6;
799                                    count = code & 0xf;
800                                    offset = 16;
801                                    break;
802    
803                            case 0xf:
804                                    opcode = code & 0xf;
805                                    if (opcode < 9)
806                                    {
807                                            count = CVAL(input);
808                                            count |= CVAL(input) << 8;
809                                    }
810                                    else
811                                    {
812                                            count = (opcode < 0xb) ? 8 : 1;
813                                    }
814                                    offset = 0;
815                                    break;
816    
817                            default:
818                                    opcode >>= 1;
819                                    count = code & 0x1f;
820                                    offset = 32;
821                                    break;
822                    }
823    
824                    /* Handle strange cases for counts */
825                    if (offset != 0)
826                    {
827                            isfillormix = ((opcode == 2) || (opcode == 7));
828    
829                            if (count == 0)
830                            {
831                                    if (isfillormix)
832                                            count = CVAL(input) + 1;
833                                    else
834                                            count = CVAL(input) + offset;
835                            }
836                            else if (isfillormix)
837                            {
838                                    count <<= 3;
839                            }
840                    }
841    
842                    /* Read preliminary data */
843                    switch (opcode)
844                    {
845                            case 0: /* Fill */
846                                    if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
847                                            insertmix = True;
848                                    break;
849                            case 8: /* Bicolour */
850                                    colour1 = cvalx(&input, Bpp);
851                            case 3: /* Colour */
852                                    colour2 = cvalx(&input, Bpp);
853                                    break;
854                            case 6: /* SetMix/Mix */
855                            case 7: /* SetMix/FillOrMix */
856                                    mix = cvalx(&input, Bpp);
857                                    opcode -= 5;
858                                    break;
859                            case 9: /* FillOrMix_1 */
860                                    mask = 0x03;
861                                    opcode = 0x02;
862                                    fom_mask = 3;
863                                    break;
864                            case 0x0a:      /* FillOrMix_2 */
865                                    mask = 0x05;
866                                    opcode = 0x02;
867                                    fom_mask = 5;
868                                    break;
869    
870                    }
871    
872                    lastopcode = opcode;
873                    mixmask = 0;
874    
875                    /* Output body */
876                    while (count > 0)
877                    {
878                            if (x >= width)
879                            {
880                                    if (height <= 0)
881                                            return False;
882    
883                                    x = 0;
884                                    height--;
885    
886                                    prevline = line;
887                                    line = output + height * width * Bpp;
888                            }
889    
890                            switch (opcode)
891                            {
892                                    case 0: /* Fill */
893                                            if (insertmix)
894                                            {
895                                                    if (prevline == NULL)
896                                                            setli(line, x, mix, Bpp);
897                                                    else
898                                                            setli(line, x,
899                                                                  getli(prevline, x, Bpp) ^ mix, Bpp);
900    
901                                                    insertmix = False;
902                                                    count--;
903                                                    x++;
904                                            }
905    
906                                            if (prevline == NULL)
907                                            {
908                                            REPEAT(setli(line, x, 0, Bpp))}
909                                            else
910                                            {
911                                                    REPEAT(setli
912                                                           (line, x, getli(prevline, x, Bpp), Bpp));
913                                            }
914                                            break;
915    
916                                    case 1: /* Mix */
917                                            if (prevline == NULL)
918                                            {
919                                                    REPEAT(setli(line, x, mix, Bpp));
920                                            }
921                                            else
922                                            {
923                                                    REPEAT(setli
924                                                           (line, x, getli(prevline, x, Bpp) ^ mix,
925                                                            Bpp));
926                                            }
927                                            break;
928    
929                                    case 2: /* Fill or Mix */
930                                            if (prevline == NULL)
931                                            {
932                                                    REPEAT(MASK_UPDATE();
933                                                           if (mask & mixmask) setli(line, x, mix, Bpp);
934                                                           else
935                                                           setli(line, x, 0, Bpp););
936                                            }
937                                            else
938                                            {
939                                                    REPEAT(MASK_UPDATE();
940                                                           if (mask & mixmask)
941                                                           setli(line, x, getli(prevline, x, Bpp) ^ mix,
942                                                                 Bpp);
943                                                           else
944                                                           setli(line, x, getli(prevline, x, Bpp),
945                                                                 Bpp););
946                                            }
947                                            break;
948    
949                                    case 3: /* Colour */
950                                            REPEAT(setli(line, x, colour2, Bpp));
951                                            break;
952    
953                                    case 4: /* Copy */
954                                            REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp));
955                                            break;
956    
957                                    case 8: /* Bicolour */
958                                            REPEAT(if (bicolour)
959                                                   {
960                                                   setli(line, x, colour2, Bpp); bicolour = False;}
961                                                   else
962                                                   {
963                                                   setli(line, x, colour1, Bpp); bicolour = True;
964                                                   count++;}
965                                            );
966                                            break;
967    
968                                    case 0xd:       /* White */
969                                            REPEAT(setli(line, x, 0xffffffff, Bpp));
970                                            break;
971    
972                                    case 0xe:       /* Black */
973                                            REPEAT(setli(line, x, 0, Bpp));
974                                          break;                                          break;
975    
976                                  default:                                  default:
977                                          NOTIMP("bitmap opcode 0x%x\n", opcode);                                          unimpl("bitmap opcode 0x%x\n", opcode);
978                                          return False;                                          return False;
979                          }                          }
980                  }                  }
# Line 210  BOOL bitmap_decompress(unsigned char *ou Line 982  BOOL bitmap_decompress(unsigned char *ou
982    
983          return True;          return True;
984  }  }
985    
986    #endif
987    
988    /* main decompress function */
989    BOOL
990    bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
991    {
992    #ifdef BITMAP_SPEED_OVER_SIZE
993            BOOL rv = False;
994            switch (Bpp)
995            {
996                    case 1:
997                            rv = bitmap_decompress1(output, width, height, input, size);
998                            break;
999                    case 2:
1000                            rv = bitmap_decompress2(output, width, height, input, size);
1001                            break;
1002                    case 3:
1003                            rv = bitmap_decompress3(output, width, height, input, size);
1004                            break;
1005            }
1006    #else
1007            BOOL rv;
1008      rv = bitmap_decompressx(output, width, height, input, size, Bpp);
1009    #endif
1010            return rv;
1011    }
1012    
1013    /* *INDENT-ON* */

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

  ViewVC Help
Powered by ViewVC 1.1.26