1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-11 18:20:43 +09:00

LibWeb: Fix "background-clip: text" for elements nested in scrollable

Instead of carrying the display list for a mask in each command that
might potentially be affected by "background-clip: text", this change
introduces a new AddMask command that is applied once for all
background layers within one box.

The new AddMask command includes a rectangle for the mask destination
that is translated by the corresponding scroll offset.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/857
This commit is contained in:
Aliaksandr Kalenik 2024-08-06 15:26:47 +03:00 committed by Alexander Kalenik
parent 861d46be3e
commit a8f4ea5226
Notes: github-actions[bot] 2024-08-06 19:15:33 +00:00
19 changed files with 135 additions and 97 deletions

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<link rel="match" href="reference/background-clip-text-inside-scrollable-ref.html" />
<style>
* {
scrollbar-width: none;
}
#text {
background: linear-gradient(#6d98cc, #8a64e5);
background-clip: text;
color: transparent;
font-size: 50px;
}
#scrollable {
width: 300px;
height: 300px;
border: 1px solid black;
overflow: scroll;
}
</style>
<div id="scrollable">
<div style="height: 200px"></div>
Clip<span id="text">Text</span>
<div style="height: 600px"></div>
</div>
<script>
const scrollContainer = document.getElementById("scrollable");
scrollContainer.scrollTop = 200;
</script>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<style>
* {
scrollbar-width: none;
}
#text {
background: linear-gradient(#6d98cc, #8a64e5);
background-clip: text;
color: transparent;
font-size: 50px;
}
#scrollable {
width: 300px;
height: 300px;
border: 1px solid black;
overflow: scroll;
}
</style>
<div id="scrollable">
Clip<span id="text">Text</span>
</div>

View file

@ -36,7 +36,7 @@ public:
virtual void resolve_for_size(Layout::NodeWithStyleAndBoxModelMetrics const&, CSSPixelSize) const {};
virtual bool is_paintable() const = 0;
virtual void paint(PaintContext& context, DevicePixelRect const& dest_rect, ImageRendering, RefPtr<Painting::DisplayList> text_clip = {}) const = 0;
virtual void paint(PaintContext& context, DevicePixelRect const& dest_rect, ImageRendering) const = 0;
virtual Optional<Gfx::Color> color_if_single_pixel_bitmap() const { return {}; }
};

View file

@ -42,12 +42,12 @@ void ConicGradientStyleValue::resolve_for_size(Layout::NodeWithStyleAndBoxModelM
m_resolved->position = m_properties.position->resolved(node, CSSPixelRect { { 0, 0 }, size });
}
void ConicGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip) const
void ConicGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering) const
{
VERIFY(m_resolved.has_value());
auto destination_rect = dest_rect.to_type<int>();
auto position = context.rounded_device_point(m_resolved->position).to_type<int>();
context.display_list_recorder().fill_rect_with_conic_gradient(destination_rect, m_resolved->data, position, text_clip);
context.display_list_recorder().fill_rect_with_conic_gradient(destination_rect, m_resolved->data, position);
}
bool ConicGradientStyleValue::equals(StyleValue const& other) const

View file

@ -25,7 +25,7 @@ public:
virtual String to_string() const override;
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip = {}) const override;
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override;
virtual bool equals(StyleValue const& other) const override;

View file

@ -137,11 +137,11 @@ Optional<CSSPixelFraction> ImageStyleValue::natural_aspect_ratio() const
return {};
}
void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, RefPtr<Painting::DisplayList> text_clip) const
void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const
{
if (auto const* b = bitmap(m_current_frame_index, dest_rect.size().to_type<int>()); b != nullptr) {
auto scaling_mode = to_gfx_scaling_mode(image_rendering, b->rect(), dest_rect.to_type<int>());
context.display_list_recorder().draw_scaled_immutable_bitmap(dest_rect.to_type<int>(), *b, b->rect(), scaling_mode, text_clip);
context.display_list_recorder().draw_scaled_immutable_bitmap(dest_rect.to_type<int>(), *b, b->rect(), scaling_mode);
}
}

View file

@ -45,7 +45,7 @@ public:
Optional<CSSPixelFraction> natural_aspect_ratio() const override;
virtual bool is_paintable() const override;
void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, RefPtr<Painting::DisplayList> clip_paths = {}) const override;
void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const override;
virtual Optional<Gfx::Color> color_if_single_pixel_bitmap() const override;
Gfx::ImmutableBitmap const* current_frame_bitmap(DevicePixelRect const& dest_rect) const;

