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.
This commit is contained in:
Adrien Destugues 2014-12-05 14:52:31 +01:00
parent 96bac1b30b
commit c4e8d88f7c
2 changed files with 19 additions and 7 deletions

View File

@ -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(&center);
ConvertToScreen(&center);
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(&center);
ConvertToScreen(&center);
diamond->SetCenter(center);
diamond->SortColorStopsByOffset();
break;
}
case BGradient::TYPE_CONIC:
@ -241,7 +237,6 @@ DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const
fDrawState->Transform(&center);
ConvertToScreen(&center);
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();
}

View File

@ -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"));