source: rtos_arduino/trunk/arduino_lib/libraries/TFT/src/utility/Adafruit_GFX.cpp@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 16.8 KB
Line 
1/*
2This is the core graphics library for all our displays, providing a common
3set of graphics primitives (points, lines, circles, etc.). It needs to be
4paired with a hardware-specific library for each display device we carry
5(to handle the lower-level functions).
6
7Adafruit invests time and resources providing this open source code, please
8support Adafruit & open-source hardware by purchasing products from Adafruit!
9
10Copyright (c) 2013 Adafruit Industries. All rights reserved.
11
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14
15- Redistributions of source code must retain the above copyright notice,
16 this list of conditions and the following disclaimer.
17- Redistributions in binary form must reproduce the above copyright notice,
18 this list of conditions and the following disclaimer in the documentation
19 and/or other materials provided with the distribution.
20
21THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE.
32*/
33
34#include "Adafruit_GFX.h"
35#include "glcdfont.c"
36#ifdef __AVR__
37 #include <avr/pgmspace.h>
38#else
39 #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
40#endif
41
42Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h) :
43 WIDTH(w), HEIGHT(h)
44{
45 _width = WIDTH;
46 _height = HEIGHT;
47 rotation = 0;
48 cursor_y = cursor_x = 0;
49 textsize = 1;
50 textcolor = textbgcolor = 0xFFFF;
51 wrap = true;
52}
53
54// draw a circle outline
55void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
56 uint16_t color) {
57 int16_t f = 1 - r;
58 int16_t ddF_x = 1;
59 int16_t ddF_y = -2 * r;
60 int16_t x = 0;
61 int16_t y = r;
62
63 drawPixel(x0, y0+r, color);
64 drawPixel(x0, y0-r, color);
65 drawPixel(x0+r, y0, color);
66 drawPixel(x0-r, y0, color);
67
68 while (x<y) {
69 if (f >= 0) {
70 y--;
71 ddF_y += 2;
72 f += ddF_y;
73 }
74 x++;
75 ddF_x += 2;
76 f += ddF_x;
77
78 drawPixel(x0 + x, y0 + y, color);
79 drawPixel(x0 - x, y0 + y, color);
80 drawPixel(x0 + x, y0 - y, color);
81 drawPixel(x0 - x, y0 - y, color);
82 drawPixel(x0 + y, y0 + x, color);
83 drawPixel(x0 - y, y0 + x, color);
84 drawPixel(x0 + y, y0 - x, color);
85 drawPixel(x0 - y, y0 - x, color);
86 }
87}
88
89void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0,
90 int16_t r, uint8_t cornername, uint16_t color) {
91 int16_t f = 1 - r;
92 int16_t ddF_x = 1;
93 int16_t ddF_y = -2 * r;
94 int16_t x = 0;
95 int16_t y = r;
96
97 while (x<y) {
98 if (f >= 0) {
99 y--;
100 ddF_y += 2;
101 f += ddF_y;
102 }
103 x++;
104 ddF_x += 2;
105 f += ddF_x;
106 if (cornername & 0x4) {
107 drawPixel(x0 + x, y0 + y, color);
108 drawPixel(x0 + y, y0 + x, color);
109 }
110 if (cornername & 0x2) {
111 drawPixel(x0 + x, y0 - y, color);
112 drawPixel(x0 + y, y0 - x, color);
113 }
114 if (cornername & 0x8) {
115 drawPixel(x0 - y, y0 + x, color);
116 drawPixel(x0 - x, y0 + y, color);
117 }
118 if (cornername & 0x1) {
119 drawPixel(x0 - y, y0 - x, color);
120 drawPixel(x0 - x, y0 - y, color);
121 }
122 }
123}
124
125void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
126 uint16_t color)
127{
128 drawFastVLine(x0, y0-r, 2*r+1, color);
129 fillCircleHelper(x0, y0, r, 3, 0, color);
130}
131
132// used to do circles and roundrects
133void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
134 uint8_t cornername, int16_t delta, uint16_t color)
135{
136 int16_t f = 1 - r;
137 int16_t ddF_x = 1;
138 int16_t ddF_y = -2 * r;
139 int16_t x = 0;
140 int16_t y = r;
141
142 while (x<y) {
143 if (f >= 0) {
144 y--;
145 ddF_y += 2;
146 f += ddF_y;
147 }
148 x++;
149 ddF_x += 2;
150 f += ddF_x;
151
152 if (cornername & 0x1) {
153 drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
154 drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
155 }
156 if (cornername & 0x2) {
157 drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
158 drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
159 }
160 }
161}
162
163// Bresenham's algorithm - thx wikpedia
164void Adafruit_GFX::drawLine(int16_t x0, int16_t y0,
165 int16_t x1, int16_t y1,
166 uint16_t color)
167{
168 int16_t steep = abs(y1 - y0) > abs(x1 - x0);
169 if (steep) {
170 swap(x0, y0);
171 swap(x1, y1);
172 }
173
174 if (x0 > x1) {
175 swap(x0, x1);
176 swap(y0, y1);
177 }
178
179 int16_t dx, dy;
180 dx = x1 - x0;
181 dy = abs(y1 - y0);
182
183 int16_t err = dx / 2;
184 int16_t ystep;
185
186 if (y0 < y1) {
187 ystep = 1;
188 } else {
189 ystep = -1;
190 }
191
192 for (; x0<=x1; x0++) {
193 if (steep) {
194 drawPixel(y0, x0, color);
195 } else {
196 drawPixel(x0, y0, color);
197 }
198 err -= dy;
199 if (err < 0) {
200 y0 += ystep;
201 err += dx;
202 }
203 }
204}
205
206
207// Draw a rectangle
208void Adafruit_GFX::drawRect(int16_t x, int16_t y,
209 int16_t w, int16_t h,
210 uint16_t color)
211{
212 drawFastHLine(x, y, w, color);
213 drawFastHLine(x, y+h-1, w, color);
214 drawFastVLine(x, y, h, color);
215 drawFastVLine(x+w-1, y, h, color);
216}
217
218void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y,
219 int16_t h, uint16_t color)
220{
221 // Update in subclasses if desired!
222 drawLine(x, y, x, y+h-1, color);
223}
224
225
226void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y,
227 int16_t w, uint16_t color)
228{
229 // Update in subclasses if desired!
230 drawLine(x, y, x+w-1, y, color);
231}
232
233void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
234 uint16_t color)
235{
236 // Update in subclasses if desired!
237 for (int16_t i=x; i<x+w; i++) {
238 drawFastVLine(i, y, h, color);
239 }
240}
241
242
243void Adafruit_GFX::fillScreen(uint16_t color) {
244 fillRect(0, 0, _width, _height, color);
245}
246
247// Draw a rounded rectangle
248void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
249 int16_t h, int16_t r, uint16_t color)
250{
251 // smarter version
252 drawFastHLine(x+r , y , w-2*r, color); // Top
253 drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
254 drawFastVLine(x , y+r , h-2*r, color); // Left
255 drawFastVLine(x+w-1, y+r , h-2*r, color); // Right
256 // draw four corners
257 drawCircleHelper(x+r , y+r , r, 1, color);
258 drawCircleHelper(x+w-r-1, y+r , r, 2, color);
259 drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
260 drawCircleHelper(x+r , y+h-r-1, r, 8, color);
261}
262
263// Fill a rounded rectangle
264void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
265 int16_t h, int16_t r, uint16_t color)
266{
267 // smarter version
268 fillRect(x+r, y, w-2*r, h, color);
269
270 // draw four corners
271 fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
272 fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
273}
274
275// Draw a triangle
276void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0,
277 int16_t x1, int16_t y1,
278 int16_t x2, int16_t y2, uint16_t color) {
279 drawLine(x0, y0, x1, y1, color);
280 drawLine(x1, y1, x2, y2, color);
281 drawLine(x2, y2, x0, y0, color);
282}
283
284// Fill a triangle
285void Adafruit_GFX::fillTriangle ( int16_t x0, int16_t y0,
286 int16_t x1, int16_t y1,
287 int16_t x2, int16_t y2, uint16_t color) {
288 int16_t a, b, y, last;
289
290 // Sort coordinates by Y order (y2 >= y1 >= y0)
291 if (y0 > y1) {
292 swap(y0, y1); swap(x0, x1);
293 }
294 if (y1 > y2) {
295 swap(y2, y1); swap(x2, x1);
296 }
297 if (y0 > y1) {
298 swap(y0, y1); swap(x0, x1);
299 }
300
301 if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
302 a = b = x0;
303 if(x1 < a) a = x1;
304 else if(x1 > b) b = x1;
305 if(x2 < a) a = x2;
306 else if(x2 > b) b = x2;
307 drawFastHLine(a, y0, b-a+1, color);
308 return;
309 }
310
311 int16_t
312 dx01 = x1 - x0,
313 dy01 = y1 - y0,
314 dx02 = x2 - x0,
315 dy02 = y2 - y0,
316 dx12 = x2 - x1,
317 dy12 = y2 - y1,
318 sa = 0,
319 sb = 0;
320
321 // For upper part of triangle, find scanline crossings for segments
322 // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
323 // is included here (and second loop will be skipped, avoiding a /0
324 // error there), otherwise scanline y1 is skipped here and handled
325 // in the second loop...which also avoids a /0 error here if y0=y1
326 // (flat-topped triangle).
327 if(y1 == y2) last = y1; // Include y1 scanline
328 else last = y1-1; // Skip it
329
330 for(y=y0; y<=last; y++) {
331 a = x0 + sa / dy01;
332 b = x0 + sb / dy02;
333 sa += dx01;
334 sb += dx02;
335 /* longhand:
336 a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
337 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
338 */
339 if(a > b) swap(a,b);
340 drawFastHLine(a, y, b-a+1, color);
341 }
342
343 // For lower part of triangle, find scanline crossings for segments
344 // 0-2 and 1-2. This loop is skipped if y1=y2.
345 sa = dx12 * (y - y1);
346 sb = dx02 * (y - y0);
347 for(; y<=y2; y++) {
348 a = x1 + sa / dy12;
349 b = x0 + sb / dy02;
350 sa += dx12;
351 sb += dx02;
352 /* longhand:
353 a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
354 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
355 */
356 if(a > b) swap(a,b);
357 drawFastHLine(a, y, b-a+1, color);
358 }
359}
360
361void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
362 const uint8_t *bitmap, int16_t w, int16_t h,
363 uint16_t color)
364{
365 int16_t i, j, byteWidth = (w + 7) / 8;
366
367 for(j=0; j<h; j++) {
368 for(i=0; i<w; i++ ) {
369 if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
370 drawPixel(x+i, y+j, color);
371 }
372 }
373 }
374}
375
376
377#if ARDUINO >= 100
378size_t Adafruit_GFX::write(uint8_t c) {
379#else
380void Adafruit_GFX::write(uint8_t c) {
381#endif
382 if (c == '\n') {
383 cursor_y += textsize*8;
384 cursor_x = 0;
385 } else if (c == '\r') {
386 // skip em
387 } else {
388 drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
389 cursor_x += textsize*6;
390 if (wrap && (cursor_x > (_width - textsize*6))) {
391 cursor_y += textsize*8;
392 cursor_x = 0;
393 }
394 }
395#if ARDUINO >= 100
396 return 1;
397#endif
398}
399
400// draw a character
401void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
402 uint16_t color, uint16_t bg, uint8_t size)
403{
404 if((x >= _width) || // Clip right
405 (y >= _height) || // Clip bottom
406 ((x + 6 * size - 1) < 0) || // Clip left
407 ((y + 8 * size - 1) < 0)) // Clip top
408 return;
409
410 for (int8_t i=0; i<6; i++ ) {
411 uint8_t line;
412 if (i == 5)
413 line = 0x0;
414 else
415 line = pgm_read_byte(font+(c*5)+i);
416 for (int8_t j = 0; j<8; j++) {
417 if (line & 0x1) {
418 if (size == 1) // default size
419 drawPixel(x+i, y+j, color);
420 else { // big size
421 fillRect(x+(i*size), y+(j*size), size, size, color);
422 }
423 } else if (bg != color) {
424 if (size == 1) // default size
425 drawPixel(x+i, y+j, bg);
426 else { // big size
427 fillRect(x+i*size, y+j*size, size, size, bg);
428 }
429 }
430 line >>= 1;
431 }
432 }
433}
434
435void Adafruit_GFX::setCursor(int16_t x, int16_t y)
436{
437 cursor_x = x;
438 cursor_y = y;
439}
440
441
442void Adafruit_GFX::setTextSize(uint8_t s)
443{
444 textsize = (s > 0) ? s : 1;
445}
446
447
448void Adafruit_GFX::setTextColor(uint16_t c) {
449 textcolor = c;
450 textbgcolor = c;
451 // for 'transparent' background, we'll set the bg
452 // to the same as fg instead of using a flag
453}
454
455 void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b)
456{
457 textcolor = c;
458 textbgcolor = b;
459}
460
461void Adafruit_GFX::setTextWrap(boolean w)
462{
463 wrap = w;
464}
465
466uint8_t Adafruit_GFX::getRotation(void)
467{
468 return rotation;
469}
470
471void Adafruit_GFX::setRotation(uint8_t x)
472{
473 rotation = (x & 3);
474 switch (x) {
475 case 0:
476 case 2:
477 _width = WIDTH;
478 _height = HEIGHT;
479 break;
480 case 1:
481 case 3:
482 _width = HEIGHT;
483 _height = WIDTH;
484 break;
485 }
486}
487
488
489
490// return the size of the display (per current rotation)
491int16_t Adafruit_GFX::width(void)
492{
493 return _width;
494}
495
496int16_t Adafruit_GFX::height(void)
497{
498 return _height;
499}
500
501void Adafruit_GFX::invertDisplay(boolean i)
502{
503 // Do nothing, must be subclassed if supported
504}
505
506
507uint16_t Adafruit_GFX::newColor(uint8_t r, uint8_t g, uint8_t b)
508{
509 return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
510}
511
512void Adafruit_GFX::background(uint8_t red, uint8_t green, uint8_t blue)
513{
514 background(newColor(red, green, blue));
515}
516
517void Adafruit_GFX::background(color c) {
518 fillScreen(c);
519}
520
521void Adafruit_GFX::stroke(uint8_t red, uint8_t green, uint8_t blue)
522{
523 stroke(newColor(red, green, blue));
524}
525
526void Adafruit_GFX::stroke(color c)
527{
528 useStroke = true;
529 strokeColor = c;
530 setTextColor(c);
531}
532
533void Adafruit_GFX::noStroke()
534{
535 useStroke = false;
536}
537
538void Adafruit_GFX::noFill() {
539 useFill = false;
540}
541
542void Adafruit_GFX::fill(uint8_t red, uint8_t green, uint8_t blue)
543{
544 fill(newColor(red, green, blue));
545}
546
547void Adafruit_GFX::fill(color c)
548{
549 useFill = true;
550 fillColor = c;
551}
552
553
554void Adafruit_GFX::text(const char * text, int16_t x, int16_t y)
555{
556 if (!useStroke)
557 return;
558
559 setTextWrap(false);
560 setTextColor(strokeColor);
561 setCursor(x, y);
562 print(text);
563}
564
565void Adafruit_GFX::textWrap(const char * text, int16_t x, int16_t y)
566{
567 if (!useStroke)
568 return;
569
570 setTextWrap(true);
571 setTextColor(strokeColor);
572 setCursor(x, y);
573 print(text);
574}
575
576
577void Adafruit_GFX::textSize(uint8_t size)
578{
579 setTextSize(size);
580}
581
582void Adafruit_GFX::point(int16_t x, int16_t y)
583{
584 if (!useStroke)
585 return;
586
587 drawPixel(x, y, strokeColor);
588}
589
590void Adafruit_GFX::line(int16_t x1, int16_t y1, int16_t x2, int16_t y2)
591{
592 if (!useStroke)
593 return;
594
595 if (x1 == x2) {
596 if (y1 < y2)
597 drawFastVLine(x1, y1, y2 - y1, strokeColor);
598 else
599 drawFastVLine(x1, y2, y1 - y2, strokeColor);
600 }
601 else if (y1 == y2) {
602 if (x1 < x2)
603 drawFastHLine(x1, y1, x2 - x1, strokeColor);
604 else
605 drawFastHLine(x2, y1, x1 - x2, strokeColor);
606 }
607 else {
608 drawLine(x1, y1, x2, y2, strokeColor);
609 }
610}
611
612void Adafruit_GFX::rect(int16_t x, int16_t y, int16_t width, int16_t height)
613{
614 if (useFill) {
615 fillRect(x, y, width, height, fillColor);
616 }
617 if (useStroke) {
618 drawRect(x, y, width, height, strokeColor);
619 }
620}
621
622void Adafruit_GFX::rect(int16_t x, int16_t y, int16_t width, int16_t height, int16_t radius)
623{
624 if (radius == 0) {
625 rect(x, y, width, height);
626 }
627 if (useFill) {
628 fillRoundRect(x, y, width, height, radius, fillColor);
629 }
630 if (useStroke) {
631 drawRoundRect(x, y, width, height, radius, strokeColor);
632 }
633}
634
635void Adafruit_GFX::circle(int16_t x, int16_t y, int16_t r)
636{
637 if (r == 0)
638 return;
639
640 if (useFill) {
641 fillCircle(x, y, r, fillColor);
642 }
643 if (useStroke) {
644 drawCircle(x, y, r, strokeColor);
645 }
646}
647
648void Adafruit_GFX::triangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3)
649{
650 if (useFill) {
651 fillTriangle(x1, y1, x2, y2, x3, y3, fillColor);
652 }
653 if (useStroke) {
654 drawTriangle(x1, y1, x2, y2, x3, y3, strokeColor);
655 }
656}
657
658#if defined(__SD_H__) // Arduino SD library
659
660#define BUFFPIXEL 20
661
662void Adafruit_GFX::image(PImage & img, uint16_t x, uint16_t y) {
663 int w, h, row, col;
664 uint8_t r, g, b;
665 uint32_t pos = 0;
666 uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
667 uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
668
669 // Crop area to be loaded
670 w = img._bmpWidth;
671 h = img._bmpHeight;
672 if((x+w-1) >= width()) w = width() - x;
673 if((y+h-1) >= height()) h = height() - y;
674
675 /*
676 // Set TFT address window to clipped image bounds
677 setAddrWindow(x, y, x+w-1, y+h-1);
678 */
679
680 for (row=0; row<h; row++) { // For each scanline...
681 // Seek to start of scan line. It might seem labor-
682 // intensive to be doing this on every line, but this
683 // method covers a lot of gritty details like cropping
684 // and scanline padding. Also, the seek only takes
685 // place if the file position actually needs to change
686 // (avoids a lot of cluster math in SD library).
687 if(img._flip) // Bitmap is stored bottom-to-top order (normal BMP)
688 pos = img._bmpImageoffset + (img._bmpHeight - 1 - row) * img._rowSize;
689 else // Bitmap is stored top-to-bottom
690 pos = img._bmpImageoffset + row * img._rowSize;
691 if(img._bmpFile.position() != pos) { // Need seek?
692 img._bmpFile.seek(pos);
693 buffidx = sizeof(sdbuffer); // Force buffer reload
694 }
695
696 for (col=0; col<w; col++) { // For each pixel...
697 // Time to read more pixel data?
698 if (buffidx >= sizeof(sdbuffer)) { // Indeed
699 img._bmpFile.read(sdbuffer, sizeof(sdbuffer));
700 buffidx = 0; // Set index to beginning
701 }
702
703 // Convert pixel from BMP to TFT format, push to display
704 b = sdbuffer[buffidx++];
705 g = sdbuffer[buffidx++];
706 r = sdbuffer[buffidx++];
707 //pushColor(tft.Color565(r,g,b));
708 drawPixel(x + col, y + row, newColor(r, g, b));
709
710 } // end pixel
711 } // end scanline
712
713}
714
715#endif
Note: See TracBrowser for help on using the repository browser.