v1.1.1
[hackover2013-badge-firmware.git] / drivers / displays / tft / drawing.c
1 /**************************************************************************/
2 /*!
3 @file drawing.c
4 @author K. Townsend (microBuilder.eu)
5
6 drawLine and drawCircle adapted from a tutorial by Leonard McMillan:
7 http://www.cs.unc.edu/~mcmillan/
8
9 @section LICENSE
10
11 Software License Agreement (BSD License)
12
13 Copyright (c) 2010, microBuilder SARL
14 All rights reserved.
15
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions are met:
18 1. Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
23 3. Neither the name of the copyright holders nor the
24 names of its contributors may be used to endorse or promote products
25 derived from this software without specific prior written permission.
26
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
28 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
31 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38 /**************************************************************************/
39 #include <string.h>
40
41 #include "drawing.h"
42
43 /**************************************************************************/
44 /* */
45 /* ----------------------- Private Methods ------------------------------ */
46 /* */
47 /**************************************************************************/
48
49 /**************************************************************************/
50 /*!
51 @brief Swaps values a and b
52 */
53 /**************************************************************************/
54 void drawSwap(uint32_t a, uint32_t b)
55 {
56 uint32_t t;
57 t = a;
58 a = b;
59 b = t;
60 }
61
62 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
63 /**************************************************************************/
64 /*!
65 @brief Draws a single smallfont character
66 */
67 /**************************************************************************/
68 void drawCharSmall(uint16_t x, uint16_t y, uint16_t color, uint8_t c, struct FONT_DEF font)
69 {
70 uint8_t col, column[font.u8Width];
71
72 // Check if the requested character is available
73 if ((c >= font.u8FirstChar) && (c <= font.u8LastChar))
74 {
75 // Retrieve appropriate columns from font data
76 for (col = 0; col < font.u8Width; col++)
77 {
78 column[col] = font.au8FontTable[((c - 32) * font.u8Width) + col]; // Get first column of appropriate character
79 }
80 }
81 else
82 {
83 // Requested character is not available in this font ... send a space instead
84 for (col = 0; col < font.u8Width; col++)
85 {
86 column[col] = 0xFF; // Send solid space
87 }
88 }
89
90 // Render each column
91 uint16_t xoffset, yoffset;
92 for (xoffset = 0; xoffset < font.u8Width; xoffset++)
93 {
94 for (yoffset = 0; yoffset < (font.u8Height + 1); yoffset++)
95 {
96 uint8_t bit = 0x00;
97 bit = (column[xoffset] << (8 - (yoffset + 1))); // Shift current row bit left
98 bit = (bit >> 7); // Shift current row but right (results in 0x01 for black, and 0x00 for white)
99 if (bit)
100 {
101 drawPixel(x + xoffset, y + yoffset, color);
102 }
103 }
104 }
105 }
106 #endif
107
108 /**************************************************************************/
109 /* */
110 /* ----------------------- Public Methods ------------------------------- */
111 /* */
112 /**************************************************************************/
113
114 /**************************************************************************/
115 /*!
116 @brief Draws a single pixel at the specified location
117
118 @param[in] x
119 Horizontal position
120 @param[in] y
121 Vertical position
122 @param[in] color
123 Color used when drawing
124 */
125 /**************************************************************************/
126 void drawPixel(uint16_t x, uint16_t y, uint16_t color)
127 {
128 if ((x < lcdGetWidth()) && (y < lcdGetHeight()))
129 {
130 lcdDrawPixel(x, y, color);
131 }
132 }
133
134 /**************************************************************************/
135 /*!
136 @brief Fills the screen with the specified color
137
138 @param[in] color
139 Color used when drawing
140 */
141 /**************************************************************************/
142 void drawFill(uint16_t color)
143 {
144 lcdFillRGB(color);
145 }
146
147 /**************************************************************************/
148 /*!
149 @brief Draws a simple color test pattern
150 */
151 /**************************************************************************/
152 void drawTestPattern(void)
153 {
154 lcdTest();
155 }
156
157 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
158 /**************************************************************************/
159 /*!
160 @brief Draws a string using a small font (6 of 8 pixels high).
161
162 @param[in] x
163 Starting x co-ordinate
164 @param[in] y
165 Starting y co-ordinate
166 @param[in] color
167 Color to use when rendering the font
168 @param[in] text
169 The string to render
170 @param[in] font
171 Pointer to the FONT_DEF to use when drawing the string
172
173 @section Example
174
175 @code
176
177 #include "drivers/displays/fonts/smallfonts.h"
178
179 drawStringSmall(1, 210, COLOR_WHITE, "5x8 System (Max 40 Characters)", Font_System5x8);
180 drawStringSmall(1, 220, COLOR_WHITE, "7x8 System (Max 30 Characters)", Font_System7x8);
181
182 @endcode
183 */
184 /**************************************************************************/
185 void drawStringSmall(uint16_t x, uint16_t y, uint16_t color, char* text, struct FONT_DEF font)
186 {
187 uint8_t l;
188 for (l = 0; l < strlen(text); l++)
189 {
190 drawCharSmall(x + (l * (font.u8Width + 1)), y, color, text[l], font);
191 }
192 }
193 #endif
194
195 /**************************************************************************/
196 /*!
197 @brief Draws a bresenham line
198
199 @param[in] x0
200 Starting x co-ordinate
201 @param[in] y0
202 Starting y co-ordinate
203 @param[in] x1
204 Ending x co-ordinate
205 @param[in] y1
206 Ending y co-ordinate
207 @param[in] color
208 Color used when drawing
209 */
210 /**************************************************************************/
211 void drawLine ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color )
212 {
213 drawLineDotted(x0, y0, x1, y1, 0, 1, color);
214 }
215
216 /**************************************************************************/
217 /*!
218 @brief Draws a bresenham line with a fixed pattern of empty
219 and solid pixels
220
221 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
222
223 @param[in] x0
224 Starting x co-ordinate
225 @param[in] y0
226 Starting y co-ordinate
227 @param[in] x1
228 Ending x co-ordinate
229 @param[in] y1
230 Ending y co-ordinate
231 @param[in] empty
232 The number of 'empty' pixels to render
233 @param[in] solid
234 The number of 'solid' pixels to render
235 @param[in] color
236 Color used when drawing
237 */
238 /**************************************************************************/
239 void drawLineDotted ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t empty, uint16_t solid, uint16_t color )
240 {
241 if (solid == 0)
242 {
243 return;
244 }
245
246 // If a negative y int was passed in it will overflow to 65K something
247 // Ugly, but drawCircleFilled() can pass in negative values so we need
248 // to check the values here
249 y0 = y0 > 65000 ? 0 : y0;
250 y1 = y1 > 65000 ? 0 : y1;
251
252 // Check if we can use the optimised horizontal line method
253 if ((y0 == y1) && (empty == 0))
254 {
255 lcdDrawHLine(x0, x1, y0, color);
256 return;
257 }
258
259 // Check if we can use the optimised vertical line method.
260 // This can make a huge difference in performance, but may
261 // not work properly on every LCD controller:
262 if ((x0 == x1) && (empty == 0))
263 {
264 // Warning: This may actually be slower than drawing individual pixels on
265 // short lines ... Set a minimum line size to use the 'optimised' method
266 // (which changes the screen orientation) ?
267 lcdDrawVLine(x0, y0, y1, color);
268 return;
269 }
270
271 // Draw non-horizontal or dotted line
272 int dy = y1 - y0;
273 int dx = x1 - x0;
274 int stepx, stepy;
275 int emptycount, solidcount;
276
277 if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
278 if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
279 dy <<= 1; // dy is now 2*dy
280 dx <<= 1; // dx is now 2*dx
281
282 emptycount = empty;
283 solidcount = solid;
284
285 drawPixel(x0, y0, color); // always start with solid pixels
286 solidcount--;
287 if (dx > dy)
288 {
289 int fraction = dy - (dx >> 1); // same as 2*dy - dx
290 while (x0 != x1)
291 {
292 if (fraction >= 0)
293 {
294 y0 += stepy;
295 fraction -= dx; // same as fraction -= 2*dx
296 }
297 x0 += stepx;
298 fraction += dy; // same as fraction -= 2*dy
299 if (empty == 0)
300 {
301 // always draw a pixel ... no dotted line requested
302 drawPixel(x0, y0, color);
303 }
304 else if (solidcount)
305 {
306 // Draw solid pxiel and decrement counter
307 drawPixel(x0, y0, color);
308 solidcount--;
309 }
310 else if(emptycount)
311 {
312 // Empty pixel ... don't draw anything an decrement counter
313 emptycount--;
314 }
315 else
316 {
317 // Reset counters and draw solid pixel
318 emptycount = empty;
319 solidcount = solid;
320 drawPixel(x0, y0, color);
321 solidcount--;
322 }
323 }
324 }
325 else
326 {
327 int fraction = dx - (dy >> 1);
328 while (y0 != y1)
329 {
330 if (fraction >= 0)
331 {
332 x0 += stepx;
333 fraction -= dy;
334 }
335 y0 += stepy;
336 fraction += dx;
337 if (empty == 0)
338 {
339 // always draw a pixel ... no dotted line requested
340 drawPixel(x0, y0, color);
341 }
342 if (solidcount)
343 {
344 // Draw solid pxiel and decrement counter
345 drawPixel(x0, y0, color);
346 solidcount--;
347 }
348 else if(emptycount)
349 {
350 // Empty pixel ... don't draw anything an decrement counter
351 emptycount--;
352 }
353 else
354 {
355 // Reset counters and draw solid pixel
356 emptycount = empty;
357 solidcount = solid;
358 drawPixel(x0, y0, color);
359 solidcount--;
360 }
361 }
362 }
363 }
364
365 /**************************************************************************/
366 /*!
367 @brief Draws a circle
368
369 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture7/circle.html
370
371 @param[in] xCenter
372 The horizontal center of the circle
373 @param[in] yCenter
374 The vertical center of the circle
375 @param[in] radius
376 The circle's radius in pixels
377 @param[in] color
378 Color used when drawing
379 */
380 /**************************************************************************/
381 void drawCircle (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint16_t color)
382 {
383 drawPixel(xCenter, yCenter+radius, color);
384 drawPixel(xCenter, yCenter-radius, color);
385 drawPixel(xCenter+radius, yCenter, color);
386 drawPixel(xCenter-radius, yCenter, color);
387 drawCorner(xCenter, yCenter, radius, DRAW_CORNERS_ALL, color);
388 }
389
390 /**************************************************************************/
391 /*!
392 @brief Draws a filled circle
393
394 @param[in] xCenter
395 The horizontal center of the circle
396 @param[in] yCenter
397 The vertical center of the circle
398 @param[in] radius
399 The circle's radius in pixels
400 @param[in] color
401 Color used when drawing
402 */
403 /**************************************************************************/
404 void drawCircleFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint16_t color)
405 {
406 int16_t f = 1 - radius;
407 int16_t ddF_x = 1;
408 int16_t ddF_y = -2 * radius;
409 int16_t x = 0;
410 int16_t y = radius;
411 int16_t xc_px, yc_my, xc_mx, xc_py, yc_mx, xc_my;
412 int16_t lcdWidth = lcdGetWidth();
413
414 if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter-radius, xCenter, (yCenter-radius) + (2*radius), color);
415
416 while (x<y)
417 {
418 if (f >= 0)
419 {
420 y--;
421 ddF_y += 2;
422 f += ddF_y;
423 }
424 x++;
425 ddF_x += 2;
426 f += ddF_x;
427
428 xc_px = xCenter+x;
429 xc_mx = xCenter-x;
430 xc_py = xCenter+y;
431 xc_my = xCenter-y;
432 yc_mx = yCenter-x;
433 yc_my = yCenter-y;
434
435 // Make sure X positions are not negative or too large or the pixels will
436 // overflow. Y overflow is handled in drawLine().
437 if ((xc_px < lcdWidth) && (xc_px >= 0)) drawLine(xc_px, yc_my, xc_px, yc_my + 2*y, color);
438 if ((xc_mx < lcdWidth) && (xc_mx >= 0)) drawLine(xc_mx, yc_my, xc_mx, yc_my + 2*y, color);
439 if ((xc_py < lcdWidth) && (xc_py >= 0)) drawLine(xc_py, yc_mx, xc_py, yc_mx + 2*x, color);
440 if ((xc_my < lcdWidth) && (xc_my >= 0)) drawLine(xc_my, yc_mx, xc_my, yc_mx + 2*x, color);
441 }
442 }
443
444 /**************************************************************************/
445 /*!
446 @brief Draws a single 1-pixel wide corner
447
448 @note Code courtesy Adafruit's excellent GFX lib:
449 https://github.com/adafruit/Adafruit-GFX-Library
450
451 @param[in] xCenter
452 The horizontal center of the circle
453 @param[in] yCenter
454 The vertical center of the circle
455 @param[in] corner
456 The drawCorners_t representing the corner(s) to draw
457 @param[in] color
458 Color used when drawing
459
460 @section EXAMPLE
461
462 @code
463
464 // Draw a top-left corner with a 10 pixel radius, centered at 20, 20
465 drawCorner(20, 20, 10, DRAW_CORNER_TOPLEFT, COLOR_GRAY_128);
466
467 @endcode
468 */
469 /**************************************************************************/
470 void drawCorner (uint16_t xCenter, uint16_t yCenter, uint16_t r, drawCorners_t corner, uint16_t color)
471 {
472 int16_t f = 1 - r;
473 int16_t ddF_x = 1;
474 int16_t ddF_y = -2 * r;
475 int16_t x = 0;
476 int16_t y = r;
477
478 while (x<y)
479 {
480 if (f >= 0)
481 {
482 y--;
483 ddF_y += 2;
484 f += ddF_y;
485 }
486 x++;
487 ddF_x += 2;
488 f += ddF_x;
489 if (corner & DRAW_CORNERS_BOTTOMRIGHT)
490 {
491 drawPixel(xCenter + x, yCenter + y, color);
492 drawPixel(xCenter + y, yCenter + x, color);
493 }
494 if (corner & DRAW_CORNERS_TOPRIGHT)
495 {
496 drawPixel(xCenter + x, yCenter - y, color);
497 drawPixel(xCenter + y, yCenter - x, color);
498 }
499 if (corner & DRAW_CORNERS_BOTTOMLEFT)
500 {
501 drawPixel(xCenter - y, yCenter + x, color);
502 drawPixel(xCenter - x, yCenter + y, color);
503 }
504 if (corner & DRAW_CORNERS_TOPLEFT)
505 {
506 drawPixel(xCenter - y, yCenter - x, color);
507 drawPixel(xCenter - x, yCenter - y, color);
508 }
509 }
510 }
511
512 /**************************************************************************/
513 /*!
514 @brief Draws a filled rounded corner
515
516 @param[in] xCenter
517 The horizontal center of the circle
518 @param[in] yCenter
519 The vertical center of the circle
520 @param[in] radius
521 The circle's radius in pixels
522 @param[in] position
523 The position of the corner, which affects how it will
524 be rendered
525 @param[in] color
526 Color used when drawing
527 */
528 /**************************************************************************/
529 void drawCornerFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, drawCorners_t position, uint16_t color)
530 {
531 int16_t f = 1 - radius;
532 int16_t ddF_x = 1;
533 int16_t ddF_y = -2 * radius;
534 int16_t x = 0;
535 int16_t y = radius;
536 int16_t xc_px, yc_my, xc_mx, xc_py, yc_mx, xc_my;
537 int16_t lcdWidth = lcdGetWidth();
538
539
540 if ((position & DRAW_CORNERS_TOPRIGHT) || (position & DRAW_CORNERS_TOPLEFT))
541 {
542 if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter-radius, xCenter, yCenter, color);
543 }
544 if ((position & DRAW_CORNERS_BOTTOMRIGHT) || (position & DRAW_CORNERS_BOTTOMLEFT))
545 {
546 if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter, xCenter, (yCenter-radius) + (2*radius), color);
547 }
548
549 while (x<y)
550 {
551 if (f >= 0)
552 {
553 y--;
554 ddF_y += 2;
555 f += ddF_y;
556 }
557 x++;
558 ddF_x += 2;
559 f += ddF_x;
560
561 xc_px = xCenter+x;
562 xc_mx = xCenter-x;
563 xc_py = xCenter+y;
564 xc_my = xCenter-y;
565 yc_mx = yCenter-x;
566 yc_my = yCenter-y;
567
568
569 if (position & DRAW_CORNERS_TOPRIGHT)
570 {
571 if ((xc_px < lcdWidth) && (xc_px >= 0)) drawLine(xc_px, yc_my, xc_px, yCenter, color);
572 if ((xc_py < lcdWidth) && (xc_py >= 0)) drawLine(xc_py, yc_mx, xc_py, yCenter, color);
573 }
574 if (position & DRAW_CORNERS_BOTTOMRIGHT)
575 {
576 if ((xc_px < lcdWidth) && (xc_px >= 0)) drawLine(xc_px, yCenter, xc_px, yc_my + 2*y, color);
577 if ((xc_py < lcdWidth) && (xc_py >= 0)) drawLine(xc_py, yCenter, xc_py, yc_mx + 2*x, color);
578 }
579 if (position & DRAW_CORNERS_TOPLEFT)
580 {
581 if ((xc_mx < lcdWidth) && (xc_mx >= 0)) drawLine(xc_mx, yc_my, xc_mx, yCenter, color);
582 if ((xc_my < lcdWidth) && (xc_my >= 0)) drawLine(xc_my, yc_mx, xc_my, yCenter, color);
583 }
584 if (position & DRAW_CORNERS_BOTTOMLEFT)
585 {
586 if ((xc_mx < lcdWidth) && (xc_mx >= 0)) drawLine(xc_mx, yCenter, xc_mx, yc_my + 2*y, color);
587 if ((xc_my < lcdWidth) && (xc_my >= 0)) drawLine(xc_my, yCenter, xc_my, yc_mx + 2*x, color);
588 }
589 }
590 }
591
592 /**************************************************************************/
593 /*!
594 @brief Draws a simple arrow of the specified width
595
596 @param[in] x
597 X co-ordinate of the smallest point of the arrow
598 @param[in] y
599 Y co-ordinate of the smallest point of the arrow
600 @param[in] size
601 Total width/height of the arrow in pixels
602 @param[in] direction
603 The direction that the arrow is pointing
604 @param[in] color
605 Color used when drawing
606 */
607 /**************************************************************************/
608 void drawArrow(uint16_t x, uint16_t y, uint16_t size, drawDirection_t direction, uint16_t color)
609 {
610 drawPixel(x, y, color);
611
612 if (size == 1)
613 {
614 return;
615 }
616
617 uint32_t i;
618 switch (direction)
619 {
620 case DRAW_DIRECTION_LEFT:
621 for (i = 1; i<size; i++)
622 {
623 drawLine(x+i, y-i, x+i, y+i, color);
624 }
625 break;
626 case DRAW_DIRECTION_RIGHT:
627 for (i = 1; i<size; i++)
628 {
629 drawLine(x-i, y-i, x-i, y+i, color);
630 }
631 break;
632 case DRAW_DIRECTION_UP:
633 for (i = 1; i<size; i++)
634 {
635 drawLine(x-i, y+i, x+i, y+i, color);
636 }
637 break;
638 case DRAW_DIRECTION_DOWN:
639 for (i = 1; i<size; i++)
640 {
641 drawLine(x-i, y-i, x+i, y-i, color);
642 }
643 break;
644 default:
645 break;
646 }
647 }
648
649 /**************************************************************************/
650 /*!
651 @brief Draws a simple (empty) rectangle
652
653 @param[in] x0
654 Starting x co-ordinate
655 @param[in] y0
656 Starting y co-ordinate
657 @param[in] x1
658 Ending x co-ordinate
659 @param[in] y1
660 Ending y co-ordinate
661 @param[in] color
662 Color used when drawing
663 */
664 /**************************************************************************/
665 void drawRectangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
666 {
667 uint16_t x, y;
668
669 if (y1 < y0)
670 {
671 // Switch y1 and y0
672 y = y1;
673 y1 = y0;
674 y0 = y;
675 }
676
677 if (x1 < x0)
678 {
679 // Switch x1 and x0
680 x = x1;
681 x1 = x0;
682 x0 = x;
683 }
684
685 drawLine (x0, y0, x1, y0, color);
686 drawLine (x1, y0, x1, y1, color);
687 drawLine (x1, y1, x0, y1, color);
688 drawLine (x0, y1, x0, y0, color);
689 }
690
691 /**************************************************************************/
692 /*!
693 @brief Draws a filled rectangle
694
695 @param[in] x0
696 Starting x co-ordinate
697 @param[in] y0
698 Starting y co-ordinate
699 @param[in] x1
700 Ending x co-ordinate
701 @param[in] y1
702 Ending y co-ordinate
703 @param[in] color
704 Color used when drawing
705 */
706 /**************************************************************************/
707 void drawRectangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
708 {
709 int height;
710 uint16_t x, y;
711
712 if (y1 < y0)
713 {
714 // Switch y1 and y0
715 y = y1;
716 y1 = y0;
717 y0 = y;
718 }
719
720 if (x1 < x0)
721 {
722 // Switch x1 and x0
723 x = x1;
724 x1 = x0;
725 x0 = x;
726 }
727
728 height = y1 - y0;
729 for (height = y0; y1 > height - 1; ++height)
730 {
731 drawLine(x0, height, x1, height, color);
732 }
733 }
734
735 /**************************************************************************/
736 /*!
737 @brief Draws a rectangle with rounded corners
738
739 @param[in] x0
740 Starting x co-ordinate
741 @param[in] y0
742 Starting y co-ordinate
743 @param[in] x1
744 Ending x co-ordinate
745 @param[in] y1
746 Ending y co-ordinate
747 @param[in] color
748 Color used when drawing
749 @param[in] radius
750 Corner radius in pixels
751 @param[in] corners
752 Which corners to round
753
754 @section EXAMPLE
755 @code
756
757 drawRoundedRectangle ( 10, 10, 200, 200, COLOR_BLACK, 10, DRAW_CORNERS_ALL );
758
759 @endcode
760
761 */
762 /**************************************************************************/
763 void drawRoundedRectangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color, uint16_t radius, drawCorners_t corners )
764 {
765 int height;
766 uint16_t y;
767
768 if (corners == DRAW_CORNERS_NONE)
769 {
770 drawRectangle(x0, y0, x1, y1, color);
771 return;
772 }
773
774 // Calculate height
775 if (y1 < y0)
776 {
777 y = y1;
778 y1 = y0;
779 y0 = y;
780 }
781 height = y1 - y0;
782
783 // Check radius
784 if (radius > height / 2)
785 {
786 radius = height / 2;
787 }
788 radius -= 1;
789
790 switch (corners)
791 {
792 case DRAW_CORNERS_ALL:
793 drawCorner(x0 + radius, y0 + radius, radius, DRAW_CORNERS_TOPLEFT, color);
794 drawCorner(x1 - radius, y0 + radius, radius, DRAW_CORNERS_TOPRIGHT, color);
795 drawCorner(x0 + radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMLEFT, color);
796 drawCorner(x1 - radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMRIGHT, color);
797 if (radius*2+1 < height)
798 {
799 drawLine(x0, y0+radius, x0, y1-radius, color);
800 drawLine(x1, y0+radius, x1, y1-radius, color);
801 }
802 drawLine(x0+radius, y0, x1-radius, y0, color);
803 drawLine(x0+radius, y1, x1-radius, y1, color);
804 break;
805 case DRAW_CORNERS_TOP:
806 drawCorner(x0 + radius, y0 + radius, radius, DRAW_CORNERS_TOPLEFT, color);
807 drawCorner(x1 - radius, y0 + radius, radius, DRAW_CORNERS_TOPRIGHT, color);
808 drawLine(x0, y0+radius, x0, y1, color);
809 drawLine(x0, y1, x1, y1, color);
810 drawLine(x1, y1, x1, y0+radius, color);
811 drawLine(x0+radius, y0, x1-radius, y0, color);
812 break;
813 case DRAW_CORNERS_BOTTOM:
814 drawCorner(x0 + radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMLEFT, color);
815 drawCorner(x1 - radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMRIGHT, color);
816 drawLine(x0, y0, x1, y0, color);
817 drawLine(x1, y0, x1, y1-radius, color );
818 drawLine(x1-radius, y1, x0+radius, y1, color);
819 drawLine(x0, y1-radius, x0, y0, color);
820 break;
821 case DRAW_CORNERS_LEFT:
822 drawCorner(x0 + radius, y0 + radius, radius, DRAW_CORNERS_TOPLEFT, color);
823 drawCorner(x0 + radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMLEFT, color);
824 if (radius*2+1 < height)
825 {
826 drawLine(x0, y0+radius, x0, y1-radius, color);
827 }
828 drawLine(x1, y0, x1, y1, color);
829 drawLine(x0+radius, y0, x1, y0, color);
830 drawLine(x0+radius, y1, x1, y1, color);
831 break;
832 case DRAW_CORNERS_RIGHT:
833 drawCorner(x1 - radius, y0 + radius, radius, DRAW_CORNERS_TOPRIGHT, color);
834 drawCorner(x1 - radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMRIGHT, color);
835 if (radius*2+1 < height)
836 {
837 drawLine(x1, y0+radius, x1, y1-radius, color);
838 }
839 drawLine(x0, y0, x0, y1, color);
840 drawLine(x0, y0, x1-radius, y0, color);
841 drawLine(x0, y1, x1-radius, y1, color);
842 break;
843 default:
844 break;
845 }
846 }
847
848 /**************************************************************************/
849 /*!
850 @brief Draws a filled rectangle with rounded corners
851
852 @param[in] x0
853 Starting x co-ordinate
854 @param[in] y0
855 Starting y co-ordinate
856 @param[in] x1
857 Ending x co-ordinate
858 @param[in] y1
859 Ending y co-ordinate
860 @param[in] color
861 Color used when drawing
862 @param[in] radius
863 Corner radius in pixels
864 @param[in] corners
865 Which corners to round
866 */
867 /**************************************************************************/
868 void drawRoundedRectangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color, uint16_t radius, drawCorners_t corners )
869 {
870 int height;
871 uint16_t y;
872
873 if (corners == DRAW_CORNERS_NONE)
874 {
875 drawRectangleFilled(x0, y0, x1, y1, color);
876 return;
877 }
878
879 // Calculate height
880 if (y1 < y0)
881 {
882 y = y1;
883 y1 = y0;
884 y0 = y;
885 }
886 height = y1 - y0;
887
888 // Check radius
889 if (radius > height / 2)
890 {
891 radius = height / 2;
892 }
893 radius -= 1;
894
895 // Draw body
896 drawRectangleFilled(x0 + radius, y0, x1 - radius, y1, color);
897
898 switch (corners)
899 {
900 case DRAW_CORNERS_ALL:
901 drawCornerFilled(x0 + radius, y0 + radius, radius, DRAW_CORNERS_TOPLEFT, color);
902 drawCornerFilled(x1 - radius, y0 + radius, radius, DRAW_CORNERS_TOPRIGHT, color);
903 drawCornerFilled(x0 + radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMLEFT, color);
904 drawCornerFilled(x1 - radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMRIGHT, color);
905 if (radius*2+1 < height)
906 {
907 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
908 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
909 }
910 break;
911 case DRAW_CORNERS_TOP:
912 drawCornerFilled(x0 + radius, y0 + radius, radius, DRAW_CORNERS_TOPLEFT, color);
913 drawCornerFilled(x1 - radius, y0 + radius, radius, DRAW_CORNERS_TOPRIGHT, color);
914 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1, color);
915 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1, color);
916 break;
917 case DRAW_CORNERS_BOTTOM:
918 drawCornerFilled(x0 + radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMLEFT, color);
919 drawCornerFilled(x1 - radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMRIGHT, color);
920 drawRectangleFilled(x0, y0, x0 + radius, y1 - radius, color);
921 drawRectangleFilled(x1 - radius, y0, x1, y1 - radius, color);
922 break;
923 case DRAW_CORNERS_LEFT:
924 drawCornerFilled(x0 + radius, y0 + radius, radius, DRAW_CORNERS_TOPLEFT, color);
925 drawCornerFilled(x0 + radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMLEFT, color);
926 if (radius*2+1 < height)
927 {
928 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
929 }
930 drawRectangleFilled(x1 - radius, y0, x1, y1, color);
931 break;
932 case DRAW_CORNERS_RIGHT:
933 drawCornerFilled(x1 - radius, y0 + radius, radius, DRAW_CORNERS_TOPRIGHT, color);
934 drawCornerFilled(x1 - radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMRIGHT, color);
935 if (radius*2+1 < height)
936 {
937 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
938 }
939 drawRectangleFilled(x0, y0, x0 + radius, y1, color);
940 break;
941 default:
942 break;
943 }
944 }
945
946 /**************************************************************************/
947 /*!
948 @brief Draws a gradient-filled rectangle
949
950 @param[in] x0
951 Starting x co-ordinate
952 @param[in] y0
953 Starting y co-ordinate
954 @param[in] x1
955 Ending x co-ordinate
956 @param[in] y1
957 Ending y co-ordinate
958 @param[in] startColor
959 The color at the start of the gradient
960 @param[in] endColor
961 The color at the end of the gradient
962
963 @section EXAMPLE
964
965 @code
966
967 #include "drivers/displays/tft/drawing.h"
968 #include "drivers/displays/tft/aafonts.h"
969 #include "drivers/displays/tft/aafonts/aa2/DejaVuSansCondensed14_AA2.h"
970
971 // Draw a gradient-filled rectangle with anti-aliased text inside it
972
973 uint16_t btnWidth, btnHeight, btnX, btnY;
974 uint16_t fntX, fntY;
975
976 btnWidth = 200;
977 btnHeight = 20;
978 btnX = 10;
979 btnY = 30;
980
981 lcdFillRGB(0xFFFF);
982
983 drawRectangle(btnX-1, btnY-1, btnX+btnWidth+1, btnY+btnHeight+1, COLOR_GRAY_80);
984 drawGradient(btnX, btnY, btnX+btnWidth, btnY+btnHeight, COLOR_WHITE, COLOR_GRAY_128);
985
986 // Center text vertically and horizontally
987 fntY = btnY + ((btnHeight - DejaVuSansCondensed14_AA2.fontHeight) / 2);
988 fntX = btnX + ((btnWidth - aafontsGetStringWidth(&DejaVuSansCondensed14_AA2, "Click to continue"))/2);
989 aafontsDrawString(fntX, fntY, COLORTABLE_AA2_BLACKONWHITE, &DejaVuSansCondensed14_AA2, "Click to continue");
990
991 @endcode
992 */
993 /**************************************************************************/
994 void drawGradient ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t startColor, uint16_t endColor)
995 {
996 int height;
997 uint16_t x, y;
998 uint8_t r, g, b;
999 int16_t rDelta, gDelta, bDelta;
1000
1001 // Clear gradient steps, etc.
1002 r = g = b = 0;
1003 rDelta = gDelta = bDelta = 0;
1004
1005 if (y1 < y0)
1006 {
1007 // Switch y1 and y0
1008 y = y1;
1009 y1 = y0;
1010 y0 = y;
1011 }
1012
1013 if (x1 < x0)
1014 {
1015 // Switch x1 and x0
1016 x = x1;
1017 x1 = x0;
1018 x0 = x;
1019 }
1020
1021 height = y1 - y0;
1022
1023 // Calculate global r/g/b changes between start and end colors
1024 rDelta = ((endColor >> 11) & 0x1F) - ((startColor >> 11) & 0x1F);
1025 gDelta = ((endColor >> 5) & 0x3F) - ((startColor >> 5) & 0x3F);
1026 bDelta = (endColor & 0x1F) - (startColor & 0x1F);
1027
1028 // Calculate interpolation deltas to 2 decimal places (fixed point)
1029 rDelta = (rDelta * 100) / height;
1030 gDelta = (gDelta * 100) / height;
1031 bDelta = (bDelta * 100) / height;
1032
1033 // Draw individual lines
1034 for (height = y0; y1 > height - 1; ++height)
1035 {
1036 // Calculate new rgb values based on: start color + (line number * interpolation delta)
1037 r = ((startColor >> 11) & 0x1F) + ((rDelta * (height - y0)) / 100);
1038 g = ((startColor >> 5) & 0x3F) + ((gDelta * (height - y0)) / 100);
1039 b = (startColor & 0x1F) + ((bDelta * (height - y0)) / 100);
1040 drawLine(x0, height, x1, height, ((r & 0x1F) << 11) | ((g & 0x3F) << 5) | (b & 0x1F));
1041 }
1042 }
1043
1044 /**************************************************************************/
1045 /*!
1046 @brief Draws a triangle
1047
1048 @param[in] x0
1049 x co-ordinate for point 0
1050 @param[in] y0
1051 y co-ordinate for point 0
1052 @param[in] x1
1053 x co-ordinate for point 1
1054 @param[in] y1
1055 y co-ordinate for point 1
1056 @param[in] x2
1057 x co-ordinate for point 2
1058 @param[in] y2
1059 y co-ordinate for point 2
1060 @param[in] color
1061 Color used when drawing
1062 */
1063 /**************************************************************************/
1064 void drawTriangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
1065 {
1066 drawLine(x0, y0, x1, y1, color);
1067 drawLine(x1, y1, x2, y2, color);
1068 drawLine(x2, y2, x0, y0, color);
1069 }
1070
1071 /**************************************************************************/
1072 /*!
1073 @brief Draws a filled triangle
1074
1075 @param[in] x0
1076 x co-ordinate for point 0
1077 @param[in] y0
1078 y co-ordinate for point 0
1079 @param[in] x1
1080 x co-ordinate for point 1
1081 @param[in] y1
1082 y co-ordinate for point 1
1083 @param[in] x2
1084 x co-ordinate for point 2
1085 @param[in] y2
1086 y co-ordinate for point 2
1087 @param[in] color
1088 Fill color
1089
1090 @section Example
1091
1092 @code
1093
1094 // Draw a white triangle
1095 drawTriangleFilled ( 100, 10, 20, 120, 230, 290, COLOR_WHITE);
1096 // Draw black circles at each point of the triangle
1097 drawCircleFilled(100, 10, 2, COLOR_BLACK);
1098 drawCircleFilled(20, 120, 2, COLOR_BLACK);
1099 drawCircleFilled(230, 290, 2, COLOR_BLACK);
1100
1101 @endcode
1102 */
1103 /**************************************************************************/
1104 void drawTriangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
1105 {
1106 // Re-order vertices by ascending Y values (smallest first)
1107 if (y0 > y1) {
1108 drawSwap(y0, y1); drawSwap(x0, x1);
1109 }
1110 if (y1 > y2) {
1111 drawSwap(y2, y1); drawSwap(x2, x1);
1112 }
1113 if (y0 > y1) {
1114 drawSwap(y0, y1); drawSwap(x0, x1);
1115 }
1116
1117 int32_t dx1, dx2, dx3; // Interpolation deltas
1118 int32_t sx1, sx2, sy; // Scanline co-ordinates
1119
1120 sx1=sx2=x0 * 1000; // Use fixed point math for x axis values
1121 sy=y0;
1122
1123 // Calculate interpolation deltas
1124 if (y1-y0 > 0) dx1=((x1-x0)*1000)/(y1-y0);
1125 else dx1=0;
1126 if (y2-y0 > 0) dx2=((x2-x0)*1000)/(y2-y0);
1127 else dx2=0;
1128 if (y2-y1 > 0) dx3=((x2-x1)*1000)/(y2-y1);
1129 else dx3=0;
1130
1131 // Render scanlines (horizontal lines are the fastest rendering method)
1132 if (dx1 > dx2)
1133 {
1134 for(; sy<=y1; sy++, sx1+=dx2, sx2+=dx1)
1135 {
1136 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1137 }
1138 sx2 = x1*1000;
1139 sy = y1;
1140 for(; sy<=y2; sy++, sx1+=dx2, sx2+=dx3)
1141 {
1142 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1143 }
1144 }
1145 else
1146 {
1147 for(; sy<=y1; sy++, sx1+=dx1, sx2+=dx2)
1148 {
1149 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1150 }
1151 sx1 = x1*1000;
1152 sy = y1;
1153 for(; sy<=y2; sy++, sx1+=dx3, sx2+=dx2)
1154 {
1155 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1156 }
1157 }
1158 }
1159
1160 /**************************************************************************/
1161 /*!
1162 @brief Renders a 16x16 monochrome icon using the supplied uint16_t
1163 array.
1164
1165 @param[in] x
1166 The horizontal location to start rendering from
1167 @param[in] x
1168 The vertical location to start rendering from
1169 @param[in] color
1170 The RGB565 color to use when rendering the icon
1171 @param[in] icon
1172 The uint16_t array containing the 16x16 image data
1173
1174 @section Example
1175
1176 @code
1177
1178 #include "drivers/displays/tft/drawing.h"
1179 #include "drivers/displays/icons16.h"
1180
1181 // Renders the info icon, which has two seperate parts ... the exterior
1182 // and a seperate interior mask if you want to fill the contents with a
1183 // different color
1184 drawIcon16(132, 202, COLOR_BLUE, icons16_info);
1185 drawIcon16(132, 202, COLOR_WHITE, icons16_info_interior);
1186
1187 @endcode
1188 */
1189 /**************************************************************************/
1190 void drawIcon16(uint16_t x, uint16_t y, uint16_t color, uint16_t icon[])
1191 {
1192 int i;
1193 for (i = 0; i<16; i++)
1194 {
1195 if (icon[i] & (0X8000)) drawPixel(x, y+i, color);
1196 if (icon[i] & (0X4000)) drawPixel(x+1, y+i, color);
1197 if (icon[i] & (0X2000)) drawPixel(x+2, y+i, color);
1198 if (icon[i] & (0X1000)) drawPixel(x+3, y+i, color);
1199 if (icon[i] & (0X0800)) drawPixel(x+4, y+i, color);
1200 if (icon[i] & (0X0400)) drawPixel(x+5, y+i, color);
1201 if (icon[i] & (0X0200)) drawPixel(x+6, y+i, color);
1202 if (icon[i] & (0X0100)) drawPixel(x+7, y+i, color);
1203 if (icon[i] & (0X0080)) drawPixel(x+8, y+i, color);
1204 if (icon[i] & (0x0040)) drawPixel(x+9, y+i, color);
1205 if (icon[i] & (0X0020)) drawPixel(x+10, y+i, color);
1206 if (icon[i] & (0X0010)) drawPixel(x+11, y+i, color);
1207 if (icon[i] & (0X0008)) drawPixel(x+12, y+i, color);
1208 if (icon[i] & (0X0004)) drawPixel(x+13, y+i, color);
1209 if (icon[i] & (0X0002)) drawPixel(x+14, y+i, color);
1210 if (icon[i] & (0X0001)) drawPixel(x+15, y+i, color);
1211 }
1212 }
This page took 0.13777 seconds and 5 git commands to generate.