General graphics tool

Dependents:   EPD_GDE021A1_demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Graphic.cpp Source File

Graphic.cpp

00001 #include "Graphic.h"
00002 
00003 /*
00004  * Code derived from:
00005  *  http://developer.mbed.org/users/dreschpe/code/EaEpaper/
00006  */
00007 Graphic::Graphic(uint8_t *buf, int w, int h, int bits) :
00008         _buf(buf), _w(w), _h(h), _bits(bits) {
00009     clear();
00010     color(0, (1 << bits) - 1);
00011 }
00012 
00013 // erase pixel after power up
00014 void Graphic::clear() {
00015     memset(_buf, 0, _w * _h / (1 << _bits));
00016     _charX = 0;
00017     _charY = 0;
00018 }
00019 
00020 void Graphic::color(int foreground, int background) {
00021     int mask = (1 << _bits) - 1;
00022     _foreColor = foreground & mask;
00023     _backgroundColor = background & mask;
00024 }
00025 
00026 // set one pixel in buffer _newImage
00027 void Graphic::pixel(int x, int y, unsigned int color) {
00028     unsigned char *v;
00029     unsigned char bak, pos;
00030     // first check parameter
00031     if (x > _w || y > _h || x < 0 || y < 0)
00032         return;
00033 
00034     color &= ((1 << _bits) - 1); // get valid color
00035     //memory:y first, then x
00036     v = &_buf[(x * _h * _bits / 8) + (y * _bits / 8)];
00037 
00038     //pix saved in reverse order in a byte
00039     pos = 8 - ((y * _bits) % 8) - _bits;
00040 
00041     bak = *v & ~(((1 << _bits) - 1) << pos);
00042     *v = bak + (color << pos);
00043 }
00044 
00045 // print line
00046 void Graphic::line(int x0, int y0, int x1, int y1) {
00047     int dx = 0, dy = 0;
00048     int dx_sym = 0, dy_sym = 0;
00049     int dx_x2 = 0, dy_x2 = 0;
00050     int di = 0;
00051 
00052     dx = x1 - x0;
00053     dy = y1 - y0;
00054 
00055     if (dx > 0) {
00056         dx_sym = 1;
00057     } else {
00058         dx_sym = -1;
00059     }
00060 
00061     if (dy > 0) {
00062         dy_sym = 1;
00063     } else {
00064         dy_sym = -1;
00065     }
00066 
00067     dx = dx_sym * dx;
00068     dy = dy_sym * dy;
00069 
00070     dx_x2 = dx * 2;
00071     dy_x2 = dy * 2;
00072 
00073     if (dx >= dy) {
00074         di = dy_x2 - dx;
00075         while (x0 != x1) {
00076 
00077             pixel(x0, y0, _foreColor);
00078             x0 += dx_sym;
00079             if (di < 0) {
00080                 di += dy_x2;
00081             } else {
00082                 di += dy_x2 - dx_x2;
00083                 y0 += dy_sym;
00084             }
00085         }
00086         pixel(x0, y0, _foreColor);
00087     } else {
00088         di = dx_x2 - dy;
00089         while (y0 != y1) {
00090             pixel(x0, y0, _foreColor);
00091             y0 += dy_sym;
00092             if (di < 0) {
00093                 di += dx_x2;
00094             } else {
00095                 di += dx_x2 - dy_x2;
00096                 x0 += dx_sym;
00097             }
00098         }
00099         pixel(x0, y0, _foreColor);
00100     }
00101 }
00102 
00103 // print rect
00104 void Graphic::rect(int x0, int y0, int x1, int y1) {
00105 
00106     if (x1 > x0)
00107         line(x0, y0, x1, y0);
00108     else
00109         line(x1, y0, x0, y0);
00110 
00111     if (y1 > y0)
00112         line(x0, y0, x0, y1);
00113     else
00114         line(x0, y1, x0, y0);
00115 
00116     if (x1 > x0)
00117         line(x0, y1, x1, y1);
00118     else
00119         line(x1, y1, x0, y1);
00120 
00121     if (y1 > y0)
00122         line(x1, y0, x1, y1);
00123     else
00124         line(x1, y1, x1, y0);
00125 }
00126 
00127 // print filled rect
00128 void Graphic::fillrect(int x0, int y0, int x1, int y1) {
00129     int l, c, i;
00130     if (x0 > x1) {
00131         i = x0;
00132         x0 = x1;
00133         x1 = i;
00134     }
00135 
00136     if (y0 > y1) {
00137         i = y0;
00138         y0 = y1;
00139         y1 = i;
00140     }
00141 
00142     for (l = x0; l <= x1; l++) {
00143         for (c = y0; c <= y1; c++) {
00144             pixel(l, c, _foreColor);
00145         }
00146     }
00147 }
00148 
00149 // print circle
00150 void Graphic::circle(int x0, int y0, int r) {
00151     int x = -r, y = 0, err = 2 - 2 * r, e2;
00152     do {
00153         pixel(x0 - x, y0 + y, _foreColor);
00154         pixel(x0 + x, y0 + y, _foreColor);
00155         pixel(x0 + x, y0 - y, _foreColor);
00156         pixel(x0 - x, y0 - y, _foreColor);
00157         e2 = err;
00158         if (e2 <= y) {
00159             err += ++y * 2 + 1;
00160             if (-x == y && e2 <= x)
00161                 e2 = 0;
00162         }
00163         if (e2 > x)
00164             err += ++x * 2 + 1;
00165     } while (x <= 0);
00166 
00167 }
00168 
00169 // print filled circle
00170 void Graphic::fillcircle(int x0, int y0, int r) {
00171     int x = -r, y = 0, err = 2 - 2 * r, e2;
00172     do {
00173         line(x0 - x, y0 - y, x0 - x, y0 + y);
00174         line(x0 + x, y0 - y, x0 + x, y0 + y);
00175         e2 = err;
00176         if (e2 <= y) {
00177             err += ++y * 2 + 1;
00178             if (-x == y && e2 <= x)
00179                 e2 = 0;
00180         }
00181         if (e2 > x)
00182             err += ++x * 2 + 1;
00183     } while (x <= 0);
00184 }
00185 
00186 // set cursor position
00187 void Graphic::locate(int column, int row) {
00188     _charX = column;
00189     _charY = row;
00190 }
00191 
00192 // calc char columns
00193 int Graphic::columns() {
00194     int fontW = _font[1];
00195     return _w / fontW;
00196 }
00197 
00198 // calc char rows
00199 int Graphic::rows() {
00200     int fontH = _font[2];
00201     return _h / fontH;
00202 }
00203 
00204 // print char
00205 void Graphic::putc(int c) {
00206     int y, x, w, offset; //font
00207     unsigned char* font;
00208 
00209     int fontBytes = _font[0];
00210     //int fontW = _font[1];
00211     int fontH = _font[2];
00212     int fontColBytes = _font[3];
00213 
00214 
00215     if (c == '\n') {    // new line
00216         _charX = 0;
00217         _charY = _charY + fontH;
00218         if (_charY >= _h - fontH) {
00219             _charY = 0;
00220         }
00221         return;
00222     }
00223     if ((c < 31) || (c > 127))
00224         return;   // test char range
00225 
00226 
00227     font = &_font[((c - 32) * fontBytes) + 4]; // start of char bitmap
00228     w = font[0];                          // width of actual char
00229     if (_charX + w > _w) {
00230         _charX = 0;
00231         _charY = _charY + fontH;
00232         if (_charY >= _h - fontH) {
00233             _charY = 0;
00234         }
00235     }
00236 
00237     font++;
00238     for (y = 0; y < fontH; y++) {  //  vert line
00239         for (x = 0; x < w; x++) {   //  horz line
00240             // vertical then horz in memory
00241             offset = (x * fontColBytes + y / 8);
00242             pixel(_charX + x, _charY + y,
00243                     ((font[offset] >> (y % 8)) & 1) ?
00244                             _foreColor : _backgroundColor);
00245         }
00246     }
00247 
00248     _charX += w;
00249 }
00250 
00251 // set actual font
00252 void Graphic::font(const unsigned char* f) {
00253     _font = (unsigned char *) f;
00254 }
00255 
00256 void Graphic::print(const char *str) {
00257     while (*str) {
00258         putc(*str);
00259         str++;
00260     }
00261 }
00262 
00263 void Graphic::print_bm(Bitmap bm, int x, int y) {
00264     int h, v, b;
00265     char d;
00266 
00267     for (v = 0; v < bm.ySize; v++) {   // lines
00268         for (h = 0; h < bm.xSize; h++) { // pixel
00269             if (h + x > _w)
00270                 break;
00271             if (v + y > _h)
00272                 break;
00273             d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)];
00274             b = 0x80 >> (h & 0x07);
00275             if ((d & b) == 0) {
00276                 pixel(x + h, y + v, _backgroundColor);
00277             } else {
00278                 pixel(x + h, y + v, _foreColor);
00279             }
00280         }
00281     }
00282 
00283 }