diff options
author | MacDue <macdue@dueutil.tech> | 2022-08-16 17:14:03 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-08-18 15:58:05 +0200 |
commit | e294b7929a48c1da784139cb7d1570e1c0f17349 (patch) | |
tree | a98e84f9c246c8398d1345ac83244ce5d56607fc /Userland | |
parent | ffdcc60b03ef3a195db4fd1ab78b92a8e919fd1b (diff) | |
download | serenity-e294b7929a48c1da784139cb7d1570e1c0f17349.zip |
LibWeb: Support painting `repeating-linear-gradient()`s
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibWeb/Painting/GradientPainting.cpp | 28 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Painting/GradientPainting.h | 1 |
2 files changed, 21 insertions, 8 deletions
diff --git a/Userland/Libraries/LibWeb/Painting/GradientPainting.cpp b/Userland/Libraries/LibWeb/Painting/GradientPainting.cpp index 0f72c20d43..3d1fcdc3fa 100644 --- a/Userland/Libraries/LibWeb/Painting/GradientPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/GradientPainting.cpp @@ -120,7 +120,11 @@ LinearGradientData resolve_linear_gradient_data(Layout::Node const& node, Gfx::F } } - return { gradient_angle, resolved_color_stops }; + Optional<float> repeat_length = {}; + if (linear_gradient.is_repeating()) + repeat_length = resolved_color_stops.last().position - resolved_color_stops.first().position; + + return { gradient_angle, resolved_color_stops, repeat_length }; } static float mix(float x, float y, float a) @@ -159,6 +163,7 @@ void paint_linear_gradient(PaintContext& context, Gfx::IntRect const& gradient_r float sin_angle, cos_angle; AK::sincos(angle, sin_angle, cos_angle); + // Full length of the gradient auto length = calulate_gradient_length(gradient_rect.size(), sin_angle, cos_angle); Gfx::FloatPoint offset { cos_angle * (length / 2), sin_angle * (length / 2) }; @@ -196,17 +201,19 @@ void paint_linear_gradient(PaintContext& context, Gfx::IntRect const& gradient_r }; Vector<Gfx::Color, 1024> gradient_line_colors; - auto int_length = round_to<int>(length); - gradient_line_colors.resize(int_length); + auto gradient_color_count = round_to<int>(data.repeat_length.value_or(length)); + gradient_line_colors.resize(gradient_color_count); auto& color_stops = data.color_stops; - for (int loc = 0; loc < int_length; loc++) { + auto start_offset = data.repeat_length.has_value() ? color_stops.first().position : 0.0f; + auto start_offset_int = round_to<int>(start_offset); + for (int loc = 0; loc < gradient_color_count; loc++) { Gfx::Color gradient_color = color_mix( color_stops[0].color, color_stops[1].color, color_stop_step( color_stops[0], color_stops[1], - loc)); + loc + start_offset_int)); for (size_t i = 1; i < color_stops.size() - 1; i++) { gradient_color = color_mix( gradient_color, @@ -214,18 +221,23 @@ void paint_linear_gradient(PaintContext& context, Gfx::IntRect const& gradient_r color_stop_step( color_stops[i], color_stops[i + 1], - loc)); + loc + start_offset_int)); } gradient_line_colors[loc] = gradient_color; } auto lookup_color = [&](int loc) { - return gradient_line_colors[clamp(loc, 0, int_length - 1)]; + return gradient_line_colors[clamp(loc, 0, gradient_color_count - 1)]; }; for (int y = 0; y < gradient_rect.height(); y++) { for (int x = 0; x < gradient_rect.width(); x++) { - auto loc = (x * cos_angle - (gradient_rect.height() - y) * -sin_angle) - rotated_start_point_x; + auto loc = (x * cos_angle - (gradient_rect.height() - y) * -sin_angle) - rotated_start_point_x - start_offset; + if (data.repeat_length.has_value()) { + loc = AK::fmod(loc, *data.repeat_length); + if (loc < 0) + loc = *data.repeat_length + loc; + } // Blend between the two neighbouring colors (this fixes some nasty aliasing issues at small angles) auto blend = loc - static_cast<int>(loc); auto gradient_color = color_mix(lookup_color(loc - 1), lookup_color(loc), blend); diff --git a/Userland/Libraries/LibWeb/Painting/GradientPainting.h b/Userland/Libraries/LibWeb/Painting/GradientPainting.h index 3a5da9d4e4..f9b313ccca 100644 --- a/Userland/Libraries/LibWeb/Painting/GradientPainting.h +++ b/Userland/Libraries/LibWeb/Painting/GradientPainting.h @@ -25,6 +25,7 @@ using ColorStopList = Vector<ColorStop, 4>; struct LinearGradientData { float gradient_angle; ColorStopList color_stops; + Optional<float> repeat_length; }; LinearGradientData resolve_linear_gradient_data(Layout::Node const&, Gfx::FloatSize const&, CSS::LinearGradientStyleValue const&); |