summaryrefslogtreecommitdiff
path: root/wx+
diff options
context:
space:
mode:
Diffstat (limited to 'wx+')
-rw-r--r--wx+/grid.cpp10
-rw-r--r--wx+/image_resources.cpp13
-rw-r--r--wx+/image_tools.cpp44
-rw-r--r--wx+/image_tools.h23
4 files changed, 73 insertions, 17 deletions
diff --git a/wx+/grid.cpp b/wx+/grid.cpp
index 377510ae..183fc3c3 100644
--- a/wx+/grid.cpp
+++ b/wx+/grid.cpp
@@ -1321,17 +1321,19 @@ void Grid::updateWindowSizes(bool updateScrollbar)
auto getMainWinSize = [&](const wxSize& clientSize) { return wxSize(std::max(0, clientSize.GetWidth() - rowLabelWidth), std::max(0, clientSize.GetHeight() - colLabelHeight)); };
- auto setScrollbars2 = [&](int logWidth, int logHeight) //replace SetScrollbars, which loses precision to pixelsPerUnitX for some brain-dead reason
+ auto setScrollbars2 = [&](int logWidth, int logHeight) //replace SetScrollbars, which loses precision of pixelsPerUnitX for some brain-dead reason
{
- int ppsuX = 0; //pixel per scroll unit
+ mainWin_->SetVirtualSize(logWidth, logHeight); //set before calling SetScrollRate():
+ //else SetScrollRate() would fail to preserve scroll position when "new virtual pixel-pos > old virtual height"
+
+ int ppsuX = 0; //pixel per scroll unit
int ppsuY = 0;
GetScrollPixelsPerUnit(&ppsuX, &ppsuY);
const int ppsuNew = rowLabelWin_->getRowHeight();
if (ppsuX != ppsuNew || ppsuY != ppsuNew) //support polling!
- SetScrollRate(ppsuNew, ppsuNew); //internally calls AdjustScrollbars()!
+ SetScrollRate(ppsuNew, ppsuNew); //internally calls AdjustScrollbars() and GetVirtualSize()!
- mainWin_->SetVirtualSize(logWidth, logHeight);
AdjustScrollbars(); //lousy wxWidgets design decision: internally calls mainWin_->GetClientSize() without considering impact of scrollbars!
//Attention: setting scrollbars triggers *synchronous* resize event if scrollbars are shown or hidden! => updateWindowSizes() recursion! (Windows)
};
diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp
index a76a2822..089acf4e 100644
--- a/wx+/image_resources.cpp
+++ b/wx+/image_resources.cpp
@@ -12,6 +12,7 @@
#include <wx/image.h>
#include <wx/mstream.h>
#include <zen/utf.h>
+#include "image_tools.h"
using namespace zen;
@@ -48,7 +49,7 @@ public:
void init(const Zstring& filepath);
- const wxBitmap& getImage(const wxString& name) const;
+ const wxBitmap& getImage (const wxString& name) const;
const wxAnimation& getAnimation(const wxString& name) const;
private:
@@ -84,7 +85,15 @@ void GlobalResources::init(const Zstring& filepath)
//generic image loading
if (endsWith(name, L".png"))
- bitmaps.emplace(name, wxImage(streamIn, wxBITMAP_TYPE_PNG));
+ {
+ wxImage img(streamIn, wxBITMAP_TYPE_PNG);
+
+ //end this alpha/no-alpha/mask/wxDC::DrawBitmap/RTL/high-contrast-scheme interoperability nightmare here and now!!!!
+ //=> there's only one type of png image: with alpha channel, no mask!!!
+ convertToVanillaImage(img);
+
+ bitmaps.emplace(name, img);
+ }
else if (endsWith(name, L".gif"))
loadAnimFromZip(streamIn, anims[name]);
}
diff --git a/wx+/image_tools.cpp b/wx+/image_tools.cpp
index 1dbd5d46..859c9e5a 100644
--- a/wx+/image_tools.cpp
+++ b/wx+/image_tools.cpp
@@ -76,7 +76,6 @@ wxImage zen::stackImages(const wxImage& img1, const wxImage& img2, ImageStackLay
wxImage output(width, height);
output.SetAlpha();
::memset(output.GetAlpha(), wxIMAGE_ALPHA_TRANSPARENT, width * height);
- ::memset(output.GetData (), 0, 3 * width * height); //redundant due to transparent alpha
auto calcPos = [&](int imageExtent, int totalExtent)
{
@@ -185,3 +184,46 @@ wxImage zen::createImageFromText(const wxString& text, const wxFont& font, const
}
return output;
}
+
+
+void zen::convertToVanillaImage(wxImage& img)
+{
+ if (!img.HasAlpha())
+ {
+ unsigned char mask_r = 0;
+ unsigned char mask_g = 0;
+ unsigned char mask_b = 0;
+ const bool haveMask = img.HasMask() && img.GetOrFindMaskColour(&mask_r, &mask_g, &mask_b);
+ //check for mask before calling wxImage::GetOrFindMaskColour() to skip needlessly searching for new mask color
+
+ img.SetAlpha();
+ ::memset(img.GetAlpha(), wxIMAGE_ALPHA_OPAQUE, img.GetWidth() * img.GetHeight());
+
+ //wxWidgets, as always, tries to be more clever than it really is and fucks up wxStaticBitmap if wxBitmap is fully opaque:
+ img.GetAlpha()[img.GetWidth() * img.GetHeight() - 1] = 254;
+
+ if (haveMask)
+ {
+ img.SetMask(false);
+ unsigned char* alphaPtr = img.GetAlpha();
+ const unsigned char* dataPtr = img.GetData();
+
+ const int pixelCount = img.GetWidth() * img.GetHeight();
+ for (int i = 0; i < pixelCount; ++ i)
+ {
+ const unsigned char r = *dataPtr++;
+ const unsigned char g = *dataPtr++;
+ const unsigned char b = *dataPtr++;
+
+ if (r == mask_r &&
+ g == mask_g &&
+ b == mask_b)
+ alphaPtr[i] = wxIMAGE_ALPHA_TRANSPARENT;
+ }
+ }
+ }
+ else
+ {
+ assert(!img.HasMask());
+ }
+} \ No newline at end of file
diff --git a/wx+/image_tools.h b/wx+/image_tools.h
index cb8da60b..b53d42ea 100644
--- a/wx+/image_tools.h
+++ b/wx+/image_tools.h
@@ -33,10 +33,10 @@ wxImage stackImages(const wxImage& img1, const wxImage& img2, ImageStackLayout d
wxImage createImageFromText(const wxString& text, const wxFont& font, const wxColor& col);
+wxBitmap layOver(const wxBitmap& foreground, const wxBitmap& background); //merge
wxImage greyScale(const wxImage& img); //greyscale + brightness adaption
wxBitmap greyScale(const wxBitmap& bmp); //
-wxBitmap layOver(const wxBitmap& foreground, const wxBitmap& background); //merge
//void moveImage(wxImage& img, int right, int up);
void adjustBrightness(wxImage& img, int targetLevel);
@@ -45,6 +45,8 @@ void brighten(wxImage& img, int level); //level: delta per channel in points
bool isEqual(const wxBitmap& lhs, const wxBitmap& rhs); //pixel-wise equality (respecting alpha channel)
+void convertToVanillaImage(wxImage& img); //add alpha channel if missing + remove mask if existing
+
//wxColor gradient(const wxColor& from, const wxColor& to, double fraction); //maps fraction within [0, 1] to an intermediate color
//wxColour hsvColor(double h, double s, double v); //h within [0, 360), s, v within [0, 1]
@@ -147,15 +149,15 @@ void adjustBrightness(wxImage& img, int targetLevel)
inline
wxBitmap layOver(const wxBitmap& foreground, const wxBitmap& background)
{
- wxBitmap output = background;
+ assert(foreground.HasAlpha() == background.HasAlpha()); //we don't support mixed-mode brittleness!
+
+ wxBitmap output(background.ConvertToImage()); //attention: wxBitmap/wxImage use ref-counting without copy on write!
{
- wxMemoryDC dc;
- dc.SelectObject(output);
+ wxMemoryDC dc(output);
const int offsetX = (background.GetWidth () - foreground.GetWidth ()) / 2;
const int offsetY = (background.GetHeight() - foreground.GetHeight()) / 2;
- dc.DrawBitmap(foreground, offsetX, offsetY, true);
- dc.SelectObject(wxNullBitmap);
+ dc.DrawBitmap(foreground, offsetX, offsetY);
}
return output;
}
@@ -179,13 +181,14 @@ bool isEqual(const wxBitmap& lhs, const wxBitmap& rhs)
if (imLhs.HasAlpha() != imRhs.HasAlpha())
return false;
- if (imLhs.HasAlpha())
- {
+ if (!std::equal(imLhs.GetData(), imLhs.GetData() + pixelCount * 3, imRhs.GetData()))
+ return false;
+
+ if (imLhs.HasAlpha())
if (!std::equal(imLhs.GetAlpha(), imLhs.GetAlpha() + pixelCount, imRhs.GetAlpha()))
return false;
- }
- return std::equal(imLhs.GetData(), imLhs.GetData() + pixelCount * 3, imRhs.GetData());
+ return true;
}
/*
bgstack15