Commit 5ffbce6d authored by Alexandre Julliard's avatar Alexandre Julliard

gdi32: Add a null driver entry point for StretchDIBits.

parent 1a34f980
......@@ -178,140 +178,95 @@ int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
return -1;
}
/***********************************************************************
* StretchDIBits (GDI32.@)
*/
INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
INT heightSrc, const void *bits,
const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
/* nulldrv fallback implementation using SetDIBits/StretchBlt */
INT CDECL nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
const BITMAPINFO *info, UINT coloruse, DWORD rop )
{
DC *dc;
DC *dc = get_nulldrv_dc( dev );
INT ret;
LONG width, height;
WORD planes, bpp;
DWORD compr, size;
HBITMAP hBitmap;
HDC hdcMem;
if (!bits || !info)
return 0;
if (!(dc = get_dc_ptr( hdc ))) return 0;
if(dc->funcs->pStretchDIBits)
{
update_dc( dc );
ret = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
heightDst, xSrc, ySrc, widthSrc,
heightSrc, bits, info, wUsage, dwRop);
release_dc_ptr( dc );
}
else /* use StretchBlt */
{
LONG height;
LONG width;
WORD planes, bpp;
DWORD compr, size;
HBITMAP hBitmap;
BOOL fastpath = FALSE;
release_dc_ptr( dc );
if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
{
ERR("Invalid bitmap\n");
return 0;
}
/* make sure we have a real implementation for StretchBlt and SetDIBits */
if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pSetDIBits ) == dev)
return 0;
if (width < 0)
{
ERR("Bitmap has a negative width\n");
return 0;
}
if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
return 0;
if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
info->bmiHeader.biCompression == BI_RGB)
{
/* Windows appears to have a fast case optimization
* that uses the wrong origin for top-down DIBs */
if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
}
if (width < 0) return 0;
hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
info->bmiHeader.biCompression == BI_RGB)
{
/* Windows appears to have a fast case optimization
* that uses the wrong origin for top-down DIBs */
if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
widthDst == widthSrc && heightDst == heightSrc &&
info->bmiHeader.biCompression == BI_RGB &&
dwRop == SRCCOPY)
if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
{
BITMAPOBJ *bmp;
if ((bmp = GDI_GetObjPtr( hBitmap, OBJ_BITMAP )))
BITMAP bm;
hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
bm.bmBitsPixel == bpp && bm.bmPlanes == planes)
{
if (bmp->bitmap.bmBitsPixel == bpp &&
bmp->bitmap.bmWidth == widthSrc &&
bmp->bitmap.bmHeight == heightSrc &&
bmp->bitmap.bmPlanes == planes)
fastpath = TRUE;
GDI_ReleaseObj( hBitmap );
/* fast path */
return SetDIBits( dev->hdc, hBitmap, 0, height, bits, info, coloruse );
}
}
}
if (fastpath)
{
/* fast path */
TRACE("using fast path\n");
ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
}
else
{
/* slow path - need to use StretchBlt */
HBITMAP hOldBitmap;
HPALETTE hpal = NULL;
HDC hdcMem;
hdcMem = CreateCompatibleDC( hdc );
hBitmap = CreateCompatibleBitmap(hdc, width, height);
hOldBitmap = SelectObject( hdcMem, hBitmap );
if(wUsage == DIB_PAL_COLORS)
{
hpal = GetCurrentObject(hdc, OBJ_PAL);
hpal = SelectPalette(hdcMem, hpal, FALSE);
}
hdcMem = CreateCompatibleDC( dev->hdc );
hBitmap = CreateCompatibleBitmap( dev->hdc, width, height );
SelectObject( hdcMem, hBitmap );
if (coloruse == DIB_PAL_COLORS)
SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
if (info->bmiHeader.biCompression == BI_RLE4 ||
info->bmiHeader.biCompression == BI_RLE8) {
/* when RLE compression is used, there may be some gaps (ie the DIB doesn't
* contain all the rectangle described in bmiHeader, but only part of it.
* This mean that those undescribed pixels must be left untouched.
* So, we first copy on a memory bitmap the current content of the
* destination rectangle, blit the DIB bits on top of it - hence leaving
* the gaps untouched -, and blitting the rectangle back.
* This insure that gaps are untouched on the destination rectangle
* Not doing so leads to trashed images (the gaps contain what was on the
* memory bitmap => generally black or garbage)
* Unfortunately, RLE DIBs without gaps will be slowed down. But this is
* another speed vs correctness issue. Anyway, if speed is needed, then the
* pStretchDIBits function shall be implemented.
* ericP (2000/09/09)
*/
/* copy existing bitmap from destination dc */
StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
dwRop );
}
if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
{
/* when RLE compression is used, there may be some gaps (ie the DIB doesn't
* contain all the rectangle described in bmiHeader, but only part of it.
* This mean that those undescribed pixels must be left untouched.
* So, we first copy on a memory bitmap the current content of the
* destination rectangle, blit the DIB bits on top of it - hence leaving
* the gaps untouched -, and blitting the rectangle back.
* This insure that gaps are untouched on the destination rectangle
*/
StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
dev->hdc, xDst, yDst, widthDst, heightDst, rop );
}
ret = SetDIBits( hdcMem, hBitmap, 0, height, bits, info, coloruse );
if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
DeleteDC( hdcMem );
DeleteObject( hBitmap );
return ret;
}
ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
/* Origin for DIBitmap may be bottom left (positive biHeight) or top
left (negative biHeight) */
if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
hdcMem, xSrc, abs(height) - heightSrc - ySrc,
widthSrc, heightSrc, dwRop );
if(hpal)
SelectPalette(hdcMem, hpal, FALSE);
SelectObject( hdcMem, hOldBitmap );
DeleteDC( hdcMem );
DeleteObject( hBitmap );
}
/***********************************************************************
* StretchDIBits (GDI32.@)
*/
INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
const BITMAPINFO *info, UINT coloruse, DWORD rop )
{
DC *dc;
INT ret = 0;
if (!bits || !info) return 0;
if ((dc = get_dc_ptr( hdc )))
{
PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
update_dc( dc );
ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
release_dc_ptr( dc );
}
return ret;
}
......
......@@ -899,7 +899,7 @@ const DC_FUNCTIONS null_driver =
nulldrv_StartDoc, /* pStartDoc */
nulldrv_StartPage, /* pStartPage */
NULL, /* pStretchBlt */
NULL, /* pStretchDIBits */
nulldrv_StretchDIBits, /* pStretchDIBits */
nulldrv_StrokeAndFillPath, /* pStrokeAndFillPath */
nulldrv_StrokePath, /* pStrokePath */
nulldrv_SwapBuffers, /* pSwapBuffers */
......
......@@ -548,6 +548,9 @@ extern BOOL CDECL nulldrv_SetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt
extern BOOL CDECL nulldrv_SetWindowExtEx( PHYSDEV dev, INT cx, INT cy, SIZE *size ) DECLSPEC_HIDDEN;
extern BOOL CDECL nulldrv_SetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN;
extern BOOL CDECL nulldrv_SetWorldTransform( PHYSDEV dev, const XFORM *xform ) DECLSPEC_HIDDEN;
extern INT CDECL nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
const BITMAPINFO *info, UINT coloruse, DWORD rop ) DECLSPEC_HIDDEN;
extern BOOL CDECL nulldrv_StrokeAndFillPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
extern BOOL CDECL nulldrv_StrokePath( PHYSDEV dev ) DECLSPEC_HIDDEN;
extern BOOL CDECL nulldrv_WidenPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment