Make SVG import parse 3-digit hex color values
[synfig.git] / synfig-core / src / modules / mod_svg / svg_parser.cpp
index 096afa6..1a35849 100644 (file)
@@ -279,18 +279,14 @@ Svg_parser::parser_graphics(const xmlpp::Node* node,xmlpp::Element* root,String
                        typeStroke=2;   //gradient
                }
                
-               xmlpp::Element* child_layer = nodeStartBasicLayer(root->add_child("layer"));
-               xmlpp::Element* child_fill = child_layer;
-               xmlpp::Element* child_stroke = child_layer;
-               if(typeFill==2){
-                       child_fill=nodeStartBasicLayer(child_fill->add_child("layer"));
-               }
-               if(typeStroke==2){
-                       child_stroke=nodeStartBasicLayer(child_stroke->add_child("layer"));
-               }
+               xmlpp::Element* child_layer = root;
+               xmlpp::Element* child_fill;
+               xmlpp::Element* child_stroke;
 
                //make simple fills
                if(nodename.compare("rect")==0 && typeFill!=0){
+                       if (mtx) child_layer = nodeStartBasicLayer(root->add_child("layer"), id);
+                       child_fill=child_layer;
                        parser_rect(nodeElement,child_fill,fill,fill_opacity,opacity);
                        if(typeFill==2){
                                build_fill (child_fill,fill,NULL);
@@ -298,7 +294,10 @@ Svg_parser::parser_graphics(const xmlpp::Node* node,xmlpp::Element* root,String
                        parser_effects(nodeElement,child_layer,parent_style,mtx);
                        return;
                }
-
+               if ((!(SVG_RESOLVE_BLINE) && mtx) || typeFill==2 || typeStroke==2)
+                       child_layer = nodeStartBasicLayer(root->add_child("layer"), id);
+               child_fill=child_layer;
+               child_stroke=child_layer;
 
                //=======================================================================
 
@@ -324,6 +323,9 @@ Svg_parser::parser_graphics(const xmlpp::Node* node,xmlpp::Element* root,String
                //int n = k.size();
 
                if(typeFill!=0){//region layer
+                       /*if(typeFill==2){
+                               child_fill=nodeStartBasicLayer(child_fill->add_child("layer"));
+                       }*/
                        for (aux = k.begin(); aux!=k.end(); aux++){
                                xmlpp::Element *child_region=child_fill->add_child("layer");
                                child_region->set_attribute("type","region");
@@ -353,6 +355,9 @@ Svg_parser::parser_graphics(const xmlpp::Node* node,xmlpp::Element* root,String
                }
 
                if(typeStroke!=0){//outline layer
+                       if(typeStroke==2){
+                               child_stroke=nodeStartBasicLayer(child_stroke->add_child("layer"),"stroke");
+                       }
                        for (aux=k.begin(); aux!=k.end(); aux++){
                                xmlpp::Element *child_outline=child_stroke->add_child("layer");
                                child_outline->set_attribute("type","outline");
@@ -390,17 +395,17 @@ Svg_parser::parser_graphics(const xmlpp::Node* node,xmlpp::Element* root,String
                        }
 
                        if(typeStroke==2){ //gradient in onto mode (stroke)
-                       if (SVG_RESOLVE_BLINE)
-                               build_fill(child_stroke,fill,mtx);
-                       else
-                               build_fill(child_stroke,fill,NULL);
-                       }
-                       if (SVG_RESOLVE_BLINE)
-                               parser_effects(nodeElement,child_layer,parent_style,NULL);
-                       else
-                               parser_effects(nodeElement,child_layer,parent_style,mtx);
-       
+                               if (SVG_RESOLVE_BLINE)
+                                       build_fill(child_stroke,stroke,mtx);
+                               else
+                                       build_fill(child_stroke,stroke,NULL);
+                       }       
                }
+
+               if (SVG_RESOLVE_BLINE)
+                       parser_effects(nodeElement,child_layer,parent_style,NULL);
+               else
+                       parser_effects(nodeElement,child_layer,parent_style,mtx);
        }
 }
 
@@ -848,7 +853,7 @@ Svg_parser::parser_path_d(String path_d,Matrix* mtx){
 /* === EFFECTS PARSERS ===================================================== */
 
 void
-Svg_parser::parser_effects(const xmlpp::Element* nodeElement,xmlpp::Element* root,String parent_style,Matrix* mtx){
+Svg_parser::parser_effects(const xmlpp::Element* /*nodeElement*/,xmlpp::Element* root,String /*parent_style*/,Matrix* mtx){
        build_transform(root, mtx);
 }
 
@@ -979,7 +984,7 @@ Svg_parser::build_linearGradient(xmlpp::Element* root,LinearGradient* data,Matri
 
                gradient->set_attribute("type","linear_gradient");
                gradient->set_attribute("active","true");
-               gradient->set_attribute("desc","Gradient004");
+               gradient->set_attribute("desc",data->name);
                build_param (gradient->add_child("param"),"z_depth","real","0");
                build_param (gradient->add_child("param"),"amount","real","1");
                //straight onto
@@ -1038,6 +1043,7 @@ Svg_parser::build_linearGradient(xmlpp::Element* root,LinearGradient* data,Matri
                //gradient link
                xmlpp::Element *child_stops=gradient->add_child("param");
                child_stops->set_attribute("name","gradient");
+               child_stops->set_attribute("guid",GUID::hasher(data->name).get_string());
                build_stop_color (child_stops->add_child("gradient"),data->stops);
                build_param (gradient->add_child("param"),"loop","bool","false");
                build_param (gradient->add_child("param"),"zigzag","bool","false");
@@ -1054,7 +1060,7 @@ Svg_parser::build_radialGradient(xmlpp::Element* root,RadialGradient* data,Matri
                        layer->set_attribute("type","PasteCanvas");
                        layer->set_attribute("active","true");
                        layer->set_attribute("version","0.1");
-                       layer->set_attribute("desc","Composite");
+                       layer->set_attribute("desc",data->name);
                        build_param (layer->add_child("param"),"z_depth","real","0");
                        build_param (layer->add_child("param"),"amount","real","1");
                        build_param (layer->add_child("param"),"blend_method","integer","21"); //straight onto
@@ -1064,6 +1070,7 @@ Svg_parser::build_radialGradient(xmlpp::Element* root,RadialGradient* data,Matri
                        xmlpp::Element* child_layer=child->add_child("canvas");
 
                        gradient=child_layer->add_child("layer");
+                       gradient->set_attribute("desc",data->name);
                        build_param (gradient->add_child("param"),"blend_method","integer","0"); //composite
                        Matrix *mtx2=NULL;
                        if (mtx && data->transform){
@@ -1077,6 +1084,7 @@ Svg_parser::build_radialGradient(xmlpp::Element* root,RadialGradient* data,Matri
                        
                }else {
                        gradient=root->add_child("layer");
+                       gradient->set_attribute("desc",data->name);
                        build_param (gradient->add_child("param"),"blend_method","integer","21"); //straight onto
                }               
 
@@ -1087,6 +1095,7 @@ Svg_parser::build_radialGradient(xmlpp::Element* root,RadialGradient* data,Matri
                //gradient link
                xmlpp::Element *child_stops=gradient->add_child("param");
                child_stops->set_attribute("name","gradient");
+               child_stops->set_attribute("guid",GUID::hasher(data->name).get_string());
                build_stop_color (child_stops->add_child("gradient"),data->stops);
 
                //here the center point and radius
@@ -1427,11 +1436,11 @@ Svg_parser::build_vector (xmlpp::Element* root,String name,float x,float y,Strin
 }
 
 xmlpp::Element*
-Svg_parser::nodeStartBasicLayer(xmlpp::Element* root){
+Svg_parser::nodeStartBasicLayer(xmlpp::Element* root, String name){
        root->set_attribute("type","PasteCanvas");
        root->set_attribute("active","true");
        root->set_attribute("version","0.1");
-       root->set_attribute("desc","Composite");
+       root->set_attribute("desc",name);
        build_param (root->add_child("param"),"z_depth","real","0");
        build_param (root->add_child("param"),"amount","real","1");
        build_param (root->add_child("param"),"blend_method","integer","0");
@@ -1632,9 +1641,9 @@ Svg_parser::newMatrix(float a,float b,float c,float d,float e,float f){
 Matrix*
 Svg_parser::newMatrix(const String mvector){
        if(!mvector.empty()){
-               Matrix* data=(Matrix*)malloc(sizeof(Matrix));
                std::vector<String> tokens=tokenize(mvector,",");
                if(tokens.size()!=6) return newMatrix(1,0,0,1,0,0);
+               Matrix* data=(Matrix*)malloc(sizeof(Matrix));
                data->a=atof(tokens.at(0).data());
                data->b=atof(tokens.at(1).data());
                data->c=atof(tokens.at(2).data());
@@ -1771,7 +1780,7 @@ Svg_parser::get_tokens_path(String path){ //mini path lexico-parser
                                        else if(a=='V'){ e=15; i++;}
                                        else if(a=='H'){ e=16; i++;}
                                        else if(a=='z' || a=='Z'){ e=17; i++;}
-                                       else if(a=='-' ||a=='.'|| isdigit (a)){ e=18;}
+                                       else if(a=='-' || a=='.' || a=='e' || a=='E' || isdigit (a)){ e=18;}
                                        else if(a==','){ e=19; i++;}
                                        else if(a==' '){i++;}
                                        break;
@@ -1795,7 +1804,7 @@ Svg_parser::get_tokens_path(String path){ //mini path lexico-parser
                        case 16: tokens.push_back("H"); e=0; break;
 
                        case 17: tokens.push_back("z"); e=0; break;//loop
-                       case 18: if(a=='-'||a=='.'|| isdigit (a)){
+                       case 18: if(a=='-' || a=='.' || a=='e' || a=='E' || isdigit (a)){
                                                buffer.append(path.substr(i,1));i++;
                                        }else{
                                                e=20;
@@ -1844,6 +1853,8 @@ Svg_parser::randomLetter(){
 int
 Svg_parser::getRed(String hex){
        if(hex.at(0)=='#'){
+               //allow for 3-digit hex codes (#rgb = #rrggbb)
+               if (hex.length()<7) return (16+1) * hextodec(hex.substr(1,1));
                return hextodec(hex.substr(1,2));
        }else if(hex.compare(0,3,"rgb")==0 || hex.compare(0,3,"RGB")==0){
                int start=hex.find_first_of("(")+1;
@@ -1856,6 +1867,7 @@ Svg_parser::getRed(String hex){
 int
 Svg_parser::getGreen(String hex){
        if(hex.at(0)=='#'){
+               if (hex.length()<7) return (16+1) * hextodec(hex.substr(2,1));
                return hextodec(hex.substr(3,2));
        }else if(hex.compare(0,3,"rgb")==0 || hex.compare(0,3,"RGB")==0){
                int start=hex.find_first_of("(")+1;
@@ -1868,6 +1880,7 @@ Svg_parser::getGreen(String hex){
 int
 Svg_parser::getBlue(String hex){
        if(hex.at(0)=='#'){
+               if (hex.length()<7) return (16+1) * hextodec(hex.substr(3,1));
                return hextodec(hex.substr(5,2));
        }else if(hex.compare(0,3,"rgb")==0 || hex.compare(0,3,"RGB")==0){
                int start=hex.find_first_of("(")+1;