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); } }
public static SvgPathSegClosePath Create(SvgPathSegment firstSegment, SvgPathSegment lastSegment) { var seg = new SvgPathSegClosePath { Start = lastSegment?.Start ?? Pnt2d.Origin, End = firstSegment?.End ?? Pnt2d.Origin }; return(seg); }
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); } } }
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 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); }
//-------------------------------------------------------------------------------------------------- protected void AddToPath(SvgPathSegment segment) { if (CurrentPath == null) { InitPathExport(); _PathStart = segment.Start; CurrentPath.Segments.Add(new SvgPathSegMoveto(segment.Start)); } else { // If Segment-Start does not match current subpath end... if (!_AreEqual(_PathPosition, segment.Start)) { if (_AreEqual(_PathStart, segment.End)) { // Segment-End matches path start, but Segment-Start // not to current subpath end, so insert on top CurrentPath.Segments.Insert(_SubPathStartIndex + 1, segment); CurrentPath.Segments[_SubPathStartIndex] = new SvgPathSegMoveto(segment.Start); _PathStart = segment.Start; return; } else { // Both Segment-Points do not match to any side of the path // Start new subpath ClosePath(); _SubPathStartIndex = CurrentPath.Segments.Count; CurrentPath.Segments.Add(new SvgPathSegMoveto(segment.Start)); _PathStart = segment.Start; } } } // Append to current / just created subpath _PathPosition = segment.End; CurrentPath.Segments.Add(segment); }
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); } } }