123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828 |
- /*
- * The Python Imaging Library.
- *
- * display support (and other windows-related stuff)
- *
- * History:
- * 1996-05-13 fl Windows DIB support
- * 1996-05-21 fl Added palette stuff
- * 1996-05-28 fl Added display_mode stuff
- * 1997-09-21 fl Added draw primitive
- * 2001-09-17 fl Added ImagingGrabScreen (from _grabscreen.c)
- * 2002-05-12 fl Added ImagingListWindows
- * 2002-11-19 fl Added clipboard support
- * 2002-11-25 fl Added GetDC/ReleaseDC helpers
- * 2003-05-21 fl Added create window support (including window callback)
- * 2003-09-05 fl Added fromstring/tostring methods
- * 2009-03-14 fl Added WMF support (from pilwmf)
- *
- * Copyright (c) 1997-2003 by Secret Labs AB.
- * Copyright (c) 1996-1997 by Fredrik Lundh.
- *
- * See the README file for information on usage and redistribution.
- */
- #include "Python.h"
- #include "Imaging.h"
- #include "py3.h"
- /* -------------------------------------------------------------------- */
- /* Windows DIB support */
- #ifdef _WIN32
- #include "ImDib.h"
- #if SIZEOF_VOID_P == 8
- #define F_HANDLE "K"
- #else
- #define F_HANDLE "k"
- #endif
- typedef struct {
- PyObject_HEAD
- ImagingDIB dib;
- } ImagingDisplayObject;
- static PyTypeObject ImagingDisplayType;
- static ImagingDisplayObject*
- _new(const char* mode, int xsize, int ysize)
- {
- ImagingDisplayObject *display;
- if (PyType_Ready(&ImagingDisplayType) < 0)
- return NULL;
- display = PyObject_New(ImagingDisplayObject, &ImagingDisplayType);
- if (display == NULL)
- return NULL;
- display->dib = ImagingNewDIB(mode, xsize, ysize);
- if (!display->dib) {
- Py_DECREF(display);
- return NULL;
- }
- return display;
- }
- static void
- _delete(ImagingDisplayObject* display)
- {
- if (display->dib)
- ImagingDeleteDIB(display->dib);
- PyObject_Del(display);
- }
- static PyObject*
- _expose(ImagingDisplayObject* display, PyObject* args)
- {
- HDC hdc;
- if (!PyArg_ParseTuple(args, F_HANDLE, &hdc))
- return NULL;
- ImagingExposeDIB(display->dib, hdc);
- Py_INCREF(Py_None);
- return Py_None;
- }
- static PyObject*
- _draw(ImagingDisplayObject* display, PyObject* args)
- {
- HDC hdc;
- int dst[4];
- int src[4];
- if (!PyArg_ParseTuple(args, F_HANDLE "(iiii)(iiii)", &hdc,
- dst+0, dst+1, dst+2, dst+3,
- src+0, src+1, src+2, src+3))
- return NULL;
- ImagingDrawDIB(display->dib, hdc, dst, src);
- Py_INCREF(Py_None);
- return Py_None;
- }
- extern Imaging PyImaging_AsImaging(PyObject *op);
- static PyObject*
- _paste(ImagingDisplayObject* display, PyObject* args)
- {
- Imaging im;
- PyObject* op;
- int xy[4];
- xy[0] = xy[1] = xy[2] = xy[3] = 0;
- if (!PyArg_ParseTuple(args, "O|(iiii)", &op, xy+0, xy+1, xy+2, xy+3))
- return NULL;
- im = PyImaging_AsImaging(op);
- if (!im)
- return NULL;
- if (xy[2] <= xy[0])
- xy[2] = xy[0] + im->xsize;
- if (xy[3] <= xy[1])
- xy[3] = xy[1] + im->ysize;
- ImagingPasteDIB(display->dib, im, xy);
- Py_INCREF(Py_None);
- return Py_None;
- }
- static PyObject*
- _query_palette(ImagingDisplayObject* display, PyObject* args)
- {
- HDC hdc;
- int status;
- if (!PyArg_ParseTuple(args, F_HANDLE, &hdc))
- return NULL;
- status = ImagingQueryPaletteDIB(display->dib, hdc);
- return Py_BuildValue("i", status);
- }
- static PyObject*
- _getdc(ImagingDisplayObject* display, PyObject* args)
- {
- HWND window;
- HDC dc;
- if (!PyArg_ParseTuple(args, F_HANDLE, &window))
- return NULL;
- dc = GetDC(window);
- if (!dc) {
- PyErr_SetString(PyExc_IOError, "cannot create dc");
- return NULL;
- }
- return Py_BuildValue(F_HANDLE, dc);
- }
- static PyObject*
- _releasedc(ImagingDisplayObject* display, PyObject* args)
- {
- HWND window;
- HDC dc;
- if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, &window, &dc))
- return NULL;
- ReleaseDC(window, dc);
- Py_INCREF(Py_None);
- return Py_None;
- }
- static PyObject*
- _frombytes(ImagingDisplayObject* display, PyObject* args)
- {
- char* ptr;
- int bytes;
- #if PY_VERSION_HEX >= 0x03000000
- if (!PyArg_ParseTuple(args, "y#:frombytes", &ptr, &bytes))
- return NULL;
- #else
- if (!PyArg_ParseTuple(args, "s#:fromstring", &ptr, &bytes))
- return NULL;
- #endif
- if (display->dib->ysize * display->dib->linesize != bytes) {
- PyErr_SetString(PyExc_ValueError, "wrong size");
- return NULL;
- }
- memcpy(display->dib->bits, ptr, bytes);
- Py_INCREF(Py_None);
- return Py_None;
- }
- static PyObject*
- _tobytes(ImagingDisplayObject* display, PyObject* args)
- {
- #if PY_VERSION_HEX >= 0x03000000
- if (!PyArg_ParseTuple(args, ":tobytes"))
- return NULL;
- #else
- if (!PyArg_ParseTuple(args, ":tostring"))
- return NULL;
- #endif
- return PyBytes_FromStringAndSize(
- display->dib->bits, display->dib->ysize * display->dib->linesize
- );
- }
- static struct PyMethodDef methods[] = {
- {"draw", (PyCFunction)_draw, 1},
- {"expose", (PyCFunction)_expose, 1},
- {"paste", (PyCFunction)_paste, 1},
- {"query_palette", (PyCFunction)_query_palette, 1},
- {"getdc", (PyCFunction)_getdc, 1},
- {"releasedc", (PyCFunction)_releasedc, 1},
- {"frombytes", (PyCFunction)_frombytes, 1},
- {"tobytes", (PyCFunction)_tobytes, 1},
- {"fromstring", (PyCFunction)_frombytes, 1},
- {"tostring", (PyCFunction)_tobytes, 1},
- {NULL, NULL} /* sentinel */
- };
- static PyObject*
- _getattr_mode(ImagingDisplayObject* self, void* closure)
- {
- return Py_BuildValue("s", self->dib->mode);
- }
- static PyObject*
- _getattr_size(ImagingDisplayObject* self, void* closure)
- {
- return Py_BuildValue("ii", self->dib->xsize, self->dib->ysize);
- }
- static struct PyGetSetDef getsetters[] = {
- { "mode", (getter) _getattr_mode },
- { "size", (getter) _getattr_size },
- { NULL }
- };
- static PyTypeObject ImagingDisplayType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "ImagingDisplay", /*tp_name*/
- sizeof(ImagingDisplayObject), /*tp_size*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)_delete, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number */
- 0, /*tp_as_sequence */
- 0, /*tp_as_mapping */
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- methods, /*tp_methods*/
- 0, /*tp_members*/
- getsetters, /*tp_getset*/
- };
- PyObject*
- PyImaging_DisplayWin32(PyObject* self, PyObject* args)
- {
- ImagingDisplayObject* display;
- char *mode;
- int xsize, ysize;
- if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize))
- return NULL;
- display = _new(mode, xsize, ysize);
- if (display == NULL)
- return NULL;
- return (PyObject*) display;
- }
- PyObject*
- PyImaging_DisplayModeWin32(PyObject* self, PyObject* args)
- {
- char *mode;
- int size[2];
- mode = ImagingGetModeDIB(size);
- return Py_BuildValue("s(ii)", mode, size[0], size[1]);
- }
- /* -------------------------------------------------------------------- */
- /* Windows screen grabber */
- typedef HANDLE(__stdcall* Func_SetThreadDpiAwarenessContext)(HANDLE);
- PyObject*
- PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
- {
- int x = 0, y = 0, width, height;
- int includeLayeredWindows = 0, all_screens = 0;
- HBITMAP bitmap;
- BITMAPCOREHEADER core;
- HDC screen, screen_copy;
- DWORD rop;
- PyObject* buffer;
- HANDLE dpiAwareness;
- HMODULE user32;
- Func_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContext_function;
- if (!PyArg_ParseTuple(args, "|ii", &includeLayeredWindows, &all_screens))
- return NULL;
- /* step 1: create a memory DC large enough to hold the
- entire screen */
- screen = CreateDC("DISPLAY", NULL, NULL, NULL);
- screen_copy = CreateCompatibleDC(screen);
- // added in Windows 10 (1607)
- // loaded dynamically to avoid link errors
- user32 = LoadLibraryA("User32.dll");
- SetThreadDpiAwarenessContext_function =
- (Func_SetThreadDpiAwarenessContext)
- GetProcAddress(user32, "SetThreadDpiAwarenessContext");
- if (SetThreadDpiAwarenessContext_function != NULL) {
- // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ((DPI_CONTEXT_HANDLE)-3)
- dpiAwareness = SetThreadDpiAwarenessContext_function((HANDLE) -3);
- }
- if (all_screens) {
- x = GetSystemMetrics(SM_XVIRTUALSCREEN);
- y = GetSystemMetrics(SM_YVIRTUALSCREEN);
- width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
- height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
- } else {
- width = GetDeviceCaps(screen, HORZRES);
- height = GetDeviceCaps(screen, VERTRES);
- }
- if (SetThreadDpiAwarenessContext_function != NULL) {
- SetThreadDpiAwarenessContext_function(dpiAwareness);
- }
- FreeLibrary(user32);
- bitmap = CreateCompatibleBitmap(screen, width, height);
- if (!bitmap)
- goto error;
- if (!SelectObject(screen_copy, bitmap))
- goto error;
- /* step 2: copy bits into memory DC bitmap */
- rop = SRCCOPY;
- if (includeLayeredWindows)
- rop |= CAPTUREBLT;
- if (!BitBlt(screen_copy, 0, 0, width, height, screen, x, y, rop))
- goto error;
- /* step 3: extract bits from bitmap */
- buffer = PyBytes_FromStringAndSize(NULL, height * ((width*3 + 3) & -4));
- if (!buffer)
- return NULL;
- core.bcSize = sizeof(core);
- core.bcWidth = width;
- core.bcHeight = height;
- core.bcPlanes = 1;
- core.bcBitCount = 24;
- if (!GetDIBits(screen_copy, bitmap, 0, height, PyBytes_AS_STRING(buffer),
- (BITMAPINFO*) &core, DIB_RGB_COLORS))
- goto error;
- DeleteObject(bitmap);
- DeleteDC(screen_copy);
- DeleteDC(screen);
- return Py_BuildValue("(ii)(ii)N", x, y, width, height, buffer);
- error:
- PyErr_SetString(PyExc_IOError, "screen grab failed");
- DeleteDC(screen_copy);
- DeleteDC(screen);
- return NULL;
- }
- static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
- {
- PyObject* window_list = (PyObject*) lParam;
- PyObject* item;
- PyObject* title;
- RECT inner, outer;
- int title_size;
- int status;
- /* get window title */
- title_size = GetWindowTextLength(hwnd);
- if (title_size > 0) {
- title = PyUnicode_FromStringAndSize(NULL, title_size);
- if (title)
- GetWindowTextW(hwnd, PyUnicode_AS_UNICODE(title), title_size+1);
- } else
- title = PyUnicode_FromString("");
- if (!title)
- return 0;
- /* get bounding boxes */
- GetClientRect(hwnd, &inner);
- GetWindowRect(hwnd, &outer);
- item = Py_BuildValue(
- F_HANDLE "N(iiii)(iiii)", hwnd, title,
- inner.left, inner.top, inner.right, inner.bottom,
- outer.left, outer.top, outer.right, outer.bottom
- );
- if (!item)
- return 0;
- status = PyList_Append(window_list, item);
- Py_DECREF(item);
- if (status < 0)
- return 0;
- return 1;
- }
- PyObject*
- PyImaging_ListWindowsWin32(PyObject* self, PyObject* args)
- {
- PyObject* window_list;
- window_list = PyList_New(0);
- if (!window_list)
- return NULL;
- EnumWindows(list_windows_callback, (LPARAM) window_list);
- if (PyErr_Occurred()) {
- Py_DECREF(window_list);
- return NULL;
- }
- return window_list;
- }
- /* -------------------------------------------------------------------- */
- /* Windows clipboard grabber */
- PyObject*
- PyImaging_GrabClipboardWin32(PyObject* self, PyObject* args)
- {
- int clip;
- HANDLE handle;
- int size;
- void* data;
- PyObject* result;
- clip = OpenClipboard(NULL);
- /* FIXME: check error status */
- handle = GetClipboardData(CF_DIB);
- if (!handle) {
- /* FIXME: add CF_HDROP support to allow cut-and-paste from
- the explorer */
- CloseClipboard();
- Py_INCREF(Py_None);
- return Py_None;
- }
- size = GlobalSize(handle);
- data = GlobalLock(handle);
- result = PyBytes_FromStringAndSize(data, size);
- GlobalUnlock(handle);
- CloseClipboard();
- return result;
- }
- /* -------------------------------------------------------------------- */
- /* Windows class */
- #ifndef WM_MOUSEWHEEL
- #define WM_MOUSEWHEEL 522
- #endif
- static int mainloop = 0;
- static void
- callback_error(const char* handler)
- {
- PyObject* sys_stderr;
- sys_stderr = PySys_GetObject("stderr");
- if (sys_stderr) {
- PyFile_WriteString("*** ImageWin: error in ", sys_stderr);
- PyFile_WriteString((char*) handler, sys_stderr);
- PyFile_WriteString(":\n", sys_stderr);
- }
- PyErr_Print();
- PyErr_Clear();
- }
- static LRESULT CALLBACK
- windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- PAINTSTRUCT ps;
- PyObject* callback = NULL;
- PyObject* result;
- PyThreadState* threadstate;
- PyThreadState* current_threadstate;
- HDC dc;
- RECT rect;
- LRESULT status = 0;
- /* set up threadstate for messages that calls back into python */
- switch (message) {
- case WM_CREATE:
- mainloop++;
- break;
- case WM_DESTROY:
- mainloop--;
- /* fall through... */
- case WM_PAINT:
- case WM_SIZE:
- callback = (PyObject*) GetWindowLongPtr(wnd, 0);
- if (callback) {
- threadstate = (PyThreadState*)
- GetWindowLongPtr(wnd, sizeof(PyObject*));
- current_threadstate = PyThreadState_Swap(NULL);
- PyEval_RestoreThread(threadstate);
- } else
- return DefWindowProc(wnd, message, wParam, lParam);
- }
- /* process message */
- switch (message) {
- case WM_PAINT:
- /* redraw (part of) window. this generates a WCK-style
- damage/clear/repair cascade */
- BeginPaint(wnd, &ps);
- dc = GetDC(wnd);
- GetWindowRect(wnd, &rect); /* in screen coordinates */
- result = PyObject_CallFunction(
- callback, "siiii", "damage",
- ps.rcPaint.left, ps.rcPaint.top,
- ps.rcPaint.right, ps.rcPaint.bottom
- );
- if (result)
- Py_DECREF(result);
- else
- callback_error("window damage callback");
- result = PyObject_CallFunction(
- callback, "s" F_HANDLE "iiii", "clear", dc,
- 0, 0, rect.right-rect.left, rect.bottom-rect.top
- );
- if (result)
- Py_DECREF(result);
- else
- callback_error("window clear callback");
- result = PyObject_CallFunction(
- callback, "s" F_HANDLE "iiii", "repair", dc,
- 0, 0, rect.right-rect.left, rect.bottom-rect.top
- );
- if (result)
- Py_DECREF(result);
- else
- callback_error("window repair callback");
- ReleaseDC(wnd, dc);
- EndPaint(wnd, &ps);
- break;
- case WM_SIZE:
- /* resize window */
- result = PyObject_CallFunction(
- callback, "sii", "resize", LOWORD(lParam), HIWORD(lParam)
- );
- if (result) {
- InvalidateRect(wnd, NULL, 1);
- Py_DECREF(result);
- } else
- callback_error("window resize callback");
- break;
- case WM_DESTROY:
- /* destroy window */
- result = PyObject_CallFunction(callback, "s", "destroy");
- if (result)
- Py_DECREF(result);
- else
- callback_error("window destroy callback");
- Py_DECREF(callback);
- break;
- default:
- status = DefWindowProc(wnd, message, wParam, lParam);
- }
- if (callback) {
- /* restore thread state */
- PyEval_SaveThread();
- PyThreadState_Swap(threadstate);
- }
- return status;
- }
- PyObject*
- PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
- {
- HWND wnd;
- WNDCLASS windowClass;
- char* title;
- PyObject* callback;
- int width = 0, height = 0;
- if (!PyArg_ParseTuple(args, "sO|ii", &title, &callback, &width, &height))
- return NULL;
- if (width <= 0)
- width = CW_USEDEFAULT;
- if (height <= 0)
- height = CW_USEDEFAULT;
- /* register toplevel window class */
- windowClass.style = CS_CLASSDC;
- windowClass.cbClsExtra = 0;
- windowClass.cbWndExtra = sizeof(PyObject*) + sizeof(PyThreadState*);
- windowClass.hInstance = GetModuleHandle(NULL);
- /* windowClass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); */
- windowClass.hbrBackground = NULL;
- windowClass.lpszMenuName = NULL;
- windowClass.lpszClassName = "pilWindow";
- windowClass.lpfnWndProc = windowCallback;
- windowClass.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(1));
- windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); /* CROSS? */
- RegisterClass(&windowClass); /* FIXME: check return status */
- wnd = CreateWindowEx(
- 0, windowClass.lpszClassName, title,
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT, width, height,
- HWND_DESKTOP, NULL, NULL, NULL
- );
- if (!wnd) {
- PyErr_SetString(PyExc_IOError, "failed to create window");
- return NULL;
- }
- /* register window callback */
- Py_INCREF(callback);
- SetWindowLongPtr(wnd, 0, (LONG_PTR) callback);
- SetWindowLongPtr(wnd, sizeof(callback), (LONG_PTR) PyThreadState_Get());
- Py_BEGIN_ALLOW_THREADS
- ShowWindow(wnd, SW_SHOWNORMAL);
- SetForegroundWindow(wnd); /* to make sure it's visible */
- Py_END_ALLOW_THREADS
- return Py_BuildValue(F_HANDLE, wnd);
- }
- PyObject*
- PyImaging_EventLoopWin32(PyObject* self, PyObject* args)
- {
- MSG msg;
- Py_BEGIN_ALLOW_THREADS
- while (mainloop && GetMessage(&msg, NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- Py_END_ALLOW_THREADS
- Py_INCREF(Py_None);
- return Py_None;
- }
- /* -------------------------------------------------------------------- */
- /* windows WMF renderer */
- #define GET32(p,o) ((DWORD*)(p+o))[0]
- PyObject *
- PyImaging_DrawWmf(PyObject* self, PyObject* args)
- {
- HBITMAP bitmap;
- HENHMETAFILE meta;
- BITMAPCOREHEADER core;
- HDC dc;
- RECT rect;
- PyObject* buffer = NULL;
- char* ptr;
- char* data;
- int datasize;
- int width, height;
- int x0, y0, x1, y1;
- if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH"(ii)(iiii):_load", &data, &datasize,
- &width, &height, &x0, &x1, &y0, &y1))
- return NULL;
- /* step 1: copy metafile contents into METAFILE object */
- if (datasize > 22 && GET32(data, 0) == 0x9ac6cdd7) {
- /* placeable windows metafile (22-byte aldus header) */
- meta = SetWinMetaFileBits(datasize-22, data+22, NULL, NULL);
- } else if (datasize > 80 && GET32(data, 0) == 1 &&
- GET32(data, 40) == 0x464d4520) {
- /* enhanced metafile */
- meta = SetEnhMetaFileBits(datasize, data);
- } else {
- /* unknown meta format */
- meta = NULL;
- }
- if (!meta) {
- PyErr_SetString(PyExc_IOError, "cannot load metafile");
- return NULL;
- }
- /* step 2: create bitmap */
- core.bcSize = sizeof(core);
- core.bcWidth = width;
- core.bcHeight = height;
- core.bcPlanes = 1;
- core.bcBitCount = 24;
- dc = CreateCompatibleDC(NULL);
- bitmap = CreateDIBSection(
- dc, (BITMAPINFO*) &core, DIB_RGB_COLORS, &ptr, NULL, 0
- );
- if (!bitmap) {
- PyErr_SetString(PyExc_IOError, "cannot create bitmap");
- goto error;
- }
- if (!SelectObject(dc, bitmap)) {
- PyErr_SetString(PyExc_IOError, "cannot select bitmap");
- goto error;
- }
- /* step 3: render metafile into bitmap */
- rect.left = rect.top = 0;
- rect.right = width;
- rect.bottom = height;
- /* FIXME: make background transparent? configurable? */
- FillRect(dc, &rect, GetStockObject(WHITE_BRUSH));
- if (!PlayEnhMetaFile(dc, meta, &rect)) {
- PyErr_SetString(PyExc_IOError, "cannot render metafile");
- goto error;
- }
- /* step 4: extract bits from bitmap */
- GdiFlush();
- buffer = PyBytes_FromStringAndSize(ptr, height * ((width*3 + 3) & -4));
- error:
- DeleteEnhMetaFile(meta);
- if (bitmap)
- DeleteObject(bitmap);
- DeleteDC(dc);
- return buffer;
- }
- #endif /* _WIN32 */
|