reactos/win32ss/gdi/ntgdi/dibobj.c

2354 lines
68 KiB
C
Raw Normal View History

/*
* PROJECT: ReactOS win32 kernel mode subsystem
* LICENSE: GPL - See COPYING in the top level directory
* FILE: win32ss/gdi/ntgdi/dibobj.c
* PURPOSE: Dib object functions
* PROGRAMMER:
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
static const RGBQUAD DefLogPaletteQuads[20] = /* Copy of Default Logical Palette */
{
/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
{ 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x80, 0x00 },
{ 0x00, 0x80, 0x00, 0x00 },
{ 0x00, 0x80, 0x80, 0x00 },
{ 0x80, 0x00, 0x00, 0x00 },
{ 0x80, 0x00, 0x80, 0x00 },
{ 0x80, 0x80, 0x00, 0x00 },
{ 0xc0, 0xc0, 0xc0, 0x00 },
{ 0xc0, 0xdc, 0xc0, 0x00 },
{ 0xf0, 0xca, 0xa6, 0x00 },
{ 0xf0, 0xfb, 0xff, 0x00 },
{ 0xa4, 0xa0, 0xa0, 0x00 },
{ 0x80, 0x80, 0x80, 0x00 },
{ 0x00, 0x00, 0xff, 0x00 },
{ 0x00, 0xff, 0x00, 0x00 },
{ 0x00, 0xff, 0xff, 0x00 },
{ 0xff, 0x00, 0x00, 0x00 },
{ 0xff, 0x00, 0xff, 0x00 },
{ 0xff, 0xff, 0x00, 0x00 },
{ 0xff, 0xff, 0xff, 0x00 }
};
PPALETTE
NTAPI
CreateDIBPalette(
_In_ const BITMAPINFO *pbmi,
_In_ PDC pdc,
_In_ ULONG iUsage)
{
PPALETTE ppal;
ULONG i, cBitsPixel, cColors;
if (pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
{
PBITMAPCOREINFO pbci = (PBITMAPCOREINFO)pbmi;
cBitsPixel = pbci->bmciHeader.bcBitCount;
}
else
{
cBitsPixel = pbmi->bmiHeader.biBitCount;
}
/* Check if the colors are indexed */
if (cBitsPixel <= 8)
{
/* We create a "full" palette */
cColors = 1 << cBitsPixel;
/* Allocate the palette */
ppal = PALETTE_AllocPalette(PAL_INDEXED,
cColors,
NULL,
0,
0,
0);
if (ppal == NULL)
{
DPRINT1("Failed to allocate palette.\n");
return NULL;
}
/* Check if the BITMAPINFO specifies how many colors to use */
if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
(pbmi->bmiHeader.biClrUsed != 0))
{
/* This is how many colors we can actually process */
cColors = min(cColors, pbmi->bmiHeader.biClrUsed);
}
/* Check how to use the colors */
if (iUsage == DIB_PAL_COLORS)
{
COLORREF crColor;
/* The colors are an array of WORD indices into the DC palette */
PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
/* Use the DCs palette or, if no DC is given, the default one */
PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault;
/* Loop all color indices in the DIB */
for (i = 0; i < cColors; i++)
{
/* Get the palette index and handle wraparound when exceeding
the number of colors in the DC palette */
WORD wIndex = pwColors[i] % ppalDC->NumColors;
/* USe the RGB value from the DC palette */
crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, wIndex);
PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
}
}
else if (iUsage == DIB_PAL_BRUSHHACK)
{
/* The colors are an array of WORD indices into the DC palette */
PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
/* Loop all color indices in the DIB */
for (i = 0; i < cColors; i++)
{
/* Set the index directly as the RGB color, the real palette
containing RGB values will be calculated when the brush is
realized */
PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]);
}
/* Mark the palette as a brush hack palette */
ppal->flFlags |= PAL_BRUSHHACK;
}
// else if (iUsage == 2)
// {
// FIXME: this one is undocumented
// ASSERT(FALSE);
// }
else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
{
/* The colors are an array of RGBQUAD values */
RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
RGBQUAD colors[256] = {{0}};
// FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro?
/* Use SEH to verify we can READ prgb[] succesfully */
_SEH2_TRY
{
RtlCopyMemory(colors, prgb, cColors * sizeof(colors[0]));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Do Nothing */
}
_SEH2_END;
for (i = 0; i < cColors; ++i)
{
/* Get the color value and translate it to a COLORREF */
COLORREF crColor = RGB(colors[i].rgbRed, colors[i].rgbGreen, colors[i].rgbBlue);
/* Set the RGB value in the palette */
PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
}
}
else
{
/* The colors are an array of RGBTRIPLE values */
RGBTRIPLE *prgb = (RGBTRIPLE*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
/* Loop all color indices in the DIB */
for (i = 0; i < cColors; i++)
{
/* Get the color value and translate it to a COLORREF */
RGBTRIPLE rgb = prgb[i];
COLORREF crColor = RGB(rgb.rgbtRed, rgb.rgbtGreen, rgb.rgbtBlue);
/* Set the RGB value in the palette */
PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
}
}
}
else
{
/* This is a bitfield / RGB palette */
ULONG flRedMask, flGreenMask, flBlueMask;
/* Check if the DIB contains bitfield values */
if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
(pbmi->bmiHeader.biCompression == BI_BITFIELDS))
{
/* Check if we have a v4/v5 header */
if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
{
/* The masks are dedicated fields in the header */
PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader;
flRedMask = pbmV4Header->bV4RedMask;
flGreenMask = pbmV4Header->bV4GreenMask;
flBlueMask = pbmV4Header->bV4BlueMask;
}
else
{
/* The masks are the first 3 values in the DIB color table */
PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
flRedMask = pdwColors[0];
flGreenMask = pdwColors[1];
flBlueMask = pdwColors[2];
}
}
else
{
/* Check what bit depth we have. Note: optimization flags are
calculated in PALETTE_AllocPalette() */
if (cBitsPixel == 16)
{
/* This is an RGB 555 palette */
flRedMask = 0x7C00;
flGreenMask = 0x03E0;
flBlueMask = 0x001F;
}
else
{
/* This is an RGB 888 palette */
flRedMask = 0xFF0000;
flGreenMask = 0x00FF00;
flBlueMask = 0x0000FF;
}
}
/* Allocate the bitfield palette */
ppal = PALETTE_AllocPalette(PAL_BITFIELDS,
0,
NULL,
flRedMask,
flGreenMask,
flBlueMask);
}
/* We're done, return the palette */
return ppal;
}
// Converts a DIB to a device-dependent bitmap
static INT
FASTCALL
IntSetDIBits(
PDC DC,
HBITMAP hBitmap,
UINT StartScan,
UINT ScanLines,
CONST VOID *Bits,
ULONG cjMaxBits,
CONST BITMAPINFO *bmi,
UINT ColorUse)
{
HBITMAP SourceBitmap;
PSURFACE psurfDst, psurfSrc;
INT result = 0;
RECT rcDst;
POINTL ptSrc;
EXLATEOBJ exlo;
PPALETTE ppalDIB = 0;
ULONG cjSizeImage;
if (!bmi || !Bits) return 0;
/* Check for uncompressed formats */
if ((bmi->bmiHeader.biCompression == BI_RGB) ||
(bmi->bmiHeader.biCompression == BI_BITFIELDS))
{
/* Calculate the image size */
cjSizeImage = DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
ScanLines,
bmi->bmiHeader.biBitCount);
}
/* Check if the header provided an image size */
else if (bmi->bmiHeader.biSizeImage != 0)
{
/* Use the given size */
cjSizeImage = bmi->bmiHeader.biSizeImage;
}
else
{
/* Compressed format without a size. This is invalid. */
DPRINT1("Compressed format without a size!");
return 0;
}
/* Check if the size that we have is ok */
if ((cjSizeImage > cjMaxBits) || (cjSizeImage == 0))
{
DPRINT1("Invalid bitmap size! cjSizeImage = %lu, cjMaxBits = %lu\n",
cjSizeImage, cjMaxBits);
return 0;
}
SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
ScanLines,
0,
BitmapFormat(bmi->bmiHeader.biBitCount,
bmi->bmiHeader.biCompression),
bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
cjSizeImage,
(PVOID)Bits,
0);
if (!SourceBitmap)
{
DPRINT1("Error: Could not create a bitmap.\n");
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
return 0;
}
psurfDst = SURFACE_ShareLockSurface(hBitmap);
psurfSrc = SURFACE_ShareLockSurface(SourceBitmap);
if(!(psurfSrc && psurfDst))
{
DPRINT1("Error: Could not lock surfaces\n");
goto cleanup;
}
/* Create a palette for the DIB */
ppalDIB = CreateDIBPalette(bmi, DC, ColorUse);
if (!ppalDIB)
{
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
goto cleanup;
}
/* Initialize EXLATEOBJ */
EXLATEOBJ_vInitialize(&exlo,
ppalDIB,
psurfDst->ppal,
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff), //DC->pdcattr->crBackgroundClr,
0); // DC->pdcattr->crForegroundClr);
rcDst.top = StartScan;
rcDst.left = 0;
rcDst.bottom = rcDst.top + ScanLines;
rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
ptSrc.x = 0;
ptSrc.y = 0;
result = IntEngCopyBits(&psurfDst->SurfObj,
&psurfSrc->SurfObj,
NULL,
&exlo.xlo,
&rcDst,
&ptSrc);
if(result)
result = ScanLines;
EXLATEOBJ_vCleanup(&exlo);
cleanup:
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc);
if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst);
GreDeleteObject(SourceBitmap);
return result;
}
static
HBITMAP
IntGdiCreateMaskFromRLE(
DWORD Width,
DWORD Height,
ULONG Compression,
const BYTE* Bits,
DWORD BitsSize)
{
HBITMAP Mask;
DWORD x, y;
SURFOBJ* SurfObj;
UINT i = 0;
BYTE Data, NumPixels, ToSkip;
ASSERT((Compression == BI_RLE8) || (Compression == BI_RLE4));
/* Create the bitmap */
Mask = GreCreateBitmapEx(Width, Height, 0, BMF_1BPP, 0, 0, NULL, 0);
if (!Mask)
return NULL;
SurfObj = EngLockSurface((HSURF)Mask);
if (!SurfObj)
{
GreDeleteObject(Mask);
return NULL;
}
ASSERT(SurfObj->pvBits != NULL);
x = y = 0;
while (i < BitsSize)
{
NumPixels = Bits[i];
Data = Bits[i + 1];
i += 2;
if (NumPixels != 0)
{
if ((x + NumPixels) > Width)
NumPixels = Width - x;
if (NumPixels == 0)
continue;
DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
x += NumPixels;
continue;
}
if (Data < 3)
{
switch (Data)
{
case 0:
/* End of line */
y++;
if (y == Height)
goto done;
x = 0;
break;
case 1:
/* End of file */
goto done;
case 2:
/* Jump */
if (i >= (BitsSize - 1))
goto done;
x += Bits[i];
if (x > Width)
x = Width;
y += Bits[i + 1];
if (y >= Height)
goto done;
i += 2;
break;
}
/* Done for this run */
continue;
}
/* Embedded data into the RLE */
NumPixels = Data;
if (Compression == BI_RLE8)
ToSkip = NumPixels;
else
ToSkip = (NumPixels / 2) + (NumPixels & 1);
if ((i + ToSkip) > BitsSize)
goto done;
ToSkip = (ToSkip + 1) & ~1;
if ((x + NumPixels) > Width)
NumPixels = Width - x;
if (NumPixels != 0)
{
DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
x += NumPixels;
}
i += ToSkip;
}
done:
EngUnlockSurface(SurfObj);
return Mask;
}
W32KAPI
INT
APIENTRY
NtGdiSetDIBitsToDeviceInternal(
IN HDC hDC,
IN INT XDest,
IN INT YDest,
IN DWORD Width,
IN DWORD Height,
IN INT XSrc,
IN INT YSrc,
IN DWORD StartScan,
IN DWORD ScanLines,
IN LPBYTE Bits,
IN LPBITMAPINFO bmi,
IN DWORD ColorUse,
IN UINT cjMaxBits,
IN UINT cjMaxInfo,
IN BOOL bTransformCoordinates,
IN OPTIONAL HANDLE hcmXform)
{
INT ret;
PDC pDC = NULL;
HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
SURFACE *pSurf;
RECTL rcDest;
POINTL ptSource;
//INT DIBWidth;
SIZEL SourceSize;
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
EXLATEOBJ exlo;
PPALETTE ppalDIB = NULL;
LPBITMAPINFO pbmiSafe;
BOOL bResult;
if (!Bits) return 0;
pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, 'pmTG');
if (!pbmiSafe) return 0;
_SEH2_TRY
{
ProbeForRead(bmi, cjMaxInfo, 1);
ProbeForRead(Bits, cjMaxBits, 1);
RtlCopyMemory(pbmiSafe, bmi, cjMaxInfo);
bmi = pbmiSafe;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ret = 0;
goto Exit;
}
_SEH2_END;
DPRINT("StartScan %d ScanLines %d Bits %p bmi %p ColorUse %d\n"
" Height %d Width %d SizeImage %d\n"
" biHeight %d biWidth %d biBitCount %d\n"
" XSrc %d YSrc %d xDext %d yDest %d\n",
StartScan, ScanLines, Bits, bmi, ColorUse,
Height, Width, bmi->bmiHeader.biSizeImage,
bmi->bmiHeader.biHeight, bmi->bmiHeader.biWidth,
bmi->bmiHeader.biBitCount,
XSrc, YSrc, XDest, YDest);
if (YDest >= 0)
{
ScanLines = min(abs(Height), ScanLines);
if (YSrc > 0)
ScanLines += YSrc;
}
else
{
ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
}
if (ScanLines == 0)
{
DPRINT1("ScanLines == 0\n");
ret = 0;
goto Exit;
}
pDC = DC_LockDc(hDC);
if (!pDC)
{
EngSetLastError(ERROR_INVALID_HANDLE);
ret = 0;
goto Exit;
}
if (pDC->dctype == DCTYPE_INFO)
{
ret = 0;
goto Exit;
}
rcDest.left = XDest;
rcDest.top = YDest;
if (bTransformCoordinates)
{
IntLPtoDP(pDC, (LPPOINT)&rcDest, 2);
}
rcDest.left += pDC->ptlDCOrig.x;
rcDest.top += pDC->ptlDCOrig.y;
rcDest.right = rcDest.left + Width;
rcDest.bottom = rcDest.top + Height;
rcDest.top += StartScan;
if (pDC->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
{
IntUpdateBoundsRect(pDC, &rcDest);
}
ptSource.x = XSrc;
ptSource.y = YSrc;
SourceSize.cx = bmi->bmiHeader.biWidth;
SourceSize.cy = ScanLines;
if (YDest >= 0 && YSrc > 0)
{
ScanLines += YSrc;
}
//DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
ScanLines,
0,
BitmapFormat(bmi->bmiHeader.biBitCount,
bmi->bmiHeader.biCompression),
bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
bmi->bmiHeader.biSizeImage,
Bits,
0);
if (!hSourceBitmap)
{
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
ret = 0;
goto Exit;
}
pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
if (!pSourceSurf)
{
ret = 0;
goto Exit;
}
/* HACK: If this is a RLE bitmap, only the relevant pixels must be set. */
if ((bmi->bmiHeader.biCompression == BI_RLE8) || (bmi->bmiHeader.biCompression == BI_RLE4))
{
hMaskBitmap = IntGdiCreateMaskFromRLE(bmi->bmiHeader.biWidth,
ScanLines,
bmi->bmiHeader.biCompression,
Bits,
cjMaxBits);
if (!hMaskBitmap)
{
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
ret = 0;
goto Exit;
}
pMaskSurf = EngLockSurface((HSURF)hMaskBitmap);
if (!pMaskSurf)
{
ret = 0;
goto Exit;
}
}
/* Create a palette for the DIB */
ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
if (!ppalDIB)
{
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
ret = 0;
goto Exit;
}
/* This is actually a blit */
DC_vPrepareDCsForBlit(pDC, &rcDest, NULL, NULL);
pSurf = pDC->dclevel.pSurface;
if (!pSurf)
{
DC_vFinishBlit(pDC, NULL);
ret = ScanLines;
goto Exit;
}
ASSERT(pSurf->ppal);
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
/* Initialize EXLATEOBJ */
EXLATEOBJ_vInitialize(&exlo,
ppalDIB,
pSurf->ppal,
RGB(0xff, 0xff, 0xff),
pDC->pdcattr->crBackgroundClr,
pDC->pdcattr->crForegroundClr);
pDestSurf = &pSurf->SurfObj;
/* Copy the bits */
DPRINT("BitsToDev with rcDest=(%d|%d) (%d|%d), ptSource=(%d|%d) w=%d h=%d\n",
rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
/* This fixes the large Google text on Google.com from being upside down */
if (rcDest.top > rcDest.bottom)
{
RECTL_vMakeWellOrdered(&rcDest);
ptSource.y -= SourceSize.cy;
}
bResult = IntEngBitBlt(pDestSurf,
pSourceSurf,
pMaskSurf,
(CLIPOBJ *)&pDC->co,
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
&exlo.xlo,
&rcDest,
&ptSource,
pMaskSurf ? &ptSource : NULL,
NULL,
NULL,
pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
/* Cleanup EXLATEOBJ */
EXLATEOBJ_vCleanup(&exlo);
/* We're done */
DC_vFinishBlit(pDC, NULL);
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
ret = bResult ? ScanLines : 0;
Exit:
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
if (pSourceSurf) EngUnlockSurface(pSourceSurf);
if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
if (pMaskSurf) EngUnlockSurface(pMaskSurf);
if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
if (pDC) DC_UnlockDc(pDC);
ExFreePoolWithTag(pbmiSafe, 'pmTG');
return ret;
}
[Sorry for too many changes in one patch, but it's nearly impossible to separate it without breaking the functionality] - Remove the eng/brush.h header and all occurrences of BRUSHINST. - Remove eng/nls.c and make the NLS functions forward exports to ntoskrnl. - Remove DDBITMAP definition. - Overall cleanup of eng/xlate.c. - Stop processing if exact match is found in ClosestColorMatch. - Move SURFGDI->PointerStatus to GDIDEVICE structure. - Remove the GDIDEVICE->DriverLock. - Replace BITMAP by SURFOBJ in BITMAPOBJ structure and added two new members (Flags and Hooks). - Replace function pointers to driver functions in SURFGDI with flHooks variable specifying the bitmask of hooked functions. - Added two new macros: GDIDEV and GDIDEVFUNCS. - Fixed locking in NtGdiGetBitmapBits. - Removed IntCopyBitmap and replaced it's usage by BITMAPOBJ_CopyBitmap. - Fixed setting of SURFOBJ->pvBits and SURFOBJ->pvScan0 in EngCreateBitmap for bottom-up surfaces. - Fix DPRINTs. - Remove unused definitions from eng/objects.h. - Call IntEngBitBlt instead of EngBitBlt from EngCopyBits. - Correctly set the SURFOBJ->hsurf field. - Merge Engine surface handling with the GDI one and remove DC->Surface, SURFGDI, BitmapToSurf. - Support for bottom-up mouse cursors in the Eng* cursor emulation routines. - Fix locking in error cases of NtGdiRestoreDC (get Primitives demo to start). - Fix BitmapFormat to return 0 for unknown bit depth. - Move code from EngCreateBitmap to IntCreateBitmap and use this function in EngCreateBitmap, NtGdiCreateBitmap and DIB_CreateDIBSection. - New implementation of NtGdiGetDIBits. svn path=/trunk/; revision=9977
2004-07-03 13:55:37 +00:00
/* Converts a device-dependent bitmap to a DIB */
INT
APIENTRY
GreGetDIBitsInternal(
HDC hDC,
HBITMAP hBitmap,
UINT StartScan,
UINT ScanLines,
LPBYTE Bits,
LPBITMAPINFO Info,
UINT Usage,
UINT MaxBits,
UINT MaxInfo)
{
BITMAPCOREINFO* pbmci = NULL;
PSURFACE psurf = NULL;
PDC pDC;
LONG width, height;
WORD planes, bpp;
DWORD compr, size ;
USHORT i;
int bitmap_type;
RGBQUAD* rgbQuads;
VOID* colorPtr;
DPRINT("Entered GreGetDIBitsInternal()\n");
if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
return 0;
pDC = DC_LockDc(hDC);
if (pDC == NULL || pDC->dctype == DCTYPE_INFO)
{
ScanLines = 0;
goto done;
}
/* Get a pointer to the source bitmap object */
psurf = SURFACE_ShareLockSurface(hBitmap);
if (psurf == NULL)
{
ScanLines = 0;
goto done;
}
colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
rgbQuads = colorPtr;
bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
&width,
&height,
&planes,
&bpp,
&compr,
&size);
if(bitmap_type == -1)
{
DPRINT1("Wrong bitmap format\n");
EngSetLastError(ERROR_INVALID_PARAMETER);
ScanLines = 0;
goto done;
}
else if(bitmap_type == 0)
{
/* We need a BITMAPINFO to create a DIB, but we have to fill
* the BITMAPCOREINFO we're provided */
pbmci = (BITMAPCOREINFO*)Info;
/* fill in the the bit count, so we can calculate the right ColorsSize during the conversion */
pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
if(Info == NULL)
{
DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
ScanLines = 0;
goto done;
}
rgbQuads = Info->bmiColors;
}
/* Validate input:
- negative width is always an invalid value
- non-null Bits and zero bpp is an invalid combination
- only check the rest of the input params if either bpp is non-zero or Bits are set */
if (width < 0 || (bpp == 0 && Bits))
{
ScanLines = 0;
goto done;
}
if (Bits || bpp)
{
if ((height == 0 || width == 0) || (compr && compr != BI_BITFIELDS && compr != BI_RGB))
{
ScanLines = 0;
goto done;
}
}
Info->bmiHeader.biClrUsed = 0;
Info->bmiHeader.biClrImportant = 0;
/* Fill in the structure */
switch(bpp)
{
case 0: /* Only info */
Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
-psurf->SurfObj.sizlBitmap.cy :
psurf->SurfObj.sizlBitmap.cy;
Info->bmiHeader.biPlanes = 1;
Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
Info->bmiHeader.biHeight,
Info->bmiHeader.biBitCount);
Info->bmiHeader.biCompression = (Info->bmiHeader.biBitCount == 16 || Info->bmiHeader.biBitCount == 32) ?
BI_BITFIELDS : BI_RGB;
Info->bmiHeader.biXPelsPerMeter = 0;
Info->bmiHeader.biYPelsPerMeter = 0;
if (Info->bmiHeader.biBitCount <= 8 && Info->bmiHeader.biClrUsed == 0)
Info->bmiHeader.biClrUsed = 1 << Info->bmiHeader.biBitCount;
ScanLines = 1;
goto done;
case 1:
case 4:
case 8:
Info->bmiHeader.biClrUsed = 1 << bpp;
/* If the bitmap is a DIB section and has the same format as what
* is requested, go ahead! */
if((psurf->hSecure) &&
(BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
{
if(Usage == DIB_RGB_COLORS)
{
ULONG colors = min(psurf->ppal->NumColors, 256);
if(colors != 256) Info->bmiHeader.biClrUsed = colors;
for(i = 0; i < colors; i++)
{
rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
rgbQuads[i].rgbReserved = 0;
}
}
else
{
for(i = 0; i < 256; i++)
((WORD*)rgbQuads)[i] = i;
}
}
else
{
if(Usage == DIB_PAL_COLORS)
{
for(i = 0; i < 256; i++)
{
((WORD*)rgbQuads)[i] = i;
}
}
else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat))
{
/* For color DDBs in native depth (mono DDBs always have
a black/white palette):
Generate the color map from the selected palette */
PPALETTE pDcPal = PALETTE_ShareLockPalette(pDC->dclevel.hpal);
if(!pDcPal)
{
ScanLines = 0 ;
goto done ;
}
for (i = 0; i < pDcPal->NumColors; i++)
{
rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
rgbQuads[i].rgbReserved = 0;
}
PALETTE_ShareUnlockPalette(pDcPal);
}
else
{
switch (bpp)
{
case 1:
rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
rgbQuads[0].rgbReserved = 0;
rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
rgbQuads[1].rgbReserved = 0;
break;
case 4:
/* The EGA palette is the first and last 8 colours of the default palette
with the innermost pair swapped */
RtlCopyMemory(rgbQuads, DefLogPaletteQuads, 7 * sizeof(RGBQUAD));
RtlCopyMemory(rgbQuads + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
RtlCopyMemory(rgbQuads + 8, DefLogPaletteQuads + 7, 1 * sizeof(RGBQUAD));
RtlCopyMemory(rgbQuads + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
break;
case 8:
{
INT i;
memcpy(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
memcpy(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
for (i = 10; i < 246; i++)
{
rgbQuads[i].rgbRed = (i & 0x07) << 5;
rgbQuads[i].rgbGreen = (i & 0x38) << 2;
rgbQuads[i].rgbBlue = i & 0xc0;
rgbQuads[i].rgbReserved = 0;
}
}
}
}
}
break;
case 15:
if (Info->bmiHeader.biCompression == BI_BITFIELDS)
{
((PDWORD)Info->bmiColors)[0] = 0x7c00;
((PDWORD)Info->bmiColors)[1] = 0x03e0;
((PDWORD)Info->bmiColors)[2] = 0x001f;
}
break;
case 16:
if (Info->bmiHeader.biCompression == BI_BITFIELDS)
{
if (psurf->hSecure)
{
((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
}
else
{
((PDWORD)Info->bmiColors)[0] = 0xf800;
((PDWORD)Info->bmiColors)[1] = 0x07e0;
((PDWORD)Info->bmiColors)[2] = 0x001f;
}
}
break;
case 24:
case 32:
if (Info->bmiHeader.biCompression == BI_BITFIELDS)
{
if (psurf->hSecure)
{
((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
}
else
{
((PDWORD)Info->bmiColors)[0] = 0xff0000;
((PDWORD)Info->bmiColors)[1] = 0x00ff00;
((PDWORD)Info->bmiColors)[2] = 0x0000ff;
}
}
break;
default:
ScanLines = 0;
goto done;
}
Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
Info->bmiHeader.biPlanes = 1;
if(Bits && ScanLines)
{
/* Create a DIBSECTION, blt it, profit */
PVOID pDIBits ;
HBITMAP hBmpDest;
PSURFACE psurfDest;
EXLATEOBJ exlo;
RECT rcDest;
POINTL srcPoint;
BOOL ret ;
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
int newLines = -1;
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
if (StartScan >= abs(Info->bmiHeader.biHeight))
{
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
ScanLines = 1;
goto done;
}
else
{
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
ScanLines = min(ScanLines, abs(Info->bmiHeader.biHeight) - StartScan);
}
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
if (abs(Info->bmiHeader.biHeight) < psurf->SurfObj.sizlBitmap.cy)
{
StartScan += psurf->SurfObj.sizlBitmap.cy - abs(Info->bmiHeader.biHeight);
}
/* Fixup values */
Info->bmiHeader.biHeight = (height < 0) ?
-(LONG)ScanLines : ScanLines;
/* Create the DIB */
hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
/* Restore them */
Info->bmiHeader.biHeight = height;
if(!hBmpDest)
{
DPRINT1("Unable to create a DIB Section!\n");
EngSetLastError(ERROR_INVALID_PARAMETER);
ScanLines = 0;
goto done ;
}
psurfDest = SURFACE_ShareLockSurface(hBmpDest);
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
RECTL_vSetRect(&rcDest, 0, 0, Info->bmiHeader.biWidth, ScanLines);
Info->bmiHeader.biWidth = width;
srcPoint.x = 0;
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
if (abs(Info->bmiHeader.biHeight) <= psurf->SurfObj.sizlBitmap.cy)
{
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
srcPoint.y = psurf->SurfObj.sizlBitmap.cy - StartScan - ScanLines;
}
else
{
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
/* Determine the actual number of lines copied from the */
/* original bitmap. It might be different from ScanLines. */
newLines = abs(Info->bmiHeader.biHeight) - psurf->SurfObj.sizlBitmap.cy;
newLines = min((int)(StartScan + ScanLines - newLines), psurf->SurfObj.sizlBitmap.cy);
if (newLines > 0)
{
srcPoint.y = psurf->SurfObj.sizlBitmap.cy - newLines;
if (StartScan > psurf->SurfObj.sizlBitmap.cy)
{
newLines -= (StartScan - psurf->SurfObj.sizlBitmap.cy);
}
}
else
{
newLines = 0;
srcPoint.y = psurf->SurfObj.sizlBitmap.cy;
}
}
EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0);
ret = IntEngCopyBits(&psurfDest->SurfObj,
&psurf->SurfObj,
NULL,
&exlo.xlo,
&rcDest,
&srcPoint);
SURFACE_ShareUnlockSurface(psurfDest);
if(!ret)
ScanLines = 0;
else
{
RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
}
[WIN32SS][COMCTL32] Commit Flip_Fix_9.patch flip_fix_9.patch fixes: CORE-16984 " 'SPINA Thrulg' / 'SPINA Thyr' / 'Sim Thyr' have images flipped" CORE-17194 "StretchDIBits test" isn't work correctly" "Output of 'Project 3 Test'" CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" CORE-14671 "'Peazip' shows icons in buttons and menubar vertically flipped" "Double Commander shoes icons flipped in buttons, menubar, listview and the treeview" CORE-13273 "Welcome to Lazarus" icon shows flipped CORE-13026 "'CudaText app' icon shows flipped" Not all of those are duplicates, although they appear to be at first glance. It affects different controls and some of those tickets do have different 'guilty revs' than others. The patch does consist of 3 parts: 1.) win32ss/gdi/ntgdi/dibobj.c This one is the most clean part of it, that addresses most of the flipping issues now. 2.) The hack in comctl32.h redefining the version: We used that in the past to appease some, but not all of the issues listed above. But it does hide additional issues, e.g. in DvDStyler, therefore we seem to still need that appeasement even today. Most likely it would make sense to aim to avoid this part in the future. part 2.) was committed as first appeasement on its own already into 0.4.14-RC-24-g 198b61e 0.4.13-RC-7-g 67211fa 0.4.12-RC-5-g 8449527 0.4.11-RC-16-g b906163 0.4.10-RC-7-g f1e80fe 0.4.9-RC-34-g 9d758ae 3.) toolbar.c change That part fixes at least the toolbar case for DvDStyler without relying on the comctl32.h hack any longer, but it was still not enough to completely get rid of part 2.) yet. Many thanks to all contributors: 'I_kill_Bugs', Doug Lyons and also 'Julenuri' for testing. The patch gave nice testbot results: KVM: https://reactos.org/testman/compare.php?ids=75704,75714 VBox: https://reactos.org/testman/compare.php?ids=75705,75715 and we also created a summary of manual test-results: https://jira.reactos.org/browse/CORE-17415?focusedCommentId=126668&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-126668 If you read this comment via git blame and your goal is to get rid of the hack in comctl32.h, I would highly recommend to redo the tests of that testing table, and if that is asked too much, then please test at least the following cases: CORE-14701 "DVDStyler 3.0.4 transparent toolbars" CORE-14701 "DVDStyler 3.0.4 erroneously black around icons of welcome-dlg" "DVDStyler 3.0.4 erroneously black/transparent within comboboxes of properties of VMGM menu" and try to add what might be needed to fix them, and double-check again: "DoubleCommander optionsDlg the most complex testcase, contains flip-prone icons in treeview, listview, menubar, buttons, statics". Only some of its flipped icons were impacted by the comctl32.h change before.
2021-01-05 19:30:40 +00:00
/* Update if line count has changed */
if (newLines != -1)
{
ScanLines = (UINT)newLines;
}
GreDeleteObject(hBmpDest);
EXLATEOBJ_vCleanup(&exlo);
}
else
{
/* Signals success and not the actual number of scan lines*/
ScanLines = 1;
}
done:
if (pbmci)
DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci, Usage);
if (psurf)
SURFACE_ShareUnlockSurface(psurf);
if (pDC)
DC_UnlockDc(pDC);
return ScanLines;
}
_Success_(return!=0)
__kernel_entry
INT
APIENTRY
NtGdiGetDIBitsInternal(
_In_ HDC hdc,
_In_ HBITMAP hbm,
_In_ UINT iStartScan,
_In_ UINT cScans,
_Out_writes_bytes_opt_(cjMaxBits) LPBYTE pjBits,
_Inout_ LPBITMAPINFO pbmi,
_In_ UINT iUsage,
_In_ UINT cjMaxBits,
_In_ UINT cjMaxInfo)
{
PBITMAPINFO pbmiSafe;
HANDLE hSecure = NULL;
INT iResult = 0;
UINT cjAlloc;
/* Check for bad iUsage */
if (iUsage > 2) return 0;
/* Check if the size of the bitmap info is large enough */
if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
{
return 0;
}
/* Use maximum size */
cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
// HACK: the underlying code sucks and doesn't care for the size, so we
// give it the maximum ever needed
cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
/* Allocate a buffer the bitmapinfo */
pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
if (!pbmiSafe)
{
/* Fail */
return 0;
}
/* Use SEH */
_SEH2_TRY
{
/* Probe and copy the BITMAPINFO */
ProbeForRead(pbmi, cjMaxInfo, 1);
RtlCopyMemory(pbmiSafe, pbmi, cjMaxInfo);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
goto cleanup;
}
_SEH2_END;
/* Check if the header size is large enough */
if ((pbmiSafe->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
(pbmiSafe->bmiHeader.biSize > cjMaxInfo))
{
goto cleanup;
}
/* Check if the caller provided bitmap bits */
if (pjBits)
{
/* Secure the user mode memory */
hSecure = EngSecureMem(pjBits, cjMaxBits);
if (!hSecure)
{
goto cleanup;
}
}
/* Now call the internal function */
iResult = GreGetDIBitsInternal(hdc,
hbm,
iStartScan,
cScans,
pjBits,
pbmiSafe,
iUsage,
cjMaxBits,
cjMaxInfo);
/* Check for success */
if (iResult)
{
/* Use SEH to copy back to user mode */
_SEH2_TRY
{
/* Copy the data back */
cjMaxInfo = min(cjMaxInfo, (UINT)DIB_BitmapInfoSize(pbmiSafe, (WORD)iUsage));
ProbeForWrite(pbmi, cjMaxInfo, 1);
RtlCopyMemory(pbmi, pbmiSafe, cjMaxInfo);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Ignore */
(VOID)0;
}
_SEH2_END;
}
cleanup:
if (hSecure) EngUnsecureMem(hSecure);
ExFreePoolWithTag(pbmiSafe, 'imBG');
return iResult;
}
W32KAPI
INT
APIENTRY
NtGdiStretchDIBitsInternal(
IN HDC hdc,
IN INT xDst,
IN INT yDst,
IN INT cxDst,
IN INT cyDst,
IN INT xSrc,
IN INT ySrc,
IN INT cxSrc,
IN INT cySrc,
IN OPTIONAL LPBYTE pjInit,
IN LPBITMAPINFO pbmi,
IN DWORD dwUsage,
IN DWORD dwRop, // MS ntgdi.h says dwRop4(?)
IN UINT cjMaxInfo,
IN UINT cjMaxBits,
IN HANDLE hcmXform)
{
SIZEL sizel;
RECTL rcSrc, rcDst;
PDC pdc;
HBITMAP hbmTmp = 0;
PSURFACE psurfTmp = 0, psurfDst = 0;
PPALETTE ppalDIB = 0;
EXLATEOBJ exlo;
PBYTE pvBits;
LPBITMAPINFO pbmiSafe;
UINT cjAlloc;
HBITMAP hBitmap, hOldBitmap = NULL;
HDC hdcMem;
HPALETTE hPal = NULL;
ULONG BmpFormat = 0;
INT LinesCopied = 0;
/* Check for bad iUsage */
if (dwUsage > 2) return 0;
/* We must have LPBITMAPINFO */
if (!pbmi)
{
DPRINT1("Error, Invalid Parameter.\n");
EngSetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
/* Check if the size of the bitmap info is large enough */
if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
{
return 0;
}
/* Use maximum size */
cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
// HACK: the underlying code sucks and doesn't care for the size, so we
// give it the maximum ever needed
cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
/* Allocate a buffer the bitmapinfo */
pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
if (!pbmiSafe)
{
/* Fail */
return 0;
}
/* Use SEH */
_SEH2_TRY
{
/* Probe and copy the BITMAPINFO */
ProbeForRead(pbmi, cjMaxInfo, 1);
RtlCopyMemory(pbmiSafe, pbmi, cjMaxInfo);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ExFreePoolWithTag(pbmiSafe, 'imBG');
return 0;
}
_SEH2_END;
/* Check if the header size is large enough */
if ((pbmiSafe->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
(pbmiSafe->bmiHeader.biSize > cjMaxInfo))
{
ExFreePoolWithTag(pbmiSafe, 'imBG');
return 0;
}
if (!(pdc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return 0;
}
/* Check for info / mem DC without surface */
if (!pdc->dclevel.pSurface)
{
DC_UnlockDc(pdc);
// CHECKME
return TRUE;
}
/* Transform dest size */
sizel.cx = cxDst;
sizel.cy = cyDst;
IntLPtoDP(pdc, (POINTL*)&sizel, 1);
DC_UnlockDc(pdc);
if (pjInit && (cjMaxBits > 0))
{
pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
if (!pvBits)
{
return 0;
}
_SEH2_TRY
{
ProbeForRead(pjInit, cjMaxBits, 1);
RtlCopyMemory(pvBits, pjInit, cjMaxBits);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ExFreePoolWithTag(pvBits, TAG_DIB);
return 0;
}
_SEH2_END;
}
else
{
pvBits = NULL;
}
/* Here we select between the dwRop with SRCCOPY or not. */
if (dwRop == SRCCOPY)
{
hdcMem = NtGdiCreateCompatibleDC(hdc);
if (hdcMem == NULL)
{
DPRINT1("NtGdiCreateCompatibleDC failed to create hdc.\n");
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
return 0;
}
hBitmap = NtGdiCreateCompatibleBitmap(hdc,
abs(pbmiSafe->bmiHeader.biWidth),
abs(pbmiSafe->bmiHeader.biHeight));
if (hBitmap == NULL)
{
DPRINT1("NtGdiCreateCompatibleBitmap failed to create bitmap.\n");
DPRINT1("hdc : 0x%08x \n", hdc);
DPRINT1("width : 0x%08x \n", pbmiSafe->bmiHeader.biWidth);
DPRINT1("height : 0x%08x \n", pbmiSafe->bmiHeader.biHeight);
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
return 0;
}
/* Select the bitmap into hdcMem, and save a handle to the old bitmap */
hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
if (dwUsage == DIB_PAL_COLORS)
{
hPal = NtGdiGetDCObject(hdc, GDI_OBJECT_TYPE_PALETTE);
hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
}
pdc = DC_LockDc(hdcMem);
if (pdc != NULL)
{
IntSetDIBits(pdc, hBitmap, 0, abs(pbmiSafe->bmiHeader.biHeight), pvBits,
cjMaxBits, pbmiSafe, dwUsage);
DC_UnlockDc(pdc);
}
/* Origin for DIBitmap may be bottom left (positive biHeight) or top
left (negative biHeight) */
if (cxSrc == cxDst && cySrc == cyDst)
{
NtGdiBitBlt(hdc, xDst, yDst, cxDst, cyDst,
hdcMem, xSrc, abs(pbmiSafe->bmiHeader.biHeight) - cySrc - ySrc,
dwRop, 0, 0);
}
else
{
NtGdiStretchBlt(hdc, xDst, yDst, cxDst, cyDst,
hdcMem, xSrc, abs(pbmiSafe->bmiHeader.biHeight) - cySrc - ySrc,
cxSrc, cySrc, dwRop, 0);
}
/* cleanup */
if (hPal)
GdiSelectPalette(hdcMem, hPal, FALSE);
if (hOldBitmap)
NtGdiSelectBitmap(hdcMem, hOldBitmap);
NtGdiDeleteObjectApp(hdcMem);
GreDeleteObject(hBitmap);
} /* End of dwRop == SRCCOPY */
else
{ /* Start of dwRop != SRCCOPY */
/* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
if (!(pdc = DC_LockDc(hdc)))
{
DPRINT1("Could not lock dc\n");
EngSetLastError(ERROR_INVALID_HANDLE);
goto cleanup;
}
/* Calculate source and destination rect */
rcSrc.left = xSrc;
rcSrc.top = ySrc;
rcSrc.right = xSrc + abs(cxSrc);
rcSrc.bottom = ySrc + abs(cySrc);
rcDst.left = xDst;
rcDst.top = yDst;
rcDst.right = rcDst.left + cxDst;
rcDst.bottom = rcDst.top + cyDst;
IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
{
IntUpdateBoundsRect(pdc, &rcDst);
}
BmpFormat = BitmapFormat(pbmiSafe->bmiHeader.biBitCount,
pbmiSafe->bmiHeader.biCompression);
hbmTmp = GreCreateBitmapEx(pbmiSafe->bmiHeader.biWidth,
abs(pbmiSafe->bmiHeader.biHeight),
0,
BmpFormat,
pbmiSafe->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
cjMaxBits,
pvBits,
0);
if (!hbmTmp)
{
goto cleanup;
}
psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
if (!psurfTmp)
{
goto cleanup;
}
/* Create a palette for the DIB */
ppalDIB = CreateDIBPalette(pbmiSafe, pdc, dwUsage);
if (!ppalDIB)
{
goto cleanup;
}
/* Prepare DC for blit */
DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
psurfDst = pdc->dclevel.pSurface;
/* Initialize XLATEOBJ */
EXLATEOBJ_vInitialize(&exlo,
ppalDIB,
psurfDst->ppal,
RGB(0xff, 0xff, 0xff),
pdc->pdcattr->crBackgroundClr,
pdc->pdcattr->crForegroundClr);
/* Perform the stretch operation */
IntEngStretchBlt(&psurfDst->SurfObj,
&psurfTmp->SurfObj,
NULL,
(CLIPOBJ *)&pdc->co,
&exlo.xlo,
&pdc->dclevel.ca,
&rcDst,
&rcSrc,
NULL,
&pdc->eboFill.BrushObject,
NULL,
WIN32_ROP3_TO_ENG_ROP4(dwRop));
/* Cleanup */
DC_vFinishBlit(pdc, NULL);
EXLATEOBJ_vCleanup(&exlo);
cleanup:
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
if (hbmTmp) GreDeleteObject(hbmTmp);
if (pdc) DC_UnlockDc(pdc);
}
if (pvBits) ExFreePoolWithTag(pvBits, TAG_DIB);
/* This is not what MSDN says is returned from this function, but it
* follows Wine's dlls/gdi32/dib.c function nulldrv_StretchDIBits
* and it fixes over 100 gdi32:dib regression tests. */
if (dwRop == SRCCOPY)
{
LinesCopied = abs(pbmiSafe->bmiHeader.biHeight);
}
else
{
LinesCopied = pbmiSafe->bmiHeader.biHeight;
}
ExFreePoolWithTag(pbmiSafe, 'imBG');
return LinesCopied;
}
HBITMAP
FASTCALL
IntCreateDIBitmap(
PDC Dc,
INT width,
INT height,
UINT planes,
UINT bpp,
ULONG compression,
DWORD init,
LPBYTE bits,
ULONG cjMaxBits,
PBITMAPINFO data,
DWORD coloruse)
{
HBITMAP handle;
BOOL fColor;
ULONG BmpFormat = 0;
if (planes && bpp)
BmpFormat = BitmapFormat(planes * bpp, compression);
// Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
// colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
if (BmpFormat != BMF_1BPP) fColor = TRUE;
else if ((coloruse > DIB_RGB_COLORS) || ((init & CBM_INIT) == 0) || !data) fColor = FALSE;
else
{
const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
// Check if the first color of the colormap is black
if (col == RGB(0, 0, 0))
{
rgb++;
col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
// If the second color is white, create a monochrome bitmap
fColor = (col != RGB(0xff,0xff,0xff));
}
else fColor = TRUE;
}
// Now create the bitmap
if (fColor)
{
if (init & CBM_CREATDIB)
{
PSURFACE Surface;
PPALETTE Palette;
/* Undocumented flag which creates a DDB of the format specified by the bitmap info. */
handle = IntCreateCompatibleBitmap(Dc, width, height, planes, bpp);
if (!handle)
{
DPRINT1("IntCreateCompatibleBitmap() failed!\n");
return NULL;
}
/* The palette must also match the given data */
Surface = SURFACE_ShareLockSurface(handle);
ASSERT(Surface);
Palette = CreateDIBPalette(data, Dc, coloruse);
if (Palette == NULL)
{
SURFACE_ShareUnlockSurface(Surface);
GreDeleteObject(handle);
return NULL;
}
SURFACE_vSetPalette(Surface, Palette);
PALETTE_ShareUnlockPalette(Palette);
SURFACE_ShareUnlockSurface(Surface);
}
else
{
/* Create a regular compatible bitmap, in the same format as the device */
handle = IntCreateCompatibleBitmap(Dc, width, height, 0, 0);
}
}
else
{
handle = GreCreateBitmap(width,
abs(height),
1,
1,
NULL);
}
if (height < 0)
height = -height;
if ((NULL != handle) && (CBM_INIT & init))
{
IntSetDIBits(Dc, handle, 0, height, bits, cjMaxBits, data, coloruse);
}
return handle;
}
// The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
// The DDB that is created will be whatever bit depth your reference DC is
HBITMAP
APIENTRY
NtGdiCreateDIBitmapInternal(
IN HDC hDc,
IN INT cx,
IN INT cy,
IN DWORD fInit,
IN OPTIONAL LPBYTE pjInit,
IN OPTIONAL LPBITMAPINFO pbmi,
IN DWORD iUsage,
IN UINT cjMaxInitInfo,
IN UINT cjMaxBits,
IN FLONG fl,
IN HANDLE hcmXform)
{
NTSTATUS Status = STATUS_SUCCESS;
PBYTE safeBits = NULL;
HBITMAP hbmResult = NULL;
if (pjInit == NULL)
{
fInit &= ~CBM_INIT;
}
if(pjInit && (fInit & CBM_INIT))
{
if (cjMaxBits == 0) return NULL;
safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
if(!safeBits)
{
DPRINT1("Failed to allocate %lu bytes\n", cjMaxBits);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
}
_SEH2_TRY
{
if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
if(pjInit && (fInit & CBM_INIT))
{
ProbeForRead(pjInit, cjMaxBits, 1);
RtlCopyMemory(safeBits, pjInit, cjMaxBits);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if(!NT_SUCCESS(Status))
{
DPRINT1("Got an exception! pjInit = %p\n", pjInit);
SetLastNtError(Status);
goto cleanup;
}
hbmResult = GreCreateDIBitmapInternal(hDc,
cx,
cy,
fInit,
safeBits,
pbmi,
iUsage,
fl,
cjMaxBits,
hcmXform);
cleanup:
if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
return hbmResult;
}
HBITMAP
NTAPI
GreCreateDIBitmapInternal(
IN HDC hDc,
IN INT cx,
IN INT cy,
IN DWORD fInit,
IN OPTIONAL LPBYTE pjInit,
IN OPTIONAL PBITMAPINFO pbmi,
IN DWORD iUsage,
IN FLONG fl,
IN UINT cjMaxBits,
IN HANDLE hcmXform)
{
PDC Dc;
HBITMAP Bmp;
USHORT bpp, planes;
DWORD compression;
HDC hdcDest;
if (!hDc) /* 1bpp monochrome bitmap */
{
// Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
hdcDest = NtGdiCreateCompatibleDC(0);
if(!hdcDest)
{
DPRINT1("NtGdiCreateCompatibleDC failed\n");
return NULL;
}
}
else
{
hdcDest = hDc;
}
Dc = DC_LockDc(hdcDest);
if (!Dc)
{
DPRINT1("Failed to lock hdcDest %p\n", hdcDest);
EngSetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
/* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
* if bpp != 1 and ignore the real value that was passed */
if (pbmi)
{
if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
BITMAPCOREHEADER* CoreHeader = (BITMAPCOREHEADER*)&pbmi->bmiHeader;
bpp = CoreHeader->bcBitCount;
planes = CoreHeader->bcPlanes ? CoreHeader->bcPlanes : 1;
compression = BI_RGB;
}
else
{
bpp = pbmi->bmiHeader.biBitCount;
planes = pbmi->bmiHeader.biPlanes ? pbmi->bmiHeader.biPlanes : 1;
compression = pbmi->bmiHeader.biCompression;
}
}
else
{
bpp = 0;
planes = 0;
compression = 0;
}
Bmp = IntCreateDIBitmap(Dc, cx, cy, planes, bpp, compression, fInit, pjInit, cjMaxBits, pbmi, iUsage);
DC_UnlockDc(Dc);
if(!hDc)
{
NtGdiDeleteObjectApp(hdcDest);
}
return Bmp;
}
HBITMAP
NTAPI
GreCreateDIBitmapFromPackedDIB(
_In_reads_(cjPackedDIB )PVOID pvPackedDIB,
_In_ UINT cjPackedDIB,
_In_ ULONG uUsage)
{
PBITMAPINFO pbmi;
PBYTE pjBits;
UINT cjInfo, cjBits;
HBITMAP hbm;
/* We only support BITMAPINFOHEADER, make sure the size is ok */
if (cjPackedDIB < sizeof(BITMAPINFOHEADER))
{
return NULL;
}
/* The packed DIB starts with the BITMAPINFOHEADER */
pbmi = pvPackedDIB;
if (cjPackedDIB < pbmi->bmiHeader.biSize)
{
return NULL;
}
/* Calculate the info size and make sure the packed DIB is large enough */
cjInfo = DIB_BitmapInfoSize(pbmi, uUsage);
if (cjPackedDIB <= cjInfo)
{
return NULL;
}
/* The bitmap bits start after the header */
pjBits = (PBYTE)pvPackedDIB + cjInfo;
cjBits = cjPackedDIB - cjInfo;
hbm = GreCreateDIBitmapInternal(NULL,
pbmi->bmiHeader.biWidth,
abs(pbmi->bmiHeader.biHeight),
CBM_INIT | CBM_CREATDIB,
pjBits,
pbmi,
uUsage,
0,
cjBits,
NULL);
return hbm;
}
HBITMAP
APIENTRY
NtGdiCreateDIBSection(
IN HDC hDC,
IN OPTIONAL HANDLE hSection,
IN DWORD dwOffset,
IN BITMAPINFO* bmi,
IN DWORD Usage,
IN UINT cjHeader,
IN FLONG fl,
IN ULONG_PTR dwColorSpace,
OUT PVOID *Bits)
{
HBITMAP hbitmap = 0;
DC *dc;
BOOL bDesktopDC = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
if (!bmi) return hbitmap; // Make sure.
_SEH2_TRY
{
ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, (WORD)Usage), 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return NULL;
}
// If the reference hdc is null, take the desktop dc
if (hDC == 0)
{
hDC = NtGdiCreateCompatibleDC(0);
bDesktopDC = TRUE;
}
if ((dc = DC_LockDc(hDC)))
{
hbitmap = DIB_CreateDIBSection(dc,
bmi,
Usage,
Bits,
hSection,
dwOffset,
0);
DC_UnlockDc(dc);
}
else
{
EngSetLastError(ERROR_INVALID_HANDLE);
}
if (bDesktopDC)
NtGdiDeleteObjectApp(hDC);
return hbitmap;
}
HBITMAP
APIENTRY
DIB_CreateDIBSection(
PDC dc,
CONST BITMAPINFO *bmi,
UINT usage,
LPVOID *bits,
HANDLE section,
DWORD offset,
DWORD ovr_pitch)
{
HBITMAP res = 0;
SURFACE *bmp = NULL;
void *mapBits = NULL;
PPALETTE ppalDIB = NULL;
// Fill BITMAP32 structure with DIB data
CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
INT effHeight;
ULONG totalSize;
BITMAP bm;
//SIZEL Size;
HANDLE hSecure;
DPRINT("format (%ld,%ld), planes %u, bpp %u, size %lu, colors %lu (%s)\n",
bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
/* CreateDIBSection should fail for compressed formats */
if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
{
DPRINT1("no compressed format allowed\n");
return (HBITMAP)NULL;
}
effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
bm.bmType = 0;
bm.bmWidth = bi->biWidth;
bm.bmHeight = effHeight;
bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
bm.bmPlanes = bi->biPlanes;
bm.bmBitsPixel = bi->biBitCount;
bm.bmBits = NULL;
// Get storage location for DIB bits. Only use biSizeImage if it's valid and
// we're dealing with a compressed bitmap. Otherwise, use width * height.
totalSize = (bi->biSizeImage && (bi->biCompression != BI_RGB) && (bi->biCompression != BI_BITFIELDS))
? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
if (section)
{
SYSTEM_BASIC_INFORMATION Sbi;
NTSTATUS Status;
DWORD mapOffset;
LARGE_INTEGER SectionOffset;
SIZE_T mapSize;
Status = ZwQuerySystemInformation(SystemBasicInformation,
&Sbi,
sizeof Sbi,
0);
if (!NT_SUCCESS(Status))
{
DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status);
return NULL;
}
mapOffset = offset - (offset % Sbi.AllocationGranularity);
mapSize = totalSize + (offset - mapOffset);
SectionOffset.LowPart = mapOffset;
SectionOffset.HighPart = 0;
Status = ZwMapViewOfSection(section,
NtCurrentProcess(),
&mapBits,
0,
0,
&SectionOffset,
&mapSize,
ViewShare,
0,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status);
EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
}
else if (ovr_pitch && offset)
bm.bmBits = UlongToPtr(offset);
else
{
offset = 0;
bm.bmBits = EngAllocUserMem(totalSize, 0);
if(!bm.bmBits)
{
DPRINT1("Failed to allocate memory\n");
goto cleanup;
}
}
// hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
// Create Device Dependent Bitmap and add DIB pointer
//Size.cx = bm.bmWidth;
//Size.cy = abs(bm.bmHeight);
res = GreCreateBitmapEx(bm.bmWidth,
abs(bm.bmHeight),
bm.bmWidthBytes,
BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
totalSize,
bm.bmBits,
0);
if (!res)
{
DPRINT1("GreCreateBitmapEx failed\n");
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
goto cleanup;
}
bmp = SURFACE_ShareLockSurface(res); // HACK
if (NULL == bmp)
{
DPRINT1("SURFACE_LockSurface failed\n");
EngSetLastError(ERROR_INVALID_HANDLE);
goto cleanup;
}
/* WINE NOTE: WINE makes use of a colormap, which is a color translation
table between the DIB and the X physical device. Obviously,
this is left out of the ReactOS implementation. Instead,
we call NtGdiSetDIBColorTable. */
bmp->hDIBSection = section;
bmp->hSecure = hSecure;
bmp->dwOffset = offset;
bmp->flags = API_BITMAP;
bmp->biClrImportant = bi->biClrImportant;
/* Create a palette for the DIB */
ppalDIB = CreateDIBPalette(bmi, dc, usage);
// Clean up in case of errors
cleanup:
if (!res || !bmp || !bm.bmBits || !ppalDIB)
{
DPRINT("Got an error res=%p, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
if (bm.bmBits)
{
// MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
if (section)
{
ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
bm.bmBits = NULL;
}
else if (!offset)
EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
}
if (bmp)
{
SURFACE_ShareUnlockSurface(bmp);
bmp = NULL;
}
if (res)
{
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
GreDeleteObject(res);
res = 0;
}
if(ppalDIB)
{
PALETTE_ShareUnlockPalette(ppalDIB);
}
}
if (bmp)
{
/* If we're here, everything went fine */
SURFACE_vSetPalette(bmp, ppalDIB);
PALETTE_ShareUnlockPalette(ppalDIB);
SURFACE_ShareUnlockSurface(bmp);
}
// Return BITMAP handle and storage location
if (NULL != bm.bmBits && NULL != bits)
{
*bits = bm.bmBits;
}
return res;
}
/***********************************************************************
* DIB_GetBitmapInfo
*
* Get the info from a bitmap header.
* Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
*/
int
FASTCALL
DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
{
if (header->biSize == sizeof(BITMAPCOREHEADER))
{
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
*width = core->bcWidth;
*height = core->bcHeight;
*planes = core->bcPlanes;
*bpp = core->bcBitCount;
*compr = BI_RGB;
*size = 0;
return 0;
}
if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* Assume BITMAPINFOHEADER */
{
*width = header->biWidth;
*height = header->biHeight;
*planes = header->biPlanes;
*bpp = header->biBitCount;
*compr = header->biCompression;
*size = header->biSizeImage;
return 1;
}
DPRINT1("(%u): unknown/wrong size for header\n", header->biSize );
return -1;
}
/***********************************************************************
* DIB_GetDIBImageBytes
*
* Return the number of bytes used to hold the image in a DIB bitmap.
* 11/16/1999 (RJJ) lifted from wine
*/
INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
{
return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
}
/***********************************************************************
* DIB_BitmapInfoSize
*
* Return the size of the bitmap info structure including color table.
* 11/16/1999 (RJJ) lifted from wine
*/
INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
{
unsigned int colors, size, masks = 0;
unsigned int colorsize;
colorsize = (coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) :
(coloruse == DIB_PAL_INDICES) ? 0 :
sizeof(WORD);
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
return sizeof(BITMAPCOREHEADER) + colors * colorsize;
}
else /* Assume BITMAPINFOHEADER */
{
colors = info->bmiHeader.biClrUsed;
if (colors > 256) colors = 256;
if (!colors && (info->bmiHeader.biBitCount <= 8))
colors = 1 << info->bmiHeader.biBitCount;
if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
return size + colors * colorsize;
}
}
HPALETTE
FASTCALL
DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
{
PPALETTE ppalNew;
ULONG nNumColors,i;
USHORT *lpIndex;
HPALETTE hpal;
if (!(ppalDc->flFlags & PAL_INDEXED))
{
return NULL;
}
nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
if (lpbmi->bmiHeader.biClrUsed)
{
nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
}
ppalNew = PALETTE_AllocPalWithHandle(PAL_INDEXED, nNumColors, NULL, 0, 0, 0);
if (ppalNew == NULL)
{
DPRINT1("Could not allocate palette\n");
return NULL;
}
lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
for (i = 0; i < nNumColors; i++)
{
ULONG iColorIndex = *lpIndex % ppalDc->NumColors;
ppalNew->IndexedColors[i] = ppalDc->IndexedColors[iColorIndex];
lpIndex++;
}
hpal = ppalNew->BaseObject.hHmgr;
PALETTE_UnlockPalette(ppalNew);
return hpal;
}
/* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
* or does nothing if it's already a BITMAPINFO (or V4 or V5) */
BITMAPINFO*
FASTCALL
DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
{
CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
BITMAPINFO* pNewBmi ;
UINT numColors = 0, ColorsSize = 0;
if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
if(pbmci->bmciHeader.bcBitCount <= 8)
{
numColors = 1 << pbmci->bmciHeader.bcBitCount;
if(Usage == DIB_PAL_COLORS)
{
ColorsSize = numColors * sizeof(WORD);
}
else
{
ColorsSize = numColors * sizeof(RGBQUAD);
}
}
else if (Usage == DIB_PAL_COLORS)
{
/* Invalid at high-res */
return NULL;
}
pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
if(!pNewBmi) return NULL;
RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
pNewBmi->bmiHeader.biCompression = BI_RGB ;
pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
pNewBmi->bmiHeader.biHeight,
pNewBmi->bmiHeader.biBitCount);
pNewBmi->bmiHeader.biClrUsed = numColors;
if(Usage == DIB_PAL_COLORS)
{
RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
}
else
{
UINT i;
for(i=0; i<numColors; i++)
{
pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
}
}
return pNewBmi ;
}
/* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
VOID
FASTCALL
DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig, DWORD usage)
{
BITMAPCOREINFO* pbmci;
if(converted == orig)
return;
if(usage == -1)
{
/* Caller don't want any conversion */
ExFreePoolWithTag(converted, TAG_DIB);
return;
}
/* Perform inverse conversion */
pbmci = (BITMAPCOREINFO*)orig;
ASSERT(pbmci->bmciHeader.bcSize == sizeof(BITMAPCOREHEADER));
pbmci->bmciHeader.bcBitCount = converted->bmiHeader.biBitCount;
pbmci->bmciHeader.bcWidth = converted->bmiHeader.biWidth;
pbmci->bmciHeader.bcHeight = converted->bmiHeader.biHeight;
pbmci->bmciHeader.bcPlanes = converted->bmiHeader.biPlanes;
if(pbmci->bmciHeader.bcBitCount <= 8)
{
UINT numColors = converted->bmiHeader.biClrUsed;
if(!numColors) numColors = 1 << pbmci->bmciHeader.bcBitCount;
if(usage == DIB_PAL_COLORS)
{
RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(WORD));
RtlCopyMemory(pbmci->bmciColors, converted->bmiColors, numColors * sizeof(WORD));
}
else
{
UINT i;
RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(RGBTRIPLE));
for(i=0; i<numColors; i++)
{
pbmci->bmciColors[i].rgbtRed = converted->bmiColors[i].rgbRed;
pbmci->bmciColors[i].rgbtGreen = converted->bmiColors[i].rgbGreen;
pbmci->bmciColors[i].rgbtBlue = converted->bmiColors[i].rgbBlue;
}
}
}
/* Now free it, it's not needed anymore */
ExFreePoolWithTag(converted, TAG_DIB);
}
/* EOF */