diff options
Diffstat (limited to 'wx+')
-rw-r--r-- | wx+/grid.cpp | 10 | ||||
-rw-r--r-- | wx+/image_resources.cpp | 13 | ||||
-rw-r--r-- | wx+/image_tools.cpp | 44 | ||||
-rw-r--r-- | wx+/image_tools.h | 23 |
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; } /* |