mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:57:35 +00:00
LibWeb: Fix destination bitmap edge clip case in transform painting
This fixes an edge case, where the destination rect falls partly outside the painter, so is clipped to a smaller size in `get_region_bitmap()` (which needs to be accounted for with an extra offset).
This commit is contained in:
parent
bbaa05fcf9
commit
f6264523b9
1 changed files with 13 additions and 8 deletions
|
@ -303,12 +303,18 @@ void StackingContext::paint(PaintContext& context) const
|
||||||
// to the size of the source (which could add some artefacts, though just scaling the bitmap already does that).
|
// to the size of the source (which could add some artefacts, though just scaling the bitmap already does that).
|
||||||
// We need to copy the background at the destination because a bunch of our rendering effects now rely on
|
// We need to copy the background at the destination because a bunch of our rendering effects now rely on
|
||||||
// being able to sample the painter (see border radii, shadows, filters, etc).
|
// being able to sample the painter (see border radii, shadows, filters, etc).
|
||||||
|
Gfx::FloatPoint destination_clipped_fixup {};
|
||||||
auto try_get_scaled_destination_bitmap = [&]() -> ErrorOr<NonnullRefPtr<Gfx::Bitmap>> {
|
auto try_get_scaled_destination_bitmap = [&]() -> ErrorOr<NonnullRefPtr<Gfx::Bitmap>> {
|
||||||
auto bitmap = TRY(context.painter().get_region_bitmap(destination_rect, Gfx::BitmapFormat::BGRA8888, destination_rect));
|
Gfx::IntRect actual_destination_rect;
|
||||||
|
auto bitmap = TRY(context.painter().get_region_bitmap(destination_rect, Gfx::BitmapFormat::BGRA8888, actual_destination_rect));
|
||||||
|
// get_region_bitmap() may clip to a smaller region if the requested rect goes outside the painter, so we need to account for that.
|
||||||
|
destination_clipped_fixup = Gfx::FloatPoint { destination_rect.location() - actual_destination_rect.location() };
|
||||||
|
destination_rect = actual_destination_rect;
|
||||||
if (source_rect.size() != transformed_destination_rect.size()) {
|
if (source_rect.size() != transformed_destination_rect.size()) {
|
||||||
bitmap = TRY(bitmap->scaled(
|
auto sx = static_cast<float>(source_rect.width()) / transformed_destination_rect.width();
|
||||||
static_cast<float>(source_rect.width()) / transformed_destination_rect.width(),
|
auto sy = static_cast<float>(source_rect.height()) / transformed_destination_rect.height();
|
||||||
static_cast<float>(source_rect.height()) / transformed_destination_rect.height()));
|
bitmap = TRY(bitmap->scaled(sx, sy));
|
||||||
|
destination_clipped_fixup.scale_by(sx, sy);
|
||||||
}
|
}
|
||||||
return bitmap;
|
return bitmap;
|
||||||
};
|
};
|
||||||
|
@ -318,13 +324,12 @@ void StackingContext::paint(PaintContext& context) const
|
||||||
return;
|
return;
|
||||||
auto bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors();
|
auto bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors();
|
||||||
Gfx::Painter painter(bitmap);
|
Gfx::Painter painter(bitmap);
|
||||||
painter.translate(-paintable().absolute_paint_rect().location().to_rounded<int>());
|
painter.translate((-paintable().absolute_paint_rect().location() + destination_clipped_fixup).to_rounded<int>());
|
||||||
auto paint_context = context.clone(painter);
|
auto paint_context = context.clone(painter);
|
||||||
paint_internal(paint_context);
|
paint_internal(paint_context);
|
||||||
|
|
||||||
// NOTE: If the destination and source rects are the same size, we round the source rect to ensure that it's pixel-aligned.
|
if (destination_rect.size() == bitmap->size())
|
||||||
if (transformed_destination_rect.size() == source_rect.size())
|
context.painter().blit(destination_rect.location(), *bitmap, bitmap->rect(), opacity);
|
||||||
context.painter().draw_scaled_bitmap(destination_rect, *bitmap, bitmap->rect(), opacity);
|
|
||||||
else
|
else
|
||||||
context.painter().draw_scaled_bitmap(destination_rect, *bitmap, bitmap->rect(), opacity, Gfx::Painter::ScalingMode::BilinearBlend);
|
context.painter().draw_scaled_bitmap(destination_rect, *bitmap, bitmap->rect(), opacity, Gfx::Painter::ScalingMode::BilinearBlend);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue