Sam Shi / Adafruit_GFX_i2c

Dependents:   unytelogo_animation

Fork of Adafruit_GFX by Neal Horman

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