From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Wed, 21 Jul 2021 03:12:09 +0000 (+0200) Subject: svg_loader: allow both clipPath and mask together (#622) X-Git-Tag: accepted/tizen/unified/20210727.124506~18 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dcb91b2dc3ed98136bef1f67a5c70da74a453684;p=platform%2Fcore%2Fgraphics%2Ftizenvg.git svg_loader: allow both clipPath and mask together (#622) * 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 --- diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 6db74f8..6a04447 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -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* 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); diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index 35928ea..4a466f6 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -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; diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index c2d608d..0c47ad3 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -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; + } + } }