1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Tests for SetLayout and its effects on other gdi functions
5 * such as StretchBlt, BitBlt, LPtoDP, DPtoLP
6 * PROGRAMMERS: Baruch Rutman
7 * Inspired by the StretchBlt test
8 */
9
10 #include "precomp.h"
11
copy(PUINT32 buffer,UINT32 value,int width,int start_x,int start_y,int end_x,int end_y)12 static void copy(PUINT32 buffer, UINT32 value, int width, int start_x, int start_y, int end_x, int end_y)
13 {
14 for (int y = start_y; y < end_y; y++)
15 {
16 for (int x = start_x; x < end_x; x++)
17 buffer[y * width + x] = value;
18 }
19 }
20
21 #define BLACK_PIXEL 0x000000
22 #define BLUE_PIXEL 0x0000FF
23 #define GREEN_PIXEL 0x00FF00
24 #define RED_PIXEL 0xFF0000
25 #define WHITE_PIXEL 0xFFFFFF
26
27 #if 0
28 #include "wincon.h"
29
30 /* Draw the bitmap as colored letters on white background */
31 static void
32 dump(PUINT32 buffer, int width, LPCSTR title)
33 {
34 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
35 CONSOLE_SCREEN_BUFFER_INFO info;
36
37 GetConsoleScreenBufferInfo(hConsole, &info);
38
39 if (title)
40 printf("%s", title);
41
42 for (int i = 0; i < width * width; i++)
43 {
44 char c;
45 WORD attributes = 0;
46 UINT32 pixel_value = buffer[i];
47
48 if (i % width == 0)
49 {
50 SetConsoleTextAttribute(hConsole, info.wAttributes);
51 putchar('\n');
52 }
53
54 switch (pixel_value)
55 {
56 case WHITE_PIXEL:
57 c = 'W';
58 break;
59 case BLUE_PIXEL:
60 c = 'B';
61 break;
62 case GREEN_PIXEL:
63 c = 'G';
64 break;
65 case RED_PIXEL:
66 c = 'R';
67 break;
68 case BLACK_PIXEL:
69 c = 'E'; /* Use 'E' for 'Empty' because 'B' is taken */
70 break;
71 default:
72 c = '?';
73 }
74
75 if (pixel_value != WHITE_PIXEL && c != '?')
76 {
77 attributes = (pixel_value & RED_PIXEL) ? FOREGROUND_RED : 0 |
78 (pixel_value & GREEN_PIXEL) ? FOREGROUND_GREEN : 0 |
79 (pixel_value & BLUE_PIXEL) ? FOREGROUND_BLUE : 0;
80 }
81
82 SetConsoleTextAttribute(hConsole, attributes | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED);
83 putchar(c);
84 }
85 SetConsoleTextAttribute(hConsole, info.wAttributes);
86 putchar('\n');
87 }
88 #endif
89
nomirror_test(PUINT32 dstBuffer,PUINT32 srcBuffer,int width,int line)90 static void nomirror_test(PUINT32 dstBuffer, PUINT32 srcBuffer, int width, int line)
91 {
92 for (int y = 0; y < width; y++)
93 {
94 for (int x = 0; x < width; x++)
95 {
96 if (x == width - 1)
97 {
98 ok(dstBuffer[y * width + x] == BLACK_PIXEL,
99 "Expected blank (black) pixel (0x0), got (%06X), coordinates (%d, %d). line: %d\n",
100 dstBuffer[y * width + x], x, y, line);
101 }
102 else
103 {
104 ok(dstBuffer[y * width + x] == srcBuffer[y * width + x + 1],
105 "Coordinates: (%d, %d), expected (%06X), got (%06X). line: %d\n",
106 x, y, srcBuffer[y * width + x + 1], dstBuffer[y * width + x], line);
107 }
108 }
109 }
110 }
111
112 #define WIDTH 10
START_TEST(SetLayout)113 START_TEST(SetLayout)
114 {
115 HBITMAP bmpDst, bmpSrc, oldDst, oldSrc;
116 HDC hdc, hdcDst, hdcSrc;
117 PUINT32 dstBuffer, srcBuffer;
118 BITMAPINFO info = { 0 };
119 size_t nBuf = WIDTH * WIDTH * sizeof(UINT32);
120
121 hdc = CreateCompatibleDC(NULL);
122 hdcDst = CreateCompatibleDC(hdc);
123 hdcSrc = CreateCompatibleDC(hdc);
124
125 info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
126 info.bmiHeader.biWidth = WIDTH;
127 info.bmiHeader.biHeight = -WIDTH;
128 info.bmiHeader.biPlanes = 1;
129 info.bmiHeader.biBitCount = 32;
130 info.bmiHeader.biCompression = BI_RGB;
131
132 /* Create bitmaps to test with */
133 bmpSrc = CreateDIBSection(hdcSrc, &info, DIB_RGB_COLORS, (PVOID*)&srcBuffer, NULL, 0);
134 bmpDst = CreateDIBSection(hdcDst, &info, DIB_RGB_COLORS, (PVOID*)&dstBuffer, NULL, 0);
135
136 if (!bmpSrc || !bmpDst)
137 {
138 skip("Failed to create bitmaps");
139 goto cleanup;
140 }
141
142 oldSrc = SelectObject(hdcSrc, bmpSrc);
143 oldDst = SelectObject(hdcDst, bmpDst);
144
145 /* Create base "image" for use in the tests */
146 copy(srcBuffer, WHITE_PIXEL, WIDTH, 0, 0, WIDTH / 2, WIDTH / 2);
147 copy(srcBuffer, BLUE_PIXEL, WIDTH, 0, WIDTH / 2, WIDTH / 2, WIDTH);
148 copy(srcBuffer, GREEN_PIXEL, WIDTH, WIDTH / 2, 0, WIDTH, WIDTH / 2);
149 copy(srcBuffer, RED_PIXEL, WIDTH, WIDTH / 2, WIDTH / 2, WIDTH, WIDTH);
150
151 /* Mirror destination DC */
152 SetLayout(hdcDst, LAYOUT_RTL);
153 ok(GetLayout(hdcDst) == LAYOUT_RTL, "DC layout is not RTL\n");
154 ok(GetMapMode(hdcDst) == MM_ANISOTROPIC, "DC Map mode is not MM_ANISOTROPIC\n");
155
156 /* Test RTL transform (using LPtoDP) and the inverse transform (DPtoLP) */
157 for (int y = 0; y < WIDTH; y++)
158 {
159 for (int x = 0; x < WIDTH; x++)
160 {
161 POINT pt = { x, y };
162 POINT mirrored = { WIDTH - 1 - x, y }; /* Expected results */
163
164 LPtoDP(hdcDst, &pt, 1);
165 /* Test LPtoDP */
166 ok(pt.x == mirrored.x && pt.y == mirrored.y,
167 "Coodinates: (%d, %d), expected (%ld, %ld), got (%ld, %ld)\n",
168 x, y, mirrored.x, mirrored.y, pt.x, pt.y);
169
170 pt = mirrored;
171
172 /* Test DPtoLP */
173 DPtoLP(hdcDst, &pt, 1);
174 ok(pt.x == x && pt.y == y,
175 "Mirrored Coodinates: (%ld, %ld), expected (%d, %d), got (%ld, %ld)\n",
176 mirrored.x, mirrored.y, x, y, pt.x, pt.y);
177 }
178 }
179
180 ZeroMemory(dstBuffer, nBuf);
181 StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY);
182 for (int y = 0; y < WIDTH; y++)
183 {
184 for (int x = 0; x < WIDTH; x++)
185 {
186 /* Test if the image is mirrored using the assumed RTL transform results */
187 ok(dstBuffer[y * WIDTH + (WIDTH - 1 - x)] == srcBuffer[y * WIDTH + x],
188 "Coordinates: (%d, %d), expected (%06X), got (%06X)\n",
189 x, y, srcBuffer[y * WIDTH + x], dstBuffer[y * WIDTH + (WIDTH - 1 - x)]);
190 }
191 }
192
193 ZeroMemory(dstBuffer, nBuf);
194 StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY | NOMIRRORBITMAP);
195 nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
196
197 ZeroMemory(dstBuffer, nBuf);
198 BitBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, SRCCOPY);
199 for (int y = 0; y < WIDTH; y++)
200 {
201 for (int x = 0; x < WIDTH; x++)
202 {
203 /* Test if the image is mirrored using the assumed RTL transform results */
204 ok(dstBuffer[y * WIDTH + (WIDTH - 1 - x)] == srcBuffer[y * WIDTH + x],
205 "Coordinates: (%d, %d), expected (%06X), got (%06X)\n",
206 x, y, srcBuffer[y * WIDTH + x], dstBuffer[y * WIDTH + (WIDTH - 1 - x)]);
207 }
208 }
209
210 ZeroMemory(dstBuffer, nBuf);
211 BitBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, SRCCOPY | NOMIRRORBITMAP);
212 nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
213
214 SetLayout(hdcDst, LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED);
215
216 ok(GetLayout(hdcDst) == (LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED),
217 "DC Layout is not LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED\n");
218 ok(GetMapMode(hdcDst) == MM_ANISOTROPIC, "DC Map mode is not MM_ANISOTROPIC\n");
219
220 ZeroMemory(dstBuffer, nBuf);
221 StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY);
222 nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
223
224 ZeroMemory(dstBuffer, nBuf);
225 StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY | NOMIRRORBITMAP);
226 nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
227
228 ZeroMemory(dstBuffer, nBuf);
229 BitBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, SRCCOPY);
230 nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
231
232 ZeroMemory(dstBuffer, nBuf);
233 BitBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, SRCCOPY | NOMIRRORBITMAP);
234 nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
235
236 /* Reset DC layout to default (LTR) */
237 SetLayout(hdcDst, LAYOUT_LTR);
238 ok(GetLayout(hdcDst) == LAYOUT_LTR, "DC layout is not LAYOUT_LTR");
239
240 for (int y = 0; y < WIDTH; y++)
241 {
242 for (int x = 0; x < WIDTH; x++)
243 {
244 POINT pt = { x, y };
245
246 LPtoDP(hdcDst, &pt, 1);
247 /* Confirm that RTL transform is not the current one */
248 ok(pt.x == x && pt.y == y,
249 "Expected (%d, %d) got (%ld, %ld)\n", x, y, pt.x, pt.y);
250 }
251 }
252
253 ZeroMemory(dstBuffer, nBuf);
254 StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY);
255 ok(memcmp(dstBuffer, srcBuffer, nBuf) == 0, "Bitmaps are not identical\n");
256
257 SetLayout(hdcDst, LAYOUT_BITMAPORIENTATIONPRESERVED);
258 ok(GetLayout(hdcDst) == LAYOUT_BITMAPORIENTATIONPRESERVED, "DC Layout is not LAYOUT_BITMAPORIENTATIONPRESERVED");
259
260 SelectObject(hdcSrc, oldSrc);
261 SelectObject(hdcDst, oldDst);
262 DeleteObject(bmpSrc);
263 DeleteObject(bmpDst);
264 cleanup:
265 DeleteDC(hdcSrc);
266 DeleteDC(hdcDst);
267 DeleteDC(hdc);
268 }
269