LibGfx: Move Gfx::Painter::ScalingMode => Gfx::ScalingMode

This will allow users to avoid including Painter.h
This commit is contained in:
Andreas Kling 2024-06-05 10:10:38 +02:00 committed by Andreas Kling
parent 5e059c80cd
commit 254d040ff4
Notes: sideshowbarker 2024-07-17 05:23:40 +09:00
14 changed files with 67 additions and 51 deletions

View file

@ -37,11 +37,11 @@ TEST_CASE(test_painter_scaling_uses_premultiplied_alpha)
EXPECT_EQ(bottom_right_pixel, Color::Transparent);
};
test_scaling_mode(Gfx::Painter::ScalingMode::BilinearBlend);
test_scaling_mode(Gfx::ScalingMode::BilinearBlend);
// FIXME: Include ScalingMode::SmoothPixels as part of this test
// This mode does not currently pass this test, as it behave according to the spec
// defined here: https://drafts.csswg.org/css-images/#valdef-image-rendering-pixelated
// test_scaling_mode(Gfx::Painter::ScalingMode::SmoothPixels);
// test_scaling_mode(Gfx::ScalingMode::SmoothPixels);
}
TEST_CASE(test_bitmap_scaling_uses_premultiplied_alpha)

View file

@ -642,13 +642,13 @@ void Painter::blit_canvas(Gfx::IntRect const& dst_rect, Canvas const& canvas, fl
void Painter::blit_canvas(Gfx::FloatRect const& dst_rect, Canvas const& canvas, float opacity, Optional<Gfx::AffineTransform> affine_transform)
{
auto texture = GL::Texture(canvas.framebuffer().texture);
blit_scaled_texture(dst_rect, texture, { { 0, 0 }, canvas.size() }, Painter::ScalingMode::NearestNeighbor, opacity, move(affine_transform));
blit_scaled_texture(dst_rect, texture, { { 0, 0 }, canvas.size() }, ScalingMode::NearestNeighbor, opacity, move(affine_transform));
}
void Painter::blit_canvas(Gfx::FloatRect const& dst_rect, Canvas const& canvas, Gfx::FloatRect const& src_rect, float opacity, Optional<Gfx::AffineTransform> affine_transform, BlendingMode blending_mode)
{
auto texture = GL::Texture(canvas.framebuffer().texture);
blit_scaled_texture(dst_rect, texture, src_rect, Painter::ScalingMode::NearestNeighbor, opacity, move(affine_transform), blending_mode);
blit_scaled_texture(dst_rect, texture, src_rect, ScalingMode::NearestNeighbor, opacity, move(affine_transform), blending_mode);
}
void Painter::blit_scaled_texture(Gfx::FloatRect const& dst_rect, GL::Texture const& texture, Gfx::FloatRect const& src_rect, ScalingMode scaling_mode, float opacity, Optional<Gfx::AffineTransform> affine_transform, BlendingMode blending_mode)

View file

@ -675,7 +675,7 @@ ALWAYS_INLINE static void do_draw_box_sampled_scaled_bitmap(Gfx::Bitmap& target,
}
}
template<bool has_alpha_channel, Painter::ScalingMode scaling_mode, typename GetPixel>
template<bool has_alpha_channel, ScalingMode scaling_mode, typename GetPixel>
ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect const& dst_rect, IntRect const& clipped_rect, Gfx::Bitmap const& source, FloatRect const& src_rect, GetPixel get_pixel, float opacity)
{
auto int_src_rect = enclosing_int_rect(src_rect);
@ -683,7 +683,7 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con
if (clipped_src_rect.is_empty())
return;
if constexpr (scaling_mode == Painter::ScalingMode::NearestNeighbor || scaling_mode == Painter::ScalingMode::SmoothPixels) {
if constexpr (scaling_mode == ScalingMode::NearestNeighbor || scaling_mode == ScalingMode::SmoothPixels) {
if (dst_rect == clipped_rect && int_src_rect == src_rect && !(dst_rect.width() % int_src_rect.width()) && !(dst_rect.height() % int_src_rect.height())) {
int hfactor = dst_rect.width() / int_src_rect.width();
int vfactor = dst_rect.height() / int_src_rect.height();
@ -697,7 +697,7 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con
}
}
if constexpr (scaling_mode == Painter::ScalingMode::BoxSampling)
if constexpr (scaling_mode == ScalingMode::BoxSampling)
return do_draw_box_sampled_scaled_bitmap<has_alpha_channel>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
bool has_opacity = opacity != 1.f;
@ -718,7 +718,7 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con
auto desired_x = (x - dst_rect.x()) * hscale + src_left;
Color src_pixel;
if constexpr (scaling_mode == Painter::ScalingMode::BilinearBlend) {
if constexpr (scaling_mode == ScalingMode::BilinearBlend) {
auto shifted_x = desired_x + bilinear_offset_x;
auto shifted_y = desired_y + bilinear_offset_y;
@ -739,7 +739,7 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con
auto bottom = bottom_left.mixed_with(bottom_right, x_ratio);
src_pixel = top.mixed_with(bottom, y_ratio);
} else if constexpr (scaling_mode == Painter::ScalingMode::SmoothPixels) {
} else if constexpr (scaling_mode == ScalingMode::SmoothPixels) {
auto scaled_x1 = clamp(desired_x >> 32, clipped_src_rect.left(), clipped_src_rect.right() - 1);
auto scaled_x0 = clamp(scaled_x1 - 1, clipped_src_rect.left(), clipped_src_rect.right() - 1);
auto scaled_y1 = clamp(desired_y >> 32, clipped_src_rect.top(), clipped_src_rect.bottom() - 1);
@ -778,23 +778,23 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con
}
template<bool has_alpha_channel, typename GetPixel>
ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect const& dst_rect, IntRect const& clipped_rect, Gfx::Bitmap const& source, FloatRect const& src_rect, GetPixel get_pixel, float opacity, Painter::ScalingMode scaling_mode)
ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect const& dst_rect, IntRect const& clipped_rect, Gfx::Bitmap const& source, FloatRect const& src_rect, GetPixel get_pixel, float opacity, ScalingMode scaling_mode)
{
switch (scaling_mode) {
case Painter::ScalingMode::NearestNeighbor:
do_draw_scaled_bitmap<has_alpha_channel, Painter::ScalingMode::NearestNeighbor>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
case ScalingMode::NearestNeighbor:
do_draw_scaled_bitmap<has_alpha_channel, ScalingMode::NearestNeighbor>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
break;
case Painter::ScalingMode::SmoothPixels:
do_draw_scaled_bitmap<has_alpha_channel, Painter::ScalingMode::SmoothPixels>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
case ScalingMode::SmoothPixels:
do_draw_scaled_bitmap<has_alpha_channel, ScalingMode::SmoothPixels>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
break;
case Painter::ScalingMode::BilinearBlend:
do_draw_scaled_bitmap<has_alpha_channel, Painter::ScalingMode::BilinearBlend>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
case ScalingMode::BilinearBlend:
do_draw_scaled_bitmap<has_alpha_channel, ScalingMode::BilinearBlend>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
break;
case Painter::ScalingMode::BoxSampling:
do_draw_scaled_bitmap<has_alpha_channel, Painter::ScalingMode::BoxSampling>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
case ScalingMode::BoxSampling:
do_draw_scaled_bitmap<has_alpha_channel, ScalingMode::BoxSampling>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
break;
case Painter::ScalingMode::None:
do_draw_scaled_bitmap<has_alpha_channel, Painter::ScalingMode::None>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
case ScalingMode::None:
do_draw_scaled_bitmap<has_alpha_channel, ScalingMode::None>(target, dst_rect, clipped_rect, source, src_rect, get_pixel, opacity);
break;
}
}
@ -1600,7 +1600,7 @@ void Painter::stroke_path(Path const& path, Color color, int thickness)
fill_path(path.stroke_to_fill(thickness), color);
}
void Painter::draw_scaled_bitmap_with_transform(IntRect const& dst_rect, Bitmap const& bitmap, FloatRect const& src_rect, AffineTransform const& transform, float opacity, Painter::ScalingMode scaling_mode)
void Painter::draw_scaled_bitmap_with_transform(IntRect const& dst_rect, Bitmap const& bitmap, FloatRect const& src_rect, AffineTransform const& transform, float opacity, ScalingMode scaling_mode)
{
if (transform.is_identity_or_translation_or_scale()) {
draw_scaled_bitmap(transform.map(dst_rect.to_type<float>()).to_rounded<int>(), bitmap, src_rect, opacity, scaling_mode);

View file

@ -19,6 +19,7 @@
#include <LibGfx/PaintStyle.h>
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibGfx/ScalingMode.h>
#include <LibGfx/Size.h>
#include <LibGfx/TextAlignment.h>
#include <LibGfx/TextDirection.h>
@ -53,14 +54,6 @@ public:
Dashed,
};
enum class ScalingMode {
NearestNeighbor,
SmoothPixels,
BilinearBlend,
BoxSampling,
None,
};
void clear_rect(IntRect const&, Color);
void fill_rect(IntRect const&, Color);
void fill_rect(IntRect const&, PaintStyle const&);

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2024, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
namespace Gfx {
enum class ScalingMode {
NearestNeighbor,
SmoothPixels,
BilinearBlend,
BoxSampling,
None,
};
}

View file

@ -8,7 +8,7 @@
#include <AK/Optional.h>
#include <LibGfx/FontCascadeList.h>
#include <LibGfx/Painter.h>
#include <LibGfx/ScalingMode.h>
#include <LibWeb/CSS/BackdropFilter.h>
#include <LibWeb/CSS/CalculatedOr.h>
#include <LibWeb/CSS/Clip.h>
@ -319,19 +319,19 @@ struct BorderRadiusData {
};
// FIXME: Find a better place for this helper.
inline Gfx::Painter::ScalingMode to_gfx_scaling_mode(CSS::ImageRendering css_value, Gfx::IntRect source, Gfx::IntRect target)
inline Gfx::ScalingMode to_gfx_scaling_mode(CSS::ImageRendering css_value, Gfx::IntRect source, Gfx::IntRect target)
{
switch (css_value) {
case CSS::ImageRendering::Auto:
case CSS::ImageRendering::HighQuality:
case CSS::ImageRendering::Smooth:
if (target.width() < source.width() || target.height() < source.height())
return Gfx::Painter::ScalingMode::BoxSampling;
return Gfx::Painter::ScalingMode::BilinearBlend;
return Gfx::ScalingMode::BoxSampling;
return Gfx::ScalingMode::BilinearBlend;
case CSS::ImageRendering::CrispEdges:
return Gfx::Painter::ScalingMode::NearestNeighbor;
return Gfx::ScalingMode::NearestNeighbor;
case CSS::ImageRendering::Pixelated:
return Gfx::Painter::ScalingMode::SmoothPixels;
return Gfx::ScalingMode::SmoothPixels;
}
VERIFY_NOT_REACHED();
}

View file

@ -10,6 +10,7 @@
#include <AK/HashMap.h>
#include <AK/Optional.h>
#include <AK/OwnPtr.h>
#include <LibGfx/Font/VectorFont.h>
#include <LibWeb/Animations/KeyframeEffect.h>
#include <LibWeb/CSS/CSSFontFaceRule.h>
#include <LibWeb/CSS/CSSKeyframesRule.h>

View file

@ -155,10 +155,10 @@ WebIDL::ExceptionOr<void> CanvasRenderingContext2D::draw_image_internal(CanvasIm
// 6. Paint the region of the image argument specified by the source rectangle on the region of the rendering context's output bitmap specified by the destination rectangle, after applying the current transformation matrix to the destination rectangle.
draw_clipped([&](auto& painter) {
auto scaling_mode = Gfx::Painter::ScalingMode::NearestNeighbor;
auto scaling_mode = Gfx::ScalingMode::NearestNeighbor;
if (drawing_state().image_smoothing_enabled) {
// FIXME: Honor drawing_state().image_smoothing_quality
scaling_mode = Gfx::Painter::ScalingMode::BilinearBlend;
scaling_mode = Gfx::ScalingMode::BilinearBlend;
}
painter.underlying_painter().draw_scaled_bitmap_with_transform(destination_rect.to_rounded<int>(), *bitmap, source_rect, drawing_state().transform, drawing_state().global_alpha, scaling_mode);

View file

@ -22,6 +22,7 @@
#include <LibGfx/Palette.h>
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibGfx/ScalingMode.h>
#include <LibGfx/Size.h>
#include <LibGfx/TextAlignment.h>
#include <LibGfx/TextDirection.h>
@ -74,7 +75,7 @@ struct DrawScaledBitmap {
Gfx::IntRect dst_rect;
NonnullRefPtr<Gfx::Bitmap> bitmap;
Gfx::IntRect src_rect;
Gfx::Painter::ScalingMode scaling_mode;
Gfx::ScalingMode scaling_mode;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return dst_rect; }
void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); }
@ -84,7 +85,7 @@ struct DrawScaledImmutableBitmap {
Gfx::IntRect dst_rect;
NonnullRefPtr<Gfx::ImmutableBitmap> bitmap;
Gfx::IntRect src_rect;
Gfx::Painter::ScalingMode scaling_mode;
Gfx::ScalingMode scaling_mode;
Vector<Gfx::Path> clip_paths;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return dst_rect; }

View file

@ -153,7 +153,7 @@ CommandResult CommandExecutorCPU::push_stacking_context(PushStackingContext cons
.painter = AK::make<Gfx::Painter>(bitmap),
.opacity = 1,
.destination = command.source_paintable_rect.translated(command.post_transform_translation),
.scaling_mode = Gfx::Painter::ScalingMode::None,
.scaling_mode = Gfx::ScalingMode::None,
.mask = command.mask });
painter().translate(-command.source_paintable_rect.location());
return CommandResult::Continue;

View file

@ -7,6 +7,7 @@
#pragma once
#include <AK/MaybeOwned.h>
#include <LibGfx/ScalingMode.h>
#include <LibWeb/Painting/AffineCommandExecutorCPU.h>
#include <LibWeb/Painting/RecordingPainter.h>
@ -71,7 +72,7 @@ private:
MaybeOwned<Gfx::Painter> painter;
float opacity;
Gfx::IntRect destination;
Gfx::Painter::ScalingMode scaling_mode;
Gfx::ScalingMode scaling_mode;
Optional<StackingContextMask> mask = {};
};

