Selaa lähdekoodia

LibWeb: Add support for CSS image-rendering property

Currently only "auto" and "pixelated" values are supported.
Maciej 3 vuotta sitten
vanhempi
commit
3e1c1c0b16

+ 16 - 0
Base/res/html/misc/image-rendering.html

@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>image-rendering property</title>
+</head>
+<body>
+    <h1>image-rendering property</h1>
+    <p>This image should be blurred:</p>
+    <img style="width: 256px" src="file:///res/graphics/buggie.png">
+    <p>This image should be blurred:</p>
+    <img style="image-rendering: auto; width: 256px" src="file:///res/graphics/buggie.png">
+    <p>This image should be pixelated:</p>
+    <img style="image-rendering: pixelated; width: 256px" src="file:///res/graphics/buggie.png">
+</body>
+</html>

+ 1 - 0
Base/res/html/misc/welcome.html

@@ -117,6 +117,7 @@
             <li><a href="float-3.html">Floating boxes with overflow=hidden</a></li>
             <li><a href="clear-1.html">Float clearing</a></li>
             <li><a href="overflow.html">Overflow</a></li>
+            <li><a href="image-rendering.html">image-rendering property</a></li>
             <li><h3>Features</h3></li>
             <li><a href="css.html">Basic functionality</a></li>
             <li><a href="colors.html">css colors</a></li>

+ 4 - 0
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<BoxShadowData> 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<BackgroundLayerData>&& layers) { m_noninherited.background_layers = move(layers); }

+ 1 - 0
Userland/Libraries/LibWeb/CSS/Identifiers.json

@@ -156,6 +156,7 @@
   "outside",
   "overline",
   "padding-box",
+  "pixelated",
   "pointer",
   "pre",
   "pre-line",

+ 8 - 0
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",

+ 13 - 0
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<StyleValue> 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: {

+ 15 - 0
Userland/Libraries/LibWeb/CSS/StyleProperties.cpp

@@ -269,6 +269,21 @@ float StyleProperties::flex_shrink() const
     return value.value()->to_number();
 }
 
+Optional<CSS::ImageRendering> 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<CSS::JustifyContent> StyleProperties::justify_content() const
 {
     auto value = property(CSS::PropertyID::JustifyContent);

+ 1 - 0
Userland/Libraries/LibWeb/CSS/StyleProperties.h

@@ -62,6 +62,7 @@ public:
     float flex_shrink() const;
     Optional<CSS::AlignItems> align_items() const;
     float opacity() const;
+    Optional<CSS::ImageRendering> image_rendering() const;
     Optional<CSS::JustifyContent> justify_content() const;
     Optional<CSS::Overflow> overflow_x() const;
     Optional<CSS::Overflow> overflow_y() const;

+ 5 - 0
Userland/Libraries/LibWeb/CSS/StyleValue.h

@@ -140,6 +140,11 @@ enum class Float {
     Right,
 };
 
+enum class ImageRendering {
+    Auto,
+    Pixelated
+};
+
 enum class JustifyContent {
     FlexStart,
     FlexEnd,

+ 5 - 1
Userland/Libraries/LibWeb/Layout/ImageBox.cpp

@@ -7,6 +7,8 @@
 #include <LibGfx/FontDatabase.h>
 #include <LibGfx/Painter.h>
 #include <LibGfx/StylePainter.h>
+#include <LibWeb/CSS/StyleValue.h>
+#include <LibWeb/CSS/ValueID.h>
 #include <LibWeb/HTML/BrowsingContext.h>
 #include <LibWeb/Layout/ImageBox.h>
 
@@ -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);
         }
     }
 }

+ 4 - 0
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());