common: ignoring color/alpha/opacity of a clip object 09/289809/1
authorMira Grudzinska <veleveta@gmail.com>
Tue, 27 Dec 2022 15:21:42 +0000 (16:21 +0100)
committerMichal Szczecinski <mihashco89@gmail.com>
Tue, 14 Mar 2023 09:47:34 +0000 (10:47 +0100)
According to the svg specs clip's fill and opacity
should be ignored. Till now setting the alpha/opacity
value to zero resulted in the shape's rendering abort.

@Issue: https://github.com/Samsung/thorvg/issues/1192

Change-Id: I03369fe91f811e7d6950dab1b594824cbfb7f9fe

inc/thorvg.h
src/lib/sw_engine/tvgSwRenderer.cpp
src/lib/tvgPaint.cpp
src/lib/tvgPaint.h

index 594fe9b10e214bdba9c1e05abb4a7bcc61347e91..45eeb5bb10a58cf142bced45b53405c344a32f46 100644 (file)
@@ -363,6 +363,20 @@ public:
      */
     CompositeMethod composite(const Paint** target) const noexcept;
 
+    /**
+     * @brief Gets the composition source object and the composition method.
+     *
+     * @param[out] source The paint of the composition source object.
+     * @param[out] method The method used to composite the source object with the target.
+     *
+     * @return Result::Success when the paint object used as a composition target, Result::InsufficientCondition otherwise.
+     *
+     * @warning Please do not use it, this API is not official one. It could be modified in the next version.
+     *
+     * @BETA_API
+     */
+    Result composite(const Paint** source, CompositeMethod* method) const noexcept;
+
     /**
      * @brief Return the unique id value of the paint instance.
      *
index 6e7b738fe7b383ff9a6b584f5ea78f072bf2bd36..a303d2d3e30c7e123b2d28e7c6944f36c9e5aeb8 100644 (file)
@@ -77,7 +77,9 @@ struct SwShapeTask : SwTask
 
     void run(unsigned tid) override
     {
-        if (opacity == 0) return;  //Invisible
+        auto compMethod = CompositeMethod::None;
+        auto usedAsClip = (sdata->composite(nullptr, &compMethod) == Result::Success) && (compMethod == CompositeMethod::ClipPath);
+        if (opacity == 0 && !usedAsClip) return;  //Invisible
 
         uint8_t strokeAlpha = 0;
         auto visibleStroke = false;
@@ -99,7 +101,7 @@ struct SwShapeTask : SwTask
             sdata->fillColor(nullptr, nullptr, nullptr, &alpha);
             alpha = static_cast<uint8_t>(static_cast<uint32_t>(alpha) * opacity / 255);
             visibleFill = (alpha > 0 || sdata->fill());
-            if (visibleFill || visibleStroke) {
+            if (visibleFill || visibleStroke || usedAsClip) {
                 shapeReset(&shape);
                 if (!shapePrepare(&shape, sdata, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err;
             }
@@ -111,7 +113,7 @@ struct SwShapeTask : SwTask
 
         //Fill
         if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
-            if (visibleFill) {
+            if (visibleFill || usedAsClip) {
                 /* We assume that if stroke width is bigger than 2,
                    shape outline below stroke could be full covered by stroke drawing.
                    Thus it turns off antialising in that condition.
index 05b7078c3fa0a7cf4abbde0402d258d98c08289b..ba5b05005bd09c75a265078fd27351762e33b6ed 100644 (file)
@@ -385,6 +385,19 @@ CompositeMethod Paint::composite(const Paint** target) const noexcept
 }
 
 
+Result Paint::composite(const Paint** source, CompositeMethod* method) const noexcept
+{
+    if (source) *source = pImpl->compSource;
+    auto met = (pImpl->compSource && pImpl->compSource->pImpl->compData ?
+                pImpl->compSource->pImpl->compData->method : CompositeMethod::None);
+    if (method) *method = met;
+
+    if (pImpl->compSource != nullptr && met != CompositeMethod::None)
+        return Result::Success;
+    return Result::InsufficientCondition;
+}
+
+
 Result Paint::opacity(uint8_t o) noexcept
 {
     if (pImpl->opacity == o) return Result::Success;
index c54b97a367c5185822886d297d4276e223a679ee..a0bd3c9669c3e421958da629d84c7ee180c53225 100644 (file)
@@ -63,6 +63,7 @@ namespace tvg
         StrategyMethod* smethod = nullptr;
         RenderTransform* rTransform = nullptr;
         Composite* compData = nullptr;
+        Paint* compSource = nullptr;
         uint32_t renderFlag = RenderUpdateFlag::None;
         uint32_t ctxFlag = ContextFlag::Invalid;
         uint32_t id;
@@ -137,6 +138,7 @@ namespace tvg
                 if (!target && method == CompositeMethod::None) return true;
                 compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
             }
+            target->pImpl->compSource = source;
             compData->target = target;
             compData->source = source;
             compData->method = method;