added 15+ bpp decompression, rename, reorganize bitmap file
authorJay Sorg <jay.sorg@gmail.com>
Sat, 9 Jul 2011 19:48:18 +0000 (12:48 -0700)
committerJay Sorg <jay.sorg@gmail.com>
Sat, 9 Jul 2011 19:48:18 +0000 (12:48 -0700)
libfreerdp-core/CMakeLists.txt
libfreerdp-core/bitmap.c [new file with mode: 0644]
libfreerdp-core/bitmap_inc.c [new file with mode: 0644]
libfreerdp-core/rle_bitmap_stream.c [deleted file]

index 9591ab9..6026882 100644 (file)
@@ -47,6 +47,7 @@ set(LIBFREERDP_CORE_SRCS
        tpkt.h
        transport.c
        transport.h
+       rle_bitmap_stream.c
 )
 
 include_directories(../libfreerdp-asn1)
diff --git a/libfreerdp-core/bitmap.c b/libfreerdp-core/bitmap.c
new file mode 100644 (file)
index 0000000..148d32a
--- /dev/null
@@ -0,0 +1,273 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * RLE Compressed Bitmap Stream
+ *
+ * Copyright 2011 Jay Sorg <jay.sorg@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+   RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM)
+   http://msdn.microsoft.com/en-us/library/cc240895%28v=prot.10%29.aspx
+   pseudo-code
+   http://msdn.microsoft.com/en-us/library/dd240593%28v=prot.10%29.aspx
+*/
+
+#include <freerdp/utils/stream.h>
+#include <freerdp/utils/memory.h>
+
+#define REGULAR_BG_RUN 0x0
+#define MEGA_MEGA_BG_RUN 0xF0
+#define REGULAR_FG_RUN 0x1
+#define MEGA_MEGA_FG_RUN 0xF1
+#define LITE_SET_FG_FG_RUN 0xC
+#define MEGA_MEGA_SET_FG_RUN 0xF6
+#define LITE_DITHERED_RUN 0xE
+#define MEGA_MEGA_DITHERED_RUN 0xF8
+#define REGULAR_COLOR_RUN 0x3
+#define MEGA_MEGA_COLOR_RUN 0xF3
+#define REGULAR_FGBG_IMAGE 0x2
+#define MEGA_MEGA_FGBG_IMAGE 0xF2
+#define LITE_SET_FG_FGBG_IMAGE 0xD
+#define MEGA_MEGA_SET_FGBG_IMAGE 0xF7
+#define REGULAR_COLOR_IMAGE 0x4
+#define MEGA_MEGA_COLOR_IMAGE 0xF4
+#define SPECIAL_FGBG_1 0xF9
+#define SPECIAL_FGBG_2 0xFA
+#define SPECIAL_WHITE 0xFD
+#define SPECIAL_BLACK 0xFE
+
+/*
+   Bitmasks
+*/
+static uint8 g_MaskBit0 = 0x01; /* Least significant bit */
+static uint8 g_MaskBit1 = 0x02;
+static uint8 g_MaskBit2 = 0x04;
+static uint8 g_MaskBit3 = 0x08;
+static uint8 g_MaskBit4 = 0x10;
+static uint8 g_MaskBit5 = 0x20;
+static uint8 g_MaskBit6 = 0x40;
+static uint8 g_MaskBit7 = 0x80; /* Most significant bit */
+
+static uint8 g_MaskRegularRunLength = 0x1F;
+static uint8 g_MaskLiteRunLength = 0x0F;
+
+static uint8 g_MaskSpecialFgBg1 = 0x03;
+static uint8 g_MaskSpecialFgBg2 = 0x05;
+
+typedef uint32 PIXEL;
+
+#define BLACK_PIXEL 0
+#define WHITE_PIXEL 0xffffff
+
+/*
+   Reads the supplied order header and extracts the compression
+   order code ID.
+*/
+static uint32 ExtractCodeId(uint8 bOrderHdr)
+{
+       int code;
+
+       switch (bOrderHdr)
+       {
+               case MEGA_MEGA_BG_RUN:
+               case MEGA_MEGA_FG_RUN:
+               case MEGA_MEGA_SET_FG_RUN:
+               case MEGA_MEGA_DITHERED_RUN:
+               case MEGA_MEGA_COLOR_RUN:
+               case MEGA_MEGA_FGBG_IMAGE:
+               case MEGA_MEGA_SET_FGBG_IMAGE:
+               case MEGA_MEGA_COLOR_IMAGE:
+               case SPECIAL_FGBG_1:
+               case SPECIAL_FGBG_2:
+               case SPECIAL_WHITE:
+               case SPECIAL_BLACK:
+                       return bOrderHdr;
+       }
+       code = bOrderHdr >> 5;
+       switch (code)
+       {
+               case REGULAR_BG_RUN:
+               case REGULAR_FG_RUN:
+               case REGULAR_COLOR_RUN:
+               case REGULAR_FGBG_IMAGE:
+               case REGULAR_COLOR_IMAGE:
+                       return code;
+       }
+       return bOrderHdr >> 4;
+}
+
+/*
+   Extract the run length of a compression order.
+*/
+static uint32 ExtractRunLength(uint32 code, uint8 * pbOrderHdr, uint32 * advance)
+{
+       uint32 runLength;
+       uint32 ladvance;
+
+       ladvance = 1;
+       runLength = 0;
+       switch (code)
+       {
+               case REGULAR_FGBG_IMAGE:
+                       runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
+                       if (runLength == 0)
+                       {
+                               runLength = (*(pbOrderHdr + 1)) + 1;
+                               ladvance += 1;
+                       }
+                       else
+                       {
+                               runLength = runLength * 8;
+                       }
+                       break;
+               case LITE_SET_FG_FGBG_IMAGE:
+                       runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
+                       if (runLength == 0)
+                       {
+                               runLength = (*(pbOrderHdr + 1)) + 1;
+                               ladvance += 1;
+                       }
+                       else
+                       {
+                               runLength = runLength * 8;
+                       }
+                       break;
+               case REGULAR_BG_RUN:
+               case REGULAR_FG_RUN:
+               case REGULAR_COLOR_RUN:
+               case REGULAR_COLOR_IMAGE:
+                       runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
+                       if (runLength == 0)
+                       {
+                               /* An extended (MEGA) run. */
+                               runLength = (*(pbOrderHdr + 1)) + 32;
+                               ladvance += 1;
+                       }
+                       break;
+               case LITE_SET_FG_FG_RUN:
+               case LITE_DITHERED_RUN:
+                       runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
+                       if (runLength == 0)
+                       {
+                               /* An extended (MEGA) run. */
+                               runLength = (*(pbOrderHdr + 1)) + 16;
+                               ladvance += 1;
+                       }
+                       break;
+               case MEGA_MEGA_BG_RUN:
+               case MEGA_MEGA_FG_RUN:
+               case MEGA_MEGA_SET_FG_RUN:
+               case MEGA_MEGA_DITHERED_RUN:
+               case MEGA_MEGA_COLOR_RUN:
+               case MEGA_MEGA_FGBG_IMAGE:
+               case MEGA_MEGA_SET_FGBG_IMAGE:
+               case MEGA_MEGA_COLOR_IMAGE:
+                       runLength = ((uint16) pbOrderHdr[1]) | ((uint16) (pbOrderHdr[2] << 8));
+                       ladvance += 2;
+                       break;
+       }
+       *advance = ladvance;
+       return runLength;
+}
+
+#define UNROLL_COUNT 4
+#define UNROLL(_exp) do { _exp _exp _exp _exp } while (0)
+
+#undef DESTWRITEPIXEL
+#undef DESTREADPIXEL
+#undef SRCREADPIXEL
+#undef DESTNEXTPIXEL
+#undef SRCNEXTPIXEL
+#undef WRITEFGBGIMAGE
+#undef WRITEFIRSTLINEFGBGIMAGE
+#undef RLEDECOMPRESS
+#undef RLEEXTRA
+#define DESTWRITEPIXEL(_buf, _pix) (_buf)[0] = (uint8)(_pix)
+#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0]
+#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0]
+#define DESTNEXTPIXEL(_buf) _buf += 1
+#define SRCNEXTPIXEL(_buf) _buf += 1
+#define WRITEFGBGIMAGE WriteFgBgImage8to8
+#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage8to8
+#define RLEDECOMPRESS RleDecompress8to8
+#define RLEEXTRA
+#include "bitmap_inc.c"
+
+#undef DESTWRITEPIXEL
+#undef DESTREADPIXEL
+#undef SRCREADPIXEL
+#undef DESTNEXTPIXEL
+#undef SRCNEXTPIXEL
+#undef WRITEFGBGIMAGE
+#undef WRITEFIRSTLINEFGBGIMAGE
+#undef RLEDECOMPRESS
+#undef RLEEXTRA
+#define DESTWRITEPIXEL(_buf, _pix) ((uint16*)(_buf))[0] = (uint16)(_pix)
+#define DESTREADPIXEL(_pix, _buf) _pix = ((uint16*)(_buf))[0]
+#define SRCREADPIXEL(_pix, _buf) _pix = ((uint16*)(_buf))[0]
+#define DESTNEXTPIXEL(_buf) _buf += 2
+#define SRCNEXTPIXEL(_buf) _buf += 2
+#define WRITEFGBGIMAGE WriteFgBgImage16to16
+#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage16to16
+#define RLEDECOMPRESS RleDecompress16to16
+#define RLEEXTRA
+#include "bitmap_inc.c"
+
+#undef DESTWRITEPIXEL
+#undef DESTREADPIXEL
+#undef SRCREADPIXEL
+#undef DESTNEXTPIXEL
+#undef SRCNEXTPIXEL
+#undef WRITEFGBGIMAGE
+#undef WRITEFIRSTLINEFGBGIMAGE
+#undef RLEDECOMPRESS
+#undef RLEEXTRA
+#define DESTWRITEPIXEL(_buf, _pix) do { (_buf)[0] = (uint8)(_pix);  \
+  (_buf)[1] = (uint8)((_pix) >> 8); (_buf)[2] = (uint8)((_pix) >> 16); } while (0)
+#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | \
+  ((_buf)[2] << 16)
+#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | \
+  ((_buf)[2] << 16)
+#define DESTNEXTPIXEL(_buf) _buf += 3
+#define SRCNEXTPIXEL(_buf) _buf += 3
+#define WRITEFGBGIMAGE WriteFgBgImage24to24
+#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage24to24
+#define RLEDECOMPRESS RleDecompress24to24
+#define RLEEXTRA
+#include "bitmap_inc.c"
+
+int bitmap_decompress(void * inst, uint8 * output, int width, int height,
+       uint8 * input, int size, int Bpp)
+{
+       switch (Bpp)
+       {
+               case 1:
+                       RleDecompress8to8(input, size, output, width, width, height);
+                       break;
+               case 2:
+                       RleDecompress16to16(input, size, output, width * 2, width, height);
+                       break;
+               case 3:
+                       RleDecompress24to24(input, size, output, width * 3, width, height);
+                       break;
+               case 4:
+                       /* TODO */
+                       break;
+               default:
+                       /* TODO */
+                       break;
+       }
+       return 0;
+}
diff --git a/libfreerdp-core/bitmap_inc.c b/libfreerdp-core/bitmap_inc.c
new file mode 100644 (file)
index 0000000..deafcff
--- /dev/null
@@ -0,0 +1,567 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * RLE Compressed Bitmap Stream
+ *
+ * Copyright 2011 Jay Sorg <jay.sorg@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* do not compile the file directly */
+
+/*
+   Write a foreground/background image to a destination buffer.
+*/
+static uint8 * WRITEFGBGIMAGE(uint8 * pbDest, uint32 rowDelta,
+       uint8 bitmask, PIXEL fgPel, uint32 cBits)
+{
+       PIXEL xorPixel;
+
+       DESTREADPIXEL(xorPixel, pbDest - rowDelta);
+       if (bitmask & g_MaskBit0)
+       {
+               DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
+       }
+       else
+       {
+               DESTWRITEPIXEL(pbDest, xorPixel);
+       }
+       DESTNEXTPIXEL(pbDest);
+       cBits = cBits - 1;
+       if (cBits > 0)
+       {
+               DESTREADPIXEL(xorPixel, pbDest - rowDelta);
+               if (bitmask & g_MaskBit1)
+               {
+                       DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
+               }
+               else
+               {
+                       DESTWRITEPIXEL(pbDest, xorPixel);
+               }
+               DESTNEXTPIXEL(pbDest);
+               cBits = cBits - 1;
+               if (cBits > 0)
+               {
+                       DESTREADPIXEL(xorPixel, pbDest - rowDelta);
+                       if (bitmask & g_MaskBit2)
+                       {
+                               DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
+                       }
+                       else
+                       {
+                               DESTWRITEPIXEL(pbDest, xorPixel);
+                       }
+                       DESTNEXTPIXEL(pbDest);
+                       cBits = cBits - 1;
+                       if (cBits > 0)
+                       {
+                               DESTREADPIXEL(xorPixel, pbDest - rowDelta);
+                               if (bitmask & g_MaskBit3)
+                               {
+                                       DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
+                               }
+                               else
+                               {
+                                       DESTWRITEPIXEL(pbDest, xorPixel);
+                               }
+                               DESTNEXTPIXEL(pbDest);
+                               cBits = cBits - 1;
+                               if (cBits > 0)
+                               {
+                                       DESTREADPIXEL(xorPixel, pbDest - rowDelta);
+                                       if (bitmask & g_MaskBit4)
+                                       {
+                                               DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
+                                       }
+                                       else
+                                       {
+                                               DESTWRITEPIXEL(pbDest, xorPixel);
+                                       }
+                                       DESTNEXTPIXEL(pbDest);
+                                       cBits = cBits - 1;
+                                       if (cBits > 0)
+                                       {
+                                               DESTREADPIXEL(xorPixel, pbDest - rowDelta);
+                                               if (bitmask & g_MaskBit5)
+                                               {
+                                                       DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
+                                               }
+                                               else
+                                               {
+                                                       DESTWRITEPIXEL(pbDest, xorPixel);
+                                               }
+                                               DESTNEXTPIXEL(pbDest);
+                                               cBits = cBits - 1;
+                                               if (cBits > 0)
+                                               {
+                                                       DESTREADPIXEL(xorPixel, pbDest - rowDelta);
+                                                       if (bitmask & g_MaskBit6)
+                                                       {
+                                                               DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
+                                                       }
+                                                       else
+                                                       {
+                                                               DESTWRITEPIXEL(pbDest, xorPixel);
+                                                       }
+                                                       DESTNEXTPIXEL(pbDest);
+                                                       cBits = cBits - 1;
+                                                       if (cBits > 0)
+                                                       {
+                                                               DESTREADPIXEL(xorPixel, pbDest - rowDelta);
+                                                               if (bitmask & g_MaskBit7)
+                                                               {
+                                                                       DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
+                                                               }
+                                                               else
+                                                               {
+                                                                       DESTWRITEPIXEL(pbDest, xorPixel);
+                                                               }
+                                                               DESTNEXTPIXEL(pbDest);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return pbDest;
+}
+
+/*
+   Write a foreground/background image to a destination buffer
+   for the first line of compressed data.
+*/
+static uint8 * WRITEFIRSTLINEFGBGIMAGE(uint8 * pbDest, uint8 bitmask,
+       PIXEL fgPel, uint32 cBits)
+{
+       if (bitmask & g_MaskBit0)
+       {
+               DESTWRITEPIXEL(pbDest, fgPel);
+       }
+       else
+       {
+               DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+       }
+       DESTNEXTPIXEL(pbDest);
+       cBits = cBits - 1;
+       if (cBits > 0)
+       {
+               if (bitmask & g_MaskBit1)
+               {
+                       DESTWRITEPIXEL(pbDest, fgPel);
+               }
+               else
+               {
+                       DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+               }
+               DESTNEXTPIXEL(pbDest);
+               cBits = cBits - 1;
+               if (cBits > 0)
+               {
+                       if (bitmask & g_MaskBit2)
+                       {
+                               DESTWRITEPIXEL(pbDest, fgPel);
+                       }
+                       else
+                       {
+                               DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+                       }
+                       DESTNEXTPIXEL(pbDest);
+                       cBits = cBits - 1;
+                       if (cBits > 0)
+                       {
+                               if (bitmask & g_MaskBit3)
+                               {
+                                       DESTWRITEPIXEL(pbDest, fgPel);
+                               }
+                               else
+                               {
+                                       DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+                               }
+                               DESTNEXTPIXEL(pbDest);
+                               cBits = cBits - 1;
+                               if (cBits > 0)
+                               {
+                                       if (bitmask & g_MaskBit4)
+                                       {
+                                               DESTWRITEPIXEL(pbDest, fgPel);
+                                       }
+                                       else
+                                       {
+                                               DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+                                       }
+                                       DESTNEXTPIXEL(pbDest);
+                                       cBits = cBits - 1;
+                                       if (cBits > 0)
+                                       {
+                                               if (bitmask & g_MaskBit5)
+                                               {
+                                                       DESTWRITEPIXEL(pbDest, fgPel);
+                                               }
+                                               else
+                                               {
+                                                       DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+                                               }
+                                               DESTNEXTPIXEL(pbDest);
+                                               cBits = cBits - 1;
+                                               if (cBits > 0)
+                                               {
+                                                       if (bitmask & g_MaskBit6)
+                                                       {
+                                                               DESTWRITEPIXEL(pbDest, fgPel);
+                                                       }
+                                                       else
+                                                       {
+                                                               DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+                                                       }
+                                                       DESTNEXTPIXEL(pbDest);
+                                                       cBits = cBits - 1;
+                                                       if (cBits > 0)
+                                                       {
+                                                               if (bitmask & g_MaskBit7)
+                                                               {
+                                                                       DESTWRITEPIXEL(pbDest, fgPel);
+                                                               }
+                                                               else
+                                                               {
+                                                                       DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+                                                               }
+                                                               DESTNEXTPIXEL(pbDest);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return pbDest;
+}
+
+/*
+   Decompress an RLE compressed bitmap.
+*/
+void RLEDECOMPRESS(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer,
+       uint32 rowDelta, uint32 width, uint32 height)
+{
+       uint8 * pbSrc = pbSrcBuffer;
+       uint8 * pbEnd = pbSrcBuffer + cbSrcBuffer;
+       uint8 * pbDest = pbDestBuffer;
+
+       PIXEL temp;
+       PIXEL fgPel = WHITE_PIXEL;
+       boolean fInsertFgPel = False;
+       boolean fFirstLine = True;
+
+       uint8 bitmask;
+       PIXEL pixelA, pixelB;
+
+       uint32 runLength;
+       uint32 code;
+
+       uint32 advance;
+
+       RLEEXTRA
+
+       while (pbSrc < pbEnd)
+       {
+               /* Watch out for the end of the first scanline. */
+               if (fFirstLine)
+               {
+                       if (pbDest - pbDestBuffer >= rowDelta)
+                       {
+                               fFirstLine = False;
+                               fInsertFgPel = False;
+                       }
+               }
+
+               /*
+                  Extract the compression order code ID from the compression
+                  order header.
+               */
+               code = ExtractCodeId(*pbSrc);
+
+               /* Handle Background Run Orders. */
+               if (code == REGULAR_BG_RUN || code == MEGA_MEGA_BG_RUN)
+               {
+                       runLength = ExtractRunLength(code, pbSrc, &advance);
+                       pbSrc = pbSrc + advance;
+                       if (fFirstLine)
+                       {
+                               if (fInsertFgPel)
+                               {
+                                       DESTWRITEPIXEL(pbDest, fgPel);
+                                       DESTNEXTPIXEL(pbDest);
+                                       runLength = runLength - 1;
+                               }
+                               while (runLength > UNROLL_COUNT)
+                               {
+                                       UNROLL(
+                                               DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+                                               DESTNEXTPIXEL(pbDest); );
+                                       runLength = runLength - UNROLL_COUNT;
+                               }
+                               while (runLength > 0)
+                               {
+                                       DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+                                       DESTNEXTPIXEL(pbDest);
+                                       runLength = runLength - 1;
+                               }
+                       }
+                       else
+                       {
+                               if (fInsertFgPel)
+                               {
+                                       DESTREADPIXEL(temp, pbDest - rowDelta);
+                                       DESTWRITEPIXEL(pbDest, temp ^ fgPel);
+                                       DESTNEXTPIXEL(pbDest);
+                                       runLength = runLength - 1;
+                               }
+                               while (runLength > UNROLL_COUNT)
+                               {
+                                       UNROLL(
+                                               DESTREADPIXEL(temp, pbDest - rowDelta);
+                                               DESTWRITEPIXEL(pbDest, temp);
+                                               DESTNEXTPIXEL(pbDest); );
+                                       runLength = runLength - UNROLL_COUNT;
+                               }
+                               while (runLength > 0)
+                               {
+                                       DESTREADPIXEL(temp, pbDest - rowDelta);
+                                       DESTWRITEPIXEL(pbDest, temp);
+                                       DESTNEXTPIXEL(pbDest);
+                                       runLength = runLength - 1;
+                               }
+                       }
+                       /* A follow-on background run order will need a foreground pel inserted. */
+                       fInsertFgPel = True;
+                       continue;
+               }
+
+               /* For any of the other run-types a follow-on background run
+                       order does not need a foreground pel inserted. */
+               fInsertFgPel = False;
+
+               switch (code)
+               {
+                       /* Handle Foreground Run Orders. */
+                       case REGULAR_FG_RUN:
+                       case MEGA_MEGA_FG_RUN:
+                       case LITE_SET_FG_FG_RUN:
+                       case MEGA_MEGA_SET_FG_RUN:
+                               runLength = ExtractRunLength(code, pbSrc, &advance);
+                               pbSrc = pbSrc + advance;
+                               if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
+                               {
+                                       SRCREADPIXEL(fgPel, pbSrc);
+                                       SRCNEXTPIXEL(pbSrc);
+                               }
+                               if (fFirstLine)
+                               {
+                                       while (runLength > UNROLL_COUNT)
+                                       {
+                                               UNROLL(
+                                                       DESTWRITEPIXEL(pbDest, fgPel);
+                                                       DESTNEXTPIXEL(pbDest); );
+                                               runLength = runLength - UNROLL_COUNT;
+                                       }
+                                       while (runLength > 0)
+                                       {
+                                               DESTWRITEPIXEL(pbDest, fgPel);
+                                               DESTNEXTPIXEL(pbDest);
+                                               runLength = runLength - 1;
+                                       }
+                               }
+                               else
+                               {
+                                       while (runLength > UNROLL_COUNT)
+                                       {
+                                               UNROLL(
+                                                       DESTREADPIXEL(temp, pbDest - rowDelta);
+                                                       DESTWRITEPIXEL(pbDest, temp ^ fgPel);
+                                                       DESTNEXTPIXEL(pbDest); );
+                                               runLength = runLength - UNROLL_COUNT;
+                                       }
+                                       while (runLength > 0)
+                                       {
+                                               DESTREADPIXEL(temp, pbDest - rowDelta);
+                                               DESTWRITEPIXEL(pbDest, temp ^ fgPel);
+                                               DESTNEXTPIXEL(pbDest);
+                                               runLength = runLength - 1;
+                                       }
+                               }
+                               break;
+
+                       /* Handle Dithered Run Orders. */
+                       case LITE_DITHERED_RUN:
+                       case MEGA_MEGA_DITHERED_RUN:
+                               runLength = ExtractRunLength(code, pbSrc, &advance);
+                               pbSrc = pbSrc + advance;
+                               SRCREADPIXEL(pixelA, pbSrc);
+                               SRCNEXTPIXEL(pbSrc);
+                               SRCREADPIXEL(pixelB, pbSrc);
+                               SRCNEXTPIXEL(pbSrc);
+                               while (runLength > UNROLL_COUNT)
+                               {
+                                       UNROLL(
+                                               DESTWRITEPIXEL(pbDest, pixelA);
+                                               DESTNEXTPIXEL(pbDest);
+                                               DESTWRITEPIXEL(pbDest, pixelB);
+                                               DESTNEXTPIXEL(pbDest); );
+                                       runLength = runLength - UNROLL_COUNT;
+                               }
+                               while (runLength > 0)
+                               {
+                                       DESTWRITEPIXEL(pbDest, pixelA);
+                                       DESTNEXTPIXEL(pbDest);
+                                       DESTWRITEPIXEL(pbDest, pixelB);
+                                       DESTNEXTPIXEL(pbDest);
+                                       runLength = runLength - 1;
+                               }
+                               break;
+
+                       /* Handle Color Run Orders. */
+                       case REGULAR_COLOR_RUN:
+                       case MEGA_MEGA_COLOR_RUN:
+                               runLength = ExtractRunLength(code, pbSrc, &advance);
+                               pbSrc = pbSrc + advance;
+                               SRCREADPIXEL(pixelA, pbSrc);
+                               SRCNEXTPIXEL(pbSrc);
+                               while (runLength > UNROLL_COUNT)
+                               {
+                                       UNROLL(
+                                               DESTWRITEPIXEL(pbDest, pixelA);
+                                               DESTNEXTPIXEL(pbDest); );
+                                       runLength = runLength - UNROLL_COUNT;
+                               }
+                               while (runLength > 0)
+                               {
+                                       DESTWRITEPIXEL(pbDest, pixelA);
+                                       DESTNEXTPIXEL(pbDest);
+                                       runLength = runLength - 1;
+                               }
+                               break;
+
+                       /* Handle Foreground/Background Image Orders. */
+                       case REGULAR_FGBG_IMAGE:
+                       case MEGA_MEGA_FGBG_IMAGE:
+                       case LITE_SET_FG_FGBG_IMAGE:
+                       case MEGA_MEGA_SET_FGBG_IMAGE:
+                               runLength = ExtractRunLength(code, pbSrc, &advance);
+                               pbSrc = pbSrc + advance;
+                               if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
+                               {
+                                       SRCREADPIXEL(fgPel, pbSrc);
+                                       SRCNEXTPIXEL(pbSrc);
+                               }
+                               if (fFirstLine)
+                               {
+                                       while (runLength > 8)
+                                       {
+                                               bitmask = *pbSrc;
+                                               pbSrc = pbSrc + 1;
+                                               pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, bitmask, fgPel, 8);
+                                               runLength = runLength - 8;
+                                       }
+                               }
+                               else
+                               {
+                                       while (runLength > 8)
+                                       {
+                                               bitmask = *pbSrc;
+                                               pbSrc = pbSrc + 1;
+                                               pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, bitmask, fgPel, 8);
+                                               runLength = runLength - 8;
+                                       }
+                               }
+                               if (runLength > 0)
+                               {
+                                       bitmask = *pbSrc;
+                                       pbSrc = pbSrc + 1;
+                                       if (fFirstLine)
+                                       {
+                                               pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, bitmask, fgPel, runLength);
+                                       }
+                                       else
+                                       {
+                                               pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, bitmask, fgPel, runLength);
+                                       }
+                               }
+                               break;
+
+                       /* Handle Color Image Orders. */
+                       case REGULAR_COLOR_IMAGE:
+                       case MEGA_MEGA_COLOR_IMAGE:
+                               runLength = ExtractRunLength(code, pbSrc, &advance);
+                               pbSrc = pbSrc + advance;
+                               while (runLength > UNROLL_COUNT)
+                               {
+                                       UNROLL(
+                                               SRCREADPIXEL(temp, pbSrc);
+                                               SRCNEXTPIXEL(pbSrc);
+                                               DESTWRITEPIXEL(pbDest, temp);
+                                               DESTNEXTPIXEL(pbDest); );
+                                       runLength = runLength - UNROLL_COUNT;
+                               }
+                               while (runLength > 0)
+                               {
+                                       SRCREADPIXEL(temp, pbSrc);
+                                       SRCNEXTPIXEL(pbSrc);
+                                       DESTWRITEPIXEL(pbDest, temp);
+                                       DESTNEXTPIXEL(pbDest);
+                                       runLength = runLength - 1;
+                               }
+                               break;
+
+                       /* Handle Special Order 1. */
+                       case SPECIAL_FGBG_1:
+                               pbSrc = pbSrc + 1;
+                               if (fFirstLine)
+                               {
+                                       pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, g_MaskSpecialFgBg1, fgPel, 8);
+                               }
+                               else
+                               {
+                                       pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, g_MaskSpecialFgBg1, fgPel, 8);
+                               }
+                               break;
+
+                       /* Handle Special Order 2. */
+                       case SPECIAL_FGBG_2:
+                               pbSrc = pbSrc + 1;
+                               if (fFirstLine)
+                               {
+                                       pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, g_MaskSpecialFgBg2, fgPel, 8);
+                               }
+                               else
+                               {
+                                       pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, g_MaskSpecialFgBg2, fgPel, 8);
+                               }
+                               break;
+
+                               /* Handle White Order. */
+                       case SPECIAL_WHITE:
+                               pbSrc = pbSrc + 1;
+                               DESTWRITEPIXEL(pbDest, WHITE_PIXEL);
+                               DESTNEXTPIXEL(pbDest);
+                               break;
+
+                       /* Handle Black Order. */
+                       case SPECIAL_BLACK:
+                               pbSrc = pbSrc + 1;
+                               DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
+                               DESTNEXTPIXEL(pbDest);
+                               break;
+               }
+       }
+}
diff --git a/libfreerdp-core/rle_bitmap_stream.c b/libfreerdp-core/rle_bitmap_stream.c
deleted file mode 100644 (file)
index 8a3f22f..0000000
+++ /dev/null
@@ -1,972 +0,0 @@
-/**
- * FreeRDP: A Remote Desktop Protocol Client
- * RLE Compressed Bitmap Stream
- *
- * Copyright 2011 Jay Sorg <jay.sorg@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
-   RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM)
-   http://msdn.microsoft.com/en-us/library/cc240895%28v=prot.10%29.aspx
-   pseudo-code
-   http://msdn.microsoft.com/en-us/library/dd240593%28v=prot.10%29.aspx
-*/
-
-#include <freerdp/utils/stream.h>
-#include <freerdp/utils/memory.h>
-
-#define REGULAR_BG_RUN 0x0
-#define MEGA_MEGA_BG_RUN 0xF0
-#define REGULAR_FG_RUN 0x1
-#define MEGA_MEGA_FG_RUN 0xF1
-#define LITE_SET_FG_FG_RUN 0xC
-#define MEGA_MEGA_SET_FG_RUN 0xF6
-#define LITE_DITHERED_RUN 0xE
-#define MEGA_MEGA_DITHERED_RUN 0xF8
-#define REGULAR_COLOR_RUN 0x3
-#define MEGA_MEGA_COLOR_RUN 0xF3
-#define REGULAR_FGBG_IMAGE 0x2
-#define MEGA_MEGA_FGBG_IMAGE 0xF2
-#define LITE_SET_FG_FGBG_IMAGE 0xD
-#define MEGA_MEGA_SET_FGBG_IMAGE 0xF7
-#define REGULAR_COLOR_IMAGE 0x4
-#define MEGA_MEGA_COLOR_IMAGE 0xF4
-#define SPECIAL_FGBG_1 0xF9
-#define SPECIAL_FGBG_2 0xFA
-#define SPECIAL_WHITE 0xFD
-#define SPECIAL_BLACK 0xFE
-
-/*
-   Bitmasks
-*/
-static uint8 g_MaskBit0 = 0x01; /* Least significant bit */
-static uint8 g_MaskBit1 = 0x02;
-static uint8 g_MaskBit2 = 0x04;
-static uint8 g_MaskBit3 = 0x08;
-static uint8 g_MaskBit4 = 0x10;
-static uint8 g_MaskBit5 = 0x20;
-static uint8 g_MaskBit6 = 0x40;
-static uint8 g_MaskBit7 = 0x80; /* Most significant bit */
-
-static uint8 g_MaskRegularRunLength = 0x1F;
-static uint8 g_MaskLiteRunLength = 0x0F;
-
-static uint8 g_MaskSpecialFgBg1 = 0x03;
-static uint8 g_MaskSpecialFgBg2 = 0x05;
-
-typedef uint32 PIXEL;
-
-/*
-   Returns the color depth (in bits per pixel) that was selected
-   for the RDP connection.
-*/
-static uint32
-GetColorDepth(void)
-{
-       return 8;
-}
-
-/*
-   Returns the color depth (in bytes per pixel) that was selected
-   for the RDP connection.
-*/
-static uint32
-GetColorDepthInBytes(void)
-{
-       /* bytes per pixel, see above */
-       return 1;
-}
-
-/*
-   PIXEL is a dynamic type that is sized based on the current color
-   depth being used for the RDP connection.
-
-   if (GetColorDepth() == 8) then PIXEL is an 8-bit unsigned integer
-   if (GetColorDepth() == 15) then PIXEL is a 16-bit unsigned integer
-   if (GetColorDepth() == 16) then PIXEL is a 16-bit unsigned integer
-   if (GetColorDepth() == 24) then PIXEL is a 24-bit unsigned integer
-*/
-
-/*
-   Writes a pixel to the specified buffer.
-*/
-static void
-WritePixel(uint8 * pbBuffer, PIXEL pixel)
-{
-       pbBuffer[0] = pixel;
-}
-
-/*
-   Reads a pixel from the specified buffer.
-*/
-static PIXEL
-ReadPixel(uint8 * pbBuffer)
-{
-       return pbBuffer[0];
-}
-
-/*
-   Returns the size of a pixel in bytes.
-*/
-static uint32
-GetPixelSize(void)
-{
-       uint32 colorDepth = GetColorDepth();
-
-       if (colorDepth == 8)
-       {
-               return 1;
-       }
-       else if (colorDepth == 15 || colorDepth == 16)
-       {
-               return 2;
-       }
-       else if (colorDepth == 24)
-       {
-               return 3;
-       }
-       return 1;
-}
-
-/*
-   Returns a pointer to the next pixel in the specified buffer.
-*/
-static uint8 *
-NextPixel(uint8 * pbBuffer)
-{
-       return pbBuffer + GetPixelSize();
-}
-
-/*
-   Reads the supplied order header and extracts the compression
-   order code ID.
-*/
-static uint32
-ExtractCodeId(uint8 bOrderHdr)
-{
-       int code;
-
-       switch (bOrderHdr)
-       {
-               case MEGA_MEGA_BG_RUN:
-               case MEGA_MEGA_FG_RUN:
-               case MEGA_MEGA_SET_FG_RUN:
-               case MEGA_MEGA_DITHERED_RUN:
-               case MEGA_MEGA_COLOR_RUN:
-               case MEGA_MEGA_FGBG_IMAGE:
-               case MEGA_MEGA_SET_FGBG_IMAGE:
-               case MEGA_MEGA_COLOR_IMAGE:
-               case SPECIAL_FGBG_1:
-               case SPECIAL_FGBG_2:
-               case SPECIAL_WHITE:
-               case SPECIAL_BLACK:
-                       return bOrderHdr;
-       }
-       code = bOrderHdr >> 5;
-       switch (code)
-       {
-               case REGULAR_BG_RUN:
-               case REGULAR_FG_RUN:
-               case REGULAR_COLOR_RUN:
-               case REGULAR_FGBG_IMAGE:
-               case REGULAR_COLOR_IMAGE:
-                       return code;
-       }
-       return bOrderHdr >> 4;
-}
-
-/*
-   Returns TRUE if the supplied code identifier is for a regular-form
-   standard compression order. For example IsRegularCode(0x01) returns
-   TRUE as 0x01 is the code ID for a Regular Foreground Run Order.
-*/
-static boolean
-IsRegularCode(uint32 codeId)
-{
-       switch (codeId)
-       {
-               case REGULAR_BG_RUN:
-               case REGULAR_FG_RUN:
-               case REGULAR_COLOR_RUN:
-               case REGULAR_FGBG_IMAGE:
-               case REGULAR_COLOR_IMAGE:
-                       return True;
-       }
-       return False;
-}
-
-/*
-   Returns TRUE if the supplied code identifier is for a lite-form
-   standard compression order. For example IsLiteCode(0x0E) returns
-   TRUE as 0x0E is the code ID for a Lite Dithered Run Order.
-*/
-static boolean
-IsLiteCode(uint32 codeId)
-{
-       switch (codeId)
-       {
-               case LITE_SET_FG_FG_RUN:
-               case LITE_DITHERED_RUN:
-               case LITE_SET_FG_FGBG_IMAGE:
-                       return True;
-       }
-       return False;
-}
-
-/*
-   Returns TRUE if the supplied code identifier is for a MEGA_MEGA
-   type extended compression order. For example IsMegaMegaCode(0xF0)
-   returns TRUE as 0xF0 is the code ID for a MEGA_MEGA Background
-   Run Order.
-*/
-static boolean
-IsMegaMegaCode(uint32 codeId)
-{
-       switch (codeId)
-       {
-               case MEGA_MEGA_BG_RUN:
-               case MEGA_MEGA_FG_RUN:
-               case MEGA_MEGA_SET_FG_RUN:
-               case MEGA_MEGA_DITHERED_RUN:
-               case MEGA_MEGA_COLOR_RUN:
-               case MEGA_MEGA_FGBG_IMAGE:
-               case MEGA_MEGA_SET_FGBG_IMAGE:
-               case MEGA_MEGA_COLOR_IMAGE:
-                       return True;
-       }
-       return False;
-}
-
-/*
-   Returns a black pixel.
-*/
-static PIXEL
-GetColorBlack(void)
-{
-       uint32 colorDepth = GetColorDepth();
-
-       if (colorDepth == 8)
-       {
-               return (PIXEL) 0x00;
-       }
-       else if (colorDepth == 15)
-       {
-               return (PIXEL) 0x0000;
-       }
-       else if (colorDepth == 16)
-       {
-               return (PIXEL) 0x0000;
-       }
-       else if (colorDepth == 24)
-       {
-               return (PIXEL) 0x000000;
-       }
-       return 0;
-}
-
-/*
-   Returns a white pixel.
-*/
-static PIXEL
-GetColorWhite(void)
-{
-       uint32 colorDepth = GetColorDepth();
-
-       if (colorDepth == 8)
-       {
-               /*
-                  Palette entry #255 holds black.
-               */
-               return (PIXEL) 0xFF;
-       }
-       else if (colorDepth == 15)
-       {
-               /*
-                  5 bits per RGB component:
-                  0111 1111 1111 1111 (binary)
-               */
-               return (PIXEL) 0x7FFF;
-       }
-       else if (colorDepth == 16)
-       {
-               /*
-                  5 bits for red, 6 bits for green, 5 bits for green:
-                  1111 1111 1111 1111 (binary)
-               */
-               return (PIXEL) 0xFFFF;
-       }
-       else if (colorDepth == 24)
-       {
-               /*
-                  8 bits per RGB component:
-                  1111 1111 1111 1111 1111 1111 (binary)
-               */
-               return (PIXEL) 0xFFFFFF;
-       }
-}
-
-/*
-   Extract the run length of a Regular-Form Foreground/Background
-   Image Order.
-*/
-static uint32
-ExtractRunLengthRegularFgBg(uint8 * pbOrderHdr, uint32 * advance)
-{
-       uint32 runLength;
-
-       runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
-       if (runLength == 0)
-       {
-               runLength = (*(pbOrderHdr + 1)) + 1;
-               *advance += 1;
-       }
-       else
-       {
-               runLength = runLength * 8;
-       }
-       return runLength;
-}
-
-/*
-   Extract the run length of a Lite-Form Foreground/Background
-   Image Order.
-*/
-static uint32
-ExtractRunLengthLiteFgBg(uint8 * pbOrderHdr, uint32 * advance)
-{
-       uint32 runLength;
-
-       runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
-       if (runLength == 0)
-       {
-               runLength = (*(pbOrderHdr + 1)) + 1;
-               *advance += 1;
-       }
-       else
-       {
-               runLength = runLength * 8;
-       }
-       return runLength;
-}
-
-/*
-   Extract the run length of a regular-form compression order.
-*/
-static uint32
-ExtractRunLengthRegular(uint8 * pbOrderHdr, uint32 * advance)
-{
-       uint32 runLength;
-
-       runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
-       if (runLength == 0)
-       {
-               /* An extended (MEGA) run. */
-               runLength = (*(pbOrderHdr + 1)) + 32;
-               *advance += 1;
-       }
-       return runLength;
-}
-
-/*
-   Extract the run length of a lite-form compression order.
-*/
-static uint32
-ExtractRunLengthLite(uint8 * pbOrderHdr, uint32 * advance)
-{
-       uint32 runLength;
-
-       runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
-       if (runLength == 0)
-       {
-               /* An extended (MEGA) run. */
-               runLength = (*(pbOrderHdr + 1)) + 16;
-               *advance += 1;
-       }
-       return runLength;
-}
-
-/*
-   Extract the run length of a MEGA_MEGA-type compression order.
-*/
-static uint32
-ExtractRunLengthMegaMega(uint8 * pbOrderHdr, uint32 * advance)
-{
-       uint32 runLength;
-
-       pbOrderHdr = pbOrderHdr + 1;
-       runLength = ((uint16) pbOrderHdr[0]) | ((uint16) (pbOrderHdr[1] << 8));
-       *advance += 2;
-       return runLength;
-}
-
-/*
-   Extract the run length of a compression order.
-*/
-static uint32
-ExtractRunLength(uint32 code, uint8 * pbOrderHdr, uint32 * advance)
-{
-       uint32 runLength;
-
-       *advance = 1;
-       if (code == REGULAR_FGBG_IMAGE)
-       {
-               runLength = ExtractRunLengthRegularFgBg(pbOrderHdr, advance);
-       }
-       else if (code == LITE_SET_FG_FGBG_IMAGE)
-       {
-               runLength = ExtractRunLengthLiteFgBg(pbOrderHdr, advance);
-       }
-       else if (IsRegularCode(code))
-       {
-               runLength = ExtractRunLengthRegular(pbOrderHdr, advance);
-       }
-       else if (IsLiteCode(code))
-       {
-               runLength = ExtractRunLengthLite(pbOrderHdr, advance);
-       }
-       else if (IsMegaMegaCode(code))
-       {
-               runLength = ExtractRunLengthMegaMega(pbOrderHdr, advance);
-       }
-       else
-       {
-               runLength = 0;
-       }
-       return runLength;
-}
-
-/*
-   Write a foreground/background image to a destination buffer.
-*/
-static uint8 *
-WriteFgBgImage(uint8 * pbDest, uint32 rowDelta, uint8 bitmask,
-       PIXEL fgPel, uint32 cBits)
-{
-       PIXEL xorPixel;
-
-       xorPixel = ReadPixel(pbDest - rowDelta);
-       if (bitmask & g_MaskBit0)
-       {
-               WritePixel(pbDest, xorPixel ^ fgPel);
-       }
-       else
-       {
-               WritePixel(pbDest, xorPixel);
-       }
-       pbDest = NextPixel(pbDest);
-       cBits = cBits - 1;
-
-       if (cBits > 0)
-       {
-               xorPixel = ReadPixel(pbDest - rowDelta);
-               if (bitmask & g_MaskBit1)
-               {
-                       WritePixel(pbDest, xorPixel ^ fgPel);
-               }
-               else
-               {
-                       WritePixel(pbDest, xorPixel);
-               }
-               pbDest = NextPixel(pbDest);
-               cBits = cBits - 1;
-
-               if (cBits > 0)
-               {
-                       xorPixel = ReadPixel(pbDest - rowDelta);
-                       if (bitmask & g_MaskBit2)
-                       {
-                               WritePixel(pbDest, xorPixel ^ fgPel);
-                       }
-                       else
-                       {
-                               WritePixel(pbDest, xorPixel);
-                       }
-                       pbDest = NextPixel(pbDest);
-                       cBits = cBits - 1;
-
-                       if (cBits > 0)
-                       {
-                               xorPixel = ReadPixel(pbDest - rowDelta);
-                               if (bitmask & g_MaskBit3)
-                               {
-                                       WritePixel(pbDest, xorPixel ^ fgPel);
-                               }
-                               else
-                               {
-                                       WritePixel(pbDest, xorPixel);
-                               }
-                               pbDest = NextPixel(pbDest);
-                               cBits = cBits - 1;
-
-                               if (cBits > 0)
-                               {
-                                       xorPixel = ReadPixel(pbDest - rowDelta);
-                                       if (bitmask & g_MaskBit4)
-                                       {
-                                               WritePixel(pbDest, xorPixel ^ fgPel);
-                                       }
-                                       else
-                                       {
-                                               WritePixel(pbDest, xorPixel);
-                                       }
-                                       pbDest = NextPixel(pbDest);
-                                       cBits = cBits - 1;
-
-                                       if (cBits > 0)
-                                       {
-                                               xorPixel = ReadPixel(pbDest - rowDelta);
-                                               if (bitmask & g_MaskBit5)
-                                               {
-                                                       WritePixel(pbDest, xorPixel ^ fgPel);
-                                               }
-                                               else
-                                               {
-                                                       WritePixel(pbDest, xorPixel);
-                                               }
-                                               pbDest = NextPixel(pbDest);
-                                               cBits = cBits - 1;
-
-                                               if (cBits > 0)
-                                               {
-                                                       xorPixel = ReadPixel(pbDest - rowDelta);
-                                                       if (bitmask & g_MaskBit6)
-                                                       {
-                                                               WritePixel(pbDest, xorPixel ^ fgPel);
-                                                       }
-                                                       else
-                                                       {
-                                                               WritePixel(pbDest, xorPixel);
-                                                       }
-                                                       pbDest = NextPixel(pbDest);
-                                                       cBits = cBits - 1;
-
-                                                       if (cBits > 0)
-                                                       {
-                                                               xorPixel = ReadPixel(pbDest - rowDelta);
-                                                               if (bitmask & g_MaskBit7)
-                                                               {
-                                                                       WritePixel(pbDest, xorPixel ^ fgPel);
-                                                               }
-                                                               else
-                                                               {
-                                                                       WritePixel(pbDest, xorPixel);
-                                                               }
-                                                               pbDest = NextPixel(pbDest);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-       return pbDest;
-}
-
-/*
-   Write a foreground/background image to a destination buffer
-   for the first line of compressed data.
-*/
-static uint8 *
-WriteFirstLineFgBgImage(uint8 * pbDest, uint8 bitmask,
-       PIXEL fgPel, uint32 cBits)
-{
-       if (bitmask & g_MaskBit0)
-       {
-               WritePixel(pbDest, fgPel);
-       }
-       else
-       {
-               WritePixel(pbDest, GetColorBlack());
-       }
-       pbDest = NextPixel(pbDest);
-       cBits = cBits - 1;
-
-       if (cBits > 0)
-       {
-               if (bitmask & g_MaskBit1)
-               {
-                       WritePixel(pbDest, fgPel);
-               }
-               else
-               {
-                       WritePixel(pbDest, GetColorBlack());
-               }
-               pbDest = NextPixel(pbDest);
-               cBits = cBits - 1;
-
-               if (cBits > 0)
-               {
-                       if (bitmask & g_MaskBit2)
-                       {
-                               WritePixel(pbDest, fgPel);
-                       }
-                       else
-                       {
-                               WritePixel(pbDest, GetColorBlack());
-                       }
-                       pbDest = NextPixel(pbDest);
-                       cBits = cBits - 1;
-
-                       if (cBits > 0)
-                       {
-                               if (bitmask & g_MaskBit3)
-                               {
-                                       WritePixel(pbDest, fgPel);
-                               }
-                               else
-                               {
-                                       WritePixel(pbDest, GetColorBlack());
-                               }
-                               pbDest = NextPixel(pbDest);
-                               cBits = cBits - 1;
-
-                               if (cBits > 0)
-                               {
-                                       if (bitmask & g_MaskBit4)
-                                       {
-                                               WritePixel(pbDest, fgPel);
-                                       }
-                                       else
-                                       {
-                                               WritePixel(pbDest, GetColorBlack());
-                                       }
-                                       pbDest = NextPixel(pbDest);
-                                       cBits = cBits - 1;
-
-                                       if (cBits > 0)
-                                       {
-                                               if (bitmask & g_MaskBit5)
-                                               {
-                                                       WritePixel(pbDest, fgPel);
-                                               }
-                                               else
-                                               {
-                                                       WritePixel(pbDest, GetColorBlack());
-                                               }
-                                               pbDest = NextPixel(pbDest);
-                                               cBits = cBits - 1;
-
-                                               if (cBits > 0)
-                                               {
-                                                       if (bitmask & g_MaskBit6)
-                                                       {
-                                                               WritePixel(pbDest, fgPel);
-                                                       }
-                                                       else
-                                                       {
-                                                               WritePixel(pbDest, GetColorBlack());
-                                                       }
-                                                       pbDest = NextPixel(pbDest);
-                                                       cBits = cBits - 1;
-
-                                                       if (cBits > 0)
-                                                       {
-                                                               if (bitmask & g_MaskBit7)
-                                                               {
-                                                                       WritePixel(pbDest, fgPel);
-                                                               }
-                                                               else
-                                                               {
-                                                                       WritePixel(pbDest, GetColorBlack());
-                                                               }
-                                                               pbDest = NextPixel(pbDest);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-       return pbDest;
-}
-
-/*
-   Decompress an RLE compressed bitmap.
-*/
-void RleDecompress(uint8 * pbSrcBuffer, uint32 cbSrcBuffer, uint8 * pbDestBuffer, uint32 rowDelta)
-{
-       uint8 * pbSrc = pbSrcBuffer;
-       uint8 * pbEnd = pbSrcBuffer + cbSrcBuffer;
-       uint8 * pbDest = pbDestBuffer;
-
-       PIXEL fgPel = GetColorWhite();
-       boolean fInsertFgPel = False;
-       boolean fFirstLine = True;
-
-       uint8 bitmask;
-       PIXEL pixelA, pixelB;
-
-       uint32 runLength;
-       uint32 code;
-
-       uint32 advance;
-
-       while (pbSrc < pbEnd)
-       {
-               /* Watch out for the end of the first scanline. */
-               if (fFirstLine)
-               {
-                       if (pbDest - pbDestBuffer >= rowDelta)
-                       {
-                               fFirstLine = False;
-                               fInsertFgPel = False;
-                       }
-               }
-
-               /*
-                  Extract the compression order code ID from the compression
-                  order header.
-               */
-               code = ExtractCodeId(*pbSrc);
-
-               /* Handle Background Run Orders. */
-               if (code == REGULAR_BG_RUN || code == MEGA_MEGA_BG_RUN)
-               {
-                       runLength = ExtractRunLength(code, pbSrc, &advance);
-                       pbSrc = pbSrc + advance;
-
-                       if (fFirstLine)
-                       {
-                               if (fInsertFgPel)
-                               {
-                                       WritePixel(pbDest, fgPel);
-                                       pbDest = NextPixel(pbDest);
-                                       runLength = runLength - 1;
-                               }
-                               while (runLength > 0)
-                               {
-                                       WritePixel(pbDest, GetColorBlack());
-                                       pbDest = NextPixel(pbDest);
-                                       runLength = runLength - 1;
-                               }
-                       }
-                       else
-                       {
-                               if (fInsertFgPel)
-                               {
-                                       WritePixel(pbDest, ReadPixel(pbDest - rowDelta) ^ fgPel);
-                                       pbDest = NextPixel(pbDest);
-                                       runLength = runLength - 1;
-                               }
-
-                               while (runLength > 0)
-                               {
-                                       WritePixel(pbDest, ReadPixel(pbDest - rowDelta));
-                                       pbDest = NextPixel(pbDest);
-                                       runLength = runLength - 1;
-                               }
-                       }
-
-                       /*
-                          A follow-on background run order will need a
-                          foreground pel inserted.
-                       */
-                       fInsertFgPel = True;
-                       continue;
-               }
-
-               /*
-                  For any of the other run-types a follow-on background run
-                  order does not need a foreground pel inserted.
-               */
-               fInsertFgPel = False;
-
-               /* Handle Foreground Run Orders. */
-               if (code == REGULAR_FG_RUN || code == MEGA_MEGA_FG_RUN ||
-                       code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
-               {
-                       runLength = ExtractRunLength(code, pbSrc, &advance);
-                       pbSrc = pbSrc + advance;
-
-                       if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
-                       {
-                               fgPel = ReadPixel(pbSrc);
-                               pbSrc = NextPixel(pbSrc);
-                       }
-
-                       while (runLength > 0)
-                       {
-                               if (fFirstLine)
-                               {
-                                       WritePixel(pbDest, fgPel);
-                                       pbDest = NextPixel(pbDest);
-                               }
-                               else
-                               {
-                                       WritePixel(pbDest, ReadPixel(pbDest - rowDelta) ^ fgPel);
-                                       pbDest = NextPixel(pbDest);
-                               }
-
-                               runLength = runLength - 1;
-                       }
-
-                       continue;
-               }
-
-               /* Handle Dithered Run Orders. */
-               if (code == LITE_DITHERED_RUN || code == MEGA_MEGA_DITHERED_RUN)
-               {
-                       runLength = ExtractRunLength(code, pbSrc, &advance);
-                       pbSrc = pbSrc + advance;
-
-                       pixelA = ReadPixel(pbSrc);
-                       pbSrc = NextPixel(pbSrc);
-                       pixelB = ReadPixel(pbSrc);
-                       pbSrc = NextPixel(pbSrc);
-
-                       while (runLength > 0)
-                       {
-                               WritePixel(pbDest, pixelA);
-                               pbDest = NextPixel(pbDest);
-                               WritePixel(pbDest, pixelB);
-                               pbDest = NextPixel(pbDest);
-
-                               runLength = runLength - 1;
-                       }
-
-                       continue;
-               }
-
-               /* Handle Color Run Orders. */
-               if (code == REGULAR_COLOR_RUN || code == MEGA_MEGA_COLOR_RUN)
-               {
-                       runLength = ExtractRunLength(code, pbSrc, &advance);
-                       pbSrc = pbSrc + advance;
-
-                       pixelA = ReadPixel(pbSrc);
-                       pbSrc = NextPixel(pbSrc);
-
-                       while (runLength > 0)
-                       {
-                               WritePixel(pbDest, pixelA);
-                               pbDest = NextPixel(pbDest);
-
-                               runLength = runLength - 1;
-                       }
-
-                       continue;
-               }
-
-               /* Handle Foreground/Background Image Orders. */
-               if (code == REGULAR_FGBG_IMAGE || code == MEGA_MEGA_FGBG_IMAGE ||
-                       code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
-               {
-                       runLength = ExtractRunLength(code, pbSrc, &advance);
-                       pbSrc = pbSrc + advance;
-
-                       if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
-                       {
-                               fgPel = ReadPixel(pbSrc);
-                               pbSrc = NextPixel(pbSrc);
-                       }
-
-                       while (runLength > 8)
-                       {
-                               bitmask = *pbSrc;
-                               pbSrc = pbSrc + 1;
-
-                               if (fFirstLine)
-                               {
-                                       pbDest = WriteFirstLineFgBgImage(pbDest, bitmask, fgPel, 8 );
-                               }
-                               else
-                               {
-                                       pbDest = WriteFgBgImage(pbDest, rowDelta, bitmask, fgPel, 8 );
-                               }
-
-                               runLength = runLength - 8;
-                       }
-
-                       if (runLength > 0)
-                       {
-                               bitmask = *pbSrc;
-                               pbSrc = pbSrc + 1;
-
-                               if (fFirstLine)
-                               {
-                                       pbDest = WriteFirstLineFgBgImage(pbDest, bitmask, fgPel, runLength);
-                               }
-                               else
-                               {
-                                       pbDest = WriteFgBgImage(pbDest, rowDelta, bitmask, fgPel, runLength);
-                               }
-                       }
-                       continue;
-               }
-
-               /* Handle Color Image Orders. */
-               if (code == REGULAR_COLOR_IMAGE || code == MEGA_MEGA_COLOR_IMAGE)
-               {
-                       runLength = ExtractRunLength(code, pbSrc, &advance);
-                       pbSrc = pbSrc + advance;
-                       while (runLength > 0)
-                       {
-                               WritePixel(pbDest, ReadPixel(pbSrc));
-                               pbDest = NextPixel(pbDest);
-                               pbSrc = NextPixel(pbSrc);
-                               runLength = runLength - 1;
-                       }
-                       continue;
-               }
-
-               /* Handle Special Order 1. */
-               if (code == SPECIAL_FGBG_1)
-               {
-                       pbSrc = pbSrc + 1;
-                       if (fFirstLine)
-                       {
-                               pbDest = WriteFirstLineFgBgImage(pbDest, g_MaskSpecialFgBg1, fgPel, 8);
-                       }
-                       else
-                       {
-                               pbDest = WriteFgBgImage(pbDest, rowDelta, g_MaskSpecialFgBg1, fgPel, 8);
-                       }
-                       continue;
-               }
-
-               /* Handle Special Order 2. */
-               if (code == SPECIAL_FGBG_2)
-               {
-                       pbSrc = pbSrc + 1;
-                       if (fFirstLine)
-                       {
-                               pbDest = WriteFirstLineFgBgImage(pbDest, g_MaskSpecialFgBg2, fgPel, 8);
-                       }
-                       else
-                       {
-                               pbDest = WriteFgBgImage(pbDest, rowDelta, g_MaskSpecialFgBg2, fgPel, 8);
-                       }
-                       continue;
-               }
-
-               /* Handle White Order. */
-               if (code == SPECIAL_WHITE)
-               {
-                       pbSrc = pbSrc + 1;
-                       WritePixel(pbDest, GetColorWhite());
-                       pbDest = NextPixel(pbDest);
-                       continue;
-               }
-
-               /* Handle Black Order. */
-               if (code == SPECIAL_BLACK)
-               {
-                       pbSrc = pbSrc + 1;
-                       WritePixel(pbDest, GetColorBlack());
-                       pbDest = NextPixel(pbDest);
-                       continue;
-               }
-       }
-}