Please run it on your NUCLEO-L152

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ADA_GFX_kbv.cpp Source File

ADA_GFX_kbv.cpp

00001 /*
00002 This is the core graphics library for all our displays, providing a common
00003 set of graphics primitives (points, lines, circles, etc.).  It needs to be
00004 paired with a hardware-specific library for each display device we carry
00005 (to handle the lower-level functions).
00006 
00007 Adafruit invests time and resources providing this open source code, please
00008 support Adafruit & open-source hardware by purchasing products from Adafruit!
00009  
00010 Copyright (c) 2013 Adafruit Industries.  All rights reserved.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014 
00015 - Redistributions of source code must retain the above copyright notice,
00016   this list of conditions and the following disclaimer.
00017 - Redistributions in binary form must reproduce the above copyright notice,
00018   this list of conditions and the following disclaimer in the documentation
00019   and/or other materials provided with the distribution.
00020 
00021 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00022 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00025 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00026 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00027 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00028 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00029 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00030 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 POSSIBILITY OF SUCH DAMAGE.
00032 */
00033 
00034 #include "ADA_GFX_kbv.h"
00035 #ifdef __AVR__
00036  #include <avr/pgmspace.h>
00037 #else
00038  #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
00039  #define PROGMEM
00040 #endif
00041 #include "glcdfont.inc"
00042 
00043 Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h):
00044   WIDTH(w), HEIGHT(h)
00045 {
00046   _width    = WIDTH;
00047   _height   = HEIGHT;
00048   rotation  = 0;
00049   cursor_y  = cursor_x    = 0;
00050   textsize  = 1;
00051   textcolor = textbgcolor = 0xFFFF;
00052   wrap      = true;
00053 }
00054 
00055 // Draw a circle outline
00056 void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
00057     uint16_t color) {
00058   int16_t f = 1 - r;
00059   int16_t ddF_x = 1;
00060   int16_t ddF_y = -2 * r;
00061   int16_t x = 0;
00062   int16_t y = r;
00063 
00064   drawPixel(x0  , y0+r, color);
00065   drawPixel(x0  , y0-r, color);
00066   drawPixel(x0+r, y0  , color);
00067   drawPixel(x0-r, y0  , color);
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     drawPixel(x0 + x, y0 + y, color);
00080     drawPixel(x0 - x, y0 + y, color);
00081     drawPixel(x0 + x, y0 - y, color);
00082     drawPixel(x0 - x, y0 - y, color);
00083     drawPixel(x0 + y, y0 + x, color);
00084     drawPixel(x0 - y, y0 + x, color);
00085     drawPixel(x0 + y, y0 - x, color);
00086     drawPixel(x0 - y, y0 - x, color);
00087   }
00088 }
00089 
00090 void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0,
00091                int16_t r, uint8_t cornername, uint16_t color) {
00092   int16_t f     = 1 - r;
00093   int16_t ddF_x = 1;
00094   int16_t ddF_y = -2 * r;
00095   int16_t x     = 0;
00096   int16_t y     = r;
00097 
00098   while (x<y) {
00099     if (f >= 0) {
00100       y--;
00101       ddF_y += 2;
00102       f     += ddF_y;
00103     }
00104     x++;
00105     ddF_x += 2;
00106     f     += ddF_x;
00107     if (cornername & 0x4) {
00108       drawPixel(x0 + x, y0 + y, color);
00109       drawPixel(x0 + y, y0 + x, color);
00110     } 
00111     if (cornername & 0x2) {
00112       drawPixel(x0 + x, y0 - y, color);
00113       drawPixel(x0 + y, y0 - x, color);
00114     }
00115     if (cornername & 0x8) {
00116       drawPixel(x0 - y, y0 + x, color);
00117       drawPixel(x0 - x, y0 + y, color);
00118     }
00119     if (cornername & 0x1) {
00120       drawPixel(x0 - y, y0 - x, color);
00121       drawPixel(x0 - x, y0 - y, color);
00122     }
00123   }
00124 }
00125 
00126 void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
00127                   uint16_t color) {
00128   drawFastVLine(x0, y0-r, 2*r+1, color);
00129   fillCircleHelper(x0, y0, r, 3, 0, color);
00130 }
00131 
00132 // Used to do circles and roundrects
00133 void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
00134     uint8_t cornername, int16_t delta, uint16_t color) {
00135 
00136   int16_t f     = 1 - r;
00137   int16_t ddF_x = 1;
00138   int16_t ddF_y = -2 * r;
00139   int16_t x     = 0;
00140   int16_t y     = r;
00141 
00142   while (x<y) {
00143     if (f >= 0) {
00144       y--;
00145       ddF_y += 2;
00146       f     += ddF_y;
00147     }
00148     x++;
00149     ddF_x += 2;
00150     f     += ddF_x;
00151 
00152     if (cornername & 0x1) {
00153       drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
00154       drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
00155     }
00156     if (cornername & 0x2) {
00157       drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
00158       drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
00159     }
00160   }
00161 }
00162 
00163 // Bresenham's algorithm - thx wikpedia
00164 void Adafruit_GFX::drawLine(int16_t x0, int16_t y0,
00165                 int16_t x1, int16_t y1,
00166                 uint16_t color) {
00167   int16_t steep = abs(y1 - y0) > abs(x1 - x0);
00168   if (steep) {
00169     swap(x0, y0);
00170     swap(x1, y1);
00171   }
00172 
00173   if (x0 > x1) {
00174     swap(x0, x1);
00175     swap(y0, y1);
00176   }
00177 
00178   int16_t dx, dy;
00179   dx = x1 - x0;
00180   dy = abs(y1 - y0);
00181 
00182   int16_t err = dx / 2;
00183   int16_t ystep;
00184 
00185   if (y0 < y1) {
00186     ystep = 1;
00187   } else {
00188     ystep = -1;
00189   }
00190 
00191   for (; x0<=x1; x0++) {
00192     if (steep) {
00193       drawPixel(y0, x0, color);
00194     } else {
00195       drawPixel(x0, y0, color);
00196     }
00197     err -= dy;
00198     if (err < 0) {
00199       y0 += ystep;
00200       err += dx;
00201     }
00202   }
00203 }
00204 
00205 // Draw a rectangle
00206 void Adafruit_GFX::drawRect(int16_t x, int16_t y,
00207                 int16_t w, int16_t h,
00208                 uint16_t color) {
00209   drawFastHLine(x, y, w, color);
00210   drawFastHLine(x, y+h-1, w, color);
00211   drawFastVLine(x, y, h, color);
00212   drawFastVLine(x+w-1, y, h, color);
00213 }
00214 
00215 void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y,
00216                  int16_t h, uint16_t color) {
00217   // Update in subclasses if desired!
00218   drawLine(x, y, x, y+h-1, color);
00219 }
00220 
00221 void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y,
00222                  int16_t w, uint16_t color) {
00223   // Update in subclasses if desired!
00224   drawLine(x, y, x+w-1, y, color);
00225 }
00226 
00227 void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
00228                 uint16_t color) {
00229   // Update in subclasses if desired!
00230   for (int16_t i=x; i<x+w; i++) {
00231     drawFastVLine(i, y, h, color);
00232   }
00233 }
00234 
00235 void Adafruit_GFX::fillScreen(uint16_t color) {
00236   fillRect(0, 0, _width, _height, color);
00237 }
00238 
00239 // Draw a rounded rectangle
00240 void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
00241   int16_t h, int16_t r, uint16_t color) {
00242   // smarter version
00243   drawFastHLine(x+r  , y    , w-2*r, color); // Top
00244   drawFastHLine(x+r  , y+h-1, w-2*r, color); // Bottom
00245   drawFastVLine(x    , y+r  , h-2*r, color); // Left
00246   drawFastVLine(x+w-1, y+r  , h-2*r, color); // Right
00247   // draw four corners
00248   drawCircleHelper(x+r    , y+r    , r, 1, color);
00249   drawCircleHelper(x+w-r-1, y+r    , r, 2, color);
00250   drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
00251   drawCircleHelper(x+r    , y+h-r-1, r, 8, color);
00252 }
00253 
00254 // Fill a rounded rectangle
00255 void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
00256                  int16_t h, int16_t r, uint16_t color) {
00257   // smarter version
00258   fillRect(x+r, y, w-2*r, h, color);
00259 
00260   // draw four corners
00261   fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
00262   fillCircleHelper(x+r    , y+r, r, 2, h-2*r-1, color);
00263 }
00264 
00265 // Draw a triangle
00266 void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0,
00267                 int16_t x1, int16_t y1,
00268                 int16_t x2, int16_t y2, uint16_t color) {
00269   drawLine(x0, y0, x1, y1, color);
00270   drawLine(x1, y1, x2, y2, color);
00271   drawLine(x2, y2, x0, y0, color);
00272 }
00273 
00274 // Fill a triangle
00275 void Adafruit_GFX::fillTriangle ( int16_t x0, int16_t y0,
00276                   int16_t x1, int16_t y1,
00277                   int16_t x2, int16_t y2, uint16_t color) {
00278 
00279   int16_t a, b, y, last;
00280 
00281   // Sort coordinates by Y order (y2 >= y1 >= y0)
00282   if (y0 > y1) {
00283     swap(y0, y1); swap(x0, x1);
00284   }
00285   if (y1 > y2) {
00286     swap(y2, y1); swap(x2, x1);
00287   }
00288   if (y0 > y1) {
00289     swap(y0, y1); swap(x0, x1);
00290   }
00291 
00292   if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
00293     a = b = x0;
00294     if(x1 < a)      a = x1;
00295     else if(x1 > b) b = x1;
00296     if(x2 < a)      a = x2;
00297     else if(x2 > b) b = x2;
00298     drawFastHLine(a, y0, b-a+1, color);
00299     return;
00300   }
00301 
00302   int16_t
00303     dx01 = x1 - x0,
00304     dy01 = y1 - y0,
00305     dx02 = x2 - x0,
00306     dy02 = y2 - y0,
00307     dx12 = x2 - x1,
00308     dy12 = y2 - y1;
00309   int32_t                    //.kbv larger triangles overflow with int16_t
00310     sa   = 0,
00311     sb   = 0;
00312 
00313   // For upper part of triangle, find scanline crossings for segments
00314   // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
00315   // is included here (and second loop will be skipped, avoiding a /0
00316   // error there), otherwise scanline y1 is skipped here and handled
00317   // in the second loop...which also avoids a /0 error here if y0=y1
00318   // (flat-topped triangle).
00319   if(y1 == y2) last = y1;   // Include y1 scanline
00320   else         last = y1-1; // Skip it
00321 
00322   for(y=y0; y<=last; y++) {
00323     a   = x0 + sa / dy01;
00324     b   = x0 + sb / dy02;
00325     sa += dx01;
00326     sb += dx02;
00327     /* longhand:
00328     a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
00329     b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00330     */
00331     if(a > b) swap(a,b);
00332     drawFastHLine(a, y, b-a+1, color);
00333   }
00334 
00335   // For lower part of triangle, find scanline crossings for segments
00336   // 0-2 and 1-2.  This loop is skipped if y1=y2.
00337   sa = dx12 * (y - y1);
00338   sb = dx02 * (y - y0);
00339   for(; y<=y2; y++) {
00340     a   = x1 + sa / dy12;
00341     b   = x0 + sb / dy02;
00342     sa += dx12;
00343     sb += dx02;
00344     /* longhand:
00345     a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
00346     b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00347     */
00348     if(a > b) swap(a,b);
00349     drawFastHLine(a, y, b-a+1, color);
00350   }
00351 }
00352 
00353 void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
00354                   const uint8_t *bitmap, int16_t w, int16_t h,
00355                   uint16_t color) {
00356 
00357   int16_t i, j, byteWidth = (w + 7) / 8;
00358 
00359   for(j=0; j<h; j++) {
00360     for(i=0; i<w; i++ ) {
00361       if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
00362     drawPixel(x+i, y+j, color);
00363       }
00364     }
00365   }
00366 }
00367 
00368 #if defined(ARDUINO) && ARDUINO < 100
00369 virtual void Adafruit_GFX::write(uint8_t c) {
00370 #else
00371 size_t Adafruit_GFX::write(uint8_t c) {
00372 #endif
00373   if (c == '\n') {
00374     cursor_y += textsize*8;
00375     cursor_x  = 0;
00376   } else if (c == '\r') {
00377     // skip em
00378   } else {
00379     drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
00380     cursor_x += textsize*6;
00381     if (wrap && (cursor_x > (_width - textsize*6))) {
00382       cursor_y += textsize*8;
00383       cursor_x = 0;
00384     }
00385   }
00386 #if !(defined(ARDUINO) && ARDUINO < 100)
00387   return 1;
00388 #endif
00389 }
00390 
00391 // Draw a character
00392 void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
00393                 uint16_t color, uint16_t bg, uint8_t size) {
00394 
00395   if((x >= _width)            || // Clip right
00396      (y >= _height)           || // Clip bottom
00397      ((x + 6 * size - 1) < 0) || // Clip left
00398      ((y + 8 * size - 1) < 0))   // Clip top
00399     return;
00400 
00401   for (int8_t i=0; i<6; i++ ) {
00402     uint8_t line;
00403     if (i == 5) 
00404       line = 0x0;
00405     else 
00406       line = pgm_read_byte(font+(c*5)+i);
00407     for (int8_t j = 0; j<8; j++) {
00408       if (line & 0x1) {
00409         if (size == 1) // default size
00410           drawPixel(x+i, y+j, color);
00411         else {  // big size
00412           fillRect(x+(i*size), y+(j*size), size, size, color);
00413         } 
00414       } else if (bg != color) {
00415         if (size == 1) // default size
00416           drawPixel(x+i, y+j, bg);
00417         else {  // big size
00418           fillRect(x+i*size, y+j*size, size, size, bg);
00419         }
00420       }
00421       line >>= 1;
00422     }
00423   }
00424 }
00425 
00426 void Adafruit_GFX::setCursor(int16_t x, int16_t y) {
00427   cursor_x = x;
00428   cursor_y = y;
00429 }
00430 
00431 void Adafruit_GFX::setTextSize(uint8_t s) {
00432   textsize = (s > 0) ? s : 1;
00433 }
00434 
00435 void Adafruit_GFX::setTextColor(uint16_t c) {
00436   // For 'transparent' background, we'll set the bg 
00437   // to the same as fg instead of using a flag
00438   textcolor = textbgcolor = c;
00439 }
00440 
00441 void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
00442   textcolor   = c;
00443   textbgcolor = b; 
00444 }
00445 
00446 void Adafruit_GFX::setTextWrap(boolean w) {
00447   wrap = w;
00448 }
00449 
00450 uint8_t Adafruit_GFX::getRotation(void) {
00451   return rotation;
00452 }
00453 
00454 void Adafruit_GFX::setRotation(uint8_t x) {
00455   rotation = (x & 3);
00456   switch(rotation) {
00457    case 0:
00458    case 2:
00459     _width  = WIDTH;
00460     _height = HEIGHT;
00461     break;
00462    case 1:
00463    case 3:
00464     _width  = HEIGHT;
00465     _height = WIDTH;
00466     break;
00467   }
00468 }
00469 
00470 // Return the size of the display (per current rotation)
00471 int16_t Adafruit_GFX::width(void) {
00472   return _width;
00473 }
00474  
00475 int16_t Adafruit_GFX::height(void) {
00476   return _height;
00477 }
00478 
00479 void Adafruit_GFX::invertDisplay(boolean i) {
00480   // Do nothing, must be subclassed if supported
00481 }
00482 
00483 // this looks the most convenient method of all.  i.e. forget about print() and println()
00484 // and could be part of ADA_GFX_kbv.cpp.  possibly overwritten by later classes.
00485 // possibly use global buffer rather than stack.
00486 #include <stdarg.h>
00487 int  Adafruit_GFX::printf(const char* format, ...)
00488 {
00489     char buffer[80];
00490     va_list args;
00491     va_start (args, format);
00492     vsnprintf (buffer, 80, format, args);
00493     for (char *p = buffer; *p; p++) write(*p);
00494     va_end (args);
00495     return strlen(buffer);
00496 }