- Update gdi32_winetest to Wine-1.1.31 keeping a bitmap font test skipping hack.
[reactos.git] / rostests / winetests / gdi32 / bitmap.c
index a0d4531..517033c 100755 (executable)
@@ -780,7 +780,9 @@ static void test_dibsections(void)
     BitBlt(hdcmem2, 0, 0, 16,16, hdcmem, 0, 0, SRCCOPY);
 
     ok(bits32[0] == 0xff00, "lower left pixel is %08x\n", bits32[0]);
-    ok(bits32[17] == 0xff00ff, "bottom but one, left pixel is %08x\n", bits32[17]);
+    ok(bits32[17] == 0xff00ff ||
+       broken(bits32[17] == 0x00ff00), /* Intermittent on Win9x/ME */
+       "bottom but one, left pixel is %08x\n", bits32[17]);
 
     SelectObject(hdcmem2, oldbm2);
     test_dib_info(hdib2, bits32, &pbmi->bmiHeader);
@@ -1954,7 +1956,9 @@ static void test_select_object(void)
         ok(bm.bmWidthBytes == BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel), "wrong bmWidthBytes %d\n", bm.bmWidthBytes);
         ok(bm.bmPlanes == planes, "wrong bmPlanes %u\n", bm.bmPlanes);
         if(depths[i] == 15) {
-            ok(bm.bmBitsPixel == 16, "wrong bmBitsPixel %d(15 bpp special)\n", bm.bmBitsPixel);
+            ok(bm.bmBitsPixel == 16 ||
+               broken(bm.bmBitsPixel == 15), /* Win9x/WinME */
+               "wrong bmBitsPixel %d(15 bpp special)\n", bm.bmBitsPixel);
         } else {
             ok(bm.bmBitsPixel == depths[i], "wrong bmBitsPixel %d\n", bm.bmBitsPixel);
         }
@@ -2248,6 +2252,469 @@ static void test_get16dibits(void)
     ReleaseDC(NULL, screen_dc);
 }
 
