mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-11 05:25:32 +03:00
LibWeb: Save "background-clip: text" mask as a nested display list
Before this change, "background-clip: text" was implemented by saving a Vector<Gfx::Path> of all glyphs needed to paint a mask for the background. The issue with this approach was that once glyphs were extracted into vector paths, the glyph rasterization cache could no longer be utilized. With this change, all text required for mask painting is saved in a nested display list and rasterized as a regular text.
This commit is contained in:
parent
50ab5642cc
commit
67d68eac64
Notes:
github-actions[bot]
2024-07-25 12:34:36 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/67d68eac64f Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/826
Binary file not shown.
Before Width: | Height: | Size: 272 KiB After Width: | Height: | Size: 267 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, Vector<Gfx::Path> const& clip_paths = {}) const = 0;
|
||||
virtual void paint(PaintContext& context, DevicePixelRect const& dest_rect, ImageRendering, RefPtr<Painting::DisplayList> text_clip = {}) 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, Vector<Gfx::Path> const& clip_paths) const
|
||||
void ConicGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip) 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, clip_paths);
|
||||
context.display_list_recorder().fill_rect_with_conic_gradient(destination_rect, m_resolved->data, position, text_clip);
|
||||
}
|
||||
|
||||
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, Vector<Gfx::Path> const& clip_paths = {}) const override;
|
||||
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip = {}) const override;
|
||||
|
||||
virtual bool equals(StyleValue const& other) const override;
|
||||
|
||||
|
@ -133,11 +133,11 @@ Optional<CSSPixelFraction> ImageStyleValue::natural_aspect_ratio() const
|
||||
return {};
|
||||
}
|
||||
|
||||
void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, Vector<Gfx::Path> const& clip_paths) const
|
||||
void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, RefPtr<Painting::DisplayList> text_clip) 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, clip_paths);
|
||||
context.display_list_recorder().draw_scaled_immutable_bitmap(dest_rect.to_type<int>(), *b, b->rect(), scaling_mode, text_clip);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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, Vector<Gfx::Path> const& clip_paths = {}) const override;
|
||||
void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, RefPtr<Painting::DisplayList> clip_paths = {}) 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, Vector<Gfx::Path> const& clip_paths) const
|
||||
void LinearGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip) const
|
||||
{
|
||||
VERIFY(m_resolved.has_value());
|
||||
context.display_list_recorder().fill_rect_with_linear_gradient(dest_rect.to_type<int>(), m_resolved->data, clip_paths);
|
||||
context.display_list_recorder().fill_rect_with_linear_gradient(dest_rect.to_type<int>(), m_resolved->data, text_clip);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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, Vector<Gfx::Path> const& clip_paths = {}) const override;
|
||||
void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, RefPtr<Painting::DisplayList> text_clip = {}) 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, Vector<Gfx::Path> const& clip_paths) const
|
||||
void RadialGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip) 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, clip_paths);
|
||||
context.display_list_recorder().fill_rect_with_radial_gradient(dest_rect.to_type<int>(), m_resolved->data, center, size, text_clip);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
|
||||
virtual String to_string() const override;
|
||||
|
||||
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering, Vector<Gfx::Path> const& clip_paths = {}) const override;
|
||||
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr<Painting::DisplayList> text_clip = {}) const override;
|
||||
|
||||
virtual bool equals(StyleValue const& other) const override;
|
||||
|
||||
|
@ -25,6 +25,7 @@ class XMLDocumentBuilder;
|
||||
|
||||
namespace Web::Painting {
|
||||
class BackingStore;
|
||||
class DisplayList;
|
||||
class DisplayListRecorder;
|
||||
class SVGGradientPaintStyle;
|
||||
using PaintStyle = RefPtr<SVGGradientPaintStyle>;
|
||||
|
@ -58,47 +58,21 @@ static CSSPixelSize run_default_sizing_algorithm(
|
||||
return default_size;
|
||||
}
|
||||
|
||||
static Vector<Gfx::Path> compute_text_clip_paths(PaintContext& context, Paintable const& paintable)
|
||||
static RefPtr<DisplayList> compute_text_clip_paths(PaintContext& context, Paintable const& paintable)
|
||||
{
|
||||
Vector<Gfx::Path> text_clip_paths;
|
||||
auto text_clip_paths = DisplayList::create();
|
||||
DisplayListRecorder display_list_recorder(*text_clip_paths);
|
||||
auto add_text_clip_path = [&](PaintableFragment const& fragment) {
|
||||
auto glyph_run = fragment.glyph_run();
|
||||
if (!glyph_run || glyph_run->glyphs().is_empty())
|
||||
return;
|
||||
// Scale to the device pixels.
|
||||
Gfx::Path glyph_run_path;
|
||||
auto const& font = fragment.glyph_run()->font();
|
||||
auto scaled_font = font.with_size(font.point_size() * static_cast<float>(context.device_pixels_per_css_pixel()));
|
||||
for (auto glyph : fragment.glyph_run()->glyphs()) {
|
||||
glyph.visit([&](auto& glyph) {
|
||||
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 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));
|
||||
DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + context.rounded_device_pixels(fragment.baseline()) };
|
||||
auto scale = context.device_pixels_per_css_pixel();
|
||||
display_list_recorder.draw_text_run(baseline_start.to_type<int>(), *glyph_run, Gfx::Color::Black, fragment_absolute_device_rect.to_type<int>(), scale);
|
||||
};
|
||||
|
||||
paintable.for_each_in_inclusive_subtree([&](auto& paintable) {
|
||||
@ -124,9 +98,9 @@ static Vector<Gfx::Path> compute_text_clip_paths(PaintContext& context, Paintabl
|
||||
// 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)
|
||||
{
|
||||
Vector<Gfx::Path> clip_paths {};
|
||||
RefPtr<DisplayList> text_clip;
|
||||
if (background_layers && !background_layers->is_empty() && background_layers->last().clip == CSS::BackgroundBox::Text) {
|
||||
clip_paths = compute_text_clip_paths(context, *layout_node.paintable());
|
||||
text_clip = compute_text_clip_paths(context, *layout_node.paintable());
|
||||
}
|
||||
|
||||
auto& display_list_recorder = context.display_list_recorder();
|
||||
@ -191,7 +165,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
||||
color_box.radii.top_right.as_corner(context),
|
||||
color_box.radii.bottom_right.as_corner(context),
|
||||
color_box.radii.bottom_left.as_corner(context),
|
||||
clip_paths);
|
||||
text_clip);
|
||||
|
||||
if (!has_paintable_layers)
|
||||
return;
|
||||
@ -459,17 +433,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(), clip_paths);
|
||||
display_list_recorder.fill_rect(fill_rect->to_type<int>(), color.value(), text_clip);
|
||||
} 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>(), *bitmap, scaling_mode, { .x = repeat_x, .y = repeat_y }, clip_paths);
|
||||
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);
|
||||
} else {
|
||||
for_each_image_device_rect([&](auto const& image_device_rect) {
|
||||
image.paint(context, image_device_rect, image_rendering, clip_paths);
|
||||
image.paint(context, image_device_rect, image_rendering, text_clip);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
class DisplayList;
|
||||
|
||||
struct DrawGlyphRun {
|
||||
NonnullRefPtr<Gfx::GlyphRun> glyph_run;
|
||||
Color color;
|
||||
@ -48,7 +50,7 @@ struct DrawGlyphRun {
|
||||
struct FillRect {
|
||||
Gfx::IntRect rect;
|
||||
Color color;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
RefPtr<DisplayList> text_clip;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
|
||||
void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); }
|
||||
@ -69,7 +71,7 @@ struct DrawScaledImmutableBitmap {
|
||||
NonnullRefPtr<Gfx::ImmutableBitmap> bitmap;
|
||||
Gfx::IntRect src_rect;
|
||||
Gfx::ScalingMode scaling_mode;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
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); }
|
||||
@ -82,10 +84,11 @@ struct DrawRepeatedImmutableBitmap {
|
||||
};
|
||||
|
||||
Gfx::IntRect dst_rect;
|
||||
Gfx::IntRect clip_rect;
|
||||
NonnullRefPtr<Gfx::ImmutableBitmap> bitmap;
|
||||
Gfx::ScalingMode scaling_mode;
|
||||
Repeat repeat;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
RefPtr<DisplayList> text_clip;
|
||||
|
||||
void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); }
|
||||
};
|
||||
@ -129,7 +132,7 @@ struct PopStackingContext { };
|
||||
struct PaintLinearGradient {
|
||||
Gfx::IntRect gradient_rect;
|
||||
LinearGradientData linear_gradient_data;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
RefPtr<DisplayList> text_clip;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return gradient_rect; }
|
||||
|
||||
@ -170,7 +173,7 @@ struct FillRectWithRoundedCorners {
|
||||
Gfx::IntRect rect;
|
||||
Color color;
|
||||
CornerRadii corner_radii;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
RefPtr<DisplayList> text_clip;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
|
||||
void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); }
|
||||
@ -310,7 +313,7 @@ struct PaintRadialGradient {
|
||||
RadialGradientData radial_gradient_data;
|
||||
Gfx::IntPoint center;
|
||||
Gfx::IntSize size;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
RefPtr<DisplayList> text_clip;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
|
||||
|
||||
@ -321,7 +324,7 @@ struct PaintConicGradient {
|
||||
Gfx::IntRect rect;
|
||||
ConicGradientData conic_gradient_data;
|
||||
Gfx::IntPoint position;
|
||||
Vector<Gfx::Path> clip_paths;
|
||||
RefPtr<DisplayList> text_clip;
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
|
||||
|
||||
|
@ -62,6 +62,11 @@ public:
|
||||
m_surface->readPixels(pixmap, 0, 0);
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> make_surface(int width, int height)
|
||||
{
|
||||
return m_surface->makeSurface(width, height);
|
||||
}
|
||||
|
||||
private:
|
||||
sk_sp<SkSurface> m_surface;
|
||||
};
|
||||
@ -368,17 +373,13 @@ static SkSamplingOptions to_skia_sampling_options(Gfx::ScalingMode scaling_mode)
|
||||
}
|
||||
}
|
||||
|
||||
#define APPLY_PATH_CLIP_IF_NEEDED \
|
||||
ScopeGuard restore_path_clip { [&] { \
|
||||
if (command.clip_paths.size() > 0) \
|
||||
surface().canvas().restore(); \
|
||||
} }; \
|
||||
if (command.clip_paths.size() > 0) { \
|
||||
surface().canvas().save(); \
|
||||
SkPath clip_path; \
|
||||
for (auto const& path : command.clip_paths) \
|
||||
clip_path.addPath(to_skia_path(path)); \
|
||||
surface().canvas().clipPath(clip_path, true); \
|
||||
#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
|
||||
@ -422,7 +423,7 @@ void DisplayListPlayerSkia::draw_glyph_run(DrawGlyphRun const& command)
|
||||
|
||||
void DisplayListPlayerSkia::fill_rect(FillRect const& command)
|
||||
{
|
||||
APPLY_PATH_CLIP_IF_NEEDED
|
||||
APPLY_TEXT_CLIP_IF_NEEDED(command.rect)
|
||||
|
||||
auto const& rect = command.rect;
|
||||
auto& canvas = surface().canvas();
|
||||
@ -444,7 +445,7 @@ void DisplayListPlayerSkia::draw_scaled_bitmap(DrawScaledBitmap const& command)
|
||||
|
||||
void DisplayListPlayerSkia::draw_scaled_immutable_bitmap(DrawScaledImmutableBitmap const& command)
|
||||
{
|
||||
APPLY_PATH_CLIP_IF_NEEDED
|
||||
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);
|
||||
@ -457,7 +458,7 @@ void DisplayListPlayerSkia::draw_scaled_immutable_bitmap(DrawScaledImmutableBitm
|
||||
|
||||
void DisplayListPlayerSkia::draw_repeated_immutable_bitmap(DrawRepeatedImmutableBitmap const& command)
|
||||
{
|
||||
APPLY_PATH_CLIP_IF_NEEDED
|
||||
APPLY_TEXT_CLIP_IF_NEEDED(command.clip_rect)
|
||||
|
||||
auto bitmap = to_skia_bitmap(command.bitmap->bitmap());
|
||||
auto image = SkImages::RasterFromBitmap(bitmap);
|
||||
@ -655,7 +656,7 @@ static ColorStopList expand_repeat_length(ColorStopList const& color_stop_list,
|
||||
|
||||
void DisplayListPlayerSkia::paint_linear_gradient(PaintLinearGradient const& command)
|
||||
{
|
||||
APPLY_PATH_CLIP_IF_NEEDED
|
||||
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;
|
||||
@ -833,7 +834,7 @@ void DisplayListPlayerSkia::paint_text_shadow(PaintTextShadow const& command)
|
||||
|
||||
void DisplayListPlayerSkia::fill_rect_with_rounded_corners(FillRectWithRoundedCorners const& command)
|
||||
{
|
||||
APPLY_PATH_CLIP_IF_NEEDED
|
||||
APPLY_TEXT_CLIP_IF_NEEDED(command.rect)
|
||||
|
||||
auto const& rect = command.rect;
|
||||
|
||||
@ -1200,7 +1201,7 @@ void DisplayListPlayerSkia::draw_rect(DrawRect const& command)
|
||||
|
||||
void DisplayListPlayerSkia::paint_radial_gradient(PaintRadialGradient const& command)
|
||||
{
|
||||
APPLY_PATH_CLIP_IF_NEEDED
|
||||
APPLY_TEXT_CLIP_IF_NEEDED(command.rect)
|
||||
|
||||
auto const& radial_gradient_data = command.radial_gradient_data;
|
||||
|
||||
@ -1249,7 +1250,7 @@ void DisplayListPlayerSkia::paint_radial_gradient(PaintRadialGradient const& com
|
||||
|
||||
void DisplayListPlayerSkia::paint_conic_gradient(PaintConicGradient const& command)
|
||||
{
|
||||
APPLY_PATH_CLIP_IF_NEEDED
|
||||
APPLY_TEXT_CLIP_IF_NEEDED(command.rect)
|
||||
|
||||
auto const& conic_gradient_data = command.conic_gradient_data;
|
||||
|
||||
@ -1312,4 +1313,22 @@ bool DisplayListPlayerSkia::would_be_fully_clipped_by_painter(Gfx::IntRect rect)
|
||||
return surface().canvas().quickReject(to_skia_rect(rect));
|
||||
}
|
||||
|
||||
void DisplayListPlayerSkia::apply_mask_painted_from(DisplayList& display_list, Gfx::IntRect 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);
|
||||
m_surface = move(previous_surface);
|
||||
|
||||
SkMatrix mask_matrix;
|
||||
mask_matrix.setTranslate(rect.x(), rect.y());
|
||||
auto image = mask_surface->makeImageSnapshot();
|
||||
auto shader = image->makeShader(SkSamplingOptions(), mask_matrix);
|
||||
surface().canvas().save();
|
||||
surface().canvas().clipShader(shader);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -80,6 +80,8 @@ private:
|
||||
|
||||
bool would_be_fully_clipped_by_painter(Gfx::IntRect) const override;
|
||||
|
||||
void apply_mask_painted_from(DisplayList&, Gfx::IntRect);
|
||||
|
||||
class SkiaSurface;
|
||||
SkiaSurface& surface() const;
|
||||
|
||||
|
@ -42,14 +42,14 @@ void DisplayListRecorder::blit_corner_clipping(u32 id)
|
||||
append(BlitCornerClipping { id, state().translation.map(clip_state.rect) });
|
||||
}
|
||||
|
||||
void DisplayListRecorder::fill_rect(Gfx::IntRect const& rect, Color color, Vector<Gfx::Path> const& clip_paths)
|
||||
void DisplayListRecorder::fill_rect(Gfx::IntRect const& rect, Color color, RefPtr<DisplayList> text_clip)
|
||||
{
|
||||
if (rect.is_empty())
|
||||
return;
|
||||
append(FillRect {
|
||||
.rect = state().translation.map(rect),
|
||||
.color = color,
|
||||
.clip_paths = clip_paths,
|
||||
.text_clip = move(text_clip),
|
||||
});
|
||||
}
|
||||
|
||||
@ -140,17 +140,17 @@ 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, Vector<Gfx::Path> const& clip_paths)
|
||||
void DisplayListRecorder::fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data, RefPtr<DisplayList> text_clip)
|
||||
{
|
||||
if (gradient_rect.is_empty())
|
||||
return;
|
||||
append(PaintLinearGradient {
|
||||
.gradient_rect = state().translation.map(gradient_rect),
|
||||
.linear_gradient_data = data,
|
||||
.clip_paths = clip_paths });
|
||||
.text_clip = text_clip });
|
||||
}
|
||||
|
||||
void DisplayListRecorder::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position, Vector<Gfx::Path> const& clip_paths)
|
||||
void DisplayListRecorder::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position, RefPtr<DisplayList> text_clip)
|
||||
{
|
||||
if (rect.is_empty())
|
||||
return;
|
||||
@ -158,10 +158,10 @@ void DisplayListRecorder::fill_rect_with_conic_gradient(Gfx::IntRect const& rect
|
||||
.rect = state().translation.map(rect),
|
||||
.conic_gradient_data = data,
|
||||
.position = position,
|
||||
.clip_paths = clip_paths });
|
||||
.text_clip = text_clip });
|
||||
}
|
||||
|
||||
void DisplayListRecorder::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 DisplayListRecorder::fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size, RefPtr<DisplayList> text_clip)
|
||||
{
|
||||
if (rect.is_empty())
|
||||
return;
|
||||
@ -170,7 +170,7 @@ void DisplayListRecorder::fill_rect_with_radial_gradient(Gfx::IntRect const& rec
|
||||
.radial_gradient_data = data,
|
||||
.center = center,
|
||||
.size = size,
|
||||
.clip_paths = clip_paths });
|
||||
.text_clip = text_clip });
|
||||
}
|
||||
|
||||
void DisplayListRecorder::draw_rect(Gfx::IntRect const& rect, Color color, bool rough)
|
||||
@ -195,7 +195,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, Vector<Gfx::Path> const& clip_paths)
|
||||
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)
|
||||
{
|
||||
if (dst_rect.is_empty())
|
||||
return;
|
||||
@ -204,18 +204,19 @@ void DisplayListRecorder::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_r
|
||||
.bitmap = bitmap,
|
||||
.src_rect = src_rect,
|
||||
.scaling_mode = scaling_mode,
|
||||
.clip_paths = clip_paths,
|
||||
.text_clip = move(text_clip),
|
||||
});
|
||||
}
|
||||
|
||||
void DisplayListRecorder::draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, NonnullRefPtr<Gfx::ImmutableBitmap> bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat repeat, Vector<Gfx::Path> const& clip_paths)
|
||||
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)
|
||||
{
|
||||
append(DrawRepeatedImmutableBitmap {
|
||||
.dst_rect = dst_rect,
|
||||
.clip_rect = clip_rect,
|
||||
.bitmap = move(bitmap),
|
||||
.scaling_mode = scaling_mode,
|
||||
.repeat = repeat,
|
||||
.clip_paths = clip_paths,
|
||||
.text_clip = move(text_clip),
|
||||
});
|
||||
}
|
||||
|
||||
@ -363,7 +364,7 @@ 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, Vector<Gfx::Path> const& clip_paths)
|
||||
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> clip_paths)
|
||||
{
|
||||
if (rect.is_empty())
|
||||
return;
|
||||
@ -382,18 +383,18 @@ void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& rec
|
||||
.bottom_right = bottom_right_radius,
|
||||
.bottom_left = bottom_left_radius,
|
||||
},
|
||||
.clip_paths = clip_paths,
|
||||
.text_clip = clip_paths,
|
||||
});
|
||||
}
|
||||
|
||||
void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius, Vector<Gfx::Path> const& clip_paths)
|
||||
void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius, RefPtr<DisplayList> clip_paths)
|
||||
{
|
||||
if (a_rect.is_empty())
|
||||
return;
|
||||
fill_rect_with_rounded_corners(a_rect, color, radius, radius, radius, radius, clip_paths);
|
||||
fill_rect_with_rounded_corners(a_rect, color, radius, radius, radius, radius, move(clip_paths));
|
||||
}
|
||||
|
||||
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, Vector<Gfx::Path> const& clip_paths)
|
||||
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> clip_paths)
|
||||
{
|
||||
if (a_rect.is_empty())
|
||||
return;
|
||||
|
@ -40,7 +40,7 @@ class DisplayListRecorder {
|
||||
AK_MAKE_NONMOVABLE(DisplayListRecorder);
|
||||
|
||||
public:
|
||||
void fill_rect(Gfx::IntRect const& rect, Color color, Vector<Gfx::Path> const& clip_paths = {});
|
||||
void fill_rect(Gfx::IntRect const& rect, Color color, RefPtr<DisplayList> text_clip = {});
|
||||
|
||||
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, 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 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 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, Vector<Gfx::Path> const& clip_paths = {});
|
||||
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_repeated_immutable_bitmap(Gfx::IntRect dst_rect, NonnullRefPtr<Gfx::ImmutableBitmap> bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat, Vector<Gfx::Path> const& clip_paths = {});
|
||||
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_line(Gfx::IntPoint from, Gfx::IntPoint to, Color color, int thickness = 1, Gfx::LineStyle style = Gfx::LineStyle::Solid, Color alternate_color = Color::Transparent);
|
||||
|
||||
@ -131,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, 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 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 draw_triangle_wave(Gfx::IntPoint a_p1, Gfx::IntPoint a_p2, Color color, int amplitude, int thickness);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user