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