1 /*
2  * PROJECT:     ReactOS API tests
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Tests for the StretchBlt API
5  * COPYRIGHT:   Copyright 2020, 2021 Doug Lyons (douglyons at douglyons dot com)
6  *              Some Code copied and modified from Wine gdi32:bitmap test.
7  */
8 
9 #include <stdarg.h>
10 #include <assert.h>
11 #include <string.h>
12 
13 #include "ntstatus.h"
14 #define WIN32_NO_STATUS
15 #include "windef.h"
16 #include "winbase.h"
17 #include "winerror.h"
18 #include "wingdi.h"
19 #include "winuser.h"
20 #include "wine/test.h"
21 #include <debug.h>
22 
23 /* Notes on using the StretchBlt function's general flip ability.
24  *
25  * The critical values for flipping are the signs of the values for DestWidth, DestHeight, SourceWidth and SourceHeight.
26  * 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.
27  * 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.
28  *
29  * If we take the normal StretchBlt function's copy/scaling with no flips, the generalized code can be represented as follows:
30  *
31  * StretchBlt(DestDC,   DestX,   DestY,   (DestWidth),   (DestHeight),
32  *            SourceDC, SourceX, SourceY, (SourceWidth), (SourceHeight), SRCCOPY); // Case1111 (15) (all positive signs)
33  *
34  * For Horizontal flipping then the generalized form on the Destination side can be represented as follows:
35  *
36  * StretchBlt(DestDC,   DestX + DestWidth - 1,  DestY,   -DestWidth,   DestHeight,
37  *            SourceDC, SourceX,                SourceY, SourceWidth,  SourceHeight, SRCCOPY);  // Case 0111 (7)
38  *
39  * and for Horizontal flipping the generalized form on the Source side can be represented as follows:
40  *
41  * StretchBlt(DestDC,   DestX,                     DestY,   DestWidth,    DestHeight,
42  *            SourceDC, SourceX + SourceWidth - 1, SourceY, -SourceWidth, SourceHeight, SRCCOPY); // Case 1101 (13)
43  *
44  * I believe that the "- 1" is used because we are moving from the rightmost position back to the 0th position.
45  *
46  * But there are three "special" cases where no flip is done (there is a copy/scale only) and the "-1" is not used.
47  * These are as follows:
48  * 1)
49  * StretchBlt(DestDC,   DestX + DestWidth,     DestY,   -DestWidth,   DestHeight,  // Both Widths negative
50  *            SourceDC, SourceX + SourceWidth, SourceY, -SourceWidth, SourceHeight, SRCCOPY); // Case0101 (5)
51  * 2)
52  * StretchBlt(DestDC,   DestX,   DestY + DestHeight,     DestWidth,   -DestHeight, // Both heights negative
53  *            SourceDC, SourceX, SourceY + SourceHeight, SourceWidth, -SourceHeight, SRCCOPY); // Case1010 (10)
54  * 3)
55  * StretchBlt(DestDC,   DestX + DestWidth,     DestY + DestHeight,     -DestWidth,   -DestHeight, // widths AND heights neg
56  *            SourceDC, SourceX + SourceWidth, SourceY + SourceHeight, -SourceWidth, -SourceHeight, SRCCOPY); // Case0000 (0)
57  *
58  * I suspect that these are like this because of legacy reasons when StretchBlt did not support so many flip options.
59  *
60  * For Vertical flipping the generalized form on the Destination side can be represented as follows:
61  *
62  * StretchBlt(DestDC,   DestX,   DestY + DestHeight - 1,  DestWidth,   -DestHeight,
63  *            SourceDC, SourceX, SourceY,                 SourceWidth, SourceHeight, SRCCOPY); // Case1011 (11)
64  *
65  * and for Vertical on the Source Side as folows:
66  *
67  * StretchBlt(DestDC,   DestX,   DestY,                      DestWidth,   -DestHeight,
68  *            SourceDC, SourceX, SourceY + SourceHeight - 1, SourceWidth, -SourceHeight, SRCCOPY); // Case 1010 (10)
69  */
70 
71 static inline int get_dib_stride( int width, int bpp )
72 {
73     return ((width * bpp + 31) >> 3) & ~3;
74 }
75 
76 static inline int get_dib_image_size( const BITMAPINFO *info )
77 {
78     return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount )
79         * abs( info->bmiHeader.biHeight );
80 }
81 
82 static void check_StretchBlt_stretch(HDC hdcDst, HDC hdcSrc, BITMAPINFO *dst_info, UINT32 *dstBuffer, UINT32 *srcBuffer,
83                                      int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
84                                      int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
85                                      UINT32 *expected, int line)
86 {
87     int dst_size = get_dib_image_size( dst_info );
88 
89     memset(dstBuffer, 0, dst_size);
90     StretchBlt(hdcDst, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
91                hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);
92     ok(memcmp(dstBuffer, expected, dst_size) == 0,
93         "StretchBlt \nexp { %08X, %08X, %08X, %08X } \ngot { %08X, %08X, %08X, %08X } \n"
94         "destination { %d, %d, %d, %d } source { %d, %d, %d, %d } from line %d\n",
95         expected[0], expected[1], expected[2], expected[3],
96         dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3],
97         nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
98         nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, line);
99 }
100 
101 static void test_StretchBlt_stretch(HDC hdcDst, HDC hdcSrc, BITMAPINFO *dst_info, UINT32 *dstBuffer, UINT32 *srcBuffer,
102                                     int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
103                                     int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
104                                     UINT32 *expected, int line, BOOL SrcTopDown, BOOL DstTopDown )
105 {
106     int dst_size = get_dib_image_size( dst_info );
107 
108     memset(dstBuffer, 0, dst_size);
109     StretchBlt(hdcDst, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
110                hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);
111     ok(memcmp(dstBuffer, expected, dst_size) == 0,
112         "Case%c%c%c%c %s - %s \nexp { %08X, %08X, %08X, %08X } \ngot { %08X, %08X, %08X, %08X }\n"
113         "destination { %d, %d, %d, %d } source { %d, %d, %d, %d } from line %d\n",
114          (nWidthDest < 0) ? '0' : '1', (nHeightDest < 0) ? '0' : '1',
115          (nWidthSrc < 0) ? '0' : '1', (nHeightSrc < 0) ? '0' : '1',
116          SrcTopDown ? "SrcTopDown" : "SrcBottomUp", DstTopDown ? "DstTopDown" : "DstBottomUp",
117         expected[0], expected[1], expected[2], expected[3],
118         dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3],
119         nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
120         nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, line);
121 }
122 
123 static void test_StretchBlt(void)
124 {
125     HBITMAP bmpDst, bmpSrc;
126     HBITMAP oldDst, oldSrc;
127     HDC hdcScreen, hdcDst, hdcSrc;
128     UINT32 *dstBuffer, *srcBuffer;
129     BITMAPINFO biDst, biSrc;
130     UINT32 expected[256];
131     RGBQUAD colors[2];
132 
133     memset(&biDst, 0, sizeof(BITMAPINFO));
134     biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
135     biDst.bmiHeader.biWidth = 16;
136     biDst.bmiHeader.biHeight = -16;
137     biDst.bmiHeader.biPlanes = 1;
138     biDst.bmiHeader.biBitCount = 32;
139     biDst.bmiHeader.biCompression = BI_RGB;
140     memcpy(&biSrc, &biDst, sizeof(BITMAPINFO));
141 
142     hdcScreen = CreateCompatibleDC(NULL);
143     hdcDst = CreateCompatibleDC(hdcScreen);
144     hdcSrc = CreateCompatibleDC(hdcDst);
145 
146     bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0);
147     oldDst = SelectObject(hdcDst, bmpDst);
148 
149     bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0);
150     oldSrc = SelectObject(hdcSrc, bmpSrc);
151 
152     /* Top-down to top-down tests */
153     srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE;
154     srcBuffer[16] = 0xFEDCBA98, srcBuffer[17] = 0x76543210;
155 
156     memset( expected, 0, get_dib_image_size( &biDst ) );
157     expected[0] = 0xCAFED00D, expected[1] = 0xFEEDFACE;
158     expected[16] = 0xFEDCBA98, expected[17] = 0x76543210;
159     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
160                              0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__);
161 
162     expected[0] = 0xCAFED00D, expected[1] = 0x00000000;
163     expected[16] = 0x00000000, expected[17] = 0x00000000;
164     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
165                              0, 0, 1, 1, 0, 0, 1, 1, expected, __LINE__);
166 
167     expected[0] = 0xCAFED00D, expected[1] = 0xCAFED00D;
168     expected[16] = 0xCAFED00D, expected[17] = 0xCAFED00D;
169     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
170                              0, 0, 2, 2, 0, 0, 1, 1, expected, __LINE__);
171 
172     /* This is an example of the dst width (height) == 1 exception, explored below */
173     expected[0] = 0xCAFED00D, expected[1] = 0x00000000;
174     expected[16] = 0x00000000, expected[17] = 0x00000000;
175     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
176                              0, 0, 1, 1, 0, 0, 2, 2, expected, __LINE__);
177 
178     expected[0] = 0xCAFED00D, expected[1] = 0x00000000;
179     expected[16] = 0x00000000, expected[17] = 0x00000000;
180     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
181                              1, 1, -2, -2, 1, 1, -2, -2, expected, __LINE__);
182 
183     expected[0] = 0x00000000, expected[1] = 0x00000000;
184     expected[16] = 0x00000000, expected[17] = 0xCAFED00D, expected[18] = 0xFEEDFACE;
185     expected[32] = 0x00000000, expected[33] = 0xFEDCBA98, expected[34] = 0x76543210;
186 
187     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
188                              1, 1, 2, 2, 0, 0, 2, 2, expected, __LINE__);
189 
190     /* when dst width is 1 merge src width - 1 pixels */
191     memset( srcBuffer, 0, get_dib_image_size( &biSrc ) );
192     srcBuffer[0] = 0x0000ff00, srcBuffer[1] = 0x0000f0f0, srcBuffer[2] = 0x0000cccc, srcBuffer[3] = 0x0000aaaa;
193     srcBuffer[16] = 0xFEDCBA98, srcBuffer[17] = 0x76543210;
194 
195     memset( expected, 0, get_dib_image_size( &biDst ) );
196     expected[0] = srcBuffer[0];
197     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
198                              0, 0, 1, 1, 0, 0, 2, 1, expected, __LINE__);
199 
200     /* similarly in the vertical direction */
201     memset( expected, 0, get_dib_image_size( &biDst ) );
202     expected[0] = srcBuffer[0];
203     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
204                              0, 0, 1, 1, 0, 0, 1, 2, expected, __LINE__);
205 
206     /* check that it's the dst size in device units that needs to be 1 */
207     SetMapMode( hdcDst, MM_ISOTROPIC );
208     SetWindowExtEx( hdcDst, 200, 200, NULL );
209     SetViewportExtEx( hdcDst, 100, 100, NULL );
210 
211     SetMapMode( hdcDst, MM_TEXT );
212 
213     SelectObject(hdcDst, oldDst);
214     DeleteObject(bmpDst);
215 
216     /* Top-down to bottom-up tests */
217     memset( srcBuffer, 0, get_dib_image_size( &biSrc ) );
218     srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE;
219     srcBuffer[16] = 0xFEDCBA98, srcBuffer[17] = 0x76543210;
220 
221     biDst.bmiHeader.biHeight = 16;
222     bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0);
223     oldDst = SelectObject(hdcDst, bmpDst);
224 
225     memset( expected, 0, get_dib_image_size( &biDst ) );
226 
227     expected[224] = 0xFEDCBA98, expected[225] = 0x76543210;
228     expected[240] = 0xCAFED00D, expected[241] = 0xFEEDFACE;
229     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
230                              0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__);
231 
232     SelectObject(hdcSrc, oldSrc);
233     DeleteObject(bmpSrc);
234 
235     /* Bottom-up to bottom-up tests */
236     biSrc.bmiHeader.biHeight = 16;
237     bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0);
238     srcBuffer[224] = 0xCAFED00D, srcBuffer[225] = 0xFEEDFACE;
239     srcBuffer[240] = 0xFEDCBA98, srcBuffer[241] = 0x76543210;
240     oldSrc = SelectObject(hdcSrc, bmpSrc);
241 
242     memset( expected, 0, get_dib_image_size( &biDst ) );
243 
244     expected[224] = 0xCAFED00D, expected[225] = 0xFEEDFACE;
245     expected[240] = 0xFEDCBA98, expected[241] = 0x76543210;
246     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
247                              0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__);
248 
249     SelectObject(hdcDst, oldDst);
250     DeleteObject(bmpDst);
251 
252     /* Bottom-up to top-down tests */
253     biDst.bmiHeader.biHeight = -16;
254     bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0);
255     oldDst = SelectObject(hdcDst, bmpDst);
256 
257     memset( expected, 0, get_dib_image_size( &biDst ) );
258     expected[0] = 0xFEDCBA98, expected[1] = 0x76543210;
259     expected[16] = 0xCAFED00D, expected[17] = 0xFEEDFACE;
260     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
261                              0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__);
262 
263     SelectObject(hdcSrc, oldSrc);
264     DeleteObject(bmpSrc);
265 
266     biSrc.bmiHeader.biHeight = -2;
267     biSrc.bmiHeader.biBitCount = 24;
268     bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0);
269     oldSrc = SelectObject(hdcSrc, bmpSrc);
270 
271     memset( expected, 0, get_dib_image_size( &biDst ) );
272     expected[0] = 0xFEEDFACE, expected[1] = 0xCAFED00D;
273     expected[2] = 0x76543210, expected[3] = 0xFEDCBA98;
274     memcpy(dstBuffer, expected, 4 * sizeof(*dstBuffer));
275     StretchBlt(hdcSrc, 0, 0, 4, 1, hdcDst, 0, 0, 4, 1, SRCCOPY );
276     memset(dstBuffer, 0x55, 4 * sizeof(*dstBuffer));
277     StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY );
278     expected[0] = 0x00EDFACE, expected[1] = 0x00FED00D;
279     expected[2] = 0x00543210, expected[3] = 0x00DCBA98;
280     ok(!memcmp(dstBuffer, expected, 16),
281        "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n",
282         expected[0], expected[1], expected[2], expected[3],
283         dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] );
284 
285     expected[0] = 0xFEEDFACE, expected[1] = 0xCAFED00D;
286     expected[2] = 0x76543210, expected[3] = 0xFEDCBA98;
287     memcpy(srcBuffer, expected, 4 * sizeof(*dstBuffer));
288     memset(dstBuffer, 0x55, 4 * sizeof(*dstBuffer));
289     StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY );
290     expected[0] = 0x00EDFACE, expected[1] = 0x00D00DFE;
291     expected[2] = 0x0010CAFE, expected[3] = 0x00765432;
292     ok(!memcmp(dstBuffer, expected, 16),
293        "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n",
294         expected[0], expected[1], expected[2], expected[3],
295         dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] );
296 
297     SelectObject(hdcSrc, oldSrc);
298     DeleteObject(bmpSrc);
299 
300     biSrc.bmiHeader.biBitCount = 1;
301     bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0);
302     oldSrc = SelectObject(hdcSrc, bmpSrc);
303     *((DWORD *)colors + 0) = 0x123456;
304     *((DWORD *)colors + 1) = 0x335577;
305     SetDIBColorTable( hdcSrc, 0, 2, colors );
306     srcBuffer[0] = 0x55555555;
307     memset(dstBuffer, 0xcc, 4 * sizeof(*dstBuffer));
308     SetTextColor( hdcDst, 0 );
309     SetBkColor( hdcDst, 0 );
310     StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY );
311     expected[0] = expected[2] = 0x00123456;
312     expected[1] = expected[3] = 0x00335577;
313     ok(!memcmp(dstBuffer, expected, 16),
314        "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n",
315         expected[0], expected[1], expected[2], expected[3],
316         dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] );
317 
318     SelectObject(hdcSrc, oldSrc);
319     DeleteObject(bmpSrc);
320 
321     bmpSrc = CreateBitmap( 16, 16, 1, 1, 0 );
322     oldSrc = SelectObject(hdcSrc, bmpSrc);
323     SetPixel( hdcSrc, 0, 0, 0 );
324     SetPixel( hdcSrc, 1, 0, 0xffffff );
325     SetPixel( hdcSrc, 2, 0, 0xffffff );
326     SetPixel( hdcSrc, 3, 0, 0 );
327     memset(dstBuffer, 0xcc, 4 * sizeof(*dstBuffer));
328     SetTextColor(hdcDst, RGB(0x22, 0x44, 0x66));
329     SetBkColor(hdcDst, RGB(0x65, 0x43, 0x21));
330     StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY );
331     expected[0] = expected[3] = 0x00224466;
332     expected[1] = expected[2] = 0x00654321;
333     ok(!memcmp(dstBuffer, expected, 16),
334        "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n",
335         expected[0], expected[1], expected[2], expected[3],
336         dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] );
337 
338     SelectObject(hdcSrc, oldSrc);
339     DeleteObject(bmpSrc);
340 
341     SelectObject(hdcSrc, oldSrc);
342     DeleteObject(bmpSrc);
343     SelectObject(hdcDst, oldDst);
344     DeleteObject(bmpDst);
345 
346     memset(&biDst, 0, sizeof(BITMAPINFO));              // Clear our Bitmap to to all zeroes
347 
348     biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);  // Set our Size to the header size
349     biDst.bmiHeader.biWidth = 2;                        // Set our Width to 2 (left-to-right)
350     biDst.bmiHeader.biHeight = -2;                      // Set our Height to -2 that's negative for top-down
351     biDst.bmiHeader.biPlanes = 1;                       // Set out planes to 1 (1 required by Windows)
352     biDst.bmiHeader.biBitCount = 32;                    // Set out BitCount to 32 (Full Color)
353     biDst.bmiHeader.biCompression = BI_RGB;             // Set our Compression to BI_RBG (uncompressed)
354 
355     memcpy(&biSrc, &biDst, sizeof(BITMAPINFO));         // Put same Destination params into the Source
356 
357     bmpSrc = CreateDIBSection(hdcSrc, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0);
358     oldSrc = SelectObject(hdcSrc, bmpSrc);
359     bmpDst = CreateDIBSection(hdcDst, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0);
360     oldDst = SelectObject(hdcDst, bmpDst);
361 
362     srcBuffer[0] = 0x000000FF;   // BLUE
363     srcBuffer[1] = 0x0000FF00;   // GREEN
364     srcBuffer[2] = 0x00FF0000;   // RED
365     srcBuffer[3] = 0xFF000000;   // ALPHA (Opacity)
366 
367     expected[0] = 0x000000FF;
368     expected[1] = 0x0000FF00;
369     expected[2] = 0x00FF0000;
370     expected[3] = 0xFF000000;
371 
372     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
373                              0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__); // Case 1111 (15) - No flip. Just copy.
374 
375     expected[0] = 0x00FF0000;
376     expected[1] = 0xFF000000;
377     expected[2] = 0x000000FF;
378     expected[3] = 0x0000FF00;
379 
380     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
381                              0, 0, 2, 2, 0, 1, 2, -2, expected, __LINE__); // Case 1110 (14) - Vertical flip.
382 
383     expected[0] = 0x0000FF00;
384     expected[1] = 0x000000FF;
385     expected[2] = 0xFF000000;
386     expected[3] = 0x00FF0000;
387 
388     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
389                              0, 0, 2, 2, 1, 0, -2, 2, expected, __LINE__); // Case 1101 (13) - Horizontal flip.
390 
391     expected[0] = 0xFF000000;
392     expected[1] = 0x00FF0000;
393     expected[2] = 0x0000FF00;
394     expected[3] = 0x000000FF;
395 
396     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
397                              0, 0, 2, 2, 1, 1, -2, -2, expected, __LINE__); // Case 1100 (12) - Both flip.
398 
399     expected[0] = 0x00FF0000;
400     expected[1] = 0xFF000000;
401     expected[2] = 0x000000FF;
402     expected[3] = 0x0000FF00;
403 
404     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
405                              0, 1, 2, -2, 0, 0, 2, 2, expected, __LINE__); // Case 1011 (11) - Vertical Flip.
406 
407     expected[0] = 0x000000FF;
408     expected[1] = 0x0000FF00;
409     expected[2] = 0x00FF0000;
410     expected[3] = 0xFF000000;
411 
412     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
413                              0, 2, 2, -2, 0, 2, 2, -2, expected, __LINE__); // Case 1010 (10) - No Flip. Special Case.
414 
415     expected[0] = 0xFF000000;
416     expected[1] = 0x00FF0000;
417     expected[2] = 0x0000FF00;
418     expected[3] = 0x000000FF;
419 
420     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
421                              0, 1, 2, -2, 1, 0, -2, 2, expected, __LINE__); // Case 1001 (9) - Both Flip.
422 
423     expected[0] = 0x0000FF00;
424     expected[1] = 0x000000FF;
425     expected[2] = 0xFF000000;
426     expected[3] = 0x00FF0000;
427 
428     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
429                              0, 1, 2, -2, 1, 1, -2, -2, expected, __LINE__); // Case 1000 (8) - Horizontal Flip.
430 
431     expected[0] = 0x0000FF00;
432     expected[1] = 0x000000FF;
433     expected[2] = 0xFF000000;
434     expected[3] = 0x00FF0000;
435 
436     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
437                              1, 0, -2, 2, 0, 0, 2, 2, expected, __LINE__); // Case 0111 (7) - Horizontal Flip.
438 
439     expected[0] = 0xFF000000;
440     expected[1] = 0x00FF0000;
441     expected[2] = 0x0000FF00;
442     expected[3] = 0x000000FF;
443 
444     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
445                              1, 0, -2, 2, 0, 1, 2, -2, expected, __LINE__); // Case 0110 (6) - Both Flip.
446 
447     expected[0] = 0x000000FF;
448     expected[1] = 0x0000FF00;
449     expected[2] = 0x00FF0000;
450     expected[3] = 0xFF000000;
451 
452     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
453                              2, 0, -2, 2, 2, 0, -2, 2, expected, __LINE__); // Case 0101 (5) - No Flip. Special Case.
454 
455     expected[0] = 0x00FF0000;
456     expected[1] = 0xFF000000;
457     expected[2] = 0x000000FF;
458     expected[3] = 0x0000FF00;
459 
460     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
461                              1, 0, -2, 2, 1, 1, -2, -2, expected, __LINE__); // Case 0100 (4) - Vertical Flip.
462 
463     expected[0] = 0xFF000000;
464     expected[1] = 0x00FF0000;
465     expected[2] = 0x0000FF00;
466     expected[3] = 0x000000FF;
467 
468     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
469                              1, 1, -2, -2, 0, 0, 2, 2, expected, __LINE__); // Case 0011 (3) - Both Flip.
470 
471     expected[0] = 0x0000FF00;
472     expected[1] = 0x000000FF;
473     expected[2] = 0xFF000000;
474     expected[3] = 0x00FF0000;
475 
476     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
477                              1, 1, -2, -2, 0, 1, 2, -2, expected, __LINE__); // Case 0010 (2) - Horizontal Flip.
478 
479     expected[0] = 0x00FF0000;
480     expected[1] = 0xFF000000;
481     expected[2] = 0x000000FF;
482     expected[3] = 0x0000FF00;
483 
484     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
485                              1, 1, -2, -2, 1, 0, -2, 2, expected, __LINE__); // Case 0001 (1) - Vertical Flip.
486 
487     expected[0] = 0x000000FF;
488     expected[1] = 0x0000FF00;
489     expected[2] = 0x00FF0000;
490     expected[3] = 0xFF000000;
491 
492     check_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
493                              2, 2, -2, -2, 2, 2, -2, -2, expected, __LINE__); // Case 0000 (0) - No Flip. Special Case.
494 
495     DeleteDC(hdcSrc);
496 
497     SelectObject(hdcDst, oldDst);
498     DeleteObject(bmpDst);
499     DeleteDC(hdcDst);
500 
501     DeleteDC(hdcScreen);
502 }
503 
504 static void test_StretchBlt_TopDownOptions(BOOL SrcTopDown, BOOL DstTopDown)
505 {
506     HBITMAP bmpDst, bmpSrc;
507     HBITMAP oldDst, oldSrc;
508     HDC hdcScreen, hdcDst, hdcSrc;
509     UINT32 *dstBuffer, *srcBuffer;
510     BITMAPINFO biDst, biSrc;
511     UINT32 expected[256];
512 
513     memset(&biDst, 0, sizeof(BITMAPINFO));
514 
515     biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
516     biDst.bmiHeader.biWidth = 2;
517     biDst.bmiHeader.biHeight = 2;
518     biDst.bmiHeader.biPlanes = 1;
519     biDst.bmiHeader.biBitCount = 32;
520     biDst.bmiHeader.biCompression = BI_RGB;
521     memcpy(&biSrc, &biDst, sizeof(BITMAPINFO));
522 
523     if (!SrcTopDown && !DstTopDown)
524     {
525         biSrc.bmiHeader.biHeight = -2;                // Converts Source bitmap to top down
526         biDst.bmiHeader.biHeight = -2;                // Converts Destination bitmap to top down
527     }
528 
529     if (SrcTopDown)
530     {
531         biSrc.bmiHeader.biHeight = -2;                // Converts Source bitmap to top down
532     }
533 
534     if (DstTopDown)
535     {
536         biDst.bmiHeader.biHeight = -2;                // Converts Destination bitmap to top down
537     }
538 
539     hdcScreen = CreateCompatibleDC(NULL);
540     hdcDst = CreateCompatibleDC(hdcScreen);
541     hdcSrc = CreateCompatibleDC(hdcDst);
542 
543     bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0);
544     oldSrc = SelectObject(hdcSrc, bmpSrc);
545     bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0);
546     oldDst = SelectObject(hdcDst, bmpDst);
547 
548     srcBuffer[0] = 0x000000FF;   // BLUE
549     srcBuffer[1] = 0x0000FF00;   // GREEN
550     srcBuffer[2] = 0x00FF0000;   // RED
551     srcBuffer[3] = 0xFF000000;   // ALPHA (Opacity)
552 
553     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
554     {
555         expected[0] = 0x00FF0000;
556         expected[1] = 0xFF000000;
557         expected[2] = 0x000000FF;
558         expected[3] = 0x0000FF00;
559     }
560     else
561     {
562         expected[0] = 0x000000FF;
563         expected[1] = 0x0000FF00;
564         expected[2] = 0x00FF0000;
565         expected[3] = 0xFF000000;
566     }
567 
568     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
569                             0, 0, 2, 2, 0, 0, 2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1111 (15) - No flip. Just copy.
570 
571     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
572     {
573         expected[0] = 0x000000FF;
574         expected[1] = 0x0000FF00;
575         expected[2] = 0x00FF0000;
576         expected[3] = 0xFF000000;
577     }
578     else
579     {
580         expected[0] = 0x00FF0000;
581         expected[1] = 0xFF000000;
582         expected[2] = 0x000000FF;
583         expected[3] = 0x0000FF00;
584     }
585 
586     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
587                             0, 0, 2, 2, 0, 1, 2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1110 (14) - Vertical flip.
588 
589     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
590     {
591         expected[0] = 0xFF000000;
592         expected[1] = 0x00FF0000;
593         expected[2] = 0x0000FF00;
594         expected[3] = 0x000000FF;
595     }
596     else
597     {
598         expected[0] = 0x0000FF00;
599         expected[1] = 0x000000FF;
600         expected[2] = 0xFF000000;
601         expected[3] = 0x00FF0000;
602     }
603 
604     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
605                             0, 0, 2, 2, 1, 0, -2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1101 (13) - Horizontal flip.
606 
607     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
608     {
609         expected[0] = 0x0000FF00;
610         expected[1] = 0x000000FF;
611         expected[2] = 0xFF000000;
612         expected[3] = 0x00FF0000;
613     }
614     else
615     {
616         expected[0] = 0xFF000000;
617         expected[1] = 0x00FF0000;
618         expected[2] = 0x0000FF00;
619         expected[3] = 0x000000FF;
620     }
621 
622     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
623                             0, 0, 2, 2, 1, 1, -2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1100 (12) - Both flip.
624 
625     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
626     {
627         expected[0] = 0x000000FF;
628         expected[1] = 0x0000FF00;
629         expected[2] = 0x00FF0000;
630         expected[3] = 0xFF000000;
631     }
632     else
633     {
634         expected[0] = 0x00FF0000;
635         expected[1] = 0xFF000000;
636         expected[2] = 0x000000FF;
637         expected[3] = 0x0000FF00;
638     }
639 
640     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
641                             0, 1, 2, -2, 0, 0, 2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1011 (11) - Vertical Flip.
642 
643     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
644     {
645         expected[0] = 0x00FF0000;
646         expected[1] = 0xFF000000;
647         expected[2] = 0x000000FF;
648         expected[3] = 0x0000FF00;
649     }
650     else
651     {
652         expected[0] = 0x000000FF;
653         expected[1] = 0x0000FF00;
654         expected[2] = 0x00FF0000;
655         expected[3] = 0xFF000000;
656     }
657 
658     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
659                             0, 2, 2, -2, 0, 2, 2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1010 (10) - No Flip. Special Case.
660 
661     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
662     {
663         expected[0] = 0x0000FF00;
664         expected[1] = 0x000000FF;
665         expected[2] = 0xFF000000;
666         expected[3] = 0x00FF0000;
667     }
668     else
669     {
670         expected[0] = 0xFF000000;
671         expected[1] = 0x00FF0000;
672         expected[2] = 0x0000FF00;
673         expected[3] = 0x000000FF;
674     }
675 
676     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
677                             0, 1, 2, -2, 1, 0, -2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1001 (9) - Both Flip.
678 
679     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
680     {
681         expected[0] = 0xFF000000;
682         expected[1] = 0x00FF0000;
683         expected[2] = 0x0000FF00;
684         expected[3] = 0x000000FF;
685     }
686     else
687     {
688         expected[0] = 0x0000FF00;
689         expected[1] = 0x000000FF;
690         expected[2] = 0xFF000000;
691         expected[3] = 0x00FF0000;
692     }
693 
694     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
695                             0, 1, 2, -2, 1, 1, -2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 1000 (8) - Horizontal Flip
696 
697     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
698     {
699         expected[0] = 0xFF000000;
700         expected[1] = 0x00FF0000;
701         expected[2] = 0x0000FF00;
702         expected[3] = 0x000000FF;
703     }
704     else
705     {
706         expected[0] = 0x0000FF00;
707         expected[1] = 0x000000FF;
708         expected[2] = 0xFF000000;
709         expected[3] = 0x00FF0000;
710     }
711 
712     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
713                             1, 0, -2, 2, 0, 0, 2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0111 (7) - Horizontal Flip
714 
715     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
716     {
717         expected[0] = 0x0000FF00;
718         expected[1] = 0x000000FF;
719         expected[2] = 0xFF000000;
720         expected[3] = 0x00FF0000;
721     }
722     else
723     {
724         expected[0] = 0xFF000000;
725         expected[1] = 0x00FF0000;
726         expected[2] = 0x0000FF00;
727         expected[3] = 0x000000FF;
728     }
729 
730     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
731                             1, 0, -2, 2, 0, 1, 2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0110 (6) - Both Flip.
732 
733     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
734     {
735         expected[0] = 0x00FF0000;
736         expected[1] = 0xFF000000;
737         expected[2] = 0x000000FF;
738         expected[3] = 0x0000FF00;
739     }
740     else
741     {
742         expected[0] = 0x000000FF;
743         expected[1] = 0x0000FF00;
744         expected[2] = 0x00FF0000;
745         expected[3] = 0xFF000000;
746     }
747 
748     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
749                             2, 0, -2, 2, 2, 0, -2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0101 (5) - No Flip. Special Case.
750 
751     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
752     {
753         expected[0] = 0x000000FF;
754         expected[1] = 0x0000FF00;
755         expected[2] = 0x00FF0000;
756         expected[3] = 0xFF000000;
757     }
758     else
759     {
760         expected[0] = 0x00FF0000;
761         expected[1] = 0xFF000000;
762         expected[2] = 0x000000FF;
763         expected[3] = 0x0000FF00;
764     }
765 
766     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
767                             1, 0, -2, 2, 1, 1, -2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0100 (4) - Vertical Flip.
768 
769     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
770     {
771         expected[0] = 0x0000FF00;
772         expected[1] = 0x000000FF;
773         expected[2] = 0xFF000000;
774         expected[3] = 0x00FF0000;
775     }
776     else
777     {
778         expected[0] = 0xFF000000;
779         expected[1] = 0x00FF0000;
780         expected[2] = 0x0000FF00;
781         expected[3] = 0x000000FF;
782     }
783 
784     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
785                             1, 1, -2, -2, 0, 0, 2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0011 (3) - Both Flip.
786 
787     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
788     {
789         expected[0] = 0xFF000000;
790         expected[1] = 0x00FF0000;
791         expected[2] = 0x0000FF00;
792         expected[3] = 0x000000FF;
793     }
794     else
795     {
796         expected[0] = 0x0000FF00;
797         expected[1] = 0x000000FF;
798         expected[2] = 0xFF000000;
799         expected[3] = 0x00FF0000;
800     }
801 
802     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
803                             1, 1, -2, -2, 0, 1, 2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0010 (2) - Horizontal Flip.
804 
805     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
806     {
807         expected[0] = 0x000000FF;
808         expected[1] = 0x0000FF00;
809         expected[2] = 0x00FF0000;
810         expected[3] = 0xFF000000;
811     }
812     else
813     {
814         expected[0] = 0x00FF0000;
815         expected[1] = 0xFF000000;
816         expected[2] = 0x000000FF;
817         expected[3] = 0x0000FF00;
818     }
819 
820     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
821                             1, 1, -2, -2, 1, 0, -2, 2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0001 (1) - Vertical Flip.
822 
823     if ((SrcTopDown || DstTopDown) && !(SrcTopDown && DstTopDown))
824     {
825         expected[0] = 0x00FF0000;
826         expected[1] = 0xFF000000;
827         expected[2] = 0x000000FF;
828         expected[3] = 0x0000FF00;
829 
830     }
831     else
832     {
833         expected[0] = 0x000000FF;
834         expected[1] = 0x0000FF00;
835         expected[2] = 0x00FF0000;
836         expected[3] = 0xFF000000;
837     }
838 
839     test_StretchBlt_stretch(hdcDst, hdcSrc, &biDst, dstBuffer, srcBuffer,
840                             2, 2, -2, -2, 2, 2, -2, -2, expected, __LINE__, SrcTopDown, DstTopDown); // Case 0000 (0) - No Flip. Special Case.
841 
842     SelectObject(hdcSrc, oldSrc);
843     DeleteObject(bmpSrc);
844     DeleteDC(hdcSrc);
845 
846     SelectObject(hdcDst, oldDst);
847     DeleteObject(bmpDst);
848     DeleteDC(hdcDst);
849 
850     DeleteDC(hdcScreen);
851 }
852 
853 START_TEST(StretchBlt)
854 {
855     trace("\n\n## Start of generalized StretchBlt tests.\n\n");
856     test_StretchBlt();
857 
858     trace("\n\n## Start of source top-down and destination top-down tests.\n\n");
859     test_StretchBlt_TopDownOptions(TRUE, TRUE);
860 
861     trace("\n\n## Start of source top-down and destination bottom-up tests.\n\n");
862     test_StretchBlt_TopDownOptions(TRUE, FALSE);
863 
864     trace("\n\n## Start of source bottom-up and destination top-down tests.\n\n");
865     test_StretchBlt_TopDownOptions(FALSE, TRUE);
866 
867     trace("\n\n## Start of source bottom-up and destination bottom-up tests.\n\n");
868     test_StretchBlt_TopDownOptions(FALSE, FALSE);
869 }
870