https://git.reactos.org/?p=reactos.git;a=commitdiff;h=89843bec564368a7e1b8b2...
commit 89843bec564368a7e1b8b26bf47d09da3a1ad9dc Author: Doug Lyons douglyons@douglyons.com AuthorDate: Sat Feb 20 17:21:51 2021 -0600 Commit: GitHub noreply@github.com CommitDate: Sun Feb 21 08:21:51 2021 +0900
[GDI32_APITEST] Add more StretchBlt Regression Tests (#3455)
Added tests for many more StretchBlt options. Created StretchBlt regression tests for verifying most flip options. This is preparation for my Pull Request #3458 which will implement the flip functionality for StretchBlt.
CORE-16642 --- modules/rostests/apitests/gdi32/StretchBlt.c | 833 +++++++++++++++++++++++++-- 1 file changed, 797 insertions(+), 36 deletions(-)
diff --git a/modules/rostests/apitests/gdi32/StretchBlt.c b/modules/rostests/apitests/gdi32/StretchBlt.c index c72f9e220f1..5db1713beb6 100644 --- a/modules/rostests/apitests/gdi32/StretchBlt.c +++ b/modules/rostests/apitests/gdi32/StretchBlt.c @@ -2,8 +2,8 @@ * PROJECT: ReactOS API tests * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Tests for the StretchBlt API - * COPYRIGHT: Copyright 2020 Doug Lyons (douglyons at douglyons dot com) - * Most Code copied and modified from Wine gdi32:bitmap test. + * COPYRIGHT: Copyright 2020, 2021 Doug Lyons (douglyons at douglyons dot com) + * Some Code copied and modified from Wine gdi32:bitmap test. */
#include <stdarg.h> @@ -18,91 +18,852 @@ #include "wingdi.h" #include "winuser.h" #include "wine/test.h" +#include <debug.h> + +/* Notes on using the StretchBlt function's general flip ability. + * + * The critical values for flipping are the signs of the values for DestWidth, DestHeight, SourceWidth and SourceHeight. + * If we assign a '0' to values having a negative sign and a '1' to values having a positive sign these can be CaseWXYZ's. + * Where the W, X, Y, and Z are replaced with the '0's and '1's representing the signs of the values in sequential order. + * + * If we take the normal StretchBlt function's copy/scaling with no flips, the generalized code can be represented as follows: + * + * StretchBlt(DestDC, DestX, DestY, (DestWidth), (DestHeight), + * SourceDC, SourceX, SourceY, (SourceWidth), (SourceHeight), SRCCOPY); // Case1111 (15) (all positive signs) + * + * For Horizontal flipping then the generalized form on the Destination side can be represented as follows: + * + * StretchBlt(DestDC, DestX + DestWidth - 1, DestY, -DestWidth, DestHeight, + * SourceDC, SourceX, SourceY, SourceWidth, SourceHeight, SRCCOPY); // Case 0111 (7) + * + * and for Horizontal flipping the generalized form on the Source side can be represented as follows: + * + * StretchBlt(DestDC, DestX, DestY, DestWidth, DestHeight, + * SourceDC, SourceX + SourceWidth - 1, SourceY, -SourceWidth, SourceHeight, SRCCOPY); // Case 1101 (13) + * + * I believe that the "- 1" is used because we are moving from the rightmost position back to the 0th position. + * + * But there are three "special" cases where no flip is done (there is a copy/scale only) and the "-1" is not used. + * These are as follows: + * 1) + * StretchBlt(DestDC, DestX + DestWidth, DestY, -DestWidth, DestHeight, // Both Widths negative + * SourceDC, SourceX + SourceWidth, SourceY, -SourceWidth, SourceHeight, SRCCOPY); // Case0101 (5) + * 2) + * StretchBlt(DestDC, DestX, DestY + DestHeight, DestWidth, -DestHeight, // Both heights negative + * SourceDC, SourceX, SourceY + SourceHeight, SourceWidth, -SourceHeight, SRCCOPY); // Case1010 (10) + * 3) + * StretchBlt(DestDC, DestX + DestWidth, DestY + DestHeight, -DestWidth, -DestHeight, // widths AND heights neg + * SourceDC, SourceX + SourceWidth, SourceY + SourceHeight, -SourceWidth, -SourceHeight, SRCCOPY); // Case0000 (0) + * + * I suspect that these are like this because of legacy reasons when StretchBlt did not support so many flip options. + * + * For Vertical flipping the generalized form on the Destination side can be represented as follows: + * + * StretchBlt(DestDC, DestX, DestY + DestHeight - 1, DestWidth, -DestHeight, + * SourceDC, SourceX, SourceY, SourceWidth, SourceHeight, SRCCOPY); // Case1011 (11) + * + * and for Vertical on the Source Side as folows: + * + * StretchBlt(DestDC, DestX, DestY, DestWidth, -DestHeight, + * SourceDC, SourceX, SourceY + SourceHeight - 1, SourceWidth, -SourceHeight, SRCCOPY); // Case 1010 (10) + */ + +static inline int get_dib_stride( int width, int bpp ) +{ + return ((width * bpp + 31) >> 3) & ~3; +} + +static inline int get_dib_image_size( const BITMAPINFO *info ) +{ + return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount ) + * abs( info->bmiHeader.biHeight ); +} + +static void check_StretchBlt_stretch(HDC hdcDst, HDC hdcSrc, BITMAPINFO *dst_info, UINT32 *dstBuffer, UINT32 *srcBuffer, + int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, + int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, + UINT32 *expected, int line) +{ + int dst_size = get_dib_image_size( dst_info ); + + memset(dstBuffer, 0, dst_size); + StretchBlt(hdcDst, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, + hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY); + ok(memcmp(dstBuffer, expected, dst_size) == 0, + "StretchBlt \nexp { %08X, %08X, %08X, %08X } \ngot { %08X, %08X, %08X, %08X } \n" + "destination { %d, %d, %d, %d } source { %d, %d, %d, %d } from line %d\n", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3], + nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, + nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, line); +} + +static void test_StretchBlt_stretch(HDC hdcDst, HDC hdcSrc, BITMAPINFO *dst_info, UINT32 *dstBuffer, UINT32 *srcBuffer, + int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, + int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, + UINT32 *expected, int line, BOOL SrcTopDown, BOOL DstTopDown ) +{ + int dst_size = get_dib_image_size( dst_info ); + + memset(dstBuffer, 0, dst_size); + StretchBlt(hdcDst, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, + hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY); + ok(memcmp(dstBuffer, expected, dst_size) == 0, + "Case%c%c%c%c %s - %s \nexp { %08X, %08X, %08X, %08X } \ngot { %08X, %08X, %08X, %08X }\n" + "destination { %d, %d, %d, %d } source { %d, %d, %d, %d } from line %d\n", + (nWidthDest < 0) ? '0' : '1', (nHeightDest < 0) ? '0' : '1', + (nWidthSrc < 0) ? '0' : '1', (nHeightSrc < 0) ? '0' : '1', + SrcTopDown ? "SrcTopDown" : "SrcBottomUp", DstTopDown ? "DstTopDown" : "DstBottomUp", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3], + nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, + nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, line); +}
static void test_StretchBlt(void) { HBITMAP bmpDst, bmpSrc; - HDC hdcDst, hdcSrc; + HBITMAP oldDst, oldSrc; + HDC hdcScreen, hdcDst, hdcSrc; UINT32 *dstBuffer, *srcBuffer; BITMAPINFO biDst, biSrc; UINT32 expected[256]; + RGBQUAD colors[2];
memset(&biDst, 0, sizeof(BITMAPINFO)); - biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - biDst.bmiHeader.biWidth = 2; - biDst.bmiHeader.biHeight = 2; // Set our Height to positive so we are bottom-up + biDst.bmiHeader.biWidth = 16; + biDst.bmiHeader.biHeight = -16; biDst.bmiHeader.biPlanes = 1; - biDst.bmiHeader.biBitCount = 32; // Set our BitCount to 32 which is Full Color + biDst.bmiHeader.biBitCount = 32; biDst.bmiHeader.biCompression = BI_RGB; + memcpy(&biSrc, &biDst, sizeof(BITMAPINFO)); + + hdcScreen = CreateCompatibleDC(NULL); + hdcDst = CreateCompatibleDC(hdcScreen); + hdcSrc = CreateCompatibleDC(hdcDst); + + bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst); + + bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0); + oldSrc = SelectObject(hdcSrc, bmpSrc); + + /* Top-down to top-down tests */ + srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE; + srcBuffer[16] = 0xFEDCBA98, srcBuffer[17] = 0x76543210; + + memset( expected, 0, get_dib_image_size( &biDst ) ); + expected[0] = 0xCAFED00D, expected[1] = 0xFEEDFACE; + expected[16] = 0xFEDCBA98, expected[17] = 0x76543210; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__); + + expected[0] = 0xCAFED00D, expected[1] = 0x00000000; + expected[16] = 0x00000000, expected[17] = 0x00000000; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 1, 1, 0, 0, 1, 1, expected, __LINE__); + + expected[0] = 0xCAFED00D, expected[1] = 0xCAFED00D; + expected[16] = 0xCAFED00D, expected[17] = 0xCAFED00D; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 1, 1, expected, __LINE__); + + /* This is an example of the dst width (height) == 1 exception, explored below */ + expected[0] = 0xCAFED00D, expected[1] = 0x00000000; + expected[16] = 0x00000000, expected[17] = 0x00000000; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 1, 1, 0, 0, 2, 2, expected, __LINE__); + + expected[0] = 0xCAFED00D, expected[1] = 0x00000000; + expected[16] = 0x00000000, expected[17] = 0x00000000; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 1, -2, -2, 1, 1, -2, -2, expected, __LINE__); + + expected[0] = 0x00000000, expected[1] = 0x00000000; + expected[16] = 0x00000000, expected[17] = 0xCAFED00D, expected[18] = 0xFEEDFACE; + expected[32] = 0x00000000, expected[33] = 0xFEDCBA98, expected[34] = 0x76543210; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 1, 2, 2, 0, 0, 2, 2, expected, __LINE__); + + /* when dst width is 1 merge src width - 1 pixels */ + memset( srcBuffer, 0, get_dib_image_size( &biSrc ) ); + srcBuffer[0] = 0x0000ff00, srcBuffer[1] = 0x0000f0f0, srcBuffer[2] = 0x0000cccc, srcBuffer[3] = 0x0000aaaa; + srcBuffer[16] = 0xFEDCBA98, srcBuffer[17] = 0x76543210; + + memset( expected, 0, get_dib_image_size( &biDst ) ); + expected[0] = srcBuffer[0]; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 1, 1, 0, 0, 2, 1, expected, __LINE__); + + /* similarly in the vertical direction */ + memset( expected, 0, get_dib_image_size( &biDst ) ); + expected[0] = srcBuffer[0]; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 1, 1, 0, 0, 1, 2, expected, __LINE__); + + /* check that it's the dst size in device units that needs to be 1 */ + SetMapMode( hdcDst, MM_ISOTROPIC ); + SetWindowExtEx( hdcDst, 200, 200, NULL ); + SetViewportExtEx( hdcDst, 100, 100, NULL ); + + SetMapMode( hdcDst, MM_TEXT ); + + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + + /* Top-down to bottom-up tests */ + memset( srcBuffer, 0, get_dib_image_size( &biSrc ) ); + srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE; + srcBuffer[16] = 0xFEDCBA98, srcBuffer[17] = 0x76543210; + + biDst.bmiHeader.biHeight = 16; + bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst); + + memset( expected, 0, get_dib_image_size( &biDst ) ); + + expected[224] = 0xFEDCBA98, expected[225] = 0x76543210; + expected[240] = 0xCAFED00D, expected[241] = 0xFEEDFACE; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__); + + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + + /* Bottom-up to bottom-up tests */ + biSrc.bmiHeader.biHeight = 16; + bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0); + srcBuffer[224] = 0xCAFED00D, srcBuffer[225] = 0xFEEDFACE; + srcBuffer[240] = 0xFEDCBA98, srcBuffer[241] = 0x76543210; + oldSrc = SelectObject(hdcSrc, bmpSrc); + + memset( expected, 0, get_dib_image_size( &biDst ) ); + + expected[224] = 0xCAFED00D, expected[225] = 0xFEEDFACE; + expected[240] = 0xFEDCBA98, expected[241] = 0x76543210; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__); + + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + + /* Bottom-up to top-down tests */ + biDst.bmiHeader.biHeight = -16; + bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst);
- memcpy(&biSrc, &biDst, sizeof(BITMAPINFO)); // Put same Destination params into the Source + memset( expected, 0, get_dib_image_size( &biDst ) ); + expected[0] = 0xFEDCBA98, expected[1] = 0x76543210; + expected[16] = 0xCAFED00D, expected[17] = 0xFEEDFACE; + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__);
- hdcDst = CreateCompatibleDC(0); - hdcSrc = CreateCompatibleDC(0); + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + + biSrc.bmiHeader.biHeight = -2; + biSrc.bmiHeader.biBitCount = 24; + bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0); + oldSrc = SelectObject(hdcSrc, bmpSrc); + + memset( expected, 0, get_dib_image_size( &biDst ) ); + expected[0] = 0xFEEDFACE, expected[1] = 0xCAFED00D; + expected[2] = 0x76543210, expected[3] = 0xFEDCBA98; + memcpy(dstBuffer, expected, 4 * sizeof(*dstBuffer)); + StretchBlt(hdcSrc, 0, 0, 4, 1, hdcDst, 0, 0, 4, 1, SRCCOPY ); + memset(dstBuffer, 0x55, 4 * sizeof(*dstBuffer)); + StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY ); + expected[0] = 0x00EDFACE, expected[1] = 0x00FED00D; + expected[2] = 0x00543210, expected[3] = 0x00DCBA98; + ok(!memcmp(dstBuffer, expected, 16), + "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] ); + + expected[0] = 0xFEEDFACE, expected[1] = 0xCAFED00D; + expected[2] = 0x76543210, expected[3] = 0xFEDCBA98; + memcpy(srcBuffer, expected, 4 * sizeof(*dstBuffer)); + memset(dstBuffer, 0x55, 4 * sizeof(*dstBuffer)); + StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY ); + expected[0] = 0x00EDFACE, expected[1] = 0x00D00DFE; + expected[2] = 0x0010CAFE, expected[3] = 0x00765432; + ok(!memcmp(dstBuffer, expected, 16), + "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] ); + + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + + biSrc.bmiHeader.biBitCount = 1; + bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0); + oldSrc = SelectObject(hdcSrc, bmpSrc); + *((DWORD *)colors + 0) = 0x123456; + *((DWORD *)colors + 1) = 0x335577; + SetDIBColorTable( hdcSrc, 0, 2, colors ); + srcBuffer[0] = 0x55555555; + memset(dstBuffer, 0xcc, 4 * sizeof(*dstBuffer)); + SetTextColor( hdcDst, 0 ); + SetBkColor( hdcDst, 0 ); + StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY ); + expected[0] = expected[2] = 0x00123456; + expected[1] = expected[3] = 0x00335577; + ok(!memcmp(dstBuffer, expected, 16), + "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] ); + + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + + bmpSrc = CreateBitmap( 16, 16, 1, 1, 0 ); + oldSrc = SelectObject(hdcSrc, bmpSrc); + SetPixel( hdcSrc, 0, 0, 0 ); + SetPixel( hdcSrc, 1, 0, 0xffffff ); + SetPixel( hdcSrc, 2, 0, 0xffffff ); + SetPixel( hdcSrc, 3, 0, 0 ); + memset(dstBuffer, 0xcc, 4 * sizeof(*dstBuffer)); + SetTextColor(hdcDst, RGB(0x22, 0x44, 0x66)); + SetBkColor(hdcDst, RGB(0x65, 0x43, 0x21)); + StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY ); + expected[0] = expected[3] = 0x00224466; + expected[1] = expected[2] = 0x00654321; + ok(!memcmp(dstBuffer, expected, 16), + "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] ); + + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + + memset(&biDst, 0, sizeof(BITMAPINFO)); // Clear our Bitmap to to all zeroes + + biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // Set our Size to the header size + biDst.bmiHeader.biWidth = 2; // Set our Width to 2 (left-to-right) + biDst.bmiHeader.biHeight = -2; // Set our Height to -2 that's negative for top-down + biDst.bmiHeader.biPlanes = 1; // Set out planes to 1 (1 required by Windows) + biDst.bmiHeader.biBitCount = 32; // Set out BitCount to 32 (Full Color) + biDst.bmiHeader.biCompression = BI_RGB; // Set our Compression to BI_RBG (uncompressed) + + memcpy(&biSrc, &biDst, sizeof(BITMAPINFO)); // Put same Destination params into the Source
bmpSrc = CreateDIBSection(hdcSrc, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0); - SelectObject(hdcSrc, bmpSrc); + oldSrc = SelectObject(hdcSrc, bmpSrc); bmpDst = CreateDIBSection(hdcDst, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0); - SelectObject(hdcDst, bmpDst); + oldDst = SelectObject(hdcDst, bmpDst); + + srcBuffer[0] = 0x000000FF; // BLUE + srcBuffer[1] = 0x0000FF00; // GREEN + srcBuffer[2] = 0x00FF0000; // RED + srcBuffer[3] = 0xFF000000; // ALPHA (Opacity) + + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000;
- srcBuffer[0] = 0x000000FF; // BLUE - stored beginning bottom left - srcBuffer[1] = 0x0000FF00; // GREEN - srcBuffer[2] = 0x00FF0000; // RED - srcBuffer[3] = 0xFF000000; // BLACK - 0xFF for alpha channel is easy to recognize when printed in hex format + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__); // Case 1111 (15) - No flip. Just copy. + + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 1, 2, -2, expected, __LINE__); // Case 1110 (14) - Vertical flip.
- /* Flip Left to Right on Source */ - StretchBlt(hdcDst, 0, 0, 2, 2, hdcSrc, 1, 0, -2, 2, SRCCOPY); expected[0] = 0x0000FF00; expected[1] = 0x000000FF; expected[2] = 0xFF000000; expected[3] = 0x00FF0000;
- ok(expected[1] == dstBuffer[1], "StretchBlt expected { %08X } got { %08X }\n", - expected[1], dstBuffer[1]); + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 0, -2, 2, expected, __LINE__); // Case 1101 (13) - Horizontal flip. + + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF;
- ok(expected[3] == dstBuffer[3], "StretchBlt expected { %08X } got { %08X }\n", - expected[3], dstBuffer[3]); + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 1, -2, -2, expected, __LINE__); // Case 1100 (12) - Both flip.
- /* Flip Top to Bottom on Source */ - StretchBlt(hdcDst, 0, 0, 2, 2, hdcSrc, 0, 1, 2, -2, SRCCOPY); expected[0] = 0x00FF0000; expected[1] = 0xFF000000; expected[2] = 0x000000FF; expected[3] = 0x0000FF00;
- ok(expected[0] == dstBuffer[0], "StretchBlt expected { %08X } got { %08X }\n", - expected[0], dstBuffer[0]); + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 1, 2, -2, 0, 0, 2, 2, expected, __LINE__); // Case 1011 (11) - Vertical Flip. + + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000;
- ok(expected[1] == dstBuffer[1], "StretchBlt expected { %08X } got { %08X }\n", - expected[1], dstBuffer[1]); + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 2, 2, -2, 0, 2, 2, -2, expected, __LINE__); // Case 1010 (10) - No Flip. Special Case.
- /* Flip Left to Right and Top to Bottom on Source */ - StretchBlt(hdcDst, 0, 0, 2, 2, hdcSrc, 1, 1, -2, -2, SRCCOPY); expected[0] = 0xFF000000; expected[1] = 0x00FF0000; expected[2] = 0x0000FF00; expected[3] = 0x000000FF;
- ok(expected[1] == dstBuffer[1], "StretchBlt expected { %08X } got { %08X }\n", - expected[1], dstBuffer[1]); + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 1, 2, -2, 1, 0, -2, 2, expected, __LINE__); // Case 1001 (9) - Both Flip. + + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 1, 2, -2, 1, 1, -2, -2, expected, __LINE__); // Case 1000 (8) - Horizontal Flip. + + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 0, -2, 2, 0, 0, 2, 2, expected, __LINE__); // Case 0111 (7) - Horizontal Flip.
- /* Flip Left to Right and Top to Bottom on both Source and Destination */ - StretchBlt(hdcDst, 1, 1, -2, -2, hdcSrc, 1, 1, -2, -2, SRCCOPY); expected[0] = 0xFF000000; expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 0, -2, 2, 0, 1, 2, -2, expected, __LINE__); // Case 0110 (6) - Both Flip. + + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 2, 0, -2, 2, 2, 0, -2, 2, expected, __LINE__); // Case 0101 (5) - No Flip. Special Case. + + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 0, -2, 2, 1, 1, -2, -2, expected, __LINE__); // Case 0100 (4) - Vertical Flip. + + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; expected[3] = 0x000000FF;
- ok(expected[1] == dstBuffer[1], "StretchBlt expected { %08X } got { %08X }\n", - expected[1], dstBuffer[1]); + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 1, -2, -2, 0, 0, 2, 2, expected, __LINE__); // Case 0011 (3) - Both Flip. + + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 1, -2, -2, 0, 1, 2, -2, expected, __LINE__); // Case 0010 (2) - Horizontal Flip. + + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 1, -2, -2, 1, 0, -2, 2, expected, __LINE__); // Case 0001 (1) - Vertical Flip. + + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + + check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 2, 2, -2, -2, 2, 2, -2, -2, expected, __LINE__); // Case 0000 (0) - No Flip. Special Case.
DeleteDC(hdcSrc); + + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); DeleteDC(hdcDst); + + DeleteDC(hdcScreen); }
+static void test_StretchBlt_TopDownOptions(BOOL SrcTopDown, BOOL DstTopDown) +{ + HBITMAP bmpDst, bmpSrc; + HBITMAP oldDst, oldSrc; + HDC hdcScreen, hdcDst, hdcSrc; + UINT32 *dstBuffer, *srcBuffer; + BITMAPINFO biDst, biSrc; + UINT32 expected[256]; + + 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)); + + if (!SrcTopDown && !DstTopDown) + { + biSrc.bmiHeader.biHeight = -2; // Converts Source bitmap to top down + biDst.bmiHeader.biHeight = -2; // Converts Destination bitmap to top down + } + + if (SrcTopDown) + { + biSrc.bmiHeader.biHeight = -2; // Converts Source bitmap to top down + } + + if (DstTopDown) + { + biDst.bmiHeader.biHeight = -2; // Converts Destination bitmap to top down + } + + hdcScreen = CreateCompatibleDC(NULL); + hdcDst = CreateCompatibleDC(hdcScreen); + hdcSrc = CreateCompatibleDC(hdcDst); + + bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0); + oldSrc = SelectObject(hdcSrc, bmpSrc); + bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst); + + srcBuffer[0] = 0x000000FF; // BLUE + srcBuffer[1] = 0x0000FF00; // GREEN + srcBuffer[2] = 0x00FF0000; // RED + srcBuffer[3] = 0xFF000000; // ALPHA (Opacity) + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + } + else + { + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1111 (15) - No flip. Just copy. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + } + else + { + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 1, 2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1110 (14) - Vertical flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF; + } + else + { + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 0, -2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1101 (13) - Horizontal flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + } + else + { + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 1, -2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1100 (12) - Both flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + } + else + { + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 1, 2, -2, 0, 0, 2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1011 (11) - Vertical Flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + } + else + { + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 2, 2, -2, 0, 2, 2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1010 (10) - No Flip. Special Case. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + } + else + { + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 1, 2, -2, 1, 0, -2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1001 (9) - Both Flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF; + } + else + { + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 0, 1, 2, -2, 1, 1, -2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1000 (8) - Horizontal Flip + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF; + } + else + { + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 0, -2, 2, 0, 0, 2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0111 (7) - Horizontal Flip + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + } + else + { + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 0, -2, 2, 0, 1, 2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0110 (6) - Both Flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + } + else + { + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 2, 0, -2, 2, 2, 0, -2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0101 (5) - No Flip. Special Case. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + } + else + { + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 0, -2, 2, 1, 1, -2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0100 (4) - Vertical Flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + } + else + { + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 1, -2, -2, 0, 0, 2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0011 (3) - Both Flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0xFF000000; + expected[1] = 0x00FF0000; + expected[2] = 0x0000FF00; + expected[3] = 0x000000FF; + } + else + { + expected[0] = 0x0000FF00; + expected[1] = 0x000000FF; + expected[2] = 0xFF000000; + expected[3] = 0x00FF0000; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 1, -2, -2, 0, 1, 2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0010 (2) - Horizontal Flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + } + else + { + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 1, 1, -2, -2, 1, 0, -2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0001 (1) - Vertical Flip. + + if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown)) + { + expected[0] = 0x00FF0000; + expected[1] = 0xFF000000; + expected[2] = 0x000000FF; + expected[3] = 0x0000FF00; + + } + else + { + expected[0] = 0x000000FF; + expected[1] = 0x0000FF00; + expected[2] = 0x00FF0000; + expected[3] = 0xFF000000; + } + + test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer, + 2, 2, -2, -2, 2, 2, -2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0000 (0) - No Flip. Special Case. + + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + DeleteDC(hdcSrc); + + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + DeleteDC(hdcDst); + + DeleteDC(hdcScreen); +}
START_TEST(StretchBlt) { + trace("\n\n## Start of generalized StretchBlt tests.\n\n"); test_StretchBlt(); + + trace("\n\n## Start of source top-down and destination top-down tests.\n\n"); + test_StretchBlt_TopDownOptions(TRUE, TRUE); + + trace("\n\n## Start of source top-down and destination bottom-up tests.\n\n"); + test_StretchBlt_TopDownOptions(TRUE, FALSE); + + trace("\n\n## Start of source bottom-up and destination top-down tests.\n\n"); + test_StretchBlt_TopDownOptions(FALSE, TRUE); + + trace("\n\n## Start of source bottom-up and destination bottom-up tests.\n\n"); + test_StretchBlt_TopDownOptions(FALSE, FALSE); }