diff options
Diffstat (limited to 'glcdgraphics')
-rw-r--r-- | glcdgraphics/bitmap.c | 448 | ||||
-rw-r--r-- | glcdgraphics/bitmap.h | 107 | ||||
-rw-r--r-- | glcdgraphics/font.c | 378 | ||||
-rw-r--r-- | glcdgraphics/font.h | 23 | ||||
-rw-r--r-- | glcdgraphics/glcd.c | 38 | ||||
-rw-r--r-- | glcdgraphics/pbm.c | 47 |
6 files changed, 675 insertions, 366 deletions
diff --git a/glcdgraphics/bitmap.c b/glcdgraphics/bitmap.c index d5ba159..c3d617a 100644 --- a/glcdgraphics/bitmap.c +++ b/glcdgraphics/bitmap.c @@ -9,7 +9,9 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2004 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * Andreas 'randy' Weinberger */ #include <stdio.h> @@ -25,21 +27,75 @@ namespace GLCD { + +cColor cColor::ParseColor(std::string col) { + if (col == "black") return cColor(cColor::Black); + else if (col == "white") return cColor(cColor::White); + else if (col == "red") return cColor(cColor::Red); + else if (col == "green") return cColor(cColor::Green); + else if (col == "blue") return cColor(cColor::Blue); + else if (col == "magenta") return cColor(cColor::Magenta); + else if (col == "cyan") return cColor(cColor::Cyan); + else if (col == "yellow") return cColor(cColor::Yellow); + else if (col == "transparent") return cColor(cColor::Transparent); + else if (col.substr(0, 2) == "0x" || col.substr(0, 2) == "0X") { + if (col.length() <= 2 || col.length() > 10) + return cColor(cColor::ERRCOL); + + char* tempptr; + const char* str = col.c_str(); + uint32_t rv = (uint32_t) strtol(str, &tempptr, 16); + + if ((str == tempptr) || (*tempptr != '\0')) + return cColor(cColor::ERRCOL); + + if (col.length() <= 8) // eg. 0xRRGGBB -> 0xFFRRGGBB + rv |= 0xFF000000; + return cColor(rv); + } + return cColor(cColor::ERRCOL); +} + +cColor cColor::Invert(void) +{ + return cColor( (uint32_t)(color ^ 0x00FFFFFF) ) ; +} + + const unsigned char bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; const unsigned char bitmaskl[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; const unsigned char bitmaskr[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; -cBitmap::cBitmap(int width, int height, unsigned char * data) +cBitmap::cBitmap(int width, int height, uint32_t * data) : width(width), height(height), - bitmap(NULL) + bitmap(NULL), + ismonochrome(false) { - // lines are byte aligned - lineSize = (width + 7) / 8; +#ifdef DEBUG + printf("%s:%s(%d) cBitmap Size %03d * %03d\n", __FILE__, __FUNCTION__, __LINE__, width, height); +#endif - bitmap = new unsigned char[lineSize * height]; - if (data) - memcpy(bitmap, data, lineSize * height); + bitmap = new uint32_t[width * height]; + if (data) { + memcpy(bitmap, data, width * height * sizeof(uint32_t)); + } + backgroundColor = cColor::White; +} + + +cBitmap::cBitmap(int width, int height, uint32_t initcol) +: width(width), + height(height), + bitmap(NULL), + ismonochrome(false) +{ +#ifdef DEBUG + printf("%s:%s(%d) cBitmap Size %03d * %03d\n", __FILE__, __FUNCTION__, __LINE__, width, height); +#endif + + bitmap = new uint32_t[width * height]; + Clear(initcol); } cBitmap::cBitmap(const cBitmap & b) @@ -47,9 +103,12 @@ cBitmap::cBitmap(const cBitmap & b) width = b.width; height = b.height; lineSize = b.lineSize; - bitmap = new unsigned char[lineSize * height]; - if (b.bitmap) - memcpy(bitmap, b.bitmap, lineSize * height); + backgroundColor = b.backgroundColor; + ismonochrome = b.ismonochrome; + bitmap = new uint32_t[b.width * b.height]; + if (b.bitmap) { + memcpy(bitmap, b.bitmap, b.width * b.height * sizeof(uint32_t)); + } } cBitmap::~cBitmap() @@ -57,35 +116,41 @@ cBitmap::~cBitmap() delete[] bitmap; } -void cBitmap::Clear() +void cBitmap::Clear(uint32_t initcol) { - memset(bitmap, 0, lineSize * height); +#ifdef DEBUG + printf("%s:%s(%d) %03d * %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, width, height, color); +#endif + uint32_t col = (initcol == cColor::Transparent) ? backgroundColor : initcol; + for (int i = 0; i < width * height; i++) + bitmap[i] = col; + backgroundColor = col; } void cBitmap::Invert() { int i; - for (i = 0; i < lineSize * height; i++) + for (i = 0; i < width * height; i++) { - bitmap[i] ^= 0xFF; + bitmap[i] ^= 0xFFFFFF; } } -void cBitmap::DrawPixel(int x, int y, eColor color) +void cBitmap::DrawPixel(int x, int y, uint32_t color) { if (x < 0 || x > width - 1) return; if (y < 0 || y > height - 1) return; - unsigned char c = 0x80 >> (x % 8); - if (color == clrBlack) - bitmap[lineSize * y + x / 8] |= c; + if (color != GLCD::cColor::Transparent) + bitmap[x + (width * y)] = cColor::AlignAlpha(color); else - bitmap[lineSize * y + x / 8] &= ~c; + bitmap[x + (width * y)] = cColor::AlignAlpha(backgroundColor); } +/* void cBitmap::Draw8Pixels(int x, int y, unsigned char pixels, eColor color) { if (x < 0 || x > width - 1) @@ -98,12 +163,15 @@ void cBitmap::Draw8Pixels(int x, int y, unsigned char pixels, eColor color) else bitmap[lineSize * y + x / 8] &= ~pixels; } +*/ -void cBitmap::DrawLine(int x1, int y1, int x2, int y2, eColor color) +void cBitmap::DrawLine(int x1, int y1, int x2, int y2, uint32_t color) { int d, sx, sy, dx, dy; unsigned int ax, ay; + color = cColor::AlignAlpha(color); + dx = x2 - x1; ax = abs(dx) << 1; if (dx < 0) @@ -151,43 +219,43 @@ void cBitmap::DrawLine(int x1, int y1, int x2, int y2, eColor color) } } -void cBitmap::DrawHLine(int x1, int y, int x2, eColor color) +void cBitmap::DrawHLine(int x1, int y, int x2, uint32_t color) { - sort(x1,x2); +#ifdef DEBUG + printf("%s:%s(%d) %03d -> %03d, %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x1, x2, y, color); +#endif + color = cColor::AlignAlpha(color); - if (x1 / 8 == x2 / 8) - { - // start and end in the same byte - Draw8Pixels(x1, y, bitmaskr[x1 % 8] & bitmaskl[x2 % 8], color); - } - else - { - // start and end in different bytes - Draw8Pixels(x1, y, bitmaskr[x1 % 8], color); - x1 = ((x1 + 8) / 8) * 8; - while (x1 < (x2 / 8) * 8) - { - Draw8Pixels(x1, y, 0xff, color); - x1 += 8; - } - Draw8Pixels(x2, y, bitmaskl[x2 % 8], color); - } + sort(x1,x2); + while (x1 <= x2) { + DrawPixel(x1, y, color); + x1++; + }; } -void cBitmap::DrawVLine(int x, int y1, int y2, eColor color) +void cBitmap::DrawVLine(int x, int y1, int y2, uint32_t color) { - int y; +#ifdef DEBUG + printf("%s:%s(%d) %03d, %03d -> %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x, y1, y2, color); +#endif + color = cColor::AlignAlpha(color); sort(y1,y2); - - for (y = y1; y <= y2; y++) - DrawPixel(x, y, color); + while (y1 <= y2) { + DrawPixel(x, y1, color); + y1++; + } } -void cBitmap::DrawRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled) +void cBitmap::DrawRectangle(int x1, int y1, int x2, int y2, uint32_t color, bool filled) { +#ifdef DEBUG + printf("%s:%s(%d) %03d * %03d -> %03d * %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2, color); +#endif int y; + color = cColor::AlignAlpha(color); + sort(x1,x2); sort(y1,y2); @@ -207,8 +275,13 @@ void cBitmap::DrawRectangle(int x1, int y1, int x2, int y2, eColor color, bool f } } -void cBitmap::DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled, int type) +void cBitmap::DrawRoundRectangle(int x1, int y1, int x2, int y2, uint32_t color, bool filled, int type) { +#ifdef DEBUG + printf("%s:%s(%d) %03d * %03d -> %03d * %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2, color); +#endif + color = cColor::AlignAlpha(color); + sort(x1,x2); sort(y1,y2); @@ -230,10 +303,14 @@ void cBitmap::DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, b if (type == 4) { // round the ugly fat box... - DrawPixel(x1 + 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite); - DrawPixel(x1 + 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite); - DrawPixel(x2 - 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite); - DrawPixel(x2 - 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite); +// DrawPixel(x1 + 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite); +// DrawPixel(x1 + 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite); +// DrawPixel(x2 - 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite); +// DrawPixel(x2 - 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite); + DrawPixel(x1 + 1, y1 + 1, backgroundColor); + DrawPixel(x1 + 1, y2 - 1, backgroundColor); + DrawPixel(x2 - 1, y1 + 1, backgroundColor); + DrawPixel(x2 - 1, y2 - 1, backgroundColor); } } else @@ -256,8 +333,13 @@ void cBitmap::DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, b } } -void cBitmap::DrawEllipse(int x1, int y1, int x2, int y2, eColor color, bool filled, int quadrants) +void cBitmap::DrawEllipse(int x1, int y1, int x2, int y2, uint32_t color, bool filled, int quadrants) { +#ifdef DEBUG + printf("%s:%s(%d) %03d * %03d -> %03d * %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2, color); +#endif + color = cColor::AlignAlpha(color); + // Algorithm based on http://homepage.smc.edu/kennedy_john/BELIPSE.PDF int rx = x2 - x1; int ry = y2 - y1; @@ -397,8 +479,13 @@ void cBitmap::DrawEllipse(int x1, int y1, int x2, int y2, eColor color, bool fil } } -void cBitmap::DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type) +void cBitmap::DrawSlope(int x1, int y1, int x2, int y2, uint32_t color, int type) { +#ifdef DEBUG + printf("%s:%s(%d) %03d * %03d -> %03d * %03d\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2); +#endif + color = cColor::AlignAlpha(color); + bool upper = type & 0x01; bool falling = type & 0x02; bool vertical = type & 0x04; @@ -410,7 +497,7 @@ void cBitmap::DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type) if (falling) c = -c; int x = int((x2 - x1 + 1) * c / 2); - if (upper && !falling || !upper && falling) + if ((upper && !falling) || (!upper && falling)) DrawRectangle(x1, y, (x1 + x2) / 2 + x, y, color, true); else DrawRectangle((x1 + x2) / 2 + x, y, x2, y, color, true); @@ -432,83 +519,56 @@ void cBitmap::DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type) } } -void cBitmap::DrawBitmap(int x, int y, const cBitmap & bitmap, eColor color) +void cBitmap::DrawBitmap(int x, int y, const cBitmap & bitmap, uint32_t color, uint32_t bgcolor) { - unsigned char cl = 0; - int xt, yt; - const unsigned char * data = bitmap.Data(); - unsigned short temp; - int h, w; +#ifdef DEBUG + printf("%s:%s(%d) '%03d' x '%03d' \n", __FILE__, __FUNCTION__, __LINE__, x, y); +#endif + color = cColor::AlignAlpha(color); + bgcolor = cColor::AlignAlpha(bgcolor); - w = bitmap.Width(); - h = bitmap.Height(); + uint32_t cl = 0; + const uint32_t * data = bitmap.Data(); + bool ismonochrome = bitmap.IsMonochrome(); + + int xt, yt; if (data) { - if (!(x % 8)) - { - // Bitmap is byte alligned (0,8,16,...) - for (yt = 0; yt < h; yt++) - { - for (xt = 0; xt < (w / 8); xt++) - { - cl = *data; - Draw8Pixels(x + (xt * 8), y + yt, cl, color); - data++; - } - if (w % 8) - { - cl = *data; - Draw8Pixels(x + ((w / 8) * 8), y + yt, cl & bitmaskl[w % 8 - 1], color); - data++; - } - } - } - else + for (yt = 0; yt < bitmap.Height(); yt++) { - // Bitmap is not byte alligned - for (yt = 0; yt < h; yt++) - { - temp = 0; - for (xt = 0; xt < (w + (x % 8)) / 8; xt++) - { - cl = *(data + yt * ((w + 7) / 8) + xt); - temp = temp | ((unsigned short) cl << (8 - (x % 8))); - cl = (temp & 0xff00) >> 8; - if (!xt) - { - // first byte - Draw8Pixels(x - (x % 8) + (xt * 8), y + yt, cl & bitmaskr[x % 8], color); - } - else - { - // not the first byte - Draw8Pixels(x - (x % 8) + (xt * 8), y + yt, cl, color); - } - temp <<= 8; - } - if ((w + (x % 8) + 7) / 8 != (w + (x % 8)) / 8) - { - // print the rest - cl = *(data + (yt + 1) * ((w + 7) / 8) - 1); - temp = temp | ((unsigned short) cl << (8 - (x % 8))); - cl = (temp & 0xff00) >> 8; - Draw8Pixels(x - (x % 8) + (((w + (x % 8)) / 8) * 8), y + yt, cl & bitmaskl[(w + x) % 8 - 1], color); - } + for (xt = 0; xt < bitmap.Width(); xt++) + { + cl = data[(yt * bitmap.Width())+xt]; + if (ismonochrome) { + DrawPixel(xt+x, yt+y, (cl == cColor::Black) ? color : bgcolor); + } else { + DrawPixel(xt+x, yt+y, cl); } - } + } + } } } int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cFont * font, - eColor color, bool proportional, int skipPixels) + uint32_t color, uint32_t bgcolor, bool proportional, int skipPixels) { +#ifdef DEBUG + printf("%s:%s(%d) text '%s', color '%08x'/'%08x'\n", __FILE__, __FUNCTION__, __LINE__, text.c_str(), color, bgcolor); +#endif int xt; int yt; int i; - char c; + uint32_t c; + uint32_t c0; + uint32_t c1; + uint32_t c2; + uint32_t c3; int start; + color = cColor::AlignAlpha(color); + bgcolor = cColor::AlignAlpha(bgcolor); + clip(x, 0, width - 1); clip(y, 0, height - 1); @@ -544,9 +604,41 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF } } } - for (i = start; i < (int) text.length(); i++) + + i = start; + while (i < (int) text.length()) +// for (i = start; i < (int) text.length(); i++) { c = text[i]; + + if ( font->IsUTF8() ) { + c0 = text[i]; + c1 = (i+1 < (int)text.length()) ? text[i+1] : 0; + c2 = (i+2 < (int)text.length()) ? text[i+2] : 0; + c3 = (i+3 < (int)text.length()) ? text[i+3] : 0; + c0 &=0xff; c1 &=0xff; c2 &=0xff; c3 &=0xff; + + if( c0 >= 0xc2 && c0 <= 0xdf && c1 >= 0x80 && c1 <= 0xbf ) { + //2 byte UTF-8 sequence found + i+=1; + c = ((c0&0x1f)<<6) | (c1&0x3f); + } else if ((c0 == 0xE0 && c1 >= 0xA0 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xE1 && c1 <= 0xEC && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 == 0xED && c1 >= 0x80 && c1 <= 0x9f && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xEE && c0 <= 0xEF && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) ) { + //3 byte UTF-8 sequence found + c = ((c0&0x0f)<<4) | ((c1&0x3f)<<6) | (c2&0x3f); + i+=2; + } else if ( (c0 == 0xF0 && c1 >= 0x90 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) + || (c0 >= 0xF1 && c0 >= 0xF3 && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && + c3 >= 0x80 && c3 <= 0xbf) + || (c0 == 0xF4 && c1 >= 0x80 && c1 <= 0x8f && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) ) { + //4 byte UTF-8 sequence found + c = ((c0&0x07)<<2) | ((c1&0x3f)<<4) | ((c2&0x3f)<<6) | (c3&0x3f); + i+=3; + } + } + if (xt > xmax) { i = text.length(); @@ -557,13 +649,13 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF { if (skipPixels > 0) { - DrawCharacter(xt, yt, xmax, c, font, color, skipPixels); + DrawCharacter(xt, yt, xmax, c, font, color, bgcolor, skipPixels); xt += font->TotalWidth() - skipPixels; skipPixels = 0; } else { - DrawCharacter(xt, yt, xmax, c, font, color); + DrawCharacter(xt, yt, xmax, c, font, color, bgcolor); xt += font->TotalWidth(); } } @@ -571,12 +663,12 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF { if (skipPixels > 0) { - xt += DrawCharacter(xt, yt, xmax, c, font, color, skipPixels); + xt += DrawCharacter(xt, yt, xmax, c, font, color, bgcolor, skipPixels); skipPixels = 0; } else { - xt += DrawCharacter(xt, yt, xmax, c, font, color); + xt += DrawCharacter(xt, yt, xmax, c, font, color, bgcolor); } if (xt <= xmax) { @@ -584,15 +676,26 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF } } } + i++; } } return xt; } -int cBitmap::DrawCharacter(int x, int y, int xmax, char c, const cFont * font, - eColor color, int skipPixels) +int cBitmap::DrawCharacter(int x, int y, int xmax, uint32_t c, const cFont * font, + uint32_t color, uint32_t bgcolor, int skipPixels) { +#ifdef DEBUG + printf("%s:%s(%d) %03d * %03d char '%c' color '%08x' bgcolor '%08x'\n", __FILE__, __FUNCTION__, __LINE__, x, y, c, color, bgcolor); +#endif const cBitmap * charBitmap; + cBitmap * drawBitmap; + + color = cColor::AlignAlpha(color); + bgcolor = cColor::AlignAlpha(bgcolor); + + uint32_t dot = 0; + int xt, yt; clip(x, 0, width - 1); clip(y, 0, height - 1); @@ -600,32 +703,43 @@ int cBitmap::DrawCharacter(int x, int y, int xmax, char c, const cFont * font, charBitmap = font->GetCharacter(c); if (charBitmap) { - cBitmap * drawBitmap = charBitmap->SubBitmap(skipPixels, 0, xmax - x + skipPixels, charBitmap->Height() - 1); - if (drawBitmap) - DrawBitmap(x, y, *drawBitmap, color); - delete drawBitmap; + drawBitmap = new cBitmap(charBitmap->Width()-skipPixels,charBitmap->Height()); + drawBitmap->Clear(bgcolor); + if (drawBitmap) { + for (xt=0;xt<charBitmap->Width();xt++) { + for (yt=0;yt<charBitmap->Height();yt++) { + dot = charBitmap->GetPixel(xt+skipPixels,yt); + if ((dot | 0xFF000000) == cColor::Black) { // todo: does not work with antialising? + drawBitmap->DrawPixel(xt, yt, color); + } else { + drawBitmap->DrawPixel(xt, yt, bgcolor); + } + } + } + DrawBitmap(x, y, *drawBitmap); + delete drawBitmap; + } return charBitmap->Width() - skipPixels; } return 0; } -unsigned char cBitmap::GetPixel(int x, int y) const +uint32_t cBitmap::GetPixel(int x, int y) const { - unsigned char value; - - value = bitmap[y * lineSize + x / 8]; - value = (value >> (7 - (x % 8))) & 1; + uint32_t value; + value = bitmap[y * width + x]; return value; } cBitmap * cBitmap::SubBitmap(int x1, int y1, int x2, int y2) const { +#ifdef DEBUG + printf("%s:%s(%d) %03d * %03d / %03d * %03d\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2); +#endif int w, h; int xt, yt; cBitmap * bmp; - unsigned char cl; - unsigned char * data; - unsigned short temp; + uint32_t cl; sort(x1,x2); sort(y1,y2); @@ -642,62 +756,23 @@ cBitmap * cBitmap::SubBitmap(int x1, int y1, int x2, int y2) const if (!bmp || !bmp->Data()) return NULL; bmp->Clear(); - if (x1 % 8 == 0) - { - // Bitmap is byte alligned (0,8,16,...) - for (yt = 0; yt < h; yt++) - { - data = &bitmap[(y1 + yt) * lineSize + x1 / 8]; - for (xt = 0; xt < (w / 8) * 8; xt += 8) - { - cl = *data; - bmp->Draw8Pixels(xt, yt, cl, clrBlack); - data++; - } - if (w % 8 != 0) - { - cl = *data; - bmp->Draw8Pixels(xt, yt, cl & bitmaskl[w % 8 - 1], clrBlack); - } - } - } - else + + for (yt = 0; yt < h; yt++) { - // Bitmap is not byte alligned - for (yt = 0; yt < h; yt++) - { - temp = 0; - data = &bitmap[(y1 + yt) * lineSize + x1 / 8]; - for (xt = 0; xt <= ((w / 8)) * 8; xt += 8) - { - cl = *data; - temp = temp | ((unsigned short) cl << (x1 % 8)); - cl = (temp & 0xff00) >> 8; - if (xt > 0) - { - bmp->Draw8Pixels(xt - 8, yt, cl, clrBlack); - } - temp <<= 8; - data++; - } - if (w % 8 != 0) - { - // print the rest - if (8 - (x1 % 8) < w % 8) - { - cl = *data; - temp = temp | ((unsigned short) cl << (x1 % 8)); - } - cl = (temp & 0xff00) >> 8; - bmp->Draw8Pixels(xt - 8, yt, cl & bitmaskl[(w % 8) - 1], clrBlack); - } - } + for (xt = 0; xt < w; xt++) + { + cl = bitmap[(w*yt+y1)+xt+x1]; + bmp->DrawPixel(xt,yt, cl); + } } return bmp; } bool cBitmap::LoadPBM(const std::string & fileName) { +#ifdef DEBUG + printf("%s:%s(%d)\n", __FILE__, __FUNCTION__, __LINE__); +#endif FILE * pbmFile; char str[32]; int i; @@ -776,10 +851,8 @@ bool cBitmap::LoadPBM(const std::string & fileName) delete[] bitmap; width = w; height = h; - // lines are byte aligned - lineSize = (width + 7) / 8; - bitmap = new unsigned char[lineSize * height]; - fread(bitmap, lineSize * height, 1, pbmFile); + bitmap = new uint32_t [width * height]; + fread(bitmap, width * height, 1, pbmFile); fclose(pbmFile); return true; @@ -787,6 +860,9 @@ bool cBitmap::LoadPBM(const std::string & fileName) void cBitmap::SavePBM(const std::string & fileName) { +#ifdef DEBUG + printf("%s:%s(%d)\n", __FILE__, __FUNCTION__, __LINE__); +#endif int i; char str[32]; FILE * fp; diff --git a/glcdgraphics/bitmap.h b/glcdgraphics/bitmap.h index b6446a0..d87745d 100644 --- a/glcdgraphics/bitmap.h +++ b/glcdgraphics/bitmap.h @@ -9,22 +9,70 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2004 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * Andreas 'randy' Weinberger */ #ifndef _GLCDGRAPHICS_BITMAP_H_ #define _GLCDGRAPHICS_BITMAP_H_ #include <string> +#include <inttypes.h> + +// graphlcd-base uses ARGB bitmaps instead of 1bit ones +#define GRAPHLCD_CBITMAP_ARGB namespace GLCD { +#if 0 enum eColor { - clrBlack, - clrWhite + clrTransparent, + clrGray50, + clrBlack, + clrRed, + clrGreen, + clrYellow, + clrMagenta, + clrBlue, + clrCyan, + clrWhite }; +#endif + + +class cColor +{ +public: + uint32_t color; + + cColor(uint32_t col) { color = col; } + cColor(const cColor & col) { color = col.color; } + + static const uint32_t Black = 0xFF000000; + static const uint32_t White = 0xFFFFFFFF; + static const uint32_t Red = 0xFFFF0000; + static const uint32_t Green = 0xFF00FF00; + static const uint32_t Blue = 0xFF0000FF; + static const uint32_t Magenta = 0xFFFF00FF; + static const uint32_t Cyan = 0xFF00FFFF; + static const uint32_t Yellow = 0xFFFFFF00; + static const uint32_t Transparent = 0x00FFFFFF; + static const uint32_t ERRCOL = 0x00000000; + + operator uint32_t(void) { return color; } + + uint32_t GetColor (void) { return color; } + void SetColor (uint32_t col) { color = col; } + + cColor Invert (void); + + static cColor ParseColor (std::string col); + static uint32_t AlignAlpha (uint32_t col) { return (col & 0xFF000000) ? col : (col | 0xFF000000); } +}; + class cFont; @@ -34,37 +82,54 @@ protected: int width; int height; int lineSize; - unsigned char * bitmap; + uint32_t * bitmap; + bool ismonochrome; + + uint32_t backgroundColor; public: - cBitmap(int width, int height, unsigned char * data = NULL); + cBitmap(int width, int height, uint32_t * data = NULL); + cBitmap(int width, int height, uint32_t initcol); cBitmap(const cBitmap & b); ~cBitmap(); int Width() const { return width; } int Height() const { return height; } int LineSize() const { return lineSize; } - const unsigned char * Data() const { return bitmap; } + const uint32_t * Data() const { return bitmap; } - void Clear(); + void Clear(uint32_t initcol = cColor::Transparent); void Invert(); - void DrawPixel(int x, int y, eColor color); - void Draw8Pixels(int x, int y, unsigned char pixels, eColor color); - void DrawLine(int x1, int y1, int x2, int y2, eColor color); - void DrawHLine(int x1, int y, int x2, eColor color); - void DrawVLine(int x, int y1, int y2, eColor color); - void DrawRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled); - void DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled, int size); - void DrawEllipse(int x1, int y1, int x2, int y2, eColor color, bool filled, int quadrants); - void DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type); - void DrawBitmap(int x, int y, const cBitmap & bitmap, eColor color); + void DrawPixel(int x, int y, uint32_t color); + void DrawLine(int x1, int y1, int x2, int y2, uint32_t color); + void DrawHLine(int x1, int y, int x2, uint32_t color); + void DrawVLine(int x, int y1, int y2, uint32_t color); + void DrawRectangle(int x1, int y1, int x2, int y2, uint32_t color, bool filled); + void DrawRoundRectangle(int x1, int y1, int x2, int y2, uint32_t color, bool filled, int size); + void DrawEllipse(int x1, int y1, int x2, int y2, uint32_t color, bool filled, int quadrants); + void DrawSlope(int x1, int y1, int x2, int y2, uint32_t color, int type); + void DrawBitmap(int x, int y, const cBitmap & bitmap, uint32_t color = cColor::White, uint32_t bgcolor = cColor::Black); int DrawText(int x, int y, int xmax, const std::string & text, const cFont * font, - eColor color = clrBlack, bool proportional = true, int skipPixels = 0); - int DrawCharacter(int x, int y, int xmax, char c, const cFont * font, - eColor color = clrBlack, int skipPixels = 0); + uint32_t color = cColor::White, uint32_t bgcolor = cColor::Black, bool proportional = true, int skipPixels = 0); + int DrawCharacter(int x, int y, int xmax, uint32_t c, const cFont * font, + uint32_t color = cColor::White, uint32_t bgcolor = cColor::Black, int skipPixels = 0); cBitmap * SubBitmap(int x1, int y1, int x2, int y2) const; - unsigned char GetPixel(int x, int y) const; + uint32_t GetPixel(int x, int y) const; + + void SetMonochrome(bool mono) { ismonochrome = mono; } + bool IsMonochrome(void) const { return ismonochrome; } + +#if 0 + int DrawText(int x, int y, int xmax, const std::string & text, const cFont * font, + uint32_t color, bool proportional = true, int skipPixels = 0) { + return DrawText(x, y, xmax, text, font, color, cColor::Black, proportional, skipPixels); + } + int DrawCharacter(int x, int y, int xmax, char c, const cFont * font, + uint32_t color, int skipPixels = 0) { + return DrawCharacter(x, y, xmax, c, font, color, cColor::Black, skipPixels); + } +#endif bool LoadPBM(const std::string & fileName); void SavePBM(const std::string & fileName); diff --git a/glcdgraphics/font.c b/glcdgraphics/font.c index 1735cf2..116d88b 100644 --- a/glcdgraphics/font.c +++ b/glcdgraphics/font.c @@ -9,7 +9,9 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2004 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * Andreas 'randy' Weinberger */ #include <stdio.h> @@ -55,6 +57,64 @@ static const uint32_t kCharHeaderSize = 4; //}; //#pragma pack() +#ifdef HAVE_FREETYPE2 + +class cBitmapCache +{ +private: +protected: + cBitmapCache *next; // next bitmap + cBitmap *ptr; + uint32_t charcode; +public: + cBitmapCache(); + ~cBitmapCache(); + + void PushBack(uint32_t ch, cBitmap *bitmap); + cBitmap *GetBitmap(uint32_t ch) const; +}; + +cBitmapCache::cBitmapCache() +: next(NULL), + ptr(NULL), + charcode(0) +{ +} + +cBitmapCache::~cBitmapCache() +{ + delete ptr; + delete next; +} + +void cBitmapCache::PushBack(uint32_t ch, cBitmap *bitmap) +{ + if (!ptr) + { + charcode = ch; + ptr = bitmap; + } + else if (!next) + { + next = new cBitmapCache(); + next->ptr = bitmap; + next->charcode = ch; + } else + next->PushBack(ch, bitmap); +} + +cBitmap *cBitmapCache::GetBitmap(uint32_t ch) const +{ + if (ptr && charcode==ch) + return ptr; + else if (next) + return next->GetBitmap(ch); + else + return NULL; +} + +#endif + cFont::cFont() { Init(); @@ -65,10 +125,12 @@ cFont::~cFont() Unload(); } -bool cFont::LoadFNT(const std::string & fileName) +bool cFont::LoadFNT(const std::string & fileName, const std::string & encoding) { // cleanup if we already had a loaded font Unload(); + fontType = 1; //original fonts + isutf8 = (encoding == "UTF-8"); FILE * fontFile; int i; @@ -88,6 +150,7 @@ bool cFont::LoadFNT(const std::string & fileName) buffer[3] != kFontFileSign[3]) { fclose(fontFile); + syslog(LOG_ERR, "cFont::LoadFNT(): Cannot open file: %s - not the correct fileheader.\n",fileName.c_str()); return false; } @@ -105,11 +168,31 @@ bool cFont::LoadFNT(const std::string & fileName) character = chdr[0] | (chdr[1] << 8); charWidth = chdr[2] | (chdr[3] << 8); fread(buffer, fontHeight * ((charWidth + 7) / 8), 1, fontFile); - if (characters[character]) - delete characters[character]; - characters[character] = new cBitmap(charWidth, fontHeight, buffer); - if (characters[character]->Width() > maxWidth) - maxWidth = characters[character]->Width(); +#ifdef DEBUG + printf ("fontHeight %0d - charWidth %0d - character %0d - bytes %0d\n", fontHeight, charWidth, character,fontHeight * ((charWidth + 7) / 8)); +#endif + + int y; int loop; + int num = 0; + uint dot; uint b; + cBitmap * charBitmap = new cBitmap(charWidth, fontHeight); + charBitmap->Clear(); + for (num=0; num<fontHeight * ((charWidth + 7) / 8);num++) { + y = (charWidth + 7) / 8; + for (loop=0;loop<((charWidth + 7) / 8); loop++) { + for (b=0;b<charWidth;b++) { + dot=buffer[num+loop] & (0x80 >> b); + if (dot) { + charBitmap->DrawPixel(b+((loop*8)),num/y,cColor::Black); + } + } + } + num=num+y-1; + } + SetCharacter(character, charBitmap); + + if (charWidth > maxWidth) + maxWidth = charWidth; } fclose(fontFile); @@ -169,7 +252,8 @@ bool cFont::SaveFNT(const std::string & fileName) const chdr[2] = (uint8_t) characters[i]->Width(); chdr[3] = (uint8_t) (characters[i]->Width() >> 8); fwrite(chdr, kCharHeaderSize, 1, fontFile); - fwrite(characters[i]->Data(), totalHeight * characters[i]->LineSize(), 1, fontFile); +// fwrite(characters[i]->Data(), totalHeight * characters[i]->LineSize(), 1, fontFile); + fwrite(characters[i]->Data(), totalHeight * characters[i]->Width(), 1, fontFile); } } @@ -185,6 +269,9 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding, { // cleanup if we already had a loaded font Unload(); + fontType = 2; // ft2 fonts + isutf8 = (encoding == "UTF-8"); + #ifdef HAVE_FREETYPE2 if (access(fileName.c_str(), F_OK) != 0) { @@ -194,7 +281,6 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding, // file exists FT_Library library; FT_Face face; - FT_GlyphSlot slot; int error = FT_Init_FreeType(&library); if (error) @@ -223,36 +309,11 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding, return false; } - // set slot - slot = face->glyph; - // set Size FT_Set_Char_Size(face, 0, size * 64, 0, 0); - wchar_t utf_buff[256]; - if (dingBats) - { -/* - FT_CharMap charmap = 0; - for (int n = 0; n < face->num_charmaps; n++) - { - if (face->charmaps[n]->platform_id == 3 && - face->charmaps[n]->encoding_id == 0) - { - charmap = face->charmaps[n]; - //break; - } - } - if (charmap) - syslog(LOG_ERR, "cFont::LoadFT2: platform_id: %d, encoding_id: %d", charmap->platform_id, charmap->encoding_id); - error = FT_Set_Charmap(_face, charmap); - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: FT_Select_Charmap encoding not supported: %d", charmap->encoding_id); - } -*/ - } - else + // generate lookup table for encoding conversions (encoding != UTF8) + if (! (isutf8 || dingBats) ) { iconv_t cd; if ((cd = iconv_open("WCHAR_T", encoding.c_str())) == (iconv_t) -1) @@ -276,87 +337,26 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding, in_buff = (char *) &char_buff; out_buff = (char *) &wchar_buff; count = iconv(cd, &in_buff, &in_len, &out_buff, &out_len); - if ((size_t) -1 == count) - { - utf_buff[c] = 0; - } - utf_buff[c] = wchar_buff; + iconv_lut[c] = ((size_t) -1 == count) ? (wchar_t)'?' : wchar_buff; } iconv_close(cd); + } else { + // don't leave LUT uninitialised + for (int c = 0; c < 256; c++) + iconv_lut[c] = (wchar_t)c; } // get some global parameters - totalHeight = (face->size->metrics.ascender >> 6) - (face->size->metrics.descender >> 6); - totalWidth = face->size->metrics.max_advance >> 6; - totalAscent = face->size->metrics.ascender >> 6; - lineHeight = face->size->metrics.height >> 6; - spaceBetween = 0; -#if 0 - syslog(LOG_DEBUG, "cFont::LoadFT2: totalHeight = %d", totalHeight); - syslog(LOG_DEBUG, "cFont::LoadFT2: totalWidth = %d", totalWidth); - syslog(LOG_DEBUG, "cFont::LoadFT2: totalAscent = %d", totalAscent); - syslog(LOG_DEBUG, "cFont::LoadFT2: lineHeight = %d", lineHeight); - syslog(LOG_DEBUG, "cFont::LoadFT2: spaceBetween = %d", spaceBetween); -#endif - // render glyphs for ASCII codes 0 to 255 in our bitmap class - FT_UInt glyph_index; - int num_char; - - for (num_char = 0; num_char < 256; num_char++) - { - if (dingBats) - { - //Get FT char index & load the char - error = FT_Load_Char(face, num_char, FT_LOAD_DEFAULT); - } - else - { - //Get FT char index - glyph_index = FT_Get_Char_Index(face, utf_buff[num_char]); - //Load the char - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); - } - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Load_Glyph: %x", error); - } + SetTotalHeight( (face->size->metrics.ascender >> 6) - (face->size->metrics.descender >> 6) ); + SetTotalWidth ( face->size->metrics.max_advance >> 6 ); + SetTotalAscent( face->size->metrics.ascender >> 6 ); + SetLineHeight ( face->size->metrics.height >> 6 ); + SetSpaceBetween( 0 ); - // convert to a mono bitmap - error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO); - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Render_Glyph: %x", error); - } + ft2_library = library; + ft2_face = face; - // now, fill our pixel data - cBitmap * charBitmap = new cBitmap(face->glyph->advance.x >> 6, totalHeight); - charBitmap->Clear(); - unsigned char * bufPtr = face->glyph->bitmap.buffer; - unsigned char pixel; - for (int y = 0; y < face->glyph->bitmap.rows; y++) - { - for (int x = 0; x < face->glyph->bitmap.width; x++) - { - pixel = (bufPtr[x / 8] >> (7 - x % 8)) & 1; - if (pixel) - charBitmap->DrawPixel((face->glyph->metrics.horiBearingX >> 6) + x, - (face->size->metrics.ascender >> 6) - (face->glyph->metrics.horiBearingY >> 6) + y, - GLCD::clrBlack); - } - bufPtr += face->glyph->bitmap.pitch; - } - SetCharacter((char) num_char, charBitmap); - } - error = FT_Done_Face(face); - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_Face(..) returned (%d)", error); - } - error = FT_Done_FreeType(library); - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_FreeType(..) returned (%d)", error); - } + characters_cache=new cBitmapCache(); return true; #else syslog(LOG_ERR, "cFont::LoadFT2: glcdgraphics was compiled without FreeType2 support!!!"); @@ -364,28 +364,18 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding, #endif } -int cFont::Width(char ch) const +int cFont::Width(uint32_t ch) const { - if (characters[(unsigned char) ch]) - return characters[(unsigned char) ch]->Width(); + const cBitmap *bitmap = GetCharacter(ch); + if (bitmap) + return bitmap->Width(); else return 0; } int cFont::Width(const std::string & str) const { - unsigned int i; - int sum = 0; - - for (i = 0; i < str.length(); i++) - { - sum += Width(str[i]); - } - if (str.length() > 1) - { - sum += spaceBetween * (str.length() - 1); - } - return sum; + return Width(str, (unsigned int) str.length()); } int cFont::Width(const std::string & str, unsigned int len) const @@ -393,21 +383,56 @@ int cFont::Width(const std::string & str, unsigned int len) const unsigned int i; int sum = 0; - for (i = 0; i < str.length() && i < len; i++) - { - sum += Width(str[i]); - } - if (std::min(str.length(), (size_t) len) > 1) + uint32_t c,c0,c1,c2,c3; + + i = 0; +// for (i = 0; i < (unsigned int)str.length() && symcount < len; i++) + while (i < (unsigned int)str.length() && i < len) { - sum += spaceBetween * (std::min(str.length(), (size_t) len) - 1); + if (isutf8) { + c = str[i]; + c0 = str[i]; + c1 = (i+1 < (unsigned int)str.length()) ? str[i+1] : 0; + c2 = (i+2 < (unsigned int)str.length()) ? str[i+2] : 0; + c3 = (i+3 < (unsigned int)str.length()) ? str[i+3] : 0; + c0 &=0xff; c1 &=0xff; c2 &=0xff; c3 &=0xff; + + if( c0 >= 0xc2 && c0 <= 0xdf && c1 >= 0x80 && c1 <= 0xbf ){ + //2 byte UTF-8 sequence found + i+=1; + c = ((c0&0x1f)<<6) | (c1&0x3f); + }else if( (c0 == 0xE0 && c1 >= 0xA0 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xE1 && c1 <= 0xEC && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 == 0xED && c1 >= 0x80 && c1 <= 0x9f && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xEE && c0 <= 0xEF && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) ){ + //3 byte UTF-8 sequence found + c = ((c0&0x0f)<<4) | ((c1&0x3f)<<6) | (c2&0x3f); + i+=2; + }else if( (c0 == 0xF0 && c1 >= 0x90 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) + || (c0 >= 0xF1 && c0 >= 0xF3 && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) + || (c0 == 0xF4 && c1 >= 0x80 && c1 <= 0x8f && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) ){ + //4 byte UTF-8 sequence found + c = ((c0&0x07)<<2) | ((c1&0x3f)<<4) | ((c2&0x3f)<<6) | (c3&0x3f); + i+=3; + } + sum += Width(c); + } else { + sum += Width(str[i]); + } + i++; } + + if (i > 1) + sum += spaceBetween * (i - 1); + return sum; } -int cFont::Height(char ch) const +int cFont::Height(uint32_t ch) const { - if (characters[(unsigned char) ch]) - return characters[(unsigned char) ch]->Height(); + const cBitmap *bitmap = GetCharacter(ch); + if (bitmap) + return bitmap->Height(); else return 0; } @@ -432,13 +457,83 @@ int cFont::Height(const std::string & str, unsigned int len) const return sum; } -const cBitmap * cFont::GetCharacter(char ch) const +const cBitmap * cFont::GetCharacter(uint32_t ch) const { +#ifdef HAVE_FREETYPE2 + if ( fontType == 2 ) { + //lookup in cache + cBitmap *ptr=characters_cache->GetBitmap(ch); + if (ptr) + return ptr; + + FT_Face face = (FT_Face) ft2_face; + FT_UInt glyph_index; + //Get FT char index + if (isutf8) { + glyph_index = FT_Get_Char_Index(face, ch); + } else { + glyph_index = FT_Get_Char_Index(face, iconv_lut[(unsigned char)ch]); + } + + //Load the char + int error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if (error) + { + syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Load_Glyph: %x", error); + return NULL; + } + + FT_Render_Mode rmode = FT_RENDER_MODE_MONO; +#if ( (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 7) || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 2 && FREETYPE_PATCH <= 1) ) + if (ch == 32) rmode = FT_RENDER_MODE_NORMAL; +#endif + + // convert to a mono bitmap + error = FT_Render_Glyph(face->glyph, rmode); + if (error) + { + syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Render_Glyph: %x", error); + return NULL; + } else { + // now, fill our pixel data + cBitmap *charBitmap = new cBitmap(face->glyph->advance.x >> 6, TotalHeight()); + charBitmap->Clear(); + unsigned char * bufPtr = face->glyph->bitmap.buffer; + unsigned char pixel; + for (int y = 0; y < face->glyph->bitmap.rows; y++) + { + for (int x = 0; x < face->glyph->bitmap.width; x++) + { + pixel = (bufPtr[x / 8] >> (7 - x % 8)) & 1; + if (pixel) + charBitmap->DrawPixel((face->glyph->metrics.horiBearingX >> 6) + x, + (face->size->metrics.ascender >> 6) - (face->glyph->metrics.horiBearingY >> 6) + y, + /*GLCD::clrBlack*/ cColor::Black); + } + bufPtr += face->glyph->bitmap.pitch; + } + + // adjust maxwidth if necessary + //if (totalWidth < charBitmap->Width()) + // totalWidth = charBitmap->Width(); + + characters_cache->PushBack(ch, charBitmap); + return charBitmap; + } + return NULL; // if any + } // else +#endif return characters[(unsigned char) ch]; } void cFont::SetCharacter(char ch, cBitmap * bitmapChar) { +#ifdef HAVE_FREETYPE2 + if ( fontType == 2 ) { + syslog(LOG_ERR, "cFont::SetCharacter: is not supported with FreeType2 fonts!!!"); + return; + } +#endif // adjust maxwidth if necessary if (totalWidth < bitmapChar->Width()) totalWidth = bitmapChar->Width(); @@ -462,6 +557,12 @@ void cFont::Init() { characters[i] = NULL; } +#ifdef HAVE_FREETYPE2 + ft2_library = NULL; + ft2_face = NULL; + characters_cache = NULL; +#endif + fontType = 1; } void cFont::Unload() @@ -474,6 +575,13 @@ void cFont::Unload() delete characters[i]; } } +#ifdef HAVE_FREETYPE2 + delete characters_cache; + if (ft2_face) + FT_Done_Face((FT_Face)ft2_face); + if (ft2_library) + FT_Done_FreeType((FT_Library)ft2_library); +#endif // re-init Init(); } diff --git a/glcdgraphics/font.h b/glcdgraphics/font.h index b36d5ac..1315123 100644 --- a/glcdgraphics/font.h +++ b/glcdgraphics/font.h @@ -9,7 +9,9 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2004 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * Andreas 'randy' Weinberger */ #ifndef _GLCDGRAPHICS_FONT_H_ @@ -23,6 +25,8 @@ namespace GLCD { +class cBitmapCache; + class cFont { private: @@ -33,6 +37,14 @@ private: int lineHeight; cBitmap * characters[256]; + int fontType; //original or FT2 font, 1-original, 2-ft2 + + bool isutf8; + wchar_t iconv_lut[256]; // lookup table needed if encoding != UTF-8 + + cBitmapCache *characters_cache; + void *ft2_library; //FT_Library + void *ft2_face; //FT_Face protected: void Init(); void Unload(); @@ -40,7 +52,7 @@ public: cFont(); ~cFont(); - bool LoadFNT(const std::string & fileName); + bool LoadFNT(const std::string & fileName, const std::string & encoding = "UTF-8"); bool SaveFNT(const std::string & fileName) const; bool LoadFT2(const std::string & fileName, const std::string & encoding, int size, bool dingBats = false); @@ -56,18 +68,19 @@ public: void SetSpaceBetween(int width) { spaceBetween = width; }; void SetLineHeight(int height) { lineHeight = height; }; - int Width(char ch) const; + int Width(uint32_t ch) const; int Width(const std::string & str) const; int Width(const std::string & str, unsigned int len) const; - int Height(char ch) const; + int Height(uint32_t ch) const; int Height(const std::string & str) const; int Height(const std::string & str, unsigned int len) const; - const cBitmap * GetCharacter(char ch) const; + const cBitmap * GetCharacter(uint32_t ch) const; void SetCharacter(char ch, cBitmap * bitmapChar); void WrapText(int Width, int Height, std::string & Text, std::vector <std::string> & Lines, int * TextWidth = NULL) const; + bool IsUTF8(void) const { return isutf8; } }; } // end of namespace diff --git a/glcdgraphics/glcd.c b/glcdgraphics/glcd.c index e79b6b8..30449b9 100644 --- a/glcdgraphics/glcd.c +++ b/glcdgraphics/glcd.c @@ -9,7 +9,9 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2004 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * Andreas 'randy' Weinberger */ #include <stdio.h> @@ -163,30 +165,53 @@ bool cGLCDFile::Load(cImage & image, const string & fileName) image.SetWidth(width); image.SetHeight(height); image.SetDelay(delay); - unsigned char * bmpdata = new unsigned char[height * ((width + 7) / 8)]; - if (bmpdata) + unsigned char * bmpdata_raw = new unsigned char[height * ((width + 7) / 8)]; + uint32_t * bmpdata = new uint32_t[height * width]; + if (bmpdata && bmpdata_raw) { for (unsigned int n = 0; n < count; n++) { - if (fread(bmpdata, height * ((width + 7) / 8), 1, fp) != 1) + if (fread(bmpdata_raw, height * ((width + 7) / 8), 1, fp) != 1) { delete[] bmpdata; fclose(fp); image.Clear(); return false; } - image.AddBitmap(new cBitmap(width, height, bmpdata)); + int colsize = (width+7)/8; + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + if ( bmpdata_raw[j*colsize + (i>>3)] & (1 << (7-(i%8))) ) { + bmpdata[j*width+i] = cColor::Black; + } else { + bmpdata[j*width+i] = cColor::White; + } + } + } +#ifdef DEBUG + printf("%s:%s(%d) - filename: '%s', count %d\n", __FILE__, __FUNCTION__, __LINE__, fileName.c_str(), n); +#endif + cBitmap * b = new cBitmap(width, height, bmpdata); + b->SetMonochrome(true); + //image.AddBitmap(new cBitmap(width, height, bmpdata)); + image.AddBitmap(b); } delete[] bmpdata; } else { syslog(LOG_ERR, "glcdgraphics: malloc failed (cGLCDFile::Load)."); + if (bmpdata) + delete[] bmpdata; + if (bmpdata_raw) + delete[] bmpdata_raw; fclose(fp); image.Clear(); return false; } fclose(fp); + if (bmpdata_raw) + delete[] bmpdata_raw; syslog(LOG_DEBUG, "glcdgraphics: image %s loaded.", fileName.c_str()); return true; @@ -260,7 +285,8 @@ bool cGLCDFile::Save(cImage & image, const string & fileName) { if (bitmap->Width() == width && bitmap->Height() == height) { - if (fwrite(bitmap->Data(), height * ((width + 7) / 8), 1, fp) != 1) +// if (fwrite(bitmap->Data(), height * ((width + 7) / 8), 1, fp) != 1) + if (fwrite(bitmap->Data(), height * width, 1, fp) != 1) { fclose(fp); return false; diff --git a/glcdgraphics/pbm.c b/glcdgraphics/pbm.c index 2bca3ef..18b2ee3 100644 --- a/glcdgraphics/pbm.c +++ b/glcdgraphics/pbm.c @@ -6,7 +6,9 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2006 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2006-2010 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * Andreas 'randy' Weinberger */ #include <stdio.h> @@ -113,18 +115,35 @@ bool cPBMFile::Load(cImage & image, const std::string & fileName) image.SetWidth(w); image.SetHeight(h); image.SetDelay(100); - unsigned char * bmpdata = new unsigned char[h * ((w + 7) / 8)]; - if (bmpdata) + + unsigned char * bmpdata_raw = new unsigned char[h * ((w + 7) / 8)]; + uint32_t * bmpdata = new uint32_t[h * w]; + if (bmpdata && bmpdata_raw) { - if (fread(bmpdata, h * ((w + 7) / 8), 1, pbmFile) != 1) - { + if (fread(bmpdata_raw, h * ((w + 7) / 8), 1, pbmFile) != 1) + { + delete[] bmpdata; + fclose(pbmFile); + image.Clear(); + return false; + } + int colsize = (w+7)/8; + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + if ( bmpdata_raw[j*colsize + (i>>3)] & (1 << (7-(i%8))) ) { + bmpdata[j*w+i] = cColor::Black; + } else { + bmpdata[j*w+i] = cColor::White; + } + } + } + delete [] bmpdata_raw; + + cBitmap * b = new cBitmap(w, h, bmpdata); + b->SetMonochrome(true); + //image.AddBitmap(new cBitmap(width, height, bmpdata)); + image.AddBitmap(b); delete[] bmpdata; - fclose(pbmFile); - image.Clear(); - return false; - } - image.AddBitmap(new cBitmap(w, h, bmpdata)); - delete[] bmpdata; } else { @@ -154,7 +173,8 @@ bool cPBMFile::Save(cImage & image, const std::string & fileName) { sprintf(str, "P4\n%d %d\n", bitmap->Width(), bitmap->Height()); fwrite(str, strlen(str), 1, fp); - fwrite(bitmap->Data(), bitmap->LineSize() * bitmap->Height(), 1, fp); +// fwrite(bitmap->Data(), bitmap->LineSize() * bitmap->Height(), 1, fp); + fwrite(bitmap->Data(), bitmap->Width() * bitmap->Height(), 1, fp); } fclose(fp); } @@ -175,7 +195,8 @@ bool cPBMFile::Save(cImage & image, const std::string & fileName) { sprintf(str, "P4\n%d %d\n", bitmap->Width(), bitmap->Height()); fwrite(str, strlen(str), 1, fp); - fwrite(bitmap->Data(), bitmap->LineSize() * bitmap->Height(), 1, fp); +// fwrite(bitmap->Data(), bitmap->LineSize() * bitmap->Height(), 1, fp); + fwrite(bitmap->Data(), bitmap->Width() * bitmap->Height(), 1, fp); } fclose(fp); } |