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