internal override void Write(StringBuilder sb, SvgConverter conv)
 {
     if (_Center.HasValue)
     {
         sb.AppendFormat("rotate({0},{1},{2}) ",
                         conv.ToSvgValue(-_Angle),
                         conv.ToSvgLength(_Center.Value.X),
                         conv.ToSvgLength(-_Center.Value.Y));
     }
     else
     {
         sb.AppendFormat("rotate({0}) ", conv.ToSvgValue(_Angle));
     }
 }
        internal static SvgMatrixTransform Create(double[] values, SvgConverter conv)
        {
            if (values.Length >= 6)
            {
                return(new SvgMatrixTransform(new[]
                {
                    values[0], values[1],
                    values[2], values[3],
                    values[4] * conv.Scale, values[5] * conv.Scale
                }));
            }

            return(null);
        }
        internal override Pnt2d?Write(StringBuilder sb, Pnt2d?lastPnt, SvgConverter conv)
        {
            if (!(lastPnt.HasValue && conv.AreEqual(lastPnt.Value, Start)))
            {
                sb.AppendFormat("M{0},{1} ", conv.ToSvgLength(Start.X), conv.ToSvgLength(-Start.Y));
            }

            sb.AppendFormat("A{0},{1} {2} {3} {4} {5},{6} ",
                            conv.ToSvgLength(RadiusX), conv.ToSvgLength(RadiusY),
                            conv.ToSvgValue(Angle),
                            (uint)Size, (uint)Sweep,
                            conv.ToSvgLength(End.X), conv.ToSvgLength(-End.Y));
            return(End);
        }
        internal static IEnumerable <SvgTransform> Create(string transformString, SvgConverter conv)
        {
            var transformParts = transformString.Split(_TransformSplitChars);

            for (int i = 0; i < transformParts.Length - 1; i += 2)
            {
                if (!conv.TrySplitValues(transformParts[i + 1], out var values, false))
                {
                    continue;
                }

                SvgTransform transform;
                switch (transformParts[i].ToLower().Trim())
                {
                case "matrix":
                    transform = SvgMatrixTransform.Create(values, conv);
                    break;

                case "translate":
                    transform = SvgTranslateTransform.Create(values, conv);
                    break;

                case "scale":
                    transform = SvgScaleTransform.Create(values, conv);
                    break;

                case "rotate":
                    transform = SvgRotateTransform.Create(values, conv);
                    break;

                case "skewx":
                    transform = SvgSkewXTransform.Create(values, conv);
                    break;

                case "skewy":
                    transform = SvgSkewYTransform.Create(values, conv);
                    break;

                default:
                    Messages.Warning($"Unknown transform type {transformParts[i]} found in SVG file.");
                    continue;
                }

                if (transform != null)
                {
                    yield return(transform);
                }
            }
        }