View file

@ -109,10 +109,10 @@ void LinearGradientStyleValue::resolve_for_size(Layout::NodeWithStyleAndBoxModel
m_resolved = ResolvedData { Painting::resolve_linear_gradient_data(node, size, *this), size };
}
void LinearGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip) const
void LinearGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering) const
{
VERIFY(m_resolved.has_value());
context.display_list_recorder().fill_rect_with_linear_gradient(dest_rect.to_type<int>(), m_resolved->data, text_clip);
context.display_list_recorder().fill_rect_with_linear_gradient(dest_rect.to_type<int>(), m_resolved->data);
}
}

View file

@ -60,7 +60,7 @@ public:
void resolve_for_size(Layout::NodeWithStyleAndBoxModelMetrics const&, CSSPixelSize) const override;
bool is_paintable() const override { return true; }
void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, RefPtr<Painting::DisplayList> text_clip = {}) const override;
void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const override;
private:
LinearGradientStyleValue(GradientDirection direction, Vector<LinearColorStopListElement> color_stop_list, GradientType type, GradientRepeating repeating)

View file

@ -207,12 +207,12 @@ bool RadialGradientStyleValue::equals(StyleValue const& other) const
return m_properties == other_gradient.m_properties;
}
void RadialGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip) const
void RadialGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering) const
{
VERIFY(m_resolved.has_value());
auto center = context.rounded_device_point(m_resolved->center).to_type<int>();
auto size = context.rounded_device_size(m_resolved->gradient_size).to_type<int>();
context.display_list_recorder().fill_rect_with_radial_gradient(dest_rect.to_type<int>(), m_resolved->data, center, size, text_clip);
context.display_list_recorder().fill_rect_with_radial_gradient(dest_rect.to_type<int>(), m_resolved->data, center, size);
}
}

View file

@ -51,7 +51,7 @@ public:
virtual String to_string() const override;
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip = {}) const override;
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override;
virtual bool equals(StyleValue const& other) const override;

View file

@ -56,10 +56,12 @@ static CSSPixelSize run_default_sizing_algorithm(
return default_size;
}
static RefPtr<DisplayList> compute_text_clip_paths(PaintContext& context, Paintable const& paintable)
static RefPtr<DisplayList> compute_text_clip_paths(PaintContext& context, Paintable const& paintable, CSSPixelPoint containing_block_location)
{
auto text_clip_paths = DisplayList::create();
DisplayListRecorder display_list_recorder(*text_clip_paths);
// Remove containing block offset, so executing the display list will produce mask at (0, 0)
display_list_recorder.translate(-context.floored_device_point(containing_block_location).to_type<int>());
auto add_text_clip_path = [&](PaintableFragment const& fragment) {
auto glyph_run = fragment.glyph_run();
if (!glyph_run || glyph_run->glyphs().is_empty())
@ -116,13 +118,15 @@ static BackgroundBox get_box(CSS::BackgroundBox box_clip, BackgroundBox border_b
// https://www.w3.org/TR/css-backgrounds-3/#backgrounds
void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMetrics const& layout_node, CSS::ImageRendering image_rendering, ResolvedBackground resolved_background, BorderRadiiData const& border_radii)
{
RefPtr<DisplayList> text_clip;
if (resolved_background.needs_text_clip) {
text_clip = compute_text_clip_paths(context, *layout_node.paintable());
}
auto& display_list_recorder = context.display_list_recorder();
DisplayListRecorderStateSaver state { display_list_recorder };
if (resolved_background.needs_text_clip) {
auto display_list = compute_text_clip_paths(context, *layout_node.paintable(), resolved_background.background_rect.location());
auto rect = context.rounded_device_rect(resolved_background.background_rect);
display_list_recorder.add_mask(move(display_list), rect.to_type<int>());
}
BackgroundBox border_box {
resolved_background.background_rect,
border_radii
@ -136,8 +140,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
color_box.radii.top_left.as_corner(context),
color_box.radii.top_right.as_corner(context),
color_box.radii.bottom_right.as_corner(context),
color_box.radii.bottom_left.as_corner(context),
text_clip);
color_box.radii.bottom_left.as_corner(context));
struct {
DevicePixels top { 0 };
@ -332,17 +335,17 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
fill_rect = fill_rect->united(image_device_rect);
}
});
display_list_recorder.fill_rect(fill_rect->to_type<int>(), color.value(), text_clip);
display_list_recorder.fill_rect(fill_rect->to_type<int>(), color.value());
} else if (is<CSS::ImageStyleValue>(image) && repeat_x && repeat_y && !repeat_x_has_gap && !repeat_y_has_gap) {
// Use a dedicated painting command for repeated images instead of recording a separate command for each instance
// of a repeated background, so the painter has the opportunity to optimize the painting of repeated images.
auto dest_rect = context.rounded_device_rect(image_rect);
auto const* bitmap = static_cast<CSS::ImageStyleValue const&>(image).current_frame_bitmap(dest_rect);
auto scaling_mode = to_gfx_scaling_mode(image_rendering, bitmap->rect(), dest_rect.to_type<int>());
context.display_list_recorder().draw_repeated_immutable_bitmap(dest_rect.to_type<int>(), clip_rect.to_type<int>(), *bitmap, scaling_mode, { .x = repeat_x, .y = repeat_y }, text_clip);
context.display_list_recorder().draw_repeated_immutable_bitmap(dest_rect.to_type<int>(), clip_rect.to_type<int>(), *bitmap, scaling_mode, { .x = repeat_x, .y = repeat_y });
} else {
for_each_image_device_rect([&](auto const& image_device_rect) {
image.paint(context, image_device_rect, image_rendering, text_clip);
image.paint(context, image_device_rect, image_rendering);
});
}
}

