From c3b3e0a3508acd6e36298ea8f4f3f173c4115327 Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Tue, 10 Dec 2019 12:42:58 -0700 Subject: [PATCH] first pass at the device-independent drawing system, including the Python representation of a device context --- src/Makefile | 2 +- src/dc_screen.c | 170 +++++++++++++++++++++++++++++++ src/dc_screen.h | 2 + src/devctxt.c | 162 ++++++++++++++++++++++++++++++ src/devctxt.h | 17 ++++ src/ep_devctxt.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++ src/ep_init.h | 2 + src/ep_upiwin.c | 24 +++++ src/gfxobj.c | 9 ++ src/gfxobj.h | 1 + 10 files changed, 641 insertions(+), 1 deletion(-) create mode 100755 src/ep_devctxt.c diff --git a/src/Makefile b/src/Makefile index 1e3d59c..86ff8a0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ BUILDUTILS=../buildutils RESOURCES=../resources SPLASHSCREEN=splash-vmwcblk.png -OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_msg.o ep_upiwin_tmp.o ep_util.o \ +OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_msg.o ep_devctxt.o ep_upiwin_tmp.o ep_util.o \ fbinit.o rect.o gfxobj.o devctxt.o dc_screen.o fontengine.o fbprimitive.o \ log.o gpio.o msg_queue.o time_func.o config.o splash.o LIBS=-lpython3.7m -lcrypt -lfreetype -lbcm2835 -lpthread -ldl -lutil -lm diff --git a/src/dc_screen.c b/src/dc_screen.c index 84fced2..8e37e98 100755 --- a/src/dc_screen.c +++ b/src/dc_screen.c @@ -1,5 +1,175 @@ +#include "fbinit.h" +#include "devctxt.h" #include "dc_screen.h" +inline static PUINT16 loc_from_coords(PSCREENPRIVDATA priv, INT32 x, INT32 y) +{ + return priv->pdata + (y * priv->pix_per_row) + x; +} + +inline static UINT16 native_from_COLORREF(COLORREF cr) +{ + return (UINT16)(((cr << 8) & 0xF800) | ((cr >> 5) & 0x7E0) | ((cr >> 19) & 0x1F)); +} + +inline static COLORREF COLORREF_from_native(UINT16 cr) +{ + UINT32 tmp = cr; + return (COLORREF)(((tmp << 19) & 0xF80000) | ((tmp << 5) & 0xFC00) | ((tmp >> 8) & 0xF800)); +} + +static inline UINT16 apply_rop2(INT32 op, UINT16 disp, UINT16 pen) +{ + switch (op) + { + case R2_BLACK: + return 0; + case R2_NOTMERGEPEN: + return ~(disp | pen); + case R2_MASKNOTPEN: + return disp & (~pen); + case R2_NOTCOPYPEN: + return ~pen; + case R2_MASKPENNOT; + return (~disp) & pen; + case R2_NOT: + return ~disp; + case R2_XORPEN: + return disp ^ pen; + case R2_NOTMASKPEN: + return ~(disp & pen); + case R2_MASKPEN: + return disp & pen; + case R2_NOTXORPEN: + return ~(disp ^ pen); + case R2_NOP: + return disp; + case R2_MERGENOTPEN: + return disp | (~pen); + case R2_COPYPEN: + return pen; + case R2_MERGEPENNOT: + return (~disp) | pen; + case R2_MERGEPEN: + return disp | pen; + case R2_WHITE: + return (UINT16)(-1); + } +} + static COLORREF screen_set_pixel(PVOID privdata, INT32 x, INT32 y, COLORREF color, INT32 op) { + PSCREENPRIVDATA priv = (PSCREENPRIVDATA)privdata; + UINT16 pencolor = native_from_COLORREF(color); + PUINT16 loc = loc_from_coords(priv, x, y); + UINT16 screen = *loc; + *loc = apply_rop2(op, screen, pencolor); + return COLORREF_from_native(screen); +} + +static BOOL screen_line(PVOID privdata, INT32 x1, INT32 y1, INT32 x2, INT32 y2, COLORREF color, INT32 op) +{ + PSCREENPRIVDATA priv = (PSCREENPRIVDATA)privdata; + UINT16 pencolor = native_from_COLORREF(color); + INT32 dx = x2 - x1; + INT32 dy = y2 - y1; + INT32 tmp; + PUINT16 loc; + + if (ABS(dx) < ABS(dy)) + { + if (y1 > y2) + { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = -dx; + dy = -dy; + } + loc = loc_from_coords(priv, x1, y1); + tmp = x1; + x1 << 16; + dx = (dx << 16) / dy; + while (y1 <= y2) + { + *loc = apply_rop2(op, *loc, pencolor); + x1 += dx; + ++y1; + loc += priv->pix_per_row; + if (tmp != (x1 >> 16)) + { + loc += ((x1 >> 16) - tmp); + tmp = x1 >> 16; + } + } + } + else + { + if (x1 > x2) + { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = -dx; + dy = -dy; + } + loc = loc_from_coords(priv, x1, y1); + tmp = y1; + y1 <<= 16; + dy = dx ? (dy << 16) / dx : 0; + while (x1 <= x2) + { + *loc = apply_rop2(op, *loc, pencolor); + y1 += dy; + ++x1; + ++loc; + if (tmp != (y1 >> 16)) + { + loc += ((((y1 >> 16) - tmp) * priv->pix_per_row); + tmp = y1 >> 16; + } + } + } +} + +static const DCFUNTABLE screen_funtable = { + screen_set_pixel, + screen_line +}; + +static void screen_context_destroy(PVOID obj) +{ + PDCTXT pdctxt = (PDCTXT)obj; + _DC_FinalizeCommon(pdctxt); + free(pdctxt->privdata); +} + +PDCTXT DC_CreateScreenContext(void) +{ + PDCTXT rc; + PSCREENPRIVDATA priv; + + priv = (PSCREENPRIVDATA)malloc(sizeof(SCREENPRIVDATA)); + if (!priv) + return NULL; + priv->pix_per_row = Fb_Info->width; + priv->pdata = Pb_Ptr; + + rc = _DC_Allocate(&screen_funtable, priv); + if (rc) + { + rc->hdr.dtor = screen_context_destroy; + rc->cliprect.left = rc->cliprect.top = 0; + rc->cliprect.right = Fb_Info->width - 1; + rc->cliprect.bottom = Fb_Info->height - 1; + } + else + free(priv); + return rc; } diff --git a/src/dc_screen.h b/src/dc_screen.h index 4c4ad6e..ecd4f31 100755 --- a/src/dc_screen.h +++ b/src/dc_screen.h @@ -9,4 +9,6 @@ typedef struct tagSCREENPRIVDATA { UINT16 *pdata; } SCREENPRIVDATA, *PSCREENPRIVDATA; +extern PDCTXT DC_CreateScreenContext(void); + #endif /* __DC_SCREEN_H_INCLUDED */ diff --git a/src/devctxt.c b/src/devctxt.c index 982325a..df89755 100755 --- a/src/devctxt.c +++ b/src/devctxt.c @@ -1,9 +1,171 @@ +#include #include "gfxtype.h" +#include "gfxobj.h" #include "devctxt.h" +inline static BYTE line_clip_outcode(INT32 x, INT32 y, INT32 xmin, INT32 ymin, INT32 xmax, INT32 ymax) +{ + BYTE rc = 0; + if (y < ymin) + rc |= 0x8; + else if (y >= ymax) + rc |= 0x4; + if (x < xmin) + rc |= 0x1; + else if (x >= xmax) + rc |= 0x2; + return rc; +} + +static BOOL line_clip(PINT32 output, INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 xmin, INT32 ymin, INT32 xmax, INT32 ymax) +{ + BYTE outcode1, outcode2, tmpb; + INT32 tmp; + + /* Cohen-Sutherland line-clipping algorithm (see Foley & Van Dam, pp. 145-149) */ + for (;;) + { + outcode1 = line_clip_outcode(x1, y1, xmin, ymin, xmax, ymax); + outcode2 = line_clip_outcode(x2, y2, xmin, ymin, xmax, ymax); + if ((outcode1 & outcode2) != 0) + return FALSE; /* trivial rejection */ + else if ((outcode1 == 0) && (outcode2 == 0)) + break; /* trivial acceptance */ + if (outcode1 == 0) + { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + tmpb = outcode1; + outcode1 = outcode2; + outcode2 = tmp; + } + if (outcode1 & 0x8) + { + x1 += (x2 - x1) * (ymin - y1) / (y2 - y1); + y1 = ymin; + } + else if (outcode1 & 0x4) + { + x1 += (x2 - x1) * (ymax - y1) / (y2 - y1); + y1 = ymax; + } + else if (outcode1 & 0x2) + { + y1 += (y2 - y1) * (xmax - x1) / (x2 - x1); + x1 = xmax; + } + else if (outcode1 & 0x1) + { + y1 += (y2 - y1) * (xmin - x1) / (x2 - x1); + x1 = xmin; + } + } + output[0] = x1; + output[1] = y1; + output[2] = x2; + output[3] = y2; + return TRUE; +} + +static BOOL internal_line(PDCTXT pdctxt, INT32 x1, INT32 y1, INT32 x2, INT32 y2) +{ + INT32 buffer[4]; + if (line_clip(buffer, x1 << 16, y1 << 16, x2 << 16, y2 << 16, pdctxt->cliprect.left << 16, pdctxt->cliprect.top << 16, + pdctxt->cliprect.right << 16, pdctxt->cliprect.bottom << 16)) + return (*pdctxt->funcs->line)(pdctxt->privdata, buffer[0] >> 16, buffer[1] >> 16, buffer[2] >> 16, buffer[3] >> 16, pdctxt->color, pdctxt->rop2); + return TRUE; +} + +PDCTXT _DC_Allocate(PDCFUNTABLE funcs, PVOID privdata) +{ + PDCTXT rc = (PDCTXT)malloc(sizeof(DCTXT)); + if (!rc) + return NULL; + memset(rc, 0, sizeof(DCTXT)); + _Go_init(&(rc->hdr), DCTXT_SIG_WORD, sizeof(DCTXT)); + rc->funcs = funcs; + rc->privdata = privdata; + rc->rop2 = R2_COPYPEN; + return rc; +} + +void _DC_FinalizeCommon(PDCTXT pdctxt) +{ + /* nothing here yet */ +} + COLORREF DC_SetPixel(PDCTXT pdctxt, INT32 x, INT32 y, COLORREF color) { if (!G_coords_in_rect(&(pdctxt->cliprect), x, y)) return (COLORREF)(-1); return (*(pdctxt->funcs->set_pixel))(pdctxt->privdata, xm, y, colorref, pdctxt->rop2); } + +BOOL DC_LineTo(PDCTXT pdctxt, INT32 x, INT32 y) +{ + BOOL rc = internal_line(pdctxt, pdctxt->pos.x, pdctxt->pos.y, x, y); + if (rc) + { + pdctxt->pos.x = x; + pdctxt->pos.y = y; + } + return rc; +} + +BOOL DC_MoveTo(PDCTXT pdctxt, INT32 x, INT32 y, PPOINT oldpt) +{ + if (oldpt) + memcpy(oldpt, &(pdctxt->pos), sizeof(POINT)); + pdctxt->pos.x = x; + pdctxt->pos.y = y; + return TRUE; +} + +BOOL DC_Rectangle(PDCTXT pdctxt, INT32 left, INT32 top, INT32 right, INT32 bottom) +{ + internal_line(pdctxt, left, top, right - 1, top); + internal_line(pdctxt, left, top + 1, left, bottom - 2); + internal_line(pdctxt, right - 1, top + 1, right - 1, bottom - 2); + internal_line(pdctxt, left, bottom - 1, right - 1, bottom - 1); + return TRUE; +} + +UINT32 DC_GetROP2(PDCTXT pdctxt) +{ + return pdctxt->rop2; +} + +UINT32 DC_SetROP2(PDCTXT pdctxt, UINT32 rop) +{ + UINT32 rc = pdctxt->rop2; + pdctxt->rop2 = rop; + return rc; +} + +COLORREF DC_GetTextColor(PDCTXT pdctxt) +{ + return pdctxt->color; +} + +COLORREF DC_SetTextColor(PDCTXT pdctxt, COLORREF cr) +{ + COLORREF rc = pdctxt->color; + pdctxt->color = cr; + return rc; +} + +BOOL DC_GetClipRect(PDCTXT pdctxt, PRECT prect) +{ + memcpy(prect, &(pdctxt->cliprect), sizeof(RECT)); + return TRUE; +} + +BOOL DC_SetClipRect(PDCTXT pdctxt, PRECT prect) +{ + memcpy(&(pdctxt->cliprect), prect, sizeof(RECT)); + return TRUE; +} diff --git a/src/devctxt.h b/src/devctxt.h index 2e8f528..1b8d3a4 100755 --- a/src/devctxt.h +++ b/src/devctxt.h @@ -26,9 +26,11 @@ #define R2_WHITE 16 typedef COLORREF (*DCtx_SetPixel)(PVOID privdata, INT32 x, INT32 y, COLORREF color, INT32 op); +typedef BOOL (*DCtx_Line)(PVOID privdata, INT32 x1, INT32 y1, INT32 x2, INT32 y2, COLORREF color, INT32 op); typedef struct tagDCFUNTABLE { DCtx_SetPixel set_pixel; /* sets a single pixel on the display */ + DCtx_Line line; /* draws a line on the display */ } DCFUNTABLE; typedef const DCFUNTABLE *PDCFUNTABLE; @@ -43,6 +45,21 @@ typedef struct tagDCTXT { COLORREF color; /* current drawing color (XXX replace with pens later) */ } DCTXT, *PDCTXT; +extern PDCTXT _DC_Allocate(PDCFUNTABLE funcs, PVOID privdata); +extern void _DC_FinalizeCommon(PDCTXT pdctxt); + extern COLORREF DC_SetPixel(PDCTXT pdctxt, INT32 x, INT32 y, COLORREF color); +extern BOOL DC_LineTo(PDCTXT pdctxt, INT32 x, INT32 y); +extern BOOL DC_MoveTo(PDCTXT pdctxt, INT32 x, INT32 y, PPOINT oldpt); +extern BOOL DC_Rectangle(PDCTXT pdctxt, INT32 left, INT32 top, INT32 right, INT32 bottom); +extern UINT32 DC_GetROP2(PDCTXT pdctxt); +extern UINT32 DC_SetROP2(PDCTXT pdctxt, UINT32 rop); +extern COLORREF DC_GetTextColor(PDCTXT pdctxt); +extern COLORREF DC_SetTextColor(PDCTXT pdctxt, COLORREF cr); +extern BOOL DC_GetClipRect(PDCTXT pdctxt, PRECT prect); +extern BOOL DC_SetClipRect(PDCTXT pdctxt, PRECT prect); + +#define DC_addref(pdctxt) Go_addref(&(pdctxt->hdr)) +#define DC_release(pdctxt) Go_release(&(pdctxt->hdr)) #endif /* __DEVCTXT_H_INCLUDED */ diff --git a/src/ep_devctxt.c b/src/ep_devctxt.c new file mode 100755 index 0000000..f8b3069 --- /dev/null +++ b/src/ep_devctxt.c @@ -0,0 +1,253 @@ +#include +#define PY_SSIZE_T_CLEAN +#include +#include "wintype.h" +#include "scode.h" +#include "devctxt.h" +#include "dc_screen.h" +#include "ep_init.h" + +typedef struct tagDevCtxtObject { + PyObject_HEAD + PDCTXT pdctxt; +} DevCtxtObject; + +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_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 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."}, + {"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" } + char *type; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &type)) + return -1; + if (stricmp(type, "screen") == 0) + { + self->pdctxt = DC_CreateScreenContext(); + if (!(self->pdctxt)) + { + PyErr_SetString(PyExc_RuntimeError, "unable to create screen context"); + return -1 + } + } + else + { + PyErr_Format(PyExc_RuntimeError, "invalid type '%s'", type); + return -1; + } + return 0; +} + +static 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; +} diff --git a/src/ep_init.h b/src/ep_init.h index 82ec538..e394470 100644 --- a/src/ep_init.h +++ b/src/ep_init.h @@ -14,6 +14,8 @@ extern PyObject *UPIWIN_tmp_module; extern PyObject *Epython_init_upiwin_module(void); extern PyObject *Epython_init_upiwin_tmp_module(void); +extern HRESULT Epython_register_devctxt(PyObject *module); + extern HRESULT Epython_setup(void); extern HRESULT Epython_run(void); diff --git a/src/ep_upiwin.c b/src/ep_upiwin.c index 4c51e34..9878d3c 100644 --- a/src/ep_upiwin.c +++ b/src/ep_upiwin.c @@ -6,6 +6,7 @@ #include "ep_init.h" #include "ep_upiwin.h" #include "ep_util.h" +#include "devctxt.h" static PyMethodDef UPIWINMethods[] = { /* Backlight control functions */ @@ -46,6 +47,23 @@ BEGIN_CONSTANT_TABLE(UPIWINConstants) CONSTANT_INT_MACRO(WM_TOUCHDOWN) CONSTANT_INT_MACRO(WM_TOUCHMOVE) CONSTANT_INT_MACRO(WM_TOUCHUP) + /* Raster op constants */ + CONSTANT_INT_MACRO(R2_BLACK) + CONSTANT_INT_MACRO(R2_NOTMERGEPEN) + CONSTANT_INT_MACRO(R2_MASKNOTPEN) + CONSTANT_INT_MACRO(R2_NOTCOPYPEN) + CONSTANT_INT_MACRO(R2_MASKPENNOT) + CONSTANT_INT_MACRO(R2_NOT) + CONSTANT_INT_MACRO(R2_XORPEN) + CONSTANT_INT_MACRO(R2_NOTMASKPEN) + CONSTANT_INT_MACRO(R2_MASKPEN) + CONSTANT_INT_MACRO(R2_NOTXORPEN) + CONSTANT_INT_MACRO(R2_NOP) + CONSTANT_INT_MACRO(R2_MERGENOTPEN) + CONSTANT_INT_MACRO(R2_COPYPEN) + CONSTANT_INT_MACRO(R2_MERGEPENNOT) + CONSTANT_INT_MACRO(R2_MERGEPEN) + CONSTANT_INT_MACRO(R2_WHITE) END_CONSTANT_TABLE PyObject *Epython_init_upiwin_module(void) @@ -62,6 +80,12 @@ PyObject *Epython_init_upiwin_module(void) Py_DECREF(module); return NULL; } + + if (FAILED(Epython_register_devctxt(module))) + { + Py_DECREF(module); + return NULL; + } /* set up the module state */ pstate = (PUPIWIN_STATE)PyModule_GetState(module); diff --git a/src/gfxobj.c b/src/gfxobj.c index 882ca1a..c721f43 100755 --- a/src/gfxobj.c +++ b/src/gfxobj.c @@ -1,6 +1,15 @@ #include +#include #include "gfxobj.h" +void _Go_init(PGFXOBJECT obj, UINT32 sig, UINT32 size) +{ + memset(obj, 0, sizeof(GFXOBJECT)); + obj->sig = sig; + obj->size = size; + obj->refcnt = 1; +} + void Go_unchain(PGFXOBJECT obj) { if (!(obj->next || obj->prev)) diff --git a/src/gfxobj.h b/src/gfxobj.h index 19d5926..0f7a6b6 100755 --- a/src/gfxobj.h +++ b/src/gfxobj.h @@ -16,6 +16,7 @@ typedef struct tagGFXOBJECT { struct tagGFXOBJECT *prev; } GFXOBJECT, *PGFXOBJECT; +extern void _Go_init(PGFXOBJECT obj, UINT32 sig, UINT32 size); extern void Go_unchain(PGFXOBJECT obj); extern INT32 Go_addref(PGFXOBJECT obj); extern INT32 Go_release(PGFXOBJECT obj);