mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-29 16:21:29 +00:00
LibWeb: Support CSS property background-clip: text
From https://drafts.csswg.org/css-backgrounds-4/#background-clip "The background is painted within (clipped to) the intersection of the border box and the geometry of the text in the element and its in-flow and floated descendants" This change implements it in the following way: 1. Traverse the descendants of the element, collecting the Gfx::Path of glyphs into a vector. 2. The vector of collected paths is saved in the background painting command. 3. The painting commands executor uses the list of glyphs to paint a mask for background clipping. Co-authored-by: Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
This commit is contained in:
parent
4a3680cafc
commit
9165faca5e
Notes:
sideshowbarker
2024-07-17 08:42:05 +09:00
Author: https://github.com/zacbrannelly Commit: https://github.com/SerenityOS/serenity/commit/9165faca5e Pull-request: https://github.com/SerenityOS/serenity/pull/23373 Reviewed-by: https://github.com/kalenikaliaksandr ✅
84
Tests/LibWeb/Ref/css-background-clip-text.html
Normal file
84
Tests/LibWeb/Ref/css-background-clip-text.html
Normal file
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="match" href="reference/css-background-clip-text-ref.html" />
|
||||
<title>Document</title>
|
||||
|
||||
<style>
|
||||
p, .container {
|
||||
border: 0.8em darkviolet;
|
||||
border-style: dotted double;
|
||||
margin: 1em 0;
|
||||
padding: 1.4em;
|
||||
font: 900 1.2em sans-serif;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.linear-gradient {
|
||||
background: linear-gradient(60deg, red, yellow, red, yellow, red);
|
||||
}
|
||||
|
||||
.radial-gradient {
|
||||
background: radial-gradient(circle, red, yellow, red, yellow, red);
|
||||
}
|
||||
|
||||
.conic-gradient {
|
||||
background: conic-gradient(red, yellow, red, yellow, red);
|
||||
}
|
||||
|
||||
.image-background {
|
||||
background: url('./assets/car.png');
|
||||
}
|
||||
|
||||
.border-box {
|
||||
background-clip: border-box;
|
||||
}
|
||||
.padding-box {
|
||||
background-clip: padding-box;
|
||||
}
|
||||
.content-box {
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
.text {
|
||||
background-clip: text;
|
||||
color: rgb(0 0 0 / 20%);
|
||||
}
|
||||
.new-background {
|
||||
background: rgb(255 255 0 / 30%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Hack to make the test runner wait for the image to load -->
|
||||
<img src="./assets/car.png" />
|
||||
|
||||
<p class="border-box linear-gradient">The background extends behind the border.</p>
|
||||
<p class="padding-box radial-gradient">
|
||||
The background extends to the inside edge of the border.
|
||||
</p>
|
||||
<p class="content-box conic-gradient">
|
||||
The background extends only to the edge of the content box.
|
||||
</p>
|
||||
<div class="text container linear-gradient">
|
||||
The background is clipped to the foreground text.
|
||||
<span>Some other text in a sub-element</span>
|
||||
</div>
|
||||
<div class="text container radial-gradient">
|
||||
The background is clipped to the foreground text.
|
||||
<span>Some other text in a sub-element</span>
|
||||
</div>
|
||||
<div class="text container conic-gradient">
|
||||
The background is clipped to the foreground text.
|
||||
<span>Some other text in a sub-element</span>
|
||||
</div>
|
||||
<div class="text container image-background">
|
||||
Testing text.
|
||||
<div>
|
||||
<div class="new-background" style="color: rgb(0 0 0 / 20%);">The is nested text that should still be clipped to the background</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
15
Tests/LibWeb/Ref/reference/css-background-clip-text-ref.html
Normal file
15
Tests/LibWeb/Ref/reference/css-background-clip-text-ref.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
<!-- To rebase:
|
||||
1. Open background-clip-text.html in Ladybird
|
||||
2. Resize the window just above the width of the canvas
|
||||
3. Right click > "Take Full Screenshot"
|
||||
4. Update the image below:
|
||||
-->
|
||||
<img src="./images/css-background-clip-text.png">
|
BIN
Tests/LibWeb/Ref/reference/images/css-background-clip-text.png
Normal file
BIN
Tests/LibWeb/Ref/reference/images/css-background-clip-text.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 203 KiB |
|
@ -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) const = 0;
|
||||
virtual void paint(PaintContext& context, DevicePixelRect const& dest_rect, ImageRendering, Vector<Gfx::Path> const& clip_paths = {}) const = 0;
|
||||
|
||||
virtual Optional<Gfx::Color> color_if_single_pixel_bitmap() const { return {}; }
|
||||
};
|
||||
|
|
|
@ -42,10 +42,10 @@ 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) const
|
||||
void ConicGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, Vector<Gfx::Path> const& clip_paths) const
|
||||
{
|
||||
VERIFY(m_resolved.has_value());
|
||||
Painting::paint_conic_gradient(context, dest_rect, m_resolved->data, context.rounded_device_point(m_resolved->position));
|
||||
Painting::paint_conic_gradient(context, dest_rect, m_resolved->data, context.rounded_device_point(m_resolved->position), clip_paths);
|
||||
}
|
||||
|
||||
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) const override;
|
||||
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering, Vector<Gfx::Path> const& clip_paths = {}) const override;
|
||||
|
||||
virtual bool equals(StyleValue const& other) const override;
|
||||
|
||||
|
|
|
@ -131,11 +131,11 @@ Optional<CSSPixelFraction> ImageStyleValue::natural_aspect_ratio() const
|
|||
return {};
|
||||
}
|
||||
|
||||
void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const
|
||||
void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, Vector<Gfx::Path> const& clip_paths) 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.recording_painter().draw_scaled_immutable_bitmap(dest_rect.to_type<int>(), *b, b->rect(), scaling_mode);
|
||||
context.recording_painter().draw_scaled_immutable_bitmap(dest_rect.to_type<int>(), *b, b->rect(), scaling_mode, clip_paths);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) const override;
|
||||
void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, Vector<Gfx::Path> const& clip_paths = {}) const override;
|
||||
|
||||
virtual Optional<Gfx::Color> color_if_single_pixel_bitmap() const override;
|
||||
|
||||
|
|
|
@ -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) const
|
||||
void LinearGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, Vector<Gfx::Path> const& clip_paths) const
|
||||
{
|
||||
VERIFY(m_resolved.has_value());
|
||||
Painting::paint_linear_gradient(context, dest_rect, m_resolved->data);
|
||||
Painting::paint_linear_gradient(context, dest_rect, m_resolved->data, clip_paths);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) const override;
|
||||
void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, Vector<Gfx::Path> const& clip_paths = {}) const override;
|
||||
|
||||
private:
|
||||
LinearGradientStyleValue(GradientDirection direction, Vector<LinearColorStopListElement> color_stop_list, GradientType type, GradientRepeating repeating)
|
||||
|
|
|
@ -207,12 +207,13 @@ 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) const
|
||||
void RadialGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, Vector<Gfx::Path> const& clip_paths) const
|
||||
{
|
||||
VERIFY(m_resolved.has_value());
|
||||
Painting::paint_radial_gradient(context, dest_rect, m_resolved->data,
|
||||
context.rounded_device_point(m_resolved->center),
|
||||
context.rounded_device_size(m_resolved->gradient_size));
|
||||
context.rounded_device_size(m_resolved->gradient_size),
|
||||
clip_paths);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
|
||||
virtual String to_string() const override;
|
||||
|
||||
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override;
|
||||
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering, Vector<Gfx::Path> const& clip_paths = {}) const override;
|
||||
|
||||
virtual bool equals(StyleValue const& other) const override;
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ static CSSPixelSize run_default_sizing_algorithm(
|
|||
}
|
||||
|
||||
// https://www.w3.org/TR/css-backgrounds-3/#backgrounds
|
||||
void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMetrics const& layout_node, CSSPixelRect const& border_rect, Color background_color, CSS::ImageRendering image_rendering, Vector<CSS::BackgroundLayerData> const* background_layers, BorderRadiiData const& border_radii)
|
||||
void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMetrics const& layout_node, CSSPixelRect const& border_rect, Color background_color, CSS::ImageRendering image_rendering, Vector<CSS::BackgroundLayerData> const* background_layers, BorderRadiiData const& border_radii, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
auto& painter = context.recording_painter();
|
||||
|
||||
|
@ -118,13 +118,14 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
}
|
||||
}
|
||||
|
||||
context.recording_painter().fill_rect_with_rounded_corners(
|
||||
painter.fill_rect_with_rounded_corners(
|
||||
context.rounded_device_rect(color_box.rect).to_type<int>(),
|
||||
background_color,
|
||||
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));
|
||||
color_box.radii.bottom_left.as_corner(context),
|
||||
clip_paths);
|
||||
|
||||
if (!has_paintable_layers)
|
||||
return;
|
||||
|
@ -388,10 +389,10 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
fill_rect = fill_rect->united(image_device_rect);
|
||||
}
|
||||
});
|
||||
painter.fill_rect(fill_rect->to_type<int>(), color.value());
|
||||
painter.fill_rect(fill_rect->to_type<int>(), color.value(), clip_paths);
|
||||
} else {
|
||||
for_each_image_device_rect([&](auto const& image_device_rect) {
|
||||
image.paint(context, image_device_rect, image_rendering);
|
||||
image.paint(context, image_device_rect, image_rendering, clip_paths);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
|
||||
namespace Web::Painting {
|
||||
|
||||
void paint_background(PaintContext&, Layout::NodeWithStyleAndBoxModelMetrics const&, CSSPixelRect const&, Color background_color, CSS::ImageRendering, Vector<CSS::BackgroundLayerData> const*, BorderRadiiData const&);
|
||||
void paint_background(PaintContext&, Layout::NodeWithStyleAndBoxModelMetrics const&, CSSPixelRect const&, Color background_color, CSS::ImageRendering, Vector<CSS::BackgroundLayerData> const*, BorderRadiiData const&, Vector<Gfx::Path> const& clip_paths = {});
|
||||
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ struct DrawText {
|
|||
struct FillRect {
|
||||
Gfx::IntRect rect;
|
||||
Color color;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
|
||||
void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); }
|
||||
|
@ -85,6 +86,7 @@ struct DrawScaledImmutableBitmap {
|
|||
NonnullRefPtr<Gfx::ImmutableBitmap> bitmap;
|
||||
Gfx::IntRect src_rect;
|
||||
Gfx::Painter::ScalingMode scaling_mode;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return dst_rect; }
|
||||
void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); }
|
||||
|
@ -128,6 +130,7 @@ struct PopStackingContext { };
|
|||
struct PaintLinearGradient {
|
||||
Gfx::IntRect gradient_rect;
|
||||
LinearGradientData linear_gradient_data;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return gradient_rect; }
|
||||
|
||||
|
@ -170,6 +173,7 @@ struct FillRectWithRoundedCorners {
|
|||
Gfx::AntiAliasingPainter::CornerRadius top_right_radius;
|
||||
Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius;
|
||||
Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
|
||||
void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); }
|
||||
|
@ -334,6 +338,7 @@ struct PaintRadialGradient {
|
|||
RadialGradientData radial_gradient_data;
|
||||
Gfx::IntPoint center;
|
||||
Gfx::IntSize size;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
|
||||
|
||||
|
@ -344,6 +349,7 @@ struct PaintConicGradient {
|
|||
Gfx::IntRect rect;
|
||||
ConicGradientData conic_gradient_data;
|
||||
Gfx::IntPoint position;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
|
||||
|
||||
|
|
|
@ -55,10 +55,38 @@ CommandResult CommandExecutorCPU::draw_text(Gfx::IntRect const& rect, String con
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorCPU::fill_rect(Gfx::IntRect const& rect, Color const& color)
|
||||
template<typename Callback>
|
||||
void apply_clip_paths_to_painter(Gfx::IntRect const& rect, Callback callback, Vector<Gfx::Path> const& clip_paths, Gfx::Painter& target_painter)
|
||||
{
|
||||
auto& painter = this->painter();
|
||||
// Setup a painter for a background canvas that we will paint to first.
|
||||
auto background_canvas = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, rect.size()).release_value_but_fixme_should_propagate_errors();
|
||||
Gfx::Painter painter(*background_canvas);
|
||||
|
||||
// Offset the painter to paint in the correct location.
|
||||
painter.translate(-rect.location());
|
||||
|
||||
// Paint the background canvas.
|
||||
callback(painter);
|
||||
|
||||
// Apply the clip path to the target painter.
|
||||
Gfx::AntiAliasingPainter aa_painter(target_painter);
|
||||
for (auto const& clip_path : clip_paths) {
|
||||
auto fill_offset = clip_path.bounding_box().location().to_type<int>() - rect.location();
|
||||
auto paint_style = Gfx::BitmapPaintStyle::create(*background_canvas, fill_offset).release_value_but_fixme_should_propagate_errors();
|
||||
aa_painter.fill_path(clip_path, paint_style);
|
||||
}
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorCPU::fill_rect(Gfx::IntRect const& rect, Color const& color, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
auto paint_op = [&](Gfx::Painter& painter) {
|
||||
painter.fill_rect(rect, color);
|
||||
};
|
||||
if (clip_paths.is_empty()) {
|
||||
paint_op(painter());
|
||||
} else {
|
||||
apply_clip_paths_to_painter(rect, paint_op, clip_paths, painter());
|
||||
}
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
|
@ -69,10 +97,16 @@ CommandResult CommandExecutorCPU::draw_scaled_bitmap(Gfx::IntRect const& dst_rec
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorCPU::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& immutable_bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode)
|
||||
CommandResult CommandExecutorCPU::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& immutable_bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
auto& painter = this->painter();
|
||||
auto paint_op = [&](Gfx::Painter& painter) {
|
||||
painter.draw_scaled_bitmap(dst_rect, immutable_bitmap.bitmap(), src_rect, 1, scaling_mode);
|
||||
};
|
||||
if (clip_paths.is_empty()) {
|
||||
paint_op(painter());
|
||||
} else {
|
||||
apply_clip_paths_to_painter(dst_rect, paint_op, clip_paths, painter());
|
||||
}
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
|
@ -200,12 +234,18 @@ CommandResult CommandExecutorCPU::pop_stacking_context()
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorCPU::paint_linear_gradient(Gfx::IntRect const& gradient_rect, Web::Painting::LinearGradientData const& linear_gradient_data)
|
||||
CommandResult CommandExecutorCPU::paint_linear_gradient(Gfx::IntRect const& gradient_rect, Web::Painting::LinearGradientData const& linear_gradient_data, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
auto const& data = linear_gradient_data;
|
||||
painter().fill_rect_with_linear_gradient(
|
||||
gradient_rect, data.color_stops.list,
|
||||
data.gradient_angle, data.color_stops.repeat_length);
|
||||
auto paint_op = [&](Gfx::Painter& painter) {
|
||||
painter.fill_rect_with_linear_gradient(
|
||||
gradient_rect, linear_gradient_data.color_stops.list,
|
||||
linear_gradient_data.gradient_angle, linear_gradient_data.color_stops.repeat_length);
|
||||
};
|
||||
if (clip_paths.is_empty()) {
|
||||
paint_op(painter());
|
||||
} else {
|
||||
apply_clip_paths_to_painter(gradient_rect, paint_op, clip_paths, painter());
|
||||
}
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
|
@ -255,9 +295,10 @@ CommandResult CommandExecutorCPU::paint_text_shadow(int blur_radius, Gfx::IntRec
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorCPU::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius)
|
||||
CommandResult CommandExecutorCPU::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
Gfx::AntiAliasingPainter aa_painter(painter());
|
||||
auto paint_op = [&](Gfx::Painter& painter) {
|
||||
Gfx::AntiAliasingPainter aa_painter(painter);
|
||||
aa_painter.fill_rect_with_rounded_corners(
|
||||
rect,
|
||||
color,
|
||||
|
@ -265,6 +306,12 @@ CommandResult CommandExecutorCPU::fill_rect_with_rounded_corners(Gfx::IntRect co
|
|||
top_right_radius,
|
||||
bottom_right_radius,
|
||||
bottom_left_radius);
|
||||
};
|
||||
if (clip_paths.is_empty()) {
|
||||
paint_op(painter());
|
||||
} else {
|
||||
apply_clip_paths_to_painter(rect, paint_op, clip_paths, painter());
|
||||
}
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
|
@ -380,15 +427,29 @@ CommandResult CommandExecutorCPU::draw_rect(Gfx::IntRect const& rect, Color cons
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorCPU::paint_radial_gradient(Gfx::IntRect const& rect, Web::Painting::RadialGradientData const& radial_gradient_data, Gfx::IntPoint const& center, Gfx::IntSize const& size)
|
||||
CommandResult CommandExecutorCPU::paint_radial_gradient(Gfx::IntRect const& rect, Web::Painting::RadialGradientData const& radial_gradient_data, Gfx::IntPoint const& center, Gfx::IntSize const& size, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
painter().fill_rect_with_radial_gradient(rect, radial_gradient_data.color_stops.list, center, size, radial_gradient_data.color_stops.repeat_length);
|
||||
auto paint_op = [&](Gfx::Painter& painter) {
|
||||
painter.fill_rect_with_radial_gradient(rect, radial_gradient_data.color_stops.list, center, size, radial_gradient_data.color_stops.repeat_length);
|
||||
};
|
||||
if (clip_paths.is_empty()) {
|
||||
paint_op(painter());
|
||||
} else {
|
||||
apply_clip_paths_to_painter(rect, paint_op, clip_paths, painter());
|
||||
}
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorCPU::paint_conic_gradient(Gfx::IntRect const& rect, Web::Painting::ConicGradientData const& conic_gradient_data, Gfx::IntPoint const& position)
|
||||
CommandResult CommandExecutorCPU::paint_conic_gradient(Gfx::IntRect const& rect, Web::Painting::ConicGradientData const& conic_gradient_data, Gfx::IntPoint const& position, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
painter().fill_rect_with_conic_gradient(rect, conic_gradient_data.color_stops.list, position, conic_gradient_data.start_angle, conic_gradient_data.color_stops.repeat_length);
|
||||
auto paint_op = [&](Gfx::Painter& painter) {
|
||||
painter.fill_rect_with_conic_gradient(rect, conic_gradient_data.color_stops.list, position, conic_gradient_data.start_angle, conic_gradient_data.color_stops.repeat_length);
|
||||
};
|
||||
if (clip_paths.is_empty()) {
|
||||
paint_op(painter());
|
||||
} else {
|
||||
apply_clip_paths_to_painter(rect, paint_op, clip_paths, painter());
|
||||
}
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,18 +15,18 @@ class CommandExecutorCPU : public CommandExecutor {
|
|||
public:
|
||||
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation, double scale) override;
|
||||
CommandResult draw_text(Gfx::IntRect const& rect, String const& raw_text, Gfx::TextAlignment alignment, Color const&, Gfx::TextElision, Gfx::TextWrapping, Optional<NonnullRefPtr<Gfx::Font>> const&) override;
|
||||
CommandResult fill_rect(Gfx::IntRect const& rect, Color const&) override;
|
||||
CommandResult fill_rect(Gfx::IntRect const& rect, Color const&, Vector<Gfx::Path> const& clip_paths) override;
|
||||
CommandResult draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) override;
|
||||
CommandResult draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) override;
|
||||
CommandResult draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode, Vector<Gfx::Path> const& clip_paths = {}) override;
|
||||
CommandResult set_clip_rect(Gfx::IntRect const& rect) override;
|
||||
CommandResult clear_clip_rect() override;
|
||||
CommandResult push_stacking_context(float opacity, bool is_fixed_position, Gfx::IntRect const& source_paintable_rect, Gfx::IntPoint post_transform_translation, CSS::ImageRendering image_rendering, StackingContextTransform transform, Optional<StackingContextMask> mask) override;
|
||||
CommandResult pop_stacking_context() override;
|
||||
CommandResult paint_linear_gradient(Gfx::IntRect const&, Web::Painting::LinearGradientData const&) override;
|
||||
CommandResult paint_linear_gradient(Gfx::IntRect const&, Web::Painting::LinearGradientData const&, Vector<Gfx::Path> const& clip_paths = {}) override;
|
||||
CommandResult paint_outer_box_shadow(PaintOuterBoxShadowParams const&) override;
|
||||
CommandResult paint_inner_box_shadow(PaintOuterBoxShadowParams const&) override;
|
||||
CommandResult paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, Span<Gfx::DrawGlyphOrEmoji const>, Color const&, int fragment_baseline, Gfx::IntPoint const& draw_location) override;
|
||||
CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const&, Color const&, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius) override;
|
||||
CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const&, Color const&, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Vector<Gfx::Path> const& clip_paths) override;
|
||||
CommandResult fill_path_using_color(Gfx::Path const&, Color const&, Gfx::Painter::WindingRule winding_rule, Gfx::FloatPoint const& aa_translation) override;
|
||||
CommandResult fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const& paint_style, Gfx::Painter::WindingRule winding_rule, float opacity, Gfx::FloatPoint const& aa_translation) override;
|
||||
CommandResult stroke_path_using_color(Gfx::Path const&, Color const& color, float thickness, Gfx::FloatPoint const& aa_translation) override;
|
||||
|
@ -38,8 +38,8 @@ public:
|
|||
CommandResult paint_frame(Gfx::IntRect const& rect, Palette const&, Gfx::FrameStyle) override;
|
||||
CommandResult apply_backdrop_filter(Gfx::IntRect const& backdrop_region, Web::CSS::ResolvedBackdropFilter const& backdrop_filter) override;
|
||||
CommandResult draw_rect(Gfx::IntRect const& rect, Color const&, bool rough) override;
|
||||
CommandResult paint_radial_gradient(Gfx::IntRect const& rect, Web::Painting::RadialGradientData const& radial_gradient_data, Gfx::IntPoint const& center, Gfx::IntSize const& size) override;
|
||||
CommandResult paint_conic_gradient(Gfx::IntRect const& rect, Web::Painting::ConicGradientData const& conic_gradient_data, Gfx::IntPoint const& position) override;
|
||||
CommandResult paint_radial_gradient(Gfx::IntRect const& rect, Web::Painting::RadialGradientData const& radial_gradient_data, Gfx::IntPoint const& center, Gfx::IntSize const& size, Vector<Gfx::Path> const& clip_paths = {}) override;
|
||||
CommandResult paint_conic_gradient(Gfx::IntRect const& rect, Web::Painting::ConicGradientData const& conic_gradient_data, Gfx::IntPoint const& position, Vector<Gfx::Path> const& clip_paths = {}) override;
|
||||
CommandResult draw_triangle_wave(Gfx::IntPoint const& p1, Gfx::IntPoint const& p2, Color const&, int amplitude, int thickness) override;
|
||||
CommandResult sample_under_corners(u32 id, CornerRadii const&, Gfx::IntRect const&, CornerClip) override;
|
||||
CommandResult blit_corner_clipping(u32 id) override;
|
||||
|
|
|
@ -53,8 +53,9 @@ CommandResult CommandExecutorGPU::draw_text(Gfx::IntRect const&, String const&,
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorGPU::fill_rect(Gfx::IntRect const& rect, Color const& color)
|
||||
CommandResult CommandExecutorGPU::fill_rect(Gfx::IntRect const& rect, Color const& color, Vector<Gfx::Path> const&)
|
||||
{
|
||||
// FIXME: Support clip paths
|
||||
painter().fill_rect(rect, color);
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
@ -80,8 +81,9 @@ CommandResult CommandExecutorGPU::draw_scaled_bitmap(Gfx::IntRect const& dst_rec
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorGPU::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& immutable_bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode)
|
||||
CommandResult CommandExecutorGPU::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& immutable_bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode, Vector<Gfx::Path> const&)
|
||||
{
|
||||
// TODO: Support clip paths
|
||||
painter().draw_scaled_immutable_bitmap(dst_rect, immutable_bitmap, src_rect, to_accelgfx_scaling_mode(scaling_mode));
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
@ -160,8 +162,9 @@ CommandResult CommandExecutorGPU::pop_stacking_context()
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorGPU::paint_linear_gradient(Gfx::IntRect const& rect, Web::Painting::LinearGradientData const& data)
|
||||
CommandResult CommandExecutorGPU::paint_linear_gradient(Gfx::IntRect const& rect, Web::Painting::LinearGradientData const& data, Vector<Gfx::Path> const&)
|
||||
{
|
||||
// FIXME: Support clip paths
|
||||
painter().fill_rect_with_linear_gradient(rect, data.color_stops.list, data.gradient_angle, data.color_stops.repeat_length);
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
@ -201,8 +204,9 @@ CommandResult CommandExecutorGPU::paint_text_shadow(int blur_radius, Gfx::IntRec
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorGPU::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius)
|
||||
CommandResult CommandExecutorGPU::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Vector<Gfx::Path> const&)
|
||||
{
|
||||
// FIXME: Support clip paths
|
||||
painter().fill_rect_with_rounded_corners(
|
||||
rect, color,
|
||||
{ static_cast<float>(top_left_radius.horizontal_radius), static_cast<float>(top_left_radius.vertical_radius) },
|
||||
|
@ -286,13 +290,13 @@ CommandResult CommandExecutorGPU::draw_rect(Gfx::IntRect const&, Color const&, b
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorGPU::paint_radial_gradient(Gfx::IntRect const&, Web::Painting::RadialGradientData const&, Gfx::IntPoint const&, Gfx::IntSize const&)
|
||||
CommandResult CommandExecutorGPU::paint_radial_gradient(Gfx::IntRect const&, Web::Painting::RadialGradientData const&, Gfx::IntPoint const&, Gfx::IntSize const&, Vector<Gfx::Path> const&)
|
||||
{
|
||||
// FIXME
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorGPU::paint_conic_gradient(Gfx::IntRect const&, Web::Painting::ConicGradientData const&, Gfx::IntPoint const&)
|
||||
CommandResult CommandExecutorGPU::paint_conic_gradient(Gfx::IntRect const&, Web::Painting::ConicGradientData const&, Gfx::IntPoint const&, Vector<Gfx::Path> const&)
|
||||
{
|
||||
// FIXME
|
||||
return CommandResult::Continue;
|
||||
|
|
|
@ -16,18 +16,18 @@ class CommandExecutorGPU : public CommandExecutor {
|
|||
public:
|
||||
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation, double scale) override;
|
||||
CommandResult draw_text(Gfx::IntRect const& rect, String const& raw_text, Gfx::TextAlignment alignment, Color const&, Gfx::TextElision, Gfx::TextWrapping, Optional<NonnullRefPtr<Gfx::Font>> const&) override;
|
||||
CommandResult fill_rect(Gfx::IntRect const& rect, Color const&) override;
|
||||
CommandResult fill_rect(Gfx::IntRect const& rect, Color const&, Vector<Gfx::Path> const& clip_paths) override;
|
||||
CommandResult draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) override;
|
||||
CommandResult draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) override;
|
||||
CommandResult draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode, Vector<Gfx::Path> const& clip_paths = {}) override;
|
||||
CommandResult set_clip_rect(Gfx::IntRect const& rect) override;
|
||||
CommandResult clear_clip_rect() override;
|
||||
CommandResult push_stacking_context(float opacity, bool, Gfx::IntRect const& source_paintable_rect, Gfx::IntPoint post_transform_translation, CSS::ImageRendering image_rendering, StackingContextTransform transform, Optional<StackingContextMask> mask) override;
|
||||
CommandResult pop_stacking_context() override;
|
||||
CommandResult paint_linear_gradient(Gfx::IntRect const&, Web::Painting::LinearGradientData const&) override;
|
||||
CommandResult paint_linear_gradient(Gfx::IntRect const&, Web::Painting::LinearGradientData const&, Vector<Gfx::Path> const& clip_paths = {}) override;
|
||||
CommandResult paint_outer_box_shadow(PaintOuterBoxShadowParams const&) override;
|
||||
CommandResult paint_inner_box_shadow(PaintOuterBoxShadowParams const&) override;
|
||||
CommandResult paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, Span<Gfx::DrawGlyphOrEmoji const>, Color const&, int fragment_baseline, Gfx::IntPoint const& draw_location) override;
|
||||
CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const&, Color const&, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius) override;
|
||||
CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const&, Color const&, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Vector<Gfx::Path> const& clip_paths) override;
|
||||
CommandResult fill_path_using_color(Gfx::Path const&, Color const&, Gfx::Painter::WindingRule winding_rule, Gfx::FloatPoint const& aa_translation) override;
|
||||
CommandResult fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const& paint_style, Gfx::Painter::WindingRule winding_rule, float opacity, Gfx::FloatPoint const& aa_translation) override;
|
||||
CommandResult stroke_path_using_color(Gfx::Path const&, Color const& color, float thickness, Gfx::FloatPoint const& aa_translation) override;
|
||||
|
@ -39,8 +39,8 @@ public:
|
|||
CommandResult paint_frame(Gfx::IntRect const& rect, Palette const&, Gfx::FrameStyle) override;
|
||||
CommandResult apply_backdrop_filter(Gfx::IntRect const& backdrop_region, Web::CSS::ResolvedBackdropFilter const& backdrop_filter) override;
|
||||
CommandResult draw_rect(Gfx::IntRect const& rect, Color const&, bool rough) override;
|
||||
CommandResult paint_radial_gradient(Gfx::IntRect const& rect, Web::Painting::RadialGradientData const& radial_gradient_data, Gfx::IntPoint const& center, Gfx::IntSize const& size) override;
|
||||
CommandResult paint_conic_gradient(Gfx::IntRect const& rect, Web::Painting::ConicGradientData const& conic_gradient_data, Gfx::IntPoint const& position) override;
|
||||
CommandResult paint_radial_gradient(Gfx::IntRect const& rect, Web::Painting::RadialGradientData const& radial_gradient_data, Gfx::IntPoint const& center, Gfx::IntSize const& size, Vector<Gfx::Path> const& clip_paths = {}) override;
|
||||
CommandResult paint_conic_gradient(Gfx::IntRect const& rect, Web::Painting::ConicGradientData const& conic_gradient_data, Gfx::IntPoint const& position, Vector<Gfx::Path> const& clip_paths = {}) override;
|
||||
CommandResult draw_triangle_wave(Gfx::IntPoint const& p1, Gfx::IntPoint const& p2, Color const&, int amplitude, int thickness) override;
|
||||
CommandResult sample_under_corners(u32 id, CornerRadii const&, Gfx::IntRect const&, CornerClip) override;
|
||||
CommandResult blit_corner_clipping(u32) override;
|
||||
|
|
|
@ -96,7 +96,7 @@ void CommandList::execute(CommandExecutor& executor)
|
|||
command.elision, command.wrapping, command.font);
|
||||
},
|
||||
[&](FillRect const& command) {
|
||||
return executor.fill_rect(command.rect, command.color);
|
||||
return executor.fill_rect(command.rect, command.color, command.clip_paths);
|
||||
},
|
||||
[&](DrawScaledBitmap const& command) {
|
||||
return executor.draw_scaled_bitmap(command.dst_rect, command.bitmap, command.src_rect,
|
||||
|
@ -104,7 +104,7 @@ void CommandList::execute(CommandExecutor& executor)
|
|||
},
|
||||
[&](DrawScaledImmutableBitmap const& command) {
|
||||
return executor.draw_scaled_immutable_bitmap(command.dst_rect, command.bitmap, command.src_rect,
|
||||
command.scaling_mode);
|
||||
command.scaling_mode, command.clip_paths);
|
||||
},
|
||||
[&](SetClipRect const& command) {
|
||||
return executor.set_clip_rect(command.rect);
|
||||
|
@ -122,15 +122,15 @@ void CommandList::execute(CommandExecutor& executor)
|
|||
return executor.pop_stacking_context();
|
||||
},
|
||||
[&](PaintLinearGradient const& command) {
|
||||
return executor.paint_linear_gradient(command.gradient_rect, command.linear_gradient_data);
|
||||
return executor.paint_linear_gradient(command.gradient_rect, command.linear_gradient_data, command.clip_paths);
|
||||
},
|
||||
[&](PaintRadialGradient const& command) {
|
||||
return executor.paint_radial_gradient(command.rect, command.radial_gradient_data,
|
||||
command.center, command.size);
|
||||
command.center, command.size, command.clip_paths);
|
||||
},
|
||||
[&](PaintConicGradient const& command) {
|
||||
return executor.paint_conic_gradient(command.rect, command.conic_gradient_data,
|
||||
command.position);
|
||||
command.position, command.clip_paths);
|
||||
},
|
||||
[&](PaintOuterBoxShadow const& command) {
|
||||
return executor.paint_outer_box_shadow(command.outer_box_shadow_params);
|
||||
|
@ -148,7 +148,8 @@ void CommandList::execute(CommandExecutor& executor)
|
|||
command.top_left_radius,
|
||||
command.top_right_radius,
|
||||
command.bottom_left_radius,
|
||||
command.bottom_right_radius);
|
||||
command.bottom_right_radius,
|
||||
command.clip_paths);
|
||||
},
|
||||
[&](FillPathUsingColor const& command) {
|
||||
return executor.fill_path_using_color(command.path, command.color, command.winding_rule,
|
||||
|
|
|
@ -49,16 +49,16 @@ public:
|
|||
|
||||
virtual CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation, double scale) = 0;
|
||||
virtual CommandResult draw_text(Gfx::IntRect const&, String const&, Gfx::TextAlignment alignment, Color const&, Gfx::TextElision, Gfx::TextWrapping, Optional<NonnullRefPtr<Gfx::Font>> const&) = 0;
|
||||
virtual CommandResult fill_rect(Gfx::IntRect const&, Color const&) = 0;
|
||||
virtual CommandResult fill_rect(Gfx::IntRect const&, Color const&, Vector<Gfx::Path> const& clip_paths) = 0;
|
||||
virtual CommandResult draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) = 0;
|
||||
virtual CommandResult draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) = 0;
|
||||
virtual CommandResult draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode, Vector<Gfx::Path> const& clip_paths = {}) = 0;
|
||||
virtual CommandResult set_clip_rect(Gfx::IntRect const& rect) = 0;
|
||||
virtual CommandResult clear_clip_rect() = 0;
|
||||
virtual CommandResult push_stacking_context(float opacity, bool is_fixed_position, Gfx::IntRect const& source_paintable_rect, Gfx::IntPoint post_transform_translation, CSS::ImageRendering image_rendering, StackingContextTransform transform, Optional<StackingContextMask> mask) = 0;
|
||||
virtual CommandResult pop_stacking_context() = 0;
|
||||
virtual CommandResult paint_linear_gradient(Gfx::IntRect const&, LinearGradientData const&) = 0;
|
||||
virtual CommandResult paint_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const&, Gfx::IntPoint const& center, Gfx::IntSize const& size) = 0;
|
||||
virtual CommandResult paint_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const&, Gfx::IntPoint const& position) = 0;
|
||||
virtual CommandResult paint_linear_gradient(Gfx::IntRect const&, LinearGradientData const&, Vector<Gfx::Path> const& clip_paths = {}) = 0;
|
||||
virtual CommandResult paint_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const&, Gfx::IntPoint const& center, Gfx::IntSize const& size, Vector<Gfx::Path> const& clip_paths = {}) = 0;
|
||||
virtual CommandResult paint_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const&, Gfx::IntPoint const& position, Vector<Gfx::Path> const& clip_paths = {}) = 0;
|
||||
virtual CommandResult paint_outer_box_shadow(PaintOuterBoxShadowParams const&) = 0;
|
||||
virtual CommandResult paint_inner_box_shadow(PaintOuterBoxShadowParams const&) = 0;
|
||||
virtual CommandResult paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, Span<Gfx::DrawGlyphOrEmoji const>, Color const&, int fragment_baseline, Gfx::IntPoint const& draw_location) = 0;
|
||||
|
@ -66,7 +66,8 @@ public:
|
|||
Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius,
|
||||
Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius,
|
||||
Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius,
|
||||
Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius)
|
||||
Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius,
|
||||
Vector<Gfx::Path> const& clip_paths = {})
|
||||
= 0;
|
||||
virtual CommandResult fill_path_using_color(Gfx::Path const&, Color const& color, Gfx::Painter::WindingRule, Gfx::FloatPoint const& aa_translation) = 0;
|
||||
virtual CommandResult fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const& paint_style, Gfx::Painter::WindingRule winding_rule, float opacity, Gfx::FloatPoint const& aa_translation) = 0;
|
||||
|
|
|
@ -146,19 +146,19 @@ RadialGradientData resolve_radial_gradient_data(Layout::NodeWithStyleAndBoxModel
|
|||
return { resolved_color_stops };
|
||||
}
|
||||
|
||||
void paint_linear_gradient(PaintContext& context, DevicePixelRect const& gradient_rect, LinearGradientData const& data)
|
||||
void paint_linear_gradient(PaintContext& context, DevicePixelRect const& gradient_rect, LinearGradientData const& data, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
context.recording_painter().fill_rect_with_linear_gradient(gradient_rect.to_type<int>(), data);
|
||||
context.recording_painter().fill_rect_with_linear_gradient(gradient_rect.to_type<int>(), data, clip_paths);
|
||||
}
|
||||
|
||||
void paint_conic_gradient(PaintContext& context, DevicePixelRect const& gradient_rect, ConicGradientData const& data, DevicePixelPoint position)
|
||||
void paint_conic_gradient(PaintContext& context, DevicePixelRect const& gradient_rect, ConicGradientData const& data, DevicePixelPoint position, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
context.recording_painter().fill_rect_with_conic_gradient(gradient_rect.to_type<int>(), data, position.to_type<int>());
|
||||
context.recording_painter().fill_rect_with_conic_gradient(gradient_rect.to_type<int>(), data, position.to_type<int>(), clip_paths);
|
||||
}
|
||||
|
||||
void paint_radial_gradient(PaintContext& context, DevicePixelRect const& gradient_rect, RadialGradientData const& data, DevicePixelPoint center, DevicePixelSize size)
|
||||
void paint_radial_gradient(PaintContext& context, DevicePixelRect const& gradient_rect, RadialGradientData const& data, DevicePixelPoint center, DevicePixelSize size, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
context.recording_painter().fill_rect_with_radial_gradient(gradient_rect.to_type<int>(), data, center.to_type<int>(), size.to_type<int>());
|
||||
context.recording_painter().fill_rect_with_radial_gradient(gradient_rect.to_type<int>(), data, center.to_type<int>(), size.to_type<int>(), clip_paths);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ LinearGradientData resolve_linear_gradient_data(Layout::NodeWithStyleAndBoxModel
|
|||
ConicGradientData resolve_conic_gradient_data(Layout::NodeWithStyleAndBoxModelMetrics const&, CSS::ConicGradientStyleValue const&);
|
||||
RadialGradientData resolve_radial_gradient_data(Layout::NodeWithStyleAndBoxModelMetrics const&, CSSPixelSize, CSS::RadialGradientStyleValue const&);
|
||||
|
||||
void paint_linear_gradient(PaintContext&, DevicePixelRect const&, LinearGradientData const&);
|
||||
void paint_conic_gradient(PaintContext&, DevicePixelRect const&, ConicGradientData const&, DevicePixelPoint position);
|
||||
void paint_radial_gradient(PaintContext&, DevicePixelRect const&, RadialGradientData const&, DevicePixelPoint position, DevicePixelSize size);
|
||||
void paint_linear_gradient(PaintContext&, DevicePixelRect const&, LinearGradientData const&, Vector<Gfx::Path> const& clip_paths = {});
|
||||
void paint_conic_gradient(PaintContext&, DevicePixelRect const&, ConicGradientData const&, DevicePixelPoint position, Vector<Gfx::Path> const& clip_paths = {});
|
||||
void paint_radial_gradient(PaintContext&, DevicePixelRect const&, RadialGradientData const&, DevicePixelPoint position, DevicePixelSize size, Vector<Gfx::Path> const& clip_paths = {});
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/GenericShorthands.h>
|
||||
#include <LibGfx/Font/ScaledFont.h>
|
||||
#include <LibUnicode/CharacterTypes.h>
|
||||
#include <LibWeb/CSS/SystemColor.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
|
@ -455,7 +456,72 @@ void PaintableBox::paint_background(PaintContext& context) const
|
|||
if (computed_values().border_top().width != 0 || computed_values().border_right().width != 0 || computed_values().border_bottom().width != 0 || computed_values().border_left().width != 0)
|
||||
background_rect = absolute_border_box_rect();
|
||||
|
||||
Painting::paint_background(context, layout_box(), background_rect, background_color, computed_values().image_rendering(), background_layers, normalized_border_radii_data());
|
||||
Vector<Gfx::Path> text_clip_paths {};
|
||||
if (background_layers && !background_layers->is_empty() && background_layers->last().clip == CSS::BackgroundBox::Text) {
|
||||
text_clip_paths = compute_text_clip_paths(context);
|
||||
}
|
||||
|
||||
Painting::paint_background(context, layout_box(), background_rect, background_color, computed_values().image_rendering(), background_layers, normalized_border_radii_data(), text_clip_paths);
|
||||
}
|
||||
|
||||
Vector<Gfx::Path> PaintableBox::compute_text_clip_paths(PaintContext& context) const
|
||||
{
|
||||
Vector<Gfx::Path> text_clip_paths;
|
||||
auto add_text_clip_path = [&](PaintableFragment const& fragment) {
|
||||
// Scale to the device pixels.
|
||||
Gfx::Path glyph_run_path;
|
||||
for (auto glyph : fragment.glyph_run().glyphs()) {
|
||||
glyph.visit([&](auto& glyph) {
|
||||
glyph.font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(context.device_pixels_per_css_pixel()));
|
||||
glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel());
|
||||
});
|
||||
|
||||
if (glyph.has<Gfx::DrawGlyph>()) {
|
||||
auto const& draw_glyph = glyph.get<Gfx::DrawGlyph>();
|
||||
|
||||
// Get the path for the glyph.
|
||||
Gfx::Path glyph_path;
|
||||
auto const& scaled_font = static_cast<Gfx::ScaledFont const&>(*draw_glyph.font);
|
||||
auto glyph_id = scaled_font.glyph_id_for_code_point(draw_glyph.code_point);
|
||||
scaled_font.append_glyph_path_to(glyph_path, glyph_id);
|
||||
|
||||
// Transform the path to the fragment's position.
|
||||
// FIXME: Record glyphs and use Painter::draw_glyphs() instead to avoid this duplicated code.
|
||||
auto top_left = draw_glyph.position + Gfx::FloatPoint(scaled_font.glyph_left_bearing(draw_glyph.code_point), 0);
|
||||
auto glyph_position = Gfx::GlyphRasterPosition::get_nearest_fit_for(top_left);
|
||||
auto transform = Gfx::AffineTransform {}.translate(glyph_position.blit_position.to_type<float>());
|
||||
glyph_run_path.append_path(glyph_path.copy_transformed(transform));
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the baseline start position.
|
||||
auto fragment_absolute_rect = fragment.absolute_rect();
|
||||
auto fragment_absolute_device_rect = context.enclosing_device_rect(fragment_absolute_rect);
|
||||
DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + context.rounded_device_pixels(fragment.baseline()) };
|
||||
|
||||
// Add the path to text_clip_paths.
|
||||
auto transform = Gfx::AffineTransform {}.translate(baseline_start.to_type<int>().to_type<float>());
|
||||
text_clip_paths.append(glyph_run_path.copy_transformed(transform));
|
||||
};
|
||||
|
||||
for_each_in_inclusive_subtree([&](auto& paintable) {
|
||||
if (is<PaintableWithLines>(paintable)) {
|
||||
auto const& paintable_lines = static_cast<PaintableWithLines const&>(paintable);
|
||||
for (auto const& fragment : paintable_lines.fragments()) {
|
||||
if (is<Layout::TextNode>(fragment.layout_node()))
|
||||
add_text_clip_path(fragment);
|
||||
}
|
||||
} else if (is<InlinePaintable>(paintable)) {
|
||||
auto const& inline_paintable = static_cast<InlinePaintable const&>(paintable);
|
||||
for (auto const& fragment : inline_paintable.fragments()) {
|
||||
if (is<Layout::TextNode>(fragment.layout_node()))
|
||||
add_text_clip_path(fragment);
|
||||
}
|
||||
}
|
||||
return TraversalDecision::Continue;
|
||||
});
|
||||
|
||||
return text_clip_paths;
|
||||
}
|
||||
|
||||
void PaintableBox::paint_box_shadow(PaintContext& context) const
|
||||
|
|
|
@ -227,6 +227,8 @@ protected:
|
|||
virtual CSSPixelRect compute_absolute_paint_rect() const;
|
||||
|
||||
private:
|
||||
Vector<Gfx::Path> compute_text_clip_paths(PaintContext&) const;
|
||||
|
||||
[[nodiscard]] virtual bool is_paintable_box() const final { return true; }
|
||||
|
||||
enum class ScrollDirection {
|
||||
|
|
|
@ -34,11 +34,12 @@ void RecordingPainter::blit_corner_clipping(u32 id, Gfx::IntRect border_rect)
|
|||
append(BlitCornerClipping { id, border_rect = state().translation.map(border_rect) });
|
||||
}
|
||||
|
||||
void RecordingPainter::fill_rect(Gfx::IntRect const& rect, Color color)
|
||||
void RecordingPainter::fill_rect(Gfx::IntRect const& rect, Color color, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
append(FillRect {
|
||||
.rect = state().translation.map(rect),
|
||||
.color = color,
|
||||
.clip_paths = clip_paths,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -118,29 +119,31 @@ void RecordingPainter::fill_ellipse(Gfx::IntRect const& a_rect, Color color, Gfx
|
|||
});
|
||||
}
|
||||
|
||||
void RecordingPainter::fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data)
|
||||
void RecordingPainter::fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
append(PaintLinearGradient {
|
||||
.gradient_rect = state().translation.map(gradient_rect),
|
||||
.linear_gradient_data = data,
|
||||
});
|
||||
.clip_paths = clip_paths });
|
||||
}
|
||||
|
||||
void RecordingPainter::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position)
|
||||
void RecordingPainter::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
append(PaintConicGradient {
|
||||
.rect = state().translation.map(rect),
|
||||
.conic_gradient_data = data,
|
||||
.position = position });
|
||||
.position = position,
|
||||
.clip_paths = clip_paths });
|
||||
}
|
||||
|
||||
void RecordingPainter::fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size)
|
||||
void RecordingPainter::fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
append(PaintRadialGradient {
|
||||
.rect = state().translation.map(rect),
|
||||
.radial_gradient_data = data,
|
||||
.center = center,
|
||||
.size = size });
|
||||
.size = size,
|
||||
.clip_paths = clip_paths });
|
||||
}
|
||||
|
||||
void RecordingPainter::draw_rect(Gfx::IntRect const& rect, Color color, bool rough)
|
||||
|
@ -161,13 +164,14 @@ void RecordingPainter::draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bit
|
|||
});
|
||||
}
|
||||
|
||||
void RecordingPainter::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode)
|
||||
void RecordingPainter::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
append(DrawScaledImmutableBitmap {
|
||||
.dst_rect = state().translation.map(dst_rect),
|
||||
.bitmap = bitmap,
|
||||
.src_rect = src_rect,
|
||||
.scaling_mode = scaling_mode,
|
||||
.clip_paths = clip_paths,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -327,10 +331,10 @@ void RecordingPainter::paint_text_shadow(int blur_radius, Gfx::IntRect bounding_
|
|||
.draw_location = state().translation.map(draw_location) });
|
||||
}
|
||||
|
||||
void RecordingPainter::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 RecordingPainter::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, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
if (!top_left_radius && !top_right_radius && !bottom_right_radius && !bottom_left_radius) {
|
||||
fill_rect(rect, color);
|
||||
fill_rect(rect, color, clip_paths);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -341,21 +345,23 @@ void RecordingPainter::fill_rect_with_rounded_corners(Gfx::IntRect const& rect,
|
|||
.top_right_radius = top_right_radius,
|
||||
.bottom_left_radius = bottom_left_radius,
|
||||
.bottom_right_radius = bottom_right_radius,
|
||||
.clip_paths = clip_paths,
|
||||
});
|
||||
}
|
||||
|
||||
void RecordingPainter::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius)
|
||||
void RecordingPainter::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
fill_rect_with_rounded_corners(a_rect, color, radius, radius, radius, radius);
|
||||
fill_rect_with_rounded_corners(a_rect, color, radius, radius, radius, radius, clip_paths);
|
||||
}
|
||||
|
||||
void RecordingPainter::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 RecordingPainter::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, Vector<Gfx::Path> const& clip_paths)
|
||||
{
|
||||
fill_rect_with_rounded_corners(a_rect, color,
|
||||
{ top_left_radius, top_left_radius },
|
||||
{ top_right_radius, top_right_radius },
|
||||
{ bottom_right_radius, bottom_right_radius },
|
||||
{ bottom_left_radius, bottom_left_radius });
|
||||
{ bottom_left_radius, bottom_left_radius },
|
||||
clip_paths);
|
||||
}
|
||||
|
||||
void RecordingPainter::draw_triangle_wave(Gfx::IntPoint a_p1, Gfx::IntPoint a_p2, Color color, int amplitude, int thickness = 1)
|
||||
|
|
|
@ -44,7 +44,7 @@ class RecordingPainter {
|
|||
AK_MAKE_NONMOVABLE(RecordingPainter);
|
||||
|
||||
public:
|
||||
void fill_rect(Gfx::IntRect const& rect, Color color);
|
||||
void fill_rect(Gfx::IntRect const& rect, Color color, Vector<Gfx::Path> const& clip_paths = {});
|
||||
|
||||
struct FillPathUsingColorParams {
|
||||
Gfx::Path path;
|
||||
|
@ -84,14 +84,14 @@ public:
|
|||
|
||||
void fill_ellipse(Gfx::IntRect const& a_rect, Color color, Gfx::AntiAliasingPainter::BlendMode blend_mode = Gfx::AntiAliasingPainter::BlendMode::Normal);
|
||||
|
||||
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 fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data, Vector<Gfx::Path> const& clip_paths = {});
|
||||
void fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position, Vector<Gfx::Path> const& clip_paths = {});
|
||||
void fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size, Vector<Gfx::Path> const& clip_paths = {});
|
||||
|
||||
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::Painter::ScalingMode scaling_mode = Gfx::Painter::ScalingMode::NearestNeighbor);
|
||||
void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode = Gfx::Painter::ScalingMode::NearestNeighbor);
|
||||
void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode = Gfx::Painter::ScalingMode::NearestNeighbor, Vector<Gfx::Path> const& clip_paths = {});
|
||||
|
||||
void draw_line(Gfx::IntPoint from, Gfx::IntPoint to, Color color, int thickness = 1, Gfx::Painter::LineStyle style = Gfx::Painter::LineStyle::Solid, Color alternate_color = Color::Transparent);
|
||||
|
||||
|
@ -137,9 +137,9 @@ public:
|
|||
void paint_inner_box_shadow_params(PaintOuterBoxShadowParams params);
|
||||
void paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color color, int fragment_baseline, 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);
|
||||
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 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, Vector<Gfx::Path> const& clip_paths = {});
|
||||
void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius, Vector<Gfx::Path> const& clip_paths = {});
|
||||
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, Vector<Gfx::Path> const& clip_paths = {});
|
||||
|
||||
void draw_triangle_wave(Gfx::IntPoint a_p1, Gfx::IntPoint a_p2, Color color, int amplitude, int thickness);
|
||||
|
||||
|
|
Loading…
Reference in a new issue