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 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 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 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