General graphics tool
Graphic.cpp@0:404c38e71c68, 2015-04-15 (annotated)
- Committer:
- steeven
- Date:
- Wed Apr 15 11:29:50 2015 +0000
- Revision:
- 0:404c38e71c68
General graphic lib
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
steeven | 0:404c38e71c68 | 1 | #include "Graphic.h" |
steeven | 0:404c38e71c68 | 2 | |
steeven | 0:404c38e71c68 | 3 | /* |
steeven | 0:404c38e71c68 | 4 | * Code derived from: |
steeven | 0:404c38e71c68 | 5 | * http://developer.mbed.org/users/dreschpe/code/EaEpaper/ |
steeven | 0:404c38e71c68 | 6 | */ |
steeven | 0:404c38e71c68 | 7 | Graphic::Graphic(uint8_t *buf, int w, int h, int bits) : |
steeven | 0:404c38e71c68 | 8 | _buf(buf), _w(w), _h(h), _bits(bits) { |
steeven | 0:404c38e71c68 | 9 | clear(); |
steeven | 0:404c38e71c68 | 10 | color(0, (1 << bits) - 1); |
steeven | 0:404c38e71c68 | 11 | } |
steeven | 0:404c38e71c68 | 12 | |
steeven | 0:404c38e71c68 | 13 | // erase pixel after power up |
steeven | 0:404c38e71c68 | 14 | void Graphic::clear() { |
steeven | 0:404c38e71c68 | 15 | memset(_buf, 0, _w * _h / (1 << _bits)); |
steeven | 0:404c38e71c68 | 16 | _charX = 0; |
steeven | 0:404c38e71c68 | 17 | _charY = 0; |
steeven | 0:404c38e71c68 | 18 | } |
steeven | 0:404c38e71c68 | 19 | |
steeven | 0:404c38e71c68 | 20 | void Graphic::color(int foreground, int background) { |
steeven | 0:404c38e71c68 | 21 | int mask = (1 << _bits) - 1; |
steeven | 0:404c38e71c68 | 22 | _foreColor = foreground & mask; |
steeven | 0:404c38e71c68 | 23 | _backgroundColor = background & mask; |
steeven | 0:404c38e71c68 | 24 | } |
steeven | 0:404c38e71c68 | 25 | |
steeven | 0:404c38e71c68 | 26 | // set one pixel in buffer _newImage |
steeven | 0:404c38e71c68 | 27 | void Graphic::pixel(int x, int y, unsigned int color) { |
steeven | 0:404c38e71c68 | 28 | unsigned char *v; |
steeven | 0:404c38e71c68 | 29 | unsigned char bak, pos; |
steeven | 0:404c38e71c68 | 30 | // first check parameter |
steeven | 0:404c38e71c68 | 31 | if (x > _w || y > _h || x < 0 || y < 0) |
steeven | 0:404c38e71c68 | 32 | return; |
steeven | 0:404c38e71c68 | 33 | |
steeven | 0:404c38e71c68 | 34 | color &= ((1 << _bits) - 1); // get valid color |
steeven | 0:404c38e71c68 | 35 | //memory:y first, then x |
steeven | 0:404c38e71c68 | 36 | v = &_buf[(x * _h * _bits / 8) + (y * _bits / 8)]; |
steeven | 0:404c38e71c68 | 37 | |
steeven | 0:404c38e71c68 | 38 | //pix saved in reverse order in a byte |
steeven | 0:404c38e71c68 | 39 | pos = 8 - ((y * _bits) % 8) - _bits; |
steeven | 0:404c38e71c68 | 40 | |
steeven | 0:404c38e71c68 | 41 | bak = *v & ~(((1 << _bits) - 1) << pos); |
steeven | 0:404c38e71c68 | 42 | *v = bak + (color << pos); |
steeven | 0:404c38e71c68 | 43 | } |
steeven | 0:404c38e71c68 | 44 | |
steeven | 0:404c38e71c68 | 45 | // print line |
steeven | 0:404c38e71c68 | 46 | void Graphic::line(int x0, int y0, int x1, int y1) { |
steeven | 0:404c38e71c68 | 47 | int dx = 0, dy = 0; |
steeven | 0:404c38e71c68 | 48 | int dx_sym = 0, dy_sym = 0; |
steeven | 0:404c38e71c68 | 49 | int dx_x2 = 0, dy_x2 = 0; |
steeven | 0:404c38e71c68 | 50 | int di = 0; |
steeven | 0:404c38e71c68 | 51 | |
steeven | 0:404c38e71c68 | 52 | dx = x1 - x0; |
steeven | 0:404c38e71c68 | 53 | dy = y1 - y0; |
steeven | 0:404c38e71c68 | 54 | |
steeven | 0:404c38e71c68 | 55 | if (dx > 0) { |
steeven | 0:404c38e71c68 | 56 | dx_sym = 1; |
steeven | 0:404c38e71c68 | 57 | } else { |
steeven | 0:404c38e71c68 | 58 | dx_sym = -1; |
steeven | 0:404c38e71c68 | 59 | } |
steeven | 0:404c38e71c68 | 60 | |
steeven | 0:404c38e71c68 | 61 | if (dy > 0) { |
steeven | 0:404c38e71c68 | 62 | dy_sym = 1; |
steeven | 0:404c38e71c68 | 63 | } else { |
steeven | 0:404c38e71c68 | 64 | dy_sym = -1; |
steeven | 0:404c38e71c68 | 65 | } |
steeven | 0:404c38e71c68 | 66 | |
steeven | 0:404c38e71c68 | 67 | dx = dx_sym * dx; |
steeven | 0:404c38e71c68 | 68 | dy = dy_sym * dy; |
steeven | 0:404c38e71c68 | 69 | |
steeven | 0:404c38e71c68 | 70 | dx_x2 = dx * 2; |
steeven | 0:404c38e71c68 | 71 | dy_x2 = dy * 2; |
steeven | 0:404c38e71c68 | 72 | |
steeven | 0:404c38e71c68 | 73 | if (dx >= dy) { |
steeven | 0:404c38e71c68 | 74 | di = dy_x2 - dx; |
steeven | 0:404c38e71c68 | 75 | while (x0 != x1) { |
steeven | 0:404c38e71c68 | 76 | |
steeven | 0:404c38e71c68 | 77 | pixel(x0, y0, _foreColor); |
steeven | 0:404c38e71c68 | 78 | x0 += dx_sym; |
steeven | 0:404c38e71c68 | 79 | if (di < 0) { |
steeven | 0:404c38e71c68 | 80 | di += dy_x2; |
steeven | 0:404c38e71c68 | 81 | } else { |
steeven | 0:404c38e71c68 | 82 | di += dy_x2 - dx_x2; |
steeven | 0:404c38e71c68 | 83 | y0 += dy_sym; |
steeven | 0:404c38e71c68 | 84 | } |
steeven | 0:404c38e71c68 | 85 | } |
steeven | 0:404c38e71c68 | 86 | pixel(x0, y0, _foreColor); |
steeven | 0:404c38e71c68 | 87 | } else { |
steeven | 0:404c38e71c68 | 88 | di = dx_x2 - dy; |
steeven | 0:404c38e71c68 | 89 | while (y0 != y1) { |
steeven | 0:404c38e71c68 | 90 | pixel(x0, y0, _foreColor); |
steeven | 0:404c38e71c68 | 91 | y0 += dy_sym; |
steeven | 0:404c38e71c68 | 92 | if (di < 0) { |
steeven | 0:404c38e71c68 | 93 | di += dx_x2; |
steeven | 0:404c38e71c68 | 94 | } else { |
steeven | 0:404c38e71c68 | 95 | di += dx_x2 - dy_x2; |
steeven | 0:404c38e71c68 | 96 | x0 += dx_sym; |
steeven | 0:404c38e71c68 | 97 | } |
steeven | 0:404c38e71c68 | 98 | } |
steeven | 0:404c38e71c68 | 99 | pixel(x0, y0, _foreColor); |
steeven | 0:404c38e71c68 | 100 | } |
steeven | 0:404c38e71c68 | 101 | } |
steeven | 0:404c38e71c68 | 102 | |
steeven | 0:404c38e71c68 | 103 | // print rect |
steeven | 0:404c38e71c68 | 104 | void Graphic::rect(int x0, int y0, int x1, int y1) { |
steeven | 0:404c38e71c68 | 105 | |
steeven | 0:404c38e71c68 | 106 | if (x1 > x0) |
steeven | 0:404c38e71c68 | 107 | line(x0, y0, x1, y0); |
steeven | 0:404c38e71c68 | 108 | else |
steeven | 0:404c38e71c68 | 109 | line(x1, y0, x0, y0); |
steeven | 0:404c38e71c68 | 110 | |
steeven | 0:404c38e71c68 | 111 | if (y1 > y0) |
steeven | 0:404c38e71c68 | 112 | line(x0, y0, x0, y1); |
steeven | 0:404c38e71c68 | 113 | else |
steeven | 0:404c38e71c68 | 114 | line(x0, y1, x0, y0); |
steeven | 0:404c38e71c68 | 115 | |
steeven | 0:404c38e71c68 | 116 | if (x1 > x0) |
steeven | 0:404c38e71c68 | 117 | line(x0, y1, x1, y1); |
steeven | 0:404c38e71c68 | 118 | else |
steeven | 0:404c38e71c68 | 119 | line(x1, y1, x0, y1); |
steeven | 0:404c38e71c68 | 120 | |
steeven | 0:404c38e71c68 | 121 | if (y1 > y0) |
steeven | 0:404c38e71c68 | 122 | line(x1, y0, x1, y1); |
steeven | 0:404c38e71c68 | 123 | else |
steeven | 0:404c38e71c68 | 124 | line(x1, y1, x1, y0); |
steeven | 0:404c38e71c68 | 125 | } |
steeven | 0:404c38e71c68 | 126 | |
steeven | 0:404c38e71c68 | 127 | // print filled rect |
steeven | 0:404c38e71c68 | 128 | void Graphic::fillrect(int x0, int y0, int x1, int y1) { |
steeven | 0:404c38e71c68 | 129 | int l, c, i; |
steeven | 0:404c38e71c68 | 130 | if (x0 > x1) { |
steeven | 0:404c38e71c68 | 131 | i = x0; |
steeven | 0:404c38e71c68 | 132 | x0 = x1; |
steeven | 0:404c38e71c68 | 133 | x1 = i; |
steeven | 0:404c38e71c68 | 134 | } |
steeven | 0:404c38e71c68 | 135 | |
steeven | 0:404c38e71c68 | 136 | if (y0 > y1) { |
steeven | 0:404c38e71c68 | 137 | i = y0; |
steeven | 0:404c38e71c68 | 138 | y0 = y1; |
steeven | 0:404c38e71c68 | 139 | y1 = i; |
steeven | 0:404c38e71c68 | 140 | } |
steeven | 0:404c38e71c68 | 141 | |
steeven | 0:404c38e71c68 | 142 | for (l = x0; l <= x1; l++) { |
steeven | 0:404c38e71c68 | 143 | for (c = y0; c <= y1; c++) { |
steeven | 0:404c38e71c68 | 144 | pixel(l, c, _foreColor); |
steeven | 0:404c38e71c68 | 145 | } |
steeven | 0:404c38e71c68 | 146 | } |
steeven | 0:404c38e71c68 | 147 | } |
steeven | 0:404c38e71c68 | 148 | |
steeven | 0:404c38e71c68 | 149 | // print circle |
steeven | 0:404c38e71c68 | 150 | void Graphic::circle(int x0, int y0, int r) { |
steeven | 0:404c38e71c68 | 151 | int x = -r, y = 0, err = 2 - 2 * r, e2; |
steeven | 0:404c38e71c68 | 152 | do { |
steeven | 0:404c38e71c68 | 153 | pixel(x0 - x, y0 + y, _foreColor); |
steeven | 0:404c38e71c68 | 154 | pixel(x0 + x, y0 + y, _foreColor); |
steeven | 0:404c38e71c68 | 155 | pixel(x0 + x, y0 - y, _foreColor); |
steeven | 0:404c38e71c68 | 156 | pixel(x0 - x, y0 - y, _foreColor); |
steeven | 0:404c38e71c68 | 157 | e2 = err; |
steeven | 0:404c38e71c68 | 158 | if (e2 <= y) { |
steeven | 0:404c38e71c68 | 159 | err += ++y * 2 + 1; |
steeven | 0:404c38e71c68 | 160 | if (-x == y && e2 <= x) |
steeven | 0:404c38e71c68 | 161 | e2 = 0; |
steeven | 0:404c38e71c68 | 162 | } |
steeven | 0:404c38e71c68 | 163 | if (e2 > x) |
steeven | 0:404c38e71c68 | 164 | err += ++x * 2 + 1; |
steeven | 0:404c38e71c68 | 165 | } while (x <= 0); |
steeven | 0:404c38e71c68 | 166 | |
steeven | 0:404c38e71c68 | 167 | } |
steeven | 0:404c38e71c68 | 168 | |
steeven | 0:404c38e71c68 | 169 | // print filled circle |
steeven | 0:404c38e71c68 | 170 | void Graphic::fillcircle(int x0, int y0, int r) { |
steeven | 0:404c38e71c68 | 171 | int x = -r, y = 0, err = 2 - 2 * r, e2; |
steeven | 0:404c38e71c68 | 172 | do { |
steeven | 0:404c38e71c68 | 173 | line(x0 - x, y0 - y, x0 - x, y0 + y); |
steeven | 0:404c38e71c68 | 174 | line(x0 + x, y0 - y, x0 + x, y0 + y); |
steeven | 0:404c38e71c68 | 175 | e2 = err; |
steeven | 0:404c38e71c68 | 176 | if (e2 <= y) { |
steeven | 0:404c38e71c68 | 177 | err += ++y * 2 + 1; |
steeven | 0:404c38e71c68 | 178 | if (-x == y && e2 <= x) |
steeven | 0:404c38e71c68 | 179 | e2 = 0; |
steeven | 0:404c38e71c68 | 180 | } |
steeven | 0:404c38e71c68 | 181 | if (e2 > x) |
steeven | 0:404c38e71c68 | 182 | err += ++x * 2 + 1; |
steeven | 0:404c38e71c68 | 183 | } while (x <= 0); |
steeven | 0:404c38e71c68 | 184 | } |
steeven | 0:404c38e71c68 | 185 | |
steeven | 0:404c38e71c68 | 186 | // set cursor position |
steeven | 0:404c38e71c68 | 187 | void Graphic::locate(int column, int row) { |
steeven | 0:404c38e71c68 | 188 | _charX = column; |
steeven | 0:404c38e71c68 | 189 | _charY = row; |
steeven | 0:404c38e71c68 | 190 | } |
steeven | 0:404c38e71c68 | 191 | |
steeven | 0:404c38e71c68 | 192 | // calc char columns |
steeven | 0:404c38e71c68 | 193 | int Graphic::columns() { |
steeven | 0:404c38e71c68 | 194 | int fontW = _font[1]; |
steeven | 0:404c38e71c68 | 195 | return _w / fontW; |
steeven | 0:404c38e71c68 | 196 | } |
steeven | 0:404c38e71c68 | 197 | |
steeven | 0:404c38e71c68 | 198 | // calc char rows |
steeven | 0:404c38e71c68 | 199 | int Graphic::rows() { |
steeven | 0:404c38e71c68 | 200 | int fontH = _font[2]; |
steeven | 0:404c38e71c68 | 201 | return _h / fontH; |
steeven | 0:404c38e71c68 | 202 | } |
steeven | 0:404c38e71c68 | 203 | |
steeven | 0:404c38e71c68 | 204 | // print char |
steeven | 0:404c38e71c68 | 205 | void Graphic::putc(int c) { |
steeven | 0:404c38e71c68 | 206 | int y, x, w, offset; //font |
steeven | 0:404c38e71c68 | 207 | unsigned char* font; |
steeven | 0:404c38e71c68 | 208 | |
steeven | 0:404c38e71c68 | 209 | int fontBytes = _font[0]; |
steeven | 0:404c38e71c68 | 210 | //int fontW = _font[1]; |
steeven | 0:404c38e71c68 | 211 | int fontH = _font[2]; |
steeven | 0:404c38e71c68 | 212 | int fontColBytes = _font[3]; |
steeven | 0:404c38e71c68 | 213 | |
steeven | 0:404c38e71c68 | 214 | |
steeven | 0:404c38e71c68 | 215 | if (c == '\n') { // new line |
steeven | 0:404c38e71c68 | 216 | _charX = 0; |
steeven | 0:404c38e71c68 | 217 | _charY = _charY + fontH; |
steeven | 0:404c38e71c68 | 218 | if (_charY >= _h - fontH) { |
steeven | 0:404c38e71c68 | 219 | _charY = 0; |
steeven | 0:404c38e71c68 | 220 | } |
steeven | 0:404c38e71c68 | 221 | return; |
steeven | 0:404c38e71c68 | 222 | } |
steeven | 0:404c38e71c68 | 223 | if ((c < 31) || (c > 127)) |
steeven | 0:404c38e71c68 | 224 | return; // test char range |
steeven | 0:404c38e71c68 | 225 | |
steeven | 0:404c38e71c68 | 226 | |
steeven | 0:404c38e71c68 | 227 | font = &_font[((c - 32) * fontBytes) + 4]; // start of char bitmap |
steeven | 0:404c38e71c68 | 228 | w = font[0]; // width of actual char |
steeven | 0:404c38e71c68 | 229 | if (_charX + w > _w) { |
steeven | 0:404c38e71c68 | 230 | _charX = 0; |
steeven | 0:404c38e71c68 | 231 | _charY = _charY + fontH; |
steeven | 0:404c38e71c68 | 232 | if (_charY >= _h - fontH) { |
steeven | 0:404c38e71c68 | 233 | _charY = 0; |
steeven | 0:404c38e71c68 | 234 | } |
steeven | 0:404c38e71c68 | 235 | } |
steeven | 0:404c38e71c68 | 236 | |
steeven | 0:404c38e71c68 | 237 | font++; |
steeven | 0:404c38e71c68 | 238 | for (y = 0; y < fontH; y++) { // vert line |
steeven | 0:404c38e71c68 | 239 | for (x = 0; x < w; x++) { // horz line |
steeven | 0:404c38e71c68 | 240 | // vertical then horz in memory |
steeven | 0:404c38e71c68 | 241 | offset = (x * fontColBytes + y / 8); |
steeven | 0:404c38e71c68 | 242 | pixel(_charX + x, _charY + y, |
steeven | 0:404c38e71c68 | 243 | ((font[offset] >> (y % 8)) & 1) ? |
steeven | 0:404c38e71c68 | 244 | _foreColor : _backgroundColor); |
steeven | 0:404c38e71c68 | 245 | } |
steeven | 0:404c38e71c68 | 246 | } |
steeven | 0:404c38e71c68 | 247 | |
steeven | 0:404c38e71c68 | 248 | _charX += w; |
steeven | 0:404c38e71c68 | 249 | } |
steeven | 0:404c38e71c68 | 250 | |
steeven | 0:404c38e71c68 | 251 | // set actual font |
steeven | 0:404c38e71c68 | 252 | void Graphic::font(const unsigned char* f) { |
steeven | 0:404c38e71c68 | 253 | _font = (unsigned char *) f; |
steeven | 0:404c38e71c68 | 254 | } |
steeven | 0:404c38e71c68 | 255 | |
steeven | 0:404c38e71c68 | 256 | void Graphic::print(const char *str) { |
steeven | 0:404c38e71c68 | 257 | while (*str) { |
steeven | 0:404c38e71c68 | 258 | putc(*str); |
steeven | 0:404c38e71c68 | 259 | str++; |
steeven | 0:404c38e71c68 | 260 | } |
steeven | 0:404c38e71c68 | 261 | } |
steeven | 0:404c38e71c68 | 262 | |
steeven | 0:404c38e71c68 | 263 | void Graphic::print_bm(Bitmap bm, int x, int y) { |
steeven | 0:404c38e71c68 | 264 | int h, v, b; |
steeven | 0:404c38e71c68 | 265 | char d; |
steeven | 0:404c38e71c68 | 266 | |
steeven | 0:404c38e71c68 | 267 | for (v = 0; v < bm.ySize; v++) { // lines |
steeven | 0:404c38e71c68 | 268 | for (h = 0; h < bm.xSize; h++) { // pixel |
steeven | 0:404c38e71c68 | 269 | if (h + x > _w) |
steeven | 0:404c38e71c68 | 270 | break; |
steeven | 0:404c38e71c68 | 271 | if (v + y > _h) |
steeven | 0:404c38e71c68 | 272 | break; |
steeven | 0:404c38e71c68 | 273 | d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)]; |
steeven | 0:404c38e71c68 | 274 | b = 0x80 >> (h & 0x07); |
steeven | 0:404c38e71c68 | 275 | if ((d & b) == 0) { |
steeven | 0:404c38e71c68 | 276 | pixel(x + h, y + v, _backgroundColor); |
steeven | 0:404c38e71c68 | 277 | } else { |
steeven | 0:404c38e71c68 | 278 | pixel(x + h, y + v, _foreColor); |
steeven | 0:404c38e71c68 | 279 | } |
steeven | 0:404c38e71c68 | 280 | } |
steeven | 0:404c38e71c68 | 281 | } |
steeven | 0:404c38e71c68 | 282 | |
steeven | 0:404c38e71c68 | 283 | } |