aboutsummaryrefslogtreecommitdiffhomepage
path: root/win32/PlatWin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'win32/PlatWin.cxx')
-rw-r--r--win32/PlatWin.cxx74
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;
}