gdi32: Create a sanitized BITMAPINFO in SetDIBitsToDevice and pass that to the drivers.

This commit is contained in:
Alexandre Julliard 2011-08-04 13:22:53 +02:00
parent d0d98046c6
commit f825f5db8c
4 changed files with 39 additions and 137 deletions

View File

@ -646,13 +646,16 @@ done:
*/ */
INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx, INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
DWORD cy, INT xSrc, INT ySrc, UINT startscan, DWORD cy, INT xSrc, INT ySrc, UINT startscan,
UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
UINT coloruse ) UINT coloruse )
{ {
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
BITMAPINFO *info = (BITMAPINFO *)buffer;
INT ret = 0; INT ret = 0;
DC *dc; DC *dc;
if (!bits) return 0; if (!bits) return 0;
if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse )) return 0;
if ((dc = get_dc_ptr( hdc ))) if ((dc = get_dc_ptr( hdc )))
{ {

View File

@ -232,8 +232,7 @@ INT EMFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD width, DWOR
{ {
EMRSETDIBITSTODEVICE* pEMR; EMRSETDIBITSTODEVICE* pEMR;
DWORD bmiSize = bitmap_info_size(info, wUsage); DWORD bmiSize = bitmap_info_size(info, wUsage);
DWORD bitsSize = get_dib_image_size( info ); DWORD size = sizeof(EMRSETDIBITSTODEVICE) + bmiSize + info->bmiHeader.biSizeImage;
DWORD size = sizeof(EMRSETDIBITSTODEVICE) + bmiSize + bitsSize;
pEMR = HeapAlloc(GetProcessHeap(), 0, size); pEMR = HeapAlloc(GetProcessHeap(), 0, size);
if (!pEMR) return 0; if (!pEMR) return 0;
@ -253,12 +252,12 @@ INT EMFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD width, DWOR
pEMR->offBmiSrc = sizeof(EMRSETDIBITSTODEVICE); pEMR->offBmiSrc = sizeof(EMRSETDIBITSTODEVICE);
pEMR->cbBmiSrc = bmiSize; pEMR->cbBmiSrc = bmiSize;
pEMR->offBitsSrc = sizeof(EMRSETDIBITSTODEVICE) + bmiSize; pEMR->offBitsSrc = sizeof(EMRSETDIBITSTODEVICE) + bmiSize;
pEMR->cbBitsSrc = bitsSize; pEMR->cbBitsSrc = info->bmiHeader.biSizeImage;
pEMR->iUsageSrc = wUsage; pEMR->iUsageSrc = wUsage;
pEMR->iStartScan = startscan; pEMR->iStartScan = startscan;
pEMR->cScans = lines; pEMR->cScans = lines;
memcpy((BYTE*)pEMR + pEMR->offBmiSrc, info, bmiSize); memcpy((BYTE*)pEMR + pEMR->offBmiSrc, info, bmiSize);
memcpy((BYTE*)pEMR + pEMR->offBitsSrc, bits, bitsSize); memcpy((BYTE*)pEMR + pEMR->offBitsSrc, bits, info->bmiHeader.biSizeImage);
if (EMFDRV_WriteRecord(dev, (EMR*)pEMR)) if (EMFDRV_WriteRecord(dev, (EMR*)pEMR))
EMFDRV_UpdateBBox(dev, &(pEMR->rclBounds)); EMFDRV_UpdateBBox(dev, &(pEMR->rclBounds));

View File

@ -171,8 +171,7 @@ INT MFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD cx,
{ {
DWORD infosize = bitmap_info_size(info, coloruse); DWORD infosize = bitmap_info_size(info, coloruse);
DWORD imagesize = get_dib_image_size( info ); DWORD len = sizeof(METARECORD) + 8 * sizeof(WORD) + infosize + info->bmiHeader.biSizeImage;
DWORD len = sizeof(METARECORD) + 8 * sizeof(WORD) + infosize + imagesize;
METARECORD *mr = HeapAlloc( GetProcessHeap(), 0, len ); METARECORD *mr = HeapAlloc( GetProcessHeap(), 0, len );
if(!mr) return 0; if(!mr) return 0;
@ -188,7 +187,7 @@ INT MFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD cx,
mr->rdParm[7] = (INT16)yDst; mr->rdParm[7] = (INT16)yDst;
mr->rdParm[8] = (INT16)xDst; mr->rdParm[8] = (INT16)xDst;
memcpy(mr->rdParm + 9, info, infosize); memcpy(mr->rdParm + 9, info, infosize);
memcpy(mr->rdParm + 9 + infosize / 2, bits, imagesize); memcpy(mr->rdParm + 9 + infosize / 2, bits, info->bmiHeader.biSizeImage);
MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 ); MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 );
HeapFree( GetProcessHeap(), 0, mr ); HeapFree( GetProcessHeap(), 0, mr );
return lines; return lines;

View File

@ -239,42 +239,6 @@ void X11DRV_DIB_DestroyXImage( XImage *image )
} }
/***********************************************************************
* DIB_GetBitmapInfoEx
*
* Get the info from a bitmap header.
* Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
*/
static int DIB_GetBitmapInfoEx( const BITMAPINFOHEADER *header, LONG *width,
LONG *height, WORD *planes, WORD *bpp,
WORD *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 = 0;
*size = 0;
return 0;
}
if (header->biSize >= sizeof(BITMAPINFOHEADER))
{
*width = header->biWidth;
*height = header->biHeight;
*planes = header->biPlanes;
*bpp = header->biBitCount;
*compr = header->biCompression;
*size = header->biSizeImage;
return 1;
}
ERR("(%d): unknown/wrong size for header\n", header->biSize );
return -1;
}
/*********************************************************************** /***********************************************************************
* X11DRV_DIB_GetColorCount * X11DRV_DIB_GetColorCount
* *
@ -283,41 +247,11 @@ static int DIB_GetBitmapInfoEx( const BITMAPINFOHEADER *header, LONG *width,
*/ */
static unsigned int X11DRV_DIB_GetColorCount(const BITMAPINFO *info) static unsigned int X11DRV_DIB_GetColorCount(const BITMAPINFO *info)
{ {
unsigned int colors; unsigned int colors = min( info->bmiHeader.biClrUsed, 256 );
BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER); if (!colors) colors = 1 << info->bmiHeader.biBitCount;
if (core_info)
{
colors = 1 << ((const BITMAPCOREINFO*)info)->bmciHeader.bcBitCount;
}
else
{
colors = info->bmiHeader.biClrUsed;
if (!colors) colors = 1 << info->bmiHeader.biBitCount;
}
if (colors > 256)
{
ERR("called with >256 colors!\n");
colors = 0;
}
return colors; return colors;
} }
/***********************************************************************
* DIB_GetBitmapInfo
*
* Get the info from a bitmap header.
* Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
*/
static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
LONG *height, WORD *bpp, WORD *compr )
{
WORD planes;
DWORD size;
return DIB_GetBitmapInfoEx( header, width, height, &planes, bpp, compr, &size);
}
static inline BOOL colour_is_brighter(RGBQUAD c1, RGBQUAD c2) static inline BOOL colour_is_brighter(RGBQUAD c1, RGBQUAD c2)
{ {
@ -332,61 +266,33 @@ static inline BOOL colour_is_brighter(RGBQUAD c1, RGBQUAD c2)
* for a >8-bit deep bitmap. * for a >8-bit deep bitmap.
*/ */
static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping, static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
WORD coloruse, WORD depth, BOOL quads, WORD coloruse, WORD depth, const void *colorPtr, int start, int end )
const void *colorPtr, int start, int end )
{ {
int i; int i;
if (coloruse == DIB_RGB_COLORS) if (coloruse == DIB_RGB_COLORS)
{ {
if (quads) const RGBQUAD * rgb = colorPtr;
if (depth == 1) /* Monochrome */
{ {
const RGBQUAD * rgb = colorPtr; BOOL invert = FALSE;
RGBQUAD table[2];
if (depth == 1) /* Monochrome */ if (GetDIBColorTable( physDev->dev.hdc, 0, 2, table ) == 2)
{ invert = !colour_is_brighter(table[1], table[0]);
BOOL invert = FALSE;
RGBQUAD table[2];
if (GetDIBColorTable( physDev->dev.hdc, 0, 2, table ) == 2) for (i = start; i < end; i++, rgb++)
invert = !colour_is_brighter(table[1], table[0]); colorMapping[i] = ((rgb->rgbRed + rgb->rgbGreen +
rgb->rgbBlue > 255*3/2 && !invert) ||
for (i = start; i < end; i++, rgb++) (rgb->rgbRed + rgb->rgbGreen +
colorMapping[i] = ((rgb->rgbRed + rgb->rgbGreen + rgb->rgbBlue <= 255*3/2 && invert));
rgb->rgbBlue > 255*3/2 && !invert) ||
(rgb->rgbRed + rgb->rgbGreen +
rgb->rgbBlue <= 255*3/2 && invert));
}
else
for (i = start; i < end; i++, rgb++)
colorMapping[i] = X11DRV_PALETTE_LookupPixel(physDev->color_shifts, RGB(rgb->rgbRed,
rgb->rgbGreen,
rgb->rgbBlue));
} }
else else
{ for (i = start; i < end; i++, rgb++)
const RGBTRIPLE * rgb = colorPtr; colorMapping[i] = X11DRV_PALETTE_LookupPixel(physDev->color_shifts, RGB(rgb->rgbRed,
rgb->rgbGreen,
if (depth == 1) /* Monochrome */ rgb->rgbBlue));
{
BOOL invert = FALSE;
RGBQUAD table[2];
if (GetDIBColorTable( physDev->dev.hdc, 0, 2, table ) == 2)
invert = !colour_is_brighter(table[1], table[0]);
for (i = start; i < end; i++, rgb++)
colorMapping[i] = ((rgb->rgbtRed + rgb->rgbtGreen +
rgb->rgbtBlue > 255*3/2 && !invert) ||
(rgb->rgbtRed + rgb->rgbtGreen +
rgb->rgbtBlue <= 255*3/2 && invert));
}
else
for (i = start; i < end; i++, rgb++)
colorMapping[i] = X11DRV_PALETTE_LookupPixel(physDev->color_shifts, RGB(rgb->rgbtRed,
rgb->rgbtGreen,
rgb->rgbtBlue));
}
} }
else /* DIB_PAL_COLORS */ else /* DIB_PAL_COLORS */
{ {
@ -408,7 +314,6 @@ static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth, static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
const BITMAPINFO *info, int *nColors ) const BITMAPINFO *info, int *nColors )
{ {
BOOL isInfo;
const void *colorPtr; const void *colorPtr;
int *colorMapping; int *colorMapping;
@ -416,13 +321,12 @@ static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WO
*nColors = X11DRV_DIB_GetColorCount(info); *nColors = X11DRV_DIB_GetColorCount(info);
if (!*nColors) return NULL; if (!*nColors) return NULL;
isInfo = info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER);
colorPtr = (const BYTE*)info + (WORD)info->bmiHeader.biSize; colorPtr = (const BYTE*)info + (WORD)info->bmiHeader.biSize;
if (!(colorMapping = HeapAlloc(GetProcessHeap(), 0, *nColors * sizeof(int) ))) if (!(colorMapping = HeapAlloc(GetProcessHeap(), 0, *nColors * sizeof(int) )))
return NULL; return NULL;
return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth, return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
isInfo, colorPtr, 0, *nColors); colorPtr, 0, *nColors);
} }
/*********************************************************************** /***********************************************************************
@ -3836,17 +3740,15 @@ INT X11DRV_SetDIBitsToDevice( PHYSDEV dev, INT xDest, INT yDest, DWORD cx, DWORD
X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
X11DRV_DIB_IMAGEBITS_DESCR descr; X11DRV_DIB_IMAGEBITS_DESCR descr;
INT result; INT result;
LONG width, height; LONG height;
BOOL top_down; BOOL top_down;
POINT pt; POINT pt;
int rop = X11DRV_XROPfunction[GetROP2(dev->hdc) - 1]; int rop = X11DRV_XROPfunction[GetROP2(dev->hdc) - 1];
if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, top_down = (info->bmiHeader.biHeight < 0);
&descr.infoBpp, &descr.compression ) == -1) height = abs( info->bmiHeader.biHeight );
return 0; descr.infoBpp = info->bmiHeader.biBitCount;
descr.compression = info->bmiHeader.biCompression;
top_down = (height < 0);
if (top_down) height = -height;
pt.x = xDest; pt.x = xDest;
pt.y = yDest; pt.y = yDest;
@ -3883,8 +3785,8 @@ INT X11DRV_SetDIBitsToDevice( PHYSDEV dev, INT xDest, INT yDest, DWORD cx, DWORD
ySrc = 0; ySrc = 0;
if (cy > lines) cy = lines; if (cy > lines) cy = lines;
} }
if (xSrc >= width) return lines; if (xSrc >= info->bmiHeader.biWidth) return lines;
if (xSrc + cx >= width) cx = width - xSrc; if (xSrc + cx >= info->bmiHeader.biWidth) cx = info->bmiHeader.biWidth - xSrc;
if (!cx || !cy) return lines; if (!cx || !cy) return lines;
/* Update the pixmap from the DIB section */ /* Update the pixmap from the DIB section */
@ -3928,7 +3830,7 @@ INT X11DRV_SetDIBitsToDevice( PHYSDEV dev, INT xDest, INT yDest, DWORD cx, DWORD
descr.image = NULL; descr.image = NULL;
descr.palentry = NULL; descr.palentry = NULL;
descr.lines = top_down ? -lines : lines; descr.lines = top_down ? -lines : lines;
descr.infoWidth = width; descr.infoWidth = info->bmiHeader.biWidth;
descr.depth = physDev->depth; descr.depth = physDev->depth;
descr.shifts = physDev->color_shifts; descr.shifts = physDev->color_shifts;
descr.drawable = physDev->drawable; descr.drawable = physDev->drawable;
@ -3940,7 +3842,7 @@ INT X11DRV_SetDIBitsToDevice( PHYSDEV dev, INT xDest, INT yDest, DWORD cx, DWORD
descr.width = cx; descr.width = cx;
descr.height = cy; descr.height = cy;
descr.shm_mode = X11DRV_SHM_NONE; descr.shm_mode = X11DRV_SHM_NONE;
descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8; descr.dibpitch = X11DRV_DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
descr.physBitmap = NULL; descr.physBitmap = NULL;
result = X11DRV_DIB_SetImageBits( &descr ); result = X11DRV_DIB_SetImageBits( &descr );
@ -4655,8 +4557,7 @@ UINT X11DRV_SetDIBColorTable( PHYSDEV dev, UINT start, UINT count, const RGBQUAD
*/ */
X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod ); X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod );
X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS, X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS,
dib.dsBm.bmBitsPixel, dib.dsBm.bmBitsPixel, colors, start, end );
TRUE, colors, start, end );
X11DRV_DIB_Unlock( physBitmap, TRUE ); X11DRV_DIB_Unlock( physBitmap, TRUE );
ret = end - start; ret = end - start;
} }