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