upiwin/src/ep_devctxt.c

353 lines
9.2 KiB
C
Executable File

#include <string.h>
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#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;
}