acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
Arduino_TFT.cpp (35127B)
1 /* 2 * start rewrite from: 3 * https://github.com/adafruit/Adafruit-GFX-Library.git 4 */ 5 #include "Arduino_DataBus.h" 6 #include "Arduino_GFX.h" 7 #include "Arduino_TFT.h" 8 #include "font/glcdfont.h" 9 10 Arduino_TFT::Arduino_TFT( 11 Arduino_DataBus *bus, int8_t rst, uint8_t r, 12 bool ips, int16_t w, int16_t h, 13 uint8_t col_offset1, uint8_t row_offset1, uint8_t col_offset2, uint8_t row_offset2) 14 : Arduino_GFX(w, h), _bus(bus), _rst(rst), _ips(ips), 15 COL_OFFSET1(col_offset1), ROW_OFFSET1(row_offset1), 16 COL_OFFSET2(col_offset2), ROW_OFFSET2(row_offset2) 17 { 18 _rotation = r; 19 } 20 21 bool Arduino_TFT::begin(int32_t speed) 22 { 23 if (_override_datamode != GFX_NOT_DEFINED) 24 { 25 if (!_bus->begin(speed, _override_datamode)) 26 { 27 return false; 28 } 29 } 30 else 31 { 32 if (!_bus->begin(speed)) 33 { 34 return false; 35 } 36 } 37 38 tftInit(); 39 setRotation(_rotation); // apply the setting rotation to the display 40 setAddrWindow(0, 0, _width, _height); 41 42 return true; 43 } 44 45 void Arduino_TFT::startWrite() 46 { 47 _bus->beginWrite(); 48 } 49 50 void Arduino_TFT::writePixelPreclipped(int16_t x, int16_t y, uint16_t color) 51 { 52 writeAddrWindow(x, y, 1, 1); 53 _bus->write16(color); 54 } 55 56 void Arduino_TFT::writeRepeat(uint16_t color, uint32_t len) 57 { 58 _bus->writeRepeat(color, len); 59 } 60 61 /*! 62 @brief Draw a vertical line on the display. Performs edge clipping and 63 rejection. Not self-contained; should follow startWrite(). 64 Typically used by higher-level graphics primitives; user code 65 shouldn't need to call this and is likely to use the self- 66 contained drawFastVLine() instead. 67 @param x Horizontal position of first point. 68 @param y Vertical position of first point. 69 @param h Line height in pixels (positive = below first point, 70 negative = above first point). 71 @param color 16-bit line color in '565' RGB format. 72 */ 73 void Arduino_TFT::writeFastVLine(int16_t x, int16_t y, int16_t h, 74 uint16_t color) 75 { 76 if (_ordered_in_range(x, 0, _max_x) && h) 77 { // X on screen, nonzero height 78 if (h < 0) 79 { // If negative height... 80 y += h + 1; // Move Y to top edge 81 h = -h; // Use positive height 82 } 83 if (y <= _max_y) 84 { // Not off bottom 85 int16_t y2 = y + h - 1; 86 if (y2 >= 0) 87 { // Not off top 88 // Line partly or fully overlaps screen 89 if (y < 0) 90 { 91 y = 0; 92 h = y2 + 1; 93 } // Clip top 94 if (y2 > _max_y) 95 { 96 h = _max_y - y + 1; 97 } // Clip bottom 98 writeFillRectPreclipped(x, y, 1, h, color); 99 } 100 } 101 } 102 } 103 104 /*! 105 @brief Draw a horizontal line on the display. Performs edge clipping 106 and rejection. Not self-contained; should follow startWrite(). 107 Typically used by higher-level graphics primitives; user code 108 shouldn't need to call this and is likely to use the self- 109 contained drawFastHLine() instead. 110 @param x Horizontal position of first point. 111 @param y Vertical position of first point. 112 @param w Line width in pixels (positive = right of first point, 113 negative = point of first corner). 114 @param color 16-bit line color in '565' RGB format. 115 */ 116 void Arduino_TFT::writeFastHLine(int16_t x, int16_t y, int16_t w, 117 uint16_t color) 118 { 119 if (_ordered_in_range(y, 0, _max_y) && w) 120 { // Y on screen, nonzero width 121 if (w < 0) 122 { // If negative width... 123 x += w + 1; // Move X to left edge 124 w = -w; // Use positive width 125 } 126 if (x <= _max_x) 127 { // Not off right 128 int16_t x2 = x + w - 1; 129 if (x2 >= 0) 130 { // Not off left 131 // Line partly or fully overlaps screen 132 if (x < 0) 133 { 134 x = 0; 135 w = x2 + 1; 136 } // Clip left 137 if (x2 > _max_x) 138 { 139 w = _max_x - x + 1; 140 } // Clip right 141 writeFillRectPreclipped(x, y, w, 1, color); 142 } 143 } 144 } 145 } 146 147 /*! 148 @brief A lower-level version of writeFillRect(). This version requires 149 all inputs are in-bounds, that width and height are positive, 150 and no part extends offscreen. NO EDGE CLIPPING OR REJECTION IS 151 PERFORMED. If higher-level graphics primitives are written to 152 handle their own clipping earlier in the drawing process, this 153 can avoid unnecessary function calls and repeated clipping 154 operations in the lower-level functions. 155 @param x Horizontal position of first corner. MUST BE WITHIN 156 SCREEN BOUNDS. 157 @param y Vertical position of first corner. MUST BE WITHIN SCREEN 158 BOUNDS. 159 @param w Rectangle width in pixels. MUST BE POSITIVE AND NOT 160 EXTEND OFF SCREEN. 161 @param h Rectangle height in pixels. MUST BE POSITIVE AND NOT 162 EXTEND OFF SCREEN. 163 @param color 16-bit fill color in '565' RGB format. 164 @note This is a new function, no graphics primitives besides rects 165 and horizontal/vertical lines are written to best use this yet. 166 */ 167 void Arduino_TFT::writeFillRectPreclipped(int16_t x, int16_t y, 168 int16_t w, int16_t h, uint16_t color) 169 { 170 #ifdef ESP8266 171 yield(); 172 #endif 173 writeAddrWindow(x, y, w, h); 174 writeRepeat(color, (uint32_t)w * h); 175 } 176 177 void Arduino_TFT::endWrite() 178 { 179 _bus->endWrite(); 180 } 181 182 void Arduino_TFT::setAddrWindow(int16_t x0, int16_t y0, uint16_t w, 183 uint16_t h) 184 { 185 startWrite(); 186 187 writeAddrWindow(x0, y0, w, h); 188 189 endWrite(); 190 } 191 192 /**************************************************************************/ 193 /*! 194 @brief Set rotation setting for display 195 @param x 0 thru 3 corresponding to 4 cardinal rotations 196 */ 197 /**************************************************************************/ 198 void Arduino_TFT::setRotation(uint8_t r) 199 { 200 Arduino_GFX::setRotation(r); 201 switch (_rotation) 202 { 203 case 5: 204 case 3: 205 _xStart = ROW_OFFSET2; 206 _yStart = COL_OFFSET1; 207 break; 208 case 6: 209 case 2: 210 _xStart = COL_OFFSET2; 211 _yStart = ROW_OFFSET2; 212 break; 213 case 7: 214 case 1: 215 _xStart = ROW_OFFSET1; 216 _yStart = COL_OFFSET2; 217 break; 218 case 4: 219 default: // case 0: 220 _xStart = COL_OFFSET1; 221 _yStart = ROW_OFFSET1; 222 break; 223 } 224 _currentX = 0xFFFF; 225 _currentY = 0xFFFF; 226 _currentW = 0xFFFF; 227 _currentH = 0xFFFF; 228 } 229 230 void Arduino_TFT::writeColor(uint16_t color) 231 { 232 _bus->write16(color); 233 } 234 235 // TFT optimization code, too big for ATMEL family 236 #if !defined(LITTLE_FOOT_PRINT) 237 238 void Arduino_TFT::writeBytes(uint8_t *data, uint32_t len) 239 { 240 _bus->writeBytes(data, len); 241 } 242 243 void Arduino_TFT::writePixels(uint16_t *data, uint32_t len) 244 { 245 _bus->writePixels(data, len); 246 } 247 248 /**************************************************************************/ 249 /*! 250 @brief Push a pixel, overwrite in subclasses if startWrite is defined! 251 @param color 16-bit 5-6-5 Color to fill with 252 */ 253 /**************************************************************************/ 254 void Arduino_TFT::pushColor(uint16_t color) 255 { 256 _bus->beginWrite(); 257 writeColor(color); 258 _bus->endWrite(); 259 } 260 261 /**************************************************************************/ 262 /*! 263 @brief Write a line. Bresenham's algorithm - thx wikpedia 264 @param x0 Start point x coordinate 265 @param y0 Start point y coordinate 266 @param x1 End point x coordinate 267 @param y1 End point y coordinate 268 @param color 16-bit 5-6-5 Color to draw with 269 */ 270 /**************************************************************************/ 271 void Arduino_TFT::writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, 272 uint16_t color) 273 { 274 int16_t dx; 275 int16_t dy; 276 int16_t err; 277 int16_t xs; 278 int16_t step; 279 int16_t len; 280 281 bool steep = _diff(y1, y0) > _diff(x1, x0); 282 if (steep) 283 { 284 _swap_int16_t(x0, y0); 285 _swap_int16_t(x1, y1); 286 } 287 288 if (x0 > x1) 289 { 290 _swap_int16_t(x0, x1); 291 _swap_int16_t(y0, y1); 292 } 293 294 dx = x1 - x0; 295 dy = _diff(y1, y0); 296 err = dx >> 1; 297 xs = x0; 298 step = (y0 < y1) ? 1 : -1; 299 len = 0; 300 301 while (x0 <= x1) 302 { 303 x0++; 304 len++; 305 err -= dy; 306 if ((err < 0) || ((x0 > x1) && len)) 307 { 308 if (steep) 309 { 310 writeFillRectPreclipped(y0, xs, 1, len, color); 311 } 312 else 313 { 314 writeFillRectPreclipped(xs, y0, len, 1, color); 315 } 316 err += dx; 317 y0 += step; 318 len = 0; 319 xs = x0; 320 } 321 } 322 } 323 324 // TFT tuned BITMAP / XBITMAP / GRAYSCALE / RGB BITMAP FUNCTIONS --------------------- 325 326 /**************************************************************************/ 327 /*! 328 @brief Draw a Indexed 16-bit image (RGB 5/6/5) at the specified (x,y) position. 329 @param bitmap byte array of Indexed color bitmap 330 @param color_index byte array of 16-bit color index 331 @param w Width of bitmap in pixels 332 @param h Height of bitmap in pixels 333 */ 334 /**************************************************************************/ 335 void Arduino_TFT::writeIndexedPixels(uint8_t *bitmap, uint16_t *color_index, uint32_t len) 336 { 337 _bus->writeIndexedPixels(bitmap, color_index, len); 338 } 339 340 /**************************************************************************/ 341 /*! 342 @brief Draw a Indexed 16-bit image (RGB 5/6/5) at the specified (x,y) position. 343 @param bitmap byte array of Indexed color bitmap 344 @param color_index byte array of 16-bit color index 345 @param w Width of bitmap in pixels 346 @param h Height of bitmap in pixels 347 */ 348 /**************************************************************************/ 349 void Arduino_TFT::writeIndexedPixelsDouble(uint8_t *bitmap, uint16_t *color_index, uint32_t len) 350 { 351 _bus->writeIndexedPixelsDouble(bitmap, color_index, len); 352 } 353 354 /**************************************************************************/ 355 /*! 356 @brief Draw a PROGMEM-resident 1-bit image at the specified (x,y) position, using the specified foreground (for set bits) and background (unset bits) colors. 357 @param x Top left corner x coordinate 358 @param y Top left corner y coordinate 359 @param bitmap byte array with monochrome bitmap 360 @param w Width of bitmap in pixels 361 @param h Height of bitmap in pixels 362 @param color 16-bit 5-6-5 Color to draw pixels with 363 @param bg 16-bit 5-6-5 Color to draw background with 364 */ 365 /**************************************************************************/ 366 void Arduino_TFT::drawBitmap(int16_t x, int16_t y, 367 const uint8_t bitmap[], int16_t w, int16_t h, 368 uint16_t color, uint16_t bg) 369 { 370 if ( 371 ((x + w - 1) < 0) || // Outside left 372 ((y + h - 1) < 0) || // Outside top 373 (x > _max_x) || // Outside right 374 (y > _max_y) // Outside bottom 375 ) 376 { 377 return; 378 } 379 else if ( 380 (x < 0) || // Clip left 381 (y < 0) || // Clip top 382 ((x + w - 1) > _max_x) || // Clip right 383 ((y + h - 1) > _max_y) // Clip bottom 384 ) 385 { 386 Arduino_GFX::drawBitmap(x, y, bitmap, w, h, color, bg); 387 } 388 else 389 { 390 int32_t pixels = w * h; 391 uint8_t byte = 0; 392 uint16_t idx = 0; 393 startWrite(); 394 writeAddrWindow(x, y, w, h); 395 for (int32_t i = 0; i < pixels; i++) 396 { 397 if (i & 7) 398 { 399 byte <<= 1; 400 } 401 else 402 { 403 byte = pgm_read_byte(&bitmap[idx++]); 404 } 405 _bus->write16((byte & 0x80) ? color : bg); 406 } 407 endWrite(); 408 } 409 } 410 411 /**************************************************************************/ 412 /*! 413 @brief Draw a RAM-resident 1-bit image at the specified (x,y) position, using the specified foreground (for set bits) and background (unset bits) colors. 414 @param x Top left corner x coordinate 415 @param y Top left corner y coordinate 416 @param bitmap byte array with monochrome bitmap 417 @param w Width of bitmap in pixels 418 @param h Height of bitmap in pixels 419 @param color 16-bit 5-6-5 Color to draw pixels with 420 @param bg 16-bit 5-6-5 Color to draw background with 421 */ 422 /**************************************************************************/ 423 void Arduino_TFT::drawBitmap(int16_t x, int16_t y, 424 uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) 425 { 426 if ( 427 ((x + w - 1) < 0) || // Outside left 428 ((y + h - 1) < 0) || // Outside top 429 (x > _max_x) || // Outside right 430 (y > _max_y) // Outside bottom 431 ) 432 { 433 return; 434 } 435 else if ( 436 (x < 0) || // Clip left 437 (y < 0) || // Clip top 438 ((x + w - 1) > _max_x) || // Clip right 439 ((y + h - 1) > _max_y) // Clip bottom 440 ) 441 { 442 Arduino_GFX::drawBitmap(x, y, bitmap, w, h, color, bg); 443 } 444 else 445 { 446 int32_t pixels = w * h; 447 uint8_t byte = 0; 448 startWrite(); 449 writeAddrWindow(x, y, w, h); 450 for (int32_t i = 0; i < pixels; i++) 451 { 452 if (i & 7) 453 { 454 byte <<= 1; 455 } 456 else 457 { 458 byte = *(bitmap++); 459 } 460 _bus->write16((byte & 0x80) ? color : bg); 461 } 462 endWrite(); 463 } 464 } 465 466 /**************************************************************************/ 467 /*! 468 @brief Draw a PROGMEM-resident 8-bit image (grayscale) at the specified (x,y) pos. 469 @param x Top left corner x coordinate 470 @param y Top left corner y coordinate 471 @param bitmap byte array with grayscale bitmap 472 @param w Width of bitmap in pixels 473 @param h Height of bitmap in pixels 474 */ 475 /**************************************************************************/ 476 void Arduino_TFT::drawGrayscaleBitmap(int16_t x, int16_t y, 477 const uint8_t bitmap[], int16_t w, int16_t h) 478 { 479 if ( 480 ((x + w - 1) < 0) || // Outside left 481 ((y + h - 1) < 0) || // Outside top 482 (x > _max_x) || // Outside right 483 (y > _max_y) // Outside bottom 484 ) 485 { 486 return; 487 } 488 else if ( 489 (x < 0) || // Clip left 490 (y < 0) || // Clip top 491 ((x + w - 1) > _max_x) || // Clip right 492 ((y + h - 1) > _max_y) // Clip bottom 493 ) 494 { 495 Arduino_GFX::drawGrayscaleBitmap(x, y, bitmap, w, h); 496 } 497 else 498 { 499 uint32_t len = (uint32_t)w * h; 500 uint8_t v; 501 startWrite(); 502 writeAddrWindow(x, y, w, h); 503 for (uint32_t i = 0; i < len; i++) 504 { 505 v = (uint8_t)pgm_read_byte(&bitmap[i]); 506 _bus->write16(color565(v, v, v)); 507 } 508 endWrite(); 509 } 510 } 511 512 /**************************************************************************/ 513 /*! 514 @brief Draw a RAM-resident 8-bit image (grayscale) at the specified (x,y) pos. 515 @param x Top left corner x coordinate 516 @param y Top left corner y coordinate 517 @param bitmap byte array with grayscale bitmap 518 @param w Width of bitmap in pixels 519 @param h Height of bitmap in pixels 520 */ 521 /**************************************************************************/ 522 void Arduino_TFT::drawGrayscaleBitmap(int16_t x, int16_t y, 523 uint8_t *bitmap, int16_t w, int16_t h) 524 { 525 if ( 526 ((x + w - 1) < 0) || // Outside left 527 ((y + h - 1) < 0) || // Outside top 528 (x > _max_x) || // Outside right 529 (y > _max_y) // Outside bottom 530 ) 531 { 532 return; 533 } 534 else if ( 535 (x < 0) || // Clip left 536 (y < 0) || // Clip top 537 ((x + w - 1) > _max_x) || // Clip right 538 ((y + h - 1) > _max_y) // Clip bottom 539 ) 540 { 541 Arduino_GFX::drawGrayscaleBitmap(x, y, bitmap, w, h); 542 } 543 else 544 { 545 uint32_t len = (uint32_t)w * h; 546 uint8_t v; 547 startWrite(); 548 writeAddrWindow(x, y, w, h); 549 while (len--) 550 { 551 v = *(bitmap++); 552 _bus->write16(color565(v, v, v)); 553 } 554 endWrite(); 555 } 556 } 557 558 /**************************************************************************/ 559 /*! 560 @brief Draw a Indexed 16-bit image (RGB 5/6/5) at the specified (x,y) position. 561 @param x Top left corner x coordinate 562 @param y Top left corner y coordinate 563 @param bitmap byte array of Indexed color bitmap 564 @param color_index byte array of 16-bit color index 565 @param w Width of bitmap in pixels 566 @param h Height of bitmap in pixels 567 */ 568 /**************************************************************************/ 569 void Arduino_TFT::drawIndexedBitmap(int16_t x, int16_t y, 570 uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h) 571 { 572 if ( 573 ((x + w - 1) < 0) || // Outside left 574 ((y + h - 1) < 0) || // Outside top 575 (x > _max_x) || // Outside right 576 (y > _max_y) // Outside bottom 577 ) 578 { 579 return; 580 } 581 else if ( 582 (x < 0) || // Clip left 583 (y < 0) || // Clip top 584 ((x + w - 1) > _max_x) || // Clip right 585 ((y + h - 1) > _max_y) // Clip bottom 586 ) 587 { 588 Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h); 589 } 590 else 591 { 592 uint32_t len = w * h; 593 startWrite(); 594 writeAddrWindow(x, y, w, h); 595 _bus->writeIndexedPixels(bitmap, color_index, len); 596 endWrite(); 597 } 598 } 599 600 /**************************************************************************/ 601 /*! 602 @brief Draw a RAM-resident 16-bit image (RGB 5/6/5) with a 1-bit mask 603 (set bits = opaque, unset bits = clear) at the specified (x,y) position. 604 BOTH buffers (color and mask) must be RAM-resident. 605 @param x Top left corner x coordinate 606 @param y Top left corner y coordinate 607 @param bitmap byte array with 16-bit color bitmap 608 @param mask byte array with monochrome mask bitmap 609 @param w Width of bitmap in pixels 610 @param h Height of bitmap in pixels 611 */ 612 /**************************************************************************/ 613 void Arduino_TFT::draw16bitRGBBitmap(int16_t x, int16_t y, 614 uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h) 615 { 616 if ( 617 ((x + w - 1) < 0) || // Outside left 618 ((y + h - 1) < 0) || // Outside top 619 (x > _max_x) || // Outside right 620 (y > _max_y) // Outside bottom 621 ) 622 { 623 return; 624 } 625 else if ( 626 (x < 0) || // Clip left 627 (y < 0) || // Clip top 628 ((x + w - 1) > _max_x) || // Clip right 629 ((y + h - 1) > _max_y) // Clip bottom 630 ) 631 { 632 Arduino_GFX::draw16bitRGBBitmap(x, y, bitmap, mask, w, h); 633 } 634 else 635 { 636 int32_t offset = 0, maskIdx = 0, len = 0; 637 uint8_t byte = 0; 638 startWrite(); 639 for (int16_t j = 0; j < h; j++, y++) 640 { 641 for (int16_t i = 0; i < w; i++) 642 { 643 if (i & 7) 644 { 645 byte <<= 1; 646 } 647 else 648 { 649 byte = mask[maskIdx++]; 650 } 651 if (byte & 0x80) 652 { 653 len++; 654 } 655 else 656 { 657 if (len) 658 { 659 writeAddrWindow(x + i - len, y, len, 1); 660 _bus->writePixels(&bitmap[offset - len], len); 661 len = 0; 662 } 663 } 664 offset++; 665 } 666 if (len) 667 { 668 writeAddrWindow(x + w - 1 - len, y, len, 1); 669 _bus->writePixels(&bitmap[offset - len], len); 670 len = 0; 671 } 672 } 673 endWrite(); 674 } 675 } 676 677 /**************************************************************************/ 678 /*! 679 @brief Draw a PROGMEM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) position. 680 For 16-bit display devices; no color reduction performed. 681 @param x Top left corner x coordinate 682 @param y Top left corner y coordinate 683 @param bitmap byte array with 16-bit color bitmap 684 @param w Width of bitmap in pixels 685 @param h Height of bitmap in pixels 686 */ 687 /**************************************************************************/ 688 void Arduino_TFT::draw16bitRGBBitmap(int16_t x, int16_t y, 689 const uint16_t bitmap[], int16_t w, int16_t h) 690 { 691 if ( 692 ((x + w - 1) < 0) || // Outside left 693 ((y + h - 1) < 0) || // Outside top 694 (x > _max_x) || // Outside right 695 (y > _max_y) // Outside bottom 696 ) 697 { 698 return; 699 } 700 else if ( 701 (x < 0) || // Clip left 702 (y < 0) || // Clip top 703 ((x + w - 1) > _max_x) || // Clip right 704 ((y + h - 1) > _max_y) // Clip bottom 705 ) 706 { 707 Arduino_GFX::draw16bitRGBBitmap(x, y, bitmap, w, h); 708 } 709 else 710 { 711 uint32_t len = (uint32_t)w * h; 712 startWrite(); 713 writeAddrWindow(x, y, w, h); 714 for (uint32_t i = 0; i < len; i++) 715 { 716 _bus->write16(pgm_read_word(&bitmap[i])); 717 } 718 endWrite(); 719 } 720 } 721 722 /**************************************************************************/ 723 /*! 724 @brief Draw a RAM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) position. 725 For 16-bit display devices; no color reduction performed. 726 @param x Top left corner x coordinate 727 @param y Top left corner y coordinate 728 @param bitmap byte array with 16-bit color bitmap 729 @param w Width of bitmap in pixels 730 @param h Height of bitmap in pixels 731 */ 732 /**************************************************************************/ 733 void Arduino_TFT::draw16bitRGBBitmap(int16_t x, int16_t y, 734 uint16_t *bitmap, int16_t w, int16_t h) 735 { 736 if ( 737 ((x + w - 1) < 0) || // Outside left 738 ((y + h - 1) < 0) || // Outside top 739 (x > _max_x) || // Outside right 740 (y > _max_y) // Outside bottom 741 ) 742 { 743 return; 744 } 745 else if ( 746 (x < 0) || // Clip left 747 (y < 0) || // Clip top 748 ((x + w - 1) > _max_x) || // Clip right 749 ((y + h - 1) > _max_y) // Clip bottom 750 ) 751 { 752 Arduino_GFX::draw16bitRGBBitmap(x, y, bitmap, w, h); 753 } 754 else 755 { 756 startWrite(); 757 writeAddrWindow(x, y, w, h); 758 _bus->writePixels(bitmap, (uint32_t)w * h); 759 endWrite(); 760 } 761 } 762 763 /**************************************************************************/ 764 /*! 765 @brief Draw a RAM-resident 16-bit Big Endian image (RGB 5/6/5) at the specified (x,y) position. 766 For 16-bit display devices; no color reduction performed. 767 @param x Top left corner x coordinate 768 @param y Top left corner y coordinate 769 @param bitmap byte array with 16-bit color bitmap 770 @param w Width of bitmap in pixels 771 @param h Height of bitmap in pixels 772 */ 773 /**************************************************************************/ 774 void Arduino_TFT::draw16bitBeRGBBitmap(int16_t x, int16_t y, 775 uint16_t *bitmap, int16_t w, int16_t h) 776 { 777 if ( 778 ((x + w - 1) < 0) || // Outside left 779 ((y + h - 1) < 0) || // Outside top 780 (x > _max_x) || // Outside right 781 (y > _max_y) // Outside bottom 782 ) 783 { 784 return; 785 } 786 else if ( 787 (x < 0) || // Clip left 788 (y < 0) || // Clip top 789 ((x + w - 1) > _max_x) || // Clip right 790 ((y + h - 1) > _max_y) // Clip bottom 791 ) 792 { 793 Arduino_GFX::draw16bitBeRGBBitmap(x, y, bitmap, w, h); 794 } 795 else 796 { 797 startWrite(); 798 writeAddrWindow(x, y, w, h); 799 _bus->writeBytes((uint8_t *)bitmap, (uint32_t)w * h * 2); 800 endWrite(); 801 } 802 } 803 804 /**************************************************************************/ 805 /*! 806 @brief Draw a PROGMEM-resident 24-bit image (RGB 5/6/5) at the specified (x,y) position. 807 @param x Top left corner x coordinate 808 @param y Top left corner y coordinate 809 @param bitmap byte array with 16-bit color bitmap 810 @param w Width of bitmap in pixels 811 @param h Height of bitmap in pixels 812 */ 813 /**************************************************************************/ 814 void Arduino_TFT::draw24bitRGBBitmap(int16_t x, int16_t y, 815 const uint8_t bitmap[], int16_t w, int16_t h) 816 { 817 if ( 818 ((x + w - 1) < 0) || // Outside left 819 ((y + h - 1) < 0) || // Outside top 820 (x > _max_x) || // Outside right 821 (y > _max_y) // Outside bottom 822 ) 823 { 824 return; 825 } 826 else if ( 827 (x < 0) || // Clip left 828 (y < 0) || // Clip top 829 ((x + w - 1) > _max_x) || // Clip right 830 ((y + h - 1) > _max_y) // Clip bottom 831 ) 832 { 833 Arduino_GFX::draw24bitRGBBitmap(x, y, bitmap, w, h); 834 } 835 else 836 { 837 uint32_t len = (uint32_t)w * h; 838 uint32_t offset = 0; 839 startWrite(); 840 writeAddrWindow(x, y, w, h); 841 while (len--) 842 { 843 _bus->write16(color565(pgm_read_byte(&bitmap[offset]), pgm_read_byte(&bitmap[offset + 1]), pgm_read_byte(&bitmap[offset + 2]))); 844 offset += 3; 845 } 846 endWrite(); 847 } 848 } 849 850 /**************************************************************************/ 851 /*! 852 @brief Draw a RAM-resident 24-bit image (RGB 5/6/5) at the specified (x,y) position. 853 @param x Top left corner x coordinate 854 @param y Top left corner y coordinate 855 @param bitmap byte array with 16-bit color bitmap 856 @param w Width of bitmap in pixels 857 @param h Height of bitmap in pixels 858 */ 859 /**************************************************************************/ 860 void Arduino_TFT::draw24bitRGBBitmap(int16_t x, int16_t y, 861 uint8_t *bitmap, int16_t w, int16_t h) 862 { 863 if ( 864 ((x + w - 1) < 0) || // Outside left 865 ((y + h - 1) < 0) || // Outside top 866 (x > _max_x) || // Outside right 867 (y > _max_y) // Outside bottom 868 ) 869 { 870 return; 871 } 872 else if ( 873 (x < 0) || // Clip left 874 (y < 0) || // Clip top 875 ((x + w - 1) > _max_x) || // Clip right 876 ((y + h - 1) > _max_y) // Clip bottom 877 ) 878 { 879 Arduino_GFX::draw24bitRGBBitmap(x, y, bitmap, w, h); 880 } 881 else 882 { 883 uint32_t len = (uint32_t)w * h; 884 uint32_t offset = 0; 885 startWrite(); 886 writeAddrWindow(x, y, w, h); 887 while (len--) 888 { 889 _bus->write16(color565(bitmap[offset], bitmap[offset + 1], bitmap[offset + 2])); 890 offset += 3; 891 } 892 endWrite(); 893 } 894 } 895 896 // Draw a character 897 /**************************************************************************/ 898 /*! 899 @brief Draw a single character 900 @param x Bottom left corner x coordinate 901 @param y Bottom left corner y coordinate 902 @param c The 8-bit font-indexed character (likely ascii) 903 @param color 16-bit 5-6-5 Color to draw chraracter with 904 @param bg 16-bit 5-6-5 Color to fill background with (if same as color, no background) 905 */ 906 /**************************************************************************/ 907 void Arduino_TFT::drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg) 908 { 909 uint16_t block_w; 910 uint16_t block_h; 911 912 #if !defined(ATTINY_CORE) 913 if (gfxFont) // custom font 914 { 915 // Character is assumed previously filtered by write() to eliminate 916 // newlines, returns, non-printable characters, etc. Calling 917 // drawChar() directly with 'bad' characters of font may cause mayhem! 918 uint8_t first = pgm_read_byte(&gfxFont->first); 919 GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first); 920 uint8_t *bitmap = pgm_read_bitmap_ptr(gfxFont); 921 922 uint16_t bo = pgm_read_word(&glyph->bitmapOffset); 923 uint8_t w = pgm_read_byte(&glyph->width), 924 h = pgm_read_byte(&glyph->height), 925 xAdvance = pgm_read_byte(&glyph->xAdvance), 926 yAdvance = pgm_read_byte(&gfxFont->yAdvance), 927 baseline = yAdvance * 2 / 3; // TODO: baseline is an arbitrary currently, may be define in font file 928 int8_t xo = pgm_read_byte(&glyph->xOffset), 929 yo = pgm_read_byte(&glyph->yOffset); 930 // urgly workaround for the character not fit in the box 931 if ((bg != color) // have background color 932 && ((xo + w) > xAdvance)) // if character draw outside the box 933 { 934 xo = xAdvance - w; // pad inside the box 935 } 936 937 uint8_t xx, yy, bits = 0, bit = 0; 938 int16_t xo16 = xo, yo16 = yo; 939 940 if (xAdvance < w) 941 { 942 xAdvance = w; // Don't know why it exists 943 } 944 945 block_w = xAdvance * textsize_x; 946 block_h = yAdvance * textsize_y; 947 int16_t x1 = (xo < 0) ? (x + xo) : x; 948 if ( 949 (x1 < 0) || // Clip left 950 ((y - baseline) < 0) || // Clip top 951 ((x1 + block_w - 1) > _max_x) || // Clip right 952 ((y - baseline + block_h - 1) > _max_y) // Clip bottom 953 ) 954 { 955 // partial draw char by parent class 956 Arduino_GFX::drawChar(x, y, c, color, bg); 957 } 958 else 959 { 960 // NOTE: Different from Adafruit_GFX design, Adruino_GFX also cater background. 961 // Since it may introduce many ugly output, it should limited using on mono font only. 962 if (xo < 0) // padding X offset to >= 0 963 { 964 x += xo; 965 xo = 0; 966 } 967 968 startWrite(); 969 if (bg != color) // have background color 970 { 971 writeAddrWindow(x, y - (baseline * textsize_y), block_w, block_h); 972 973 uint16_t line_buf[block_w]; 974 int8_t i; 975 bool draw_dot; 976 for (yy = 0; yy < yAdvance; yy++) 977 { 978 if ((yy < (baseline + yo)) || (yy > (baseline + yo + h - 1))) 979 { 980 writeRepeat(bg, block_w * textsize_y); 981 } 982 else 983 { 984 i = 0; 985 for (xx = 0; xx < xAdvance; xx++) 986 { 987 if ((xx < xo) || (xx > (xo + w - 1))) 988 { 989 draw_dot = false; 990 } 991 else 992 { 993 if (!(bit++ & 7)) 994 { 995 bits = pgm_read_byte(&bitmap[bo++]); 996 } 997 draw_dot = bits & 0x80; 998 bits <<= 1; 999 } 1000 1001 if (textsize_x == 1) 1002 { 1003 line_buf[i++] = draw_dot ? color : bg; 1004 } 1005 else 1006 { 1007 if (draw_dot) 1008 { 1009 for (int8_t k = 0; k < textsize_x; k++) 1010 { 1011 line_buf[i++] = (k < (textsize_x - text_pixel_margin)) ? color : bg; 1012 } 1013 } 1014 else 1015 { 1016 for (int8_t k = 0; k < textsize_x; k++) 1017 { 1018 line_buf[i++] = bg; 1019 } 1020 } 1021 } 1022 } 1023 if (textsize_y == 1) 1024 { 1025 writePixels(line_buf, block_w); 1026 } 1027 else 1028 { 1029 for (int8_t l = 0; l < textsize_y; l++) 1030 { 1031 if (l < (textsize_y - text_pixel_margin)) 1032 { 1033 writePixels(line_buf, block_w); 1034 } 1035 else 1036 { 1037 writeRepeat(bg, block_w); 1038 } 1039 } 1040 } 1041 } 1042 } 1043 } 1044 else // (bg == color), no background color 1045 { 1046 for (yy = 0; yy < h; yy++) 1047 { 1048 for (xx = 0; xx < w; xx++) 1049 { 1050 if (!(bit++ & 7)) 1051 { 1052 bits = pgm_read_byte(&bitmap[bo++]); 1053 } 1054 if (bits & 0x80) 1055 { 1056 if (textsize_x == 1 && textsize_y == 1) 1057 { 1058 writePixelPreclipped(x + xo + xx, y + yo + yy, color); 1059 } 1060 else 1061 { 1062 writeFillRectPreclipped(x + (xo16 + xx) * textsize_x, y + (yo16 + yy) * textsize_y, 1063 textsize_x - text_pixel_margin, textsize_y - text_pixel_margin, color); 1064 } 1065 } 1066 bits <<= 1; 1067 } 1068 } 1069 } 1070 endWrite(); 1071 } 1072 } 1073 else // not gfxFont 1074 #endif // !defined(ATTINY_CORE) 1075 #if defined(U8G2_FONT_SUPPORT) 1076 if (u8g2Font) 1077 { 1078 Arduino_GFX::drawChar(x, y, c, color, bg); 1079 } 1080 else // not u8g2Font 1081 #endif // defined(U8G2_FONT_SUPPORT) 1082 { 1083 block_w = 6 * textsize_x; 1084 block_h = 8 * textsize_y; 1085 if ( 1086 (x < 0) || // Clip left 1087 (y < 0) || // Clip top 1088 ((x + block_w - 1) > _max_x) || // Clip right 1089 ((y + block_h - 1) > _max_y) // Clip bottom 1090 ) 1091 { 1092 // partial draw char by parent class 1093 Arduino_GFX::drawChar(x, y, c, color, bg); 1094 } 1095 else 1096 { 1097 uint8_t col[5]; 1098 for (int8_t i = 0; i < 5; i++) 1099 { 1100 col[i] = pgm_read_byte(&font[c * 5 + i]); 1101 } 1102 1103 startWrite(); 1104 if (bg != color) // have background color 1105 { 1106 writeAddrWindow(x, y, block_w, block_h); 1107 1108 uint16_t line_buf[block_w]; 1109 if (textsize_x == 1) 1110 { 1111 line_buf[5] = bg; // last column always bg 1112 } 1113 else 1114 { 1115 for (int8_t k = 0; k < textsize_x; k++) 1116 { 1117 line_buf[5 * textsize_x + k] = bg; 1118 } 1119 } 1120 uint8_t bit = 1; 1121 bool draw_dot; 1122 1123 while (bit) 1124 { 1125 for (int8_t i = 0; i < 5; i++) 1126 { 1127 draw_dot = col[i] & bit; 1128 if (textsize_x == 1) 1129 { 1130 line_buf[i] = (draw_dot) ? color : bg; 1131 } 1132 else 1133 { 1134 if (draw_dot) 1135 { 1136 for (int8_t k = 0; k < textsize_x; k++) 1137 { 1138 line_buf[i * textsize_x + k] = (k < (textsize_x - text_pixel_margin)) ? color : bg; 1139 } 1140 } 1141 else 1142 { 1143 for (int8_t k = 0; k < textsize_x; k++) 1144 { 1145 line_buf[i * textsize_x + k] = bg; 1146 } 1147 } 1148 } 1149 } 1150 if (textsize_y == 1) 1151 { 1152 writePixels(line_buf, block_w); 1153 } 1154 else 1155 { 1156 for (int8_t l = 0; l < textsize_y; l++) 1157 { 1158 if (l < (textsize_y - text_pixel_margin)) 1159 { 1160 writePixels(line_buf, block_w); 1161 } 1162 else 1163 { 1164 writeRepeat(bg, block_w); 1165 } 1166 } 1167 } 1168 bit <<= 1; 1169 } 1170 } 1171 else // (bg == color), no background color 1172 { 1173 for (int8_t i = 0; i < 5; i++) 1174 { // Char bitmap = 5 columns 1175 uint8_t line = col[i]; 1176 for (int8_t j = 0; j < 8; j++, line >>= 1) 1177 { 1178 if (line & 1) 1179 { 1180 if (textsize_x == 1 && textsize_y == 1) 1181 { 1182 writePixelPreclipped(x + i, y + j, color); 1183 } 1184 else 1185 { 1186 writeFillRectPreclipped(x + i * textsize_x, y + j * textsize_y, textsize_x - text_pixel_margin, textsize_y - text_pixel_margin, color); 1187 } 1188 } 1189 } 1190 } 1191 } 1192 endWrite(); 1193 } 1194 } 1195 } 1196 1197 #endif // !defined(LITTLE_FOOT_PRINT)