Skip to content

Commit f128108

Browse files
committed
added offset for paths, for importing and exporting.
1 parent f7dc8a8 commit f128108

File tree

5 files changed

+282
-129
lines changed

5 files changed

+282
-129
lines changed

addons/ofxSvg/src/ofxSvg.cpp

Lines changed: 139 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,12 @@ void ofxSvg::_parseXmlNode( ofXml& aParentNode, vector< shared_ptr<ofxSvgElement
586586
shared_ptr<ofxSvgElement> ofxSvg::_addElementFromXmlNode( ofXml& tnode, vector< shared_ptr<ofxSvgElement> >& aElements ) {
587587
shared_ptr<ofxSvgElement> telement;
588588

589+
bool bHasMatOrTrans = false;
590+
591+
if(auto transAttr = tnode.getAttribute("transform") ) {
592+
bHasMatOrTrans = true;
593+
}
594+
589595
if( tnode.getName() == "use") {
590596
if( auto hrefAtt = tnode.getAttribute("xlink:href")) {
591597
ofLogVerbose("ofxSvg") << "found a use node with href " << hrefAtt.getValue();
@@ -635,47 +641,62 @@ shared_ptr<ofxSvgElement> ofxSvg::_addElementFromXmlNode( ofXml& tnode, vector<
635641

636642
} else if( tnode.getName() == "ellipse" ) {
637643
auto ellipse = std::make_shared<ofxSvgEllipse>();
638-
auto cxAttr = tnode.getAttribute("cx");
639644

640645
auto tpos = glm::vec2(0.f, 0.f);
646+
auto cxAttr = tnode.getAttribute("cx");
641647
if(cxAttr) {tpos.x = cxAttr.getFloatValue();}
642648
auto cyAttr = tnode.getAttribute("cy");
643649
if(cyAttr) {tpos.y = cyAttr.getFloatValue();}
644650

645-
ellipse->setPosition( tpos.x, tpos.y, 0.0f);
651+
if( bHasMatOrTrans ) {
652+
ellipse->setOffsetPathPosition(tpos.x,tpos.y);
653+
} else {
654+
ellipse->setPosition( tpos.x, tpos.y, 0.0f);
655+
}
656+
657+
glm::vec2 radii(0.f, 0.f);
646658

647-
auto rxAttr = tnode.getAttribute( "rx" );
648-
if(rxAttr) ellipse->radiusX = rxAttr.getFloatValue();
649-
auto ryAttr = tnode.getAttribute( "ry" );
650-
if(ryAttr) ellipse->radiusY = ryAttr.getFloatValue();
659+
if(auto rxAttr = tnode.getAttribute( "rx" )) {
660+
radii.x = rxAttr.getFloatValue();
661+
}
662+
if(auto ryAttr = tnode.getAttribute( "ry" )) {
663+
radii.y = ryAttr.getFloatValue();
664+
}
651665

652666
ellipse->path.setCircleResolution(mCircleResolution);
653667
ellipse->path.setCurveResolution(mCurveResolution);
654668
// make local so we can apply transform later in the function
655-
ellipse->path.ellipse({0.f,0.f}, ellipse->radiusX * 2.0f, ellipse->radiusY * 2.0f );
669+
// ellipse->path.ellipse({0.f,0.f}, ellipse->radiusX * 2.0f, ellipse->radiusY * 2.0f );
670+
ellipse->setRadius(radii.x, radii.y);
656671

657672
_applyStyleToPath( tnode, ellipse );
658673

659674
telement = ellipse;
660675
} else if( tnode.getName() == "circle" ) {
661676
auto circle = std::make_shared<ofxSvgCircle>();
662677
auto tpos = glm::vec2(0.f, 0.f);
678+
663679
if(auto cxAttr = tnode.getAttribute("cx")) {
664680
tpos.x = cxAttr.getFloatValue();
665681
}
666682
if(auto cyAttr = tnode.getAttribute("cy")) {
667683
tpos.y = cyAttr.getFloatValue();
668684
}
669-
circle->setPosition(tpos.x, tpos.y, 0.f);
670685

671-
auto rAttr = tnode.getAttribute( "r" );
672-
if(rAttr) circle->radius = rAttr.getFloatValue();
686+
if( bHasMatOrTrans ) {
687+
circle->setOffsetPathPosition(tpos.x,tpos.y);
688+
} else {
689+
circle->setPosition(tpos.x, tpos.y, 0.f);
690+
}
673691

674692
// make local so we can apply transform later in the function
675693
// position is from the top left
676694
circle->path.setCircleResolution(mCircleResolution);
677695
circle->path.setCurveResolution(mCurveResolution);
678-
circle->path.circle({0.f,0.f}, circle->radius );
696+
// circle->path.circle({0.f,0.f}, circle->radius );
697+
if(auto rAttr = tnode.getAttribute( "r" )) {
698+
circle->setRadius(rAttr.getFloatValue());
699+
}
679700

680701
_applyStyleToPath( tnode, circle );
681702

@@ -720,39 +741,54 @@ shared_ptr<ofxSvgElement> ofxSvg::_addElementFromXmlNode( ofXml& tnode, vector<
720741

721742
auto tpos = glm::vec2(0.f, 0.f);
722743
if(auto xattr = tnode.getAttribute("x")) {
723-
tpos.x = xattr.getFloatValue();
744+
tpos.x = xattr.getFloatValue();
724745
}
725746
if(auto yattr = tnode.getAttribute("y")) {
726-
tpos.y = yattr.getFloatValue();
747+
tpos.y = yattr.getFloatValue();
727748
}
728749
if(auto wattr = tnode.getAttribute("width")) {
729-
rect->width = wattr.getFloatValue();
750+
rect->width = wattr.getFloatValue();
730751
}
731752
if(auto hattr = tnode.getAttribute("height")) {
732-
rect->height = hattr.getFloatValue();
753+
rect->height = hattr.getFloatValue();
754+
}
755+
756+
if( bHasMatOrTrans ) {
757+
rect->setOffsetPathPosition(tpos.x,tpos.y);
758+
} else {
759+
rect->setPosition(tpos.x, tpos.y, 0.0f);
733760
}
734-
rect->setPosition(tpos.x, tpos.y, 0.0f);
735761

736762
auto rxAttr = tnode.getAttribute("rx");
737763
auto ryAttr = tnode.getAttribute("ry");
738764

739765
rect->path.setCircleResolution(mCircleResolution);
740766
rect->path.setCurveResolution(mCurveResolution);
741767

742-
// make local so we can apply transform later in the function
768+
float rRadius = 0.0f;
769+
743770
if( !ofxSvgCssClass::sIsNone(rxAttr.getValue()) || !ofxSvgCssClass::sIsNone(ryAttr.getValue())) {
744-
rect->roundRadius = -1.f; // force an update in setRoundRadius
745-
rect->setRoundRadius(std::max(ofxSvgCssClass::sGetFloat(rxAttr.getValue()),
746-
ofxSvgCssClass::sGetFloat(ryAttr.getValue()))
747-
);
748-
// rect->roundRadius = std::max(ofxSvgCssClass::sGetFloat(rxAttr.getValue()),
749-
// ofxSvgCssClass::sGetFloat(ryAttr.getValue()));
750-
751-
// rect->path.rectRounded(0.f, 0.f, rect->width, rect->height, rect->roundRadius);
752-
753-
} else {
754-
rect->path.rectangle(0.f, 0.f, rect->getWidth(), rect->getHeight());
755-
}
771+
rRadius = std::max(ofxSvgCssClass::sGetFloat(rxAttr.getValue()),
772+
ofxSvgCssClass::sGetFloat(ryAttr.getValue()));
773+
}
774+
rect->roundRadius = -1.f;
775+
rect->setRoundRadius(rRadius);
776+
777+
// // make local so we can apply transform later in the function
778+
// if( !ofxSvgCssClass::sIsNone(rxAttr.getValue()) || !ofxSvgCssClass::sIsNone(ryAttr.getValue())) {
779+
// rect->roundRadius = -1.f; // force an update in setRoundRadius
780+
// rect->setRoundRadius(std::max(ofxSvgCssClass::sGetFloat(rxAttr.getValue()),
781+
// ofxSvgCssClass::sGetFloat(ryAttr.getValue()))
782+
// );
783+
//// rect->roundRadius = std::max(ofxSvgCssClass::sGetFloat(rxAttr.getValue()),
784+
//// ofxSvgCssClass::sGetFloat(ryAttr.getValue()));
785+
////
786+
////
787+
//// rect->path.rectRounded(tpos.x, tpos.y, rect->width, rect->height, rect->roundRadius);
788+
//
789+
// } else {
790+
// rect->path.rectangle(tpos.x, tpos.y, rect->getWidth(), rect->getHeight());
791+
// }
756792

757793
telement = rect;
758794

@@ -887,6 +923,11 @@ shared_ptr<ofxSvgElement> ofxSvg::_addElementFromXmlNode( ofXml& tnode, vector<
887923
telement->layer = mCurrentLayer += 1.0;
888924
aElements.push_back( telement );
889925

926+
if( telement->getType() == OFXSVG_TYPE_RECTANGLE ) {
927+
auto rect = std::dynamic_pointer_cast<ofxSvgRectangle>( telement );
928+
ofLogNotice("ofxSvg::_addElementFromXmlNode") << "rect->pos: " << rect->getGlobalPosition() << " shape: " << rect->getOffsetPathPosition();
929+
}
930+
890931
if( mGroupStack.size() > 0 ) {
891932
auto pgroup = mGroupStack.back();
892933
ofLogVerbose("ofxSvg::_addElementFromXmlNode") << "element: " << telement->getTypeAsString() << " -" << telement->getCleanName() << "- pos: " << telement->getPosition() << "- parent: " << pgroup->getCleanName();
@@ -1878,7 +1919,7 @@ glm::mat4 ofxSvg::setTransformFromSvgMatrixString( string aStr, std::shared_ptr<
18781919
// gmat = glm::translate(gmat, glm::vec3(tp.x, tp.y, 0.0f));
18791920
// aele->pos.x = tp.x;
18801921
// aele->pos.y = tp.y;
1881-
// aele->setPosition(tp.x, tp.y, 0.0f);
1922+
aele->setPosition(tp.x, tp.y, 0.0f);
18821923
} else {
18831924
mat = glm::translate(glm::mat4(1.0f), glm::vec3(0.f, 0.f, 0.0f));
18841925
// gmat = glm::translate(gmat, glm::vec3(0.f, 0.f, 0.0f));
@@ -1938,7 +1979,7 @@ glm::mat4 ofxSvg::setTransformFromSvgMatrixString( string aStr, std::shared_ptr<
19381979
// pos3 = gmat * glm::vec4( aele->pos.x, aele->pos.y, 0.0f, 1.f );
19391980
// aele->pos.x = pos3.x;
19401981
// aele->pos.y = pos3.y;
1941-
aele->setPosition( pos3.x, pos3.y, 0.0f);
1982+
// aele->setPosition( pos3.x, pos3.y, 0.0f);
19421983

19431984
// aele
19441985

@@ -2045,13 +2086,15 @@ std::string ofxSvg::getSvgMatrixStringFromElement( std::shared_ptr<ofxSvgElement
20452086
// matrix(1 0 0 1 352.4516 349.0799)">
20462087

20472088
std::ostringstream matrixStream;
2048-
matrixStream << std::fixed << std::setprecision(6);
2089+
matrixStream << std::fixed << std::setprecision(1);
20492090
bool bFirst = true;
20502091

2051-
if( aele->getPosition().x != 0.f || aele->getPosition().y != 0.f ) {
2052-
bFirst = false;
2053-
matrixStream << "translate(" << aele->getPosition().x << "," << aele->getPosition().y << ")";
2054-
}
2092+
// if( aele->getType() != OFXSVG_TYPE_RECTANGLE && aele->getType() != OFXSVG_TYPE_CIRCLE && aele->getType() != OFXSVG_TYPE_ELLIPSE ) {
2093+
if( aele->getPosition().x != 0.f || aele->getPosition().y != 0.f ) {
2094+
bFirst = false;
2095+
matrixStream << "translate(" << aele->getPosition().x << "," << aele->getPosition().y << ")";
2096+
}
2097+
// }
20552098
if( aele->getRotationDeg() != 0.f ) {
20562099
if(!bFirst) {
20572100
matrixStream << " ";
@@ -2156,7 +2199,7 @@ void ofxSvg::_getTextSpanFromXmlNode( ofXml& anode, std::vector< std::shared_ptr
21562199

21572200
aspans.push_back(tspan);
21582201

2159-
_pushCssClass(tspan->getCss());
2202+
_pushCssClass(tspan->getCssClass());
21602203
for( auto& kid : anode.getChildren() ) {
21612204
if( kid ) {
21622205
if( kid.getName() == "tspan") {
@@ -2696,6 +2739,34 @@ void ofxSvg::_addCssClassFromImage( std::shared_ptr<ofxSvgImage> aSvgImage, ofXm
26962739
}
26972740
}
26982741

2742+
//--------------------------------------------------------------
2743+
void ofxSvg::_addCssClassFromTextSpan( std::shared_ptr<ofxSvgText::TextSpan> aSvgTextSpan, ofXml& anode ) {
2744+
2745+
auto textCss = aSvgTextSpan->getCssClass();
2746+
2747+
if( textCss.name.empty() ) {
2748+
textCss.name = "ts";
2749+
}
2750+
2751+
auto& tcss = mSvgCss.getAddClass(textCss);
2752+
2753+
if( auto xattr = anode.appendAttribute("class") ) {
2754+
xattr.set(tcss.name);
2755+
}
2756+
2757+
// if( !aSvgTextSpan->isVisible() ) {
2758+
// ofxSvgCssClass tcss;
2759+
// tcss.name = "st";
2760+
// tcss.addProperty("display", "none" );
2761+
//
2762+
// auto& addedClass = mSvgCss.getAddClass(tcss);
2763+
//
2764+
// if( auto xattr = anode.appendAttribute("class") ) {
2765+
// xattr.set(addedClass.name);
2766+
// }
2767+
// }
2768+
}
2769+
26992770
//--------------------------------------------------------------
27002771
bool ofxSvg::_toXml( ofXml& aParentNode, std::shared_ptr<ofxSvgElement> aele ) {
27012772
ofXml txml = aParentNode.appendChild( ofxSvgElement::sGetSvgXmlName(aele->getType()));
@@ -2718,10 +2789,12 @@ bool ofxSvg::_toXml( ofXml& aParentNode, std::shared_ptr<ofxSvgElement> aele ) {
27182789
_addCssClassFromPath( trect, txml );
27192790

27202791
if( auto xattr = txml.appendAttribute("x")) {
2721-
xattr.set(trect->getPosition().x);
2792+
// xattr.set(trect->getPosition().x);
2793+
xattr.set(trect->getOffsetPathPosition().x);
27222794
}
27232795
if( auto xattr = txml.appendAttribute("y")) {
2724-
xattr.set(trect->getPosition().y);
2796+
// xattr.set(trect->getPosition().y);
2797+
xattr.set(trect->getOffsetPathPosition().y);
27252798
}
27262799
if( auto xattr = txml.appendAttribute("width")) {
27272800
xattr.set(trect->getWidth());
@@ -2784,10 +2857,10 @@ bool ofxSvg::_toXml( ofXml& aParentNode, std::shared_ptr<ofxSvgElement> aele ) {
27842857
_addCssClassFromPath( tellipse, txml );
27852858

27862859
if( auto xattr = txml.appendAttribute("cx")) {
2787-
xattr.set(tellipse->getPosition().x);
2860+
xattr.set(tellipse->getOffsetPathPosition().x);
27882861
}
27892862
if( auto xattr = txml.appendAttribute("cy")) {
2790-
xattr.set(tellipse->getPosition().y);
2863+
xattr.set(tellipse->getOffsetPathPosition().y);
27912864
}
27922865
if( auto xattr = txml.appendAttribute("rx")) {
27932866
xattr.set(tellipse->radiusX);
@@ -2801,10 +2874,10 @@ bool ofxSvg::_toXml( ofXml& aParentNode, std::shared_ptr<ofxSvgElement> aele ) {
28012874
_addCssClassFromPath( tcircle, txml );
28022875

28032876
if( auto xattr = txml.appendAttribute("cx")) {
2804-
xattr.set(tcircle->getPosition().x);
2877+
xattr.set(tcircle->getOffsetPathPosition().x);
28052878
}
28062879
if( auto xattr = txml.appendAttribute("cy")) {
2807-
xattr.set(tcircle->getPosition().y);
2880+
xattr.set(tcircle->getOffsetPathPosition().y);
28082881
}
28092882
if( auto xattr = txml.appendAttribute("r")) {
28102883
xattr.set(tcircle->getRadius());
@@ -2887,14 +2960,33 @@ bool ofxSvg::_toXml( ofXml& aParentNode, std::shared_ptr<ofxSvgElement> aele ) {
28872960

28882961
} else if( aele->getType() == OFXSVG_TYPE_TEXT ) {
28892962
// TODO: Maybe at some point ;/
2963+
auto ttext = std::dynamic_pointer_cast<ofxSvgText>(aele);
2964+
for( auto tspan : ttext->textSpans ) {
2965+
if( auto spanXml = txml.appendChild("tspan")) {
2966+
if( auto xattr = spanXml.appendAttribute("x")) {
2967+
xattr.set(tspan->rect.x);
2968+
}
2969+
if( auto yattr = spanXml.appendAttribute("y")) {
2970+
yattr.set(tspan->rect.y);
2971+
}
2972+
spanXml.set(tspan->getText());
2973+
_addCssClassFromTextSpan( tspan, spanXml );
2974+
}
2975+
}
28902976
}
28912977

28922978
// figure out if we need a transform attribute
2893-
if( aele->getType() == OFXSVG_TYPE_IMAGE || aele->getRotationDeg() != 0.0f || aele->getScale().x != 1.0f || aele->getScale().y != 1.0f ) {
2894-
if( auto xattr = txml.appendAttribute("transform")) {
2895-
xattr.set( getSvgMatrixStringFromElement(aele) );
2979+
// if( aele->getType() == OFXSVG_TYPE_IMAGE || aele->getRotationDeg() != 0.0f || aele->getScale().x != 1.0f || aele->getScale().y != 1.0f ) {
2980+
auto matrixString = getSvgMatrixStringFromElement(aele);
2981+
if( !matrixString.empty() ) {
2982+
if( auto xattr = txml.appendAttribute("transform")) {
2983+
xattr.set(matrixString);
2984+
}
28962985
}
2897-
}
2986+
// if( auto xattr = txml.appendAttribute("transform")) {
2987+
// xattr.set( getSvgMatrixStringFromElement(aele) );
2988+
// }
2989+
// }
28982990
return txml;
28992991
}
29002992

addons/ofxSvg/src/ofxSvg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ class ofxSvg : public ofxSvgGroup {
251251
ofxSvgCssClass& _addCssClassFromPath( std::shared_ptr<ofxSvgPath> aSvgPath );
252252
void _addCssClassFromPath( std::shared_ptr<ofxSvgPath> aSvgPath, ofXml& anode );
253253
void _addCssClassFromImage( std::shared_ptr<ofxSvgImage> aSvgImage, ofXml& anode );
254+
void _addCssClassFromTextSpan( std::shared_ptr<ofxSvgText::TextSpan> aSvgTextSpan, ofXml& anode );
254255
bool _toXml( ofXml& aParentNode, std::shared_ptr<ofxSvgElement> aele );
255256

256257
void _pushCssClass( const ofxSvgCssClass& acss );

0 commit comments

Comments
 (0)