first pass at the device-independent drawing system, including the Python
representation of a device context
This commit is contained in:
parent
ee292d3aab
commit
c3b3e0a350
|
@ -2,7 +2,7 @@ BUILDUTILS=../buildutils
|
||||||
RESOURCES=../resources
|
RESOURCES=../resources
|
||||||
SPLASHSCREEN=splash-vmwcblk.png
|
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 \
|
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
|
log.o gpio.o msg_queue.o time_func.o config.o splash.o
|
||||||
LIBS=-lpython3.7m -lcrypt -lfreetype -lbcm2835 -lpthread -ldl -lutil -lm
|
LIBS=-lpython3.7m -lcrypt -lfreetype -lbcm2835 -lpthread -ldl -lutil -lm
|
||||||
|
|
170
src/dc_screen.c
170
src/dc_screen.c
|
@ -1,5 +1,175 @@
|
||||||
|
#include "fbinit.h"
|
||||||
|
#include "devctxt.h"
|
||||||
#include "dc_screen.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)
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,4 +9,6 @@ typedef struct tagSCREENPRIVDATA {
|
||||||
UINT16 *pdata;
|
UINT16 *pdata;
|
||||||
} SCREENPRIVDATA, *PSCREENPRIVDATA;
|
} SCREENPRIVDATA, *PSCREENPRIVDATA;
|
||||||
|
|
||||||
|
extern PDCTXT DC_CreateScreenContext(void);
|
||||||
|
|
||||||
#endif /* __DC_SCREEN_H_INCLUDED */
|
#endif /* __DC_SCREEN_H_INCLUDED */
|
||||||
|
|
162
src/devctxt.c
162
src/devctxt.c
|
@ -1,9 +1,171 @@
|
||||||
|
#include <string.h>
|
||||||
#include "gfxtype.h"
|
#include "gfxtype.h"
|
||||||
|
#include "gfxobj.h"
|
||||||
#include "devctxt.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)
|
COLORREF DC_SetPixel(PDCTXT pdctxt, INT32 x, INT32 y, COLORREF color)
|
||||||
{
|
{
|
||||||
if (!G_coords_in_rect(&(pdctxt->cliprect), x, y))
|
if (!G_coords_in_rect(&(pdctxt->cliprect), x, y))
|
||||||
return (COLORREF)(-1);
|
return (COLORREF)(-1);
|
||||||
return (*(pdctxt->funcs->set_pixel))(pdctxt->privdata, xm, y, colorref, pdctxt->rop2);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -26,9 +26,11 @@
|
||||||
#define R2_WHITE 16
|
#define R2_WHITE 16
|
||||||
|
|
||||||
typedef COLORREF (*DCtx_SetPixel)(PVOID privdata, INT32 x, INT32 y, COLORREF color, INT32 op);
|
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 {
|
typedef struct tagDCFUNTABLE {
|
||||||
DCtx_SetPixel set_pixel; /* sets a single pixel on the display */
|
DCtx_SetPixel set_pixel; /* sets a single pixel on the display */
|
||||||
|
DCtx_Line line; /* draws a line on the display */
|
||||||
} DCFUNTABLE;
|
} DCFUNTABLE;
|
||||||
|
|
||||||
typedef const DCFUNTABLE *PDCFUNTABLE;
|
typedef const DCFUNTABLE *PDCFUNTABLE;
|
||||||
|
@ -43,6 +45,21 @@ typedef struct tagDCTXT {
|
||||||
COLORREF color; /* current drawing color (XXX replace with pens later) */
|
COLORREF color; /* current drawing color (XXX replace with pens later) */
|
||||||
} DCTXT, *PDCTXT;
|
} 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 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 */
|
#endif /* __DEVCTXT_H_INCLUDED */
|
||||||
|
|
253
src/ep_devctxt.c
Executable file
253
src/ep_devctxt.c
Executable file
|
@ -0,0 +1,253 @@
|
||||||
|
#include <string.h>
|
||||||
|
#define PY_SSIZE_T_CLEAN
|
||||||
|
#include <Python.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -14,6 +14,8 @@ extern PyObject *UPIWIN_tmp_module;
|
||||||
extern PyObject *Epython_init_upiwin_module(void);
|
extern PyObject *Epython_init_upiwin_module(void);
|
||||||
extern PyObject *Epython_init_upiwin_tmp_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_setup(void);
|
||||||
extern HRESULT Epython_run(void);
|
extern HRESULT Epython_run(void);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "ep_init.h"
|
#include "ep_init.h"
|
||||||
#include "ep_upiwin.h"
|
#include "ep_upiwin.h"
|
||||||
#include "ep_util.h"
|
#include "ep_util.h"
|
||||||
|
#include "devctxt.h"
|
||||||
|
|
||||||
static PyMethodDef UPIWINMethods[] = {
|
static PyMethodDef UPIWINMethods[] = {
|
||||||
/* Backlight control functions */
|
/* Backlight control functions */
|
||||||
|
@ -46,6 +47,23 @@ BEGIN_CONSTANT_TABLE(UPIWINConstants)
|
||||||
CONSTANT_INT_MACRO(WM_TOUCHDOWN)
|
CONSTANT_INT_MACRO(WM_TOUCHDOWN)
|
||||||
CONSTANT_INT_MACRO(WM_TOUCHMOVE)
|
CONSTANT_INT_MACRO(WM_TOUCHMOVE)
|
||||||
CONSTANT_INT_MACRO(WM_TOUCHUP)
|
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
|
END_CONSTANT_TABLE
|
||||||
|
|
||||||
PyObject *Epython_init_upiwin_module(void)
|
PyObject *Epython_init_upiwin_module(void)
|
||||||
|
@ -63,6 +81,12 @@ PyObject *Epython_init_upiwin_module(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FAILED(Epython_register_devctxt(module)))
|
||||||
|
{
|
||||||
|
Py_DECREF(module);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* set up the module state */
|
/* set up the module state */
|
||||||
pstate = (PUPIWIN_STATE)PyModule_GetState(module);
|
pstate = (PUPIWIN_STATE)PyModule_GetState(module);
|
||||||
pstate->backlight_on = TRUE;
|
pstate->backlight_on = TRUE;
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "gfxobj.h"
|
#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)
|
void Go_unchain(PGFXOBJECT obj)
|
||||||
{
|
{
|
||||||
if (!(obj->next || obj->prev))
|
if (!(obj->next || obj->prev))
|
||||||
|
|
|
@ -16,6 +16,7 @@ typedef struct tagGFXOBJECT {
|
||||||
struct tagGFXOBJECT *prev;
|
struct tagGFXOBJECT *prev;
|
||||||
} GFXOBJECT, *PGFXOBJECT;
|
} GFXOBJECT, *PGFXOBJECT;
|
||||||
|
|
||||||
|
extern void _Go_init(PGFXOBJECT obj, UINT32 sig, UINT32 size);
|
||||||
extern void Go_unchain(PGFXOBJECT obj);
|
extern void Go_unchain(PGFXOBJECT obj);
|
||||||
extern INT32 Go_addref(PGFXOBJECT obj);
|
extern INT32 Go_addref(PGFXOBJECT obj);
|
||||||
extern INT32 Go_release(PGFXOBJECT obj);
|
extern INT32 Go_release(PGFXOBJECT obj);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user