https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f6de3342bfc3d077723c2…
commit f6de3342bfc3d077723c282252c7a30ba9af97c8
Author: Baruch Rutman <peterooch(a)gmail.com>
AuthorDate: Sat Dec 26 18:48:21 2020 +0200
Commit: GitHub <noreply(a)github.com>
CommitDate: Sat Dec 26 19:48:21 2020 +0300
[GDI32_APITEST] Add tests for SetLayout and its effects (#3203)
As part of the efforts to fix mirroring (Right-to-left UI), this API test
should help determine what is wrong currently in how certain functions behave
when the DC is mirrored. It focuses mostly on BitBlt, StretchBlt and LPtoDP.
Inspired by PR #3109.
CORE-17298
---
modules/rostests/apitests/gdi32/CMakeLists.txt | 1 +
modules/rostests/apitests/gdi32/SetLayout.c | 268 +++++++++++++++++++++++++
modules/rostests/apitests/gdi32/testlist.c | 2 +
3 files changed, 271 insertions(+)
diff --git a/modules/rostests/apitests/gdi32/CMakeLists.txt
b/modules/rostests/apitests/gdi32/CMakeLists.txt
index 27bd589e2b4..486a112c319 100644
--- a/modules/rostests/apitests/gdi32/CMakeLists.txt
+++ b/modules/rostests/apitests/gdi32/CMakeLists.txt
@@ -69,6 +69,7 @@ list(APPEND SOURCE
SetDCPenColor.c
SetDIBits.c
SetDIBitsToDevice.c
+ SetLayout.c
SetMapMode.c
SetPixel.c
SetSysColors.c
diff --git a/modules/rostests/apitests/gdi32/SetLayout.c
b/modules/rostests/apitests/gdi32/SetLayout.c
new file mode 100644
index 00000000000..254fd426533
--- /dev/null
+++ b/modules/rostests/apitests/gdi32/SetLayout.c
@@ -0,0 +1,268 @@
+/*
+ * PROJECT: ReactOS api tests
+ * LICENSE: GPL - See COPYING in the top level directory
+ * PURPOSE: Tests for SetLayout and its effects on other gdi functions
+ * such as StretchBlt, BitBlt, LPtoDP, DPtoLP
+ * PROGRAMMERS: Baruch Rutman
+ * Inspired by the StretchBlt test
+ */
+
+#include "precomp.h"
+
+static void copy(PUINT32 buffer, UINT32 value, int width, int start_x, int start_y, int
end_x, int end_y)
+{
+ for (int y = start_y; y < end_y; y++)
+ {
+ for (int x = start_x; x < end_x; x++)
+ buffer[y * width + x] = value;
+ }
+}
+
+#define BLACK_PIXEL 0x000000
+#define BLUE_PIXEL 0x0000FF
+#define GREEN_PIXEL 0x00FF00
+#define RED_PIXEL 0xFF0000
+#define WHITE_PIXEL 0xFFFFFF
+
+#if 0
+#include "wincon.h"
+
+/* Draw the bitmap as colored letters on white background */
+static void
+dump(PUINT32 buffer, int width, LPCSTR title)
+{
+ HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO info;
+
+ GetConsoleScreenBufferInfo(hConsole, &info);
+
+ if (title)
+ printf("%s", title);
+
+ for (int i = 0; i < width * width; i++)
+ {
+ char c;
+ WORD attributes = 0;
+ UINT32 pixel_value = buffer[i];
+
+ if (i % width == 0)
+ {
+ SetConsoleTextAttribute(hConsole, info.wAttributes);
+ putchar('\n');
+ }
+
+ switch (pixel_value)
+ {
+ case WHITE_PIXEL:
+ c = 'W';
+ break;
+ case BLUE_PIXEL:
+ c = 'B';
+ break;
+ case GREEN_PIXEL:
+ c = 'G';
+ break;
+ case RED_PIXEL:
+ c = 'R';
+ break;
+ case BLACK_PIXEL:
+ c = 'E'; /* Use 'E' for 'Empty' because
'B' is taken */
+ break;
+ default:
+ c = '?';
+ }
+
+ if (pixel_value != WHITE_PIXEL && c != '?')
+ {
+ attributes = (pixel_value & RED_PIXEL) ? FOREGROUND_RED : 0 |
+ (pixel_value & GREEN_PIXEL) ? FOREGROUND_GREEN : 0 |
+ (pixel_value & BLUE_PIXEL) ? FOREGROUND_BLUE : 0;
+ }
+
+ SetConsoleTextAttribute(hConsole, attributes | BACKGROUND_BLUE | BACKGROUND_GREEN
| BACKGROUND_RED);
+ putchar(c);
+ }
+ SetConsoleTextAttribute(hConsole, info.wAttributes);
+ putchar('\n');
+}
+#endif
+
+static void nomirror_test(PUINT32 dstBuffer, PUINT32 srcBuffer, int width, int line)
+{
+ for (int y = 0; y < width; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ if (x == width - 1)
+ {
+ ok(dstBuffer[y * width + x] == BLACK_PIXEL,
+ "Expected blank (black) pixel (0x0), got (%06X), coordinates (%d,
%d). line: %d\n",
+ dstBuffer[y * width + x], x, y, line);
+ }
+ else
+ {
+ ok(dstBuffer[y * width + x] == srcBuffer[y * width + x + 1],
+ "Coordinates: (%d, %d), expected (%06X), got (%06X). line:
%d\n",
+ x, y, srcBuffer[y * width + x + 1], dstBuffer[y * width + x], line);
+ }
+ }
+ }
+}
+
+#define WIDTH 10
+START_TEST(SetLayout)
+{
+ HBITMAP bmpDst, bmpSrc, oldDst, oldSrc;
+ HDC hdc, hdcDst, hdcSrc;
+ PUINT32 dstBuffer, srcBuffer;
+ BITMAPINFO info = { 0 };
+ size_t nBuf = WIDTH * WIDTH * sizeof(UINT32);
+
+ hdc = CreateCompatibleDC(NULL);
+ hdcDst = CreateCompatibleDC(hdc);
+ hdcSrc = CreateCompatibleDC(hdc);
+
+ info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ info.bmiHeader.biWidth = WIDTH;
+ info.bmiHeader.biHeight = -WIDTH;
+ info.bmiHeader.biPlanes = 1;
+ info.bmiHeader.biBitCount = 32;
+ info.bmiHeader.biCompression = BI_RGB;
+
+ /* Create bitmaps to test with */
+ bmpSrc = CreateDIBSection(hdcSrc, &info, DIB_RGB_COLORS, (PVOID*)&srcBuffer,
NULL, 0);
+ bmpDst = CreateDIBSection(hdcDst, &info, DIB_RGB_COLORS, (PVOID*)&dstBuffer,
NULL, 0);
+
+ if (!bmpSrc || !bmpDst)
+ {
+ skip("Failed to create bitmaps");
+ goto cleanup;
+ }
+
+ oldSrc = SelectObject(hdcSrc, bmpSrc);
+ oldDst = SelectObject(hdcDst, bmpDst);
+
+ /* Create base "image" for use in the tests */
+ copy(srcBuffer, WHITE_PIXEL, WIDTH, 0, 0, WIDTH / 2, WIDTH / 2);
+ copy(srcBuffer, BLUE_PIXEL, WIDTH, 0, WIDTH / 2, WIDTH / 2, WIDTH);
+ copy(srcBuffer, GREEN_PIXEL, WIDTH, WIDTH / 2, 0, WIDTH, WIDTH / 2);
+ copy(srcBuffer, RED_PIXEL, WIDTH, WIDTH / 2, WIDTH / 2, WIDTH, WIDTH);
+
+ /* Mirror destination DC */
+ SetLayout(hdcDst, LAYOUT_RTL);
+ ok(GetLayout(hdcDst) == LAYOUT_RTL, "DC layout is not RTL\n");
+ ok(GetMapMode(hdcDst) == MM_ANISOTROPIC, "DC Map mode is not
MM_ANISOTROPIC\n");
+
+ /* Test RTL transform (using LPtoDP) and the inverse transform (DPtoLP) */
+ for (int y = 0; y < WIDTH; y++)
+ {
+ for (int x = 0; x < WIDTH; x++)
+ {
+ POINT pt = { x, y };
+ POINT mirrored = { WIDTH - 1 - x, y }; /* Expected results */
+
+ LPtoDP(hdcDst, &pt, 1);
+ /* Test LPtoDP */
+ ok(pt.x == mirrored.x && pt.y == mirrored.y,
+ "Coodinates: (%d, %d), expected (%ld, %ld), got (%ld, %ld)\n",
+ x, y, mirrored.x, mirrored.y, pt.x, pt.y);
+
+ pt = mirrored;
+
+ /* Test DPtoLP */
+ DPtoLP(hdcDst, &pt, 1);
+ ok(pt.x == x && pt.y == y,
+ "Mirrored Coodinates: (%ld, %ld), expected (%d, %d), got (%ld,
%ld)\n",
+ mirrored.x, mirrored.y, x, y, pt.x, pt.y);
+ }
+ }
+
+ ZeroMemory(dstBuffer, nBuf);
+ StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY);
+ for (int y = 0; y < WIDTH; y++)
+ {
+ for (int x = 0; x < WIDTH; x++)
+ {
+ /* Test if the image is mirrored using the assumed RTL transform results */
+ ok(dstBuffer[y * WIDTH + (WIDTH - 1 - x)] == srcBuffer[y * WIDTH + x],
+ "Coordinates: (%d, %d), expected (%06X), got (%06X)\n",
+ x, y, srcBuffer[y * WIDTH + x], dstBuffer[y * WIDTH + (WIDTH - 1 - x)]);
+ }
+ }
+
+ ZeroMemory(dstBuffer, nBuf);
+ StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY |
NOMIRRORBITMAP);
+ nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
+
+ ZeroMemory(dstBuffer, nBuf);
+ BitBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, SRCCOPY);
+ for (int y = 0; y < WIDTH; y++)
+ {
+ for (int x = 0; x < WIDTH; x++)
+ {
+ /* Test if the image is mirrored using the assumed RTL transform results */
+ ok(dstBuffer[y * WIDTH + (WIDTH - 1 - x)] == srcBuffer[y * WIDTH + x],
+ "Coordinates: (%d, %d), expected (%06X), got (%06X)\n",
+ x, y, srcBuffer[y * WIDTH + x], dstBuffer[y * WIDTH + (WIDTH - 1 - x)]);
+ }
+ }
+
+ ZeroMemory(dstBuffer, nBuf);
+ BitBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, SRCCOPY | NOMIRRORBITMAP);
+ nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
+
+ SetLayout(hdcDst, LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED);
+
+ ok(GetLayout(hdcDst) == (LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED),
+ "DC Layout is not LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED\n");
+ ok(GetMapMode(hdcDst) == MM_ANISOTROPIC, "DC Map mode is not
MM_ANISOTROPIC\n");
+
+ ZeroMemory(dstBuffer, nBuf);
+ StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY);
+ nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
+
+ ZeroMemory(dstBuffer, nBuf);
+ StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY |
NOMIRRORBITMAP);
+ nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
+
+ ZeroMemory(dstBuffer, nBuf);
+ BitBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, SRCCOPY);
+ nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
+
+ ZeroMemory(dstBuffer, nBuf);
+ BitBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, SRCCOPY | NOMIRRORBITMAP);
+ nomirror_test(dstBuffer, srcBuffer, WIDTH, __LINE__);
+
+ /* Reset DC layout to default (LTR) */
+ SetLayout(hdcDst, LAYOUT_LTR);
+ ok(GetLayout(hdcDst) == LAYOUT_LTR, "DC layout is not LAYOUT_LTR");
+
+ for (int y = 0; y < WIDTH; y++)
+ {
+ for (int x = 0; x < WIDTH; x++)
+ {
+ POINT pt = { x, y };
+
+ LPtoDP(hdcDst, &pt, 1);
+ /* Confirm that RTL transform is not the current one */
+ ok(pt.x == x && pt.y == y,
+ "Expected (%d, %d) got (%ld, %ld)\n", x, y, pt.x, pt.y);
+ }
+ }
+
+ ZeroMemory(dstBuffer, nBuf);
+ StretchBlt(hdcDst, 0, 0, WIDTH, WIDTH, hdcSrc, 0, 0, WIDTH, WIDTH, SRCCOPY);
+ ok(memcmp(dstBuffer, srcBuffer, nBuf) == 0, "Bitmaps are not
identical\n");
+
+ SetLayout(hdcDst, LAYOUT_BITMAPORIENTATIONPRESERVED);
+ ok(GetLayout(hdcDst) == LAYOUT_BITMAPORIENTATIONPRESERVED, "DC Layout is not
LAYOUT_BITMAPORIENTATIONPRESERVED");
+
+ SelectObject(hdcSrc, oldSrc);
+ SelectObject(hdcDst, oldDst);
+ DeleteObject(bmpSrc);
+ DeleteObject(bmpDst);
+cleanup:
+ DeleteDC(hdcSrc);
+ DeleteDC(hdcDst);
+ DeleteDC(hdc);
+}
diff --git a/modules/rostests/apitests/gdi32/testlist.c
b/modules/rostests/apitests/gdi32/testlist.c
index 623f530c90c..22ddc690c2a 100644
--- a/modules/rostests/apitests/gdi32/testlist.c
+++ b/modules/rostests/apitests/gdi32/testlist.c
@@ -70,6 +70,7 @@ extern void func_SetBrushOrgEx(void);
extern void func_SetDCPenColor(void);
extern void func_SetDIBits(void);
extern void func_SetDIBitsToDevice(void);
+extern void func_SetLayout(void);
extern void func_SetMapMode(void);
extern void func_SetPixel(void);
extern void func_SetSysColors(void);
@@ -147,6 +148,7 @@ const struct test winetest_testlist[] =
{ "SetDCPenColor", func_SetDCPenColor },
{ "SetDIBits", func_SetDIBits },
{ "SetDIBitsToDevice", func_SetDIBitsToDevice },
+ { "SetLayout", func_SetLayout },
{ "SetMapMode", func_SetMapMode },
{ "SetPixel", func_SetPixel },
{ "SetSysColors", func_SetSysColors },