A first port of the excellent Adafruit GFX library
Embed:
(wiki syntax)
Show/hide line numbers
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 00034 #include "mbed.h" 00035 #include "Adafruit_GFX.h" 00036 #include "glcdfont.h" 00037 00038 Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h): WIDTH(w), HEIGHT(h) { 00039 00040 _width = WIDTH; 00041 _height = HEIGHT; 00042 00043 rotation = 0; 00044 cursor_y = cursor_x = 0; 00045 textsize = 1; 00046 textcolor = textbgcolor = 0xFFFF; 00047 wrap = true; 00048 } 00049 00050 00051 // draw a circle outline 00052 void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, 00053 uint16_t color) { 00054 int16_t f = 1 - r; 00055 int16_t ddF_x = 1; 00056 int16_t ddF_y = -2 * r; 00057 int16_t x = 0; 00058 int16_t y = r; 00059 00060 drawPixel(x0, y0+r, color); 00061 drawPixel(x0, y0-r, color); 00062 drawPixel(x0+r, y0, color); 00063 drawPixel(x0-r, y0, color); 00064 00065 while (x<y) { 00066 if (f >= 0) { 00067 y--; 00068 ddF_y += 2; 00069 f += ddF_y; 00070 } 00071 x++; 00072 ddF_x += 2; 00073 f += ddF_x; 00074 00075 drawPixel(x0 + x, y0 + y, color); 00076 drawPixel(x0 - x, y0 + y, color); 00077 drawPixel(x0 + x, y0 - y, color); 00078 drawPixel(x0 - x, y0 - y, color); 00079 drawPixel(x0 + y, y0 + x, color); 00080 drawPixel(x0 - y, y0 + x, color); 00081 drawPixel(x0 + y, y0 - x, color); 00082 drawPixel(x0 - y, y0 - x, color); 00083 00084 } 00085 } 00086 00087 void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0, 00088 int16_t r, uint8_t cornername, uint16_t color) { 00089 int16_t f = 1 - r; 00090 int16_t ddF_x = 1; 00091 int16_t ddF_y = -2 * r; 00092 int16_t x = 0; 00093 int16_t y = r; 00094 00095 while (x<y) { 00096 if (f >= 0) { 00097 y--; 00098 ddF_y += 2; 00099 f += ddF_y; 00100 } 00101 x++; 00102 ddF_x += 2; 00103 f += ddF_x; 00104 if (cornername & 0x4) { 00105 drawPixel(x0 + x, y0 + y, color); 00106 drawPixel(x0 + y, y0 + x, color); 00107 } 00108 if (cornername & 0x2) { 00109 drawPixel(x0 + x, y0 - y, color); 00110 drawPixel(x0 + y, y0 - x, color); 00111 } 00112 if (cornername & 0x8) { 00113 drawPixel(x0 - y, y0 + x, color); 00114 drawPixel(x0 - x, y0 + y, color); 00115 } 00116 if (cornername & 0x1) { 00117 drawPixel(x0 - y, y0 - x, color); 00118 drawPixel(x0 - x, y0 - y, color); 00119 } 00120 } 00121 } 00122 00123 void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, 00124 uint16_t color) { 00125 drawFastVLine(x0, y0-r, 2*r+1, color); 00126 fillCircleHelper(x0, y0, r, 3, 0, color); 00127 } 00128 00129 // used to do circles and roundrects! 00130 void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, 00131 uint8_t cornername, int16_t delta, uint16_t color) { 00132 00133 int16_t f = 1 - r; 00134 int16_t ddF_x = 1; 00135 int16_t ddF_y = -2 * r; 00136 int16_t x = 0; 00137 int16_t y = r; 00138 00139 while (x<y) { 00140 if (f >= 0) { 00141 y--; 00142 ddF_y += 2; 00143 f += ddF_y; 00144 } 00145 x++; 00146 ddF_x += 2; 00147 f += ddF_x; 00148 00149 if (cornername & 0x1) { 00150 drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); 00151 drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); 00152 } 00153 if (cornername & 0x2) { 00154 drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); 00155 drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); 00156 } 00157 } 00158 } 00159 00160 // bresenham's algorithm - thx wikpedia 00161 void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, 00162 int16_t x1, int16_t y1, 00163 uint16_t color) { 00164 int16_t steep = abs(y1 - y0) > abs(x1 - x0); 00165 if (steep) { 00166 aswap(x0, y0); 00167 aswap(x1, y1); 00168 } 00169 00170 if (x0 > x1) { 00171 aswap(x0, x1); 00172 aswap(y0, y1); 00173 } 00174 00175 int16_t dx, dy; 00176 dx = x1 - x0; 00177 dy = abs(y1 - y0); 00178 00179 int16_t err = dx / 2; 00180 int16_t ystep; 00181 00182 if (y0 < y1) { 00183 ystep = 1; 00184 } else { 00185 ystep = -1; 00186 } 00187 00188 for (; x0<=x1; x0++) { 00189 if (steep) { 00190 drawPixel(y0, x0, color); 00191 } else { 00192 drawPixel(x0, y0, color); 00193 } 00194 err -= dy; 00195 if (err < 0) { 00196 y0 += ystep; 00197 err += dx; 00198 } 00199 } 00200 } 00201 00202 00203 // draw a rectangle 00204 void Adafruit_GFX::drawRect(int16_t x, int16_t y, 00205 int16_t w, int16_t h, 00206 uint16_t color) { 00207 drawFastHLine(x, y, w, color); 00208 drawFastHLine(x, y+h-1, w, color); 00209 drawFastVLine(x, y, h, color); 00210 drawFastVLine(x+w-1, y, h, color); 00211 } 00212 00213 void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, 00214 int16_t h, uint16_t color) { 00215 // stupidest version - update in subclasses if desired! 00216 drawLine(x, y, x, y+h-1, color); 00217 } 00218 00219 00220 void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, 00221 int16_t w, uint16_t color) { 00222 // stupidest version - update in subclasses if desired! 00223 drawLine(x, y, x+w-1, y, color); 00224 } 00225 00226 void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, 00227 uint16_t color) { 00228 // stupidest version - update in subclasses if desired! 00229 for (int16_t i=x; i<x+w; i++) { 00230 drawFastVLine(i, y, h, color); 00231 } 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 aswap(y0, y1); aswap(x0, x1); 00284 } 00285 if (y1 > y2) { 00286 aswap(y2, y1); aswap(x2, x1); 00287 } 00288 if (y0 > y1) { 00289 aswap(y0, y1); aswap(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 sa = 0, 00310 sb = 0; 00311 00312 // For upper part of triangle, find scanline crossings for segments 00313 // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 00314 // is included here (and second loop will be skipped, avoiding a /0 00315 // error there), otherwise scanline y1 is skipped here and handled 00316 // in the second loop...which also avoids a /0 error here if y0=y1 00317 // (flat-topped triangle). 00318 if(y1 == y2) last = y1; // Include y1 scanline 00319 else last = y1-1; // Skip it 00320 00321 for(y=y0; y<=last; y++) { 00322 a = x0 + sa / dy01; 00323 b = x0 + sb / dy02; 00324 sa += dx01; 00325 sb += dx02; 00326 /* longhand: 00327 a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); 00328 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); 00329 */ 00330 if(a > b) aswap(a,b); 00331 drawFastHLine(a, y, b-a+1, color); 00332 } 00333 00334 // For lower part of triangle, find scanline crossings for segments 00335 // 0-2 and 1-2. This loop is skipped if y1=y2. 00336 sa = dx12 * (y - y1); 00337 sb = dx02 * (y - y0); 00338 for(; y<=y2; y++) { 00339 a = x1 + sa / dy12; 00340 b = x0 + sb / dy02; 00341 sa += dx12; 00342 sb += dx02; 00343 /* longhand: 00344 a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); 00345 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); 00346 */ 00347 if(a > b) aswap(a,b); 00348 drawFastHLine(a, y, b-a+1, color); 00349 } 00350 } 00351 00352 void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, 00353 const uint8_t *bitmap, int16_t w, int16_t h, 00354 uint16_t color) { 00355 00356 int16_t i, j, byteWidth = (w + 7) / 8; 00357 00358 for(j=0; j<h; j++) { 00359 for(i=0; i<w; i++ ) { 00360 // if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) { 00361 if(bitmap[ j * byteWidth + i / 8] & (128 >> (i & 7))) { 00362 drawPixel(x+i, y+j, color); 00363 } 00364 } 00365 } 00366 } 00367 00368 int Adafruit_GFX::_putc(int c) { 00369 if (c == '\n') { 00370 cursor_y += textsize*8; 00371 cursor_x = 0; 00372 } else if (c == '\r') { 00373 // skip em 00374 } else { 00375 drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); 00376 cursor_x += textsize*6; 00377 if (wrap && (cursor_x > (_width - textsize*6))) { 00378 cursor_y += textsize*8; 00379 cursor_x = 0; 00380 } 00381 } 00382 00383 return c; 00384 } 00385 int Adafruit_GFX::_getc() { 00386 return -1; 00387 } 00388 00389 // draw a character 00390 void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, 00391 uint16_t color, uint16_t bg, uint8_t size) { 00392 00393 if((x >= _width) || // Clip right 00394 (y >= _height) || // Clip bottom 00395 ((x + 6 * size - 1) < 0) || // Clip left 00396 ((y + 8 * size - 1) < 0)) // Clip top 00397 return; 00398 00399 for (int8_t i=0; i<6; i++ ) { 00400 uint8_t line; 00401 if (i == 5) 00402 line = 0x0; 00403 else 00404 line = font[(c*5)+i]; 00405 for (int8_t j = 0; j<8; j++) { 00406 if (line & 0x1) { 00407 if (size == 1) // default size 00408 drawPixel(x+i, y+j, color); 00409 else { // big size 00410 fillRect(x+(i*size), y+(j*size), size, size, color); 00411 } 00412 } else if (bg != color) { 00413 if (size == 1) // default size 00414 drawPixel(x+i, y+j, bg); 00415 else { // big size 00416 fillRect(x+i*size, y+j*size, size, size, bg); 00417 } 00418 } 00419 line >>= 1; 00420 } 00421 } 00422 } 00423 00424 void Adafruit_GFX::setCursor(int16_t x, int16_t y) { 00425 cursor_x = x; 00426 cursor_y = y; 00427 } 00428 00429 00430 void Adafruit_GFX::setTextSize(uint8_t s) { 00431 textsize = (s > 0) ? s : 1; 00432 } 00433 00434 00435 void Adafruit_GFX::setTextColor(uint16_t c) { 00436 textcolor = c; 00437 textbgcolor = c; 00438 // for 'transparent' background, we'll set the bg 00439 // to the same as fg instead of using a flag 00440 } 00441 00442 void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) { 00443 textcolor = c; 00444 textbgcolor = b; 00445 } 00446 00447 void Adafruit_GFX::setTextWrap(boolean w) { 00448 wrap = w; 00449 } 00450 00451 uint8_t Adafruit_GFX::getRotation(void) { 00452 rotation %= 4; 00453 return rotation; 00454 } 00455 00456 void Adafruit_GFX::setRotation(uint8_t x) { 00457 x %= 4; // cant be higher than 3 00458 rotation = x; 00459 switch (x) { 00460 case 0: 00461 case 2: 00462 _width = WIDTH; 00463 _height = HEIGHT; 00464 break; 00465 case 1: 00466 case 3: 00467 _width = HEIGHT; 00468 _height = WIDTH; 00469 break; 00470 } 00471 } 00472 00473 00474 void Adafruit_GFX::invertDisplay(boolean i) { 00475 // do nothing, can be subclassed 00476 } 00477 00478 00479 // return the size of the display which depends on the rotation! 00480 int16_t Adafruit_GFX::width(void) { 00481 return _width; 00482 } 00483 00484 int16_t Adafruit_GFX::height(void) { 00485 return _height; 00486 }
Generated on Sat Jul 16 2022 18:58:44 by 1.7.2