Skip to content

Commit

Permalink
Bitmap: Do not require a mask for GetOperator. BitmapBlit checks now …
Browse files Browse the repository at this point in the history
…for support of the operation.
  • Loading branch information
Ghabry committed Aug 30, 2024
1 parent 9e5b31e commit 59f184f
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 50 deletions.
38 changes: 18 additions & 20 deletions src/bitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <iostream>
#include <pixman.h>

#include "opacity.h"
#include "pixel_format.h"
#include "utils.h"
#include "cache.h"
Expand Down Expand Up @@ -546,6 +547,10 @@ void Bitmap::Init(int width, int height, void* data, int pitch, bool destroy) {

if (data != NULL && destroy)
pixman_image_set_destroy_function(bitmap.get(), destroy_func, data);

if (!GetTransparent()) {
image_opacity = ImageOpacity::Opaque;
}
}

void Bitmap::ConvertImage(int& width, int& height, void*& pixels, bool transparent) {
Expand Down Expand Up @@ -625,17 +630,13 @@ namespace {
} // anonymous namespace

void Bitmap::Blit(int x, int y, Bitmap const& src, Rect const& src_rect, Opacity const& opacity, Bitmap::BlendMode blend_mode) {
if (opacity.IsTransparent()) {
auto pixman_op = src.GetOperator(opacity, blend_mode);

if (BitmapBlit::Blit(*this, x, y, src, src_rect, opacity, pixman_op)) {
return;
}

auto mask = CreateMask(opacity, src_rect);
auto pixman_op = src.GetOperator(mask.get(), blend_mode);

if (!mask && src.pixman_format == pixman_format) {
BitmapBlit::Blit(*this, x, y, src, src_rect, opacity, pixman_op);
return;
}

pixman_image_composite32(pixman_op,
src.bitmap.get(),
Expand All @@ -647,12 +648,7 @@ void Bitmap::Blit(int x, int y, Bitmap const& src, Rect const& src_rect, Opacity
}

void Bitmap::BlitFast(int x, int y, Bitmap const & src, Rect const & src_rect, Opacity const & opacity) {
if (opacity.IsTransparent()) {
return;
}

if (src.pixman_format == pixman_format) {
BitmapBlit::BlitFast(*this, x, y, src, src_rect, opacity);
if (BitmapBlit::BlitFast(*this, x, y, src, src_rect, opacity)) {
return;
}

Expand Down Expand Up @@ -691,7 +687,7 @@ void Bitmap::TiledBlit(int ox, int oy, Rect const& src_rect, Bitmap const& src,

auto mask = CreateMask(opacity, src_rect);

pixman_image_composite32(src.GetOperator(mask.get(), blend_mode),
pixman_image_composite32(src.GetOperator(opacity, blend_mode),
src_bm.get(), mask.get(), bitmap.get(),
ox, oy,
0, 0,
Expand All @@ -717,7 +713,7 @@ void Bitmap::StretchBlit(Rect const& dst_rect, Bitmap const& src, Rect const& sr

auto mask = CreateMask(opacity, src_rect, &xform);

pixman_image_composite32(src.GetOperator(mask.get(), blend_mode),
pixman_image_composite32(src.GetOperator(opacity, blend_mode),
src.bitmap.get(), mask.get(), bitmap.get(),
src_rect.x / zoom_x, src_rect.y / zoom_y,
0, 0,
Expand Down Expand Up @@ -752,7 +748,7 @@ void Bitmap::WaverBlit(int x, int y, double zoom_x, double zoom_y, Bitmap const&
const double sy = (i - yclip) * (2 * M_PI) / (32.0 * zoom_y);
const int offset = 2 * zoom_x * depth * std::sin(phase + sy);

pixman_image_composite32(src.GetOperator(mask.get(), blend_mode),
pixman_image_composite32(src.GetOperator(opacity, blend_mode),
src.bitmap.get(), mask.get(), bitmap.get(),
xoff, yoff + i,
0, i,
Expand Down Expand Up @@ -1234,7 +1230,7 @@ void Bitmap::RotateZoomOpacityBlit(int x, int y, int ox, int oy,

// OP_SRC draws a black rectangle around the rotated image making this operator unusable here
blend_mode = (blend_mode == BlendMode::Default ? BlendMode::Normal : blend_mode);
pixman_image_composite32(GetOperator(mask.get(), blend_mode),
pixman_image_composite32(GetOperator(opacity, blend_mode),
src_img, mask.get(), bitmap.get(),
dst_rect.x, dst_rect.y,
dst_rect.x, dst_rect.y,
Expand All @@ -1261,7 +1257,7 @@ void Bitmap::ZoomOpacityBlit(int x, int y, int ox, int oy,
StretchBlit(dst_rect, src, src_rect, opacity, blend_mode);
}

pixman_op_t Bitmap::GetOperator(pixman_image_t* mask, Bitmap::BlendMode blend_mode) const {
pixman_op_t Bitmap::GetOperator(Opacity const& opacity, Bitmap::BlendMode blend_mode) const {
if (blend_mode != BlendMode::Default) {
switch (blend_mode) {
case BlendMode::Normal:
Expand Down Expand Up @@ -1299,7 +1295,9 @@ pixman_op_t Bitmap::GetOperator(pixman_image_t* mask, Bitmap::BlendMode blend_mo
}
}

if (!mask && (!GetTransparent() || GetImageOpacity() == ImageOpacity::Opaque)) {
bool has_mask = !opacity.IsOpaque() && !opacity.IsTransparent();

if (!has_mask && GetImageOpacity() == ImageOpacity::Opaque) {
return PIXMAN_OP_SRC;
}

Expand All @@ -1315,7 +1313,7 @@ void Bitmap::EdgeMirrorBlit(int x, int y, Bitmap const& src, Rect const& src_rec
const auto dst_rect = GetRect();

auto draw = [&](int x, int y) {
pixman_image_composite32(src.GetOperator(mask.get()),
pixman_image_composite32(src.GetOperator(opacity),
src.bitmap.get(),
mask.get(), bitmap.get(),
src_rect.x, src_rect.y,
Expand Down
2 changes: 1 addition & 1 deletion src/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ class Bitmap {
* @param blend_mode When >= 0: Force this blend mode as operator
* @return blend mode
*/
pixman_op_t GetOperator(pixman_image_t* mask = nullptr, BlendMode blend_mode = BlendMode::Default) const;
pixman_op_t GetOperator(Opacity const& opacity = Opacity::Opaque(), BlendMode blend_mode = BlendMode::Default) const;
bool read_only = false;
};

Expand Down
52 changes: 29 additions & 23 deletions src/bitmap_blit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@
namespace {

bool adjust_rects(Bitmap const& dest, Rect& dst_rect, Bitmap const& src, Rect& src_rect, Opacity const& opacity) {
if (opacity.IsTransparent()) {
return false;
}

if (!Rect::AdjustRectangles(src_rect, dst_rect, src.GetRect()))
return false;

Expand All @@ -34,30 +30,34 @@ bool adjust_rects(Bitmap const& dest, Rect& dst_rect, Bitmap const& src, Rect& s
return true;
}

void BlitFastT() {

}

}

namespace BitmapBlit {

void Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
bool Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
Opacity const& opacity, pixman_op_t blend_mode) {

if (blend_mode == PIXMAN_OP_SRC) {
BlitFast(dest, x, y, src, src_rect, opacity);
return;
return BlitFast(dest, x, y, src, src_rect, opacity);
}

if (blend_mode != PIXMAN_OP_OVER) {
return;
if (opacity.IsTransparent()) {
return true;
}

if (dest.format != src.format) {
return false;
}

if (blend_mode != PIXMAN_OP_OVER || src.bpp() != 2) {
// Not supported
return false;
}

Rect dst_rect = {x, y, 0, 0};

if (!adjust_rects(dest, dst_rect, src, src_rect, opacity)) {
return;
return true;
}

int bpp = src.bpp();
Expand Down Expand Up @@ -112,16 +112,10 @@ void Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
x - bpp - run_beg);
}
}

/*if (run_alpha != 0 && x - bpp >= run_beg) {
memcpy(
dst_pixels + y * dst_pitch,
src_pixels + y * src_pitch,
to_copy);
}*/
}

/*
// Naive implementation
for (int y = 0; y < src_rect.height; ++y) {
for (int x = 0; x < src_rect.width * bpp; x += bpp) {
src_pixel = *(uint16_t*)(src_pixels + y * src_pitch + x);
Expand All @@ -132,15 +126,25 @@ void Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
}
}
*/

return true;
}

void BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
bool BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
Opacity const& opacity) {

if (opacity.IsTransparent()) {
return true;
}

if (dest.format != src.format) {
return false;
}

Rect dst_rect = {x, y, 0, 0};

if (!adjust_rects(dest, dst_rect, src, src_rect, opacity)) {
return;
return true;
}

int bpp = src.bpp();
Expand All @@ -158,6 +162,8 @@ void BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
src_pixels + y * src_pitch,
to_copy);
}

return true;
}

} // namespace BitmapBlit
4 changes: 2 additions & 2 deletions src/bitmap_blit.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
#include <pixman.h>

namespace BitmapBlit {
void Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
bool Blit(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
Opacity const& opacity, pixman_op_t blend_mode);

void BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
bool BlitFast(Bitmap& dest, int x, int y, Bitmap const& src, Rect src_rect,
Opacity const& opacity);
}

Expand Down
8 changes: 4 additions & 4 deletions src/pixel_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ struct Component {
byte = shift / 8;
}

constexpr bool operator==(const Component& c) {
constexpr bool operator==(const Component& c) const {
return mask == c.mask;
}

constexpr bool operator!=(const Component& c) {
constexpr bool operator!=(const Component& c) const {
return mask != c.mask;
}

Expand Down Expand Up @@ -189,11 +189,11 @@ class DynamicFormat {
return r.pack(_r) | g.pack(_g) | b.pack(_b) | a.pack(_a);
}

constexpr bool operator==(const DynamicFormat& f) {
constexpr bool operator==(const DynamicFormat& f) const {
return r == f.r && g == f.g && b == f.b && a == f.a && alpha_type == f.alpha_type;
}

constexpr bool operator!=(const DynamicFormat& f) {
constexpr bool operator!=(const DynamicFormat& f) const {
return r != f.r || g != f.g || b != f.b || a != f.a || alpha_type != f.alpha_type;
}
};
Expand Down

0 comments on commit 59f184f

Please sign in to comment.