Browse Source

started implementing svg parsing: implemented rect, line, polyline, polygon parsing, created circle, ellipse stubs, begun implementation of path parsing

Vincenz Mechler 5 years ago
parent
commit
e50cdc5fa8

+ 502 - 0
SketchAssistant/SketchAssistant/FileImporter.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Drawing;
+using System.Globalization;
 using System.Linq;
 using System.Text;
 using System.Text.RegularExpressions;
@@ -16,6 +17,21 @@ namespace SketchAssistant
         /// </summary>
         Form1 program;
 
+        /// <summary>
+        /// scale factor for coordinates of svg file
+        /// </summary>
+        double scale;
+
+        /// <summary>
+        /// line pointer for the current svg document
+        /// </summary>
+        int i;
+
+        /// <summary>
+        /// array containing all characters interpreted as whitespaces which seperate words/tokens in the input file
+        /// </summary>
+        readonly char[] whitespaces = new char[] { ' ' , ',' };
+
         public FileImporter(Form1 newProgram)
         {
             program = newProgram;
@@ -151,5 +167,491 @@ namespace SketchAssistant
             return ParseISADInput(allLines);
         }
 
+        /// <summary>
+        /// parses a svg drawing, given as a .svg file
+        /// </summary>
+        /// <param name="fileName">the path of the input file</param>
+        /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
+        public (int, int, List<Line>) ParseSVGInputFile(String fileName, int windowWidth, int windowHeight)
+        {
+            return ParseSVGInput(System.IO.File.ReadAllLines(fileName), windowWidth, windowHeight);
+        }
+
+        /// <summary>
+        /// parses a svg drawing, given as the content of a .svg file, seperated into lines
+        /// </summary>
+        /// <param name="allLines">an array holding all lines of the input file</param>
+        /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
+        private (int, int, List<Line>) ParseSVGInput(String[] allLines, double windowWidth, double windowHeight)
+        {
+            i = 0; //reset line pointer
+            if (allLines.Length == 0) //check for empty file
+            {
+                throw new FileImporterException("file is empty", "", -1);
+            }
+            (int, int) sizedef = ParseSVGHeader(allLines); //parse svg file header and get internal coordinate range
+            i++;
+            int width; //width of the resulting picture in pixels
+            int height; //height of the resulting picture in pixels
+            if (windowWidth / windowHeight > sizedef.Item1 / sizedef.Item2) //height dominant, width has to be smaller than drawing window to preserve xy-scale
+            {
+                scale = windowHeight / sizedef.Item2;
+                Console.WriteLine("scale: (heights) " + windowHeight + "/" + sizedef.Item2);
+                Console.WriteLine("widths: " + windowWidth + "/" + sizedef.Item1);
+                height = (int)Math.Round(windowHeight);
+                width = (int) Math.Round(scale * sizedef.Item1);
+                Console.WriteLine(width + "x" + height + " (" + scale + ")");
+            }
+            else //width dominant, height has to be smaller than drawing window to preserve xy-scale
+            {
+                scale = windowWidth / sizedef.Item1;
+                Console.WriteLine("scale: (widths) " + windowWidth + "/" + sizedef.Item1);
+                Console.WriteLine("heights: " + windowHeight + "/" + sizedef.Item2);
+                width = (int)Math.Round(windowWidth);
+                height = (int)Math.Round(scale * sizedef.Item2);
+                Console.WriteLine(width + "x" + height + " (" + scale + ")");
+            }
+            for(int j=0; j < allLines.Length; j++)
+            {
+                allLines[j] = allLines[j].Trim(whitespaces);
+            }
+            List<Line> picture = ParseSVGBody(allLines); //parse whole svg drawing into list of lines
+            return (width, height, picture);
+        }
+
+        /// <summary>
+        /// parses the svg file header and returns the internal coordinate range of this drawing, and iterates i to point to the start of svg element definitions
+        /// </summary>
+        /// <param name="allLines">an array holding all lines of the input file</param>
+        /// <returns>the internal coordinate range of this drawing</returns>
+        private (int, int) ParseSVGHeader(String[] allLines)
+        {
+            while (!allLines[i].StartsWith("<svg")) //skip non-relevant metadata at start of svg file
+            {
+                i++;
+            }
+            String[] currentLine = allLines[i].Split(' ');
+            int width= -1;
+            int height= -1;
+            for(int j= 0; j < currentLine.Length; j++)
+            {
+                if (currentLine[j].StartsWith("width"))
+                {
+                    width = Convert.ToInt32(ParseSingleSVGAttribute(currentLine[j]));
+                }
+                else if (currentLine[j].StartsWith("height"))
+                {
+                    height = Convert.ToInt32(ParseSingleSVGAttribute(currentLine[j]));
+                }
+            }
+            if(width == -1)
+            {
+                throw new FileImporterException("missing width definition in SVG header", "the header should contain the \"width=...\" attribute", i+1);
+            }
+            if (height == -1)
+            {
+                throw new FileImporterException("missing height definition in SVG header", "the header should contain the \"height=...\" attribute", i + 1);
+            }
+            return (width, height);
+        }
+
+        /// <summary>
+        /// parses all relevant svg element definitions and skips the ones not representable by the sketch assistant
+        /// </summary>
+        /// <param name="allLines">an array holding all lines of the input file</param>
+        /// <returns>the parsed picture as a list of lines</returns>
+        private List<Line> ParseSVGBody(String[] allLines)
+        {
+            List<Line> picture = new List<Line>();
+            while (!allLines[i].StartsWith("</svg"))
+            {
+                List<Line> element = ParseSingleSVGElement(allLines);
+                if (element != null)
+                {
+                    picture.AddRange(element);
+                }
+                i++;
+            }
+            return picture;
+        }
+
+        /// <summary>
+        /// parses one toplevel svg element
+        /// </summary>
+        /// <param name="allLines">an array holding all lines of the input file</param>
+        /// <returns>the parsed Element as a list of lines</returns>
+        private List<Line> ParseSingleSVGElement(string[] allLines)
+        {
+            String[] currentElement = GetCurrentElement(allLines);
+            if (currentElement[currentElement.Length - 1].EndsWith("/>")) //single line element
+            {
+                return ParseSingleLineSVGElement(currentElement);
+            }
+            else //element containing sub-elements
+            {
+                return ParseMultiLineSVGElement(currentElement, allLines);
+            }
+        }
+
+        /// <summary>
+        /// parses a single toplevel svg element only taking one line
+        /// </summary>
+        /// <param name="allLines">an array holding all lines of the input file</param>
+        /// <returns>the parsed element as a Line object, or null if the element is not supported</returns>
+        private List<Line> ParseSingleLineSVGElement(string[] currentElement)
+        {
+            List<Point> points= null;
+            List<Line> element = null;
+            switch (currentElement[0])
+            {
+                case "<rect":
+                    points = parseRect(currentElement);
+                    break;
+                case "<circle":
+                    points = parseCircle(currentElement);
+                    break;
+                case "<ellipse":
+                    points = parseEllipse(currentElement);
+                    break;
+                case "<line":
+                    points = parseLine(currentElement);
+                    break;
+                case "<polyline":
+                    points = parsePolyline(currentElement);
+                    break;
+                case "<polygon":
+                    points = parsePolygon(currentElement);
+                    break;
+                case "<path":
+                    element = parsePath(currentElement);
+                    break;
+                default: //unsupported svg element
+                    Console.WriteLine("unsupported element: " + currentElement[0] + currentElement[0].Length);
+                    return null;
+            }
+            if (element == null)
+            {
+                element = new List<Line>();
+                element.Add(new Line(points));
+            }
+            return element;
+        }
+
+        /// <summary>
+        /// parses a rectangle definition into a List of Points representing a single line around the rectangle (in clockwise direction)
+        /// </summary>
+        /// <param name="currentElement">the definition of the element as whitespace seperated String[]</param>
+        /// <returns>the parsed element as a List of Points</returns>
+        private List<Point> parseRect(string[] currentElement)
+        {
+            double x = 0;
+            double y = 0;
+            double w = 0;
+            double h = 0;
+            double rx = 0;
+            double ry = 0;
+            for(int j= 0; j < currentElement.Length; j++)
+            {
+                if (currentElement[j].StartsWith("x="))
+                {
+                    x = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("y="))
+                {
+                    y = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("width="))
+                {
+                    w = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("height="))
+                {
+                    h = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("rx="))
+                {
+                    rx = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("ry="))
+                {
+                    ry = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+            }
+            List<Point> rect = new List<Point>();
+            rect.Add(ScaleAndCreatePoint(x, y));
+            rect.Add(ScaleAndCreatePoint(x + w, y));
+            rect.Add(ScaleAndCreatePoint(x + w, y + h));
+            rect.Add(ScaleAndCreatePoint(x, y + h));
+            rect.Add(ScaleAndCreatePoint(x, y));
+            Console.WriteLine("parsed point: " + x + ";" + y);
+            return rect;
+        }
+
+        /// <summary>
+        /// parses a circle definition into a List of Points
+        /// </summary>
+        /// <param name="currentElement">the definition of the element as whitespace seperated String[]</param>
+        /// <returns>the parsed element as a List of Points</returns>
+        private List<Point> parseCircle(string[] currentElement)
+        {
+            double x = 0;
+            double y = 0;
+            double r = 0;
+            for (int j = 0; j < currentElement.Length; j++)
+            {
+                if (currentElement[j].StartsWith("cx="))
+                {
+                    x = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("cy="))
+                {
+                    y = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("r="))
+                {
+                    r = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+            }
+            return SampleEllipse(x, y, r, r);
+        }
+
+        /// <summary>
+        /// parses a ellipse definition into a List of Points
+        /// </summary>
+        /// <param name="currentElement">the definition of the element as whitespace seperated String[]</param>
+        /// <returns>the parsed element as a List of Points</returns>
+        private List<Point> parseEllipse(string[] currentElement)
+        {
+            double x = 0;
+            double y = 0;
+            double rx = 0;
+            double ry = 0;
+            for (int j = 0; j < currentElement.Length; j++)
+            {
+                if (currentElement[j].StartsWith("cx="))
+                {
+                    x = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("cy="))
+                {
+                    y = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("rx="))
+                {
+                    rx = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("ry="))
+                {
+                    ry = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+            }
+            return SampleEllipse(x, y, rx, ry);
+        }
+
+        /// <summary>
+        /// parses a line definition into a List of two Points
+        /// </summary>
+        /// <param name="currentElement">the definition of the element as whitespace seperated String[]</param>
+        /// <returns>the parsed element as a List of Points</returns>
+        private List<Point> parseLine(string[] currentElement)
+        {
+            double x1 = 0;
+            double y1 = 0;
+            double x2 = 0;
+            double y2 = 0;
+            for (int j = 0; j < currentElement.Length; j++)
+            {
+                if (currentElement[j].StartsWith("x1="))
+                {
+                    x1 = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("y1="))
+                {
+                    y1 = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("x2="))
+                {
+                    x2 = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+                else if (currentElement[j].StartsWith("y2="))
+                {
+                    y2 = Convert.ToDouble(ParseSingleSVGAttribute(currentElement[j]), CultureInfo.InvariantCulture);
+                }
+            }
+            List<Point> line = new List<Point>();
+            line.Add(ScaleAndCreatePoint(x1, y1));
+            line.Add(ScaleAndCreatePoint(x2, y2));
+            return line;
+        }
+
+        /// <summary>
+        /// parses a polyline definition into a List of Points
+        /// </summary>
+        /// <param name="currentElement">the definition of the element as whitespace seperated String[]</param>
+        /// <returns>the parsed element as a List of Points</returns>
+        private List<Point> parsePolyline(string[] currentElement)
+        {
+            String[] points = null;
+            for (int j = 0; j < currentElement.Length; j++)
+            {
+                if (currentElement[j].StartsWith("points="))
+                {
+                    List<String> pointDefs = new List<string>();
+                    pointDefs.Add(currentElement[j].Substring(8)); //parse first point coordinates by removing 'points="'
+                    j++;
+                    while (!currentElement[j].EndsWith("\""))
+                    {
+                        pointDefs.Add(currentElement[j]); //parse intermediate point coordinates
+                        j++;
+                    }
+                    pointDefs.Add(currentElement[j].Trim('"')); //parse last point coordinates by removing '"'
+                    points = pointDefs.ToArray();
+                }
+            }
+            List<Point> polyline = new List<Point>();
+            for (int k = 0; k < points.Length - 1; k += 2)
+            {
+                polyline.Add(ScaleAndCreatePoint(Convert.ToDouble(points[k], CultureInfo.InvariantCulture), Convert.ToDouble(points[k + 1], CultureInfo.InvariantCulture)));
+            }
+            return polyline;
+        }
+
+        /// <summary>
+        /// parses a polygon definition into a List of Points
+        /// </summary>
+        /// <param name="currentElement">the definition of the element as whitespace seperated String[]</param>
+        /// <returns>the parsed element as a List of Points</returns>
+        private List<Point> parsePolygon(string[] currentElement)
+        {
+            String[] points = null;
+            for (int j = 0; j < currentElement.Length; j++)
+            {
+                if (currentElement[j].StartsWith("points="))
+                {
+                    List<String> pointDefs = new List<string>();
+                    pointDefs.Add(currentElement[j].Substring(8)); //parse first point coordinates by removing 'points="'
+                    j++;
+                    while (!currentElement[j].EndsWith("\""))
+                    {
+                        pointDefs.Add(currentElement[j]); //parse intermediate point coordinates
+                        j++;
+                    }
+                    pointDefs.Add(currentElement[j].Trim('"')); //parse last point coordinates by removing '"'
+                    points = pointDefs.ToArray();
+                }
+            }
+            List<Point> polygon = new List<Point>();
+            for (int k = 0; k < points.Length - 1; k+=2)
+            {
+                polygon.Add(ScaleAndCreatePoint(Convert.ToDouble(points[k], CultureInfo.InvariantCulture), Convert.ToDouble(points[k+1], CultureInfo.InvariantCulture)));
+                Console.WriteLine("parsed point: " + points[k] + ";" + points[k + 1]);
+            }
+            polygon.Add(ScaleAndCreatePoint(Convert.ToDouble(points[0], CultureInfo.InvariantCulture), Convert.ToDouble(points[1], CultureInfo.InvariantCulture))); //close polygon
+            Console.WriteLine("parsed point: " + points[0] + ";" + points[1]);
+            return polygon;
+        }
+
+        /// <summary>
+        /// parses a path definition into a List of Points
+        /// </summary>
+        /// <param name="currentElement">the definition of the element as whitespace seperated String[]</param>
+        /// <returns>the parsed element as a List of Points</returns>
+        private List<Line> parsePath(string[] currentElement)
+        {
+            List<String> pathElements = new List<string>();
+            for (int j = 0; j < currentElement.Length; j++)
+            {
+                if (currentElement[j].StartsWith("d="))
+                {
+                    pathElements.Add(currentElement[j].Substring(3)); //parse first path element by removing 'd="'
+                    j++;
+                    while (!currentElement[j].EndsWith("\""))
+                    {
+                        pathElements.Add(currentElement[j]); //parse intermediate path element
+                        j++;
+                    }
+                    pathElements.Add(currentElement[j].Trim('"')); //parse last path element by removing '"'
+                }
+            }
+            List<Line> element = new List<Line>();
+            List<Point> currentLine = new List<Point>();
+            Point mirroredBezierPoint;
+            pathElements = PreparePathElements(pathElements); //split pathElement list objects until every object is atomar (single character or single number (coordinate))
+            //int k = 0; //index of active element in pathElements is always 0
+            currentLine = parse_M(pathElements);
+            while(!(pathElements.Count == 0){
+                if (pathElements.First().Equals("M"))
+                {
+                    element.Add(new Line(currentLine));
+                    currentLine = parse_M(pathElements);
+                }
+                else if (pathElements.First().Equals(""))
+                {
+
+                }
+            }
+            return element;
+        }
+
+        /// <summary>
+        /// parses a hierarchical svg element and all its sub-elements
+        /// </summary>
+        /// <param name="currentElement">the definition of the top level element as whitespace seperated String[]</param>
+        /// <param name="allLines">an array holding all lines of the input file</param>
+        /// <returns>the parsed element as a Line object, or null if the element is not supported</returns>
+        private List<Line> ParseMultiLineSVGElement(string[] currentElement, string[] allLines)
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <summary>
+        /// removes the name of the attribute aswell as the '="' at the beginning and the '"' or '">' at the end of an attribute definition
+        /// </summary>
+        /// <param name="definition">the definition from the svg file</param>
+        /// <returns>the value of the attribute, as String (the part of definition contained between '"'s)</returns>
+        private String ParseSingleSVGAttribute(String definition)
+        {
+            return definition.Split('"')[1];
+        }
+
+        /// <summary>
+        /// fetches a single svg element definition that may extend ovr several lines of the input file, iterates i to point to the last line of the element definition
+        /// </summary>
+        /// <param name="allLines">an array holding all lines of the input file</param>
+        /// <returns>the definition of the current svg element, as String[] split by whitespaces</returns>
+        private String[] GetCurrentElement(String[] allLines)
+        {
+            List<String> currentElementTemp = allLines[i].Split(whitespaces).ToList();
+            while (!currentElementTemp.Last().EndsWith(">"))
+            {
+                i++;
+                currentElementTemp.AddRange(allLines[i].Split(whitespaces).ToList());
+            }
+            return currentElementTemp.ToArray();
+        }
+
+        /// <summary>
+        /// applies the scale factor to the coordinates and creates a new Point
+        /// </summary>
+        /// <param name="x">unscaled x coordinate</param>
+        /// <param name="y">unscaled y coordinate</param>
+        /// <returns>new Point with scaled coordinates</returns>
+        private Point ScaleAndCreatePoint(double x, double y)
+        {
+            return new Point((int)Math.Round(x * scale), (int)Math.Round(y * scale));
+        }
+
+        /// <summary>
+        /// creates a representation of an ellipse as a List of Points by sampling the outline of the ellipse
+        /// </summary>
+        /// <param name="x">x coordinate of the center of the ellipse</param>
+        /// <param name="y">y coordinate of the center of the ellipse</param>
+        /// <param name="rx">x radius of the ellipse</param>
+        /// <param name="ry">y radius of the ellipse</param>
+        /// <returns>the parsed element as a List of Points</returns>
+        private List<Point> SampleEllipse(double x, double y, double rx, double ry)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 35 - 25
SketchAssistant/SketchAssistant/Form1.Designer.cs

@@ -43,13 +43,14 @@ namespace SketchAssistant
             this.canvasButton = new System.Windows.Forms.ToolStripButton();
             this.drawButton = new System.Windows.Forms.ToolStripButton();
             this.deleteButton = new System.Windows.Forms.ToolStripButton();
+            this.undoButton = new System.Windows.Forms.ToolStripButton();
+            this.redoButton = new System.Windows.Forms.ToolStripButton();
             this.statusStrip1 = new System.Windows.Forms.StatusStrip();
             this.toolStripLoadStatus = new System.Windows.Forms.ToolStripStatusLabel();
+            this.lastActionTakenLabel = new System.Windows.Forms.ToolStripStatusLabel();
             this.backgroundWorker2 = new System.ComponentModel.BackgroundWorker();
             this.mouseTimer = new System.Windows.Forms.Timer(this.components);
-            this.lastActionTakenLabel = new System.Windows.Forms.ToolStripStatusLabel();
-            this.undoButton = new System.Windows.Forms.ToolStripButton();
-            this.redoButton = new System.Windows.Forms.ToolStripButton();
+            this.sVGDrawingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.tableLayoutPanel1.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.pictureBoxRight)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.pictureBoxLeft)).BeginInit();
@@ -133,7 +134,8 @@ namespace SketchAssistant
             // importToolStripMenuItem
             // 
             this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.examplePictureToolStripMenuItem});
