summaryrefslogtreecommitdiff
path: root/glcdgraphics
diff options
context:
space:
mode:
Diffstat (limited to 'glcdgraphics')
-rw-r--r--glcdgraphics/bitmap.c448
-rw-r--r--glcdgraphics/bitmap.h107
-rw-r--r--glcdgraphics/font.c378
-rw-r--r--glcdgraphics/font.h23
-rw-r--r--glcdgraphics/glcd.c38
-rw-r--r--glcdgraphics/pbm.c47
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);
}