summaryrefslogtreecommitdiff
path: root/redo/imagelist_windows.c
diff options
context:
space:
mode:
Diffstat (limited to 'redo/imagelist_windows.c')
-rw-r--r--redo/imagelist_windows.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/redo/imagelist_windows.c b/redo/imagelist_windows.c
new file mode 100644
index 0000000..434190c
--- /dev/null
+++ b/redo/imagelist_windows.c
@@ -0,0 +1,86 @@
+// 16 august 2014
+
+#include "winapi_windows.h"
+#include "_cgo_export.h"
+
+HBITMAP unscaledBitmap(void *i, intptr_t dx, intptr_t dy)
+{
+ BITMAPINFO bi;
+ VOID *ppvBits;
+ HBITMAP bitmap;
+
+ ZeroMemory(&bi, sizeof (BITMAPINFO));
+ bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+ bi.bmiHeader.biWidth = (LONG) dx;
+ bi.bmiHeader.biHeight = -((LONG) dy); // negative height to force top-down drawing;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+ bi.bmiHeader.biSizeImage = (DWORD) (dx * dy * 4);
+ bitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppvBits, 0, 0);
+ if (bitmap == NULL)
+ xpanic("error creating HBITMAP for unscaled ImageList image copy", GetLastError());
+ dotoARGB(i, (void *) ppvBits);
+ return bitmap;
+}
+
+HIMAGELIST newImageList(int width, int height)
+{
+ HIMAGELIST il;
+
+ // TODO does this strip alpha?
+ // sinni800 in irc.freenode.net/#go-nuts suggests our use of *image.RGBA makes this not so much of an issue
+ il = (*fv_ImageList_Create)(width, height, ILC_COLOR32, 20, 20); // should be reasonable
+ if (il == NULL)
+ xpanic("error creating image list", GetLastError());
+ return il;
+}
+
+void addImage(HIMAGELIST il, HBITMAP bitmap, int origwid, int oright, int width, int height)
+{
+ BOOL wasScaled = FALSE;
+ HDC scaledDC, origDC;
+ HBITMAP scaled;
+ HBITMAP prevscaled, prevorig;
+
+ // first we need to scale the bitmap
+ if (origwid == width && oright == height) {
+ scaled = bitmap;
+ goto noscale;
+ }
+ wasScaled = TRUE;
+ scaledDC = GetDC(NULL);
+ if (scaledDC == NULL)
+ xpanic("error getting screen DC for scaled ImageList bitmap", GetLastError());
+ scaled = CreateCompatibleBitmap(scaledDC, width, height);
+ if (scaled == NULL)
+ xpanic("error creating scaled ImageList bitmap", GetLastError());
+ prevscaled = SelectObject(scaledDC, scaled);
+ if (prevscaled == NULL)
+ xpanic("error selecting scaled ImageList bitmap into screen DC", GetLastError());
+ origDC = GetDC(NULL);
+ if (origDC == NULL)
+ xpanic("error getting screen DC for original ImageList bitmap", GetLastError());
+ prevorig = SelectObject(origDC, bitmap);
+ if (prevorig == NULL)
+ xpanic("error selecting original ImageList bitmap into screen DC", GetLastError());
+ if (StretchBlt(scaledDC, 0, 0, width, height,
+ origDC, 0, 0, origwid, oright,
+ SRCCOPY) == 0)
+ xpanic("error scaling ImageList bitmap down", GetLastError());
+ if (SelectObject(origDC, prevorig) != bitmap)
+ xpanic("error selecting previous bitmap into original image's screen DC", GetLastError());
+ if (DeleteDC(origDC) == 0)
+ xpanic("error deleting original image's screen DC", GetLastError());
+ if (SelectObject(scaledDC, prevscaled) != scaled)
+ xpanic("error selecting previous bitmap into scaled image's screen DC", GetLastError());
+ if (DeleteDC(scaledDC) == 0)
+ xpanic("error deleting scaled image's screen DC", GetLastError());
+
+noscale:
+ if ((*fv_ImageList_Add)(il, scaled, NULL) == -1)
+ xpanic("error adding ImageList image to image list", GetLastError());
+ if (wasScaled) // clean up
+ if (DeleteObject(scaled) == 0)
+ xpanic("error deleting scaled bitmap", GetLastError());
+}