diff options
Diffstat (limited to 'win32/PlatWin.cxx')
-rw-r--r-- | win32/PlatWin.cxx | 74 |
1 files changed, 63 insertions, 11 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 7ef0e7b2c..35d66030f 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -13,6 +13,13 @@ #include <time.h> #include <limits.h> +#ifdef _MSC_VER +#pragma warning(disable: 4786) +#endif + +#include <vector> +#include <map> + #undef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #include <windows.h> @@ -404,6 +411,7 @@ public: void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back); void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, ColourAllocated outline, int alphaOutline, int flags); + void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage); void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); void Copy(PRectangle rc, Point from, Surface &surfaceSource); @@ -696,6 +704,45 @@ void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated } } +void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) { + if (AlphaBlendFn && rc.Width() > 0) { + HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc)); + if (rc.Width() > width) + rc.left += (rc.Width() - width) / 2; + rc.right = rc.left + width; + if (rc.Height() > height) + rc.top += (rc.Height() - height) / 2; + rc.bottom = rc.top + height; + + BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0}; + unsigned char *image = 0; + HBITMAP hbmMem = CreateDIBSection(reinterpret_cast<HDC>(hMemDC), &bpih, + DIB_RGB_COLORS, reinterpret_cast<void **>(&image), NULL, 0); + HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem); + + for (int y=height-1; y>=0; y--) { + for (int x=0; x<width; x++) { + unsigned char *pixel = image + (y*width+x) * 4; + unsigned char alpha = pixelsImage[3]; + // Input is RGBA, output is BGRA with premultiplied alpha + pixel[2] = (*pixelsImage++) * alpha / 255; + pixel[1] = (*pixelsImage++) * alpha / 255; + pixel[0] = (*pixelsImage++) * alpha / 255; + pixel[3] = *pixelsImage++; + } + } + + BLENDFUNCTION merge = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + + AlphaBlendFn(reinterpret_cast<HDC>(hdc), rc.left, rc.top, rc.Width(), rc.Height(), hMemDC, 0, 0, width, height, merge); + + SelectBitmap(hMemDC, hbmOld); + ::DeleteObject(hbmMem); + ::DeleteDC(hMemDC); + + } +} + void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { PenColour(fore); BrushColor(back); @@ -1318,7 +1365,7 @@ ListBox::~ListBox() { class ListBoxX : public ListBox { int lineHeight; FontID fontCopy; - XPMSet xset; + RGBAImageSet images; LineToItem lti; HWND lb; bool unicodeMode; @@ -1385,6 +1432,7 @@ public: virtual int Find(const char *prefix); virtual void GetValue(int n, char *value, int len); virtual void RegisterImage(int type, const char *xpm_data); + virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage); virtual void ClearRegisteredImages(); virtual void SetDoubleClickAction(CallBackAction action, void *data) { doubleClickAction = action; @@ -1491,7 +1539,7 @@ PRectangle ListBoxX::GetDesiredRect() { } int ListBoxX::TextOffset() const { - int pixWidth = const_cast<XPMSet*>(&xset)->GetWidth(); + int pixWidth = images.GetWidth(); return pixWidth == 0 ? ItemInset.x : ItemInset.x + pixWidth + (ImageInset.x * 2); } @@ -1550,11 +1598,16 @@ void ListBoxX::GetValue(int n, char *value, int len) { } void ListBoxX::RegisterImage(int type, const char *xpm_data) { - xset.Add(type, xpm_data); + XPM xpmImage(xpm_data); + images.Add(type, new RGBAImage(xpmImage)); +} + +void ListBoxX::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) { + images.Add(type, new RGBAImage(width, height, pixelsImage)); } void ListBoxX::ClearRegisteredImages() { - xset.Clear(); + images.Clear(); } void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { @@ -1594,17 +1647,16 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { } // Draw the image, if any - XPM *pxpm = xset.Get(pixId); - if (pxpm) { + RGBAImage *pimage = images.Get(pixId); + if (pimage) { Surface *surfaceItem = Surface::Allocate(); if (surfaceItem) { surfaceItem->Init(pDrawItem->hDC, pDrawItem->hwndItem); - //surfaceItem->SetUnicodeMode(unicodeMode); - //surfaceItem->SetDBCSMode(codePage); int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x; PRectangle rcImage(left, pDrawItem->rcItem.top, - left + xset.GetWidth(), pDrawItem->rcItem.bottom); - pxpm->Draw(surfaceItem, rcImage); + left + images.GetWidth(), pDrawItem->rcItem.bottom); + surfaceItem->DrawRGBAImage(rcImage, + pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels()); delete surfaceItem; ::SetTextAlign(pDrawItem->hDC, TA_TOP); } @@ -1678,7 +1730,7 @@ void ListBoxX::AdjustWindowRect(PRectangle *rc) const { int ListBoxX::ItemHeight() const { int itemHeight = lineHeight + (TextInset.y * 2); - int pixHeight = const_cast<XPMSet*>(&xset)->GetHeight() + (ImageInset.y * 2); + int pixHeight = images.GetHeight() + (ImageInset.y * 2); if (itemHeight < pixHeight) { itemHeight = pixHeight; } |