Port of the Adafruit_GFX library for use in MBED. This is the core graphics library for all Adafruit's displays, providing a common set of graphics primitives (points, lines, circles, strings,bitmaps. etc). Complete details found @ https://github.com/adafruit/Adafruit-GFX-Library Required by Adafruit_PCD8544 Driver. BSD license.

Dependents:   ili9341_test ece495_firmware Adafruit-64x32-PWM-Demo Pong_ILI9163C

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Adafruit_GFX.cpp Source File

Adafruit_GFX.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 /*Modified for MBED usage and tested with STM32F411RE on a Nucleo board.
00034 Embedded Print methods from Arduino Print.Cpp/Print.h
00035 
00036 by James Kidd 2014
00037  * */
00038 
00039 #include <stdint.h>
00040 #include "Adafruit_GFX.h"
00041 #include "glcdfont.c"
00042 #include <math.h>
00043 #include <stdlib.h>
00044 #include <stddef.h>
00045  #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
00046 
00047 
00048 Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h):
00049   WIDTH(w), HEIGHT(h)
00050 {
00051   _width    = WIDTH;
00052   _height   = HEIGHT;
00053   rotation  = 0;
00054   cursor_y  = cursor_x    = 0;
00055   textsize  = 1;
00056   textcolor = textbgcolor = 0xFFFF;
00057   wrap      = true;
00058 }
00059 
00060 // Draw a circle outline
00061 void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
00062     uint16_t color) {
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   drawPixel(x0  , y0+r, color);
00070   drawPixel(x0  , y0-r, color);
00071   drawPixel(x0+r, y0  , color);
00072   drawPixel(x0-r, y0  , color);
00073 
00074   while (x<y) {
00075     if (f >= 0) {
00076       y--;
00077       ddF_y += 2;
00078       f += ddF_y;
00079     }
00080     x++;
00081     ddF_x += 2;
00082     f += ddF_x;
00083   
00084     drawPixel(x0 + x, y0 + y, color);
00085     drawPixel(x0 - x, y0 + y, color);
00086     drawPixel(x0 + x, y0 - y, color);
00087     drawPixel(x0 - x, y0 - y, color);
00088     drawPixel(x0 + y, y0 + x, color);
00089     drawPixel(x0 - y, y0 + x, color);
00090     drawPixel(x0 + y, y0 - x, color);
00091     drawPixel(x0 - y, y0 - x, color);
00092   }
00093 }
00094 
00095 void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0,
00096                int16_t r, uint8_t cornername, uint16_t color) {
00097   int16_t f     = 1 - r;
00098   int16_t ddF_x = 1;
00099   int16_t ddF_y = -2 * r;
00100   int16_t x     = 0;
00101   int16_t y     = r;
00102 
00103   while (x<y) {
00104     if (f >= 0) {
00105       y--;
00106       ddF_y += 2;
00107       f     += ddF_y;
00108     }
00109     x++;
00110     ddF_x += 2;
00111     f     += ddF_x;
00112     if (cornername & 0x4) {
00113       drawPixel(x0 + x, y0 + y, color);
00114       drawPixel(x0 + y, y0 + x, color);
00115     } 
00116     if (cornername & 0x2) {
00117       drawPixel(x0 + x, y0 - y, color);
00118       drawPixel(x0 + y, y0 - x, color);
00119     }
00120     if (cornername & 0x8) {
00121       drawPixel(x0 - y, y0 + x, color);
00122       drawPixel(x0 - x, y0 + y, color);
00123     }
00124     if (cornername & 0x1) {
00125       drawPixel(x0 - y, y0 - x, color);
00126       drawPixel(x0 - x, y0 - y, color);
00127     }
00128   }
00129 }
00130 
00131 void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
00132                   uint16_t color) {
00133   drawFastVLine(x0, y0-r, 2*r+1, color);
00134   fillCircleHelper(x0, y0, r, 3, 0, color);
00135 }
00136 
00137 // Used to do circles and roundrects
00138 void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
00139     uint8_t cornername, int16_t delta, uint16_t color) {
00140 
00141   int16_t f     = 1 - r;
00142   int16_t ddF_x = 1;
00143   int16_t ddF_y = -2 * r;
00144   int16_t x     = 0;
00145   int16_t y     = r;
00146 
00147   while (x<y) {
00148     if (f >= 0) {
00149       y--;
00150       ddF_y += 2;
00151       f     += ddF_y;
00152     }
00153     x++;
00154     ddF_x += 2;
00155     f     += ddF_x;
00156 
00157     if (cornername & 0x1) {
00158       drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
00159       drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
00160     }
00161     if (cornername & 0x2) {
00162       drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
00163       drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
00164     }
00165   }
00166 }
00167 
00168 // Bresenham's algorithm - thx wikpedia
00169 void Adafruit_GFX::drawLine(int16_t x0, int16_t y0,
00170                 int16_t x1, int16_t y1,
00171                 uint16_t color) {
00172   int16_t steep =  abs(y1 - y0) > abs(x1 - x0);
00173   if (steep) {
00174     swap(x0, y0);
00175     swap(x1, y1);
00176   }
00177 
00178   if (x0 > x1) {
00179     swap(x0, x1);
00180     swap(y0, y1);
00181   }
00182 
00183   int16_t dx, dy;
00184   dx = x1 - x0;
00185   dy = abs(y1 - y0);
00186 
00187   int16_t err = dx / 2;
00188   int16_t ystep;
00189 
00190   if (y0 < y1) {
00191     ystep = 1;
00192   } else {
00193     ystep = -1;
00194   }
00195 
00196   for (; x0<=x1; x0++) {
00197     if (steep) {
00198       drawPixel(y0, x0, color);
00199     } else {
00200       drawPixel(x0, y0, color);
00201     }
00202     err -= dy;
00203     if (err < 0) {
00204       y0 += ystep;
00205       err += dx;
00206     }
00207   }
00208 }
00209 
00210 // Draw a rectangle
00211 void Adafruit_GFX::drawRect(int16_t x, int16_t y,
00212                 int16_t w, int16_t h,
00213                 uint16_t color) {
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::drawFastVLine(int16_t x, int16_t y,
00221                  int16_t h, uint16_t color) {
00222   // Update in subclasses if desired!
00223   drawLine(x, y, x, y+h-1, color);
00224 }
00225 
00226 void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y,
00227                  int16_t w, uint16_t color) {
00228   // Update in subclasses if desired!
00229   drawLine(x, y, x+w-1, y, color);
00230 }
00231 
00232 void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
00233                 uint16_t color) {
00234   // Update in subclasses if desired!
00235   for (int16_t i=x; i<x+w; i++) {
00236     drawFastVLine(i, y, h, color);
00237   }
00238 }
00239 
00240 void Adafruit_GFX::fillScreen(uint16_t color) {
00241   fillRect(0, 0, _width, _height, color);
00242 }
00243 
00244 // Draw a rounded rectangle
00245 void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
00246   int16_t h, int16_t r, uint16_t color) {
00247   // smarter version
00248   drawFastHLine(x+r  , y    , w-2*r, color); // Top
00249   drawFastHLine(x+r  , y+h-1, w-2*r, color); // Bottom
00250   drawFastVLine(x    , y+r  , h-2*r, color); // Left
00251   drawFastVLine(x+w-1, y+r  , h-2*r, color); // Right
00252   // draw four corners
00253   drawCircleHelper(x+r    , y+r    , r, 1, color);
00254   drawCircleHelper(x+w-r-1, y+r    , r, 2, color);
00255   drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
00256   drawCircleHelper(x+r    , y+h-r-1, r, 8, color);
00257 }
00258 
00259 // Fill a rounded rectangle
00260 void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
00261                  int16_t h, int16_t r, uint16_t color) {
00262   // smarter version
00263   fillRect(x+r, y, w-2*r, h, color);
00264 
00265   // draw four corners
00266   fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
00267   fillCircleHelper(x+r    , y+r, r, 2, h-2*r-1, color);
00268 }
00269 
00270 // Draw a triangle
00271 void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0,
00272                 int16_t x1, int16_t y1,
00273                 int16_t x2, int16_t y2, uint16_t color) {
00274   drawLine(x0, y0, x1, y1, color);
00275   drawLine(x1, y1, x2, y2, color);
00276   drawLine(x2, y2, x0, y0, color);
00277 }
00278 
00279 // Fill a triangle
00280 void Adafruit_GFX::fillTriangle ( int16_t x0, int16_t y0,
00281                   int16_t x1, int16_t y1,
00282                   int16_t x2, int16_t y2, uint16_t color) {
00283 
00284   int16_t a, b, y, last;
00285 
00286   // Sort coordinates by Y order (y2 >= y1 >= y0)
00287   if (y0 > y1) {
00288     swap(y0, y1); swap(x0, x1);
00289   }
00290   if (y1 > y2) {
00291     swap(y2, y1); swap(x2, x1);
00292   }
00293   if (y0 > y1) {
00294     swap(y0, y1); swap(x0, x1);
00295   }
00296 
00297   if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
00298     a = b = x0;
00299     if(x1 < a)      a = x1;
00300     else if(x1 > b) b = x1;
00301     if(x2 < a)      a = x2;
00302     else if(x2 > b) b = x2;
00303     drawFastHLine(a, y0, b-a+1, color);
00304     return;
00305   }
00306 
00307   int16_t
00308     dx01 = x1 - x0,
00309     dy01 = y1 - y0,
00310     dx02 = x2 - x0,
00311     dy02 = y2 - y0,
00312     dx12 = x2 - x1,
00313     dy12 = y2 - y1;
00314   int32_t
00315     sa   = 0,
00316     sb   = 0;
00317 
00318   // For upper part of triangle, find scanline crossings for segments
00319   // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
00320   // is included here (and second loop will be skipped, avoiding a /0
00321   // error there), otherwise scanline y1 is skipped here and handled
00322   // in the second loop...which also avoids a /0 error here if y0=y1
00323   // (flat-topped triangle).
00324   if(y1 == y2) last = y1;   // Include y1 scanline
00325   else         last = y1-1; // Skip it
00326 
00327   for(y=y0; y<=last; y++) {
00328     a   = x0 + sa / dy01;
00329     b   = x0 + sb / dy02;
00330     sa += dx01;
00331     sb += dx02;
00332     /* longhand:
00333     a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
00334     b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00335     */
00336     if(a > b) swap(a,b);
00337     drawFastHLine(a, y, b-a+1, color);
00338   }
00339 
00340   // For lower part of triangle, find scanline crossings for segments
00341   // 0-2 and 1-2.  This loop is skipped if y1=y2.
00342   sa = dx12 * (y - y1);
00343   sb = dx02 * (y - y0);
00344   for(; y<=y2; y++) {
00345     a   = x1 + sa / dy12;
00346     b   = x0 + sb / dy02;
00347     sa += dx12;
00348     sb += dx02;
00349     /* longhand:
00350     a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
00351     b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00352     */
00353     if(a > b) swap(a,b);
00354     drawFastHLine(a, y, b-a+1, color);
00355   }
00356 }
00357 
00358 void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
00359                   const uint8_t *bitmap, int16_t w, int16_t h,
00360                   uint16_t color) {
00361 
00362   int16_t i, j, byteWidth = (w + 7) / 8;
00363 
00364   for(j=0; j<h; j++) {
00365     for(i=0; i<w; i++ ) {
00366       if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
00367         drawPixel(x+i, y+j, color);
00368       }
00369     }
00370   }
00371 }
00372 
00373 // Draw a 1-bit color bitmap at the specified x, y position from the
00374 // provided bitmap buffer (must be PROGMEM memory) using color as the
00375 // foreground color and bg as the background color.
00376 void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
00377             const uint8_t *bitmap, int16_t w, int16_t h,
00378             uint16_t color, uint16_t bg) {
00379 
00380   int16_t i, j, byteWidth = (w + 7) / 8;
00381   
00382   for(j=0; j<h; j++) {
00383     for(i=0; i<w; i++ ) {
00384       if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
00385         drawPixel(x+i, y+j, color);
00386       }
00387       else {
00388         drawPixel(x+i, y+j, bg);
00389       }
00390     }
00391   }
00392 }
00393 
00394 //Draw XBitMap Files (*.xbm), exported from GIMP,
00395 //Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor.
00396 //C Array can be directly used with this function
00397 void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y,
00398                               const uint8_t *bitmap, int16_t w, int16_t h,
00399                               uint16_t color) {
00400   
00401   int16_t i, j, byteWidth = (w + 7) / 8;
00402   
00403   for(j=0; j<h; j++) {
00404     for(i=0; i<w; i++ ) {
00405       if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i % 8))) {
00406         drawPixel(x+i, y+j, color);
00407       }
00408     }
00409   }
00410 }
00411 
00412 
00413 uint8_t Adafruit_GFX::write(uint8_t c) {
00414 
00415   if (c == '\n') {
00416     cursor_y += textsize*8;
00417     cursor_x  = 0;
00418   } else if (c == '\r') {
00419     // skip em
00420   } else {
00421     drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
00422     cursor_x += textsize*6;
00423     if (wrap && (cursor_x > (_width - textsize*6))) {
00424       cursor_y += textsize*8;
00425       cursor_x = 0;
00426     }
00427   }
00428 
00429   return 1;
00430 
00431 }
00432 
00433 // Draw a character
00434 void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
00435                 uint16_t color, uint16_t bg, uint8_t size) {
00436 
00437   if((x >= _width)            || // Clip right
00438      (y >= _height)           || // Clip bottom
00439      ((x + 6 * size - 1) < 0) || // Clip left
00440      ((y + 8 * size - 1) < 0))   // Clip top
00441     return;
00442 
00443   for (int8_t i=0; i<6; i++ ) {
00444     uint8_t line;
00445     if (i == 5) 
00446       line = 0x0;
00447     else 
00448       line = pgm_read_byte(font+(c*5)+i);
00449     for (int8_t j = 0; j<8; j++) {
00450       if (line & 0x1) {
00451         if (size == 1) // default size
00452           drawPixel(x+i, y+j, color);
00453         else {  // big size
00454           fillRect(x+(i*size), y+(j*size), size, size, color);
00455         } 
00456       } else if (bg != color) {
00457         if (size == 1) // default size
00458           drawPixel(x+i, y+j, bg);
00459         else {  // big size
00460           fillRect(x+i*size, y+j*size, size, size, bg);
00461         }
00462       }
00463       line >>= 1;
00464     }
00465   }
00466 }
00467 
00468 void Adafruit_GFX::setCursor(int16_t x, int16_t y) {
00469   cursor_x = x;
00470   cursor_y = y;
00471 }
00472 
00473 void Adafruit_GFX::setTextSize(uint8_t s) {
00474   textsize = (s > 0) ? s : 1;
00475 }
00476 
00477 void Adafruit_GFX::setTextColor(uint16_t c) {
00478   // For 'transparent' background, we'll set the bg 
00479   // to the same as fg instead of using a flag
00480   textcolor = textbgcolor = c;
00481 }
00482 
00483 void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
00484   textcolor   = c;
00485   textbgcolor = b; 
00486 }
00487 
00488 void Adafruit_GFX::setTextWrap(bool w) {
00489   wrap = w;
00490 }
00491 
00492 uint8_t Adafruit_GFX::getRotation(void) const {
00493   return rotation;
00494 }
00495 
00496 void Adafruit_GFX::setRotation(uint8_t x) {
00497   rotation = (x & 3);
00498   switch(rotation) {
00499    case 0:
00500    case 2:
00501     _width  = WIDTH;
00502     _height = HEIGHT;
00503     break;
00504    case 1:
00505    case 3:
00506     _width  = HEIGHT;
00507     _height = WIDTH;
00508     break;
00509   }
00510 }
00511 
00512 // Return the size of the display (per current rotation)
00513 int16_t Adafruit_GFX::width(void) const {
00514   return _width;
00515 }
00516  
00517 int16_t Adafruit_GFX::height(void) const {
00518   return _height;
00519 }
00520 
00521 void Adafruit_GFX::invertDisplay(bool i) {
00522   // Do nothing, must be subclassed if supported
00523 }
00524 
00525 
00526 //Methods from Print.cpp Arduino
00527 
00528 uint8_t Adafruit_GFX::write(const uint8_t *buffer, uint8_t size)
00529 {
00530     uint8_t n = 0;
00531   while (size--) {
00532     n += write(*buffer++);
00533   }
00534   return n;
00535 }
00536 
00537 uint8_t Adafruit_GFX::print(const char str[])
00538 {
00539   return write(str);
00540 }
00541 
00542 uint8_t Adafruit_GFX::print(char c)
00543 {
00544   return write(c);
00545 }
00546 
00547 uint8_t Adafruit_GFX::print(unsigned char b, int base)
00548 {
00549   return print((unsigned long) b, base);
00550 }
00551 
00552 uint8_t Adafruit_GFX::print(int n, int base)
00553 {
00554   return print((long) n, base);
00555 }
00556 
00557 uint8_t Adafruit_GFX::print(unsigned int n, int base)
00558 {
00559   return print((unsigned long) n, base);
00560 }
00561 
00562 uint8_t Adafruit_GFX::print(long n, int base)
00563 {
00564   if (base == 0) {
00565     return write(n);
00566   } else if (base == 10) {
00567     if (n < 0) {
00568       int t = print('-');
00569       n = -n;
00570       return printNumber(n, 10) + t;
00571     }
00572     return printNumber(n, 10);
00573   } else {
00574     return printNumber(n, base);
00575   }
00576 }
00577 
00578 uint8_t Adafruit_GFX::print(unsigned long n, int base)
00579 {
00580   if (base == 0) return write(n);
00581   else return printNumber(n, base);
00582 }
00583 
00584 uint8_t Adafruit_GFX::print(double n, int digits)
00585 {
00586   return printFloat(n, digits);
00587 }
00588 
00589 
00590 
00591 
00592 
00593 uint8_t Adafruit_GFX::println(void)
00594 {
00595   size_t n = print('\r');
00596   n += print('\n');
00597   return n;
00598 }
00599 
00600 
00601 
00602 uint8_t Adafruit_GFX::println(const char c[])
00603 {
00604   size_t n = print(c);
00605   n += println();
00606   return n;
00607 }
00608 
00609 uint8_t Adafruit_GFX::println(char c)
00610 {
00611   size_t n = print(c);
00612   n += println();
00613   return n;
00614 }
00615 
00616 uint8_t Adafruit_GFX::println(unsigned char b, int numBase)
00617 {
00618   size_t n = print(b, numBase);
00619   n += println();
00620   return n;
00621 }
00622 
00623 uint8_t Adafruit_GFX::println(int num, int base)
00624 {
00625   size_t n = print(num, base);
00626   n += println();
00627   return n;
00628 }
00629 
00630 uint8_t Adafruit_GFX::println(unsigned int num, int base)
00631 {
00632   size_t n = print(num, base);
00633   n += println();
00634   return n;
00635 }
00636 
00637 uint8_t Adafruit_GFX::println(long num, int base)
00638 {
00639   size_t n = print(num, base);
00640   n += println();
00641   return n;
00642 }
00643 
00644 uint8_t Adafruit_GFX::println(unsigned long num, int base)
00645 {
00646   size_t n = print(num, base);
00647   n += println();
00648   return n;
00649 }
00650 
00651 uint8_t Adafruit_GFX::println(double num, int digits)
00652 {
00653   size_t n = print(num, digits);
00654   n += println();
00655   return n;
00656 }
00657 
00658 
00659 
00660 // Private Methods /////////////////////////////////////////////////////////////
00661 
00662 uint8_t Adafruit_GFX::printNumber(unsigned long n, uint8_t base) {
00663   char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
00664   char *str = &buf[sizeof(buf) - 1];
00665 
00666   *str = '\0';
00667 
00668   // prevent crash if called with base == 1
00669   if (base < 2) base = 10;
00670 
00671   do {
00672     unsigned long m = n;
00673     n /= base;
00674     char c = m - base * n;
00675     *--str = c < 10 ? c + '0' : c + 'A' - 10;
00676   } while(n);
00677 
00678   return write(str);
00679 }
00680 
00681 uint8_t Adafruit_GFX::printFloat(double number, uint8_t digits)
00682 {
00683     uint8_t n = 0;
00684 
00685   if (isnan(number)) return print("nan");
00686   if (isinf(number)) return print("inf");
00687   if (number > 4294967040.0) return print ("ovf");  // constant determined empirically
00688   if (number <-4294967040.0) return print ("ovf");  // constant determined empirically
00689 
00690   // Handle negative numbers
00691   if (number < 0.0)
00692   {
00693      n += print('-');
00694      number = -number;
00695   }
00696 
00697   // Round correctly so that print(1.999, 2) prints as "2.00"
00698   double rounding = 0.5;
00699   for (uint8_t i=0; i<digits; ++i)
00700     rounding /= 10.0;
00701 
00702   number += rounding;
00703 
00704   // Extract the integer part of the number and print it
00705   unsigned long int_part = (unsigned long)number;
00706   double remainder = number - (double)int_part;
00707   n += print(int_part);
00708 
00709   // Print the decimal point, but only if there are digits beyond
00710   if (digits > 0) {
00711     n += print(".");
00712   }
00713 
00714   // Extract digits from the remainder one at a time
00715   while (digits-- > 0)
00716   {
00717     remainder *= 10.0;
00718     int toPrint = int(remainder);
00719     n += print(toPrint);
00720     remainder -= toPrint;
00721   }
00722 
00723   return n;
00724 }
00725 
00726