+static BOOL compare_buffers_no_alpha(UINT32 *a, UINT32 *b, int length)
+{
+    int i;
+    for(i = 0; i < length; i++)
+        if((a[i] & 0x00FFFFFF) != (b[i] & 0x00FFFFFF))
+            return FALSE;
+    return TRUE;
+}
+
+static void check_BitBlt_pixel(HDC hdcDst, HDC hdcSrc, UINT32 *dstBuffer, UINT32 *srcBuffer,
+                               DWORD dwRop, UINT32 expected, int line)
+{
+    *srcBuffer = 0xFEDCBA98;
+    *dstBuffer = 0x89ABCDEF;
+    Rectangle(hdcSrc, 0, 0, 1, 1);  /* A null operation to ensure dibs are coerced to X11 */
+    BitBlt(hdcDst, 0, 0, 1, 1, hdcSrc, 0, 0, dwRop);
+    ok(expected == *dstBuffer,
+        "BitBlt with dwRop %06X. Expected 0x%08X, got 0x%08X from line %d\n",
+        dwRop, expected, *dstBuffer, line);
+}
+
+static void test_BitBlt(void)
+{
+    HBITMAP bmpDst, bmpSrc;
+    HBITMAP oldDst, oldSrc;
+    HDC hdcScreen, hdcDst, hdcSrc;
+    UINT32 *dstBuffer, *srcBuffer;
+    HBRUSH hBrush, hOldBrush;
+    BITMAPINFO bitmapInfo;
+
+    memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
+    bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bitmapInfo.bmiHeader.biWidth = 1;
+    bitmapInfo.bmiHeader.biHeight = 1;
+    bitmapInfo.bmiHeader.biPlanes = 1;
+    bitmapInfo.bmiHeader.biBitCount = 32;
+    bitmapInfo.bmiHeader.biCompression = BI_RGB;
+    bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
+
+    hdcScreen = CreateCompatibleDC(0);
+    hdcDst = CreateCompatibleDC(hdcScreen);
+    hdcSrc = CreateCompatibleDC(hdcDst);
+
+    /* Setup the destination dib section */
+    bmpDst = CreateDIBSection(hdcScreen, &bitmapInfo, DIB_RGB_COLORS, (void**)&dstBuffer,
+        NULL, 0);
+    oldDst = SelectObject(hdcDst, bmpDst);
+
+    hBrush = CreateSolidBrush(0x012345678);
+    hOldBrush = SelectObject(hdcDst, hBrush);
+
+    /* Setup the source dib section */
+    bmpSrc = CreateDIBSection(hdcScreen, &bitmapInfo, DIB_RGB_COLORS, (void**)&srcBuffer,
+        NULL, 0);
+    oldSrc = SelectObject(hdcSrc, bmpSrc);
+
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCCOPY, 0xFEDCBA98, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCPAINT, 0xFFFFFFFF, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCAND, 0x88888888, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCINVERT, 0x77777777, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCERASE, 0x76543210, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, NOTSRCCOPY, 0x01234567, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, NOTSRCERASE, 0x00000000, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, MERGECOPY, 0x00581210, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, MERGEPAINT, 0x89ABCDEF, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATCOPY, 0x00785634, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATPAINT, 0x89FBDFFF, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATINVERT, 0x89D39BDB, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, DSTINVERT, 0x76543210, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, BLACKNESS, 0x00000000, __LINE__);
+    check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, WHITENESS, 0xFFFFFFFF, __LINE__);
+
+    /* Tidy up */
+    SelectObject(hdcSrc, oldSrc);
+    DeleteObject(bmpSrc);
+    DeleteDC(hdcSrc);
+
+    SelectObject(hdcDst, hOldBrush);
+    DeleteObject(hBrush);
+    SelectObject(hdcDst, oldDst);
+    DeleteObject(bmpDst);
+    DeleteDC(hdcDst);
+
+
+    DeleteDC(hdcScreen);
+}
+
+static void check_StretchBlt_pixel(HDC hdcDst, HDC hdcSrc, UINT32 *dstBuffer, UINT32 *srcBuffer,
+                                   DWORD dwRop, UINT32 expected, int line)
+{
+    *srcBuffer = 0xFEDCBA98;
+    *dstBuffer = 0x89ABCDEF;
+    StretchBlt(hdcDst, 0, 0, 2, 1, hdcSrc, 0, 0, 1, 1, dwRop);
+    ok(expected == *dstBuffer,
+        "StretchBlt with dwRop %06X. Expected 0x%08X, got 0x%08X from line %d\n",
+        dwRop, expected, *dstBuffer, line);
+}
+
+static void check_StretchBlt_stretch(HDC hdcDst, HDC hdcSrc, UINT32 *dstBuffer, UINT32 *srcBuffer,
+                                     int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
+                                     int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
+                                     UINT32 expected[4], UINT32 legacy_expected[4], int line)
+{
+    memset(dstBuffer, 0, 16);
+    StretchBlt(hdcDst, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
+               hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);
+    ok(memcmp(dstBuffer, expected, 16) == 0 ||
+        broken(compare_buffers_no_alpha(dstBuffer, legacy_expected, 4)),
+        "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X } "
+        "stretching { %d, %d, %d, %d } to { %d, %d, %d, %d } from line %d\n",
+        expected[0], expected[1], expected[2], expected[3],
+        dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3],
+        nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+        nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, line);
+}
+
+static void test_StretchBlt(void)
+{
+    HBITMAP bmpDst, bmpSrc;
+    HBITMAP oldDst, oldSrc;
+    HDC hdcScreen, hdcDst, hdcSrc;
+    UINT32 *dstBuffer, *srcBuffer;
+    HBRUSH hBrush, hOldBrush;
+    BITMAPINFO biDst, biSrc;
+    UINT32 expected[4], legacy_expected[4];
+
+    memset(&biDst, 0, sizeof(BITMAPINFO));
+    biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    biDst.bmiHeader.biWidth = 2;
+    biDst.bmiHeader.biHeight = -2;
+    biDst.bmiHeader.biPlanes = 1;
+    biDst.bmiHeader.biBitCount = 32;
+    biDst.bmiHeader.biCompression = BI_RGB;
+    memcpy(&biSrc, &biDst, sizeof(BITMAPINFO));
+
+    hdcScreen = CreateCompatibleDC(0);
+    hdcDst = CreateCompatibleDC(hdcScreen);
+    hdcSrc = CreateCompatibleDC(hdcDst);
+
+    /* Pixel Tests */
+    bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer,
+        NULL, 0);
+    oldDst = SelectObject(hdcDst, bmpDst);
+
+    bmpSrc = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&srcBuffer,
+        NULL, 0);
+    oldSrc = SelectObject(hdcSrc, bmpSrc);
+
+    hBrush = CreateSolidBrush(0x012345678);
+    hOldBrush = SelectObject(hdcDst, hBrush);
+
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCCOPY, 0xFEDCBA98, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCPAINT, 0xFFFFFFFF, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCAND, 0x88888888, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCINVERT, 0x77777777, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCERASE, 0x76543210, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, NOTSRCCOPY, 0x01234567, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, NOTSRCERASE, 0x00000000, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, MERGECOPY, 0x00581210, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, MERGEPAINT, 0x89ABCDEF, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATCOPY, 0x00785634, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATPAINT, 0x89FBDFFF, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATINVERT, 0x89D39BDB, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, DSTINVERT, 0x76543210, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, BLACKNESS, 0x00000000, __LINE__);
+    check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, WHITENESS, 0xFFFFFFFF, __LINE__);
+
+    SelectObject(hdcDst, hOldBrush);
+    DeleteObject(hBrush);
+
+    /* Top-down to top-down tests */
+    srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE;
+    srcBuffer[2] = 0xFEDCBA98, srcBuffer[3] = 0x76543210;
+
+    expected[0] = 0xCAFED00D, expected[1] = 0xFEEDFACE;
+    expected[2] = 0xFEDCBA98, expected[3] = 0x76543210;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    expected[0] = 0xCAFED00D, expected[1] = 0x00000000;
+    expected[2] = 0x00000000, expected[3] = 0x00000000;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 1, 1, 0, 0, 1, 1, expected, expected, __LINE__);
+
+    expected[0] = 0xCAFED00D, expected[1] = 0xCAFED00D;
+    expected[2] = 0xCAFED00D, expected[3] = 0xCAFED00D;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 2, 2, 0, 0, 1, 1, expected, expected, __LINE__);
+
+    expected[0] = 0xCAFED00D, expected[1] = 0x00000000;
+    expected[2] = 0x00000000, expected[3] = 0x00000000;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 1, 1, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    expected[0] = 0x76543210, expected[1] = 0xFEDCBA98;
+    expected[2] = 0xFEEDFACE, expected[3] = 0xCAFED00D;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__);
+
+    expected[0] = 0x76543210, expected[1] = 0xFEDCBA98;
+    expected[2] = 0xFEEDFACE, expected[3] = 0xCAFED00D;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             1, 1, -2, -2, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    /* This result seems broken. One might expect the following result:
+     * 0xCAFED00D 0xFEEDFACE
+     * 0xFEDCBA98 0x76543210
+     */
+    expected[0] = 0xCAFED00D, expected[1] = 0x00000000;
+    expected[2] = 0xFEDCBA98, expected[3] = 0x76543210;
+    legacy_expected[0] = 0xCAFED00D, legacy_expected[1] = 0x00000000;
+    legacy_expected[2] = 0x00000000, legacy_expected[3] = 0x00000000;
+    todo_wine check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                                       1, 1, -2, -2, 1, 1, -2, -2, expected,
+                                       legacy_expected, __LINE__);
+
+    expected[0] = 0x00000000, expected[1] = 0x00000000;
+    expected[2] = 0x00000000, expected[3] = 0xCAFED00D;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             1, 1, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    SelectObject(hdcDst, oldDst);
+    DeleteObject(bmpDst);
+
+    /* Top-down to bottom-up tests */
+    biDst.bmiHeader.biHeight = 2;
+    bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer,
+        NULL, 0);
+    oldDst = SelectObject(hdcDst, bmpDst);
+
+    expected[0] = 0xFEDCBA98, expected[1] = 0x76543210;
+    expected[2] = 0xCAFED00D, expected[3] = 0xFEEDFACE;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    expected[0] = 0xFEEDFACE, expected[1] = 0xCAFED00D;
+    expected[2] = 0x76543210, expected[3] = 0xFEDCBA98;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__);
+
+    SelectObject(hdcSrc, oldSrc);
+    DeleteObject(bmpSrc);
+
+    /* Bottom-up to bottom-up tests */
+    biSrc.bmiHeader.biHeight = 2;
+    bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer,
+        NULL, 0);
+    srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE;
+    srcBuffer[2] = 0xFEDCBA98, srcBuffer[3] = 0x76543210;
+    oldSrc = SelectObject(hdcSrc, bmpSrc);
+
+    expected[0] = 0xCAFED00D, expected[1] = 0xFEEDFACE;
+    expected[2] = 0xFEDCBA98, expected[3] = 0x76543210;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    expected[0] = 0x76543210, expected[1] = 0xFEDCBA98;
+    expected[2] = 0xFEEDFACE, expected[3] = 0xCAFED00D;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__);
+
+    SelectObject(hdcDst, oldDst);
+    DeleteObject(bmpDst);
+
+    /* Bottom-up to top-down tests */
+    biDst.bmiHeader.biHeight = -2;
+    bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer,
+        NULL, 0);
+    oldDst = SelectObject(hdcDst, bmpDst);
+
+    expected[0] = 0xFEDCBA98, expected[1] = 0x76543210;
+    expected[2] = 0xCAFED00D, expected[3] = 0xFEEDFACE;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    expected[0] = 0xFEEDFACE, expected[1] = 0xCAFED00D;
+    expected[2] = 0x76543210, expected[3] = 0xFEDCBA98;
+    check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer,
+                             0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__);
+
+    /* Tidy up */
+    SelectObject(hdcSrc, oldSrc);
+    DeleteObject(bmpSrc);
+    DeleteDC(hdcSrc);
+
+    SelectObject(hdcDst, oldDst);
+    DeleteObject(bmpDst);
+    DeleteDC(hdcDst);
+
+    DeleteDC(hdcScreen);
+}
+
+static void check_StretchDIBits_pixel(HDC hdcDst, UINT32 *dstBuffer, UINT32 *srcBuffer,
+                                      DWORD dwRop, UINT32 expected, int line)
+{
+    const UINT32 buffer[2] = { 0xFEDCBA98, 0 };
+    BITMAPINFO bitmapInfo;
+
+    memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
+    bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bitmapInfo.bmiHeader.biWidth = 2;
+    bitmapInfo.bmiHeader.biHeight = 1;
+    bitmapInfo.bmiHeader.biPlanes = 1;
+    bitmapInfo.bmiHeader.biBitCount = 32;
+    bitmapInfo.bmiHeader.biCompression = BI_RGB;
+    bitmapInfo.bmiHeader.biSizeImage = sizeof(buffer);
+
+    *dstBuffer = 0x89ABCDEF;
+
+    StretchDIBits(hdcDst, 0, 0, 2, 1, 0, 0, 1, 1, &buffer, &bitmapInfo, DIB_RGB_COLORS, dwRop);
+    ok(expected == *dstBuffer,
+        "StretchDIBits with dwRop %06X. Expected 0x%08X, got 0x%08X from line %d\n",
+        dwRop, expected, *dstBuffer, line);
+}
+
+static void check_StretchDIBits_stretch(HDC hdcDst, UINT32 *dstBuffer, UINT32 *srcBuffer,
+                                        int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
+                                        int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
+                                        UINT32 expected[4], UINT32 legacy_expected[4], int line)
+{
+    BITMAPINFO bitmapInfo;
+
+    memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
+    bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bitmapInfo.bmiHeader.biWidth = 2;
+    bitmapInfo.bmiHeader.biHeight = -2;
+    bitmapInfo.bmiHeader.biPlanes = 1;
+    bitmapInfo.bmiHeader.biBitCount = 32;
+    bitmapInfo.bmiHeader.biCompression = BI_RGB;
+
+    memset(dstBuffer, 0, 16);
+    StretchDIBits(hdcDst, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
+                  nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+                  srcBuffer, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
+    ok(memcmp(dstBuffer, expected, 16) == 0 ||                              /* Win2k/XP */
+        broken(compare_buffers_no_alpha(dstBuffer, legacy_expected, 4)) ||  /* Win9X/ME */
+        broken(nWidthSrc < 0 || nHeightSrc < 0),                            /* Win9X/ME */
+        "StretchDIBits expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X } "
+        "stretching { %d, %d, %d, %d } to { %d, %d, %d, %d } from line %d\n",
+        expected[0], expected[1], expected[2], expected[3],
+        dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3],
+        nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+        nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, line);
+}
+
+static void test_StretchDIBits(void)
+{
+    HBITMAP bmpDst;
+    HBITMAP oldDst;
+    HDC hdcScreen, hdcDst;
+    UINT32 *dstBuffer, srcBuffer[4];
+    HBRUSH hBrush, hOldBrush;
+    BITMAPINFO biDst;
+    UINT32 expected[4], legacy_expected[4];
+
+    memset(&biDst, 0, sizeof(BITMAPINFO));
+    biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    biDst.bmiHeader.biWidth = 2;
+    biDst.bmiHeader.biHeight = -2;
+    biDst.bmiHeader.biPlanes = 1;
+    biDst.bmiHeader.biBitCount = 32;
+    biDst.bmiHeader.biCompression = BI_RGB;
+
+    hdcScreen = CreateCompatibleDC(0);
+    hdcDst = CreateCompatibleDC(hdcScreen);
+
+    /* Pixel Tests */
+    bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer,
+        NULL, 0);
+    oldDst = SelectObject(hdcDst, bmpDst);
+
+    hBrush = CreateSolidBrush(0x012345678);
+    hOldBrush = SelectObject(hdcDst, hBrush);
+
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCCOPY, 0xFEDCBA98, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCPAINT, 0xFFFFFFFF, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCAND, 0x88888888, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCINVERT, 0x77777777, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCERASE, 0x76543210, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, NOTSRCCOPY, 0x01234567, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, NOTSRCERASE, 0x00000000, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, MERGECOPY, 0x00581210, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, MERGEPAINT, 0x89ABCDEF, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, PATCOPY, 0x00785634, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, PATPAINT, 0x89FBDFFF, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, PATINVERT, 0x89D39BDB, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, DSTINVERT, 0x76543210, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, BLACKNESS, 0x00000000, __LINE__);
+    check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, WHITENESS, 0xFFFFFFFF, __LINE__);
+
+    SelectObject(hdcDst, hOldBrush);
+    DeleteObject(hBrush);
+
+    /* Top-down destination tests */
+    srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE;
+    srcBuffer[2] = 0xFEDCBA98, srcBuffer[3] = 0x76543210;
+
+    expected[0] = 0xCAFED00D, expected[1] = 0xFEEDFACE;
+    expected[2] = 0xFEDCBA98, expected[3] = 0x76543210;
+    check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer,
+                                0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    expected[0] = 0xCAFED00D, expected[1] = 0x00000000;
+    expected[2] = 0x00000000, expected[3] = 0x00000000;
+    legacy_expected[0] = 0xFEDCBA98, legacy_expected[1] = 0x00000000;
+    legacy_expected[2] = 0x00000000, legacy_expected[3] = 0x00000000;
+    todo_wine check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer,
+                                0, 0, 1, 1, 0, 0, 1, 1, expected, legacy_expected, __LINE__);
+
+    expected[0] = 0xFEDCBA98, expected[1] = 0xFEDCBA98;
+    expected[2] = 0xFEDCBA98, expected[3] = 0xFEDCBA98;
+    check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer,
+                                0, 0, 2, 2, 0, 0, 1, 1, expected, expected, __LINE__);
+
+    expected[0] = 0x42441000, expected[1] = 0x00000000;
+    expected[2] = 0x00000000, expected[3] = 0x00000000;
+    legacy_expected[0] = 0x00543210, legacy_expected[1] = 0x00000000;
+    legacy_expected[2] = 0x00000000, legacy_expected[3] = 0x00000000;
+    todo_wine check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer,
+                                0, 0, 1, 1, 0, 0, 2, 2, expected, legacy_expected, __LINE__);
+
+    expected[0] = 0x00000000, expected[1] = 0x00000000;
+    expected[2] = 0x00000000, expected[3] = 0x00000000;
+    check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer,
+                                0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__);
+
+    expected[0] = 0x00000000, expected[1] = 0x00000000;
+    expected[2] = 0x00000000, expected[3] = 0x00000000;
+    check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer,
+                                0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__);
+
+    expected[0] = 0x00000000, expected[1] = 0x00000000;
+    expected[2] = 0x00000000, expected[3] = 0x00000000;
+    check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer,
+                                1, 1, -2, -2, 1, 1, -2, -2, expected, expected, __LINE__);
+
+    expected[0] = 0x00000000, expected[1] = 0x00000000;
+    expected[2] = 0x00000000, expected[3] = 0xCAFED00D;
+    check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer,
+                                1, 1, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    SelectObject(hdcDst, oldDst);
+    DeleteObject(bmpDst);
+
+    /* Bottom up destination tests */
+    biDst.bmiHeader.biHeight = 2;
+    bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer,
+        NULL, 0);
+    oldDst = SelectObject(hdcDst, bmpDst);
+
+    expected[0] = 0xFEDCBA98, expected[1] = 0x76543210;
+    expected[2] = 0xCAFED00D, expected[3] = 0xFEEDFACE;
+    check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer,
+                                0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__);
+
+    /* Tidy up */
+    SelectObject(hdcDst, oldDst);
+    DeleteObject(bmpDst);
+    DeleteDC(hdcDst);
+
+    DeleteDC(hdcScreen);
+}
+
 static void test_GdiAlphaBlend(void)
 {
     /* test out-of-bound parameters for GdiAlphaBlend */
@@ -2311,6 +2778,10 @@ static void test_GdiAlphaBlend(void)
     expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, -1, 0, 30, 30, blend), TRUE, BOOL, "%d");
     expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, 0, -1, 30, 30, blend), TRUE, BOOL, "%d");
 
+    SetLastError(0xdeadbeef);
+    expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, NULL, 0, 0, 20, 20, blend), FALSE, BOOL, "%d");
+    expect_eq(GetLastError(), 0xdeadbeef, int, "%d");
+
     SelectObject(hdcDst, oldDst);
     SelectObject(hdcSrc, oldSrc);
     DeleteObject(bmpSrc);
@@ -2389,6 +2860,9 @@ START_TEST(bitmap)
     test_GetDIBits_BI_BITFIELDS();
     test_select_object();
     test_CreateBitmap();
+    test_BitBlt();
+    test_StretchBlt();
+    test_StretchDIBits();
     test_GdiAlphaBlend();
     test_bitmapinfoheadersize();
     test_get16dibits();