Prep for v1.1.0
[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 filled 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 /**************************************************************************/
755 void drawRoundedRectangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color, uint16_t radius, drawCorners_t corners )
756 {
757 int height;
758 uint16_t y;
759
760 if (corners == DRAW_CORNERS_NONE)
761 {
762 drawRectangleFilled(x0, y0, x1, y1, color);
763 return;
764 }
765
766 // Calculate height
767 if (y1 < y0)
768 {
769 y = y1;
770 y1 = y0;
771 y0 = y;
772 }
773 height = y1 - y0;
774
775 // Check radius
776 if (radius > height / 2)
777 {
778 radius = height / 2;
779 }
780 radius -= 1;
781
782 // Draw body
783 drawRectangleFilled(x0 + radius, y0, x1 - radius, y1, color);
784
785 switch (corners)
786 {
787 case DRAW_CORNERS_ALL:
788 drawCornerFilled(x0 + radius, y0 + radius, radius, DRAW_CORNERS_TOPLEFT, color);
789 drawCornerFilled(x1 - radius, y0 + radius, radius, DRAW_CORNERS_TOPRIGHT, color);
790 drawCornerFilled(x0 + radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMLEFT, color);
791 drawCornerFilled(x1 - radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMRIGHT, color);
792 if (radius*2+1 < height)
793 {
794 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
795 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
796 }
797 break;
798 case DRAW_CORNERS_TOP:
799 drawCornerFilled(x0 + radius, y0 + radius, radius, DRAW_CORNERS_TOPLEFT, color);
800 drawCornerFilled(x1 - radius, y0 + radius, radius, DRAW_CORNERS_TOPRIGHT, color);
801 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1, color);
802 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1, color);
803 break;
804 case DRAW_CORNERS_BOTTOM:
805 drawCornerFilled(x0 + radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMLEFT, color);
806 drawCornerFilled(x1 - radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMRIGHT, color);
807 drawRectangleFilled(x0, y0, x0 + radius, y1 - radius, color);
808 drawRectangleFilled(x1 - radius, y0, x1, y1 - radius, color);
809 break;
810 case DRAW_CORNERS_LEFT:
811 drawCornerFilled(x0 + radius, y0 + radius, radius, DRAW_CORNERS_TOPLEFT, color);
812 drawCornerFilled(x0 + radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMLEFT, color);
813 if (radius*2+1 < height)
814 {
815 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
816 }
817 drawRectangleFilled(x1 - radius, y0, x1, y1, color);
818 break;
819 case DRAW_CORNERS_RIGHT:
820 drawCornerFilled(x1 - radius, y0 + radius, radius, DRAW_CORNERS_TOPRIGHT, color);
821 drawCornerFilled(x1 - radius, y1 - radius, radius, DRAW_CORNERS_BOTTOMRIGHT, color);
822 if (radius*2+1 < height)
823 {
824 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
825 }
826 drawRectangleFilled(x0, y0, x0 + radius, y1, color);
827 break;
828 default:
829 break;
830 }
831 }
832
833 /**************************************************************************/
834 /*!
835 @brief Draws a gradient-filled rectangle
836
837 @param[in] x0
838 Starting x co-ordinate
839 @param[in] y0
840 Starting y co-ordinate
841 @param[in] x1
842 Ending x co-ordinate
843 @param[in] y1
844 Ending y co-ordinate
845 @param[in] startColor
846 The color at the start of the gradient
847 @param[in] endColor
848 The color at the end of the gradient
849
850 @section EXAMPLE
851
852 @code
853
854 #include "drivers/displays/tft/drawing.h"
855 #include "drivers/displays/tft/aafonts.h"
856 #include "drivers/displays/tft/aafonts/aa2/DejaVuSansCondensed14_AA2.h"
857
858 // Draw a gradient-filled rectangle with anti-aliased text inside it
859
860 uint16_t btnWidth, btnHeight, btnX, btnY;
861 uint16_t fntX, fntY;
862
863 btnWidth = 200;
864 btnHeight = 20;
865 btnX = 10;
866 btnY = 30;
867
868 lcdFillRGB(0xFFFF);
869
870 drawRectangle(btnX-1, btnY-1, btnX+btnWidth+1, btnY+btnHeight+1, COLOR_GRAY_80);
871 drawGradient(btnX, btnY, btnX+btnWidth, btnY+btnHeight, COLOR_WHITE, COLOR_GRAY_128);
872
873 // Center text vertically and horizontally
874 fntY = btnY + ((btnHeight - DejaVuSansCondensed14_AA2.fontHeight) / 2);
875 fntX = btnX + ((btnWidth - aafontsGetStringWidth(&DejaVuSansCondensed14_AA2, "Click to continue"))/2);
876 aafontsDrawString(fntX, fntY, COLORTABLE_AA2_BLACKONWHITE, &DejaVuSansCondensed14_AA2, "Click to continue");
877
878 @endcode
879 */
880 /**************************************************************************/
881 void drawGradient ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t startColor, uint16_t endColor)
882 {
883 int height;
884 uint16_t x, y;
885 uint8_t r, g, b;
886 int16_t rDelta, gDelta, bDelta;
887
888 // Clear gradient steps, etc.
889 r = g = b = 0;
890 rDelta = gDelta = bDelta = 0;
891
892 if (y1 < y0)
893 {
894 // Switch y1 and y0
895 y = y1;
896 y1 = y0;
897 y0 = y;
898 }
899
900 if (x1 < x0)
901 {
902 // Switch x1 and x0
903 x = x1;
904 x1 = x0;
905 x0 = x;
906 }
907
908 height = y1 - y0;
909
910 // Calculate global r/g/b changes between start and end colors
911 rDelta = ((endColor >> 11) & 0x1F) - ((startColor >> 11) & 0x1F);
912 gDelta = ((endColor >> 5) & 0x3F) - ((startColor >> 5) & 0x3F);
913 bDelta = (endColor & 0x1F) - (startColor & 0x1F);
914
915 // Calculate interpolation deltas to 2 decimal places (fixed point)
916 rDelta = (rDelta * 100) / height;
917 gDelta = (gDelta * 100) / height;
918 bDelta = (bDelta * 100) / height;
919
920 // Draw individual lines
921 for (height = y0; y1 > height - 1; ++height)
922 {
923 // Calculate new rgb values based on: start color + (line number * interpolation delta)
924 r = ((startColor >> 11) & 0x1F) + ((rDelta * (height - y0)) / 100);
925 g = ((startColor >> 5) & 0x3F) + ((gDelta * (height - y0)) / 100);
926 b = (startColor & 0x1F) + ((bDelta * (height - y0)) / 100);
927 drawLine(x0, height, x1, height, ((r & 0x1F) << 11) | ((g & 0x3F) << 5) | (b & 0x1F));
928 }
929 }
930
931 /**************************************************************************/
932 /*!
933 @brief Draws a triangle
934
935 @param[in] x0
936 x co-ordinate for point 0
937 @param[in] y0
938 y co-ordinate for point 0
939 @param[in] x1
940 x co-ordinate for point 1
941 @param[in] y1
942 y co-ordinate for point 1
943 @param[in] x2
944 x co-ordinate for point 2
945 @param[in] y2
946 y co-ordinate for point 2
947 @param[in] color
948 Color used when drawing
949 */
950 /**************************************************************************/
951 void drawTriangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
952 {
953 drawLine(x0, y0, x1, y1, color);
954 drawLine(x1, y1, x2, y2, color);
955 drawLine(x2, y2, x0, y0, color);
956 }
957
958 /**************************************************************************/
959 /*!
960 @brief Draws a filled triangle
961
962 @param[in] x0
963 x co-ordinate for point 0
964 @param[in] y0
965 y co-ordinate for point 0
966 @param[in] x1
967 x co-ordinate for point 1
968 @param[in] y1
969 y co-ordinate for point 1
970 @param[in] x2
971 x co-ordinate for point 2
972 @param[in] y2
973 y co-ordinate for point 2
974 @param[in] color
975 Fill color
976
977 @section Example
978
979 @code
980
981 // Draw a white triangle
982 drawTriangleFilled ( 100, 10, 20, 120, 230, 290, COLOR_WHITE);
983 // Draw black circles at each point of the triangle
984 drawCircleFilled(100, 10, 2, COLOR_BLACK);
985 drawCircleFilled(20, 120, 2, COLOR_BLACK);
986 drawCircleFilled(230, 290, 2, COLOR_BLACK);
987
988 @endcode
989 */
990 /**************************************************************************/
991 void drawTriangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
992 {
993 // Re-order vertices by ascending Y values (smallest first)
994 if (y0 > y1) {
995 drawSwap(y0, y1); drawSwap(x0, x1);
996 }
997 if (y1 > y2) {
998 drawSwap(y2, y1); drawSwap(x2, x1);
999 }
1000 if (y0 > y1) {
1001 drawSwap(y0, y1); drawSwap(x0, x1);
1002 }
1003
1004 int32_t dx1, dx2, dx3; // Interpolation deltas
1005 int32_t sx1, sx2, sy; // Scanline co-ordinates
1006
1007 sx1=sx2=x0 * 1000; // Use fixed point math for x axis values
1008 sy=y0;
1009
1010 // Calculate interpolation deltas
1011 if (y1-y0 > 0) dx1=((x1-x0)*1000)/(y1-y0);
1012 else dx1=0;
1013 if (y2-y0 > 0) dx2=((x2-x0)*1000)/(y2-y0);
1014 else dx2=0;
1015 if (y2-y1 > 0) dx3=((x2-x1)*1000)/(y2-y1);
1016 else dx3=0;
1017
1018 // Render scanlines (horizontal lines are the fastest rendering method)
1019 if (dx1 > dx2)
1020 {
1021 for(; sy<=y1; sy++, sx1+=dx2, sx2+=dx1)
1022 {
1023 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1024 }
1025 sx2 = x1*1000;
1026 sy = y1;
1027 for(; sy<=y2; sy++, sx1+=dx2, sx2+=dx3)
1028 {
1029 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1030 }
1031 }
1032 else
1033 {
1034 for(; sy<=y1; sy++, sx1+=dx1, sx2+=dx2)
1035 {
1036 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1037 }
1038 sx1 = x1*1000;
1039 sy = y1;
1040 for(; sy<=y2; sy++, sx1+=dx3, sx2+=dx2)
1041 {
1042 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1043 }
1044 }
1045 }
1046
1047 /**************************************************************************/
1048 /*!
1049 @brief Renders a 16x16 monochrome icon using the supplied uint16_t
1050 array.
1051
1052 @param[in] x
1053 The horizontal location to start rendering from
1054 @param[in] x
1055 The vertical location to start rendering from
1056 @param[in] color
1057 The RGB565 color to use when rendering the icon
1058 @param[in] icon
1059 The uint16_t array containing the 16x16 image data
1060
1061 @section Example
1062
1063 @code
1064
1065 #include "drivers/displays/tft/drawing.h"
1066 #include "drivers/displays/icons16.h"
1067
1068 // Renders the info icon, which has two seperate parts ... the exterior
1069 // and a seperate interior mask if you want to fill the contents with a
1070 // different color
1071 drawIcon16(132, 202, COLOR_BLUE, icons16_info);
1072 drawIcon16(132, 202, COLOR_WHITE, icons16_info_interior);
1073
1074 @endcode
1075 */
1076 /**************************************************************************/
1077 void drawIcon16(uint16_t x, uint16_t y, uint16_t color, uint16_t icon[])
1078 {
1079 int i;
1080 for (i = 0; i<16; i++)
1081 {
1082 if (icon[i] & (0X8000)) drawPixel(x, y+i, color);
1083 if (icon[i] & (0X4000)) drawPixel(x+1, y+i, color);
1084 if (icon[i] & (0X2000)) drawPixel(x+2, y+i, color);
1085 if (icon[i] & (0X1000)) drawPixel(x+3, y+i, color);
1086 if (icon[i] & (0X0800)) drawPixel(x+4, y+i, color);
1087 if (icon[i] & (0X0400)) drawPixel(x+5, y+i, color);
1088 if (icon[i] & (0X0200)) drawPixel(x+6, y+i, color);
1089 if (icon[i] & (0X0100)) drawPixel(x+7, y+i, color);
1090 if (icon[i] & (0X0080)) drawPixel(x+8, y+i, color);
1091 if (icon[i] & (0x0040)) drawPixel(x+9, y+i, color);
1092 if (icon[i] & (0X0020)) drawPixel(x+10, y+i, color);
1093 if (icon[i] & (0X0010)) drawPixel(x+11, y+i, color);
1094 if (icon[i] & (0X0008)) drawPixel(x+12, y+i, color);
1095 if (icon[i] & (0X0004)) drawPixel(x+13, y+i, color);
1096 if (icon[i] & (0X0002)) drawPixel(x+14, y+i, color);
1097 if (icon[i] & (0X0001)) drawPixel(x+15, y+i, color);
1098 }
1099 }
This page took 0.117878 seconds and 5 git commands to generate.