From 3e1c1c0b16a5af859172d46a361f3f995e87820b Mon Sep 17 00:00:00 2001 From: Maciej Date: Fri, 18 Feb 2022 12:21:27 +0100 Subject: [PATCH] LibWeb: Add support for CSS image-rendering property Currently only "auto" and "pixelated" values are supported. --- Base/res/html/misc/image-rendering.html | 16 ++++++++++++++++ Base/res/html/misc/welcome.html | 1 + Userland/Libraries/LibWeb/CSS/ComputedValues.h | 4 ++++ Userland/Libraries/LibWeb/CSS/Identifiers.json | 1 + Userland/Libraries/LibWeb/CSS/Properties.json | 8 ++++++++ .../LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp | 13 +++++++++++++ .../Libraries/LibWeb/CSS/StyleProperties.cpp | 15 +++++++++++++++ Userland/Libraries/LibWeb/CSS/StyleProperties.h | 1 + Userland/Libraries/LibWeb/CSS/StyleValue.h | 5 +++++ Userland/Libraries/LibWeb/Layout/ImageBox.cpp | 6 +++++- Userland/Libraries/LibWeb/Layout/Node.cpp | 4 ++++ 11 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 Base/res/html/misc/image-rendering.html diff --git a/Base/res/html/misc/image-rendering.html b/Base/res/html/misc/image-rendering.html new file mode 100644 index 0000000000..d0d2641052 --- /dev/null +++ b/Base/res/html/misc/image-rendering.html @@ -0,0 +1,16 @@ + + + + + image-rendering property + + +

image-rendering property

+

This image should be blurred:

+ +

This image should be blurred:

+ +

This image should be pixelated:

