Marcel Visser
/
DisplayBRW
brw1
Diff: RA8875/GraphicsDisplay.cpp
- Revision:
- 0:a115ff47d1c1
diff -r 000000000000 -r a115ff47d1c1 RA8875/GraphicsDisplay.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/GraphicsDisplay.cpp Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,563 @@ +/* mbed GraphicsDisplay Display Library Base Class + * Copyright (c) 2007-2009 sford + * Released under the MIT License: http://mbed.org/license/mit + * + * Derivative work by D.Smart 2014 + */ + +#include "GraphicsDisplay.h" +#include "Bitmap.h" +#include "string.h" + +//#define DEBUG "GD" +// ... +// INFO("Stuff to show %d", var); // new-line is automatically appended +// +#if (defined(DEBUG) && !defined(TARGET_LPC11U24)) +#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +static void HexDump(char * title, uint8_t * p, int count) +{ + int i; + char buf[100] = "0000: "; + + if (*title) + INFO("%s", title); + for (i=0; i<count; ) { + sprintf(buf + strlen(buf), "%02X ", *(p+i)); + if ((++i & 0x0F) == 0x00) { + INFO("%s", buf); + if (i < count) + sprintf(buf, "%04X: ", i); + else + buf[0] = '\0'; + } + } + if (strlen(buf)) + INFO("%s", buf); +} +#else +#define INFO(x, ...) +#define WARN(x, ...) +#define ERR(x, ...) +#define HexDump(a, b, c) +#endif + +#ifdef LOCALFONT +const unsigned char FONT8x8[97][8] = { + 0x08, 0x08, 0x08, 0X00, 0X00, 0X00, 0X00, 0X00, // columns, rows, num_bytes_per_char + 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // space 0x20 + 0x30, 0x78, 0x78, 0x30, 0x30, 0X00, 0x30, 0X00, // ! + 0x6C, 0x6C, 0x6C, 0X00, 0X00, 0X00, 0X00, 0X00, // " + 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0X00, // # + 0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0X00, // $ + 0X00, 0x63, 0x66, 0x0C, 0x18, 0x33, 0x63, 0X00, // % + 0x1C, 0x36, 0x1C, 0x3B, 0x6E, 0x66, 0x3B, 0X00, // & + 0x30, 0x30, 0x60, 0X00, 0X00, 0X00, 0X00, 0X00, // ' + 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0X00, // ( + 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0X00, // ) + 0X00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0X00, 0X00, // * + 0X00, 0x30, 0x30, 0xFC, 0x30, 0x30, 0X00, 0X00, // + + 0X00, 0X00, 0X00, 0X00, 0X00, 0x18, 0x18, 0x30, // , + 0X00, 0X00, 0X00, 0x7E, 0X00, 0X00, 0X00, 0X00, // - + 0X00, 0X00, 0X00, 0X00, 0X00, 0x18, 0x18, 0X00, // . + 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0X00, // / (forward slash) + 0x3E, 0x63, 0x63, 0x6B, 0x63, 0x63, 0x3E, 0X00, // 0 0x30 + 0x18, 0x38, 0x58, 0x18, 0x18, 0x18, 0x7E, 0X00, // 1 + 0x3C, 0x66, 0x06, 0x1C, 0x30, 0x66, 0x7E, 0X00, // 2 + 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0X00, // 3 + 0x0E, 0x1E, 0x36, 0x66, 0x7F, 0x06, 0x0F, 0X00, // 4 + 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0X00, // 5 + 0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0X00, // 6 + 0x7E, 0x66, 0x06, 0x0C, 0x18, 0x18, 0x18, 0X00, // 7 + 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0X00, // 8 + 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0X00, // 9 + 0X00, 0x18, 0x18, 0X00, 0X00, 0x18, 0x18, 0X00, // : + 0X00, 0x18, 0x18, 0X00, 0X00, 0x18, 0x18, 0x30, // ; + 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0X00, // < + 0X00, 0X00, 0x7E, 0X00, 0X00, 0x7E, 0X00, 0X00, // = + 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0X00, // > + 0x3C, 0x66, 0x06, 0x0C, 0x18, 0X00, 0x18, 0X00, // ? + 0x3E, 0x63, 0x6F, 0x69, 0x6F, 0x60, 0x3E, 0X00, // @ 0x40 + 0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0X00, // A + 0x7E, 0x33, 0x33, 0x3E, 0x33, 0x33, 0x7E, 0X00, // B + 0x1E, 0x33, 0x60, 0x60, 0x60, 0x33, 0x1E, 0X00, // C + 0x7C, 0x36, 0x33, 0x33, 0x33, 0x36, 0x7C, 0X00, // D + 0x7F, 0x31, 0x34, 0x3C, 0x34, 0x31, 0x7F, 0X00, // E + 0x7F, 0x31, 0x34, 0x3C, 0x34, 0x30, 0x78, 0X00, // F + 0x1E, 0x33, 0x60, 0x60, 0x67, 0x33, 0x1F, 0X00, // G + 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0X00, // H + 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // I + 0x0F, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0X00, // J + 0x73, 0x33, 0x36, 0x3C, 0x36, 0x33, 0x73, 0X00, // K + 0x78, 0x30, 0x30, 0x30, 0x31, 0x33, 0x7F, 0X00, // L + 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0X00, // M + 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63, 0x63, 0X00, // N + 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0X00, // O + 0x7E, 0x33, 0x33, 0x3E, 0x30, 0x30, 0x78, 0X00, // P 0x50 + 0x3C, 0x66, 0x66, 0x66, 0x6E, 0x3C, 0x0E, 0X00, // Q + 0x7E, 0x33, 0x33, 0x3E, 0x36, 0x33, 0x73, 0X00, // R + 0x3C, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x3C, 0X00, // S + 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // T + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7E, 0X00, // U + 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0X00, // V + 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0X00, // W + 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0X00, // X + 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0X00, // Y + 0x7F, 0x63, 0x46, 0x0C, 0x19, 0x33, 0x7F, 0X00, // Z + 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0X00, // [ + 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0X00, // \ (back slash) + 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0X00, // ] + 0x08, 0x1C, 0x36, 0x63, 0X00, 0X00, 0X00, 0X00, // ^ + 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0xFF, // _ + 0x18, 0x18, 0x0C, 0X00, 0X00, 0X00, 0X00, 0X00, // ` 0x60 + 0X00, 0X00, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0X00, // a + 0x70, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x6E, 0X00, // b + 0X00, 0X00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0X00, // c + 0x0E, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3B, 0X00, // d + 0X00, 0X00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0X00, // e + 0x1C, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0X00, // f + 0X00, 0X00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x7C, // g + 0x70, 0x30, 0x36, 0x3B, 0x33, 0x33, 0x73, 0X00, // h + 0x18, 0X00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0X00, // i + 0x06, 0X00, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, // j + 0x70, 0x30, 0x33, 0x36, 0x3C, 0x36, 0x73, 0X00, // k + 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // l + 0X00, 0X00, 0x66, 0x7F, 0x7F, 0x6B, 0x63, 0X00, // m + 0X00, 0X00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0X00, // n + 0X00, 0X00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0X00, // o + 0X00, 0X00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78, // p + 0X00, 0X00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F, // q + 0X00, 0X00, 0x6E, 0x3B, 0x33, 0x30, 0x78, 0X00, // r + 0X00, 0X00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0X00, // s + 0x08, 0x18, 0x3E, 0x18, 0x18, 0x1A, 0x0C, 0X00, // t + 0X00, 0X00, 0x66, 0x66, 0x66, 0x66, 0x3B, 0X00, // u + 0X00, 0X00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0X00, // v + 0X00, 0X00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0X00, // w + 0X00, 0X00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0X00, // x + 0X00, 0X00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x7C, // y + 0X00, 0X00, 0x7E, 0x4C, 0x18, 0x32, 0x7E, 0X00, // z + 0x0E, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0E, 0X00, // { + 0x0C, 0x0C, 0x0C, 0X00, 0x0C, 0x0C, 0x0C, 0X00, // | + 0x70, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x70, 0X00, // } + 0x3B, 0x6E, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // ~ + 0x1C, 0x36, 0x36, 0x1C, 0X00, 0X00, 0X00, 0X00 // DEL +}; +#endif // LOCALFONT + +char mytolower(char a) { + if (a >= 'A' && a <= 'Z') + return (a - 'A' + 'a'); + else + return a; +} +/// mystrnicmp exists because not all compiler libraries have this function. +/// +/// Some have strnicmp, others _strnicmp, and others have C++ methods, which +/// is outside the scope of this C-portable set of functions. +/// +/// @param l is a pointer to the string on the left +/// @param r is a pointer to the string on the right +/// @param n is the number of characters to compare +/// @returns -1 if l < r +/// @returns 0 if l == r +/// @returns +1 if l > r +/// +int mystrnicmp(const char *l, const char *r, size_t n) { + int result = 0; + + if (n != 0) { + do { + result = mytolower(*l++) - mytolower(*r++); + } while ((result == 0) && (*l != '\0') && (--n > 0)); + } + if (result < -1) + result = -1; + else if (result > 1) + result = 1; + return result; +} + + +GraphicsDisplay::GraphicsDisplay(const char *name) + : TextDisplay(name) +{ + font = NULL; +} + +RetCode_t GraphicsDisplay::set_font(const unsigned char * _font) +{ + font = _font; // trusting them, but it might be good to put some checks in here... + return noerror; +} + +#ifdef LOCALFONT +int GraphicsDisplay::character(int x, int y, int value) +{ + if (value <= 0x1F && value >= 7F) + return 0; + + return blitbit(x, y, FONT8X8[0][0], FONT8X8[0][1], + (char *)&(FONT8x8[value - 0x1F][0])); +} +#else +int GraphicsDisplay::character(int x, int y, int c) +{ + unsigned int offset; + const unsigned char * charRecord; + + if (c <= 0x1F || c >= 0x7F) + return 0; + offset = font[0]; // bytes / char + charRecord = &font[((c - ' ') * offset) + 4]; // start of char bitmap + return fontblit(x, y, font, charRecord); +} +#endif + +RetCode_t GraphicsDisplay::window(loc_t x, loc_t y, dim_t w, dim_t h) +{ + // current pixel location + _x = x; + _y = y; + // window settings + _x1 = x; + _x2 = x + w - 1; + _y1 = y; + _y2 = y + h - 1; + return noerror; +} + +RetCode_t GraphicsDisplay::WindowMax(void) +{ + return window(0,0, width(),height()); +} + +RetCode_t GraphicsDisplay::_putp(color_t color) +{ + pixel(_x, _y, color); + // update pixel location based on window settings + _x++; + if(_x > _x2) { + _x = _x1; + _y++; + if(_y > _y2) { + _y = _y1; + } + } + return noerror; +} + +RetCode_t GraphicsDisplay::fill(int x, int y, int w, int h, color_t color) +{ + return fillrect(x,y, x+w, y+h, color); +} + +RetCode_t GraphicsDisplay::cls(uint16_t layers) +{ + return fill(0, 0, width(), height(), _background); +} + +RetCode_t GraphicsDisplay::blit(int x, int y, int w, int h, const int * color) +{ + window(x, y, w, h); + _StartGraphicsStream(); + for (int i=0; i<w*h; i++) { + _putp(color[i]); + } + _EndGraphicsStream(); + return WindowMax(); +} + +#ifdef LOCALFONT +int GraphicsDisplay::blitbit(int x, int y, int w, int h, const char * color) +{ + _foreground = 0xFFFF; + INFO("blitbit(%d,%d, %d,%d, %02X) [%04X,%04X]", x,y, w,h, *color, _foreground, _background); + INFO("%lu %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + color, + color[0], color[1], color[2], color[3], color[4], color[5], color[6], color[7], + color[8], color[9], color[10], color[11], color[12], color[13], color[14], color[15]); + window(x, y, w, h); + _StartGraphicsStream(); + for (int i = 0; i < w*h; i++) { + char byte = color[i >> 3]; + int offset = i & 0x7; + if (offset == 0) + INFO(" %2d = %02X", i>>3, byte); + int c = ((byte << offset) & 0x80) ? _foreground : _background; + _putp(c); + } + _EndGraphicsStream(); + WindowMax(); + return w; +} +#endif + + +int GraphicsDisplay::fontblit(int x, int y, const unsigned char * fontTable, const unsigned char * fontChar) +{ + //int fontWidth = font[1]; // get hor size of font + int fontHeight = font[2]; // get vert size of font + int bytesPerLine = font[3]; // bytes per line + int charWidth = fontChar[0]; // width of this character + int px, py; + + //INFO("(%d,%d) %lu, %lu %X/%X", x,y, fontTable, fontChar, _foreground, _background); + //INFO("char size (%d,%d)", charWidth, fontHeight); + //HexDump("char", (uint8_t *)fontChar, 32); + //INFO("(f,b) = (%04X,%04X)", _foreground, _background) + window(x, y, charWidth, fontHeight); + _StartGraphicsStream(); + //INFO("(f,b) = (%04X,%04X)", _foreground, _background) + for (py = 0; py < fontHeight; py++) { + int bitmask = 1 << (py & 7); + + for (px = 0; px < charWidth; px++) { + int offset = (py / 8) + px * bytesPerLine; + unsigned char byte = fontChar[offset + 1]; // skip the char's # bits wide value + color_t c = (byte & bitmask) ? _foreground : _background; + //INFO("(%2d,%2d) %02X & %02X => %04X [%04X,%04X]", px, py, byte, bitmask, c, _foreground, _background); + //pixel(x+px, y+py, c); + _putp(c); + } + } + _EndGraphicsStream(); + WindowMax(); + return charWidth; +} + +// BMP Color Palette is BGRx +// BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000 +// RGB16 is +// RRRR RGGG GGGB BBBB +// swap to little endian +// GGGB BBBB RRRR RGGG +color_t GraphicsDisplay::RGBQuadToRGB16(RGBQUAD * colorPalette, uint16_t i) +{ + color_t c; + + c = ((colorPalette[i].rgbBlue >> 3) << 0); + c |= ((colorPalette[i].rgbGreen >> 2) << 5); + c |= ((colorPalette[i].rgbRed >> 3) << 11); + return c; +} + +/// RRRR RGGG GGGB BBBB +RGBQUAD GraphicsDisplay::RGB16ToRGBQuad(color_t c) +{ + RGBQUAD q; + + memset(&q, 0, sizeof(q)); + q.rgbBlue = ((c & 0x001F) << 3) | (c & 0x07); /* Blue value */ + q.rgbGreen = ((c & 0x07E0) >> 3) | ((c >> 7) & 0x03); /* Green value */ + q.rgbRed = ((c & 0xF800) >> 8) | ((c >> 11) & 0x07); /* Red value */ + q.rgbReserved = 0; + return q; +} + +RetCode_t GraphicsDisplay::_RenderBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image) +{ + BITMAPINFOHEADER BMP_Info; + RGBQUAD * colorPalette = NULL; + int colorCount; + uint8_t * lineBuffer = NULL; + color_t * pixelBuffer = NULL; + uint16_t BPP_t; + uint32_t PixelWidth, PixelHeight; + unsigned int i, offset; + int padd,j; + #ifdef DEBUG + uint32_t start_data; + #endif + + // Now, Read the bitmap info header + fread(&BMP_Info, 1, sizeof(BMP_Info), Image); + HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); + BPP_t = BMP_Info.biBitCount; + INFO("biBitCount %04X", BPP_t); + if (BPP_t != 4 && BPP_t != 8 && BPP_t != 16 && BPP_t != 24) { // Support 4, 8, 16, 24-bits per pixel + fclose(Image); + return(not_supported_format); + } + + PixelHeight = BMP_Info.biHeight; + PixelWidth = BMP_Info.biWidth; + INFO("(%d,%d) (%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight, width(), height()); + if (PixelHeight > height() + y || PixelWidth > width() + x) { + fclose(Image); + return(image_too_big); + } + if (BMP_Info.biBitCount <= 8) { + int paletteSize; + // Read the color palette + colorCount = 1 << BMP_Info.biBitCount; + paletteSize = sizeof(RGBQUAD) * colorCount; + colorPalette = (RGBQUAD *)malloc(paletteSize); + if (colorPalette == NULL) { + fclose(Image); + return(not_enough_ram); + } + fread(colorPalette, 1, paletteSize, Image); + HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize); + } + + int lineBufSize = ((BPP_t * PixelWidth + 7)/8); + INFO("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize); + lineBuffer = (uint8_t *)malloc(lineBufSize); + if (lineBuffer == NULL) { + free(colorPalette); + fclose(Image); + return(not_enough_ram); + } + pixelBuffer = (color_t *)malloc(PixelWidth * sizeof(color_t)); + if (pixelBuffer == NULL) { + free(lineBuffer); + if (colorPalette) + free(colorPalette); + fclose(Image); + return(not_enough_ram); + } + + // the Raw Data records are padded to a multiple of 4 bytes + int recordSize = 2; + if (BPP_t == 4) { + recordSize = 1; + } else if (BPP_t == 8) { + recordSize = 1; + } else if (BPP_t == 16) { + recordSize = 2; + } else if (BPP_t == 24) { + recordSize = 3; + } + padd = -1; + do { + padd++; + } while ((PixelWidth * recordSize + padd) % 4 != 0); + + // Define window for top to bottom and left to right so writing auto-wraps + window(x,y, PixelWidth,PixelHeight); + SetGraphicsCursor(x, y); + _StartGraphicsStream(); + + //start_data = BMP_Header.bfOffBits; + HexDump("Raw Data", (uint8_t *)&start_data, 32); + INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd); + for (j = PixelHeight - 1; j >= 0; j--) { //Lines bottom up + offset = fileOffset + j * (lineBufSize + padd); // start of line + fseek(Image, offset, SEEK_SET); + fread(lineBuffer, 1, lineBufSize, Image); // read a line - slow ! + //INFO("offset: %6X", offset); + for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT + if (BPP_t == 4) { + uint8_t dPix = lineBuffer[i/2]; + if ((i & 1) == 0) + dPix >>= 4; + dPix &= 0x0F; + pixelBuffer[i] = RGBQuadToRGB16(colorPalette, dPix); + } else if (BPP_t == 8) { + pixelBuffer[i] = RGBQuadToRGB16(colorPalette, lineBuffer[i]); + } else if (BPP_t == 16) { + pixelBuffer[i] = lineBuffer[i]; + } else if (BPP_t == 24) { + color_t color; + color = RGB(lineBuffer[i*3+2], lineBuffer[i*3+1], lineBuffer[i*3+0]); + pixelBuffer[i] = color; + } + } + pixelStream(pixelBuffer, PixelWidth, x, y++); + } + _EndGraphicsStream(); + WindowMax(); + free(pixelBuffer); // don't leak memory + free(lineBuffer); + if (colorPalette) + free(colorPalette); + return (noerror); +} + + +RetCode_t GraphicsDisplay::RenderImageFile(loc_t x, loc_t y, const char *FileName) +{ + if (mystrnicmp(FileName + strlen(FileName) - 4, ".bmp", 4) == 0) { + return RenderBitmapFile(x,y,FileName); + } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".ico", 4) == 0) { + return RenderIconFile(x,y,FileName); + } else { + return not_supported_format; + } +} + +RetCode_t GraphicsDisplay::RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP) +{ + BITMAPFILEHEADER BMP_Header; + + INFO("Opening {%s}", Name_BMP); + FILE *Image = fopen(Name_BMP, "rb"); + if (!Image) { + return(file_not_found); + } + + fread(&BMP_Header, 1, sizeof(BMP_Header), Image); // get the BMP Header + INFO("bfType %04X", BMP_Header.bfType); + HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); + if (BMP_Header.bfType != BF_TYPE) { + fclose(Image); + return(not_bmp_format); + } + RetCode_t rt = _RenderBitmap(x, y, BMP_Header.bfOffBits, Image); + if (rt != noerror) { + return rt; + } else { + fclose(Image); + return (noerror); + } +} + +RetCode_t GraphicsDisplay::RenderIconFile(loc_t x, loc_t y, const char *Name_ICO) +{ + ICOFILEHEADER ICO_Header; + ICODIRENTRY ICO_DirEntry; + + INFO("Opening {%s}", Name_ICO); + FILE *Image = fopen(Name_ICO, "rb"); + if (!Image) { + return(file_not_found); + } + + fread(&ICO_Header, 1, sizeof(ICO_Header), Image); // get the BMP Header + HexDump("ICO_Header", (uint8_t *)&ICO_Header, sizeof(ICO_Header)); + if (ICO_Header.Reserved_zero != 0 + || ICO_Header.icType != IC_TYPE + || ICO_Header.icImageCount == 0) { + fclose(Image); + return(not_ico_format); + } + + // Read ONLY the first of n possible directory entries. + fread(&ICO_DirEntry, 1, sizeof(ICO_DirEntry), Image); + HexDump("ICO_DirEntry", (uint8_t *)&ICO_DirEntry, sizeof(ICO_DirEntry)); + INFO("biBitCount %04X", ICO_DirEntry.biBitCount); + if (ICO_DirEntry.biBitCount != 0) { // Expecting this to be zero for ico + fclose(Image); + return(not_supported_format); + } + + RetCode_t rt = _RenderBitmap(x, y, ICO_DirEntry.bfOffBits, Image); + if (rt == noerror) { + fclose(Image); + return (noerror); + } else { + return rt; + } +} + +int GraphicsDisplay::columns() +{ + return width() / 8; +} + +int GraphicsDisplay::rows() +{ + return height() / 8; +}