From 8659bddce80321bcb7b2e1059de406b0d0f7e205 Mon Sep 17 00:00:00 2001 From: Jurjen Biewenga Date: Tue, 26 Sep 2017 22:54:07 +0200 Subject: [PATCH] Implemented path markup for Q S and T --- .../Media/PathMarkupParser.cs | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Media/PathMarkupParser.cs b/src/Avalonia.Visuals/Media/PathMarkupParser.cs index 145013d76b..9aedf314ce 100644 --- a/src/Avalonia.Visuals/Media/PathMarkupParser.cs +++ b/src/Avalonia.Visuals/Media/PathMarkupParser.cs @@ -21,7 +21,10 @@ namespace Avalonia.Media { 'L', Command.Line }, { 'H', Command.HorizontalLine }, { 'V', Command.VerticalLine }, + { 'Q', Command.QuadraticBezierCurve }, + { 'T', Command.SmoothQuadraticBezierCurve }, { 'C', Command.CubicBezierCurve }, + { 'S', Command.SmoothCubicBezierCurve }, { 'A', Command.Arc }, { 'Z', Command.Close }, }; @@ -55,6 +58,9 @@ namespace Avalonia.Media HorizontalLine, VerticalLine, CubicBezierCurve, + QuadraticBezierCurve, + SmoothCubicBezierCurve, + SmoothQuadraticBezierCurve, Arc, Close, } @@ -71,7 +77,8 @@ namespace Avalonia.Media { Command command = Command.None; Point point = new Point(); - bool relative = false; + bool relative = false; + Point? previousControlPoint = null; while (ReadCommand(reader, ref command, ref relative)) { @@ -79,6 +86,7 @@ namespace Avalonia.Media { case Command.FillRule: _context.SetFillRule(ReadFillRule(reader)); + previousControlPoint = null; break; case Command.Move: @@ -90,11 +98,13 @@ namespace Avalonia.Media point = ReadPoint(reader, point, relative); _context.BeginFigure(point, true); openFigure = true; + previousControlPoint = null; break; case Command.Line: point = ReadPoint(reader, point, relative); _context.LineTo(point); + previousControlPoint = null; break; case Command.HorizontalLine: @@ -108,6 +118,7 @@ namespace Avalonia.Media } _context.LineTo(point); + previousControlPoint = null; break; case Command.VerticalLine: @@ -121,18 +132,57 @@ namespace Avalonia.Media } _context.LineTo(point); + previousControlPoint = null; break; + case Command.QuadraticBezierCurve: + { + Point handle = ReadPoint(reader, point, relative); + previousControlPoint = handle; + ReadSeparator(reader); + point = ReadPoint(reader, point, relative); + _context.QuadraticBezierTo(handle, point); + break; + } + + case Command.SmoothQuadraticBezierCurve: + { + Point end = ReadPoint(reader, point, relative); + + if(previousControlPoint != null) + previousControlPoint = MirrorControlPoint((Point)previousControlPoint, point); + + _context.QuadraticBezierTo(previousControlPoint ?? point, end); + point = end; + break; + } + case Command.CubicBezierCurve: { Point point1 = ReadPoint(reader, point, relative); ReadSeparator(reader); Point point2 = ReadPoint(reader, point, relative); + previousControlPoint = point2; ReadSeparator(reader); point = ReadPoint(reader, point, relative); _context.CubicBezierTo(point1, point2, point); break; } + + case Command.SmoothCubicBezierCurve: + { + Point point2 = ReadPoint(reader, point, relative); + ReadSeparator(reader); + Point end = ReadPoint(reader, point, relative); + + if(previousControlPoint != null) + previousControlPoint = MirrorControlPoint((Point)previousControlPoint, point); + + _context.CubicBezierTo(previousControlPoint ?? point, point2, end); + previousControlPoint = point2; + point = end; + break; + } case Command.Arc: { @@ -147,12 +197,14 @@ namespace Avalonia.Media point = ReadPoint(reader, point, relative); _context.ArcTo(point, size, rotationAngle, isLargeArc, sweepDirection); + previousControlPoint = null; break; } case Command.Close: _context.EndFigure(true); openFigure = false; + previousControlPoint = null; break; default: @@ -167,6 +219,14 @@ namespace Avalonia.Media } } + private Point MirrorControlPoint(Point controlPoint, Point center) + { + Point dir = (controlPoint - center); + double xOffset = center.X - controlPoint.X, yOffset = center.Y - controlPoint.Y; +// return new Point(center.X - xOffset, center.Y - yOffset); + return center + -dir; + } + private static bool ReadCommand( StringReader reader, ref Command command, @@ -243,6 +303,9 @@ namespace Avalonia.Media (c == 'E' && !readExponent) || char.IsDigit(c)) { + if (b.Length != 0 && !readExponent && c == '-') + break; + b.Append(c); reader.Read();