1

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Adafruit_GFX.cpp Source File

Adafruit_GFX.cpp

00001 /***********************************
00002 This is a our graphics core library, for all our displays.
00003 We'll be adapting all the
00004 existing libaries to use this core to make updating, support
00005 and upgrading easier!
00006 
00007 Adafruit invests time and resources providing this open source code,
00008 please support Adafruit and open-source hardware by purchasing
00009 products from Adafruit!
00010 
00011 Written by Limor Fried/Ladyada  for Adafruit Industries.
00012 BSD license, check license.txt for more information
00013 All text above must be included in any redistribution
00014 ****************************************/
00015 
00016 /*
00017  *  Modified by Neal Horman 7/14/2012 for use in mbed
00018  */
00019 
00020 #include "mbed.h"
00021 
00022 #include "Adafruit_GFX.h"
00023 #include "glcdfont.h"
00024 
00025 #if defined(GFX_WANT_ABSTRACTS)
00026 // draw a circle outline
00027 void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
00028 {
00029     int16_t f = 1 - r;
00030     int16_t ddF_x = 1;
00031     int16_t ddF_y = -2 * r;
00032     int16_t x = 0;
00033     int16_t y = r;
00034 
00035     drawPixel(x0, y0+r, color);
00036     drawPixel(x0, y0-r, color);
00037     drawPixel(x0+r, y0, color);
00038     drawPixel(x0-r, y0, color);
00039 
00040     while (x<y) {
00041         if (f >= 0) {
00042             y--;
00043             ddF_y += 2;
00044             f += ddF_y;
00045         }
00046         x++;
00047         ddF_x += 2;
00048         f += ddF_x;
00049 
00050         drawPixel(x0 + x, y0 + y, color);
00051         drawPixel(x0 - x, y0 + y, color);
00052         drawPixel(x0 + x, y0 - y, color);
00053         drawPixel(x0 - x, y0 - y, color);
00054         drawPixel(x0 + y, y0 + x, color);
00055         drawPixel(x0 - y, y0 + x, color);
00056         drawPixel(x0 + y, y0 - x, color);
00057         drawPixel(x0 - y, y0 - x, color);
00058     }
00059 }
00060 
00061 void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color)
00062 {
00063     int16_t f     = 1 - r;
00064     int16_t ddF_x = 1;
00065     int16_t ddF_y = -2 * r;
00066     int16_t x     = 0;
00067     int16_t y     = r;
00068 
00069     while (x<y) {
00070         if (f >= 0) {
00071             y--;
00072             ddF_y += 2;
00073             f += ddF_y;
00074         }
00075         x++;
00076         ddF_x += 2;
00077         f += ddF_x;
00078 
00079         if (cornername & 0x4) {
00080             drawPixel(x0 + x, y0 + y, color);
00081             drawPixel(x0 + y, y0 + x, color);
00082         }
00083 
00084         if (cornername & 0x2) {
00085             drawPixel(x0 + x, y0 - y, color);
00086             drawPixel(x0 + y, y0 - x, color);
00087         }
00088 
00089         if (cornername & 0x8) {
00090             drawPixel(x0 - y, y0 + x, color);
00091             drawPixel(x0 - x, y0 + y, color);
00092         }
00093 
00094         if (cornername & 0x1) {
00095             drawPixel(x0 - y, y0 - x, color);
00096             drawPixel(x0 - x, y0 - y, color);
00097         }
00098     }
00099 }
00100 
00101 void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
00102 {
00103     drawFastVLine(x0, y0-r, 2*r+1, color);
00104     fillCircleHelper(x0, y0, r, 3, 0, color);
00105 }
00106 
00107 // used to do circles and roundrects!
00108 void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color)
00109 {
00110     int16_t f     = 1 - r;
00111     int16_t ddF_x = 1;
00112     int16_t ddF_y = -2 * r;
00113     int16_t x     = 0;
00114     int16_t y     = r;
00115 
00116     while (x<y) {
00117         if (f >= 0) {
00118             y--;
00119             ddF_y += 2;
00120             f += ddF_y;
00121         }
00122         x++;
00123         ddF_x += 2;
00124         f += ddF_x;
00125 
00126         if (cornername & 0x1) {
00127             drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
00128             drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
00129         }
00130 
00131         if (cornername & 0x2) {
00132             drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
00133             drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
00134         }
00135     }
00136 }
00137 #endif
00138 
00139 #if defined(GFX_WANT_ABSTRACTS) || defined(GFX_SIZEABLE_TEXT)
00140 // bresenham's algorithm - thx wikpedia
00141 void Adafruit_GFX::drawLine(int16_t x0, int16_t y0,  int16_t x1, int16_t y1, uint16_t color)
00142 {
00143     int16_t steep = abs(y1 - y0) > abs(x1 - x0);
00144 
00145     if (steep) {
00146         swap(x0, y0);
00147         swap(x1, y1);
00148     }
00149 
00150     if (x0 > x1) {
00151         swap(x0, x1);
00152         swap(y0, y1);
00153     }
00154 
00155     int16_t dx, dy;
00156     dx = x1 - x0;
00157     dy = abs(y1 - y0);
00158 
00159     int16_t err = dx / 2;
00160     int16_t ystep;
00161 
00162     if (y0 < y1)
00163         ystep = 1;
00164     else
00165         ystep = -1;
00166 
00167     for (; x0<=x1; x0++) {
00168         if (steep)
00169             drawPixel(y0, x0, color);
00170         else
00171             drawPixel(x0, y0, color);
00172 
00173         err -= dy;
00174         if (err < 0) {
00175             y0 += ystep;
00176             err += dx;
00177         }
00178     }
00179 }
00180 
00181 void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
00182 {
00183     // stupidest version - update in subclasses if desired!
00184     drawLine(x, y, x, y+h-1, color);
00185 }
00186 
00187 void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
00188 {
00189     // stupidest version - update in subclasses if desired!
00190     for (int16_t i=x; i<x+w; i++)
00191         drawFastVLine(i, y, h, color);
00192 }
00193 #endif
00194 
00195 #if defined(GFX_WANT_ABSTRACTS)
00196 // draw a rectangle
00197 void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
00198 {
00199     drawFastHLine(x, y, w, color);
00200     drawFastHLine(x, y+h-1, w, color);
00201     drawFastVLine(x, y, h, color);
00202     drawFastVLine(x+w-1, y, h, color);
00203 }
00204 
00205 void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
00206 {
00207     // stupidest version - update in subclasses if desired!
00208     drawLine(x, y, x+w-1, y, color);
00209 }
00210 
00211 void Adafruit_GFX::fillScreen(uint16_t color)
00212 {
00213     fillRect(0, 0, _width, _height, color);
00214 }
00215 
00216 // draw a rounded rectangle!
00217 void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
00218 {
00219     // smarter version
00220     drawFastHLine(x+r, y, w-2*r, color);       // Top
00221     drawFastHLine(x+r, y+h-1, w-2*r, color);   // Bottom
00222     drawFastVLine(  x, y+r, h-2*r, color);       // Left
00223     drawFastVLine(  x+w-1, y+r, h-2*r, color);   // Right
00224     // draw four corners
00225     drawCircleHelper(x+r, y+r, r, 1, color);
00226     drawCircleHelper(x+w-r-1, y+r, r, 2, color);
00227     drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
00228     drawCircleHelper(x+r, y+h-r-1, r, 8, color);
00229 }
00230 
00231 // fill a rounded rectangle!
00232 void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
00233 {
00234     // smarter version
00235     fillRect(x+r, y, w-2*r, h, color);
00236 
00237     // draw four corners
00238     fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
00239     fillCircleHelper(x+r, y+r, r, 2, h-2*r-1, color);
00240 }
00241 
00242 // draw a triangle!
00243 void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
00244 {
00245     drawLine(x0, y0, x1, y1, color);
00246     drawLine(x1, y1, x2, y2, color);
00247     drawLine(x2, y2, x0, y0, color);
00248 }
00249 
00250 // fill a triangle!
00251 void Adafruit_GFX::fillTriangle ( int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
00252 {
00253     int16_t a, b, y, last;
00254 
00255     // Sort coordinates by Y order (y2 >= y1 >= y0)
00256     if (y0 > y1)
00257         swap(y0, y1);
00258     swap(x0, x1);
00259 
00260     if (y1 > y2)
00261         swap(y2, y1);
00262     swap(x2, x1);
00263 
00264     if (y0 > y1)
00265         swap(y0, y1);
00266     swap(x0, x1);
00267 
00268 
00269     if(y0 == y2) {
00270         // Handle awkward all-on-same-line case as its own thing
00271         a = b = x0;
00272         if(x1 < a)
00273             a = x1;
00274         else if(x1 > b)
00275             b = x1;
00276 
00277         if(x2 < a)
00278             a = x2;
00279         else if(x2 > b) b = x2;
00280         drawFastHLine(a, y0, b-a+1, color);
00281         return;
00282     }
00283 
00284     int16_t
00285     dx01 = x1 - x0,
00286     dy01 = y1 - y0,
00287     dx02 = x2 - x0,
00288     dy02 = y2 - y0,
00289     dx12 = x2 - x1,
00290     dy12 = y2 - y1,
00291     sa   = 0,
00292     sb   = 0;
00293 
00294     // For upper part of triangle, find scanline crossings for segments
00295     // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
00296     // is included here (and second loop will be skipped, avoiding a /0
00297     // error there), otherwise scanline y1 is skipped here and handled
00298     // in the second loop...which also avoids a /0 error here if y0=y1
00299     // (flat-topped triangle).
00300     if(y1 == y2)
00301         last = y1;   // Include y1 scanline
00302     else
00303         last = y1-1; // Skip it
00304 
00305     for(y=y0; y<=last; y++) {
00306         a   = x0 + sa / dy01;
00307         b   = x0 + sb / dy02;
00308         sa += dx01;
00309         sb += dx02;
00310         /* longhand:
00311         a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
00312         b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00313         */
00314         if(a > b)
00315             swap(a,b);
00316         drawFastHLine(a, y, b-a+1, color);
00317     }
00318 
00319     // For lower part of triangle, find scanline crossings for segments
00320     // 0-2 and 1-2.  This loop is skipped if y1=y2.
00321     sa = dx12 * (y - y1);
00322     sb = dx02 * (y - y0);
00323     for(; y<=y2; y++) {
00324         a   = x1 + sa / dy12;
00325         b   = x0 + sb / dy02;
00326         sa += dx12;
00327         sb += dx02;
00328         /* longhand:
00329         a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
00330         b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00331         */
00332         if(a > b)
00333             swap(a,b);
00334         drawFastHLine(a, y, b-a+1, color);
00335     }
00336 }
00337 
00338 void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color)
00339 {
00340     for (int16_t j=0; j<h; j++) {
00341         for (int16_t i=0; i<w; i++ ) {
00342             if (bitmap[i + (j/8)*w] & _BV(j%8))
00343                 drawPixel(x+i, y+j, color);
00344         }
00345     }
00346 }
00347 #endif
00348 
00349 size_t Adafruit_GFX::writeChar(uint8_t c)
00350 {
00351     if (c == '\n') {
00352         cursor_y += textsize*8;
00353         cursor_x = 0;
00354     } else if (c == '\r')
00355         cursor_x = 0;
00356     else {
00357         drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
00358         cursor_x += textsize*6;
00359         if (wrap && (cursor_x > (_width - textsize*6))) {
00360             cursor_y += textsize*8;
00361             cursor_x = 0;
00362         }
00363     }
00364     return 1;
00365 }
00366 
00367 // draw a character
00368 void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size)
00369 {
00370     if(
00371         (x >= _width) || // Clip right
00372         (y >= _height) || // Clip bottom
00373         ((x + 5 * size - 1) < 0) || // Clip left
00374         ((y + 8 * size - 1) < 0) // Clip top
00375     )
00376         return;
00377 
00378     for (int8_t i=0; i<6; i++ ) {
00379         uint8_t line = 0;
00380 
00381         if (i == 5)
00382             line = 0x0;
00383         else
00384             line = font[(c*5)+i];
00385 
00386         for (int8_t j = 0; j<8; j++) {
00387             if (line & 0x1) {
00388 #if defined(GFX_WANT_ABSTRACTS) || defined(GFX_SIZEABLE_TEXT)
00389                 if (size == 1) // default size
00390                     drawPixel(x+i, y+j, color);
00391                 else // big size
00392                     fillRect(x+(i*size), y+(j*size), size, size, color);
00393 #else
00394                 drawPixel(x+i, y+j, color);
00395 #endif
00396             } else if (bg != color) {
00397 #if defined(GFX_WANT_ABSTRACTS) || defined(GFX_SIZEABLE_TEXT)
00398                 if (size == 1) // default size
00399                     drawPixel(x+i, y+j, bg);
00400                 else // big size
00401                     fillRect(x+i*size, y+j*size, size, size, bg);
00402 #else
00403                 drawPixel(x+i, y+j, bg);
00404 #endif
00405             }
00406             line >>= 1;
00407         }
00408     }
00409 }
00410 
00411 void Adafruit_GFX::setRotation(uint8_t x)
00412 {
00413     x %= 4;  // cant be higher than 3
00414     rotation = x;
00415     switch (x) {
00416         case 0:
00417         case 2:
00418             _width = _rawWidth;
00419             _height = _rawHeight;
00420             break;
00421         case 1:
00422         case 3:
00423             _width = _rawHeight;
00424             _height = _rawWidth;
00425             break;
00426     }
00427 }
00428 
00429 void Adafruit_GFX::drawX11BitMap(const uint8_t bitmap[],uint16_t bitMapWidth,uint16_t bitMapSize,uint16_t posX,uint16_t posY)
00430 {
00431     int16_t x1 = posX;
00432     int16_t y1 = posY;
00433     for(unsigned int i=0; i<bitMapSize; i++) {
00434         uint8_t val = bitmap[i];
00435         for(int j=0; j<8; j++) {
00436             uint16_t pixColor;
00437             if(val>>j & 0x01)
00438                 pixColor = 1;
00439             else
00440                 pixColor = 0;
00441             drawPixel(x1,y1, pixColor);
00442             x1 = x1 + 1;
00443             if(x1 == posX + bitMapWidth) {
00444                 x1 = posX;
00445                 y1 = y1 + 1;
00446             }
00447         }
00448     }
00449 }