Fork of the latest Adafruit GFX Library as of 2017-12-13 to make it compatible with Mbed

Committer:
mjromeijn
Date:
Wed Dec 13 20:24:59 2017 +0000
Revision:
0:cc4253367fc7
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew 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