1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
6 drawLine and drawCircle adapted from a tutorial by Leonard McMillan:
7 http://www.cs.unc.edu/~mcmillan/
9 drawString based on an example from Eran Duchan:
10 http://www.pavius.net/downloads/tools/53-the-dot-factory
14 Software License Agreement (BSD License)
16 Copyright (c) 2010, microBuilder SARL
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions are met:
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23 2. Redistributions in binary form must reproduce the above copyright
24 notice, this list of conditions and the following disclaimer in the
25 documentation and/or other materials provided with the distribution.
26 3. Neither the name of the copyright holders nor the
27 names of its contributors may be used to endorse or promote products
28 derived from this software without specific prior written permission.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
31 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 /**************************************************************************/
50 /**************************************************************************/
52 /* ----------------------- Private Methods ------------------------------ */
54 /**************************************************************************/
56 /**************************************************************************/
58 @brief Draws a single bitmap character
60 /**************************************************************************/
61 void drawCharBitmap(const uint16_t xPixel
, const uint16_t yPixel
, uint16_t color
, const uint8_t *glyph
, uint8_t glyphHeightPages
, uint8_t glyphWidthBits
)
63 uint16_t verticalPage
, horizBit
, currentY
, currentX
;
64 uint16_t indexIntoGlyph
;
66 // set initial current y
70 // for each page of the glyph
71 for (verticalPage
= glyphHeightPages
; verticalPage
> 0; --verticalPage
)
73 // for each horizontol bit
74 for (horizBit
= 0; horizBit
< glyphWidthBits
; ++horizBit
)
77 indexIntoGlyph
= (glyphHeightPages
* horizBit
) + verticalPage
- 1;
79 currentX
= xPixel
+ (horizBit
);
81 if (glyph
[indexIntoGlyph
] & (0X80)) drawPixel(currentX
, currentY
, color
);
82 if (glyph
[indexIntoGlyph
] & (0X40)) drawPixel(currentX
, currentY
- 1, color
);
83 if (glyph
[indexIntoGlyph
] & (0X20)) drawPixel(currentX
, currentY
- 2, color
);
84 if (glyph
[indexIntoGlyph
] & (0X10)) drawPixel(currentX
, currentY
- 3, color
);
85 if (glyph
[indexIntoGlyph
] & (0X08)) drawPixel(currentX
, currentY
- 4, color
);
86 if (glyph
[indexIntoGlyph
] & (0X04)) drawPixel(currentX
, currentY
- 5, color
);
87 if (glyph
[indexIntoGlyph
] & (0X02)) drawPixel(currentX
, currentY
- 6, color
);
88 if (glyph
[indexIntoGlyph
] & (0X01)) drawPixel(currentX
, currentY
- 7, color
);
95 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
96 /**************************************************************************/
98 @brief Draws a single smallfont character
100 /**************************************************************************/
101 void drawCharSmall(uint16_t x
, uint16_t y
, uint16_t color
, uint8_t c
, struct FONT_DEF font
)
103 uint8_t col
, column
[font
.u8Width
];
105 // Check if the requested character is available
106 if ((c
>= font
.u8FirstChar
) && (c
<= font
.u8LastChar
))
108 // Retrieve appropriate columns from font data
109 for (col
= 0; col
< font
.u8Width
; col
++)
111 column
[col
] = font
.au8FontTable
[((c
- 32) * font
.u8Width
) + col
]; // Get first column of appropriate character
116 // Requested character is not available in this font ... send a space instead
117 for (col
= 0; col
< font
.u8Width
; col
++)
119 column
[col
] = 0xFF; // Send solid space
123 // Render each column
124 uint16_t xoffset
, yoffset
;
125 for (xoffset
= 0; xoffset
< font
.u8Width
; xoffset
++)
127 for (yoffset
= 0; yoffset
< (font
.u8Height
+ 1); yoffset
++)
130 bit
= (column
[xoffset
] << (8 - (yoffset
+ 1))); // Shift current row bit left
131 bit
= (bit
>> 7); // Shift current row but right (results in 0x01 for black, and 0x00 for white)
134 drawPixel(x
+ xoffset
, y
+ yoffset
, color
);
141 /**************************************************************************/
143 @brief Helper method to accurately draw individual circle points
145 /**************************************************************************/
146 void drawCirclePoints(int cx
, int cy
, int x
, int y
, uint16_t color
)
150 drawPixel(cx
, cy
+ y
, color
);
151 drawPixel(cx
, cy
- y
, color
);
152 drawPixel(cx
+ y
, cy
, color
);
153 drawPixel(cx
- y
, cy
, color
);
157 drawPixel(cx
+ x
, cy
+ y
, color
);
158 drawPixel(cx
- x
, cy
+ y
, color
);
159 drawPixel(cx
+ x
, cy
- y
, color
);
160 drawPixel(cx
- x
, cy
- y
, color
);
164 drawPixel(cx
+ x
, cy
+ y
, color
);
165 drawPixel(cx
- x
, cy
+ y
, color
);
166 drawPixel(cx
+ x
, cy
- y
, color
);
167 drawPixel(cx
- x
, cy
- y
, color
);
168 drawPixel(cx
+ y
, cy
+ x
, color
);
169 drawPixel(cx
- y
, cy
+ x
, color
);
170 drawPixel(cx
+ y
, cy
- x
, color
);
171 drawPixel(cx
- y
, cy
- x
, color
);
175 /**************************************************************************/
177 /* ----------------------- Public Methods ------------------------------- */
179 /**************************************************************************/
181 /**************************************************************************/
183 @brief Draws a single pixel at the specified location
190 Color used when drawing
192 /**************************************************************************/
193 void drawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
195 if ((x
>= lcdGetWidth()) || (y
>= lcdGetHeight()))
197 // Pixel out of range
202 lcdDrawPixel(x
, y
, color
);
205 /**************************************************************************/
207 @brief Fills the screen with the specified color
210 Color used when drawing
212 /**************************************************************************/
213 void drawFill(uint16_t color
)
218 /**************************************************************************/
220 @brief Draws a simple color test pattern
222 /**************************************************************************/
223 void drawTestPattern(void)
228 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
229 /**************************************************************************/
231 @brief Draws a string using a small font (6 of 8 pixels high).
234 Starting x co-ordinate
236 Starting y co-ordinate
238 Color to use when rendering the font
242 Pointer to the FONT_DEF to use when drawing the string
248 #include "drivers/lcd/fonts/smallfonts.h"
250 drawStringSmall(1, 210, COLOR_WHITE, "5x8 System (Max 40 Characters)", Font_System5x8);
251 drawStringSmall(1, 220, COLOR_WHITE, "7x8 System (Max 30 Characters)", Font_System7x8);
255 /**************************************************************************/
256 void drawStringSmall(uint16_t x
, uint16_t y
, uint16_t color
, char* text
, struct FONT_DEF font
)
259 for (l
= 0; l
< strlen(text
); l
++)
261 drawCharSmall(x
+ (l
* (font
.u8Width
+ 1)), y
, color
, text
[l
], font
);
266 /**************************************************************************/
268 @brief Draws a string using the supplied font
271 Starting x co-ordinate
273 Starting y co-ordinate
275 Color to use when rendering the font
277 Pointer to the FONT_INFO to use when drawing the string
285 #include "drivers/lcd/tft/fonts/veramono9.h"
287 drawString(0, 90, COLOR_BLACK, &bitstreamVeraSansMono9ptFontInfo, "Vera Mono 9 (30 chars wide)");
288 drawString(0, 105, COLOR_BLACK, &bitstreamVeraSansMono9ptFontInfo, "123456789012345678901234567890");
292 /**************************************************************************/
293 void drawString(uint16_t x
, uint16_t y
, uint16_t color
, const FONT_INFO
*fontInfo
, char *str
)
295 uint16_t currentX
, charWidth
, characterToOutput
;
296 const FONT_CHAR_INFO
*charInfo
;
299 // set current x, y to that of requested
305 // get character to output
306 characterToOutput
= *str
;
309 charInfo
= fontInfo
->charInfo
;
311 // some fonts have character descriptors, some don't
312 if (charInfo
!= NULL
)
314 // get correct char offset
315 charInfo
+= (characterToOutput
- fontInfo
->startChar
);
317 // get width from char info
318 charWidth
= charInfo
->widthBits
;
320 // get offset from char info
321 charOffset
= charInfo
->offset
;
325 // if no char info, char width is always 5
328 // char offset - assume 5 * letter offset
329 charOffset
= (characterToOutput
- fontInfo
->startChar
) * 5;
332 // Send individual characters
333 drawCharBitmap(currentX
, y
, color
, &fontInfo
->data
[charOffset
], fontInfo
->heightPages
, charWidth
);
336 currentX
+= charWidth
+ 1;
343 /**************************************************************************/
345 @brief Returns the width in pixels of a string when it is rendered
347 This method can be used to determine whether a string will fit
348 inside a specific area, or if it needs to be broken up into multiple
349 lines to be properly rendered on the screen.
351 This function only applied to bitmap fonts (which can have variable
352 widths). All smallfonts (if available) are fixed width and can
353 easily have their width calculated without costly functions like
357 Pointer to the FONT_INFO for the font that will be used
359 The string that will be rendered
361 /**************************************************************************/
362 uint16_t drawGetStringWidth(const FONT_INFO
*fontInfo
, char *str
)
366 uint32_t startChar
= fontInfo
->startChar
;
369 for (currChar
= *str
; currChar
; currChar
= *(++str
))
371 // if char info exists for the font, use width from there
372 if (fontInfo
->charInfo
!= NULL
)
374 width
+= fontInfo
->charInfo
[currChar
- startChar
].widthBits
+ 1;
382 /* return the wdith */
386 /**************************************************************************/
388 @brief Draws a bresenham line
391 Starting x co-ordinate
393 Starting y co-ordinate
399 Color used when drawing
401 /**************************************************************************/
402 void drawLine ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
404 drawLineDotted(x0
, y0
, x1
, y1
, 0, 1, color
);
407 /**************************************************************************/
409 @brief Draws a bresenham line with a fixed pattern of empty
412 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
415 Starting x co-ordinate
417 Starting y co-ordinate
423 The number of 'empty' pixels to render
425 The number of 'solid' pixels to render
427 Color used when drawing
429 /**************************************************************************/
430 void drawLineDotted ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t empty
, uint16_t solid
, uint16_t color
)
437 // If a negative y int was passed in it will overflow to 65K something
438 // Ugly, but drawCircleFilled() can pass in negative values so we need
439 // to check the values here
440 y0
= y0
> 65000 ? 0 : y0
;
441 y1
= y1
> 65000 ? 0 : y1
;
443 // Check if we can use the optimised horizontal line method
444 if ((y0
== y1
) && (empty
== 0))
446 lcdDrawHLine(x0
, x1
, y0
, color
);
450 // Check if we can use the optimised vertical line method.
451 // This can make a huge difference in performance, but may
452 // not work properly on every LCD controller:
453 // ex.: drawCircleFilled(120, 160, 50, COLOR_RED);
454 // = 678834 cycles using lcdDrawVLine w/ILI9328 = 9.43mS @ 72MHz
455 // = 7546261 w/o lcdDrawVLine, setting each pixel = 104.8mS @ 72MHz
456 if ((x0
== x1
) && (empty
== 0))
458 // Warning: This may actually be slower than drawing individual pixels on
459 // short lines ... Set a minimum line size to use the 'optimised' method
460 // (which changes the screen orientation) ?
461 lcdDrawVLine(x0
, y0
, y1
, color
);
465 // Draw non-horizontal or dotted line
469 int emptycount
, solidcount
;
471 if (dy
< 0) { dy
= -dy
; stepy
= -1; } else { stepy
= 1; }
472 if (dx
< 0) { dx
= -dx
; stepx
= -1; } else { stepx
= 1; }
473 dy
<<= 1; // dy is now 2*dy
474 dx
<<= 1; // dx is now 2*dx
479 drawPixel(x0
, y0
, color
); // always start with solid pixels
483 int fraction
= dy
- (dx
>> 1); // same as 2*dy - dx
489 fraction
-= dx
; // same as fraction -= 2*dx
492 fraction
+= dy
; // same as fraction -= 2*dy
495 // always draw a pixel ... no dotted line requested
496 drawPixel(x0
, y0
, color
);
500 // Draw solid pxiel and decrement counter
501 drawPixel(x0
, y0
, color
);
506 // Empty pixel ... don't draw anything an decrement counter
511 // Reset counters and draw solid pixel
514 drawPixel(x0
, y0
, color
);
521 int fraction
= dx
- (dy
>> 1);
533 // always draw a pixel ... no dotted line requested
534 drawPixel(x0
, y0
, color
);
538 // Draw solid pxiel and decrement counter
539 drawPixel(x0
, y0
, color
);
544 // Empty pixel ... don't draw anything an decrement counter
549 // Reset counters and draw solid pixel
552 drawPixel(x0
, y0
, color
);
559 /**************************************************************************/
561 @brief Draws a circle
563 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture7/circle.html
566 The horizontal center of the circle
568 The vertical center of the circle
570 The circle's radius in pixels
572 Color used when drawing
574 /**************************************************************************/
575 void drawCircle (uint16_t xCenter
, uint16_t yCenter
, uint16_t radius
, uint16_t color
)
579 int p
= (5 - radius
*4)/4;
581 drawCirclePoints(xCenter
, yCenter
, x
, y
, color
);
594 drawCirclePoints(xCenter
, yCenter
, x
, y
, color
);
598 /**************************************************************************/
600 @brief Draws a filled circle
603 The horizontal center of the circle
605 The vertical center of the circle
607 The circle's radius in pixels
609 Color used when drawing
611 /**************************************************************************/
612 void drawCircleFilled (uint16_t xCenter
, uint16_t yCenter
, uint16_t radius
, uint16_t color
)
614 int16_t f
= 1 - radius
;
616 int16_t ddF_y
= -2 * radius
;
619 int16_t xc_px
, yc_my
, xc_mx
, xc_py
, yc_mx
, xc_my
;
620 int16_t lcdWidth
= lcdGetWidth();
622 if (xCenter
< lcdWidth
) drawLine(xCenter
, yCenter
-radius
< 0 ? 0 : yCenter
-radius
, xCenter
, (yCenter
-radius
) + (2*radius
), color
);
643 // Make sure X positions are not negative or too large or the pixels will
644 // overflow. Y overflow is handled in drawLine().
645 if ((xc_px
< lcdWidth
) && (xc_px
>= 0)) drawLine(xc_px
, yc_my
, xc_px
, yc_my
+ 2*y
, color
);
646 if ((xc_mx
< lcdWidth
) && (xc_mx
>= 0)) drawLine(xc_mx
, yc_my
, xc_mx
, yc_my
+ 2*y
, color
);
647 if ((xc_py
< lcdWidth
) && (xc_py
>= 0)) drawLine(xc_py
, yc_mx
, xc_py
, yc_mx
+ 2*x
, color
);
648 if ((xc_my
< lcdWidth
) && (xc_my
>= 0)) drawLine(xc_my
, yc_mx
, xc_my
, yc_mx
+ 2*x
, color
);
652 /**************************************************************************/
654 @brief Draws a filled rounded corner
657 The horizontal center of the circle
659 The vertical center of the circle
661 The circle's radius in pixels
663 The position of the corner, which affects how it will
666 Color used when drawing
668 /**************************************************************************/
669 void drawCornerFilled (uint16_t xCenter
, uint16_t yCenter
, uint16_t radius
, drawCornerPosition_t position
, uint16_t color
)
671 int16_t f
= 1 - radius
;
673 int16_t ddF_y
= -2 * radius
;
676 int16_t xc_px
, yc_my
, xc_mx
, xc_py
, yc_mx
, xc_my
;
677 int16_t lcdWidth
= lcdGetWidth();
681 case DRAW_CORNERPOSITION_TOPRIGHT
:
682 case DRAW_CORNERPOSITION_TOPLEFT
:
683 if (xCenter
< lcdWidth
) drawLine(xCenter
, yCenter
-radius
< 0 ? 0 : yCenter
-radius
, xCenter
, yCenter
, color
);
685 case DRAW_CORNERPOSITION_BOTTOMRIGHT
:
686 case DRAW_CORNERPOSITION_BOTTOMLEFT
:
687 if (xCenter
< lcdWidth
) drawLine(xCenter
, yCenter
-radius
< 0 ? 0 : yCenter
, xCenter
, (yCenter
-radius
) + (2*radius
), color
);
712 case DRAW_CORNERPOSITION_TOPRIGHT
:
713 if ((xc_px
< lcdWidth
) && (xc_px
>= 0)) drawLine(xc_px
, yc_my
, xc_px
, yCenter
, color
);
714 if ((xc_py
< lcdWidth
) && (xc_py
>= 0)) drawLine(xc_py
, yc_mx
, xc_py
, yCenter
, color
);
716 case DRAW_CORNERPOSITION_BOTTOMRIGHT
:
717 if ((xc_px
< lcdWidth
) && (xc_px
>= 0)) drawLine(xc_px
, yCenter
, xc_px
, yc_my
+ 2*y
, color
);
718 if ((xc_py
< lcdWidth
) && (xc_py
>= 0)) drawLine(xc_py
, yCenter
, xc_py
, yc_mx
+ 2*x
, color
);
720 case DRAW_CORNERPOSITION_TOPLEFT
:
721 if ((xc_mx
< lcdWidth
) && (xc_mx
>= 0)) drawLine(xc_mx
, yc_my
, xc_mx
, yCenter
, color
);
722 if ((xc_my
< lcdWidth
) && (xc_my
>= 0)) drawLine(xc_my
, yc_mx
, xc_my
, yCenter
, color
);
724 case DRAW_CORNERPOSITION_BOTTOMLEFT
:
725 if ((xc_mx
< lcdWidth
) && (xc_mx
>= 0)) drawLine(xc_mx
, yCenter
, xc_mx
, yc_my
+ 2*y
, color
);
726 if ((xc_my
< lcdWidth
) && (xc_my
>= 0)) drawLine(xc_my
, yCenter
, xc_my
, yc_mx
+ 2*x
, color
);
732 /**************************************************************************/
734 @brief Draws a simple arrow of the specified width
737 X co-ordinate of the smallest point of the arrow
739 Y co-ordinate of the smallest point of the arrow
741 Total width/height of the arrow in pixels
743 The direction that the arrow is pointing
745 Color used when drawing
747 /**************************************************************************/
748 void drawArrow(uint16_t x
, uint16_t y
, uint16_t size
, drawDirection_t direction
, uint16_t color
)
750 drawPixel(x
, y
, color
);
760 case DRAW_DIRECTION_LEFT
:
761 for (i
= 1; i
<size
; i
++)
763 drawLine(x
+i
, y
-i
, x
+i
, y
+i
, color
);
766 case DRAW_DIRECTION_RIGHT
:
767 for (i
= 1; i
<size
; i
++)
769 drawLine(x
-i
, y
-i
, x
-i
, y
+i
, color
);
772 case DRAW_DIRECTION_UP
:
773 for (i
= 1; i
<size
; i
++)
775 drawLine(x
-i
, y
+i
, x
+i
, y
+i
, color
);
778 case DRAW_DIRECTION_DOWN
:
779 for (i
= 1; i
<size
; i
++)
781 drawLine(x
-i
, y
-i
, x
+i
, y
-i
, color
);
789 /**************************************************************************/
791 @brief Draws a simple (empty) rectangle
794 Starting x co-ordinate
796 Starting y co-ordinate
802 Color used when drawing
804 /**************************************************************************/
805 void drawRectangle ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
825 drawLine (x0
, y0
, x1
, y0
, color
);
826 drawLine (x1
, y0
, x1
, y1
, color
);
827 drawLine (x1
, y1
, x0
, y1
, color
);
828 drawLine (x0
, y1
, x0
, y0
, color
);
831 /**************************************************************************/
833 @brief Draws a filled rectangle
836 Starting x co-ordinate
838 Starting y co-ordinate
844 Color used when drawing
846 /**************************************************************************/
847 void drawRectangleFilled ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
869 for (height
= y0
; y1
> height
- 1; ++height
)
871 drawLine(x0
, height
, x1
, height
, color
);
875 /**************************************************************************/
877 @brief Draws a filled rectangle with rounded corners
880 Starting x co-ordinate
882 Starting y co-ordinate
888 Color used when drawing
890 Corner radius in pixels
892 Which corners to round
894 /**************************************************************************/
895 void drawRectangleRounded ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
, uint16_t radius
, drawRoundedCorners_t corners
)
900 if (corners
== DRAW_ROUNDEDCORNERS_NONE
)
902 drawRectangleFilled(x0
, y0
, x1
, y1
, color
);
916 if (radius
> height
/ 2)
923 drawRectangleFilled(x0
+ radius
, y0
, x1
- radius
, y1
, color
);
927 case DRAW_ROUNDEDCORNERS_ALL
:
928 drawCircleFilled(x0
+ radius
, y0
+ radius
, radius
, color
);
929 drawCircleFilled(x1
- radius
, y0
+ radius
, radius
, color
);
930 drawCircleFilled(x0
+ radius
, y1
- radius
, radius
, color
);
931 drawCircleFilled(x1
- radius
, y1
- radius
, radius
, color
);
932 if (radius
*2+1 < height
)
934 drawRectangleFilled(x0
, y0
+ radius
, x0
+ radius
, y1
- radius
, color
);
935 drawRectangleFilled(x1
- radius
, y0
+ radius
, x1
, y1
- radius
, color
);
938 case DRAW_ROUNDEDCORNERS_TOP
:
939 drawCircleFilled(x0
+ radius
, y0
+ radius
, radius
, color
);
940 drawCircleFilled(x1
- radius
, y0
+ radius
, radius
, color
);
941 drawRectangleFilled(x0
, y0
+ radius
, x0
+ radius
, y1
, color
);
942 drawRectangleFilled(x1
- radius
, y0
+ radius
, x1
, y1
, color
);
944 case DRAW_ROUNDEDCORNERS_BOTTOM
:
945 drawCircleFilled(x0
+ radius
, y1
- radius
, radius
, color
);
946 drawCircleFilled(x1
- radius
, y1
- radius
, radius
, color
);
947 drawRectangleFilled(x0
, y0
, x0
+ radius
, y1
- radius
, color
);
948 drawRectangleFilled(x1
- radius
, y0
, x1
, y1
- radius
, color
);
950 case DRAW_ROUNDEDCORNERS_LEFT
:
951 drawCircleFilled(x0
+ radius
, y0
+ radius
, radius
, color
);
952 drawCircleFilled(x0
+ radius
, y1
- radius
, radius
, color
);
953 if (radius
*2+1 < height
)
955 drawRectangleFilled(x0
, y0
+ radius
, x0
+ radius
, y1
- radius
, color
);
957 drawRectangleFilled(x1
- radius
, y0
, x1
, y1
, color
);
959 case DRAW_ROUNDEDCORNERS_RIGHT
:
960 drawCircleFilled(x1
- radius
, y0
+ radius
, radius
, color
);
961 drawCircleFilled(x1
- radius
, y1
- radius
, radius
, color
);
962 if (radius
*2+1 < height
)
964 drawRectangleFilled(x1
- radius
, y0
+ radius
, x1
, y1
- radius
, color
);
966 drawRectangleFilled(x0
, y0
, x0
+ radius
, y1
, color
);
973 /**************************************************************************/
975 @brief Draws a triangle
978 x co-ordinate for point 0
980 y co-ordinate for point 0
982 x co-ordinate for point 1
984 y co-ordinate for point 1
986 x co-ordinate for point 2
988 y co-ordinate for point 2
990 Color used when drawing
992 /**************************************************************************/
993 void drawTriangle ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t x2
, uint16_t y2
, uint16_t color
)
995 drawLine(x0
, y0
, x1
, y1
, color
);
996 drawLine(x1
, y1
, x2
, y2
, color
);
997 drawLine(x2
, y2
, x0
, y0
, color
);
1000 /**************************************************************************/
1002 @brief Draws a triangle
1005 x co-ordinate for point 0
1007 y co-ordinate for point 0
1009 x co-ordinate for point 1
1011 y co-ordinate for point 1
1013 x co-ordinate for point 2
1015 y co-ordinate for point 2
1023 // Draw a white triangle
1024 drawTriangleFilled ( 100, 10, 20, 120, 230, 290, COLOR_WHITE);
1025 // Draw black circles at each point of the triangle
1026 drawCircleFilled(100, 10, 2, COLOR_BLACK);
1027 drawCircleFilled(20, 120, 2, COLOR_BLACK);
1028 drawCircleFilled(230, 290, 2, COLOR_BLACK);
1032 /**************************************************************************/
1033 void drawTriangleFilled ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t x2
, uint16_t y2
, uint16_t color
)
1035 // ToDo: re-order vertices by ascending Y values (smallest first)
1037 int32_t dx1
, dx2
, dx3
; // Interpolation deltas
1038 int32_t sx1
, sx2
, sy
; // Scanline co-ordinates
1040 sx1
=sx2
=x0
* 1000; // Use fixed point math for x axis values
1043 // Calculate interpolation deltas
1044 if (y1
-y0
> 0) dx1
=((x1
-x0
)*1000)/(y1
-y0
);
1046 if (y2
-y0
> 0) dx2
=((x2
-x0
)*1000)/(y2
-y0
);
1048 if (y2
-y1
> 0) dx3
=((x2
-x1
)*1000)/(y2
-y1
);
1051 // Render scanlines (horizontal lines are the fastest rendering method)
1054 for(; sy
<=y1
; sy
++, sx1
+=dx2
, sx2
+=dx1
)
1056 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1060 for(; sy
<=y2
; sy
++, sx1
+=dx2
, sx2
+=dx3
)
1062 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1067 for(; sy
<=y1
; sy
++, sx1
+=dx1
, sx2
+=dx2
)
1069 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1073 for(; sy
<=y2
; sy
++, sx1
+=dx3
, sx2
+=dx2
)
1075 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1080 /**************************************************************************/
1082 @brief Converts a 24-bit RGB color to an equivalent 16-bit RGB565 value
1095 // Get 16-bit equivalent of 24-bit color
1096 uint16_t gray = drawRGB24toRGB565(0x33, 0x33, 0x33);
1100 /**************************************************************************/
1101 uint16_t drawRGB24toRGB565(uint8_t r
, uint8_t g
, uint8_t b
)
1103 return ((r
/ 8) << 11) | ((g
/ 4) << 5) | (b
/ 8);
1106 /**************************************************************************/
1108 @brief Converts a 16-bit RGB565 color to a standard 32-bit BGRA32
1109 color (with alpha set to 0xFF)
1118 // First convert 24-bit color to RGB565
1119 uint16_t rgb565 = drawRGB24toRGB565(0xFF, 0x00, 0x00);
1121 // Convert RGB565 color back to BGRA32
1122 uint32_t bgra32 = drawRGB565toBGRA32(rgb565);
1125 printf("BGRA32: 0x%08X R: %u G: %u B: %u A: %u \r\n",
1127 (bgra32 & 0x000000FF), // Blue
1128 (bgra32 & 0x0000FF00) >> 8, // Green
1129 (bgra32 & 0x00FF0000) >> 16, // Red
1130 (bgra32 & 0xFF000000) >> 24); // Alpha
1134 /**************************************************************************/
1135 uint32_t drawRGB565toBGRA32(uint16_t color
)
1137 uint32_t bits
= (uint32_t)color
;
1138 uint32_t blue
= bits
& 0x001F; // 5 bits blue
1139 uint32_t green
= bits
& 0x07E0; // 6 bits green
1140 uint32_t red
= bits
& 0xF800; // 5 bits red
1142 // Return shifted bits with alpha set to 0xFF
1143 return (red
<< 8) | (green
<< 5) | (blue
<< 3) | 0xFF000000;
1146 /**************************************************************************/
1148 @brief Reverses a 16-bit color from BGR to RGB
1150 /**************************************************************************/
1151 uint16_t drawBGR2RGB(uint16_t color
)
1155 b
= (color
>>0) & 0x1f;
1156 g
= (color
>>5) & 0x3f;
1157 r
= (color
>>11) & 0x1f;
1159 return( (b
<<11) + (g
<<5) + (r
<<0) );
1162 /**************************************************************************/
1164 @brief Draws a progress bar with rounded corners
1171 Total width of the progress bar in pixels
1173 Total height of the progress bar in pixels
1174 @param[in] borderCorners
1175 The type of rounded corners to render with the progress bar border
1176 @param[in] progressCorners
1177 The type of rounded corners to render with the inner progress bar
1178 @param[in] borderColor
1179 16-bit color for the outer border
1180 @param[in] borderFillColor
1181 16-bit color for the interior of the outer border
1182 @param[in] progressBorderColor
1183 16-bit color for the progress bar's border
1184 @param[in] progressFillColor
1185 16-bit color for the inner bar's fill
1187 Progress percentage (between 0 and 100)
1192 #include "drivers/lcd/tft/drawing.h"
1194 // Draw a the progress bar (150x15 pixels large, starting at X:10, Y:195
1195 // with rounded corners on the top and showing 72% progress)
1196 drawProgressBar(10, 195, 150, 15, DRAW_ROUNDEDCORNERS_TOP, DRAW_ROUNDEDCORNERS_TOP, COLOR_DARKERGRAY, COLOR_DARKGRAY, COLOR_LIMEGREENDIM, COLOR_LIMEGREEN, 72 );
1200 /**************************************************************************/
1201 void drawProgressBar ( uint16_t x
, uint16_t y
, uint16_t width
, uint16_t height
, drawRoundedCorners_t borderCorners
, drawRoundedCorners_t progressCorners
, uint16_t borderColor
, uint16_t borderFillColor
, uint16_t progressBorderColor
, uint16_t progressFillColor
, uint8_t progress
)
1203 // Draw border with rounded corners
1204 drawRectangleRounded(x
, y
, x
+ width
, y
+ height
, borderColor
, 5, borderCorners
);
1205 drawRectangleRounded(x
+1, y
+1, x
+ width
- 1, y
+ height
- 1, borderFillColor
, 5, borderCorners
);
1208 if (progress
> 0 && progress
<= 100)
1210 // Calculate bar size
1212 bw
= (width
- 6); // bar at 100%
1213 if (progress
!= 100)
1215 bw
= (bw
* progress
) / 100;
1217 drawRectangleRounded(x
+ 3, y
+ 3, bw
+ x
+ 3, y
+ height
- 3, progressBorderColor
, 5, progressCorners
);
1218 drawRectangleRounded(x
+ 4, y
+ 4, bw
+ x
+ 3 - 1, y
+ height
- 4, progressFillColor
, 5, progressCorners
);
1222 /**************************************************************************/
1224 @brief Draws a simple button
1231 Total width of the button in pixels
1233 Total height of the button in pixels
1235 Pointer to the FONT_INFO used to render the button text
1236 @param[in] fontHeight
1237 The height in pixels of the font (used for centering)
1238 @param[in] borderclr
1239 The rgb565 border color
1241 The rgb565 background color
1243 The rgb565 font color
1245 The text to render on the button
1251 #include "drivers/lcd/tft/drawing.h"
1252 #include "drivers/lcd/tft/fonts/dejavusansbold9.h"
1254 // Draw two buttons using Vera Sans Bold 9
1255 drawButton(20, 195, 200, 35, &dejaVuSansBold9ptFontInfo, 7, COLOR_DARKERGRAY, COLOR_DARKERGRAY, COLOR_WHITE, "System Settings");
1256 drawButton(20, 235, 200, 35, &dejaVuSansBold9ptFontInfo, 7, COLOR_LIMEGREENDIM, COLOR_LIMEGREEN, COLOR_BLACK, "System Settings");
1260 /**************************************************************************/
1261 void drawButton(uint16_t x
, uint16_t y
, uint16_t width
, uint16_t height
, const FONT_INFO
*fontInfo
, uint16_t fontHeight
, uint16_t borderclr
, uint16_t fillclr
, uint16_t fontclr
, char* text
)
1264 drawRectangleRounded(x
, y
, x
+ width
, y
+ height
, borderclr
, 5, DRAW_ROUNDEDCORNERS_ALL
);
1266 drawRectangleRounded(x
+2, y
+2, x
+width
-2, y
+height
-2, fillclr
, 5, DRAW_ROUNDEDCORNERS_ALL
);
1271 uint16_t textWidth
= drawGetStringWidth(&*fontInfo
, text
);
1272 uint16_t xStart
= x
+ (width
/ 2) - (textWidth
/ 2);
1273 uint16_t yStart
= y
+ (height
/ 2) - (fontHeight
/ 2) + 1;
1274 drawString(xStart
, yStart
, fontclr
, &*fontInfo
, text
);
1278 /**************************************************************************/
1280 @brief Renders a 16x16 monochrome icon using the supplied uint16_t
1284 The horizontal location to start rendering from
1286 The vertical location to start rendering from
1288 The RGB565 color to use when rendering the icon
1290 The uint16_t array containing the 16x16 image data
1296 #include "drivers/lcd/tft/drawing.h"
1297 #include "drivers/lcd/icons16.h"
1299 // Renders the info icon, which has two seperate parts ... the exterior
1300 // and a seperate interior mask if you want to fill the contents with a
1302 drawIcon16(132, 202, COLOR_BLUE, icons16_info);
1303 drawIcon16(132, 202, COLOR_WHITE, icons16_info_interior);
1307 /**************************************************************************/
1308 void drawIcon16(uint16_t x
, uint16_t y
, uint16_t color
, uint16_t icon
[])
1311 for (i
= 0; i
<16; i
++)
1313 if (icon
[i
] & (0X8000)) drawPixel(x
, y
+i
, color
);
1314 if (icon
[i
] & (0X4000)) drawPixel(x
+1, y
+i
, color
);
1315 if (icon
[i
] & (0X2000)) drawPixel(x
+2, y
+i
, color
);
1316 if (icon
[i
] & (0X1000)) drawPixel(x
+3, y
+i
, color
);
1317 if (icon
[i
] & (0X0800)) drawPixel(x
+4, y
+i
, color
);
1318 if (icon
[i
] & (0X0400)) drawPixel(x
+5, y
+i
, color
);
1319 if (icon
[i
] & (0X0200)) drawPixel(x
+6, y
+i
, color
);
1320 if (icon
[i
] & (0X0100)) drawPixel(x
+7, y
+i
, color
);
1321 if (icon
[i
] & (0X0080)) drawPixel(x
+8, y
+i
, color
);
1322 if (icon
[i
] & (0x0040)) drawPixel(x
+9, y
+i
, color
);
1323 if (icon
[i
] & (0X0020)) drawPixel(x
+10, y
+i
, color
);
1324 if (icon
[i
] & (0X0010)) drawPixel(x
+11, y
+i
, color
);
1325 if (icon
[i
] & (0X0008)) drawPixel(x
+12, y
+i
, color
);
1326 if (icon
[i
] & (0X0004)) drawPixel(x
+13, y
+i
, color
);
1327 if (icon
[i
] & (0X0002)) drawPixel(x
+14, y
+i
, color
);
1328 if (icon
[i
] & (0X0001)) drawPixel(x
+15, y
+i
, color
);
1333 /**************************************************************************/
1335 @brief Loads a 24-bit Windows bitmap image from an SD card and
1342 #include "drivers/lcd/tft/drawing.h"
1344 // Draw image.bmp (from the root folder) starting at pixel 0,0
1345 bmp_error_t error = drawBitmapImage(0, 0, "/image.bmp");
1351 case BMP_ERROR_SDINITFAIL:
1353 case BMP_ERROR_FILENOTFOUND:
1355 case BMP_ERROR_NOTABITMAP:
1356 // First two bytes of image not 'BM'
1358 case BMP_ERROR_INVALIDBITDEPTH:
1359 // Image is not 24-bits
1361 case BMP_ERROR_COMPRESSEDDATA:
1362 // Image contains compressed data
1364 case BMP_ERROR_INVALIDDIMENSIONS:
1365 // Width or Height is > LCD size
1367 case BMP_ERROR_PREMATUREEOF:
1368 // EOF unexpectedly reached in pixel data
1375 /**************************************************************************/
1376 bmp_error_t
drawBitmapImage(uint16_t x
, uint16_t y
, char *filename
)
1378 return bmpDrawBitmap(x
, y
, filename
);