View file

@ -50,7 +50,6 @@ struct DrawGlyphRun {
struct FillRect {
Gfx::IntRect rect;
Color color;
RefPtr<DisplayList> text_clip;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); }
@ -71,7 +70,6 @@ struct DrawScaledImmutableBitmap {
NonnullRefPtr<Gfx::ImmutableBitmap> bitmap;
Gfx::IntRect src_rect;
Gfx::ScalingMode scaling_mode;
RefPtr<DisplayList> text_clip;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return dst_rect; }
void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); }
@ -88,7 +86,6 @@ struct DrawRepeatedImmutableBitmap {
NonnullRefPtr<Gfx::ImmutableBitmap> bitmap;
Gfx::ScalingMode scaling_mode;
Repeat repeat;
RefPtr<DisplayList> text_clip;
void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); }
};
@ -133,7 +130,6 @@ struct PopStackingContext { };
struct PaintLinearGradient {
Gfx::IntRect gradient_rect;
LinearGradientData linear_gradient_data;
RefPtr<DisplayList> text_clip;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return gradient_rect; }
@ -174,7 +170,6 @@ struct FillRectWithRoundedCorners {
Gfx::IntRect rect;
Color color;
CornerRadii corner_radii;
RefPtr<DisplayList> text_clip;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); }
@ -314,7 +309,6 @@ struct PaintRadialGradient {
RadialGradientData radial_gradient_data;
Gfx::IntPoint center;
Gfx::IntSize size;
RefPtr<DisplayList> text_clip;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
@ -325,7 +319,6 @@ struct PaintConicGradient {
Gfx::IntRect rect;
ConicGradientData conic_gradient_data;
Gfx::IntPoint position;
RefPtr<DisplayList> text_clip;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
@ -356,6 +349,16 @@ struct AddRoundedRectClip {
void translate_by(Gfx::IntPoint const& offset) { border_rect.translate_by(offset); }
};
struct AddMask {
RefPtr<DisplayList> display_list;
Gfx::IntRect rect;
void translate_by(Gfx::IntPoint const& offset)
{
rect.translate_by(offset);
}
};
using Command = Variant<
DrawGlyphRun,
FillRect,
@ -384,6 +387,7 @@ using Command = Variant<
ApplyBackdropFilter,
DrawRect,
DrawTriangleWave,
AddRoundedRectClip>;
AddRoundedRectClip,
AddMask>;
}

View file

@ -85,6 +85,7 @@ void DisplayListPlayer::execute(DisplayList& display_list)
else HANDLE_COMMAND(DrawRect, draw_rect)
else HANDLE_COMMAND(DrawTriangleWave, draw_triangle_wave)
else HANDLE_COMMAND(AddRoundedRectClip, add_rounded_rect_clip)
else HANDLE_COMMAND(AddMask, add_mask)
else VERIFY_NOT_REACHED();
// clang-format on
}

View file

