work in progress - support for bitmaps and BitBlt
This commit is contained in:
parent
59c8dcc638
commit
b390886277
|
@ -3,7 +3,7 @@ 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 fbprimitive.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 \
|
||||
|
|
25
src/bitmap.c
Executable file
25
src/bitmap.c
Executable file
|
@ -0,0 +1,25 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bitmap.h"
|
||||
|
||||
PBITMAP BMP_Create(INT32 width, INT32 height, const VOID *bits)
|
||||
{
|
||||
PBITMAP rc;
|
||||
UINT32 tot_size = sizeof(BITMAP) + (width * height * sizeof(UINT16));
|
||||
|
||||
rc = (PBITMAP)malloc(tot_size);
|
||||
if (!rc)
|
||||
return NULL;
|
||||
memset(rc, 0, tot_size);
|
||||
_Go_init(&(rc->hdr), BMP_SIG_WORD, tot_size);
|
||||
rc->width = width;
|
||||
rc->height = height;
|
||||
if (bits)
|
||||
memcpy(rc->bits, bits, width * height * sizeof(UINT16));
|
||||
return rc;
|
||||
}
|
||||
|
||||
void BMP_Delete(PBITMAP pbmp)
|
||||
{
|
||||
Go_release(&(pbmp->hdr));
|
||||
}
|
19
src/bitmap.h
Executable file
19
src/bitmap.h
Executable file
|
@ -0,0 +1,19 @@
|
|||
#ifndef __BITMAP_H_INCLUDED
|
||||
#define __BITMAP_H_INCLUDED
|
||||
|
||||
#include "wintype.h"
|
||||
#include "gfxobj.h"
|
||||
|
||||
#define BMP_SIG_WORD 0x706D4221 /* !Bmp */
|
||||
|
||||
typedef struct tagBITMAP {
|
||||
GFXOBJECT hdr;
|
||||
INT32 width;
|
||||
INT32 height;
|
||||
UINT16 bits[0];
|
||||
} BITMAP, *PBITMAP;
|
||||
|
||||
extern PBITMAP BMP_Create(INT32 width, INT32 height, const VOID *bits);
|
||||
extern void BMP_Delete(PBITMAP pbmp);
|
||||
|
||||
#endif /* __BITMAP_H_INCLUDED */
|
104
src/dc_screen.c
104
src/dc_screen.c
|
@ -3,6 +3,7 @@
|
|||
#include "fbinit.h"
|
||||
#include "devctxt.h"
|
||||
#include "dc_screen.h"
|
||||
#include "bitmap.h"
|
||||
|
||||
inline static PUINT16 loc_from_coords(PSCREENPRIVDATA priv, INT32 x, INT32 y)
|
||||
{
|
||||
|
@ -151,9 +152,97 @@ static BOOL screen_line(PVOID privdata, INT32 x1, INT32 y1, INT32 x2, INT32 y2,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL screen_solid_rect(PVOID privdata, PRECT rect, COLORREF color, INT32 op)
|
||||
{
|
||||
PSCREENPRIVDATA priv = (PSCREENPRIVDATA)privdata;
|
||||
UINT16 pencolor = native_from_COLORREF(color);
|
||||
PUINT16 ps, p;
|
||||
int y, x;
|
||||
|
||||
ps = loc_from_coords(rect->left, rect->top);
|
||||
for (y = rect->top; y < rect->bottom; y++)
|
||||
{
|
||||
p = ps;
|
||||
for (x = rect->left; x < rect->right; x++)
|
||||
{
|
||||
*p = apply_rop2(op, *p, pencolor);
|
||||
++p;
|
||||
}
|
||||
ps += priv->pix_per_row;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static PDCTXT screen_create_compat(PVOID privdata)
|
||||
{
|
||||
PSCREENPRIVDATA priv_new;
|
||||
PBITMAP pbmp;
|
||||
|
||||
pbmp = BMP_Create(1, 1, NULL);
|
||||
if (!pbmp)
|
||||
return NULL;
|
||||
priv_new = (PSCREENPRIVDATA)malloc(sizeof(SCREENPRIVDATA));
|
||||
if (!priv_new)
|
||||
{
|
||||
Go_release(&(pbmp->hdr));
|
||||
return NULL;
|
||||
}
|
||||
priv_new->pix_per_row = pbmp->width;
|
||||
priv_new->pdata = pbmp->bits;
|
||||
|
||||
rc = _DC_Allocate(&screen_funtable, priv_new);
|
||||
if (rc)
|
||||
{
|
||||
rc->hdr.dtor = screen_context_destroy;
|
||||
rc->flags = DCFLG_IS_MEMORY;
|
||||
rc->baserect.left = rc->baserect.top = 0;
|
||||
rc->baserect.right = pbmp->width;
|
||||
rc->baserect.bottom = pbmp->height;
|
||||
memcpy(&(rc->cliprect), &(rc->baserect), sizeof(RECT));
|
||||
rc->cur_bitmap = pbmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(priv);
|
||||
Go_release(&(pbmp->hdr));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL screen_new_bitmap(PVOID privdata, PBITMAP pbmp)
|
||||
{
|
||||
PSCREENPRIVDATA priv = (PSCREENPRIVDATA)privdata;
|
||||
priv->pix_per_row = pbmp->width;
|
||||
priv->pdata = pbmp->bits;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL screen_bitblt(PVOID p_dest, PRECT r_dest, PVOID p_src, PRECT r_src, UINT32 op)
|
||||
{
|
||||
PSCREENPRIVDATA dest = (PSCREENPRIVDATA)p_dest;
|
||||
PSCREENPRIVDATA src = (PSCREENPRIVDATA)p_src;
|
||||
PUINT16 pd, ps;
|
||||
INT32 width, i;
|
||||
|
||||
pd = loc_from_coords(dest, r_dest->left, r_dest->top);
|
||||
ps = loc_from_coords(src, r_src->left, r_src->top);
|
||||
width = r_src->right - r_src->left;
|
||||
for (i = r_src->top; i < r_src->bottom; ++i)
|
||||
{
|
||||
memcpy(pd, ps, width * sizeof(UINT16));
|
||||
pd += dest->pix_per_row;
|
||||
ps += src->pix_per_row;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const DCFUNTABLE screen_funtable = {
|
||||
screen_set_pixel,
|
||||
screen_line
|
||||
screen_line,
|
||||
screen_solid_rect,
|
||||
screen_create_compat,
|
||||
screen_new_bitmap,
|
||||
screen_bitblt
|
||||
};
|
||||
|
||||
static void screen_context_destroy(PVOID obj)
|
||||
|
@ -178,11 +267,18 @@ PDCTXT DC_CreateScreenContext(void)
|
|||
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;
|
||||
rc->flags = DCFLG_IS_SCREEN;
|
||||
rc->baserect.left = rc->baserect.top = 0;
|
||||
rc->baserect.right = Fb_Info->width;
|
||||
rc->baserect.bottom = Fb_Info->height;
|
||||
memcpy(&(rc->cliprect), &(rc->baserect), sizeof(RECT));
|
||||
}
|
||||
else
|
||||
free(priv);
|
||||
return rc;
|
||||
}
|
||||
|
||||
PDCTXT _DC_CreateScreenCompatibleContext(void)
|
||||
{
|
||||
return screen_create_compat(NULL);
|
||||
}
|
||||
|
|
|
@ -10,5 +10,6 @@ typedef struct tagSCREENPRIVDATA {
|
|||
} SCREENPRIVDATA, *PSCREENPRIVDATA;
|
||||
|
||||
extern PDCTXT DC_CreateScreenContext(void);
|
||||
extern PDCTXT _DC_CreateScreenCompatibleContext(void);
|
||||
|
||||
#endif /* __DC_SCREEN_H_INCLUDED */
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "gfxtype.h"
|
||||
#include "gfxobj.h"
|
||||
#include "devctxt.h"
|
||||
#include "bitmap.h"
|
||||
#include "dc_screen.h"
|
||||
|
||||
inline static BYTE line_clip_outcode(INT32 x, INT32 y, INT32 xmin, INT32 ymin, INT32 xmax, INT32 ymax)
|
||||
{
|
||||
|
@ -124,7 +126,8 @@ PDCTXT _DC_Allocate(PDCFUNTABLE funcs, PVOID privdata)
|
|||
|
||||
void _DC_FinalizeCommon(PDCTXT pdctxt)
|
||||
{
|
||||
/* nothing here yet */
|
||||
if (pdctxt->cur_bitmap)
|
||||
Go_release(&(pdctxt->cur_bitmap->hdr));
|
||||
}
|
||||
|
||||
COLORREF DC_SetPixel(PDCTXT pdctxt, INT32 x, INT32 y, COLORREF color)
|
||||
|
@ -163,6 +166,15 @@ BOOL DC_Rectangle(PDCTXT pdctxt, INT32 left, INT32 top, INT32 right, INT32 botto
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DC_SolidRectangle(PDCTXT pdctxt, INT32 left, INT32 top, INT32 right, INT32 bottom)
|
||||
{
|
||||
RECT rect, actual;
|
||||
G_set_rect(&rect, left, top, right, bottom);
|
||||
if (!G_intersect_rect(&actual, &rect, &(pdctxt->cliprect)))
|
||||
return TRUE;
|
||||
return (*(pdctxt->funcs-solid_rect))(pdctxt->privdata, &actual, pdctxt->color, pdctxt->rop2);
|
||||
}
|
||||
|
||||
UINT32 DC_GetROP2(PDCTXT pdctxt)
|
||||
{
|
||||
return pdctxt->rop2;
|
||||
|
@ -198,3 +210,50 @@ BOOL DC_SetClipRect(PDCTXT pdctxt, PRECT prect)
|
|||
memcpy(&(pdctxt->cliprect), prect, sizeof(RECT));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PDCTXT DC_CreateCompatible(PDCTXT pdctxt)
|
||||
{
|
||||
if (pdctxt)
|
||||
return (*(pdctxt->funcs->create_compat))(pdctxt->privdata);
|
||||
return _DC_CreateScreenCompatibleContext();
|
||||
}
|
||||
|
||||
PGFXOBJECT DC_SelectObject(PDCTXT pdctxt, PGFXOBJECT pobj)
|
||||
{
|
||||
if (pobj->sig == BMP_SIG_WORD)
|
||||
{
|
||||
if ((pdctxt->flags & DCFLG_TYPES) == DCFLG_IS_MEMORY)
|
||||
{
|
||||
RECT rtmp;
|
||||
PBITMAP rbmp = pdctxt->cur_bitmap;
|
||||
Go_addref(pobj);
|
||||
if ((*(pdctxt->funcs->new_bitmap))(pdctxt->privdata, (PBITMAP)pobj))
|
||||
{
|
||||
pdctxt->cur_bitmap = (PBITMAP)pobj;
|
||||
pdctxt->baserect.left = pdctxt->baserect.top = 0;
|
||||
pdctxt->baserect.right = ((PBITMAP)pobj)->width;
|
||||
pdctxt->baserect.bottom = ((PBITMAP)pobj)->height;
|
||||
G_intersect_rect(&rtmp, &(pdctxt->baserect), &(pdctxt->cliprect));
|
||||
memcpy(&(pdctxt->cliprect), &rtmp, sizeof(RECT));
|
||||
return rbmp;
|
||||
}
|
||||
Go_release(pobj);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL DC_BitBlt(PDCTXT dest, INT32 x, INT32 y, INT32 width, INT32 height, PDCTXT source, INT32 x1, INT32 y1, UINT32 rop)
|
||||
{
|
||||
RECT destrect, actualdest, srcrect, actualsrc;
|
||||
|
||||
G_set_rect(&destrect, x, y, x + width, y + height);
|
||||
if (!G_rect_intersect(&actualdest, &destrect, &(dest->cliprect)))
|
||||
return TRUE; /* no-op */
|
||||
G_set_rect(&srcrect, x1, y1, x1 + (actualdest.right - actualdest.left), y1 + (actualdest.bottom - actualdest.top));
|
||||
if (!G_rect_intersect(&actualsrc, &srcrect, &(src->baserect)))
|
||||
return TRUE;
|
||||
actualdest.right = actualdest.left + (actualsrc.right - actualsrc.left);
|
||||
actualdest.bottom = actualdest.top + (actualsrc.bottom - actualsrc.top);
|
||||
return (*(dest->funcs->bitblt))(dest->privdata, &actualdest, src->privdata, &actualsrc, rop);
|
||||
}
|
||||
|
|
|
@ -27,10 +27,18 @@
|
|||
|
||||
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 BOOL (*DCtx_SolidRect)(PVOID privdata, PRECT rect, COLORREF color, INT32 op);
|
||||
typedef PDCTXT (*DCtx_CreateCompat)(PVOID privdata);
|
||||
typedef BOOL (*DCtx_NewBitmap)(PVOID privdata, PBITMAP pbmp);
|
||||
typedef BOOL (*DCtx_BitBlt)(PVOID p_dest, PRECT r_dest, PVOID p_src, PRECT r_src, UINT32 op);
|
||||
|
||||
typedef struct tagDCFUNTABLE {
|
||||
DCtx_SetPixel set_pixel; /* sets a single pixel on the display */
|
||||
DCtx_Line line; /* draws a line on the display */
|
||||
DCtx_SetPixel set_pixel; /* sets a single pixel on the display */
|
||||
DCtx_Line line; /* draws a line on the display */
|
||||
DCtx_SolidRect solid_rect; /* draws a solid rectangle on the display */
|
||||
DCtx_CreateCompat create_compat; /* create a memory DC compatible with this one */
|
||||
DCtx_NewBitmap new_bitmap; /* new bitmap selected notification */
|
||||
DCtx_BitBlt bitblt; /* bit block transfer */
|
||||
} DCFUNTABLE;
|
||||
|
||||
typedef const DCFUNTABLE *PDCFUNTABLE;
|
||||
|
@ -39,12 +47,19 @@ typedef struct tagDCTXT {
|
|||
GFXOBJECT hdr; /* the header of all objects */
|
||||
PDCFUNTABLE funcs; /* device context functions */
|
||||
PVOID privdata; /* private data for the type of DC */
|
||||
UINT32 flags; /* flags for the DC */
|
||||
RECT baserect; /* base rectangle */
|
||||
RECT cliprect; /* clipping rectangle */
|
||||
POINT pos; /* current position */
|
||||
UINT32 rop2; /* current raster operation */
|
||||
COLORREF color; /* current drawing color (XXX replace with pens later) */
|
||||
PBITMAP cur_bitmap; /* current selected bitmap */
|
||||
} DCTXT, *PDCTXT;
|
||||
|
||||
#define DCFLG_TYPES 0x03
|
||||
#define DCFLG_IS_SCREEN 0x00
|
||||
#define DCFLG_IS_MEMORY 0x01
|
||||
|
||||
extern PDCTXT _DC_Allocate(PDCFUNTABLE funcs, PVOID privdata);
|
||||
extern void _DC_FinalizeCommon(PDCTXT pdctxt);
|
||||
|
||||
|
@ -52,12 +67,16 @@ 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 BOOL DC_SolidRectangle(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);
|
||||
extern PDCTXT DC_CreateCompatible(PDCTXT pdctxt);
|
||||
extern PGFXOBJECT DC_SelectObject(PDCTXT pdctxt, PGFXOBJECT pobj);
|
||||
extern BOOL DC_BitBlt(PDCTXT dest, INT32 x, INT32 y, INT32 width, INT32 height, PDCTXT source, INT32 x1, INT32 y1, UINT32 rop);
|
||||
|
||||
#define DC_addref(pdctxt) Go_addref(&(pdctxt->hdr))
|
||||
#define DC_release(pdctxt) Go_release(&(pdctxt->hdr))
|
||||
|
|
|
@ -13,6 +13,8 @@ typedef struct tagDevCtxtObject {
|
|||
PDCTXT pdctxt;
|
||||
} DevCtxtObject;
|
||||
|
||||
PyTypeObject DevCtxtType; /* forward declaration */
|
||||
|
||||
static PyObject *devctxt_set_pixel(DevCtxtObject *self, PyObject *args)
|
||||
{
|
||||
INT32 x, y;
|
||||
|
@ -77,6 +79,41 @@ static PyObject *devctxt_rectangle(DevCtxtObject *self, PyObject *args)
|
|||
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;
|
||||
|
@ -117,6 +154,10 @@ static PyMethodDef DevCtxtMethods[] = {
|
|||
"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."},
|
||||
{"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,
|
||||
|
@ -218,6 +259,15 @@ static int devctxt_init(DevCtxtObject *self, PyObject *args, PyObject *kwds)
|
|||
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);
|
||||
|
@ -226,7 +276,7 @@ static int devctxt_init(DevCtxtObject *self, PyObject *args, PyObject *kwds)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static PyTypeObject DevCtxtType = {
|
||||
PyTypeObject DevCtxtType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
.tp_name = "upiwin.DevCtxt",
|
||||
.tp_doc = "Device context object",
|
||||
|
|
Loading…
Reference in New Issue
Block a user