View file

@ -61,15 +61,15 @@ CommandResult CommandExecutorGPU::fill_rect(FillRect const& command)
return CommandResult::Continue;
}
static AccelGfx::Painter::ScalingMode to_accelgfx_scaling_mode(Gfx::Painter::ScalingMode scaling_mode)
static AccelGfx::Painter::ScalingMode to_accelgfx_scaling_mode(Gfx::ScalingMode scaling_mode)
{
switch (scaling_mode) {
case Gfx::Painter::ScalingMode::NearestNeighbor:
case Gfx::Painter::ScalingMode::BoxSampling:
case Gfx::Painter::ScalingMode::SmoothPixels:
case Gfx::Painter::ScalingMode::None:
case Gfx::ScalingMode::NearestNeighbor:
case Gfx::ScalingMode::BoxSampling:
case Gfx::ScalingMode::SmoothPixels:
case Gfx::ScalingMode::None:
return AccelGfx::Painter::ScalingMode::NearestNeighbor;
case Gfx::Painter::ScalingMode::BilinearBlend:
case Gfx::ScalingMode::BilinearBlend:
return AccelGfx::Painter::ScalingMode::Bilinear;
default:
VERIFY_NOT_REACHED();

View file

@ -185,7 +185,7 @@ void RecordingPainter::draw_rect(Gfx::IntRect const& rect, Color color, bool rou
.rough = rough });
}
void RecordingPainter::draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode)
void RecordingPainter::draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode)
{
if (dst_rect.is_empty())
return;
@ -197,7 +197,7 @@ 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, Vector<Gfx::Path> const& clip_paths)
void RecordingPainter::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)
{
if (dst_rect.is_empty())
return;

View file

@ -22,6 +22,7 @@
#include <LibGfx/Palette.h>
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibGfx/ScalingMode.h>
#include <LibGfx/Size.h>
#include <LibGfx/TextAlignment.h>
#include <LibGfx/TextDirection.h>
@ -89,8 +90,8 @@ public:
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, Vector<Gfx::Path> const& clip_paths = {});
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_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);