#include /****************************************************************************/ /* abdapi.c */ /* */ /* Bitmap Decompression API functions */ /* */ /* Copyright(C) Microsoft Corporation 1996-1999 */ /****************************************************************************/ #define DC_EXTRACT_UINT16_UA(pA) ((unsigned short) (((PBYTE)(pA))[0]) | \ (unsigned short) ((((PBYTE)(pA))[1]) << 8) ) /****************************************************************************/ /* Name: BDMemcpy */ /* */ /* Purpose: Copies a given number of bytes from source to destination. */ /* Source and destination may overlap, but copy is always */ /* performed upwards (from start address onwards). */ /* */ /* Params: pDst - pointer to destination */ /* pSrc - pointer to source data */ /* count - number of bytes to copy */ /****************************************************************************/ _inline void RDPCALL BDMemcpy(PBYTE pDst, PBYTE pSrc, unsigned int count) { #if defined(DC_DEBUG) || defined(DC_NO_UNALIGNED) || defined(_M_IA64) unsigned int i; #endif DC_BEGIN_FN("BDMemcpy"); /************************************************************************/ /* Bitmap decompression deliberately does overlapped memcpys, e.g. */ /* from the previous bitmap row to the current bitmap row for more than */ /* one row. */ /* */ /* When using the intrinsic memcpy (in the retail build) this works */ /* fine (in the current implementation of the MS compiler), as the copy */ /* always goes upwards through memory. However, if we use the MSVC */ /* run-time library (in the debug build) then memcpy appears to check */ /* for overlap and performs the copy so as to avoid clashing of src and */ /* dst (i.e. effectively performs a memmove). Therefore this does not */ /* do what we want, so manually copy the bytes in a debug build. */ /* */ /* This solution is a little unsatisfactory, as the operation of memset */ /* is officially undefined, but the performance-critical nature of */ /* this bit of code means that we really do want to use a memcpy. */ /* */ /* For non-Intel platforms, cannot rely on the above - so always use */ /* manual version. */ /* */ /************************************************************************/ #if defined(DC_DEBUG) || defined(DC_NO_UNALIGNED) || defined(_M_IA64) /************************************************************************/ /* Debug build implementation. */ /************************************************************************/ for (i = 0; i < count; i++) { *pDst++ = *pSrc++; } #else /************************************************************************/ /* Retail build implementation. */ /************************************************************************/ DC_MEMCPY(pDst, pSrc, count); #endif DC_END_FN(); return; } /****************************************************************************/ /* Utility macros for decoding codes */ /****************************************************************************/ #define CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr, trc ) \ {\ if (((BYTE*)(pBuffer)) >= (BYTE*)(pEnd)) { \ BCTRACE( trc ); \ hr = E_FAIL; \ DC_QUIT; \ } \ } #define CHECK_READ_ONE_BYTE_2ENDED(pBuffer, pStart, pEnd, hr, trc ) \ {\ if (((BYTE*)(pBuffer)) >= (BYTE*)(pEnd) || \ (BYTE*)(pBuffer) < (BYTE*)(pStart)) { \ BCTRACE( trc ); \ hr = E_FAIL; \ DC_QUIT; \ } \ } #define CHECK_WRITE_ONE_BYTE(pBuffer, pEnd, hr, trc ) \ {\ if (((BYTE*)(pBuffer)) >= (BYTE*)(pEnd)) { \ BCTRACE( trc ); \ hr = E_FAIL; \ DC_QUIT; \ } \ } #define CHECK_WRITE_ONE_BYTE_NO_HR(pBuffer, pEnd, trc ) \ {\ if (((BYTE*)(pBuffer)) >= (BYTE*)(pEnd)) { \ BCTRACE( trc ); \ DC_QUIT; \ } \ } #define CHECK_READ_N_BYTES(pBuffer, pEnd, N, hr, trc ) \ {\ if (((BYTE*)(pBuffer)) + (N) > (BYTE*)(pEnd)) { \ BCTRACE( trc ); \ hr = E_FAIL; \ DC_QUIT; \ } \ } #define CHECK_READ_N_BYTES_NO_HR(pBuffer, pEnd, N, trc ) \ {\ if (((BYTE*)(pBuffer)) + (N) > (BYTE*)(pEnd)) { \ BCTRACE( trc ); \ DC_QUIT; \ } \ } #define CHECK_READ_N_BYTES_2ENDED(pBuffer, pStart, pEnd, N, hr, trc ) \ {\ if (((BYTE*)(pBuffer)) + (N) > (BYTE*)(pEnd) || \ ((BYTE*)(pBuffer) < (BYTE*)(pStart)) ) { \ BCTRACE( trc ); \ hr = E_FAIL; \ DC_QUIT; \ } \ } #define CHECK_WRITE_N_BYTES(pBuffer, pEnd, N, hr, trc ) \ {\ if (((BYTE*)(pBuffer)) + (N) > (BYTE*)(pEnd)) { \ BCTRACE( trc ); \ hr = E_FAIL; \ DC_QUIT; \ } \ } #define CHECK_WRITE_N_BYTES_NO_HR(pBuffer, pEnd, N, trc ) \ {\ if (((BYTE*)(pBuffer)) + (N) > (BYTE*)(pEnd)) { \ BCTRACE( trc ); \ DC_QUIT; \ } \ } #define BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr, \ (TB, "Decompress reads one byte end of buffer; [p=0x%x pEnd=0x%x]", \ (pBuffer), (pEnd) )) #define BD_CHECK_READ_ONE_BYTE_2ENDED(pBuffer, pStart, pEnd, hr ) \ CHECK_READ_ONE_BYTE_2ENDED(pBuffer, pStart, pEnd, hr, (TB, "Decompress reads one byte off end of buffer; [p=0x%x pStart=0x%x pEnd=0x%x]", \ (pBuffer), (pStart), (pEnd) )) #define BD_CHECK_WRITE_ONE_BYTE(pBuffer, pEnd, hr ) \ CHECK_WRITE_ONE_BYTE(pBuffer, pEnd, hr, (TB, "Decompress writes one byte off end of buffer; [p=0x%x pEnd=0x%x]", \ (pBuffer), (pEnd) )) #define BD_CHECK_READ_N_BYTES(pBuffer, pEnd, N, hr ) \ CHECK_READ_N_BYTES(pBuffer, pEnd, N, hr, (TB, "Decompress reads off end of buffer; [p=0x%x pEnd=0x%x N=%u]", \ (pBuffer), (pEnd), (ULONG)(N))) #define BD_CHECK_READ_N_BYTES_2ENDED(pBuffer, pStart, pEnd, N, hr ) \ CHECK_READ_N_BYTES_2ENDED(pBuffer, pStart, pEnd, N, hr, (TB, "Decompress reads off end of buffer; [p=0x%x pStart=0x%x pEnd=0x%x N=%u]", \ (pBuffer), (pStart), (pEnd), (ULONG)(N) )) #define BD_CHECK_WRITE_N_BYTES(pBuffer, pEnd, N, hr ) \ CHECK_WRITE_N_BYTES(pBuffer, pEnd, N, hr, (TB, "Decompress write off end of buffer; [p=0x%x pEnd=0x%x N=%u]", \ (pBuffer), (pEnd), (ULONG)(N))) /****************************************************************************/ /* Macros to extract the length from order codes */ /****************************************************************************/ #define EXTRACT_LENGTH(pBuffer, pEnd, length, hr) \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ & MAX_LENGTH_ORDER; \ if (length == 0) \ { \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ + MAX_LENGTH_ORDER + 1; \ } #define EXTRACT_LENGTH_LITE(pBuffer, pEnd, length, hr ) \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ & MAX_LENGTH_ORDER_LITE; \ if (length == 0) \ { \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ + MAX_LENGTH_ORDER_LITE + 1; \ } #define EXTRACT_LENGTH_FGBG(pBuffer, pEnd, length, hr ) \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ & MAX_LENGTH_ORDER; \ if (length == 0) \ { \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ + 1; \ } \ else \ { \ length = length << 3; \ } #define EXTRACT_LENGTH_FGBG_LITE(pBuffer, pEnd, length, hr) \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ & MAX_LENGTH_ORDER_LITE; \ if (length == 0) \ { \ BD_CHECK_READ_ONE_BYTE(pBuffer, pEnd, hr ) \ length = *pBuffer++ + 1; \ } \ else \ { \ length = length << 3; \ } /****************************************************************************/ /* Macro to store an FGBG image */ /* This macro expects that the function defines pDst, pEndDst, hr */ /* If there is not enough data to write the full run, this will set error */ /* and quit */ /****************************************************************************/ #define STORE_FGBG(xorbyte, fgbgChar, fgChar, bits) \ { \ unsigned int numbits = bits; \ BD_CHECK_WRITE_N_BYTES( pDst, pEndDst, max(1, min(numbits, 8)), hr ) \ if (fgbgChar & 0x01) \ { \ *pDst++ = (BYTE)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x02) \ { \ *pDst++ = (BYTE)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x04) \ { \ *pDst++ = (BYTE)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x08) \ { \ *pDst++ = (BYTE)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x10) \ { \ *pDst++ = (BYTE)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x20) \ { \ *pDst++ = (BYTE)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x40) \ { \ *pDst++ = (BYTE)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ if (--numbits > 0) \ { \ if (fgbgChar & 0x80) \ { \ *pDst++ = (BYTE)(xorbyte ^ fgChar); \ } \ else \ { \ *pDst++ = xorbyte; \ } \ } \ } \ } \ } \ } \ } \ } \ } #ifdef DC_HICOLOR /****************************************************************************/ /* 8bpp decompression */ /****************************************************************************/ #define BCTRACE(string) _inline HRESULT RDPCALL BDDecompressBitmap8( PBYTE pSrc, PBYTE pDstBuffer, unsigned int compressedDataSize, unsigned int dstBufferSize, BYTE bitmapBitsPerPel, unsigned short rowDelta) { HRESULT hr = S_OK; unsigned int codeLength; BYTE codeByte; BYTE codeByte2; BYTE decode; BYTE decodeLite; BYTE decodeMega; BYTE fgChar; PBYTE pDst; PBYTE pEndSrc; PBYTE pEndDst; BOOL backgroundNeedsPel; BOOL firstLine; DC_BEGIN_FN("BDDecompressBitmap8"); pEndSrc = pSrc + compressedDataSize; pDst = pDstBuffer; pEndDst = pDst + dstBufferSize; fgChar = 0xFF; backgroundNeedsPel = FALSE; firstLine = TRUE; /************************************************************************/ /* */ /* Main decompression loop */ /* */ /************************************************************************/ while (pSrc < pEndSrc) { /********************************************************************/ /* While we are processing the first line we should keep a look out */ /* for the end of the line */ /********************************************************************/ if (firstLine) { if ((unsigned int)(pDst - pDstBuffer) >= rowDelta) { firstLine = FALSE; backgroundNeedsPel = FALSE; } } /********************************************************************/ /* Get the decode */ /********************************************************************/ BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); decode = (BYTE)(*pSrc & CODE_MASK); decodeLite = (BYTE)(*pSrc & CODE_MASK_LITE); decodeMega = (BYTE)(*pSrc); /********************************************************************/ /* BG RUN */ /********************************************************************/ if ((decode == CODE_BG_RUN) || (decodeMega == CODE_MEGA_MEGA_BG_RUN)) { if (decode == CODE_BG_RUN) { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } else { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } BCTRACE((TB, "Background run %u",codeLength)); if (!firstLine) { if (backgroundNeedsPel) { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr); *pDst++ = (BYTE)(*(pDst - rowDelta) ^ fgChar); codeLength--; } BD_CHECK_READ_N_BYTES_2ENDED(pDst-rowDelta, pDstBuffer, pEndDst, codeLength, hr) BD_CHECK_WRITE_N_BYTES( pDst, pEndDst, codeLength, hr) BDMemcpy(pDst, pDst-rowDelta, codeLength); pDst += codeLength; } else { if (backgroundNeedsPel) { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr) *pDst++ = fgChar; codeLength--; } BD_CHECK_WRITE_N_BYTES( pDst, pEndDst, codeLength, hr) memset(pDst, 0x00, codeLength); pDst += codeLength; } /****************************************************************/ /* A follow on BG run will need a pel inserted */ /****************************************************************/ backgroundNeedsPel = TRUE; continue; } /********************************************************************/ /* For any of the other runtypes a follow on BG run does not need */ /* a FG pel inserted */ /********************************************************************/ backgroundNeedsPel = FALSE; /********************************************************************/ /* FGBG IMAGE */ /********************************************************************/ if ((decode == CODE_FG_BG_IMAGE) || (decodeLite == CODE_SET_FG_FG_BG) || (decodeMega == CODE_MEGA_MEGA_FGBG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { if ((decodeMega == CODE_MEGA_MEGA_FGBG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_BG_IMAGE) { EXTRACT_LENGTH_FGBG(pSrc, pEndSrc, codeLength, hr); } else { EXTRACT_LENGTH_FGBG_LITE(pSrc, pEndSrc, codeLength, hr); } } if ((decodeLite == CODE_SET_FG_FG_BG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); fgChar = *pSrc++; BCTRACE((TB, "Set FGBG image %u",codeLength)); } else { BCTRACE((TB, "FGBG image %u",codeLength)); } while (codeLength > 8) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; if (firstLine) { STORE_FGBG(0x00, codeByte, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED( pDst-rowDelta, pDstBuffer, pEndDst, hr ) STORE_FGBG(*(pDst - rowDelta), codeByte, fgChar, 8); } codeLength -= 8; } if (codeLength > 0) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; if (firstLine) { STORE_FGBG(0x00, codeByte, fgChar, codeLength); } else { BD_CHECK_READ_ONE_BYTE_2ENDED( pDst -rowDelta, pDstBuffer, pEndDst, hr ) STORE_FGBG(*(pDst - rowDelta), codeByte, fgChar, codeLength); } } continue; } /********************************************************************/ /* FG RUN */ /********************************************************************/ if ((decode == CODE_FG_RUN) || (decodeLite == CODE_SET_FG_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { if ((decodeMega == CODE_MEGA_MEGA_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_RUN) { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } else { EXTRACT_LENGTH_LITE(pSrc, pEndSrc, codeLength, hr); } } /****************************************************************/ /* Push the old fgChar down to the ALT position */ /****************************************************************/ if ((decodeLite == CODE_SET_FG_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); BCTRACE((TB, "Set FG run %u",codeLength)); fgChar = *pSrc++; } else { BCTRACE((TB, "FG run %u",codeLength)); } BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) while (codeLength-- > 0) { if (!firstLine) { BD_CHECK_READ_ONE_BYTE_2ENDED((pDst -rowDelta), pDstBuffer, pEndDst, hr) *pDst++ = (BYTE)(*(pDst - rowDelta) ^ fgChar); } else { *pDst++ = fgChar; } } continue; } /********************************************************************/ /* DITHERED RUN */ /********************************************************************/ if ((decodeLite == CODE_DITHERED_RUN) || (decodeMega == CODE_MEGA_MEGA_DITHER)) { if (decodeMega == CODE_MEGA_MEGA_DITHER) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH_LITE(pSrc, pEndSrc, codeLength, hr); } BCTRACE((TB, "Dithered run %u",codeLength)); BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, 2, hr); codeByte = *pSrc++; codeByte2 = *pSrc++; BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength * 2, hr) while (codeLength-- > 0) { *pDst++ = codeByte; *pDst++ = codeByte2; } continue; } /********************************************************************/ /* COLOR IMAGE */ /********************************************************************/ if ((decode == CODE_COLOR_IMAGE) || (decodeMega == CODE_MEGA_MEGA_CLR_IMG)) { if (decodeMega == CODE_MEGA_MEGA_CLR_IMG) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } BCTRACE((TB, "Color image %u",codeLength)); BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, codeLength, hr) BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) BDMemcpy(pDst, pSrc, codeLength); pDst += codeLength; pSrc += codeLength; continue; } /********************************************************************/ /* COLOR RUN */ /********************************************************************/ if ((decode == CODE_COLOR_RUN) || (decodeMega == CODE_MEGA_MEGA_COLOR_RUN)) { if (decodeMega == CODE_MEGA_MEGA_COLOR_RUN) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } BCTRACE((TB, "Color run %u",codeLength)); BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr) codeByte = *pSrc++; BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) memset(pDst, codeByte, codeLength); pDst += codeLength; continue; } /********************************************************************/ /* If we get here then the code must be a special one */ /********************************************************************/ BCTRACE((TB, "Special code %#x",decodeMega)); switch (decodeMega) { case CODE_BLACK: { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = 0x00; } break; case CODE_WHITE: { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = 0xFF; } break; /****************************************************************/ /* Ignore the unreachable code warnings that follow */ /* Simply because we use the STORE_FGBG macro with a constant */ /* value */ /****************************************************************/ case CODE_SPECIAL_FGBG_1: { if (firstLine) { STORE_FGBG(0x00, SPECIAL_FGBG_CODE_1, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst-rowDelta, pDstBuffer, pEndDst, hr); STORE_FGBG(*(pDst - rowDelta), SPECIAL_FGBG_CODE_1, fgChar, 8); } } break; case CODE_SPECIAL_FGBG_2: { if (firstLine) { STORE_FGBG(0x00, SPECIAL_FGBG_CODE_2, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst-rowDelta, pDstBuffer, pEndDst, hr); STORE_FGBG(*(pDst - rowDelta), SPECIAL_FGBG_CODE_2, fgChar, 8); } } break; default: { BCTRACE((TB, "Invalid compression data %x",decodeMega)); } break; } pSrc++; } BCTRACE((TB, "Decompressed to %d", pDst-pDstBuffer)); DC_EXIT_POINT: DC_END_FN(); return hr; } /****************************************************************************/ /* 15bpp decompression */ /****************************************************************************/ _inline HRESULT RDPCALL BDDecompressBitmap15(PBYTE pSrc, PBYTE pDstBuffer, unsigned int srcDataSize, unsigned int dstBufferSize, unsigned short rowDelta) /****************************************************************************/ /* Function name */ /****************************************************************************/ #define BC_FN_NAME "BDDecompressBitmap15" /****************************************************************************/ /* Data type of a pixel */ /****************************************************************************/ #define BC_PIXEL unsigned short /****************************************************************************/ /* Length in bytes of a pixel */ /****************************************************************************/ #define BC_PIXEL_LEN 2 /****************************************************************************/ /* Default fgPel */ /****************************************************************************/ #define BC_DEFAULT_FGPEL 0x0000FF7F /****************************************************************************/ /* Macro to move to the next pixel in the buffer (modifies pPos) */ /****************************************************************************/ #define BC_TO_NEXT_PIXEL(pPos) pPos += 2 /****************************************************************************/ /* Macro to returns the value of the pixel at pPos (doesn't modify pPos) */ /****************************************************************************/ #define BC_GET_PIXEL(pPos) ((unsigned short) (((PBYTE)(pPos))[1]) | \ (unsigned short) ((((PBYTE)(pPos))[0]) << 8) ) /****************************************************************************/ /* Macro to insert a pixel value pel at position pPos (doesn't modify pPos) */ /* */ /* pel may well be an expression (e.g. a BC_GET_PIXEL macro) so evaluate */ /* it once into a local variable. */ /****************************************************************************/ #define BC_SET_PIXEL(pPos, pel) \ { \ BC_PIXEL val = pel; \ (((PBYTE)(pPos))[1]) = (BYTE)( (val) & 0x00FF); \ (((PBYTE)(pPos))[0]) = (BYTE)(((val)>>8) & 0x00FF); \ } /****************************************************************************/ /* Include the function body */ /****************************************************************************/ #include /****************************************************************************/ /* Undefine everything */ /****************************************************************************/ #undef BC_FN_NAME #undef BC_PIXEL #undef BC_PIXEL_LEN #undef BC_TO_NEXT_PIXEL #undef BC_GET_PIXEL #undef BC_SET_PIXEL #undef BC_DEFAULT_FGPEL /****************************************************************************/ /* 16bpp decompression */ /****************************************************************************/ _inline HRESULT BDDecompressBitmap16(PBYTE pSrc, PBYTE pDstBuffer, unsigned int srcDataSize, unsigned int dstBufferSize, unsigned short rowDelta) /****************************************************************************/ /* Function name */ /****************************************************************************/ #define BC_FN_NAME "BDDecompressBitmap16" /****************************************************************************/ /* Data type of a pixel */ /****************************************************************************/ #define BC_PIXEL unsigned short /****************************************************************************/ /* Length in bytes of a pixel */ /****************************************************************************/ #define BC_PIXEL_LEN 2 /****************************************************************************/ /* Default fgPel */ /****************************************************************************/ #define BC_DEFAULT_FGPEL 0x0000FFFF /****************************************************************************/ /* Macro to move to the next pixel in the buffer (modifies pPos) */ /****************************************************************************/ #define BC_TO_NEXT_PIXEL(pPos) pPos += 2 /****************************************************************************/ /* Macro to returns the value of the pixel at pPos (doesn't modify pPos) */ /****************************************************************************/ #define BC_GET_PIXEL(pPos) ((unsigned short) (((PBYTE)(pPos))[1]) | \ (unsigned short) ((((PBYTE)(pPos))[0]) << 8) ) /****************************************************************************/ /* Macro to insert a pixel value pel at position pPos (doesn't modify pPos) */ /* */ /* pel may well be an expression (e.g. a BC_GET_PIXEL macro) so evaluate */ /* it once into a local variable. */ /****************************************************************************/ #define BC_SET_PIXEL(pPos, pel) \ { \ BC_PIXEL val = pel; \ (((PBYTE)(pPos))[1]) = (BYTE)( (val) & 0x00FF); \ (((PBYTE)(pPos))[0]) = (BYTE)(((val)>>8) & 0x00FF); \ } /****************************************************************************/ /* Include the function body */ /****************************************************************************/ #include /****************************************************************************/ /* Undefine everything */ /****************************************************************************/ #undef BC_FN_NAME #undef BC_PIXEL #undef BC_PIXEL_LEN #undef BC_TO_NEXT_PIXEL #undef BC_GET_PIXEL #undef BC_SET_PIXEL #undef BC_DEFAULT_FGPEL /****************************************************************************/ /* 24bpp decompression */ /****************************************************************************/ _inline HRESULT BDDecompressBitmap24(PBYTE pSrc, PBYTE pDstBuffer, unsigned int srcDataSize, unsigned int dstBufferSize, unsigned short rowDelta) /****************************************************************************/ /* Function name */ /****************************************************************************/ #define BC_FN_NAME "BDDecompressBitmap24" /****************************************************************************/ /* Data type of a pixel */ /****************************************************************************/ #define BC_PIXEL TSUINT32 /****************************************************************************/ /* Length in bytes of a pixel */ /****************************************************************************/ #define BC_PIXEL_LEN 3 /****************************************************************************/ /* Default fgPel */ /****************************************************************************/ #define BC_DEFAULT_FGPEL 0x00FFFFFF /****************************************************************************/ /* Macro to move to the next pixel in the buffer (modifies pPos) */ /****************************************************************************/ #define BC_TO_NEXT_PIXEL(pPos) pPos += 3 /****************************************************************************/ /* Macro to returns the value of the pixel at pPos (doesn't modify pPos) */ /****************************************************************************/ #define BC_GET_PIXEL(pPos) ( \ (TSUINT32) ( (unsigned short)(((PBYTE)(pPos))[2]) ) | \ (TSUINT32) (((unsigned short)(((PBYTE)(pPos))[1])) << 8) | \ (TSUINT32) (((TSUINT32)(((PBYTE)(pPos))[0])) << 16) ) /****************************************************************************/ /* Macro to insert a pixel value pel at position pPos (doesn't modify pPos) */ /* */ /* pel may well be an expression (e.g. a BC_GET_PIXEL macro) so evaluate */ /* it once into a local variable. */ /****************************************************************************/ #define BC_SET_PIXEL(pPos, pel) \ { \ BC_PIXEL val = pel; \ (((PBYTE)(pPos))[2]) = (BYTE)((val) & 0x000000FF); \ (((PBYTE)(pPos))[1]) = (BYTE)(((val)>>8) & 0x000000FF); \ (((PBYTE)(pPos))[0]) = (BYTE)(((val)>>16) & 0x000000FF); \ } /****************************************************************************/ /* Include the function body */ /****************************************************************************/ #include /****************************************************************************/ /* Undefine everything */ /****************************************************************************/ #undef BC_FN_NAME #undef BC_PIXEL #undef BC_PIXEL_LEN #undef BC_TO_NEXT_PIXEL #undef BC_GET_PIXEL #undef BC_SET_PIXEL #undef BC_DEFAULT_FGPEL /****************************************************************************/ /* Name: BD_DecompressBitmap */ /* */ /* Purpose: Decompresses compressed bitmap data */ /* */ /* Params: IN - pCompressedData: pointer to compressed bitmap data */ /* OUT - pDstBitmap: pointer to buffer for decompressed data */ /* IN - srcDataSize: the compressed data size */ /* IN - bitmapBitsPerPel: the bits per pel of the data */ /****************************************************************************/ HRESULT BD_DecompressBitmap( #ifndef DLL_DISP PTSHARE_WD m_pTSWd, #endif PBYTE pCompressedData, PBYTE pDstBuffer, unsigned int srcDataSize, unsigned int dstBufferSize, unsigned int noBCHeader, BYTE bitmapBitsPerPel, unsigned short bitmapWidth, unsigned short bitmapHeight) { HRESULT hr = S_OK; PBYTE pSrc; unsigned short rowDelta; unsigned int compressedDataSize; PTS_CD_HEADER pCompDataHeader; #ifdef DC_NO_UNALIGNED TS_CD_HEADER compDataHeader; #endif DC_BEGIN_FN("BD_DecompressBitmap"); TRC_ASSERT( (pCompressedData != NULL), (TB, "Invalid pCompressedData(%p)", pCompressedData) ); TRC_ASSERT( (pDstBuffer != NULL), (TB, "Invalid pDstBuffer(%p)", pDstBuffer) ); TRC_ASSERT( (dstBufferSize != 0), (TB, "Invalid dstBufferSize(%u)", dstBufferSize) ); TRC_ASSERT( (srcDataSize != 0), (TB, "Invalid srcDataSize(%u)", srcDataSize) ); TRC_ASSERT( (dstBufferSize != 0), (TB, "Invalid dstBufferSize(%u)", dstBufferSize) ); #ifdef DC_HICOLOR #else TRC_ASSERT( (bitmapBitsPerPel == 8), (TB, "Invalid bitmapBitsPerPel(%u)", bitmapBitsPerPel) ); #endif /************************************************************************/ /* Initialize variables before main loop. */ /* */ /* No bitmap compression header included */ /************************************************************************/ if (noBCHeader) { compressedDataSize = srcDataSize; pSrc = pCompressedData; rowDelta = TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel); } else { /************************************************************************/ /* Work out the location in the source data of each component. */ /* Make sure this is naturally aligned (for RISC platforms) */ /************************************************************************/ BD_CHECK_READ_N_BYTES(pCompressedData, pCompressedData + srcDataSize, sizeof(TS_CD_HEADER), hr ); #ifdef DC_NO_UNALIGNED DC_MEMCPY(&compDataHeader, pCompressedData, sizeof(TS_CD_HEADER)); pCompDataHeader = &compDataHeader; #else pCompDataHeader = (PTS_CD_HEADER)pCompressedData; #endif /********************************************************************/ /* Bitmap compression header included */ /********************************************************************/ compressedDataSize = pCompDataHeader->cbCompMainBodySize; BD_CHECK_READ_N_BYTES(pCompressedData, pCompressedData + srcDataSize, compressedDataSize + sizeof(TS_CD_HEADER), hr ); pSrc = pCompressedData + sizeof(TS_CD_HEADER); rowDelta = pCompDataHeader->cbScanWidth; if (rowDelta != TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel)) { TRC_ABORT((TB, "rowDelta in TS_CD_HEADER incorrect " "[got %u expected %u]", rowDelta, TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel))); hr = E_FAIL; DC_QUIT; } } /************************************************************************/ /* Call the appropriate decompress function, based on the color depth */ /************************************************************************/ switch (bitmapBitsPerPel) { case 24: { hr = BDDecompressBitmap24 (pSrc, pDstBuffer, compressedDataSize, dstBufferSize, rowDelta); } break; case 16: { hr = BDDecompressBitmap16 (pSrc, pDstBuffer, compressedDataSize, dstBufferSize, rowDelta); } break; case 15: { hr = BDDecompressBitmap15 (pSrc, pDstBuffer, compressedDataSize, dstBufferSize, rowDelta); } break; case 8: default: { hr = BDDecompressBitmap8 (pSrc, pDstBuffer, compressedDataSize, dstBufferSize, bitmapBitsPerPel, rowDelta); } break; } DC_EXIT_POINT: return hr; } #else /****************************************************************************/ /* Name: BD_DecompressBitmap */ /* */ /* Purpose: Decompresses compressed bitmap data */ /* */ /* Params: IN - pCompressedData: pointer to compressed bitmap data */ /* OUT - pDstBitmap: pointer to buffer for decompressed data */ /* IN - srcDataSize: the compressed data size */ /* IN - bitmapBitsPerPel: the bits per pel of the data */ /****************************************************************************/ HRESULT RDPCALL BD_DecompressBitmap( PBYTE pCompressedData, PBYTE pDstBuffer, unsigned int srcDataSize, unsigned int dstBufferSize, unsigned int noBCHeader, BYTE bitmapBitsPerPel, unsigned short bitmapWidth, unsigned short bitmapHeight ) { HRESULT hr = S_OK; #ifdef DC_NO_UNALIGNED TS_CD_HEADER compDataHeader; #endif PTS_CD_HEADER pCompDataHeader; unsigned int compressedDataSize; unsigned int codeLength; BYTE codeByte; BYTE codeByte2; BYTE decode; BYTE decodeLite; BYTE decodeMega; BYTE fgChar; PBYTE pSrc; PBYTE pDst; PBYTE pEndSrc; PBYTE pEndDst; BOOL backgroundNeedsPel; BOOL firstLine; unsigned int rowDelta; DC_BEGIN_FN("BD_DecompressBitmap"); TRC_ASSERT( (pCompressedData != NULL), (TB, "Invalid pCompressedData(%p)", pCompressedData) ); TRC_ASSERT( (pDstBuffer != NULL), (TB, "Invalid pDstBuffer(%p)", pDstBuffer) ); TRC_ASSERT( (srcDataSize != 0), (TB, "Invalid srcDataSize(%u)", srcDataSize) ); TRC_ASSERT( (dstBufferSize != 0), (TB, "Invalid dstBufferSize(%u)", dstBufferSize) ); TRC_ASSERT( (bitmapBitsPerPel == 8), (TB, "Invalid bitmapBitsPerPel(%u)", bitmapBitsPerPel) ); /************************************************************************/ /* Trace the important parameters. */ /************************************************************************/ TRC_DBG((TB, "pData(%p) pDst(%p) cbSrc(%u) cbDst(%u)", pCompressedData, pDstBuffer, srcDataSize, dstBufferSize)); /************************************************************************/ /* Initialize variables before main loop. */ /************************************************************************/ // no bitmap compression header included if (noBCHeader) { compressedDataSize = srcDataSize; pSrc = pCompressedData; rowDelta = TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel); } // bitmap compression header included else { /************************************************************************/ /* Work out the location in the source data of each component. */ /* Make sure this is naturally aligned (for RISC platforms) */ /************************************************************************/ BD_CHECK_READ_N_BYTES(pCompressedData, pCompressedData + srcDataSize, sizeof(TS_CD_HEADER), hr ); #ifdef DC_NO_UNALIGNED DC_MEMCPY(&compDataHeader, pCompressedData, sizeof(TS_CD_HEADER)); pCompDataHeader = &compDataHeader; #else pCompDataHeader = (PTS_CD_HEADER)pCompressedData; #endif compressedDataSize = pCompDataHeader->cbCompMainBodySize; BD_CHECK_READ_N_BYTES(pCompressedData, pCompressedData + srcDataSize, compressedDataSize + sizeof(TS_CD_HEADER), hr ); pSrc = pCompressedData + sizeof(TS_CD_HEADER); rowDelta = pCompDataHeader->cbScanWidth; if (rowDelta != TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel)) { TRC_ABORT((TB, "rowDelta in TS_CD_HEADER incorrect " "[got %u expected %u]", rowDelta, TS_BYTES_IN_SCANLINE(bitmapWidth, bitmapBitsPerPel))); hr = E_FAIL; DC_QUIT; } } pEndSrc = pSrc + compressedDataSize; pDst = pDstBuffer; pEndDst = pDst + dstBufferSize; fgChar = 0xFF; backgroundNeedsPel = FALSE; firstLine = TRUE; /************************************************************************/ /* */ /* Main decompression loop */ /* */ /************************************************************************/ while(pSrc < pEndSrc) { /********************************************************************/ /* While we are processing the first line we should keep a look out */ /* for the end of the line */ /********************************************************************/ if (firstLine) { if ((unsigned int)(pDst - pDstBuffer) >= rowDelta) { firstLine = FALSE; backgroundNeedsPel = FALSE; } } /********************************************************************/ /* Get the decode */ /********************************************************************/ BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); decode = (BYTE)(*pSrc & CODE_MASK); decodeLite = (BYTE)(*pSrc & CODE_MASK_LITE); decodeMega = (BYTE)(*pSrc); /********************************************************************/ /* BG RUN */ /********************************************************************/ if ((decode == CODE_BG_RUN) || (decodeMega == CODE_MEGA_MEGA_BG_RUN)) { if (decode == CODE_BG_RUN) { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } else { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } TRC_DBG((TB, "Background run %u",codeLength)); if (!firstLine) { if (backgroundNeedsPel) { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr); *pDst++ = (BYTE)(*(pDst - rowDelta) ^ fgChar); codeLength--; } BD_CHECK_READ_N_BYTES_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, codeLength, hr); BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr); BDMemcpy(pDst, pDst-rowDelta, codeLength); pDst += codeLength; } else { if (backgroundNeedsPel) { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = fgChar; codeLength--; } BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr); memset(pDst, 0x00, codeLength); pDst += codeLength; } /****************************************************************/ /* A follow on BG run will need a pel inserted */ /****************************************************************/ backgroundNeedsPel = TRUE; continue; } /********************************************************************/ /* For any of the other runtypes a follow on BG run does not need */ /* a FG pel inserted */ /********************************************************************/ backgroundNeedsPel = FALSE; /********************************************************************/ /* FGBG IMAGE */ /********************************************************************/ if ((decode == CODE_FG_BG_IMAGE) || (decodeLite == CODE_SET_FG_FG_BG) || (decodeMega == CODE_MEGA_MEGA_FGBG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { if ((decodeMega == CODE_MEGA_MEGA_FGBG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_BG_IMAGE) { EXTRACT_LENGTH_FGBG(pSrc, pEndSrc, codeLength, hr); } else { EXTRACT_LENGTH_FGBG_LITE(pSrc, pEndSrc, codeLength, hr); } } if ((decodeLite == CODE_SET_FG_FG_BG) || (decodeMega == CODE_MEGA_MEGA_SET_FGBG)) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); fgChar = *pSrc++; TRC_DBG((TB, "Set FGBG image %u",codeLength)); } else { TRC_DBG((TB, "FGBG image %u",codeLength)); } while (codeLength > 8) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; if (firstLine) { STORE_FGBG(0x00, codeByte, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) STORE_FGBG(*(pDst - rowDelta), codeByte, fgChar, 8); } codeLength -= 8; } if (codeLength > 0) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; if (firstLine) { STORE_FGBG(0x00, codeByte, fgChar, codeLength); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) STORE_FGBG(*(pDst - rowDelta), codeByte, fgChar, codeLength); } } continue; } /********************************************************************/ /* FG RUN */ /********************************************************************/ if ((decode == CODE_FG_RUN) || (decodeLite == CODE_SET_FG_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { if ((decodeMega == CODE_MEGA_MEGA_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { if (decode == CODE_FG_RUN) { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } else { EXTRACT_LENGTH_LITE(pSrc, pEndSrc, codeLength, hr); } } /****************************************************************/ /* Push the old fgChar down to the ALT position */ /****************************************************************/ if ((decodeLite == CODE_SET_FG_FG_RUN) || (decodeMega == CODE_MEGA_MEGA_SET_FG_RUN)) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); TRC_DBG((TB, "Set FG run %u",codeLength)); fgChar = *pSrc++; } else { TRC_DBG((TB, "FG run %u",codeLength)); } BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr) while (codeLength-- > 0) { if (!firstLine) { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) *pDst++ = (BYTE)(*(pDst - rowDelta) ^ fgChar); } else { *pDst++ = fgChar; } } continue; } /********************************************************************/ /* DITHERED RUN */ /********************************************************************/ if ((decodeLite == CODE_DITHERED_RUN) || (decodeMega == CODE_MEGA_MEGA_DITHER)) { if (decodeMega == CODE_MEGA_MEGA_DITHER) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH_LITE(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, "Dithered run %u",codeLength)); BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, 2, hr); codeByte = *pSrc++; codeByte2 = *pSrc++; BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength * 2, hr) while (codeLength-- > 0) { *pDst++ = codeByte; *pDst++ = codeByte2; } continue; } /********************************************************************/ /* COLOR IMAGE */ /********************************************************************/ if ((decode == CODE_COLOR_IMAGE) || (decodeMega == CODE_MEGA_MEGA_CLR_IMG)) { if (decodeMega == CODE_MEGA_MEGA_CLR_IMG) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, "Color image %u",codeLength)); BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, codeLength, hr); BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr); BDMemcpy(pDst, pSrc, codeLength); pDst += codeLength; pSrc += codeLength; continue; } /********************************************************************/ /* PACKED COLOR IMAGE */ /********************************************************************/ if ((decode == CODE_PACKED_COLOR_IMAGE) || (decodeMega == CODE_MEGA_MEGA_PACKED_CLR)) { if (decodeMega == CODE_MEGA_MEGA_PACKED_CLR) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, "Packed color %u",codeLength)); if (bitmapBitsPerPel == 4) { unsigned int worklen = (codeLength)/2; BYTE workchar; BD_CHECK_READ_N_BYTES(pSrc, pEndSrc, worklen, hr); BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, worklen * 2, hr); while (worklen--) { workchar = *pSrc++; *pDst++ = (BYTE)(workchar >> 4); *pDst++ = (BYTE)(workchar & 0x0F); } if (codeLength & 0x0001) { BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = (BYTE)(*pSrc++>>4); } } else { TRC_ERR((TB, "Don't support packed color for 8bpp")); } continue; } /********************************************************************/ /* COLOR RUN */ /********************************************************************/ if ((decode == CODE_COLOR_RUN) || (decodeMega == CODE_MEGA_MEGA_COLOR_RUN)) { if (decodeMega == CODE_MEGA_MEGA_COLOR_RUN) { BD_CHECK_READ_N_BYTES(pSrc+1, pEndSrc, 2, hr); codeLength = DC_EXTRACT_UINT16_UA(pSrc+1); pSrc += 3; } else { EXTRACT_LENGTH(pSrc, pEndSrc, codeLength, hr); } TRC_DBG((TB, "Color run %u",codeLength)); BD_CHECK_READ_ONE_BYTE(pSrc, pEndSrc, hr); codeByte = *pSrc++; BD_CHECK_WRITE_N_BYTES(pDst, pEndDst, codeLength, hr); memset(pDst, codeByte, codeLength); pDst += codeLength; continue; } /********************************************************************/ /* If we get here then the code must be a special one */ /********************************************************************/ TRC_DBG((TB, "Special code %#x",decodeMega)); switch (decodeMega) { case CODE_BLACK: { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = 0x00; } break; case CODE_WHITE: { BD_CHECK_WRITE_ONE_BYTE(pDst, pEndDst, hr); *pDst++ = 0xFF; } break; /****************************************************************/ /* Ignore the unreachable code warnings that follow */ /* Simply because we use the STORE_FGBG macro with a constant */ /* value */ /****************************************************************/ case CODE_SPECIAL_FGBG_1: { if (firstLine) { STORE_FGBG(0x00, SPECIAL_FGBG_CODE_1, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) STORE_FGBG(*(pDst - rowDelta), SPECIAL_FGBG_CODE_1, fgChar, 8); } } break; case CODE_SPECIAL_FGBG_2: { if (firstLine) { STORE_FGBG(0x00, SPECIAL_FGBG_CODE_2, fgChar, 8); } else { BD_CHECK_READ_ONE_BYTE_2ENDED(pDst - rowDelta, pDstBuffer, pEndDst, hr) STORE_FGBG(*(pDst - rowDelta), SPECIAL_FGBG_CODE_2, fgChar, 8); } } break; default: { TRC_ERR((TB, "Invalid compression data %x",decodeMega)); } break; } pSrc++; } TRC_DBG((TB, "Decompressed to %d", pDst-pDstBuffer)); DC_EXIT_POINT: DC_END_FN(); return hr; } #endif #ifdef OS_WINDOWS #pragma warning (default: 4127) #endif /* OS_WINDOWS */