+            this.examplePictureToolStripMenuItem,
+            this.sVGDrawingToolStripMenuItem});
             this.importToolStripMenuItem.Name = "importToolStripMenuItem";
             this.importToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
             this.importToolStripMenuItem.Text = "Import...";
@@ -189,6 +191,26 @@ namespace SketchAssistant
             this.deleteButton.Text = "Delete";
             this.deleteButton.Click += new System.EventHandler(this.deleteButton_Click);
             // 
+            // undoButton
+            // 
+            this.undoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+            this.undoButton.Image = ((System.Drawing.Image)(resources.GetObject("undoButton.Image")));
+            this.undoButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.undoButton.Name = "undoButton";
+            this.undoButton.Size = new System.Drawing.Size(40, 22);
+            this.undoButton.Text = "Undo";
+            this.undoButton.Click += new System.EventHandler(this.undoButton_Click);
+            // 
+            // redoButton
+            // 
+            this.redoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+            this.redoButton.Image = ((System.Drawing.Image)(resources.GetObject("redoButton.Image")));
+            this.redoButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.redoButton.Name = "redoButton";
+            this.redoButton.Size = new System.Drawing.Size(38, 22);
+            this.redoButton.Text = "Redo";
+            this.redoButton.Click += new System.EventHandler(this.redoButton_Click);
+            // 
             // statusStrip1
             // 
             this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -206,11 +228,6 @@ namespace SketchAssistant
             this.toolStripLoadStatus.Size = new System.Drawing.Size(40, 19);
             this.toolStripLoadStatus.Text = "no file";
             // 
