Adafruit_GFX.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /***********************************
  2. This is a our graphics core library, for all our displays.
  3. We'll be adapting all the
  4. existing libaries to use this core to make updating, support
  5. and upgrading easier!
  6. Adafruit invests time and resources providing this open source code,
  7. please support Adafruit and open-source hardware by purchasing
  8. products from Adafruit!
  9. Written by Limor Fried/Ladyada for Adafruit Industries.
  10. BSD license, check license.txt for more information
  11. All text above must be included in any redistribution
  12. ****************************************/
  13. #include "Adafruit_GFX.h"
  14. #include "glcdfont.c"
  15. #include <avr/pgmspace.h>
  16. void Adafruit_GFX::constructor(uint16_t w, uint16_t h) {
  17. _width = WIDTH = w;
  18. _height = HEIGHT = h;
  19. rotation = 0;
  20. cursor_y = cursor_x = 0;
  21. textsize = 1;
  22. textcolor = 0xFFFF;
  23. textbgcolor = 0x0000;
  24. }
  25. // draw a circle outline
  26. void Adafruit_GFX::drawCircle(uint16_t x0, uint16_t y0, uint16_t r,
  27. uint16_t color) {
  28. int16_t f = 1 - r;
  29. int16_t ddF_x = 1;
  30. int16_t ddF_y = -2 * r;
  31. int16_t x = 0;
  32. int16_t y = r;
  33. drawPixel(x0, y0+r, color);
  34. drawPixel(x0, y0-r, color);
  35. drawPixel(x0+r, y0, color);
  36. drawPixel(x0-r, y0, color);
  37. while (x<y) {
  38. if (f >= 0) {
  39. y--;
  40. ddF_y += 2;
  41. f += ddF_y;
  42. }
  43. x++;
  44. ddF_x += 2;
  45. f += ddF_x;
  46. drawPixel(x0 + x, y0 + y, color);
  47. drawPixel(x0 - x, y0 + y, color);
  48. drawPixel(x0 + x, y0 - y, color);
  49. drawPixel(x0 - x, y0 - y, color);
  50. drawPixel(x0 + y, y0 + x, color);
  51. drawPixel(x0 - y, y0 + x, color);
  52. drawPixel(x0 + y, y0 - x, color);
  53. drawPixel(x0 - y, y0 - x, color);
  54. }
  55. }
  56. void Adafruit_GFX::drawCircleHelper(uint16_t x0, uint16_t y0,
  57. uint16_t r, uint8_t cornername, uint16_t color) {
  58. int16_t f = 1 - r;
  59. int16_t ddF_x = 1;
  60. int16_t ddF_y = -2 * r;
  61. int16_t x = 0;
  62. int16_t y = r;
  63. while (x<y) {
  64. if (f >= 0) {
  65. y--;
  66. ddF_y += 2;
  67. f += ddF_y;
  68. }
  69. x++;
  70. ddF_x += 2;
  71. f += ddF_x;
  72. if (cornername & 0x4) {
  73. drawPixel(x0 + x, y0 + y, color);
  74. drawPixel(x0 + y, y0 + x, color);
  75. }
  76. if (cornername & 0x2) {
  77. drawPixel(x0 + x, y0 - y, color);
  78. drawPixel(x0 + y, y0 - x, color);
  79. }
  80. if (cornername & 0x8) {
  81. drawPixel(x0 - y, y0 + x, color);
  82. drawPixel(x0 - x, y0 + y, color);
  83. }
  84. if (cornername & 0x1) {
  85. drawPixel(x0 - y, y0 - x, color);
  86. drawPixel(x0 - x, y0 - y, color);
  87. }
  88. }
  89. }
  90. void Adafruit_GFX::fillCircle(uint16_t x0, uint16_t y0, uint16_t r,
  91. uint16_t color) {
  92. drawFastVLine(x0, y0-r, 2*r+1, color);
  93. fillCircleHelper(x0, y0, r, 3, 0, color);
  94. }
  95. // used to do circles and roundrects!
  96. void Adafruit_GFX::fillCircleHelper(uint16_t x0, uint16_t y0, uint16_t r,
  97. uint8_t cornername, uint16_t delta, uint16_t color) {
  98. int16_t f = 1 - r;
  99. int16_t ddF_x = 1;
  100. int16_t ddF_y = -2 * r;
  101. int16_t x = 0;
  102. int16_t y = r;
  103. while (x<y) {
  104. if (f >= 0) {
  105. y--;
  106. ddF_y += 2;
  107. f += ddF_y;
  108. }
  109. x++;
  110. ddF_x += 2;
  111. f += ddF_x;
  112. if (cornername & 0x1) {
  113. drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
  114. drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
  115. }
  116. if (cornername & 0x2) {
  117. drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
  118. drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
  119. }
  120. }
  121. }
  122. // bresenham's algorithm - thx wikpedia
  123. void Adafruit_GFX::drawLine(int16_t x0, int16_t y0,
  124. int16_t x1, int16_t y1,
  125. uint16_t color) {
  126. int16_t steep = abs(y1 - y0) > abs(x1 - x0);
  127. if (steep) {
  128. swap(x0, y0);
  129. swap(x1, y1);
  130. }
  131. if (x0 > x1) {
  132. swap(x0, x1);
  133. swap(y0, y1);
  134. }
  135. int16_t dx, dy;
  136. dx = x1 - x0;
  137. dy = abs(y1 - y0);
  138. int16_t err = dx / 2;
  139. int16_t ystep;
  140. if (y0 < y1) {
  141. ystep = 1;
  142. } else {
  143. ystep = -1;
  144. }
  145. for (; x0<=x1; x0++) {
  146. if (steep) {
  147. drawPixel(y0, x0, color);
  148. } else {
  149. drawPixel(x0, y0, color);
  150. }
  151. err -= dy;
  152. if (err < 0) {
  153. y0 += ystep;
  154. err += dx;
  155. }
  156. }
  157. }
  158. // draw a rectangle
  159. void Adafruit_GFX::drawRect(uint16_t x, uint16_t y,
  160. uint16_t w, uint16_t h,
  161. uint16_t color) {
  162. drawFastHLine(x, y, w, color);
  163. drawFastHLine(x, y+h-1, w, color);
  164. drawFastVLine(x, y, h, color);
  165. drawFastVLine(x+w-1, y, h, color);
  166. }
  167. void Adafruit_GFX::drawFastVLine(uint16_t x, uint16_t y,
  168. uint16_t h, uint16_t color) {
  169. // stupidest version - update in subclasses if desired!
  170. drawLine(x, y, x, y+h-1, color);
  171. }
  172. void Adafruit_GFX::drawFastHLine(uint16_t x, uint16_t y,
  173. uint16_t w, uint16_t color) {
  174. // stupidest version - update in subclasses if desired!
  175. drawLine(x, y, x+w-1, y, color);
  176. }
  177. void Adafruit_GFX::fillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h,
  178. uint16_t color) {
  179. // stupidest version - update in subclasses if desired!
  180. for (uint16_t i=x; i<x+w; i++) {
  181. drawFastVLine(i, y, h, color);
  182. }
  183. }
  184. void Adafruit_GFX::fillScreen(uint16_t color) {
  185. fillRect(0, 0, _width, _height, color);
  186. }
  187. // draw a rounded rectangle!
  188. void Adafruit_GFX::drawRoundRect(uint16_t x, uint16_t y, uint16_t w,
  189. uint16_t h, uint16_t r, uint16_t color) {
  190. // smarter version
  191. drawFastHLine(x+r , y , w-2*r, color); // Top
  192. drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
  193. drawFastVLine( x , y+r , h-2*r, color); // Left
  194. drawFastVLine( x+w-1, y+r , h-2*r, color); // Right
  195. // draw four corners
  196. drawCircleHelper(x+r , y+r , r, 1, color);
  197. drawCircleHelper(x+w-r-1, y+r , r, 2, color);
  198. drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
  199. drawCircleHelper(x+r , y+h-r-1, r, 8, color);
  200. }
  201. // fill a rounded rectangle!
  202. void Adafruit_GFX::fillRoundRect(uint16_t x, uint16_t y, uint16_t w,
  203. uint16_t h, uint16_t r, uint16_t color) {
  204. // smarter version
  205. fillRect(x+r, y, w-2*r, h, color);
  206. // draw four corners
  207. fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
  208. fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
  209. }
  210. // draw a triangle!
  211. void Adafruit_GFX::drawTriangle(uint16_t x0, uint16_t y0,
  212. uint16_t x1, uint16_t y1,
  213. uint16_t x2, uint16_t y2, uint16_t color) {
  214. drawLine(x0, y0, x1, y1, color);
  215. drawLine(x1, y1, x2, y2, color);
  216. drawLine(x2, y2, x0, y0, color);
  217. }
  218. // fill a triangle!
  219. void Adafruit_GFX::fillTriangle ( uint16_t x0, uint16_t y0,
  220. uint16_t x1, uint16_t y1,
  221. uint16_t x2, uint16_t y2, uint16_t color) {
  222. int16_t a, b, y, last;
  223. // Sort coordinates by Y order (y2 >= y1 >= y0)
  224. if (y0 > y1) {
  225. swap(y0, y1); swap(x0, x1);
  226. }
  227. if (y1 > y2) {
  228. swap(y2, y1); swap(x2, x1);
  229. }
  230. if (y0 > y1) {
  231. swap(y0, y1); swap(x0, x1);
  232. }
  233. if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
  234. a = b = x0;
  235. if(x1 < a) a = x1;
  236. else if(x1 > b) b = x1;
  237. if(x2 < a) a = x2;
  238. else if(x2 > b) b = x2;
  239. drawFastHLine(a, y0, b-a+1, color);
  240. return;
  241. }
  242. int16_t
  243. dx01 = x1 - x0,
  244. dy01 = y1 - y0,
  245. dx02 = x2 - x0,
  246. dy02 = y2 - y0,
  247. dx12 = x2 - x1,
  248. dy12 = y2 - y1,
  249. sa = 0,
  250. sb = 0;
  251. // For upper part of triangle, find scanline crossings for segments
  252. // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
  253. // is included here (and second loop will be skipped, avoiding a /0
  254. // error there), otherwise scanline y1 is skipped here and handled
  255. // in the second loop...which also avoids a /0 error here if y0=y1
  256. // (flat-topped triangle).
  257. if(y1 == y2) last = y1; // Include y1 scanline
  258. else last = y1-1; // Skip it
  259. for(y=y0; y<=last; y++) {
  260. a = x0 + sa / dy01;
  261. b = x0 + sb / dy02;
  262. sa += dx01;
  263. sb += dx02;
  264. /* longhand:
  265. a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
  266. b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
  267. */
  268. if(a > b) swap(a,b);
  269. drawFastHLine(a, y, b-a+1, color);
  270. }
  271. // For lower part of triangle, find scanline crossings for segments
  272. // 0-2 and 1-2. This loop is skipped if y1=y2.
  273. sa = dx12 * (y - y1);
  274. sb = dx02 * (y - y0);
  275. for(; y<=y2; y++) {
  276. a = x1 + sa / dy12;
  277. b = x0 + sb / dy02;
  278. sa += dx12;
  279. sb += dx02;
  280. /* longhand:
  281. a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
  282. b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
  283. */
  284. if(a > b) swap(a,b);
  285. drawFastHLine(a, y, b-a+1, color);
  286. }
  287. }
  288. void Adafruit_GFX::drawBitmap(uint16_t x, uint16_t y,
  289. const uint8_t *bitmap, uint16_t w, uint16_t h,
  290. uint16_t color) {
  291. for (uint16_t j=0; j<h; j++) {
  292. for (uint16_t i=0; i<w; i++ ) {
  293. if (pgm_read_byte(bitmap + i + (j/8)*w) & _BV(j%8)) {
  294. drawPixel(x+i, y+j, color);
  295. }
  296. }
  297. }
  298. }
  299. #if ARDUINO >= 100
  300. size_t Adafruit_GFX::write(uint8_t c) {
  301. #else
  302. void Adafruit_GFX::write(uint8_t c) {
  303. #endif
  304. if (c == '\n') {
  305. cursor_y += textsize*8;
  306. cursor_x = 0;
  307. } else if (c == '\r') {
  308. // skip em
  309. } else {
  310. drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
  311. cursor_x += textsize*6;
  312. if (cursor_x > (width() - textsize*6)) {
  313. cursor_y += textsize*8;
  314. cursor_x = 0;
  315. }
  316. }
  317. #if ARDUINO >= 100
  318. return 1;
  319. #endif
  320. }
  321. // draw a character
  322. void Adafruit_GFX::drawChar(uint16_t x, uint16_t y, char c,
  323. uint16_t color, uint16_t bg, uint8_t size) {
  324. for (uint8_t i=0; i<6; i++ ) {
  325. uint8_t line;
  326. if (i == 5)
  327. line = 0x0;
  328. else
  329. line = pgm_read_byte(font+(c*5)+i);
  330. for (uint8_t j = 0; j<8; j++) {
  331. if (line & 0x1) {
  332. if (size == 1) // default size
  333. drawPixel(x+i, y+j, color);
  334. else { // big size
  335. fillRect(x+(i*size), y+(j*size), size, size, color);
  336. }
  337. } else if (bg != color) {
  338. if (size == 1) // default size
  339. drawPixel(x+i, y+j, bg);
  340. else { // big size
  341. fillRect(x+i*size, y+j*size, size, size, bg);
  342. }
  343. }
  344. line >>= 1;
  345. }
  346. }
  347. }
  348. void Adafruit_GFX::setCursor(uint16_t x, uint16_t y) {
  349. cursor_x = x;
  350. cursor_y = y;
  351. }
  352. void Adafruit_GFX::setTextSize(uint8_t s) {
  353. textsize = (s > 0) ? s : 1;
  354. }
  355. void Adafruit_GFX::setTextColor(uint16_t c) {
  356. textcolor = c;
  357. textbgcolor = c;
  358. // for 'transparent' background, we'll set the bg
  359. // to the same as fg instead of using a flag
  360. }
  361. void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
  362. textcolor = c;
  363. textbgcolor = b;
  364. }
  365. uint8_t Adafruit_GFX::getRotation(void) {
  366. rotation %= 4;
  367. return rotation;
  368. }
  369. void Adafruit_GFX::setRotation(uint8_t x) {
  370. x %= 4; // cant be higher than 3
  371. rotation = x;
  372. switch (x) {
  373. case 0:
  374. case 2:
  375. _width = WIDTH;
  376. _height = HEIGHT;
  377. break;
  378. case 1:
  379. case 3:
  380. _width = HEIGHT;
  381. _height = WIDTH;
  382. break;
  383. }
  384. }
  385. // return the size of the display which depends on the rotation!
  386. uint16_t Adafruit_GFX::width(void) {
  387. return _width;
  388. }
  389. uint16_t Adafruit_GFX::height(void) {
  390. return _height;
  391. }