Basic Adafruit_GFX v1.10.7 library files with ADA_GFX_kbv.h and renamed glcdfont.inc MCUFRIEND_kbv library inherits from Adafruit_GFX
Dependents: TFT_Touch_botao_v1 TFT_Touch_exemplo5_git_touch TESTE_1 TFT_Touch_exemplo6_git_touch_button_3_ ... more
Adafruit_GFX.cpp@0:8ee30e15ac7b, 2021-04-26 (annotated)
- Committer:
- davidprentice
- Date:
- Mon Apr 26 14:39:27 2021 +0000
- Revision:
- 0:8ee30e15ac7b
Basic Adafruit_GFX v1.10.7 Arduino library files; with ADA_GFX_kbv.h and renamed glcdfont.inc
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
davidprentice | 0:8ee30e15ac7b | 1 | /* |
davidprentice | 0:8ee30e15ac7b | 2 | This is the core graphics library for all our displays, providing a common |
davidprentice | 0:8ee30e15ac7b | 3 | set of graphics primitives (points, lines, circles, etc.). It needs to be |
davidprentice | 0:8ee30e15ac7b | 4 | paired with a hardware-specific library for each display device we carry |
davidprentice | 0:8ee30e15ac7b | 5 | (to handle the lower-level functions). |
davidprentice | 0:8ee30e15ac7b | 6 | |
davidprentice | 0:8ee30e15ac7b | 7 | Adafruit invests time and resources providing this open source code, please |
davidprentice | 0:8ee30e15ac7b | 8 | support Adafruit & open-source hardware by purchasing products from Adafruit! |
davidprentice | 0:8ee30e15ac7b | 9 | |
davidprentice | 0:8ee30e15ac7b | 10 | Copyright (c) 2013 Adafruit Industries. All rights reserved. |
davidprentice | 0:8ee30e15ac7b | 11 | |
davidprentice | 0:8ee30e15ac7b | 12 | Redistribution and use in source and binary forms, with or without |
davidprentice | 0:8ee30e15ac7b | 13 | modification, are permitted provided that the following conditions are met: |
davidprentice | 0:8ee30e15ac7b | 14 | |
davidprentice | 0:8ee30e15ac7b | 15 | - Redistributions of source code must retain the above copyright notice, |
davidprentice | 0:8ee30e15ac7b | 16 | this list of conditions and the following disclaimer. |
davidprentice | 0:8ee30e15ac7b | 17 | - Redistributions in binary form must reproduce the above copyright notice, |
davidprentice | 0:8ee30e15ac7b | 18 | this list of conditions and the following disclaimer in the documentation |
davidprentice | 0:8ee30e15ac7b | 19 | and/or other materials provided with the distribution. |
davidprentice | 0:8ee30e15ac7b | 20 | |
davidprentice | 0:8ee30e15ac7b | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
davidprentice | 0:8ee30e15ac7b | 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
davidprentice | 0:8ee30e15ac7b | 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
davidprentice | 0:8ee30e15ac7b | 24 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
davidprentice | 0:8ee30e15ac7b | 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
davidprentice | 0:8ee30e15ac7b | 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
davidprentice | 0:8ee30e15ac7b | 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
davidprentice | 0:8ee30e15ac7b | 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
davidprentice | 0:8ee30e15ac7b | 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
davidprentice | 0:8ee30e15ac7b | 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
davidprentice | 0:8ee30e15ac7b | 31 | POSSIBILITY OF SUCH DAMAGE. |
davidprentice | 0:8ee30e15ac7b | 32 | */ |
davidprentice | 0:8ee30e15ac7b | 33 | |
davidprentice | 0:8ee30e15ac7b | 34 | #include "Adafruit_GFX.h" |
davidprentice | 0:8ee30e15ac7b | 35 | #include "glcdfont.inc" //.kbv |
davidprentice | 0:8ee30e15ac7b | 36 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 37 | #include <avr/pgmspace.h> |
davidprentice | 0:8ee30e15ac7b | 38 | #elif defined(ESP8266) || defined(ESP32) |
davidprentice | 0:8ee30e15ac7b | 39 | #include <pgmspace.h> |
davidprentice | 0:8ee30e15ac7b | 40 | #endif |
davidprentice | 0:8ee30e15ac7b | 41 | |
davidprentice | 0:8ee30e15ac7b | 42 | // Many (but maybe not all) non-AVR board installs define macros |
davidprentice | 0:8ee30e15ac7b | 43 | // for compatibility with existing PROGMEM-reading AVR code. |
davidprentice | 0:8ee30e15ac7b | 44 | // Do our own checks and defines here for good measure... |
davidprentice | 0:8ee30e15ac7b | 45 | |
davidprentice | 0:8ee30e15ac7b | 46 | #ifndef pgm_read_byte |
davidprentice | 0:8ee30e15ac7b | 47 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) |
davidprentice | 0:8ee30e15ac7b | 48 | #endif |
davidprentice | 0:8ee30e15ac7b | 49 | #ifndef pgm_read_word |
davidprentice | 0:8ee30e15ac7b | 50 | #define pgm_read_word(addr) (*(const unsigned short *)(addr)) |
davidprentice | 0:8ee30e15ac7b | 51 | #endif |
davidprentice | 0:8ee30e15ac7b | 52 | #ifndef pgm_read_dword |
davidprentice | 0:8ee30e15ac7b | 53 | #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) |
davidprentice | 0:8ee30e15ac7b | 54 | #endif |
davidprentice | 0:8ee30e15ac7b | 55 | |
davidprentice | 0:8ee30e15ac7b | 56 | // Pointers are a peculiar case...typically 16-bit on AVR boards, |
davidprentice | 0:8ee30e15ac7b | 57 | // 32 bits elsewhere. Try to accommodate both... |
davidprentice | 0:8ee30e15ac7b | 58 | |
davidprentice | 0:8ee30e15ac7b | 59 | #if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF) |
davidprentice | 0:8ee30e15ac7b | 60 | #define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr)) |
davidprentice | 0:8ee30e15ac7b | 61 | #else |
davidprentice | 0:8ee30e15ac7b | 62 | #define pgm_read_pointer(addr) ((void *)pgm_read_word(addr)) |
davidprentice | 0:8ee30e15ac7b | 63 | #endif |
davidprentice | 0:8ee30e15ac7b | 64 | |
davidprentice | 0:8ee30e15ac7b | 65 | inline GFXglyph *pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c) { |
davidprentice | 0:8ee30e15ac7b | 66 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 67 | return &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); |
davidprentice | 0:8ee30e15ac7b | 68 | #else |
davidprentice | 0:8ee30e15ac7b | 69 | // expression in __AVR__ section may generate "dereferencing type-punned |
davidprentice | 0:8ee30e15ac7b | 70 | // pointer will break strict-aliasing rules" warning In fact, on other |
davidprentice | 0:8ee30e15ac7b | 71 | // platforms (such as STM32) there is no need to do this pointer magic as |
davidprentice | 0:8ee30e15ac7b | 72 | // program memory may be read in a usual way So expression may be simplified |
davidprentice | 0:8ee30e15ac7b | 73 | return gfxFont->glyph + c; |
davidprentice | 0:8ee30e15ac7b | 74 | #endif //__AVR__ |
davidprentice | 0:8ee30e15ac7b | 75 | } |
davidprentice | 0:8ee30e15ac7b | 76 | |
davidprentice | 0:8ee30e15ac7b | 77 | inline uint8_t *pgm_read_bitmap_ptr(const GFXfont *gfxFont) { |
davidprentice | 0:8ee30e15ac7b | 78 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 79 | return (uint8_t *)pgm_read_pointer(&gfxFont->bitmap); |
davidprentice | 0:8ee30e15ac7b | 80 | #else |
davidprentice | 0:8ee30e15ac7b | 81 | // expression in __AVR__ section generates "dereferencing type-punned pointer |
davidprentice | 0:8ee30e15ac7b | 82 | // will break strict-aliasing rules" warning In fact, on other platforms (such |
davidprentice | 0:8ee30e15ac7b | 83 | // as STM32) there is no need to do this pointer magic as program memory may |
davidprentice | 0:8ee30e15ac7b | 84 | // be read in a usual way So expression may be simplified |
davidprentice | 0:8ee30e15ac7b | 85 | return gfxFont->bitmap; |
davidprentice | 0:8ee30e15ac7b | 86 | #endif //__AVR__ |
davidprentice | 0:8ee30e15ac7b | 87 | } |
davidprentice | 0:8ee30e15ac7b | 88 | |
davidprentice | 0:8ee30e15ac7b | 89 | #ifndef min |
davidprentice | 0:8ee30e15ac7b | 90 | #define min(a, b) (((a) < (b)) ? (a) : (b)) |
davidprentice | 0:8ee30e15ac7b | 91 | #endif |
davidprentice | 0:8ee30e15ac7b | 92 | |
davidprentice | 0:8ee30e15ac7b | 93 | #ifndef _swap_int16_t |
davidprentice | 0:8ee30e15ac7b | 94 | #define _swap_int16_t(a, b) \ |
davidprentice | 0:8ee30e15ac7b | 95 | { \ |
davidprentice | 0:8ee30e15ac7b | 96 | int16_t t = a; \ |
davidprentice | 0:8ee30e15ac7b | 97 | a = b; \ |
davidprentice | 0:8ee30e15ac7b | 98 | b = t; \ |
davidprentice | 0:8ee30e15ac7b | 99 | } |
davidprentice | 0:8ee30e15ac7b | 100 | #endif |
davidprentice | 0:8ee30e15ac7b | 101 | |
davidprentice | 0:8ee30e15ac7b | 102 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 103 | /*! |
davidprentice | 0:8ee30e15ac7b | 104 | @brief Instatiate a GFX context for graphics! Can only be done by a |
davidprentice | 0:8ee30e15ac7b | 105 | superclass |
davidprentice | 0:8ee30e15ac7b | 106 | @param w Display width, in pixels |
davidprentice | 0:8ee30e15ac7b | 107 | @param h Display height, in pixels |
davidprentice | 0:8ee30e15ac7b | 108 | */ |
davidprentice | 0:8ee30e15ac7b | 109 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 110 | Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h) : WIDTH(w), HEIGHT(h) { |
davidprentice | 0:8ee30e15ac7b | 111 | _width = WIDTH; |
davidprentice | 0:8ee30e15ac7b | 112 | _height = HEIGHT; |
davidprentice | 0:8ee30e15ac7b | 113 | rotation = 0; |
davidprentice | 0:8ee30e15ac7b | 114 | cursor_y = cursor_x = 0; |
davidprentice | 0:8ee30e15ac7b | 115 | textsize_x = textsize_y = 1; |
davidprentice | 0:8ee30e15ac7b | 116 | textcolor = textbgcolor = 0xFFFF; |
davidprentice | 0:8ee30e15ac7b | 117 | wrap = true; |
davidprentice | 0:8ee30e15ac7b | 118 | _cp437 = false; |
davidprentice | 0:8ee30e15ac7b | 119 | gfxFont = NULL; |
davidprentice | 0:8ee30e15ac7b | 120 | } |
davidprentice | 0:8ee30e15ac7b | 121 | |
davidprentice | 0:8ee30e15ac7b | 122 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 123 | /*! |
davidprentice | 0:8ee30e15ac7b | 124 | @brief Write a line. Bresenham's algorithm - thx wikpedia |
davidprentice | 0:8ee30e15ac7b | 125 | @param x0 Start point x coordinate |
davidprentice | 0:8ee30e15ac7b | 126 | @param y0 Start point y coordinate |
davidprentice | 0:8ee30e15ac7b | 127 | @param x1 End point x coordinate |
davidprentice | 0:8ee30e15ac7b | 128 | @param y1 End point y coordinate |
davidprentice | 0:8ee30e15ac7b | 129 | @param color 16-bit 5-6-5 Color to draw with |
davidprentice | 0:8ee30e15ac7b | 130 | */ |
davidprentice | 0:8ee30e15ac7b | 131 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 132 | void Adafruit_GFX::writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, |
davidprentice | 0:8ee30e15ac7b | 133 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 134 | #if defined(ESP8266) |
davidprentice | 0:8ee30e15ac7b | 135 | yield(); |
davidprentice | 0:8ee30e15ac7b | 136 | #endif |
davidprentice | 0:8ee30e15ac7b | 137 | int16_t steep = abs(y1 - y0) > abs(x1 - x0); |
davidprentice | 0:8ee30e15ac7b | 138 | if (steep) { |
davidprentice | 0:8ee30e15ac7b | 139 | _swap_int16_t(x0, y0); |
davidprentice | 0:8ee30e15ac7b | 140 | _swap_int16_t(x1, y1); |
davidprentice | 0:8ee30e15ac7b | 141 | } |
davidprentice | 0:8ee30e15ac7b | 142 | |
davidprentice | 0:8ee30e15ac7b | 143 | if (x0 > x1) { |
davidprentice | 0:8ee30e15ac7b | 144 | _swap_int16_t(x0, x1); |
davidprentice | 0:8ee30e15ac7b | 145 | _swap_int16_t(y0, y1); |
davidprentice | 0:8ee30e15ac7b | 146 | } |
davidprentice | 0:8ee30e15ac7b | 147 | |
davidprentice | 0:8ee30e15ac7b | 148 | int16_t dx, dy; |
davidprentice | 0:8ee30e15ac7b | 149 | dx = x1 - x0; |
davidprentice | 0:8ee30e15ac7b | 150 | dy = abs(y1 - y0); |
davidprentice | 0:8ee30e15ac7b | 151 | |
davidprentice | 0:8ee30e15ac7b | 152 | int16_t err = dx / 2; |
davidprentice | 0:8ee30e15ac7b | 153 | int16_t ystep; |
davidprentice | 0:8ee30e15ac7b | 154 | |
davidprentice | 0:8ee30e15ac7b | 155 | if (y0 < y1) { |
davidprentice | 0:8ee30e15ac7b | 156 | ystep = 1; |
davidprentice | 0:8ee30e15ac7b | 157 | } else { |
davidprentice | 0:8ee30e15ac7b | 158 | ystep = -1; |
davidprentice | 0:8ee30e15ac7b | 159 | } |
davidprentice | 0:8ee30e15ac7b | 160 | |
davidprentice | 0:8ee30e15ac7b | 161 | for (; x0 <= x1; x0++) { |
davidprentice | 0:8ee30e15ac7b | 162 | if (steep) { |
davidprentice | 0:8ee30e15ac7b | 163 | writePixel(y0, x0, color); |
davidprentice | 0:8ee30e15ac7b | 164 | } else { |
davidprentice | 0:8ee30e15ac7b | 165 | writePixel(x0, y0, color); |
davidprentice | 0:8ee30e15ac7b | 166 | } |
davidprentice | 0:8ee30e15ac7b | 167 | err -= dy; |
davidprentice | 0:8ee30e15ac7b | 168 | if (err < 0) { |
davidprentice | 0:8ee30e15ac7b | 169 | y0 += ystep; |
davidprentice | 0:8ee30e15ac7b | 170 | err += dx; |
davidprentice | 0:8ee30e15ac7b | 171 | } |
davidprentice | 0:8ee30e15ac7b | 172 | } |
davidprentice | 0:8ee30e15ac7b | 173 | } |
davidprentice | 0:8ee30e15ac7b | 174 | |
davidprentice | 0:8ee30e15ac7b | 175 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 176 | /*! |
davidprentice | 0:8ee30e15ac7b | 177 | @brief Start a display-writing routine, overwrite in subclasses. |
davidprentice | 0:8ee30e15ac7b | 178 | */ |
davidprentice | 0:8ee30e15ac7b | 179 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 180 | void Adafruit_GFX::startWrite() {} |
davidprentice | 0:8ee30e15ac7b | 181 | |
davidprentice | 0:8ee30e15ac7b | 182 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 183 | /*! |
davidprentice | 0:8ee30e15ac7b | 184 | @brief Write a pixel, overwrite in subclasses if startWrite is defined! |
davidprentice | 0:8ee30e15ac7b | 185 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 186 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 187 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 188 | */ |
davidprentice | 0:8ee30e15ac7b | 189 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 190 | void Adafruit_GFX::writePixel(int16_t x, int16_t y, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 191 | drawPixel(x, y, color); |
davidprentice | 0:8ee30e15ac7b | 192 | } |
davidprentice | 0:8ee30e15ac7b | 193 | |
davidprentice | 0:8ee30e15ac7b | 194 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 195 | /*! |
davidprentice | 0:8ee30e15ac7b | 196 | @brief Write a perfectly vertical line, overwrite in subclasses if |
davidprentice | 0:8ee30e15ac7b | 197 | startWrite is defined! |
davidprentice | 0:8ee30e15ac7b | 198 | @param x Top-most x coordinate |
davidprentice | 0:8ee30e15ac7b | 199 | @param y Top-most y coordinate |
davidprentice | 0:8ee30e15ac7b | 200 | @param h Height in pixels |
davidprentice | 0:8ee30e15ac7b | 201 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 202 | */ |
davidprentice | 0:8ee30e15ac7b | 203 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 204 | void Adafruit_GFX::writeFastVLine(int16_t x, int16_t y, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 205 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 206 | // Overwrite in subclasses if startWrite is defined! |
davidprentice | 0:8ee30e15ac7b | 207 | // Can be just writeLine(x, y, x, y+h-1, color); |
davidprentice | 0:8ee30e15ac7b | 208 | // or writeFillRect(x, y, 1, h, color); |
davidprentice | 0:8ee30e15ac7b | 209 | drawFastVLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 210 | } |
davidprentice | 0:8ee30e15ac7b | 211 | |
davidprentice | 0:8ee30e15ac7b | 212 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 213 | /*! |
davidprentice | 0:8ee30e15ac7b | 214 | @brief Write a perfectly horizontal line, overwrite in subclasses if |
davidprentice | 0:8ee30e15ac7b | 215 | startWrite is defined! |
davidprentice | 0:8ee30e15ac7b | 216 | @param x Left-most x coordinate |
davidprentice | 0:8ee30e15ac7b | 217 | @param y Left-most y coordinate |
davidprentice | 0:8ee30e15ac7b | 218 | @param w Width in pixels |
davidprentice | 0:8ee30e15ac7b | 219 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 220 | */ |
davidprentice | 0:8ee30e15ac7b | 221 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 222 | void Adafruit_GFX::writeFastHLine(int16_t x, int16_t y, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 223 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 224 | // Overwrite in subclasses if startWrite is defined! |
davidprentice | 0:8ee30e15ac7b | 225 | // Example: writeLine(x, y, x+w-1, y, color); |
davidprentice | 0:8ee30e15ac7b | 226 | // or writeFillRect(x, y, w, 1, color); |
davidprentice | 0:8ee30e15ac7b | 227 | drawFastHLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 228 | } |
davidprentice | 0:8ee30e15ac7b | 229 | |
davidprentice | 0:8ee30e15ac7b | 230 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 231 | /*! |
davidprentice | 0:8ee30e15ac7b | 232 | @brief Write a rectangle completely with one color, overwrite in |
davidprentice | 0:8ee30e15ac7b | 233 | subclasses if startWrite is defined! |
davidprentice | 0:8ee30e15ac7b | 234 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 235 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 236 | @param w Width in pixels |
davidprentice | 0:8ee30e15ac7b | 237 | @param h Height in pixels |
davidprentice | 0:8ee30e15ac7b | 238 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 239 | */ |
davidprentice | 0:8ee30e15ac7b | 240 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 241 | void Adafruit_GFX::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 242 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 243 | // Overwrite in subclasses if desired! |
davidprentice | 0:8ee30e15ac7b | 244 | fillRect(x, y, w, h, color); |
davidprentice | 0:8ee30e15ac7b | 245 | } |
davidprentice | 0:8ee30e15ac7b | 246 | |
davidprentice | 0:8ee30e15ac7b | 247 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 248 | /*! |
davidprentice | 0:8ee30e15ac7b | 249 | @brief End a display-writing routine, overwrite in subclasses if |
davidprentice | 0:8ee30e15ac7b | 250 | startWrite is defined! |
davidprentice | 0:8ee30e15ac7b | 251 | */ |
davidprentice | 0:8ee30e15ac7b | 252 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 253 | void Adafruit_GFX::endWrite() {} |
davidprentice | 0:8ee30e15ac7b | 254 | |
davidprentice | 0:8ee30e15ac7b | 255 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 256 | /*! |
davidprentice | 0:8ee30e15ac7b | 257 | @brief Draw a perfectly vertical line (this is often optimized in a |
davidprentice | 0:8ee30e15ac7b | 258 | subclass!) |
davidprentice | 0:8ee30e15ac7b | 259 | @param x Top-most x coordinate |
davidprentice | 0:8ee30e15ac7b | 260 | @param y Top-most y coordinate |
davidprentice | 0:8ee30e15ac7b | 261 | @param h Height in pixels |
davidprentice | 0:8ee30e15ac7b | 262 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 263 | */ |
davidprentice | 0:8ee30e15ac7b | 264 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 265 | void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 266 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 267 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 268 | writeLine(x, y, x, y + h - 1, color); |
davidprentice | 0:8ee30e15ac7b | 269 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 270 | } |
davidprentice | 0:8ee30e15ac7b | 271 | |
davidprentice | 0:8ee30e15ac7b | 272 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 273 | /*! |
davidprentice | 0:8ee30e15ac7b | 274 | @brief Draw a perfectly horizontal line (this is often optimized in a |
davidprentice | 0:8ee30e15ac7b | 275 | subclass!) |
davidprentice | 0:8ee30e15ac7b | 276 | @param x Left-most x coordinate |
davidprentice | 0:8ee30e15ac7b | 277 | @param y Left-most y coordinate |
davidprentice | 0:8ee30e15ac7b | 278 | @param w Width in pixels |
davidprentice | 0:8ee30e15ac7b | 279 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 280 | */ |
davidprentice | 0:8ee30e15ac7b | 281 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 282 | void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 283 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 284 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 285 | writeLine(x, y, x + w - 1, y, color); |
davidprentice | 0:8ee30e15ac7b | 286 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 287 | } |
davidprentice | 0:8ee30e15ac7b | 288 | |
davidprentice | 0:8ee30e15ac7b | 289 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 290 | /*! |
davidprentice | 0:8ee30e15ac7b | 291 | @brief Fill a rectangle completely with one color. Update in subclasses if |
davidprentice | 0:8ee30e15ac7b | 292 | desired! |
davidprentice | 0:8ee30e15ac7b | 293 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 294 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 295 | @param w Width in pixels |
davidprentice | 0:8ee30e15ac7b | 296 | @param h Height in pixels |
davidprentice | 0:8ee30e15ac7b | 297 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 298 | */ |
davidprentice | 0:8ee30e15ac7b | 299 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 300 | void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 301 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 302 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 303 | for (int16_t i = x; i < x + w; i++) { |
davidprentice | 0:8ee30e15ac7b | 304 | writeFastVLine(i, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 305 | } |
davidprentice | 0:8ee30e15ac7b | 306 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 307 | } |
davidprentice | 0:8ee30e15ac7b | 308 | |
davidprentice | 0:8ee30e15ac7b | 309 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 310 | /*! |
davidprentice | 0:8ee30e15ac7b | 311 | @brief Fill the screen completely with one color. Update in subclasses if |
davidprentice | 0:8ee30e15ac7b | 312 | desired! |
davidprentice | 0:8ee30e15ac7b | 313 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 314 | */ |
davidprentice | 0:8ee30e15ac7b | 315 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 316 | void Adafruit_GFX::fillScreen(uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 317 | fillRect(0, 0, _width, _height, color); |
davidprentice | 0:8ee30e15ac7b | 318 | } |
davidprentice | 0:8ee30e15ac7b | 319 | |
davidprentice | 0:8ee30e15ac7b | 320 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 321 | /*! |
davidprentice | 0:8ee30e15ac7b | 322 | @brief Draw a line |
davidprentice | 0:8ee30e15ac7b | 323 | @param x0 Start point x coordinate |
davidprentice | 0:8ee30e15ac7b | 324 | @param y0 Start point y coordinate |
davidprentice | 0:8ee30e15ac7b | 325 | @param x1 End point x coordinate |
davidprentice | 0:8ee30e15ac7b | 326 | @param y1 End point y coordinate |
davidprentice | 0:8ee30e15ac7b | 327 | @param color 16-bit 5-6-5 Color to draw with |
davidprentice | 0:8ee30e15ac7b | 328 | */ |
davidprentice | 0:8ee30e15ac7b | 329 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 330 | void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, |
davidprentice | 0:8ee30e15ac7b | 331 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 332 | // Update in subclasses if desired! |
davidprentice | 0:8ee30e15ac7b | 333 | if (x0 == x1) { |
davidprentice | 0:8ee30e15ac7b | 334 | if (y0 > y1) |
davidprentice | 0:8ee30e15ac7b | 335 | _swap_int16_t(y0, y1); |
davidprentice | 0:8ee30e15ac7b | 336 | drawFastVLine(x0, y0, y1 - y0 + 1, color); |
davidprentice | 0:8ee30e15ac7b | 337 | } else if (y0 == y1) { |
davidprentice | 0:8ee30e15ac7b | 338 | if (x0 > x1) |
davidprentice | 0:8ee30e15ac7b | 339 | _swap_int16_t(x0, x1); |
davidprentice | 0:8ee30e15ac7b | 340 | drawFastHLine(x0, y0, x1 - x0 + 1, color); |
davidprentice | 0:8ee30e15ac7b | 341 | } else { |
davidprentice | 0:8ee30e15ac7b | 342 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 343 | writeLine(x0, y0, x1, y1, color); |
davidprentice | 0:8ee30e15ac7b | 344 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 345 | } |
davidprentice | 0:8ee30e15ac7b | 346 | } |
davidprentice | 0:8ee30e15ac7b | 347 | |
davidprentice | 0:8ee30e15ac7b | 348 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 349 | /*! |
davidprentice | 0:8ee30e15ac7b | 350 | @brief Draw a circle outline |
davidprentice | 0:8ee30e15ac7b | 351 | @param x0 Center-point x coordinate |
davidprentice | 0:8ee30e15ac7b | 352 | @param y0 Center-point y coordinate |
davidprentice | 0:8ee30e15ac7b | 353 | @param r Radius of circle |
davidprentice | 0:8ee30e15ac7b | 354 | @param color 16-bit 5-6-5 Color to draw with |
davidprentice | 0:8ee30e15ac7b | 355 | */ |
davidprentice | 0:8ee30e15ac7b | 356 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 357 | void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, |
davidprentice | 0:8ee30e15ac7b | 358 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 359 | #if defined(ESP8266) |
davidprentice | 0:8ee30e15ac7b | 360 | yield(); |
davidprentice | 0:8ee30e15ac7b | 361 | #endif |
davidprentice | 0:8ee30e15ac7b | 362 | int16_t f = 1 - r; |
davidprentice | 0:8ee30e15ac7b | 363 | int16_t ddF_x = 1; |
davidprentice | 0:8ee30e15ac7b | 364 | int16_t ddF_y = -2 * r; |
davidprentice | 0:8ee30e15ac7b | 365 | int16_t x = 0; |
davidprentice | 0:8ee30e15ac7b | 366 | int16_t y = r; |
davidprentice | 0:8ee30e15ac7b | 367 | |
davidprentice | 0:8ee30e15ac7b | 368 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 369 | writePixel(x0, y0 + r, color); |
davidprentice | 0:8ee30e15ac7b | 370 | writePixel(x0, y0 - r, color); |
davidprentice | 0:8ee30e15ac7b | 371 | writePixel(x0 + r, y0, color); |
davidprentice | 0:8ee30e15ac7b | 372 | writePixel(x0 - r, y0, color); |
davidprentice | 0:8ee30e15ac7b | 373 | |
davidprentice | 0:8ee30e15ac7b | 374 | while (x < y) { |
davidprentice | 0:8ee30e15ac7b | 375 | if (f >= 0) { |
davidprentice | 0:8ee30e15ac7b | 376 | y--; |
davidprentice | 0:8ee30e15ac7b | 377 | ddF_y += 2; |
davidprentice | 0:8ee30e15ac7b | 378 | f += ddF_y; |
davidprentice | 0:8ee30e15ac7b | 379 | } |
davidprentice | 0:8ee30e15ac7b | 380 | x++; |
davidprentice | 0:8ee30e15ac7b | 381 | ddF_x += 2; |
davidprentice | 0:8ee30e15ac7b | 382 | f += ddF_x; |
davidprentice | 0:8ee30e15ac7b | 383 | |
davidprentice | 0:8ee30e15ac7b | 384 | writePixel(x0 + x, y0 + y, color); |
davidprentice | 0:8ee30e15ac7b | 385 | writePixel(x0 - x, y0 + y, color); |
davidprentice | 0:8ee30e15ac7b | 386 | writePixel(x0 + x, y0 - y, color); |
davidprentice | 0:8ee30e15ac7b | 387 | writePixel(x0 - x, y0 - y, color); |
davidprentice | 0:8ee30e15ac7b | 388 | writePixel(x0 + y, y0 + x, color); |
davidprentice | 0:8ee30e15ac7b | 389 | writePixel(x0 - y, y0 + x, color); |
davidprentice | 0:8ee30e15ac7b | 390 | writePixel(x0 + y, y0 - x, color); |
davidprentice | 0:8ee30e15ac7b | 391 | writePixel(x0 - y, y0 - x, color); |
davidprentice | 0:8ee30e15ac7b | 392 | } |
davidprentice | 0:8ee30e15ac7b | 393 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 394 | } |
davidprentice | 0:8ee30e15ac7b | 395 | |
davidprentice | 0:8ee30e15ac7b | 396 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 397 | /*! |
davidprentice | 0:8ee30e15ac7b | 398 | @brief Quarter-circle drawer, used to do circles and roundrects |
davidprentice | 0:8ee30e15ac7b | 399 | @param x0 Center-point x coordinate |
davidprentice | 0:8ee30e15ac7b | 400 | @param y0 Center-point y coordinate |
davidprentice | 0:8ee30e15ac7b | 401 | @param r Radius of circle |
davidprentice | 0:8ee30e15ac7b | 402 | @param cornername Mask bit #1 or bit #2 to indicate which quarters of |
davidprentice | 0:8ee30e15ac7b | 403 | the circle we're doing |
davidprentice | 0:8ee30e15ac7b | 404 | @param color 16-bit 5-6-5 Color to draw with |
davidprentice | 0:8ee30e15ac7b | 405 | */ |
davidprentice | 0:8ee30e15ac7b | 406 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 407 | void Adafruit_GFX::drawCircleHelper(int16_t x0, int16_t y0, int16_t r, |
davidprentice | 0:8ee30e15ac7b | 408 | uint8_t cornername, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 409 | int16_t f = 1 - r; |
davidprentice | 0:8ee30e15ac7b | 410 | int16_t ddF_x = 1; |
davidprentice | 0:8ee30e15ac7b | 411 | int16_t ddF_y = -2 * r; |
davidprentice | 0:8ee30e15ac7b | 412 | int16_t x = 0; |
davidprentice | 0:8ee30e15ac7b | 413 | int16_t y = r; |
davidprentice | 0:8ee30e15ac7b | 414 | |
davidprentice | 0:8ee30e15ac7b | 415 | while (x < y) { |
davidprentice | 0:8ee30e15ac7b | 416 | if (f >= 0) { |
davidprentice | 0:8ee30e15ac7b | 417 | y--; |
davidprentice | 0:8ee30e15ac7b | 418 | ddF_y += 2; |
davidprentice | 0:8ee30e15ac7b | 419 | f += ddF_y; |
davidprentice | 0:8ee30e15ac7b | 420 | } |
davidprentice | 0:8ee30e15ac7b | 421 | x++; |
davidprentice | 0:8ee30e15ac7b | 422 | ddF_x += 2; |
davidprentice | 0:8ee30e15ac7b | 423 | f += ddF_x; |
davidprentice | 0:8ee30e15ac7b | 424 | if (cornername & 0x4) { |
davidprentice | 0:8ee30e15ac7b | 425 | writePixel(x0 + x, y0 + y, color); |
davidprentice | 0:8ee30e15ac7b | 426 | writePixel(x0 + y, y0 + x, color); |
davidprentice | 0:8ee30e15ac7b | 427 | } |
davidprentice | 0:8ee30e15ac7b | 428 | if (cornername & 0x2) { |
davidprentice | 0:8ee30e15ac7b | 429 | writePixel(x0 + x, y0 - y, color); |
davidprentice | 0:8ee30e15ac7b | 430 | writePixel(x0 + y, y0 - x, color); |
davidprentice | 0:8ee30e15ac7b | 431 | } |
davidprentice | 0:8ee30e15ac7b | 432 | if (cornername & 0x8) { |
davidprentice | 0:8ee30e15ac7b | 433 | writePixel(x0 - y, y0 + x, color); |
davidprentice | 0:8ee30e15ac7b | 434 | writePixel(x0 - x, y0 + y, color); |
davidprentice | 0:8ee30e15ac7b | 435 | } |
davidprentice | 0:8ee30e15ac7b | 436 | if (cornername & 0x1) { |
davidprentice | 0:8ee30e15ac7b | 437 | writePixel(x0 - y, y0 - x, color); |
davidprentice | 0:8ee30e15ac7b | 438 | writePixel(x0 - x, y0 - y, color); |
davidprentice | 0:8ee30e15ac7b | 439 | } |
davidprentice | 0:8ee30e15ac7b | 440 | } |
davidprentice | 0:8ee30e15ac7b | 441 | } |
davidprentice | 0:8ee30e15ac7b | 442 | |
davidprentice | 0:8ee30e15ac7b | 443 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 444 | /*! |
davidprentice | 0:8ee30e15ac7b | 445 | @brief Draw a circle with filled color |
davidprentice | 0:8ee30e15ac7b | 446 | @param x0 Center-point x coordinate |
davidprentice | 0:8ee30e15ac7b | 447 | @param y0 Center-point y coordinate |
davidprentice | 0:8ee30e15ac7b | 448 | @param r Radius of circle |
davidprentice | 0:8ee30e15ac7b | 449 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 450 | */ |
davidprentice | 0:8ee30e15ac7b | 451 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 452 | void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, |
davidprentice | 0:8ee30e15ac7b | 453 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 454 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 455 | writeFastVLine(x0, y0 - r, 2 * r + 1, color); |
davidprentice | 0:8ee30e15ac7b | 456 | fillCircleHelper(x0, y0, r, 3, 0, color); |
davidprentice | 0:8ee30e15ac7b | 457 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 458 | } |
davidprentice | 0:8ee30e15ac7b | 459 | |
davidprentice | 0:8ee30e15ac7b | 460 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 461 | /*! |
davidprentice | 0:8ee30e15ac7b | 462 | @brief Quarter-circle drawer with fill, used for circles and roundrects |
davidprentice | 0:8ee30e15ac7b | 463 | @param x0 Center-point x coordinate |
davidprentice | 0:8ee30e15ac7b | 464 | @param y0 Center-point y coordinate |
davidprentice | 0:8ee30e15ac7b | 465 | @param r Radius of circle |
davidprentice | 0:8ee30e15ac7b | 466 | @param corners Mask bits indicating which quarters we're doing |
davidprentice | 0:8ee30e15ac7b | 467 | @param delta Offset from center-point, used for round-rects |
davidprentice | 0:8ee30e15ac7b | 468 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 469 | */ |
davidprentice | 0:8ee30e15ac7b | 470 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 471 | void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, |
davidprentice | 0:8ee30e15ac7b | 472 | uint8_t corners, int16_t delta, |
davidprentice | 0:8ee30e15ac7b | 473 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 474 | |
davidprentice | 0:8ee30e15ac7b | 475 | int16_t f = 1 - r; |
davidprentice | 0:8ee30e15ac7b | 476 | int16_t ddF_x = 1; |
davidprentice | 0:8ee30e15ac7b | 477 | int16_t ddF_y = -2 * r; |
davidprentice | 0:8ee30e15ac7b | 478 | int16_t x = 0; |
davidprentice | 0:8ee30e15ac7b | 479 | int16_t y = r; |
davidprentice | 0:8ee30e15ac7b | 480 | int16_t px = x; |
davidprentice | 0:8ee30e15ac7b | 481 | int16_t py = y; |
davidprentice | 0:8ee30e15ac7b | 482 | |
davidprentice | 0:8ee30e15ac7b | 483 | delta++; // Avoid some +1's in the loop |
davidprentice | 0:8ee30e15ac7b | 484 | |
davidprentice | 0:8ee30e15ac7b | 485 | while (x < y) { |
davidprentice | 0:8ee30e15ac7b | 486 | if (f >= 0) { |
davidprentice | 0:8ee30e15ac7b | 487 | y--; |
davidprentice | 0:8ee30e15ac7b | 488 | ddF_y += 2; |
davidprentice | 0:8ee30e15ac7b | 489 | f += ddF_y; |
davidprentice | 0:8ee30e15ac7b | 490 | } |
davidprentice | 0:8ee30e15ac7b | 491 | x++; |
davidprentice | 0:8ee30e15ac7b | 492 | ddF_x += 2; |
davidprentice | 0:8ee30e15ac7b | 493 | f += ddF_x; |
davidprentice | 0:8ee30e15ac7b | 494 | // These checks avoid double-drawing certain lines, important |
davidprentice | 0:8ee30e15ac7b | 495 | // for the SSD1306 library which has an INVERT drawing mode. |
davidprentice | 0:8ee30e15ac7b | 496 | if (x < (y + 1)) { |
davidprentice | 0:8ee30e15ac7b | 497 | if (corners & 1) |
davidprentice | 0:8ee30e15ac7b | 498 | writeFastVLine(x0 + x, y0 - y, 2 * y + delta, color); |
davidprentice | 0:8ee30e15ac7b | 499 | if (corners & 2) |
davidprentice | 0:8ee30e15ac7b | 500 | writeFastVLine(x0 - x, y0 - y, 2 * y + delta, color); |
davidprentice | 0:8ee30e15ac7b | 501 | } |
davidprentice | 0:8ee30e15ac7b | 502 | if (y != py) { |
davidprentice | 0:8ee30e15ac7b | 503 | if (corners & 1) |
davidprentice | 0:8ee30e15ac7b | 504 | writeFastVLine(x0 + py, y0 - px, 2 * px + delta, color); |
davidprentice | 0:8ee30e15ac7b | 505 | if (corners & 2) |
davidprentice | 0:8ee30e15ac7b | 506 | writeFastVLine(x0 - py, y0 - px, 2 * px + delta, color); |
davidprentice | 0:8ee30e15ac7b | 507 | py = y; |
davidprentice | 0:8ee30e15ac7b | 508 | } |
davidprentice | 0:8ee30e15ac7b | 509 | px = x; |
davidprentice | 0:8ee30e15ac7b | 510 | } |
davidprentice | 0:8ee30e15ac7b | 511 | } |
davidprentice | 0:8ee30e15ac7b | 512 | |
davidprentice | 0:8ee30e15ac7b | 513 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 514 | /*! |
davidprentice | 0:8ee30e15ac7b | 515 | @brief Draw a rectangle with no fill color |
davidprentice | 0:8ee30e15ac7b | 516 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 517 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 518 | @param w Width in pixels |
davidprentice | 0:8ee30e15ac7b | 519 | @param h Height in pixels |
davidprentice | 0:8ee30e15ac7b | 520 | @param color 16-bit 5-6-5 Color to draw with |
davidprentice | 0:8ee30e15ac7b | 521 | */ |
davidprentice | 0:8ee30e15ac7b | 522 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 523 | void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 524 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 525 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 526 | writeFastHLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 527 | writeFastHLine(x, y + h - 1, w, color); |
davidprentice | 0:8ee30e15ac7b | 528 | writeFastVLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 529 | writeFastVLine(x + w - 1, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 530 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 531 | } |
davidprentice | 0:8ee30e15ac7b | 532 | |
davidprentice | 0:8ee30e15ac7b | 533 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 534 | /*! |
davidprentice | 0:8ee30e15ac7b | 535 | @brief Draw a rounded rectangle with no fill color |
davidprentice | 0:8ee30e15ac7b | 536 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 537 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 538 | @param w Width in pixels |
davidprentice | 0:8ee30e15ac7b | 539 | @param h Height in pixels |
davidprentice | 0:8ee30e15ac7b | 540 | @param r Radius of corner rounding |
davidprentice | 0:8ee30e15ac7b | 541 | @param color 16-bit 5-6-5 Color to draw with |
davidprentice | 0:8ee30e15ac7b | 542 | */ |
davidprentice | 0:8ee30e15ac7b | 543 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 544 | void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 545 | int16_t r, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 546 | int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis |
davidprentice | 0:8ee30e15ac7b | 547 | if (r > max_radius) |
davidprentice | 0:8ee30e15ac7b | 548 | r = max_radius; |
davidprentice | 0:8ee30e15ac7b | 549 | // smarter version |
davidprentice | 0:8ee30e15ac7b | 550 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 551 | writeFastHLine(x + r, y, w - 2 * r, color); // Top |
davidprentice | 0:8ee30e15ac7b | 552 | writeFastHLine(x + r, y + h - 1, w - 2 * r, color); // Bottom |
davidprentice | 0:8ee30e15ac7b | 553 | writeFastVLine(x, y + r, h - 2 * r, color); // Left |
davidprentice | 0:8ee30e15ac7b | 554 | writeFastVLine(x + w - 1, y + r, h - 2 * r, color); // Right |
davidprentice | 0:8ee30e15ac7b | 555 | // draw four corners |
davidprentice | 0:8ee30e15ac7b | 556 | drawCircleHelper(x + r, y + r, r, 1, color); |
davidprentice | 0:8ee30e15ac7b | 557 | drawCircleHelper(x + w - r - 1, y + r, r, 2, color); |
davidprentice | 0:8ee30e15ac7b | 558 | drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color); |
davidprentice | 0:8ee30e15ac7b | 559 | drawCircleHelper(x + r, y + h - r - 1, r, 8, color); |
davidprentice | 0:8ee30e15ac7b | 560 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 561 | } |
davidprentice | 0:8ee30e15ac7b | 562 | |
davidprentice | 0:8ee30e15ac7b | 563 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 564 | /*! |
davidprentice | 0:8ee30e15ac7b | 565 | @brief Draw a rounded rectangle with fill color |
davidprentice | 0:8ee30e15ac7b | 566 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 567 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 568 | @param w Width in pixels |
davidprentice | 0:8ee30e15ac7b | 569 | @param h Height in pixels |
davidprentice | 0:8ee30e15ac7b | 570 | @param r Radius of corner rounding |
davidprentice | 0:8ee30e15ac7b | 571 | @param color 16-bit 5-6-5 Color to draw/fill with |
davidprentice | 0:8ee30e15ac7b | 572 | */ |
davidprentice | 0:8ee30e15ac7b | 573 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 574 | void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 575 | int16_t r, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 576 | int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis |
davidprentice | 0:8ee30e15ac7b | 577 | if (r > max_radius) |
davidprentice | 0:8ee30e15ac7b | 578 | r = max_radius; |
davidprentice | 0:8ee30e15ac7b | 579 | // smarter version |
davidprentice | 0:8ee30e15ac7b | 580 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 581 | writeFillRect(x + r, y, w - 2 * r, h, color); |
davidprentice | 0:8ee30e15ac7b | 582 | // draw four corners |
davidprentice | 0:8ee30e15ac7b | 583 | fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1, color); |
davidprentice | 0:8ee30e15ac7b | 584 | fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1, color); |
davidprentice | 0:8ee30e15ac7b | 585 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 586 | } |
davidprentice | 0:8ee30e15ac7b | 587 | |
davidprentice | 0:8ee30e15ac7b | 588 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 589 | /*! |
davidprentice | 0:8ee30e15ac7b | 590 | @brief Draw a triangle with no fill color |
davidprentice | 0:8ee30e15ac7b | 591 | @param x0 Vertex #0 x coordinate |
davidprentice | 0:8ee30e15ac7b | 592 | @param y0 Vertex #0 y coordinate |
davidprentice | 0:8ee30e15ac7b | 593 | @param x1 Vertex #1 x coordinate |
davidprentice | 0:8ee30e15ac7b | 594 | @param y1 Vertex #1 y coordinate |
davidprentice | 0:8ee30e15ac7b | 595 | @param x2 Vertex #2 x coordinate |
davidprentice | 0:8ee30e15ac7b | 596 | @param y2 Vertex #2 y coordinate |
davidprentice | 0:8ee30e15ac7b | 597 | @param color 16-bit 5-6-5 Color to draw with |
davidprentice | 0:8ee30e15ac7b | 598 | */ |
davidprentice | 0:8ee30e15ac7b | 599 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 600 | void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, |
davidprentice | 0:8ee30e15ac7b | 601 | int16_t x2, int16_t y2, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 602 | drawLine(x0, y0, x1, y1, color); |
davidprentice | 0:8ee30e15ac7b | 603 | drawLine(x1, y1, x2, y2, color); |
davidprentice | 0:8ee30e15ac7b | 604 | drawLine(x2, y2, x0, y0, color); |
davidprentice | 0:8ee30e15ac7b | 605 | } |
davidprentice | 0:8ee30e15ac7b | 606 | |
davidprentice | 0:8ee30e15ac7b | 607 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 608 | /*! |
davidprentice | 0:8ee30e15ac7b | 609 | @brief Draw a triangle with color-fill |
davidprentice | 0:8ee30e15ac7b | 610 | @param x0 Vertex #0 x coordinate |
davidprentice | 0:8ee30e15ac7b | 611 | @param y0 Vertex #0 y coordinate |
davidprentice | 0:8ee30e15ac7b | 612 | @param x1 Vertex #1 x coordinate |
davidprentice | 0:8ee30e15ac7b | 613 | @param y1 Vertex #1 y coordinate |
davidprentice | 0:8ee30e15ac7b | 614 | @param x2 Vertex #2 x coordinate |
davidprentice | 0:8ee30e15ac7b | 615 | @param y2 Vertex #2 y coordinate |
davidprentice | 0:8ee30e15ac7b | 616 | @param color 16-bit 5-6-5 Color to fill/draw with |
davidprentice | 0:8ee30e15ac7b | 617 | */ |
davidprentice | 0:8ee30e15ac7b | 618 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 619 | void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, |
davidprentice | 0:8ee30e15ac7b | 620 | int16_t x2, int16_t y2, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 621 | |
davidprentice | 0:8ee30e15ac7b | 622 | int16_t a, b, y, last; |
davidprentice | 0:8ee30e15ac7b | 623 | |
davidprentice | 0:8ee30e15ac7b | 624 | // Sort coordinates by Y order (y2 >= y1 >= y0) |
davidprentice | 0:8ee30e15ac7b | 625 | if (y0 > y1) { |
davidprentice | 0:8ee30e15ac7b | 626 | _swap_int16_t(y0, y1); |
davidprentice | 0:8ee30e15ac7b | 627 | _swap_int16_t(x0, x1); |
davidprentice | 0:8ee30e15ac7b | 628 | } |
davidprentice | 0:8ee30e15ac7b | 629 | if (y1 > y2) { |
davidprentice | 0:8ee30e15ac7b | 630 | _swap_int16_t(y2, y1); |
davidprentice | 0:8ee30e15ac7b | 631 | _swap_int16_t(x2, x1); |
davidprentice | 0:8ee30e15ac7b | 632 | } |
davidprentice | 0:8ee30e15ac7b | 633 | if (y0 > y1) { |
davidprentice | 0:8ee30e15ac7b | 634 | _swap_int16_t(y0, y1); |
davidprentice | 0:8ee30e15ac7b | 635 | _swap_int16_t(x0, x1); |
davidprentice | 0:8ee30e15ac7b | 636 | } |
davidprentice | 0:8ee30e15ac7b | 637 | |
davidprentice | 0:8ee30e15ac7b | 638 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 639 | if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing |
davidprentice | 0:8ee30e15ac7b | 640 | a = b = x0; |
davidprentice | 0:8ee30e15ac7b | 641 | if (x1 < a) |
davidprentice | 0:8ee30e15ac7b | 642 | a = x1; |
davidprentice | 0:8ee30e15ac7b | 643 | else if (x1 > b) |
davidprentice | 0:8ee30e15ac7b | 644 | b = x1; |
davidprentice | 0:8ee30e15ac7b | 645 | if (x2 < a) |
davidprentice | 0:8ee30e15ac7b | 646 | a = x2; |
davidprentice | 0:8ee30e15ac7b | 647 | else if (x2 > b) |
davidprentice | 0:8ee30e15ac7b | 648 | b = x2; |
davidprentice | 0:8ee30e15ac7b | 649 | writeFastHLine(a, y0, b - a + 1, color); |
davidprentice | 0:8ee30e15ac7b | 650 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 651 | return; |
davidprentice | 0:8ee30e15ac7b | 652 | } |
davidprentice | 0:8ee30e15ac7b | 653 | |
davidprentice | 0:8ee30e15ac7b | 654 | int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0, |
davidprentice | 0:8ee30e15ac7b | 655 | dx12 = x2 - x1, dy12 = y2 - y1; |
davidprentice | 0:8ee30e15ac7b | 656 | int32_t sa = 0, sb = 0; |
davidprentice | 0:8ee30e15ac7b | 657 | |
davidprentice | 0:8ee30e15ac7b | 658 | // For upper part of triangle, find scanline crossings for segments |
davidprentice | 0:8ee30e15ac7b | 659 | // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 |
davidprentice | 0:8ee30e15ac7b | 660 | // is included here (and second loop will be skipped, avoiding a /0 |
davidprentice | 0:8ee30e15ac7b | 661 | // error there), otherwise scanline y1 is skipped here and handled |
davidprentice | 0:8ee30e15ac7b | 662 | // in the second loop...which also avoids a /0 error here if y0=y1 |
davidprentice | 0:8ee30e15ac7b | 663 | // (flat-topped triangle). |
davidprentice | 0:8ee30e15ac7b | 664 | if (y1 == y2) |
davidprentice | 0:8ee30e15ac7b | 665 | last = y1; // Include y1 scanline |
davidprentice | 0:8ee30e15ac7b | 666 | else |
davidprentice | 0:8ee30e15ac7b | 667 | last = y1 - 1; // Skip it |
davidprentice | 0:8ee30e15ac7b | 668 | |
davidprentice | 0:8ee30e15ac7b | 669 | for (y = y0; y <= last; y++) { |
davidprentice | 0:8ee30e15ac7b | 670 | a = x0 + sa / dy01; |
davidprentice | 0:8ee30e15ac7b | 671 | b = x0 + sb / dy02; |
davidprentice | 0:8ee30e15ac7b | 672 | sa += dx01; |
davidprentice | 0:8ee30e15ac7b | 673 | sb += dx02; |
davidprentice | 0:8ee30e15ac7b | 674 | /* longhand: |
davidprentice | 0:8ee30e15ac7b | 675 | a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); |
davidprentice | 0:8ee30e15ac7b | 676 | b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); |
davidprentice | 0:8ee30e15ac7b | 677 | */ |
davidprentice | 0:8ee30e15ac7b | 678 | if (a > b) |
davidprentice | 0:8ee30e15ac7b | 679 | _swap_int16_t(a, b); |
davidprentice | 0:8ee30e15ac7b | 680 | writeFastHLine(a, y, b - a + 1, color); |
davidprentice | 0:8ee30e15ac7b | 681 | } |
davidprentice | 0:8ee30e15ac7b | 682 | |
davidprentice | 0:8ee30e15ac7b | 683 | // For lower part of triangle, find scanline crossings for segments |
davidprentice | 0:8ee30e15ac7b | 684 | // 0-2 and 1-2. This loop is skipped if y1=y2. |
davidprentice | 0:8ee30e15ac7b | 685 | sa = (int32_t)dx12 * (y - y1); |
davidprentice | 0:8ee30e15ac7b | 686 | sb = (int32_t)dx02 * (y - y0); |
davidprentice | 0:8ee30e15ac7b | 687 | for (; y <= y2; y++) { |
davidprentice | 0:8ee30e15ac7b | 688 | a = x1 + sa / dy12; |
davidprentice | 0:8ee30e15ac7b | 689 | b = x0 + sb / dy02; |
davidprentice | 0:8ee30e15ac7b | 690 | sa += dx12; |
davidprentice | 0:8ee30e15ac7b | 691 | sb += dx02; |
davidprentice | 0:8ee30e15ac7b | 692 | /* longhand: |
davidprentice | 0:8ee30e15ac7b | 693 | a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); |
davidprentice | 0:8ee30e15ac7b | 694 | b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); |
davidprentice | 0:8ee30e15ac7b | 695 | */ |
davidprentice | 0:8ee30e15ac7b | 696 | if (a > b) |
davidprentice | 0:8ee30e15ac7b | 697 | _swap_int16_t(a, b); |
davidprentice | 0:8ee30e15ac7b | 698 | writeFastHLine(a, y, b - a + 1, color); |
davidprentice | 0:8ee30e15ac7b | 699 | } |
davidprentice | 0:8ee30e15ac7b | 700 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 701 | } |
davidprentice | 0:8ee30e15ac7b | 702 | |
davidprentice | 0:8ee30e15ac7b | 703 | // BITMAP / XBITMAP / GRAYSCALE / RGB BITMAP FUNCTIONS --------------------- |
davidprentice | 0:8ee30e15ac7b | 704 | |
davidprentice | 0:8ee30e15ac7b | 705 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 706 | /*! |
davidprentice | 0:8ee30e15ac7b | 707 | @brief Draw a PROGMEM-resident 1-bit image at the specified (x,y) |
davidprentice | 0:8ee30e15ac7b | 708 | position, using the specified foreground color (unset bits are transparent). |
davidprentice | 0:8ee30e15ac7b | 709 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 710 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 711 | @param bitmap byte array with monochrome bitmap |
davidprentice | 0:8ee30e15ac7b | 712 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 713 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 714 | @param color 16-bit 5-6-5 Color to draw with |
davidprentice | 0:8ee30e15ac7b | 715 | */ |
davidprentice | 0:8ee30e15ac7b | 716 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 717 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], |
davidprentice | 0:8ee30e15ac7b | 718 | int16_t w, int16_t h, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 719 | |
davidprentice | 0:8ee30e15ac7b | 720 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
davidprentice | 0:8ee30e15ac7b | 721 | uint8_t byte = 0; |
davidprentice | 0:8ee30e15ac7b | 722 | |
davidprentice | 0:8ee30e15ac7b | 723 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 724 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 725 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 726 | if (i & 7) |
davidprentice | 0:8ee30e15ac7b | 727 | byte <<= 1; |
davidprentice | 0:8ee30e15ac7b | 728 | else |
davidprentice | 0:8ee30e15ac7b | 729 | byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]); |
davidprentice | 0:8ee30e15ac7b | 730 | if (byte & 0x80) |
davidprentice | 0:8ee30e15ac7b | 731 | writePixel(x + i, y, color); |
davidprentice | 0:8ee30e15ac7b | 732 | } |
davidprentice | 0:8ee30e15ac7b | 733 | } |
davidprentice | 0:8ee30e15ac7b | 734 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 735 | } |
davidprentice | 0:8ee30e15ac7b | 736 | |
davidprentice | 0:8ee30e15ac7b | 737 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 738 | /*! |
davidprentice | 0:8ee30e15ac7b | 739 | @brief Draw a PROGMEM-resident 1-bit image at the specified (x,y) |
davidprentice | 0:8ee30e15ac7b | 740 | position, using the specified foreground (for set bits) and background (unset |
davidprentice | 0:8ee30e15ac7b | 741 | bits) colors. |
davidprentice | 0:8ee30e15ac7b | 742 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 743 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 744 | @param bitmap byte array with monochrome bitmap |
davidprentice | 0:8ee30e15ac7b | 745 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 746 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 747 | @param color 16-bit 5-6-5 Color to draw pixels with |
davidprentice | 0:8ee30e15ac7b | 748 | @param bg 16-bit 5-6-5 Color to draw background with |
davidprentice | 0:8ee30e15ac7b | 749 | */ |
davidprentice | 0:8ee30e15ac7b | 750 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 751 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], |
davidprentice | 0:8ee30e15ac7b | 752 | int16_t w, int16_t h, uint16_t color, |
davidprentice | 0:8ee30e15ac7b | 753 | uint16_t bg) { |
davidprentice | 0:8ee30e15ac7b | 754 | |
davidprentice | 0:8ee30e15ac7b | 755 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
davidprentice | 0:8ee30e15ac7b | 756 | uint8_t byte = 0; |
davidprentice | 0:8ee30e15ac7b | 757 | |
davidprentice | 0:8ee30e15ac7b | 758 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 759 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 760 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 761 | if (i & 7) |
davidprentice | 0:8ee30e15ac7b | 762 | byte <<= 1; |
davidprentice | 0:8ee30e15ac7b | 763 | else |
davidprentice | 0:8ee30e15ac7b | 764 | byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]); |
davidprentice | 0:8ee30e15ac7b | 765 | writePixel(x + i, y, (byte & 0x80) ? color : bg); |
davidprentice | 0:8ee30e15ac7b | 766 | } |
davidprentice | 0:8ee30e15ac7b | 767 | } |
davidprentice | 0:8ee30e15ac7b | 768 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 769 | } |
davidprentice | 0:8ee30e15ac7b | 770 | |
davidprentice | 0:8ee30e15ac7b | 771 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 772 | /*! |
davidprentice | 0:8ee30e15ac7b | 773 | @brief Draw a RAM-resident 1-bit image at the specified (x,y) position, |
davidprentice | 0:8ee30e15ac7b | 774 | using the specified foreground color (unset bits are transparent). |
davidprentice | 0:8ee30e15ac7b | 775 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 776 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 777 | @param bitmap byte array with monochrome bitmap |
davidprentice | 0:8ee30e15ac7b | 778 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 779 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 780 | @param color 16-bit 5-6-5 Color to draw with |
davidprentice | 0:8ee30e15ac7b | 781 | */ |
davidprentice | 0:8ee30e15ac7b | 782 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 783 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 784 | int16_t h, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 785 | |
davidprentice | 0:8ee30e15ac7b | 786 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
davidprentice | 0:8ee30e15ac7b | 787 | uint8_t byte = 0; |
davidprentice | 0:8ee30e15ac7b | 788 | |
davidprentice | 0:8ee30e15ac7b | 789 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 790 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 791 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 792 | if (i & 7) |
davidprentice | 0:8ee30e15ac7b | 793 | byte <<= 1; |
davidprentice | 0:8ee30e15ac7b | 794 | else |
davidprentice | 0:8ee30e15ac7b | 795 | byte = bitmap[j * byteWidth + i / 8]; |
davidprentice | 0:8ee30e15ac7b | 796 | if (byte & 0x80) |
davidprentice | 0:8ee30e15ac7b | 797 | writePixel(x + i, y, color); |
davidprentice | 0:8ee30e15ac7b | 798 | } |
davidprentice | 0:8ee30e15ac7b | 799 | } |
davidprentice | 0:8ee30e15ac7b | 800 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 801 | } |
davidprentice | 0:8ee30e15ac7b | 802 | |
davidprentice | 0:8ee30e15ac7b | 803 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 804 | /*! |
davidprentice | 0:8ee30e15ac7b | 805 | @brief Draw a RAM-resident 1-bit image at the specified (x,y) position, |
davidprentice | 0:8ee30e15ac7b | 806 | using the specified foreground (for set bits) and background (unset bits) |
davidprentice | 0:8ee30e15ac7b | 807 | colors. |
davidprentice | 0:8ee30e15ac7b | 808 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 809 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 810 | @param bitmap byte array with monochrome bitmap |
davidprentice | 0:8ee30e15ac7b | 811 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 812 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 813 | @param color 16-bit 5-6-5 Color to draw pixels with |
davidprentice | 0:8ee30e15ac7b | 814 | @param bg 16-bit 5-6-5 Color to draw background with |
davidprentice | 0:8ee30e15ac7b | 815 | */ |
davidprentice | 0:8ee30e15ac7b | 816 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 817 | void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 818 | int16_t h, uint16_t color, uint16_t bg) { |
davidprentice | 0:8ee30e15ac7b | 819 | |
davidprentice | 0:8ee30e15ac7b | 820 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
davidprentice | 0:8ee30e15ac7b | 821 | uint8_t byte = 0; |
davidprentice | 0:8ee30e15ac7b | 822 | |
davidprentice | 0:8ee30e15ac7b | 823 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 824 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 825 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 826 | if (i & 7) |
davidprentice | 0:8ee30e15ac7b | 827 | byte <<= 1; |
davidprentice | 0:8ee30e15ac7b | 828 | else |
davidprentice | 0:8ee30e15ac7b | 829 | byte = bitmap[j * byteWidth + i / 8]; |
davidprentice | 0:8ee30e15ac7b | 830 | writePixel(x + i, y, (byte & 0x80) ? color : bg); |
davidprentice | 0:8ee30e15ac7b | 831 | } |
davidprentice | 0:8ee30e15ac7b | 832 | } |
davidprentice | 0:8ee30e15ac7b | 833 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 834 | } |
davidprentice | 0:8ee30e15ac7b | 835 | |
davidprentice | 0:8ee30e15ac7b | 836 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 837 | /*! |
davidprentice | 0:8ee30e15ac7b | 838 | @brief Draw PROGMEM-resident XBitMap Files (*.xbm), exported from GIMP. |
davidprentice | 0:8ee30e15ac7b | 839 | Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor. |
davidprentice | 0:8ee30e15ac7b | 840 | C Array can be directly used with this function. |
davidprentice | 0:8ee30e15ac7b | 841 | There is no RAM-resident version of this function; if generating bitmaps |
davidprentice | 0:8ee30e15ac7b | 842 | in RAM, use the format defined by drawBitmap() and call that instead. |
davidprentice | 0:8ee30e15ac7b | 843 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 844 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 845 | @param bitmap byte array with monochrome bitmap |
davidprentice | 0:8ee30e15ac7b | 846 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 847 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 848 | @param color 16-bit 5-6-5 Color to draw pixels with |
davidprentice | 0:8ee30e15ac7b | 849 | */ |
davidprentice | 0:8ee30e15ac7b | 850 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 851 | void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y, const uint8_t bitmap[], |
davidprentice | 0:8ee30e15ac7b | 852 | int16_t w, int16_t h, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 853 | |
davidprentice | 0:8ee30e15ac7b | 854 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte |
davidprentice | 0:8ee30e15ac7b | 855 | uint8_t byte = 0; |
davidprentice | 0:8ee30e15ac7b | 856 | |
davidprentice | 0:8ee30e15ac7b | 857 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 858 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 859 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 860 | if (i & 7) |
davidprentice | 0:8ee30e15ac7b | 861 | byte >>= 1; |
davidprentice | 0:8ee30e15ac7b | 862 | else |
davidprentice | 0:8ee30e15ac7b | 863 | byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]); |
davidprentice | 0:8ee30e15ac7b | 864 | // Nearly identical to drawBitmap(), only the bit order |
davidprentice | 0:8ee30e15ac7b | 865 | // is reversed here (left-to-right = LSB to MSB): |
davidprentice | 0:8ee30e15ac7b | 866 | if (byte & 0x01) |
davidprentice | 0:8ee30e15ac7b | 867 | writePixel(x + i, y, color); |
davidprentice | 0:8ee30e15ac7b | 868 | } |
davidprentice | 0:8ee30e15ac7b | 869 | } |
davidprentice | 0:8ee30e15ac7b | 870 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 871 | } |
davidprentice | 0:8ee30e15ac7b | 872 | |
davidprentice | 0:8ee30e15ac7b | 873 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 874 | /*! |
davidprentice | 0:8ee30e15ac7b | 875 | @brief Draw a PROGMEM-resident 8-bit image (grayscale) at the specified |
davidprentice | 0:8ee30e15ac7b | 876 | (x,y) pos. Specifically for 8-bit display devices such as IS31FL3731; no |
davidprentice | 0:8ee30e15ac7b | 877 | color reduction/expansion is performed. |
davidprentice | 0:8ee30e15ac7b | 878 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 879 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 880 | @param bitmap byte array with grayscale bitmap |
davidprentice | 0:8ee30e15ac7b | 881 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 882 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 883 | */ |
davidprentice | 0:8ee30e15ac7b | 884 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 885 | void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y, |
davidprentice | 0:8ee30e15ac7b | 886 | const uint8_t bitmap[], int16_t w, |
davidprentice | 0:8ee30e15ac7b | 887 | int16_t h) { |
davidprentice | 0:8ee30e15ac7b | 888 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 889 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 890 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 891 | writePixel(x + i, y, (uint8_t)pgm_read_byte(&bitmap[j * w + i])); |
davidprentice | 0:8ee30e15ac7b | 892 | } |
davidprentice | 0:8ee30e15ac7b | 893 | } |
davidprentice | 0:8ee30e15ac7b | 894 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 895 | } |
davidprentice | 0:8ee30e15ac7b | 896 | |
davidprentice | 0:8ee30e15ac7b | 897 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 898 | /*! |
davidprentice | 0:8ee30e15ac7b | 899 | @brief Draw a RAM-resident 8-bit image (grayscale) at the specified (x,y) |
davidprentice | 0:8ee30e15ac7b | 900 | pos. Specifically for 8-bit display devices such as IS31FL3731; no color |
davidprentice | 0:8ee30e15ac7b | 901 | reduction/expansion is performed. |
davidprentice | 0:8ee30e15ac7b | 902 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 903 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 904 | @param bitmap byte array with grayscale bitmap |
davidprentice | 0:8ee30e15ac7b | 905 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 906 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 907 | */ |
davidprentice | 0:8ee30e15ac7b | 908 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 909 | void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, |
davidprentice | 0:8ee30e15ac7b | 910 | int16_t w, int16_t h) { |
davidprentice | 0:8ee30e15ac7b | 911 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 912 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 913 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 914 | writePixel(x + i, y, bitmap[j * w + i]); |
davidprentice | 0:8ee30e15ac7b | 915 | } |
davidprentice | 0:8ee30e15ac7b | 916 | } |
davidprentice | 0:8ee30e15ac7b | 917 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 918 | } |
davidprentice | 0:8ee30e15ac7b | 919 | |
davidprentice | 0:8ee30e15ac7b | 920 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 921 | /*! |
davidprentice | 0:8ee30e15ac7b | 922 | @brief Draw a PROGMEM-resident 8-bit image (grayscale) with a 1-bit mask |
davidprentice | 0:8ee30e15ac7b | 923 | (set bits = opaque, unset bits = clear) at the specified (x,y) position. |
davidprentice | 0:8ee30e15ac7b | 924 | BOTH buffers (grayscale and mask) must be PROGMEM-resident. |
davidprentice | 0:8ee30e15ac7b | 925 | Specifically for 8-bit display devices such as IS31FL3731; no color |
davidprentice | 0:8ee30e15ac7b | 926 | reduction/expansion is performed. |
davidprentice | 0:8ee30e15ac7b | 927 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 928 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 929 | @param bitmap byte array with grayscale bitmap |
davidprentice | 0:8ee30e15ac7b | 930 | @param mask byte array with mask bitmap |
davidprentice | 0:8ee30e15ac7b | 931 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 932 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 933 | */ |
davidprentice | 0:8ee30e15ac7b | 934 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 935 | void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y, |
davidprentice | 0:8ee30e15ac7b | 936 | const uint8_t bitmap[], |
davidprentice | 0:8ee30e15ac7b | 937 | const uint8_t mask[], int16_t w, |
davidprentice | 0:8ee30e15ac7b | 938 | int16_t h) { |
davidprentice | 0:8ee30e15ac7b | 939 | int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte |
davidprentice | 0:8ee30e15ac7b | 940 | uint8_t byte = 0; |
davidprentice | 0:8ee30e15ac7b | 941 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 942 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 943 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 944 | if (i & 7) |
davidprentice | 0:8ee30e15ac7b | 945 | byte <<= 1; |
davidprentice | 0:8ee30e15ac7b | 946 | else |
davidprentice | 0:8ee30e15ac7b | 947 | byte = pgm_read_byte(&mask[j * bw + i / 8]); |
davidprentice | 0:8ee30e15ac7b | 948 | if (byte & 0x80) { |
davidprentice | 0:8ee30e15ac7b | 949 | writePixel(x + i, y, (uint8_t)pgm_read_byte(&bitmap[j * w + i])); |
davidprentice | 0:8ee30e15ac7b | 950 | } |
davidprentice | 0:8ee30e15ac7b | 951 | } |
davidprentice | 0:8ee30e15ac7b | 952 | } |
davidprentice | 0:8ee30e15ac7b | 953 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 954 | } |
davidprentice | 0:8ee30e15ac7b | 955 | |
davidprentice | 0:8ee30e15ac7b | 956 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 957 | /*! |
davidprentice | 0:8ee30e15ac7b | 958 | @brief Draw a RAM-resident 8-bit image (grayscale) with a 1-bit mask |
davidprentice | 0:8ee30e15ac7b | 959 | (set bits = opaque, unset bits = clear) at the specified (x,y) position. |
davidprentice | 0:8ee30e15ac7b | 960 | BOTH buffers (grayscale and mask) must be RAM-residentt, no mix-and-match |
davidprentice | 0:8ee30e15ac7b | 961 | Specifically for 8-bit display devices such as IS31FL3731; no color |
davidprentice | 0:8ee30e15ac7b | 962 | reduction/expansion is performed. |
davidprentice | 0:8ee30e15ac7b | 963 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 964 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 965 | @param bitmap byte array with grayscale bitmap |
davidprentice | 0:8ee30e15ac7b | 966 | @param mask byte array with mask bitmap |
davidprentice | 0:8ee30e15ac7b | 967 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 968 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 969 | */ |
davidprentice | 0:8ee30e15ac7b | 970 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 971 | void Adafruit_GFX::drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, |
davidprentice | 0:8ee30e15ac7b | 972 | uint8_t *mask, int16_t w, int16_t h) { |
davidprentice | 0:8ee30e15ac7b | 973 | int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte |
davidprentice | 0:8ee30e15ac7b | 974 | uint8_t byte = 0; |
davidprentice | 0:8ee30e15ac7b | 975 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 976 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 977 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 978 | if (i & 7) |
davidprentice | 0:8ee30e15ac7b | 979 | byte <<= 1; |
davidprentice | 0:8ee30e15ac7b | 980 | else |
davidprentice | 0:8ee30e15ac7b | 981 | byte = mask[j * bw + i / 8]; |
davidprentice | 0:8ee30e15ac7b | 982 | if (byte & 0x80) { |
davidprentice | 0:8ee30e15ac7b | 983 | writePixel(x + i, y, bitmap[j * w + i]); |
davidprentice | 0:8ee30e15ac7b | 984 | } |
davidprentice | 0:8ee30e15ac7b | 985 | } |
davidprentice | 0:8ee30e15ac7b | 986 | } |
davidprentice | 0:8ee30e15ac7b | 987 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 988 | } |
davidprentice | 0:8ee30e15ac7b | 989 | |
davidprentice | 0:8ee30e15ac7b | 990 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 991 | /*! |
davidprentice | 0:8ee30e15ac7b | 992 | @brief Draw a PROGMEM-resident 16-bit image (RGB 5/6/5) at the specified |
davidprentice | 0:8ee30e15ac7b | 993 | (x,y) position. For 16-bit display devices; no color reduction performed. |
davidprentice | 0:8ee30e15ac7b | 994 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 995 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 996 | @param bitmap byte array with 16-bit color bitmap |
davidprentice | 0:8ee30e15ac7b | 997 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 998 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 999 | */ |
davidprentice | 0:8ee30e15ac7b | 1000 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1001 | void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], |
davidprentice | 0:8ee30e15ac7b | 1002 | int16_t w, int16_t h) { |
davidprentice | 0:8ee30e15ac7b | 1003 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 1004 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 1005 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 1006 | writePixel(x + i, y, pgm_read_word(&bitmap[j * w + i])); |
davidprentice | 0:8ee30e15ac7b | 1007 | } |
davidprentice | 0:8ee30e15ac7b | 1008 | } |
davidprentice | 0:8ee30e15ac7b | 1009 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 1010 | } |
davidprentice | 0:8ee30e15ac7b | 1011 | |
davidprentice | 0:8ee30e15ac7b | 1012 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1013 | /*! |
davidprentice | 0:8ee30e15ac7b | 1014 | @brief Draw a RAM-resident 16-bit image (RGB 5/6/5) at the specified (x,y) |
davidprentice | 0:8ee30e15ac7b | 1015 | position. For 16-bit display devices; no color reduction performed. |
davidprentice | 0:8ee30e15ac7b | 1016 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 1017 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 1018 | @param bitmap byte array with 16-bit color bitmap |
davidprentice | 0:8ee30e15ac7b | 1019 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 1020 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 1021 | */ |
davidprentice | 0:8ee30e15ac7b | 1022 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1023 | void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, |
davidprentice | 0:8ee30e15ac7b | 1024 | int16_t w, int16_t h) { |
davidprentice | 0:8ee30e15ac7b | 1025 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 1026 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 1027 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 1028 | writePixel(x + i, y, bitmap[j * w + i]); |
davidprentice | 0:8ee30e15ac7b | 1029 | } |
davidprentice | 0:8ee30e15ac7b | 1030 | } |
davidprentice | 0:8ee30e15ac7b | 1031 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 1032 | } |
davidprentice | 0:8ee30e15ac7b | 1033 | |
davidprentice | 0:8ee30e15ac7b | 1034 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1035 | /*! |
davidprentice | 0:8ee30e15ac7b | 1036 | @brief Draw a PROGMEM-resident 16-bit image (RGB 5/6/5) with a 1-bit mask |
davidprentice | 0:8ee30e15ac7b | 1037 | (set bits = opaque, unset bits = clear) at the specified (x,y) position. BOTH |
davidprentice | 0:8ee30e15ac7b | 1038 | buffers (color and mask) must be PROGMEM-resident. For 16-bit display |
davidprentice | 0:8ee30e15ac7b | 1039 | devices; no color reduction performed. |
davidprentice | 0:8ee30e15ac7b | 1040 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 1041 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 1042 | @param bitmap byte array with 16-bit color bitmap |
davidprentice | 0:8ee30e15ac7b | 1043 | @param mask byte array with monochrome mask bitmap |
davidprentice | 0:8ee30e15ac7b | 1044 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 1045 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 1046 | */ |
davidprentice | 0:8ee30e15ac7b | 1047 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1048 | void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], |
davidprentice | 0:8ee30e15ac7b | 1049 | const uint8_t mask[], int16_t w, int16_t h) { |
davidprentice | 0:8ee30e15ac7b | 1050 | int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte |
davidprentice | 0:8ee30e15ac7b | 1051 | uint8_t byte = 0; |
davidprentice | 0:8ee30e15ac7b | 1052 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 1053 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 1054 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 1055 | if (i & 7) |
davidprentice | 0:8ee30e15ac7b | 1056 | byte <<= 1; |
davidprentice | 0:8ee30e15ac7b | 1057 | else |
davidprentice | 0:8ee30e15ac7b | 1058 | byte = pgm_read_byte(&mask[j * bw + i / 8]); |
davidprentice | 0:8ee30e15ac7b | 1059 | if (byte & 0x80) { |
davidprentice | 0:8ee30e15ac7b | 1060 | writePixel(x + i, y, pgm_read_word(&bitmap[j * w + i])); |
davidprentice | 0:8ee30e15ac7b | 1061 | } |
davidprentice | 0:8ee30e15ac7b | 1062 | } |
davidprentice | 0:8ee30e15ac7b | 1063 | } |
davidprentice | 0:8ee30e15ac7b | 1064 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 1065 | } |
davidprentice | 0:8ee30e15ac7b | 1066 | |
davidprentice | 0:8ee30e15ac7b | 1067 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1068 | /*! |
davidprentice | 0:8ee30e15ac7b | 1069 | @brief Draw a RAM-resident 16-bit image (RGB 5/6/5) with a 1-bit mask (set |
davidprentice | 0:8ee30e15ac7b | 1070 | bits = opaque, unset bits = clear) at the specified (x,y) position. BOTH |
davidprentice | 0:8ee30e15ac7b | 1071 | buffers (color and mask) must be RAM-resident. For 16-bit display devices; no |
davidprentice | 0:8ee30e15ac7b | 1072 | color reduction performed. |
davidprentice | 0:8ee30e15ac7b | 1073 | @param x Top left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 1074 | @param y Top left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 1075 | @param bitmap byte array with 16-bit color bitmap |
davidprentice | 0:8ee30e15ac7b | 1076 | @param mask byte array with monochrome mask bitmap |
davidprentice | 0:8ee30e15ac7b | 1077 | @param w Width of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 1078 | @param h Height of bitmap in pixels |
davidprentice | 0:8ee30e15ac7b | 1079 | */ |
davidprentice | 0:8ee30e15ac7b | 1080 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1081 | void Adafruit_GFX::drawRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, |
davidprentice | 0:8ee30e15ac7b | 1082 | uint8_t *mask, int16_t w, int16_t h) { |
davidprentice | 0:8ee30e15ac7b | 1083 | int16_t bw = (w + 7) / 8; // Bitmask scanline pad = whole byte |
davidprentice | 0:8ee30e15ac7b | 1084 | uint8_t byte = 0; |
davidprentice | 0:8ee30e15ac7b | 1085 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 1086 | for (int16_t j = 0; j < h; j++, y++) { |
davidprentice | 0:8ee30e15ac7b | 1087 | for (int16_t i = 0; i < w; i++) { |
davidprentice | 0:8ee30e15ac7b | 1088 | if (i & 7) |
davidprentice | 0:8ee30e15ac7b | 1089 | byte <<= 1; |
davidprentice | 0:8ee30e15ac7b | 1090 | else |
davidprentice | 0:8ee30e15ac7b | 1091 | byte = mask[j * bw + i / 8]; |
davidprentice | 0:8ee30e15ac7b | 1092 | if (byte & 0x80) { |
davidprentice | 0:8ee30e15ac7b | 1093 | writePixel(x + i, y, bitmap[j * w + i]); |
davidprentice | 0:8ee30e15ac7b | 1094 | } |
davidprentice | 0:8ee30e15ac7b | 1095 | } |
davidprentice | 0:8ee30e15ac7b | 1096 | } |
davidprentice | 0:8ee30e15ac7b | 1097 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 1098 | } |
davidprentice | 0:8ee30e15ac7b | 1099 | |
davidprentice | 0:8ee30e15ac7b | 1100 | // TEXT- AND CHARACTER-HANDLING FUNCTIONS ---------------------------------- |
davidprentice | 0:8ee30e15ac7b | 1101 | |
davidprentice | 0:8ee30e15ac7b | 1102 | // Draw a character |
davidprentice | 0:8ee30e15ac7b | 1103 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1104 | /*! |
davidprentice | 0:8ee30e15ac7b | 1105 | @brief Draw a single character |
davidprentice | 0:8ee30e15ac7b | 1106 | @param x Bottom left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 1107 | @param y Bottom left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 1108 | @param c The 8-bit font-indexed character (likely ascii) |
davidprentice | 0:8ee30e15ac7b | 1109 | @param color 16-bit 5-6-5 Color to draw chraracter with |
davidprentice | 0:8ee30e15ac7b | 1110 | @param bg 16-bit 5-6-5 Color to fill background with (if same as color, |
davidprentice | 0:8ee30e15ac7b | 1111 | no background) |
davidprentice | 0:8ee30e15ac7b | 1112 | @param size Font magnification level, 1 is 'original' size |
davidprentice | 0:8ee30e15ac7b | 1113 | */ |
davidprentice | 0:8ee30e15ac7b | 1114 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1115 | void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, |
davidprentice | 0:8ee30e15ac7b | 1116 | uint16_t color, uint16_t bg, uint8_t size) { |
davidprentice | 0:8ee30e15ac7b | 1117 | drawChar(x, y, c, color, bg, size, size); |
davidprentice | 0:8ee30e15ac7b | 1118 | } |
davidprentice | 0:8ee30e15ac7b | 1119 | |
davidprentice | 0:8ee30e15ac7b | 1120 | // Draw a character |
davidprentice | 0:8ee30e15ac7b | 1121 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1122 | /*! |
davidprentice | 0:8ee30e15ac7b | 1123 | @brief Draw a single character |
davidprentice | 0:8ee30e15ac7b | 1124 | @param x Bottom left corner x coordinate |
davidprentice | 0:8ee30e15ac7b | 1125 | @param y Bottom left corner y coordinate |
davidprentice | 0:8ee30e15ac7b | 1126 | @param c The 8-bit font-indexed character (likely ascii) |
davidprentice | 0:8ee30e15ac7b | 1127 | @param color 16-bit 5-6-5 Color to draw chraracter with |
davidprentice | 0:8ee30e15ac7b | 1128 | @param bg 16-bit 5-6-5 Color to fill background with (if same as color, |
davidprentice | 0:8ee30e15ac7b | 1129 | no background) |
davidprentice | 0:8ee30e15ac7b | 1130 | @param size_x Font magnification level in X-axis, 1 is 'original' size |
davidprentice | 0:8ee30e15ac7b | 1131 | @param size_y Font magnification level in Y-axis, 1 is 'original' size |
davidprentice | 0:8ee30e15ac7b | 1132 | */ |
davidprentice | 0:8ee30e15ac7b | 1133 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1134 | void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, |
davidprentice | 0:8ee30e15ac7b | 1135 | uint16_t color, uint16_t bg, uint8_t size_x, |
davidprentice | 0:8ee30e15ac7b | 1136 | uint8_t size_y) { |
davidprentice | 0:8ee30e15ac7b | 1137 | |
davidprentice | 0:8ee30e15ac7b | 1138 | if (!gfxFont) { // 'Classic' built-in font |
davidprentice | 0:8ee30e15ac7b | 1139 | |
davidprentice | 0:8ee30e15ac7b | 1140 | if ((x >= _width) || // Clip right |
davidprentice | 0:8ee30e15ac7b | 1141 | (y >= _height) || // Clip bottom |
davidprentice | 0:8ee30e15ac7b | 1142 | ((x + 6 * size_x - 1) < 0) || // Clip left |
davidprentice | 0:8ee30e15ac7b | 1143 | ((y + 8 * size_y - 1) < 0)) // Clip top |
davidprentice | 0:8ee30e15ac7b | 1144 | return; |
davidprentice | 0:8ee30e15ac7b | 1145 | |
davidprentice | 0:8ee30e15ac7b | 1146 | if (!_cp437 && (c >= 176)) |
davidprentice | 0:8ee30e15ac7b | 1147 | c++; // Handle 'classic' charset behavior |
davidprentice | 0:8ee30e15ac7b | 1148 | |
davidprentice | 0:8ee30e15ac7b | 1149 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 1150 | for (int8_t i = 0; i < 5; i++) { // Char bitmap = 5 columns |
davidprentice | 0:8ee30e15ac7b | 1151 | uint8_t line = pgm_read_byte(&font[c * 5 + i]); |
davidprentice | 0:8ee30e15ac7b | 1152 | for (int8_t j = 0; j < 8; j++, line >>= 1) { |
davidprentice | 0:8ee30e15ac7b | 1153 | if (line & 1) { |
davidprentice | 0:8ee30e15ac7b | 1154 | if (size_x == 1 && size_y == 1) |
davidprentice | 0:8ee30e15ac7b | 1155 | writePixel(x + i, y + j, color); |
davidprentice | 0:8ee30e15ac7b | 1156 | else |
davidprentice | 0:8ee30e15ac7b | 1157 | writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, |
davidprentice | 0:8ee30e15ac7b | 1158 | color); |
davidprentice | 0:8ee30e15ac7b | 1159 | } else if (bg != color) { |
davidprentice | 0:8ee30e15ac7b | 1160 | if (size_x == 1 && size_y == 1) |
davidprentice | 0:8ee30e15ac7b | 1161 | writePixel(x + i, y + j, bg); |
davidprentice | 0:8ee30e15ac7b | 1162 | else |
davidprentice | 0:8ee30e15ac7b | 1163 | writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, bg); |
davidprentice | 0:8ee30e15ac7b | 1164 | } |
davidprentice | 0:8ee30e15ac7b | 1165 | } |
davidprentice | 0:8ee30e15ac7b | 1166 | } |
davidprentice | 0:8ee30e15ac7b | 1167 | if (bg != color) { // If opaque, draw vertical line for last column |
davidprentice | 0:8ee30e15ac7b | 1168 | if (size_x == 1 && size_y == 1) |
davidprentice | 0:8ee30e15ac7b | 1169 | writeFastVLine(x + 5, y, 8, bg); |
davidprentice | 0:8ee30e15ac7b | 1170 | else |
davidprentice | 0:8ee30e15ac7b | 1171 | writeFillRect(x + 5 * size_x, y, size_x, 8 * size_y, bg); |
davidprentice | 0:8ee30e15ac7b | 1172 | } |
davidprentice | 0:8ee30e15ac7b | 1173 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 1174 | |
davidprentice | 0:8ee30e15ac7b | 1175 | } else { // Custom font |
davidprentice | 0:8ee30e15ac7b | 1176 | |
davidprentice | 0:8ee30e15ac7b | 1177 | // Character is assumed previously filtered by write() to eliminate |
davidprentice | 0:8ee30e15ac7b | 1178 | // newlines, returns, non-printable characters, etc. Calling |
davidprentice | 0:8ee30e15ac7b | 1179 | // drawChar() directly with 'bad' characters of font may cause mayhem! |
davidprentice | 0:8ee30e15ac7b | 1180 | |
davidprentice | 0:8ee30e15ac7b | 1181 | c -= (uint8_t)pgm_read_byte(&gfxFont->first); |
davidprentice | 0:8ee30e15ac7b | 1182 | GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c); |
davidprentice | 0:8ee30e15ac7b | 1183 | uint8_t *bitmap = pgm_read_bitmap_ptr(gfxFont); |
davidprentice | 0:8ee30e15ac7b | 1184 | |
davidprentice | 0:8ee30e15ac7b | 1185 | uint16_t bo = pgm_read_word(&glyph->bitmapOffset); |
davidprentice | 0:8ee30e15ac7b | 1186 | uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height); |
davidprentice | 0:8ee30e15ac7b | 1187 | int8_t xo = pgm_read_byte(&glyph->xOffset), |
davidprentice | 0:8ee30e15ac7b | 1188 | yo = pgm_read_byte(&glyph->yOffset); |
davidprentice | 0:8ee30e15ac7b | 1189 | uint8_t xx, yy, bits = 0, bit = 0; |
davidprentice | 0:8ee30e15ac7b | 1190 | int16_t xo16 = 0, yo16 = 0; |
davidprentice | 0:8ee30e15ac7b | 1191 | |
davidprentice | 0:8ee30e15ac7b | 1192 | if (size_x > 1 || size_y > 1) { |
davidprentice | 0:8ee30e15ac7b | 1193 | xo16 = xo; |
davidprentice | 0:8ee30e15ac7b | 1194 | yo16 = yo; |
davidprentice | 0:8ee30e15ac7b | 1195 | } |
davidprentice | 0:8ee30e15ac7b | 1196 | |
davidprentice | 0:8ee30e15ac7b | 1197 | // Todo: Add character clipping here |
davidprentice | 0:8ee30e15ac7b | 1198 | |
davidprentice | 0:8ee30e15ac7b | 1199 | // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS. |
davidprentice | 0:8ee30e15ac7b | 1200 | // THIS IS ON PURPOSE AND BY DESIGN. The background color feature |
davidprentice | 0:8ee30e15ac7b | 1201 | // has typically been used with the 'classic' font to overwrite old |
davidprentice | 0:8ee30e15ac7b | 1202 | // screen contents with new data. This ONLY works because the |
davidprentice | 0:8ee30e15ac7b | 1203 | // characters are a uniform size; it's not a sensible thing to do with |
davidprentice | 0:8ee30e15ac7b | 1204 | // proportionally-spaced fonts with glyphs of varying sizes (and that |
davidprentice | 0:8ee30e15ac7b | 1205 | // may overlap). To replace previously-drawn text when using a custom |
davidprentice | 0:8ee30e15ac7b | 1206 | // font, use the getTextBounds() function to determine the smallest |
davidprentice | 0:8ee30e15ac7b | 1207 | // rectangle encompassing a string, erase the area with fillRect(), |
davidprentice | 0:8ee30e15ac7b | 1208 | // then draw new text. This WILL infortunately 'blink' the text, but |
davidprentice | 0:8ee30e15ac7b | 1209 | // is unavoidable. Drawing 'background' pixels will NOT fix this, |
davidprentice | 0:8ee30e15ac7b | 1210 | // only creates a new set of problems. Have an idea to work around |
davidprentice | 0:8ee30e15ac7b | 1211 | // this (a canvas object type for MCUs that can afford the RAM and |
davidprentice | 0:8ee30e15ac7b | 1212 | // displays supporting setAddrWindow() and pushColors()), but haven't |
davidprentice | 0:8ee30e15ac7b | 1213 | // implemented this yet. |
davidprentice | 0:8ee30e15ac7b | 1214 | |
davidprentice | 0:8ee30e15ac7b | 1215 | startWrite(); |
davidprentice | 0:8ee30e15ac7b | 1216 | for (yy = 0; yy < h; yy++) { |
davidprentice | 0:8ee30e15ac7b | 1217 | for (xx = 0; xx < w; xx++) { |
davidprentice | 0:8ee30e15ac7b | 1218 | if (!(bit++ & 7)) { |
davidprentice | 0:8ee30e15ac7b | 1219 | bits = pgm_read_byte(&bitmap[bo++]); |
davidprentice | 0:8ee30e15ac7b | 1220 | } |
davidprentice | 0:8ee30e15ac7b | 1221 | if (bits & 0x80) { |
davidprentice | 0:8ee30e15ac7b | 1222 | if (size_x == 1 && size_y == 1) { |
davidprentice | 0:8ee30e15ac7b | 1223 | writePixel(x + xo + xx, y + yo + yy, color); |
davidprentice | 0:8ee30e15ac7b | 1224 | } else { |
davidprentice | 0:8ee30e15ac7b | 1225 | writeFillRect(x + (xo16 + xx) * size_x, y + (yo16 + yy) * size_y, |
davidprentice | 0:8ee30e15ac7b | 1226 | size_x, size_y, color); |
davidprentice | 0:8ee30e15ac7b | 1227 | } |
davidprentice | 0:8ee30e15ac7b | 1228 | } |
davidprentice | 0:8ee30e15ac7b | 1229 | bits <<= 1; |
davidprentice | 0:8ee30e15ac7b | 1230 | } |
davidprentice | 0:8ee30e15ac7b | 1231 | } |
davidprentice | 0:8ee30e15ac7b | 1232 | endWrite(); |
davidprentice | 0:8ee30e15ac7b | 1233 | |
davidprentice | 0:8ee30e15ac7b | 1234 | } // End classic vs custom font |
davidprentice | 0:8ee30e15ac7b | 1235 | } |
davidprentice | 0:8ee30e15ac7b | 1236 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1237 | /*! |
davidprentice | 0:8ee30e15ac7b | 1238 | @brief Print one byte/character of data, used to support print() |
davidprentice | 0:8ee30e15ac7b | 1239 | @param c The 8-bit ascii character to write |
davidprentice | 0:8ee30e15ac7b | 1240 | */ |
davidprentice | 0:8ee30e15ac7b | 1241 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1242 | size_t Adafruit_GFX::write(uint8_t c) { |
davidprentice | 0:8ee30e15ac7b | 1243 | if (!gfxFont) { // 'Classic' built-in font |
davidprentice | 0:8ee30e15ac7b | 1244 | |
davidprentice | 0:8ee30e15ac7b | 1245 | if (c == '\n') { // Newline? |
davidprentice | 0:8ee30e15ac7b | 1246 | cursor_x = 0; // Reset x to zero, |
davidprentice | 0:8ee30e15ac7b | 1247 | cursor_y += textsize_y * 8; // advance y one line |
davidprentice | 0:8ee30e15ac7b | 1248 | } else if (c != '\r') { // Ignore carriage returns |
davidprentice | 0:8ee30e15ac7b | 1249 | if (wrap && ((cursor_x + textsize_x * 6) > _width)) { // Off right? |
davidprentice | 0:8ee30e15ac7b | 1250 | cursor_x = 0; // Reset x to zero, |
davidprentice | 0:8ee30e15ac7b | 1251 | cursor_y += textsize_y * 8; // advance y one line |
davidprentice | 0:8ee30e15ac7b | 1252 | } |
davidprentice | 0:8ee30e15ac7b | 1253 | drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize_x, |
davidprentice | 0:8ee30e15ac7b | 1254 | textsize_y); |
davidprentice | 0:8ee30e15ac7b | 1255 | cursor_x += textsize_x * 6; // Advance x one char |
davidprentice | 0:8ee30e15ac7b | 1256 | } |
davidprentice | 0:8ee30e15ac7b | 1257 | |
davidprentice | 0:8ee30e15ac7b | 1258 | } else { // Custom font |
davidprentice | 0:8ee30e15ac7b | 1259 | |
davidprentice | 0:8ee30e15ac7b | 1260 | if (c == '\n') { |
davidprentice | 0:8ee30e15ac7b | 1261 | cursor_x = 0; |
davidprentice | 0:8ee30e15ac7b | 1262 | cursor_y += |
davidprentice | 0:8ee30e15ac7b | 1263 | (int16_t)textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
davidprentice | 0:8ee30e15ac7b | 1264 | } else if (c != '\r') { |
davidprentice | 0:8ee30e15ac7b | 1265 | uint8_t first = pgm_read_byte(&gfxFont->first); |
davidprentice | 0:8ee30e15ac7b | 1266 | if ((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) { |
davidprentice | 0:8ee30e15ac7b | 1267 | GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first); |
davidprentice | 0:8ee30e15ac7b | 1268 | uint8_t w = pgm_read_byte(&glyph->width), |
davidprentice | 0:8ee30e15ac7b | 1269 | h = pgm_read_byte(&glyph->height); |
davidprentice | 0:8ee30e15ac7b | 1270 | if ((w > 0) && (h > 0)) { // Is there an associated bitmap? |
davidprentice | 0:8ee30e15ac7b | 1271 | int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic |
davidprentice | 0:8ee30e15ac7b | 1272 | if (wrap && ((cursor_x + textsize_x * (xo + w)) > _width)) { |
davidprentice | 0:8ee30e15ac7b | 1273 | cursor_x = 0; |
davidprentice | 0:8ee30e15ac7b | 1274 | cursor_y += (int16_t)textsize_y * |
davidprentice | 0:8ee30e15ac7b | 1275 | (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
davidprentice | 0:8ee30e15ac7b | 1276 | } |
davidprentice | 0:8ee30e15ac7b | 1277 | drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize_x, |
davidprentice | 0:8ee30e15ac7b | 1278 | textsize_y); |
davidprentice | 0:8ee30e15ac7b | 1279 | } |
davidprentice | 0:8ee30e15ac7b | 1280 | cursor_x += |
davidprentice | 0:8ee30e15ac7b | 1281 | (uint8_t)pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize_x; |
davidprentice | 0:8ee30e15ac7b | 1282 | } |
davidprentice | 0:8ee30e15ac7b | 1283 | } |
davidprentice | 0:8ee30e15ac7b | 1284 | } |
davidprentice | 0:8ee30e15ac7b | 1285 | return 1; |
davidprentice | 0:8ee30e15ac7b | 1286 | } |
davidprentice | 0:8ee30e15ac7b | 1287 | |
davidprentice | 0:8ee30e15ac7b | 1288 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1289 | /*! |
davidprentice | 0:8ee30e15ac7b | 1290 | @brief Set text 'magnification' size. Each increase in s makes 1 pixel |
davidprentice | 0:8ee30e15ac7b | 1291 | that much bigger. |
davidprentice | 0:8ee30e15ac7b | 1292 | @param s Desired text size. 1 is default 6x8, 2 is 12x16, 3 is 18x24, etc |
davidprentice | 0:8ee30e15ac7b | 1293 | */ |
davidprentice | 0:8ee30e15ac7b | 1294 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1295 | void Adafruit_GFX::setTextSize(uint8_t s) { setTextSize(s, s); } |
davidprentice | 0:8ee30e15ac7b | 1296 | |
davidprentice | 0:8ee30e15ac7b | 1297 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1298 | /*! |
davidprentice | 0:8ee30e15ac7b | 1299 | @brief Set text 'magnification' size. Each increase in s makes 1 pixel |
davidprentice | 0:8ee30e15ac7b | 1300 | that much bigger. |
davidprentice | 0:8ee30e15ac7b | 1301 | @param s_x Desired text width magnification level in X-axis. 1 is default |
davidprentice | 0:8ee30e15ac7b | 1302 | @param s_y Desired text width magnification level in Y-axis. 1 is default |
davidprentice | 0:8ee30e15ac7b | 1303 | */ |
davidprentice | 0:8ee30e15ac7b | 1304 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1305 | void Adafruit_GFX::setTextSize(uint8_t s_x, uint8_t s_y) { |
davidprentice | 0:8ee30e15ac7b | 1306 | textsize_x = (s_x > 0) ? s_x : 1; |
davidprentice | 0:8ee30e15ac7b | 1307 | textsize_y = (s_y > 0) ? s_y : 1; |
davidprentice | 0:8ee30e15ac7b | 1308 | } |
davidprentice | 0:8ee30e15ac7b | 1309 | |
davidprentice | 0:8ee30e15ac7b | 1310 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1311 | /*! |
davidprentice | 0:8ee30e15ac7b | 1312 | @brief Set rotation setting for display |
davidprentice | 0:8ee30e15ac7b | 1313 | @param x 0 thru 3 corresponding to 4 cardinal rotations |
davidprentice | 0:8ee30e15ac7b | 1314 | */ |
davidprentice | 0:8ee30e15ac7b | 1315 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1316 | void Adafruit_GFX::setRotation(uint8_t x) { |
davidprentice | 0:8ee30e15ac7b | 1317 | rotation = (x & 3); |
davidprentice | 0:8ee30e15ac7b | 1318 | switch (rotation) { |
davidprentice | 0:8ee30e15ac7b | 1319 | case 0: |
davidprentice | 0:8ee30e15ac7b | 1320 | case 2: |
davidprentice | 0:8ee30e15ac7b | 1321 | _width = WIDTH; |
davidprentice | 0:8ee30e15ac7b | 1322 | _height = HEIGHT; |
davidprentice | 0:8ee30e15ac7b | 1323 | break; |
davidprentice | 0:8ee30e15ac7b | 1324 | case 1: |
davidprentice | 0:8ee30e15ac7b | 1325 | case 3: |
davidprentice | 0:8ee30e15ac7b | 1326 | _width = HEIGHT; |
davidprentice | 0:8ee30e15ac7b | 1327 | _height = WIDTH; |
davidprentice | 0:8ee30e15ac7b | 1328 | break; |
davidprentice | 0:8ee30e15ac7b | 1329 | } |
davidprentice | 0:8ee30e15ac7b | 1330 | } |
davidprentice | 0:8ee30e15ac7b | 1331 | |
davidprentice | 0:8ee30e15ac7b | 1332 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1333 | /*! |
davidprentice | 0:8ee30e15ac7b | 1334 | @brief Set the font to display when print()ing, either custom or default |
davidprentice | 0:8ee30e15ac7b | 1335 | @param f The GFXfont object, if NULL use built in 6x8 font |
davidprentice | 0:8ee30e15ac7b | 1336 | */ |
davidprentice | 0:8ee30e15ac7b | 1337 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1338 | void Adafruit_GFX::setFont(const GFXfont *f) { |
davidprentice | 0:8ee30e15ac7b | 1339 | if (f) { // Font struct pointer passed in? |
davidprentice | 0:8ee30e15ac7b | 1340 | if (!gfxFont) { // And no current font struct? |
davidprentice | 0:8ee30e15ac7b | 1341 | // Switching from classic to new font behavior. |
davidprentice | 0:8ee30e15ac7b | 1342 | // Move cursor pos down 6 pixels so it's on baseline. |
davidprentice | 0:8ee30e15ac7b | 1343 | cursor_y += 6; |
davidprentice | 0:8ee30e15ac7b | 1344 | } |
davidprentice | 0:8ee30e15ac7b | 1345 | } else if (gfxFont) { // NULL passed. Current font struct defined? |
davidprentice | 0:8ee30e15ac7b | 1346 | // Switching from new to classic font behavior. |
davidprentice | 0:8ee30e15ac7b | 1347 | // Move cursor pos up 6 pixels so it's at top-left of char. |
davidprentice | 0:8ee30e15ac7b | 1348 | cursor_y -= 6; |
davidprentice | 0:8ee30e15ac7b | 1349 | } |
davidprentice | 0:8ee30e15ac7b | 1350 | gfxFont = (GFXfont *)f; |
davidprentice | 0:8ee30e15ac7b | 1351 | } |
davidprentice | 0:8ee30e15ac7b | 1352 | |
davidprentice | 0:8ee30e15ac7b | 1353 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1354 | /*! |
davidprentice | 0:8ee30e15ac7b | 1355 | @brief Helper to determine size of a character with current font/size. |
davidprentice | 0:8ee30e15ac7b | 1356 | Broke this out as it's used by both the PROGMEM- and RAM-resident |
davidprentice | 0:8ee30e15ac7b | 1357 | getTextBounds() functions. |
davidprentice | 0:8ee30e15ac7b | 1358 | @param c The ASCII character in question |
davidprentice | 0:8ee30e15ac7b | 1359 | @param x Pointer to x location of character. Value is modified by |
davidprentice | 0:8ee30e15ac7b | 1360 | this function to advance to next character. |
davidprentice | 0:8ee30e15ac7b | 1361 | @param y Pointer to y location of character. Value is modified by |
davidprentice | 0:8ee30e15ac7b | 1362 | this function to advance to next character. |
davidprentice | 0:8ee30e15ac7b | 1363 | @param minx Pointer to minimum X coordinate, passed in to AND returned |
davidprentice | 0:8ee30e15ac7b | 1364 | by this function -- this is used to incrementally build a |
davidprentice | 0:8ee30e15ac7b | 1365 | bounding rectangle for a string. |
davidprentice | 0:8ee30e15ac7b | 1366 | @param miny Pointer to minimum Y coord, passed in AND returned. |
davidprentice | 0:8ee30e15ac7b | 1367 | @param maxx Pointer to maximum X coord, passed in AND returned. |
davidprentice | 0:8ee30e15ac7b | 1368 | @param maxy Pointer to maximum Y coord, passed in AND returned. |
davidprentice | 0:8ee30e15ac7b | 1369 | */ |
davidprentice | 0:8ee30e15ac7b | 1370 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1371 | void Adafruit_GFX::charBounds(unsigned char c, int16_t *x, int16_t *y, |
davidprentice | 0:8ee30e15ac7b | 1372 | int16_t *minx, int16_t *miny, int16_t *maxx, |
davidprentice | 0:8ee30e15ac7b | 1373 | int16_t *maxy) { |
davidprentice | 0:8ee30e15ac7b | 1374 | |
davidprentice | 0:8ee30e15ac7b | 1375 | if (gfxFont) { |
davidprentice | 0:8ee30e15ac7b | 1376 | |
davidprentice | 0:8ee30e15ac7b | 1377 | if (c == '\n') { // Newline? |
davidprentice | 0:8ee30e15ac7b | 1378 | *x = 0; // Reset x to zero, advance y by one line |
davidprentice | 0:8ee30e15ac7b | 1379 | *y += textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
davidprentice | 0:8ee30e15ac7b | 1380 | } else if (c != '\r') { // Not a carriage return; is normal char |
davidprentice | 0:8ee30e15ac7b | 1381 | uint8_t first = pgm_read_byte(&gfxFont->first), |
davidprentice | 0:8ee30e15ac7b | 1382 | last = pgm_read_byte(&gfxFont->last); |
davidprentice | 0:8ee30e15ac7b | 1383 | if ((c >= first) && (c <= last)) { // Char present in this font? |
davidprentice | 0:8ee30e15ac7b | 1384 | GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first); |
davidprentice | 0:8ee30e15ac7b | 1385 | uint8_t gw = pgm_read_byte(&glyph->width), |
davidprentice | 0:8ee30e15ac7b | 1386 | gh = pgm_read_byte(&glyph->height), |
davidprentice | 0:8ee30e15ac7b | 1387 | xa = pgm_read_byte(&glyph->xAdvance); |
davidprentice | 0:8ee30e15ac7b | 1388 | int8_t xo = pgm_read_byte(&glyph->xOffset), |
davidprentice | 0:8ee30e15ac7b | 1389 | yo = pgm_read_byte(&glyph->yOffset); |
davidprentice | 0:8ee30e15ac7b | 1390 | if (wrap && ((*x + (((int16_t)xo + gw) * textsize_x)) > _width)) { |
davidprentice | 0:8ee30e15ac7b | 1391 | *x = 0; // Reset x to zero, advance y by one line |
davidprentice | 0:8ee30e15ac7b | 1392 | *y += textsize_y * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); |
davidprentice | 0:8ee30e15ac7b | 1393 | } |
davidprentice | 0:8ee30e15ac7b | 1394 | int16_t tsx = (int16_t)textsize_x, tsy = (int16_t)textsize_y, |
davidprentice | 0:8ee30e15ac7b | 1395 | x1 = *x + xo * tsx, y1 = *y + yo * tsy, x2 = x1 + gw * tsx - 1, |
davidprentice | 0:8ee30e15ac7b | 1396 | y2 = y1 + gh * tsy - 1; |
davidprentice | 0:8ee30e15ac7b | 1397 | if (x1 < *minx) |
davidprentice | 0:8ee30e15ac7b | 1398 | *minx = x1; |
davidprentice | 0:8ee30e15ac7b | 1399 | if (y1 < *miny) |
davidprentice | 0:8ee30e15ac7b | 1400 | *miny = y1; |
davidprentice | 0:8ee30e15ac7b | 1401 | if (x2 > *maxx) |
davidprentice | 0:8ee30e15ac7b | 1402 | *maxx = x2; |
davidprentice | 0:8ee30e15ac7b | 1403 | if (y2 > *maxy) |
davidprentice | 0:8ee30e15ac7b | 1404 | *maxy = y2; |
davidprentice | 0:8ee30e15ac7b | 1405 | *x += xa * tsx; |
davidprentice | 0:8ee30e15ac7b | 1406 | } |
davidprentice | 0:8ee30e15ac7b | 1407 | } |
davidprentice | 0:8ee30e15ac7b | 1408 | |
davidprentice | 0:8ee30e15ac7b | 1409 | } else { // Default font |
davidprentice | 0:8ee30e15ac7b | 1410 | |
davidprentice | 0:8ee30e15ac7b | 1411 | if (c == '\n') { // Newline? |
davidprentice | 0:8ee30e15ac7b | 1412 | *x = 0; // Reset x to zero, |
davidprentice | 0:8ee30e15ac7b | 1413 | *y += textsize_y * 8; // advance y one line |
davidprentice | 0:8ee30e15ac7b | 1414 | // min/max x/y unchaged -- that waits for next 'normal' character |
davidprentice | 0:8ee30e15ac7b | 1415 | } else if (c != '\r') { // Normal char; ignore carriage returns |
davidprentice | 0:8ee30e15ac7b | 1416 | if (wrap && ((*x + textsize_x * 6) > _width)) { // Off right? |
davidprentice | 0:8ee30e15ac7b | 1417 | *x = 0; // Reset x to zero, |
davidprentice | 0:8ee30e15ac7b | 1418 | *y += textsize_y * 8; // advance y one line |
davidprentice | 0:8ee30e15ac7b | 1419 | } |
davidprentice | 0:8ee30e15ac7b | 1420 | int x2 = *x + textsize_x * 6 - 1, // Lower-right pixel of char |
davidprentice | 0:8ee30e15ac7b | 1421 | y2 = *y + textsize_y * 8 - 1; |
davidprentice | 0:8ee30e15ac7b | 1422 | if (x2 > *maxx) |
davidprentice | 0:8ee30e15ac7b | 1423 | *maxx = x2; // Track max x, y |
davidprentice | 0:8ee30e15ac7b | 1424 | if (y2 > *maxy) |
davidprentice | 0:8ee30e15ac7b | 1425 | *maxy = y2; |
davidprentice | 0:8ee30e15ac7b | 1426 | if (*x < *minx) |
davidprentice | 0:8ee30e15ac7b | 1427 | *minx = *x; // Track min x, y |
davidprentice | 0:8ee30e15ac7b | 1428 | if (*y < *miny) |
davidprentice | 0:8ee30e15ac7b | 1429 | *miny = *y; |
davidprentice | 0:8ee30e15ac7b | 1430 | *x += textsize_x * 6; // Advance x one char |
davidprentice | 0:8ee30e15ac7b | 1431 | } |
davidprentice | 0:8ee30e15ac7b | 1432 | } |
davidprentice | 0:8ee30e15ac7b | 1433 | } |
davidprentice | 0:8ee30e15ac7b | 1434 | |
davidprentice | 0:8ee30e15ac7b | 1435 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1436 | /*! |
davidprentice | 0:8ee30e15ac7b | 1437 | @brief Helper to determine size of a string with current font/size. |
davidprentice | 0:8ee30e15ac7b | 1438 | Pass string and a cursor position, returns UL corner and W,H. |
davidprentice | 0:8ee30e15ac7b | 1439 | @param str The ASCII string to measure |
davidprentice | 0:8ee30e15ac7b | 1440 | @param x The current cursor X |
davidprentice | 0:8ee30e15ac7b | 1441 | @param y The current cursor Y |
davidprentice | 0:8ee30e15ac7b | 1442 | @param x1 The boundary X coordinate, returned by function |
davidprentice | 0:8ee30e15ac7b | 1443 | @param y1 The boundary Y coordinate, returned by function |
davidprentice | 0:8ee30e15ac7b | 1444 | @param w The boundary width, returned by function |
davidprentice | 0:8ee30e15ac7b | 1445 | @param h The boundary height, returned by function |
davidprentice | 0:8ee30e15ac7b | 1446 | */ |
davidprentice | 0:8ee30e15ac7b | 1447 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1448 | void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y, |
davidprentice | 0:8ee30e15ac7b | 1449 | int16_t *x1, int16_t *y1, uint16_t *w, |
davidprentice | 0:8ee30e15ac7b | 1450 | uint16_t *h) { |
davidprentice | 0:8ee30e15ac7b | 1451 | |
davidprentice | 0:8ee30e15ac7b | 1452 | uint8_t c; // Current character |
davidprentice | 0:8ee30e15ac7b | 1453 | int16_t minx = 0x7FFF, miny = 0x7FFF, maxx = -1, maxy = -1; // Bound rect |
davidprentice | 0:8ee30e15ac7b | 1454 | // Bound rect is intentionally initialized inverted, so 1st char sets it |
davidprentice | 0:8ee30e15ac7b | 1455 | |
davidprentice | 0:8ee30e15ac7b | 1456 | *x1 = x; // Initial position is value passed in |
davidprentice | 0:8ee30e15ac7b | 1457 | *y1 = y; |
davidprentice | 0:8ee30e15ac7b | 1458 | *w = *h = 0; // Initial size is zero |
davidprentice | 0:8ee30e15ac7b | 1459 | |
davidprentice | 0:8ee30e15ac7b | 1460 | while ((c = *str++)) { |
davidprentice | 0:8ee30e15ac7b | 1461 | // charBounds() modifies x/y to advance for each character, |
davidprentice | 0:8ee30e15ac7b | 1462 | // and min/max x/y are updated to incrementally build bounding rect. |
davidprentice | 0:8ee30e15ac7b | 1463 | charBounds(c, &x, &y, &minx, &miny, &maxx, &maxy); |
davidprentice | 0:8ee30e15ac7b | 1464 | } |
davidprentice | 0:8ee30e15ac7b | 1465 | |
davidprentice | 0:8ee30e15ac7b | 1466 | if (maxx >= minx) { // If legit string bounds were found... |
davidprentice | 0:8ee30e15ac7b | 1467 | *x1 = minx; // Update x1 to least X coord, |
davidprentice | 0:8ee30e15ac7b | 1468 | *w = maxx - minx + 1; // And w to bound rect width |
davidprentice | 0:8ee30e15ac7b | 1469 | } |
davidprentice | 0:8ee30e15ac7b | 1470 | if (maxy >= miny) { // Same for height |
davidprentice | 0:8ee30e15ac7b | 1471 | *y1 = miny; |
davidprentice | 0:8ee30e15ac7b | 1472 | *h = maxy - miny + 1; |
davidprentice | 0:8ee30e15ac7b | 1473 | } |
davidprentice | 0:8ee30e15ac7b | 1474 | } |
davidprentice | 0:8ee30e15ac7b | 1475 | |
davidprentice | 0:8ee30e15ac7b | 1476 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1477 | /*! |
davidprentice | 0:8ee30e15ac7b | 1478 | @brief Helper to determine size of a string with current font/size. Pass |
davidprentice | 0:8ee30e15ac7b | 1479 | string and a cursor position, returns UL corner and W,H. |
davidprentice | 0:8ee30e15ac7b | 1480 | @param str The ascii string to measure (as an arduino String() class) |
davidprentice | 0:8ee30e15ac7b | 1481 | @param x The current cursor X |
davidprentice | 0:8ee30e15ac7b | 1482 | @param y The current cursor Y |
davidprentice | 0:8ee30e15ac7b | 1483 | @param x1 The boundary X coordinate, set by function |
davidprentice | 0:8ee30e15ac7b | 1484 | @param y1 The boundary Y coordinate, set by function |
davidprentice | 0:8ee30e15ac7b | 1485 | @param w The boundary width, set by function |
davidprentice | 0:8ee30e15ac7b | 1486 | @param h The boundary height, set by function |
davidprentice | 0:8ee30e15ac7b | 1487 | */ |
davidprentice | 0:8ee30e15ac7b | 1488 | #if defined(USE_STRING) |
davidprentice | 0:8ee30e15ac7b | 1489 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1490 | void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y, |
davidprentice | 0:8ee30e15ac7b | 1491 | int16_t *x1, int16_t *y1, uint16_t *w, |
davidprentice | 0:8ee30e15ac7b | 1492 | uint16_t *h) { |
davidprentice | 0:8ee30e15ac7b | 1493 | if (str.length() != 0) { |
davidprentice | 0:8ee30e15ac7b | 1494 | getTextBounds(const_cast<char *>(str.c_str()), x, y, x1, y1, w, h); |
davidprentice | 0:8ee30e15ac7b | 1495 | } |
davidprentice | 0:8ee30e15ac7b | 1496 | } |
davidprentice | 0:8ee30e15ac7b | 1497 | |
davidprentice | 0:8ee30e15ac7b | 1498 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1499 | /*! |
davidprentice | 0:8ee30e15ac7b | 1500 | @brief Helper to determine size of a PROGMEM string with current |
davidprentice | 0:8ee30e15ac7b | 1501 | font/size. Pass string and a cursor position, returns UL corner and W,H. |
davidprentice | 0:8ee30e15ac7b | 1502 | @param str The flash-memory ascii string to measure |
davidprentice | 0:8ee30e15ac7b | 1503 | @param x The current cursor X |
davidprentice | 0:8ee30e15ac7b | 1504 | @param y The current cursor Y |
davidprentice | 0:8ee30e15ac7b | 1505 | @param x1 The boundary X coordinate, set by function |
davidprentice | 0:8ee30e15ac7b | 1506 | @param y1 The boundary Y coordinate, set by function |
davidprentice | 0:8ee30e15ac7b | 1507 | @param w The boundary width, set by function |
davidprentice | 0:8ee30e15ac7b | 1508 | @param h The boundary height, set by function |
davidprentice | 0:8ee30e15ac7b | 1509 | */ |
davidprentice | 0:8ee30e15ac7b | 1510 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1511 | void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str, int16_t x, |
davidprentice | 0:8ee30e15ac7b | 1512 | int16_t y, int16_t *x1, int16_t *y1, |
davidprentice | 0:8ee30e15ac7b | 1513 | uint16_t *w, uint16_t *h) { |
davidprentice | 0:8ee30e15ac7b | 1514 | uint8_t *s = (uint8_t *)str, c; |
davidprentice | 0:8ee30e15ac7b | 1515 | |
davidprentice | 0:8ee30e15ac7b | 1516 | *x1 = x; |
davidprentice | 0:8ee30e15ac7b | 1517 | *y1 = y; |
davidprentice | 0:8ee30e15ac7b | 1518 | *w = *h = 0; |
davidprentice | 0:8ee30e15ac7b | 1519 | |
davidprentice | 0:8ee30e15ac7b | 1520 | int16_t minx = _width, miny = _height, maxx = -1, maxy = -1; |
davidprentice | 0:8ee30e15ac7b | 1521 | |
davidprentice | 0:8ee30e15ac7b | 1522 | while ((c = pgm_read_byte(s++))) |
davidprentice | 0:8ee30e15ac7b | 1523 | charBounds(c, &x, &y, &minx, &miny, &maxx, &maxy); |
davidprentice | 0:8ee30e15ac7b | 1524 | |
davidprentice | 0:8ee30e15ac7b | 1525 | if (maxx >= minx) { |
davidprentice | 0:8ee30e15ac7b | 1526 | *x1 = minx; |
davidprentice | 0:8ee30e15ac7b | 1527 | *w = maxx - minx + 1; |
davidprentice | 0:8ee30e15ac7b | 1528 | } |
davidprentice | 0:8ee30e15ac7b | 1529 | if (maxy >= miny) { |
davidprentice | 0:8ee30e15ac7b | 1530 | *y1 = miny; |
davidprentice | 0:8ee30e15ac7b | 1531 | *h = maxy - miny + 1; |
davidprentice | 0:8ee30e15ac7b | 1532 | } |
davidprentice | 0:8ee30e15ac7b | 1533 | } |
davidprentice | 0:8ee30e15ac7b | 1534 | #endif |
davidprentice | 0:8ee30e15ac7b | 1535 | |
davidprentice | 0:8ee30e15ac7b | 1536 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1537 | /*! |
davidprentice | 0:8ee30e15ac7b | 1538 | @brief Invert the display (ideally using built-in hardware command) |
davidprentice | 0:8ee30e15ac7b | 1539 | @param i True if you want to invert, false to make 'normal' |
davidprentice | 0:8ee30e15ac7b | 1540 | */ |
davidprentice | 0:8ee30e15ac7b | 1541 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1542 | void Adafruit_GFX::invertDisplay(bool i) { |
davidprentice | 0:8ee30e15ac7b | 1543 | // Do nothing, must be subclassed if supported by hardware |
davidprentice | 0:8ee30e15ac7b | 1544 | (void)i; // disable -Wunused-parameter warning |
davidprentice | 0:8ee30e15ac7b | 1545 | } |
davidprentice | 0:8ee30e15ac7b | 1546 | |
davidprentice | 0:8ee30e15ac7b | 1547 | /***************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1548 | |
davidprentice | 0:8ee30e15ac7b | 1549 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1550 | /*! |
davidprentice | 0:8ee30e15ac7b | 1551 | @brief Create a simple drawn button UI element |
davidprentice | 0:8ee30e15ac7b | 1552 | */ |
davidprentice | 0:8ee30e15ac7b | 1553 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1554 | Adafruit_GFX_Button::Adafruit_GFX_Button(void) { _gfx = 0; } |
davidprentice | 0:8ee30e15ac7b | 1555 | |
davidprentice | 0:8ee30e15ac7b | 1556 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1557 | /*! |
davidprentice | 0:8ee30e15ac7b | 1558 | @brief Initialize button with our desired color/size/settings |
davidprentice | 0:8ee30e15ac7b | 1559 | @param gfx Pointer to our display so we can draw to it! |
davidprentice | 0:8ee30e15ac7b | 1560 | @param x The X coordinate of the center of the button |
davidprentice | 0:8ee30e15ac7b | 1561 | @param y The Y coordinate of the center of the button |
davidprentice | 0:8ee30e15ac7b | 1562 | @param w Width of the buttton |
davidprentice | 0:8ee30e15ac7b | 1563 | @param h Height of the buttton |
davidprentice | 0:8ee30e15ac7b | 1564 | @param outline Color of the outline (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1565 | @param fill Color of the button fill (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1566 | @param textcolor Color of the button label (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1567 | @param label Ascii string of the text inside the button |
davidprentice | 0:8ee30e15ac7b | 1568 | @param textsize The font magnification of the label text |
davidprentice | 0:8ee30e15ac7b | 1569 | */ |
davidprentice | 0:8ee30e15ac7b | 1570 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1571 | // Classic initButton() function: pass center & size |
davidprentice | 0:8ee30e15ac7b | 1572 | void Adafruit_GFX_Button::initButton(Adafruit_GFX *gfx, int16_t x, int16_t y, |
davidprentice | 0:8ee30e15ac7b | 1573 | uint16_t w, uint16_t h, uint16_t outline, |
davidprentice | 0:8ee30e15ac7b | 1574 | uint16_t fill, uint16_t textcolor, |
davidprentice | 0:8ee30e15ac7b | 1575 | char *label, uint8_t textsize) { |
davidprentice | 0:8ee30e15ac7b | 1576 | // Tweak arguments and pass to the newer initButtonUL() function... |
davidprentice | 0:8ee30e15ac7b | 1577 | initButtonUL(gfx, x - (w / 2), y - (h / 2), w, h, outline, fill, textcolor, |
davidprentice | 0:8ee30e15ac7b | 1578 | label, textsize); |
davidprentice | 0:8ee30e15ac7b | 1579 | } |
davidprentice | 0:8ee30e15ac7b | 1580 | |
davidprentice | 0:8ee30e15ac7b | 1581 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1582 | /*! |
davidprentice | 0:8ee30e15ac7b | 1583 | @brief Initialize button with our desired color/size/settings |
davidprentice | 0:8ee30e15ac7b | 1584 | @param gfx Pointer to our display so we can draw to it! |
davidprentice | 0:8ee30e15ac7b | 1585 | @param x The X coordinate of the center of the button |
davidprentice | 0:8ee30e15ac7b | 1586 | @param y The Y coordinate of the center of the button |
davidprentice | 0:8ee30e15ac7b | 1587 | @param w Width of the buttton |
davidprentice | 0:8ee30e15ac7b | 1588 | @param h Height of the buttton |
davidprentice | 0:8ee30e15ac7b | 1589 | @param outline Color of the outline (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1590 | @param fill Color of the button fill (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1591 | @param textcolor Color of the button label (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1592 | @param label Ascii string of the text inside the button |
davidprentice | 0:8ee30e15ac7b | 1593 | @param textsize_x The font magnification in X-axis of the label text |
davidprentice | 0:8ee30e15ac7b | 1594 | @param textsize_y The font magnification in Y-axis of the label text |
davidprentice | 0:8ee30e15ac7b | 1595 | */ |
davidprentice | 0:8ee30e15ac7b | 1596 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1597 | // Classic initButton() function: pass center & size |
davidprentice | 0:8ee30e15ac7b | 1598 | void Adafruit_GFX_Button::initButton(Adafruit_GFX *gfx, int16_t x, int16_t y, |
davidprentice | 0:8ee30e15ac7b | 1599 | uint16_t w, uint16_t h, uint16_t outline, |
davidprentice | 0:8ee30e15ac7b | 1600 | uint16_t fill, uint16_t textcolor, |
davidprentice | 0:8ee30e15ac7b | 1601 | char *label, uint8_t textsize_x, |
davidprentice | 0:8ee30e15ac7b | 1602 | uint8_t textsize_y) { |
davidprentice | 0:8ee30e15ac7b | 1603 | // Tweak arguments and pass to the newer initButtonUL() function... |
davidprentice | 0:8ee30e15ac7b | 1604 | initButtonUL(gfx, x - (w / 2), y - (h / 2), w, h, outline, fill, textcolor, |
davidprentice | 0:8ee30e15ac7b | 1605 | label, textsize_x, textsize_y); |
davidprentice | 0:8ee30e15ac7b | 1606 | } |
davidprentice | 0:8ee30e15ac7b | 1607 | |
davidprentice | 0:8ee30e15ac7b | 1608 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1609 | /*! |
davidprentice | 0:8ee30e15ac7b | 1610 | @brief Initialize button with our desired color/size/settings, with |
davidprentice | 0:8ee30e15ac7b | 1611 | upper-left coordinates |
davidprentice | 0:8ee30e15ac7b | 1612 | @param gfx Pointer to our display so we can draw to it! |
davidprentice | 0:8ee30e15ac7b | 1613 | @param x1 The X coordinate of the Upper-Left corner of the button |
davidprentice | 0:8ee30e15ac7b | 1614 | @param y1 The Y coordinate of the Upper-Left corner of the button |
davidprentice | 0:8ee30e15ac7b | 1615 | @param w Width of the buttton |
davidprentice | 0:8ee30e15ac7b | 1616 | @param h Height of the buttton |
davidprentice | 0:8ee30e15ac7b | 1617 | @param outline Color of the outline (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1618 | @param fill Color of the button fill (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1619 | @param textcolor Color of the button label (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1620 | @param label Ascii string of the text inside the button |
davidprentice | 0:8ee30e15ac7b | 1621 | @param textsize The font magnification of the label text |
davidprentice | 0:8ee30e15ac7b | 1622 | */ |
davidprentice | 0:8ee30e15ac7b | 1623 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1624 | void Adafruit_GFX_Button::initButtonUL(Adafruit_GFX *gfx, int16_t x1, |
davidprentice | 0:8ee30e15ac7b | 1625 | int16_t y1, uint16_t w, uint16_t h, |
davidprentice | 0:8ee30e15ac7b | 1626 | uint16_t outline, uint16_t fill, |
davidprentice | 0:8ee30e15ac7b | 1627 | uint16_t textcolor, char *label, |
davidprentice | 0:8ee30e15ac7b | 1628 | uint8_t textsize) { |
davidprentice | 0:8ee30e15ac7b | 1629 | initButtonUL(gfx, x1, y1, w, h, outline, fill, textcolor, label, textsize, |
davidprentice | 0:8ee30e15ac7b | 1630 | textsize); |
davidprentice | 0:8ee30e15ac7b | 1631 | } |
davidprentice | 0:8ee30e15ac7b | 1632 | |
davidprentice | 0:8ee30e15ac7b | 1633 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1634 | /*! |
davidprentice | 0:8ee30e15ac7b | 1635 | @brief Initialize button with our desired color/size/settings, with |
davidprentice | 0:8ee30e15ac7b | 1636 | upper-left coordinates |
davidprentice | 0:8ee30e15ac7b | 1637 | @param gfx Pointer to our display so we can draw to it! |
davidprentice | 0:8ee30e15ac7b | 1638 | @param x1 The X coordinate of the Upper-Left corner of the button |
davidprentice | 0:8ee30e15ac7b | 1639 | @param y1 The Y coordinate of the Upper-Left corner of the button |
davidprentice | 0:8ee30e15ac7b | 1640 | @param w Width of the buttton |
davidprentice | 0:8ee30e15ac7b | 1641 | @param h Height of the buttton |
davidprentice | 0:8ee30e15ac7b | 1642 | @param outline Color of the outline (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1643 | @param fill Color of the button fill (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1644 | @param textcolor Color of the button label (16-bit 5-6-5 standard) |
davidprentice | 0:8ee30e15ac7b | 1645 | @param label Ascii string of the text inside the button |
davidprentice | 0:8ee30e15ac7b | 1646 | @param textsize_x The font magnification in X-axis of the label text |
davidprentice | 0:8ee30e15ac7b | 1647 | @param textsize_y The font magnification in Y-axis of the label text |
davidprentice | 0:8ee30e15ac7b | 1648 | */ |
davidprentice | 0:8ee30e15ac7b | 1649 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1650 | void Adafruit_GFX_Button::initButtonUL(Adafruit_GFX *gfx, int16_t x1, |
davidprentice | 0:8ee30e15ac7b | 1651 | int16_t y1, uint16_t w, uint16_t h, |
davidprentice | 0:8ee30e15ac7b | 1652 | uint16_t outline, uint16_t fill, |
davidprentice | 0:8ee30e15ac7b | 1653 | uint16_t textcolor, char *label, |
davidprentice | 0:8ee30e15ac7b | 1654 | uint8_t textsize_x, uint8_t textsize_y) { |
davidprentice | 0:8ee30e15ac7b | 1655 | _x1 = x1; |
davidprentice | 0:8ee30e15ac7b | 1656 | _y1 = y1; |
davidprentice | 0:8ee30e15ac7b | 1657 | _w = w; |
davidprentice | 0:8ee30e15ac7b | 1658 | _h = h; |
davidprentice | 0:8ee30e15ac7b | 1659 | _outlinecolor = outline; |
davidprentice | 0:8ee30e15ac7b | 1660 | _fillcolor = fill; |
davidprentice | 0:8ee30e15ac7b | 1661 | _textcolor = textcolor; |
davidprentice | 0:8ee30e15ac7b | 1662 | _textsize_x = textsize_x; |
davidprentice | 0:8ee30e15ac7b | 1663 | _textsize_y = textsize_y; |
davidprentice | 0:8ee30e15ac7b | 1664 | _gfx = gfx; |
davidprentice | 0:8ee30e15ac7b | 1665 | strncpy(_label, label, 9); |
davidprentice | 0:8ee30e15ac7b | 1666 | } |
davidprentice | 0:8ee30e15ac7b | 1667 | |
davidprentice | 0:8ee30e15ac7b | 1668 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1669 | /*! |
davidprentice | 0:8ee30e15ac7b | 1670 | @brief Draw the button on the screen |
davidprentice | 0:8ee30e15ac7b | 1671 | @param inverted Whether to draw with fill/text swapped to indicate |
davidprentice | 0:8ee30e15ac7b | 1672 | 'pressed' |
davidprentice | 0:8ee30e15ac7b | 1673 | */ |
davidprentice | 0:8ee30e15ac7b | 1674 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1675 | void Adafruit_GFX_Button::drawButton(bool inverted) { |
davidprentice | 0:8ee30e15ac7b | 1676 | uint16_t fill, outline, text; |
davidprentice | 0:8ee30e15ac7b | 1677 | |
davidprentice | 0:8ee30e15ac7b | 1678 | if (!inverted) { |
davidprentice | 0:8ee30e15ac7b | 1679 | fill = _fillcolor; |
davidprentice | 0:8ee30e15ac7b | 1680 | outline = _outlinecolor; |
davidprentice | 0:8ee30e15ac7b | 1681 | text = _textcolor; |
davidprentice | 0:8ee30e15ac7b | 1682 | } else { |
davidprentice | 0:8ee30e15ac7b | 1683 | fill = _textcolor; |
davidprentice | 0:8ee30e15ac7b | 1684 | outline = _outlinecolor; |
davidprentice | 0:8ee30e15ac7b | 1685 | text = _fillcolor; |
davidprentice | 0:8ee30e15ac7b | 1686 | } |
davidprentice | 0:8ee30e15ac7b | 1687 | |
davidprentice | 0:8ee30e15ac7b | 1688 | uint8_t r = min(_w, _h) / 4; // Corner radius |
davidprentice | 0:8ee30e15ac7b | 1689 | _gfx->fillRoundRect(_x1, _y1, _w, _h, r, fill); |
davidprentice | 0:8ee30e15ac7b | 1690 | _gfx->drawRoundRect(_x1, _y1, _w, _h, r, outline); |
davidprentice | 0:8ee30e15ac7b | 1691 | |
davidprentice | 0:8ee30e15ac7b | 1692 | _gfx->setCursor(_x1 + (_w / 2) - (strlen(_label) * 3 * _textsize_x), |
davidprentice | 0:8ee30e15ac7b | 1693 | _y1 + (_h / 2) - (4 * _textsize_y)); |
davidprentice | 0:8ee30e15ac7b | 1694 | _gfx->setTextColor(text); |
davidprentice | 0:8ee30e15ac7b | 1695 | _gfx->setTextSize(_textsize_x, _textsize_y); |
davidprentice | 0:8ee30e15ac7b | 1696 | _gfx->print(_label); |
davidprentice | 0:8ee30e15ac7b | 1697 | } |
davidprentice | 0:8ee30e15ac7b | 1698 | |
davidprentice | 0:8ee30e15ac7b | 1699 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1700 | /*! |
davidprentice | 0:8ee30e15ac7b | 1701 | @brief Helper to let us know if a coordinate is within the bounds of the |
davidprentice | 0:8ee30e15ac7b | 1702 | button |
davidprentice | 0:8ee30e15ac7b | 1703 | @param x The X coordinate to check |
davidprentice | 0:8ee30e15ac7b | 1704 | @param y The Y coordinate to check |
davidprentice | 0:8ee30e15ac7b | 1705 | @returns True if within button graphics outline |
davidprentice | 0:8ee30e15ac7b | 1706 | */ |
davidprentice | 0:8ee30e15ac7b | 1707 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1708 | bool Adafruit_GFX_Button::contains(int16_t x, int16_t y) { |
davidprentice | 0:8ee30e15ac7b | 1709 | return ((x >= _x1) && (x < (int16_t)(_x1 + _w)) && (y >= _y1) && |
davidprentice | 0:8ee30e15ac7b | 1710 | (y < (int16_t)(_y1 + _h))); |
davidprentice | 0:8ee30e15ac7b | 1711 | } |
davidprentice | 0:8ee30e15ac7b | 1712 | |
davidprentice | 0:8ee30e15ac7b | 1713 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1714 | /*! |
davidprentice | 0:8ee30e15ac7b | 1715 | @brief Query whether the button was pressed since we last checked state |
davidprentice | 0:8ee30e15ac7b | 1716 | @returns True if was not-pressed before, now is. |
davidprentice | 0:8ee30e15ac7b | 1717 | */ |
davidprentice | 0:8ee30e15ac7b | 1718 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1719 | bool Adafruit_GFX_Button::justPressed() { return (currstate && !laststate); } |
davidprentice | 0:8ee30e15ac7b | 1720 | |
davidprentice | 0:8ee30e15ac7b | 1721 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1722 | /*! |
davidprentice | 0:8ee30e15ac7b | 1723 | @brief Query whether the button was released since we last checked state |
davidprentice | 0:8ee30e15ac7b | 1724 | @returns True if was pressed before, now is not. |
davidprentice | 0:8ee30e15ac7b | 1725 | */ |
davidprentice | 0:8ee30e15ac7b | 1726 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1727 | bool Adafruit_GFX_Button::justReleased() { return (!currstate && laststate); } |
davidprentice | 0:8ee30e15ac7b | 1728 | |
davidprentice | 0:8ee30e15ac7b | 1729 | // ------------------------------------------------------------------------- |
davidprentice | 0:8ee30e15ac7b | 1730 | |
davidprentice | 0:8ee30e15ac7b | 1731 | // GFXcanvas1, GFXcanvas8 and GFXcanvas16 (currently a WIP, don't get too |
davidprentice | 0:8ee30e15ac7b | 1732 | // comfy with the implementation) provide 1-, 8- and 16-bit offscreen |
davidprentice | 0:8ee30e15ac7b | 1733 | // canvases, the address of which can be passed to drawBitmap() or |
davidprentice | 0:8ee30e15ac7b | 1734 | // pushColors() (the latter appears only in a couple of GFX-subclassed TFT |
davidprentice | 0:8ee30e15ac7b | 1735 | // libraries at this time). This is here mostly to help with the recently- |
davidprentice | 0:8ee30e15ac7b | 1736 | // added proportionally-spaced fonts; adds a way to refresh a section of the |
davidprentice | 0:8ee30e15ac7b | 1737 | // screen without a massive flickering clear-and-redraw...but maybe you'll |
davidprentice | 0:8ee30e15ac7b | 1738 | // find other uses too. VERY RAM-intensive, since the buffer is in MCU |
davidprentice | 0:8ee30e15ac7b | 1739 | // memory and not the display driver...GXFcanvas1 might be minimally useful |
davidprentice | 0:8ee30e15ac7b | 1740 | // on an Uno-class board, but this and the others are much more likely to |
davidprentice | 0:8ee30e15ac7b | 1741 | // require at least a Mega or various recent ARM-type boards (recommended, |
davidprentice | 0:8ee30e15ac7b | 1742 | // as the text+bitmap draw can be pokey). GFXcanvas1 requires 1 bit per |
davidprentice | 0:8ee30e15ac7b | 1743 | // pixel (rounded up to nearest byte per scanline), GFXcanvas8 is 1 byte |
davidprentice | 0:8ee30e15ac7b | 1744 | // per pixel (no scanline pad), and GFXcanvas16 uses 2 bytes per pixel (no |
davidprentice | 0:8ee30e15ac7b | 1745 | // scanline pad). |
davidprentice | 0:8ee30e15ac7b | 1746 | // NOT EXTENSIVELY TESTED YET. MAY CONTAIN WORST BUGS KNOWN TO HUMANKIND. |
davidprentice | 0:8ee30e15ac7b | 1747 | |
davidprentice | 0:8ee30e15ac7b | 1748 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 1749 | // Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR |
davidprentice | 0:8ee30e15ac7b | 1750 | const uint8_t PROGMEM GFXcanvas1::GFXsetBit[] = {0x80, 0x40, 0x20, 0x10, |
davidprentice | 0:8ee30e15ac7b | 1751 | 0x08, 0x04, 0x02, 0x01}; |
davidprentice | 0:8ee30e15ac7b | 1752 | const uint8_t PROGMEM GFXcanvas1::GFXclrBit[] = {0x7F, 0xBF, 0xDF, 0xEF, |
davidprentice | 0:8ee30e15ac7b | 1753 | 0xF7, 0xFB, 0xFD, 0xFE}; |
davidprentice | 0:8ee30e15ac7b | 1754 | #endif |
davidprentice | 0:8ee30e15ac7b | 1755 | |
davidprentice | 0:8ee30e15ac7b | 1756 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1757 | /*! |
davidprentice | 0:8ee30e15ac7b | 1758 | @brief Instatiate a GFX 1-bit canvas context for graphics |
davidprentice | 0:8ee30e15ac7b | 1759 | @param w Display width, in pixels |
davidprentice | 0:8ee30e15ac7b | 1760 | @param h Display height, in pixels |
davidprentice | 0:8ee30e15ac7b | 1761 | */ |
davidprentice | 0:8ee30e15ac7b | 1762 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1763 | GFXcanvas1::GFXcanvas1(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) { |
davidprentice | 0:8ee30e15ac7b | 1764 | uint16_t bytes = ((w + 7) / 8) * h; |
davidprentice | 0:8ee30e15ac7b | 1765 | if ((buffer = (uint8_t *)malloc(bytes))) { |
davidprentice | 0:8ee30e15ac7b | 1766 | memset(buffer, 0, bytes); |
davidprentice | 0:8ee30e15ac7b | 1767 | } |
davidprentice | 0:8ee30e15ac7b | 1768 | } |
davidprentice | 0:8ee30e15ac7b | 1769 | |
davidprentice | 0:8ee30e15ac7b | 1770 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1771 | /*! |
davidprentice | 0:8ee30e15ac7b | 1772 | @brief Delete the canvas, free memory |
davidprentice | 0:8ee30e15ac7b | 1773 | */ |
davidprentice | 0:8ee30e15ac7b | 1774 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1775 | GFXcanvas1::~GFXcanvas1(void) { |
davidprentice | 0:8ee30e15ac7b | 1776 | if (buffer) |
davidprentice | 0:8ee30e15ac7b | 1777 | free(buffer); |
davidprentice | 0:8ee30e15ac7b | 1778 | } |
davidprentice | 0:8ee30e15ac7b | 1779 | |
davidprentice | 0:8ee30e15ac7b | 1780 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1781 | /*! |
davidprentice | 0:8ee30e15ac7b | 1782 | @brief Draw a pixel to the canvas framebuffer |
davidprentice | 0:8ee30e15ac7b | 1783 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 1784 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 1785 | @param color Binary (on or off) color to fill with |
davidprentice | 0:8ee30e15ac7b | 1786 | */ |
davidprentice | 0:8ee30e15ac7b | 1787 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1788 | void GFXcanvas1::drawPixel(int16_t x, int16_t y, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 1789 | if (buffer) { |
davidprentice | 0:8ee30e15ac7b | 1790 | if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) |
davidprentice | 0:8ee30e15ac7b | 1791 | return; |
davidprentice | 0:8ee30e15ac7b | 1792 | |
davidprentice | 0:8ee30e15ac7b | 1793 | int16_t t; |
davidprentice | 0:8ee30e15ac7b | 1794 | switch (rotation) { |
davidprentice | 0:8ee30e15ac7b | 1795 | case 1: |
davidprentice | 0:8ee30e15ac7b | 1796 | t = x; |
davidprentice | 0:8ee30e15ac7b | 1797 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 1798 | y = t; |
davidprentice | 0:8ee30e15ac7b | 1799 | break; |
davidprentice | 0:8ee30e15ac7b | 1800 | case 2: |
davidprentice | 0:8ee30e15ac7b | 1801 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 1802 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 1803 | break; |
davidprentice | 0:8ee30e15ac7b | 1804 | case 3: |
davidprentice | 0:8ee30e15ac7b | 1805 | t = x; |
davidprentice | 0:8ee30e15ac7b | 1806 | x = y; |
davidprentice | 0:8ee30e15ac7b | 1807 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 1808 | break; |
davidprentice | 0:8ee30e15ac7b | 1809 | } |
davidprentice | 0:8ee30e15ac7b | 1810 | |
davidprentice | 0:8ee30e15ac7b | 1811 | uint8_t *ptr = &buffer[(x / 8) + y * ((WIDTH + 7) / 8)]; |
davidprentice | 0:8ee30e15ac7b | 1812 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 1813 | if (color) |
davidprentice | 0:8ee30e15ac7b | 1814 | *ptr |= pgm_read_byte(&GFXsetBit[x & 7]); |
davidprentice | 0:8ee30e15ac7b | 1815 | else |
davidprentice | 0:8ee30e15ac7b | 1816 | *ptr &= pgm_read_byte(&GFXclrBit[x & 7]); |
davidprentice | 0:8ee30e15ac7b | 1817 | #else |
davidprentice | 0:8ee30e15ac7b | 1818 | if (color) |
davidprentice | 0:8ee30e15ac7b | 1819 | *ptr |= 0x80 >> (x & 7); |
davidprentice | 0:8ee30e15ac7b | 1820 | else |
davidprentice | 0:8ee30e15ac7b | 1821 | *ptr &= ~(0x80 >> (x & 7)); |
davidprentice | 0:8ee30e15ac7b | 1822 | #endif |
davidprentice | 0:8ee30e15ac7b | 1823 | } |
davidprentice | 0:8ee30e15ac7b | 1824 | } |
davidprentice | 0:8ee30e15ac7b | 1825 | |
davidprentice | 0:8ee30e15ac7b | 1826 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1827 | /*! |
davidprentice | 0:8ee30e15ac7b | 1828 | @brief Get the pixel color value at a given coordinate |
davidprentice | 0:8ee30e15ac7b | 1829 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 1830 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 1831 | @returns The desired pixel's binary color value, either 0x1 (on) or 0x0 |
davidprentice | 0:8ee30e15ac7b | 1832 | (off) |
davidprentice | 0:8ee30e15ac7b | 1833 | */ |
davidprentice | 0:8ee30e15ac7b | 1834 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1835 | bool GFXcanvas1::getPixel(int16_t x, int16_t y) const { |
davidprentice | 0:8ee30e15ac7b | 1836 | int16_t t; |
davidprentice | 0:8ee30e15ac7b | 1837 | switch (rotation) { |
davidprentice | 0:8ee30e15ac7b | 1838 | case 1: |
davidprentice | 0:8ee30e15ac7b | 1839 | t = x; |
davidprentice | 0:8ee30e15ac7b | 1840 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 1841 | y = t; |
davidprentice | 0:8ee30e15ac7b | 1842 | break; |
davidprentice | 0:8ee30e15ac7b | 1843 | case 2: |
davidprentice | 0:8ee30e15ac7b | 1844 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 1845 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 1846 | break; |
davidprentice | 0:8ee30e15ac7b | 1847 | case 3: |
davidprentice | 0:8ee30e15ac7b | 1848 | t = x; |
davidprentice | 0:8ee30e15ac7b | 1849 | x = y; |
davidprentice | 0:8ee30e15ac7b | 1850 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 1851 | break; |
davidprentice | 0:8ee30e15ac7b | 1852 | } |
davidprentice | 0:8ee30e15ac7b | 1853 | return getRawPixel(x, y); |
davidprentice | 0:8ee30e15ac7b | 1854 | } |
davidprentice | 0:8ee30e15ac7b | 1855 | |
davidprentice | 0:8ee30e15ac7b | 1856 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1857 | /*! |
davidprentice | 0:8ee30e15ac7b | 1858 | @brief Get the pixel color value at a given, unrotated coordinate. |
davidprentice | 0:8ee30e15ac7b | 1859 | This method is intended for hardware drivers to get pixel value |
davidprentice | 0:8ee30e15ac7b | 1860 | in physical coordinates. |
davidprentice | 0:8ee30e15ac7b | 1861 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 1862 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 1863 | @returns The desired pixel's binary color value, either 0x1 (on) or 0x0 |
davidprentice | 0:8ee30e15ac7b | 1864 | (off) |
davidprentice | 0:8ee30e15ac7b | 1865 | */ |
davidprentice | 0:8ee30e15ac7b | 1866 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1867 | bool GFXcanvas1::getRawPixel(int16_t x, int16_t y) const { |
davidprentice | 0:8ee30e15ac7b | 1868 | if ((x < 0) || (y < 0) || (x >= WIDTH) || (y >= HEIGHT)) |
davidprentice | 0:8ee30e15ac7b | 1869 | return 0; |
davidprentice | 0:8ee30e15ac7b | 1870 | if (this->getBuffer()) { |
davidprentice | 0:8ee30e15ac7b | 1871 | uint8_t *buffer = this->getBuffer(); |
davidprentice | 0:8ee30e15ac7b | 1872 | uint8_t *ptr = &buffer[(x / 8) + y * ((WIDTH + 7) / 8)]; |
davidprentice | 0:8ee30e15ac7b | 1873 | |
davidprentice | 0:8ee30e15ac7b | 1874 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 1875 | return ((*ptr) & pgm_read_byte(&GFXsetBit[x & 7])) != 0; |
davidprentice | 0:8ee30e15ac7b | 1876 | #else |
davidprentice | 0:8ee30e15ac7b | 1877 | return ((*ptr) & (0x80 >> (x & 7))) != 0; |
davidprentice | 0:8ee30e15ac7b | 1878 | #endif |
davidprentice | 0:8ee30e15ac7b | 1879 | } |
davidprentice | 0:8ee30e15ac7b | 1880 | return 0; |
davidprentice | 0:8ee30e15ac7b | 1881 | } |
davidprentice | 0:8ee30e15ac7b | 1882 | |
davidprentice | 0:8ee30e15ac7b | 1883 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1884 | /*! |
davidprentice | 0:8ee30e15ac7b | 1885 | @brief Fill the framebuffer completely with one color |
davidprentice | 0:8ee30e15ac7b | 1886 | @param color Binary (on or off) color to fill with |
davidprentice | 0:8ee30e15ac7b | 1887 | */ |
davidprentice | 0:8ee30e15ac7b | 1888 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1889 | void GFXcanvas1::fillScreen(uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 1890 | if (buffer) { |
davidprentice | 0:8ee30e15ac7b | 1891 | uint16_t bytes = ((WIDTH + 7) / 8) * HEIGHT; |
davidprentice | 0:8ee30e15ac7b | 1892 | memset(buffer, color ? 0xFF : 0x00, bytes); |
davidprentice | 0:8ee30e15ac7b | 1893 | } |
davidprentice | 0:8ee30e15ac7b | 1894 | } |
davidprentice | 0:8ee30e15ac7b | 1895 | |
davidprentice | 0:8ee30e15ac7b | 1896 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1897 | /*! |
davidprentice | 0:8ee30e15ac7b | 1898 | @brief Speed optimized vertical line drawing |
davidprentice | 0:8ee30e15ac7b | 1899 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 1900 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 1901 | @param h Length of vertical line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 1902 | @param color Color to fill with |
davidprentice | 0:8ee30e15ac7b | 1903 | */ |
davidprentice | 0:8ee30e15ac7b | 1904 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1905 | void GFXcanvas1::drawFastVLine(int16_t x, int16_t y, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 1906 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 1907 | |
davidprentice | 0:8ee30e15ac7b | 1908 | if (h < 0) { // Convert negative heights to positive equivalent |
davidprentice | 0:8ee30e15ac7b | 1909 | h *= -1; |
davidprentice | 0:8ee30e15ac7b | 1910 | y -= h - 1; |
davidprentice | 0:8ee30e15ac7b | 1911 | if (y < 0) { |
davidprentice | 0:8ee30e15ac7b | 1912 | h += y; |
davidprentice | 0:8ee30e15ac7b | 1913 | y = 0; |
davidprentice | 0:8ee30e15ac7b | 1914 | } |
davidprentice | 0:8ee30e15ac7b | 1915 | } |
davidprentice | 0:8ee30e15ac7b | 1916 | |
davidprentice | 0:8ee30e15ac7b | 1917 | // Edge rejection (no-draw if totally off canvas) |
davidprentice | 0:8ee30e15ac7b | 1918 | if ((x < 0) || (x >= width()) || (y >= height()) || ((y + h - 1) < 0)) { |
davidprentice | 0:8ee30e15ac7b | 1919 | return; |
davidprentice | 0:8ee30e15ac7b | 1920 | } |
davidprentice | 0:8ee30e15ac7b | 1921 | |
davidprentice | 0:8ee30e15ac7b | 1922 | if (y < 0) { // Clip top |
davidprentice | 0:8ee30e15ac7b | 1923 | h += y; |
davidprentice | 0:8ee30e15ac7b | 1924 | y = 0; |
davidprentice | 0:8ee30e15ac7b | 1925 | } |
davidprentice | 0:8ee30e15ac7b | 1926 | if (y + h > height()) { // Clip bottom |
davidprentice | 0:8ee30e15ac7b | 1927 | h = height() - y; |
davidprentice | 0:8ee30e15ac7b | 1928 | } |
davidprentice | 0:8ee30e15ac7b | 1929 | |
davidprentice | 0:8ee30e15ac7b | 1930 | if (getRotation() == 0) { |
davidprentice | 0:8ee30e15ac7b | 1931 | drawFastRawVLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 1932 | } else if (getRotation() == 1) { |
davidprentice | 0:8ee30e15ac7b | 1933 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 1934 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 1935 | y = t; |
davidprentice | 0:8ee30e15ac7b | 1936 | x -= h - 1; |
davidprentice | 0:8ee30e15ac7b | 1937 | drawFastRawHLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 1938 | } else if (getRotation() == 2) { |
davidprentice | 0:8ee30e15ac7b | 1939 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 1940 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 1941 | |
davidprentice | 0:8ee30e15ac7b | 1942 | y -= h - 1; |
davidprentice | 0:8ee30e15ac7b | 1943 | drawFastRawVLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 1944 | } else if (getRotation() == 3) { |
davidprentice | 0:8ee30e15ac7b | 1945 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 1946 | x = y; |
davidprentice | 0:8ee30e15ac7b | 1947 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 1948 | drawFastRawHLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 1949 | } |
davidprentice | 0:8ee30e15ac7b | 1950 | } |
davidprentice | 0:8ee30e15ac7b | 1951 | |
davidprentice | 0:8ee30e15ac7b | 1952 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1953 | /*! |
davidprentice | 0:8ee30e15ac7b | 1954 | @brief Speed optimized horizontal line drawing |
davidprentice | 0:8ee30e15ac7b | 1955 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 1956 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 1957 | @param w Length of horizontal line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 1958 | @param color Color to fill with |
davidprentice | 0:8ee30e15ac7b | 1959 | */ |
davidprentice | 0:8ee30e15ac7b | 1960 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 1961 | void GFXcanvas1::drawFastHLine(int16_t x, int16_t y, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 1962 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 1963 | if (w < 0) { // Convert negative widths to positive equivalent |
davidprentice | 0:8ee30e15ac7b | 1964 | w *= -1; |
davidprentice | 0:8ee30e15ac7b | 1965 | x -= w - 1; |
davidprentice | 0:8ee30e15ac7b | 1966 | if (x < 0) { |
davidprentice | 0:8ee30e15ac7b | 1967 | w += x; |
davidprentice | 0:8ee30e15ac7b | 1968 | x = 0; |
davidprentice | 0:8ee30e15ac7b | 1969 | } |
davidprentice | 0:8ee30e15ac7b | 1970 | } |
davidprentice | 0:8ee30e15ac7b | 1971 | |
davidprentice | 0:8ee30e15ac7b | 1972 | // Edge rejection (no-draw if totally off canvas) |
davidprentice | 0:8ee30e15ac7b | 1973 | if ((y < 0) || (y >= height()) || (x >= width()) || ((x + w - 1) < 0)) { |
davidprentice | 0:8ee30e15ac7b | 1974 | return; |
davidprentice | 0:8ee30e15ac7b | 1975 | } |
davidprentice | 0:8ee30e15ac7b | 1976 | |
davidprentice | 0:8ee30e15ac7b | 1977 | if (x < 0) { // Clip left |
davidprentice | 0:8ee30e15ac7b | 1978 | w += x; |
davidprentice | 0:8ee30e15ac7b | 1979 | x = 0; |
davidprentice | 0:8ee30e15ac7b | 1980 | } |
davidprentice | 0:8ee30e15ac7b | 1981 | if (x + w >= width()) { // Clip right |
davidprentice | 0:8ee30e15ac7b | 1982 | w = width() - x; |
davidprentice | 0:8ee30e15ac7b | 1983 | } |
davidprentice | 0:8ee30e15ac7b | 1984 | |
davidprentice | 0:8ee30e15ac7b | 1985 | if (getRotation() == 0) { |
davidprentice | 0:8ee30e15ac7b | 1986 | drawFastRawHLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 1987 | } else if (getRotation() == 1) { |
davidprentice | 0:8ee30e15ac7b | 1988 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 1989 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 1990 | y = t; |
davidprentice | 0:8ee30e15ac7b | 1991 | drawFastRawVLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 1992 | } else if (getRotation() == 2) { |
davidprentice | 0:8ee30e15ac7b | 1993 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 1994 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 1995 | |
davidprentice | 0:8ee30e15ac7b | 1996 | x -= w - 1; |
davidprentice | 0:8ee30e15ac7b | 1997 | drawFastRawHLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 1998 | } else if (getRotation() == 3) { |
davidprentice | 0:8ee30e15ac7b | 1999 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 2000 | x = y; |
davidprentice | 0:8ee30e15ac7b | 2001 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 2002 | y -= w - 1; |
davidprentice | 0:8ee30e15ac7b | 2003 | drawFastRawVLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 2004 | } |
davidprentice | 0:8ee30e15ac7b | 2005 | } |
davidprentice | 0:8ee30e15ac7b | 2006 | |
davidprentice | 0:8ee30e15ac7b | 2007 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2008 | /*! |
davidprentice | 0:8ee30e15ac7b | 2009 | @brief Speed optimized vertical line drawing into the raw canvas buffer |
davidprentice | 0:8ee30e15ac7b | 2010 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2011 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2012 | @param h length of vertical line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 2013 | @param color Binary (on or off) color to fill with |
davidprentice | 0:8ee30e15ac7b | 2014 | */ |
davidprentice | 0:8ee30e15ac7b | 2015 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2016 | void GFXcanvas1::drawFastRawVLine(int16_t x, int16_t y, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 2017 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2018 | // x & y already in raw (rotation 0) coordinates, no need to transform. |
davidprentice | 0:8ee30e15ac7b | 2019 | int16_t row_bytes = ((WIDTH + 7) / 8); |
davidprentice | 0:8ee30e15ac7b | 2020 | uint8_t *buffer = this->getBuffer(); |
davidprentice | 0:8ee30e15ac7b | 2021 | uint8_t *ptr = &buffer[(x / 8) + y * row_bytes]; |
davidprentice | 0:8ee30e15ac7b | 2022 | |
davidprentice | 0:8ee30e15ac7b | 2023 | if (color > 0) { |
davidprentice | 0:8ee30e15ac7b | 2024 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 2025 | uint8_t bit_mask = pgm_read_byte(&GFXsetBit[x & 7]); |
davidprentice | 0:8ee30e15ac7b | 2026 | #else |
davidprentice | 0:8ee30e15ac7b | 2027 | uint8_t bit_mask = (0x80 >> (x & 7)); |
davidprentice | 0:8ee30e15ac7b | 2028 | #endif |
davidprentice | 0:8ee30e15ac7b | 2029 | for (int16_t i = 0; i < h; i++) { |
davidprentice | 0:8ee30e15ac7b | 2030 | *ptr |= bit_mask; |
davidprentice | 0:8ee30e15ac7b | 2031 | ptr += row_bytes; |
davidprentice | 0:8ee30e15ac7b | 2032 | } |
davidprentice | 0:8ee30e15ac7b | 2033 | } else { |
davidprentice | 0:8ee30e15ac7b | 2034 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 2035 | uint8_t bit_mask = pgm_read_byte(&GFXclrBit[x & 7]); |
davidprentice | 0:8ee30e15ac7b | 2036 | #else |
davidprentice | 0:8ee30e15ac7b | 2037 | uint8_t bit_mask = ~(0x80 >> (x & 7)); |
davidprentice | 0:8ee30e15ac7b | 2038 | #endif |
davidprentice | 0:8ee30e15ac7b | 2039 | for (int16_t i = 0; i < h; i++) { |
davidprentice | 0:8ee30e15ac7b | 2040 | *ptr &= bit_mask; |
davidprentice | 0:8ee30e15ac7b | 2041 | ptr += row_bytes; |
davidprentice | 0:8ee30e15ac7b | 2042 | } |
davidprentice | 0:8ee30e15ac7b | 2043 | } |
davidprentice | 0:8ee30e15ac7b | 2044 | } |
davidprentice | 0:8ee30e15ac7b | 2045 | |
davidprentice | 0:8ee30e15ac7b | 2046 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2047 | /*! |
davidprentice | 0:8ee30e15ac7b | 2048 | @brief Speed optimized horizontal line drawing into the raw canvas buffer |
davidprentice | 0:8ee30e15ac7b | 2049 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2050 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2051 | @param w length of horizontal line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 2052 | @param color Binary (on or off) color to fill with |
davidprentice | 0:8ee30e15ac7b | 2053 | */ |
davidprentice | 0:8ee30e15ac7b | 2054 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2055 | void GFXcanvas1::drawFastRawHLine(int16_t x, int16_t y, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 2056 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2057 | // x & y already in raw (rotation 0) coordinates, no need to transform. |
davidprentice | 0:8ee30e15ac7b | 2058 | int16_t rowBytes = ((WIDTH + 7) / 8); |
davidprentice | 0:8ee30e15ac7b | 2059 | uint8_t *buffer = this->getBuffer(); |
davidprentice | 0:8ee30e15ac7b | 2060 | uint8_t *ptr = &buffer[(x / 8) + y * rowBytes]; |
davidprentice | 0:8ee30e15ac7b | 2061 | size_t remainingWidthBits = w; |
davidprentice | 0:8ee30e15ac7b | 2062 | |
davidprentice | 0:8ee30e15ac7b | 2063 | // check to see if first byte needs to be partially filled |
davidprentice | 0:8ee30e15ac7b | 2064 | if ((x & 7) > 0) { |
davidprentice | 0:8ee30e15ac7b | 2065 | // create bit mask for first byte |
davidprentice | 0:8ee30e15ac7b | 2066 | uint8_t startByteBitMask = 0x00; |
davidprentice | 0:8ee30e15ac7b | 2067 | for (int8_t i = (x & 7); ((i < 8) && (remainingWidthBits > 0)); i++) { |
davidprentice | 0:8ee30e15ac7b | 2068 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 2069 | startByteBitMask |= pgm_read_byte(&GFXsetBit[i]); |
davidprentice | 0:8ee30e15ac7b | 2070 | #else |
davidprentice | 0:8ee30e15ac7b | 2071 | startByteBitMask |= (0x80 >> i); |
davidprentice | 0:8ee30e15ac7b | 2072 | #endif |
davidprentice | 0:8ee30e15ac7b | 2073 | remainingWidthBits--; |
davidprentice | 0:8ee30e15ac7b | 2074 | } |
davidprentice | 0:8ee30e15ac7b | 2075 | if (color > 0) { |
davidprentice | 0:8ee30e15ac7b | 2076 | *ptr |= startByteBitMask; |
davidprentice | 0:8ee30e15ac7b | 2077 | } else { |
davidprentice | 0:8ee30e15ac7b | 2078 | *ptr &= ~startByteBitMask; |
davidprentice | 0:8ee30e15ac7b | 2079 | } |
davidprentice | 0:8ee30e15ac7b | 2080 | |
davidprentice | 0:8ee30e15ac7b | 2081 | ptr++; |
davidprentice | 0:8ee30e15ac7b | 2082 | } |
davidprentice | 0:8ee30e15ac7b | 2083 | |
davidprentice | 0:8ee30e15ac7b | 2084 | // do the next remainingWidthBits bits |
davidprentice | 0:8ee30e15ac7b | 2085 | if (remainingWidthBits > 0) { |
davidprentice | 0:8ee30e15ac7b | 2086 | size_t remainingWholeBytes = remainingWidthBits / 8; |
davidprentice | 0:8ee30e15ac7b | 2087 | size_t lastByteBits = remainingWidthBits % 8; |
davidprentice | 0:8ee30e15ac7b | 2088 | uint8_t wholeByteColor = color > 0 ? 0xFF : 0x00; |
davidprentice | 0:8ee30e15ac7b | 2089 | |
davidprentice | 0:8ee30e15ac7b | 2090 | memset(ptr, wholeByteColor, remainingWholeBytes); |
davidprentice | 0:8ee30e15ac7b | 2091 | |
davidprentice | 0:8ee30e15ac7b | 2092 | if (lastByteBits > 0) { |
davidprentice | 0:8ee30e15ac7b | 2093 | uint8_t lastByteBitMask = 0x00; |
davidprentice | 0:8ee30e15ac7b | 2094 | for (size_t i = 0; i < lastByteBits; i++) { |
davidprentice | 0:8ee30e15ac7b | 2095 | #ifdef __AVR__ |
davidprentice | 0:8ee30e15ac7b | 2096 | lastByteBitMask |= pgm_read_byte(&GFXsetBit[i]); |
davidprentice | 0:8ee30e15ac7b | 2097 | #else |
davidprentice | 0:8ee30e15ac7b | 2098 | lastByteBitMask |= (0x80 >> i); |
davidprentice | 0:8ee30e15ac7b | 2099 | #endif |
davidprentice | 0:8ee30e15ac7b | 2100 | } |
davidprentice | 0:8ee30e15ac7b | 2101 | ptr += remainingWholeBytes; |
davidprentice | 0:8ee30e15ac7b | 2102 | |
davidprentice | 0:8ee30e15ac7b | 2103 | if (color > 0) { |
davidprentice | 0:8ee30e15ac7b | 2104 | *ptr |= lastByteBitMask; |
davidprentice | 0:8ee30e15ac7b | 2105 | } else { |
davidprentice | 0:8ee30e15ac7b | 2106 | *ptr &= ~lastByteBitMask; |
davidprentice | 0:8ee30e15ac7b | 2107 | } |
davidprentice | 0:8ee30e15ac7b | 2108 | } |
davidprentice | 0:8ee30e15ac7b | 2109 | } |
davidprentice | 0:8ee30e15ac7b | 2110 | } |
davidprentice | 0:8ee30e15ac7b | 2111 | |
davidprentice | 0:8ee30e15ac7b | 2112 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2113 | /*! |
davidprentice | 0:8ee30e15ac7b | 2114 | @brief Instatiate a GFX 8-bit canvas context for graphics |
davidprentice | 0:8ee30e15ac7b | 2115 | @param w Display width, in pixels |
davidprentice | 0:8ee30e15ac7b | 2116 | @param h Display height, in pixels |
davidprentice | 0:8ee30e15ac7b | 2117 | */ |
davidprentice | 0:8ee30e15ac7b | 2118 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2119 | GFXcanvas8::GFXcanvas8(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) { |
davidprentice | 0:8ee30e15ac7b | 2120 | uint32_t bytes = w * h; |
davidprentice | 0:8ee30e15ac7b | 2121 | if ((buffer = (uint8_t *)malloc(bytes))) { |
davidprentice | 0:8ee30e15ac7b | 2122 | memset(buffer, 0, bytes); |
davidprentice | 0:8ee30e15ac7b | 2123 | } |
davidprentice | 0:8ee30e15ac7b | 2124 | } |
davidprentice | 0:8ee30e15ac7b | 2125 | |
davidprentice | 0:8ee30e15ac7b | 2126 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2127 | /*! |
davidprentice | 0:8ee30e15ac7b | 2128 | @brief Delete the canvas, free memory |
davidprentice | 0:8ee30e15ac7b | 2129 | */ |
davidprentice | 0:8ee30e15ac7b | 2130 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2131 | GFXcanvas8::~GFXcanvas8(void) { |
davidprentice | 0:8ee30e15ac7b | 2132 | if (buffer) |
davidprentice | 0:8ee30e15ac7b | 2133 | free(buffer); |
davidprentice | 0:8ee30e15ac7b | 2134 | } |
davidprentice | 0:8ee30e15ac7b | 2135 | |
davidprentice | 0:8ee30e15ac7b | 2136 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2137 | /*! |
davidprentice | 0:8ee30e15ac7b | 2138 | @brief Draw a pixel to the canvas framebuffer |
davidprentice | 0:8ee30e15ac7b | 2139 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 2140 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 2141 | @param color 8-bit Color to fill with. Only lower byte of uint16_t is used. |
davidprentice | 0:8ee30e15ac7b | 2142 | */ |
davidprentice | 0:8ee30e15ac7b | 2143 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2144 | void GFXcanvas8::drawPixel(int16_t x, int16_t y, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2145 | if (buffer) { |
davidprentice | 0:8ee30e15ac7b | 2146 | if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) |
davidprentice | 0:8ee30e15ac7b | 2147 | return; |
davidprentice | 0:8ee30e15ac7b | 2148 | |
davidprentice | 0:8ee30e15ac7b | 2149 | int16_t t; |
davidprentice | 0:8ee30e15ac7b | 2150 | switch (rotation) { |
davidprentice | 0:8ee30e15ac7b | 2151 | case 1: |
davidprentice | 0:8ee30e15ac7b | 2152 | t = x; |
davidprentice | 0:8ee30e15ac7b | 2153 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2154 | y = t; |
davidprentice | 0:8ee30e15ac7b | 2155 | break; |
davidprentice | 0:8ee30e15ac7b | 2156 | case 2: |
davidprentice | 0:8ee30e15ac7b | 2157 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 2158 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2159 | break; |
davidprentice | 0:8ee30e15ac7b | 2160 | case 3: |
davidprentice | 0:8ee30e15ac7b | 2161 | t = x; |
davidprentice | 0:8ee30e15ac7b | 2162 | x = y; |
davidprentice | 0:8ee30e15ac7b | 2163 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 2164 | break; |
davidprentice | 0:8ee30e15ac7b | 2165 | } |
davidprentice | 0:8ee30e15ac7b | 2166 | |
davidprentice | 0:8ee30e15ac7b | 2167 | buffer[x + y * WIDTH] = color; |
davidprentice | 0:8ee30e15ac7b | 2168 | } |
davidprentice | 0:8ee30e15ac7b | 2169 | } |
davidprentice | 0:8ee30e15ac7b | 2170 | |
davidprentice | 0:8ee30e15ac7b | 2171 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2172 | /*! |
davidprentice | 0:8ee30e15ac7b | 2173 | @brief Get the pixel color value at a given coordinate |
davidprentice | 0:8ee30e15ac7b | 2174 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 2175 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 2176 | @returns The desired pixel's 8-bit color value |
davidprentice | 0:8ee30e15ac7b | 2177 | */ |
davidprentice | 0:8ee30e15ac7b | 2178 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2179 | uint8_t GFXcanvas8::getPixel(int16_t x, int16_t y) const { |
davidprentice | 0:8ee30e15ac7b | 2180 | int16_t t; |
davidprentice | 0:8ee30e15ac7b | 2181 | switch (rotation) { |
davidprentice | 0:8ee30e15ac7b | 2182 | case 1: |
davidprentice | 0:8ee30e15ac7b | 2183 | t = x; |
davidprentice | 0:8ee30e15ac7b | 2184 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2185 | y = t; |
davidprentice | 0:8ee30e15ac7b | 2186 | break; |
davidprentice | 0:8ee30e15ac7b | 2187 | case 2: |
davidprentice | 0:8ee30e15ac7b | 2188 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 2189 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2190 | break; |
davidprentice | 0:8ee30e15ac7b | 2191 | case 3: |
davidprentice | 0:8ee30e15ac7b | 2192 | t = x; |
davidprentice | 0:8ee30e15ac7b | 2193 | x = y; |
davidprentice | 0:8ee30e15ac7b | 2194 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 2195 | break; |
davidprentice | 0:8ee30e15ac7b | 2196 | } |
davidprentice | 0:8ee30e15ac7b | 2197 | return getRawPixel(x, y); |
davidprentice | 0:8ee30e15ac7b | 2198 | } |
davidprentice | 0:8ee30e15ac7b | 2199 | |
davidprentice | 0:8ee30e15ac7b | 2200 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2201 | /*! |
davidprentice | 0:8ee30e15ac7b | 2202 | @brief Get the pixel color value at a given, unrotated coordinate. |
davidprentice | 0:8ee30e15ac7b | 2203 | This method is intended for hardware drivers to get pixel value |
davidprentice | 0:8ee30e15ac7b | 2204 | in physical coordinates. |
davidprentice | 0:8ee30e15ac7b | 2205 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 2206 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 2207 | @returns The desired pixel's 8-bit color value |
davidprentice | 0:8ee30e15ac7b | 2208 | */ |
davidprentice | 0:8ee30e15ac7b | 2209 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2210 | uint8_t GFXcanvas8::getRawPixel(int16_t x, int16_t y) const { |
davidprentice | 0:8ee30e15ac7b | 2211 | if ((x < 0) || (y < 0) || (x >= WIDTH) || (y >= HEIGHT)) |
davidprentice | 0:8ee30e15ac7b | 2212 | return 0; |
davidprentice | 0:8ee30e15ac7b | 2213 | if (buffer) { |
davidprentice | 0:8ee30e15ac7b | 2214 | return buffer[x + y * WIDTH]; |
davidprentice | 0:8ee30e15ac7b | 2215 | } |
davidprentice | 0:8ee30e15ac7b | 2216 | return 0; |
davidprentice | 0:8ee30e15ac7b | 2217 | } |
davidprentice | 0:8ee30e15ac7b | 2218 | |
davidprentice | 0:8ee30e15ac7b | 2219 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2220 | /*! |
davidprentice | 0:8ee30e15ac7b | 2221 | @brief Fill the framebuffer completely with one color |
davidprentice | 0:8ee30e15ac7b | 2222 | @param color 8-bit Color to fill with. Only lower byte of uint16_t is used. |
davidprentice | 0:8ee30e15ac7b | 2223 | */ |
davidprentice | 0:8ee30e15ac7b | 2224 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2225 | void GFXcanvas8::fillScreen(uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2226 | if (buffer) { |
davidprentice | 0:8ee30e15ac7b | 2227 | memset(buffer, color, WIDTH * HEIGHT); |
davidprentice | 0:8ee30e15ac7b | 2228 | } |
davidprentice | 0:8ee30e15ac7b | 2229 | } |
davidprentice | 0:8ee30e15ac7b | 2230 | |
davidprentice | 0:8ee30e15ac7b | 2231 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2232 | /*! |
davidprentice | 0:8ee30e15ac7b | 2233 | @brief Speed optimized vertical line drawing |
davidprentice | 0:8ee30e15ac7b | 2234 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2235 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2236 | @param h Length of vertical line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 2237 | @param color 8-bit Color to fill with. Only lower byte of uint16_t is |
davidprentice | 0:8ee30e15ac7b | 2238 | used. |
davidprentice | 0:8ee30e15ac7b | 2239 | */ |
davidprentice | 0:8ee30e15ac7b | 2240 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2241 | void GFXcanvas8::drawFastVLine(int16_t x, int16_t y, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 2242 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2243 | if (h < 0) { // Convert negative heights to positive equivalent |
davidprentice | 0:8ee30e15ac7b | 2244 | h *= -1; |
davidprentice | 0:8ee30e15ac7b | 2245 | y -= h - 1; |
davidprentice | 0:8ee30e15ac7b | 2246 | if (y < 0) { |
davidprentice | 0:8ee30e15ac7b | 2247 | h += y; |
davidprentice | 0:8ee30e15ac7b | 2248 | y = 0; |
davidprentice | 0:8ee30e15ac7b | 2249 | } |
davidprentice | 0:8ee30e15ac7b | 2250 | } |
davidprentice | 0:8ee30e15ac7b | 2251 | |
davidprentice | 0:8ee30e15ac7b | 2252 | // Edge rejection (no-draw if totally off canvas) |
davidprentice | 0:8ee30e15ac7b | 2253 | if ((x < 0) || (x >= width()) || (y >= height()) || ((y + h - 1) < 0)) { |
davidprentice | 0:8ee30e15ac7b | 2254 | return; |
davidprentice | 0:8ee30e15ac7b | 2255 | } |
davidprentice | 0:8ee30e15ac7b | 2256 | |
davidprentice | 0:8ee30e15ac7b | 2257 | if (y < 0) { // Clip top |
davidprentice | 0:8ee30e15ac7b | 2258 | h += y; |
davidprentice | 0:8ee30e15ac7b | 2259 | y = 0; |
davidprentice | 0:8ee30e15ac7b | 2260 | } |
davidprentice | 0:8ee30e15ac7b | 2261 | if (y + h > height()) { // Clip bottom |
davidprentice | 0:8ee30e15ac7b | 2262 | h = height() - y; |
davidprentice | 0:8ee30e15ac7b | 2263 | } |
davidprentice | 0:8ee30e15ac7b | 2264 | |
davidprentice | 0:8ee30e15ac7b | 2265 | if (getRotation() == 0) { |
davidprentice | 0:8ee30e15ac7b | 2266 | drawFastRawVLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 2267 | } else if (getRotation() == 1) { |
davidprentice | 0:8ee30e15ac7b | 2268 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 2269 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2270 | y = t; |
davidprentice | 0:8ee30e15ac7b | 2271 | x -= h - 1; |
davidprentice | 0:8ee30e15ac7b | 2272 | drawFastRawHLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 2273 | } else if (getRotation() == 2) { |
davidprentice | 0:8ee30e15ac7b | 2274 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 2275 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2276 | |
davidprentice | 0:8ee30e15ac7b | 2277 | y -= h - 1; |
davidprentice | 0:8ee30e15ac7b | 2278 | drawFastRawVLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 2279 | } else if (getRotation() == 3) { |
davidprentice | 0:8ee30e15ac7b | 2280 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 2281 | x = y; |
davidprentice | 0:8ee30e15ac7b | 2282 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 2283 | drawFastRawHLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 2284 | } |
davidprentice | 0:8ee30e15ac7b | 2285 | } |
davidprentice | 0:8ee30e15ac7b | 2286 | |
davidprentice | 0:8ee30e15ac7b | 2287 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2288 | /*! |
davidprentice | 0:8ee30e15ac7b | 2289 | @brief Speed optimized horizontal line drawing |
davidprentice | 0:8ee30e15ac7b | 2290 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2291 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2292 | @param w Length of horizontal line to be drawn, including 1st point |
davidprentice | 0:8ee30e15ac7b | 2293 | @param color 8-bit Color to fill with. Only lower byte of uint16_t is |
davidprentice | 0:8ee30e15ac7b | 2294 | used. |
davidprentice | 0:8ee30e15ac7b | 2295 | */ |
davidprentice | 0:8ee30e15ac7b | 2296 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2297 | void GFXcanvas8::drawFastHLine(int16_t x, int16_t y, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 2298 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2299 | |
davidprentice | 0:8ee30e15ac7b | 2300 | if (w < 0) { // Convert negative widths to positive equivalent |
davidprentice | 0:8ee30e15ac7b | 2301 | w *= -1; |
davidprentice | 0:8ee30e15ac7b | 2302 | x -= w - 1; |
davidprentice | 0:8ee30e15ac7b | 2303 | if (x < 0) { |
davidprentice | 0:8ee30e15ac7b | 2304 | w += x; |
davidprentice | 0:8ee30e15ac7b | 2305 | x = 0; |
davidprentice | 0:8ee30e15ac7b | 2306 | } |
davidprentice | 0:8ee30e15ac7b | 2307 | } |
davidprentice | 0:8ee30e15ac7b | 2308 | |
davidprentice | 0:8ee30e15ac7b | 2309 | // Edge rejection (no-draw if totally off canvas) |
davidprentice | 0:8ee30e15ac7b | 2310 | if ((y < 0) || (y >= height()) || (x >= width()) || ((x + w - 1) < 0)) { |
davidprentice | 0:8ee30e15ac7b | 2311 | return; |
davidprentice | 0:8ee30e15ac7b | 2312 | } |
davidprentice | 0:8ee30e15ac7b | 2313 | |
davidprentice | 0:8ee30e15ac7b | 2314 | if (x < 0) { // Clip left |
davidprentice | 0:8ee30e15ac7b | 2315 | w += x; |
davidprentice | 0:8ee30e15ac7b | 2316 | x = 0; |
davidprentice | 0:8ee30e15ac7b | 2317 | } |
davidprentice | 0:8ee30e15ac7b | 2318 | if (x + w >= width()) { // Clip right |
davidprentice | 0:8ee30e15ac7b | 2319 | w = width() - x; |
davidprentice | 0:8ee30e15ac7b | 2320 | } |
davidprentice | 0:8ee30e15ac7b | 2321 | |
davidprentice | 0:8ee30e15ac7b | 2322 | if (getRotation() == 0) { |
davidprentice | 0:8ee30e15ac7b | 2323 | drawFastRawHLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 2324 | } else if (getRotation() == 1) { |
davidprentice | 0:8ee30e15ac7b | 2325 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 2326 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2327 | y = t; |
davidprentice | 0:8ee30e15ac7b | 2328 | drawFastRawVLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 2329 | } else if (getRotation() == 2) { |
davidprentice | 0:8ee30e15ac7b | 2330 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 2331 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2332 | |
davidprentice | 0:8ee30e15ac7b | 2333 | x -= w - 1; |
davidprentice | 0:8ee30e15ac7b | 2334 | drawFastRawHLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 2335 | } else if (getRotation() == 3) { |
davidprentice | 0:8ee30e15ac7b | 2336 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 2337 | x = y; |
davidprentice | 0:8ee30e15ac7b | 2338 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 2339 | y -= w - 1; |
davidprentice | 0:8ee30e15ac7b | 2340 | drawFastRawVLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 2341 | } |
davidprentice | 0:8ee30e15ac7b | 2342 | } |
davidprentice | 0:8ee30e15ac7b | 2343 | |
davidprentice | 0:8ee30e15ac7b | 2344 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2345 | /*! |
davidprentice | 0:8ee30e15ac7b | 2346 | @brief Speed optimized vertical line drawing into the raw canvas buffer |
davidprentice | 0:8ee30e15ac7b | 2347 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2348 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2349 | @param h length of vertical line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 2350 | @param color 8-bit Color to fill with. Only lower byte of uint16_t is |
davidprentice | 0:8ee30e15ac7b | 2351 | used. |
davidprentice | 0:8ee30e15ac7b | 2352 | */ |
davidprentice | 0:8ee30e15ac7b | 2353 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2354 | void GFXcanvas8::drawFastRawVLine(int16_t x, int16_t y, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 2355 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2356 | // x & y already in raw (rotation 0) coordinates, no need to transform. |
davidprentice | 0:8ee30e15ac7b | 2357 | uint8_t *buffer_ptr = buffer + y * WIDTH + x; |
davidprentice | 0:8ee30e15ac7b | 2358 | for (int16_t i = 0; i < h; i++) { |
davidprentice | 0:8ee30e15ac7b | 2359 | (*buffer_ptr) = color; |
davidprentice | 0:8ee30e15ac7b | 2360 | buffer_ptr += WIDTH; |
davidprentice | 0:8ee30e15ac7b | 2361 | } |
davidprentice | 0:8ee30e15ac7b | 2362 | } |
davidprentice | 0:8ee30e15ac7b | 2363 | |
davidprentice | 0:8ee30e15ac7b | 2364 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2365 | /*! |
davidprentice | 0:8ee30e15ac7b | 2366 | @brief Speed optimized horizontal line drawing into the raw canvas buffer |
davidprentice | 0:8ee30e15ac7b | 2367 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2368 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2369 | @param w length of horizontal line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 2370 | @param color 8-bit Color to fill with. Only lower byte of uint16_t is |
davidprentice | 0:8ee30e15ac7b | 2371 | used. |
davidprentice | 0:8ee30e15ac7b | 2372 | */ |
davidprentice | 0:8ee30e15ac7b | 2373 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2374 | void GFXcanvas8::drawFastRawHLine(int16_t x, int16_t y, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 2375 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2376 | // x & y already in raw (rotation 0) coordinates, no need to transform. |
davidprentice | 0:8ee30e15ac7b | 2377 | memset(buffer + y * WIDTH + x, color, w); |
davidprentice | 0:8ee30e15ac7b | 2378 | } |
davidprentice | 0:8ee30e15ac7b | 2379 | |
davidprentice | 0:8ee30e15ac7b | 2380 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2381 | /*! |
davidprentice | 0:8ee30e15ac7b | 2382 | @brief Instatiate a GFX 16-bit canvas context for graphics |
davidprentice | 0:8ee30e15ac7b | 2383 | @param w Display width, in pixels |
davidprentice | 0:8ee30e15ac7b | 2384 | @param h Display height, in pixels |
davidprentice | 0:8ee30e15ac7b | 2385 | */ |
davidprentice | 0:8ee30e15ac7b | 2386 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2387 | GFXcanvas16::GFXcanvas16(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) { |
davidprentice | 0:8ee30e15ac7b | 2388 | uint32_t bytes = w * h * 2; |
davidprentice | 0:8ee30e15ac7b | 2389 | if ((buffer = (uint16_t *)malloc(bytes))) { |
davidprentice | 0:8ee30e15ac7b | 2390 | memset(buffer, 0, bytes); |
davidprentice | 0:8ee30e15ac7b | 2391 | } |
davidprentice | 0:8ee30e15ac7b | 2392 | } |
davidprentice | 0:8ee30e15ac7b | 2393 | |
davidprentice | 0:8ee30e15ac7b | 2394 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2395 | /*! |
davidprentice | 0:8ee30e15ac7b | 2396 | @brief Delete the canvas, free memory |
davidprentice | 0:8ee30e15ac7b | 2397 | */ |
davidprentice | 0:8ee30e15ac7b | 2398 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2399 | GFXcanvas16::~GFXcanvas16(void) { |
davidprentice | 0:8ee30e15ac7b | 2400 | if (buffer) |
davidprentice | 0:8ee30e15ac7b | 2401 | free(buffer); |
davidprentice | 0:8ee30e15ac7b | 2402 | } |
davidprentice | 0:8ee30e15ac7b | 2403 | |
davidprentice | 0:8ee30e15ac7b | 2404 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2405 | /*! |
davidprentice | 0:8ee30e15ac7b | 2406 | @brief Draw a pixel to the canvas framebuffer |
davidprentice | 0:8ee30e15ac7b | 2407 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 2408 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 2409 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 2410 | */ |
davidprentice | 0:8ee30e15ac7b | 2411 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2412 | void GFXcanvas16::drawPixel(int16_t x, int16_t y, uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2413 | if (buffer) { |
davidprentice | 0:8ee30e15ac7b | 2414 | if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) |
davidprentice | 0:8ee30e15ac7b | 2415 | return; |
davidprentice | 0:8ee30e15ac7b | 2416 | |
davidprentice | 0:8ee30e15ac7b | 2417 | int16_t t; |
davidprentice | 0:8ee30e15ac7b | 2418 | switch (rotation) { |
davidprentice | 0:8ee30e15ac7b | 2419 | case 1: |
davidprentice | 0:8ee30e15ac7b | 2420 | t = x; |
davidprentice | 0:8ee30e15ac7b | 2421 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2422 | y = t; |
davidprentice | 0:8ee30e15ac7b | 2423 | break; |
davidprentice | 0:8ee30e15ac7b | 2424 | case 2: |
davidprentice | 0:8ee30e15ac7b | 2425 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 2426 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2427 | break; |
davidprentice | 0:8ee30e15ac7b | 2428 | case 3: |
davidprentice | 0:8ee30e15ac7b | 2429 | t = x; |
davidprentice | 0:8ee30e15ac7b | 2430 | x = y; |
davidprentice | 0:8ee30e15ac7b | 2431 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 2432 | break; |
davidprentice | 0:8ee30e15ac7b | 2433 | } |
davidprentice | 0:8ee30e15ac7b | 2434 | |
davidprentice | 0:8ee30e15ac7b | 2435 | buffer[x + y * WIDTH] = color; |
davidprentice | 0:8ee30e15ac7b | 2436 | } |
davidprentice | 0:8ee30e15ac7b | 2437 | } |
davidprentice | 0:8ee30e15ac7b | 2438 | |
davidprentice | 0:8ee30e15ac7b | 2439 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2440 | /*! |
davidprentice | 0:8ee30e15ac7b | 2441 | @brief Get the pixel color value at a given coordinate |
davidprentice | 0:8ee30e15ac7b | 2442 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 2443 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 2444 | @returns The desired pixel's 16-bit 5-6-5 color value |
davidprentice | 0:8ee30e15ac7b | 2445 | */ |
davidprentice | 0:8ee30e15ac7b | 2446 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2447 | uint16_t GFXcanvas16::getPixel(int16_t x, int16_t y) const { |
davidprentice | 0:8ee30e15ac7b | 2448 | int16_t t; |
davidprentice | 0:8ee30e15ac7b | 2449 | switch (rotation) { |
davidprentice | 0:8ee30e15ac7b | 2450 | case 1: |
davidprentice | 0:8ee30e15ac7b | 2451 | t = x; |
davidprentice | 0:8ee30e15ac7b | 2452 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2453 | y = t; |
davidprentice | 0:8ee30e15ac7b | 2454 | break; |
davidprentice | 0:8ee30e15ac7b | 2455 | case 2: |
davidprentice | 0:8ee30e15ac7b | 2456 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 2457 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2458 | break; |
davidprentice | 0:8ee30e15ac7b | 2459 | case 3: |
davidprentice | 0:8ee30e15ac7b | 2460 | t = x; |
davidprentice | 0:8ee30e15ac7b | 2461 | x = y; |
davidprentice | 0:8ee30e15ac7b | 2462 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 2463 | break; |
davidprentice | 0:8ee30e15ac7b | 2464 | } |
davidprentice | 0:8ee30e15ac7b | 2465 | return getRawPixel(x, y); |
davidprentice | 0:8ee30e15ac7b | 2466 | } |
davidprentice | 0:8ee30e15ac7b | 2467 | |
davidprentice | 0:8ee30e15ac7b | 2468 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2469 | /*! |
davidprentice | 0:8ee30e15ac7b | 2470 | @brief Get the pixel color value at a given, unrotated coordinate. |
davidprentice | 0:8ee30e15ac7b | 2471 | This method is intended for hardware drivers to get pixel value |
davidprentice | 0:8ee30e15ac7b | 2472 | in physical coordinates. |
davidprentice | 0:8ee30e15ac7b | 2473 | @param x x coordinate |
davidprentice | 0:8ee30e15ac7b | 2474 | @param y y coordinate |
davidprentice | 0:8ee30e15ac7b | 2475 | @returns The desired pixel's 16-bit 5-6-5 color value |
davidprentice | 0:8ee30e15ac7b | 2476 | */ |
davidprentice | 0:8ee30e15ac7b | 2477 | /**********************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2478 | uint16_t GFXcanvas16::getRawPixel(int16_t x, int16_t y) const { |
davidprentice | 0:8ee30e15ac7b | 2479 | if ((x < 0) || (y < 0) || (x >= WIDTH) || (y >= HEIGHT)) |
davidprentice | 0:8ee30e15ac7b | 2480 | return 0; |
davidprentice | 0:8ee30e15ac7b | 2481 | if (buffer) { |
davidprentice | 0:8ee30e15ac7b | 2482 | return buffer[x + y * WIDTH]; |
davidprentice | 0:8ee30e15ac7b | 2483 | } |
davidprentice | 0:8ee30e15ac7b | 2484 | return 0; |
davidprentice | 0:8ee30e15ac7b | 2485 | } |
davidprentice | 0:8ee30e15ac7b | 2486 | |
davidprentice | 0:8ee30e15ac7b | 2487 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2488 | /*! |
davidprentice | 0:8ee30e15ac7b | 2489 | @brief Fill the framebuffer completely with one color |
davidprentice | 0:8ee30e15ac7b | 2490 | @param color 16-bit 5-6-5 Color to fill with |
davidprentice | 0:8ee30e15ac7b | 2491 | */ |
davidprentice | 0:8ee30e15ac7b | 2492 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2493 | void GFXcanvas16::fillScreen(uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2494 | if (buffer) { |
davidprentice | 0:8ee30e15ac7b | 2495 | uint8_t hi = color >> 8, lo = color & 0xFF; |
davidprentice | 0:8ee30e15ac7b | 2496 | if (hi == lo) { |
davidprentice | 0:8ee30e15ac7b | 2497 | memset(buffer, lo, WIDTH * HEIGHT * 2); |
davidprentice | 0:8ee30e15ac7b | 2498 | } else { |
davidprentice | 0:8ee30e15ac7b | 2499 | uint32_t i, pixels = WIDTH * HEIGHT; |
davidprentice | 0:8ee30e15ac7b | 2500 | for (i = 0; i < pixels; i++) |
davidprentice | 0:8ee30e15ac7b | 2501 | buffer[i] = color; |
davidprentice | 0:8ee30e15ac7b | 2502 | } |
davidprentice | 0:8ee30e15ac7b | 2503 | } |
davidprentice | 0:8ee30e15ac7b | 2504 | } |
davidprentice | 0:8ee30e15ac7b | 2505 | |
davidprentice | 0:8ee30e15ac7b | 2506 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2507 | /*! |
davidprentice | 0:8ee30e15ac7b | 2508 | @brief Reverses the "endian-ness" of each 16-bit pixel within the |
davidprentice | 0:8ee30e15ac7b | 2509 | canvas; little-endian to big-endian, or big-endian to little. |
davidprentice | 0:8ee30e15ac7b | 2510 | Most microcontrollers (such as SAMD) are little-endian, while |
davidprentice | 0:8ee30e15ac7b | 2511 | most displays tend toward big-endianness. All the drawing |
davidprentice | 0:8ee30e15ac7b | 2512 | functions (including RGB bitmap drawing) take care of this |
davidprentice | 0:8ee30e15ac7b | 2513 | automatically, but some specialized code (usually involving |
davidprentice | 0:8ee30e15ac7b | 2514 | DMA) can benefit from having pixel data already in the |
davidprentice | 0:8ee30e15ac7b | 2515 | display-native order. Note that this does NOT convert to a |
davidprentice | 0:8ee30e15ac7b | 2516 | SPECIFIC endian-ness, it just flips the bytes within each word. |
davidprentice | 0:8ee30e15ac7b | 2517 | */ |
davidprentice | 0:8ee30e15ac7b | 2518 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2519 | void GFXcanvas16::byteSwap(void) { |
davidprentice | 0:8ee30e15ac7b | 2520 | if (buffer) { |
davidprentice | 0:8ee30e15ac7b | 2521 | uint32_t i, pixels = WIDTH * HEIGHT; |
davidprentice | 0:8ee30e15ac7b | 2522 | for (i = 0; i < pixels; i++) |
davidprentice | 0:8ee30e15ac7b | 2523 | buffer[i] = __builtin_bswap16(buffer[i]); |
davidprentice | 0:8ee30e15ac7b | 2524 | } |
davidprentice | 0:8ee30e15ac7b | 2525 | } |
davidprentice | 0:8ee30e15ac7b | 2526 | |
davidprentice | 0:8ee30e15ac7b | 2527 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2528 | /*! |
davidprentice | 0:8ee30e15ac7b | 2529 | @brief Speed optimized vertical line drawing |
davidprentice | 0:8ee30e15ac7b | 2530 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2531 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2532 | @param h length of vertical line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 2533 | @param color color 16-bit 5-6-5 Color to draw line with |
davidprentice | 0:8ee30e15ac7b | 2534 | */ |
davidprentice | 0:8ee30e15ac7b | 2535 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2536 | void GFXcanvas16::drawFastVLine(int16_t x, int16_t y, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 2537 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2538 | if (h < 0) { // Convert negative heights to positive equivalent |
davidprentice | 0:8ee30e15ac7b | 2539 | h *= -1; |
davidprentice | 0:8ee30e15ac7b | 2540 | y -= h - 1; |
davidprentice | 0:8ee30e15ac7b | 2541 | if (y < 0) { |
davidprentice | 0:8ee30e15ac7b | 2542 | h += y; |
davidprentice | 0:8ee30e15ac7b | 2543 | y = 0; |
davidprentice | 0:8ee30e15ac7b | 2544 | } |
davidprentice | 0:8ee30e15ac7b | 2545 | } |
davidprentice | 0:8ee30e15ac7b | 2546 | |
davidprentice | 0:8ee30e15ac7b | 2547 | // Edge rejection (no-draw if totally off canvas) |
davidprentice | 0:8ee30e15ac7b | 2548 | if ((x < 0) || (x >= width()) || (y >= height()) || ((y + h - 1) < 0)) { |
davidprentice | 0:8ee30e15ac7b | 2549 | return; |
davidprentice | 0:8ee30e15ac7b | 2550 | } |
davidprentice | 0:8ee30e15ac7b | 2551 | |
davidprentice | 0:8ee30e15ac7b | 2552 | if (y < 0) { // Clip top |
davidprentice | 0:8ee30e15ac7b | 2553 | h += y; |
davidprentice | 0:8ee30e15ac7b | 2554 | y = 0; |
davidprentice | 0:8ee30e15ac7b | 2555 | } |
davidprentice | 0:8ee30e15ac7b | 2556 | if (y + h > height()) { // Clip bottom |
davidprentice | 0:8ee30e15ac7b | 2557 | h = height() - y; |
davidprentice | 0:8ee30e15ac7b | 2558 | } |
davidprentice | 0:8ee30e15ac7b | 2559 | |
davidprentice | 0:8ee30e15ac7b | 2560 | if (getRotation() == 0) { |
davidprentice | 0:8ee30e15ac7b | 2561 | drawFastRawVLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 2562 | } else if (getRotation() == 1) { |
davidprentice | 0:8ee30e15ac7b | 2563 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 2564 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2565 | y = t; |
davidprentice | 0:8ee30e15ac7b | 2566 | x -= h - 1; |
davidprentice | 0:8ee30e15ac7b | 2567 | drawFastRawHLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 2568 | } else if (getRotation() == 2) { |
davidprentice | 0:8ee30e15ac7b | 2569 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 2570 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2571 | |
davidprentice | 0:8ee30e15ac7b | 2572 | y -= h - 1; |
davidprentice | 0:8ee30e15ac7b | 2573 | drawFastRawVLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 2574 | } else if (getRotation() == 3) { |
davidprentice | 0:8ee30e15ac7b | 2575 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 2576 | x = y; |
davidprentice | 0:8ee30e15ac7b | 2577 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 2578 | drawFastRawHLine(x, y, h, color); |
davidprentice | 0:8ee30e15ac7b | 2579 | } |
davidprentice | 0:8ee30e15ac7b | 2580 | } |
davidprentice | 0:8ee30e15ac7b | 2581 | |
davidprentice | 0:8ee30e15ac7b | 2582 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2583 | /*! |
davidprentice | 0:8ee30e15ac7b | 2584 | @brief Speed optimized horizontal line drawing |
davidprentice | 0:8ee30e15ac7b | 2585 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2586 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2587 | @param w Length of horizontal line to be drawn, including 1st point |
davidprentice | 0:8ee30e15ac7b | 2588 | @param color Color 16-bit 5-6-5 Color to draw line with |
davidprentice | 0:8ee30e15ac7b | 2589 | */ |
davidprentice | 0:8ee30e15ac7b | 2590 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2591 | void GFXcanvas16::drawFastHLine(int16_t x, int16_t y, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 2592 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2593 | if (w < 0) { // Convert negative widths to positive equivalent |
davidprentice | 0:8ee30e15ac7b | 2594 | w *= -1; |
davidprentice | 0:8ee30e15ac7b | 2595 | x -= w - 1; |
davidprentice | 0:8ee30e15ac7b | 2596 | if (x < 0) { |
davidprentice | 0:8ee30e15ac7b | 2597 | w += x; |
davidprentice | 0:8ee30e15ac7b | 2598 | x = 0; |
davidprentice | 0:8ee30e15ac7b | 2599 | } |
davidprentice | 0:8ee30e15ac7b | 2600 | } |
davidprentice | 0:8ee30e15ac7b | 2601 | |
davidprentice | 0:8ee30e15ac7b | 2602 | // Edge rejection (no-draw if totally off canvas) |
davidprentice | 0:8ee30e15ac7b | 2603 | if ((y < 0) || (y >= height()) || (x >= width()) || ((x + w - 1) < 0)) { |
davidprentice | 0:8ee30e15ac7b | 2604 | return; |
davidprentice | 0:8ee30e15ac7b | 2605 | } |
davidprentice | 0:8ee30e15ac7b | 2606 | |
davidprentice | 0:8ee30e15ac7b | 2607 | if (x < 0) { // Clip left |
davidprentice | 0:8ee30e15ac7b | 2608 | w += x; |
davidprentice | 0:8ee30e15ac7b | 2609 | x = 0; |
davidprentice | 0:8ee30e15ac7b | 2610 | } |
davidprentice | 0:8ee30e15ac7b | 2611 | if (x + w >= width()) { // Clip right |
davidprentice | 0:8ee30e15ac7b | 2612 | w = width() - x; |
davidprentice | 0:8ee30e15ac7b | 2613 | } |
davidprentice | 0:8ee30e15ac7b | 2614 | |
davidprentice | 0:8ee30e15ac7b | 2615 | if (getRotation() == 0) { |
davidprentice | 0:8ee30e15ac7b | 2616 | drawFastRawHLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 2617 | } else if (getRotation() == 1) { |
davidprentice | 0:8ee30e15ac7b | 2618 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 2619 | x = WIDTH - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2620 | y = t; |
davidprentice | 0:8ee30e15ac7b | 2621 | drawFastRawVLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 2622 | } else if (getRotation() == 2) { |
davidprentice | 0:8ee30e15ac7b | 2623 | x = WIDTH - 1 - x; |
davidprentice | 0:8ee30e15ac7b | 2624 | y = HEIGHT - 1 - y; |
davidprentice | 0:8ee30e15ac7b | 2625 | |
davidprentice | 0:8ee30e15ac7b | 2626 | x -= w - 1; |
davidprentice | 0:8ee30e15ac7b | 2627 | drawFastRawHLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 2628 | } else if (getRotation() == 3) { |
davidprentice | 0:8ee30e15ac7b | 2629 | int16_t t = x; |
davidprentice | 0:8ee30e15ac7b | 2630 | x = y; |
davidprentice | 0:8ee30e15ac7b | 2631 | y = HEIGHT - 1 - t; |
davidprentice | 0:8ee30e15ac7b | 2632 | y -= w - 1; |
davidprentice | 0:8ee30e15ac7b | 2633 | drawFastRawVLine(x, y, w, color); |
davidprentice | 0:8ee30e15ac7b | 2634 | } |
davidprentice | 0:8ee30e15ac7b | 2635 | } |
davidprentice | 0:8ee30e15ac7b | 2636 | |
davidprentice | 0:8ee30e15ac7b | 2637 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2638 | /*! |
davidprentice | 0:8ee30e15ac7b | 2639 | @brief Speed optimized vertical line drawing into the raw canvas buffer |
davidprentice | 0:8ee30e15ac7b | 2640 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2641 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2642 | @param h length of vertical line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 2643 | @param color color 16-bit 5-6-5 Color to draw line with |
davidprentice | 0:8ee30e15ac7b | 2644 | */ |
davidprentice | 0:8ee30e15ac7b | 2645 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2646 | void GFXcanvas16::drawFastRawVLine(int16_t x, int16_t y, int16_t h, |
davidprentice | 0:8ee30e15ac7b | 2647 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2648 | // x & y already in raw (rotation 0) coordinates, no need to transform. |
davidprentice | 0:8ee30e15ac7b | 2649 | uint16_t *buffer_ptr = buffer + y * WIDTH + x; |
davidprentice | 0:8ee30e15ac7b | 2650 | for (int16_t i = 0; i < h; i++) { |
davidprentice | 0:8ee30e15ac7b | 2651 | (*buffer_ptr) = color; |
davidprentice | 0:8ee30e15ac7b | 2652 | buffer_ptr += WIDTH; |
davidprentice | 0:8ee30e15ac7b | 2653 | } |
davidprentice | 0:8ee30e15ac7b | 2654 | } |
davidprentice | 0:8ee30e15ac7b | 2655 | |
davidprentice | 0:8ee30e15ac7b | 2656 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2657 | /*! |
davidprentice | 0:8ee30e15ac7b | 2658 | @brief Speed optimized horizontal line drawing into the raw canvas buffer |
davidprentice | 0:8ee30e15ac7b | 2659 | @param x Line horizontal start point |
davidprentice | 0:8ee30e15ac7b | 2660 | @param y Line vertical start point |
davidprentice | 0:8ee30e15ac7b | 2661 | @param w length of horizontal line to be drawn, including first point |
davidprentice | 0:8ee30e15ac7b | 2662 | @param color color 16-bit 5-6-5 Color to draw line with |
davidprentice | 0:8ee30e15ac7b | 2663 | */ |
davidprentice | 0:8ee30e15ac7b | 2664 | /**************************************************************************/ |
davidprentice | 0:8ee30e15ac7b | 2665 | void GFXcanvas16::drawFastRawHLine(int16_t x, int16_t y, int16_t w, |
davidprentice | 0:8ee30e15ac7b | 2666 | uint16_t color) { |
davidprentice | 0:8ee30e15ac7b | 2667 | // x & y already in raw (rotation 0) coordinates, no need to transform. |
davidprentice | 0:8ee30e15ac7b | 2668 | uint32_t buffer_index = y * WIDTH + x; |
davidprentice | 0:8ee30e15ac7b | 2669 | for (uint32_t i = buffer_index; i < buffer_index + w; i++) { |
davidprentice | 0:8ee30e15ac7b | 2670 | buffer[i] = color; |
davidprentice | 0:8ee30e15ac7b | 2671 | } |
davidprentice | 0:8ee30e15ac7b | 2672 | } |