Exemple #5
0
        internal override void Write(XmlWriter writer, SvgConverter conv)
        {
            writer.WriteStartElement("path");

            var   sb      = new StringBuilder();
            Pnt2d?lastPnt = null;

            foreach (var segment in Segments)
            {
                lastPnt = segment.Write(sb, lastPnt, conv);
            }
            writer.WriteAttributeString("d", sb.ToString().Trim());

            base.Write(writer, conv);
            writer.WriteEndElement();
        }
        //--------------------------------------------------------------------------------------------------

        void _CalculateScale(XmlReader reader, SvgConverter conv)
        {
            var viewBox = reader.GetAttribute("viewBox");

            if (viewBox.IsNullOrWhiteSpace() || !conv.TrySplitValues(viewBox, out var viewBoxValues, false))
            {
                Messages.Warning("SVG document has not defined a ViewBox. The scaling may be incorrect.");
                return;
            }

            double fScaleX = 1.0;
            double fScaleY = 1.0;

            if (conv.TryConvertToMillimeter(reader.GetAttribute("width"), out var width, false) &&
                conv.TryConvertToMillimeter(reader.GetAttribute("height"), out var height, false))
            {
                fScaleX = width / viewBoxValues[2];
                fScaleY = height / viewBoxValues[3];
            }
Exemple #7
0
        internal override bool Read(XmlReader reader, SvgConverter conv)
        {
            var data = reader.GetAttribute("d");

            if (!base.Read(reader, conv))
            {
                return(false);
            }

            if (!data.IsNullOrEmpty())
            {
                Segments.AddRange(SvgPathSegment.Create(data, conv));
            }

            Segments.ForEach(seg => seg.Transform(conv));

            conv.PopTransform();
            return(Segments.Count > 0);
        }
        //--------------------------------------------------------------------------------------------------

        public MemoryStream WriteToStream()
        {
            var conv = new SvgConverter()
            {
                DotsPerInch = DotsPerInch,
                Scale       = 25.4 / DotsPerInch
            };

            var xmlWriterSettings = new XmlWriterSettings
            {
                Encoding    = Encoding.UTF8,
                Indent      = true,
                IndentChars = "  ",
            };

            var stream = new MemoryStream();
            var writer = XmlWriter.Create(stream, xmlWriterSettings);

            writer.WriteStartDocument();
            writer.WriteDocType("svg", "-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd", null);

            writer.WriteStartElement("svg", XmlnsSvg);

            writer.WriteAttributeString("width", $"{conv.ToSvgValue(Width)}mm"); // Use AngleToSvg to get unscaled values
            writer.WriteAttributeString("height", $"{conv.ToSvgValue(Height)}mm");
            writer.WriteAttributeString("viewBox", $"0, 0, {conv.ToSvgLength(Width)}, {conv.ToSvgLength(Height)}");
            writer.WriteAttributeString("version", "1.1");

            writer.WriteAttributeString("xmlns", "xlink", null, "http://www.w3.org/1999/xlink");
            writer.WriteAttributeString("xmlns", "xml", null, "http://www.w3.org/XML/1998/namespace");
            writer.WriteAttributeString("xmlns", "sodipodi", null, XmlnsSodipodi);
            writer.WriteAttributeString("xmlns", "inkscape", null, XmlnsInkscape);

            writer.WriteStartElement("namedview", XmlnsSodipodi);
            writer.WriteAttributeString("document-units", XmlnsInkscape, "mm");
            writer.WriteEndElement();

            base.Write(writer, conv);

            writer.WriteEndElement();
            writer.Close();
            return(stream);
        }
Exemple #9
0
        internal override bool Read(XmlReader reader, SvgConverter conv)
        {
            bool   res = false;
            string sx  = reader.GetAttribute("cx") ?? "0";
            string sy  = reader.GetAttribute("cy") ?? "0";
            string sr  = reader.GetAttribute("r");

            if (!base.Read(reader, conv))
            {
                return(false);
            }

            if (!sx.IsNullOrEmpty() && !sy.IsNullOrEmpty() && !sr.IsNullOrEmpty())
            {
                Center = new Pnt2d(conv.FromSvgLength(sx), conv.FromSvgLength(sy));
                conv.Transform(ref Center);
                Radius = conv.FromSvgLength(sr);
                res    = true;
            }

            conv.PopTransform();
            return(res);
        }
Exemple #10
0
        internal virtual void Write(XmlWriter writer, SvgConverter conv)
        {
            if (!ID.IsNullOrEmpty())
            {
                writer.WriteAttributeString("id", ID);
            }

            Style?.Write(writer, conv);

            if (Transforms.Count > 0)
            {
                var sb = new StringBuilder();
                foreach (var transform in Transforms)
                {
                    transform.Write(sb, conv);
                }
                writer.WriteAttributeString("transform", sb.ToString().Trim());
            }

            foreach (var child in Children)
            {
                child.Write(writer, conv);
            }
        }
Exemple #11
0
        internal virtual bool Read(XmlReader reader, SvgConverter conv)
        {
            var transformString = reader.GetAttribute("transform");

            if (!transformString.IsNullOrEmpty())
            {
                Transforms.AddRange(SvgTransform.Create(transformString, conv));
            }

            conv.PushTransform(Transforms);
            var depth = reader.Depth;

            reader.Read();
            while (!reader.EOF && reader.Depth > depth)
            {
                if (reader.NodeType != XmlNodeType.Element)
                {
                    reader.Read();
                    continue;
                }

                SvgElement newElement = null;
                switch (reader.LocalName.ToLower())
                {
                case "g":
                    newElement = new SvgGroupElement();
                    break;

                case "circle":
                    newElement = new SvgCircleElement();
                    break;

                case "ellipse":
                    newElement = new SvgEllipseElement();
                    break;

                case "path":
                    newElement = new SvgPathElement();
                    break;

                case "line":
                    newElement = new SvgLineElement();
                    break;

                case "rect":
                    newElement = new SvgRectElement();
                    break;
                }

                if (newElement != null)
                {
                    if (newElement.Read(reader, conv))
                    {
                        Children.Add(newElement);
                    }
                }
                else
                {
                    reader.Skip();
                }
            }

            return(true);
        }
 internal virtual void Transform(SvgConverter conv)
 {
     conv.Transform(ref Start);
     conv.Transform(ref End);
 }
 internal override void Write(StringBuilder sb, SvgConverter conv)
 {
     sb.AppendFormat("translate({0},{1}) ", conv.ToSvgLength(_Tx), conv.ToSvgLength(-_Ty));
 }
        public static IEnumerable <SvgPathSegment> Create(SvgPathSegment lastSegment, string commandString, SvgConverter conv)
        {
            if (!conv.TrySplitValues(commandString.Substring(1), out var values, true))
            {
                yield break;
            }

            bool  isRelative = commandString[0] == 'm';
            int   valuePos   = 0;
            Pnt2d endPoint   = new Pnt2d();

            if (valuePos < values.Length)
            {
                endPoint = new Pnt2d(values[valuePos], values[valuePos + 1]);
                if (isRelative && lastSegment != null)
                {
                    endPoint += lastSegment.End;
                }
                yield return(new SvgPathSegMoveto(endPoint));

                valuePos += 2;
            }

            // subsequent value pairs are implicit lineto's
            while (valuePos < values.Length)
            {
                var startPoint = endPoint;
                endPoint = new Pnt2d(values[valuePos], values[valuePos + 1]);
                if (isRelative)
                {
                    endPoint += startPoint;
                }
                yield return(new SvgPathSegLineto(startPoint, endPoint));

                valuePos += 2;
            }
        }
        internal static IEnumerable <SvgPathSegment> Create(string pathString, SvgConverter conv)
        {
            SvgPathSegment lastSegment  = null;
            SvgPathSegment firstSegment = null;
            int            next         = 0;

            while (next < pathString.Length)
            {
                int start = next;
                next = pathString.IndexOfAny(_PathCommands, start + 1);
                if (next == -1)
                {
                    next = pathString.Length;
                }

                IEnumerable <SvgPathSegment> newSegments = null;
                var commandString = pathString.Substring(start, next - start);
                switch (char.ToLower(commandString[0]))
                {
                case 'm':
                    newSegments = SvgPathSegMoveto.Create(lastSegment, commandString, conv);
                    break;

                case 'l':
                case 'h':
                case 'v':
                    newSegments = SvgPathSegLineto.Create(lastSegment, commandString, conv);
                    break;

                case 'c':
                case 's':
                    newSegments = SvgPathSegCurvetoCubic.Create(lastSegment, commandString, conv);
                    break;

                case 'q':
                case 't':
                    newSegments = SvgPathSegCurvetoQuadratic.Create(lastSegment, commandString, conv);
                    break;

                case 'a':
                    newSegments = SvgPathSegArc.Create(lastSegment, commandString, conv);
                    break;

                case 'z':
                    lastSegment = SvgPathSegClosePath.Create(firstSegment, lastSegment);
                    yield return(lastSegment);

                    firstSegment = null;
                    continue;
                }

                if (newSegments == null)
                {
                    continue;
                }

                foreach (var segment in newSegments)
                {
                    if (firstSegment == null)
                    {
                        firstSegment = segment;
                    }
                    lastSegment = segment;
                    yield return(segment);
                }
            }
        }
 internal override void Write(StringBuilder sb, SvgConverter conv)
 {
     sb.AppendFormat("scale({0},{1}) ", conv.ToSvgValue(_Sx), conv.ToSvgValue(_Sy));
 }
 internal abstract Pnt2d?Write(StringBuilder sb, Pnt2d?lastPnt, SvgConverter conv);
        public static IEnumerable <SvgPathSegment> Create(SvgPathSegment lastSegment, string commandString, SvgConverter conv)
        {
            if (!conv.TrySplitValues(commandString.Substring(1), out var values, true))
            {
                yield break;
            }

            int valuePos = 0;

            while (valuePos < values.Length)
            {
                var start = lastSegment?.End ?? Pnt2d.Origin;

                Pnt2d c1;
                Pnt2d c2;
                Pnt2d end;
                if (char.ToLower(commandString[0]) == 'c')
                {
                    c1        = new Pnt2d(values[valuePos], values[valuePos + 1]);
                    c2        = new Pnt2d(values[valuePos + 2], values[valuePos + 3]);
                    end       = new Pnt2d(values[valuePos + 4], values[valuePos + 5]);
                    valuePos += 6;

                    if (char.IsLower(commandString[0]))
                    {
                        c1  += start;
                        c2  += start;
                        end += start;
                    }
                    lastSegment = new SvgPathSegCurvetoCubic(start, c1, c2, end);
                    yield return(lastSegment);
                }
                else if (char.ToLower(commandString[0]) == 's')
                {
                    c2        = new Pnt2d(values[valuePos], values[valuePos + 1]);
                    end       = new Pnt2d(values[valuePos + 2], values[valuePos + 3]);
                    valuePos += 4;

                    if (char.IsLower(commandString[0]))
                    {
                        c2  += start;
                        end += start;
                    }

                    if (lastSegment is SvgPathSegCurvetoCubic lastSeg)
                    {
                        c1 = lastSeg.C2;
                    }
                    else
                    {
                        c1 = c2;
                    }
                    lastSegment = new SvgPathSegCurvetoCubic(start, c1, c2, end);
                    yield return(lastSegment);
                }
            }
        }
 internal abstract void Write(StringBuilder sb, SvgConverter conv);
        public static IEnumerable <SvgPathSegment> Create(SvgPathSegment lastSegment, string commandString, SvgConverter conv)
        {
            if (!conv.TrySplitValues(commandString.Substring(1), out var values, false))
            {
                yield break;
            }

            int valuePos = 0;

            while (valuePos < values.Length)
            {
                var start = new Pnt2d();
                if (lastSegment != null)
                {
                    start = lastSegment.End;
                }

                double      rx    = values[0] * conv.Scale;
                double      ry    = values[1] * conv.Scale;
                double      angle = values[2];
                SvgArcSize  size  = values[3] == 0 ? SvgArcSize.Small : SvgArcSize.Large;
                SvgArcSweep sweep = values[4] == 0 ? SvgArcSweep.Negative : SvgArcSweep.Positive;
                Pnt2d       end   = new Pnt2d(values[5] * conv.Scale, values[6] * conv.Scale);
                if (char.IsLower(commandString[0]))
                {
                    end += start;
                }
                valuePos += 7;

                lastSegment = new SvgPathSegArc(start, rx, ry, angle, size, sweep, end);
                yield return(lastSegment);
            }
        }
 internal override void Transform(SvgConverter conv)
 {
     conv.Transform(ref C1);
     conv.Transform(ref C2);
     base.Transform(conv);
 }
 internal override void Write(StringBuilder sb, SvgConverter conv)
 {
     sb.AppendFormat("skewy({0}) ", conv.ToSvgValue(_Skew));
 }
        public static IEnumerable <SvgPathSegment> Create(SvgPathSegment lastSegment, string commandString, SvgConverter conv)
        {
            if (!conv.TrySplitValues(commandString.Substring(1), out var values, true))
            {
                yield break;
            }

            int valuePos = 0;

            while (valuePos < values.Length)
            {
                var start = lastSegment?.End ?? Pnt2d.Origin;

                SvgPathSegLineto segment = null;
                switch (commandString[0])
                {
                case 'L':
                    segment   = new SvgPathSegLineto(start, new Pnt2d(values[valuePos], values[valuePos + 1]));
                    valuePos += 2;
                    break;

                case 'l':
                    segment   = new SvgPathSegLineto(start, start + new Pnt2d(values[valuePos], values[valuePos + 1]));
                    valuePos += 2;
                    break;

                case 'H':
                    segment   = new SvgPathSegLineto(start, new Pnt2d(values[valuePos], start.Y));
                    valuePos += 1;
                    break;

                case 'h':
                    segment   = new SvgPathSegLineto(start, start + new Pnt2d(values[valuePos], 0));
                    valuePos += 1;
                    break;

                case 'V':
                    segment   = new SvgPathSegLineto(start, new Pnt2d(start.X, values[valuePos]));
                    valuePos += 1;
                    break;

                case 'v':
                    segment   = new SvgPathSegLineto(start, start + new Pnt2d(0, values[valuePos]));
                    valuePos += 1;
                    break;
                }
                yield return(segment);

                lastSegment = segment;
            }
        }
 internal override Pnt2d?Write(StringBuilder sb, Pnt2d?lastPnt, SvgConverter conv)
 {
     sb.AppendFormat("M{0},{1} ", conv.ToSvgLength(End.X), conv.ToSvgLength(-End.Y));
     return(End);
 }