/// <summary> /// Create a complete deep copy of the given tree of <c>SvgElement</c> objects. /// A new set of elements is created, and if the attributes are cloneable they are deep-copied too. /// Since strings and all SvgType classes are cloneable, the new tree is independant of the old. /// </summary> /// <param name="el"></param> /// <returns></returns> public static SvgElement CloneElement(SvgElement el) { SvgElement clone = (SvgElement)el.GetType().GetConstructor(new System.Type[0]).Invoke(new object[0]); foreach(string key in el.Attributes.Keys) { object o = el[key]; if (typeof(ICloneable).IsInstanceOfType(o)) clone[key] = ((ICloneable)o).Clone(); else clone[key] = o; } foreach(SvgElement ch in el.Children) { clone.AddChild(CloneElement(ch)); } return clone; }
/// <summary> /// Used by LoadFromXML /// </summary> /// <param name="e"></param> /// <param name="doc"></param> /// <param name="el"></param> private static void RecLoadFromXML(SvgElement e, XmlDocument doc, XmlElement el) { e.ReadXmlElement(doc, el); foreach(XmlNode noddo in el.ChildNodes) { if (noddo.GetType() == typeof(XmlElement)) { XmlElement childXml = (XmlElement)noddo; Type t = (Type)_elementNameDictionary[childXml.Name]; SvgElement childSvg=null; if (t == null) { childSvg = new SvgGenericElement(childXml.Name); } else { childSvg = (SvgElement)t.GetConstructor(new System.Type[0]).Invoke(new object[0]); } e.AddChild(childSvg); RecLoadFromXML(childSvg, doc, childXml); } else if (noddo.GetType() == typeof(XmlText)) { XmlText xt = (XmlText)noddo; TextNode tn = new TextNode(xt.InnerText); e.AddChild(tn); } } }
/// <summary> /// Adds a child, and sets the child's parent to this element. /// </summary> /// <param name="ch"></param> public virtual void AddChild(SvgElement ch) { if (ch.Parent != null) { throw new SvgException("Child already has a parent", ch.ToString()); } _children.Add(ch); ch._parent = this; }
/// <summary> /// Adds a child, and sets the child's parent to this element. /// </summary> /// <param name="ch"></param> public override void AddChild(SvgElement ch) { throw new SvgException("A TextNode cannot have children"); }
private void button1_Click(object sender, System.EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); if (dlg.ShowDialog() == DialogResult.OK) { string fname = dlg.FileName; StreamReader str = File.OpenText(dlg.FileName); tbIn.Text = str.ReadToEnd(); XmlDocument doc = new XmlDocument(); doc.Load(fname); svgIn.SRC = fname; _e = SvgFactory.LoadFromXML(doc, null); string output = _e.WriteSVGString(true); tbOut.Text = output; StreamWriter tw = new StreamWriter("c:\\temp\\foo.svg", false); tw.Write(output); tw.Close(); svgOut.SRC = "c:\\temp\\foo.svg"; } }
Figure SvgElementToFigure(SvgElement e) { Figure f = null; if (e is SvgRectElement || e is SvgImageElement) { if (e.Attributes.ContainsKey("x") && e.Attributes.ContainsKey("y") && e.Attributes.ContainsKey("width") && e.Attributes.ContainsKey("height")) { SvgLength X = new SvgLength((string)e.Attributes["x"]); SvgLength Y = new SvgLength((string)e.Attributes["y"]); SvgLength Width = new SvgLength((string)e.Attributes["width"]); SvgLength Height = new SvgLength((string)e.Attributes["height"]); DRect r = new DRect(X.Value, Y.Value, Width.Value, Height.Value); if (e is SvgRectElement) f = new RectFigure(r, 0); else if (e is SvgImageElement) { SvgImageElement e2 = (SvgImageElement)e; byte[] imgData = Read(e2.Href); if (imgData != null) f = new BitmapFigure(r, 0, imgData, Path.GetFileName(e2.Href)); } } } else if (e is SvgEllipseElement) { SvgEllipseElement e2 = (SvgEllipseElement)e; if (e2.Attributes.ContainsKey("cx") && e2.Attributes.ContainsKey("cy") && e2.Attributes.ContainsKey("rx") && e2.Attributes.ContainsKey("ry")) { e2.CX = new SvgLength((string)e2.Attributes["cx"]); e2.CY = new SvgLength((string)e2.Attributes["cy"]); e2.RX = new SvgLength((string)e2.Attributes["rx"]); e2.RY = new SvgLength((string)e2.Attributes["ry"]); f = new EllipseFigure(new DRect(e2.CX.Value - e2.RX.Value, e2.CY.Value - e2.RY.Value, e2.RX.Value * 2, e2.RY.Value * 2), 0); } } else if (e is SvgPathElement) { SvgPathElement e2 = (SvgPathElement)e; if (e2.Attributes.ContainsKey("d")) { e2.D = new SvgPath((string)e2.Attributes["d"]); // treat all paths as polygons for the moment DPoints pts = new DPoints(); for (int i = 0; i < e2.D.Count; i++) { PathSeg s = e2.D[i]; if ((s.Type == SvgPathSegType.SVG_SEGTYPE_MOVETO || s.Type == SvgPathSegType.SVG_SEGTYPE_LINETO) && s.Abs) pts.Add(new DPoint(s.Data[0], s.Data[1])); } if (pts.Count >= 3) { DRect r = pts.Bounds(); foreach (DPoint pt in pts) { pt.X = (pt.X - r.Left) / r.Width; pt.Y = (pt.Y - r.Top) / r.Height; } f = new PolygonFigure(pts); f.Rect = r; } } } else if (e is SvgPolylineElement) { SvgPolylineElement e2 = (SvgPolylineElement)e; if (e2.Attributes.ContainsKey("points")) f = new PolylineFigure(DPoints.FromString((string)e2.Attributes["points"])); } else if (e is SvgLineElement) { SvgLineElement e2 = (SvgLineElement)e; if (e2.Attributes.ContainsKey("x1") && e2.Attributes.ContainsKey("y1") && e2.Attributes.ContainsKey("x2") && e2.Attributes.ContainsKey("y2")) { e2.X1 = new SvgLength((string)e2.Attributes["x1"]); e2.Y1 = new SvgLength((string)e2.Attributes["y1"]); e2.X2 = new SvgLength((string)e2.Attributes["x2"]); e2.Y2 = new SvgLength((string)e2.Attributes["y2"]); f = new LineFigure2(new DPoint(e2.X1.Value, e2.Y1.Value), new DPoint(e2.X2.Value, e2.Y2.Value)); } } else if (e is SvgGroupElement) { SvgGroupElement e2 = (SvgGroupElement)e; f = new GroupFigure(); GroupFigure gf = (GroupFigure)f; foreach (SvgElement childEle in e2.Children) { Figure childFig = SvgElementToFigure(childEle); if (childFig != null) gf.ChildFigures.Add(childFig); } if (gf.ChildFigures.Count > 0) gf.ChildFigures = gf.ChildFigures; else f = null; } else if (e is SvgTextElement) { double fontSize; string fontFamily; DColor fill; bool bold, italic, underline; string text = ExtractText(e, 0, out fontSize, out fontFamily, out fill, out bold, out italic, out underline); while (text.EndsWith("\n")) text = text.Substring(0, text.Length - 1); if (text != null) { DPoint translation = GetSvgElementTranslation((SvgTextElement)e); f = new TextFigure(translation, text, 0); ((TextFigure)f).FontSize = fontSize; ((TextFigure)f).FontName = fontFamily; ((TextFigure)f).Fill = fill; ((TextFigure)f).Bold = bold; ((TextFigure)f).Italics = italic; ((TextFigure)f).Underline = underline; // set wrap threshold const double editWidthMod = 1.435; if (((SvgTextElement)e).Attributes.ContainsKey(NBTextEditWidth)) { string editwidth = (string)((SvgTextElement)e).Attributes[NBTextEditWidth]; if (editwidth != null && editwidth.Length != 0) { ((TextFigure)f).WrapThreshold = double.Parse(editwidth) * editWidthMod; ((TextFigure)f).WrapFontSize = ((TextFigure)f).FontSize; ((TextFigure)f).WrapText = true; } } // scale DPoint scale = GetSvgElementScale((SvgTextElement)e); const double scaleMod = 0.694; f.Width *= scale.X * scaleMod; f.Height *= scale.Y * scaleMod; } } if (f != null) { if (e is SvgStyledTransformedElement) f.Rotation = GetSvgElementRotation((SvgStyledTransformedElement)e); if (f is IFillable && e.Attributes.ContainsKey("fill")) ((IFillable)f).Fill = DColor.FromHtml((string)e.Attributes["fill"]); if (f is IStrokeable) { if (e.Attributes.ContainsKey("stroke")) ((IStrokeable)f).Stroke = DColor.FromHtml((string)e.Attributes["stroke"]); if (e.Attributes.ContainsKey("stroke-width")) ((IStrokeable)f).StrokeWidth = double.Parse((string)e.Attributes["stroke-width"]); if (e.Attributes.ContainsKey("stroke-dasharray")) ((IStrokeable)f).StrokeStyle = NotebookDashArrayToStrokeStyle((string)e.Attributes["stroke-dasharray"]); } if (f is IMarkable) { if (e.Attributes.ContainsKey("marker-start")) ((IMarkable)f).StartMarker = NotebookMarkerToDMarker((string)e.Attributes["marker-start"]); if (e.Attributes.ContainsKey("marker-end")) ((IMarkable)f).EndMarker = NotebookMarkerToDMarker((string)e.Attributes["marker-end"]); } if (f is IAlphaBlendable && e.Attributes.ContainsKey("opacity")) ((IAlphaBlendable)f).Alpha = double.Parse((string)e.Attributes["opacity"]); applyLink(f, e); applyLock(f, e); } return f; }
string ExtractText(SvgElement e, int level, out double fontSize, out string fontFamily, out DColor fill, out bool bold, out bool italic, out bool underline) { string text; text = ""; fontSize = 12; fontFamily = "Arial"; fill = DColor.Black; bold = false; italic = false; underline = false; if ((e is SvgTextElement || e is SvgTspanElement) && e.Children.Count == 1 && e.Children[0] is TextNode) { text = ((TextNode)e.Children[0]).Text; if (e.Attributes.ContainsKey(NBFontSizeAttr)) fontSize = double.Parse((string)e.Attributes[NBFontSizeAttr]); if (e.Attributes.ContainsKey(NBFontFamilyAttr)) fontFamily = (string)e.Attributes[NBFontFamilyAttr]; if (e.Attributes.ContainsKey(NBFillAttr)) fill = DColor.FromHtml((string)e.Attributes[NBFillAttr]); if (e.Attributes.ContainsKey(NBFontWeightAttr)) bold = NotebookFontWeightToBold((string)e.Attributes[NBFontWeightAttr]); if (e.Attributes.ContainsKey(NBFontStyleAttr)) italic = NotebookFontStyleToItalic((string)e.Attributes[NBFontStyleAttr]); if (e.Attributes.ContainsKey(NBTextDecorationAttr)) underline = NotebookTextDecorationToUnderline((string)e.Attributes[NBTextDecorationAttr]); } else { foreach (SvgElement child in e.Children) { string childText = ExtractText(child, level + 1, out fontSize, out fontFamily, out fill, out bold, out italic, out underline); if (childText != null) text += childText; } } if (level == 1) text += "\n"; return text; }
void applyLock(Figure f, SvgElement e) { f.Locked = e.Attributes.ContainsKey(NBLockedAttr); }
void applyLink(Figure f, SvgElement e) { if (e.Attributes.ContainsKey(NBLinkShortCutAttr)) { string shortcut = (string)e.Attributes[NBLinkShortCutAttr]; if (shortcut.StartsWith(NBLinkHttpPrefix)) { f.UserAttrs[Links.LinkType] = LinkType.WebPage.ToString(); f.UserAttrs[Links.Link] = shortcut; } else if (shortcut.StartsWith(NBLinkPagePrefix)) { f.UserAttrs[Links.LinkType] = LinkType.Page.ToString(); f.UserAttrs[Links.Link] = GetPageNumberFromPageName(shortcut.Substring(NBLinkPagePrefix.Length)).ToString(); } else if (shortcut == NBLinkFirstPage) { f.UserAttrs[Links.LinkType] = LinkType.Page.ToString(); f.UserAttrs[Links.Link] = LinkPage.First.ToString(); } else if (shortcut == NBLinkLastPage) { f.UserAttrs[Links.LinkType] = LinkType.Page.ToString(); f.UserAttrs[Links.Link] = LinkPage.Last.ToString(); } else if (shortcut == NBLinkNextPage) { f.UserAttrs[Links.LinkType] = LinkType.Page.ToString(); f.UserAttrs[Links.Link] = LinkPage.Next.ToString(); } else if (shortcut == NBLinkPreviousPage) { f.UserAttrs[Links.LinkType] = LinkType.Page.ToString(); f.UserAttrs[Links.Link] = LinkPage.Previous.ToString(); } else if (shortcut.StartsWith(NBLinkAttachmentPrefix)) { f.UserAttrs[Links.LinkType] = LinkType.Attachment.ToString(); f.UserAttrs[Links.Link] = shortcut.Substring(NBLinkAttachmentPrefix.Length); } else if (shortcut.StartsWith(NBLinkFilePrefix)) { f.UserAttrs[Links.LinkType] = LinkType.File.ToString(); f.UserAttrs[Links.Link] = shortcut.Substring(NBLinkFilePrefix.Length); } // link body? if (e.Attributes.ContainsKey(NBLinkShortCutAreaAttr) && (string)e.Attributes[NBLinkShortCutAreaAttr] == "1") f.UserAttrs[Links.LinkBody] = ""; } }
private void button1_Click(object sender, System.EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); if (dlg.ShowDialog() == DialogResult.OK) { string fname = dlg.FileName; StreamReader str = File.OpenText(dlg.FileName); tbIn.Text = str.ReadToEnd(); XmlDocument doc = new XmlDocument(); doc.Load(fname); svgIn.Navigate(new Uri(fname)); svgIn.Refresh(WebBrowserRefreshOption.Completely); _e = SvgFactory.LoadFromXML(doc, null); string output = _e.WriteSVGString(true); tbOut.Text = output; string tempFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "foo.svg"); StreamWriter tw = new StreamWriter(tempFile, false); tw.Write(output); tw.Close(); svgOut.Navigate(new Uri(tempFile)); svgOut.Refresh(WebBrowserRefreshOption.Completely); } }