1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 09:27:35 +00:00

Painter: Simplify the draw_scaled_bitmap() fast path for integer scale.

Iterate over the source image instead of the destination image, and blow it
up pixel by pixel. This code will only run for upscaling so we don't need
to worry about anything else.
This commit is contained in:
Andreas Kling 2019-05-11 16:53:53 +02:00
parent 1652cb7db9
commit 788fb7699b

View file

@ -349,21 +349,20 @@ void Painter::blit(const Point& position, const GraphicsBitmap& source, const Re
} }
template<bool has_alpha_channel, typename GetPixel> template<bool has_alpha_channel, typename GetPixel>
ALWAYS_INLINE static void do_draw_integer_scaled_bitmap(GraphicsBitmap& target, const Rect& dst_rect, const Rect& clipped_rect, const GraphicsBitmap& source, int hscale, int vscale, int hfactor, int vfactor, GetPixel get_pixel) ALWAYS_INLINE static void do_draw_integer_scaled_bitmap(GraphicsBitmap& target, const Rect& dst_rect, const GraphicsBitmap& source, int hfactor, int vfactor, GetPixel get_pixel)
{ {
for (int y = clipped_rect.top(); y <= clipped_rect.bottom(); y += vfactor) { for (int y = source.rect().top(); y <= source.rect().bottom(); ++y) {
for (int x = clipped_rect.left(); x <= clipped_rect.right(); x += hfactor) { int dst_y = dst_rect.y() + y * vfactor;
auto scaled_x = ((x - dst_rect.x()) * hscale) >> 16; for (int x = source.rect().left(); x <= source.rect().right(); ++x) {
auto scaled_y = ((y - dst_rect.y()) * vscale) >> 16; auto src_pixel = get_pixel(source, x, y);
auto src_pixel = get_pixel(source, scaled_x, scaled_y);
for (int yo = 0; yo < vfactor; ++yo) { for (int yo = 0; yo < vfactor; ++yo) {
auto* scanline = (Color*)target.scanline(y + yo); auto* scanline = (Color*)target.scanline(dst_y + yo);
int dst_x = dst_rect.x() + x * hfactor;
for (int xo = 0; xo < hfactor; ++xo) { for (int xo = 0; xo < hfactor; ++xo) {
if constexpr (has_alpha_channel) if constexpr (has_alpha_channel)
scanline[x + xo] = scanline[x].blend(src_pixel); scanline[dst_x + xo] = scanline[dst_x + xo].blend(src_pixel);
else else
scanline[x + xo] = src_pixel; scanline[dst_x + xo] = src_pixel;
} }
} }
} }
@ -377,12 +376,12 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(GraphicsBitmap& target, const Re
int hfactor = dst_rect.width() / src_rect.width(); int hfactor = dst_rect.width() / src_rect.width();
int vfactor = dst_rect.height() / src_rect.height(); int vfactor = dst_rect.height() / src_rect.height();
if (hfactor == 2 && vfactor == 2) if (hfactor == 2 && vfactor == 2)
return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, clipped_rect, source, hscale, vscale, 2, 2, get_pixel); return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, source, 2, 2, get_pixel);
if (hfactor == 3 && vfactor == 3) if (hfactor == 3 && vfactor == 3)
return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, clipped_rect, source, hscale, vscale, 3, 3, get_pixel); return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, source, 3, 3, get_pixel);
if (hfactor == 4 && vfactor == 4) if (hfactor == 4 && vfactor == 4)
return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, clipped_rect, source, hscale, vscale, 4, 4, get_pixel); return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, source, 4, 4, get_pixel);
return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, clipped_rect, source, hscale, vscale, hfactor, vfactor, get_pixel); return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, source, hfactor, vfactor, get_pixel);
} }
for (int y = clipped_rect.top(); y <= clipped_rect.bottom(); ++y) { for (int y = clipped_rect.top(); y <= clipped_rect.bottom(); ++y) {