-            // mouseTimer
-            // 
-            this.mouseTimer.Interval = 1;
-            this.mouseTimer.Tick += new System.EventHandler(this.mouseTimer_Tick);
-            // 
             // lastActionTakenLabel
             // 
             this.lastActionTakenLabel.BorderSides = System.Windows.Forms.ToolStripStatusLabelBorderSides.Left;
@@ -219,25 +236,17 @@ namespace SketchAssistant
             this.lastActionTakenLabel.Text = "none";
             this.lastActionTakenLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
             // 
-            // undoButton
+            // mouseTimer
             // 
-            this.undoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
-            this.undoButton.Image = ((System.Drawing.Image)(resources.GetObject("undoButton.Image")));
-            this.undoButton.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.undoButton.Name = "undoButton";
-            this.undoButton.Size = new System.Drawing.Size(40, 22);
-            this.undoButton.Text = "Undo";
-            this.undoButton.Click += new System.EventHandler(this.undoButton_Click);
+            this.mouseTimer.Interval = 1;
+            this.mouseTimer.Tick += new System.EventHandler(this.mouseTimer_Tick);
             // 
-            // redoButton
+            // sVGDrawingToolStripMenuItem
             // 
-            this.redoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
-            this.redoButton.Image = ((System.Drawing.Image)(resources.GetObject("redoButton.Image")));
-            this.redoButton.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.redoButton.Name = "redoButton";
-            this.redoButton.Size = new System.Drawing.Size(38, 22);
-            this.redoButton.Text = "Redo";
-            this.redoButton.Click += new System.EventHandler(this.redoButton_Click);
+            this.sVGDrawingToolStripMenuItem.Name = "sVGDrawingToolStripMenuItem";
+            this.sVGDrawingToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+            this.sVGDrawingToolStripMenuItem.Text = "SVG drawing";
+            this.sVGDrawingToolStripMenuItem.Click += new System.EventHandler(this.SVGDrawingToolStripMenuItem_Click);
             // 
             // Form1
             // 
