Final
Dependencies: IRremote HCSR04 TB6612FNG
oled/Adafruit_GFX.cpp@97:59d348745d96, 2019-06-16 (annotated)
- Committer:
- eunmango
- Date:
- Sun Jun 16 04:51:51 2019 +0000
- Revision:
- 97:59d348745d96
s
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
eunmango | 97:59d348745d96 | 1 | /* |
eunmango | 97:59d348745d96 | 2 | This is the core graphics library for all our displays, providing a common |
eunmango | 97:59d348745d96 | 3 | set of graphics primitives (points, lines, circles, etc.). It needs to be |
eunmango | 97:59d348745d96 | 4 | paired with a hardware-specific library for each display device we carry |
eunmango | 97:59d348745d96 | 5 | (to handle the lower-level functions). |
eunmango | 97:59d348745d96 | 6 | |
eunmango | 97:59d348745d96 | 7 | Adafruit invests time and resources providing this open source code, please |
eunmango | 97:59d348745d96 | 8 | support Adafruit & open-source hardware by purchasing products from Adafruit! |
eunmango | 97:59d348745d96 | 9 | |
eunmango | 97:59d348745d96 | 10 | Copyright (c) 2013 Adafruit Industries. All rights reserved. |
eunmango | 97:59d348745d96 | 11 | |
eunmango | 97:59d348745d96 | 12 | Redistribution and use in source and binary forms, with or without |
eunmango | 97:59d348745d96 | 13 | modification, are permitted provided that the following conditions are met: |
eunmango | 97:59d348745d96 | 14 | |
eunmango | 97:59d348745d96 | 15 | - Redistributions of source code must retain the above copyright notice, |
eunmango | 97:59d348745d96 | 16 | this list of conditions and the following disclaimer. |
eunmango | 97:59d348745d96 | 17 | - Redistributions in binary form must reproduce the above copyright notice, |
eunmango | 97:59d348745d96 | 18 | this list of conditions and the following disclaimer in the documentation |
eunmango | 97:59d348745d96 | 19 | and/or other materials provided with the distribution. |
eunmango | 97:59d348745d96 | 20 | |
eunmango | 97:59d348745d96 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
eunmango | 97:59d348745d96 | 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
eunmango | 97:59d348745d96 | 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
eunmango | 97:59d348745d96 | 24 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
eunmango | 97:59d348745d96 | 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
eunmango | 97:59d348745d96 | 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
eunmango | 97:59d348745d96 | 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
eunmango | 97:59d348745d96 | 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
eunmango | 97:59d348745d96 | 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
eunmango | 97:59d348745d96 | 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
eunmango | 97:59d348745d96 | 31 | POSSIBILITY OF SUCH DAMAGE. |
eunmango | 97:59d348745d96 | 32 | */ |
eunmango | 97:59d348745d96 | 33 | |
eunmango | 97:59d348745d96 | 34 | #include "Adafruit_GFX.h" |
eunmango | 97:59d348745d96 | 35 | #include "glcdfont.c" |
eunmango | 97:59d348745d96 | 36 | |
eunmango | 97:59d348745d96 | 37 | // Many (but maybe not all) non-AVR board installs define macros |
eunmango | 97:59d348745d96 | 38 | // for compatibility with existing PROGMEM-reading AVR code. |
eunmango | 97:59d348745d96 | 39 | // Do our own checks and defines here for good measure... |
eunmango | 97:59d348745d96 | 40 | |
eunmango | 97:59d348745d96 | 41 | #ifndef pgm_read_byte |
eunmango | 97:59d348745d96 | 42 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) |
eunmango | 97:59d348745d96 | 43 | #endif |
eunmango | 97:59d348745d96 | 44 | #ifndef pgm_read_word |
eunmango | 97:59d348745d96 | 45 | #define pgm_read_word(addr) (*(const unsigned short *)(addr)) |
eunmango | 97:59d348745d96 | 46 | #endif |
eunmango | 97:59d348745d96 | 47 | #ifndef pgm_read_dword |
eunmango | 97:59d348745d96 | 48 | #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) |
eunmango | 97:59d348745d96 | 49 | #endif |
eunmango | 97:59d348745d96 | 50 | |
eunmango | 97:59d348745d96 | 51 | // Pointers are a peculiar case...typically 16-bit on AVR boards, |
eunmango | 97:59d348745d96 | 52 | // 32 bits elsewhere. Try to accommodate both... |
eunmango | 97:59d348745d96 | 53 | |
eunmango | 97:59d348745d96 | 54 | #if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF) |
eunmango | 97:59d348745d96 | 55 | #define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr)) |
eunmango | 97:59d348745d96 | 56 | #else |
eunmango | 97:59d348745d96 | 57 | #define pgm_read_pointer(addr) ((void *)pgm_read_word(addr)) |
eunmango | 97:59d348745d96 | 58 | #endif |
eunmango | 97:59d348745d96 | 59 | |
eunmango | 97:59d348745d96 | 60 | #ifndef min |
eunmango | 97:59d348745d96 | 61 | #define min(a,b) (((a) < (b)) ? (a) : (b)) |
eunmango | 97:59d348745d96 | 62 | #endif |
eunmango | 97:59d348745d96 | 63 | |
eunmango | 97:59d348745d96 | 64 | #ifndef _swap_int16_t |
eunmango | 97:59d348745d96 | 65 | #define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } |
eunmango | 97:59d348745d96 | 66 | #endif |
eunmango | 97:59d348745d96 | 67 | |
eunmango | 97:59d348745d96 | 68 | Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h): |
eunmango | 97:59d348745d96 | 69 | WIDTH(w), HEIGHT(h) |
eunmango | 97:59d348745d96 | 70 | { |
eunmango | 97:59d348745d96 | 71 | _width = WIDTH; |
eunmango | 97:59d348745d96 | 72 | _height = HEIGHT; |
eunmango | 97:59d348745d96 | 73 | rotation = 0; |
eunmango | 97:59d348745d96 | 74 | cursor_y = cursor_x = 0; |
eunmango | 97:59d348745d96 | 75 | textsize = 1; |
eunmango | 97:59d348745d96 | 76 | textcolor = textbgcolor = 0xFFFF; |
eunmango | 97:59d348745d96 | 77 | wrap = true; |
eunmango | 97:59d348745d96 | 78 | gfxFont = NULL; |
eunmango | 97:59d348745d96 | 79 | } |
eunmango | 97:59d348745d96 | 80 | |
eunmango | 97:59d348745d96 | 81 | // Draw a circle outline |
eunmango | 97:59d348745d96 | 82 | void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, |
eunmango | 97:59d348745d96 | 83 | uint16_t color) { |
eunmango | 97:59d348745d96 | 84 | int16_t f = 1 - r; |
eunmango | 97:59d348745d96 | 85 | int16_t ddF_x = 1; |
eunmango | 97:59d348745d96 | 86 | int16_t ddF_y = -2 * r; |
eunmango | 97:59d348745d96 | 87 | int16_t x = 0; |
eunmango | 97:59d348745d96 | 88 | int16_t y = r; |
eunmango | 97:59d348745d96 | 89 | |
eunmango | 97:59d348745d96 | 90 | drawPixel(x0 , y0+r, color); |
eunmango | 97:59d348745d96 | 91 | drawPixel(x0 , y0-r, color); |
eunmango | 97:59d348745d96 | 92 | drawPixel(x0+r, y0 , color); |
eunmango | 97:59d348745d96 | 93 | drawPixel(x0-r, y0 , color); |
eunmango | 97:59d348745d96 | 94 | |
eunmango | 97:59d348745d96 | 95 | while (x<y) { |
eunmango | 97:59d348745d96 | 96 | if (f >= 0) { |
eunmango | 97:59d348745d96 | 97 | y--; |
eunmango | 97:59d348745d96 | 98 | ddF_y += 2; |
eunmango | 97:59d348745d96 | 99 | f += ddF_y; |
eunmango | 97:59d348745d96 | 100 | } |
eunmango | 97:59d348745d96 | 101 | x++; |
eunmango | 97:59d348745d96 | 102 | ddF_x += 2; |
eunmango | 97:59d348745d96 | 103 | f += ddF_x; |
eunmango | 97:59d348745d96 | 104 | |
eunmango | 97:59d348745d96 | 105 | drawPixel(x0 + x, y0 + y, color); |
eunmango | 97:59d348745d96 | 106 | drawPixel(x0 - x, y0 + y, color); |
eunmango | 97:59d348745d96 | 107 | drawPixel(x0 + x, y0 - y, color); |
eunmango | 97:59d348745d96 | 108 | drawPixel(x0 - x, y0 - y, color); |
eunmango | 97:59d348745d96 | 109 | drawPixel(x0 + y, y0 + x, color); |
eunmango | 97:59d348745d96 | 110 | drawPixel(x0 - y, y0 + x, color); |
eunmango | 97:59d348745d96 | 111 | drawPixel(x0 + y, y0 - x, color); |
eunmango | 97:59d348745d96 | 112 | drawPixel(x0 - y, y0 - x, color); |
eunmango | 97:59d348745d96 | 113 | } |
eunmango | 97:59d348745d96 | 114 | } |
eunmango | 97:59d348745d96 | 115 | |
eunmango | 97:59d348745d96 | 116 | void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0, |
eunmango | 97:59d348745d96 | 117 | int16_t r, uint8_t cornername, uint16_t color) { |
eunmango | 97:59d348745d96 | 118 | int16_t f = 1 - r; |
eunmango | 97:59d348745d96 | 119 | int16_t ddF_x = 1; |
eunmango | 97:59d348745d96 | 120 | int16_t ddF_y = -2 * r; |
eunmango | 97:59d348745d96 | 121 | int16_t x = 0; |
eunmango | 97:59d348745d96 | 122 | int16_t y = r; |
eunmango | 97:59d348745d96 | 123 | |
eunmango | 97:59d348745d96 | 124 | while (x<y) { |
eunmango | 97:59d348745d96 | 125 | if (f >= 0) { |
eunmango | 97:59d348745d96 | 126 | y--; |
eunmango | 97:59d348745d96 | 127 | ddF_y += 2; |
eunmango | 97:59d348745d96 | 128 | f += ddF_y; |
eunmango | 97:59d348745d96 | 129 | } |
eunmango | 97:59d348745d96 | 130 | x++; |
eunmango | 97:59d348745d96 | 131 | ddF_x += 2; |
eunmango | 97:59d348745d96 | 132 | f += ddF_x; |
eunmango | 97:59d348745d96 | 133 | if (cornername & 0x4) { |
eunmango | 97:59d348745d96 | 134 | drawPixel(x0 + x, y0 + y, color); |
eunmango | 97:59d348745d96 | 135 | drawPixel(x0 + y, y0 + x, color); |
eunmango | 97:59d348745d96 | 136 | } |
eunmango | 97:59d348745d96 | 137 | if (cornername & 0x2) { |
eunmango | 97:59d348745d96 | 138 | drawPixel(x0 + x, y0 - y, color); |
eunmango | 97:59d348745d96 | 139 | drawPixel(x0 + y, y0 - x, color); |
eunmango | 97:59d348745d96 | 140 | } |
eunmango | 97:59d348745d96 | 141 | if (cornername & 0x8) { |
eunmango | 97:59d348745d96 | 142 | drawPixel(x0 - y, y0 + x, color); |
eunmango | 97:59d348745d96 | 143 | drawPixel(x0 - x, y0 + y, color); |
eunmango | 97:59d348745d96 | 144 | } |
eunmango | 97:59d348745d96 | 145 | if (cornername & 0x1) { |
eunmango | 97:59d348745d96 | 146 | drawPixel(x0 - y, y0 - x, color); |
eunmango | 97:59d348745d96 | 147 | drawPixel(x0 - x, y0 - y, color); |
eunmango | 97:59d348745d96 | 148 | } |
eunmango | 97:59d348745d96 | 149 | } |
eunmango | 97:59d348745d96 | 150 | } |
eunmango | 97:59d348745d96 | 151 | |
eunmango | 97:59d348745d96 | 152 | void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) { |
eunmango | 97:59d348745d96 | 153 | drawFastVLine(x0, y0-r, 2*r+1, color); |
eunmango | 97:59d348745d96 | 154 | fillCircleHelper(x0, y0, r, 3, 0, color); |
eunmango | 97:59d348745d96 | 155 | } |
eunmango | 97:59d348745d96 | 156 | |
eunmango | 97:59d348745d96 | 157 | // Used to do circles and roundrects |
eunmango | 97:59d348745d96 | 158 | void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, |
eunmango | 97:59d348745d96 | 159 | uint8_t cornername, int16_t delta, uint16_t color) { |
eunmango | 97:59d348745d96 | 160 | |
eunmango | 97:59d348745d96 | 161 | int16_t f = 1 - r; |
eunmango | 97:59d348745d96 | 162 | int16_t ddF_x = 1; |
eunmango | 97:59d348745d96 | 163 | int16_t ddF_y = -2 * r; |
eunmango | 97:59d348745d96 | 164 | int16_t x = 0; |
eunmango | 97:59d348745d96 | 165 | int16_t y = r; |
eunmango | 97:59d348745d96 | 166 | |
eunmango | 97:59d348745d96 | 167 | while (x<y) { |
eunmango | 97:59d348745d96 | 168 | if (f >= 0) { |
eunmango | 97:59d348745d96 | 169 | y--; |
eunmango | 97:59d348745d96 | 170 | ddF_y += 2; |
eunmango | 97:59d348745d96 | 171 | f += ddF_y; |
eunmango | 97:59d348745d96 | 172 | } |
eunmango | 97:59d348745d96 | 173 | x++; |
eunmango | 97:59d348745d96 | 174 | ddF_x += 2; |
eunmango | 97:59d348745d96 | 175 | f += ddF_x; |
eunmango | 97:59d348745d96 | 176 | |
eunmango | 97:59d348745d96 | 177 | if (cornername & 0x1) { |
eunmango | 97:59d348745d96 | 178 | drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); |
eunmango | 97:59d348745d96 | 179 | drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); |
eunmango | 97:59d348745d96 | 180 | } |
eunmango | 97:59d348745d96 | 181 | if (cornername & 0x2) { |
eunmango | 97:59d348745d96 | 182 | drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); |
eunmango | 97:59d348745d96 | 183 | drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); |
eunmango | 97:59d348745d96 | 184 | } |
eunmango | 97:59d348745d96 | 185 | } |
eunmango | 97:59d348745d96 | 186 | } |
eunmango | 97:59d348745d96 | 187 | |
eunmango | 97:59d348745d96 | 188 | // Bresenham's algorithm - thx wikpedia |
eunmango | 97:59d348745d96 | 189 | void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, |
eunmango | 97:59d348745d96 | 190 | uint16_t color) { |
eunmango | 97:59d348745d96 | 191 | int16_t steep = abs(y1 - y0) > abs(x1 - x0); |
eunmango | 97:59d348745d96 | 192 | if (steep) { |
eunmango | 97:59d348745d96 | 193 | _swap_int16_t(x0, y0); |
eunmango | 97:59d348745d96 | 194 | _swap_int16_t(x1, y1); |
eunmango | 97:59d348745d96 | 195 | } |
eunmango | 97:59d348745d96 | 196 | |
eunmango | 97:59d348745d96 | 197 | if (x0 > x1) { |
eunmango | 97:59d348745d96 | 198 | _swap_int16_t(x0, x1); |
eunmango | 97:59d348745d96 | 199 | _swap_int16_t(y0, y1); |
eunmango | 97:59d348745d96 | 200 | } |
eunmango | 97:59d348745d96 | 201 | |
eunmango | 97:59d348745d96 | 202 | int16_t dx, dy; |
eunmango | 97:59d348745d96 | 203 | dx = x1 - x0; |
eunmango | 97:59d348745d96 | 204 | dy = abs(y1 - y0); |
eunmango | 97:59d348745d96 | 205 | |
eunmango | 97:59d348745d96 | 206 | int16_t err = dx / 2; |
eunmango | 97:59d348745d96 | 207 | int16_t ystep; |
eunmango | 97:59d348745d96 | 208 | |
eunmango | 97:59d348745d96 | 209 | if (y0 < y1) { |
eunmango | 97:59d348745d96 | 210 | ystep = 1; |
eunmango | 97:59d348745d96 | 211 | } else { |
eunmango | 97:59d348745d96 | 212 | ystep = -1; |
eunmango | 97:59d348745d96 | 213 | } |
eunmango | 97:59d348745d96 | 214 | |
eunmango | 97:59d348745d96 | 215 | for (; x0<=x1; x0++) { |
eunmango | 97:59d348745d96 | 216 | if (steep) { |
eunmango | 97:59d348745d96 | 217 | drawPixel(y0, x0, color); |
eunmango | 97:59d348745d96 | 218 | } else { |
eunmango | 97:59d348745d96 | 219 | drawPixel(x0, y0, color); |
eunmango | 97:59d348745d96 | 220 | } |
eunmango | 97:59d348745d96 | 221 | err -= dy; |
eunmango | 97:59d348745d96 | 222 | if (err < 0) { |
eunmango | 97:59d348745d96 | 223 | y0 += ystep; |
eunmango | 97:59d348745d96 | 224 | err += dx; |
eunmango | 97:59d348745d96 | 225 | } |
eunmango | 97:59d348745d96 | 226 | } |
eunmango | 97:59d348745d96 | 227 | } |
eunmango | 97:59d348745d96 | 228 | |
eunmango | 97:59d348745d96 | 229 | // Draw a rectangle |
eunmango | 97:59d348745d96 | 230 | void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, |
eunmango | 97:59d348745d96 | 231 | uint16_t color) { |
eunmango | 97:59d348745d96 | 232 | drawFastHLine(x, y, w, color); |
eunmango | 97:59d348745d96 | 233 | drawFastHLine(x, y+h-1, w, color); |
eunmango | 97:59d348745d96 | 234 | drawFastVLine(x, y, h, color); |
eunmango | 97:59d348745d96 | 235 | drawFastVLine(x+w-1, y, h, color); |
eunmango | 97:59d348745d96 | 236 | } |
eunmango | 97:59d348745d96 | 237 | |
eunmango | 97:59d348745d96 | 238 | void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, |
eunmango | 97:59d348745d96 | 239 | int16_t h, uint16_t color) { |
eunmango | 97:59d348745d96 | 240 | // Update in subclasses if desired! |
eunmango | 97:59d348745d96 | 241 | drawLine(x, y, x, y+h-1, color); |
eunmango | 97:59d348745d96 | 242 | } |
eunmango | 97:59d348745d96 | 243 | |
eunmango | 97:59d348745d96 | 244 | void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, |
eunmango | 97:59d348745d96 | 245 | int16_t w, uint16_t color) { |
eunmango | 97:59d348745d96 | 246 | // Update in subclasses if desired! |
eunmango | 97:59d348745d96 | 247 | drawLine(x, y, x+w-1, y, color); |
eunmango | 97:59d348745d96 | 248 | } |
eunmango | 97:59d348745d96 | 249 | |
eunmango | 97:59d348745d96 | 250 | void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, |
eunmango | 97:59d348745d96 | 251 | uint16_t color) { |
eunmango | 97:59d348745d96 | 252 | // Update in subclasses if desired! |
eunmango | 97:59d348745d96 | 253 | for (int16_t i=x; i<x+w; i++) { |
eunmango | 97:59d348745d96 | 254 | drawFastVLine(i, y, h, color); |
eunmango | 97:59d348745d96 | 255 | } |
eunmango | 97:59d348745d96 | 256 | } |
eunmango | 97:59d348745d96 | 257 | |
eunmango | 97:59d348745d96 | 258 | void Adafruit_GFX::fillScreen(uint16_t color) { |
eunmango | 97:59d348745d96 | 259 | fillRect(0, 0, _width, _height, color); |
eunmango | 97:59d348745d96 | 260 | } |
eunmango | 97:59d348745d96 | 261 | |
eunmango | 97:59d348745d96 | 262 | // Draw a rounded rectangle |
eunmango | 97:59d348745d96 | 263 | void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w, |
eunmango | 97:59d348745d96 | 264 | int16_t h, int16_t r, uint16_t color) { |
eunmango | 97:59d348745d96 | 265 | // smarter version |
eunmango | 97:59d348745d96 | 266 | drawFastHLine(x+r , y , w-2*r, color); // Top |
eunmango | 97:59d348745d96 | 267 | drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom |
eunmango | 97:59d348745d96 | 268 | drawFastVLine(x , y+r , h-2*r, color); // Left |
eunmango | 97:59d348745d96 | 269 | drawFastVLine(x+w-1, y+r , h-2*r, color); // Right |
eunmango | 97:59d348745d96 | 270 | // draw four corners |
eunmango | 97:59d348745d96 | 271 | drawCircleHelper(x+r , y+r , r, 1, color); |
eunmango | 97:59d348745d96 | 272 | drawCircleHelper(x+w-r-1, y+r , r, 2, color); |
eunmango | 97:59d348745d96 | 273 | drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); |
eunmango | 97:59d348745d96 | 274 | drawCircleHelper(x+r , y+h-r-1, r, 8, color); |
eunmango | 97:59d348745d96 | 275 | } |
eunmango | 97:59d348745d96 | 276 | |
eunmango | 97:59d348745d96 | 277 | // Fill a rounded rectangle |
eunmango | 97:59d348745d96 | 278 | void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w, |
eunmango | 97:59d348745d96 | 279 | int16_t h, int16_t r, uint16_t color) { |
eunmango | 97:59d348745d96 | 280 | // smarter version |
eunmango | 97:59d348745d96 | 281 | fillRect(x+r, y, w-2*r, h, color); |
eunmango | 97:59d348745d96 | 282 | |
eunmango | 97:59d348745d96 | 283 | // draw four corners |
eunmango | 97:59d348745d96 | 284 | fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color); |
eunmango | 97:59d348745d96 | 285 | fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color); |
eunmango | 97:59d348745d96 | 286 | } |
eunmango | 97:59d348745d96 | 287 | |
eunmango | 97:59d348745d96 | 288 | // Draw a triangle |
eunmango | 97:59d348745d96 | 289 | void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0, |
eunmango | 97:59d348745d96 | 290 | int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) { |
eunmango | 97:59d348745d96 | 291 | drawLine(x0, y0, x1, y1, color); |
eunmango | 97:59d348745d96 | 292 | drawLine(x1, y1, x2, y2, color); |
eunmango | 97:59d348745d96 | 293 | drawLine(x2, y2, x0, y0, color); |
eunmango | 97:59d348745d96 | 294 | } |
eunmango | 97:59d348745d96 | 295 | |
eunmango | 97:59d348745d96 | 296 | // Fill a triangle |
eunmango | 97:59d348745d96 | 297 | void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0, |
eunmango | 97:59d348745d96 | 298 | int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) { |
eunmango | 97:59d348745d96 | 299 | |
eunmango | 97:59d348745d96 | 300 | int16_t a, b, y, last; |
eunmango | 97:59d348745d96 | 301 | |
eunmango | 97:59d348745d96 | 302 | // Sort coordinates by Y order (y2 >= y1 >= y0) |
eunmango | 97:59d348745d96 | 303 | if (y0 > y1) { |
eunmango | 97:59d348745d96 | 304 | _swap_int16_t(y0, y1); _swap_int16_t(x0, x1); |
eunmango | 97:59d348745d96 | 305 | } |
eunmango | 97:59d348745d96 | 306 | if (y1 > y2) { |
eunmango | 97:59d348745d96 | 307 | _swap_int16_t(y2, y1); _swap_int16_t(x2, x1); |
eunmango | 97:59d348745d96 | 308 | } |
eunmango | 97:59d348745d96 | 309 | if (y0 > y1) { |
eunmango | 97:59d348745d96 | 310 | _swap_int16_t(y0, y1); _swap_int16_t(x0, x1); |
eunmango | 97:59d348745d96 | 311 | } |
eunmango | 97:59d348745d96 | 312 | |
eunmango | 97:59d348745d96 | 313 | if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing |
eunmango | 97:59d348745d96 | 314 | a = b = x0; |
eunmango | 97:59d348745d96 | 315 | if(x1 < a) a = x1; |
eunmango | 97:59d348745d96 | 316 | else if(x1 > b) b = x1; |
eunmango | 97:59d348745d96 | 317 | if(x2 < a) a = x2; |
eunmango | 97:59d348745d96 | 318 | else if(x2 > b) b = x2; |
eunmango | 97:59d348745d96 | 319 | drawFastHLine(a, y0, b-a+1, color); |
eunmango | 97:59d348745d96 | 320 | return; |
eunmango | 97:59d348745d96 | 321 | } |
eunmango | 97:59d348745d96 | 322 | |
eunmango | 97:59d348745d96 | 323 | int16_t |
eunmango | 97:59d348745d96 | 324 | dx01 = x1 - x0, |
eunmango | 97:59d348745d96 | 325 | dy01 = y1 - y0, |
eunmango | 97:59d348745d96 | 326 | dx02 = x2 - x0, |
eunmango | 97:59d348745d96 | 327 | dy02 = y2 - y0, |
eunmango | 97:59d348745d96 | 328 | dx12 = x2 - x1, |
eunmango | 97:59d348745d96 | 329 | dy12 = y2 - y1; |
eunmango | 97:59d348745d96 | 330 | int32_t |
eunmango | 97:59d348745d96 | 331 | sa = 0, |
eunmango | 97:59d348745d96 | 332 | sb = 0; |
eunmango | 97:59d348745d96 | 333 | |
eunmango | 97:59d348745d96 | 334 | // For upper part of triangle, find scanline crossings for segments |
eunmango | 97:59d348745d96 | 335 | // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 |
eunmango | 97:59d348745d96 | 336 | // is included here (and second loop will be skipped, avoiding a /0 |
eunmango | 97:59d348745d96 | 337 | // error there), otherwise scanline y1 is skipped here and handled |
eunmango | 97:59d348745d96 | 338 | // in the second loop...which also avoids a /0 error here if y0=y1 |
eunmango | 97:59d348745d96 | 339 | // (flat-topped triangle). |
eunmango | 97:59d348745d96 | 340 | if(y1 == y2) last = y1; // Include y1 scanline |
eunmango | 97:59d348745d96 | 341 | else last = y1-1; // Skip it |
eunmango | 97:59d348745d96 | 342 | |
eunmango | 97:59d348745d96 | 343 | for(y=y0; y<=last; y++) { |
eunmango | 97:59d348745d96 | 344 | a = x0 + sa / dy01; |
eunmango | 97:59d348745d96 | 345 | b = x0 + sb / dy02; |
eunmango | 97:59d348745d96 | 346 | sa += dx01; |
eunmango | 97:59d348745d96 | 347 | sb += dx02; |
eunmango | 97:59d348745d96 | 348 | /* longhand: |
eunmango | 97:59d348745d96 | 349 | a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); |
eunmango | 97:59d348745d96 | 350 | b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); |
eunmango | 97:59d348745d96 | 351 | */ |
eunmango | 97:59d348745d96 | 352 | if(a > b) _swap_int16_t(a,b); |
eunmango | 97:59d348745d96 | 353 | drawFastHLine(a, y, b-a+1, color); |
eunmango | 97:59d348745d96 | 354 | } |
eunmango | 97:59d348745d96 | 355 | |
eunmango | 97:59d348745d96 | 356 | // For lower part of triangle, find scanline crossings for segments |
eunmango | 97:59d348745d96 | 357 | // 0-2 and 1-2. This loop is skipped if y1=y2. |
eunmango | 97:59d348745d96 | 358 | sa = dx12 * (y - y1); |
eunmango | 97:59d348745d96 | 359 | sb = dx02 * (y - y0); |
eunmango | 97:59d348745d96 | 360 | for(; y<=y2; y++) { |
eunmango | 97:59d348745d96 | 361 | a = x1 + sa / dy12; |
eunmango | 97:59d348745d96 | 362 | b = x0 + sb / dy02; |
eunmango | 97:59d348745d96 | 363 | sa += dx12; |
eunmango | 97:59d348745d96 | 364 | sb += dx02; |
eunmango | 97:59d348745d96 | 365 | /* longhand: |
eunmango | 97:59d348745d96 | 366 | a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); |
eunmango | 97:59d348745d96 | 367 | b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); |
eunmango | 97:59d348745d96 | 368 | */ |
eunmango | 97:59d348745d96 | 369 | if(a > b) _swap_int16_t(a,b); |
eunmango | 97:59d348745d96 | 370 | drawFastHLine(a, y, b-a+1, color); |
eunmango | 97:59d348745d96 | 371 | } |
eunmango | 97:59d348745d96 | 372 | } |
eunmango | 97:59d348745d96 | 373 | |
eunmango | 97:59d348745d96 | 374 | |
eunmango | 97:59d348745d96 | 375 | // Draw a 1-bit image (bitmap) at the specified (x,y) position from the |
eunmango | 97:59d348745d96 | 376 | // provided bitmap buffer using the specified |
eunmango | 97:59d348745d96 | 377 | // foreground color (unset bits are transparent). |
eunmango | 97:59d348745d96 | 378 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, |
eunmango | 97:59d348745d96 | 379 | const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { |
eunmango | 97:59d348745d96 | 380 | |
eunmango | 97:59d348745d96 | 381 | int16_t i, j, byteWidth = (w + 7) / 8; |
eunmango | 97:59d348745d96 | 382 | uint8_t byte; |
eunmango | 97:59d348745d96 | 383 | |
eunmango | 97:59d348745d96 | 384 | for(j=0; j<h; j++) { |
eunmango | 97:59d348745d96 | 385 | for(i=0; i<w; i++ ) { |
eunmango | 97:59d348745d96 | 386 | if(i & 7) byte <<= 1; |
eunmango | 97:59d348745d96 | 387 | else byte = bitmap[j * byteWidth + i / 8]; |
eunmango | 97:59d348745d96 | 388 | if(byte & 0x80) drawPixel(x+i, y+j, color); |
eunmango | 97:59d348745d96 | 389 | } |
eunmango | 97:59d348745d96 | 390 | } |
eunmango | 97:59d348745d96 | 391 | } |
eunmango | 97:59d348745d96 | 392 | |
eunmango | 97:59d348745d96 | 393 | // Draw a 1-bit image (bitmap) at the specified (x,y) position from the |
eunmango | 97:59d348745d96 | 394 | // provided bitmap buffer using the specified |
eunmango | 97:59d348745d96 | 395 | // foreground (for set bits) and background (for clear bits) colors. |
eunmango | 97:59d348745d96 | 396 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, |
eunmango | 97:59d348745d96 | 397 | const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) { |
eunmango | 97:59d348745d96 | 398 | |
eunmango | 97:59d348745d96 | 399 | int16_t i, j, byteWidth = (w + 7) / 8; |
eunmango | 97:59d348745d96 | 400 | uint8_t byte; |
eunmango | 97:59d348745d96 | 401 | |
eunmango | 97:59d348745d96 | 402 | for(j=0; j<h; j++) { |
eunmango | 97:59d348745d96 | 403 | for(i=0; i<w; i++ ) { |
eunmango | 97:59d348745d96 | 404 | if(i & 7) byte <<= 1; |
eunmango | 97:59d348745d96 | 405 | else byte = bitmap[j * byteWidth + i / 8]; |
eunmango | 97:59d348745d96 | 406 | if(byte & 0x80) drawPixel(x+i, y+j, color); |
eunmango | 97:59d348745d96 | 407 | else drawPixel(x+i, y+j, bg); |
eunmango | 97:59d348745d96 | 408 | } |
eunmango | 97:59d348745d96 | 409 | } |
eunmango | 97:59d348745d96 | 410 | } |
eunmango | 97:59d348745d96 | 411 | |
eunmango | 97:59d348745d96 | 412 | //Draw XBitMap Files (*.xbm), exported from GIMP, |
eunmango | 97:59d348745d96 | 413 | //Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor. |
eunmango | 97:59d348745d96 | 414 | //C Array can be directly used with this function |
eunmango | 97:59d348745d96 | 415 | void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y, |
eunmango | 97:59d348745d96 | 416 | const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { |
eunmango | 97:59d348745d96 | 417 | |
eunmango | 97:59d348745d96 | 418 | int16_t i, j, byteWidth = (w + 7) / 8; |
eunmango | 97:59d348745d96 | 419 | uint8_t byte; |
eunmango | 97:59d348745d96 | 420 | |
eunmango | 97:59d348745d96 | 421 | for(j=0; j<h; j++) { |
eunmango | 97:59d348745d96 | 422 | for(i=0; i<w; i++ ) { |
eunmango | 97:59d348745d96 | 423 | if(i & 7) byte >>= 1; |
eunmango | 97:59d348745d96 | 424 | else byte = pgm_read_byte(bitmap + j * byteWidth + i / 8); |
eunmango | 97:59d348745d96 | 425 | if(byte & 0x01) drawPixel(x+i, y+j, color); |
eunmango | 97:59d348745d96 | 426 | } |
eunmango | 97:59d348745d96 | 427 | } |
eunmango | 97:59d348745d96 | 428 | } |
eunmango | 97:59d348745d96 | 429 | |
eunmango | 97:59d348745d96 | 430 | size_t Adafruit_GFX::write(uint8_t c) { |
eunmango | 97:59d348745d96 | 431 | if(!gfxFont) { // 'Classic' built-in font |
eunmango | 97:59d348745d96 | 432 | |
eunmango | 97:59d348745d96 | 433 | if(c == '\n') { |
eunmango | 97:59d348745d96 | 434 | cursor_y += textsize*8; |
eunmango | 97:59d348745d96 | 435 | cursor_x = 0; |
eunmango | 97:59d348745d96 | 436 | } else if(c == '\r') { |
eunmango | 97:59d348745d96 | 437 | // skip em |
eunmango | 97:59d348745d96 | 438 | } else { |
eunmango | 97:59d348745d96 | 439 | if(wrap && ((cursor_x + textsize * 6) >= _width)) { // Heading off edge? |
eunmango | 97:59d348745d96 | 440 | cursor_x = 0; // Reset x to zero |
eunmango | 97:59d348745d96 | 441 | cursor_y += textsize * 8; // Advance y one line |
eunmango | 97:59d348745d96 | 442 | } |
eunmango | 97:59d348745d96 | 443 | drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); |
eunmango | 97:59d348745d96 | 444 | cursor_x += textsize * 6; |
eunmango | 97:59d348745d96 | 445 | } |
eunmango | 97:59d348745d96 | 446 | |
eunmango | 97:59d348745d96 | 447 | } else { // Custom font |
eunmango | 97:59d348745d96 | 448 | |
eunmango | 97:59d348745d96 | 449 | if(c == '\n') { |
eunmango | 97:59d348745d96 | 450 | cursor_x = 0; |
eunmango | 97:59d348745d96 | 451 | cursor_y += (int16_t)textsize * |
eunmango | 97:59d348745d96 | 452 | (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
eunmango | 97:59d348745d96 | 453 | } else if(c != '\r') { |
eunmango | 97:59d348745d96 | 454 | uint8_t first = pgm_read_byte(&gfxFont->first); |
eunmango | 97:59d348745d96 | 455 | if((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) { |
eunmango | 97:59d348745d96 | 456 | uint8_t c2 = c - pgm_read_byte(&gfxFont->first); |
eunmango | 97:59d348745d96 | 457 | GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c2]); |
eunmango | 97:59d348745d96 | 458 | uint8_t w = pgm_read_byte(&glyph->width), |
eunmango | 97:59d348745d96 | 459 | h = pgm_read_byte(&glyph->height); |
eunmango | 97:59d348745d96 | 460 | if((w > 0) && (h > 0)) { // Is there an associated bitmap? |
eunmango | 97:59d348745d96 | 461 | int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic |
eunmango | 97:59d348745d96 | 462 | if(wrap && ((cursor_x + textsize * (xo + w)) >= _width)) { |
eunmango | 97:59d348745d96 | 463 | // Drawing character would go off right edge; wrap to new line |
eunmango | 97:59d348745d96 | 464 | cursor_x = 0; |
eunmango | 97:59d348745d96 | 465 | cursor_y += (int16_t)textsize * |
eunmango | 97:59d348745d96 | 466 | (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
eunmango | 97:59d348745d96 | 467 | } |
eunmango | 97:59d348745d96 | 468 | drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); |
eunmango | 97:59d348745d96 | 469 | } |
eunmango | 97:59d348745d96 | 470 | cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; |
eunmango | 97:59d348745d96 | 471 | } |
eunmango | 97:59d348745d96 | 472 | } |
eunmango | 97:59d348745d96 | 473 | |
eunmango | 97:59d348745d96 | 474 | } |
eunmango | 97:59d348745d96 | 475 | return 1; |
eunmango | 97:59d348745d96 | 476 | } |
eunmango | 97:59d348745d96 | 477 | |
eunmango | 97:59d348745d96 | 478 | // Draw a character |
eunmango | 97:59d348745d96 | 479 | void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, |
eunmango | 97:59d348745d96 | 480 | uint16_t color, uint16_t bg, uint8_t size) { |
eunmango | 97:59d348745d96 | 481 | |
eunmango | 97:59d348745d96 | 482 | if(!gfxFont) { // 'Classic' built-in font |
eunmango | 97:59d348745d96 | 483 | |
eunmango | 97:59d348745d96 | 484 | if((x >= _width) || // Clip right |
eunmango | 97:59d348745d96 | 485 | (y >= _height) || // Clip bottom |
eunmango | 97:59d348745d96 | 486 | ((x + 6 * size - 1) < 0) || // Clip left |
eunmango | 97:59d348745d96 | 487 | ((y + 8 * size - 1) < 0)) // Clip top |
eunmango | 97:59d348745d96 | 488 | return; |
eunmango | 97:59d348745d96 | 489 | |
eunmango | 97:59d348745d96 | 490 | for(int8_t i=0; i<6; i++ ) { |
eunmango | 97:59d348745d96 | 491 | uint8_t line; |
eunmango | 97:59d348745d96 | 492 | if(i < 5) line = pgm_read_byte(font+(c*5)+i); |
eunmango | 97:59d348745d96 | 493 | else line = 0x0; |
eunmango | 97:59d348745d96 | 494 | for(int8_t j=0; j<8; j++, line >>= 1) { |
eunmango | 97:59d348745d96 | 495 | if(line & 0x1) { |
eunmango | 97:59d348745d96 | 496 | if(size == 1) drawPixel(x+i, y+j, color); |
eunmango | 97:59d348745d96 | 497 | else fillRect(x+(i*size), y+(j*size), size, size, color); |
eunmango | 97:59d348745d96 | 498 | } else if(bg != color) { |
eunmango | 97:59d348745d96 | 499 | if(size == 1) drawPixel(x+i, y+j, bg); |
eunmango | 97:59d348745d96 | 500 | else fillRect(x+i*size, y+j*size, size, size, bg); |
eunmango | 97:59d348745d96 | 501 | } |
eunmango | 97:59d348745d96 | 502 | } |
eunmango | 97:59d348745d96 | 503 | } |
eunmango | 97:59d348745d96 | 504 | |
eunmango | 97:59d348745d96 | 505 | } else { // Custom font |
eunmango | 97:59d348745d96 | 506 | |
eunmango | 97:59d348745d96 | 507 | // Character is assumed previously filtered by write() to eliminate |
eunmango | 97:59d348745d96 | 508 | // newlines, returns, non-printable characters, etc. Calling drawChar() |
eunmango | 97:59d348745d96 | 509 | // directly with 'bad' characters of font may cause mayhem! |
eunmango | 97:59d348745d96 | 510 | |
eunmango | 97:59d348745d96 | 511 | c -= pgm_read_byte(&gfxFont->first); |
eunmango | 97:59d348745d96 | 512 | GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); |
eunmango | 97:59d348745d96 | 513 | uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap); |
eunmango | 97:59d348745d96 | 514 | |
eunmango | 97:59d348745d96 | 515 | uint16_t bo = pgm_read_word(&glyph->bitmapOffset); |
eunmango | 97:59d348745d96 | 516 | uint8_t w = pgm_read_byte(&glyph->width), |
eunmango | 97:59d348745d96 | 517 | h = pgm_read_byte(&glyph->height), |
eunmango | 97:59d348745d96 | 518 | xa = pgm_read_byte(&glyph->xAdvance); |
eunmango | 97:59d348745d96 | 519 | int8_t xo = pgm_read_byte(&glyph->xOffset); |
eunmango | 97:59d348745d96 | 520 | int8_t yo = pgm_read_byte(&glyph->yOffset); |
eunmango | 97:59d348745d96 | 521 | uint8_t xx, yy, bits, bit = 0; |
eunmango | 97:59d348745d96 | 522 | int16_t xo16, yo16; |
eunmango | 97:59d348745d96 | 523 | |
eunmango | 97:59d348745d96 | 524 | if(size > 1) { |
eunmango | 97:59d348745d96 | 525 | xo16 = xo; |
eunmango | 97:59d348745d96 | 526 | yo16 = yo; |
eunmango | 97:59d348745d96 | 527 | } |
eunmango | 97:59d348745d96 | 528 | |
eunmango | 97:59d348745d96 | 529 | // Todo: Add character clipping here |
eunmango | 97:59d348745d96 | 530 | |
eunmango | 97:59d348745d96 | 531 | // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS. |
eunmango | 97:59d348745d96 | 532 | // THIS IS ON PURPOSE AND BY DESIGN. The background color feature |
eunmango | 97:59d348745d96 | 533 | // has typically been used with the 'classic' font to overwrite old |
eunmango | 97:59d348745d96 | 534 | // screen contents with new data. This ONLY works because the |
eunmango | 97:59d348745d96 | 535 | // characters are a uniform size; it's not a sensible thing to do with |
eunmango | 97:59d348745d96 | 536 | // proportionally-spaced fonts with glyphs of varying sizes (and that |
eunmango | 97:59d348745d96 | 537 | // may overlap). To replace previously-drawn text when using a custom |
eunmango | 97:59d348745d96 | 538 | // font, use the getTextBounds() function to determine the smallest |
eunmango | 97:59d348745d96 | 539 | // rectangle encompassing a string, erase the area with fillRect(), |
eunmango | 97:59d348745d96 | 540 | // then draw new text. This WILL infortunately 'blink' the text, but |
eunmango | 97:59d348745d96 | 541 | // is unavoidable. Drawing 'background' pixels will NOT fix this, |
eunmango | 97:59d348745d96 | 542 | // only creates a new set of problems. Have an idea to work around |
eunmango | 97:59d348745d96 | 543 | // this (a canvas object type for MCUs that can afford the RAM and |
eunmango | 97:59d348745d96 | 544 | // displays supporting setAddrWindow() and pushColors()), but haven't |
eunmango | 97:59d348745d96 | 545 | // implemented this yet. |
eunmango | 97:59d348745d96 | 546 | |
eunmango | 97:59d348745d96 | 547 | for(yy=0; yy<h; yy++) { |
eunmango | 97:59d348745d96 | 548 | for(xx=0; xx<w; xx++) { |
eunmango | 97:59d348745d96 | 549 | if(!(bit++ & 7)) { |
eunmango | 97:59d348745d96 | 550 | bits = pgm_read_byte(&bitmap[bo++]); |
eunmango | 97:59d348745d96 | 551 | } |
eunmango | 97:59d348745d96 | 552 | if(bits & 0x80) { |
eunmango | 97:59d348745d96 | 553 | if(size == 1) { |
eunmango | 97:59d348745d96 | 554 | drawPixel(x+xo+xx, y+yo+yy, color); |
eunmango | 97:59d348745d96 | 555 | } else { |
eunmango | 97:59d348745d96 | 556 | fillRect(x+(xo16+xx)*size, y+(yo16+yy)*size, size, size, color); |
eunmango | 97:59d348745d96 | 557 | } |
eunmango | 97:59d348745d96 | 558 | } |
eunmango | 97:59d348745d96 | 559 | bits <<= 1; |
eunmango | 97:59d348745d96 | 560 | } |
eunmango | 97:59d348745d96 | 561 | } |
eunmango | 97:59d348745d96 | 562 | |
eunmango | 97:59d348745d96 | 563 | } // End classic vs custom font |
eunmango | 97:59d348745d96 | 564 | } |
eunmango | 97:59d348745d96 | 565 | |
eunmango | 97:59d348745d96 | 566 | void Adafruit_GFX::setCursor(int16_t x, int16_t y) { |
eunmango | 97:59d348745d96 | 567 | cursor_x = x; |
eunmango | 97:59d348745d96 | 568 | cursor_y = y; |
eunmango | 97:59d348745d96 | 569 | } |
eunmango | 97:59d348745d96 | 570 | |
eunmango | 97:59d348745d96 | 571 | int16_t Adafruit_GFX::getCursorX(void) const { |
eunmango | 97:59d348745d96 | 572 | return cursor_x; |
eunmango | 97:59d348745d96 | 573 | } |
eunmango | 97:59d348745d96 | 574 | |
eunmango | 97:59d348745d96 | 575 | int16_t Adafruit_GFX::getCursorY(void) const { |
eunmango | 97:59d348745d96 | 576 | return cursor_y; |
eunmango | 97:59d348745d96 | 577 | } |
eunmango | 97:59d348745d96 | 578 | |
eunmango | 97:59d348745d96 | 579 | void Adafruit_GFX::setTextSize(uint8_t s) { |
eunmango | 97:59d348745d96 | 580 | textsize = (s > 0) ? s : 1; |
eunmango | 97:59d348745d96 | 581 | } |
eunmango | 97:59d348745d96 | 582 | |
eunmango | 97:59d348745d96 | 583 | void Adafruit_GFX::setTextColor(uint16_t c) { |
eunmango | 97:59d348745d96 | 584 | // For 'transparent' background, we'll set the bg |
eunmango | 97:59d348745d96 | 585 | // to the same as fg instead of using a flag |
eunmango | 97:59d348745d96 | 586 | textcolor = textbgcolor = c; |
eunmango | 97:59d348745d96 | 587 | } |
eunmango | 97:59d348745d96 | 588 | |
eunmango | 97:59d348745d96 | 589 | void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) { |
eunmango | 97:59d348745d96 | 590 | textcolor = c; |
eunmango | 97:59d348745d96 | 591 | textbgcolor = b; |
eunmango | 97:59d348745d96 | 592 | } |
eunmango | 97:59d348745d96 | 593 | |
eunmango | 97:59d348745d96 | 594 | void Adafruit_GFX::setTextWrap(bool w) { |
eunmango | 97:59d348745d96 | 595 | wrap = w; |
eunmango | 97:59d348745d96 | 596 | } |
eunmango | 97:59d348745d96 | 597 | |
eunmango | 97:59d348745d96 | 598 | uint8_t Adafruit_GFX::getRotation(void) const { |
eunmango | 97:59d348745d96 | 599 | return rotation; |
eunmango | 97:59d348745d96 | 600 | } |
eunmango | 97:59d348745d96 | 601 | |
eunmango | 97:59d348745d96 | 602 | void Adafruit_GFX::setRotation(uint8_t x) { |
eunmango | 97:59d348745d96 | 603 | rotation = (x & 3); |
eunmango | 97:59d348745d96 | 604 | switch(rotation) { |
eunmango | 97:59d348745d96 | 605 | case 0: |
eunmango | 97:59d348745d96 | 606 | case 2: |
eunmango | 97:59d348745d96 | 607 | _width = WIDTH; |
eunmango | 97:59d348745d96 | 608 | _height = HEIGHT; |
eunmango | 97:59d348745d96 | 609 | break; |
eunmango | 97:59d348745d96 | 610 | case 1: |
eunmango | 97:59d348745d96 | 611 | case 3: |
eunmango | 97:59d348745d96 | 612 | _width = HEIGHT; |
eunmango | 97:59d348745d96 | 613 | _height = WIDTH; |
eunmango | 97:59d348745d96 | 614 | break; |
eunmango | 97:59d348745d96 | 615 | } |
eunmango | 97:59d348745d96 | 616 | } |
eunmango | 97:59d348745d96 | 617 | |
eunmango | 97:59d348745d96 | 618 | |
eunmango | 97:59d348745d96 | 619 | void Adafruit_GFX::setFont(const GFXfont *f) { |
eunmango | 97:59d348745d96 | 620 | if(f) { // Font struct pointer passed in? |
eunmango | 97:59d348745d96 | 621 | if(!gfxFont) { // And no current font struct? |
eunmango | 97:59d348745d96 | 622 | // Switching from classic to new font behavior. |
eunmango | 97:59d348745d96 | 623 | // Move cursor pos down 6 pixels so it's on baseline. |
eunmango | 97:59d348745d96 | 624 | cursor_y += 6; |
eunmango | 97:59d348745d96 | 625 | } |
eunmango | 97:59d348745d96 | 626 | } else if(gfxFont) { // NULL passed. Current font struct defined? |
eunmango | 97:59d348745d96 | 627 | // Switching from new to classic font behavior. |
eunmango | 97:59d348745d96 | 628 | // Move cursor pos up 6 pixels so it's at top-left of char. |
eunmango | 97:59d348745d96 | 629 | cursor_y -= 6; |
eunmango | 97:59d348745d96 | 630 | } |
eunmango | 97:59d348745d96 | 631 | gfxFont = (GFXfont *)f; |
eunmango | 97:59d348745d96 | 632 | } |
eunmango | 97:59d348745d96 | 633 | |
eunmango | 97:59d348745d96 | 634 | // Pass string and a cursor position, returns UL corner and W,H. |
eunmango | 97:59d348745d96 | 635 | void Adafruit_GFX::getTextBounds(char *str, int16_t x, int16_t y, |
eunmango | 97:59d348745d96 | 636 | int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) { |
eunmango | 97:59d348745d96 | 637 | uint8_t c; // Current character |
eunmango | 97:59d348745d96 | 638 | |
eunmango | 97:59d348745d96 | 639 | *x1 = x; |
eunmango | 97:59d348745d96 | 640 | *y1 = y; |
eunmango | 97:59d348745d96 | 641 | *w = *h = 0; |
eunmango | 97:59d348745d96 | 642 | |
eunmango | 97:59d348745d96 | 643 | if(gfxFont) { |
eunmango | 97:59d348745d96 | 644 | |
eunmango | 97:59d348745d96 | 645 | GFXglyph *glyph; |
eunmango | 97:59d348745d96 | 646 | uint8_t first = pgm_read_byte(&gfxFont->first), |
eunmango | 97:59d348745d96 | 647 | last = pgm_read_byte(&gfxFont->last), |
eunmango | 97:59d348745d96 | 648 | gw, gh, xa; |
eunmango | 97:59d348745d96 | 649 | int8_t xo, yo; |
eunmango | 97:59d348745d96 | 650 | int16_t minx = _width, miny = _height, maxx = -1, maxy = -1, |
eunmango | 97:59d348745d96 | 651 | gx1, gy1, gx2, gy2, ts = (int16_t)textsize, |
eunmango | 97:59d348745d96 | 652 | ya = ts * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
eunmango | 97:59d348745d96 | 653 | |
eunmango | 97:59d348745d96 | 654 | while((c = *str++)) { |
eunmango | 97:59d348745d96 | 655 | if(c != '\n') { // Not a newline |
eunmango | 97:59d348745d96 | 656 | if(c != '\r') { // Not a carriage return, is normal char |
eunmango | 97:59d348745d96 | 657 | if((c >= first) && (c <= last)) { // Char present in current font |
eunmango | 97:59d348745d96 | 658 | c -= first; |
eunmango | 97:59d348745d96 | 659 | glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); |
eunmango | 97:59d348745d96 | 660 | gw = pgm_read_byte(&glyph->width); |
eunmango | 97:59d348745d96 | 661 | gh = pgm_read_byte(&glyph->height); |
eunmango | 97:59d348745d96 | 662 | xa = pgm_read_byte(&glyph->xAdvance); |
eunmango | 97:59d348745d96 | 663 | xo = pgm_read_byte(&glyph->xOffset); |
eunmango | 97:59d348745d96 | 664 | yo = pgm_read_byte(&glyph->yOffset); |
eunmango | 97:59d348745d96 | 665 | if(wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) { |
eunmango | 97:59d348745d96 | 666 | // Line wrap |
eunmango | 97:59d348745d96 | 667 | x = 0; // Reset x to 0 |
eunmango | 97:59d348745d96 | 668 | y += ya; // Advance y by 1 line |
eunmango | 97:59d348745d96 | 669 | } |
eunmango | 97:59d348745d96 | 670 | gx1 = x + xo * ts; |
eunmango | 97:59d348745d96 | 671 | gy1 = y + yo * ts; |
eunmango | 97:59d348745d96 | 672 | gx2 = gx1 + gw * ts - 1; |
eunmango | 97:59d348745d96 | 673 | gy2 = gy1 + gh * ts - 1; |
eunmango | 97:59d348745d96 | 674 | if(gx1 < minx) minx = gx1; |
eunmango | 97:59d348745d96 | 675 | if(gy1 < miny) miny = gy1; |
eunmango | 97:59d348745d96 | 676 | if(gx2 > maxx) maxx = gx2; |
eunmango | 97:59d348745d96 | 677 | if(gy2 > maxy) maxy = gy2; |
eunmango | 97:59d348745d96 | 678 | x += xa * ts; |
eunmango | 97:59d348745d96 | 679 | } |
eunmango | 97:59d348745d96 | 680 | } // Carriage return = do nothing |
eunmango | 97:59d348745d96 | 681 | } else { // Newline |
eunmango | 97:59d348745d96 | 682 | x = 0; // Reset x |
eunmango | 97:59d348745d96 | 683 | y += ya; // Advance y by 1 line |
eunmango | 97:59d348745d96 | 684 | } |
eunmango | 97:59d348745d96 | 685 | } |
eunmango | 97:59d348745d96 | 686 | // End of string |
eunmango | 97:59d348745d96 | 687 | *x1 = minx; |
eunmango | 97:59d348745d96 | 688 | *y1 = miny; |
eunmango | 97:59d348745d96 | 689 | if(maxx >= minx) *w = maxx - minx + 1; |
eunmango | 97:59d348745d96 | 690 | if(maxy >= miny) *h = maxy - miny + 1; |
eunmango | 97:59d348745d96 | 691 | |
eunmango | 97:59d348745d96 | 692 | } else { // Default font |
eunmango | 97:59d348745d96 | 693 | |
eunmango | 97:59d348745d96 | 694 | uint16_t lineWidth = 0, maxWidth = 0; // Width of current, all lines |
eunmango | 97:59d348745d96 | 695 | |
eunmango | 97:59d348745d96 | 696 | while((c = *str++)) { |
eunmango | 97:59d348745d96 | 697 | if(c != '\n') { // Not a newline |
eunmango | 97:59d348745d96 | 698 | if(c != '\r') { // Not a carriage return, is normal char |
eunmango | 97:59d348745d96 | 699 | if(wrap && ((x + textsize * 6) >= _width)) { |
eunmango | 97:59d348745d96 | 700 | x = 0; // Reset x to 0 |
eunmango | 97:59d348745d96 | 701 | y += textsize * 8; // Advance y by 1 line |
eunmango | 97:59d348745d96 | 702 | if(lineWidth > maxWidth) maxWidth = lineWidth; // Save widest line |
eunmango | 97:59d348745d96 | 703 | lineWidth = textsize * 6; // First char on new line |
eunmango | 97:59d348745d96 | 704 | } else { // No line wrap, just keep incrementing X |
eunmango | 97:59d348745d96 | 705 | lineWidth += textsize * 6; // Includes interchar x gap |
eunmango | 97:59d348745d96 | 706 | } |
eunmango | 97:59d348745d96 | 707 | } // Carriage return = do nothing |
eunmango | 97:59d348745d96 | 708 | } else { // Newline |
eunmango | 97:59d348745d96 | 709 | x = 0; // Reset x to 0 |
eunmango | 97:59d348745d96 | 710 | y += textsize * 8; // Advance y by 1 line |
eunmango | 97:59d348745d96 | 711 | if(lineWidth > maxWidth) maxWidth = lineWidth; // Save widest line |
eunmango | 97:59d348745d96 | 712 | lineWidth = 0; // Reset lineWidth for new line |
eunmango | 97:59d348745d96 | 713 | } |
eunmango | 97:59d348745d96 | 714 | } |
eunmango | 97:59d348745d96 | 715 | // End of string |
eunmango | 97:59d348745d96 | 716 | if(lineWidth) y += textsize * 8; // Add height of last (or only) line |
eunmango | 97:59d348745d96 | 717 | if(lineWidth > maxWidth) maxWidth = lineWidth; // Is the last or only line the widest? |
eunmango | 97:59d348745d96 | 718 | *w = maxWidth - 1; // Don't include last interchar x gap |
eunmango | 97:59d348745d96 | 719 | *h = y - *y1; |
eunmango | 97:59d348745d96 | 720 | |
eunmango | 97:59d348745d96 | 721 | } // End classic vs custom font |
eunmango | 97:59d348745d96 | 722 | } |
eunmango | 97:59d348745d96 | 723 | |
eunmango | 97:59d348745d96 | 724 | |
eunmango | 97:59d348745d96 | 725 | |
eunmango | 97:59d348745d96 | 726 | void Adafruit_GFX::print(const char* str) { |
eunmango | 97:59d348745d96 | 727 | const char* p = str; |
eunmango | 97:59d348745d96 | 728 | while (*p!=0) |
eunmango | 97:59d348745d96 | 729 | write(*p++); |
eunmango | 97:59d348745d96 | 730 | } |
eunmango | 97:59d348745d96 | 731 | |
eunmango | 97:59d348745d96 | 732 | void Adafruit_GFX::println(const char* str) { |
eunmango | 97:59d348745d96 | 733 | print(str); |
eunmango | 97:59d348745d96 | 734 | write('\n'); |
eunmango | 97:59d348745d96 | 735 | } |
eunmango | 97:59d348745d96 | 736 | |
eunmango | 97:59d348745d96 | 737 | // Return the size of the display (per current rotation) |
eunmango | 97:59d348745d96 | 738 | int16_t Adafruit_GFX::width(void) const { |
eunmango | 97:59d348745d96 | 739 | return _width; |
eunmango | 97:59d348745d96 | 740 | } |
eunmango | 97:59d348745d96 | 741 | |
eunmango | 97:59d348745d96 | 742 | int16_t Adafruit_GFX::height(void) const { |
eunmango | 97:59d348745d96 | 743 | return _height; |
eunmango | 97:59d348745d96 | 744 | } |
eunmango | 97:59d348745d96 | 745 | |
eunmango | 97:59d348745d96 | 746 | void Adafruit_GFX::invertDisplay(bool i) { |
eunmango | 97:59d348745d96 | 747 | // Do nothing, must be subclassed if supported by hardware |
eunmango | 97:59d348745d96 | 748 | } |
eunmango | 97:59d348745d96 | 749 | |
eunmango | 97:59d348745d96 | 750 | |
eunmango | 97:59d348745d96 | 751 | /***************************************************************************/ |
eunmango | 97:59d348745d96 | 752 |