+ + + diff --git a/Base/res/html/misc/welcome.html b/Base/res/html/misc/welcome.html index e4518ad0eb..3cd6292dd1 100644 --- a/Base/res/html/misc/welcome.html +++ b/Base/res/html/misc/welcome.html @@ -117,6 +117,7 @@
  • Floating boxes with overflow=hidden
  • Float clearing
  • Overflow
  • +
  • image-rendering property
  • Features

  • Basic functionality
  • css colors
  • diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h index b82d66099c..b7e73e80bb 100644 --- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h @@ -29,6 +29,7 @@ public: static CSS::ListStyleType list_style_type() { return CSS::ListStyleType::Disc; } static CSS::FlexDirection flex_direction() { return CSS::FlexDirection::Row; } static CSS::FlexWrap flex_wrap() { return CSS::FlexWrap::Nowrap; } + static CSS::ImageRendering image_rendering() { return CSS::ImageRendering::Auto; } static CSS::JustifyContent justify_content() { return CSS::JustifyContent::FlexStart; } static CSS::AlignItems align_items() { return CSS::AlignItems::Stretch; } static CSS::Overflow overflow() { return CSS::Overflow::Visible; } @@ -105,6 +106,7 @@ public: float flex_shrink() const { return m_noninherited.flex_shrink; } CSS::AlignItems align_items() const { return m_noninherited.align_items; } float opacity() const { return m_noninherited.opacity; } + CSS::ImageRendering image_rendering() const { return m_inherited.image_rendering; } CSS::JustifyContent justify_content() const { return m_noninherited.justify_content; } Vector const& box_shadow() const { return m_noninherited.box_shadow; } CSS::BoxSizing box_sizing() const { return m_noninherited.box_sizing; } @@ -155,6 +157,7 @@ protected: struct { Color color { InitialValues::color() }; CSS::Cursor cursor { InitialValues::cursor() }; + CSS::ImageRendering image_rendering { InitialValues::image_rendering() }; CSS::PointerEvents pointer_events { InitialValues::pointer_events() }; CSS::TextAlign text_align { InitialValues::text_align() }; CSS::TextTransform text_transform { InitialValues::text_transform() }; @@ -216,6 +219,7 @@ class MutableComputedValues final : public ComputedValues { public: void set_color(const Color& color) { m_inherited.color = color; } void set_cursor(CSS::Cursor cursor) { m_inherited.cursor = cursor; } + void set_image_rendering(CSS::ImageRendering value) { m_inherited.image_rendering = value; } void set_pointer_events(CSS::PointerEvents value) { m_inherited.pointer_events = value; } void set_background_color(const Color& color) { m_noninherited.background_color = color; } void set_background_layers(Vector&& layers) { m_noninherited.background_layers = move(layers); } diff --git a/Userland/Libraries/LibWeb/CSS/Identifiers.json b/Userland/Libraries/LibWeb/CSS/Identifiers.json index 65f1753af4..5a2451a5af 100644 --- a/Userland/Libraries/LibWeb/CSS/Identifiers.json +++ b/Userland/Libraries/LibWeb/CSS/Identifiers.json @@ -156,6 +156,7 @@ "outside", "overline", "padding-box", + "pixelated", "pointer", "pre", "pre-line", diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index 9bb799a67e..76b2980fee 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -748,6 +748,14 @@ "unitless-length" ] }, + "image-rendering": { + "inherited": true, + "initial": "auto", + "valid-identifiers": [ + "auto", + "pixelated" + ] + }, "justify-content": { "inherited": false, "initial": "flex-start", diff --git a/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp b/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp index 752c637665..fc496310db 100644 --- a/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp +++ b/Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp @@ -358,6 +358,17 @@ static CSS::ValueID to_css_value_id(CSS::FlexWrap value) VERIFY_NOT_REACHED(); } +static CSS::ValueID to_css_value_id(CSS::ImageRendering value) +{ + switch (value) { + case ImageRendering::Auto: + return CSS::ValueID::Auto; + case ImageRendering::Pixelated: + return CSS::ValueID::Pixelated; + } + VERIFY_NOT_REACHED(); +} + static CSS::ValueID to_css_value_id(CSS::JustifyContent value) { switch (value) { @@ -515,6 +526,8 @@ RefPtr ResolvedCSSStyleDeclaration::style_value_for_property(Layout: return NumericStyleValue::create_float(layout_node.computed_values().flex_shrink()); case CSS::PropertyID::Opacity: return NumericStyleValue::create_float(layout_node.computed_values().opacity()); + case CSS::PropertyID::ImageRendering: + return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().image_rendering())); case CSS::PropertyID::JustifyContent: return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().justify_content())); case CSS::PropertyID::BoxShadow: { diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index e86721850d..1ae062b8d1 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -269,6 +269,21 @@ float StyleProperties::flex_shrink() const return value.value()->to_number(); } +Optional StyleProperties::image_rendering() const +{ + auto value = property(CSS::PropertyID::ImageRendering); + if (!value.has_value()) + return {}; + switch (value.value()->to_identifier()) { + case CSS::ValueID::Auto: + return CSS::ImageRendering::Auto; + case CSS::ValueID::Pixelated: + return CSS::ImageRendering::Pixelated; + default: + return {}; + } +} + Optional StyleProperties::justify_content() const { auto value = property(CSS::PropertyID::JustifyContent); diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.h b/Userland/Libraries/LibWeb/CSS/StyleProperties.h index 09263ce1ba..f0790a04ac 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.h +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.h @@ -62,6 +62,7 @@ public: float flex_shrink() const; Optional align_items() const; float opacity() const; + Optional image_rendering() const; Optional justify_content() const; Optional overflow_x() const; Optional overflow_y() const; diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 88f320c8c2..03bc0c48e6 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -140,6 +140,11 @@ enum class Float { Right, }; +enum class ImageRendering { + Auto, + Pixelated +}; + enum class JustifyContent { FlexStart, FlexEnd, diff --git a/Userland/Libraries/LibWeb/Layout/ImageBox.cpp b/Userland/Libraries/LibWeb/Layout/ImageBox.cpp index c1123467f8..e9dc183fd7 100644 --- a/Userland/Libraries/LibWeb/Layout/ImageBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/ImageBox.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -91,7 +93,9 @@ void ImageBox::paint(PaintContext& context, PaintPhase phase) alt = image_element.src(); context.painter().draw_text(enclosing_int_rect(absolute_rect()), alt, Gfx::TextAlignment::Center, computed_values().color(), Gfx::TextElision::Right); } else if (auto bitmap = m_image_loader.bitmap(m_image_loader.current_frame_index())) { - context.painter().draw_scaled_bitmap(rounded_int_rect(absolute_rect()), *bitmap, bitmap->rect(), 1.0f, Gfx::Painter::ScalingMode::BilinearBlend); + // FIXME: Support 'crisp-edges', 'smooth' and 'high-quality' + auto scaling_mode = computed_values().image_rendering() == CSS::ImageRendering::Pixelated ? Gfx::Painter::ScalingMode::NearestNeighbor : Gfx::Painter::ScalingMode::BilinearBlend; + context.painter().draw_scaled_bitmap(rounded_int_rect(absolute_rect()), *bitmap, bitmap->rect(), 1.0f, scaling_mode); } } } diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 98239a1f37..d8da6e9be3 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -396,6 +396,10 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style) if (cursor.has_value()) computed_values.set_cursor(cursor.value()); + auto image_rendering = specified_style.image_rendering(); + if (image_rendering.has_value()) + computed_values.set_image_rendering(image_rendering.value()); + auto pointer_events = specified_style.pointer_events(); if (pointer_events.has_value()) computed_values.set_pointer_events(pointer_events.value());