diff options
author | inmarket <andrewh@inmarket.com.au> | 2015-01-13 13:50:46 +1000 |
---|---|---|
committer | inmarket <andrewh@inmarket.com.au> | 2015-01-13 13:50:46 +1000 |
commit | ef00cac45de322ba9366731809c680056b5200b1 (patch) | |
tree | 1b9fe655aa6f0142988cf9a1e6e72da9599e00a9 /src/gdisp/gdisp_pixmap.c | |
parent | a22a32e8db12e38e47d9cbd3ec62ddd2eabbe9a5 (diff) | |
download | uGFX-ef00cac45de322ba9366731809c680056b5200b1.tar.gz uGFX-ef00cac45de322ba9366731809c680056b5200b1.tar.bz2 uGFX-ef00cac45de322ba9366731809c680056b5200b1.zip |
Add support and demo for pixmaps (in memory drawing)
Diffstat (limited to 'src/gdisp/gdisp_pixmap.c')
-rw-r--r-- | src/gdisp/gdisp_pixmap.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/gdisp/gdisp_pixmap.c b/src/gdisp/gdisp_pixmap.c new file mode 100644 index 00000000..19757757 --- /dev/null +++ b/src/gdisp/gdisp_pixmap.c @@ -0,0 +1,223 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#include "gfx.h" + +#if GFX_USE_GDISP && GDISP_NEED_PIXMAP + +// We undef everything because the system may think we are in a single controller situation +// but the pixmap supports adds another virtual display +#undef GDISP_HARDWARE_DEINIT +#undef GDISP_HARDWARE_FLUSH +#undef GDISP_HARDWARE_STREAM_WRITE +#undef GDISP_HARDWARE_STREAM_READ +#undef GDISP_HARDWARE_STREAM_POS +#undef GDISP_HARDWARE_DRAWPIXEL +#undef GDISP_HARDWARE_CLEARS +#undef GDISP_HARDWARE_FILLS +#undef GDISP_HARDWARE_BITFILLS +#undef GDISP_HARDWARE_SCROLL +#undef GDISP_HARDWARE_PIXELREAD +#undef GDISP_HARDWARE_CONTROL +#undef GDISP_HARDWARE_QUERY +#undef GDISP_HARDWARE_CLIP +#define GDISP_HARDWARE_DEINIT TRUE +#define GDISP_HARDWARE_DRAWPIXEL TRUE +#define GDISP_HARDWARE_PIXELREAD TRUE +#define GDISP_HARDWARE_CONTROL TRUE +#define IN_PIXMAP_DRIVER TRUE +#define GDISP_DRIVER_VMT GDISPVMT_pixmap + +// This pseudo driver currently only supports unpacked formats with more than 8 bits per pixel +// that is, we only support GRAY_SCALE and PALETTE with 8 bits per pixel or any unpacked TRUE_COLOR format. +#if (GDISP_LLD_PIXELFORMAT & GDISP_COLORSYSTEM_GRAYSCALE) && (GDISP_LLD_PIXELFORMAT & 0xFF) != 8 + #error "GDISP Pixmap: Pixmap's do not currently support the specified GDISP_LLD_PIXELFORMAT" +#endif + +#include "src/gdisp/driver.h" +#include "src/gdriver/sys_defs.h" + +typedef struct pixmap { + #if GDISP_NEED_PIXMAP_IMAGE + uint8_t imghdr[8]; // This field must come just before the data member. + #endif + color_t pixels[1]; // We really want pixels[0] but some compilers don't allow that even though it is C standard. + } pixmap; + +GDisplay *gdispCreatePixmap(coord_t width, coord_t height) { + GDisplay *g; + pixmap *p; + unsigned i; + + // Calculate the size of the display surface in bytes + i = width*height*sizeof(color_t); + if (i < 2*sizeof(coord_t)) + i = 2*sizeof(coord_t); + + // Allocate the pixmap + if (!(p = gfxAlloc(i+sizeof(pixmap)-sizeof(p->pixels)))) + return 0; + + // Fill in the image header (if required) + #if GDISP_NEED_PIXMAP_IMAGE + p->imghdr[0] = 'N'; + p->imghdr[1] = 'I'; + p->imghdr[2] = (uint8_t)(width >> 8); + p->imghdr[3] = (uint8_t)width; + p->imghdr[4] = (uint8_t)(height >> 8); + p->imghdr[5] = (uint8_t)height; + p->imghdr[6] = (uint8_t)(GDISP_PIXELFORMAT >> 8); + p->imghdr[7] = (uint8_t)(GDISP_PIXELFORMAT); + #endif + + // Save the width and height so the driver can retrieve it. + ((coord_t *)p->pixels)[0] = width; + ((coord_t *)p->pixels)[1] = height; + + // Register the driver + g = (GDisplay *)gdriverRegister(&GDISPVMT_pixmap->d, p); + if (!g) + gfxFree(p); + return g; +} + +void gdispDeletePixmap(GDisplay *g) { + if (gvmt(g) != GDISPVMT_pixmap) + return; + gdriverUnRegister(&g->d); +} + +pixel_t *gdispGetPixmapBits(GDisplay *g) { + if (gvmt(g) != GDISPVMT_pixmap) + return 0; + return ((pixmap *)g->priv)->pixels; +} + +#if GDISP_NEED_PIXMAP_IMAGE + void *gdispGetPixmapMemoryImage(GDisplay *g) { + if (gvmt(g) != GDISPVMT_pixmap) + return 0; + return ((pixmap *)g->priv)->imghdr; + } +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { + // The user api function should have already allocated and initialised the pixmap + // structure and put it into the priv member during driver initialisation. + if (!g->priv) + return FALSE; + + // Initialize the GDISP structure + // Width and height were saved into the start of the framebuffer. + g->g.Width = ((coord_t *)((pixmap *)g->priv)->pixels)[0]; + g->g.Height = ((coord_t *)((pixmap *)g->priv)->pixels)[1]; + g->g.Backlight = 100; + g->g.Contrast = 50; + g->g.Orientation = GDISP_ROTATE_0; + g->g.Powermode = powerOn; + g->board = 0; + + return TRUE; +} + +LLDSPEC void gdisp_lld_deinit(GDisplay *g) { + gfxFree(g->priv); +} + +LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { + unsigned pos; + + #if GDISP_NEED_CONTROL + switch(g->g.Orientation) { + case GDISP_ROTATE_0: + default: + pos = g->p.y * g->g.Width + g->p.x; + break; + case GDISP_ROTATE_90: + pos = (g->g.Width-g->p.x-1) * g->g.Height + g->p.y; + break; + case GDISP_ROTATE_180: + pos = (g->g.Height-g->p.y-1) * g->g.Width + g->g.Width-g->p.x-1; + break; + case GDISP_ROTATE_270: + pos = g->p.x * g->g.Height + g->g.Height-g->p.y-1; + break; + } + #else + pos = g->p.y * g->g.Width + g->p.x; + #endif + + ((pixmap *)(g)->priv)->pixels[pos] = g->p.color; +} + +LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { + unsigned pos; + + #if GDISP_NEED_CONTROL + switch(g->g.Orientation) { + case GDISP_ROTATE_0: + default: + pos = g->p.y * g->g.Width + g->p.x; + break; + case GDISP_ROTATE_90: + pos = (g->g.Width-g->p.x-1) * g->g.Height + g->p.y; + break; + case GDISP_ROTATE_180: + pos = (g->g.Height-g->p.y-1) * g->g.Width + g->g.Width-g->p.x-1; + break; + case GDISP_ROTATE_270: + pos = g->p.x * g->g.Height + g->g.Height-g->p.y-1; + break; + } + #else + pos = g->p.y * g->g.Width + g->p.x; + #endif + + return ((pixmap *)(g)->priv)->pixels[pos]; +} + +#if GDISP_NEED_CONTROL + LLDSPEC void gdisp_lld_control(GDisplay *g) { + switch(g->p.x) { + case GDISP_CONTROL_ORIENTATION: + if (g->g.Orientation == (orientation_t)g->p.ptr) + return; + switch((orientation_t)g->p.ptr) { + case GDISP_ROTATE_0: + case GDISP_ROTATE_180: + if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) { + coord_t tmp; + + tmp = g->g.Width; + g->g.Width = g->g.Height; + g->g.Height = tmp; + } + break; + case GDISP_ROTATE_90: + case GDISP_ROTATE_270: + if (g->g.Orientation == GDISP_ROTATE_0 || g->g.Orientation == GDISP_ROTATE_180) { + coord_t tmp; + + tmp = g->g.Width; + g->g.Width = g->g.Height; + g->g.Height = tmp; + } + break; + default: + return; + } + g->g.Orientation = (orientation_t)g->p.ptr; + return; + } + } +#endif + +#endif /* GFX_USE_GDISP */ |