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:
parent
861d46be3e
commit
a8f4ea5226
Notes:
github-actions[bot]
2024-08-06 19:15:33 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: a8f4ea5226
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/988
19 changed files with 135 additions and 97 deletions
30
Tests/LibWeb/Ref/background-clip-text-inside-scrollable.html
Normal file
30
Tests/LibWeb/Ref/background-clip-text-inside-scrollable.html
Normal 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>
|
|
@ -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>
|
|
@ -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 {}; }
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue