svg_loader: handling the ColorStop offset values
authorMira Grudzinska <m.grudzinska@samsung.com>
Tue, 22 Jun 2021 18:32:48 +0000 (20:32 +0200)
committerJunsuChoi <jsuya.choi@samsung.com>
Fri, 25 Jun 2021 00:45:46 +0000 (09:45 +0900)
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.

src/lib/tvgFill.cpp
src/loaders/svg/tvgSvgSceneBuilder.cpp

index b3fbc7369895b5f459d89973012a90f13d6e4d09..757f78b9517c3c68bdb7d7c1a843e2432ff6a1df 100644 (file)
@@ -90,4 +90,4 @@ FillSpread Fill::spread() const noexcept
 Fill* Fill::duplicate() const noexcept
 {
     return pImpl->duplicate();
-}
\ No newline at end of file
+}
index ec0d8a5c408fb6589631e371ce223b4b61e150d8..4cfb1341d823aa7a3517b3715c1643ba0a3f0e53 100644 (file)
@@ -73,6 +73,7 @@ static unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient*
     if (stopCount > 0) {
         stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
         if (!stops) return fillGrad;
+        auto prevOffset = 0.0f;
         for (uint32_t i = 0; i < g->stops.count; ++i) {
             auto colorStop = g->stops.data[i];
             //Use premultiplied color
@@ -81,6 +82,10 @@ static unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient*
             stops[i].b = colorStop->b;
             stops[i].a = (colorStop->a * fillOpacity) / 255.0f;
             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);
         free(stops);
@@ -136,6 +141,7 @@ static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient*
     if (stopCount > 0) {
         stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
         if (!stops) return fillGrad;
+        auto prevOffset = 0.0f;
         for (uint32_t i = 0; i < g->stops.count; ++i) {
             auto colorStop = g->stops.data[i];
             //Use premultiplied color
@@ -144,6 +150,10 @@ static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient*
             stops[i].b = colorStop->b;
             stops[i].a = (colorStop->a * fillOpacity) / 255.0f;
             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);
         free(stops);