mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 06:07:34 +00:00
LibWeb: Implement SVG preserveAspectRatio
attribute
This attribute is used to define how the viewBox should be scaled. Previously the behaviour implemented was that of "xMidYMid meet", now all of them work (expect none :P). With this the Discord login backend is now correctly scaled/positioned. This also brings our SVG code a little closer to the spec! With spec comments and all :^) (Minor non-visible update to layout tests)
This commit is contained in:
parent
5a12e9f222
commit
5df4e64eb7
6 changed files with 205 additions and 25 deletions
|
@ -397,16 +397,77 @@ int AttributeParser::parse_sign()
|
|||
return 1;
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-transforms/#svg-syntax
|
||||
Optional<Vector<Transform>> AttributeParser::parse_transform()
|
||||
static bool whitespace(char c)
|
||||
{
|
||||
// wsp:
|
||||
// Either a U+000A LINE FEED, U+000D CARRIAGE RETURN, U+0009 CHARACTER TABULATION, or U+0020 SPACE.
|
||||
auto wsp = [](char c) {
|
||||
return AK::first_is_one_of(c, '\n', '\r', '\t', '\f', ' ');
|
||||
};
|
||||
return AK::first_is_one_of(c, '\n', '\r', '\t', '\f', ' ');
|
||||
}
|
||||
|
||||
// https://svgwg.org/svg2-draft/coords.html#PreserveAspectRatioAttribute
|
||||
Optional<PreserveAspectRatio> AttributeParser::parse_preserve_aspect_ratio(StringView input)
|
||||
{
|
||||
// <align> <meetOrSlice>?
|
||||
GenericLexer lexer { input };
|
||||
lexer.ignore_while(whitespace);
|
||||
auto align_string = lexer.consume_until(whitespace);
|
||||
if (align_string.is_empty())
|
||||
return {};
|
||||
lexer.ignore_while(whitespace);
|
||||
auto meet_or_slice_string = lexer.consume_until(whitespace);
|
||||
|
||||
// <align> =
|
||||
// none
|
||||
// | xMinYMin | xMidYMin | xMaxYMin
|
||||
// | xMinYMid | xMidYMid | xMaxYMid
|
||||
// | xMinYMax | xMidYMax | xMaxYMax
|
||||
auto align = [&]() -> Optional<PreserveAspectRatio::Align> {
|
||||
if (align_string == "none"sv)
|
||||
return PreserveAspectRatio::Align::None;
|
||||
if (align_string == "xMinYMin"sv)
|
||||
return PreserveAspectRatio::Align::xMinYMin;
|
||||
if (align_string == "xMidYMin"sv)
|
||||
return PreserveAspectRatio::Align::xMidYMin;
|
||||
if (align_string == "xMaxYMin"sv)
|
||||
return PreserveAspectRatio::Align::xMaxYMin;
|
||||
if (align_string == "xMinYMid"sv)
|
||||
return PreserveAspectRatio::Align::xMinYMid;
|
||||
if (align_string == "xMidYMid"sv)
|
||||
return PreserveAspectRatio::Align::xMidYMid;
|
||||
if (align_string == "xMaxYMid"sv)
|
||||
return PreserveAspectRatio::Align::xMaxYMid;
|
||||
if (align_string == "xMinYMax"sv)
|
||||
return PreserveAspectRatio::Align::xMinYMax;
|
||||
if (align_string == "xMidYMax"sv)
|
||||
return PreserveAspectRatio::Align::xMidYMax;
|
||||
if (align_string == "xMaxYMax"sv)
|
||||
return PreserveAspectRatio::Align::xMaxYMax;
|
||||
return {};
|
||||
}();
|
||||
|
||||
if (!align.has_value())
|
||||
return {};
|
||||
|
||||
// <meetOrSlice> = meet | slice
|
||||
auto meet_or_slice = [&]() -> Optional<PreserveAspectRatio::MeetOrSlice> {
|
||||
if (meet_or_slice_string.is_empty() || meet_or_slice_string == "meet"sv)
|
||||
return PreserveAspectRatio::MeetOrSlice::Meet;
|
||||
if (meet_or_slice_string == "slice"sv)
|
||||
return PreserveAspectRatio::MeetOrSlice::Slice;
|
||||
return {};
|
||||
}();
|
||||
|
||||
if (!meet_or_slice.has_value())
|
||||
return {};
|
||||
|
||||
return PreserveAspectRatio { *align, *meet_or_slice };
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-transforms/#svg-syntax
|
||||
Optional<Vector<Transform>> AttributeParser::parse_transform()
|
||||
{
|
||||
auto consume_whitespace = [&] {
|
||||
m_lexer.consume_while(wsp);
|
||||
m_lexer.ignore_while(whitespace);
|
||||
};
|
||||
|
||||
auto consume_comma_whitespace = [&] {
|
||||
|
|
|
@ -67,6 +67,27 @@ struct Transform {
|
|||
Operation operation;
|
||||
};
|
||||
|
||||
struct PreserveAspectRatio {
|
||||
enum class Align {
|
||||
None,
|
||||
xMinYMin,
|
||||
xMidYMin,
|
||||
xMaxYMin,
|
||||
xMinYMid,
|
||||
xMidYMid,
|
||||
xMaxYMid,
|
||||
xMinYMax,
|
||||
xMidYMax,
|
||||
xMaxYMax
|
||||
};
|
||||
enum class MeetOrSlice {
|
||||
Meet,
|
||||
Slice
|
||||
};
|
||||
Align align { Align::xMidYMid };
|
||||
MeetOrSlice meet_or_slice { MeetOrSlice::Meet };
|
||||
};
|
||||
|
||||
class AttributeParser final {
|
||||
public:
|
||||
~AttributeParser() = default;
|
||||
|
@ -77,6 +98,7 @@ public:
|
|||
static Vector<Gfx::FloatPoint> parse_points(StringView input);
|
||||
static Vector<PathInstruction> parse_path_data(StringView input);
|
||||
static Optional<Vector<Transform>> parse_transform(StringView input);
|
||||
static Optional<PreserveAspectRatio> parse_preserve_aspect_ratio(StringView input);
|
||||
|
||||
private:
|
||||
AttributeParser(StringView source);
|
||||
|
|
|
@ -73,6 +73,8 @@ void SVGSVGElement::parse_attribute(DeprecatedFlyString const& name, DeprecatedS
|
|||
|
||||
if (name.equals_ignoring_ascii_case(SVG::AttributeNames::viewBox))
|
||||
m_view_box = try_parse_view_box(value);
|
||||
if (name.equals_ignoring_ascii_case(SVG::AttributeNames::preserveAspectRatio))
|
||||
m_preserve_aspect_ratio = AttributeParser::parse_preserve_aspect_ratio(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibWeb/SVG/AttributeParser.h>
|
||||
#include <LibWeb/SVG/SVGGraphicsElement.h>
|
||||
#include <LibWeb/SVG/ViewBox.h>
|
||||
|
||||
|
@ -24,6 +25,7 @@ public:
|
|||
virtual bool is_svg_container() const override { return true; }
|
||||
|
||||
Optional<ViewBox> const& view_box() const { return m_view_box; }
|
||||
Optional<PreserveAspectRatio> const& preserve_aspect_ratio() const { return m_preserve_aspect_ratio; }
|
||||
|
||||
private:
|
||||
SVGSVGElement(DOM::Document&, DOM::QualifiedName);
|
||||
|
@ -35,6 +37,7 @@ private:
|
|||
virtual void parse_attribute(DeprecatedFlyString const& name, DeprecatedString const& value) override;
|
||||
|
||||
Optional<ViewBox> m_view_box;
|
||||
Optional<PreserveAspectRatio> m_preserve_aspect_ratio;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue