Index: surface.c =================================================================== --- surface.c (revision 47056) +++ surface.c (working copy) @@ -204,81 +204,29 @@ return NewBitmap; } -VOID Decompress4bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta) +BOOL DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta, ULONG Format) { - int x = 0; - int y = Size.cy - 1; - int c; - int length; - int width = ((Size.cx+1)/2); - int height = Size.cy - 1; + INT x = 0; + INT y = Size.cy - 1; + INT c; + INT length; + INT width; + INT height = Size.cy - 1; BYTE *begin = CompressedBits; BYTE *bits = CompressedBits; BYTE *temp; - while (y >= 0) - { - length = *bits++ / 2; - if (length) - { - c = *bits++; - while (length--) - { - if (x >= width) break; - temp = UncompressedBits + (((height - y) * Delta) + x); - x++; - *temp = c; - } - } - else - { - length = *bits++; - switch (length) - { - case RLE_EOL: - x = 0; - y--; - break; - case RLE_END: - return; - case RLE_DELTA: - x += (*bits++)/2; - y -= (*bits++)/2; - break; - default: - length /= 2; - while (length--) - { - c = *bits++; - if (x < width) - { - temp = UncompressedBits + (((height - y) * Delta) + x); - x++; - *temp = c; - } - } - if ((bits - begin) & 1) - { - bits++; - } - } - } - } -} + INT shift = 0; -VOID Decompress8bpp(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta) -{ - int x = 0; - int y = Size.cy - 1; - int c; - int length; - int width = Size.cx; - int height = Size.cy - 1; - BYTE *begin = CompressedBits; - BYTE *bits = CompressedBits; - BYTE *temp; + if (Format == BMF_4RLE) + shift = 1; + else if(Format != BMF_8RLE) + return FALSE; + + width = ((Size.cx + shift) >> shift); + while (y >= 0) { - length = *bits++; + length = (*bits++) >> shift; if (length) { c = *bits++; @@ -300,12 +248,13 @@ y--; break; case RLE_END: - return; + return TRUE; case RLE_DELTA: - x += *bits++; - y -= *bits++; + x += (*bits++) >> shift; + y -= (*bits++) >> shift; break; default: + length = length >> shift; while (length--) { c = *bits++; @@ -323,6 +272,7 @@ } } } + return TRUE; } HBITMAP FASTCALL @@ -362,7 +312,7 @@ pso->cjBits = pso->lDelta * Size.cy; UncompressedFormat = BMF_4BPP; UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB); - Decompress4bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta); + DecompressBitmap(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta, BMF_4BPP); } else if (Format == BMF_8RLE) { @@ -370,7 +320,7 @@ pso->cjBits = pso->lDelta * Size.cy; UncompressedFormat = BMF_8BPP; UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB); - Decompress8bpp(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta); + DecompressBitmap(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta, BMF_8RLE); } else { @@ -467,6 +417,7 @@ PSURFACE psurf; SIZEL LocalSize; BOOLEAN AllocatedLocally = FALSE; + PVOID DecompressedBits = NULL; /* * First, check the format so we can get the aligned scanline width. @@ -500,17 +451,29 @@ break; case BMF_8RLE: + ScanLine = (BitmapInfo->Width + 3) & ~3; + Compressed = TRUE; + break; case BMF_4RLE: - case BMF_JPEG: - case BMF_PNG: + ScanLine = ((BitmapInfo->Width + 7) & ~7) >> 1; Compressed = TRUE; break; + case BMF_JPEG: + case BMF_PNG: + ASSERT(FALSE); // ENGDDI shouldn't be creating PNGs for drivers ;-) + DPRINT1("No support for JPEG and PNG formats\n"); + return NULL; + default: DPRINT1("Invalid bitmap format\n"); return NULL; } + /* Save local bitmap size */ + LocalSize.cy = BitmapInfo->Height; + LocalSize.cx = BitmapInfo->Width; + /* Does the device manage its own surface? */ if (!Bits) { @@ -519,7 +482,8 @@ { /* Note: we should not be seeing this scenario from ENGDDI */ ASSERT(FALSE); - Size = BitmapInfo->Size; + DPRINT1("RLE compressed bitmap requested with no valid bitmap bits\n"); + return NULL; } else { @@ -551,6 +515,22 @@ { /* Should not have asked for user memory */ ASSERT((BitmapInfo->Flags & BMF_USERMEM) == 0); + + if (Compressed) + { + DecompressedBits = EngAllocMem(FL_ZERO_MEMORY, BitmapInfo->Height * ScanLine, TAG_DIB); + + if(!Bits) + return NULL; + + if(!DecompressBitmap(LocalSize, (BYTE *)Bits, (BYTE *)DecompressedBits, ScanLine, BitmapInfo->Format)) + { + EngFreeMem(DecompressedBits); + return NULL; + } + + BitmapInfo->Format = (BitmapInfo->Format == BMF_4RLE) ? BMF_4BPP : BMF_8BPP; + } } /* Allocate the actual surface object structure */ @@ -564,6 +544,8 @@ else EngFreeMem(Bits); } + if (DecompressedBits) + EngFreeMem(DecompressedBits); return NULL; } @@ -584,11 +566,9 @@ pso->fjBitmap = BitmapInfo->Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM); /* Save size and type */ - LocalSize.cy = BitmapInfo->Height; - LocalSize.cx = BitmapInfo->Width; pso->sizlBitmap = LocalSize; pso->iType = STYPE_BITMAP; - + /* Device-managed surface, no flags or dimension */ pso->dhsurf = 0; pso->dhpdev = NULL; @@ -599,48 +579,28 @@ psurf->hSecure = NULL; psurf->hDIBSection = NULL; psurf->flHooks = 0; - + /* Set bits */ - pso->pvBits = Bits; - - /* Check for bitmap type */ - if (!Compressed) + if(Compressed) + pso->pvBits = DecompressedBits; + else + pso->pvBits = Bits; + + /* Number of bits is based on the height times the scanline */ + pso->cjBits = BitmapInfo->Height * ScanLine; + if (BitmapInfo->Flags & BMF_TOPDOWN) { - /* Number of bits is based on the height times the scanline */ - pso->cjBits = BitmapInfo->Height * ScanLine; - if (BitmapInfo->Flags & BMF_TOPDOWN) - { - /* For topdown, the base address starts with the bits */ - pso->pvScan0 = pso->pvBits; - pso->lDelta = ScanLine; - } - else - { - /* Otherwise we start with the end and go up */ - pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ScanLine); - pso->lDelta = -ScanLine; - } + /* For topdown, the base address starts with the bits */ + pso->pvScan0 = pso->pvBits; + pso->lDelta = ScanLine; } else { - /* Compressed surfaces don't have scanlines! */ - pso->lDelta = 0; - pso->cjBits = BitmapInfo->Size; - - /* Check for JPG or PNG */ - if ((BitmapInfo->Format != BMF_JPEG) && (BitmapInfo->Format != BMF_PNG)) - { - /* Wherever the bit data is */ - pso->pvScan0 = pso->pvBits; - } - else - { - /* Fancy formats don't use a base address */ - pso->pvScan0 = NULL; - ASSERT(FALSE); // ENGDDI shouldn't be creating PNGs for drivers ;-) - } + /* Otherwise we start with the end and go up */ + pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ScanLine); + pso->lDelta = -ScanLine; } - + /* Finally set the handle and uniq */ pso->hsurf = (HSURF)psurf->BaseObject.hHmgr; pso->iUniq = 0;