source: rtos_arduino/trunk/arduino_lib/libraries/Robot_Control/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: 17.1 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 drawFastVLine(x0, y0-r, 2*r+1, color);
128 fillCircleHelper(x0, y0, r, 3, 0, color);
129}
130
131// Used to do circles and roundrects
132void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
133 uint8_t cornername, int16_t delta, uint16_t color) {
134
135 int16_t f = 1 - r;
136 int16_t ddF_x = 1;
137 int16_t ddF_y = -2 * r;
138 int16_t x = 0;
139 int16_t y = r;
140
141 while (x<y) {
142 if (f >= 0) {
143 y--;
144 ddF_y += 2;
145 f += ddF_y;
146 }
147 x++;
148 ddF_x += 2;
149 f += ddF_x;
150
151 if (cornername & 0x1) {
152 drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
153 drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
154 }
155 if (cornername & 0x2) {
156 drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
157 drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
158 }
159 }
160}
161
162// Bresenham's algorithm - thx wikpedia
163void Adafruit_GFX::drawLine(int16_t x0, int16_t y0,
164 int16_t x1, int16_t y1,
165 uint16_t color) {
166 int16_t steep = abs(y1 - y0) > abs(x1 - x0);
167 if (steep) {
168 swap(x0, y0);
169 swap(x1, y1);
170 }
171
172 if (x0 > x1) {
173 swap(x0, x1);
174 swap(y0, y1);
175 }
176
177 int16_t dx, dy;
178 dx = x1 - x0;
179 dy = abs(y1 - y0);
180
181 int16_t err = dx / 2;
182 int16_t ystep;
183
184 if (y0 < y1) {
185 ystep = 1;
186 } else {
187 ystep = -1;
188 }
189
190 for (; x0<=x1; x0++) {
191 if (steep) {
192 drawPixel(y0, x0, color);
193 } else {
194 drawPixel(x0, y0, color);
195 }
196 err -= dy;
197 if (err < 0) {
198 y0 += ystep;
199 err += dx;
200 }
201 }
202}
203
204// Draw a rectangle
205void Adafruit_GFX::drawRect(int16_t x, int16_t y,
206 int16_t w, int16_t h,
207 uint16_t color) {
208 drawFastHLine(x, y, w, color);
209 drawFastHLine(x, y+h-1, w, color);
210 drawFastVLine(x, y, h, color);
211 drawFastVLine(x+w-1, y, h, color);
212}
213
214void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y,
215 int16_t h, uint16_t color) {
216 // Update in subclasses if desired!
217 drawLine(x, y, x, y+h-1, color);
218}
219
220void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y,
221 int16_t w, uint16_t color) {
222 // Update in subclasses if desired!
223 drawLine(x, y, x+w-1, y, color);
224}
225
226void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
227 uint16_t color) {
228 // Update in subclasses if desired!
229 for (int16_t i=x; i<x+w; i++) {
230 drawFastVLine(i, y, h, color);
231 }
232}
233
234void Adafruit_GFX::fillScreen(uint16_t color) {
235 fillRect(0, 0, _width, _height, color);
236}
237
238// Draw a rounded rectangle
239void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
240 int16_t h, int16_t r, uint16_t color) {
241 // smarter version
242 drawFastHLine(x+r , y , w-2*r, color); // Top
243 drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
244 drawFastVLine(x , y+r , h-2*r, color); // Left
245 drawFastVLine(x+w-1, y+r , h-2*r, color); // Right
246 // draw four corners
247 drawCircleHelper(x+r , y+r , r, 1, color);
248 drawCircleHelper(x+w-r-1, y+r , r, 2, color);
249 drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
250 drawCircleHelper(x+r , y+h-r-1, r, 8, color);
251}
252
253// Fill a rounded rectangle
254void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
255 int16_t h, int16_t r, uint16_t color) {
256 // smarter version
257 fillRect(x+r, y, w-2*r, h, color);
258
259 // draw four corners
260 fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
261 fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
262}
263
264// Draw a triangle
265void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0,
266 int16_t x1, int16_t y1,
267 int16_t x2, int16_t y2, uint16_t color) {
268 drawLine(x0, y0, x1, y1, color);
269 drawLine(x1, y1, x2, y2, color);
270 drawLine(x2, y2, x0, y0, color);
271}
272
273// Fill a triangle
274void Adafruit_GFX::fillTriangle ( int16_t x0, int16_t y0,
275 int16_t x1, int16_t y1,
276 int16_t x2, int16_t y2, uint16_t color) {
277
278 int16_t a, b, y, last;
279
280 // Sort coordinates by Y order (y2 >= y1 >= y0)
281 if (y0 > y1) {
282 swap(y0, y1); swap(x0, x1);
283 }
284 if (y1 > y2) {
285 swap(y2, y1); swap(x2, x1);
286 }
287 if (y0 > y1) {
288 swap(y0, y1); swap(x0, x1);
289 }
290
291 if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
292 a = b = x0;
293 if(x1 < a) a = x1;
294 else if(x1 > b) b = x1;
295 if(x2 < a) a = x2;
296 else if(x2 > b) b = x2;
297 drawFastHLine(a, y0, b-a+1, color);
298 return;
299 }
300
301 int16_t
302 dx01 = x1 - x0,
303 dy01 = y1 - y0,
304 dx02 = x2 - x0,
305 dy02 = y2 - y0,
306 dx12 = x2 - x1,
307 dy12 = y2 - y1,
308 sa = 0,
309 sb = 0;
310
311 // For upper part of triangle, find scanline crossings for segments
312 // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
313 // is included here (and second loop will be skipped, avoiding a /0
314 // error there), otherwise scanline y1 is skipped here and handled
315 // in the second loop...which also avoids a /0 error here if y0=y1
316 // (flat-topped triangle).
317 if(y1 == y2) last = y1; // Include y1 scanline
318 else last = y1-1; // Skip it
319
320 for(y=y0; y<=last; y++) {
321 a = x0 + sa / dy01;
322 b = x0 + sb / dy02;
323 sa += dx01;
324 sb += dx02;
325 /* longhand:
326 a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
327 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
328 */
329 if(a > b) swap(a,b);
330 drawFastHLine(a, y, b-a+1, color);
331 }
332
333 // For lower part of triangle, find scanline crossings for segments
334 // 0-2 and 1-2. This loop is skipped if y1=y2.
335 sa = dx12 * (y - y1);
336 sb = dx02 * (y - y0);
337 for(; y<=y2; y++) {
338 a = x1 + sa / dy12;
339 b = x0 + sb / dy02;
340 sa += dx12;
341 sb += dx02;
342 /* longhand:
343 a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
344 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
345 */
346 if(a > b) swap(a,b);
347 drawFastHLine(a, y, b-a+1, color);
348 }
349}
350
351void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
352 const uint8_t *bitmap, int16_t w, int16_t h,
353 uint16_t color) {
354
355 int16_t i, j, byteWidth = (w + 7) / 8;
356
357 for(j=0; j<h; j++) {
358 for(i=0; i<w; i++ ) {
359 if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
360 drawPixel(x+i, y+j, color);
361 }
362 }
363 }
364}
365
366#if ARDUINO >= 100
367size_t Adafruit_GFX::write(uint8_t c) {
368#else
369void Adafruit_GFX::write(uint8_t c) {
370#endif
371 if (c == '\n') {
372 cursor_y += textsize*8;
373 cursor_x = 0;
374 } else if (c == '\r') {
375 // skip em
376 } else {
377 drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
378 cursor_x += textsize*6;
379 if (wrap && (cursor_x > (_width - textsize*6))) {
380 cursor_y += textsize*8;
381 cursor_x = 0;
382 }
383 }
384#if ARDUINO >= 100
385 return 1;
386#endif
387}
388
389// Draw a character
390void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
391 uint16_t color, uint16_t bg, uint8_t size) {
392
393 if((x >= _width) || // Clip right
394 (y >= _height) || // Clip bottom
395 ((x + 6 * size - 1) < 0) || // Clip left
396 ((y + 8 * size - 1) < 0)) // Clip top
397 return;
398
399 for (int8_t i=0; i<6; i++ ) {
400 uint8_t line;
401 if (i == 5)
402 line = 0x0;
403 else
404 line = pgm_read_byte(font+(c*5)+i);
405 for (int8_t j = 0; j<8; j++) {
406 if (line & 0x1) {
407 if (size == 1) // default size
408 drawPixel(x+i, y+j, color);
409 else { // big size
410 fillRect(x+(i*size), y+(j*size), size, size, color);
411 }
412 } else if (bg != color) {
413 if (size == 1) // default size
414 drawPixel(x+i, y+j, bg);
415 else { // big size
416 fillRect(x+i*size, y+j*size, size, size, bg);
417 }
418 }
419 line >>= 1;
420 }
421 }
422}
423
424void Adafruit_GFX::setCursor(int16_t x, int16_t y) {
425 cursor_x = x;
426 cursor_y = y;
427}
428
429void Adafruit_GFX::setTextSize(uint8_t s) {
430 textsize = (s > 0) ? s : 1;
431}
432
433void Adafruit_GFX::setTextColor(uint16_t c) {
434 // For 'transparent' background, we'll set the bg
435 // to the same as fg instead of using a flag
436 textcolor = textbgcolor = c;
437}
438
439void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
440 textcolor = c;
441 textbgcolor = b;
442}
443
444void Adafruit_GFX::setTextWrap(boolean w) {
445 wrap = w;
446}
447
448uint8_t Adafruit_GFX::getRotation(void) {
449 return rotation;
450}
451
452void Adafruit_GFX::setRotation(uint8_t x) {
453 rotation = (x & 3);
454 switch(rotation) {
455 case 0:
456 case 2:
457 _width = WIDTH;
458 _height = HEIGHT;
459 break;
460 case 1:
461 case 3:
462 _width = HEIGHT;
463 _height = WIDTH;
464 break;
465 }
466}
467
468// Return the size of the display (per current rotation)
469int16_t Adafruit_GFX::width(void) {
470 return _width;
471}
472
473int16_t Adafruit_GFX::height(void) {
474 return _height;
475}
476
477void Adafruit_GFX::invertDisplay(boolean i) {
478 // Do nothing, must be subclassed if supported
479}
480
481uint16_t Adafruit_GFX::newColor(uint8_t r, uint8_t g, uint8_t b) {
482 return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
483}
484
485void Adafruit_GFX::background(uint8_t red, uint8_t green, uint8_t blue) {
486 background(newColor(red, green, blue));
487}
488
489void Adafruit_GFX::background(color c) {
490 fillScreen(c);
491}
492
493void Adafruit_GFX::stroke(uint8_t red, uint8_t green, uint8_t blue) {
494 stroke(newColor(red, green, blue));
495}
496
497void Adafruit_GFX::stroke(color c) {
498 useStroke = true;
499 strokeColor = c;
500 setTextColor(c);
501}
502
503void Adafruit_GFX::noStroke() {
504 useStroke = false;
505}
506
507void Adafruit_GFX::noFill() {
508 useFill = false;
509}
510
511void Adafruit_GFX::fill(uint8_t red, uint8_t green, uint8_t blue) {
512 fill(newColor(red, green, blue));
513}
514
515void Adafruit_GFX::fill(color c) {
516 useFill = true;
517 fillColor = c;
518}
519
520void Adafruit_GFX::text(int value, uint8_t x, uint8_t y){
521 if (!useStroke)
522 return;
523
524 setTextWrap(false);
525 setTextColor(strokeColor);
526 setCursor(x, y);
527 print(value);
528}
529void Adafruit_GFX::text(long value, uint8_t x, uint8_t y){
530 if (!useStroke)
531 return;
532
533 setTextWrap(false);
534 setTextColor(strokeColor);
535 setCursor(x, y);
536 print(value);
537}
538void Adafruit_GFX::text(char value, uint8_t x, uint8_t y){
539 if (!useStroke)
540 return;
541
542 setTextWrap(false);
543 setTextColor(strokeColor);
544 setCursor(x, y);
545 print(value);
546}
547
548void Adafruit_GFX::text(const char * text, int16_t x, int16_t y) {
549 if (!useStroke)
550 return;
551
552 setTextWrap(false);
553 setTextColor(strokeColor);
554 setCursor(x, y);
555 print(text);
556}
557
558void Adafruit_GFX::textWrap(const char * text, int16_t x, int16_t y) {
559 if (!useStroke)
560 return;
561
562 setTextWrap(true);
563 setTextColor(strokeColor);
564 setCursor(x, y);
565 print(text);
566}
567
568
569void Adafruit_GFX::textSize(uint8_t size) {
570 setTextSize(size);
571}
572
573void Adafruit_GFX::point(int16_t x, int16_t y) {
574 if (!useStroke)
575 return;
576
577 drawPixel(x, y, strokeColor);
578}
579
580void Adafruit_GFX::line(int16_t x1, int16_t y1, int16_t x2, int16_t y2) {
581 if (!useStroke)
582 return;
583
584 if (x1 == x2) {
585 drawFastVLine(x1, y1, y2 - y1, strokeColor);
586 }
587 else if (y1 == y2) {
588 drawFastHLine(x1, y1, x2 - x1, strokeColor);
589 }
590 else {
591 drawLine(x1, y1, x2, y2, strokeColor);
592 }
593}
594
595void Adafruit_GFX::rect(int16_t x, int16_t y, int16_t width, int16_t height) {
596 if (useFill) {
597 fillRect(x, y, width, height, fillColor);
598 }
599 if (useStroke) {
600 drawRect(x, y, width, height, strokeColor);
601 }
602}
603
604void Adafruit_GFX::rect(int16_t x, int16_t y, int16_t width, int16_t height, int16_t radius) {
605 if (radius == 0) {
606 rect(x, y, width, height);
607 }
608 if (useFill) {
609 fillRoundRect(x, y, width, height, radius, fillColor);
610 }
611 if (useStroke) {
612 drawRoundRect(x, y, width, height, radius, strokeColor);
613 }
614}
615
616void Adafruit_GFX::circle(int16_t x, int16_t y, int16_t r) {
617 if (r == 0)
618 return;
619
620 if (useFill) {
621 fillCircle(x, y, r, fillColor);
622 }
623 if (useStroke) {
624 drawCircle(x, y, r, strokeColor);
625 }
626}
627
628void Adafruit_GFX::triangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3) {
629 if (useFill) {
630 fillTriangle(x1, y1, x2, y2, x3, y3, fillColor);
631 }
632 if (useStroke) {
633 drawTriangle(x1, y1, x2, y2, x3, y3, strokeColor);
634 }
635}
636
637#define BUFFPIXEL 20
638/*
639void Adafruit_GFX::image(PImage & img, uint16_t x, uint16_t y) {
640 int w, h, row, col;
641 uint8_t r, g, b;
642 uint32_t pos = 0;
643 uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
644 uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
645
646 // Crop area to be loaded
647 w = img._bmpWidth;
648 h = img._bmpHeight;
649 if((x+w-1) >= width()) w = width() - x;
650 if((y+h-1) >= height()) h = height() - y;
651
652
653 // Set TFT address window to clipped image bounds
654 //setAddrWindow(x, y, x+w-1, y+h-1);
655
656
657 for (row=0; row<h; row++) { // For each scanline...
658 // Seek to start of scan line. It might seem labor-
659 // intensive to be doing this on every line, but this
660 // method covers a lot of gritty details like cropping
661 // and scanline padding. Also, the seek only takes
662 // place if the file position actually needs to change
663 // (avoids a lot of cluster math in SD library).
664 if(img._flip) // Bitmap is stored bottom-to-top order (normal BMP)
665 pos = img._bmpImageoffset + (img._bmpHeight - 1 - row) * img._rowSize;
666 else // Bitmap is stored top-to-bottom
667 pos = img._bmpImageoffset + row * img._rowSize;
668 if(img._bmpFile.position() != pos) { // Need seek?
669 img._bmpFile.seek(pos);
670 buffidx = sizeof(sdbuffer); // Force buffer reload
671 }
672
673 for (col=0; col<w; col++) { // For each pixel...
674 // Time to read more pixel data?
675 if (buffidx >= sizeof(sdbuffer)) { // Indeed
676 img._bmpFile.read(sdbuffer, sizeof(sdbuffer));
677 buffidx = 0; // Set index to beginning
678 }
679
680 // Convert pixel from BMP to TFT format, push to display
681 b = sdbuffer[buffidx++];
682 g = sdbuffer[buffidx++];
683 r = sdbuffer[buffidx++];
684 //pushColor(tft.Color565(r,g,b));
685 drawPixel(x + col, y + row, newColor(r, g, b));
686
687 } // end pixel
688 } // end scanline
689
690}*/
Note: See TracBrowser for help on using the repository browser.