Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/gdiplus/tests/brush.c | 384 +++++++++++++++++-------------------- 1 file changed, 181 insertions(+), 203 deletions(-)
diff --git a/dlls/gdiplus/tests/brush.c b/dlls/gdiplus/tests/brush.c index 0451948175..bc6b57f9b2 100644 --- a/dlls/gdiplus/tests/brush.c +++ b/dlls/gdiplus/tests/brush.c @@ -621,141 +621,103 @@ static void test_texturewrap(void)
static void test_gradientgetrect(void) { + static const struct + { + LinearGradientMode mode; + GpRectF rect; + REAL transform[6]; + } + create_from_rect[] = + { + { LinearGradientModeHorizontal, { 10.0f, 10.0f, -100.0f, -100.0f } }, + { LinearGradientModeHorizontal, { 10.0f, 10.0f, 100.0f, 100.0f } }, + { LinearGradientModeHorizontal, { 10.0f, -5.0f, 100.0f, 50.0f } }, + { LinearGradientModeHorizontal, { -5.0f, 10.0f, 100.0f, 50.0f } }, + { LinearGradientModeVertical, { 0.0f, 0.0f, 100.0f, 10.0f }, { 0.0f, 0.1f, -10.0f, -0.0f, 100.0f, 0.0f } }, + { LinearGradientModeVertical, { 10.0f, -12.0f, 100.0f, 105.0f }, { 0.0f, 1.05f, -0.952f, 0.0f, 98.571f, -22.5f } }, + }; + static const struct + { + GpPointF pt1, pt2; + GpRectF rect; + REAL transform[6]; + } + create_from_pt[] = + { + { { 1.0f, 1.0f }, { 100.0f, 100.0f }, { 1.0f, 1.0f, 99.0f, 99.0f }, { 1.0f, 1.0f, -1.0f, 1.0f, 50.50f, -50.50f } }, + { { 0.0f, 0.0f }, { 0.0f, 10.0f }, { -5.0f, 0.0f, 10.0f, 10.0f }, { 0.0f, 1.0f, -1.0f, 0.0f, 5.0f, 5.0f } }, + { { 0.0f, 0.0f }, { 10.0f, 0.0f }, { 0.0f, -5.0f, 10.0f, 10.0f }, { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f } }, + /* Slope = -1 */ + { { 0.0f, 0.0f }, { 20.0f, -20.0f }, { 0.0f, -20.0f, 20.0f, 20.0f }, { 1.0f, -1.0f, 1.0f, 1.0f, 10.0f, 10.0f } }, + /* Slope = 1/100 */ + { { 0.0f, 0.0f }, { 100.0f, 1.0f }, { 0.0f, 0.0f, 100.0f, 1.0f }, { 1.0f, 0.01f, -0.02f, 2.0f, 0.01f, -1.0f } }, + { { 10.0f, 10.0f }, { -90.0f, 10.0f }, { -90.0f, -40.0f, 100.0f, 100.0f }, { -1.0f, 0.0f, 0.0f, -1.0f, -80.0f, 20.0f } }, + }; + static const struct + { + GpRectF rect; + REAL angle; + BOOL is_scalable; + REAL transform[6]; + } + create_with_angle[] = + { + { { 10.0f, 10.0f, -100.0f, -100.0f }, 0.0f, TRUE }, + { { 10.0f, 10.0f, -100.0f, -100.0f }, 0.0f, FALSE }, + { { 10.0f, 10.0f, 100.0f, 100.0f }, 0.0f, FALSE }, + { { 10.0f, 10.0f, 100.0f, 100.0f }, 0.0f, TRUE }, + { { 10.0f, -5.0f, 100.0f, 50.0f }, 0.0f, FALSE }, + { { 10.0f, -5.0f, 100.0f, 50.0f }, 0.0f, TRUE }, + { { -5.0f, 10.0f, 100.0f, 50.0f }, 0.0f, FALSE }, + { { -5.0f, 10.0f, 100.0f, 50.0f }, 0.0f, TRUE }, + { { 0.0f, 0.0f, 100.0f, 10.0f }, -90.0f, TRUE, { 0.0f, -0.1f, 10.0f, 0.0f, 0.0f, 10.0f } }, + { { 10.0f, -12.0f, 100.0f, 105.0f }, -90.0f, TRUE, { 0.0f, -1.05f, 0.952f, 0.0f, 21.429f, 103.5f } }, + { { 0.0f, 0.0f, 100.0f, 10.0f }, -90.0f, FALSE, { 0.0f, -0.1f, 10.0f, -0.0f, 0.0f, 10.0f } }, + { { 10.0f, -12.0f, 100.0f, 105.0f }, -90.0f, FALSE, { 0.0f, -1.05f, 0.952f, 0.0f, 21.429f, 103.5f } }, + }; GpLineGradient *brush; GpMatrix *transform; REAL elements[6]; - GpRectF rectf; GpStatus status; - GpPointF pt1, pt2; + unsigned int i; + ARGB colors[2]; + GpRectF rectf;
status = GdipCreateMatrix(&transform); expect(Ok, status);
- pt1.X = pt1.Y = 1.0; - pt2.X = pt2.Y = 100.0; - status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush); - expect(Ok, status); - memset(&rectf, 0, sizeof(GpRectF)); - status = GdipGetLineRect(brush, &rectf); - expect(Ok, status); - expectf(1.0, rectf.X); - expectf(1.0, rectf.Y); - expectf(99.0, rectf.Width); - expectf(99.0, rectf.Height); - status = GdipGetLineTransform(brush, transform); - expect(Ok, status); - status = GdipGetMatrixElements(transform, elements); - expect(Ok, status); - expectf(1.0, elements[0]); - expectf(1.0, elements[1]); - expectf(-1.0, elements[2]); - expectf(1.0, elements[3]); - expectf(50.50, elements[4]); - expectf(-50.50, elements[5]); - status = GdipDeleteBrush((GpBrush*)brush); - expect(Ok, status); - - /* vertical gradient */ - pt1.X = pt1.Y = pt2.X = 0.0; - pt2.Y = 10.0; - status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush); - expect(Ok, status); - memset(&rectf, 0, sizeof(GpRectF)); - status = GdipGetLineRect(brush, &rectf); - expect(Ok, status); - expectf(-5.0, rectf.X); - expectf(0.0, rectf.Y); - expectf(10.0, rectf.Width); - expectf(10.0, rectf.Height); - status = GdipGetLineTransform(brush, transform); - expect(Ok, status); - status = GdipGetMatrixElements(transform, elements); - expect(Ok, status); - expectf(0.0, elements[0]); - expectf(1.0, elements[1]); - expectf(-1.0, elements[2]); - expectf(0.0, elements[3]); - expectf(5.0, elements[4]); - expectf(5.0, elements[5]); - status = GdipDeleteBrush((GpBrush*)brush); - expect(Ok, status); - - /* horizontal gradient */ - pt1.X = pt1.Y = pt2.Y = 0.0; - pt2.X = 10.0; - status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush); - expect(Ok, status); - memset(&rectf, 0, sizeof(GpRectF)); - status = GdipGetLineRect(brush, &rectf); - expect(Ok, status); - expectf(0.0, rectf.X); - expectf(-5.0, rectf.Y); - expectf(10.0, rectf.Width); - expectf(10.0, rectf.Height); - status = GdipGetLineTransform(brush, transform); - expect(Ok, status); - status = GdipGetMatrixElements(transform, elements); - expect(Ok, status); - expectf(1.0, elements[0]); - expectf(0.0, elements[1]); - expectf(0.0, elements[2]); - expectf(1.0, elements[3]); - expectf(0.0, elements[4]); - expectf(0.0, elements[5]); - status = GdipDeleteBrush((GpBrush*)brush); - expect(Ok, status); - - /* slope = -1 */ - pt1.X = pt1.Y = 0.0; - pt2.X = 20.0; - pt2.Y = -20.0; - status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush); - expect(Ok, status); - memset(&rectf, 0, sizeof(GpRectF)); - status = GdipGetLineRect(brush, &rectf); - expect(Ok, status); - expectf(0.0, rectf.X); - expectf(-20.0, rectf.Y); - expectf(20.0, rectf.Width); - expectf(20.0, rectf.Height); - status = GdipGetLineTransform(brush, transform); - expect(Ok, status); - status = GdipGetMatrixElements(transform, elements); - expect(Ok, status); - expectf(1.0, elements[0]); - expectf(-1.0, elements[1]); - expectf(1.0, elements[2]); - expectf(1.0, elements[3]); - expectf(10.0, elements[4]); - expectf(10.0, elements[5]); - status = GdipDeleteBrush((GpBrush*)brush); - expect(Ok, status); - - /* slope = 1/100 */ - pt1.X = pt1.Y = 0.0; - pt2.X = 100.0; - pt2.Y = 1.0; - status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush); - expect(Ok, status); - memset(&rectf, 0, sizeof(GpRectF)); - status = GdipGetLineRect(brush, &rectf); - expect(Ok, status); - expectf(0.0, rectf.X); - expectf(0.0, rectf.Y); - expectf(100.0, rectf.Width); - expectf(1.0, rectf.Height); - status = GdipGetLineTransform(brush, transform); - expect(Ok, status); - status = GdipGetMatrixElements(transform, elements); - expect(Ok,status); - expectf(1.0, elements[0]); - expectf(0.01, elements[1]); - expectf(-0.02, elements[2]); - /* expectf(2.0, elements[3]); */ - expectf(0.01, elements[4]); - /* expectf(-1.0, elements[5]); */ - status = GdipDeleteBrush((GpBrush*)brush); - expect(Ok,status); + for (i = 0; i < ARRAY_SIZE(create_from_pt); ++i) + { + status = GdipCreateLineBrush(&create_from_pt[i].pt1, &create_from_pt[i].pt2, 0x1, 0x2, WrapModeTile, &brush); + ok(status == Ok, "Failed to create a brush, %d.\n", status); + + memset(&rectf, 0, sizeof(rectf)); + status = GdipGetLineRect(brush, &rectf); + ok(status == Ok, "Failed to get brush rect, %d.\n", status); + ok(!memcmp(&rectf, &create_from_pt[i].rect, sizeof(rectf)), "Unexpected brush rect.\n"); + + status = GdipGetLineTransform(brush, transform); + ok(status == Ok, "Failed to get brush transform, %d.\n", status); + + status = GdipGetMatrixElements(transform, elements); + ok(status == Ok, "Failed to get matrix elements, %d.\n", status); + +#define expectf2(expected, got) ok(fabs(expected - got) < 0.001, "%u: expected %.3f, got %.3f.\n", i, expected, got) + expectf2(create_from_pt[i].transform[0], elements[0]); + expectf2(create_from_pt[i].transform[1], elements[1]); + expectf2(create_from_pt[i].transform[2], elements[2]); + expectf2(create_from_pt[i].transform[3], elements[3]); + expectf2(create_from_pt[i].transform[4], elements[4]); + expectf2(create_from_pt[i].transform[5], elements[5]); +#undef expect2f + + status = GdipGetLineColors(brush, colors); + ok(status == Ok, "Failed to get line colors, %d.\n", status); + ok(colors[0] == 0x1 && colors[1] == 0x2, "Unexpected brush colors.\n"); + + status = GdipDeleteBrush((GpBrush *)brush); + ok(status == Ok, "Failed to delete a brush, %d.\n", status); + }
/* zero height rect */ rectf.X = rectf.Y = 10.0; @@ -773,84 +735,100 @@ static void test_gradientgetrect(void) WrapModeTile, &brush); expect(OutOfMemory, status);
- /* from rect with LinearGradientModeHorizontal */ - rectf.X = rectf.Y = 10.0; - rectf.Width = rectf.Height = 100.0; - status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeHorizontal, - WrapModeTile, &brush); - expect(Ok, status); - memset(&rectf, 0, sizeof(GpRectF)); - status = GdipGetLineRect(brush, &rectf); - expect(Ok, status); - expectf(10.0, rectf.X); - expectf(10.0, rectf.Y); - expectf(100.0, rectf.Width); - expectf(100.0, rectf.Height); - status = GdipGetLineTransform(brush, transform); - expect(Ok, status); - status = GdipGetMatrixElements(transform, elements); - expect(Ok,status); - expectf(1.0, elements[0]); - expectf(0.0, elements[1]); - expectf(0.0, elements[2]); - expectf(1.0, elements[3]); - expectf(0.0, elements[4]); - expectf(0.0, elements[5]); - status = GdipDeleteBrush((GpBrush*)brush); - expect(Ok,status); + for (i = 0; i < ARRAY_SIZE(create_from_rect); ++i) + { + ARGB colors[2]; + BOOL ret;
- /* passing negative Width/Height to LinearGradientModeHorizontal */ - rectf.X = rectf.Y = 10.0; - rectf.Width = rectf.Height = -100.0; - status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeHorizontal, - WrapModeTile, &brush); - expect(Ok, status); - memset(&rectf, 0, sizeof(GpRectF)); - status = GdipGetLineRect(brush, &rectf); - expect(Ok, status); - expectf(10.0, rectf.X); - expectf(10.0, rectf.Y); - expectf(-100.0, rectf.Width); - expectf(-100.0, rectf.Height); - status = GdipGetLineTransform(brush, transform); - expect(Ok, status); - status = GdipGetMatrixElements(transform, elements); - expect(Ok,status); - expectf(1.0, elements[0]); - expectf(0.0, elements[1]); - expectf(0.0, elements[2]); - expectf(1.0, elements[3]); - expectf(0.0, elements[4]); - expectf(0.0, elements[5]); - status = GdipDeleteBrush((GpBrush*)brush); - expect(Ok,status); + status = GdipCreateLineBrushFromRect(&create_from_rect[i].rect, 0x1, 0x2, create_from_rect[i].mode, + WrapModeTile, &brush); + ok(status == Ok, "Failed to create a brush, %d.\n", status);
- /* reverse gradient line as immediately previous */ - pt1.X = 10.0; - pt1.Y = 10.0; - pt2.X = -90.0; - pt2.Y = 10.0; - status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush); - expect(Ok, status); - memset(&rectf, 0, sizeof(GpRectF)); - status = GdipGetLineRect(brush, &rectf); - expect(Ok, status); - expectf(-90.0, rectf.X); - expectf(-40.0, rectf.Y); - expectf(100.0, rectf.Width); - expectf(100.0, rectf.Height); - status = GdipGetLineTransform(brush, transform); - expect(Ok, status); - status = GdipGetMatrixElements(transform, elements); - expect(Ok, status); - expectf(-1.0, elements[0]); - expectf(0.0, elements[1]); - expectf(0.0, elements[2]); - expectf(-1.0, elements[3]); - expectf(-80.0, elements[4]); - expectf(20.0, elements[5]); - status = GdipDeleteBrush((GpBrush*)brush); - expect(Ok, status); + memset(&rectf, 0, sizeof(rectf)); + status = GdipGetLineRect(brush, &rectf); + ok(status == Ok, "Failed to get brush rect, %d.\n", status); + ok(!memcmp(&rectf, &create_from_rect[i].rect, sizeof(rectf)), "Unexpected brush rect.\n"); + + status = GdipGetLineTransform(brush, transform); + ok(status == Ok, "Failed to get brush transform, %d.\n", status); + + if (create_from_rect[i].mode == LinearGradientModeHorizontal) + { + status = GdipIsMatrixIdentity(transform, &ret); + ok(status == Ok, "Unexpected ret value %d.\n", status); + } + else + { + status = GdipGetMatrixElements(transform, elements); + ok(status == Ok, "Failed to get matrix elements, %d.\n", status); + +#define expectf2(expected, got) ok(fabs(expected - got) < 0.001, "%u: expected %.3f, got %.3f.\n", i, expected, got) + expectf2(create_from_rect[i].transform[0], elements[0]); + todo_wine_if(create_from_rect[i].mode == LinearGradientModeVertical) { + expectf2(create_from_rect[i].transform[1], elements[1]); + expectf2(create_from_rect[i].transform[2], elements[2]); + } + expectf2(create_from_rect[i].transform[3], elements[3]); + todo_wine_if(create_from_rect[i].mode == LinearGradientModeVertical) { + expectf2(create_from_rect[i].transform[4], elements[4]); + expectf2(create_from_rect[i].transform[5], elements[5]); + } +#undef expectf2 + } + + status = GdipGetLineColors(brush, colors); + ok(status == Ok, "Failed to get line colors, %d.\n", status); + ok(colors[0] == 0x1 && colors[1] == 0x2, "Unexpected brush colors.\n"); + + status = GdipDeleteBrush((GpBrush*)brush); + ok(status == Ok, "Failed to delete a brush, %d.\n", status); + } + + for (i = 0; i < ARRAY_SIZE(create_with_angle); ++i) + { + ARGB colors[2]; + BOOL ret; + + status = GdipCreateLineBrushFromRectWithAngle(&create_with_angle[i].rect, 0x1, 0x2, create_with_angle[i].angle, + create_with_angle[i].is_scalable, WrapModeTile, &brush); + ok(status == Ok, "Failed to create a brush, %d.\n", status); + + memset(&rectf, 0, sizeof(rectf)); + status = GdipGetLineRect(brush, &rectf); + ok(status == Ok, "Failed to get brush rect, %d.\n", status); + ok(!memcmp(&rectf, &create_with_angle[i].rect, sizeof(rectf)), "%u: unexpected brush rect {%f,%f,%f,%f}.\n", + i, rectf.X, rectf.Y, rectf.Width, rectf.Height); + + status = GdipGetLineTransform(brush, transform); + ok(status == Ok, "Failed to get brush transform, %d.\n", status); + + if (create_with_angle[i].angle == 0.0f) + { + status = GdipIsMatrixIdentity(transform, &ret); + ok(status == Ok, "Unexpected ret value %d.\n", status); + } + else + { + status = GdipGetMatrixElements(transform, elements); + ok(status == Ok, "Failed to get matrix elements, %d.\n", status); + +#define expectf2(expected, got) ok(fabs(expected - got) < 0.001, "%u: expected %.3f, got %.3f.\n", i, expected, got) + expectf2(create_with_angle[i].transform[0], elements[0]); + expectf2(create_with_angle[i].transform[1], elements[1]); + expectf2(create_with_angle[i].transform[2], elements[2]); + expectf2(create_with_angle[i].transform[3], elements[3]); + expectf2(create_with_angle[i].transform[4], elements[4]); + expectf2(create_with_angle[i].transform[5], elements[5]); +#undef expectf2 + } + + status = GdipGetLineColors(brush, colors); + ok(status == Ok, "Failed to get line colors, %d.\n", status); + ok(colors[0] == 0x1 && colors[1] == 0x2, "Unexpected brush colors.\n"); + + status = GdipDeleteBrush((GpBrush*)brush); + ok(status == Ok, "Failed to delete a brush, %d.\n", status); + }
GdipDeleteMatrix(transform); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/gdiplus/brush.c | 185 +++++++++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 78 deletions(-)
diff --git a/dlls/gdiplus/brush.c b/dlls/gdiplus/brush.c index 3aeb654086..808e021fa1 100644 --- a/dlls/gdiplus/brush.c +++ b/dlls/gdiplus/brush.c @@ -265,12 +265,49 @@ GpStatus WINGDIPAPI GdipCreateHatchBrush(GpHatchStyle hatchstyle, ARGB forecol, return Ok; }
-static void linegradient_init_transform(GpLineGradient *line) +static GpStatus create_line_brush(const GpRectF *rect, ARGB startcolor, ARGB endcolor, + GpWrapMode wrap, GpLineGradient **line) +{ + *line = heap_alloc_zero(sizeof(GpLineGradient)); + if(!*line) return OutOfMemory; + + (*line)->brush.bt = BrushTypeLinearGradient; + (*line)->startcolor = startcolor; + (*line)->endcolor = endcolor; + (*line)->wrap = wrap; + (*line)->gamma = FALSE; + (*line)->rect = *rect; + (*line)->blendcount = 1; + (*line)->blendfac = heap_alloc_zero(sizeof(REAL)); + (*line)->blendpos = heap_alloc_zero(sizeof(REAL)); + + if (!(*line)->blendfac || !(*line)->blendpos) + { + heap_free((*line)->blendfac); + heap_free((*line)->blendpos); + heap_free(*line); + *line = NULL; + return OutOfMemory; + } + + (*line)->blendfac[0] = 1.0f; + (*line)->blendpos[0] = 1.0f; + + (*line)->pblendcolor = NULL; + (*line)->pblendpos = NULL; + (*line)->pblendcount = 0; + + GdipSetMatrixElements(&(*line)->transform, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); + + return Ok; +} + +static void linegradient_init_transform(const GpPointF *startpoint, const GpPointF *endpoint, GpLineGradient *line) { float trans_x = line->rect.X + (line->rect.Width / 2.f); float trans_y = line->rect.Y + (line->rect.Height / 2.f); - float dx = line->endpoint.X - line->startpoint.X; - float dy = line->endpoint.Y - line->startpoint.Y; + float dx = endpoint->X - startpoint->X; + float dy = endpoint->Y - startpoint->Y; float t_cos, t_sin, w_ratio, h_ratio; float h; GpMatrix rot; @@ -307,6 +344,9 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint, GDIPCONST GpPointF* endpoint, ARGB startcolor, ARGB endcolor, GpWrapMode wrap, GpLineGradient **line) { + GpStatus stat; + GpRectF rect; + TRACE("(%s, %s, %x, %x, %d, %p)\n", debugstr_pointf(startpoint), debugstr_pointf(endpoint), startcolor, endcolor, wrap, line);
@@ -316,57 +356,27 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint, if (startpoint->X == endpoint->X && startpoint->Y == endpoint->Y) return OutOfMemory;
- *line = heap_alloc_zero(sizeof(GpLineGradient)); - if(!*line) return OutOfMemory; + rect.X = startpoint->X < endpoint->X ? startpoint->X : endpoint->X; + rect.Y = startpoint->Y < endpoint->Y ? startpoint->Y : endpoint->Y; + rect.Width = fabs(startpoint->X - endpoint->X); + rect.Height = fabs(startpoint->Y - endpoint->Y);
- (*line)->brush.bt = BrushTypeLinearGradient; - - (*line)->startpoint.X = startpoint->X; - (*line)->startpoint.Y = startpoint->Y; - (*line)->endpoint.X = endpoint->X; - (*line)->endpoint.Y = endpoint->Y; - (*line)->startcolor = startcolor; - (*line)->endcolor = endcolor; - (*line)->wrap = wrap; - (*line)->gamma = FALSE; - - (*line)->rect.X = (startpoint->X < endpoint->X ? startpoint->X: endpoint->X); - (*line)->rect.Y = (startpoint->Y < endpoint->Y ? startpoint->Y: endpoint->Y); - (*line)->rect.Width = fabs(startpoint->X - endpoint->X); - (*line)->rect.Height = fabs(startpoint->Y - endpoint->Y); - - if ((*line)->rect.Width == 0) + if (rect.Width == 0.0f) { - (*line)->rect.X -= (*line)->rect.Height / 2.0f; - (*line)->rect.Width = (*line)->rect.Height; + rect.X -= rect.Height / 2.0f; + rect.Width = rect.Height; } - else if ((*line)->rect.Height == 0) + else if (rect.Height == 0.0f) { - (*line)->rect.Y -= (*line)->rect.Width / 2.0f; - (*line)->rect.Height = (*line)->rect.Width; - } - - (*line)->blendcount = 1; - (*line)->blendfac = heap_alloc_zero(sizeof(REAL)); - (*line)->blendpos = heap_alloc_zero(sizeof(REAL)); - - if (!(*line)->blendfac || !(*line)->blendpos) - { - heap_free((*line)->blendfac); - heap_free((*line)->blendpos); - heap_free(*line); - *line = NULL; - return OutOfMemory; + rect.Y -= rect.Width / 2.0f; + rect.Height = rect.Width; }
- (*line)->blendfac[0] = 1.0f; - (*line)->blendpos[0] = 1.0f; - - (*line)->pblendcolor = NULL; - (*line)->pblendpos = NULL; - (*line)->pblendcount = 0; + stat = create_line_brush(&rect, startcolor, endcolor, wrap, line); + if (stat != Ok) + return stat;
- linegradient_init_transform(*line); + linegradient_init_transform(startpoint, endpoint, *line);
TRACE("<-- %p\n", *line);
@@ -474,9 +484,9 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF* rect GpLineGradient **line) { GpStatus stat; - LinearGradientMode mode; - REAL exofs, eyofs; + REAL exofs, eyofs, far_x, far_y; REAL sin_angle, cos_angle, sin_cos_angle; + GpPointF start, end;
TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable, wrap, line); @@ -515,42 +525,61 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF* rect cos_angle = cosf(angle); sin_cos_angle = sin_angle * cos_angle;
- if (sin_cos_angle >= 0) - mode = LinearGradientModeForwardDiagonal; + far_x = rect->X + rect->Width; + far_y = rect->Y + rect->Height; + + if (angle == 0.0f) + { + start.X = min(rect->X, far_x); + start.Y = rect->Y; + end.X = max(rect->X, far_x); + end.Y = rect->Y; + } + else if (sin_cos_angle >= 0) + { + start.X = min(rect->X, far_x); + start.Y = min(rect->Y, far_y); + end.X = max(rect->X, far_x); + end.Y = max(rect->Y, far_y); + } else - mode = LinearGradientModeBackwardDiagonal; + { + start.X = max(rect->X, far_x); + start.Y = min(rect->Y, far_y); + end.X = min(rect->X, far_x); + end.Y = max(rect->Y, far_y); + }
- stat = GdipCreateLineBrushFromRect(rect, startcolor, endcolor, mode, wrap, line); + stat = create_line_brush(rect, startcolor, endcolor, wrap, line); + if (stat != Ok || angle == 0.0f) + return stat;
- if (stat == Ok) + if (sin_cos_angle >= 0) { - if (sin_cos_angle >= 0) - { - exofs = rect->Height * sin_cos_angle + rect->Width * cos_angle * cos_angle; - eyofs = rect->Height * sin_angle * sin_angle + rect->Width * sin_cos_angle; - } - else - { - exofs = rect->Width * sin_angle * sin_angle + rect->Height * sin_cos_angle; - eyofs = -rect->Width * sin_cos_angle + rect->Height * sin_angle * sin_angle; - } - - if (sin_angle >= 0) - { - (*line)->endpoint.X = rect->X + exofs; - (*line)->endpoint.Y = rect->Y + eyofs; - } - else - { - (*line)->endpoint.X = (*line)->startpoint.X; - (*line)->endpoint.Y = (*line)->startpoint.Y; - (*line)->startpoint.X = rect->X + exofs; - (*line)->startpoint.Y = rect->Y + eyofs; - } + exofs = rect->Height * sin_cos_angle + rect->Width * cos_angle * cos_angle; + eyofs = rect->Height * sin_angle * sin_angle + rect->Width * sin_cos_angle; + } + else + { + exofs = rect->Width * sin_angle * sin_angle + rect->Height * sin_cos_angle; + eyofs = -rect->Width * sin_cos_angle + rect->Height * sin_angle * sin_angle; + }
- linegradient_init_transform(*line); + if (sin_angle >= 0) + { + end.X = rect->X + exofs; + end.Y = rect->Y + eyofs; + } + else + { + end.X = start.X; + end.Y = start.Y; + start.X = rect->X + exofs; + start.Y = rect->Y + eyofs; }
+ linegradient_init_transform(&start, &end, *line); + return stat; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
Should help with https://bugs.winehq.org/show_bug.cgi?id=43889
dlls/gdiplus/brush.c | 34 ++++++---------------------------- dlls/gdiplus/tests/brush.c | 4 ---- 2 files changed, 6 insertions(+), 32 deletions(-)
diff --git a/dlls/gdiplus/brush.c b/dlls/gdiplus/brush.c index 808e021fa1..42b7e8457c 100644 --- a/dlls/gdiplus/brush.c +++ b/dlls/gdiplus/brush.c @@ -408,9 +408,7 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF* rect, ARGB startcolor, ARGB endcolor, LinearGradientMode mode, GpWrapMode wrap, GpLineGradient **line) { - GpPointF start, end; - GpStatus stat; - float far_x, far_y; + float angle;
TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode, wrap, line); @@ -418,45 +416,25 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF* rect, if(!line || !rect) return InvalidParameter;
- far_x = rect->X + rect->Width; - far_y = rect->Y + rect->Height; - switch (mode) { case LinearGradientModeHorizontal: - start.X = min(rect->X, far_x); - start.Y = rect->Y; - end.X = max(rect->X, far_x); - end.Y = rect->Y; + angle = 0.0f; break; case LinearGradientModeVertical: - start.X = rect->X; - start.Y = min(rect->Y, far_y); - end.X = rect->X; - end.Y = max(rect->Y, far_y); + angle = 90.0f; break; case LinearGradientModeForwardDiagonal: - start.X = min(rect->X, far_x); - start.Y = min(rect->Y, far_y); - end.X = max(rect->X, far_x); - end.Y = max(rect->Y, far_y); + angle = 45.0f; break; case LinearGradientModeBackwardDiagonal: - start.X = max(rect->X, far_x); - start.Y = min(rect->Y, far_y); - end.X = min(rect->X, far_x); - end.Y = max(rect->Y, far_y); + angle = 135.0f; break; default: return InvalidParameter; }
- stat = GdipCreateLineBrush(&start, &end, startcolor, endcolor, wrap, line); - - if (stat == Ok) - (*line)->rect = *rect; - - return stat; + return GdipCreateLineBrushFromRectWithAngle(rect, startcolor, endcolor, angle, TRUE, wrap, line); }
GpStatus WINGDIPAPI GdipCreateLineBrushFromRectI(GDIPCONST GpRect* rect, diff --git a/dlls/gdiplus/tests/brush.c b/dlls/gdiplus/tests/brush.c index bc6b57f9b2..bb645ffef9 100644 --- a/dlls/gdiplus/tests/brush.c +++ b/dlls/gdiplus/tests/brush.c @@ -764,15 +764,11 @@ static void test_gradientgetrect(void)
#define expectf2(expected, got) ok(fabs(expected - got) < 0.001, "%u: expected %.3f, got %.3f.\n", i, expected, got) expectf2(create_from_rect[i].transform[0], elements[0]); - todo_wine_if(create_from_rect[i].mode == LinearGradientModeVertical) { expectf2(create_from_rect[i].transform[1], elements[1]); expectf2(create_from_rect[i].transform[2], elements[2]); - } expectf2(create_from_rect[i].transform[3], elements[3]); - todo_wine_if(create_from_rect[i].mode == LinearGradientModeVertical) { expectf2(create_from_rect[i].transform[4], elements[4]); expectf2(create_from_rect[i].transform[5], elements[5]); - } #undef expectf2 }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/gdiplus/gdiplus_private.h | 2 -- 1 file changed, 2 deletions(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index b2e4f1e93f..8c4fcceded 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -291,8 +291,6 @@ struct GpPathGradient{
struct GpLineGradient{ GpBrush brush; - GpPointF startpoint; - GpPointF endpoint; ARGB startcolor; ARGB endcolor; RectF rect;