#include #define PY_SSIZE_T_CLEAN #include #include "wintype.h" #include "scode.h" #include "log.h" #include "devctxt.h" #include "dc_screen.h" #include "ep_init.h" #include "ep_types.h" static PyObject *devctxt_set_pixel(DevCtxtObject *self, PyObject *args) { INT32 x, y; COLORREF color, rc; if (!PyArg_ParseTuple(args, "iik", &x, &y, &color)) return NULL; if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } rc = DC_SetPixel(self->pdctxt, x, y, color); return PyLong_FromUnsignedLong(rc); } static PyObject *devctxt_line_to(DevCtxtObject *self, PyObject *args) { INT32 x, y; BOOL rc; if (!PyArg_ParseTuple(args, "ii", &x, &y)) return NULL; if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } rc = DC_LineTo(self->pdctxt, x, y); return PyBool_FromLong(rc); } static PyObject *devctxt_move_to(DevCtxtObject *self, PyObject *args) { INT32 x, y; BOOL rc; if (!PyArg_ParseTuple(args, "ii", &x, &y)) return NULL; if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } rc = DC_MoveTo(self->pdctxt, x, y, NULL); return PyBool_FromLong(rc); } static PyObject *devctxt_rectangle(DevCtxtObject *self, PyObject *args) { INT32 left, top, right, bottom; BOOL rc; if (!PyArg_ParseTuple(args, "iiii", &left, &top, &right, &bottom)) return NULL; if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } rc = DC_Rectangle(self->pdctxt, left, top, right, bottom); return PyBool_FromLong(rc); } static PyObject *devctxt_solid_rectangle(DevCtxtObject *self, PyObject *args) { INT32 left, top, right, bottom; BOOL rc; if (!PyArg_ParseTuple(args, "iiii", &left, &top, &right, &bottom)) return NULL; if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } rc = DC_SolidRectangle(self->pdctxt, left, top, right, bottom); return PyBool_FromLong(rc); } static PyObject *devctxt_bitblt(DevCtxtObject *self, PyObject *args) { INT32 x, y, width, height, x1, y1; UINT32 rop; DevCtxtObject *source; BOOL rc; if (!PyArg_ParseTuple(args, "iiiiO!iik", &x, &y, &width, &height, &DevCtxtType, &source, &x1, &y1, &rop)) return NULL; if (!(self->pdctxt) || !(source->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } rc = DC_BitBlt(self->pdctxt, x, y, width, height, source->pdctxt, x1, y1, rop); return PyBool_FromLong(rc); } static PyObject *devctxt_get_clip_rect(DevCtxtObject *self, PyObject *args) { RECT rect; if (!PyArg_ParseTuple(args, "")) return NULL; if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } DC_GetClipRect(self->pdctxt, &rect); return Py_BuildValue("(i,i,i,i)", rect.left, rect.top, rect.right, rect.bottom); } static PyObject *devctxt_set_clip_rect(DevCtxtObject *self, PyObject *args) { RECT rect; BOOL rc; if (!PyArg_ParseTuple(args, "iiii", &(rect.left), &(rect.top), &(rect.right), &(rect.bottom))) return NULL; if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } rc = DC_SetClipRect(self->pdctxt, &rect); return PyBool_FromLong(rc); } static PyObject *devctxt_select_bitmap(DevCtxtObject *self, BitmapObject *newbmp) { BitmapObject *old_bitmap = NULL; PBITMAP old_pbmp; Log(LDEBUG, "select_bitmap entry"); if ((self->pdctxt->flags & DCFLG_TYPES) != DCFLG_IS_MEMORY) { PyErr_SetString(PyExc_RuntimeError, "must select bitmap into memory device context"); return NULL; } Log(LDEBUG, "verified 1"); old_bitmap = self->selected_bitmap; old_pbmp = (PBITMAP)DC_SelectObject(self->pdctxt, (PGFXOBJECT)(newbmp->pbmp)); Log(LDEBUG, "old_bitmap present=%d, old_pbmp present=%d", !!old_bitmap, !!old_pbmp); if (!old_bitmap) { Log(LDEBUG, "need to wrap old bitmap"); old_bitmap = (BitmapObject *)Epython_wrap_bitmap(old_pbmp); if (!old_bitmap) { DC_SelectObject(self->pdctxt, (PGFXOBJECT)old_pbmp); return NULL; } else Py_INCREF(old_bitmap); } Log(LDEBUG, "replacement sequence"); Py_DECREF(self->selected_bitmap); self->selected_bitmap = newbmp; Py_INCREF(self->selected_bitmap); return (PyObject *)old_bitmap; } static PyObject *devctxt_select_object(DevCtxtObject *self, PyObject *args) { PyObject *obj; Log(LDEBUG, "select_object entry"); if (!PyArg_ParseTuple(args, "O", &obj)) return NULL; if (!obj) { PyErr_SetString(PyExc_RuntimeError, "bad object selected"); return NULL; } Log(LDEBUG, "ready to comb objects"); if (PyObject_TypeCheck(obj, &BitmapType)) return devctxt_select_bitmap(self, (BitmapObject *)obj); PyErr_SetString(PyExc_RuntimeError, "unknown type of object selected"); return NULL; } static PyMethodDef DevCtxtMethods[] = { {"set_pixel", (PyCFunction)devctxt_set_pixel, METH_VARARGS, "Sets a single pixel on the display."}, {"line_to", (PyCFunction)devctxt_line_to, METH_VARARGS, "Draws a line from the current position to the specified location."}, {"move_to", (PyCFunction)devctxt_move_to, METH_VARARGS, "Draws a line from the current position to the specified location."}, {"rectangle", (PyCFunction)devctxt_rectangle, METH_VARARGS, "Draws a rectangle."}, {"solid_rectangle", (PyCFunction)devctxt_solid_rectangle, METH_VARARGS, "Draws a solid rectangle."}, {"bitblt", (PyCFunction)devctxt_bitblt, METH_VARARGS, "Copy bits from one device context to another."}, {"select_object", (PyCFunction)devctxt_select_object, METH_VARARGS, "Selects a graphic object into the device context."}, {"get_clip_rect", (PyCFunction)devctxt_get_clip_rect, METH_VARARGS, "Returns the current clipping rectangle of the device context."}, {"set_clip_rect", (PyCFunction)devctxt_set_clip_rect, METH_VARARGS, "Sets the current clipping rectangle of the device context."}, {NULL, NULL, 0, NULL} }; static PyObject *devctxt_get_rop2(DevCtxtObject *self, void *closure) { if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } return PyLong_FromUnsignedLong(DC_GetROP2(self->pdctxt)); } static int devctxt_set_rop2(DevCtxtObject *self, PyObject *value, void *closure) { UINT32 v; if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return -1; } if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute"); return -1; } v = PyLong_AsUnsignedLong(value); if (PyErr_Occurred()) return -1; DC_SetROP2(self->pdctxt, v); return 0; } static PyObject *devctxt_get_text_color(DevCtxtObject *self, void *closure) { if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return NULL; } return PyLong_FromUnsignedLong(DC_GetTextColor(self->pdctxt)); } static int devctxt_set_text_color(DevCtxtObject *self, PyObject *value, void *closure) { COLORREF v; if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "bad device context"); return -1; } if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute"); return -1; } v = PyLong_AsUnsignedLong(value); if (PyErr_Occurred()) return -1; DC_SetTextColor(self->pdctxt, v); return 0; } static PyGetSetDef DevCtxtProperties[] = { {"rop2", (getter)devctxt_get_rop2, (setter)devctxt_set_rop2, "Current raster operation", NULL}, {"text_color", (getter)devctxt_get_text_color, (setter)devctxt_set_text_color, "Current text color", NULL}, {NULL, NULL, NULL, NULL, NULL} }; static void devctxt_dealloc(DevCtxtObject *self) { if (self->pdctxt) DC_release(self->pdctxt); Py_TYPE(self)->tp_free((PyObject *)self); } static int devctxt_init(DevCtxtObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "type", NULL }; const char *type; if (!PyArg_ParseTupleAndKeywords(args, kwds, "$s", kwlist, &type)) return -1; if (strcmp(type, "screen") == 0) { self->pdctxt = DC_CreateScreenContext(); if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "unable to create screen context"); return -1; } } else if (strcmp(type, "memory") == 0) { self->pdctxt = _DC_CreateScreenCompatibleContext(); if (!(self->pdctxt)) { PyErr_SetString(PyExc_RuntimeError, "unable to create memory context"); return -1; } } else { PyErr_Format(PyExc_RuntimeError, "invalid type '%s'", type); return -1; } return 0; } PyTypeObject DevCtxtType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "upiwin.DevCtxt", .tp_doc = "Device context object", .tp_basicsize = sizeof(DevCtxtObject), .tp_itemsize = 0, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_new = PyType_GenericNew, .tp_init = (initproc)devctxt_init, .tp_dealloc = (destructor)devctxt_dealloc, .tp_methods = DevCtxtMethods, .tp_getset = DevCtxtProperties, }; HRESULT Epython_register_devctxt(PyObject *module) { if (PyType_Ready(&DevCtxtType) < 0) return E_FAIL; Py_INCREF(&DevCtxtType); if (PyModule_AddObject(module, "DevCtxt", (PyObject *)(&DevCtxtType)) < 0) { Py_DECREF(&DevCtxtType); return E_FAIL; } return S_OK; }