General graphics tool

Dependents:   EPD_GDE021A1_demo

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);
+            }
+        }
+    }
+
+}