@ -69,6 +69,7 @@ private:
virtual void draw_rect(DrawRect const&) = 0;
virtual void draw_triangle_wave(DrawTriangleWave const&) = 0;
virtual void add_rounded_rect_clip(AddRoundedRectClip const&) = 0;
virtual void add_mask(AddMask const&) = 0;
virtual bool would_be_fully_clipped_by_painter(Gfx::IntRect) const = 0;
};

View file

@ -374,15 +374,6 @@ static SkSamplingOptions to_skia_sampling_options(Gfx::ScalingMode scaling_mode)
}
}
#define APPLY_TEXT_CLIP_IF_NEEDED(MASK_RECT) \
ScopeGuard const restore { [&] { \
if (command.text_clip) \
surface().canvas().restore(); \
} }; \
if (command.text_clip) { \
apply_mask_painted_from(*command.text_clip, MASK_RECT); \
}
DisplayListPlayerSkia::SkiaSurface& DisplayListPlayerSkia::surface() const
{
return static_cast<SkiaSurface&>(*m_surface);
@ -422,8 +413,6 @@ void DisplayListPlayerSkia::draw_glyph_run(DrawGlyphRun const& command)
void DisplayListPlayerSkia::fill_rect(FillRect const& command)
{
APPLY_TEXT_CLIP_IF_NEEDED(command.rect)
auto const& rect = command.rect;
auto& canvas = surface().canvas();
SkPaint paint;
@ -444,8 +433,6 @@ void DisplayListPlayerSkia::draw_scaled_bitmap(DrawScaledBitmap const& command)
void DisplayListPlayerSkia::draw_scaled_immutable_bitmap(DrawScaledImmutableBitmap const& command)
{
APPLY_TEXT_CLIP_IF_NEEDED(command.dst_rect)
auto src_rect = to_skia_rect(command.src_rect);
auto dst_rect = to_skia_rect(command.dst_rect);
auto bitmap = to_skia_bitmap(command.bitmap->bitmap());
@ -457,8 +444,6 @@ void DisplayListPlayerSkia::draw_scaled_immutable_bitmap(DrawScaledImmutableBitm
void DisplayListPlayerSkia::draw_repeated_immutable_bitmap(DrawRepeatedImmutableBitmap const& command)
{
APPLY_TEXT_CLIP_IF_NEEDED(command.clip_rect)
auto bitmap = to_skia_bitmap(command.bitmap->bitmap());
auto image = SkImages::RasterFromBitmap(bitmap);
@ -655,8 +640,6 @@ static ColorStopList expand_repeat_length(ColorStopList const& color_stop_list,
void DisplayListPlayerSkia::paint_linear_gradient(PaintLinearGradient const& command)
{
APPLY_TEXT_CLIP_IF_NEEDED(command.gradient_rect)
auto const& linear_gradient_data = command.linear_gradient_data;
auto color_stop_list = linear_gradient_data.color_stops.list;
auto const& repeat_length = linear_gradient_data.color_stops.repeat_length;
@ -833,8 +816,6 @@ void DisplayListPlayerSkia::paint_text_shadow(PaintTextShadow const& command)
void DisplayListPlayerSkia::fill_rect_with_rounded_corners(FillRectWithRoundedCorners const& command)
{
APPLY_TEXT_CLIP_IF_NEEDED(command.rect)
auto const& rect = command.rect;
auto& canvas = surface().canvas();
@ -1200,8 +1181,6 @@ void DisplayListPlayerSkia::draw_rect(DrawRect const& command)
void DisplayListPlayerSkia::paint_radial_gradient(PaintRadialGradient const& command)
{
APPLY_TEXT_CLIP_IF_NEEDED(command.rect)
auto const& radial_gradient_data = command.radial_gradient_data;
auto color_stop_list = radial_gradient_data.color_stops.list;
@ -1249,8 +1228,6 @@ void DisplayListPlayerSkia::paint_radial_gradient(PaintRadialGradient const& com
void DisplayListPlayerSkia::paint_conic_gradient(PaintConicGradient const& command)
{
APPLY_TEXT_CLIP_IF_NEEDED(command.rect)
auto const& conic_gradient_data = command.conic_gradient_data;
auto color_stop_list = conic_gradient_data.color_stops.list;
@ -1300,19 +1277,14 @@ void DisplayListPlayerSkia::add_rounded_rect_clip(AddRoundedRectClip const& comm
canvas.clipRRect(rounded_rect, clip_op, true);
}
bool DisplayListPlayerSkia::would_be_fully_clipped_by_painter(Gfx::IntRect rect) const
{
return surface().canvas().quickReject(to_skia_rect(rect));
}
void DisplayListPlayerSkia::apply_mask_painted_from(DisplayList& display_list, Gfx::IntRect rect)
void DisplayListPlayerSkia::add_mask(AddMask const& command)
{
auto const& rect = command.rect;
auto mask_surface = m_surface->make_surface(rect.width(), rect.height());
auto previous_surface = move(m_surface);
m_surface = make<SkiaSurface>(mask_surface);
surface().canvas().translate(-rect.x(), -rect.y());
execute(display_list);
execute(*command.display_list);
m_surface = move(previous_surface);
SkMatrix mask_matrix;
@ -1323,4 +1295,9 @@ void DisplayListPlayerSkia::apply_mask_painted_from(DisplayList& display_list, G
surface().canvas().clipShader(shader);
}
bool DisplayListPlayerSkia::would_be_fully_clipped_by_painter(Gfx::IntRect rect) const
{
return surface().canvas().quickReject(to_skia_rect(rect));
}
}

View file

@ -76,11 +76,10 @@ private:
void paint_conic_gradient(PaintConicGradient const&) override;
void draw_triangle_wave(DrawTriangleWave const&) override;
void add_rounded_rect_clip(AddRoundedRectClip const&) override;
void add_mask(AddMask const&) override;
bool would_be_fully_clipped_by_painter(Gfx::IntRect) const override;
void apply_mask_painted_from(DisplayList&, Gfx::IntRect);
class SkiaSurface;
SkiaSurface& surface() const;

View file

@ -30,14 +30,20 @@ void DisplayListRecorder::add_rounded_rect_clip(CornerRadii corner_radii, Gfx::I
corner_clip });
}
void DisplayListRecorder::fill_rect(Gfx::IntRect const& rect, Color color, RefPtr<DisplayList> text_clip)
void DisplayListRecorder::add_mask(RefPtr<DisplayList> display_list, Gfx::IntRect rect)
{
append(AddMask {
.display_list = move(display_list),
.rect = state().translation.map(rect) });
}
void DisplayListRecorder::fill_rect(Gfx::IntRect const& rect, Color color)
{
if (rect.is_empty())
return;
append(FillRect {
.rect = state().translation.map(rect),
.color = color,
.text_clip = move(text_clip),
});
}
@ -128,28 +134,26 @@ void DisplayListRecorder::fill_ellipse(Gfx::IntRect const& a_rect, Color color)
});
}
void DisplayListRecorder::fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data, RefPtr<DisplayList> text_clip)
void DisplayListRecorder::fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data)
{
if (gradient_rect.is_empty())
return;
append(PaintLinearGradient {
.gradient_rect = state().translation.map(gradient_rect),
.linear_gradient_data = data,
.text_clip = move(text_clip) });
.linear_gradient_data = data });
}
void DisplayListRecorder::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position, RefPtr<DisplayList> text_clip)
void DisplayListRecorder::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position)
{
if (rect.is_empty())
return;
append(PaintConicGradient {
.rect = state().translation.map(rect),
.conic_gradient_data = data,
.position = position,
.text_clip = move(text_clip) });
.position = position });
}
void DisplayListRecorder::fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size, RefPtr<DisplayList> text_clip)
void DisplayListRecorder::fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size)
{
if (rect.is_empty())
return;
@ -157,8 +161,7 @@ void DisplayListRecorder::fill_rect_with_radial_gradient(Gfx::IntRect const& rec
.rect = state().translation.map(rect),
.radial_gradient_data = data,
.center = center,
.size = size,
.text_clip = move(text_clip) });
.size = size });
}
void DisplayListRecorder::draw_rect(Gfx::IntRect const& rect, Color color, bool rough)
@ -183,7 +186,7 @@ void DisplayListRecorder::draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::
});
}
void DisplayListRecorder::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode, RefPtr<DisplayList> text_clip)
void DisplayListRecorder::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode)
{
if (dst_rect.is_empty())
return;
@ -192,11 +195,10 @@ void DisplayListRecorder::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_r
.bitmap = bitmap,
.src_rect = src_rect,
.scaling_mode = scaling_mode,
.text_clip = move(text_clip),
});
}
void DisplayListRecorder::draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, NonnullRefPtr<Gfx::ImmutableBitmap> bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat repeat, RefPtr<DisplayList> text_clip)
void DisplayListRecorder::draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, NonnullRefPtr<Gfx::ImmutableBitmap> bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat repeat)
{
append(DrawRepeatedImmutableBitmap {
.dst_rect = dst_rect,
@ -204,7 +206,6 @@ void DisplayListRecorder::draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect,
.bitmap = move(bitmap),
.scaling_mode = scaling_mode,
.repeat = repeat,
.text_clip = move(text_clip),
});
}
@ -352,13 +353,13 @@ void DisplayListRecorder::paint_text_shadow(int blur_radius, Gfx::IntRect boundi
.draw_location = state().translation.map(draw_location) });
}
void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius, RefPtr<DisplayList> text_clip)
void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius)
{
if (rect.is_empty())
return;
if (!top_left_radius && !top_right_radius && !bottom_right_radius && !bottom_left_radius) {
fill_rect(rect, color, text_clip);
fill_rect(rect, color);
return;
}
@ -371,18 +372,17 @@ void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& rec
.bottom_right = bottom_right_radius,
.bottom_left = bottom_left_radius,
},
.text_clip = text_clip,
});
}
void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius, RefPtr<DisplayList> text_clip)
void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius)
{
if (a_rect.is_empty())
return;
fill_rect_with_rounded_corners(a_rect, color, radius, radius, radius, radius, move(text_clip));
fill_rect_with_rounded_corners(a_rect, color, radius, radius, radius, radius);
}
void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius, RefPtr<DisplayList> text_clip)
void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius)
{
if (a_rect.is_empty())
return;
@ -390,8 +390,7 @@ void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_r
{ top_left_radius, top_left_radius },
{ top_right_radius, top_right_radius },
{ bottom_right_radius, bottom_right_radius },
{ bottom_left_radius, bottom_left_radius },
move(text_clip));
{ bottom_left_radius, bottom_left_radius });
}
void DisplayListRecorder::draw_triangle_wave(Gfx::IntPoint a_p1, Gfx::IntPoint a_p2, Color color, int amplitude, int thickness = 1)

