From c4e8d88f7c53179606b32acb0cab1265eaa47bf3 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 5 Dec 2014 14:52:31 +0100 Subject: [PATCH] app_server: fix gradients with no stops at the ends When a gradient has no stop at offset 0 or 255, the drawing code will not automatically complete the gradiet with the first or last color, instead agg interpolation generated invalid random colors. To avoid this, insert extra stops at the start and end in the DrawingEngine when we prepare the gradient for drawing. We just copy the first and last stops to new stops at offsets 0 and 255, which makes sure the gradients covers the whole range and gives the expected result. Fixes #2945. --- src/servers/app/DrawingContext.cpp | 24 +++++++++++++++------ src/servers/app/drawing/Painter/Painter.cpp | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/servers/app/DrawingContext.cpp b/src/servers/app/DrawingContext.cpp index b259f5e98e..8a61f9b00a 100644 --- a/src/servers/app/DrawingContext.cpp +++ b/src/servers/app/DrawingContext.cpp @@ -185,7 +185,7 @@ DrawingContext::ConvertToScreenForDrawing(BRegion* region) const void DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const { - switch(gradient->GetType()) { + switch (gradient->GetType()) { case BGradient::TYPE_LINEAR: { BGradientLinear* linear = (BGradientLinear*) gradient; @@ -197,7 +197,6 @@ DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const ConvertToScreen(&end); linear->SetStart(start); linear->SetEnd(end); - linear->SortColorStopsByOffset(); break; } case BGradient::TYPE_RADIAL: @@ -207,7 +206,6 @@ DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const fDrawState->Transform(¢er); ConvertToScreen(¢er); radial->SetCenter(center); - radial->SortColorStopsByOffset(); break; } case BGradient::TYPE_RADIAL_FOCUS: @@ -221,7 +219,6 @@ DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const ConvertToScreen(&focal); radialFocus->SetCenter(center); radialFocus->SetFocal(focal); - radialFocus->SortColorStopsByOffset(); break; } case BGradient::TYPE_DIAMOND: @@ -231,7 +228,6 @@ DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const fDrawState->Transform(¢er); ConvertToScreen(¢er); diamond->SetCenter(center); - diamond->SortColorStopsByOffset(); break; } case BGradient::TYPE_CONIC: @@ -241,7 +237,6 @@ DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const fDrawState->Transform(¢er); ConvertToScreen(¢er); conic->SetCenter(center); - conic->SortColorStopsByOffset(); break; } case BGradient::TYPE_NONE: @@ -249,6 +244,23 @@ DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const break; } } + + // Make sure the gradient is fully padded so that out of bounds access + // get the correct colors + gradient->SortColorStopsByOffset(); + + BGradient::ColorStop* end = gradient->ColorStopAtFast( + gradient->CountColorStops() - 1); + + if (end->offset != 255) + gradient->AddColor(end->color, 255); + + BGradient::ColorStop* start = gradient->ColorStopAtFast(0); + + if (start->offset != 0) + gradient->AddColor(start->color, 0); + + gradient->SortColorStopsByOffset(); } diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 97f1a1f8cc..9ac646eb6c 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -2881,7 +2881,7 @@ Painter::_RasterizePath(VertexSource& path, const BGradient& gradient) const agg::trans_affine gradientTransform; - switch(gradient.GetType()) { + switch (gradient.GetType()) { case BGradient::TYPE_LINEAR: { GTRACE(("Painter::_FillPath> type == TYPE_LINEAR\n"));