/// <summary> /// Parse an SVG given as XElement root /// </summary> public GraphicVisual ParseRoot(XElement root) { var nameSpaceAttributes = root.Attributes().Where(a => a.IsNamespaceDeclaration); var defaultNamespaceAttribute = root.Attributes().Where(a => a.IsNamespaceDeclaration && a.Name.Namespace == XNamespace.None).FirstOrDefault(); XNamespace defaultNamespace = defaultNamespaceAttribute.Value; Matrix currentTransformationMatrix = Matrix.Identity; cssStyleCascade = new CssStyleCascade(root); var svgViewBox = new SvgViewBox { ViewBox = new Rect(0, 0, 100, 100), Align = "none", Slice = "meet" }; cssStyleCascade.PushViewBox(svgViewBox); doubleParser = new DoubleParser(cssStyleCascade); ReadGlobalDefinitions(root); var brushParser = new BrushParser(defaultNamespace, cssStyleCascade, globalDefinitions, doubleParser); var geometryParser = new GeometryParser(doubleParser); var geometryTextParser = new GeometryTextParser(cssStyleCascade, doubleParser); clipping = new Clipping(cssStyleCascade, globalDefinitions, geometryParser, geometryTextParser); shapeParser = new ShapeParser(cssStyleCascade, brushParser, geometryParser, clipping); textParser = new TextParser(cssStyleCascade, doubleParser, brushParser, clipping); GraphicVisual visual = ParseSVG(root, currentTransformationMatrix, true); visual = OptimizeVisual.Optimize(visual); return(visual); }
/// <summary> /// Get the viewbox transformation matrix /// </summary> private (bool, Matrix) GetViewBoxMatrix(XElement element, bool isTopLevel) { var viewPort = GetViewPort(element, isTopLevel); var viewBox = GetViewBox(element); if (viewPort.IsEmpty && viewBox.IsEmpty) { return(false, Matrix.Identity); } Matrix matrix; bool newViewBoxPushOnStack = false; string align; string slice; if (viewPort.IsEmpty) { var svgViewBox = cssStyleCascade.GetCurrentViewBox(); viewPort = new Rect(0, 0, svgViewBox.ViewBox.Width, svgViewBox.ViewBox.Height); } if (viewBox.IsEmpty) { var svgViewBox = cssStyleCascade.GetCurrentViewBox(); viewBox = svgViewBox.ViewBox; align = svgViewBox.Align; slice = svgViewBox.Slice; } else { (align, slice) = GetAlignSlice(element); var svgViewBox = new SvgViewBox { ViewBox = viewBox, Align = align, Slice = slice }; cssStyleCascade.PushViewBox(svgViewBox); newViewBoxPushOnStack = true; } var scaleX = viewPort.Width / viewBox.Width; var scaleY = viewPort.Height / viewBox.Height; matrix = Matrix.Identity; if (align == "none") { matrix.Translate(-viewBox.X, -viewBox.Y); matrix.Scale(scaleX, scaleY); matrix.Translate(viewPort.X, viewPort.Y); } else { switch (slice) { case "meet": if (scaleX < scaleY) { scaleY = scaleX; } else { scaleX = scaleY; } break; case "slice": if (scaleX > scaleY) { scaleY = scaleX; } else { scaleX = scaleY; } break; default: throw new ArgumentException("invalid argument"); } var xOperation = align.Substring(0, 4); var yOperation = align.Substring(4, 4); double translateX; double translateY; switch (xOperation) { case "xmid": translateX = viewBox.Width / 2; break; case "xmax": translateX = viewBox.Width; break; default: throw new ArgumentException("invalid argument"); } switch (yOperation) { case "ymid": translateY = viewBox.Height / 2; break; case "ymax": translateY = viewBox.Height; break; default: throw new ArgumentException("invalid argument"); } matrix.Translate(-viewBox.X - translateX, -viewBox.Y - translateY); matrix.Scale(scaleX, scaleY); matrix.Translate(viewPort.X + viewPort.Width / 2, viewPort.Y + viewPort.Height / 2); } return(newViewBoxPushOnStack, matrix); }
/// <summary> /// Push a new view box on the stack /// </summary> public void PushViewBox(SvgViewBox svgViewBox) { svgViewBoxStack.Push(svgViewBox); }