diff --git a/src/Makefile b/src/Makefile index df44460..eb11555 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,9 +2,9 @@ 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_devctxt.o ep_upiwin_tmp.o ep_util.o \ - fbinit.o rect.o gfxobj.o devctxt.o dc_screen.o fontengine.o bitmap.o fbprimitive.o \ - log.o gpio.o msg_queue.o time_func.o config.o splash.o +OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_msg.o ep_devctxt.o ep_bitmap.o + ep_upiwin_tmp.o ep_util.o fbinit.o rect.o gfxobj.o devctxt.o dc_screen.o fontengine.o \ + bitmap.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 CFLAGS=-I/usr/include/python3.7m -I/usr/include/freetype2 -I/usr/include/libpng16 \ -Wall -fstack-protector -fwrapv -fno-PIE -g -O3 -DDEBUG_ASSERT diff --git a/src/dc_screen.c b/src/dc_screen.c index caf5595..e6f5149 100755 --- a/src/dc_screen.c +++ b/src/dc_screen.c @@ -89,6 +89,7 @@ static BOOL screen_line(PVOID privdata, INT32 x1, INT32 y1, INT32 x2, INT32 y2, ASSERT(y2 >= 0); ASSERT(y2 < Fb_Info->height); + /* uses Bresenham's line algorithm with 16-bit fixed-point arithmetic */ if (ABS(dx) < ABS(dy)) { if (y1 > y2) diff --git a/src/devctxt.c b/src/devctxt.c index 9e954d3..4d342f7 100755 --- a/src/devctxt.c +++ b/src/devctxt.c @@ -35,9 +35,6 @@ static BOOL line_clip(PINT32 output, INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT INT32 tmp; int nloop = 0; - Log(LDEBUG, "clipping line from (%d, %d) to (%d, %d) against bounding box (%d, %d, %d, %d)", x1 >> CPX, y1 >> CPX, x2 >> CPX, y2 >> CPX, - xmin >> CPX, ymin >> CPX, xmax >> CPX, ymax >> CPX); - /* Cohen-Sutherland line-clipping algorithm (see Foley & Van Dam, pp. 145-149) */ for (;;) { @@ -49,18 +46,11 @@ static BOOL line_clip(PINT32 output, INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT outcode1 = line_clip_outcode(x1, y1, xmin, ymin, xmax, ymax); outcode2 = line_clip_outcode(x2, y2, xmin, ymin, xmax, ymax); if ((outcode1 & outcode2) != 0) - { - Log(LDEBUG,"*REJECT*"); return FALSE; /* trivial rejection */ - } else if ((outcode1 == 0) && (outcode2 == 0)) - { - Log(LDEBUG,"*ACCEPT*"); break; /* trivial acceptance */ - } if (outcode1 == 0) { - Log(LDEBUG, "exchange points"); tmp = x1; x1 = x2; x2 = tmp; @@ -73,28 +63,23 @@ static BOOL line_clip(PINT32 output, INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT { x1 += M(x2 - x1, D(ymin - y1, y2 - y1)); y1 = ymin; - Log(LDEBUG, "clipped against top to point (%d, %d)", x1 >> CPX, y1 >> CPX); } else if (outcode1 & 0x4) { x1 += M(x2 - x1, D(ymax - ONE - y1, y2 - y1)); y1 = ymax - ONE; - Log(LDEBUG, "clipped against bottom to point (%d, %d)", x1 >> CPX, y1 >> CPX); } else if (outcode1 & 0x2) { y1 += M(y2 - y1, D(xmax - ONE - x1, x2 - x1)); x1 = xmax - ONE; - Log(LDEBUG, "clipped against right to point (%d, %d)", x1 >> CPX, y1 >> CPX); } else if (outcode1 & 0x1) { y1 += M(y2 - y1, D(xmin - x1, x2 - x1)); x1 = xmin; - Log(LDEBUG, "clipped against left to point (%d, %d)", x1 >> CPX, y1 >> CPX); } } - Log(LDEBUG, "final line is from (%d, %d) to (%d, %d)", x1 >> CPX, y1 >> CPX, x2 >> CPX, y2 >> CPX); output[0] = x1; output[1] = y1; output[2] = x2; diff --git a/src/ep_bitmap.c b/src/ep_bitmap.c new file mode 100755 index 0000000..9f99ac6 --- /dev/null +++ b/src/ep_bitmap.c @@ -0,0 +1,119 @@ +#include +#define PY_SSIZE_T_CLEAN +#include +#include "gfxobj.h" +#include "bitmap.h" +#include "ep_types.h" + +static PyMethodDef BitmapMethods[] = { + {NULL, NULL, 0, NULL} +}; + +static PyObject *bitmap_get_width(BitmapObject *self, void *closure) +{ + if (!(self->pbmp)) + { + PyErr_SetString(PyExc_RuntimeError, "bad bitmap object"); + return NULL; + } + return PyLong_FromUnsignedLong(self->pbmp->width); +} + +static PyObject *bitmap_get_height(BitmapObject *self, void *closure) +{ + if (!(self->pbmp)) + { + PyErr_SetString(PyExc_RuntimeError, "bad bitmap object"); + return NULL; + } + return PyLong_FromUnsignedLong(self->pbmp->height); +} + +static PyGetSetDef BitmapProperties[] = { + {"width", (getter)bitmap_get_width, NULL, + "Width of this bitmap", NULL}, + {"height", (getter)bitmap_get_height, NULL, + "Height of this bitmap", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + +static int bitmap_init(BitmapObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = { "width", "height", NULL }; + int width = 0, height = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "$ii", kwlist, &width, &height)) + return -1; + + width = MAX(1, width); + height = MAX(1, height); + self->pbmp = BMP_Create(width, height, NULL); + if (!(self->bmp)) + { + PyErr_SetString(PyExc_RuntimeError, "unable to create bitmap"); + return -1; + } + return 0; +} + +static void bitmap_dealloc(BitmapObject *self) +{ + if (self->pbmp) + BMP_Delete(self->pbmp); + Py_TYPE(self)->tp_free((PyObject *)self); +} + +PyTypeObject BitmapType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "upiwin.Bitmap", + .tp_doc = "Bitmap object", + .tp_basicsize = sizeof(BitmapObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = PyType_GenericNew, + .tp_init = (initproc)bitmap_init, + .tp_dealloc = (destructor)bitmap_dealloc, + .tp_methods = BitmapMethods, + .tp_getset = BitmapProperties, +}; + +HRESULT Epython_register_bitmap(PyObject *module) +{ + if (PyType_Ready(&BitmapType) < 0) + return E_FAIL; + Py_INCREF(&BitmapType); + if (PyModule_AddObject(module, "Bitmap", (PyObject *)(&BitmapType)) < 0) + { + Py_DECREF(&BitmapType); + return E_FAIL; + } + return S_OK; +} + +PyObject *Epython_wrap_bitmap(PBITMAP pbmp) +{ + PyObject *rc = NULL, *args, *kwargs; + BitmapObject *pbitmapobj; + + args = PyTuple_New(0); + if (args) + { + kwargs = PyDict_New(); + if (kwargs) + { + rc = PyType_GenericNew(&BitmapType, args, kwargs); + if (rc) + { + pbitmapobj = (BitmapObject)rc; + BMP_Delete(pbitmapobj->pbmp); + pbitmapobj->pbmp = pbmp; + } + Py_DECREF(kwargs); + } + Py_DECREF(args); + } + + if (!rc) + PyErr_SetString(PyExc_RuntimeError, "unable to create bitmap"); + return rc; +} diff --git a/src/ep_devctxt.c b/src/ep_devctxt.c index e61611e..09c0687 100755 --- a/src/ep_devctxt.c +++ b/src/ep_devctxt.c @@ -7,13 +7,7 @@ #include "devctxt.h" #include "dc_screen.h" #include "ep_init.h" - -typedef struct tagDevCtxtObject { - PyObject_HEAD - PDCTXT pdctxt; -} DevCtxtObject; - -PyTypeObject DevCtxtType; /* forward declaration */ +#include "ep_types.h" static PyObject *devctxt_set_pixel(DevCtxtObject *self, PyObject *args) { @@ -145,6 +139,54 @@ static PyObject *devctxt_set_clip_rect(DevCtxtObject *self, PyObject *args) return PyBool_FromLong(rc); } +static PyObject *devctxt_select_bitmap(DevCtxtObject *self, BitmapObject *newbmp) +{ + BitmapObject *old_bitmap = NULL; + PBITMAP old_pbmp; + + if ((self->pdctxt->flags & DCFLG_TYPES) != DCFLG_IS_MEMORY) + { + PyErr_SetString(PyExc_RuntimeError, "must select bitmap into memory device context"); + return NULL; + } + old_bitmap = self->selected_bitmap; + old_pbmp = DC_SelectObject(self->pdctxt, newbmp->pbmp); + if (!old_bitmap) + { + old_bitmap = Epython_wrap_bitmap(old_pbmp); + if (!old_bitmap) + { + DC_SelectObject(self->pdctxt, old_pbmp); + return NULL; + } + else + PY_INCREF(old_bitmap); + } + Py_DECREF(self->selected_bitmap); + self->selected_bitmap = newbmp; + Py_INCREF(self->selected_bitmap); + return old_bitmap; +} + +static PyObject *devctxt_select_object(DevCtxtObject *self, PyObject *args) +{ + PyObject *obj; + PBITMAP old_bitmap; + BitmapObject *old_bmp_object, *new_bmp_object; + + if (!PyArg_ParseTuple(args, "O", &obj)) + return NULL; + if (!obj) + { + PyErr_SetString(PyExc_RuntimeError, "bad object selected"); + return NULL; + } + 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."}, @@ -158,6 +200,8 @@ static PyMethodDef DevCtxtMethods[] = { "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, @@ -165,7 +209,6 @@ static PyMethodDef DevCtxtMethods[] = { {NULL, NULL, 0, NULL} }; - static PyObject *devctxt_get_rop2(DevCtxtObject *self, void *closure) { if (!(self->pdctxt)) diff --git a/src/ep_types.h b/src/ep_types.h new file mode 100755 index 0000000..55d2eae --- /dev/null +++ b/src/ep_types.h @@ -0,0 +1,28 @@ +#ifndef __EP_TYPES_H_INCLUDED +#define __EP_TYPES_H_INCLUDED + +#define PY_SSIZE_T_CLEAN +#include +#include "wintype.h" +#include "gfxtype.h" +#include "gfxobj.h" +#include "devctxt.h" +#include "bitmap.h" + +typedef struct tagBitmapObject { + PyObject_HEAD + PBITMAP pbmp; +} BitmapObject; + +typedef struct tagDevCtxtObject { + PyObject_HEAD + PDCTXT pdctxt; + BitmapObject *selected_bitmap; +} DevCtxtObject; + +extern PyTypeObject DevCtxtType; +extern PyTypeObject BitmapType; + +extern PyObject *Epython_wrap_bitmap(PBITMAP pbmp); + +#endif /* __EP_TYPES_H_INCLUDED */