/* * svg2poly.ulp * Jan 2013, By Cruz Monrreal II (Cruz.Monrreal@gmail.com) * * Imports Plain .svg file and will draw it as a set of polygons * For best results, follow GitHub instructions as closely as * possible. * * * NOTE: This is not a universal .svg converter. The spec is * simply too large, and the .ulp language is not robust * enough to create an entire .svg parser. * */ #usage "Import a Plain SVG file to a Polygon\n" "

NOTE: Polygons will automatically be centered about the current 'mark'

" "

Usage: run svg2poly [ -ratio num ] [ -layer name ] [ -outline thickness ]" "

Options:
" "" "" "" "" "
-ratio numscale SVG with the given ratio, default 1
-layer namechange layer that SVG is drawn on, default tDocu
-outline thickness draw an outline of the given size, default 0
" "

Example:" "

run svg2poly -ratio 2 -layer tDocu" "

This will import a Plain SVG file, scale it 2x, and draw it on the tDocu layer with no outline" "

" "" "" "" "" "
Cruz Monrreal
cruz.monrreal@gmail.com
http://anomalousmaker.com
" /* Inputs, Defaults */ string layer = "tNames"; real outline = 0.0005; real ratioX = 0.01, ratioY = 0.01; /* Globals */ string tmp[], master_xml; int poly_start[], global_pts=0, num_polys=0; real pts_x[], pts_y[]; real tmp_coords[]; real scaleFactor = 1.0; // SVG defined string file; // filename of SVG /* Output */ string cmd; /* * Stack imlemented to get around lack of recursion */ string stack = ""; /*** Stack Helper Functions ***/ void push(string s){ stack = (stack == "") ? s : stack + "|" + s; } string pull() { string tmp; if (stack == "") // Nothing in stack return ""; else if (strrstr(stack, "|") == -1){ // Stack only has one element tmp = stack; stack = ""; return tmp; } // Search for the last `|` in string // Return string past last `|` tmp = strsub(stack, strrstr(stack, "|") + 1); stack = strsub(stack, 0, strrstr(stack, "|")); return tmp; } /* * Encodes all necessary information into a single string * for stack-based recursion */ string pack(string xml, int global_pts) { string tmp; sprintf(tmp, "%s^%d", xml, global_pts); return tmp; } /*** Functions ***/ void print(string s) {printf("%s\n", s);} /* * Sets up the eagle commands for the script. */ void setup_cmd() { int i; // Search for parameters for(i=0; i= 0) { string scaleString = strsub(transform,scalePos+6); scaleFactor = strtod(strsub(scaleString,0, strlen(scaleString)-1)); // trim last char ")" } else { scaleFactor = 1.0; } printf("Scale factor = %f\n",scaleFactor); string svg_pts[]; int size = strsplit(svg_pts, pts, ' '), new_pts = 0; int i = 2; int mode; if(svg_pts[0] == "M"){ // Coords are Absolute mode = 1; sprintf(svg_pts[1], "%s,%s", svg_pts[1], svg_pts[2]); }else{ // Coords are Relative mode = 0; } poly_start[global_pts] = 1; // Path format: // m x,y x,y L X,Y l x,y .... z svgcoords_to_coords(svg_pts[1]); pts_x[global_pts] = tmp_coords[0] * scaleFactor; pts_y[global_pts] = tmp_coords[1] * scaleFactor; new_pts++; printf("%2d) %2.2f,%2.2f\n", num_polys, tmp_coords[0], tmp_coords[1]); while (i < size - 1){ if (svg_pts[i] == "m" || svg_pts[i] == "M") { if(svg_pts[i] == "M") { // Coords are Absolute mode = 1; sprintf(svg_pts[i], "%s,%s", svg_pts[i], svg_pts[i+1]); }else{ // Coords are Relative mode = 0; } svgcoords_to_coords(svg_pts[++i]); if(mode == 0){ pts_x[global_pts + new_pts] += tmp_coords[0] * scaleFactor; pts_y[global_pts + new_pts] += tmp_coords[1] * scaleFactor; }else{ pts_x[global_pts + new_pts] = tmp_coords[0] * scaleFactor; pts_y[global_pts + new_pts] = tmp_coords[1] * scaleFactor; i++; } new_pts++; } else if (svg_pts[i] == "L" ) { // Coords are Absolute, command is L mode = 1; } else if (svg_pts[i] == "l") { // Coords are Offset, command is l mode = 0; } else if (svg_pts[i] == "H") { // Coords are Absolute, command is H mode = 3; } else if (svg_pts[i] == "h") { // Coords are Offset, command is h mode = 2; } else if (svg_pts[i] == "V" ) { // Coords are Absolute, command is V mode = 5; } else if (svg_pts[i] == "v") { // Coords are Offset, command is v mode = 4; } // assume numerical coords if none of the above conditions are met else { if (mode == 1) { sprintf(svg_pts[i], "%s,%s", svg_pts[i], svg_pts[i+1]); } // Line-to command, parse coordinates from text if ((mode == 0) || (mode == 1)) { svgcoords_to_coords(svg_pts[i]); } // horizontal line, update X only else if ((mode == 2) || (mode == 3)) { mode -= 2; tmp_coords[0] = strtod(svg_pts[i]); } // vertical line, update Y only if ((mode == 4) || (mode == 5)) { mode -= 4; tmp_coords[1] = strtod(svg_pts[i]); } if (tmp_coords[0] == 0 && tmp_coords[1] == 0) { print("ERROR"); } else { poly_start[global_pts + new_pts] = 0; if (mode == 0) { pts_x[global_pts + new_pts] = pts_x[global_pts + new_pts - 1] + tmp_coords[0] * scaleFactor; pts_y[global_pts + new_pts] = pts_y[global_pts + new_pts - 1] + tmp_coords[1] * scaleFactor; } else if (mode == 1) { pts_x[global_pts + new_pts] = tmp_coords[0] * scaleFactor; pts_y[global_pts + new_pts] = tmp_coords[1] * scaleFactor; } printf(" %2.2f,%2.2f\n", pts_x[global_pts + new_pts], pts_y[global_pts + new_pts]); poly_start[global_pts + new_pts] = 0; new_pts++; } } i++; } // Close the polygon with the starting point svgcoords_to_coords(svg_pts[1]); pts_x[global_pts + new_pts] = tmp_coords[0] * scaleFactor; pts_y[global_pts + new_pts] = tmp_coords[1] * scaleFactor; new_pts++; global_pts += new_pts; num_polys++; } /* * Traverse through the tree of groups, adding points to paths, * while applying group transforms in the process */ void extract_nested_data() { string xml[]; string elements[]; string tags[]; int size; while(stack != ""){ // Pop xml to parse strsplit(xml, pull(), '^'); // Find name of root string tmp[], root; xmltags(tmp, xml[0], ""); root = tmp[0]; if (root == "path"){ // Path found print(" PATH " + xmlattribute(xml[0], "path", "id") + " FOUND "); extract_pts(xmlattribute(xml[0], "path", "d"), xmlattribute(xml[0], "path", "transform")); //}else if (root == ""){ // Add more cases here }else{ int a = xmltags(tags, xml[0], root); for(int i=0; i max_x) max_x = pts_x[i]; if (pts_y[i] < min_y) min_y = pts_y[i]; if (pts_y[i] > max_y) max_y = pts_y[i]; } real x_center = (max_x - min_x)/2, y_center = (max_y - min_y)/2; // Apply offsets to all points for(i=0; i < global_pts; i++){ pts_x[i] -= min_x + x_center; pts_y[i] -= min_y + y_center; } printf("\nObject origin:\n%f %f\n", x_center, y_center); // Generate eagle command for(i=0; i