svg_loader: handling the ColorStop offset values

The ColorStop offset < 0 and > 1 should be treated as 0 and 1 respectively.
The offset value < than the previous offset value should be replaced
by the previous value - without this change segfault occurred.
Validating the APIs parameters values is the user responsibility.
This commit is contained in:
Mira Grudzinska 2021-06-22 20:32:48 +02:00 committed by Hermet Park
parent 750ad90bf0
commit 286f700305
2 changed files with 11 additions and 1 deletions

View file

@ -90,4 +90,4 @@ FillSpread Fill::spread() const noexcept
Fill* Fill::duplicate() const noexcept Fill* Fill::duplicate() const noexcept
{ {
return pImpl->duplicate(); return pImpl->duplicate();
} }

View file

@ -73,6 +73,7 @@ static unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient*
if (stopCount > 0) { if (stopCount > 0) {
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop)); stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
if (!stops) return fillGrad; if (!stops) return fillGrad;
auto prevOffset = 0.0f;
for (uint32_t i = 0; i < g->stops.count; ++i) { for (uint32_t i = 0; i < g->stops.count; ++i) {
auto colorStop = g->stops.data[i]; auto colorStop = g->stops.data[i];
//Use premultiplied color //Use premultiplied color
@ -81,6 +82,10 @@ static unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient*
stops[i].b = colorStop->b; stops[i].b = colorStop->b;
stops[i].a = (colorStop->a * fillOpacity) / 255.0f; stops[i].a = (colorStop->a * fillOpacity) / 255.0f;
stops[i].offset = colorStop->offset; stops[i].offset = colorStop->offset;
// check the offset corner cases - refer to: https://svgwg.org/svg2-draft/pservers.html#StopNotes
if (colorStop->offset < prevOffset) stops[i].offset = prevOffset;
else if (colorStop->offset > 1) stops[i].offset = 1;
prevOffset = stops[i].offset;
} }
fillGrad->colorStops(stops, stopCount); fillGrad->colorStops(stops, stopCount);
free(stops); free(stops);
@ -136,6 +141,7 @@ static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient*
if (stopCount > 0) { if (stopCount > 0) {
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop)); stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
if (!stops) return fillGrad; if (!stops) return fillGrad;
auto prevOffset = 0.0f;
for (uint32_t i = 0; i < g->stops.count; ++i) { for (uint32_t i = 0; i < g->stops.count; ++i) {
auto colorStop = g->stops.data[i]; auto colorStop = g->stops.data[i];
//Use premultiplied color //Use premultiplied color
@ -144,6 +150,10 @@ static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient*
stops[i].b = colorStop->b; stops[i].b = colorStop->b;
stops[i].a = (colorStop->a * fillOpacity) / 255.0f; stops[i].a = (colorStop->a * fillOpacity) / 255.0f;
stops[i].offset = colorStop->offset; stops[i].offset = colorStop->offset;
// check the offset corner cases - refer to: https://svgwg.org/svg2-draft/pservers.html#StopNotes
if (colorStop->offset < prevOffset) stops[i].offset = prevOffset;
else if (colorStop->offset > 1) stops[i].offset = 1;
prevOffset = stops[i].offset;
} }
fillGrad->colorStops(stops, stopCount); fillGrad->colorStops(stops, stopCount);
free(stops); free(stops);