mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-10 14:41:50 +00:00
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
This commit is contained in:
parent
02b3d7dd20
commit
c2ec997db5
3 changed files with 65 additions and 42 deletions
|
@ -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)
|
static void _handleClipPathAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
|
||||||
{
|
{
|
||||||
SvgStyleProperty* style = node->style;
|
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);
|
int len = strlen(value);
|
||||||
if (len >= 3 && !strncmp(value, "url", 3)) {
|
if (len >= 3 && !strncmp(value, "url", 3)) {
|
||||||
//FIXME: Support multiple composition.
|
if (style->clipPath.url) delete(style->clipPath.url);
|
||||||
if (style->comp.url) delete(style->comp.url);
|
style->clipPath.url = _idFromUrl((const char*)(value + 3));
|
||||||
style->comp.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)
|
static void _handleMaskAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
|
||||||
{
|
{
|
||||||
SvgStyleProperty* style = node->style;
|
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);
|
int len = strlen(value);
|
||||||
if (len >= 3 && !strncmp(value, "url", 3)) {
|
if (len >= 3 && !strncmp(value, "url", 3)) {
|
||||||
//FIXME: Support multiple composition.
|
if (style->mask.url) delete(style->mask.url);
|
||||||
if (style->comp.url) delete(style->comp.url);
|
style->mask.url = _idFromUrl((const char*)(value + 3));
|
||||||
style->comp.url = _idFromUrl((const char*)(value + 3));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1707,7 +1697,8 @@ static void _copyAttr(SvgNode* to, const SvgNode* from)
|
||||||
*to->style = *from->style;
|
*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->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->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
|
//Copy node attribute
|
||||||
switch (from->type) {
|
switch (from->type) {
|
||||||
|
@ -2598,9 +2589,13 @@ static void _updateGradient(SvgNode* node, Array<SvgStyleGradient*>* gradients)
|
||||||
|
|
||||||
static void _updateComposite(SvgNode* node, SvgNode* root)
|
static void _updateComposite(SvgNode* node, SvgNode* root)
|
||||||
{
|
{
|
||||||
if (node->style->comp.url && !node->style->comp.node) {
|
if (node->style->clipPath.url && !node->style->clipPath.node) {
|
||||||
SvgNode *findResult = _findNodeById(root, node->style->comp.url);
|
SvgNode *findResult = _findNodeById(root, node->style->clipPath.url);
|
||||||
if (findResult) node->style->comp.node = findResult;
|
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) {
|
if (node->child.count > 0) {
|
||||||
auto child = node->child.data;
|
auto child = node->child.data;
|
||||||
|
@ -2615,8 +2610,9 @@ static void _freeNodeStyle(SvgStyleProperty* style)
|
||||||
{
|
{
|
||||||
if (!style) return;
|
if (!style) return;
|
||||||
|
|
||||||
//style->comp.node has only the addresses of node. Therefore, style->comp.node is released from _freeNode.
|
//style->clipPath.node and style->mask.node has only the addresses of node. Therefore, node is released from _freeNode.
|
||||||
delete(style->comp.url);
|
delete(style->clipPath.url);
|
||||||
|
delete(style->mask.url);
|
||||||
|
|
||||||
if (style->fill.paint.gradient) delete(style->fill.paint.gradient);
|
if (style->fill.paint.gradient) delete(style->fill.paint.gradient);
|
||||||
if (style->stroke.paint.gradient) delete(style->stroke.paint.gradient);
|
if (style->stroke.paint.gradient) delete(style->stroke.paint.gradient);
|
||||||
|
|
|
@ -225,10 +225,9 @@ struct SvgRadialGradient
|
||||||
|
|
||||||
struct SvgComposite
|
struct SvgComposite
|
||||||
{
|
{
|
||||||
CompositeMethod method; //TODO: Currently support either one method
|
|
||||||
string *url;
|
string *url;
|
||||||
SvgNode* node;
|
SvgNode* node;
|
||||||
bool applying; //flag for checking circualr dependency.
|
bool applying; //flag for checking circular dependency.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SvgColor
|
struct SvgColor
|
||||||
|
@ -302,7 +301,8 @@ struct SvgStyleProperty
|
||||||
{
|
{
|
||||||
SvgStyleFill fill;
|
SvgStyleFill fill;
|
||||||
SvgStyleStroke stroke;
|
SvgStyleStroke stroke;
|
||||||
SvgComposite comp;
|
SvgComposite clipPath;
|
||||||
|
SvgComposite mask;
|
||||||
int opacity;
|
int opacity;
|
||||||
SvgColor color;
|
SvgColor color;
|
||||||
bool curColorSet;
|
bool curColorSet;
|
||||||
|
|
|
@ -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)
|
static void _applyComposition(Paint* paint, const SvgNode* node, float vx, float vy, float vw, float vh)
|
||||||
{
|
{
|
||||||
if (node->style->comp.method == CompositeMethod::None) return;
|
/* ClipPath */
|
||||||
|
/* Do not drop in Circular Dependency for ClipPath.
|
||||||
/* Do not drop in Circular Dependency.
|
|
||||||
Composition can be applied recursively if its children nodes have composition target to this one. */
|
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
|
#ifdef THORVG_LOG_ENABLED
|
||||||
printf("SVG: Multiple Composition Tried! Check out Circular dependency?\n");
|
printf("SVG: Multiple Composition Tried! Check out Circular dependency?\n");
|
||||||
#endif
|
#endif
|
||||||
return;
|
} else {
|
||||||
|
auto compNode = node->style->clipPath.node;
|
||||||
|
if (compNode && compNode->child.count > 0) {
|
||||||
|
node->style->clipPath.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::ClipPath);
|
||||||
|
|
||||||
|
node->style->clipPath.applying = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto compNode = node->style->comp.node;
|
/* Mask */
|
||||||
if (!compNode || compNode->child.count == 0) return;
|
/* 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;
|
||||||
|
|
||||||
node->style->comp.applying = true;
|
auto comp = Shape::gen();
|
||||||
|
comp->fill(255, 255, 255, 255);
|
||||||
|
if (node->transform) comp->transform(*node->transform);
|
||||||
|
|
||||||
auto comp = Shape::gen();
|
auto child = compNode->child.data;
|
||||||
comp->fill(255, 255, 255, 255);
|
auto valid = false; //Composite only when valid shapes are existed
|
||||||
if (node->transform) comp->transform(*node->transform);
|
|
||||||
|
|
||||||
auto child = compNode->child.data;
|
for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) {
|
||||||
auto valid = false; //Composite only when valid shapes are existed
|
if (_appendChildShape(*child, comp.get(), vx, vy, vw, vh)) valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) {
|
if (valid) paint->composite(move(comp), CompositeMethod::AlphaMask);
|
||||||
if (_appendChildShape(*child, comp.get(), vx, vy, vw, vh)) valid = true;
|
|
||||||
|
node->style->mask.applying = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid) paint->composite(move(comp), node->style->comp.method);
|
|
||||||
|
|
||||||
node->style->comp.applying = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue