From: Paul Gofman pgofman@codeweavers.com
--- dlls/d2d1/d2d1.spec | 1 + dlls/d2d1/factory.c | 21 +++++++++++++++ dlls/d2d1/tests/d2d1.c | 61 ++++++++++++++++++++++++++++++++++++++++++ include/d2d1_1.idl | 1 + 4 files changed, 84 insertions(+)
diff --git a/dlls/d2d1/d2d1.spec b/dlls/d2d1/d2d1.spec index 3fa85a93bae..b44d7114044 100644 --- a/dlls/d2d1/d2d1.spec +++ b/dlls/d2d1/d2d1.spec @@ -9,3 +9,4 @@ @ stdcall D2D1SinCos(float ptr ptr) @ stdcall D2D1Tan(float) @ stdcall D2D1Vec3Length(float float float) +@ stdcall D2D1ComputeMaximumScaleFactor(ptr) diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c index 1294d8c8fa3..0261c78f783 100644 --- a/dlls/d2d1/factory.c +++ b/dlls/d2d1/factory.c @@ -1511,6 +1511,27 @@ float WINAPI D2D1Vec3Length(float x, float y, float z) return sqrtf(x * x + y * y + z * z); }
+float WINAPI D2D1ComputeMaximumScaleFactor(const D2D1_MATRIX_3X2_F *mat) +{ + const float (*m)[2] = mat->m; + float a1, a2, c, e; + + TRACE("mat %p stub.\n", mat); + + /* 2x2 matrix, _31 and _32 are ignored. */ + a1 = m[0][0] * m[0][0] + m[1][0] * m[1][0]; + a2 = m[0][1] * m[0][1] + m[1][1] * m[1][1]; + c = m[0][0] * m[0][1] + m[1][0] * m[1][1]; + + /* Maximum scale factor equals to the maximum of the singular values s1, s2 of the matrix M + * s_i^2 = e_i where e_i (e1, e2) are eugenvalues of (transpose(M) * M) + * e1 + e2 = trace(transpose(M) * M) = a1 + a2 + * e1 * e2 = det(transpose(M) * M) = a1 * a2 - c ^ 2. */ + + e = a1 + a2 + sqrtf((a1 - a2) * (a1 - a2) + 4 * c * c); + return sqrtf(0.5f * e); +} + /* See IEC 61966-2-1:1999; also described in the EXT_texture_sRGB OpenGL * extension, among others. */ static float srgb_transfer_function(float x) diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 1cded691d6c..d3c37c1a879 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -297,6 +297,7 @@ static HRESULT (WINAPI *pD2D1CreateDevice)(IDXGIDevice *dxgi_device, static void (WINAPI *pD2D1SinCos)(float angle, float *s, float *c); static float (WINAPI *pD2D1Tan)(float angle); static float (WINAPI *pD2D1Vec3Length)(float x, float y, float z); +static float (WINAPI *pD2D1ComputeMaximumScaleFactor)(const D2D1_MATRIX_3X2_F *mat); static D2D1_COLOR_F (WINAPI *pD2D1ConvertColorSpace)(D2D1_COLOR_SPACE src_colour_space, D2D1_COLOR_SPACE dst_colour_space, const D2D1_COLOR_F *colour);
@@ -10689,6 +10690,52 @@ static void test_math(BOOL d3d11) {1.0f, 2.0f, 3.0f, 3.74165750f}, };
+ static const struct + { + D2D1_MATRIX_3X2_F mat; + float res; + } + scale_factor_tests[] = + { + { + .mat = {.m = + {{0.0f, 0.0f}, + {0.0f, 0.0f}, + {0.0f, 0.0f}, + }}, + 0.0f, + }, + { + .mat = {.m = + {{-3.0f, 0.0f}, + { 0.0f, 2.0f}, + { 2.0f, 1.0f}, + }}, + 3.0f, + }, + { + .mat = {.m = + {{-3.0f, 1.0f}, + { 2.0f, 2.0f}, + }}, + 3.62258267f, + }, + { + .mat = {.m = + {{1.0f, -1.0f}, + {1.0f, 1.0f}, + }}, + 1.41421354f, + }, + { + .mat = {.m = + {{0.0f, 1.0f}, + {2.0f, 0.0f}, + }}, + 2.0f, + }, + }; + if (!pD2D1SinCos || !pD2D1Tan || !pD2D1Vec3Length) { win_skip("D2D1SinCos/D2D1Tan/D2D1Vec3Length not available, skipping test.\n"); @@ -10717,6 +10764,19 @@ static void test_math(BOOL d3d11) ok(compare_float(l, l_data[i].l, 0), "Test %u: Got unexpected length %.8e, expected %.8e.\n", i, l, l_data[i].l); } + + if (!pD2D1ComputeMaximumScaleFactor) + { + win_skip(" D2D1ComputeMaximumScaleFactor not available, skipping test.\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(scale_factor_tests); ++i) + { + s = pD2D1ComputeMaximumScaleFactor(&scale_factor_tests[i].mat); + ok(compare_float(s, scale_factor_tests[i].res, 1), + "Test %u: Got unexpected factor %.8e, expected %.8e.\n", i, s, scale_factor_tests[i].res); + } }
static void test_colour_space(BOOL d3d11) @@ -15864,6 +15924,7 @@ START_TEST(d2d1) pD2D1Tan = (void *)GetProcAddress(d2d1_dll, "D2D1Tan"); pD2D1Vec3Length = (void *)GetProcAddress(d2d1_dll, "D2D1Vec3Length"); pD2D1ConvertColorSpace = (void *)GetProcAddress(d2d1_dll, "D2D1ConvertColorSpace"); + pD2D1ComputeMaximumScaleFactor = (void *)GetProcAddress(d2d1_dll, "D2D1ComputeMaximumScaleFactor");
use_mt = !getenv("WINETEST_NO_MT_D3D"); /* Some host drivers (MacOS, Mesa radeonsi) never unmap memory even when diff --git a/include/d2d1_1.idl b/include/d2d1_1.idl index 5560f24a38e..8e3cbb8a656 100644 --- a/include/d2d1_1.idl +++ b/include/d2d1_1.idl @@ -979,5 +979,6 @@ interface ID2D1Multithread : IUnknown [local] void __stdcall D2D1SinCos(float angle, float *s, float *c); [local] float __stdcall D2D1Tan(float angle); [local] float __stdcall D2D1Vec3Length(float x, float y, float z); +[local] float __stdcall D2D1ComputeMaximumScaleFactor(const D2D1_MATRIX_3X2_F *mat); [local] D2D1_COLOR_F __stdcall D2D1ConvertColorSpace(D2D1_COLOR_SPACE src_colour_space, D2D1_COLOR_SPACE dst_colour_space, const D2D1_COLOR_F *colour);