summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/Painting
diff options
context:
space:
mode:
authorMacDue <macdue@dueutil.tech>2022-07-12 00:30:35 +0100
committerSam Atkins <atkinssj@gmail.com>2022-07-17 20:11:38 +0100
commitcbc04a6285a401d2858d93a25a12367f243ecb05 (patch)
tree099d9c6cee2ee499c92ddeaad9be7a4b43061658 /Userland/Libraries/LibWeb/Painting
parentee7e9e7c86b34ebc7c9439e84dd185f383d7a998 (diff)
downloadserenity-cbc04a6285a401d2858d93a25a12367f243ecb05.zip
LibWeb: Support painting simple linear-gradients
This is just a quick test that everything is working. Currently it paints the gradients with the existing painter.fill_rect_with_gradient(). This can only handle two-color orthogonal gradients.
Diffstat (limited to 'Userland/Libraries/LibWeb/Painting')
-rw-r--r--Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp53
1 files changed, 52 insertions, 1 deletions
diff --git a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp
index 713b9044c3..77ab00bb31 100644
--- a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp
+++ b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
+ * Copyright (c) 2022, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -15,6 +16,43 @@
namespace Web::Painting {
+struct GfxGradient {
+ Gfx::Orientation orientation;
+ Gfx::Color color_a;
+ Gfx::Color color_b;
+};
+
+static Optional<GfxGradient> linear_gradient_to_gfx_gradient(CSS::LinearGradientStyleValue const& linear_gradient, Gfx::FloatRect const& background_rect)
+{
+ if (linear_gradient.color_stop_list().size() != 2)
+ return {};
+
+ auto angle = round_to<int>(linear_gradient.angle(background_rect));
+ auto color_a = linear_gradient.color_stop_list()[0].color_stop.color;
+ auto color_b = linear_gradient.color_stop_list()[1].color_stop.color;
+ auto orientation = [&]() -> Optional<Gfx::Orientation> {
+ switch (angle) {
+ case 0:
+ swap(color_a, color_b);
+ [[fallthrough]];
+ case 180:
+ return Gfx::Orientation::Vertical;
+ case 270:
+ swap(color_a, color_b);
+ [[fallthrough]];
+ case 90:
+ return Gfx::Orientation::Horizontal;
+ default:
+ return {};
+ }
+ }();
+
+ if (!orientation.has_value())
+ return {};
+
+ return GfxGradient { *orientation, color_a, color_b };
+};
+
// https://www.w3.org/TR/css-backgrounds-3/#backgrounds
void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMetrics const& layout_node, Gfx::FloatRect const& border_rect, Color background_color, Vector<CSS::BackgroundLayerData> const* background_layers, BorderRadiiData const& border_radii)
{
@@ -60,7 +98,9 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
color_box = get_box(background_layers->last().clip);
auto layer_is_paintable = [&](auto& layer) {
- return layer.background_image && layer.background_image->is_image() && layer.background_image->as_image().bitmap();
+ return (layer.background_image
+ && ((layer.background_image->is_image() && layer.background_image->as_image().bitmap())
+ || layer.background_image->is_linear_gradient()));
};
bool has_paintable_layers = false;
@@ -93,6 +133,17 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
painter.add_clip_rect(clip_rect);
ScopedCornerRadiusClip corner_clip { painter, clip_rect, clip_box.radii };
+ if (layer.background_image->is_linear_gradient()) {
+ // FIXME: Paint non-orthogonal gradients, gradients with > 2 color stops, gradients with custom stop positions ...
+ // FIXME: Support sizing and positioning rules with gradients.
+ auto& linear_gradient = layer.background_image->as_linear_gradient();
+ auto gfx_gradient = linear_gradient_to_gfx_gradient(linear_gradient, border_box.rect);
+ if (gfx_gradient.has_value()) {
+ painter.fill_rect_with_gradient(gfx_gradient->orientation, border_box.rect.to_rounded<int>(), gfx_gradient->color_a, gfx_gradient->color_b);
+ }
+ continue;
+ }
+
auto& image = *layer.background_image->as_image().bitmap();
Gfx::FloatRect background_positioning_area;