tpkt.h
transport.c
transport.h
+ rle_bitmap_stream.c
)
include_directories(../libfreerdp-asn1)
--- /dev/null
+/**
+ * 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;
+}
--- /dev/null
+/**
+ * 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;
+ }
+ }
+}
+++ /dev/null
-/**
- * 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;
- }
- }
-}