View file

@ -40,7 +40,7 @@ class DisplayListRecorder {
AK_MAKE_NONMOVABLE(DisplayListRecorder);
public:
void fill_rect(Gfx::IntRect const& rect, Color color, RefPtr<DisplayList> text_clip = {});
void fill_rect(Gfx::IntRect const& rect, Color color);
struct FillPathUsingColorParams {
Gfx::Path path;
@ -80,16 +80,16 @@ public:
void fill_ellipse(Gfx::IntRect const& a_rect, Color color);
void fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data, RefPtr<DisplayList> text_clip = {});
void fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position, RefPtr<DisplayList> text_clip = {});
void fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size, RefPtr<DisplayList> text_clip = {});
void fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data);
void fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position);
void fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size);
void draw_rect(Gfx::IntRect const& rect, Color color, bool rough = false);
void draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor, RefPtr<DisplayList> text_clip = {});
void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
void draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, NonnullRefPtr<Gfx::ImmutableBitmap> bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat, RefPtr<DisplayList> text_clip = {});
void draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, NonnullRefPtr<Gfx::ImmutableBitmap> bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat);
void draw_line(Gfx::IntPoint from, Gfx::IntPoint to, Color color, int thickness = 1, Gfx::LineStyle style = Gfx::LineStyle::Solid, Color alternate_color = Color::Transparent);
@ -123,6 +123,7 @@ public:
void pop_stacking_context();
void add_rounded_rect_clip(CornerRadii corner_radii, Gfx::IntRect border_rect, CornerClip corner_clip);
void add_mask(RefPtr<DisplayList> display_list, Gfx::IntRect rect);
void apply_backdrop_filter(Gfx::IntRect const& backdrop_region, BorderRadiiData const& border_radii_data, CSS::ResolvedBackdropFilter const& backdrop_filter);
@ -130,9 +131,9 @@ public:
void paint_inner_box_shadow_params(PaintBoxShadowParams params);
void paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Gfx::GlyphRun const&, double glyph_run_scale, Color color, Gfx::IntPoint draw_location);
void fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius, RefPtr<DisplayList> text_clip = {});
void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius, RefPtr<DisplayList> text_clip = {});
void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius, RefPtr<DisplayList> text_clip = {});
void fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius);
void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius);
void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius);
void draw_triangle_wave(Gfx::IntPoint a_p1, Gfx::IntPoint a_p2, Color color, int amplitude, int thickness);