General graphics tool
Diff: Graphic.cpp
- Revision:
- 0:404c38e71c68
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Graphic.cpp Wed Apr 15 11:29:50 2015 +0000 @@ -0,0 +1,283 @@ +#include "Graphic.h" + +/* + * Code derived from: + * http://developer.mbed.org/users/dreschpe/code/EaEpaper/ + */ +Graphic::Graphic(uint8_t *buf, int w, int h, int bits) : + _buf(buf), _w(w), _h(h), _bits(bits) { + clear(); + color(0, (1 << bits) - 1); +} + +// erase pixel after power up +void Graphic::clear() { + memset(_buf, 0, _w * _h / (1 << _bits)); + _charX = 0; + _charY = 0; +} + +void Graphic::color(int foreground, int background) { + int mask = (1 << _bits) - 1; + _foreColor = foreground & mask; + _backgroundColor = background & mask; +} + +// set one pixel in buffer _newImage +void Graphic::pixel(int x, int y, unsigned int color) { + unsigned char *v; + unsigned char bak, pos; + // first check parameter + if (x > _w || y > _h || x < 0 || y < 0) + return; + + color &= ((1 << _bits) - 1); // get valid color + //memory:y first, then x + v = &_buf[(x * _h * _bits / 8) + (y * _bits / 8)]; + + //pix saved in reverse order in a byte + pos = 8 - ((y * _bits) % 8) - _bits; + + bak = *v & ~(((1 << _bits) - 1) << pos); + *v = bak + (color << pos); +} + +// print line +void Graphic::line(int x0, int y0, int x1, int y1) { + int dx = 0, dy = 0; + int dx_sym = 0, dy_sym = 0; + int dx_x2 = 0, dy_x2 = 0; + int di = 0; + + dx = x1 - x0; + dy = y1 - y0; + + if (dx > 0) { + dx_sym = 1; + } else { + dx_sym = -1; + } + + if (dy > 0) { + dy_sym = 1; + } else { + dy_sym = -1; + } + + dx = dx_sym * dx; + dy = dy_sym * dy; + + dx_x2 = dx * 2; + dy_x2 = dy * 2; + + if (dx >= dy) { + di = dy_x2 - dx; + while (x0 != x1) { + + pixel(x0, y0, _foreColor); + x0 += dx_sym; + if (di < 0) { + di += dy_x2; + } else { + di += dy_x2 - dx_x2; + y0 += dy_sym; + } + } + pixel(x0, y0, _foreColor); + } else { + di = dx_x2 - dy; + while (y0 != y1) { + pixel(x0, y0, _foreColor); + y0 += dy_sym; + if (di < 0) { + di += dx_x2; + } else { + di += dx_x2 - dy_x2; + x0 += dx_sym; + } + } + pixel(x0, y0, _foreColor); + } +} + +// print rect +void Graphic::rect(int x0, int y0, int x1, int y1) { + + if (x1 > x0) + line(x0, y0, x1, y0); + else + line(x1, y0, x0, y0); + + if (y1 > y0) + line(x0, y0, x0, y1); + else + line(x0, y1, x0, y0); + + if (x1 > x0) + line(x0, y1, x1, y1); + else + line(x1, y1, x0, y1); + + if (y1 > y0) + line(x1, y0, x1, y1); + else + line(x1, y1, x1, y0); +} + +// print filled rect +void Graphic::fillrect(int x0, int y0, int x1, int y1) { + int l, c, i; + if (x0 > x1) { + i = x0; + x0 = x1; + x1 = i; + } + + if (y0 > y1) { + i = y0; + y0 = y1; + y1 = i; + } + + for (l = x0; l <= x1; l++) { + for (c = y0; c <= y1; c++) { + pixel(l, c, _foreColor); + } + } +} + +// print circle +void Graphic::circle(int x0, int y0, int r) { + int x = -r, y = 0, err = 2 - 2 * r, e2; + do { + pixel(x0 - x, y0 + y, _foreColor); + pixel(x0 + x, y0 + y, _foreColor); + pixel(x0 + x, y0 - y, _foreColor); + pixel(x0 - x, y0 - y, _foreColor); + e2 = err; + if (e2 <= y) { + err += ++y * 2 + 1; + if (-x == y && e2 <= x) + e2 = 0; + } + if (e2 > x) + err += ++x * 2 + 1; + } while (x <= 0); + +} + +// print filled circle +void Graphic::fillcircle(int x0, int y0, int r) { + int x = -r, y = 0, err = 2 - 2 * r, e2; + do { + line(x0 - x, y0 - y, x0 - x, y0 + y); + line(x0 + x, y0 - y, x0 + x, y0 + y); + e2 = err; + if (e2 <= y) { + err += ++y * 2 + 1; + if (-x == y && e2 <= x) + e2 = 0; + } + if (e2 > x) + err += ++x * 2 + 1; + } while (x <= 0); +} + +// set cursor position +void Graphic::locate(int column, int row) { + _charX = column; + _charY = row; +} + +// calc char columns +int Graphic::columns() { + int fontW = _font[1]; + return _w / fontW; +} + +// calc char rows +int Graphic::rows() { + int fontH = _font[2]; + return _h / fontH; +} + +// print char +void Graphic::putc(int c) { + int y, x, w, offset; //font + unsigned char* font; + + int fontBytes = _font[0]; + //int fontW = _font[1]; + int fontH = _font[2]; + int fontColBytes = _font[3]; + + + if (c == '\n') { // new line + _charX = 0; + _charY = _charY + fontH; + if (_charY >= _h - fontH) { + _charY = 0; + } + return; + } + if ((c < 31) || (c > 127)) + return; // test char range + + + font = &_font[((c - 32) * fontBytes) + 4]; // start of char bitmap + w = font[0]; // width of actual char + if (_charX + w > _w) { + _charX = 0; + _charY = _charY + fontH; + if (_charY >= _h - fontH) { + _charY = 0; + } + } + + font++; + for (y = 0; y < fontH; y++) { // vert line + for (x = 0; x < w; x++) { // horz line + // vertical then horz in memory + offset = (x * fontColBytes + y / 8); + pixel(_charX + x, _charY + y, + ((font[offset] >> (y % 8)) & 1) ? + _foreColor : _backgroundColor); + } + } + + _charX += w; +} + +// set actual font +void Graphic::font(const unsigned char* f) { + _font = (unsigned char *) f; +} + +void Graphic::print(const char *str) { + while (*str) { + putc(*str); + str++; + } +} + +void Graphic::print_bm(Bitmap bm, int x, int y) { + int h, v, b; + char d; + + for (v = 0; v < bm.ySize; v++) { // lines + for (h = 0; h < bm.xSize; h++) { // pixel + if (h + x > _w) + break; + if (v + y > _h) + break; + d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)]; + b = 0x80 >> (h & 0x07); + if ((d & b) == 0) { + pixel(x + h, y + v, _backgroundColor); + } else { + pixel(x + h, y + v, _foreColor); + } + } + } + +}