Sam Shi / Adafruit_GFX_customizedfont

Dependents:   unytefont

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