diff --git a/patches/d2d1_ID2D1GeometryGroup/0001-d2d1-Add-tests-for-drawing-ID2D1GeometryGroup.patch b/patches/d2d1_ID2D1GeometryGroup/0001-d2d1-Add-tests-for-drawing-ID2D1GeometryGroup.patch new file mode 100644 index 00000000..38e5b6de --- /dev/null +++ b/patches/d2d1_ID2D1GeometryGroup/0001-d2d1-Add-tests-for-drawing-ID2D1GeometryGroup.patch @@ -0,0 +1,267 @@ +From e4d55d451648b67c9269241efce8eee63faf70a4 Mon Sep 17 00:00:00 2001 +From: Philipp Knechtges +Date: Fri, 13 Sep 2024 11:16:44 +0200 +Subject: [PATCH] d2d1: Add tests for drawing ID2D1GeometryGroup + +The functionality to draw ID2D1GeometryGroup is currently missing. +Nothing is drawn. This causes the blank pages in the bug below. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51139 +--- + dlls/d2d1/tests/d2d1.c | 219 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 219 insertions(+) + +diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c +index 40bcf5079b8..41b36ef0dd5 100644 +--- a/dlls/d2d1/tests/d2d1.c ++++ b/dlls/d2d1/tests/d2d1.c +@@ -7061,6 +7061,7 @@ static void test_gradient(BOOL d3d11) + static void test_draw_geometry(BOOL d3d11) + { + ID2D1TransformedGeometry *transformed_geometry[4]; ++ ID2D1GeometryGroup *geometry_group; + ID2D1RectangleGeometry *rect_geometry[2]; + D2D1_POINT_2F point = {0.0f, 0.0f}; + D2D1_ROUNDED_RECT rounded_rect; +@@ -7970,6 +7971,117 @@ static void test_draw_geometry(BOOL d3d11) + hr = ID2D1PathGeometry_Open(geometry, &sink); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ++ set_point(&point, -0.402914f, 0.915514f); ++ ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW); ++ quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f); ++ quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f); ++ quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f); ++ quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f); ++ quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f); ++ quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f); ++ quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f); ++ quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f); ++ quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f); ++ quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f); ++ quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f); ++ quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f); ++ ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED); ++ ++ hr = ID2D1GeometrySink_Close(sink); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID2D1GeometrySink_Release(sink); ++ ++ set_matrix_identity(&matrix); ++ translate_matrix(&matrix, 40.0f, 160.0f); ++ scale_matrix(&matrix, 20.0f, 80.0f); ++ hr = ID2D1Factory_CreateTransformedGeometry(factory, ++ (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ set_matrix_identity(&matrix); ++ translate_matrix(&matrix, 160.0f, 640.0f); ++ scale_matrix(&matrix, 40.0f, 160.0f); ++ rotate_matrix(&matrix, M_PI / -5.0f); ++ hr = ID2D1Factory_CreateTransformedGeometry(factory, ++ (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID2D1PathGeometry_Release(geometry); ++ ++ set_matrix_identity(&matrix); ++ scale_matrix(&matrix, 0.5f, 1.0f); ++ translate_matrix(&matrix, -80.0f, 0.0f); ++ hr = ID2D1Factory_CreateTransformedGeometry(factory, ++ (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ set_matrix_identity(&matrix); ++ rotate_matrix(&matrix, M_PI / 2.0f); ++ translate_matrix(&matrix, 80.0f, -320.0f); ++ scale_matrix(&matrix, 2.0f, 0.25f); ++ hr = ID2D1Factory_CreateTransformedGeometry(factory, ++ (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ hr = ID2D1Factory_CreateGeometryGroup(factory, D2D1_FILL_MODE_WINDING, ++ (ID2D1Geometry**) &transformed_geometry, 4, &geometry_group); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID2D1TransformedGeometry_Release(transformed_geometry[3]); ++ ID2D1TransformedGeometry_Release(transformed_geometry[2]); ++ ID2D1TransformedGeometry_Release(transformed_geometry[1]); ++ ID2D1TransformedGeometry_Release(transformed_geometry[0]); ++ ++ ID2D1RenderTarget_BeginDraw(rt); ++ ID2D1RenderTarget_Clear(rt, &color); ++ ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry_group, (ID2D1Brush *)brush, 10.0f, NULL); ++ hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID2D1GeometryGroup_Release(geometry_group); ++ ++ match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 256, ++ "iTANiwEagQEkeSp0LnIWAhZyFAYUchQGFHIUBhRyFAYUchQGFHIUBhRyFAYUchQGFHIUBhRyFAYU" ++ "cxQFFHMUBRRzFAUUcxQFFHMUBRRzFAUUcxQFFHMUBRRzFAUUcxQFFHQUBBR0FAQUdBQDFHUUAxR1" ++ "FAMUdRQDFHUUAxR1FQIUdhQCFHYUAhR2FAIUdhQCFHYUAhR2FAIUdhQBFHgoeCh4KHkmeiZ7JHwk" ++ "fSJ+In8ggAEfggEeggEdhAEchQEbhQEahwEZhwEYiQEXiQEWigEWigEWigEWiwEViwEViwEViwEV" ++ "igEXiQEXiQEXiQEYhwEZhgEbgwEefyR5KXQvbxgEGG4VBxhtMnAudCp6IoMBGOMu"); ++ ok(match, "Figure does not match.\n"); ++ match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 512, ++ "xpcBB7QCEqkCG6ACJJgCLI8CNYcCHgMc/gEeDBr4AR4UGPIBHR0W7AEdIxbmAR0pFt8BHTAV2gEd" ++ "MBrWARwuIdMBGiwi1gEYKiPZARYoJNwBFiQk4AEWHyWxAQQvFhsltgEKKBYWJrwBECBOwQEXF0rI" ++ "ARwOSM4Ba9UBYeABRf0BOIoCMZECLJYCKJoCJ5wCJp0CJJ8CIqICH6QCHagCGa4CFLoCB/yUAQAA"); ++ ok(match, "Figure does not match.\n"); ++ match = compare_figure(&ctx, 0, 160, 160, 320, 0xff652e89, 512, ++ "yWQBnQEEmQEHlgELkwENkAEQjgETiwEVigEXhwEZhgEahQEcgwEdggEfgAEgfyF+I30jfCR8JXom" ++ "eid4KHgodxQCFHYUAhR1FAMUdBUEFHMUBRRyFQUUchQHFHEUBxRwFAgUcBQJFG4UChRuFAoUbRUL" ++ "FGwUDBRsFAwUbBQNFGwUDBRsFAwUbRQMFGwUDBRsFAwUbRQLFWwUDBRtFAsUbRQLFG0VCxRtFAsU" ++ "bRQLFG4UCxRtFAsUbhQKFG4UCxRuFAoUbhQKFG4VCRRvFAoUbhQKFG8UCRRvFAoUbxQJFG8UCRRw" ++ "FAgVbxQJFHAUCBRwFAgUcBUIFHAUCBRwFAgUcRQHFHEUBxRyFAYUchQGFHMUBRRzFAUUdBQEFHQU" ++ "BBR1FAQUdBQEFHUUAxR1FAMUdhQCFHYUAhR2FQEUdxQBFHcpeCh4KHkneSd6JnoneiZ7JXwkfSN+" ++ "In8hgAEggQEfgwEdhAEdhAEchQEbhgEahwEZiAEYGAFwGBYCcRcUBHEXEgZyFhEHchcOCXMWDAtz" ++ "FgsMdBYIDnQWBhB1FgQQdhYCEnYqdyl3KXcpeCd5J3kneSd5JnomeyR8JHwkfCN9I30ifiF/IX4h" ++ "fyF/IH8ggAEgfyCAASCAAR+AAR+BAR6CAR6BAR6CAR2CAR2DARyEARuEARuFARqGARmGARiKARSR" ++ "AQqhYwAA"); ++ ok(match, "Figure does not match.\n"); ++ match = compare_figure(&ctx, 160, 160, 320, 320, 0xff652e89, 1024, ++ "ytABA7gCCbICD60CFKkCF6cCGqMCHqACIZ0CJJoCJpgCKZUCFgIUkgIWBBWPAhYHFI4CFQoUjAIV" ++ "DBSKAhUNFYgCFQ8UhwIVERSFAhUTFIMCFRQVgQIUFxSAAhQZFP4BFBoV/AEUHBT7ARQeFPkBFB8V" ++ "9wEUIRT2ARQjFPQBFSMV8gEVJRTxARUnFPABFCgV7gEUKhTtARQsFOwBFCwV7AEULBTsARUsFOwB" ++ "FSsV7AEULBTtARQsFO0BFCsU7QEVKxTtARUqFe0BFSoU7gEUKxTuARQqFe4BFCoU7wEUKhTuARUp" ++ "FO8BFSkU7wEVKBXvARUoFPABFCkU8AEUKBTxARQoFPEBFCcV8QEUJxTxARUnFPEBFSYU8gEVJhTy" ++ "ARUlFfIBFSUU8wEUJRXzARQlFPQBFCUU9AEUJBT1ARQkFPUBFCMU9gEUIhT2ARUhFPcBFSAU+AEV" ++ "HxT5ARUeFPoBFR4U+gEVHRT7ARUcFPwBFRsU/QEVGhT+ARUZFP8BFBkUgAIUGBSBAhQXFIICFBcU" ++ "ggIUFhSDAhQVFIQCFBQUhQIUExSGAhQSFIcCFBIUhwIUERSIAhUPFIkCFg0UigIXCxSNAhYJFI8C" ++ "FggUkAIXBRSSAhcDFJQCFwEUlgIrlwIpmgImnAIkngIjnwIhoQIfowIepAIcpgIbpgIaqAIZqAIZ" ++ "qAIYKwP7ARgnBf0BGCMI/QEZHgz+ARgbD/8BGBcSgAIYEhaAAhoNGIICGggcgwIaBB+DAjyEAjyF" ++ "AjqGAjmIAjiIAiECFIkCFAIIBBSKAhQNFIsCFAwUjAIUCxSNAhQKFI4CFAkUjwIUBxWQAhQGFZEC" ++ "FAUVkQIUBRWRAhQFFZECFQMVkwIUAxWTAhQDFZMCFAIVlAIVARWVAiqVAimWAimWAiiYAiaZAiaZ" ++ "AiWaAiScAiKdAiGeAh+hAhyjAhmuAg3GxgEA"); ++ ok(match, "Figure does not match.\n"); ++ ++ hr = ID2D1Factory_CreatePathGeometry(factory, &geometry); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ hr = ID2D1PathGeometry_Open(geometry, &sink); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ + set_point(&point, 20.0f, 80.0f); + ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW); + quadratic_to(sink, 20.0f, 160.0f, 60.0f, 160.0f); +@@ -8011,6 +8123,7 @@ static void test_draw_geometry(BOOL d3d11) + static void test_fill_geometry(BOOL d3d11) + { + ID2D1TransformedGeometry *transformed_geometry[4]; ++ ID2D1GeometryGroup *geometry_group; + ID2D1RectangleGeometry *rect_geometry[2]; + D2D1_POINT_2F point = {0.0f, 0.0f}; + D2D1_ROUNDED_RECT rounded_rect; +@@ -8728,6 +8841,112 @@ static void test_fill_geometry(BOOL d3d11) + hr = ID2D1PathGeometry_Open(geometry, &sink); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ++ set_point(&point, -0.402914f, 0.915514f); ++ ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED); ++ quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f); ++ quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f); ++ quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f); ++ quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f); ++ quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f); ++ quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f); ++ quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f); ++ quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f); ++ quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f); ++ quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f); ++ quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f); ++ quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f); ++ ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED); ++ ++ hr = ID2D1GeometrySink_Close(sink); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID2D1GeometrySink_Release(sink); ++ ++ set_matrix_identity(&matrix); ++ translate_matrix(&matrix, 40.0f, 160.0f); ++ scale_matrix(&matrix, 20.0f, 80.0f); ++ hr = ID2D1Factory_CreateTransformedGeometry(factory, ++ (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ set_matrix_identity(&matrix); ++ translate_matrix(&matrix, 160.0f, 640.0f); ++ scale_matrix(&matrix, 40.0f, 160.0f); ++ rotate_matrix(&matrix, M_PI / -5.0f); ++ hr = ID2D1Factory_CreateTransformedGeometry(factory, ++ (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID2D1PathGeometry_Release(geometry); ++ ++ set_matrix_identity(&matrix); ++ scale_matrix(&matrix, 0.5f, 1.0f); ++ translate_matrix(&matrix, -80.0f, 0.0f); ++ hr = ID2D1Factory_CreateTransformedGeometry(factory, ++ (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ set_matrix_identity(&matrix); ++ rotate_matrix(&matrix, M_PI / 2.0f); ++ translate_matrix(&matrix, 80.0f, -320.0f); ++ scale_matrix(&matrix, 2.0f, 0.25f); ++ hr = ID2D1Factory_CreateTransformedGeometry(factory, ++ (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ++ hr = ID2D1Factory_CreateGeometryGroup(factory, D2D1_FILL_MODE_WINDING, ++ (ID2D1Geometry**) &transformed_geometry, 4, &geometry_group); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID2D1TransformedGeometry_Release(transformed_geometry[3]); ++ ID2D1TransformedGeometry_Release(transformed_geometry[2]); ++ ID2D1TransformedGeometry_Release(transformed_geometry[1]); ++ ID2D1TransformedGeometry_Release(transformed_geometry[0]); ++ ++ ID2D1RenderTarget_BeginDraw(rt); ++ ID2D1RenderTarget_Clear(rt, &color); ++ ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry_group, (ID2D1Brush *)brush, NULL); ++ hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ ID2D1GeometryGroup_Release(geometry_group); ++ ++ match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 32, ++ "zzIBlwEOjQEXiAEahgEahgEahgEahgEahgEahgEahgEahgEahgEahgEahwEZhwEZhwEZhwEZhwEZ" ++ "hwEZhwEZhwEZhwEZhwEZiAEYiAEYiAEXiQEXiQEXiQEXiQEXiQEXigEWigEWigEWigEWigEWigEW" ++ "igEVjAEUjAEUjAEUjQESjgESjwEQkAEQkQEOkgENlAEMlAELlgEKlwEImAEImQEHmQEGmwEFmwEE" ++ "nQEDnQECngECngECngECnwEBnwEBnwEBnwEBngEDnQEDnQEDnQEEmwEFmgEHmQEHlwELkQERjAEX" ++ "hgEdhAEfgwEchwEWjwEMqTEA"); ++ ok(match, "Figure does not match.\n"); ++ match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 32, ++ "h58BBrUCD6wCGKQCIJsCKZMCMIwCNoUCPf8BQ/kBSPQBTu0BTu4BTfEBSfUBRfkBQf0BPYECOYUC" ++ "NIoCMI4CK+UBAS0W/AEHIweQAgsZBpcCEAwIngIepAIZqQIWrAITsAIRswIOtQIMuAIJuwIHwAIB" ++ "ypwB"); ++ ok(match, "Figure does not match.\n"); ++ match = compare_figure(&ctx, 0, 160, 160, 320, 0xff652e89, 32, ++ "wW4DnAEEmwEFmgEHmAEIlwEKlQELlAEMkwEOkQEPkAEQkAERjgESjgESjQEUjAEUiwEWigEWiQEX" ++ "iQEYhwEZhwEZhgEbhQEbhAEchAEdggEeggEeggEfgAEggAEggAEhgAEggAEggQEggAEggAEggQEf" ++ "gQEggQEfgQEfggEfgQEfgQEfggEfgQEfggEeggEfggEeggEeggEegwEeggEegwEdgwEegwEdgwEd" ++ "hAEchAEdhAEchAEchAEdhAEchAEchQEbhQEbhgEahgEahwEZhwEZiAEYiAEYiQEYiAEYiQEXiQEX" ++ "igEWigEWiwEViwEVjAEUjAEUjAEUjQETjQETjgESjgETjgESjwERkAEQkgEOkwENlAEMlQELlgEK" ++ "lwEJmAEJmAEImQEHmgEGmwEFnAEEnQEEnQEDnQEDngECngEDngECngECnwECngECnwECngECngED" ++ "ngECEgGLAQMQAosBAw4EjAEDCwWNAQQJBo0BBQYIjQEHAgqNARKOARKPARCQARCQARCQAQ+RAQ6S" ++ "AQ6SAQ2TAQ2SAQ2TAQ2TAQyTAQyUAQyTAQyUAQuVAQuUAQuVAQqWAQmWAQqWAQmXAQiXAQiYAQeY" ++ "AQeZAQWbAQSDZwAA"); ++ ok(match, "Figure does not match.\n"); ++ match = compare_figure(&ctx, 160, 160, 320, 320, 0xff652e89, 32, ++ "g90BBLkCCLYCC7ICDrACEa0CFKoCF6cCGqQCHKMCHqECIJ8CIpwCJJsCJpkCKJcCKZYCK5QCLZIC" ++ "L5ACMI8CMo0CNIsCNYoCN4gCOYcCOYYCO4QCPYICPoECQIACQYACQIECQIACQIECQIECQIECP4IC" ++ "P4ICP4ECP4ICP4ICPoMCPoMCPoMCPYQCPYMCPYQCPYQCPYQCPIUCPIUCPIUCO4YCO4YCOoYCO4YC" ++ "OocCOocCOocCOYgCOYgCOIkCOIkCN4oCNosCNYwCNI0CM44CMo4CM44CMo8CMZACMJECL5ICLpMC" ++ "LZQCLJUCK5YCK5YCKpcCKZgCKJkCJ5oCJpsCJpsCJZwCJJ4CIqACIKICH6MCHaUCG6cCGakCF6wC" ++ "Fa0CE68CEbECD7MCDrQCDLYCCrgCCbkCB7sCBrsCBbwCBbwCBL0CBL0CBL0CBL0CA70CBL0CBL0C" ++ "BLwCBSUBlgIFIQSXAgYbCJcCBxcKmQIIEQ6ZAgoMEJoCDQUTnAIknAIjnQIingIhnwIgoAIfoQIe" ++ "ogIdowIcpAIbpQIapQIZpgIZpgIZpwIYpwIXqAIXqAIXqQIVqgIVqgIUqwITrQISrQIRrgIQsAIO" ++ "sQIMswILtQIIhs4B"); ++ ok(match, "Figure does not match.\n"); ++ ++ hr = ID2D1Factory_CreatePathGeometry(factory, &geometry); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ hr = ID2D1PathGeometry_Open(geometry, &sink); ++ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ++ + set_point(&point, -0.402914f, 0.915514f); + ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW); + quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f); +-- +2.45.2 + diff --git a/patches/d2d1_ID2D1GeometryGroup/0002-d2d1-Implement-drawing-for-ID2D1GeometryGroup.patch b/patches/d2d1_ID2D1GeometryGroup/0002-d2d1-Implement-drawing-for-ID2D1GeometryGroup.patch new file mode 100644 index 00000000..a9dfca7c --- /dev/null +++ b/patches/d2d1_ID2D1GeometryGroup/0002-d2d1-Implement-drawing-for-ID2D1GeometryGroup.patch @@ -0,0 +1,279 @@ +From be0fbef50483da8fe3fd0c4b74469d15a5c9f1ea Mon Sep 17 00:00:00 2001 +From: Philipp Knechtges +Date: Fri, 13 Sep 2024 16:37:31 +0200 +Subject: [PATCH] d2d1: Implement drawing for ID2D1GeometryGroup + +Drawing of ID2D1GeometryGroup was so far unimplemented and resulted in +blank drawing buffers. This partially fixes the rendering issues mentioned +in the bug below. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51139 +--- + dlls/d2d1/geometry.c | 236 ++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 235 insertions(+), 1 deletion(-) + +diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c +index 3da3ad2e65b..93925408077 100644 +--- a/dlls/d2d1/geometry.c ++++ b/dlls/d2d1/geometry.c +@@ -5497,8 +5497,13 @@ static const struct ID2D1GeometryGroupVtbl d2d_geometry_group_vtbl = + HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *factory, + D2D1_FILL_MODE fill_mode, ID2D1Geometry **geometries, unsigned int geometry_count) + { +- unsigned int i; ++ unsigned int i, j; ++ struct d2d_geometry *other_geom; ++ D2D_MATRIX_3X2_F g, gplain; ++ size_t f_vertex_count, f_face_count, f_bezier_vertex_count, f_arc_vertex_count; ++ size_t o_vertex_count, o_face_count, o_bezier_count, o_bezier_face_count, o_arc_count, o_arc_face_count; + ++ FIXME("Ignoring fill_mode=%#x!\n", fill_mode); + d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_geometry_group_vtbl); + + if (!(geometry->u.group.src_geometries = calloc(geometry_count, sizeof(*geometries)))) +@@ -5507,13 +5512,242 @@ HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *fac + return E_OUTOFMEMORY; + } + ++ geometry->fill.vertex_count = 0; ++ geometry->fill.face_count = 0; ++ geometry->fill.bezier_vertex_count = 0; ++ geometry->fill.arc_vertex_count = 0; ++ geometry->outline.vertex_count = 0; ++ geometry->outline.face_count = 0; ++ geometry->outline.bezier_count = 0; ++ geometry->outline.bezier_face_count = 0; ++ geometry->outline.arc_count = 0; ++ geometry->outline.arc_face_count = 0; + for (i = 0; i < geometry_count; ++i) + { + ID2D1Geometry_AddRef(geometry->u.group.src_geometries[i] = geometries[i]); ++ other_geom = unsafe_impl_from_ID2D1Geometry(geometries[i]); ++ geometry->fill.vertex_count += other_geom->fill.vertex_count; ++ geometry->fill.face_count += other_geom->fill.face_count; ++ geometry->fill.bezier_vertex_count += other_geom->fill.bezier_vertex_count; ++ geometry->fill.arc_vertex_count += other_geom->fill.arc_vertex_count; ++ geometry->outline.vertex_count += other_geom->outline.vertex_count; ++ geometry->outline.face_count += other_geom->outline.face_count; ++ geometry->outline.bezier_count += other_geom->outline.bezier_count; ++ geometry->outline.bezier_face_count += other_geom->outline.bezier_face_count; ++ geometry->outline.arc_count += other_geom->outline.arc_count; ++ geometry->outline.arc_face_count += other_geom->outline.arc_face_count; + } + geometry->u.group.geometry_count = geometry_count; + geometry->u.group.fill_mode = fill_mode; + ++ if (!(geometry->fill.vertices = calloc(geometry->fill.vertex_count, sizeof(D2D1_POINT_2F)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ if (!(geometry->fill.faces = calloc(geometry->fill.face_count, sizeof(struct d2d_face)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ geometry->fill.faces_size = geometry->fill.face_count; ++ if (!(geometry->fill.bezier_vertices = calloc(geometry->fill.bezier_vertex_count, sizeof(struct d2d_curve_vertex)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ geometry->fill.bezier_vertices_size = geometry->fill.bezier_vertex_count; ++ if (!(geometry->fill.arc_vertices = calloc(geometry->fill.arc_vertex_count, sizeof(struct d2d_curve_vertex)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ geometry->fill.arc_vertices_size = geometry->fill.arc_vertex_count; ++ if (!(geometry->outline.vertices = calloc(geometry->outline.vertex_count, sizeof(struct d2d_outline_vertex)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ geometry->outline.vertices_size = geometry->outline.vertex_count; ++ if (!(geometry->outline.faces = calloc(geometry->outline.face_count, sizeof(struct d2d_face)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ geometry->outline.faces_size = geometry->outline.face_count; ++ if (!(geometry->outline.beziers = calloc(geometry->outline.bezier_count, sizeof(struct d2d_curve_outline_vertex)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ geometry->outline.beziers_size = geometry->outline.bezier_count; ++ if (!(geometry->outline.bezier_faces = calloc(geometry->outline.bezier_face_count, sizeof(struct d2d_face)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ geometry->outline.bezier_faces_size = geometry->outline.bezier_face_count; ++ if (!(geometry->outline.arcs = calloc(geometry->outline.arc_count, sizeof(struct d2d_curve_outline_vertex)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ geometry->outline.arcs_size = geometry->outline.arc_count; ++ if (!(geometry->outline.arc_faces = calloc(geometry->outline.arc_face_count, sizeof(struct d2d_face)))) ++ { ++ for (i = 0; i < geometry->u.group.geometry_count; ++i) ++ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]); ++ d2d_geometry_cleanup(geometry); ++ return E_OUTOFMEMORY; ++ } ++ geometry->outline.arc_faces_size = geometry->outline.arc_face_count; ++ ++ f_vertex_count = 0; ++ f_face_count = 0; ++ f_bezier_vertex_count = 0; ++ f_arc_vertex_count = 0; ++ o_vertex_count = 0; ++ o_face_count = 0; ++ o_bezier_count = 0; ++ o_bezier_face_count = 0; ++ o_arc_count = 0; ++ o_arc_face_count = 0; ++ for (i = 0; i < geometry_count; ++i) ++ { ++ other_geom = unsafe_impl_from_ID2D1Geometry(geometries[i]); ++ g = other_geom->transform; ++ gplain = g; ++ gplain.dx = 0.0f; ++ gplain.dy = 0.0f; ++ ++ for (j = 0; j < other_geom->fill.vertex_count; ++j) { ++ d2d_point_transform(&geometry->fill.vertices[j+f_vertex_count], &g, ++ other_geom->fill.vertices[j].x, other_geom->fill.vertices[j].y); ++ } ++ for (j = 0; j < other_geom->fill.face_count; ++j) { ++ geometry->fill.faces[f_face_count+j].v[0] = other_geom->fill.faces[j].v[0] ++ + (UINT16) f_vertex_count; ++ geometry->fill.faces[f_face_count+j].v[1] = other_geom->fill.faces[j].v[1] ++ + (UINT16) f_vertex_count; ++ geometry->fill.faces[f_face_count+j].v[2] = other_geom->fill.faces[j].v[2] ++ + (UINT16) f_vertex_count; ++ } ++ f_vertex_count += other_geom->fill.vertex_count; ++ f_face_count += other_geom->fill.face_count; ++ ++ for (j = 0; j < other_geom->fill.bezier_vertex_count; ++j) { ++ d2d_point_transform(&geometry->fill.bezier_vertices[j+f_bezier_vertex_count].position, ++ &g, other_geom->fill.bezier_vertices[j].position.x, ++ other_geom->fill.bezier_vertices[j].position.y); ++ geometry->fill.bezier_vertices[j+f_bezier_vertex_count].texcoord ++ = other_geom->fill.bezier_vertices[j].texcoord; ++ } ++ f_bezier_vertex_count += other_geom->fill.bezier_vertex_count; ++ ++ for (j = 0; j < other_geom->fill.arc_vertex_count; ++j) { ++ d2d_point_transform(&geometry->fill.arc_vertices[j+f_arc_vertex_count].position, ++ &g, other_geom->fill.arc_vertices[j].position.x, ++ other_geom->fill.arc_vertices[j].position.y); ++ geometry->fill.arc_vertices[j+f_arc_vertex_count].texcoord ++ = other_geom->fill.arc_vertices[j].texcoord; ++ ++ } ++ f_arc_vertex_count += other_geom->fill.arc_vertex_count; ++ ++ for (j = 0; j < other_geom->outline.vertex_count; ++j) { ++ d2d_point_transform(&geometry->outline.vertices[j+o_vertex_count].position, &g, ++ other_geom->outline.vertices[j].position.x, other_geom->outline.vertices[j].position.y); ++ d2d_point_transform(&geometry->outline.vertices[j+o_vertex_count].prev, &gplain, ++ other_geom->outline.vertices[j].prev.x, other_geom->outline.vertices[j].prev.y); ++ d2d_point_normalise(&geometry->outline.vertices[j+o_vertex_count].prev); ++ d2d_point_transform(&geometry->outline.vertices[j+o_vertex_count].next, &gplain, ++ other_geom->outline.vertices[j].next.x, other_geom->outline.vertices[j].next.y); ++ d2d_point_normalise(&geometry->outline.vertices[j+o_vertex_count].next); ++ } ++ for (j = 0; j < other_geom->outline.face_count; ++j) { ++ geometry->outline.faces[o_face_count+j].v[0] = other_geom->outline.faces[j].v[0] ++ + (UINT16) o_vertex_count; ++ geometry->outline.faces[o_face_count+j].v[1] = other_geom->outline.faces[j].v[1] ++ + (UINT16) o_vertex_count; ++ geometry->outline.faces[o_face_count+j].v[2] = other_geom->outline.faces[j].v[2] ++ + (UINT16) o_vertex_count; ++ } ++ o_vertex_count += other_geom->outline.vertex_count; ++ o_face_count += other_geom->outline.face_count; ++ ++ for (j = 0; j < other_geom->outline.bezier_count; ++j) { ++ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].position, &g, ++ other_geom->outline.beziers[j].position.x, other_geom->outline.beziers[j].position.y); ++ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].prev, &gplain, ++ other_geom->outline.beziers[j].prev.x, other_geom->outline.beziers[j].prev.y); ++ d2d_point_normalise(&geometry->outline.beziers[j+o_bezier_count].prev); ++ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].next, &gplain, ++ other_geom->outline.beziers[j].next.x, other_geom->outline.beziers[j].next.y); ++ d2d_point_normalise(&geometry->outline.beziers[j+o_bezier_count].next); ++ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].p0, &g, ++ other_geom->outline.beziers[j].p0.x, other_geom->outline.beziers[j].p0.y); ++ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].p1, &g, ++ other_geom->outline.beziers[j].p1.x, other_geom->outline.beziers[j].p1.y); ++ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].p2, &g, ++ other_geom->outline.beziers[j].p2.x, other_geom->outline.beziers[j].p2.y); ++ } ++ for (j = 0; j < other_geom->outline.bezier_face_count; ++j) { ++ geometry->outline.bezier_faces[o_bezier_face_count+j].v[0] ++ = other_geom->outline.bezier_faces[j].v[0] + (UINT16) o_bezier_count; ++ geometry->outline.bezier_faces[o_bezier_face_count+j].v[1] ++ = other_geom->outline.bezier_faces[j].v[1] + (UINT16) o_bezier_count; ++ geometry->outline.bezier_faces[o_bezier_face_count+j].v[2] ++ = other_geom->outline.bezier_faces[j].v[2] + (UINT16) o_bezier_count; ++ } ++ o_bezier_count += other_geom->outline.bezier_count; ++ o_bezier_face_count += other_geom->outline.bezier_face_count; ++ ++ for (j = 0; j < other_geom->outline.arc_count; ++j) { ++ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].position, &g, ++ other_geom->outline.arcs[j].position.x, other_geom->outline.arcs[j].position.y); ++ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].prev, &gplain, ++ other_geom->outline.arcs[j].prev.x, other_geom->outline.arcs[j].prev.y); ++ d2d_point_normalise(&geometry->outline.arcs[j+o_arc_count].prev); ++ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].next, &gplain, ++ other_geom->outline.arcs[j].next.x, other_geom->outline.arcs[j].next.y); ++ d2d_point_normalise(&geometry->outline.arcs[j+o_arc_count].next); ++ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].p0, &g, ++ other_geom->outline.arcs[j].p0.x, other_geom->outline.arcs[j].p0.y); ++ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].p1, &g, ++ other_geom->outline.arcs[j].p1.x, other_geom->outline.arcs[j].p1.y); ++ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].p2, &g, ++ other_geom->outline.arcs[j].p2.x, other_geom->outline.arcs[j].p2.y); ++ } ++ for (j = 0; j < other_geom->outline.arc_face_count; ++j) { ++ geometry->outline.arc_faces[o_arc_face_count+j].v[0] ++ = other_geom->outline.arc_faces[j].v[0] + (UINT16) o_arc_count; ++ geometry->outline.arc_faces[o_arc_face_count+j].v[1] ++ = other_geom->outline.arc_faces[j].v[1] + (UINT16) o_arc_count; ++ geometry->outline.arc_faces[o_arc_face_count+j].v[2] ++ = other_geom->outline.arc_faces[j].v[2] + (UINT16) o_arc_count; ++ } ++ o_arc_count += other_geom->outline.arc_count; ++ o_arc_face_count += other_geom->outline.arc_face_count; ++ } ++ + return S_OK; + } + +-- +2.45.2 + diff --git a/patches/d2d1_ID2D1GeometryGroup/definition b/patches/d2d1_ID2D1GeometryGroup/definition new file mode 100644 index 00000000..78c689d6 --- /dev/null +++ b/patches/d2d1_ID2D1GeometryGroup/definition @@ -0,0 +1,3 @@ +Fixes: [51139] d2d1: Implement drawing of ID2D1GeometryGroup + +# MR https://gitlab.winehq.org/wine/wine/-/merge_requests/6492