/// <summary> /// Parses a series of points. /// </summary> /// <param name="lexer">The lexer.</param> /// <param name="diagnostics">The diagnostics.</param> /// <returns>The list of points.</returns> public static List <Vector2> ParsePoints(SvgPathDataLexer lexer, IDiagnosticHandler diagnostics) { var points = new List <Vector2>(); while (lexer.Type != TokenType.EndOfContent) { // Keep parsing vectors lexer.ParseVector(diagnostics, out var p); points.Add(p); } return(points); }
/// <summary> /// Parse Svg path. /// </summary> /// <param name="lexer">The lexer.</param> /// <param name="b">The path builder.</param> /// <param name="diagnostics">The diagnostics message handler.</param> public static void Parse(SvgPathDataLexer lexer, PathBuilder b, IDiagnosticHandler diagnostics) { while (lexer.Type != TokenType.EndOfContent) { Vector2 h1, h2, p; double d; bool result = true; if (!lexer.Branch(TokenType.Command, out var cmd)) { diagnostics?.Post(new TokenDiagnosticMessage(cmd, SeverityLevel.Error, "DW001", $"Could not recognize the SVG path command '{cmd.Content}'")); break; } switch (cmd.Content.Span[0]) { case 'M': if (!lexer.ParseVector(diagnostics, out p)) { lexer.Skip(~TokenType.Command); continue; } b.MoveTo(p); while (lexer.TryParseVector(diagnostics, new(), out p)) { b.LineTo(p); } break; case 'm': if (!lexer.ParseVector(diagnostics, out p)) { lexer.Skip(~TokenType.Command); continue; } b.Move(p); while (lexer.TryParseVector(diagnostics, new(), out p)) { b.Line(p); } break; case 'L': if (!lexer.ParseVector(diagnostics, out p)) { lexer.Skip(~TokenType.Command); continue; } b.LineTo(p); while (lexer.TryParseVector(diagnostics, new(), out p)) { b.LineTo(p); } break; case 'l': if (!lexer.ParseVector(diagnostics, out p)) { lexer.Skip(~TokenType.Command); continue; } b.Line(p); while (lexer.TryParseVector(diagnostics, new(), out p)) { b.Line(p); } break; case 'H': if (!lexer.ParseCoordinate(diagnostics, out d)) { lexer.Skip(~TokenType.Command); continue; } b.HorizontalTo(d); while (lexer.TryParseCoordinate(diagnostics, 0.0, out d)) { b.HorizontalTo(d); } break; case 'h': if (!lexer.ParseCoordinate(diagnostics, out d)) { lexer.Skip(~TokenType.Command); continue; } b.Horizontal(d); while (lexer.TryParseCoordinate(diagnostics, 0.0, out d)) { b.Horizontal(d); } break; case 'V': if (!lexer.ParseCoordinate(diagnostics, out d)) { lexer.Skip(~TokenType.Command); continue; } b.VerticalTo(d); while (lexer.TryParseCoordinate(diagnostics, 0.0, out d)) { b.VerticalTo(d); } break; case 'v': if (!lexer.ParseCoordinate(diagnostics, out d)) { lexer.Skip(~TokenType.Command); continue; } b.Vertical(d); while (lexer.TryParseCoordinate(diagnostics, 0.0, out d)) { b.Vertical(d); } break; case 'C': result &= lexer.ParseVector(diagnostics, out h1); result &= lexer.ParseVector(diagnostics, out h2); result &= lexer.ParseVector(diagnostics, out p); if (!result) { lexer.Skip(~TokenType.Command); continue; } b.CurveTo(h1, h2, p); while (lexer.TryParseVector(diagnostics, new(), out h1) && lexer.ParseVector(diagnostics, out h2) && lexer.ParseVector(diagnostics, out p)) { b.CurveTo(h1, h2, p); } break; case 'c': result &= lexer.ParseVector(diagnostics, out h1); result &= lexer.ParseVector(diagnostics, out h2); result &= lexer.ParseVector(diagnostics, out p); if (!result) { lexer.Skip(~TokenType.Command); continue; } b.Curve(h1, h2, p); while (lexer.TryParseVector(diagnostics, new(), out h1) && lexer.ParseVector(diagnostics, out h2) && lexer.ParseVector(diagnostics, out p)) { b.Curve(h1, h2, p); } break; case 'S': result &= lexer.ParseVector(diagnostics, out h2); result &= lexer.ParseVector(diagnostics, out p); if (!result) { lexer.Skip(~TokenType.Command); continue; } b.SmoothTo(h2, p); while (lexer.TryParseVector(diagnostics, new(), out h2) && lexer.ParseVector(diagnostics, out p)) { b.SmoothTo(h2, p); } break; case 's': result &= lexer.ParseVector(diagnostics, out h2); result &= lexer.ParseVector(diagnostics, out p); if (!result) { lexer.Skip(~TokenType.Command); continue; } b.Smooth(h2, p); while (lexer.TryParseVector(diagnostics, new(), out h2) && lexer.ParseVector(diagnostics, out p)) { b.Smooth(h2, p); } break; case 'Q': result &= lexer.ParseVector(diagnostics, out h1); result &= lexer.ParseVector(diagnostics, out p); if (!result) { lexer.Skip(~TokenType.Command); continue; } b.QuadCurveTo(h1, p); while (lexer.TryParseVector(diagnostics, new(), out h1) && lexer.ParseVector(diagnostics, out p)) { b.QuadCurveTo(h1, p); } break; case 'q': result &= lexer.ParseVector(diagnostics, out h1); result &= lexer.ParseVector(diagnostics, out p); if (!result) { lexer.Skip(~TokenType.Command); continue; } b.QuadCurve(h1, p); while (lexer.TryParseVector(diagnostics, new(), out h1) && lexer.ParseVector(diagnostics, out p)) { b.QuadCurve(h1, p); } break; case 'T': if (!lexer.ParseVector(diagnostics, out p)) { lexer.Skip(~TokenType.Command); continue; } b.SmoothQuadTo(p); while (lexer.TryParseVector(diagnostics, new(), out p)) { b.SmoothQuadTo(p); } break; case 't': if (!lexer.ParseVector(diagnostics, out p)) { lexer.Skip(~TokenType.Command); continue; } b.SmoothQuad(p); while (lexer.TryParseVector(diagnostics, new(), out p)) { b.SmoothQuad(p); } break; case 'z': case 'Z': b.Close(); break; default: diagnostics?.Post(new DiagnosticMessage(SeverityLevel.Error, "DRAW001", $"Could not recognize path command '{cmd}'.")); break; } } }