@@ -294,6 +303,7 @@ namespace SketchAssistant
         private System.Windows.Forms.ToolStripStatusLabel lastActionTakenLabel;
         private System.Windows.Forms.ToolStripButton undoButton;
         private System.Windows.Forms.ToolStripButton redoButton;
+        private System.Windows.Forms.ToolStripMenuItem sVGDrawingToolStripMenuItem;
     }
 }
 

+ 29 - 1
SketchAssistant/SketchAssistant/Form1.cs

@@ -99,6 +99,7 @@ namespace SketchAssistant
         /// Size of deletion area
         /// </summary>
         uint deletionSize = 2;
+
         /// <summary>
         /// History of Actions
         /// </summary>
@@ -138,7 +139,7 @@ namespace SketchAssistant
         }
 
         /// <summary>
-        /// Import button, will open an OpenFileDialog
+        /// Import example picture button, will open an OpenFileDialog
         /// </summary>
         private void examplePictureToolStripMenuItem_Click(object sender, EventArgs e)
         {
@@ -160,6 +161,33 @@ namespace SketchAssistant
             }
         }
 
+        /// <summary>
+        /// Import svg drawing button, will open an OpenFileDialog
+        /// </summary>
+        private void SVGDrawingToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            openFileDialog.Filter = "Scalable Vector Graphics|*.svg";
+            if (openFileDialog.ShowDialog() == DialogResult.OK)
+            {
+                toolStripLoadStatus.Text = openFileDialog.SafeFileName;
+                try
+                {
+                    (int, int, List<Line>) drawing = fileImporter.ParseSVGInputFile(openFileDialog.FileName, pictureBoxLeft.Width, pictureBoxLeft.Height);
+                    DrawEmptyCanvasLeft(drawing.Item1, drawing.Item2);
+                    BindAndDrawLeftImage(drawing.Item3);
+                    this.Refresh();
+                }
+                catch (FileImporterException ex)
+                {
+                    ShowInfoMessage(ex.ToString());
+                }
+                catch (Exception ex)
+                {
+                    ShowInfoMessage("exception occured while trying to parse svg file:\n\n" + ex.ToString() + "\n\n" + ex.StackTrace);
+                }
+            }
+        }
+
         //Changes the state of the program to drawing
         private void drawButton_Click(object sender, EventArgs e)
         {

+ 9 - 9
SketchAssistant/SketchAssistant/Form1.resx

@@ -172,15 +172,6 @@
         TgDQASA1MVpwzwAAAABJRU5ErkJggg==
 </value>
   </data>
-  <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>506, 17</value>
-  </metadata>
-  <metadata name="backgroundWorker2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>622, 17</value>
-  </metadata>
-  <metadata name="mouseTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>786, 17</value>
-  </metadata>
   <data name="undoButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
@@ -211,6 +202,15 @@
         TgDQASA1MVpwzwAAAABJRU5ErkJggg==
 </value>
   </data>
+  <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>506, 17</value>
+  </metadata>
+  <metadata name="backgroundWorker2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>622, 17</value>
+  </metadata>
+  <metadata name="mouseTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>786, 17</value>
+  </metadata>
   <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>47</value>
   </metadata>