Browse Source

Implemented path markup for Q S and T

Jurjen Biewenga 8 years ago
parent
commit
8659bddce8
1 changed files with 64 additions and 1 deletions
  1. 64 1
      src/Avalonia.Visuals/Media/PathMarkupParser.cs

+ 64 - 1
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();