From f5ede3588e4d31eb1d28486f4e6f7467876d9c07 Mon Sep 17 00:00:00 2001 From: Nikita Kitaev Date: Fri, 23 Oct 2009 22:51:12 -0700 Subject: [PATCH] Update Path Parser Parser now supports relative coordinates, as well as multiple sets of arguments after a single command. --- synfig-core/src/modules/mod_svg/svg_parser.cpp | 312 +++++++++++-------------- 1 file changed, 142 insertions(+), 170 deletions(-) diff --git a/synfig-core/src/modules/mod_svg/svg_parser.cpp b/synfig-core/src/modules/mod_svg/svg_parser.cpp index d062ab5..25f3e24 100644 --- a/synfig-core/src/modules/mod_svg/svg_parser.cpp +++ b/synfig-core/src/modules/mod_svg/svg_parser.cpp @@ -605,42 +605,68 @@ std::list > Svg_parser::parser_path_d(String path_d,Matrix* mtx){ std::list > k; std::list k1; + std::vector tokens=get_tokens_path(path_d); + String command="M"; //the current command float ax,ay,tgx,tgy,tgx2,tgy2;//each method - float actual_x=0,actual_y=0;//for relative methods; + ax=ay=0; + float actual_x=0,actual_y=0; //in svg coordinate space + float old_x=0,old_y=0; //needed in rare cases loop=false; - unsigned int i; - std::vector tokens=get_tokens_path(path_d); - for(i=0;ix,k1.back()->y,tgx,tgy); setSplit(k1.back(),TRUE); } - }else if(tokens.at(i).compare("Q")==0){ //absolute quadractic curve + }else if(command.compare("Q")==0 || command.compare("q")==0){ //quadractic curve //tg1 and tg2 - i++; tgx=ax=atof(tokens.at(i).data()); + tgx=actual_x+atof(tokens.at(i).data()); i++; if(tokens.at(i).compare(",")==0) i++; - tgy=ay=atof(tokens.at(i).data()); + tgy=actual_y+atof(tokens.at(i).data()); //point - i++; ax=atof(tokens.at(i).data()); + i++; actual_x+=atof(tokens.at(i).data()); i++; if(tokens.at(i).compare(",")==0) i++; - ay=atof(tokens.at(i).data()); - actual_x=ax; - actual_y=ay; + actual_y+=atof(tokens.at(i).data()); + + ax=actual_x; + ay=actual_y; //mtx if(mtx){ transformPoint2D(mtx,&ax,&ay); @@ -684,72 +711,14 @@ Svg_parser::parser_path_d(String path_d,Matrix* mtx){ setSplit(k1.back(),FALSE); k1.push_back(newVertice (ax,ay)); setTg1(k1.back(),k1.back()->x,k1.back()->y,tgx,tgy); - }else if(tokens.at(i).compare("L")==0){ //absolute line to + }else if(command.compare("L")==0 || command.compare("l")==0){ //line to //point - i++; ax=atof(tokens.at(i).data()); + actual_x+=atof(tokens.at(i).data()); i++; if(tokens.at(i).compare(",")==0) i++; - ay=atof(tokens.at(i).data()); - actual_x=ax; - actual_y=ay; - //mtx - if(mtx) transformPoint2D(mtx,&ax,&ay); - //adjust - coor2vect(&ax,&ay); - //save - setTg2(k1.back(),k1.back()->x,k1.back()->y,k1.back()->x,k1.back()->y); - if(isFirst(k1.front(),ax,ay)){ - setTg1(k1.front(),k1.front()->x,k1.front()->y,k1.front()->x,k1.front()->y); - }else{ - k1.push_back(newVertice(ax,ay)); - setTg1(k1.back(),k1.back()->x,k1.back()->y,k1.back()->x,k1.back()->y); - } - }else if(tokens.at(i).compare("l")==0){//relative line to - //point read - i++; ax=atof(tokens.at(i).data()); - i++; if(tokens.at(i).compare(",")==0) i++; - ay=atof(tokens.at(i).data()); - //relative - ax=actual_x+ax; - ay=actual_y+ay; - actual_x=ax; - actual_y=ay; - //mtx - if(mtx) transformPoint2D(mtx,&ax,&ay); - //adjust - coor2vect(&ax,&ay); - //save - setTg2(k1.back(),k1.back()->x,k1.back()->y,k1.back()->x,k1.back()->y); - if(isFirst(k1.front(),ax,ay)){ - setTg1(k1.front(),k1.front()->x,k1.front()->y,k1.front()->x,k1.front()->y); - }else{ - k1.push_back(newVertice(ax,ay)); - setTg1(k1.back(),k1.back()->x,k1.back()->y,k1.back()->x,k1.back()->y); - } - }else if(tokens.at(i).compare("H")==0){//absolute horizontal move - //the same that L but only Horizontal movement - //point - i++; ax=atof(tokens.at(i).data()); - ay=actual_y; - actual_x=ax; - actual_y=ay; - //mtx - if(mtx) transformPoint2D(mtx,&ax,&ay); - //adjust - coor2vect(&ax,&ay); - //save - setTg2(k1.back(),k1.back()->x,k1.back()->y,k1.back()->x,k1.back()->y); - if(isFirst(k1.front(),ax,ay)){ - setTg1(k1.front(),k1.front()->x,k1.front()->y,k1.front()->x,k1.front()->y); - }else{ - k1.push_back(newVertice(ax,ay)); - setTg1(k1.back(),k1.back()->x,k1.back()->y,k1.back()->x,k1.back()->y); - } - }else if(tokens.at(i).compare("h")==0){//horizontal relative - i++; ax=atof(tokens.at(i).data()); - ax=actual_x+ax; + actual_y+=atof(tokens.at(i).data()); + + ax=actual_x; ay=actual_y; - actual_x=ax; - actual_y=ay; //mtx if(mtx) transformPoint2D(mtx,&ax,&ay); //adjust @@ -762,12 +731,13 @@ Svg_parser::parser_path_d(String path_d,Matrix* mtx){ k1.push_back(newVertice(ax,ay)); setTg1(k1.back(),k1.back()->x,k1.back()->y,k1.back()->x,k1.back()->y); } - }else if(tokens.at(i).compare("V")==0){//vertical absolute + }else if(command.compare("H")==0 || command.compare("h")==0){// horizontal move + //the same that L but only Horizontal movement //point - i++; ay=atof(tokens.at(i).data()); + actual_x+=atof(tokens.at(i).data()); + ax=actual_x; - actual_x=ax; - actual_y=ay; + ay=old_y; //mtx if(mtx) transformPoint2D(mtx,&ax,&ay); //adjust @@ -780,13 +750,12 @@ Svg_parser::parser_path_d(String path_d,Matrix* mtx){ k1.push_back(newVertice(ax,ay)); setTg1(k1.back(),k1.back()->x,k1.back()->y,k1.back()->x,k1.back()->y); } - }else if(tokens.at(i).compare("v")==0){//relative + }else if(command.compare("V")==0 || command.compare("v")==0){//vertical //point - i++; ay=atof(tokens.at(i).data()); - ax=actual_x; - ay=actual_y+ay; - actual_x=ax; - actual_y=ay; + actual_y+=atof(tokens.at(i).data()); + + ax=old_x; + ay=actual_y; //mtx if(mtx) transformPoint2D(mtx,&ax,&ay); //adjust @@ -799,8 +768,11 @@ Svg_parser::parser_path_d(String path_d,Matrix* mtx){ k1.push_back(newVertice(ax,ay)); setTg1(k1.back(),k1.back()->x,k1.back()->y,k1.back()->x,k1.back()->y); } - }else if(tokens.at(i).compare("T")==0){// I don't know what does it - }else if(tokens.at(i).compare("A")==0){//elliptic arc + }else if(command.compare("T")==0 || command.compare("t")==0){// I don't know what does it + actual_x+=atof(tokens.at(i).data()); + i++; if(tokens.at(i).compare(",")==0) i++; + actual_y+=atof(tokens.at(i).data()); + }else if(command.compare("A")==0 || command.compare("a")==0){//elliptic arc //isn't complete support, is only for circles @@ -810,7 +782,7 @@ Svg_parser::parser_path_d(String path_d,Matrix* mtx){ float angle; bool sweep,large; //radio - i++; radio_x=atof(tokens.at(i).data()); + radio_x=atof(tokens.at(i).data()); i++; if(tokens.at(i).compare(",")==0) i++; radio_y=atof(tokens.at(i).data()); //angle @@ -819,18 +791,19 @@ Svg_parser::parser_path_d(String path_d,Matrix* mtx){ i++; large=atoi(tokens.at(i).data()); i++; sweep=atoi(tokens.at(i).data()); //point - i++; ax=atof(tokens.at(i).data()); + i++; actual_x+=atof(tokens.at(i).data()); i++; if(tokens.at(i).compare(",")==0) i++; - ay=atof(tokens.at(i).data()); + actual_y+=atof(tokens.at(i).data()); //how to draw? if(!large && !sweep){ //points - tgx2 = actual_x + radio_x*0.5; - tgy2 = actual_y ; - tgx = ax; - tgy = ay + radio_y*0.5; - actual_x=ax; - actual_y=ay; + tgx2 = old_x + radio_x*0.5; + tgy2 = old_y ; + tgx = actual_x; + tgy = actual_y + radio_y*0.5; + + ax=actual_x; + ay=actual_y; //transformations if(mtx){ transformPoint2D(mtx,&tgx2,&tgy2); @@ -852,12 +825,13 @@ Svg_parser::parser_path_d(String path_d,Matrix* mtx){ } }else if(!large && sweep){ //points - tgx2 = actual_x; - tgy2 = actual_y + radio_y*0.5; - tgx = ax + radio_x*0.5; - tgy = ay ; - actual_x=ax; - actual_y=ay; + tgx2 = old_x; + tgy2 = old_y + radio_y*0.5; + tgx = actual_x + radio_x*0.5; + tgy = actual_y ; + + ax=actual_x; + ay=actual_y; //transformations if(mtx){ transformPoint2D(mtx,&tgx2,&tgy2); @@ -880,65 +854,63 @@ Svg_parser::parser_path_d(String path_d,Matrix* mtx){ }else if( large && !sweep){//rare //this need more than one vertex }else if( large && sweep){//circles in inkscape are made with this kind of arc - if(actual_y==ay){//circles - //intermediate point - int sense=1; - if(actual_x>ax) sense =-1; - float in_x,in_y,in_tgx1,in_tgy1,in_tgx2,in_tgy2; - in_x = (actual_x+ax)/2; - in_y = actual_y - sense*radio_y; - in_tgx1 = in_x - sense*(radio_x*0.5); - in_tgx2 = in_x + sense*(radio_x*0.5); - in_tgy1 = in_y; - in_tgy2 = in_y; - //start/end points - tgx2=actual_x; - tgy2=ay - sense*(radio_y*0.5); - tgx =ax; - tgy =ay - sense*(radio_y*0.5); - - actual_x=ax; - actual_y=ay; - //transformations - if(mtx){ - transformPoint2D(mtx,&tgx2,&tgy2); - transformPoint2D(mtx,&tgx ,&tgy ); - transformPoint2D(mtx,&ax,&ay); - - transformPoint2D(mtx,&in_tgx2,&in_tgy2); - transformPoint2D(mtx,&in_tgx1,&in_tgy1); - transformPoint2D(mtx,&in_x,&in_y); - } - //adjust - coor2vect(&tgx2 , &tgy2); - coor2vect(&ax , &ay ); - coor2vect(&tgx , &tgy ); - - coor2vect(&in_tgx2 , &in_tgy2); - coor2vect(&in_tgx1 , &in_tgy1); - coor2vect(&in_x , &in_y ); - - //save the last tg2 - setTg2(k1.back(),k1.back()->x,k1.back()->y,tgx2,tgy2); - //save the intermediate point - k1.push_back(newVertice (in_x,in_y)); - setTg1(k1.back(),k1.back()->x,k1.back()->y, in_tgx1 , in_tgy1); - setTg2(k1.back(),k1.back()->x,k1.back()->y, in_tgx2 , in_tgy2); - setSplit(k1.back(),TRUE); //this could be changed - //save the new point - if(isFirst(k1.front(),ax,ay)){ - setTg1(k1.front(),k1.front()->x,k1.front()->y,tgx,tgy); - }else{ - k1.push_back(newVertice (ax,ay)); - setTg1(k1.back(),k1.back()->x,k1.back()->y,tgx,tgy); - setSplit(k1.back(),TRUE); - } + //intermediate point + int sense=1; + if(old_x>actual_x) sense =-1; + float in_x,in_y,in_tgx1,in_tgy1,in_tgx2,in_tgy2; + in_x = (old_x+actual_x)/2; + in_y = old_y - sense*radio_y; + in_tgx1 = in_x - sense*(radio_x*0.5); + in_tgx2 = in_x + sense*(radio_x*0.5); + in_tgy1 = in_y; + in_tgy2 = in_y; + //start/end points + tgx2=old_x; + tgy2=actual_y - sense*(radio_y*0.5); + tgx =actual_x; + tgy =actual_y - sense*(radio_y*0.5); + + ax=actual_x; + ay=actual_y; + //transformations + if(mtx){ + transformPoint2D(mtx,&tgx2,&tgy2); + transformPoint2D(mtx,&tgx ,&tgy ); + transformPoint2D(mtx,&ax,&ay); + + transformPoint2D(mtx,&in_tgx2,&in_tgy2); + transformPoint2D(mtx,&in_tgx1,&in_tgy1); + transformPoint2D(mtx,&in_x,&in_y); + } + //adjust + coor2vect(&tgx2 , &tgy2); + coor2vect(&ax , &ay ); + coor2vect(&tgx , &tgy ); + + coor2vect(&in_tgx2 , &in_tgy2); + coor2vect(&in_tgx1 , &in_tgy1); + coor2vect(&in_x , &in_y ); + + //save the last tg2 + setTg2(k1.back(),k1.back()->x,k1.back()->y,tgx2,tgy2); + //save the intermediate point + k1.push_back(newVertice (in_x,in_y)); + setTg1(k1.back(),k1.back()->x,k1.back()->y, in_tgx1 , in_tgy1); + setTg2(k1.back(),k1.back()->x,k1.back()->y, in_tgx2 , in_tgy2); + setSplit(k1.back(),TRUE); //this could be changed + //save the new point + if(isFirst(k1.front(),ax,ay)){ + setTg1(k1.front(),k1.front()->x,k1.front()->y,tgx,tgy); + }else{ + k1.push_back(newVertice (ax,ay)); + setTg1(k1.back(),k1.back()->x,k1.back()->y,tgx,tgy); + setSplit(k1.back(),TRUE); } } - }else if(tokens.at(i).compare("z")==0){ + }else if(command.compare("z")==0){ loop=true; }else{ - std::cout<<"don't supported: "<