LibWeb/SVG: Add serialization of Paths

CSS users (like the `path()` function) need to be able to serialize
their path data in a canonical form.
This commit is contained in:
Sam Atkins 2025-07-17 16:28:47 +01:00 committed by Alexander Kalenik
commit 8538186ca5
Notes: github-actions[bot] 2025-07-17 18:00:37 +00:00
2 changed files with 61 additions and 0 deletions

View file

@ -8,11 +8,54 @@
#include <AK/Debug.h>
#include <AK/Span.h>
#include <AK/String.h>
#include <LibGfx/Path.h>
#include <LibWeb/SVG/Path.h>
namespace Web::SVG {
void PathInstruction::serialize(StringBuilder& builder) const
{
switch (type) {
case PathInstructionType::Move:
builder.append(absolute ? 'M' : 'm');
break;
case PathInstructionType::ClosePath:
// NB: This is always canonicalized as Z, not z.
builder.append('Z');
break;
case PathInstructionType::Line:
builder.append(absolute ? 'L' : 'l');
break;
case PathInstructionType::HorizontalLine:
builder.append(absolute ? 'H' : 'h');
break;
case PathInstructionType::VerticalLine:
builder.append(absolute ? 'V' : 'v');
break;
case PathInstructionType::Curve:
builder.append(absolute ? 'C' : 'c');
break;
case PathInstructionType::SmoothCurve:
builder.append(absolute ? 'S' : 's');
break;
case PathInstructionType::QuadraticBezierCurve:
builder.append(absolute ? 'Q' : 'q');
break;
case PathInstructionType::SmoothQuadraticBezierCurve:
builder.append(absolute ? 'T' : 't');
break;
case PathInstructionType::EllipticalArc:
builder.append(absolute ? 'A' : 'a');
break;
case PathInstructionType::Invalid:
break;
}
for (auto const& value : data)
builder.appendff(" {}", value);
}
void PathInstruction::dump() const
{
switch (type) {
@ -245,4 +288,19 @@ Gfx::Path Path::to_gfx_path() const
return path;
}
String Path::serialize() const
{
StringBuilder builder;
bool first = true;
for (auto const& instruction : m_instructions) {
if (first) {
first = false;
} else {
builder.append(' ');
}
instruction.serialize(builder);
}
return builder.to_string_without_validation();
}
}

View file

@ -36,6 +36,8 @@ struct PathInstruction {
bool operator==(PathInstruction const&) const = default;
void serialize(StringBuilder&) const;
void dump() const;
};
@ -50,6 +52,7 @@ public:
ReadonlySpan<PathInstruction> instructions() const { return m_instructions; }
[[nodiscard]] Gfx::Path to_gfx_path() const;
String serialize() const;
bool operator==(Path const&) const = default;