diff options
40 files changed, 1960 insertions, 1595 deletions
diff --git a/boards/base/Linux-Framebuffer/board_framebuffer.h b/boards/base/Linux-Framebuffer/board_framebuffer.h index e1836527..9b760e08 100644 --- a/boards/base/Linux-Framebuffer/board_framebuffer.h +++ b/boards/base/Linux-Framebuffer/board_framebuffer.h @@ -123,7 +123,7 @@ } if (fb_var.red.offset != LLDCOLOR_SHIFT_R || fb_var.green.offset != LLDCOLOR_SHIFT_G || fb_var.blue.offset != LLDCOLOR_SHIFT_B) { #if LLDCOLOR_SHIFT_B == 0 - fprintf(stderr, "GDISP Framebuffer: THe display pixel format is not RGB\n"); + fprintf(stderr, "GDISP Framebuffer: The display pixel format is not RGB\n"); #else fprintf(stderr, "GDISP Framebuffer: The display pixel format is not BGR\n"); #endif diff --git a/boards/base/RaspberryPi/readme.txt b/boards/base/RaspberryPi/readme.txt index d4a59bf2..6ff2246f 100644 --- a/boards/base/RaspberryPi/readme.txt +++ b/boards/base/RaspberryPi/readme.txt @@ -1,15 +1,20 @@ -This directory contains the interface for the Raspberry Pi framebuffer. +This directory contains the interface for the Raspberry Pi direct hardware framebuffer. This talks directly to the raspberry pi hardware (not via a linux framebuffer driver). +If you are using linux on the Pi then consider using the linux-X or the linux-Framebuffer +board definitions instead of this one. This is really designed for non-Linux platforms +or where there is no linux display driver available. It will still work under linux but +the other solutions might be better. + This graphics interface is software driven - it is not an accelerated interface. -This board definition should work on any operating system that will work on the Raspberry Pi - eg. Linux, FreeRTOS. +The board definition should work on any operating system that will work on the Raspberry Pi + eg. Linux, FreeRTOS, FreeBSD. On this board uGFX currently supports: - GDISP via the framebuffer driver -THe following variables may optionally be defined in your gfxconf.h or your makefile... +The following variables may optionally be defined in your gfxconf.h or your makefile... - GDISP_LLD_PIXELFORMAT default = GDISP_PIXELFORMAT_RGB565 - GDISP_SCREEN_WIDTH default = 800 - GDISP_SCREEN_HEIGHT default = 600 diff --git a/demos/modules/gdisp/images/gfxconf.h b/demos/modules/gdisp/images/gfxconf.h index 4ef9ab9e..55420275 100644 --- a/demos/modules/gdisp/images/gfxconf.h +++ b/demos/modules/gdisp/images/gfxconf.h @@ -43,17 +43,18 @@ #define GDISP_NEED_VALIDATION TRUE #define GDISP_NEED_CLIP TRUE #define GDISP_NEED_IMAGE TRUE +#define GDISP_STARTUP_COLOR HTML2COLOR(0xC0C0C0) /* GDISP image decoders */ -#define GDISP_NEED_IMAGE_NATIVE FALSE -#define GDISP_NEED_IMAGE_GIF FALSE +//#define GDISP_NEED_IMAGE_NATIVE TRUE +//#define GDISP_NEED_IMAGE_GIF TRUE #define GDISP_NEED_IMAGE_BMP TRUE -#define GDISP_NEED_IMAGE_JPG FALSE -#define GDISP_NEED_IMAGE_PNG FALSE +//#define GDISP_NEED_IMAGE_JPG TRUE +//#define GDISP_NEED_IMAGE_PNG TRUE #define GFX_USE_GFILE TRUE #define GFILE_NEED_ROMFS TRUE -//#define GFILE_NEED_NATIVEFS TRUE +//#define GFILE_NEED_NATIVEFS TRUE #endif /* _GFXCONF_H */ diff --git a/demos/modules/gwin/graph/gfxconf.h b/demos/modules/gwin/graph/gfxconf.h index bc65beea..b3b089ae 100644 --- a/demos/modules/gwin/graph/gfxconf.h +++ b/demos/modules/gwin/graph/gfxconf.h @@ -44,6 +44,7 @@ /* Features for the GDISP sub-system. */ #define GDISP_NEED_VALIDATION TRUE #define GDISP_NEED_CLIP TRUE +#define GDISP_NEED_MULTITHREAD TRUE /* Features for the GWIN subsystem. */ #define GWIN_NEED_WINDOWMANAGER TRUE diff --git a/docs/releases.txt b/docs/releases.txt index 5f0b693b..ee0fed1f 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -10,6 +10,8 @@ FEATURE: Added Altera-MAX10-NEEK board support FIX: Vastly improving keyboard widget default rendering FEATURE: Added ILI9342 driver FIX: Fixing issues where wrong 'progress' color from widget style palette was used +FEATURE: Added GWIN_FRAME_KEEPONCLOSE flag to prevent destruction of a frame on close +FEATURE: Added support for PNG images *** Release 2.4 *** diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_board_example.h b/drivers/gdisp/ED060SC4/board_ED060SC4_example.h index 6cda606b..6cda606b 100644 --- a/drivers/gdisp/ED060SC4/gdisp_lld_board_example.h +++ b/drivers/gdisp/ED060SC4/board_ED060SC4_example.h diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_board_template.h b/drivers/gdisp/ED060SC4/gdisp_lld_board_template.h deleted file mode 100644 index a45cc208..00000000 --- a/drivers/gdisp/ED060SC4/gdisp_lld_board_template.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 - */ - -/* Board interface definitions for ED060SC4 PrimeView E-ink panel. - * - * You should implement the following functions to define the interface to - * the panel on your board. - */ - -#ifndef _GDISP_LLD_BOARD_H -#define _GDISP_LLD_BOARD_H - -/* Set up IO pins for the panel connection. */ -static GFXINLINE void init_board(void) { - #error Unimplemented -} - -/* Delay for display waveforms. Should be an accurate microsecond delay. */ -static void eink_delay(int us) -{ - #error Unimplemented -} - -/* Turn the E-ink panel Vdd supply (+3.3V) on or off. */ -static GFXINLINE void setpower_vdd(bool_t on) { - #error Unimplemented -} - -/* Turn the E-ink panel negative supplies (-15V, -20V) on or off. */ -static GFXINLINE void setpower_vneg(bool_t on) { - #error Unimplemented -} - -/* Turn the E-ink panel positive supplies (-15V, -20V) on or off. */ -static GFXINLINE void setpower_vpos(bool_t on) { - #error Unimplemented -} - -/* Set the state of the LE (source driver Latch Enable) pin. */ -static GFXINLINE void setpin_le(bool_t on) { - #error Unimplemented -} - -/* Set the state of the OE (source driver Output Enable) pin. */ -static GFXINLINE void setpin_oe(bool_t on) { - #error Unimplemented -} - -/* Set the state of the CL (source driver Clock) pin. */ -static GFXINLINE void setpin_cl(bool_t on) { - #error Unimplemented -} - -/* Set the state of the SPH (source driver Start Pulse Horizontal) pin. */ -static GFXINLINE void setpin_sph(bool_t on) { - #error Unimplemented -} - -/* Set the state of the D0-D7 (source driver Data) pins. */ -static GFXINLINE void setpins_data(uint8_t value) { - #error Unimplemented -} - -/* Set the state of the CKV (gate driver Clock Vertical) pin. */ -static GFXINLINE void setpin_ckv(bool_t on) { - #error Unimplemented -} - -/* Set the state of the GMODE (gate driver Gate Mode) pin. */ -static GFXINLINE void setpin_gmode(bool_t on) { - #error Unimplemented -} - -/* Set the state of the SPV (gate driver Start Pulse Vertical) pin. */ -static GFXINLINE void setpin_spv(bool_t on) { - #error Unimplemented -} - -#endif diff --git a/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c b/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c index 9d1aafa0..4aa16eff 100644 --- a/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c +++ b/drivers/gdisp/STM32LTDC/gdisp_lld_STM32LTDC.c @@ -380,7 +380,7 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) { #if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 DMA2D->OPFCCR = OPFCCR_RGB565; #elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888 - DMA2D->OPFCCR = OPFCCR_OPFCCR_RGB888; + DMA2D->OPFCCR = OPFCCR_RGB888; #endif // Foreground color format diff --git a/gfxconf.example.h b/gfxconf.example.h index df22e86f..37094a62 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -107,16 +107,31 @@ // #define GDISP_NEED_IMAGE_NATIVE FALSE // #define GDISP_NEED_IMAGE_GIF FALSE // #define GDISP_NEED_IMAGE_BMP FALSE -// #define GDISP_NEED_IMAGE_BMP_1 FALSE -// #define GDISP_NEED_IMAGE_BMP_4 FALSE -// #define GDISP_NEED_IMAGE_BMP_4_RLE FALSE -// #define GDISP_NEED_IMAGE_BMP_8 FALSE -// #define GDISP_NEED_IMAGE_BMP_8_RLE FALSE -// #define GDISP_NEED_IMAGE_BMP_16 FALSE -// #define GDISP_NEED_IMAGE_BMP_24 FALSE -// #define GDISP_NEED_IMAGE_BMP_32 FALSE +// #define GDISP_NEED_IMAGE_BMP_1 TRUE +// #define GDISP_NEED_IMAGE_BMP_4 TRUE +// #define GDISP_NEED_IMAGE_BMP_4_RLE TRUE +// #define GDISP_NEED_IMAGE_BMP_8 TRUE +// #define GDISP_NEED_IMAGE_BMP_8_RLE TRUE +// #define GDISP_NEED_IMAGE_BMP_16 TRUE +// #define GDISP_NEED_IMAGE_BMP_24 TRUE +// #define GDISP_NEED_IMAGE_BMP_32 TRUE // #define GDISP_NEED_IMAGE_JPG FALSE // #define GDISP_NEED_IMAGE_PNG FALSE +// #define GDISP_NEED_IMAGE_PNG_INTERLACED FALSE +// #define GDISP_NEED_IMAGE_PNG_TRANSPARENCY TRUE +// #define GDISP_NEED_IMAGE_PNG_BACKGROUND TRUE +// #define GDISP_NEED_IMAGE_PNG_ALPHACLIFF 32 +// #define GDISP_NEED_IMAGE_PNG_PALETTE_124 TRUE +// #define GDISP_NEED_IMAGE_PNG_PALETTE_8 TRUE +// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 TRUE +// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 TRUE +// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 TRUE +// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 TRUE +// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 TRUE +// #define GDISP_NEED_IMAGE_PNG_RGB_8 TRUE +// #define GDISP_NEED_IMAGE_PNG_RGB_16 TRUE +// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_8 TRUE +// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_16 TRUE // #define GDISP_NEED_IMAGE_ACCOUNTING FALSE //#define GDISP_NEED_PIXMAP FALSE diff --git a/src/gdisp/gdisp_image.c b/src/gdisp/gdisp_image.c index 853d2f75..356ba64f 100644 --- a/src/gdisp/gdisp_image.c +++ b/src/gdisp/gdisp_image.c @@ -154,6 +154,16 @@ gdispImageError gdispImageCache(gdispImage *img) { gdispImageError gdispGImageDraw(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT; + + // Check on window + if (cx <= 0 || cy <= 0) return GDISP_IMAGE_ERR_OK; + if (sx < 0) sx = 0; + if (sy < 0) sy = 0; + if (sx >= img->width || sy >= img->height) return GDISP_IMAGE_ERR_OK; + if (sx + cx > img->width) cx = img->width - sx; + if (sy + cy > img->height) cy = img->height - sy; + + // Draw return img->fns->draw(g, img, x, y, cx, cy, sx, sy); } diff --git a/src/gdisp/gdisp_image_png.c b/src/gdisp/gdisp_image_png.c index 9a3e3cf0..8b2bfb04 100644 --- a/src/gdisp/gdisp_image_png.c +++ b/src/gdisp/gdisp_image_png.c @@ -11,6 +11,1636 @@ #include "gdisp_image_support.h" -#error "PNG support not implemented yet" +/** + * How big a pixel array to allocate for blitting the image to the display (in pixels) + * Bigger is faster but uses more RAM. + */ +#define PNG_BLIT_BUFFER_SIZE 32 +/** + * How big a byte array to use for input file buffer + * Bigger is faster but uses more RAM. + * Must be more than 8 bytes + */ +#define PNG_FILE_BUFFER_SIZE 8 +/** + * How big a byte array to use for inflate decompression + * Bigger is faster but uses more RAM. + * Must be >= 32768 due to the PNG 32K sliding window + * More efficient code is generated if it is a power of 2 + */ +#define PNG_Z_BUFFER_SIZE 32768 + +/*----------------------------------------------------------------- + * Structure definitions + *---------------------------------------------------------------*/ + +struct PNG_decode; + +// PNG info (comes from the PNG header) +typedef struct PNG_info { + uint8_t flags; // Flags (global) + #define PNG_FLG_HEADERDONE 0x01 // The header has been processed + #define PNG_FLG_TRANSPARENT 0x02 // Has transparency + #define PNG_FLG_INTERLACE 0x04 // Is Interlaced + #define PNG_FLG_BACKGROUND 0x08 // Has a specified background color + uint8_t bitdepth; // 1, 2, 4, 8, 16 + uint8_t mode; // The PNG color-mode + #define PNG_COLORMODE_GRAY 0x00 // Grayscale + #define PNG_COLORMODE_RGB 0x02 // RGB + #define PNG_COLORMODE_PALETTE 0x03 // Pallete + #define PNG_COLORMODE_GRAYALPHA 0x04 // Grayscale with Alpha + #define PNG_COLORMODE_RGBA 0x06 // RGBA + uint8_t bpp; // Bits per pixel + + uint8_t *cache; // The image cache + unsigned cachesz; // The image cache size + + void (*out)(struct PNG_decode *); // The scan line output function + + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + color_t bg; // The background color + #endif + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + uint16_t trans_r; // Red/grayscale component of the transparent color (PNG_COLORMODE_GRAY and PNG_COLORMODE_RGB only) + uint16_t trans_g; // Green component of the transparent color (PNG_COLORMODE_RGB only) + uint16_t trans_b; // Blue component of the transparent color (PNG_COLORMODE_RGB only) + #endif + #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8 + uint16_t palsize; // palette size in number of colors + uint8_t *palette; // palette in RGBA RGBA... order (4 bytes per entry - PNG_COLORMODE_PALETTE only) + #endif + } PNG_info; + +// Handle the PNG file stream +typedef struct PNG_input { + GFILE * f; // The gfile to retrieve data from + unsigned buflen; // The number of bytes left in the buffer + uint8_t *pbuf; // The pointer to the next byte + uint32_t chunklen; // The number of bytes left in the current PNG chunk + uint32_t chunknext; // The file position of the next PNG chunk + uint8_t buf[PNG_FILE_BUFFER_SIZE]; // Must be a minimum of 8 bytes to hold a chunk header + } PNG_input; + +// Handle the display output and windowing +typedef struct PNG_output { + GDisplay *g; + coord_t x, y; + coord_t cx, cy; + coord_t sx, sy; + coord_t ix, iy; + unsigned cnt; + pixel_t buf[PNG_BLIT_BUFFER_SIZE]; + } PNG_output; + +// Handle the PNG scan line filter +typedef struct PNG_filter { + unsigned scanbytes; + unsigned bytewidth; + uint8_t *line; + uint8_t *prev; + } PNG_filter; + +// Handle the PNG inflate decompression +typedef struct PNG_zTree { + uint16_t table[16]; // Table of code length counts + uint16_t trans[288]; // Code to symbol translation table + } PNG_zTree; + +typedef struct PNG_zinflate { + uint8_t data; // The current input stream data byte + uint8_t bits; // The number of bits left in the data byte + uint8_t flags; // Decompression flags + #define PNG_ZFLG_EOF 0x01 // No more input data + #define PNG_ZFLG_FINAL 0x02 // This is the final block + #define PNG_ZFLG_RESUME_MASK 0x0C // The mask of bits for the resume state + #define PNG_ZFLG_RESUME_NEW 0x00 // Process a new block + #define PNG_ZFLG_RESUME_COPY 0x04 // Resume a byte copy from the input stream (length in tmp) + #define PNG_ZFLG_RESUME_INFLATE 0x08 // Resume using the specified symbol (symbol in tmp[0]) + #define PNG_ZFLG_RESUME_OFFSET 0x0C // Resume a byte offset copy from the buffer (length and offset in tmp) + + unsigned bufpos; // The current buffer output position + unsigned bufend; // The current buffer end position (wraps) + + PNG_zTree ltree; // The dynamic length tree + PNG_zTree dtree; // The dynamic distance tree + uint8_t tmp[288+32]; // Temporary space for decoding dynamic trees and other temporary uses + uint8_t buf[PNG_Z_BUFFER_SIZE]; // The decoding buffer and sliding window + } PNG_zinflate; + +// Put all the decoding structures together. +// Note this is immediately followed by 2 scan lines of uncompressed image data for filtering (dynamic size). +typedef struct PNG_decode { + gdispImage *img; + PNG_info *pinfo; + PNG_input i; + PNG_output o; + PNG_filter f; + PNG_zinflate z; + } PNG_decode; + +/*----------------------------------------------------------------- + * PNG input data stream functions + *---------------------------------------------------------------*/ + +// Input initialization +static void PNG_iInit(PNG_decode *d) { + if (d->pinfo->cache) { + d->i.pbuf = d->pinfo->cache; + d->i.buflen = d->pinfo->cachesz; + d->i.f = 0; + } else { + d->i.buflen = 0; + d->i.chunklen = 0; + d->i.chunknext = 8; + d->i.f = d->img->f; + } +} + +// Load the next byte of image data from the PNG file +static bool_t PNG_iLoadData(PNG_decode *d) { + uint32_t sz; + + // Is there data still left in the buffer? + if (d->i.buflen) + return TRUE; + + // If we are cached then we have no more data + if (!d->i.f) + return FALSE; + + // Have we finished the current chunk? + if (!d->i.chunklen) { + while(1) { + // Find a new chunk + gfileSetPos(d->i.f, d->i.chunknext); + if (gfileRead(d->i.f, d->i.buf, 8) != 8) + return FALSE; + + // Calculate the chunk length and next chunk + d->i.chunklen = gdispImageGetAlignedBE32(d->i.buf, 0); + d->i.chunknext += d->i.chunklen + 12; + + // Process only image data chunks + switch (gdispImageGetAlignedBE32(d->i.buf, 4)) { + case 0x49444154: // "IDAT" - Image Data + if (!d->i.chunklen) + break; + goto gotchunk; + case 0x49454E44: // "IEND" - All done + return FALSE; + } + } + } + +gotchunk: + + // Try to read data some from the chunk + sz = d->i.chunklen; + if (sz > PNG_FILE_BUFFER_SIZE) + sz = PNG_FILE_BUFFER_SIZE; + if (gfileRead(d->i.f, d->i.buf, sz) != sz) + return FALSE; + d->i.chunklen -= sz; + d->i.buflen = sz; + d->i.pbuf = d->i.buf; + return TRUE; +} + +// Get the last loaded byte of image data from the PNG file +static uint8_t PNG_iGetByte(PNG_decode *d) { + d->i.buflen--; + return *d->i.pbuf++; +} + +/*----------------------------------------------------------------- + * Display output and windowing functions + *---------------------------------------------------------------*/ + +// Initialize the display output window +static void PNG_oInit(PNG_output *o, GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { + o->g = g; + o->x = x; + o->y = y; + o->cx = cx; + o->cy = cy; + o->sx = sx; + o->sy = sy; + o->ix = o->iy = 0; + o->cnt = 0; +} + +// Flush the output buffer to the display +static void PNG_oFlush(PNG_output *o) { + switch(o->cnt) { + case 0: return; + case 1: gdispGDrawPixel(o->g, o->x+o->ix-o->sx, o->y+o->iy-o->sy, o->buf[0]); break; + default: gdispGBlitArea(o->g, o->x+o->ix-o->sx, o->y+o->iy-o->sy, o->cnt, 1, 0, 0, o->cnt, o->buf); break; + } + o->ix += o->cnt; + o->cnt = 0; +} + +// Start a new image line +static bool_t PNG_oStartY(PNG_output *o, coord_t y) { + if (y < o->sy || y >= o->sy+o->cy) + return FALSE; + o->ix = 0; + o->iy = y; + return TRUE; +} + +// Feed a pixel color to the display buffer +static void PNG_oColor(PNG_output *o, color_t c) { + // Is it in the window + if (o->ix+(coord_t)o->cnt < o->sx || o->ix+(coord_t)o->cnt >= o->sx+o->cx) { + // No - just skip the pixel + PNG_oFlush(o); + o->ix++; + return; + } + + // Is the buffer full + if (o->cnt >= sizeof(o->buf)/sizeof(o->buf[0])) + PNG_oFlush(o); + + // Save the pixel + o->buf[o->cnt++] = c; +} + +#if GDISP_NEED_IMAGE_PNG_TRANSPARENCY || GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0 + // Feed a transparent pixel to the display buffer + static void PNG_oTransparent(PNG_output *o) { + // Flush any existing pixels + PNG_oFlush(o); + + // Just skip the pixel + o->ix++; + } +#endif + +/*----------------------------------------------------------------- + * Inflate uncompress functions + *---------------------------------------------------------------*/ + +// Wrap the zInflate buffer position (after increment) +#if (PNG_Z_BUFFER_SIZE & ~(PNG_Z_BUFFER_SIZE-1)) == PNG_Z_BUFFER_SIZE + #define WRAP_ZBUF(x) { x &= PNG_Z_BUFFER_SIZE-1; } +#else + #warning "PNG: PNG_Z_BUFFER_SIZE is more efficient as a power of 2" + #define WRAP_ZBUF(x) { if (x >= PNG_Z_BUFFER_SIZE) x = 0; } +#endif + +// Initialize the inflate decompressor +static void PNG_zInit(PNG_zinflate *z) { + z->bits = 0; + z->flags = 0; + z->bufpos = z->bufend = 0; +} + +// Get the inflate header (slightly customized for PNG validity testing) +static bool_t PNG_zGetHeader(PNG_decode *d) { + if (!PNG_iLoadData(d)) + return FALSE; + d->z.tmp[0] = PNG_iGetByte(d); + if (!PNG_iLoadData(d)) + return FALSE; + d->z.tmp[1] = PNG_iGetByte(d); + if (gdispImageGetAlignedBE16(d->z.tmp, 0) % 31 != 0 // Must be modulo 31, the FCHECK value is made that way + || (d->z.tmp[0] & 0x0F) != 8 || (d->z.tmp[0] & 0x80) // only method 8: inflate 32k sliding window + || (d->z.tmp[1] & 0x20)) // no preset dictionary + return FALSE; + return TRUE; +} + +// Get a bit from the input (treated as a LSB first stream) +static unsigned PNG_zGetBit(PNG_decode *d) { + unsigned bit; + + // Check for EOF + if ((d->z.flags & PNG_ZFLG_EOF)) + return 1; + + // Check if data is empty + if (!d->z.bits) { + if (!PNG_iLoadData(d)) { + d->z.flags |= PNG_ZFLG_EOF; + return 1; + } + d->z.data = PNG_iGetByte(d); + d->z.bits = 8; + } + + // Get the next bit + d->z.bits--; + bit = d->z.data & 0x01; + d->z.data >>= 1; + return bit; +} + +// Get multiple bits from the input (treated as a LSB first stream with bit order retained) +static unsigned PNG_zGetBits(PNG_decode *d, unsigned num) { + unsigned val; + unsigned limit; + unsigned mask; + + val = 0; + limit = 1 << num; + + for (mask = 1; mask < limit; mask <<= 1) + if (PNG_zGetBit(d)) + val += mask; + return val; +} + +// Build an inflate dynamic tree using a string of byte lengths +static void PNG_zBuildTree(PNG_zTree *t, const uint8_t *lengths, unsigned num) { + unsigned i, sum; + uint16_t offs[16]; + + for (i = 0; i < 16; ++i) + t->table[i] = 0; + for (i = 0; i < num; ++i) + t->table[lengths[i]]++; + + t->table[0] = 0; + + for (sum = 0, i = 0; i < 16; ++i) { + offs[i] = sum; + sum += t->table[i]; + } + for (i = 0; i < num; ++i) { + if (lengths[i]) + t->trans[offs[lengths[i]]++] = i; + } +} + +// Get an inflate decode symbol +static uint16_t PNG_zGetSymbol(PNG_decode *d, PNG_zTree *t) { + int sum, cur; + unsigned len; + + sum = cur = 0; + len = 0; + do { + cur <<= 1; + cur += PNG_zGetBit(d); + if ((d->z.flags & PNG_ZFLG_EOF)) + return 0; + len++; + + sum += t->table[len]; + cur -= t->table[len]; + } while (cur >= 0); + + return t->trans[sum + cur]; +} + +// Build inflate fixed length and distance trees +static void PNG_zBuildFixedTrees(PNG_decode *d) { + unsigned i; + + for (i = 0; i < 16; ++i) d->z.ltree.table[i] = 0; + d->z.ltree.table[7] = 24; + d->z.ltree.table[8] = 152; + d->z.ltree.table[9] = 112; + for (i = 0; i < 24; ++i) d->z.ltree.trans[i] = 256 + i; + for (i = 0; i < 144; ++i) d->z.ltree.trans[24 + i] = i; + for (i = 0; i < 8; ++i) d->z.ltree.trans[24 + 144 + i] = 280 + i; + for (i = 0; i < 112; ++i) d->z.ltree.trans[24 + 144 + 8 + i] = 144 + i; + + for (i = 0; i < 16; ++i) d->z.dtree.table[i] = 0; + d->z.dtree.table[5] = 32; + for (i = 0; i < 32; ++i) d->z.dtree.trans[i] = i; + for ( ; i < 288; ++i) d->z.dtree.trans[i] = 0; +} + +// Build inflate dynamic length and distance trees +static bool_t PNG_zDecodeTrees(PNG_decode *d) { + static const uint8_t IndexLookup[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + unsigned hlit, hdist, hclen; + unsigned i, num; + uint16_t symbol; + uint8_t val; + + hlit = PNG_zGetBits(d, 5) + 257; // 257 - 286 + hdist = PNG_zGetBits(d, 5) + 1; // 1 - 32 + hclen = PNG_zGetBits(d, 4) + 4; // 4 - 19 + + if ((d->z.flags & PNG_ZFLG_EOF)) + return FALSE; + + for (i = 0; i < 19; ++i) + d->z.tmp[i] = 0; + + // Get code lengths for the code length alphabet + for (i = 0; i < hclen; ++i) + d->z.tmp[IndexLookup[i]] = PNG_zGetBits(d, 3); + + if ((d->z.flags & PNG_ZFLG_EOF)) + return FALSE; + + // Build the code length tree + PNG_zBuildTree(&d->z.ltree, d->z.tmp, 19); + + // Decode code lengths + for (num = 0; num < hlit + hdist; ) { + symbol = PNG_zGetSymbol(d, &d->z.ltree); + if ((d->z.flags & PNG_ZFLG_EOF)) + return FALSE; + + switch(symbol) { + case 16: // Copy the previous code length 3-6 times + val = d->z.tmp[num - 1]; + for (i = PNG_zGetBits(d, 2) + 3; i; i--) + d->z.tmp[num++] = val; + break; + case 17: // Repeat code length 0 for 3-10 times + for (i = PNG_zGetBits(d, 3) + 3; i; i--) + d->z.tmp[num++] = 0; + break; + case 18: // Repeat code length 0 for 11-138 times + for (i = PNG_zGetBits(d, 7) + 11; i; i--) + d->z.tmp[num++] = 0; + break; + default: // symbols 0-15 are the actual code lengths + d->z.tmp[num++] = symbol; + break; + } + } + + // Build the trees + PNG_zBuildTree(&d->z.ltree, d->z.tmp, hlit); + PNG_zBuildTree(&d->z.dtree, d->z.tmp + hlit, hdist); + return TRUE; +} + +// Copy bytes from the input stream. Completing the copy completes the block. +static bool_t PNG_zCopyInput(PNG_decode *d, unsigned length) { + // Copy the block + while(length--) { + if (!PNG_iLoadData(d)) { // EOF? + d->z.flags |= PNG_ZFLG_EOF; + return FALSE; + } + d->z.buf[d->z.bufend++] = PNG_iGetByte(d); + WRAP_ZBUF(d->z.bufend); + if (d->z.bufend == d->z.bufpos) { // Buffer full? + d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_COPY; + ((unsigned *)d->z.tmp)[0] = length; + return TRUE; + } + } + + // The block is done + d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_NEW; + return TRUE; +} + +// Copy an uncompressed inflate block into the output +static bool_t PNG_zUncompressedBlock(PNG_decode *d) { + unsigned length; + + // This block works on byte boundaries + d->z.bits = 0; + + // Get 4 byte header + for (length = 0; length < 4; length++) { + if (!PNG_iLoadData(d)) { // EOF? + d->z.flags |= PNG_ZFLG_EOF; + return FALSE; + } + d->z.tmp[length] = PNG_iGetByte(d); + } + + // Get length + length = gdispImageGetAlignedLE16(d->z.tmp, 0); + + // Check length + if ((uint16_t)length != (uint16_t)~gdispImageGetAlignedLE16(d->z.tmp, 2)) { + d->z.flags |= PNG_ZFLG_EOF; + return FALSE; + } + + // Copy the block + return PNG_zCopyInput(d, length); +} + +// Inflate a compressed inflate block into the output +static bool_t PNG_zInflateBlock(PNG_decode *d) { + static const uint8_t lbits[30] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 6 }; + static const uint16_t lbase[30] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 323 }; + static const uint8_t dbits[30] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 }; + static const uint16_t dbase[30] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }; + unsigned length, dist, offset; + uint16_t symbol; + + while(1) { + symbol = PNG_zGetSymbol(d, &d->z.ltree); // EOF? + if ((d->z.flags & PNG_ZFLG_EOF)) + goto iserror; + + // Is the block done? + if (symbol == 256) { + d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_NEW; + return TRUE; + } + + if (symbol < 256) { + // The symbol is the data + d->z.buf[d->z.bufend++] = (uint8_t)symbol; + WRAP_ZBUF(d->z.bufend); + if (d->z.bufend == d->z.bufpos) { // Buffer full? + d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_INFLATE; + return TRUE; + } + continue; + } + + // Shift the symbol down into an index + symbol -= 257; + + if (symbol >= sizeof(lbits)) // Bad index? + goto iserror; + + // Get more bits from length code + length = PNG_zGetBits(d, lbits[symbol]) + lbase[symbol]; + if ((d->z.flags & PNG_ZFLG_EOF) || length >= PNG_Z_BUFFER_SIZE) // Bad length? + goto iserror; + + // Get the distance code + dist = PNG_zGetSymbol(d, &d->z.dtree); // Bad distance? + if ((d->z.flags & PNG_ZFLG_EOF) || dist >= sizeof(dbits)) + goto iserror; + + // Get more bits from distance code + offset = PNG_zGetBits(d, dbits[dist]) + dbase[dist]; + if ((d->z.flags & PNG_ZFLG_EOF) || offset >= PNG_Z_BUFFER_SIZE) // Bad offset? + goto iserror; + + // Work out the source buffer position allowing for wrapping + if (offset > d->z.bufend) + offset -= PNG_Z_BUFFER_SIZE; + offset = d->z.bufend - offset; + + // Copy the matching string + while (length--) { + d->z.buf[d->z.bufend++] = d->z.buf[offset++]; + WRAP_ZBUF(d->z.bufend); + WRAP_ZBUF(offset); + if (d->z.bufend == d->z.bufpos) { // Buffer full? + d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_OFFSET; + ((unsigned *)d->z.tmp)[0] = length; + ((unsigned *)d->z.tmp)[1] = offset; + return TRUE; + } + } + } + +iserror: + d->z.flags |= PNG_ZFLG_EOF; + return FALSE; +} + +// Start a new uncompressed/inflate block +static bool_t PNG_zStartBlock(PNG_decode *d) { + // Check for previous error, EOF or no more blocks + if ((d->z.flags & (PNG_ZFLG_EOF|PNG_ZFLG_FINAL))) + return FALSE; + + // Is this the final inflate block? + if (PNG_zGetBit(d)) + d->z.flags |= PNG_ZFLG_FINAL; + + // Get the block type + switch (PNG_zGetBits(d, 2)) { + + case 0: // Decompress uncompressed block + if (!PNG_zUncompressedBlock(d)) + return FALSE; + break; + + case 1: // Decompress block with fixed huffman trees + PNG_zBuildFixedTrees(d); + if (!PNG_zInflateBlock(d)) + return FALSE; + break; + + case 2: // Decompress block with dynamic huffman trees + if (!PNG_zDecodeTrees(d)) + return FALSE; + if (!PNG_zInflateBlock(d)) + return FALSE; + break; + + default: // Bad block type + // Mark it as an error + d->z.flags |= PNG_ZFLG_EOF; + return FALSE; + } + return TRUE; +} + +// Resume an offset copy +static bool_t PNG_zResumeOffset(PNG_decode *d, unsigned length, unsigned offset) { + // Copy the matching string + while (length--) { + d->z.buf[d->z.bufend++] = d->z.buf[offset++]; + WRAP_ZBUF(d->z.bufend); + WRAP_ZBUF(offset); + if (d->z.bufend == d->z.bufpos) { // Buffer full? + d->z.flags = (d->z.flags & ~PNG_ZFLG_RESUME_MASK) | PNG_ZFLG_RESUME_OFFSET; + ((unsigned *)d->z.tmp)[0] = length; + ((unsigned *)d->z.tmp)[1] = offset; + return TRUE; + } + } + return PNG_zInflateBlock(d); +} + +// Get a fully decompressed byte from the inflate data stream +static uint8_t PNG_zGetByte(PNG_decode *d) { + uint8_t data; + + // Do we have any data in the buffers + while (d->z.bufpos == d->z.bufend) { + + // No, get some more data + + switch((d->z.flags & PNG_ZFLG_RESUME_MASK)) { + case PNG_ZFLG_RESUME_NEW: // Start a new inflate block + if (!PNG_zStartBlock(d)) + return 0xFF; + break; + case PNG_ZFLG_RESUME_COPY: // Resume uncompressed block copy for length bytes + if (!PNG_zCopyInput(d, ((unsigned *)d->z.tmp)[0])) + return 0xFF; + break; + case PNG_ZFLG_RESUME_INFLATE: // Resume compressed block + if (!PNG_zInflateBlock(d)) + return 0xFF; + break; + case PNG_ZFLG_RESUME_OFFSET: // Resume compressed block using offset copy for length bytes + if (!PNG_zResumeOffset(d, ((unsigned *)d->z.tmp)[0], ((unsigned *)d->z.tmp)[1])) + return 0xFF; + break; + } + + // Check for no data being provided + // A resume code means the buffer is completely full so the test must be skipped + if ((d->z.flags & PNG_ZFLG_RESUME_MASK) != PNG_ZFLG_RESUME_NEW) + break; + } + + // Get the next data byte + data = d->z.buf[d->z.bufpos++]; + WRAP_ZBUF(d->z.bufpos); + + return data; +} + +/*----------------------------------------------------------------- + * Scan-line filter functions + *---------------------------------------------------------------*/ + +// Initialise the scan-line engine +static void PNG_fInit(PNG_filter *f, uint8_t *buf, unsigned bytewidth, unsigned scanbytes) { + f->scanbytes = scanbytes; + f->bytewidth = bytewidth; + f->line = buf; + f->prev = 0; +} + +// Get ready for the next scan-line +static void PNG_fNext(PNG_filter *f) { + if (f->prev && f->line > f->prev) { + f->line = f->prev; + f->prev += f->scanbytes; + } else { + f->prev = f->line; + f->line += f->scanbytes; + } +} + +// Predictor function for filter0 mode 4 +static uint8_t PNG_fCalcPath(uint16_t a, uint16_t b, uint16_t c) { + uint16_t pa = b > c ? (b - c) : (c - b); + uint16_t pb = a > c ? (a - c) : (c - a); + uint16_t pc = a + b > c + c ? (a + b - c - c) : (c + c - a - b); + + if (pc < pa && pc < pb) + return (uint8_t)c; + if (pb < pa) + return (uint8_t)b; + return (uint8_t)a; +} + +// Scan-line filter type 0 +static bool_t PNG_unfilter_type0(PNG_decode *d) { // PNG filter method 0 + uint8_t ft; + unsigned i; + + // Get the filter type and check for validity (eg not EOF) + ft = PNG_zGetByte(d); + if (ft > 0x04) + return FALSE; + + // Uncompress the scan line + for(i = 0; i < d->f.scanbytes; i++) + d->f.line[i] = PNG_zGetByte(d); + + // Adjust the scan line based on the filter type + // 0 = no adjustment + switch(ft) { + case 1: + for(i = d->f.bytewidth; i < d->f.scanbytes; i++) + d->f.line[i] += d->f.line[i - d->f.bytewidth]; + break; + case 2: + if (d->f.prev) { + for(i = 0; i < d->f.scanbytes; i++) + d->f.line[i] += d->f.prev[i]; + } + break; + case 3: + if (d->f.prev) { + for(i = 0; i < d->f.bytewidth; i++) + d->f.line[i] += d->f.prev[i] / 2; + for( ; i < d->f.scanbytes; i++) + d->f.line[i] += (d->f.line[i - d->f.bytewidth] + d->f.prev[i]) / 2; + } else { + for(i = d->f.bytewidth; i < d->f.scanbytes; i++) + d->f.line[i] += d->f.line[i - d->f.bytewidth] / 2; + } + break; + case 4: + if (d->f.prev) { + for(i = 0; i < d->f.bytewidth; i++) + d->f.line[i] += d->f.prev[i]; // PNG_fCalcPath(0, val, 0) is always val + for( ; i < d->f.scanbytes; i++) + d->f.line[i] += PNG_fCalcPath(d->f.line[i - d->f.bytewidth], d->f.prev[i], d->f.prev[i - d->f.bytewidth]); + } else { + for(i = d->f.bytewidth; i < d->f.scanbytes; i++) + d->f.line[i] += d->f.line[i - d->f.bytewidth]; // PNG_fCalcPath(val, 0, 0) is always val + } + break; + } + + return TRUE; +} + +/*----------------------------------------------------------------- + * Scan-line output and color conversion functions + *---------------------------------------------------------------*/ + +#if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 + static void PNG_OutGRAY124(PNG_decode *d) { + unsigned i; + PNG_info *pinfo; + uint8_t px; + uint8_t bits; + + pinfo = d->pinfo; + for(i = 0; i < d->f.scanbytes; i++) { + for(bits = 8; bits; bits -= pinfo->bitdepth) { + px = (d->f.line[i] >> (bits - pinfo->bitdepth)) & ((1U << pinfo->bitdepth)-1); + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + if ((pinfo->flags & PNG_FLG_TRANSPARENT) && (uint16_t)px == pinfo->trans_r) { + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if ((pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, pinfo->bg); + continue; + } + #endif + PNG_oTransparent(&d->o); + continue; + } + #endif + px = px << (8-pinfo->bitdepth); + if (px >= 0x80) px += ((1U << (8-pinfo->bitdepth))-1); + PNG_oColor(&d->o, LUMA2COLOR(px)); + } + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 + static void PNG_OutGRAY8(PNG_decode *d) { + unsigned i; + uint8_t px; + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + PNG_info *pinfo = d->pinfo; + #endif + + for(i = 0; i < d->f.scanbytes; i++) { + px = d->f.line[i]; + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + if ((pinfo->flags & PNG_FLG_TRANSPARENT) && (uint16_t)px == pinfo->trans_r) { + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if ((pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, pinfo->bg); + continue; + } + #endif + PNG_oTransparent(&d->o); + continue; + } + #endif + PNG_oColor(&d->o, LUMA2COLOR(px)); + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 + static void PNG_OutGRAY16(PNG_decode *d) { + unsigned i; + uint8_t px; + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + PNG_info *pinfo = d->pinfo; + #endif + + for(i = 0; i < d->f.scanbytes; i+=2) { + px = d->f.line[i]; + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + if ((pinfo->flags & PNG_FLG_TRANSPARENT) && gdispImageGetBE16(d->f.line, i) == pinfo->trans_r) { + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if ((pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, pinfo->bg); + continue; + } + #endif + PNG_oTransparent(&d->o); + continue; + } + #endif + PNG_oColor(&d->o, LUMA2COLOR(px)); + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_RGB_8 + static void PNG_OutRGB8(PNG_decode *d) { + unsigned i; + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + PNG_info *pinfo = d->pinfo; + #endif + + for(i = 0; i < d->f.scanbytes; i+=3) { + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + if ((pinfo->flags & PNG_FLG_TRANSPARENT) + && (uint16_t)d->f.line[i+0] == pinfo->trans_r + && (uint16_t)d->f.line[i+1] == pinfo->trans_g + && (uint16_t)d->f.line[i+2] == pinfo->trans_b) { + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if ((pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, pinfo->bg); + continue; + } + #endif + PNG_oTransparent(&d->o); + continue; + } + #endif + PNG_oColor(&d->o, RGB2COLOR(d->f.line[i+0], d->f.line[i+1], d->f.line[i+2])); + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_RGB_16 + static void PNG_OutRGB16(PNG_decode *d) { + unsigned i; + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + PNG_info *pinfo = d->pinfo; + #endif + + for(i = 0; i < d->f.scanbytes; i+=6) { + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + if ((pinfo->flags & PNG_FLG_TRANSPARENT) + && gdispImageGetBE16(d->f.line, i+0) == pinfo->trans_r + && gdispImageGetBE16(d->f.line, i+2) == pinfo->trans_g + && gdispImageGetBE16(d->f.line, i+4) == pinfo->trans_b) { + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if ((pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, pinfo->bg); + continue; + } + #endif + PNG_oTransparent(&d->o); + continue; + } + #endif + PNG_oColor(&d->o, RGB2COLOR(d->f.line[i+0], d->f.line[i+2], d->f.line[i+4])); + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_PALETTE_124 + static void PNG_OutPAL124(PNG_decode *d) { + unsigned i; + PNG_info *pinfo; + unsigned idx; + uint8_t bits; + + pinfo = d->pinfo; + for(i = 0; i < d->f.scanbytes; i++) { + for(bits = 8; bits; bits -= pinfo->bitdepth) { + idx = (d->f.line[i] >> (bits - pinfo->bitdepth)) & ((1U << pinfo->bitdepth)-1); + + if ((uint16_t)idx >= pinfo->palsize) { + PNG_oColor(&d->o, RGB2COLOR(0, 0, 0)); + continue; + } + idx *= 4; + + #define pix_color RGB2COLOR(pinfo->palette[idx], pinfo->palette[idx+1], pinfo->palette[idx+2]) + #define pix_alpha pinfo->palette[idx+3] + + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha)); + continue; + } + #endif + #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0 + if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) { + PNG_oTransparent(&d->o); + continue; + } + #endif + #endif + + PNG_oColor(&d->o, pix_color); + + #undef pix_color + #undef pix_alpha + } + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_PALETTE_8 + static void PNG_OutPAL8(PNG_decode *d) { + unsigned i; + PNG_info *pinfo; + unsigned idx; + + pinfo = d->pinfo; + for(i = 0; i < d->f.scanbytes; i++) { + idx = (unsigned)d->f.line[i]; + + if ((uint16_t)idx >= pinfo->palsize) { + PNG_oColor(&d->o, RGB2COLOR(0, 0, 0)); + continue; + } + idx *= 4; + + #define pix_color RGB2COLOR(pinfo->palette[idx], pinfo->palette[idx+1], pinfo->palette[idx+2]) + #define pix_alpha pinfo->palette[idx+3] + + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha)); + continue; + } + #endif + #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0 + if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) { + PNG_oTransparent(&d->o); + continue; + } + #endif + #endif + + PNG_oColor(&d->o, pix_color); + + #undef pix_color + #undef pix_alpha + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 + static void PNG_OutGRAYA8(PNG_decode *d) { + unsigned i; + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + PNG_info *pinfo = d->pinfo; + #endif + + for(i = 0; i < d->f.scanbytes; i+=2) { + #define pix_color LUMA2COLOR(d->f.line[i]) + #define pix_alpha d->f.line[i+1] + + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha)); + continue; + } + #endif + #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0 + if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) { + PNG_oTransparent(&d->o); + continue; + } + #endif + + PNG_oColor(&d->o, pix_color); + + #undef pix_color + #undef pix_alpha + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 + static void PNG_OutGRAYA16(PNG_decode *d) { + unsigned i; + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + PNG_info *pinfo = d->pinfo; + #endif + + for(i = 0; i < d->f.scanbytes; i+=4) { + #define pix_color LUMA2COLOR(d->f.line[i]) + #define pix_alpha d->f.line[i+2] + + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha)); + continue; + } + #endif + #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0 + if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) { + PNG_oTransparent(&d->o); + continue; + } + #endif + + PNG_oColor(&d->o, pix_color); + + #undef pix_color + #undef pix_alpha + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_RGBALPHA_8 + static void PNG_OutRGBA8(PNG_decode *d) { + unsigned i; + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + PNG_info *pinfo = d->pinfo; + #endif + + for(i = 0; i < d->f.scanbytes; i+=4) { + #define pix_color RGB2COLOR(d->f.line[i+0], d->f.line[i+1], d->f.line[i+2]) + #define pix_alpha d->f.line[i+3] + + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha)); + continue; + } + #endif + #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0 + if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) { + PNG_oTransparent(&d->o); + continue; + } + #endif + + PNG_oColor(&d->o, pix_color); + + #undef pix_color + #undef pix_alpha + } + } +#endif +#if GDISP_NEED_IMAGE_PNG_RGBALPHA_16 + static void PNG_OutRGBA16(PNG_decode *d) { + unsigned i; + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + PNG_info *pinfo = d->pinfo; + #endif + + for(i = 0; i < d->f.scanbytes; i+=8) { + #define pix_color RGB2COLOR(d->f.line[i+0], d->f.line[i+2], d->f.line[i+4]) + #define pix_alpha d->f.line[i+6] + + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + if (pix_alpha != 255 && (pinfo->flags & PNG_FLG_BACKGROUND)) { + PNG_oColor(&d->o, gdispBlendColor(pix_color, pinfo->bg, pix_alpha)); + continue; + } + #endif + #if GDISP_NEED_IMAGE_PNG_ALPHACLIFF > 0 + if (pix_alpha < GDISP_NEED_IMAGE_PNG_ALPHACLIFF) { + PNG_oTransparent(&d->o); + continue; + } + #endif + + PNG_oColor(&d->o, pix_color); + + #undef pix_color + #undef pix_alpha + } + } +#endif + +/*----------------------------------------------------------------- + * Public PNG functions + *---------------------------------------------------------------*/ + +void gdispImageClose_PNG(gdispImage *img) { + PNG_info *pinfo; + + pinfo = (PNG_info *)img->priv; + if (pinfo) { + if (pinfo->palette) + gdispImageFree(img, (void *)pinfo->palette, pinfo->palsize*4); + if (pinfo->cache) + gdispImageFree(img, (void *)pinfo->cache, pinfo->cachesz); + gdispImageFree(img, (void *)pinfo, sizeof(PNG_info)); + img->priv = 0; + } +} + +gdispImageError gdispImageOpen_PNG(gdispImage *img) { + PNG_info *pinfo; + uint32_t pos; + uint32_t len; + uint8_t buf[13]; + + /* Read the file identifier */ + if (gfileRead(img->f, buf, 8) != 8) + return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us + + // Check the PNG signature + if(buf[0] != 137 || buf[1] != 80 || buf[2] != 78 || buf[3] != 71 || buf[4] != 13 || buf[5] != 10 || buf[6] != 26 || buf[7] != 10) + return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us + + /* We know we are a PNG format image */ + img->flags = 0; + img->priv = 0; + img->type = GDISP_IMAGE_TYPE_PNG; + + /* Allocate our private area */ + if (!(img->priv = gdispImageAlloc(img, sizeof(PNG_info)))) + return GDISP_IMAGE_ERR_NOMEMORY; + + /* Initialise the essential bits in the private area */ + pinfo = (PNG_info *)img->priv; + pinfo->flags = 0; + pinfo->cache = 0; + pinfo->trans_r = 0; + pinfo->trans_g = 0; + pinfo->trans_b = 0; + #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8 + pinfo->palsize = 0; + pinfo->palette = 0; + #endif + + // Cycle the chunks to get other information + for(pos = 8; ; pos += len+12, gfileSetPos(img->f, pos)) { + // Get a chunk header + if (gfileRead(img->f, buf, 8) != 8) + goto exit_baddata; + + // Calculate the chunk length + len = gdispImageGetAlignedBE32(buf, 0); + + // Process the interesting information chunks + switch (gdispImageGetAlignedBE32(buf, 4)) { + case 0x49484452: // "IHDR" - Header block + + // Check if the header is already done + if ((pinfo->flags & PNG_FLG_HEADERDONE)) + goto exit_baddata; + + // Read the image parameters + if (len < 13 || gfileRead(img->f, buf, 13) != 13) + goto exit_baddata; + + img->width = gdispImageGetAlignedBE16(buf, 2); + img->height = gdispImageGetAlignedBE16(buf, 6); + pinfo->bitdepth = gdispImageGetVar(uint8_t, buf, 8); + pinfo->mode = gdispImageGetVar(uint8_t, buf, 9); + if (gdispImageGetVar(uint8_t, buf, 12)) { + pinfo->flags |= PNG_FLG_INTERLACE; + #if !GDISP_NEED_IMAGE_PNG_INTERLACED + goto exit_unsupported; + #endif + } + + // Check width and height, filter, compression and interlacing + if (gdispImageGetVar(uint16_t, buf, 0) != 0 || img->width <= 0 // width + || gdispImageGetVar(uint16_t, buf, 4) != 0 || img->height <= 0 // height + || gdispImageGetVar(uint8_t, buf, 10) != 0 // compression + || gdispImageGetVar(uint8_t, buf, 11) != 0 // filter + || gdispImageGetVar(uint8_t, buf, 12) > 1 // interlace + ) + goto exit_unsupported; + + // Check mode, bitdepth and calculate bits per pixel + switch(pinfo->mode) { + #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 + case PNG_COLORMODE_GRAY: + switch(pinfo->bitdepth) { + #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 + case 1: + case 2: + case 4: pinfo->out = PNG_OutGRAY124; break; + #endif + #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 + case 8: pinfo->out = PNG_OutGRAY8; break; + #endif + #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 + case 16: pinfo->out = PNG_OutGRAY16; break; + #endif + default: goto exit_unsupported; + } + pinfo->bpp = pinfo->bitdepth; + break; + #endif + #if GDISP_NEED_IMAGE_PNG_RGB_8 || GDISP_NEED_IMAGE_PNG_RGB_16 + case PNG_COLORMODE_RGB: + switch(pinfo->bitdepth) { + #if GDISP_NEED_IMAGE_PNG_RGB_8 + case 8: pinfo->out = PNG_OutRGB8; break; + #endif + #if GDISP_NEED_IMAGE_PNG_RGB_16 + case 16: pinfo->out = PNG_OutRGB16; break; + #endif + default: goto exit_unsupported; + } + pinfo->bpp = pinfo->bitdepth * 3; + break; + #endif + #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8 + case PNG_COLORMODE_PALETTE: + switch(pinfo->bitdepth) { + #if GDISP_NEED_IMAGE_PNG_PALETTE_124 + case 1: + case 2: + case 4: pinfo->out = PNG_OutPAL124; break; + #endif + #if GDISP_NEED_IMAGE_PNG_PALETTE_8 + case 8: pinfo->out = PNG_OutPAL8; break; + #endif + default: goto exit_unsupported; + } + pinfo->bpp = pinfo->bitdepth; + break; + #endif + #if GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 + case PNG_COLORMODE_GRAYALPHA: + switch(pinfo->bitdepth) { + #if GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 + case 8: pinfo->out = PNG_OutGRAYA8; break; + #endif + #if GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 + case 16: pinfo->out = PNG_OutGRAYA16; break; + #endif + default: goto exit_unsupported; + } + pinfo->bpp = pinfo->bitdepth * 2; + break; + #endif + #if GDISP_NEED_IMAGE_PNG_RGBALPHA_8 || GDISP_NEED_IMAGE_PNG_RGBALPHA_16 + case PNG_COLORMODE_RGBA: + switch(pinfo->bitdepth) { + #if GDISP_NEED_IMAGE_PNG_RGBALPHA_8 + case 8: pinfo->out = PNG_OutRGBA8; break; + #endif + #if GDISP_NEED_IMAGE_PNG_RGBALPHA_16 + case 16: pinfo->out = PNG_OutRGBA16; break; + #endif + default: goto exit_unsupported; + } + pinfo->bpp = pinfo->bitdepth * 4; + break; + #endif + default: + goto exit_unsupported; + } + + pinfo->flags |= PNG_FLG_HEADERDONE; + break; + + case 0x49454E44: // "IEND" - All done + goto exit_baddata; // Oops we didn't get any data. + + case 0x49444154: // "IDAT" - Image Data + + // Check if the header is already done + if (!(pinfo->flags & PNG_FLG_HEADERDONE)) + goto exit_baddata; + + #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8 + // Make sure a palette image actually has a palette + if (pinfo->mode == PNG_COLORMODE_PALETTE && !pinfo->palette) + goto exit_baddata; + #endif + + // All good + return GDISP_IMAGE_ERR_OK; + + #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8 + case 0x504C5445: // "PLTE" - Palette + + // Check if the header is already done + if (!(pinfo->flags & PNG_FLG_HEADERDONE)) + goto exit_baddata; + + // Skip a palette if we don't need it. + if (pinfo->mode != PNG_COLORMODE_PALETTE) + break; + + // Check the size and that we don't have one already + if (len > 3 * 256 || pinfo->palette) + goto exit_baddata; + + // Allocate the palette + pinfo->palsize = len / 3; + if (!(pinfo->palette = gfxAlloc(pinfo->palsize * 4))) + goto exit_nonmem; + + // Read the palette + { + uint16_t idx; + uint8_t *p; + + for(idx=pinfo->palsize, p=pinfo->palette; idx; p += 4, idx--) { + if (gfileRead(img->f, p, 3) != 3) + goto exit_baddata; + p[3] = 255; + } + } + + break; + #endif + + #if GDISP_NEED_IMAGE_PNG_TRANSPARENCY + case 0x74524E53: // "tRNS" - Transparency + + // Check if the header is already done + if (!(pinfo->flags & PNG_FLG_HEADERDONE)) + goto exit_baddata; + + // Transparency is handled differently depending on the mode + switch(pinfo->mode) { + + #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8 + case PNG_COLORMODE_PALETTE: + if (len > pinfo->palsize) + goto exit_baddata; + + // Adjust the palette + { + uint16_t idx; + uint8_t *p; + + for(idx=len, p=pinfo->palette+3; idx; p += 4, idx--) { + if (gfileRead(img->f, p, 1) != 1) + goto exit_baddata; + } + } + break; + #endif + + #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 + case PNG_COLORMODE_GRAY: + // Read the transparency color + if (len != 2 || gfileRead(img->f, buf, 2) != 2) + goto exit_baddata; + + pinfo->flags |= PNG_FLG_TRANSPARENT; + pinfo->trans_r = gdispImageGetAlignedBE16(buf, 0); + break; + #endif + #if GDISP_NEED_IMAGE_PNG_RGB_8 || GDISP_NEED_IMAGE_PNG_RGB_16 + case PNG_COLORMODE_RGB: + // Read the transparency color + if (len != 6 || gfileRead(img->f, buf, 6) != 6) + goto exit_baddata; + + pinfo->flags |= PNG_FLG_TRANSPARENT; + pinfo->trans_r = gdispImageGetAlignedBE16(buf, 0); + pinfo->trans_g = gdispImageGetAlignedBE16(buf, 2); + pinfo->trans_b = gdispImageGetAlignedBE16(buf, 4); + break; + #endif + default: + goto exit_unsupported; + } + + break; + #endif + + #if GDISP_NEED_IMAGE_PNG_BACKGROUND + case 0x624B4744: // "bKGD" - Background + + // Check if the header is already done + if (!(pinfo->flags & PNG_FLG_HEADERDONE)) + goto exit_baddata; + + pinfo->flags |= PNG_FLG_BACKGROUND; + + // Background data is handled differently depending on the mode + switch(pinfo->mode) { + + #if GDISP_NEED_IMAGE_PNG_PALETTE_124 || GDISP_NEED_IMAGE_PNG_PALETTE_8 + case PNG_COLORMODE_PALETTE: + if (!pinfo->palette || len < 1 || gfileRead(img->f, buf, 1) != 1 || (uint16_t)buf[0] >= pinfo->palsize) + goto exit_baddata; + pinfo->bg = RGB2COLOR(pinfo->palette[((unsigned)buf[0])*4+0], + pinfo->palette[((unsigned)buf[0])*4+1], + pinfo->palette[((unsigned)buf[0])*4+2]); + break; + #endif + + #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 || GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 + case PNG_COLORMODE_GRAY: + case PNG_COLORMODE_GRAYALPHA: + if (len < 2 || gfileRead(img->f, buf, 2) != 2) + goto exit_baddata; + switch(pinfo->bitdepth) { + #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 + case 1: + case 2: + case 4: + buf[1] <<= 8-pinfo->bitdepth; + if (buf[1] >= 0x80) + buf[1] += ((1U << (8-pinfo->bitdepth))-1); + pinfo->bg = LUMA2COLOR(buf[1]); + break; + #endif + #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 + case 8: + pinfo->bg = LUMA2COLOR(buf[1]); + break; + #endif + #if GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 || GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 + case 16: + pinfo->bg = LUMA2COLOR(buf[0]); + break; + #endif + } + break; + #endif + #if GDISP_NEED_IMAGE_PNG_RGB_8 || GDISP_NEED_IMAGE_PNG_RGB_16 || GDISP_NEED_IMAGE_PNG_RGBALPHA_8 || GDISP_NEED_IMAGE_PNG_RGBALPHA_16 + case PNG_COLORMODE_RGB: + case PNG_COLORMODE_RGBA: + if (len < 6 || gfileRead(img->f, buf, 6) != 6) + goto exit_baddata; + + #if GDISP_NEED_IMAGE_PNG_RGB_16 || GDISP_NEED_IMAGE_PNG_RGBALPHA_16 + if (pinfo->bitdepth == 16) { + pinfo->bg = RGB2COLOR(buf[0], buf[2], buf[4]); + } else + #endif + pinfo->bg = RGB2COLOR(buf[1], buf[3], buf[5]); + break; + #endif + default: + goto exit_unsupported; + } + break; + #endif + + } + } +exit_baddata: + gdispImageClose_PNG(img); + return GDISP_IMAGE_ERR_BADDATA; +exit_unsupported: + gdispImageClose_PNG(img); + return GDISP_IMAGE_ERR_UNSUPPORTED; +exit_nonmem: + gdispImageClose_PNG(img); + return GDISP_IMAGE_ERR_NOMEMORY; +} + +gdispImageError gdispGImageDraw_PNG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { + PNG_info *pinfo; + PNG_decode *d; + + // Allocate the space to decode with including space for 2 full scan lines for filtering. + pinfo = (PNG_info *)img->priv; + if (!(d = gdispImageAlloc(img, sizeof(PNG_decode) + (img->width * pinfo->bpp + 7) / 4))) + return GDISP_IMAGE_ERR_NOMEMORY; + + + // Initialise the decoder + d->img = img; + d->pinfo = pinfo; + PNG_iInit(d); + PNG_oInit(&d->o, g, x, y, cx, cy, sx, sy); + PNG_zInit(&d->z); + + // Process the zlib inflate header + if (!PNG_zGetHeader(d)) + goto exit_baddata; + + #if GDISP_NEED_IMAGE_PNG_INTERLACED + if ((pinfo->flags & PNG_FLG_INTERLACE)) { + // Interlaced decoding + #error "PNG Decoder: Interlaced PNG's are not supported yet!" + } else + #endif + { + // Non-interlaced decoding + PNG_fInit(&d->f, (uint8_t *)(d+1), (pinfo->bpp + 7) / 8, (img->width * pinfo->bpp + 7) / 8); + for(y = 0; y < sy+cy; PNG_fNext(&d->f), y++) { + if (!PNG_unfilter_type0(d)) + goto exit_baddata; + if (PNG_oStartY(&d->o, y)) { + pinfo->out(d); + PNG_oFlush(&d->o); + } + } + } + + // Clean up + gdispImageFree(img, d, sizeof(PNG_decode) + (img->width * pinfo->bpp + 7) / 4); + return GDISP_IMAGE_ERR_OK; + +exit_baddata: + gdispImageFree(img, d, sizeof(PNG_decode) + (img->width * pinfo->bpp + 7) / 4); + return GDISP_IMAGE_ERR_BADDATA; +} + +gdispImageError gdispImageCache_PNG(gdispImage *img) { + PNG_info *pinfo; + unsigned chunknext; + unsigned chunklen; + uint8_t *pcache; + uint8_t buf[8]; + + // If we are already cached - just return OK + pinfo = (PNG_info *)img->priv; + if (pinfo->cache) + return GDISP_IMAGE_ERR_OK; + + // Calculate the size of all the image data blocks in the image + pinfo->cachesz = 0; + chunknext = 8; + while(1) { + // Find a new chunk + gfileSetPos(img->f, chunknext); + if (gfileRead(img->f, buf, 8) != 8) + return GDISP_IMAGE_ERR_BADDATA; + + // Calculate the chunk length and next chunk + chunklen = gdispImageGetAlignedBE32(buf, 0); + chunknext += chunklen + 12; + + // Process only image data chunks + switch (gdispImageGetAlignedBE32(buf, 4)) { + case 0x49444154: // "IDAT" - Image Data + pinfo->cachesz += chunklen; + break; + case 0x49454E44: // "IEND" - All done + if (!pinfo->cachesz) + return GDISP_IMAGE_ERR_BADDATA; + goto gotsize; + } + } + +gotsize: + // Allocate the cache + if (!(pcache = gdispImageAlloc(img, pinfo->cachesz))) + return GDISP_IMAGE_ERR_NOMEMORY; + + pinfo->cache = pcache; + + // Read the image data into the cache + chunknext = 8; + while(1) { + // Find a new chunk + gfileSetPos(img->f, chunknext); + if (gfileRead(img->f, buf, 8) != 8) + goto baddata; + + // Calculate the chunk length and next chunk + chunklen = gdispImageGetAlignedBE32(buf, 0); + chunknext += chunklen + 12; + + // Process only image data chunks + switch (gdispImageGetAlignedBE32(buf, 4)) { + case 0x49444154: // "IDAT" - Image Data + if (gfileRead(img->f, pcache, chunklen) != chunklen) + goto baddata; + pcache += chunklen; + break; + case 0x49454E44: // "IEND" - All done + return GDISP_IMAGE_ERR_OK; + } + } + +baddata: + // Oops - can't read the data. Throw away the cache. + gdispImageFree(img, pinfo->cache, pinfo->cachesz); + pinfo->cache = 0; + return GDISP_IMAGE_ERR_BADDATA; +} + +delaytime_t gdispImageNext_PNG(gdispImage *img) { + (void) img; + + /* No more frames/pages */ + return TIME_INFINITE; +} #endif /* GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_PNG */ diff --git a/src/gdisp/gdisp_options.h b/src/gdisp/gdisp_options.h index c3eec451..4c004808 100644 --- a/src/gdisp/gdisp_options.h +++ b/src/gdisp/gdisp_options.h @@ -383,6 +383,127 @@ /** * @} * + * @name GDISP PNG Image Options + * @pre GDISP_NEED_IMAGE and GDISP_NEED_IMAGE_PNG must be TRUE + * @{ + */ + /** + * @brief Is PNG Interlaced image decoding required. + * @details Defaults to FALSE + * @note Currently not supported due to the complex decoding and display requirements + */ + #ifndef GDISP_NEED_IMAGE_PNG_INTERLACED + #define GDISP_NEED_IMAGE_PNG_INTERLACED FALSE + #endif + /** + * @brief Is PNG image transparency processed. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_TRANSPARENCY + #define GDISP_NEED_IMAGE_PNG_TRANSPARENCY TRUE + #endif + /** + * @brief Is PNG background data processed. + * @details Defaults to TRUE + * @note If the background is specified in the image file and this define is TRUE, + * that background color is used for transparency and alpha blending. + */ + #ifndef GDISP_NEED_IMAGE_PNG_BACKGROUND + #define GDISP_NEED_IMAGE_PNG_BACKGROUND TRUE + #endif + /** + * @brief What is the cliff between non-blended alpha pixels being displayed or not. + * @details Range of 0 to 255 + * @note If GDISP_NEED_IMAGE_PNG_BACKGROUND is TRUE and the PNG file contains a + * background color then the pixel will be blended with the background color + * according to the alpha. + * If not then no blending occurs. The pixel will either be set or not. + * Any alpha value greater or equal to this number will be displayed. + * Anything less than this number is not displayed. + */ + #ifndef GDISP_NEED_IMAGE_PNG_ALPHACLIFF + #define GDISP_NEED_IMAGE_PNG_ALPHACLIFF 32 + #endif + /** + * @brief Is 1, 2 and 4 bit PNG palettized image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_PALETTE_124 + #define GDISP_NEED_IMAGE_PNG_PALETTE_124 TRUE + #endif + /** + * @brief Is 8 bit PNG palettized image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_PALETTE_8 + #define GDISP_NEED_IMAGE_PNG_PALETTE_8 TRUE + #endif + /** + * @brief Is 1,2 and 4 bit PNG grayscale image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 + #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 TRUE + #endif + /** + * @brief Is 8 bit PNG grayscale image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 + #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 TRUE + #endif + /** + * @brief Is 16 bit PNG grayscale image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 + #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 TRUE + #endif + /** + * @brief Is 8 bit PNG grayscale with 8 bit alpha image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 + #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 TRUE + #endif + /** + * @brief Is 16 bit PNG grayscale with 16 bit alpha image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 + #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 TRUE + #endif + /** + * @brief Is 8/8/8 bit PNG RGB image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_RGB_8 + #define GDISP_NEED_IMAGE_PNG_RGB_8 TRUE + #endif + /** + * @brief Is 16/16/16 bit PNG RGB image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_RGB_16 + #define GDISP_NEED_IMAGE_PNG_RGB_16 TRUE + #endif + /** + * @brief Is 8/8/8 bit PNG RGB with 8 bit alpha image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_RGBALPHA_8 + #define GDISP_NEED_IMAGE_PNG_RGBALPHA_8 TRUE + #endif + /** + * @brief Is 16/16/16 bit PNG RGB with 16 bit alpha image decoding required. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_IMAGE_PNG_RGBALPHA_16 + #define GDISP_NEED_IMAGE_PNG_RGBALPHA_16 TRUE + #endif +/** + * @} + * * @name GDISP Text Rendering Options * @{ */ @@ -142,7 +142,7 @@ void gfxDeinit(void) #if GFX_USE_GWIN _gwinDeinit(); #endif - #if GFX_USE_GAUDIN + #if GFX_USE_GAUDIO _gaudioDeinit(); #endif #if GFX_USE_GADC diff --git a/src/gfx_compilers.h b/src/gfx_compilers.h index 5af1244a..c34c7d02 100644 --- a/src/gfx_compilers.h +++ b/src/gfx_compilers.h @@ -430,6 +430,7 @@ #endif #elif GFX_COMPILER == GFX_COMPILER_IAR #define GFX_COMPILER_NAME "IAR C++" + #define GFX_COMPILER_TESTED TRUE #define GFX_COMPILER_VERSION_MAJOR ((__VER__)/100) #define GFX_COMPILER_VERSION_MINOR ((__VER__)%100) #elif GFX_COMPILER == GFX_COMPILER_IBMXL diff --git a/src/gos/gos_options.h b/src/gos/gos_options.h index 0c6fd7a7..5c051fea 100644 --- a/src/gos/gos_options.h +++ b/src/gos/gos_options.h @@ -195,6 +195,18 @@ #ifndef GFX_OS_HEAP_SIZE #define GFX_OS_HEAP_SIZE 0 #endif + /** + * @brief Enable wrappers for malloc() and free() + * @details Defaults to FALSE + * @note If enabled, malloc() and free() will be implemented as wrappers that call gfxAlloc() and + * gfxFree() in order to provide portability to libraries using these function. + * @note Enabling this can solve 'unresolved _sbrk' issues + * @note It is strongly recommended to always use gfxAlloc() and gfxFree() directy to ensure + * portability of uGFX applications across all platforms. + */ + #ifndef GFX_EMULATE_MALLOC + #define GFX_EMULATE_MALLOC FALSE + #endif /** @} */ #endif /* _GOS_OPTIONS_H */ diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c index f448453b..586636ec 100644 --- a/src/gwin/gwin.c +++ b/src/gwin/gwin.c @@ -196,6 +196,7 @@ GHandle gwinGWindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pI return 0; gwinSetVisible(pgw, pInit->show); + _gwinFlushRedraws(REDRAW_WAIT); return pgw; } diff --git a/src/gwin/gwin_button.c b/src/gwin/gwin_button.c index 6e25ab6c..c96d3cdd 100644 --- a/src/gwin/gwin_button.c +++ b/src/gwin/gwin_button.c @@ -23,9 +23,6 @@ #define BTN_TOP_FADE 50 // (BTN_TOP_FADE/255)% fade to white for top of button #define BTN_BOTTOM_FADE 25 // (BTN_BOTTOM_FADE/255)% fade to black for bottom of button -// Our pressed state -#define GBUTTON_FLG_PRESSED (GWIN_FIRST_CONTROL_FLAG<<0) - #if GINPUT_NEED_MOUSE // A mouse down has occurred over the button static void ButtonMouseDown(GWidgetObject *gw, coord_t x, coord_t y) { diff --git a/src/gwin/gwin_button.h b/src/gwin/gwin_button.h index dcbab682..11af82e0 100644 --- a/src/gwin/gwin_button.h +++ b/src/gwin/gwin_button.h @@ -40,6 +40,14 @@ typedef GEventGWin GEventGWinButton; /** + * @brief The internal button flags + * @note Used only for writing a custom draw routine. + * @{ + */ +#define GBUTTON_FLG_PRESSED 0x01 +/** @} */ + +/** * @brief The button widget structure * @note Do not use the members directly - treat it as a black-box. */ diff --git a/src/gwin/gwin_checkbox.c b/src/gwin/gwin_checkbox.c index 43d74f23..436a0806 100644 --- a/src/gwin/gwin_checkbox.c +++ b/src/gwin/gwin_checkbox.c @@ -20,9 +20,6 @@ #define CHK_TOP_FADE 50 // (CHK_TOP_FADE/255)% fade to white for top of button #define CHK_BOTTOM_FADE 25 // (CHK_BOTTOM_FADE/255)% fade to black for bottom of button -// Our checked state -#define GCHECKBOX_FLG_CHECKED (GWIN_FIRST_CONTROL_FLAG<<0) - // Send the checkbox event static void SendCheckboxEvent(GWidgetObject *gw) { GSourceListener * psl; diff --git a/src/gwin/gwin_checkbox.h b/src/gwin/gwin_checkbox.h index 10401624..b704dffe 100644 --- a/src/gwin/gwin_checkbox.h +++ b/src/gwin/gwin_checkbox.h @@ -45,6 +45,14 @@ typedef struct GEventGWinCheckbox { bool_t isChecked; // Is the checkbox currently checked or unchecked? } GEventGWinCheckbox; +/** + * @brief The internal checkbox flags + * @note Used only for writing a custom draw routine. + * @{ + */ +#define GCHECKBOX_FLG_CHECKED 0x01 +/** @} */ + /* A Checkbox window */ typedef struct GCheckboxObject { GWidgetObject w; diff --git a/src/gwin/gwin_class.h b/src/gwin/gwin_class.h index f2aa4df0..ea5c260c 100644 --- a/src/gwin/gwin_class.h +++ b/src/gwin/gwin_class.h @@ -27,7 +27,7 @@ * @brief The predefined flags for a Window * @{ */ -#define GWIN_FIRST_CONTROL_FLAG 0x00000001 /**< 8 bits free for the control to use */ +#define GWIN_FIRST_CONTROL_FLAG 0x00000001 /**< 8 bits free for the control to use. Don't change this value as it is relied upon definitions in widget header files. */ #define GWIN_LAST_CONTROL_FLAG 0x00000080 /**< 8 bits free for the control to use */ #define GWIN_FLG_VISIBLE 0x00000100 /**< The window is "visible" */ #define GWIN_FLG_SYSVISIBLE 0x00000200 /**< The window is visible after parents are tested */ diff --git a/src/gwin/gwin_console.c b/src/gwin/gwin_console.c index 667ec560..37ae079e 100644 --- a/src/gwin/gwin_console.c +++ b/src/gwin/gwin_console.c @@ -353,6 +353,7 @@ GHandle gwinGConsoleCreate(GDisplay *g, GConsoleObject *gc, const GWindowInit *p #endif gwinSetVisible((GHandle)gc, pInit->show); + _gwinFlushRedraws(REDRAW_WAIT); return (GHandle)gc; } diff --git a/src/gwin/gwin_frame.c b/src/gwin/gwin_frame.c index 28d7c01d..9aed4c06 100644 --- a/src/gwin/gwin_frame.c +++ b/src/gwin/gwin_frame.c @@ -28,11 +28,8 @@ #define FRM_BORDER_B 2 // Bottom Border /* Internal state flags */ -#define GWIN_FRAME_USER_FLAGS (GWIN_FRAME_CLOSE_BTN|GWIN_FRAME_MINMAX_BTN) -#define GWIN_FRAME_CLOSE_PRESSED (GWIN_FRAME_MINMAX_BTN << 1) -#define GWIN_FRAME_MIN_PRESSED (GWIN_FRAME_MINMAX_BTN << 2) -#define GWIN_FRAME_MAX_PRESSED (GWIN_FRAME_MINMAX_BTN << 3) -#define GWIN_FRAME_REDRAW_FRAME (GWIN_FRAME_MINMAX_BTN << 4) // Only redraw the frame +#define GWIN_FRAME_USER_FLAGS (GWIN_FRAME_CLOSE_BTN|GWIN_FRAME_MINMAX_BTN|GWIN_FRAME_KEEPONCLOSE) + #if GWIN_FRAME_CLOSE_BTN < GWIN_FIRST_CONTROL_FLAG #error "GWIN Frame: - Flag definitions don't match" #endif @@ -96,7 +93,8 @@ static void forceFrameRedraw(GWidgetObject *gw) { gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED); forceFrameRedraw(gw); _gwinSendEvent(&gw->g, GEVENT_GWIN_CLOSE); - _gwinDestroy(&gw->g, REDRAW_INSESSION); + if (!(gw->g.flags & GWIN_FRAME_KEEPONCLOSE)) + _gwinDestroy(&gw->g, REDRAW_INSESSION); return; } if ((gw->g.flags & GWIN_FRAME_MAX_PRESSED)) { @@ -129,7 +127,8 @@ static void forceFrameRedraw(GWidgetObject *gw) { gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED); forceFrameRedraw(gw); _gwinSendEvent(&gw->g, GEVENT_GWIN_CLOSE); - _gwinDestroy(&gw->g, REDRAW_INSESSION); + if (!(gw->g.flags & GWIN_FRAME_KEEPONCLOSE)) + _gwinDestroy(&gw->g, REDRAW_INSESSION); return; } pos -= FRM_BUTTON_X; diff --git a/src/gwin/gwin_frame.h b/src/gwin/gwin_frame.h index 18af2e50..f39d3df6 100644 --- a/src/gwin/gwin_frame.h +++ b/src/gwin/gwin_frame.h @@ -31,9 +31,21 @@ * @brief Flags for gwinFrameCreate() * @{ */ -#define GWIN_FRAME_BORDER 0x00000000 // Deprecated. A border is always shown with a frame window now. -#define GWIN_FRAME_CLOSE_BTN 0x00000001 -#define GWIN_FRAME_MINMAX_BTN 0x00000002 +#define GWIN_FRAME_BORDER 0x00000000 /**< Deprecated. A border is always shown with a frame window now. */ +#define GWIN_FRAME_CLOSE_BTN 0x00000001 /**< Should a close button be shown? */ +#define GWIN_FRAME_MINMAX_BTN 0x00000002 /**< Should minimize and maximize buttons be shown? */ +#define GWIN_FRAME_KEEPONCLOSE 0x00000004 /**< Don't automatically destroy the frame on close */ +/** @} */ + +/** + * @brief The internal frame flags + * @note Used only for writing a custom draw routine. + * @{ + */ +#define GWIN_FRAME_CLOSE_PRESSED 0x00000008 +#define GWIN_FRAME_MIN_PRESSED 0x00000010 +#define GWIN_FRAME_MAX_PRESSED 0x00000020 +#define GWIN_FRAME_REDRAW_FRAME 0x00000040 // Only redraw the frame /** @} */ typedef GContainerObject GFrameObject; diff --git a/src/gwin/gwin_graph.c b/src/gwin/gwin_graph.c index 95743ced..6f0ce2a4 100644 --- a/src/gwin/gwin_graph.c +++ b/src/gwin/gwin_graph.c @@ -172,6 +172,7 @@ GHandle gwinGGraphCreate(GDisplay *g, GGraphObject *gg, const GWindowInit *pInit gg->lastx = gg->lasty = 0; gwinGraphSetStyle((GHandle)gg, &GGraphDefaultStyle); gwinSetVisible((GHandle)gg, pInit->show); + _gwinFlushRedraws(REDRAW_WAIT); return (GHandle)gg; } diff --git a/src/gwin/gwin_keyboard.c b/src/gwin/gwin_keyboard.c index 075ef4c8..f3dd6fb0 100644 --- a/src/gwin/gwin_keyboard.c +++ b/src/gwin/gwin_keyboard.c @@ -17,12 +17,6 @@ #include "gwin_class.h" #include "gwin_keyboard_layout.h" - -#define GKEYBOARD_FLG_REVERTSET (GWIN_FIRST_CONTROL_FLAG<<0) -#define GKEYBOARD_FLG_QUICKUPDATE (GWIN_FIRST_CONTROL_FLAG<<1) - -#define GKEY_BAD_ROWCOL 255 - typedef uint8_t utf8; typedef uint16_t utf16; typedef uint32_t utf32; diff --git a/src/gwin/gwin_keyboard.h b/src/gwin/gwin_keyboard.h index 1d792d7a..98780485 100644 --- a/src/gwin/gwin_keyboard.h +++ b/src/gwin/gwin_keyboard.h @@ -40,6 +40,16 @@ typedef GEventGWin GEventGWinKeyboard; /** + * @brief The internal keyboard flags and other defines + * @note Used only for writing a custom draw routine. + * @{ + */ +#define GKEYBOARD_FLG_REVERTSET 0x01 +#define GKEYBOARD_FLG_QUICKUPDATE 0x02 +#define GKEY_BAD_ROWCOL 255 +/** @} */ + +/** * @brief The keyboard widget structure * @note Do not use the members directly - treat it as a black-box. */ diff --git a/src/gwin/gwin_label.c b/src/gwin/gwin_label.c index e6b4e986..e6e31eec 100644 --- a/src/gwin/gwin_label.c +++ b/src/gwin/gwin_label.c @@ -20,11 +20,6 @@ #define gh2obj ((GLabelObject *)gh) #define gw2obj ((GLabelObject *)gw) -// flags for the GLabelObject -#define GLABEL_FLG_WAUTO (GWIN_FIRST_CONTROL_FLAG << 0) -#define GLABEL_FLG_HAUTO (GWIN_FIRST_CONTROL_FLAG << 1) -#define GLABEL_FLG_BORDER (GWIN_FIRST_CONTROL_FLAG << 2) - // simple: single line with no wrapping static coord_t getwidth(const char *text, font_t font, coord_t maxwidth) { (void) maxwidth; diff --git a/src/gwin/gwin_label.h b/src/gwin/gwin_label.h index c08eb85d..1e8ba53e 100644 --- a/src/gwin/gwin_label.h +++ b/src/gwin/gwin_label.h @@ -33,6 +33,16 @@ // This file is included within "src/gwin/gwin_widget.h" +/** + * @brief The internal label flags + * @note Used only for writing a custom draw routine. + * @{ + */ +#define GLABEL_FLG_WAUTO 0x01 +#define GLABEL_FLG_HAUTO 0x02 +#define GLABEL_FLG_BORDER 0x04 +/** @} */ + // An label window typedef struct GLabelObject { GWidgetObject w; diff --git a/src/gwin/gwin_list.c b/src/gwin/gwin_list.c index 4bb9c283..f0bd7362 100644 --- a/src/gwin/gwin_list.c +++ b/src/gwin/gwin_list.c @@ -31,27 +31,6 @@ #define qix2li ((ListItem *)qix) #define ple ((GEventGWinList *)pe) -// Flags for the GListObject -#define GLIST_FLG_MULTISELECT (GWIN_FIRST_CONTROL_FLAG << 0) -#define GLIST_FLG_HASIMAGES (GWIN_FIRST_CONTROL_FLAG << 1) -#define GLIST_FLG_SCROLLALWAYS (GWIN_FIRST_CONTROL_FLAG << 2) -#define GLIST_FLG_SCROLLSMOOTH (GWIN_FIRST_CONTROL_FLAG << 3) -#define GLIST_FLG_ENABLERENDER (GWIN_FIRST_CONTROL_FLAG << 4) - -// Flags on a ListItem. -#define GLIST_FLG_SELECTED 0x0001 - -typedef struct ListItem { - gfxQueueASyncItem q_item; // This must be the first member in the struct - - uint16_t flags; - uint16_t param; // A parameter the user can specify himself - const char* text; - #if GWIN_NEED_LIST_IMAGES - gdispImage* pimg; - #endif -} ListItem; - static void sendListEvent(GWidgetObject *gw, int item) { GSourceListener* psl; GEvent* pe; diff --git a/src/gwin/gwin_list.h b/src/gwin/gwin_list.h index 2ab06960..a4d8aca7 100644 --- a/src/gwin/gwin_list.h +++ b/src/gwin/gwin_list.h @@ -76,6 +76,35 @@ typedef struct GListObject { */ typedef enum scroll_t { scrollAlways, scrollAuto, scrollSmooth } scroll_t; +/** + * @brief The internal list object flags + * @note Used only for writing a custom draw routine. + * @{ + */ +#define GLIST_FLG_MULTISELECT 0x01 +#define GLIST_FLG_HASIMAGES 0x02 +#define GLIST_FLG_SCROLLALWAYS 0x04 +#define GLIST_FLG_SCROLLSMOOTH 0x08 +#define GLIST_FLG_ENABLERENDER 0x10 +/** @} */ + +/** + * @brief The internal list item structure + * @note Used only for writing a custom draw routine. + */ +typedef struct ListItem { + gfxQueueASyncItem q_item; // This must be the first member in the struct + + uint16_t flags; + #define GLIST_FLG_SELECTED 0x0001 + uint16_t param; // A parameter the user can specify himself + const char* text; + #if GWIN_NEED_LIST_IMAGES + gdispImage* pimg; + #endif +} ListItem; + + #ifdef __cplusplus extern "C" { #endif diff --git a/src/gwin/gwin_options.h b/src/gwin/gwin_options.h index ab3e284a..6bf59d2a 100644 --- a/src/gwin/gwin_options.h +++ b/src/gwin/gwin_options.h @@ -136,6 +136,13 @@ #define GWIN_NEED_RADIO FALSE #endif /** + * @brief Should list widget functions be included. + * @details Defaults to FALSE + */ + #ifndef GWIN_NEED_LIST + #define GWIN_NEED_LIST FALSE + #endif + /** * @brief Should tabset functions be included. * @details Defaults to FALSE */ @@ -308,6 +315,22 @@ #define GWIN_NEED_IMAGE_ANIMATION FALSE #endif /** + * @brief Enable the API to use attributes in the label widget + * @details Defaults to FALSE + * @note Using this feature is discouraged. The proper (and faster as well + * as more efficient) way is to use two separate labels. + */ + #ifndef GWIN_LABEL_ATTRIBUTE + #define GWIN_LABEL_ATTRIBUTE FALSE + #endif + /** + * @brief Enable the API to use images in items in the list widget + * @details Defaults to FALSE + */ + #ifndef GWIN_NEED_LIST_IMAGES + #define GWIN_NEED_LIST_IMAGES FALSE + #endif + /** * @brief Enable the API to automatically increment the progressbar over time * @details Defaults to FALSE */ diff --git a/src/gwin/gwin_progressbar.c b/src/gwin/gwin_progressbar.c index b1bc917c..d06f8058 100644 --- a/src/gwin/gwin_progressbar.c +++ b/src/gwin/gwin_progressbar.c @@ -283,7 +283,7 @@ void gwinProgressbarDraw_Image(GWidgetObject *gw, void *param) { // Vertical progressbar if (gw->g.width < gw->g.height) { if (gsw->dpos != 0) // The unfilled area - gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gw->pstyle->enabled.progress); // Inactive area + gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gsw->dpos-1, gw->pstyle->enabled.progress); // Inactive area if (gsw->dpos != gw->g.height-1) { // The filled area for(z=gw->g.height, v=gi->height; z > gsw->dpos;) { z -= v; @@ -291,25 +291,25 @@ void gwinProgressbarDraw_Image(GWidgetObject *gw, void *param) { v -= gsw->dpos - z; z = gsw->dpos; } - gdispGImageDraw(gw->g.display, gi, gw->g.x, gw->g.y+z, gw->g.width, v, 0, gi->height-v); + gdispGImageDraw(gw->g.display, gi, gw->g.x+1, gw->g.y+z+1, gw->g.width-1, v-2, 0, gi->height-v); } } gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge - gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, pcol->edge); // Thumb + gdispGDrawLine(gw->g.display, gw->g.x+1, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-2, gw->g.y+gsw->dpos, pcol->edge); // Thumb // Horizontal progressbar } else { if (gsw->dpos != gw->g.width-1) // The unfilled area - gdispGFillArea(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gw->pstyle->enabled.progress); // Inactive area + gdispGFillArea(gw->g.display, gw->g.x+gsw->dpos+1, gw->g.y+1, gw->g.width-gsw->dpos-2, gw->g.height-2, gw->pstyle->enabled.progress); // Inactive area if (gsw->dpos != 0) { // The filled area for(z=0, v=gi->width; z < gsw->dpos; z += v) { if (z+v > gsw->dpos) v -= z+v - gsw->dpos; - gdispGImageDraw(gw->g.display, gi, gw->g.x+z, gw->g.y, v, gw->g.height, 0, 0); + gdispGImageDraw(gw->g.display, gi, gw->g.x+z+1, gw->g.y+1, v-1, gw->g.height-2, 0, 0); } } gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge - gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, pcol->edge); // Thumb + gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos, gw->g.y+1, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-2, pcol->edge); // Thumb } gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); diff --git a/src/gwin/gwin_radio.c b/src/gwin/gwin_radio.c index 9b9f589b..6d9bd60e 100644 --- a/src/gwin/gwin_radio.c +++ b/src/gwin/gwin_radio.c @@ -21,9 +21,6 @@ #define GRADIO_BOTTOM_FADE 25 // (GRADIO_BOTTOM_FADE/255)% fade to black for bottom of tab/button #define GRADIO_OUTLINE_FADE 128 // (GRADIO_OUTLINE_FADE/255)% fade to background for active tab edge -// Our pressed state -#define GRADIO_FLG_PRESSED (GWIN_FIRST_CONTROL_FLAG<<0) - // Send the button event static void SendRadioEvent(GWidgetObject *gw) { GSourceListener * psl; diff --git a/src/gwin/gwin_radio.h b/src/gwin/gwin_radio.h index 17d64d8b..3371a9ef 100644 --- a/src/gwin/gwin_radio.h +++ b/src/gwin/gwin_radio.h @@ -46,6 +46,14 @@ typedef struct GEventGWinRadio { } GEventGWinRadio; /** + * @brief The internal radio button object flags + * @note Used only for writing a custom draw routine. + * @{ + */ +#define GRADIO_FLG_PRESSED 0x01 +/** @} */ + +/** * @brief The radio button widget structure * @note Do not use the members directly - treat it as a black-box. */ diff --git a/src/gwin/gwin_slider.c b/src/gwin/gwin_slider.c index 7415e4bb..d2e671b1 100644 --- a/src/gwin/gwin_slider.c +++ b/src/gwin/gwin_slider.c @@ -16,8 +16,6 @@ #include "gwin_class.h" -#define GSLIDER_FLG_EXTENDED_EVENTS (GWIN_FIRST_CONTROL_FLAG<<0) - // Calculate the slider position from the display position static int SliderCalcPosFromDPos(GSliderObject *gsw) { int halfbit; @@ -405,7 +403,7 @@ void gwinSliderDraw_Image(GWidgetObject *gw, void *param) { if (gw->g.width < gw->g.height) { // Vertical slider if (gsw->dpos != 0) // The unfilled area - gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gw->pstyle->enabled.progress); // Inactive area + gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gsw->dpos-1, gw->pstyle->enabled.progress); // Inactive area if (gsw->dpos != gw->g.height-1) { // The filled area for(z=gw->g.height, v=gi->height; z > gsw->dpos;) { z -= v; @@ -413,25 +411,25 @@ void gwinSliderDraw_Image(GWidgetObject *gw, void *param) { v -= gsw->dpos - z; z = gsw->dpos; } - gdispGImageDraw(gw->g.display, gi, gw->g.x, gw->g.y+z, gw->g.width, v, 0, gi->height-v); + gdispGImageDraw(gw->g.display, gi, gw->g.x+1, gw->g.y+z+1, gw->g.width-1, v-2, 0, gi->height-v); } } gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge - gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, pcol->edge); // Thumb + gdispGDrawLine(gw->g.display, gw->g.x+1, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-2, gw->g.y+gsw->dpos, pcol->edge); // Thumb // Horizontal slider } else { if (gsw->dpos != gw->g.width-1) // The unfilled area - gdispGFillArea(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gw->pstyle->enabled.progress); // Inactive area + gdispGFillArea(gw->g.display, gw->g.x+gsw->dpos+1, gw->g.y+1, gw->g.width-gsw->dpos-2, gw->g.height-2, gw->pstyle->enabled.progress); // Inactive area if (gsw->dpos != 0) { // The filled area for(z=0, v=gi->width; z < gsw->dpos; z += v) { if (z+v > gsw->dpos) v -= z+v - gsw->dpos; - gdispGImageDraw(gw->g.display, gi, gw->g.x+z, gw->g.y, v, gw->g.height, 0, 0); + gdispGImageDraw(gw->g.display, gi, gw->g.x+z+1, gw->g.y+1, v-1, gw->g.height-2, 0, 0); } } gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge - gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, pcol->edge); // Thumb + gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos, gw->g.y+1, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-2, pcol->edge); // Thumb } gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); diff --git a/src/gwin/gwin_slider.h b/src/gwin/gwin_slider.h index d42aa67b..a3c8489b 100644 --- a/src/gwin/gwin_slider.h +++ b/src/gwin/gwin_slider.h @@ -45,6 +45,14 @@ typedef struct GEventGWinSlider { // There are currently no GEventGWinSlider listening flags - use 0 +/** + * @brief The internal slider object flags + * @note Used only for writing a custom draw routine. + * @{ + */ +#define GSLIDER_FLG_EXTENDED_EVENTS 0x01 +/** @} */ + // A slider window typedef struct GSliderObject { GWidgetObject w; diff --git a/tools/studio/options.json b/tools/studio/options.json deleted file mode 100644 index edaf5efa..00000000 --- a/tools/studio/options.json +++ /dev/null @@ -1,471 +0,0 @@ -[ - { - "GOS" : [ - { - "Priorities" : [ - { - "User": "Low", - "Library": "LOW_PRIORITY" - }, - { - "User": "Normal", - "Library": "NORMAL_PRIORITY" - }, - { - "User": "High", - "Library": "HIGH_PRIORITY" - } - ] - } - ] - }, - { - "GDISP" : [ - { - "Orientations" : [ - { - "User": "Native", - "Library": "GDISP_ROTATE_0" - }, - { - "User": "Portrait", - "Library": "GDISP_ROTATE_PORTRAIT" - }, - { - "User": "Landscape", - "Library": "GDISP_ROTATE_LANDSCAPE" - }, - { - "User": "Rotate 90 degree", - "Library": "GDISP_ROTATE_90" - }, - { - "User": "Rotate 180 degree", - "Library": "GDISP_ROTATE_180" - }, - { - "User": "Rotate 270 degree", - "Library": "GDISP_ROTATE_270" - } - ] - }, - { - "Colors" : [ - { - "User": "White", - "Library" : "White", - "RGB": "0xFFFFFF" - }, - { - "User": "Black", - "Library": "Black", - "RGB": "0x000000" - }, - { - "User": "Gray", - "Library": "Gray", - "RGB": "0x808080" - }, - { - "User": "Blue", - "Library": "Blue", - "RGB": "0x0000FF" - }, - { - "User": "Red", - "Library": "Red", - "RGB": "0xFF0000" - }, - { - "User": "Magenta", - "Library": "Magenta", - "RGB": "0xFF00FF" - }, - { - "User": "Green", - "Library": "Green", - "RGB": "0x008000" - }, - { - "User": "Yellow", - "Library": "Yellow", - "RGB": "0xFFFF00" - }, - { - "User": "Cyan", - "Library": "Cyan", - "RGB": "0x00FFFF" - }, - { - "User": "Lime", - "Library": "Lime", - "RGB": "0x00FF00" - }, - { - "User": "Maroon", - "Library": "Maroon", - "RGB": "0x800000" - }, - { - "User": "Navy", - "Library": "Navy", - "RGB": "0x000080" - }, - { - "User": "Olive", - "Library": "Olive", - "RGB": "0x808000" - }, - { - "User": "Purple", - "Library": "Purple", - "RGB": "0x800080" - }, - { - "User": "Silver", - "Library": "Silver", - "RGB": "0xC0C0C0" - }, - { - "User": "Teal", - "Library": "Teal", - "RGB": "0x008080" - }, - { - "User": "Orange", - "Library": "Orange", - "RGB": "0xFFA500" - }, - { - "User": "Pink", - "Library": "Pink", - "RGB": "0xFFC0CB" - }, - { - "User": "SkyBlue", - "Library": "SkyBlue", - "RGB": "0x87CEEB" - } - ] - }, - { - "Justifications" : [ - { - "User": "Left", - "Library": "justifyLeft" - }, - { - "User": "Right", - "Library": "justifyRight" - }, - { - "User": "Center", - "Library": "justifyCenter" - } - ] - } - ] - }, - { - "GWIN" : [ - { - "Fonts" : [ - { - "User": "uGFX Font 1", - "Library": "UI1", - "Config": "GDISP_INCLUDE_FONT_UI1", - "Size": 10 - }, - { - "User": "uGFX Font 2", - "Library": "UI2", - "Config": "GDISP_INCLUDE_FONT_UI2", - "Size": 10 - }, - { - "User": "Fixed 5x8", - "Library": "fixed_5x8", - "Config": "GDISP_INCLUDE_FONT_FIXED_5X8", - "Size": 8 - }, - { - "User": "Fixed 7x14", - "Library": "fixed_7x14", - "Config": "GDISP_INCLUDE_FONT_FIXED_7X14", - "Size": 14 - }, - { - "User": "Fixed 10x20", - "Library": "fixed_10x20", - "Config": "GDISP_INCLUDE_FONT_FIXED_10X20", - "Size": 20 - }, - { - "User": "DejaVu Sans 10", - "Library": "DejaVuSans10", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS10", - "Size": 10 - }, - { - "User": "DejaVu Sans 12", - "Library": "DejaVuSans12", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS12", - "Size": 12 - }, - { - "User": "DejaVu Sans 16", - "Library": "DejaVuSans16", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS16", - "Size": 16 - }, - { - "User": "DejaVu Sans 20", - "Library": "DejaVuSans20", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS20", - "Size": 20 - }, - { - "User": "DejaVu Sans 24", - "Library": "DejaVuSans24", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS24", - "Size": 24 - }, - { - "User": "DejaVu Sans 32", - "Library": "DejaVuSans32", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS32", - "Size": 32 - }, - { - "User": "DejaVu Sans 12 Anti-Aliased", - "Library": "DejaVuSans12_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS12_AA", - "Size": 12 - }, - { - "User": "DejaVu Sans 16 Anti-Aliased", - "Library": "DejaVuSans16_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS16_AA", - "Size": 16 - }, - { - "User": "DejaVu Sans 20 Anti-Aliased", - "Library": "DejaVuSans20_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS20_AA", - "Size": 20 - }, - { - "User": "DejaVu Sans 24 Anti-Aliased", - "Library": "DejaVuSans24_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS24_AA", - "Size": 24 - }, - { - "User": "DejaVu Sans 32 Anti-Aliased", - "Library": "DejaVuSans32_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS32_AA", - "Size": 32 - }, - { - "User": "Large Numbers", - "Library": "LargeNumbers", - "Config": "GDISP_INCLUDE_FONT_LARGENUMBERS", - "Size": 23 - } - ] - }, - { - "Styles" : [ - { - "User": "White", - "Handle": "WhiteWidgetStyle", - "Colors": - { - "Background": - { - "User": "", - "Library": "", - "RGB": "0xFFFFFF" - }, - "Enabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0x000000" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - } - }, - "Disabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x808080" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0xC0E0C0" - } - }, - "Pressed": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0x808080" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x00E000" - } - } - } - }, - { - "User": "Black", - "Handle": "BlackWidgetStyle", - "Colors": - { - "Background": - { - "User": "", - "Library": "", - "RGB": "0x000000" - }, - "Enabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0x606060" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x404040" - } - }, - "Disabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0x808080" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x004000" - } - }, - "Pressed": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0xFFFFFF" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x008000" - } - } - } - } - ] - } - ] - } -] diff --git a/tools/studio/options_v1.json b/tools/studio/options_v1.json deleted file mode 100644 index edaf5efa..00000000 --- a/tools/studio/options_v1.json +++ /dev/null @@ -1,471 +0,0 @@ -[ - { - "GOS" : [ - { - "Priorities" : [ - { - "User": "Low", - "Library": "LOW_PRIORITY" - }, - { - "User": "Normal", - "Library": "NORMAL_PRIORITY" - }, - { - "User": "High", - "Library": "HIGH_PRIORITY" - } - ] - } - ] - }, - { - "GDISP" : [ - { - "Orientations" : [ - { - "User": "Native", - "Library": "GDISP_ROTATE_0" - }, - { - "User": "Portrait", - "Library": "GDISP_ROTATE_PORTRAIT" - }, - { - "User": "Landscape", - "Library": "GDISP_ROTATE_LANDSCAPE" - }, - { - "User": "Rotate 90 degree", - "Library": "GDISP_ROTATE_90" - }, - { - "User": "Rotate 180 degree", - "Library": "GDISP_ROTATE_180" - }, - { - "User": "Rotate 270 degree", - "Library": "GDISP_ROTATE_270" - } - ] - }, - { - "Colors" : [ - { - "User": "White", - "Library" : "White", - "RGB": "0xFFFFFF" - }, - { - "User": "Black", - "Library": "Black", - "RGB": "0x000000" - }, - { - "User": "Gray", - "Library": "Gray", - "RGB": "0x808080" - }, - { - "User": "Blue", - "Library": "Blue", - "RGB": "0x0000FF" - }, - { - "User": "Red", - "Library": "Red", - "RGB": "0xFF0000" - }, - { - "User": "Magenta", - "Library": "Magenta", - "RGB": "0xFF00FF" - }, - { - "User": "Green", - "Library": "Green", - "RGB": "0x008000" - }, - { - "User": "Yellow", - "Library": "Yellow", - "RGB": "0xFFFF00" - }, - { - "User": "Cyan", - "Library": "Cyan", - "RGB": "0x00FFFF" - }, - { - "User": "Lime", - "Library": "Lime", - "RGB": "0x00FF00" - }, - { - "User": "Maroon", - "Library": "Maroon", - "RGB": "0x800000" - }, - { - "User": "Navy", - "Library": "Navy", - "RGB": "0x000080" - }, - { - "User": "Olive", - "Library": "Olive", - "RGB": "0x808000" - }, - { - "User": "Purple", - "Library": "Purple", - "RGB": "0x800080" - }, - { - "User": "Silver", - "Library": "Silver", - "RGB": "0xC0C0C0" - }, - { - "User": "Teal", - "Library": "Teal", - "RGB": "0x008080" - }, - { - "User": "Orange", - "Library": "Orange", - "RGB": "0xFFA500" - }, - { - "User": "Pink", - "Library": "Pink", - "RGB": "0xFFC0CB" - }, - { - "User": "SkyBlue", - "Library": "SkyBlue", - "RGB": "0x87CEEB" - } - ] - }, - { - "Justifications" : [ - { - "User": "Left", - "Library": "justifyLeft" - }, - { - "User": "Right", - "Library": "justifyRight" - }, - { - "User": "Center", - "Library": "justifyCenter" - } - ] - } - ] - }, - { - "GWIN" : [ - { - "Fonts" : [ - { - "User": "uGFX Font 1", - "Library": "UI1", - "Config": "GDISP_INCLUDE_FONT_UI1", - "Size": 10 - }, - { - "User": "uGFX Font 2", - "Library": "UI2", - "Config": "GDISP_INCLUDE_FONT_UI2", - "Size": 10 - }, - { - "User": "Fixed 5x8", - "Library": "fixed_5x8", - "Config": "GDISP_INCLUDE_FONT_FIXED_5X8", - "Size": 8 - }, - { - "User": "Fixed 7x14", - "Library": "fixed_7x14", - "Config": "GDISP_INCLUDE_FONT_FIXED_7X14", - "Size": 14 - }, - { - "User": "Fixed 10x20", - "Library": "fixed_10x20", - "Config": "GDISP_INCLUDE_FONT_FIXED_10X20", - "Size": 20 - }, - { - "User": "DejaVu Sans 10", - "Library": "DejaVuSans10", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS10", - "Size": 10 - }, - { - "User": "DejaVu Sans 12", - "Library": "DejaVuSans12", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS12", - "Size": 12 - }, - { - "User": "DejaVu Sans 16", - "Library": "DejaVuSans16", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS16", - "Size": 16 - }, - { - "User": "DejaVu Sans 20", - "Library": "DejaVuSans20", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS20", - "Size": 20 - }, - { - "User": "DejaVu Sans 24", - "Library": "DejaVuSans24", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS24", - "Size": 24 - }, - { - "User": "DejaVu Sans 32", - "Library": "DejaVuSans32", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS32", - "Size": 32 - }, - { - "User": "DejaVu Sans 12 Anti-Aliased", - "Library": "DejaVuSans12_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS12_AA", - "Size": 12 - }, - { - "User": "DejaVu Sans 16 Anti-Aliased", - "Library": "DejaVuSans16_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS16_AA", - "Size": 16 - }, - { - "User": "DejaVu Sans 20 Anti-Aliased", - "Library": "DejaVuSans20_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS20_AA", - "Size": 20 - }, - { - "User": "DejaVu Sans 24 Anti-Aliased", - "Library": "DejaVuSans24_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS24_AA", - "Size": 24 - }, - { - "User": "DejaVu Sans 32 Anti-Aliased", - "Library": "DejaVuSans32_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS32_AA", - "Size": 32 - }, - { - "User": "Large Numbers", - "Library": "LargeNumbers", - "Config": "GDISP_INCLUDE_FONT_LARGENUMBERS", - "Size": 23 - } - ] - }, - { - "Styles" : [ - { - "User": "White", - "Handle": "WhiteWidgetStyle", - "Colors": - { - "Background": - { - "User": "", - "Library": "", - "RGB": "0xFFFFFF" - }, - "Enabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0x000000" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - } - }, - "Disabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x808080" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0xC0E0C0" - } - }, - "Pressed": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0x808080" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x00E000" - } - } - } - }, - { - "User": "Black", - "Handle": "BlackWidgetStyle", - "Colors": - { - "Background": - { - "User": "", - "Library": "", - "RGB": "0x000000" - }, - "Enabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0x606060" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x404040" - } - }, - "Disabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0x808080" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x004000" - } - }, - "Pressed": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0xFFFFFF" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x008000" - } - } - } - } - ] - } - ] - } -] diff --git a/tools/studio/options_v2.json b/tools/studio/options_v2.json deleted file mode 100644 index d6d7c99a..00000000 --- a/tools/studio/options_v2.json +++ /dev/null @@ -1,483 +0,0 @@ -[ - { - "GOS" : [ - { - "Priorities" : [ - { - "User": "Low", - "Library": "LOW_PRIORITY" - }, - { - "User": "Normal", - "Library": "NORMAL_PRIORITY" - }, - { - "User": "High", - "Library": "HIGH_PRIORITY" - } - ] - } - ] - }, - { - "GDISP" : [ - { - "Orientations" : [ - { - "User": "Native", - "Library": "GDISP_ROTATE_0" - }, - { - "User": "Portrait", - "Library": "GDISP_ROTATE_PORTRAIT" - }, - { - "User": "Landscape", - "Library": "GDISP_ROTATE_LANDSCAPE" - }, - { - "User": "Rotate 90 degree", - "Library": "GDISP_ROTATE_90" - }, - { - "User": "Rotate 180 degree", - "Library": "GDISP_ROTATE_180" - }, - { - "User": "Rotate 270 degree", - "Library": "GDISP_ROTATE_270" - } - ] - }, - { - "Colors" : [ - { - "User": "White", - "Library" : "White", - "RGB": "0xFFFFFF" - }, - { - "User": "Black", - "Library": "Black", - "RGB": "0x000000" - }, - { - "User": "Gray", - "Library": "Gray", - "RGB": "0x808080" - }, - { - "User": "Blue", - "Library": "Blue", - "RGB": "0x0000FF" - }, - { - "User": "Red", - "Library": "Red", - "RGB": "0xFF0000" - }, - { - "User": "Magenta", - "Library": "Magenta", - "RGB": "0xFF00FF" - }, - { - "User": "Green", - "Library": "Green", - "RGB": "0x008000" - }, - { - "User": "Yellow", - "Library": "Yellow", - "RGB": "0xFFFF00" - }, - { - "User": "Cyan", - "Library": "Cyan", - "RGB": "0x00FFFF" - }, - { - "User": "Lime", - "Library": "Lime", - "RGB": "0x00FF00" - }, - { - "User": "Maroon", - "Library": "Maroon", - "RGB": "0x800000" - }, - { - "User": "Navy", - "Library": "Navy", - "RGB": "0x000080" - }, - { - "User": "Olive", - "Library": "Olive", - "RGB": "0x808000" - }, - { - "User": "Purple", - "Library": "Purple", - "RGB": "0x800080" - }, - { - "User": "Silver", - "Library": "Silver", - "RGB": "0xC0C0C0" - }, - { - "User": "Teal", - "Library": "Teal", - "RGB": "0x008080" - }, - { - "User": "Orange", - "Library": "Orange", - "RGB": "0xFFA500" - }, - { - "User": "Pink", - "Library": "Pink", - "RGB": "0xFFC0CB" - }, - { - "User": "SkyBlue", - "Library": "SkyBlue", - "RGB": "0x87CEEB" - } - ] - }, - { - "Justifications" : [ - { - "User": "Left", - "Library": "justifyLeft" - }, - { - "User": "Right", - "Library": "justifyRight" - }, - { - "User": "Center", - "Library": "justifyCenter" - } - ] - } - ] - }, - { - "GWIN" : [ - { - "Fonts" : [ - { - "User": "uGFX Font 1", - "Library": "UI1", - "Config": "GDISP_INCLUDE_FONT_UI1", - "Size": 10 - }, - { - "User": "uGFX Font 2", - "Library": "UI2", - "Config": "GDISP_INCLUDE_FONT_UI2", - "Size": 10 - }, - { - "User": "Fixed 5x8", - "Library": "fixed_5x8", - "Config": "GDISP_INCLUDE_FONT_FIXED_5X8", - "Size": 8 - }, - { - "User": "Fixed 7x14", - "Library": "fixed_7x14", - "Config": "GDISP_INCLUDE_FONT_FIXED_7X14", - "Size": 14 - }, - { - "User": "Fixed 10x20", - "Library": "fixed_10x20", - "Config": "GDISP_INCLUDE_FONT_FIXED_10X20", - "Size": 20 - }, - { - "User": "DejaVu Sans 10", - "Library": "DejaVuSans10", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS10", - "Size": 10 - }, - { - "User": "DejaVu Sans 12", - "Library": "DejaVuSans12", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS12", - "Size": 12 - }, - { - "User": "DejaVu Sans 16", - "Library": "DejaVuSans16", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS16", - "Size": 16 - }, - { - "User": "DejaVu Sans 20", - "Library": "DejaVuSans20", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS20", - "Size": 20 - }, - { - "User": "DejaVu Sans 24", - "Library": "DejaVuSans24", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS24", - "Size": 24 - }, - { - "User": "DejaVu Sans 32", - "Library": "DejaVuSans32", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS32", - "Size": 32 - }, - { - "User": "DejaVu Sans 12 Anti-Aliased", - "Library": "DejaVuSans12_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS12_AA", - "Size": 12 - }, - { - "User": "DejaVu Sans 16 Anti-Aliased", - "Library": "DejaVuSans16_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS16_AA", - "Size": 16 - }, - { - "User": "DejaVu Sans 20 Anti-Aliased", - "Library": "DejaVuSans20_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS20_AA", - "Size": 20 - }, - { - "User": "DejaVu Sans 24 Anti-Aliased", - "Library": "DejaVuSans24_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS24_AA", - "Size": 24 - }, - { - "User": "DejaVu Sans 32 Anti-Aliased", - "Library": "DejaVuSans32_aa", - "Config": "GDISP_INCLUDE_FONT_DEJAVUSANS32_AA", - "Size": 32 - }, - { - "User": "Large Numbers", - "Library": "LargeNumbers", - "Config": "GDISP_INCLUDE_FONT_LARGENUMBERS", - "Size": 23 - } - ] - }, - { - "Styles" : [ - { - "User": "White", - "Handle": "WhiteWidgetStyle", - "Colors": - { - "Background": - { - "User": "", - "Library": "", - "RGB": "0xFFFFFF" - }, - "Focus": - { - "User": "", - "Library": "", - "RGB": "0x2A8FCD" - }, - "Enabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0x000000" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x00E000" - } - }, - "Disabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x808080" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0xC0E0C0" - } - }, - "Pressed": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0x808080" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x00E000" - } - } - } - }, - { - "User": "Black", - "Handle": "BlackWidgetStyle", - "Colors": - { - "Background": - { - "User": "", - "Library": "", - "RGB": "0x000000" - }, - "Focus": - { - "User": "", - "Library": "", - "RGB": "0x2A8FCD" - }, - "Enabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0x606060" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x008000" - } - }, - "Disabled": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0x808080" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0x404040" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x004000" - } - }, - "Pressed": - { - "Text": - { - "User": "", - "Library": "", - "RGB": "0xFFFFFF" - }, - "Edge": - { - "User": "", - "Library": "", - "RGB": "0xC0C0C0" - }, - "Fill": - { - "User": "", - "Library": "", - "RGB": "0xE0E0E0" - }, - "Progress": - { - "User": "", - "Library": "", - "RGB": "0x008000" - } - } - } - } - ] - } - ] - } -] |