mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 21:27:34 +00:00
LibGfx: Add Painter::fill_pixels()
This function fills a region of pixels with the result of a callback function. This is an alternative to a for loop that repeatedly calls Painter::set_pixel(), which can get very expensive due to the clipping checks set_pixel() does each call.
This commit is contained in:
parent
7e701f6256
commit
ca01017f32
2 changed files with 30 additions and 1 deletions
|
@ -1842,7 +1842,14 @@ void Painter::set_pixel(IntPoint p, Color color, bool blend)
|
||||||
// scaling and call set_pixel() -- do not scale the pixel.
|
// scaling and call set_pixel() -- do not scale the pixel.
|
||||||
if (!clip_rect().contains(point / scale()))
|
if (!clip_rect().contains(point / scale()))
|
||||||
return;
|
return;
|
||||||
auto& dst = m_target->scanline(point.y())[point.x()];
|
set_physical_pixel(point, color, blend);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Painter::set_physical_pixel(IntPoint physical_point, Color color, bool blend)
|
||||||
|
{
|
||||||
|
// This function should only be called after translation, clipping, etc has been handled elsewhere
|
||||||
|
// if not use set_pixel().
|
||||||
|
auto& dst = m_target->scanline(physical_point.y())[physical_point.x()];
|
||||||
if (!blend || color.alpha() == 255)
|
if (!blend || color.alpha() == 255)
|
||||||
dst = color.value();
|
dst = color.value();
|
||||||
else if (color.alpha())
|
else if (color.alpha())
|
||||||
|
|
|
@ -162,6 +162,27 @@ public:
|
||||||
|
|
||||||
int scale() const { return state().scale; }
|
int scale() const { return state().scale; }
|
||||||
|
|
||||||
|
template<typename TGetPixelCallback>
|
||||||
|
void fill_pixels(Gfx::IntRect const& region, TGetPixelCallback callback, bool blend = false)
|
||||||
|
{
|
||||||
|
// Note: This function paints physical pixels and therefore does not make sense when
|
||||||
|
// called on a scaled painter. Scaling the region painted may break the caller (this
|
||||||
|
// would be the case for gradients in LibWeb), and if you scale the pixels (to squares)
|
||||||
|
// then this is no longer filling pixels.
|
||||||
|
VERIFY(scale() == 1);
|
||||||
|
auto paint_region = region.translated(translation());
|
||||||
|
auto clipped_region = paint_region.intersected(clip_rect());
|
||||||
|
if (clipped_region.is_empty())
|
||||||
|
return;
|
||||||
|
auto start_offset = clipped_region.location() - paint_region.location();
|
||||||
|
for (int y = 0; y < clipped_region.height(); y++) {
|
||||||
|
for (int x = 0; x < clipped_region.width(); x++) {
|
||||||
|
auto pixel = callback(IntPoint(x, y).translated(start_offset));
|
||||||
|
set_physical_pixel(clipped_region.location().translated(x, y), pixel, blend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
IntRect to_physical(IntRect const& r) const { return r.translated(translation()) * scale(); }
|
IntRect to_physical(IntRect const& r) const { return r.translated(translation()) * scale(); }
|
||||||
IntPoint to_physical(IntPoint p) const { return p.translated(translation()) * scale(); }
|
IntPoint to_physical(IntPoint p) const { return p.translated(translation()) * scale(); }
|
||||||
|
@ -170,6 +191,7 @@ protected:
|
||||||
void fill_rect_with_draw_op(IntRect const&, Color);
|
void fill_rect_with_draw_op(IntRect const&, Color);
|
||||||
void blit_with_opacity(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, float opacity, bool apply_alpha = true);
|
void blit_with_opacity(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, float opacity, bool apply_alpha = true);
|
||||||
void draw_physical_pixel(IntPoint, Color, int thickness = 1);
|
void draw_physical_pixel(IntPoint, Color, int thickness = 1);
|
||||||
|
void set_physical_pixel(IntPoint, Color color, bool blend);
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
Font const* font;
|
Font const* font;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue