Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 70 additions & 39 deletions src/grandorgue/gui/panels/primitives/GOBitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,37 @@ unsigned GOBitmap::GetSourceHeight() const {

void GOBitmap::BuildBitmapFrom(
const wxImage &img, double scale, const wxRect &rect, GOBitmap *background) {
if (background && img.HasAlpha()) {
wxBitmap bmp(img.GetWidth(), img.GetHeight());
wxBitmap orig(img);
wxMemoryDC dc;

dc.SelectObject(bmp);
dc.DrawBitmap(
background->GetResultBitmap(), -rect.GetX(), -rect.GetY(), false);
dc.DrawBitmap(orig, 0, 0, true);
bmp.SetMask(orig.GetMask());
wxImage img_result = bmp.ConvertToImage();
if (!img_result.HasAlpha())
img_result.InitAlpha();
memcpy(
img_result.GetAlpha(), img.GetAlpha(), img.GetWidth() * img.GetHeight());

m_ResultBitmap = (wxBitmap)img_result.Scale(
img.GetWidth() * scale, img.GetHeight() * scale, wxIMAGE_QUALITY_BICUBIC);
} else
m_ResultBitmap = (wxBitmap)img.Scale(
img.GetWidth() * scale, img.GetHeight() * scale, wxIMAGE_QUALITY_BICUBIC);
const int imgHeight = img.GetHeight();
const int imgWidth = img.GetWidth();
const int newHeight = imgHeight * scale;
const int newWidth = imgWidth * scale;

m_ResultValid = newHeight > 0 && newWidth > 0;
if (m_ResultValid) {
const wxBitmap *pBackgroundBitmap
= background ? background->GetResultBitmap() : nullptr;

if (pBackgroundBitmap && img.HasAlpha()) {
wxBitmap bmp(imgWidth, imgHeight);
wxBitmap orig(img);
wxMemoryDC dc;

dc.SelectObject(bmp);
dc.DrawBitmap(*pBackgroundBitmap, -rect.GetX(), -rect.GetY(), false);
dc.DrawBitmap(orig, 0, 0, true);
bmp.SetMask(orig.GetMask());

wxImage img_result = bmp.ConvertToImage();

if (!img_result.HasAlpha())
img_result.InitAlpha();
memcpy(img_result.GetAlpha(), img.GetAlpha(), imgWidth * imgHeight);
m_ResultBitmap = (wxBitmap)img_result.Scale(
newWidth, newHeight, wxIMAGE_QUALITY_BICUBIC);
} else
m_ResultBitmap
= (wxBitmap)img.Scale(newWidth, newHeight, wxIMAGE_QUALITY_BICUBIC);
}
m_Scale = scale;
}

Expand All @@ -56,26 +66,47 @@ void GOBitmap::BuildScaledBitmap(

void GOBitmap::BuildTileBitmap(
double scale,
const wxRect &rect,
unsigned xo,
unsigned yo,
const wxRect &newRect,
unsigned newXOffset,
unsigned newYOffset,
GOBitmap *background) {
const int tgtHeight = newRect.GetHeight();
const int tgtWidth = newRect.GetWidth();

if (
p_SourceImage
&& (
scale != m_Scale
|| m_ResultWidth != rect.GetWidth()
|| m_ResultHeight != rect.GetHeight() || xo != m_ResultXOffset
|| yo != m_ResultYOffset)) {
wxImage img(rect.GetWidth(), rect.GetHeight());

for (int y = -yo; y < img.GetHeight(); y += GetSourceHeight())
for (int x = -xo; x < img.GetWidth(); x += GetSourceWidth())
img.Paste(*p_SourceImage, x, y);
BuildBitmapFrom(img, scale, rect, background);
m_ResultWidth = rect.GetWidth();
m_ResultHeight = rect.GetHeight();
m_ResultXOffset = xo;
m_ResultYOffset = yo;
&& (scale != m_Scale || m_ResultWidth != tgtHeight || m_ResultHeight != tgtWidth || newXOffset != m_ResultXOffset || newYOffset != m_ResultYOffset)) {
const int srcHeight = p_SourceImage->GetHeight();
const int srcWidth = p_SourceImage->GetWidth();
wxImage img(tgtWidth, tgtHeight);

for (int y = -newYOffset; y < tgtHeight; y += srcHeight)
for (int x = -newXOffset; x < tgtWidth; x += srcWidth) {
// Calculate source starting position using std::max(0, -offset)
const int srcX = std::max(0, -x);
const int srcY = std::max(0, -y);

// Ensure copy stays within target bounds using std::min
const int copyWidth = std::min(srcWidth - srcX, tgtWidth - x);
const int copyHeight = std::min(srcHeight - srcY, tgtHeight - y);

// Paste only if valid copy region exists
if (copyWidth > 0 && copyHeight > 0) {
if (copyWidth != (int)srcWidth || copyHeight != (int)srcHeight) {
// Partial copy - use GetSubImage
wxImage tile = p_SourceImage->GetSubImage(
wxRect(srcX, srcY, copyWidth, copyHeight));
img.Paste(tile, x, y);
} else {
// Full tile copy - use direct Paste
img.Paste(*p_SourceImage, x, y);
}
}
}
BuildBitmapFrom(img, scale, newRect, background);
m_ResultHeight = tgtHeight;
m_ResultWidth = tgtWidth;
m_ResultXOffset = newXOffset;
m_ResultYOffset = newYOffset;
}
}
11 changes: 7 additions & 4 deletions src/grandorgue/gui/panels/primitives/GOBitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class GOBitmap {
int m_ResultHeight = 0;
unsigned m_ResultXOffset = 0;
unsigned m_ResultYOffset = 0;
bool m_ResultValid = false;

void BuildBitmapFrom(
const wxImage &img, double scale, const wxRect &rect, GOBitmap *background);
Expand All @@ -41,12 +42,14 @@ class GOBitmap {
double scale, const wxRect &rect, GOBitmap *background);
void BuildTileBitmap(
double scale,
const wxRect &rect,
unsigned xo,
unsigned yo,
const wxRect &newRect,
unsigned newXOffset,
unsigned newYOffset,
GOBitmap *background);

const wxBitmap &GetResultBitmap() const { return m_ResultBitmap; }
const wxBitmap *GetResultBitmap() const {
return m_ResultValid ? &m_ResultBitmap : nullptr;
}
};

#endif
11 changes: 8 additions & 3 deletions src/grandorgue/gui/panels/primitives/GODC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ wxRect GODC::ScaleRect(const wxRect &rect) {
}

void GODC::DrawBitmap(GOBitmap &bitmap, const wxRect &target) {
unsigned xpos = target.GetX() * m_Scale + 0.5;
unsigned ypos = target.GetY() * m_Scale + 0.5;
m_DC->DrawBitmap(bitmap.GetResultBitmap(), xpos, ypos, true);
const wxBitmap *pBitmap = bitmap.GetResultBitmap();

if (pBitmap) {
unsigned xpos = target.GetX() * m_Scale + 0.5;
unsigned ypos = target.GetY() * m_Scale + 0.5;

m_DC->DrawBitmap(*pBitmap, xpos, ypos, true);
}
}

wxString GODC::WrapText(const wxString &string, unsigned width) {
Expand Down