hrev48447 adds 2 changesets to branch 'master' old head: 336c69d9c4dfc80a6d9450e51d64b0569bbba603 new head: c4e8d88f7c53179606b32acb0cab1265eaa47bf3 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=c4e8d88+%5E336c69d ---------------------------------------------------------------------------- 96bac1b: Add a test for #2945. c4e8d88: 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. [ Adrien Destugues <pulkomandy@xxxxxxxxx> ] ---------------------------------------------------------------------------- 3 files changed, 56 insertions(+), 8 deletions(-) src/servers/app/DrawingContext.cpp | 24 ++++++++++++---- src/servers/app/drawing/Painter/Painter.cpp | 2 +- src/tests/servers/app/gradients/main.cpp | 38 ++++++++++++++++++++++++- ############################################################################ Commit: 96bac1b30b7608c473264dfa7d234d6ef95667e5 URL: http://cgit.haiku-os.org/haiku/commit/?id=96bac1b Author: Adrien Destugues <pulkomandy@xxxxxxxxx> Date: Fri Dec 5 13:51:47 2014 UTC Ticket: https://dev.haiku-os.org/ticket/2945 Add a test for #2945. ---------------------------------------------------------------------------- diff --git a/src/tests/servers/app/gradients/main.cpp b/src/tests/servers/app/gradients/main.cpp index 52c684a..47810a8 100644 --- a/src/tests/servers/app/gradients/main.cpp +++ b/src/tests/servers/app/gradients/main.cpp @@ -42,7 +42,7 @@ public: Test("Radial Gradient") { } - + virtual void Draw(BView* view, BRect updateRect) { // Draws two radial gradients with the same stops and different radiis, @@ -157,6 +157,41 @@ public: }; +// Test for https://dev.haiku-os.org/ticket/2945 +// Gradients with no stop at offset 0 or 255 draw random colors +class OutOfBoundsGradientTest : public Test { +public: + OutOfBoundsGradientTest() + : + Test("Out of bounds gradients") + { + } + + virtual void Draw(BView* view, BRect updateRect) + { + { + // Linear gradient - Vertical + BPoint from(275, 10); + BPoint to(275, 138); + BGradientLinear l(from, to); + l.AddColor((rgb_color){ 255, 0, 0, 255 }, 100.0); + l.AddColor((rgb_color){ 255, 255, 0, 255 }, 156.0); + view->FillRect(BRect(275, 10, 2*265, 265), l); + } + + { + // Linear gradient - Horizontal + BPoint from(10, 10); + BPoint to(138, 10); + BGradientLinear l(from, to); + l.AddColor((rgb_color){ 255, 0, 0, 255 }, 100.0); + l.AddColor((rgb_color){ 255, 255, 0, 255 }, 156.0); + view->FillRect(BRect(10, 10, 265, 265), l); + } + } +}; + + // #pragma mark - @@ -169,6 +204,7 @@ main(int argc, char** argv) window->AddTest(new RadialGradientTest()); window->AddTest(new AlphaGradientTest()); + window->AddTest(new OutOfBoundsGradientTest()); window->SetToTest(0); window->Show(); ############################################################################ Revision: hrev48447 Commit: c4e8d88f7c53179606b32acb0cab1265eaa47bf3 URL: http://cgit.haiku-os.org/haiku/commit/?id=c4e8d88 Author: Adrien Destugues <pulkomandy@xxxxxxxxx> Date: Fri Dec 5 13:52:31 2014 UTC Ticket: https://dev.haiku-os.org/ticket/2945 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. ---------------------------------------------------------------------------- diff --git a/src/servers/app/DrawingContext.cpp b/src/servers/app/DrawingContext.cpp index b259f5e..8a61f9b 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 97f1a1f..9ac646e 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"));