@@ -743,10 +743,10 @@ static Matrix* _parseTransformationMatrix(const char* value)
743743 } else goto error;
744744 } else if (state == MatrixState::Rotate) {
745745 // Transform to signed.
746- points[0 ] = fmod (points[0 ], 360 );
747- if (points[0 ] < 0 ) points[0 ] += 360 ;
748- auto c = cosf (points[0 ] * (M_PI / 180.0 ));
749- auto s = sinf (points[0 ] * (M_PI / 180.0 ));
746+ points[0 ] = fmodf (points[0 ], 360 . 0f );
747+ if (points[0 ] < 0 ) points[0 ] += 360 . 0f ;
748+ auto c = cosf (points[0 ] * (MATH_PI / 180 .0f ));
749+ auto s = sinf (points[0 ] * (MATH_PI / 180 .0f ));
750750 if (ptCount == 1 ) {
751751 Matrix tmp = { c, -s, 0 , s, c, 0 , 0 , 0 , 1 };
752752 *matrix = mathMultiply (matrix, &tmp);
@@ -769,12 +769,12 @@ static Matrix* _parseTransformationMatrix(const char* value)
769769 *matrix = mathMultiply (matrix, &tmp);
770770 } else if (state == MatrixState::SkewX) {
771771 if (ptCount != 1 ) goto error;
772- auto deg = tanf (points[0 ] * (M_PI / 180.0 ));
772+ auto deg = tanf (points[0 ] * (MATH_PI / 180 .0f ));
773773 Matrix tmp = { 1 , deg, 0 , 0 , 1 , 0 , 0 , 0 , 1 };
774774 *matrix = mathMultiply (matrix, &tmp);
775775 } else if (state == MatrixState::SkewY) {
776776 if (ptCount != 1 ) goto error;
777- auto deg = tanf (points[0 ] * (M_PI / 180.0 ));
777+ auto deg = tanf (points[0 ] * (MATH_PI / 180 .0f ));
778778 Matrix tmp = { 1 , 0 , 0 , deg, 1 , 0 , 0 , 0 , 1 };
779779 *matrix = mathMultiply (matrix, &tmp);
780780 }
@@ -1919,6 +1919,19 @@ static SvgNode* _findNodeById(SvgNode *node, const char* id)
19191919}
19201920
19211921
1922+ static SvgNode* _findParentById (SvgNode* node, char * id, SvgNode* doc)
1923+ {
1924+ SvgNode *parent = node->parent ;
1925+ while (parent != nullptr && parent != doc) {
1926+ if (parent->id && !strcmp (parent->id , id)) {
1927+ return parent;
1928+ }
1929+ parent = parent->parent ;
1930+ }
1931+ return nullptr ;
1932+ }
1933+
1934+
19221935static constexpr struct
19231936{
19241937 const char * tag;
@@ -1959,8 +1972,12 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
19591972 defs = _getDefsNode (node);
19601973 nodeFrom = _findNodeById (defs, id);
19611974 if (nodeFrom) {
1962- _cloneNode (nodeFrom, node, 0 );
1963- if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom;
1975+ if (!_findParentById (node, id, loader->doc )) {
1976+ _cloneNode (nodeFrom, node, 0 );
1977+ if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom;
1978+ } else {
1979+ TVGLOG (" SVG" , " %s is ancestor element. This reference is invalid." , id);
1980+ }
19641981 free (id);
19651982 } else {
19661983 // some svg export software include <defs> element at the end of the file
@@ -2669,7 +2686,7 @@ static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgSty
26692686 if (to->transform ) memcpy (to->transform , from->transform , sizeof (Matrix));
26702687 }
26712688
2672- if (to->type == SvgGradientType::Linear && from-> type == SvgGradientType::Linear ) {
2689+ if (to->type == SvgGradientType::Linear) {
26732690 for (unsigned int i = 0 ; i < sizeof (linear_tags) / sizeof (linear_tags[0 ]); i++) {
26742691 bool coordSet = to->flags & linear_tags[i].flag ;
26752692 if (!(to->flags & linear_tags[i].flag ) && (from->flags & linear_tags[i].flag )) {
@@ -2686,7 +2703,7 @@ static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgSty
26862703 linear_tags[i].tagInheritedRecalc (loader, to->linear , to->userSpace );
26872704 }
26882705 }
2689- } else if (to->type == SvgGradientType::Radial && from-> type == SvgGradientType::Radial ) {
2706+ } else if (to->type == SvgGradientType::Radial) {
26902707 for (unsigned int i = 0 ; i < sizeof (radialTags) / sizeof (radialTags[0 ]); i++) {
26912708 bool coordSet = (to->flags & radialTags[i].flag );
26922709 if (!(to->flags & radialTags[i].flag ) && (from->flags & radialTags[i].flag )) {
@@ -2696,10 +2713,16 @@ static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgSty
26962713 // GradUnits not set directly, coord set
26972714 if (!gradUnitSet && coordSet) {
26982715 radialTags[i].tagRecalc (loader, to->radial , to->userSpace );
2716+ // If fx and fy are not set, set cx and cy.
2717+ if (!strcmp (radialTags[i].tag , " cx" ) && !(to->flags & SvgGradientFlags::Fx)) to->radial ->fx = to->radial ->cx ;
2718+ if (!strcmp (radialTags[i].tag , " cy" ) && !(to->flags & SvgGradientFlags::Fy)) to->radial ->fy = to->radial ->cy ;
26992719 }
27002720 // GradUnits set, coord not set directly
27012721 if (to->userSpace == from->userSpace ) continue ;
27022722 if (gradUnitSet && !coordSet) {
2723+ // If fx and fx are not set, do not call recalc.
2724+ if (!strcmp (radialTags[i].tag , " fx" ) && !(to->flags & SvgGradientFlags::Fx)) continue ;
2725+ if (!strcmp (radialTags[i].tag , " fy" ) && !(to->flags & SvgGradientFlags::Fy)) continue ;
27032726 radialTags[i].tagInheritedRecalc (loader, to->radial , to->userSpace );
27042727 }
27052728 }
@@ -3018,9 +3041,13 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
30183041 auto defs = _getDefsNode (nodeIdPair.node );
30193042 auto nodeFrom = _findNodeById (defs, nodeIdPair.id );
30203043 if (!nodeFrom) nodeFrom = _findNodeById (doc, nodeIdPair.id );
3021- _cloneNode (nodeFrom, nodeIdPair.node , 0 );
3022- if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node ->type == SvgNodeType::Use) {
3023- nodeIdPair.node ->node .use .symbol = nodeFrom;
3044+ if (!_findParentById (nodeIdPair.node , nodeIdPair.id , doc)) {
3045+ _cloneNode (nodeFrom, nodeIdPair.node , 0 );
3046+ if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node ->type == SvgNodeType::Use) {
3047+ nodeIdPair.node ->node .use .symbol = nodeFrom;
3048+ }
3049+ } else {
3050+ TVGLOG (" SVG" , " %s is ancestor element. This reference is invalid." , nodeIdPair.id );
30243051 }
30253052 free (nodeIdPair.id );
30263053 }
0 commit comments