diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index e8b3dc92200..d53b8f2e173 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -205,13 +205,12 @@ INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, } else /* use StretchBlt */ { - HBITMAP hBitmap, hOldBitmap; - HPALETTE hpal = NULL; - HDC hdcMem; LONG height; LONG width; WORD planes, bpp; DWORD compr, size; + HBITMAP hBitmap; + BOOL fastpath = FALSE; release_dc_ptr( dc ); @@ -227,51 +226,84 @@ INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, return 0; } - hdcMem = CreateCompatibleDC( hdc ); - hBitmap = CreateCompatibleBitmap(hdc, width, height); - hOldBitmap = SelectObject( hdcMem, hBitmap ); - if(wUsage == DIB_PAL_COLORS) + hBitmap = GetCurrentObject(hdc, OBJ_BITMAP); + + if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 && + widthDst == widthSrc && heightDst == heightSrc && + info->bmiHeader.biCompression == BI_RGB && + dwRop == SRCCOPY) { - hpal = GetCurrentObject(hdc, OBJ_PAL); - hpal = SelectPalette(hdcMem, hpal, FALSE); + BITMAPOBJ *bmp; + if ((bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC ))) + { + if (bmp->bitmap.bmBitsPixel == bpp && + bmp->bitmap.bmWidth == widthSrc && + bmp->bitmap.bmHeight == heightSrc && + bmp->bitmap.bmPlanes == planes) + fastpath = TRUE; + GDI_ReleaseObj( hBitmap ); + } } - 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 (fastpath) + { + /* fast path */ + TRACE("using fast path\n"); + heightSrc = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage); } + else + { + /* slow path - need to use StretchBlt */ + HBITMAP hOldBitmap; + HPALETTE hpal = NULL; + HDC hdcMem; - SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage); + 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); + } - /* Origin for DIBitmap may be bottom left (positive biHeight) or top - left (negative biHeight) */ - 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 ); + 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 ); + } + + SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage); + + /* Origin for DIBitmap may be bottom left (positive biHeight) or top + left (negative biHeight) */ + 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 ); + } } return heightSrc; }