reactos/modules/rostests/apitests/gdi32/StretchBlt.c
Hermès Bélusca-Maïto 9393fc320e
[FORMATTING] Remove trailing whitespace. Addendum to 34593d93.
Excluded: 3rd-party code (incl. wine) and most of the win32ss.
2021-09-13 03:52:22 +02:00

870 lines
34 KiB
C

/*
* 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, 2021 Doug Lyons (douglyons at douglyons dot com)
* Some Code copied and modified from Wine gdi32:bitmap test.
*/
#include <stdarg.h>
#include <assert.h>
#include <string.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#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;
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 = 16;
biDst.bmiHeader.biHeight = -16;
biDst.bmiHeader.biPlanes = 1;
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);
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__);
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);
oldSrc = SelectObject(hdcSrc, bmpSrc);
bmpDst = CreateDIBSection(hdcDst, &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)
expected[0] = 0x000000FF;
expected[1] = 0x0000FF00;
expected[2] = 0x00FF0000;
expected[3] = 0xFF000000;
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.
expected[0] = 0x0000FF00;
expected[1] = 0x000000FF;
expected[2] = 0xFF000000;
expected[3] = 0x00FF0000;
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;
check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
0, 0, 2, 2, 1, 1, -2, -2, expected, __LINE__); // Case 1100 (12) - Both flip.
expected[0] = 0x00FF0000;
expected[1] = 0xFF000000;
expected[2] = 0x000000FF;
expected[3] = 0x0000FF00;
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;
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.
expected[0] = 0xFF000000;
expected[1] = 0x00FF0000;
expected[2] = 0x0000FF00;
expected[3] = 0x000000FF;
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.
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;
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);
}