Esempio n. 1
0
        /// <summary>
        /// Create the xml export structure
        /// </summary>
        private static XElement CreateXmlExport(GraphicVisual visual, int width)
        {
            XNamespace ns   = "http://www.w3.org/2000/svg";
            XElement   root = new XElement(ns + "svg");

            root.Add(new XAttribute("Version", "1.1"));

            var normalizer       = new NormalizeVisual();
            var normalizedVisual = normalizer.Normalize(visual, NormalizeAspect.Width, width);

            double height = normalizer.AspectRatio * width;

            root.Add(new XAttribute("viewBox", $"0 0 {width} {height}"));

            XElement definitions      = new XElement(ns + "defs");
            int      definitionsCount = 0;
            var      element          = GenerateXmlTree(normalizedVisual, ns, definitions, ref definitionsCount);

            if (definitions.HasElements)
            {
                root.Add(definitions);
            }

            root.Add(element);
            return(root);
        }
Esempio n. 2
0
        /// <summary>
        /// Export to an image format
        /// </summary>
        public static void ExportSvg(GraphicVisual visual, int width, string filename)
        {
            XNamespace ns   = "http://www.w3.org/2000/svg";
            XElement   root = new XElement(ns + "svg");

            root.Add(new XAttribute("Version", "1.1"));

            var normalizer       = new NormalizeVisual();
            var normalizedVisual = normalizer.Normalize(visual, NormalizeAspect.Width, width);

            double height = normalizer.AspectRatio * width;

            root.Add(new XAttribute("viewBox", $"0 0 {width} {height}"));

            XElement definitions      = new XElement(ns + "defs");
            int      definitionsCount = 0;
            var      element          = Generate(normalizedVisual, ns, definitions, ref definitionsCount);

            if (definitions.HasElements)
            {
                root.Add(definitions);
            }

            root.Add(element);

            using (var writer =
                       XmlWriter.Create(filename, new XmlWriterSettings {
                OmitXmlDeclaration = true, Indent = true
            }))
            {
                root.Save(writer);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Parse the given file
        /// </summary>
        GraphicVisual IFileParser.Parse(string filename)
        {
            GraphicVisual visual = null;

            try
            {
                using (var file = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    using (GZipStream decompressionStream = new GZipStream(file, CompressionMode.Decompress))
                    {
                        var root = XElement.Load(decompressionStream);

                        var svgParser = new SvgParser();
                        visual = svgParser.ParseRoot(root);
                    }
                }
            }
#pragma warning disable CS0168 // Variable is declared but never used
            catch (Exception e)
#pragma warning restore CS0168 // Variable is declared but never used
            {
            }

            return(visual);
        }
Esempio n. 4
0
        /// <summary>
        /// Export to EPS
        /// </summary>
        public void Export(GraphicVisual visual, int width, string filename, out string message)
        {
            outputStream = new StreamWriter(filename, false, Encoding.ASCII);

            var normalizer       = new NormalizeVisual();
            var normalizedVisual = normalizer.Normalize(visual, NormalizeAspect.Width, width);

            double height = normalizer.AspectRatio * width;

            InitEpsFile(width, height);
            Generate(normalizedVisual);
            FinalizeEpsFile();

            outputStream.Close();
            outputStream.Dispose();

            if (nonSupportedOpacityFound)
            {
                message = "EPS does not support opacity, opacity ignored";
            }
            else
            {
                message = string.Empty;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Determines the scale factor of the specified geometry tree
        /// </summary>
        private Rect DetermineBounds(GraphicVisual visual)
        {
            var left   = double.PositiveInfinity;
            var top    = double.PositiveInfinity;
            var right  = double.NegativeInfinity;
            var bottom = double.NegativeInfinity;

            void DetermineBoundsRecursive(GraphicVisual visualRecursive)
            {
                switch (visualRecursive)
                {
                case GraphicGroup group:
                {
                    foreach (var childVisual in group.Children)
                    {
                        DetermineBoundsRecursive(childVisual);
                    }

                    break;
                }

                case GraphicPath graphicPath:
                {
                    var bounds = graphicPath.Geometry.Bounds;

                    if (bounds.Left < left)
                    {
                        left = bounds.Left;
                    }

                    if (bounds.Top < top)
                    {
                        top = bounds.Top;
                    }

                    if (bounds.Right > right)
                    {
                        right = bounds.Right;
                    }

                    if (bounds.Bottom > bottom)
                    {
                        bottom = bounds.Bottom;
                    }

                    break;
                }
                }
            }

            DetermineBoundsRecursive(visual);

            if (double.IsPositiveInfinity(left))
            {
                return(new Rect());
            }

            return(new Rect(left, top, right - left, bottom - top));
        }
        /// <summary>
        /// Generate a list of raw (pure) geometry streams without any code around
        /// </summary>
        public static List <string> GenerateStreamGeometries(GraphicVisual visual)
        {
            List <string> list = new List <string>();

            GenerateStreamGeometries(visual, list);

            return(list);
        }
Esempio n. 7
0
        /// <summary>
        /// Remove all unneeded groups with clipping set that doesn't clip anything
        /// In sum this is a very, very expensive operation. But it helps to
        /// create cleaner and faster code without unnecessary clipping
        /// </summary>
        private static Geometry RemoveClipping(GraphicVisual visual)
        {
            Geometry geometry = null;

            switch (visual)
            {
            case GraphicGroup group:
            {
                var childrenGeometry = new PathGeometry();
                geometry = childrenGeometry;

                foreach (var childVisual in group.Children)
                {
                    var childgeometry = RemoveClipping(childVisual);
                    childrenGeometry.AddGeometry(childgeometry);
                }

                if (group.Clip != null)
                {
                    var groupClipGeometry = GeometryBinaryGenerator.GenerateGeometry(group.Clip);
                    var intersection      = groupClipGeometry.FillContainsWithDetail(childrenGeometry, 0.0001, ToleranceType.Absolute);

                    if (intersection == IntersectionDetail.FullyContains)
                    {
                        group.Clip = null;
                    }
                    else
                    if (intersection == IntersectionDetail.Intersects)
                    {
                        var pen1 = new Pen(Brushes.Black, 2);
                        groupClipGeometry = groupClipGeometry.GetWidenedPathGeometry(pen1);
                        groupClipGeometry = groupClipGeometry.GetOutlinedPathGeometry();

                        var pen2 = new Pen(Brushes.Black, 1);
                        childrenGeometry = childrenGeometry.GetWidenedPathGeometry(pen2);
                        childrenGeometry = childrenGeometry.GetOutlinedPathGeometry();

                        intersection = groupClipGeometry.FillContainsWithDetail(childrenGeometry, 0.0001, ToleranceType.Absolute);

                        if (intersection == IntersectionDetail.FullyContains)
                        {
                            group.Clip = null;
                        }
                    }
                }

                break;
            }

            case GraphicPath graphicPath:
            {
                geometry = GeometryBinaryGenerator.GenerateGeometry(graphicPath.Geometry);
                break;
            }
            }

            return(geometry);
        }
        /// <summary>
        /// Initialize a stream generation
        /// </summary>
        protected override void Init(GraphicVisual visual)
        {
            var code   = Code;
            var indent = MethodBodyIndent;

            code.AppendLine($"{indent}PathGeometry pathGeometry = new PathGeometry();");
            code.AppendLine($"{indent}PathFigureCollection pathFigureCollection = new PathFigureCollection();");
            code.AppendLine($"{indent}pathGeometry.Figures = pathFigureCollection;");
        }
Esempio n. 9
0
        /// <summary>
        /// Generate the XAML Path source code for a visual
        /// </summary>
        private static void GeneratePathGroup(GraphicVisual visual, StringBuilder result, int level, GeometryGeneratorType geometryGeneratorType)
        {
            switch (visual)
            {
            case GraphicGroup group:
            {
                var tag       = "Grid";
                var indentTag = SourceFormatterHelper.GetTagIndent(level);
                result.Append($"{indentTag}<{tag}");

                bool tagIndent = false;

                if (!DoubleUtilities.IsEqual(group.Opacity, 1.0))
                {
                    tagIndent = true;
                    string opac = string.Format(CultureInfo.InvariantCulture, " Opacity=\"{0}\"", DoubleUtilities.FormatString(group.Opacity));
                    result.Append(opac);
                }

                if (group.Clip != null)
                {
                    if (tagIndent)
                    {
                        var indentProperty = SourceFormatterHelper.GetPropertyIndent(level, tag);
                        result.AppendLine();
                        result.Append(indentProperty);
                    }
                    else
                    {
                        result.Append(" ");
                    }

                    result.Append(string.Format("Clip=\""));
                    var stream = StreamSourceGenerator.GenerateStreamGeometry(group.Clip);
                    result.Append(stream);
                    result.Append("\"");
                }

                result.AppendLine(">");

                foreach (var childVisual in group.Children)
                {
                    GeneratePathGroup(childVisual, result, level + 1, geometryGeneratorType);
                }

                result.AppendLine($"{indentTag}</{tag}>");

                break;
            }

            case GraphicPath graphicPath:
            {
                result.AppendLine(GeneratePath(graphicPath, false, level, geometryGeneratorType));
                break;
            }
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Initialize a stream generation
        /// </summary>
        protected override void Init(GraphicVisual visual)
        {
            var code   = Code;
            var indent = MethodBodyIndent;

            code.AppendLine($"{indent}StreamGeometry geometry = new StreamGeometry();");
            code.AppendLine($"{indent}geometry.FillRule = FillRule.EvenOdd;");
            code.AppendLine($"{indent}StreamGeometryContext ctx = geometry.Open();");
        }
Esempio n. 11
0
        /// <summary>
        /// Initialize a stream generation
        /// </summary>
        protected override void Init(GraphicVisual visual)
        {
            InitCode(visual);

            var indent2 = Indent2;

            code.AppendLine($"{indent2}StreamGeometry geometry = new StreamGeometry();");
            code.AppendLine($"{indent2}geometry.FillRule = FillRule.EvenOdd;");
            code.AppendLine($"{indent2}StreamGeometryContext ctx = geometry.Open();");
        }
Esempio n. 12
0
        /// <summary>
        /// Generate the XAML source code for a PathGeometry
        /// </summary>
        public static string GeneratePathGeometry(GraphicVisual visual)
        {
            StringBuilder result = new StringBuilder();

            int xKey = 1;

            GeneratePathGeometry(result, visual, ref xKey);

            return(result.ToString());
        }
        /// <summary>
        /// Generates a WPF brush from the specified drawing.
        /// </summary>
        public static Brush Generate(GraphicVisual visual)
        {
            var drawingBrush = new DrawingBrush();

            drawingBrush.Stretch = Stretch.Uniform;

            drawingBrush.Drawing = GenerateDrawing(visual);

            return(drawingBrush);
        }
Esempio n. 14
0
        /// <summary>
        /// Remove all unneeded groups (neutral groups with only one child or
        /// with clipping set that doesn't clip anything)
        /// Attention: Modifies the original visual
        /// </summary>
        public static GraphicVisual Optimize(GraphicVisual visual)
        {
            if (visual == null)
            {
                return(null);
            }

            RemoveClipping(visual);
            return(Optimize(visual, 0));
        }
Esempio n. 15
0
        /// <summary>
        /// Initialize a stream generation
        /// </summary>
        protected override void Init(GraphicVisual visual)
        {
            InitCode(visual);

            var indent2 = Indent2;

            code.AppendLine($"{indent2}PathGeometry pathGeometry = new PathGeometry();");
            code.AppendLine($"{indent2}PathFigureCollection pathFigureCollection = new PathFigureCollection();");
            code.AppendLine($"{indent2}pathGeometry.Figures = pathFigureCollection;");
        }
Esempio n. 16
0
        /// <summary>
        /// Export to SVG
        /// </summary>
        public static void ExportSvg(GraphicVisual visual, int width, string filename)
        {
            XElement root = CreateXmlExport(visual, width);

            using (var writer = XmlWriter.Create(filename, new XmlWriterSettings {
                OmitXmlDeclaration = true, Indent = true
            }))
            {
                root.Save(writer);
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Set a new visual
        /// </summary>
        public void SetNewGraphicVisual(GraphicVisual visual)
        {
            selectedVisual = visual;

            if (visual == null)
            {
                SourceCode = null;
            }

            UpdateSourceCode();
        }
Esempio n. 18
0
        /// <summary>
        /// Set a new visual
        /// </summary>
        public void SetNewGraphicVisual(GraphicVisual visual, GraphicColorPrecision?colorPrecision = null)
        {
            if (visual == null)
            {
                ColorPrecisionMessage = null;
                Preview = null;
                return;
            }

            ColorPrecisionMessage = CommonViews.Helper.GetColorPrecisionText(colorPrecision);
            Preview = DrawingBrushBinaryGenerator.Generate(visual);
        }
Esempio n. 19
0
        /// <summary>
        /// Generate a visual recursively to xml
        /// </summary>
        private static XElement Generate(GraphicVisual visual, XNamespace ns, XElement definitions, ref int definitionsCount)
        {
            XElement element = null;

            switch (visual)
            {
            case GraphicGroup group:
            {
                element = new XElement(ns + "g");

                if (!DoubleUtilities.IsEqual(group.Opacity, 1))
                {
                    element.Add(new XAttribute("opacity", DoubleUtilities.FormatString(group.Opacity)));
                }

                if (group.Clip != null)
                {
                    var clipElement = new XElement(ns + "clipPath");
                    definitions.Add(clipElement);

                    definitionsCount++;
                    string defId = $"clip{definitionsCount}";

                    element.Add(new XAttribute("clip-path", $"url(#{defId})"));
                    clipElement.Add(new XAttribute("id", defId));

                    var pathElement = new XElement(ns + "path");
                    clipElement.Add(pathElement);

                    var pathStr = StreamSourceGenerator.GenerateStreamGeometry(group.Clip, false);
                    pathElement.Add(new XAttribute("d", pathStr));
                }

                foreach (var childVisual in group.Childreen)
                {
                    var path = Generate(childVisual, ns, definitions, ref definitionsCount);
                    element.Add(path);
                }

                break;
            }

            case GraphicPath graphicPath:
            {
                element = GeneratePath(graphicPath, ns, definitions, ref definitionsCount);

                break;
            }
            }

            return(element);
        }
Esempio n. 20
0
        /// <summary>
        /// Set a new visual
        /// </summary>
        public void SetNewGraphicVisual(GraphicVisual visual, GraphicColorPrecision?colorPrecision = null)
        {
            selectedVisual = visual;

            if (visual == null)
            {
                ColorPrecisionMessage = null;
                SourceCode            = null;
            }

            ColorPrecisionMessage = Helper.GetColorPrecisionText(colorPrecision);
            UpdateSourceCode();
        }
        /// <summary>
        /// Builds the selected visual.
        /// </summary>
        private GraphicVisual BuildSelectedDrawing(GraphicVisual visual)
        {
            var           selectedShapes = GetSelectedPaths();
            GraphicVisual selectedVisual = null;

            if (visual != null)
            {
                selectedVisual = BuildSelectedGeometry(visual, selectedShapes);
                selectedVisual = OptimizeVisual.Optimize(selectedVisual);
            }

            return(selectedVisual);
        }
        /// <summary>
        /// Generates the drawing brush source code for a given graphic drawing.
        /// </summary>
        public static string Generate(GraphicVisual visual, GeometryGeneratorType geometryGeneratorType)
        {
            StringBuilder result    = new StringBuilder();
            var           indentTag = SourceFormatterHelper.GetTagIndent(1);

            result.AppendLine("<DrawingBrush Stretch=\"Uniform\">");
            result.AppendLine($"{indentTag}<DrawingBrush.Drawing>");

            Generate(visual, result, 2, geometryGeneratorType);

            result.AppendLine($"{indentTag}</DrawingBrush.Drawing>");
            result.AppendLine("</DrawingBrush>");

            return(result.ToString());
        }
Esempio n. 23
0
        /// <summary>
        /// Parse a single SVG shape
        /// </summary>
        public GraphicVisual Parse(XElement shape,
                                   XNamespace svgNamespace,
                                   Matrix currentTransformationMatrix,
                                   CssStyleCascade cssStyleCascade,
                                   Dictionary <string, XElement> globalDefinitions)
        {
            GraphicVisual graphicVisual = null;

            cssStyleCascade.PushStyles(shape);

            var transform = cssStyleCascade.GetPropertyFromTop("transform");

            if (!string.IsNullOrEmpty(transform))
            {
                var transformMatrix = TransformMatrixParser.GetTransformMatrix(transform);
                currentTransformationMatrix = transformMatrix * currentTransformationMatrix;
            }

            var geometry = GeometryParser.Parse(shape, currentTransformationMatrix);

            if (geometry != null)
            {
                var graphicPath = new GraphicPath();
                graphicPath.Geometry = geometry;
                graphicVisual        = graphicPath;

                this.svgNamespace                = svgNamespace;
                this.globalDefinitions           = globalDefinitions;
                this.currentTransformationMatrix = currentTransformationMatrix;
                this.cssStyleCascade             = cssStyleCascade;

                SetFillAndStroke(shape, graphicPath);

                if (Clipping.IsClipPathSet(cssStyleCascade))
                {
                    // shapes don't support clipping, create a group around it
                    var group = new GraphicGroup();
                    graphicVisual = group;
                    group.Childreen.Add(graphicPath);

                    Clipping.SetClipPath(group, currentTransformationMatrix, cssStyleCascade, globalDefinitions);
                }

                cssStyleCascade.Pop();
            }

            return(graphicVisual);
        }
        /// <summary>
        /// Generates geometry source code
        /// </summary>
        public string GenerateSource(GraphicVisual visual, 
                                     NormalizeGeometrySourceAspect normalizeGeometrySourceAspect,
                                     bool includeOffset,
                                     string filename)
        {
            this.normalizeAspect = normalizeGeometrySourceAspect;
            this.includeOffset = includeOffset;
            this.filename = filename;

            Code = new StringBuilder();

            var normalizer = new NormalizeVisual();
            NormalizeAspect normalizeType;

            switch (normalizeAspect)
            {
                case NormalizeGeometrySourceAspect.Width:
                    normalizeType = NormalizeAspect.Width;
                    scaleWidthVariableName = "scale";
                    scaleHeightVariableName = "scale";
                    break;

                case NormalizeGeometrySourceAspect.Height:
                    normalizeType = NormalizeAspect.Height;
                    scaleWidthVariableName = "scale";
                    scaleHeightVariableName = "scale";
                    break;

                default:
                    normalizeType = NormalizeAspect.Individual;
                    scaleWidthVariableName = "width";
                    scaleHeightVariableName = "height";
                    break;
            }

            var normalizedVisual = normalizer.Normalize(visual, normalizeType, 1.0);
            aspectRatio = normalizer.AspectRatio;

            InitCode(visual);
            Init(visual);

            GenerateSourceRecursive(normalizedVisual);

            Terminate();
            FinalizeCode();

            return Code.ToString();
        }
Esempio n. 25
0
        /// <summary>
        /// Generate the XAML Path source code for all given graphic paths
        /// </summary>
        public static string GeneratePath(GraphicVisual visual, GeometryGeneratorType geometryGeneratorType)
        {
            StringBuilder result = new StringBuilder();

            if (visual is GraphicPath graphicPath)
            {
                result.AppendLine(GeneratePath(graphicPath, true, 0, geometryGeneratorType));
            }
            else
            {
                result.AppendLine("<Viewbox>");
                GeneratePathGroup(visual, result, 1, geometryGeneratorType);
                result.AppendLine("</Viewbox>");
            }

            return(result.ToString());
        }
Esempio n. 26
0
        /// <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);

            ReadGlobalDefinitions(root);
            GraphicVisual visual = ParseGroup(defaultNamespace, root, currentTransformationMatrix);

            visual = OptimizeVisual.Optimize(visual);

            return(visual);
        }
Esempio n. 27
0
        /// <summary>
        /// Parse the given file
        /// </summary>
        GraphicVisual IFileParser.Parse(string filename)
        {
            GraphicVisual visual = null;

            try
            {
                var root = XElement.Load(new Uri(filename).ToString());
                visual = ParseRoot(root);
            }
#pragma warning disable CS0168 // Variable is declared but never used
            catch (Exception e)
#pragma warning restore CS0168 // Variable is declared but never used
            {
            }

            return(visual);
        }
Esempio n. 28
0
        private GraphicVisual ParseElement(XElement element, Matrix matrix)
        {
            GraphicVisual graphicVisual = null;

            switch (element.Name.LocalName)
            {
            case "defs":
            case "style":
            {
                // already read, ignore
                break;
            }

            case "svg":
            {
                graphicVisual = ParseSVG(element, matrix, false);
                break;
            }

            case "g":
            {
                graphicVisual = ParseGContainer(element, matrix);
                break;
            }

            case "text":
            {
                graphicVisual = textParser.Parse(element, matrix);
                break;
            }

            case "use":
            {
                graphicVisual = ParseUseElement(element, matrix);
                break;
            }

            default:
            {
                graphicVisual = shapeParser.Parse(element, matrix);
                break;
            }
            }

            return(graphicVisual);
        }
Esempio n. 29
0
        /// <summary>
        /// Export to SVGZ
        /// </summary>
        public static void ExportSvgz(GraphicVisual visual, int width, string filename)
        {
            XElement root = CreateXmlExport(visual, width);

            using (var fs = File.Create(filename))
            {
                using (var gz = new GZipStream(fs, CompressionMode.Compress))
                {
                    using (var writer = XmlWriter.Create(gz, new XmlWriterSettings {
                        OmitXmlDeclaration = true, Indent = true
                    }))
                    {
                        root.Save(writer);
                    }
                }
            }
        }
        /// <summary>
        /// Generate the XAML source code (a <Path/> for a single graphic path
        /// </summary>
        public static string GenerateGeometry(GraphicVisual visual)
        {
            var           tag    = "Geometry";
            StringBuilder result = new StringBuilder();

            var geometries = StreamSourceGenerator.GenerateStreamGeometries(visual);
            int i          = 1;

            foreach (var geometry in geometries)
            {
                result.Append($"<{tag} x:Key=\"shape{i}\">");
                result.Append(geometry);
                result.AppendLine($"</{tag}>");
                i++;
            }

            return(result.ToString());
        }