1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 19:37:36 +00:00

LibWeb: Add SVG transform parsing

This parses SVG transforms using the syntax from CSS Transforms
Module Level 1. Note: This looks very similar to CSS tranforms, but
the syntax is not compatible. For example, SVG rotate() is
rotate(<a> <x> <y>) where all parameters are unitless numbers whereas
CSS rotate() is rotate(<angle> unit) along with separate rotateX/Y/Z().

(At the same time AttributeParser is updated to use GenericLexer which
makes for easier string matching).

There is work needed for error handling (which AttributeParser does not
deal with very gracefully right now).
This commit is contained in:
MacDue 2023-04-10 12:22:06 +01:00 committed by Andreas Kling
parent b8d1fae31f
commit 62f087bd56
2 changed files with 156 additions and 8 deletions

View file

@ -7,6 +7,8 @@
#pragma once
#include <AK/GenericLexer.h>
#include <AK/Variant.h>
#include <AK/Vector.h>
#include <LibGfx/Point.h>
@ -32,6 +34,39 @@ struct PathInstruction {
Vector<float> data;
};
struct Transform {
struct Translate {
float x;
float y;
};
struct Scale {
float x;
float y;
};
struct Rotate {
float a;
float x;
float y;
};
struct SkewX {
float a;
};
struct SkewY {
float a;
};
struct Matrix {
float a;
float b;
float c;
float d;
float e;
float f;
};
using Operation = Variant<Translate, Scale, Rotate, SkewX, SkewY, Matrix>;
Operation operation;
};
class AttributeParser final {
public:
~AttributeParser() = default;
@ -41,6 +76,7 @@ public:
static Optional<float> parse_positive_length(StringView input);
static Vector<Gfx::FloatPoint> parse_points(StringView input);
static Vector<PathInstruction> parse_path_data(StringView input);
static Optional<Vector<Transform>> parse_transform(StringView input);
private:
AttributeParser(StringView source);
@ -57,6 +93,8 @@ private:
void parse_smooth_quadratic_bezier_curveto();
void parse_elliptical_arc();
Optional<Vector<Transform>> parse_transform();
float parse_length();
float parse_coordinate();
Vector<float> parse_coordinate_pair();
@ -79,12 +117,11 @@ private:
bool match_length() const;
bool match(char c) const { return !done() && ch() == c; }
bool done() const { return m_cursor >= m_source.length(); }
char ch() const { return m_source[m_cursor]; }
char consume() { return m_source[m_cursor++]; }
bool done() const { return m_lexer.is_eof(); }
char ch() const { return m_lexer.peek(); }
char consume() { return m_lexer.consume(); }
StringView m_source;
size_t m_cursor { 0 };
GenericLexer m_lexer;
Vector<PathInstruction> m_instructions;
};