Fork of the latest Adafruit GFX Library as of 2017-12-13 to make it compatible with Mbed
Adafruit_GFX.cpp@0:cc4253367fc7, 2017-12-13 (annotated)
- Committer:
- mjromeijn
- Date:
- Wed Dec 13 20:24:59 2017 +0000
- Revision:
- 0:cc4253367fc7
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mjromeijn | 0:cc4253367fc7 | 1 | /* |
mjromeijn | 0:cc4253367fc7 | 2 | This is the core graphics library for all our displays, providing a common |
mjromeijn | 0:cc4253367fc7 | 3 | set of graphics primitives (points, lines, circles, etc.). It needs to be |
mjromeijn | 0:cc4253367fc7 | 4 | paired with a hardware-specific library for each display device we carry |
mjromeijn | 0:cc4253367fc7 | 5 | (to handle the lower-level functions). |
mjromeijn | 0:cc4253367fc7 | 6 | |
mjromeijn | 0:cc4253367fc7 | 7 | Adafruit invests time and resources providing this open source code, please |
mjromeijn | 0:cc4253367fc7 | 8 | support Adafruit & open-source hardware by purchasing products from Adafruit! |
mjromeijn | 0:cc4253367fc7 | 9 | |
mjromeijn | 0:cc4253367fc7 | 10 | Copyright (c) 2013 Adafruit Industries. All rights reserved. |
mjromeijn | 0:cc4253367fc7 | 11 | |
mjromeijn | 0:cc4253367fc7 | 12 | Redistribution and use in source and binary forms, with or without |
mjromeijn | 0:cc4253367fc7 | 13 | modification, are permitted provided that the following conditions are met: |
mjromeijn | 0:cc4253367fc7 | 14 | |
mjromeijn | 0:cc4253367fc7 | 15 | - Redistributions of source code must retain the above copyright notice, |
mjromeijn | 0:cc4253367fc7 | 16 | this list of conditions and the following disclaimer. |
mjromeijn | 0:cc4253367fc7 | 17 | - Redistributions in binary form must reproduce the above copyright notice, |
mjromeijn | 0:cc4253367fc7 | 18 | this list of conditions and the following disclaimer in the documentation |
mjromeijn | 0:cc4253367fc7 | 19 | and/or other materials provided with the distribution. |
mjromeijn | 0:cc4253367fc7 | 20 | |
mjromeijn | 0:cc4253367fc7 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
mjromeijn | 0:cc4253367fc7 | 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
mjromeijn | 0:cc4253367fc7 | 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
mjromeijn | 0:cc4253367fc7 | 24 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
mjromeijn | 0:cc4253367fc7 | 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
mjromeijn | 0:cc4253367fc7 | 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
mjromeijn | 0:cc4253367fc7 | 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
mjromeijn | 0:cc4253367fc7 | 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
mjromeijn | 0:cc4253367fc7 | 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
mjromeijn | 0:cc4253367fc7 | 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
mjromeijn | 0:cc4253367fc7 | 31 | POSSIBILITY OF SUCH DAMAGE. |
mjromeijn | 0:cc4253367fc7 | 32 | */ |
mjromeijn | 0:cc4253367fc7 | 33 | |
mjromeijn | 0:cc4253367fc7 | 34 | #include "Adafruit_GFX.h" |
mjromeijn | 0:cc4253367fc7 | 35 | #include "glcdfont.c" |
mjromeijn | 0:cc4253367fc7 | 36 | #ifdef __AVR__ |
mjromeijn | 0:cc4253367fc7 | 37 | #include <avr/pgmspace.h> |
mjromeijn | 0:cc4253367fc7 | 38 | #elif defined(ESP8266) || defined(ESP32) |
mjromeijn | 0:cc4253367fc7 | 39 | #include <pgmspace.h> |
mjromeijn | 0:cc4253367fc7 | 40 | #endif |
mjromeijn | 0:cc4253367fc7 | 41 | |
mjromeijn | 0:cc4253367fc7 | 42 | // Many (but maybe not all) non-AVR board installs define macros |
mjromeijn | 0:cc4253367fc7 | 43 | // for compatibility with existing PROGMEM-reading AVR code. |
mjromeijn | 0:cc4253367fc7 | 44 | // Do our own checks and defines here for good measure... |
mjromeijn | 0:cc4253367fc7 | 45 | |
mjromeijn | 0:cc4253367fc7 | 46 | #ifndef pgm_read_byte |
mjromeijn | 0:cc4253367fc7 | 47 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) |
mjromeijn | 0:cc4253367fc7 | 48 | #endif |
mjromeijn | 0:cc4253367fc7 | 49 | #ifndef pgm_read_word |
mjromeijn | 0:cc4253367fc7 | 50 | #define pgm_read_word(addr) (*(const unsigned short *)(addr)) |
mjromeijn | 0:cc4253367fc7 | 51 | #endif |
mjromeijn | 0:cc4253367fc7 | 52 | #ifndef pgm_read_dword |
mjromeijn | 0:cc4253367fc7 | 53 | #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) |
mjromeijn | 0:cc4253367fc7 | 54 | #endif |
mjromeijn | 0:cc4253367fc7 | 55 | |
mjromeijn | 0:cc4253367fc7 | 56 | // Pointers are a peculiar case...typically 16-bit on AVR boards, |
mjromeijn | 0:cc4253367fc7 | 57 | // 32 bits elsewhere. Try to accommodate both... |
mjromeijn | 0:cc4253367fc7 | 58 | |
mjromeijn | 0:cc4253367fc7 | 59 | #if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF) |
mjromeijn | 0:cc4253367fc7 | 60 | #define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr)) |
mjromeijn | 0:cc4253367fc7 | 61 | #else |
mjromeijn | 0:cc4253367fc7 | 62 | #define pgm_read_pointer(addr) ((void *)pgm_read_word(addr)) |
mjromeijn | 0:cc4253367fc7 | 63 | #endif |
mjromeijn | 0:cc4253367fc7 | 64 | |
mjromeijn | 0:cc4253367fc7 | 65 | #ifndef min |
mjromeijn | 0:cc4253367fc7 | 66 | #define min(a,b) (((a) < (b)) ? (a) : (b)) |
mjromeijn | 0:cc4253367fc7 | 67 | #endif |
mjromeijn | 0:cc4253367fc7 | 68 | |
mjromeijn | 0:cc4253367fc7 | 69 | #ifndef _swap_int16_t |
mjromeijn | 0:cc4253367fc7 | 70 | #define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } |
mjromeijn | 0:cc4253367fc7 | 71 | #endif |
mjromeijn | 0:cc4253367fc7 | 72 | |
mjromeijn | 0:cc4253367fc7 | 73 | Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h): |
mjromeijn | 0:cc4253367fc7 | 74 | WIDTH(w), HEIGHT(h) |
mjromeijn | 0:cc4253367fc7 | 75 | { |
mjromeijn | 0:cc4253367fc7 | 76 | _width = WIDTH; |
mjromeijn | 0:cc4253367fc7 | 77 | _height = HEIGHT; |
mjromeijn | 0:cc4253367fc7 | 78 | rotation = 0; |
mjromeijn | 0:cc4253367fc7 | 79 | cursor_y = cursor_x = 0; |
mjromeijn | 0:cc4253367fc7 | 80 | textsize = 1; |
mjromeijn | 0:cc4253367fc7 | 81 | textcolor = textbgcolor = 0xFFFF; |
mjromeijn | 0:cc4253367fc7 | 82 | wrap = true; |
mjromeijn | 0:cc4253367fc7 | 83 | _cp437 = false; |
mjromeijn | 0:cc4253367fc7 | 84 | gfxFont = NULL; |
mjromeijn | 0:cc4253367fc7 | 85 | } |
mjromeijn | 0:cc4253367fc7 | 86 | |
mjromeijn | 0:cc4253367fc7 | 87 | // Bresenham's algorithm - thx wikpedia |
mjromeijn | 0:cc4253367fc7 | 88 | void Adafruit_GFX::writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, |
mjromeijn | 0:cc4253367fc7 | 89 | uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 90 | int16_t steep = abs(y1 - y0) > abs(x1 - x0); |
mjromeijn | 0:cc4253367fc7 | 91 | if (steep) { |
mjromeijn | 0:cc4253367fc7 | 92 | _swap_int16_t(x0, y0); |
mjromeijn | 0:cc4253367fc7 | 93 | _swap_int16_t(x1, y1); |
mjromeijn | 0:cc4253367fc7 | 94 | } |
mjromeijn | 0:cc4253367fc7 | 95 | |
mjromeijn | 0:cc4253367fc7 | 96 | if (x0 > x1) { |
mjromeijn | 0:cc4253367fc7 | 97 | _swap_int16_t(x0, x1); |
mjromeijn | 0:cc4253367fc7 | 98 | _swap_int16_t(y0, y1); |
mjromeijn | 0:cc4253367fc7 | 99 | } |
mjromeijn | 0:cc4253367fc7 | 100 | |
mjromeijn | 0:cc4253367fc7 | 101 | int16_t dx, dy; |
mjromeijn | 0:cc4253367fc7 | 102 | dx = x1 - x0; |
mjromeijn | 0:cc4253367fc7 | 103 | dy = abs(y1 - y0); |
mjromeijn | 0:cc4253367fc7 | 104 | |
mjromeijn | 0:cc4253367fc7 | 105 | int16_t err = dx / 2; |
mjromeijn | 0:cc4253367fc7 | 106 | int16_t ystep; |
mjromeijn | 0:cc4253367fc7 | 107 | |
mjromeijn | 0:cc4253367fc7 | 108 | if (y0 < y1) { |
mjromeijn | 0:cc4253367fc7 | 109 | ystep = 1; |
mjromeijn | 0:cc4253367fc7 | 110 | } else { |
mjromeijn | 0:cc4253367fc7 | 111 | ystep = -1; |
mjromeijn | 0:cc4253367fc7 | 112 | } |
mjromeijn | 0:cc4253367fc7 | 113 | |
mjromeijn | 0:cc4253367fc7 | 114 | for (; x0<=x1; x0++) { |
mjromeijn | 0:cc4253367fc7 | 115 | if (steep) { |
mjromeijn | 0:cc4253367fc7 | 116 | writePixel(y0, x0, color); |
mjromeijn | 0:cc4253367fc7 | 117 | } else { |
mjromeijn | 0:cc4253367fc7 | 118 | writePixel(x0, y0, color); |
mjromeijn | 0:cc4253367fc7 | 119 | } |
mjromeijn | 0:cc4253367fc7 | 120 | err -= dy; |
mjromeijn | 0:cc4253367fc7 | 121 | if (err < 0) { |
mjromeijn | 0:cc4253367fc7 | 122 | y0 += ystep; |
mjromeijn | 0:cc4253367fc7 | 123 | err += dx; |
mjromeijn | 0:cc4253367fc7 | 124 | } |
mjromeijn | 0:cc4253367fc7 | 125 | } |
mjromeijn | 0:cc4253367fc7 | 126 | } |
mjromeijn | 0:cc4253367fc7 | 127 | |
mjromeijn | 0:cc4253367fc7 | 128 | void Adafruit_GFX::startWrite(){ |
mjromeijn | 0:cc4253367fc7 | 129 | // Overwrite in subclasses if desired! |
mjromeijn | 0:cc4253367fc7 | 130 | } |
mjromeijn | 0:cc4253367fc7 | 131 | |
mjromeijn | 0:cc4253367fc7 | 132 | void Adafruit_GFX::writePixel(int16_t x, int16_t y, uint16_t color){ |
mjromeijn | 0:cc4253367fc7 | 133 | // Overwrite in subclasses if startWrite is defined! |
mjromeijn | 0:cc4253367fc7 | 134 | drawPixel(x, y, color); |
mjromeijn | 0:cc4253367fc7 | 135 | } |
mjromeijn | 0:cc4253367fc7 | 136 | |
mjromeijn | 0:cc4253367fc7 | 137 | // (x,y) is topmost point; if unsure, calling function |
mjromeijn | 0:cc4253367fc7 | 138 | // should sort endpoints or call writeLine() instead |
mjromeijn | 0:cc4253367fc7 | 139 | void Adafruit_GFX::writeFastVLine(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 140 | int16_t h, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 141 | // Overwrite in subclasses if startWrite is defined! |
mjromeijn | 0:cc4253367fc7 | 142 | // Can be just writeLine(x, y, x, y+h-1, color); |
mjromeijn | 0:cc4253367fc7 | 143 | // or writeFillRect(x, y, 1, h, color); |
mjromeijn | 0:cc4253367fc7 | 144 | drawFastVLine(x, y, h, color); |
mjromeijn | 0:cc4253367fc7 | 145 | } |
mjromeijn | 0:cc4253367fc7 | 146 | |
mjromeijn | 0:cc4253367fc7 | 147 | // (x,y) is leftmost point; if unsure, calling function |
mjromeijn | 0:cc4253367fc7 | 148 | // should sort endpoints or call writeLine() instead |
mjromeijn | 0:cc4253367fc7 | 149 | void Adafruit_GFX::writeFastHLine(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 150 | int16_t w, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 151 | // Overwrite in subclasses if startWrite is defined! |
mjromeijn | 0:cc4253367fc7 | 152 | // Example: writeLine(x, y, x+w-1, y, color); |
mjromeijn | 0:cc4253367fc7 | 153 | // or writeFillRect(x, y, w, 1, color); |
mjromeijn | 0:cc4253367fc7 | 154 | drawFastHLine(x, y, w, color); |
mjromeijn | 0:cc4253367fc7 | 155 | } |
mjromeijn | 0:cc4253367fc7 | 156 | |
mjromeijn | 0:cc4253367fc7 | 157 | void Adafruit_GFX::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, |
mjromeijn | 0:cc4253367fc7 | 158 | uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 159 | // Overwrite in subclasses if desired! |
mjromeijn | 0:cc4253367fc7 | 160 | fillRect(x,y,w,h,color); |
mjromeijn | 0:cc4253367fc7 | 161 | } |
mjromeijn | 0:cc4253367fc7 | 162 | |
mjromeijn | 0:cc4253367fc7 | 163 | void Adafruit_GFX::endWrite(){ |
mjromeijn | 0:cc4253367fc7 | 164 | // Overwrite in subclasses if startWrite is defined! |
mjromeijn | 0:cc4253367fc7 | 165 | } |
mjromeijn | 0:cc4253367fc7 | 166 | |
mjromeijn | 0:cc4253367fc7 | 167 | // (x,y) is topmost point; if unsure, calling function |
mjromeijn | 0:cc4253367fc7 | 168 | // should sort endpoints or call drawLine() instead |
mjromeijn | 0:cc4253367fc7 | 169 | void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 170 | int16_t h, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 171 | // Update in subclasses if desired! |
mjromeijn | 0:cc4253367fc7 | 172 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 173 | writeLine(x, y, x, y+h-1, color); |
mjromeijn | 0:cc4253367fc7 | 174 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 175 | } |
mjromeijn | 0:cc4253367fc7 | 176 | |
mjromeijn | 0:cc4253367fc7 | 177 | // (x,y) is leftmost point; if unsure, calling function |
mjromeijn | 0:cc4253367fc7 | 178 | // should sort endpoints or call drawLine() instead |
mjromeijn | 0:cc4253367fc7 | 179 | void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 180 | int16_t w, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 181 | // Update in subclasses if desired! |
mjromeijn | 0:cc4253367fc7 | 182 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 183 | writeLine(x, y, x+w-1, y, color); |
mjromeijn | 0:cc4253367fc7 | 184 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 185 | } |
mjromeijn | 0:cc4253367fc7 | 186 | |
mjromeijn | 0:cc4253367fc7 | 187 | void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, |
mjromeijn | 0:cc4253367fc7 | 188 | uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 189 | // Update in subclasses if desired! |
mjromeijn | 0:cc4253367fc7 | 190 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 191 | for (int16_t i=x; i<x+w; i++) { |
mjromeijn | 0:cc4253367fc7 | 192 | writeFastVLine(i, y, h, color); |
mjromeijn | 0:cc4253367fc7 | 193 | } |
mjromeijn | 0:cc4253367fc7 | 194 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 195 | } |
mjromeijn | 0:cc4253367fc7 | 196 | |
mjromeijn | 0:cc4253367fc7 | 197 | void Adafruit_GFX::fillScreen(uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 198 | // Update in subclasses if desired! |
mjromeijn | 0:cc4253367fc7 | 199 | fillRect(0, 0, _width, _height, color); |
mjromeijn | 0:cc4253367fc7 | 200 | } |
mjromeijn | 0:cc4253367fc7 | 201 | |
mjromeijn | 0:cc4253367fc7 | 202 | void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, |
mjromeijn | 0:cc4253367fc7 | 203 | uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 204 | // Update in subclasses if desired! |
mjromeijn | 0:cc4253367fc7 | 205 | if(x0 == x1){ |
mjromeijn | 0:cc4253367fc7 | 206 | if(y0 > y1) _swap_int16_t(y0, y1); |
mjromeijn | 0:cc4253367fc7 | 207 | drawFastVLine(x0, y0, y1 - y0 + 1, color); |
mjromeijn | 0:cc4253367fc7 | 208 | } else if(y0 == y1){ |
mjromeijn | 0:cc4253367fc7 | 209 | if(x0 > x1) _swap_int16_t(x0, x1); |
mjromeijn | 0:cc4253367fc7 | 210 | drawFastHLine(x0, y0, x1 - x0 + 1, color); |
mjromeijn | 0:cc4253367fc7 | 211 | } else { |
mjromeijn | 0:cc4253367fc7 | 212 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 213 | writeLine(x0, y0, x1, y1, color); |
mjromeijn | 0:cc4253367fc7 | 214 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 215 | } |
mjromeijn | 0:cc4253367fc7 | 216 | } |
mjromeijn | 0:cc4253367fc7 | 217 | |
mjromeijn | 0:cc4253367fc7 | 218 | // Draw a circle outline |
mjromeijn | 0:cc4253367fc7 | 219 | void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, |
mjromeijn | 0:cc4253367fc7 | 220 | uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 221 | int16_t f = 1 - r; |
mjromeijn | 0:cc4253367fc7 | 222 | int16_t ddF_x = 1; |
mjromeijn | 0:cc4253367fc7 | 223 | int16_t ddF_y = -2 * r; |
mjromeijn | 0:cc4253367fc7 | 224 | int16_t x = 0; |
mjromeijn | 0:cc4253367fc7 | 225 | int16_t y = r; |
mjromeijn | 0:cc4253367fc7 | 226 | |
mjromeijn | 0:cc4253367fc7 | 227 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 228 | writePixel(x0 , y0+r, color); |
mjromeijn | 0:cc4253367fc7 | 229 | writePixel(x0 , y0-r, color); |
mjromeijn | 0:cc4253367fc7 | 230 | writePixel(x0+r, y0 , color); |
mjromeijn | 0:cc4253367fc7 | 231 | writePixel(x0-r, y0 , color); |
mjromeijn | 0:cc4253367fc7 | 232 | |
mjromeijn | 0:cc4253367fc7 | 233 | while (x<y) { |
mjromeijn | 0:cc4253367fc7 | 234 | if (f >= 0) { |
mjromeijn | 0:cc4253367fc7 | 235 | y--; |
mjromeijn | 0:cc4253367fc7 | 236 | ddF_y += 2; |
mjromeijn | 0:cc4253367fc7 | 237 | f += ddF_y; |
mjromeijn | 0:cc4253367fc7 | 238 | } |
mjromeijn | 0:cc4253367fc7 | 239 | x++; |
mjromeijn | 0:cc4253367fc7 | 240 | ddF_x += 2; |
mjromeijn | 0:cc4253367fc7 | 241 | f += ddF_x; |
mjromeijn | 0:cc4253367fc7 | 242 | |
mjromeijn | 0:cc4253367fc7 | 243 | writePixel(x0 + x, y0 + y, color); |
mjromeijn | 0:cc4253367fc7 | 244 | writePixel(x0 - x, y0 + y, color); |
mjromeijn | 0:cc4253367fc7 | 245 | writePixel(x0 + x, y0 - y, color); |
mjromeijn | 0:cc4253367fc7 | 246 | writePixel(x0 - x, y0 - y, color); |
mjromeijn | 0:cc4253367fc7 | 247 | writePixel(x0 + y, y0 + x, color); |
mjromeijn | 0:cc4253367fc7 | 248 | writePixel(x0 - y, y0 + x, color); |
mjromeijn | 0:cc4253367fc7 | 249 | writePixel(x0 + y, y0 - x, color); |
mjromeijn | 0:cc4253367fc7 | 250 | writePixel(x0 - y, y0 - x, color); |
mjromeijn | 0:cc4253367fc7 | 251 | } |
mjromeijn | 0:cc4253367fc7 | 252 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 253 | } |
mjromeijn | 0:cc4253367fc7 | 254 | |
mjromeijn | 0:cc4253367fc7 | 255 | void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0, |
mjromeijn | 0:cc4253367fc7 | 256 | int16_t r, uint8_t cornername, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 257 | int16_t f = 1 - r; |
mjromeijn | 0:cc4253367fc7 | 258 | int16_t ddF_x = 1; |
mjromeijn | 0:cc4253367fc7 | 259 | int16_t ddF_y = -2 * r; |
mjromeijn | 0:cc4253367fc7 | 260 | int16_t x = 0; |
mjromeijn | 0:cc4253367fc7 | 261 | int16_t y = r; |
mjromeijn | 0:cc4253367fc7 | 262 | |
mjromeijn | 0:cc4253367fc7 | 263 | while (x<y) { |
mjromeijn | 0:cc4253367fc7 | 264 | if (f >= 0) { |
mjromeijn | 0:cc4253367fc7 | 265 | y--; |
mjromeijn | 0:cc4253367fc7 | 266 | ddF_y += 2; |
mjromeijn | 0:cc4253367fc7 | 267 | f += ddF_y; |
mjromeijn | 0:cc4253367fc7 | 268 | } |
mjromeijn | 0:cc4253367fc7 | 269 | x++; |
mjromeijn | 0:cc4253367fc7 | 270 | ddF_x += 2; |
mjromeijn | 0:cc4253367fc7 | 271 | f += ddF_x; |
mjromeijn | 0:cc4253367fc7 | 272 | if (cornername & 0x4) { |
mjromeijn | 0:cc4253367fc7 | 273 | writePixel(x0 + x, y0 + y, color); |
mjromeijn | 0:cc4253367fc7 | 274 | writePixel(x0 + y, y0 + x, color); |
mjromeijn | 0:cc4253367fc7 | 275 | } |
mjromeijn | 0:cc4253367fc7 | 276 | if (cornername & 0x2) { |
mjromeijn | 0:cc4253367fc7 | 277 | writePixel(x0 + x, y0 - y, color); |
mjromeijn | 0:cc4253367fc7 | 278 | writePixel(x0 + y, y0 - x, color); |
mjromeijn | 0:cc4253367fc7 | 279 | } |
mjromeijn | 0:cc4253367fc7 | 280 | if (cornername & 0x8) { |
mjromeijn | 0:cc4253367fc7 | 281 | writePixel(x0 - y, y0 + x, color); |
mjromeijn | 0:cc4253367fc7 | 282 | writePixel(x0 - x, y0 + y, color); |
mjromeijn | 0:cc4253367fc7 | 283 | } |
mjromeijn | 0:cc4253367fc7 | 284 | if (cornername & 0x1) { |
mjromeijn | 0:cc4253367fc7 | 285 | writePixel(x0 - y, y0 - x, color); |
mjromeijn | 0:cc4253367fc7 | 286 | writePixel(x0 - x, y0 - y, color); |
mjromeijn | 0:cc4253367fc7 | 287 | } |
mjromeijn | 0:cc4253367fc7 | 288 | } |
mjromeijn | 0:cc4253367fc7 | 289 | } |
mjromeijn | 0:cc4253367fc7 | 290 | |
mjromeijn | 0:cc4253367fc7 | 291 | void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, |
mjromeijn | 0:cc4253367fc7 | 292 | uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 293 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 294 | writeFastVLine(x0, y0-r, 2*r+1, color); |
mjromeijn | 0:cc4253367fc7 | 295 | fillCircleHelper(x0, y0, r, 3, 0, color); |
mjromeijn | 0:cc4253367fc7 | 296 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 297 | } |
mjromeijn | 0:cc4253367fc7 | 298 | |
mjromeijn | 0:cc4253367fc7 | 299 | // Used to do circles and roundrects |
mjromeijn | 0:cc4253367fc7 | 300 | void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, |
mjromeijn | 0:cc4253367fc7 | 301 | uint8_t cornername, int16_t delta, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 302 | |
mjromeijn | 0:cc4253367fc7 | 303 | int16_t f = 1 - r; |
mjromeijn | 0:cc4253367fc7 | 304 | int16_t ddF_x = 1; |
mjromeijn | 0:cc4253367fc7 | 305 | int16_t ddF_y = -2 * r; |
mjromeijn | 0:cc4253367fc7 | 306 | int16_t x = 0; |
mjromeijn | 0:cc4253367fc7 | 307 | int16_t y = r; |
mjromeijn | 0:cc4253367fc7 | 308 | |
mjromeijn | 0:cc4253367fc7 | 309 | while (x<y) { |
mjromeijn | 0:cc4253367fc7 | 310 | if (f >= 0) { |
mjromeijn | 0:cc4253367fc7 | 311 | y--; |
mjromeijn | 0:cc4253367fc7 | 312 | ddF_y += 2; |
mjromeijn | 0:cc4253367fc7 | 313 | f += ddF_y; |
mjromeijn | 0:cc4253367fc7 | 314 | } |
mjromeijn | 0:cc4253367fc7 | 315 | x++; |
mjromeijn | 0:cc4253367fc7 | 316 | ddF_x += 2; |
mjromeijn | 0:cc4253367fc7 | 317 | f += ddF_x; |
mjromeijn | 0:cc4253367fc7 | 318 | |
mjromeijn | 0:cc4253367fc7 | 319 | if (cornername & 0x1) { |
mjromeijn | 0:cc4253367fc7 | 320 | writeFastVLine(x0+x, y0-y, 2*y+1+delta, color); |
mjromeijn | 0:cc4253367fc7 | 321 | writeFastVLine(x0+y, y0-x, 2*x+1+delta, color); |
mjromeijn | 0:cc4253367fc7 | 322 | } |
mjromeijn | 0:cc4253367fc7 | 323 | if (cornername & 0x2) { |
mjromeijn | 0:cc4253367fc7 | 324 | writeFastVLine(x0-x, y0-y, 2*y+1+delta, color); |
mjromeijn | 0:cc4253367fc7 | 325 | writeFastVLine(x0-y, y0-x, 2*x+1+delta, color); |
mjromeijn | 0:cc4253367fc7 | 326 | } |
mjromeijn | 0:cc4253367fc7 | 327 | } |
mjromeijn | 0:cc4253367fc7 | 328 | } |
mjromeijn | 0:cc4253367fc7 | 329 | |
mjromeijn | 0:cc4253367fc7 | 330 | // Draw a rectangle |
mjromeijn | 0:cc4253367fc7 | 331 | void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, |
mjromeijn | 0:cc4253367fc7 | 332 | uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 333 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 334 | writeFastHLine(x, y, w, color); |
mjromeijn | 0:cc4253367fc7 | 335 | writeFastHLine(x, y+h-1, w, color); |
mjromeijn | 0:cc4253367fc7 | 336 | writeFastVLine(x, y, h, color); |
mjromeijn | 0:cc4253367fc7 | 337 | writeFastVLine(x+w-1, y, h, color); |
mjromeijn | 0:cc4253367fc7 | 338 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 339 | } |
mjromeijn | 0:cc4253367fc7 | 340 | |
mjromeijn | 0:cc4253367fc7 | 341 | // Draw a rounded rectangle |
mjromeijn | 0:cc4253367fc7 | 342 | void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w, |
mjromeijn | 0:cc4253367fc7 | 343 | int16_t h, int16_t r, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 344 | // smarter version |
mjromeijn | 0:cc4253367fc7 | 345 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 346 | writeFastHLine(x+r , y , w-2*r, color); // Top |
mjromeijn | 0:cc4253367fc7 | 347 | writeFastHLine(x+r , y+h-1, w-2*r, color); // Bottom |
mjromeijn | 0:cc4253367fc7 | 348 | writeFastVLine(x , y+r , h-2*r, color); // Left |
mjromeijn | 0:cc4253367fc7 | 349 | writeFastVLine(x+w-1, y+r , h-2*r, color); // Right |
mjromeijn | 0:cc4253367fc7 | 350 | // draw four corners |
mjromeijn | 0:cc4253367fc7 | 351 | drawCircleHelper(x+r , y+r , r, 1, color); |
mjromeijn | 0:cc4253367fc7 | 352 | drawCircleHelper(x+w-r-1, y+r , r, 2, color); |
mjromeijn | 0:cc4253367fc7 | 353 | drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); |
mjromeijn | 0:cc4253367fc7 | 354 | drawCircleHelper(x+r , y+h-r-1, r, 8, color); |
mjromeijn | 0:cc4253367fc7 | 355 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 356 | } |
mjromeijn | 0:cc4253367fc7 | 357 | |
mjromeijn | 0:cc4253367fc7 | 358 | // Fill a rounded rectangle |
mjromeijn | 0:cc4253367fc7 | 359 | void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w, |
mjromeijn | 0:cc4253367fc7 | 360 | int16_t h, int16_t r, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 361 | // smarter version |
mjromeijn | 0:cc4253367fc7 | 362 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 363 | writeFillRect(x+r, y, w-2*r, h, color); |
mjromeijn | 0:cc4253367fc7 | 364 | |
mjromeijn | 0:cc4253367fc7 | 365 | // draw four corners |
mjromeijn | 0:cc4253367fc7 | 366 | fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color); |
mjromeijn | 0:cc4253367fc7 | 367 | fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color); |
mjromeijn | 0:cc4253367fc7 | 368 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 369 | } |
mjromeijn | 0:cc4253367fc7 | 370 | |
mjromeijn | 0:cc4253367fc7 | 371 | // Draw a triangle |
mjromeijn | 0:cc4253367fc7 | 372 | void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0, |
mjromeijn | 0:cc4253367fc7 | 373 | int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 374 | drawLine(x0, y0, x1, y1, color); |
mjromeijn | 0:cc4253367fc7 | 375 | drawLine(x1, y1, x2, y2, color); |
mjromeijn | 0:cc4253367fc7 | 376 | drawLine(x2, y2, x0, y0, color); |
mjromeijn | 0:cc4253367fc7 | 377 | } |
mjromeijn | 0:cc4253367fc7 | 378 | |
mjromeijn | 0:cc4253367fc7 | 379 | // Fill a triangle |
mjromeijn | 0:cc4253367fc7 | 380 | void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0, |
mjromeijn | 0:cc4253367fc7 | 381 | int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 382 | |
mjromeijn | 0:cc4253367fc7 | 383 | int16_t a, b, y, last; |
mjromeijn | 0:cc4253367fc7 | 384 | |
mjromeijn | 0:cc4253367fc7 | 385 | // Sort coordinates by Y order (y2 >= y1 >= y0) |
mjromeijn | 0:cc4253367fc7 | 386 | if (y0 > y1) { |
mjromeijn | 0:cc4253367fc7 | 387 | _swap_int16_t(y0, y1); _swap_int16_t(x0, x1); |
mjromeijn | 0:cc4253367fc7 | 388 | } |
mjromeijn | 0:cc4253367fc7 | 389 | if (y1 > y2) { |
mjromeijn | 0:cc4253367fc7 | 390 | _swap_int16_t(y2, y1); _swap_int16_t(x2, x1); |
mjromeijn | 0:cc4253367fc7 | 391 | } |
mjromeijn | 0:cc4253367fc7 | 392 | if (y0 > y1) { |
mjromeijn | 0:cc4253367fc7 | 393 | _swap_int16_t(y0, y1); _swap_int16_t(x0, x1); |
mjromeijn | 0:cc4253367fc7 | 394 | } |
mjromeijn | 0:cc4253367fc7 | 395 | |
mjromeijn | 0:cc4253367fc7 | 396 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 397 | if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing |
mjromeijn | 0:cc4253367fc7 | 398 | a = b = x0; |
mjromeijn | 0:cc4253367fc7 | 399 | if(x1 < a) a = x1; |
mjromeijn | 0:cc4253367fc7 | 400 | else if(x1 > b) b = x1; |
mjromeijn | 0:cc4253367fc7 | 401 | if(x2 < a) a = x2; |
mjromeijn | 0:cc4253367fc7 | 402 | else if(x2 > b) b = x2; |
mjromeijn | 0:cc4253367fc7 | 403 | writeFastHLine(a, y0, b-a+1, color); |
mjromeijn | 0:cc4253367fc7 | 404 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 405 | return; |
mjromeijn | 0:cc4253367fc7 | 406 | } |
mjromeijn | 0:cc4253367fc7 | 407 | |
mjromeijn | 0:cc4253367fc7 | 408 | int16_t |
mjromeijn | 0:cc4253367fc7 | 409 | dx01 = x1 - x0, |
mjromeijn | 0:cc4253367fc7 | 410 | dy01 = y1 - y0, |
mjromeijn | 0:cc4253367fc7 | 411 | dx02 = x2 - x0, |
mjromeijn | 0:cc4253367fc7 | 412 | dy02 = y2 - y0, |
mjromeijn | 0:cc4253367fc7 | 413 | dx12 = x2 - x1, |
mjromeijn | 0:cc4253367fc7 | 414 | dy12 = y2 - y1; |
mjromeijn | 0:cc4253367fc7 | 415 | int32_t |
mjromeijn | 0:cc4253367fc7 | 416 | sa = 0, |
mjromeijn | 0:cc4253367fc7 | 417 | sb = 0; |
mjromeijn | 0:cc4253367fc7 | 418 | |
mjromeijn | 0:cc4253367fc7 | 419 | // For upper part of triangle, find scanline crossings for segments |
mjromeijn | 0:cc4253367fc7 | 420 | // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 |
mjromeijn | 0:cc4253367fc7 | 421 | // is included here (and second loop will be skipped, avoiding a /0 |
mjromeijn | 0:cc4253367fc7 | 422 | // error there), otherwise scanline y1 is skipped here and handled |
mjromeijn | 0:cc4253367fc7 | 423 | // in the second loop...which also avoids a /0 error here if y0=y1 |
mjromeijn | 0:cc4253367fc7 | 424 | // (flat-topped triangle). |
mjromeijn | 0:cc4253367fc7 | 425 | if(y1 == y2) last = y1; // Include y1 scanline |
mjromeijn | 0:cc4253367fc7 | 426 | else last = y1-1; // Skip it |
mjromeijn | 0:cc4253367fc7 | 427 | |
mjromeijn | 0:cc4253367fc7 | 428 | for(y=y0; y<=last; y++) { |
mjromeijn | 0:cc4253367fc7 | 429 | a = x0 + sa / dy01; |
mjromeijn | 0:cc4253367fc7 | 430 | b = x0 + sb / dy02; |
mjromeijn | 0:cc4253367fc7 | 431 | sa += dx01; |
mjromeijn | 0:cc4253367fc7 | 432 | sb += dx02; |
mjromeijn | 0:cc4253367fc7 | 433 | /* longhand: |
mjromeijn | 0:cc4253367fc7 | 434 | a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); |
mjromeijn | 0:cc4253367fc7 | 435 | b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); |
mjromeijn | 0:cc4253367fc7 | 436 | */ |
mjromeijn | 0:cc4253367fc7 | 437 | if(a > b) _swap_int16_t(a,b); |
mjromeijn | 0:cc4253367fc7 | 438 | writeFastHLine(a, y, b-a+1, color); |
mjromeijn | 0:cc4253367fc7 | 439 | } |
mjromeijn | 0:cc4253367fc7 | 440 | |
mjromeijn | 0:cc4253367fc7 | 441 | // For lower part of triangle, find scanline crossings for segments |
mjromeijn | 0:cc4253367fc7 | 442 | // 0-2 and 1-2. This loop is skipped if y1=y2. |
mjromeijn | 0:cc4253367fc7 | 443 | sa = dx12 * (y - y1); |
mjromeijn | 0:cc4253367fc7 | 444 | sb = dx02 * (y - y0); |
mjromeijn | 0:cc4253367fc7 | 445 | for(; y<=y2; y++) { |
mjromeijn | 0:cc4253367fc7 | 446 | a = x1 + sa / dy12; |
mjromeijn | 0:cc4253367fc7 | 447 | b = x0 + sb / dy02; |
mjromeijn | 0:cc4253367fc7 | 448 | sa += dx12; |
mjromeijn | 0:cc4253367fc7 | 449 | sb += dx02; |
mjromeijn | 0:cc4253367fc7 | 450 | /* longhand: |
mjromeijn | 0:cc4253367fc7 | 451 | a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); |
mjromeijn | 0:cc4253367fc7 | 452 | b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); |
mjromeijn | 0:cc4253367fc7 | 453 | */ |
mjromeijn | 0:cc4253367fc7 | 454 | if(a > b) _swap_int16_t(a,b); |
mjromeijn | 0:cc4253367fc7 | 455 | writeFastHLine(a, y, b-a+1, color); |
mjromeijn | 0:cc4253367fc7 | 456 | } |
mjromeijn | 0:cc4253367fc7 | 457 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 458 | } |
mjromeijn | 0:cc4253367fc7 | 459 | |
mjromeijn | 0:cc4253367fc7 | 460 | // BITMAP / XBITMAP / GRAYSCALE / RGB BITMAP FUNCTIONS --------------------- |
mjromeijn | 0:cc4253367fc7 | 461 | |
mjromeijn | 0:cc4253367fc7 | 462 | // Draw a PROGMEM-resident 1-bit image at the specified (x,y) position, |
mjromeijn | 0:cc4253367fc7 | 463 | // using the specified foreground color (unset bits are transparent). |
mjromeijn | 0:cc4253367fc7 | 464 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 465 | const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 466 | |
mjromeijn | 0:cc4253367fc7 | 467 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
mjromeijn | 0:cc4253367fc7 | 468 | uint8_t byte = 0; |
mjromeijn | 0:cc4253367fc7 | 469 | |
mjromeijn | 0:cc4253367fc7 | 470 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 471 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 472 | for(int16_t i=0; i<w; i++) { |
mjromeijn | 0:cc4253367fc7 | 473 | if(i & 7) byte <<= 1; |
mjromeijn | 0:cc4253367fc7 | 474 | else byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]); |
mjromeijn | 0:cc4253367fc7 | 475 | if(byte & 0x80) writePixel(x+i, y, color); |
mjromeijn | 0:cc4253367fc7 | 476 | } |
mjromeijn | 0:cc4253367fc7 | 477 | } |
mjromeijn | 0:cc4253367fc7 | 478 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 479 | } |
mjromeijn | 0:cc4253367fc7 | 480 | |
mjromeijn | 0:cc4253367fc7 | 481 | // Draw a PROGMEM-resident 1-bit image at the specified (x,y) position, |
mjromeijn | 0:cc4253367fc7 | 482 | // using the specified foreground (for set bits) and background (unset |
mjromeijn | 0:cc4253367fc7 | 483 | // bits) colors. |
mjromeijn | 0:cc4253367fc7 | 484 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 485 | const uint8_t bitmap[], int16_t w, int16_t h, |
mjromeijn | 0:cc4253367fc7 | 486 | uint16_t color, uint16_t bg) { |
mjromeijn | 0:cc4253367fc7 | 487 | |
mjromeijn | 0:cc4253367fc7 | 488 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
mjromeijn | 0:cc4253367fc7 | 489 | uint8_t byte = 0; |
mjromeijn | 0:cc4253367fc7 | 490 | |
mjromeijn | 0:cc4253367fc7 | 491 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 492 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 493 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 494 | if(i & 7) byte <<= 1; |
mjromeijn | 0:cc4253367fc7 | 495 | else byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]); |
mjromeijn | 0:cc4253367fc7 | 496 | writePixel(x+i, y, (byte & 0x80) ? color : bg); |
mjromeijn | 0:cc4253367fc7 | 497 | } |
mjromeijn | 0:cc4253367fc7 | 498 | } |
mjromeijn | 0:cc4253367fc7 | 499 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 500 | } |
mjromeijn | 0:cc4253367fc7 | 501 | |
mjromeijn | 0:cc4253367fc7 | 502 | // Draw a RAM-resident 1-bit image at the specified (x,y) position, |
mjromeijn | 0:cc4253367fc7 | 503 | // using the specified foreground color (unset bits are transparent). |
mjromeijn | 0:cc4253367fc7 | 504 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 505 | uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 506 | |
mjromeijn | 0:cc4253367fc7 | 507 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
mjromeijn | 0:cc4253367fc7 | 508 | uint8_t byte = 0; |
mjromeijn | 0:cc4253367fc7 | 509 | |
mjromeijn | 0:cc4253367fc7 | 510 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 511 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 512 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 513 | if(i & 7) byte <<= 1; |
mjromeijn | 0:cc4253367fc7 | 514 | else byte = bitmap[j * byteWidth + i / 8]; |
mjromeijn | 0:cc4253367fc7 | 515 | if(byte & 0x80) writePixel(x+i, y, color); |
mjromeijn | 0:cc4253367fc7 | 516 | } |
mjromeijn | 0:cc4253367fc7 | 517 | } |
mjromeijn | 0:cc4253367fc7 | 518 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 519 | } |
mjromeijn | 0:cc4253367fc7 | 520 | |
mjromeijn | 0:cc4253367fc7 | 521 | // Draw a RAM-resident 1-bit image at the specified (x,y) position, |
mjromeijn | 0:cc4253367fc7 | 522 | // using the specified foreground (for set bits) and background (unset |
mjromeijn | 0:cc4253367fc7 | 523 | // bits) colors. |
mjromeijn | 0:cc4253367fc7 | 524 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 525 | uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) { |
mjromeijn | 0:cc4253367fc7 | 526 | |
mjromeijn | 0:cc4253367fc7 | 527 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
mjromeijn | 0:cc4253367fc7 | 528 | uint8_t byte = 0; |
mjromeijn | 0:cc4253367fc7 | 529 | |
mjromeijn | 0:cc4253367fc7 | 530 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 531 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 532 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 533 | if(i & 7) byte <<= 1; |
mjromeijn | 0:cc4253367fc7 | 534 | else byte = bitmap[j * byteWidth + i / 8]; |
mjromeijn | 0:cc4253367fc7 | 535 | writePixel(x+i, y, (byte & 0x80) ? color : bg); |
mjromeijn | 0:cc4253367fc7 | 536 | } |
mjromeijn | 0:cc4253367fc7 | 537 | } |
mjromeijn | 0:cc4253367fc7 | 538 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 539 | } |
mjromeijn | 0:cc4253367fc7 | 540 | |
mjromeijn | 0:cc4253367fc7 | 541 | // Draw PROGMEM-resident XBitMap Files (*.xbm), exported from GIMP, |
mjromeijn | 0:cc4253367fc7 | 542 | // Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor. |
mjromeijn | 0:cc4253367fc7 | 543 | // C Array can be directly used with this function. |
mjromeijn | 0:cc4253367fc7 | 544 | // There is no RAM-resident version of this function; if generating bitmaps |
mjromeijn | 0:cc4253367fc7 | 545 | // in RAM, use the format defined by drawBitmap() and call that instead. |
mjromeijn | 0:cc4253367fc7 | 546 | void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 547 | const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 548 | |
mjromeijn | 0:cc4253367fc7 | 549 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
mjromeijn | 0:cc4253367fc7 | 550 | uint8_t byte = 0; |
mjromeijn | 0:cc4253367fc7 | 551 | |
mjromeijn | 0:cc4253367fc7 | 552 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 553 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 554 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 555 | if(i & 7) byte >>= 1; |
mjromeijn | 0:cc4253367fc7 | 556 | else byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]); |
mjromeijn | 0:cc4253367fc7 | 557 | // Nearly identical to drawBitmap(), only the bit order |
mjromeijn | 0:cc4253367fc7 | 558 | // is reversed here (left-to-right = LSB to MSB): |
mjromeijn | 0:cc4253367fc7 | 559 | if(byte & 0x01) writePixel(x+i, y, color); |
mjromeijn | 0:cc4253367fc7 | 560 | } |
mjromeijn | 0:cc4253367fc7 | 561 | } |
mjromeijn | 0:cc4253367fc7 | 562 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 563 | } |
mjromeijn | 0:cc4253367fc7 | 564 | |
mjromeijn | 0:cc4253367fc7 | 565 | // Draw a PROGMEM-resident 8-bit image (grayscale) at the specified (x,y) |
mjromeijn | 0:cc4253367fc7 | 566 | // pos. Specifically for 8-bit display devices such as IS31FL3731; |
mjromeijn | 0:cc4253367fc7 | 567 | // no color reduction/expansion is performed. |
mjromeijn | 0:cc4253367fc7 | 568 | void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 569 | const uint8_t bitmap[], int16_t w, int16_t h) { |
mjromeijn | 0:cc4253367fc7 | 570 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 571 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 572 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 573 | writePixel(x+i, y, (uint8_t)pgm_read_byte(&bitmap[j * w + i])); |
mjromeijn | 0:cc4253367fc7 | 574 | } |
mjromeijn | 0:cc4253367fc7 | 575 | } |
mjromeijn | 0:cc4253367fc7 | 576 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 577 | } |
mjromeijn | 0:cc4253367fc7 | 578 | |
mjromeijn | 0:cc4253367fc7 | 579 | // Draw a RAM-resident 8-bit image (grayscale) at the specified (x,y) |
mjromeijn | 0:cc4253367fc7 | 580 | // pos. Specifically for 8-bit display devices such as IS31FL3731; |
mjromeijn | 0:cc4253367fc7 | 581 | // no color reduction/expansion is performed. |
mjromeijn | 0:cc4253367fc7 | 582 | void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 583 | uint8_t *bitmap, int16_t w, int16_t h) { |
mjromeijn | 0:cc4253367fc7 | 584 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 585 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 586 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 587 | writePixel(x+i, y, bitmap[j * w + i]); |
mjromeijn | 0:cc4253367fc7 | 588 | } |
mjromeijn | 0:cc4253367fc7 | 589 | } |
mjromeijn | 0:cc4253367fc7 | 590 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 591 | } |
mjromeijn | 0:cc4253367fc7 | 592 | |
mjromeijn | 0:cc4253367fc7 | 593 | // Draw a PROGMEM-resident 8-bit image (grayscale) with a 1-bit mask |
mjromeijn | 0:cc4253367fc7 | 594 | // (set bits = opaque, unset bits = clear) at the specified (x,y) position. |
mjromeijn | 0:cc4253367fc7 | 595 | // BOTH buffers (grayscale and mask) must be PROGMEM-resident. |
mjromeijn | 0:cc4253367fc7 | 596 | // Specifically for 8-bit display devices such as IS31FL3731; |
mjromeijn | 0:cc4253367fc7 | 597 | // no color reduction/expansion is performed. |
mjromeijn | 0:cc4253367fc7 | 598 | void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 599 | const uint8_t bitmap[], const uint8_t mask[], |
mjromeijn | 0:cc4253367fc7 | 600 | int16_t w, int16_t h) { |
mjromeijn | 0:cc4253367fc7 | 601 | int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte |
mjromeijn | 0:cc4253367fc7 | 602 | uint8_t byte = 0; |
mjromeijn | 0:cc4253367fc7 | 603 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 604 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 605 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 606 | if(i & 7) byte <<= 1; |
mjromeijn | 0:cc4253367fc7 | 607 | else byte = pgm_read_byte(&mask[j * bw + i / 8]); |
mjromeijn | 0:cc4253367fc7 | 608 | if(byte & 0x80) { |
mjromeijn | 0:cc4253367fc7 | 609 | writePixel(x+i, y, (uint8_t)pgm_read_byte(&bitmap[j * w + i])); |
mjromeijn | 0:cc4253367fc7 | 610 | } |
mjromeijn | 0:cc4253367fc7 | 611 | } |
mjromeijn | 0:cc4253367fc7 | 612 | } |
mjromeijn | 0:cc4253367fc7 | 613 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 614 | } |
mjromeijn | 0:cc4253367fc7 | 615 | |
mjromeijn | 0:cc4253367fc7 | 616 | // Draw a RAM-resident 8-bit image (grayscale) with a 1-bit mask |
mjromeijn | 0:cc4253367fc7 | 617 | // (set bits = opaque, unset bits = clear) at the specified (x,y) pos. |
mjromeijn | 0:cc4253367fc7 | 618 | // BOTH buffers (grayscale and mask) must be RAM-resident, no mix-and- |
mjromeijn | 0:cc4253367fc7 | 619 | // match. Specifically for 8-bit display devices such as IS31FL3731; |
mjromeijn | 0:cc4253367fc7 | 620 | // no color reduction/expansion is performed. |
mjromeijn | 0:cc4253367fc7 | 621 | void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 622 | uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h) { |
mjromeijn | 0:cc4253367fc7 | 623 | int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte |
mjromeijn | 0:cc4253367fc7 | 624 | uint8_t byte = 0; |
mjromeijn | 0:cc4253367fc7 | 625 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 626 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 627 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 628 | if(i & 7) byte <<= 1; |
mjromeijn | 0:cc4253367fc7 | 629 | else byte = mask[j * bw + i / 8]; |
mjromeijn | 0:cc4253367fc7 | 630 | if(byte & 0x80) { |
mjromeijn | 0:cc4253367fc7 | 631 | writePixel(x+i, y, bitmap[j * w + i]); |
mjromeijn | 0:cc4253367fc7 | 632 | } |
mjromeijn | 0:cc4253367fc7 | 633 | } |
mjromeijn | 0:cc4253367fc7 | 634 | } |
mjromeijn | 0:cc4253367fc7 | 635 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 636 | } |
mjromeijn | 0:cc4253367fc7 | 637 | |
mjromeijn | 0:cc4253367fc7 | 638 | // Draw a PROGMEM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) |
mjromeijn | 0:cc4253367fc7 | 639 | // position. For 16-bit display devices; no color reduction performed. |
mjromeijn | 0:cc4253367fc7 | 640 | void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 641 | const uint16_t bitmap[], int16_t w, int16_t h) { |
mjromeijn | 0:cc4253367fc7 | 642 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 643 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 644 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 645 | writePixel(x+i, y, pgm_read_word(&bitmap[j * w + i])); |
mjromeijn | 0:cc4253367fc7 | 646 | } |
mjromeijn | 0:cc4253367fc7 | 647 | } |
mjromeijn | 0:cc4253367fc7 | 648 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 649 | } |
mjromeijn | 0:cc4253367fc7 | 650 | |
mjromeijn | 0:cc4253367fc7 | 651 | // Draw a RAM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) |
mjromeijn | 0:cc4253367fc7 | 652 | // position. For 16-bit display devices; no color reduction performed. |
mjromeijn | 0:cc4253367fc7 | 653 | void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 654 | uint16_t *bitmap, int16_t w, int16_t h) { |
mjromeijn | 0:cc4253367fc7 | 655 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 656 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 657 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 658 | writePixel(x+i, y, bitmap[j * w + i]); |
mjromeijn | 0:cc4253367fc7 | 659 | } |
mjromeijn | 0:cc4253367fc7 | 660 | } |
mjromeijn | 0:cc4253367fc7 | 661 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 662 | } |
mjromeijn | 0:cc4253367fc7 | 663 | |
mjromeijn | 0:cc4253367fc7 | 664 | // Draw a PROGMEM-resident 16-bit image (RGB 5/6/5) with a 1-bit mask |
mjromeijn | 0:cc4253367fc7 | 665 | // (set bits = opaque, unset bits = clear) at the specified (x,y) position. |
mjromeijn | 0:cc4253367fc7 | 666 | // BOTH buffers (color and mask) must be PROGMEM-resident. |
mjromeijn | 0:cc4253367fc7 | 667 | // For 16-bit display devices; no color reduction performed. |
mjromeijn | 0:cc4253367fc7 | 668 | void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 669 | const uint16_t bitmap[], const uint8_t mask[], |
mjromeijn | 0:cc4253367fc7 | 670 | int16_t w, int16_t h) { |
mjromeijn | 0:cc4253367fc7 | 671 | int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte |
mjromeijn | 0:cc4253367fc7 | 672 | uint8_t byte = 0; |
mjromeijn | 0:cc4253367fc7 | 673 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 674 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 675 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 676 | if(i & 7) byte <<= 1; |
mjromeijn | 0:cc4253367fc7 | 677 | else byte = pgm_read_byte(&mask[j * bw + i / 8]); |
mjromeijn | 0:cc4253367fc7 | 678 | if(byte & 0x80) { |
mjromeijn | 0:cc4253367fc7 | 679 | writePixel(x+i, y, pgm_read_word(&bitmap[j * w + i])); |
mjromeijn | 0:cc4253367fc7 | 680 | } |
mjromeijn | 0:cc4253367fc7 | 681 | } |
mjromeijn | 0:cc4253367fc7 | 682 | } |
mjromeijn | 0:cc4253367fc7 | 683 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 684 | } |
mjromeijn | 0:cc4253367fc7 | 685 | |
mjromeijn | 0:cc4253367fc7 | 686 | // Draw a RAM-resident 16-bit image (RGB 5/6/5) with a 1-bit mask |
mjromeijn | 0:cc4253367fc7 | 687 | // (set bits = opaque, unset bits = clear) at the specified (x,y) pos. |
mjromeijn | 0:cc4253367fc7 | 688 | // BOTH buffers (color and mask) must be RAM-resident, no mix-and-match. |
mjromeijn | 0:cc4253367fc7 | 689 | // For 16-bit display devices; no color reduction performed. |
mjromeijn | 0:cc4253367fc7 | 690 | void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 691 | uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h) { |
mjromeijn | 0:cc4253367fc7 | 692 | int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte |
mjromeijn | 0:cc4253367fc7 | 693 | uint8_t byte = 0; |
mjromeijn | 0:cc4253367fc7 | 694 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 695 | for(int16_t j=0; j<h; j++, y++) { |
mjromeijn | 0:cc4253367fc7 | 696 | for(int16_t i=0; i<w; i++ ) { |
mjromeijn | 0:cc4253367fc7 | 697 | if(i & 7) byte <<= 1; |
mjromeijn | 0:cc4253367fc7 | 698 | else byte = mask[j * bw + i / 8]; |
mjromeijn | 0:cc4253367fc7 | 699 | if(byte & 0x80) { |
mjromeijn | 0:cc4253367fc7 | 700 | writePixel(x+i, y, bitmap[j * w + i]); |
mjromeijn | 0:cc4253367fc7 | 701 | } |
mjromeijn | 0:cc4253367fc7 | 702 | } |
mjromeijn | 0:cc4253367fc7 | 703 | } |
mjromeijn | 0:cc4253367fc7 | 704 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 705 | } |
mjromeijn | 0:cc4253367fc7 | 706 | |
mjromeijn | 0:cc4253367fc7 | 707 | // TEXT- AND CHARACTER-HANDLING FUNCTIONS ---------------------------------- |
mjromeijn | 0:cc4253367fc7 | 708 | |
mjromeijn | 0:cc4253367fc7 | 709 | // Draw a character |
mjromeijn | 0:cc4253367fc7 | 710 | void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, |
mjromeijn | 0:cc4253367fc7 | 711 | uint16_t color, uint16_t bg, uint8_t size) { |
mjromeijn | 0:cc4253367fc7 | 712 | |
mjromeijn | 0:cc4253367fc7 | 713 | if(!gfxFont) { // 'Classic' built-in font |
mjromeijn | 0:cc4253367fc7 | 714 | |
mjromeijn | 0:cc4253367fc7 | 715 | if((x >= _width) || // Clip right |
mjromeijn | 0:cc4253367fc7 | 716 | (y >= _height) || // Clip bottom |
mjromeijn | 0:cc4253367fc7 | 717 | ((x + 6 * size - 1) < 0) || // Clip left |
mjromeijn | 0:cc4253367fc7 | 718 | ((y + 8 * size - 1) < 0)) // Clip top |
mjromeijn | 0:cc4253367fc7 | 719 | return; |
mjromeijn | 0:cc4253367fc7 | 720 | |
mjromeijn | 0:cc4253367fc7 | 721 | if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior |
mjromeijn | 0:cc4253367fc7 | 722 | |
mjromeijn | 0:cc4253367fc7 | 723 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 724 | for(int8_t i=0; i<5; i++ ) { // Char bitmap = 5 columns |
mjromeijn | 0:cc4253367fc7 | 725 | uint8_t line = pgm_read_byte(&font[c * 5 + i]); |
mjromeijn | 0:cc4253367fc7 | 726 | for(int8_t j=0; j<8; j++, line >>= 1) { |
mjromeijn | 0:cc4253367fc7 | 727 | if(line & 1) { |
mjromeijn | 0:cc4253367fc7 | 728 | if(size == 1) |
mjromeijn | 0:cc4253367fc7 | 729 | writePixel(x+i, y+j, color); |
mjromeijn | 0:cc4253367fc7 | 730 | else |
mjromeijn | 0:cc4253367fc7 | 731 | writeFillRect(x+i*size, y+j*size, size, size, color); |
mjromeijn | 0:cc4253367fc7 | 732 | } else if(bg != color) { |
mjromeijn | 0:cc4253367fc7 | 733 | if(size == 1) |
mjromeijn | 0:cc4253367fc7 | 734 | writePixel(x+i, y+j, bg); |
mjromeijn | 0:cc4253367fc7 | 735 | else |
mjromeijn | 0:cc4253367fc7 | 736 | writeFillRect(x+i*size, y+j*size, size, size, bg); |
mjromeijn | 0:cc4253367fc7 | 737 | } |
mjromeijn | 0:cc4253367fc7 | 738 | } |
mjromeijn | 0:cc4253367fc7 | 739 | } |
mjromeijn | 0:cc4253367fc7 | 740 | if(bg != color) { // If opaque, draw vertical line for last column |
mjromeijn | 0:cc4253367fc7 | 741 | if(size == 1) writeFastVLine(x+5, y, 8, bg); |
mjromeijn | 0:cc4253367fc7 | 742 | else writeFillRect(x+5*size, y, size, 8*size, bg); |
mjromeijn | 0:cc4253367fc7 | 743 | } |
mjromeijn | 0:cc4253367fc7 | 744 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 745 | |
mjromeijn | 0:cc4253367fc7 | 746 | } else { // Custom font |
mjromeijn | 0:cc4253367fc7 | 747 | |
mjromeijn | 0:cc4253367fc7 | 748 | // Character is assumed previously filtered by write() to eliminate |
mjromeijn | 0:cc4253367fc7 | 749 | // newlines, returns, non-printable characters, etc. Calling |
mjromeijn | 0:cc4253367fc7 | 750 | // drawChar() directly with 'bad' characters of font may cause mayhem! |
mjromeijn | 0:cc4253367fc7 | 751 | |
mjromeijn | 0:cc4253367fc7 | 752 | c -= (uint8_t)pgm_read_byte(&gfxFont->first); |
mjromeijn | 0:cc4253367fc7 | 753 | GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); |
mjromeijn | 0:cc4253367fc7 | 754 | uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap); |
mjromeijn | 0:cc4253367fc7 | 755 | |
mjromeijn | 0:cc4253367fc7 | 756 | uint16_t bo = pgm_read_word(&glyph->bitmapOffset); |
mjromeijn | 0:cc4253367fc7 | 757 | uint8_t w = pgm_read_byte(&glyph->width), |
mjromeijn | 0:cc4253367fc7 | 758 | h = pgm_read_byte(&glyph->height); |
mjromeijn | 0:cc4253367fc7 | 759 | int8_t xo = pgm_read_byte(&glyph->xOffset), |
mjromeijn | 0:cc4253367fc7 | 760 | yo = pgm_read_byte(&glyph->yOffset); |
mjromeijn | 0:cc4253367fc7 | 761 | uint8_t xx, yy, bits = 0, bit = 0; |
mjromeijn | 0:cc4253367fc7 | 762 | int16_t xo16 = 0, yo16 = 0; |
mjromeijn | 0:cc4253367fc7 | 763 | |
mjromeijn | 0:cc4253367fc7 | 764 | if(size > 1) { |
mjromeijn | 0:cc4253367fc7 | 765 | xo16 = xo; |
mjromeijn | 0:cc4253367fc7 | 766 | yo16 = yo; |
mjromeijn | 0:cc4253367fc7 | 767 | } |
mjromeijn | 0:cc4253367fc7 | 768 | |
mjromeijn | 0:cc4253367fc7 | 769 | // Todo: Add character clipping here |
mjromeijn | 0:cc4253367fc7 | 770 | |
mjromeijn | 0:cc4253367fc7 | 771 | // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS. |
mjromeijn | 0:cc4253367fc7 | 772 | // THIS IS ON PURPOSE AND BY DESIGN. The background color feature |
mjromeijn | 0:cc4253367fc7 | 773 | // has typically been used with the 'classic' font to overwrite old |
mjromeijn | 0:cc4253367fc7 | 774 | // screen contents with new data. This ONLY works because the |
mjromeijn | 0:cc4253367fc7 | 775 | // characters are a uniform size; it's not a sensible thing to do with |
mjromeijn | 0:cc4253367fc7 | 776 | // proportionally-spaced fonts with glyphs of varying sizes (and that |
mjromeijn | 0:cc4253367fc7 | 777 | // may overlap). To replace previously-drawn text when using a custom |
mjromeijn | 0:cc4253367fc7 | 778 | // font, use the getTextBounds() function to determine the smallest |
mjromeijn | 0:cc4253367fc7 | 779 | // rectangle encompassing a string, erase the area with fillRect(), |
mjromeijn | 0:cc4253367fc7 | 780 | // then draw new text. This WILL infortunately 'blink' the text, but |
mjromeijn | 0:cc4253367fc7 | 781 | // is unavoidable. Drawing 'background' pixels will NOT fix this, |
mjromeijn | 0:cc4253367fc7 | 782 | // only creates a new set of problems. Have an idea to work around |
mjromeijn | 0:cc4253367fc7 | 783 | // this (a canvas object type for MCUs that can afford the RAM and |
mjromeijn | 0:cc4253367fc7 | 784 | // displays supporting setAddrWindow() and pushColors()), but haven't |
mjromeijn | 0:cc4253367fc7 | 785 | // implemented this yet. |
mjromeijn | 0:cc4253367fc7 | 786 | |
mjromeijn | 0:cc4253367fc7 | 787 | startWrite(); |
mjromeijn | 0:cc4253367fc7 | 788 | for(yy=0; yy<h; yy++) { |
mjromeijn | 0:cc4253367fc7 | 789 | for(xx=0; xx<w; xx++) { |
mjromeijn | 0:cc4253367fc7 | 790 | if(!(bit++ & 7)) { |
mjromeijn | 0:cc4253367fc7 | 791 | bits = pgm_read_byte(&bitmap[bo++]); |
mjromeijn | 0:cc4253367fc7 | 792 | } |
mjromeijn | 0:cc4253367fc7 | 793 | if(bits & 0x80) { |
mjromeijn | 0:cc4253367fc7 | 794 | if(size == 1) { |
mjromeijn | 0:cc4253367fc7 | 795 | writePixel(x+xo+xx, y+yo+yy, color); |
mjromeijn | 0:cc4253367fc7 | 796 | } else { |
mjromeijn | 0:cc4253367fc7 | 797 | writeFillRect(x+(xo16+xx)*size, y+(yo16+yy)*size, |
mjromeijn | 0:cc4253367fc7 | 798 | size, size, color); |
mjromeijn | 0:cc4253367fc7 | 799 | } |
mjromeijn | 0:cc4253367fc7 | 800 | } |
mjromeijn | 0:cc4253367fc7 | 801 | bits <<= 1; |
mjromeijn | 0:cc4253367fc7 | 802 | } |
mjromeijn | 0:cc4253367fc7 | 803 | } |
mjromeijn | 0:cc4253367fc7 | 804 | endWrite(); |
mjromeijn | 0:cc4253367fc7 | 805 | |
mjromeijn | 0:cc4253367fc7 | 806 | } // End classic vs custom font |
mjromeijn | 0:cc4253367fc7 | 807 | } |
mjromeijn | 0:cc4253367fc7 | 808 | |
mjromeijn | 0:cc4253367fc7 | 809 | #if ARDUINO >= 100 |
mjromeijn | 0:cc4253367fc7 | 810 | size_t Adafruit_GFX::write(uint8_t c) { |
mjromeijn | 0:cc4253367fc7 | 811 | #else |
mjromeijn | 0:cc4253367fc7 | 812 | void Adafruit_GFX::write(uint8_t c) { |
mjromeijn | 0:cc4253367fc7 | 813 | #endif |
mjromeijn | 0:cc4253367fc7 | 814 | if(!gfxFont) { // 'Classic' built-in font |
mjromeijn | 0:cc4253367fc7 | 815 | |
mjromeijn | 0:cc4253367fc7 | 816 | if(c == '\n') { // Newline? |
mjromeijn | 0:cc4253367fc7 | 817 | cursor_x = 0; // Reset x to zero, |
mjromeijn | 0:cc4253367fc7 | 818 | cursor_y += textsize * 8; // advance y one line |
mjromeijn | 0:cc4253367fc7 | 819 | } else if(c != '\r') { // Ignore carriage returns |
mjromeijn | 0:cc4253367fc7 | 820 | if(wrap && ((cursor_x + textsize * 6) > _width)) { // Off right? |
mjromeijn | 0:cc4253367fc7 | 821 | cursor_x = 0; // Reset x to zero, |
mjromeijn | 0:cc4253367fc7 | 822 | cursor_y += textsize * 8; // advance y one line |
mjromeijn | 0:cc4253367fc7 | 823 | } |
mjromeijn | 0:cc4253367fc7 | 824 | drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); |
mjromeijn | 0:cc4253367fc7 | 825 | cursor_x += textsize * 6; // Advance x one char |
mjromeijn | 0:cc4253367fc7 | 826 | } |
mjromeijn | 0:cc4253367fc7 | 827 | |
mjromeijn | 0:cc4253367fc7 | 828 | } else { // Custom font |
mjromeijn | 0:cc4253367fc7 | 829 | |
mjromeijn | 0:cc4253367fc7 | 830 | if(c == '\n') { |
mjromeijn | 0:cc4253367fc7 | 831 | cursor_x = 0; |
mjromeijn | 0:cc4253367fc7 | 832 | cursor_y += (int16_t)textsize * |
mjromeijn | 0:cc4253367fc7 | 833 | (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
mjromeijn | 0:cc4253367fc7 | 834 | } else if(c != '\r') { |
mjromeijn | 0:cc4253367fc7 | 835 | uint8_t first = pgm_read_byte(&gfxFont->first); |
mjromeijn | 0:cc4253367fc7 | 836 | if((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) { |
mjromeijn | 0:cc4253367fc7 | 837 | GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer( |
mjromeijn | 0:cc4253367fc7 | 838 | &gfxFont->glyph))[c - first]); |
mjromeijn | 0:cc4253367fc7 | 839 | uint8_t w = pgm_read_byte(&glyph->width), |
mjromeijn | 0:cc4253367fc7 | 840 | h = pgm_read_byte(&glyph->height); |
mjromeijn | 0:cc4253367fc7 | 841 | if((w > 0) && (h > 0)) { // Is there an associated bitmap? |
mjromeijn | 0:cc4253367fc7 | 842 | int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic |
mjromeijn | 0:cc4253367fc7 | 843 | if(wrap && ((cursor_x + textsize * (xo + w)) > _width)) { |
mjromeijn | 0:cc4253367fc7 | 844 | cursor_x = 0; |
mjromeijn | 0:cc4253367fc7 | 845 | cursor_y += (int16_t)textsize * |
mjromeijn | 0:cc4253367fc7 | 846 | (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
mjromeijn | 0:cc4253367fc7 | 847 | } |
mjromeijn | 0:cc4253367fc7 | 848 | drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); |
mjromeijn | 0:cc4253367fc7 | 849 | } |
mjromeijn | 0:cc4253367fc7 | 850 | cursor_x += (uint8_t)pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; |
mjromeijn | 0:cc4253367fc7 | 851 | } |
mjromeijn | 0:cc4253367fc7 | 852 | } |
mjromeijn | 0:cc4253367fc7 | 853 | |
mjromeijn | 0:cc4253367fc7 | 854 | } |
mjromeijn | 0:cc4253367fc7 | 855 | #if ARDUINO >= 100 |
mjromeijn | 0:cc4253367fc7 | 856 | return 1; |
mjromeijn | 0:cc4253367fc7 | 857 | #endif |
mjromeijn | 0:cc4253367fc7 | 858 | } |
mjromeijn | 0:cc4253367fc7 | 859 | |
mjromeijn | 0:cc4253367fc7 | 860 | void Adafruit_GFX::print(char* textPtr) { |
mjromeijn | 0:cc4253367fc7 | 861 | while(*textPtr != 0) write(*textPtr++); |
mjromeijn | 0:cc4253367fc7 | 862 | } |
mjromeijn | 0:cc4253367fc7 | 863 | |
mjromeijn | 0:cc4253367fc7 | 864 | void Adafruit_GFX::setCursor(int16_t x, int16_t y) { |
mjromeijn | 0:cc4253367fc7 | 865 | cursor_x = x; |
mjromeijn | 0:cc4253367fc7 | 866 | cursor_y = y; |
mjromeijn | 0:cc4253367fc7 | 867 | } |
mjromeijn | 0:cc4253367fc7 | 868 | |
mjromeijn | 0:cc4253367fc7 | 869 | int16_t Adafruit_GFX::getCursorX(void) const { |
mjromeijn | 0:cc4253367fc7 | 870 | return cursor_x; |
mjromeijn | 0:cc4253367fc7 | 871 | } |
mjromeijn | 0:cc4253367fc7 | 872 | |
mjromeijn | 0:cc4253367fc7 | 873 | int16_t Adafruit_GFX::getCursorY(void) const { |
mjromeijn | 0:cc4253367fc7 | 874 | return cursor_y; |
mjromeijn | 0:cc4253367fc7 | 875 | } |
mjromeijn | 0:cc4253367fc7 | 876 | |
mjromeijn | 0:cc4253367fc7 | 877 | void Adafruit_GFX::setTextSize(uint8_t s) { |
mjromeijn | 0:cc4253367fc7 | 878 | textsize = (s > 0) ? s : 1; |
mjromeijn | 0:cc4253367fc7 | 879 | } |
mjromeijn | 0:cc4253367fc7 | 880 | |
mjromeijn | 0:cc4253367fc7 | 881 | void Adafruit_GFX::setTextColor(uint16_t c) { |
mjromeijn | 0:cc4253367fc7 | 882 | // For 'transparent' background, we'll set the bg |
mjromeijn | 0:cc4253367fc7 | 883 | // to the same as fg instead of using a flag |
mjromeijn | 0:cc4253367fc7 | 884 | textcolor = textbgcolor = c; |
mjromeijn | 0:cc4253367fc7 | 885 | } |
mjromeijn | 0:cc4253367fc7 | 886 | |
mjromeijn | 0:cc4253367fc7 | 887 | void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) { |
mjromeijn | 0:cc4253367fc7 | 888 | textcolor = c; |
mjromeijn | 0:cc4253367fc7 | 889 | textbgcolor = b; |
mjromeijn | 0:cc4253367fc7 | 890 | } |
mjromeijn | 0:cc4253367fc7 | 891 | |
mjromeijn | 0:cc4253367fc7 | 892 | void Adafruit_GFX::setTextWrap(boolean w) { |
mjromeijn | 0:cc4253367fc7 | 893 | wrap = w; |
mjromeijn | 0:cc4253367fc7 | 894 | } |
mjromeijn | 0:cc4253367fc7 | 895 | |
mjromeijn | 0:cc4253367fc7 | 896 | uint8_t Adafruit_GFX::getRotation(void) const { |
mjromeijn | 0:cc4253367fc7 | 897 | return rotation; |
mjromeijn | 0:cc4253367fc7 | 898 | } |
mjromeijn | 0:cc4253367fc7 | 899 | |
mjromeijn | 0:cc4253367fc7 | 900 | void Adafruit_GFX::setRotation(uint8_t x) { |
mjromeijn | 0:cc4253367fc7 | 901 | rotation = (x & 3); |
mjromeijn | 0:cc4253367fc7 | 902 | switch(rotation) { |
mjromeijn | 0:cc4253367fc7 | 903 | case 0: |
mjromeijn | 0:cc4253367fc7 | 904 | case 2: |
mjromeijn | 0:cc4253367fc7 | 905 | _width = WIDTH; |
mjromeijn | 0:cc4253367fc7 | 906 | _height = HEIGHT; |
mjromeijn | 0:cc4253367fc7 | 907 | break; |
mjromeijn | 0:cc4253367fc7 | 908 | case 1: |
mjromeijn | 0:cc4253367fc7 | 909 | case 3: |
mjromeijn | 0:cc4253367fc7 | 910 | _width = HEIGHT; |
mjromeijn | 0:cc4253367fc7 | 911 | _height = WIDTH; |
mjromeijn | 0:cc4253367fc7 | 912 | break; |
mjromeijn | 0:cc4253367fc7 | 913 | } |
mjromeijn | 0:cc4253367fc7 | 914 | } |
mjromeijn | 0:cc4253367fc7 | 915 | |
mjromeijn | 0:cc4253367fc7 | 916 | // Enable (or disable) Code Page 437-compatible charset. |
mjromeijn | 0:cc4253367fc7 | 917 | // There was an error in glcdfont.c for the longest time -- one character |
mjromeijn | 0:cc4253367fc7 | 918 | // (#176, the 'light shade' block) was missing -- this threw off the index |
mjromeijn | 0:cc4253367fc7 | 919 | // of every character that followed it. But a TON of code has been written |
mjromeijn | 0:cc4253367fc7 | 920 | // with the erroneous character indices. By default, the library uses the |
mjromeijn | 0:cc4253367fc7 | 921 | // original 'wrong' behavior and old sketches will still work. Pass 'true' |
mjromeijn | 0:cc4253367fc7 | 922 | // to this function to use correct CP437 character values in your code. |
mjromeijn | 0:cc4253367fc7 | 923 | void Adafruit_GFX::cp437(boolean x) { |
mjromeijn | 0:cc4253367fc7 | 924 | _cp437 = x; |
mjromeijn | 0:cc4253367fc7 | 925 | } |
mjromeijn | 0:cc4253367fc7 | 926 | |
mjromeijn | 0:cc4253367fc7 | 927 | void Adafruit_GFX::setFont(const GFXfont *f) { |
mjromeijn | 0:cc4253367fc7 | 928 | if(f) { // Font struct pointer passed in? |
mjromeijn | 0:cc4253367fc7 | 929 | if(!gfxFont) { // And no current font struct? |
mjromeijn | 0:cc4253367fc7 | 930 | // Switching from classic to new font behavior. |
mjromeijn | 0:cc4253367fc7 | 931 | // Move cursor pos down 6 pixels so it's on baseline. |
mjromeijn | 0:cc4253367fc7 | 932 | cursor_y += 6; |
mjromeijn | 0:cc4253367fc7 | 933 | } |
mjromeijn | 0:cc4253367fc7 | 934 | } else if(gfxFont) { // NULL passed. Current font struct defined? |
mjromeijn | 0:cc4253367fc7 | 935 | // Switching from new to classic font behavior. |
mjromeijn | 0:cc4253367fc7 | 936 | // Move cursor pos up 6 pixels so it's at top-left of char. |
mjromeijn | 0:cc4253367fc7 | 937 | cursor_y -= 6; |
mjromeijn | 0:cc4253367fc7 | 938 | } |
mjromeijn | 0:cc4253367fc7 | 939 | gfxFont = (GFXfont *)f; |
mjromeijn | 0:cc4253367fc7 | 940 | } |
mjromeijn | 0:cc4253367fc7 | 941 | |
mjromeijn | 0:cc4253367fc7 | 942 | // Broke this out as it's used by both the PROGMEM- and RAM-resident |
mjromeijn | 0:cc4253367fc7 | 943 | // getTextBounds() functions. |
mjromeijn | 0:cc4253367fc7 | 944 | void Adafruit_GFX::charBounds(char c, int16_t *x, int16_t *y, |
mjromeijn | 0:cc4253367fc7 | 945 | int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy) { |
mjromeijn | 0:cc4253367fc7 | 946 | |
mjromeijn | 0:cc4253367fc7 | 947 | if(gfxFont) { |
mjromeijn | 0:cc4253367fc7 | 948 | |
mjromeijn | 0:cc4253367fc7 | 949 | if(c == '\n') { // Newline? |
mjromeijn | 0:cc4253367fc7 | 950 | *x = 0; // Reset x to zero, advance y by one line |
mjromeijn | 0:cc4253367fc7 | 951 | *y += textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
mjromeijn | 0:cc4253367fc7 | 952 | } else if(c != '\r') { // Not a carriage return; is normal char |
mjromeijn | 0:cc4253367fc7 | 953 | uint8_t first = pgm_read_byte(&gfxFont->first), |
mjromeijn | 0:cc4253367fc7 | 954 | last = pgm_read_byte(&gfxFont->last); |
mjromeijn | 0:cc4253367fc7 | 955 | if((c >= first) && (c <= last)) { // Char present in this font? |
mjromeijn | 0:cc4253367fc7 | 956 | GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer( |
mjromeijn | 0:cc4253367fc7 | 957 | &gfxFont->glyph))[c - first]); |
mjromeijn | 0:cc4253367fc7 | 958 | uint8_t gw = pgm_read_byte(&glyph->width), |
mjromeijn | 0:cc4253367fc7 | 959 | gh = pgm_read_byte(&glyph->height), |
mjromeijn | 0:cc4253367fc7 | 960 | xa = pgm_read_byte(&glyph->xAdvance); |
mjromeijn | 0:cc4253367fc7 | 961 | int8_t xo = pgm_read_byte(&glyph->xOffset), |
mjromeijn | 0:cc4253367fc7 | 962 | yo = pgm_read_byte(&glyph->yOffset); |
mjromeijn | 0:cc4253367fc7 | 963 | if(wrap && ((*x+(((int16_t)xo+gw)*textsize)) > _width)) { |
mjromeijn | 0:cc4253367fc7 | 964 | *x = 0; // Reset x to zero, advance y by one line |
mjromeijn | 0:cc4253367fc7 | 965 | *y += textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
mjromeijn | 0:cc4253367fc7 | 966 | } |
mjromeijn | 0:cc4253367fc7 | 967 | int16_t ts = (int16_t)textsize, |
mjromeijn | 0:cc4253367fc7 | 968 | x1 = *x + xo * ts, |
mjromeijn | 0:cc4253367fc7 | 969 | y1 = *y + yo * ts, |
mjromeijn | 0:cc4253367fc7 | 970 | x2 = x1 + gw * ts - 1, |
mjromeijn | 0:cc4253367fc7 | 971 | y2 = y1 + gh * ts - 1; |
mjromeijn | 0:cc4253367fc7 | 972 | if(x1 < *minx) *minx = x1; |
mjromeijn | 0:cc4253367fc7 | 973 | if(y1 < *miny) *miny = y1; |
mjromeijn | 0:cc4253367fc7 | 974 | if(x2 > *maxx) *maxx = x2; |
mjromeijn | 0:cc4253367fc7 | 975 | if(y2 > *maxy) *maxy = y2; |
mjromeijn | 0:cc4253367fc7 | 976 | *x += xa * ts; |
mjromeijn | 0:cc4253367fc7 | 977 | } |
mjromeijn | 0:cc4253367fc7 | 978 | } |
mjromeijn | 0:cc4253367fc7 | 979 | |
mjromeijn | 0:cc4253367fc7 | 980 | } else { // Default font |
mjromeijn | 0:cc4253367fc7 | 981 | |
mjromeijn | 0:cc4253367fc7 | 982 | if(c == '\n') { // Newline? |
mjromeijn | 0:cc4253367fc7 | 983 | *x = 0; // Reset x to zero, |
mjromeijn | 0:cc4253367fc7 | 984 | *y += textsize * 8; // advance y one line |
mjromeijn | 0:cc4253367fc7 | 985 | // min/max x/y unchaged -- that waits for next 'normal' character |
mjromeijn | 0:cc4253367fc7 | 986 | } else if(c != '\r') { // Normal char; ignore carriage returns |
mjromeijn | 0:cc4253367fc7 | 987 | if(wrap && ((*x + textsize * 6) > _width)) { // Off right? |
mjromeijn | 0:cc4253367fc7 | 988 | *x = 0; // Reset x to zero, |
mjromeijn | 0:cc4253367fc7 | 989 | *y += textsize * 8; // advance y one line |
mjromeijn | 0:cc4253367fc7 | 990 | } |
mjromeijn | 0:cc4253367fc7 | 991 | int x2 = *x + textsize * 6 - 1, // Lower-right pixel of char |
mjromeijn | 0:cc4253367fc7 | 992 | y2 = *y + textsize * 8 - 1; |
mjromeijn | 0:cc4253367fc7 | 993 | if(x2 > *maxx) *maxx = x2; // Track max x, y |
mjromeijn | 0:cc4253367fc7 | 994 | if(y2 > *maxy) *maxy = y2; |
mjromeijn | 0:cc4253367fc7 | 995 | if(*x < *minx) *minx = *x; // Track min x, y |
mjromeijn | 0:cc4253367fc7 | 996 | if(*y < *miny) *miny = *y; |
mjromeijn | 0:cc4253367fc7 | 997 | *x += textsize * 6; // Advance x one char |
mjromeijn | 0:cc4253367fc7 | 998 | } |
mjromeijn | 0:cc4253367fc7 | 999 | } |
mjromeijn | 0:cc4253367fc7 | 1000 | } |
mjromeijn | 0:cc4253367fc7 | 1001 | |
mjromeijn | 0:cc4253367fc7 | 1002 | // Pass string and a cursor position, returns UL corner and W,H. |
mjromeijn | 0:cc4253367fc7 | 1003 | void Adafruit_GFX::getTextBounds(char *str, int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 1004 | int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) { |
mjromeijn | 0:cc4253367fc7 | 1005 | uint8_t c; // Current character |
mjromeijn | 0:cc4253367fc7 | 1006 | |
mjromeijn | 0:cc4253367fc7 | 1007 | *x1 = x; |
mjromeijn | 0:cc4253367fc7 | 1008 | *y1 = y; |
mjromeijn | 0:cc4253367fc7 | 1009 | *w = *h = 0; |
mjromeijn | 0:cc4253367fc7 | 1010 | |
mjromeijn | 0:cc4253367fc7 | 1011 | int16_t minx = _width, miny = _height, maxx = -1, maxy = -1; |
mjromeijn | 0:cc4253367fc7 | 1012 | |
mjromeijn | 0:cc4253367fc7 | 1013 | while((c = *str++)) |
mjromeijn | 0:cc4253367fc7 | 1014 | charBounds(c, &x, &y, &minx, &miny, &maxx, &maxy); |
mjromeijn | 0:cc4253367fc7 | 1015 | |
mjromeijn | 0:cc4253367fc7 | 1016 | if(maxx >= minx) { |
mjromeijn | 0:cc4253367fc7 | 1017 | *x1 = minx; |
mjromeijn | 0:cc4253367fc7 | 1018 | *w = maxx - minx + 1; |
mjromeijn | 0:cc4253367fc7 | 1019 | } |
mjromeijn | 0:cc4253367fc7 | 1020 | if(maxy >= miny) { |
mjromeijn | 0:cc4253367fc7 | 1021 | *y1 = miny; |
mjromeijn | 0:cc4253367fc7 | 1022 | *h = maxy - miny + 1; |
mjromeijn | 0:cc4253367fc7 | 1023 | } |
mjromeijn | 0:cc4253367fc7 | 1024 | } |
mjromeijn | 0:cc4253367fc7 | 1025 | |
mjromeijn | 0:cc4253367fc7 | 1026 | // Same as above, but for PROGMEM strings |
mjromeijn | 0:cc4253367fc7 | 1027 | /*void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str, |
mjromeijn | 0:cc4253367fc7 | 1028 | int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) { |
mjromeijn | 0:cc4253367fc7 | 1029 | uint8_t *s = (uint8_t *)str, c; |
mjromeijn | 0:cc4253367fc7 | 1030 | |
mjromeijn | 0:cc4253367fc7 | 1031 | *x1 = x; |
mjromeijn | 0:cc4253367fc7 | 1032 | *y1 = y; |
mjromeijn | 0:cc4253367fc7 | 1033 | *w = *h = 0; |
mjromeijn | 0:cc4253367fc7 | 1034 | |
mjromeijn | 0:cc4253367fc7 | 1035 | int16_t minx = _width, miny = _height, maxx = -1, maxy = -1; |
mjromeijn | 0:cc4253367fc7 | 1036 | |
mjromeijn | 0:cc4253367fc7 | 1037 | while((c = pgm_read_byte(s++))) |
mjromeijn | 0:cc4253367fc7 | 1038 | charBounds(c, &x, &y, &minx, &miny, &maxx, &maxy); |
mjromeijn | 0:cc4253367fc7 | 1039 | |
mjromeijn | 0:cc4253367fc7 | 1040 | if(maxx >= minx) { |
mjromeijn | 0:cc4253367fc7 | 1041 | *x1 = minx; |
mjromeijn | 0:cc4253367fc7 | 1042 | *w = maxx - minx + 1; |
mjromeijn | 0:cc4253367fc7 | 1043 | } |
mjromeijn | 0:cc4253367fc7 | 1044 | if(maxy >= miny) { |
mjromeijn | 0:cc4253367fc7 | 1045 | *y1 = miny; |
mjromeijn | 0:cc4253367fc7 | 1046 | *h = maxy - miny + 1; |
mjromeijn | 0:cc4253367fc7 | 1047 | } |
mjromeijn | 0:cc4253367fc7 | 1048 | }*/ |
mjromeijn | 0:cc4253367fc7 | 1049 | |
mjromeijn | 0:cc4253367fc7 | 1050 | // Return the size of the display (per current rotation) |
mjromeijn | 0:cc4253367fc7 | 1051 | int16_t Adafruit_GFX::width(void) const { |
mjromeijn | 0:cc4253367fc7 | 1052 | return _width; |
mjromeijn | 0:cc4253367fc7 | 1053 | } |
mjromeijn | 0:cc4253367fc7 | 1054 | |
mjromeijn | 0:cc4253367fc7 | 1055 | int16_t Adafruit_GFX::height(void) const { |
mjromeijn | 0:cc4253367fc7 | 1056 | return _height; |
mjromeijn | 0:cc4253367fc7 | 1057 | } |
mjromeijn | 0:cc4253367fc7 | 1058 | |
mjromeijn | 0:cc4253367fc7 | 1059 | void Adafruit_GFX::invertDisplay(boolean i) { |
mjromeijn | 0:cc4253367fc7 | 1060 | // Do nothing, must be subclassed if supported by hardware |
mjromeijn | 0:cc4253367fc7 | 1061 | } |
mjromeijn | 0:cc4253367fc7 | 1062 | |
mjromeijn | 0:cc4253367fc7 | 1063 | /***************************************************************************/ |
mjromeijn | 0:cc4253367fc7 | 1064 | // code for the GFX button UI element |
mjromeijn | 0:cc4253367fc7 | 1065 | |
mjromeijn | 0:cc4253367fc7 | 1066 | Adafruit_GFX_Button::Adafruit_GFX_Button(void) { |
mjromeijn | 0:cc4253367fc7 | 1067 | _gfx = 0; |
mjromeijn | 0:cc4253367fc7 | 1068 | } |
mjromeijn | 0:cc4253367fc7 | 1069 | |
mjromeijn | 0:cc4253367fc7 | 1070 | // Classic initButton() function: pass center & size |
mjromeijn | 0:cc4253367fc7 | 1071 | void Adafruit_GFX_Button::initButton( |
mjromeijn | 0:cc4253367fc7 | 1072 | Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t w, uint16_t h, |
mjromeijn | 0:cc4253367fc7 | 1073 | uint16_t outline, uint16_t fill, uint16_t textcolor, |
mjromeijn | 0:cc4253367fc7 | 1074 | char *label, uint8_t textsize) |
mjromeijn | 0:cc4253367fc7 | 1075 | { |
mjromeijn | 0:cc4253367fc7 | 1076 | // Tweak arguments and pass to the newer initButtonUL() function... |
mjromeijn | 0:cc4253367fc7 | 1077 | initButtonUL(gfx, x - (w / 2), y - (h / 2), w, h, outline, fill, |
mjromeijn | 0:cc4253367fc7 | 1078 | textcolor, label, textsize); |
mjromeijn | 0:cc4253367fc7 | 1079 | } |
mjromeijn | 0:cc4253367fc7 | 1080 | |
mjromeijn | 0:cc4253367fc7 | 1081 | // Newer function instead accepts upper-left corner & size |
mjromeijn | 0:cc4253367fc7 | 1082 | void Adafruit_GFX_Button::initButtonUL( |
mjromeijn | 0:cc4253367fc7 | 1083 | Adafruit_GFX *gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h, |
mjromeijn | 0:cc4253367fc7 | 1084 | uint16_t outline, uint16_t fill, uint16_t textcolor, |
mjromeijn | 0:cc4253367fc7 | 1085 | char *label, uint8_t textsize) |
mjromeijn | 0:cc4253367fc7 | 1086 | { |
mjromeijn | 0:cc4253367fc7 | 1087 | _x1 = x1; |
mjromeijn | 0:cc4253367fc7 | 1088 | _y1 = y1; |
mjromeijn | 0:cc4253367fc7 | 1089 | _w = w; |
mjromeijn | 0:cc4253367fc7 | 1090 | _h = h; |
mjromeijn | 0:cc4253367fc7 | 1091 | _outlinecolor = outline; |
mjromeijn | 0:cc4253367fc7 | 1092 | _fillcolor = fill; |
mjromeijn | 0:cc4253367fc7 | 1093 | _textcolor = textcolor; |
mjromeijn | 0:cc4253367fc7 | 1094 | _textsize = textsize; |
mjromeijn | 0:cc4253367fc7 | 1095 | _gfx = gfx; |
mjromeijn | 0:cc4253367fc7 | 1096 | strncpy(_label, label, 9); |
mjromeijn | 0:cc4253367fc7 | 1097 | } |
mjromeijn | 0:cc4253367fc7 | 1098 | |
mjromeijn | 0:cc4253367fc7 | 1099 | void Adafruit_GFX_Button::drawButton(boolean inverted) { |
mjromeijn | 0:cc4253367fc7 | 1100 | uint16_t fill, outline, text; |
mjromeijn | 0:cc4253367fc7 | 1101 | |
mjromeijn | 0:cc4253367fc7 | 1102 | if(!inverted) { |
mjromeijn | 0:cc4253367fc7 | 1103 | fill = _fillcolor; |
mjromeijn | 0:cc4253367fc7 | 1104 | outline = _outlinecolor; |
mjromeijn | 0:cc4253367fc7 | 1105 | text = _textcolor; |
mjromeijn | 0:cc4253367fc7 | 1106 | } else { |
mjromeijn | 0:cc4253367fc7 | 1107 | fill = _textcolor; |
mjromeijn | 0:cc4253367fc7 | 1108 | outline = _outlinecolor; |
mjromeijn | 0:cc4253367fc7 | 1109 | text = _fillcolor; |
mjromeijn | 0:cc4253367fc7 | 1110 | } |
mjromeijn | 0:cc4253367fc7 | 1111 | |
mjromeijn | 0:cc4253367fc7 | 1112 | uint8_t r = min(_w, _h) / 4; // Corner radius |
mjromeijn | 0:cc4253367fc7 | 1113 | _gfx->fillRoundRect(_x1, _y1, _w, _h, r, fill); |
mjromeijn | 0:cc4253367fc7 | 1114 | _gfx->drawRoundRect(_x1, _y1, _w, _h, r, outline); |
mjromeijn | 0:cc4253367fc7 | 1115 | |
mjromeijn | 0:cc4253367fc7 | 1116 | _gfx->setCursor(_x1 + (_w/2) - (strlen(_label) * 3 * _textsize), |
mjromeijn | 0:cc4253367fc7 | 1117 | _y1 + (_h/2) - (4 * _textsize)); |
mjromeijn | 0:cc4253367fc7 | 1118 | _gfx->setTextColor(text); |
mjromeijn | 0:cc4253367fc7 | 1119 | _gfx->setTextSize(_textsize); |
mjromeijn | 0:cc4253367fc7 | 1120 | _gfx->print(_label); |
mjromeijn | 0:cc4253367fc7 | 1121 | } |
mjromeijn | 0:cc4253367fc7 | 1122 | |
mjromeijn | 0:cc4253367fc7 | 1123 | boolean Adafruit_GFX_Button::contains(int16_t x, int16_t y) { |
mjromeijn | 0:cc4253367fc7 | 1124 | return ((x >= _x1) && (x < (_x1 + _w)) && |
mjromeijn | 0:cc4253367fc7 | 1125 | (y >= _y1) && (y < (_y1 + _h))); |
mjromeijn | 0:cc4253367fc7 | 1126 | } |
mjromeijn | 0:cc4253367fc7 | 1127 | |
mjromeijn | 0:cc4253367fc7 | 1128 | void Adafruit_GFX_Button::press(boolean p) { |
mjromeijn | 0:cc4253367fc7 | 1129 | laststate = currstate; |
mjromeijn | 0:cc4253367fc7 | 1130 | currstate = p; |
mjromeijn | 0:cc4253367fc7 | 1131 | } |
mjromeijn | 0:cc4253367fc7 | 1132 | |
mjromeijn | 0:cc4253367fc7 | 1133 | boolean Adafruit_GFX_Button::isPressed() { return currstate; } |
mjromeijn | 0:cc4253367fc7 | 1134 | boolean Adafruit_GFX_Button::justPressed() { return (currstate && !laststate); } |
mjromeijn | 0:cc4253367fc7 | 1135 | boolean Adafruit_GFX_Button::justReleased() { return (!currstate && laststate); } |
mjromeijn | 0:cc4253367fc7 | 1136 | |
mjromeijn | 0:cc4253367fc7 | 1137 | // ------------------------------------------------------------------------- |
mjromeijn | 0:cc4253367fc7 | 1138 | |
mjromeijn | 0:cc4253367fc7 | 1139 | // GFXcanvas1, GFXcanvas8 and GFXcanvas16 (currently a WIP, don't get too |
mjromeijn | 0:cc4253367fc7 | 1140 | // comfy with the implementation) provide 1-, 8- and 16-bit offscreen |
mjromeijn | 0:cc4253367fc7 | 1141 | // canvases, the address of which can be passed to drawBitmap() or |
mjromeijn | 0:cc4253367fc7 | 1142 | // pushColors() (the latter appears only in a couple of GFX-subclassed TFT |
mjromeijn | 0:cc4253367fc7 | 1143 | // libraries at this time). This is here mostly to help with the recently- |
mjromeijn | 0:cc4253367fc7 | 1144 | // added proportionally-spaced fonts; adds a way to refresh a section of the |
mjromeijn | 0:cc4253367fc7 | 1145 | // screen without a massive flickering clear-and-redraw...but maybe you'll |
mjromeijn | 0:cc4253367fc7 | 1146 | // find other uses too. VERY RAM-intensive, since the buffer is in MCU |
mjromeijn | 0:cc4253367fc7 | 1147 | // memory and not the display driver...GXFcanvas1 might be minimally useful |
mjromeijn | 0:cc4253367fc7 | 1148 | // on an Uno-class board, but this and the others are much more likely to |
mjromeijn | 0:cc4253367fc7 | 1149 | // require at least a Mega or various recent ARM-type boards (recommended, |
mjromeijn | 0:cc4253367fc7 | 1150 | // as the text+bitmap draw can be pokey). GFXcanvas1 requires 1 bit per |
mjromeijn | 0:cc4253367fc7 | 1151 | // pixel (rounded up to nearest byte per scanline), GFXcanvas8 is 1 byte |
mjromeijn | 0:cc4253367fc7 | 1152 | // per pixel (no scanline pad), and GFXcanvas16 uses 2 bytes per pixel (no |
mjromeijn | 0:cc4253367fc7 | 1153 | // scanline pad). |
mjromeijn | 0:cc4253367fc7 | 1154 | // NOT EXTENSIVELY TESTED YET. MAY CONTAIN WORST BUGS KNOWN TO HUMANKIND. |
mjromeijn | 0:cc4253367fc7 | 1155 | |
mjromeijn | 0:cc4253367fc7 | 1156 | GFXcanvas1::GFXcanvas1(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) { |
mjromeijn | 0:cc4253367fc7 | 1157 | uint16_t bytes = ((w + 7) / 8) * h; |
mjromeijn | 0:cc4253367fc7 | 1158 | if((buffer = (uint8_t *)malloc(bytes))) { |
mjromeijn | 0:cc4253367fc7 | 1159 | memset(buffer, 0, bytes); |
mjromeijn | 0:cc4253367fc7 | 1160 | } |
mjromeijn | 0:cc4253367fc7 | 1161 | } |
mjromeijn | 0:cc4253367fc7 | 1162 | |
mjromeijn | 0:cc4253367fc7 | 1163 | GFXcanvas1::~GFXcanvas1(void) { |
mjromeijn | 0:cc4253367fc7 | 1164 | if(buffer) free(buffer); |
mjromeijn | 0:cc4253367fc7 | 1165 | } |
mjromeijn | 0:cc4253367fc7 | 1166 | |
mjromeijn | 0:cc4253367fc7 | 1167 | uint8_t* GFXcanvas1::getBuffer(void) { |
mjromeijn | 0:cc4253367fc7 | 1168 | return buffer; |
mjromeijn | 0:cc4253367fc7 | 1169 | } |
mjromeijn | 0:cc4253367fc7 | 1170 | |
mjromeijn | 0:cc4253367fc7 | 1171 | void GFXcanvas1::drawPixel(int16_t x, int16_t y, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 1172 | #ifdef __AVR__ |
mjromeijn | 0:cc4253367fc7 | 1173 | // Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR |
mjromeijn | 0:cc4253367fc7 | 1174 | static const uint8_t PROGMEM |
mjromeijn | 0:cc4253367fc7 | 1175 | GFXsetBit[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, |
mjromeijn | 0:cc4253367fc7 | 1176 | GFXclrBit[] = { 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE }; |
mjromeijn | 0:cc4253367fc7 | 1177 | #endif |
mjromeijn | 0:cc4253367fc7 | 1178 | |
mjromeijn | 0:cc4253367fc7 | 1179 | if(buffer) { |
mjromeijn | 0:cc4253367fc7 | 1180 | if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return; |
mjromeijn | 0:cc4253367fc7 | 1181 | |
mjromeijn | 0:cc4253367fc7 | 1182 | int16_t t; |
mjromeijn | 0:cc4253367fc7 | 1183 | switch(rotation) { |
mjromeijn | 0:cc4253367fc7 | 1184 | case 1: |
mjromeijn | 0:cc4253367fc7 | 1185 | t = x; |
mjromeijn | 0:cc4253367fc7 | 1186 | x = WIDTH - 1 - y; |
mjromeijn | 0:cc4253367fc7 | 1187 | y = t; |
mjromeijn | 0:cc4253367fc7 | 1188 | break; |
mjromeijn | 0:cc4253367fc7 | 1189 | case 2: |
mjromeijn | 0:cc4253367fc7 | 1190 | x = WIDTH - 1 - x; |
mjromeijn | 0:cc4253367fc7 | 1191 | y = HEIGHT - 1 - y; |
mjromeijn | 0:cc4253367fc7 | 1192 | break; |
mjromeijn | 0:cc4253367fc7 | 1193 | case 3: |
mjromeijn | 0:cc4253367fc7 | 1194 | t = x; |
mjromeijn | 0:cc4253367fc7 | 1195 | x = y; |
mjromeijn | 0:cc4253367fc7 | 1196 | y = HEIGHT - 1 - t; |
mjromeijn | 0:cc4253367fc7 | 1197 | break; |
mjromeijn | 0:cc4253367fc7 | 1198 | } |
mjromeijn | 0:cc4253367fc7 | 1199 | |
mjromeijn | 0:cc4253367fc7 | 1200 | uint8_t *ptr = &buffer[(x / 8) + y * ((WIDTH + 7) / 8)]; |
mjromeijn | 0:cc4253367fc7 | 1201 | #ifdef __AVR__ |
mjromeijn | 0:cc4253367fc7 | 1202 | if(color) *ptr |= pgm_read_byte(&GFXsetBit[x & 7]); |
mjromeijn | 0:cc4253367fc7 | 1203 | else *ptr &= pgm_read_byte(&GFXclrBit[x & 7]); |
mjromeijn | 0:cc4253367fc7 | 1204 | #else |
mjromeijn | 0:cc4253367fc7 | 1205 | if(color) *ptr |= 0x80 >> (x & 7); |
mjromeijn | 0:cc4253367fc7 | 1206 | else *ptr &= ~(0x80 >> (x & 7)); |
mjromeijn | 0:cc4253367fc7 | 1207 | #endif |
mjromeijn | 0:cc4253367fc7 | 1208 | } |
mjromeijn | 0:cc4253367fc7 | 1209 | } |
mjromeijn | 0:cc4253367fc7 | 1210 | |
mjromeijn | 0:cc4253367fc7 | 1211 | void GFXcanvas1::fillScreen(uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 1212 | if(buffer) { |
mjromeijn | 0:cc4253367fc7 | 1213 | uint16_t bytes = ((WIDTH + 7) / 8) * HEIGHT; |
mjromeijn | 0:cc4253367fc7 | 1214 | memset(buffer, color ? 0xFF : 0x00, bytes); |
mjromeijn | 0:cc4253367fc7 | 1215 | } |
mjromeijn | 0:cc4253367fc7 | 1216 | } |
mjromeijn | 0:cc4253367fc7 | 1217 | |
mjromeijn | 0:cc4253367fc7 | 1218 | GFXcanvas8::GFXcanvas8(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) { |
mjromeijn | 0:cc4253367fc7 | 1219 | uint32_t bytes = w * h; |
mjromeijn | 0:cc4253367fc7 | 1220 | if((buffer = (uint8_t *)malloc(bytes))) { |
mjromeijn | 0:cc4253367fc7 | 1221 | memset(buffer, 0, bytes); |
mjromeijn | 0:cc4253367fc7 | 1222 | } |
mjromeijn | 0:cc4253367fc7 | 1223 | } |
mjromeijn | 0:cc4253367fc7 | 1224 | |
mjromeijn | 0:cc4253367fc7 | 1225 | GFXcanvas8::~GFXcanvas8(void) { |
mjromeijn | 0:cc4253367fc7 | 1226 | if(buffer) free(buffer); |
mjromeijn | 0:cc4253367fc7 | 1227 | } |
mjromeijn | 0:cc4253367fc7 | 1228 | |
mjromeijn | 0:cc4253367fc7 | 1229 | uint8_t* GFXcanvas8::getBuffer(void) { |
mjromeijn | 0:cc4253367fc7 | 1230 | return buffer; |
mjromeijn | 0:cc4253367fc7 | 1231 | } |
mjromeijn | 0:cc4253367fc7 | 1232 | |
mjromeijn | 0:cc4253367fc7 | 1233 | void GFXcanvas8::drawPixel(int16_t x, int16_t y, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 1234 | if(buffer) { |
mjromeijn | 0:cc4253367fc7 | 1235 | if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return; |
mjromeijn | 0:cc4253367fc7 | 1236 | |
mjromeijn | 0:cc4253367fc7 | 1237 | int16_t t; |
mjromeijn | 0:cc4253367fc7 | 1238 | switch(rotation) { |
mjromeijn | 0:cc4253367fc7 | 1239 | case 1: |
mjromeijn | 0:cc4253367fc7 | 1240 | t = x; |
mjromeijn | 0:cc4253367fc7 | 1241 | x = WIDTH - 1 - y; |
mjromeijn | 0:cc4253367fc7 | 1242 | y = t; |
mjromeijn | 0:cc4253367fc7 | 1243 | break; |
mjromeijn | 0:cc4253367fc7 | 1244 | case 2: |
mjromeijn | 0:cc4253367fc7 | 1245 | x = WIDTH - 1 - x; |
mjromeijn | 0:cc4253367fc7 | 1246 | y = HEIGHT - 1 - y; |
mjromeijn | 0:cc4253367fc7 | 1247 | break; |
mjromeijn | 0:cc4253367fc7 | 1248 | case 3: |
mjromeijn | 0:cc4253367fc7 | 1249 | t = x; |
mjromeijn | 0:cc4253367fc7 | 1250 | x = y; |
mjromeijn | 0:cc4253367fc7 | 1251 | y = HEIGHT - 1 - t; |
mjromeijn | 0:cc4253367fc7 | 1252 | break; |
mjromeijn | 0:cc4253367fc7 | 1253 | } |
mjromeijn | 0:cc4253367fc7 | 1254 | |
mjromeijn | 0:cc4253367fc7 | 1255 | buffer[x + y * WIDTH] = color; |
mjromeijn | 0:cc4253367fc7 | 1256 | } |
mjromeijn | 0:cc4253367fc7 | 1257 | } |
mjromeijn | 0:cc4253367fc7 | 1258 | |
mjromeijn | 0:cc4253367fc7 | 1259 | void GFXcanvas8::fillScreen(uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 1260 | if(buffer) { |
mjromeijn | 0:cc4253367fc7 | 1261 | memset(buffer, color, WIDTH * HEIGHT); |
mjromeijn | 0:cc4253367fc7 | 1262 | } |
mjromeijn | 0:cc4253367fc7 | 1263 | } |
mjromeijn | 0:cc4253367fc7 | 1264 | |
mjromeijn | 0:cc4253367fc7 | 1265 | void GFXcanvas8::writeFastHLine(int16_t x, int16_t y, |
mjromeijn | 0:cc4253367fc7 | 1266 | int16_t w, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 1267 | |
mjromeijn | 0:cc4253367fc7 | 1268 | if((x >= _width) || (y < 0) || (y >= _height)) return; |
mjromeijn | 0:cc4253367fc7 | 1269 | int16_t x2 = x + w - 1; |
mjromeijn | 0:cc4253367fc7 | 1270 | if(x2 < 0) return; |
mjromeijn | 0:cc4253367fc7 | 1271 | |
mjromeijn | 0:cc4253367fc7 | 1272 | // Clip left/right |
mjromeijn | 0:cc4253367fc7 | 1273 | if(x < 0) { |
mjromeijn | 0:cc4253367fc7 | 1274 | x = 0; |
mjromeijn | 0:cc4253367fc7 | 1275 | w = x2 + 1; |
mjromeijn | 0:cc4253367fc7 | 1276 | } |
mjromeijn | 0:cc4253367fc7 | 1277 | if(x2 >= _width) w = _width - x; |
mjromeijn | 0:cc4253367fc7 | 1278 | |
mjromeijn | 0:cc4253367fc7 | 1279 | int16_t t; |
mjromeijn | 0:cc4253367fc7 | 1280 | switch(rotation) { |
mjromeijn | 0:cc4253367fc7 | 1281 | case 1: |
mjromeijn | 0:cc4253367fc7 | 1282 | t = x; |
mjromeijn | 0:cc4253367fc7 | 1283 | x = WIDTH - 1 - y; |
mjromeijn | 0:cc4253367fc7 | 1284 | y = t; |
mjromeijn | 0:cc4253367fc7 | 1285 | break; |
mjromeijn | 0:cc4253367fc7 | 1286 | case 2: |
mjromeijn | 0:cc4253367fc7 | 1287 | x = WIDTH - 1 - x; |
mjromeijn | 0:cc4253367fc7 | 1288 | y = HEIGHT - 1 - y; |
mjromeijn | 0:cc4253367fc7 | 1289 | break; |
mjromeijn | 0:cc4253367fc7 | 1290 | case 3: |
mjromeijn | 0:cc4253367fc7 | 1291 | t = x; |
mjromeijn | 0:cc4253367fc7 | 1292 | x = y; |
mjromeijn | 0:cc4253367fc7 | 1293 | y = HEIGHT - 1 - t; |
mjromeijn | 0:cc4253367fc7 | 1294 | break; |
mjromeijn | 0:cc4253367fc7 | 1295 | } |
mjromeijn | 0:cc4253367fc7 | 1296 | |
mjromeijn | 0:cc4253367fc7 | 1297 | memset(buffer + y * WIDTH + x, color, w); |
mjromeijn | 0:cc4253367fc7 | 1298 | } |
mjromeijn | 0:cc4253367fc7 | 1299 | |
mjromeijn | 0:cc4253367fc7 | 1300 | GFXcanvas16::GFXcanvas16(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) { |
mjromeijn | 0:cc4253367fc7 | 1301 | uint32_t bytes = w * h * 2; |
mjromeijn | 0:cc4253367fc7 | 1302 | if((buffer = (uint16_t *)malloc(bytes))) { |
mjromeijn | 0:cc4253367fc7 | 1303 | memset(buffer, 0, bytes); |
mjromeijn | 0:cc4253367fc7 | 1304 | } |
mjromeijn | 0:cc4253367fc7 | 1305 | } |
mjromeijn | 0:cc4253367fc7 | 1306 | |
mjromeijn | 0:cc4253367fc7 | 1307 | GFXcanvas16::~GFXcanvas16(void) { |
mjromeijn | 0:cc4253367fc7 | 1308 | if(buffer) free(buffer); |
mjromeijn | 0:cc4253367fc7 | 1309 | } |
mjromeijn | 0:cc4253367fc7 | 1310 | |
mjromeijn | 0:cc4253367fc7 | 1311 | uint16_t* GFXcanvas16::getBuffer(void) { |
mjromeijn | 0:cc4253367fc7 | 1312 | return buffer; |
mjromeijn | 0:cc4253367fc7 | 1313 | } |
mjromeijn | 0:cc4253367fc7 | 1314 | |
mjromeijn | 0:cc4253367fc7 | 1315 | void GFXcanvas16::drawPixel(int16_t x, int16_t y, uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 1316 | if(buffer) { |
mjromeijn | 0:cc4253367fc7 | 1317 | if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return; |
mjromeijn | 0:cc4253367fc7 | 1318 | |
mjromeijn | 0:cc4253367fc7 | 1319 | int16_t t; |
mjromeijn | 0:cc4253367fc7 | 1320 | switch(rotation) { |
mjromeijn | 0:cc4253367fc7 | 1321 | case 1: |
mjromeijn | 0:cc4253367fc7 | 1322 | t = x; |
mjromeijn | 0:cc4253367fc7 | 1323 | x = WIDTH - 1 - y; |
mjromeijn | 0:cc4253367fc7 | 1324 | y = t; |
mjromeijn | 0:cc4253367fc7 | 1325 | break; |
mjromeijn | 0:cc4253367fc7 | 1326 | case 2: |
mjromeijn | 0:cc4253367fc7 | 1327 | x = WIDTH - 1 - x; |
mjromeijn | 0:cc4253367fc7 | 1328 | y = HEIGHT - 1 - y; |
mjromeijn | 0:cc4253367fc7 | 1329 | break; |
mjromeijn | 0:cc4253367fc7 | 1330 | case 3: |
mjromeijn | 0:cc4253367fc7 | 1331 | t = x; |
mjromeijn | 0:cc4253367fc7 | 1332 | x = y; |
mjromeijn | 0:cc4253367fc7 | 1333 | y = HEIGHT - 1 - t; |
mjromeijn | 0:cc4253367fc7 | 1334 | break; |
mjromeijn | 0:cc4253367fc7 | 1335 | } |
mjromeijn | 0:cc4253367fc7 | 1336 | |
mjromeijn | 0:cc4253367fc7 | 1337 | buffer[x + y * WIDTH] = color; |
mjromeijn | 0:cc4253367fc7 | 1338 | } |
mjromeijn | 0:cc4253367fc7 | 1339 | } |
mjromeijn | 0:cc4253367fc7 | 1340 | |
mjromeijn | 0:cc4253367fc7 | 1341 | void GFXcanvas16::fillScreen(uint16_t color) { |
mjromeijn | 0:cc4253367fc7 | 1342 | if(buffer) { |
mjromeijn | 0:cc4253367fc7 | 1343 | uint8_t hi = color >> 8, lo = color & 0xFF; |
mjromeijn | 0:cc4253367fc7 | 1344 | if(hi == lo) { |
mjromeijn | 0:cc4253367fc7 | 1345 | memset(buffer, lo, WIDTH * HEIGHT * 2); |
mjromeijn | 0:cc4253367fc7 | 1346 | } else { |
mjromeijn | 0:cc4253367fc7 | 1347 | uint32_t i, pixels = WIDTH * HEIGHT; |
mjromeijn | 0:cc4253367fc7 | 1348 | for(i=0; i<pixels; i++) buffer[i] = color; |
mjromeijn | 0:cc4253367fc7 | 1349 | } |
mjromeijn | 0:cc4253367fc7 | 1350 | } |
mjromeijn | 0:cc4253367fc7 | 1351 | } |
mjromeijn | 0:cc4253367fc7 | 1352 |