mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-13 19:44:28 +00:00
svg_loader: postponed nodes properly cloned
In case when no defs tag was used, no child node was found. Also the node attributes should not override those set in the ancestor.
This commit is contained in:
parent
f0141e63de
commit
6fb0984b49
1 changed files with 116 additions and 57 deletions
|
@ -1745,6 +1745,112 @@ error_grad_alloc:
|
|||
}
|
||||
|
||||
|
||||
static void _styleInherit(SvgStyleProperty* child, const SvgStyleProperty* parent)
|
||||
{
|
||||
if (parent == nullptr) return;
|
||||
//Inherit the property of parent if not present in child.
|
||||
if (!child->curColorSet) {
|
||||
child->color = parent->color;
|
||||
child->curColorSet = parent->curColorSet;
|
||||
}
|
||||
//Fill
|
||||
if (!((int)child->fill.flags & (int)SvgFillFlags::Paint)) {
|
||||
child->fill.paint.color = parent->fill.paint.color;
|
||||
child->fill.paint.none = parent->fill.paint.none;
|
||||
child->fill.paint.curColor = parent->fill.paint.curColor;
|
||||
if (parent->fill.paint.url) child->fill.paint.url = _copyId(parent->fill.paint.url);
|
||||
}
|
||||
if (!((int)child->fill.flags & (int)SvgFillFlags::Opacity)) {
|
||||
child->fill.opacity = parent->fill.opacity;
|
||||
}
|
||||
if (!((int)child->fill.flags & (int)SvgFillFlags::FillRule)) {
|
||||
child->fill.fillRule = parent->fill.fillRule;
|
||||
}
|
||||
//Stroke
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Paint)) {
|
||||
child->stroke.paint.color = parent->stroke.paint.color;
|
||||
child->stroke.paint.none = parent->stroke.paint.none;
|
||||
child->stroke.paint.curColor = parent->stroke.paint.curColor;
|
||||
child->stroke.paint.url = parent->stroke.paint.url ? _copyId(parent->stroke.paint.url) : nullptr;
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Opacity)) {
|
||||
child->stroke.opacity = parent->stroke.opacity;
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Width)) {
|
||||
child->stroke.width = parent->stroke.width;
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Dash)) {
|
||||
if (parent->stroke.dash.array.count > 0) {
|
||||
child->stroke.dash.array.clear();
|
||||
child->stroke.dash.array.reserve(parent->stroke.dash.array.count);
|
||||
for (uint32_t i = 0; i < parent->stroke.dash.array.count; ++i) {
|
||||
child->stroke.dash.array.push(parent->stroke.dash.array.data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Cap)) {
|
||||
child->stroke.cap = parent->stroke.cap;
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Join)) {
|
||||
child->stroke.join = parent->stroke.join;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _styleCopy(SvgStyleProperty* to, const SvgStyleProperty* from)
|
||||
{
|
||||
if (from == nullptr) return;
|
||||
//Copy the properties of 'from' only if they were explicitly set (not the default ones).
|
||||
if (from->curColorSet) {
|
||||
to->color = from->color;
|
||||
to->curColorSet = true;
|
||||
}
|
||||
//Fill
|
||||
to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)from->fill.flags);
|
||||
if (((int)from->fill.flags & (int)SvgFillFlags::Paint)) {
|
||||
to->fill.paint.color = from->fill.paint.color;
|
||||
to->fill.paint.none = from->fill.paint.none;
|
||||
to->fill.paint.curColor = from->fill.paint.curColor;
|
||||
if (from->fill.paint.url) to->fill.paint.url = _copyId(from->fill.paint.url);
|
||||
}
|
||||
if (((int)from->fill.flags & (int)SvgFillFlags::Opacity)) {
|
||||
to->fill.opacity = from->fill.opacity;
|
||||
}
|
||||
if (((int)from->fill.flags & (int)SvgFillFlags::FillRule)) {
|
||||
to->fill.fillRule = from->fill.fillRule;
|
||||
}
|
||||
//Stroke
|
||||
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)from->stroke.flags);
|
||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Paint)) {
|
||||
to->stroke.paint.color = from->stroke.paint.color;
|
||||
to->stroke.paint.none = from->stroke.paint.none;
|
||||
to->stroke.paint.curColor = from->stroke.paint.curColor;
|
||||
to->stroke.paint.url = from->stroke.paint.url ? _copyId(from->stroke.paint.url) : nullptr;
|
||||
}
|
||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Opacity)) {
|
||||
to->stroke.opacity = from->stroke.opacity;
|
||||
}
|
||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Width)) {
|
||||
to->stroke.width = from->stroke.width;
|
||||
}
|
||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Dash)) {
|
||||
if (from->stroke.dash.array.count > 0) {
|
||||
to->stroke.dash.array.clear();
|
||||
to->stroke.dash.array.reserve(from->stroke.dash.array.count);
|
||||
for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
|
||||
to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Cap)) {
|
||||
to->stroke.cap = from->stroke.cap;
|
||||
}
|
||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Join)) {
|
||||
to->stroke.join = from->stroke.join;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _copyAttr(SvgNode* to, const SvgNode* from)
|
||||
{
|
||||
//Copy matrix attribute
|
||||
|
@ -1753,7 +1859,8 @@ static void _copyAttr(SvgNode* to, const SvgNode* from)
|
|||
if (to->transform) *to->transform = *from->transform;
|
||||
}
|
||||
//Copy style attribute
|
||||
*to->style = *from->style;
|
||||
_styleCopy(to->style, from->style);
|
||||
to->style->flags = (SvgStyleFlags)((int)to->style->flags | (int)from->style->flags);
|
||||
if (from->style->fill.paint.url) to->style->fill.paint.url = strdup(from->style->fill.paint.url);
|
||||
if (from->style->stroke.paint.url) to->style->stroke.paint.url = strdup(from->style->stroke.paint.url);
|
||||
if (from->style->clipPath.url) to->style->clipPath.url = strdup(from->style->clipPath.url);
|
||||
|
@ -1829,9 +1936,9 @@ static void _cloneNode(SvgNode* from, SvgNode* parent)
|
|||
if (!from || !parent) return;
|
||||
|
||||
newNode = _createNode(parent, from->type);
|
||||
|
||||
if (!newNode) return;
|
||||
|
||||
_styleInherit(newNode->style, parent->style);
|
||||
_copyAttr(newNode, from);
|
||||
|
||||
auto child = from->child.data;
|
||||
|
@ -1841,16 +1948,19 @@ static void _cloneNode(SvgNode* from, SvgNode* parent)
|
|||
}
|
||||
|
||||
|
||||
static void _postponeCloneNode(SvgLoaderData* loader, SvgNode *node, char* id) {
|
||||
static void _postponeCloneNode(SvgLoaderData* loader, SvgNode *node, char* id)
|
||||
{
|
||||
loader->cloneNodes.push({node, id});
|
||||
}
|
||||
|
||||
|
||||
static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes) {
|
||||
static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
|
||||
{
|
||||
for (uint32_t i = 0; i < cloneNodes->count; ++i) {
|
||||
auto nodeIdPair = cloneNodes->data[i];
|
||||
auto defs = _getDefsNode(nodeIdPair.node);
|
||||
auto nodeFrom = _findChildById(defs, nodeIdPair.id);
|
||||
if (!nodeFrom) nodeFrom = _findChildById(doc, nodeIdPair.id);
|
||||
_cloneNode(nodeFrom, nodeIdPair.node);
|
||||
free(nodeIdPair.id);
|
||||
}
|
||||
|
@ -2508,59 +2618,8 @@ static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content
|
|||
}
|
||||
|
||||
|
||||
static void _styleInherit(SvgStyleProperty* child, const SvgStyleProperty* parent)
|
||||
static void _inefficientNodeCheck(TVG_UNUSED SvgNode* node)
|
||||
{
|
||||
if (parent == nullptr) return;
|
||||
//Inherit the property of parent if not present in child.
|
||||
if (!child->curColorSet) {
|
||||
child->color = parent->color;
|
||||
child->curColorSet = parent->curColorSet;
|
||||
}
|
||||
//Fill
|
||||
if (!((int)child->fill.flags & (int)SvgFillFlags::Paint)) {
|
||||
child->fill.paint.color = parent->fill.paint.color;
|
||||
child->fill.paint.none = parent->fill.paint.none;
|
||||
child->fill.paint.curColor = parent->fill.paint.curColor;
|
||||
if (parent->fill.paint.url) child->fill.paint.url = _copyId(parent->fill.paint.url);
|
||||
}
|
||||
if (!((int)child->fill.flags & (int)SvgFillFlags::Opacity)) {
|
||||
child->fill.opacity = parent->fill.opacity;
|
||||
}
|
||||
if (!((int)child->fill.flags & (int)SvgFillFlags::FillRule)) {
|
||||
child->fill.fillRule = parent->fill.fillRule;
|
||||
}
|
||||
//Stroke
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Paint)) {
|
||||
child->stroke.paint.color = parent->stroke.paint.color;
|
||||
child->stroke.paint.none = parent->stroke.paint.none;
|
||||
child->stroke.paint.curColor = parent->stroke.paint.curColor;
|
||||
child->stroke.paint.url = parent->stroke.paint.url ? _copyId(parent->stroke.paint.url) : nullptr;
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Opacity)) {
|
||||
child->stroke.opacity = parent->stroke.opacity;
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Width)) {
|
||||
child->stroke.width = parent->stroke.width;
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Dash)) {
|
||||
if (parent->stroke.dash.array.count > 0) {
|
||||
child->stroke.dash.array.clear();
|
||||
child->stroke.dash.array.reserve(parent->stroke.dash.array.count);
|
||||
for (uint32_t i = 0; i < parent->stroke.dash.array.count; ++i) {
|
||||
child->stroke.dash.array.push(parent->stroke.dash.array.data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Cap)) {
|
||||
child->stroke.cap = parent->stroke.cap;
|
||||
}
|
||||
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Join)) {
|
||||
child->stroke.join = parent->stroke.join;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _inefficientNodeCheck(TVG_UNUSED SvgNode* node){
|
||||
#ifdef THORVG_LOG_ENABLED
|
||||
auto type = simpleXmlNodeTypeToString(node->type);
|
||||
|
||||
|
@ -2857,7 +2916,7 @@ void SvgLoader::run(unsigned tid)
|
|||
_updateComposite(loaderData.doc, loaderData.doc);
|
||||
if (defs) _updateComposite(loaderData.doc, defs);
|
||||
|
||||
if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes);
|
||||
if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes, loaderData.doc);
|
||||
|
||||
if (loaderData.gradients.count > 0) _updateGradient(loaderData.doc, &loaderData.gradients);
|
||||
if (defs) _updateGradient(loaderData.doc, &defs->node.defs.gradients);
|
||||
|
|
Loading…
Add table
Reference in a new issue