svg_loader: allow both clipPath and mask together (#622)
authorMichal Maciola <71131832+mmaciola@users.noreply.github.com>
Wed, 21 Jul 2021 03:12:09 +0000 (05:12 +0200)
committerJunsuChoi <jsuya.choi@samsung.com>
Thu, 22 Jul 2021 08:24:22 +0000 (17:24 +0900)
* svg_loader: allow both clipPath and mask together

* svg_loader: allow both clipPath and mask together fix #1

Changed seperate functions _applyClipPathComposition and _applyMaskComposition into single function _applyComposition

src/loaders/svg/tvgSvgLoader.cpp
src/loaders/svg/tvgSvgLoaderCommon.h
src/loaders/svg/tvgSvgSceneBuilder.cpp

index 6db74f8..6a04447 100644 (file)
@@ -873,15 +873,10 @@ static void _handleTransformAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node
 static void _handleClipPathAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
 {
     SvgStyleProperty* style = node->style;
-#ifdef THORVG_LOG_ENABLED
-    if (style->comp.method != CompositeMethod::None) printf("SVG: Multiple Composition Tried!\n");
-#endif
-    style->comp.method = CompositeMethod::ClipPath;
     int len = strlen(value);
     if (len >= 3 && !strncmp(value, "url", 3)) {
-        //FIXME: Support multiple composition.
-        if (style->comp.url) delete(style->comp.url);
-        style->comp.url = _idFromUrl((const char*)(value + 3));
+        if (style->clipPath.url) delete(style->clipPath.url);
+        style->clipPath.url = _idFromUrl((const char*)(value + 3));
     }
 }
 
@@ -889,15 +884,10 @@ static void _handleClipPathAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node,
 static void _handleMaskAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
 {
     SvgStyleProperty* style = node->style;
-#ifdef THORVG_LOG_ENABLED
-    if (style->comp.method != CompositeMethod::None) printf("SVG: Multiple Composition Tried!\n");
-#endif
-    style->comp.method = CompositeMethod::AlphaMask;
     int len = strlen(value);
     if (len >= 3 && !strncmp(value, "url", 3)) {
-        //FIXME: Support multiple composition.
-        if (style->comp.url) delete(style->comp.url);
-        style->comp.url = _idFromUrl((const char*)(value + 3));
+        if (style->mask.url) delete(style->mask.url);
+        style->mask.url = _idFromUrl((const char*)(value + 3));
     }
 }
 
@@ -1707,7 +1697,8 @@ static void _copyAttr(SvgNode* to, const SvgNode* from)
     *to->style = *from->style;
     if (from->style->fill.paint.url) to->style->fill.paint.url = new string(from->style->fill.paint.url->c_str());
     if (from->style->stroke.paint.url) to->style->stroke.paint.url = new string(from->style->stroke.paint.url->c_str());
-    if (from->style->comp.url) to->style->comp.url = new string(from->style->comp.url->c_str());
+    if (from->style->clipPath.url) to->style->clipPath.url = new string(from->style->clipPath.url->c_str());
+    if (from->style->mask.url) to->style->mask.url = new string(from->style->mask.url->c_str());
 
     //Copy node attribute
     switch (from->type) {
@@ -2598,9 +2589,13 @@ static void _updateGradient(SvgNode* node, Array<SvgStyleGradient*>* gradients)
 
 static void _updateComposite(SvgNode* node, SvgNode* root)
 {
-    if (node->style->comp.url && !node->style->comp.node) {
-        SvgNode *findResult = _findNodeById(root, node->style->comp.url);
-        if (findResult) node->style->comp.node = findResult;
+    if (node->style->clipPath.url && !node->style->clipPath.node) {
+        SvgNode *findResult = _findNodeById(root, node->style->clipPath.url);
+        if (findResult) node->style->clipPath.node = findResult;
+    }
+    if (node->style->mask.url && !node->style->mask.node) {
+        SvgNode *findResult = _findNodeById(root, node->style->mask.url);
+        if (findResult) node->style->mask.node = findResult;
     }
     if (node->child.count > 0) {
         auto child = node->child.data;
@@ -2615,8 +2610,9 @@ static void _freeNodeStyle(SvgStyleProperty* style)
 {
     if (!style) return;
 
-    //style->comp.node has only the addresses of node. Therefore, style->comp.node is released from _freeNode.
-    delete(style->comp.url);
+    //style->clipPath.node and style->mask.node has only the addresses of node. Therefore, node is released from _freeNode.
+    delete(style->clipPath.url);
+    delete(style->mask.url);
 
     if (style->fill.paint.gradient) delete(style->fill.paint.gradient);
     if (style->stroke.paint.gradient) delete(style->stroke.paint.gradient);
index 35928ea..4a466f6 100644 (file)
@@ -225,10 +225,9 @@ struct SvgRadialGradient
 
 struct SvgComposite
 {
-    CompositeMethod method;     //TODO: Currently support either one method
     string *url;
     SvgNode* node;
-    bool applying;              //flag for checking circualr dependency.
+    bool applying;              //flag for checking circular dependency.
 };
 
 struct SvgColor
@@ -302,7 +301,8 @@ struct SvgStyleProperty
 {
     SvgStyleFill fill;
     SvgStyleStroke stroke;
-    SvgComposite comp;
+    SvgComposite clipPath;
+    SvgComposite mask;
     int opacity;
     SvgColor color;
     bool curColorSet;
index c2d608d..0c47ad3 100644 (file)
@@ -178,36 +178,63 @@ static bool _appendChildShape(SvgNode* node, Shape* shape, float vx, float vy, f
 
 static void _applyComposition(Paint* paint, const SvgNode* node, float vx, float vy, float vw, float vh)
 {
-    if (node->style->comp.method == CompositeMethod::None) return;
-
-    /* Do not drop in Circular Dependency.
+    /* ClipPath */
+    /* Do not drop in Circular Dependency for ClipPath.
        Composition can be applied recursively if its children nodes have composition target to this one. */
-    if (node->style->comp.applying) {
+    if (node->style->clipPath.applying) {
 #ifdef THORVG_LOG_ENABLED
     printf("SVG: Multiple Composition Tried! Check out Circular dependency?\n");
 #endif
-        return;
-    }
+    } else {
+        auto compNode = node->style->clipPath.node;
+        if (compNode && compNode->child.count > 0) {
+            node->style->clipPath.applying = true;
 
-    auto compNode = node->style->comp.node;
-    if (!compNode || compNode->child.count == 0) return;
+            auto comp = Shape::gen();
+            comp->fill(255, 255, 255, 255);
+            if (node->transform) comp->transform(*node->transform);
 
-    node->style->comp.applying = true;
+            auto child = compNode->child.data;
+            auto valid = false; //Composite only when valid shapes are existed
 
-    auto comp = Shape::gen();
-    comp->fill(255, 255, 255, 255);
-    if (node->transform) comp->transform(*node->transform);
+            for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) {
+                if (_appendChildShape(*child, comp.get(), vx, vy, vw, vh)) valid = true;
+            }
 
-    auto child = compNode->child.data;
-    auto valid = false;      //Composite only when valid shapes are existed
+            if (valid) paint->composite(move(comp), CompositeMethod::ClipPath);
 
-    for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) {
-        if (_appendChildShape(*child, comp.get(), vx, vy, vw, vh)) valid = true;
+            node->style->clipPath.applying = false;
+        }
     }
 
-    if (valid) paint->composite(move(comp), node->style->comp.method);
+    /* Mask */
+    /* Do not drop in Circular Dependency for Mask.
+       Composition can be applied recursively if its children nodes have composition target to this one. */
+    if (node->style->mask.applying) {
+#ifdef THORVG_LOG_ENABLED
+    printf("SVG: Multiple Composition Tried! Check out Circular dependency?\n");
+#endif
+    } else  {
+        auto compNode = node->style->mask.node;
+        if (compNode && compNode->child.count > 0) {
+            node->style->mask.applying = true;
+
+            auto comp = Shape::gen();
+            comp->fill(255, 255, 255, 255);
+            if (node->transform) comp->transform(*node->transform);
+
+            auto child = compNode->child.data;
+            auto valid = false; //Composite only when valid shapes are existed
+
+            for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) {
+                if (_appendChildShape(*child, comp.get(), vx, vy, vw, vh)) valid = true;
+            }
+
+            if (valid) paint->composite(move(comp), CompositeMethod::AlphaMask);
 
-    node->style->comp.applying = false;
+            node->style->mask.applying = false;
+        }
+    }
 }