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 Swaps values a and b
60 /**************************************************************************/
61 void drawSwap(uint32_t a
, uint32_t b
)
69 /**************************************************************************/
71 @brief Draws a single bitmap character
73 /**************************************************************************/
74 void drawCharBitmap(const uint16_t xPixel
, const uint16_t yPixel
, uint16_t color
, const uint8_t *glyph
, uint8_t cols
, uint8_t rows
)
76 uint16_t verticalPage
, horizBit
, currentY
, currentX
;
77 uint16_t indexIntoGlyph
;
79 uint16_t _row
, _col
, _colPages
;
81 // set initial current y
85 // Figure out how many columns worth of data we have
87 _colPages
= cols
/ 8 + 1;
91 for (_row
= 0; _row
< rows
; _row
++)
93 for (_col
= 0; _col
< _colPages
; _col
++)
96 indexIntoGlyph
= _col
;
98 indexIntoGlyph
= (_row
* _colPages
) + _col
;
100 currentY
= yPixel
+ _row
;
101 currentX
= xPixel
+ (_col
*8);
102 // send the data byte
103 if (glyph
[indexIntoGlyph
] & (0X80)) drawPixel(currentX
, currentY
, color
);
104 if (glyph
[indexIntoGlyph
] & (0X40)) drawPixel(currentX
+1, currentY
, color
);
105 if (glyph
[indexIntoGlyph
] & (0X20)) drawPixel(currentX
+2, currentY
, color
);
106 if (glyph
[indexIntoGlyph
] & (0X10)) drawPixel(currentX
+3, currentY
, color
);
107 if (glyph
[indexIntoGlyph
] & (0X08)) drawPixel(currentX
+4, currentY
, color
);
108 if (glyph
[indexIntoGlyph
] & (0X04)) drawPixel(currentX
+5, currentY
, color
);
109 if (glyph
[indexIntoGlyph
] & (0X02)) drawPixel(currentX
+6, currentY
, color
);
110 if (glyph
[indexIntoGlyph
] & (0X01)) drawPixel(currentX
+7, currentY
, color
);
115 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
116 /**************************************************************************/
118 @brief Draws a single smallfont character
120 /**************************************************************************/
121 void drawCharSmall(uint16_t x
, uint16_t y
, uint16_t color
, uint8_t c
, struct FONT_DEF font
)
123 uint8_t col
, column
[font
.u8Width
];
125 // Check if the requested character is available
126 if ((c
>= font
.u8FirstChar
) && (c
<= font
.u8LastChar
))
128 // Retrieve appropriate columns from font data
129 for (col
= 0; col
< font
.u8Width
; col
++)
131 column
[col
] = font
.au8FontTable
[((c
- 32) * font
.u8Width
) + col
]; // Get first column of appropriate character
136 // Requested character is not available in this font ... send a space instead
137 for (col
= 0; col
< font
.u8Width
; col
++)
139 column
[col
] = 0xFF; // Send solid space
143 // Render each column
144 uint16_t xoffset
, yoffset
;
145 for (xoffset
= 0; xoffset
< font
.u8Width
; xoffset
++)
147 for (yoffset
= 0; yoffset
< (font
.u8Height
+ 1); yoffset
++)
150 bit
= (column
[xoffset
] << (8 - (yoffset
+ 1))); // Shift current row bit left
151 bit
= (bit
>> 7); // Shift current row but right (results in 0x01 for black, and 0x00 for white)
154 drawPixel(x
+ xoffset
, y
+ yoffset
, color
);
161 /**************************************************************************/
163 @brief Helper method to accurately draw individual circle points
165 /**************************************************************************/
166 void drawCirclePoints(int cx
, int cy
, int x
, int y
, uint16_t color
)
170 drawPixel(cx
, cy
+ y
, color
);
171 drawPixel(cx
, cy
- y
, color
);
172 drawPixel(cx
+ y
, cy
, color
);
173 drawPixel(cx
- y
, cy
, color
);
177 drawPixel(cx
+ x
, cy
+ y
, color
);
178 drawPixel(cx
- x
, cy
+ y
, color
);
179 drawPixel(cx
+ x
, cy
- y
, color
);
180 drawPixel(cx
- x
, cy
- y
, color
);
184 drawPixel(cx
+ x
, cy
+ y
, color
);
185 drawPixel(cx
- x
, cy
+ y
, color
);
186 drawPixel(cx
+ x
, cy
- y
, color
);
187 drawPixel(cx
- x
, cy
- y
, color
);
188 drawPixel(cx
+ y
, cy
+ x
, color
);
189 drawPixel(cx
- y
, cy
+ x
, color
);
190 drawPixel(cx
+ y
, cy
- x
, color
);
191 drawPixel(cx
- y
, cy
- x
, color
);
195 /**************************************************************************/
197 /* ----------------------- Public Methods ------------------------------- */
199 /**************************************************************************/
201 /**************************************************************************/
203 @brief Draws a single pixel at the specified location
210 Color used when drawing
212 /**************************************************************************/
213 void drawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
215 if ((x
>= lcdGetWidth()) || (y
>= lcdGetHeight()))
217 // Pixel out of range
222 lcdDrawPixel(x
, y
, color
);
225 /**************************************************************************/
227 @brief Fills the screen with the specified color
230 Color used when drawing
232 /**************************************************************************/
233 void drawFill(uint16_t color
)
238 /**************************************************************************/
240 @brief Draws a simple color test pattern
242 /**************************************************************************/
243 void drawTestPattern(void)
248 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
249 /**************************************************************************/
251 @brief Draws a string using a small font (6 of 8 pixels high).
254 Starting x co-ordinate
256 Starting y co-ordinate
258 Color to use when rendering the font
262 Pointer to the FONT_DEF to use when drawing the string
268 #include "drivers/lcd/fonts/smallfonts.h"
270 drawStringSmall(1, 210, COLOR_WHITE, "5x8 System (Max 40 Characters)", Font_System5x8);
271 drawStringSmall(1, 220, COLOR_WHITE, "7x8 System (Max 30 Characters)", Font_System7x8);
275 /**************************************************************************/
276 void drawStringSmall(uint16_t x
, uint16_t y
, uint16_t color
, char* text
, struct FONT_DEF font
)
279 for (l
= 0; l
< strlen(text
); l
++)
281 drawCharSmall(x
+ (l
* (font
.u8Width
+ 1)), y
, color
, text
[l
], font
);
286 /**************************************************************************/
288 @brief Draws a string using the supplied font
291 Starting x co-ordinate
293 Starting y co-ordinate
295 Color to use when rendering the font
297 Pointer to the FONT_INFO to use when drawing the string
305 #include "drivers/lcd/tft/fonts/veramono9.h"
307 drawString(0, 90, COLOR_BLACK, &bitstreamVeraSansMono9ptFontInfo, "Vera Mono 9 (30 chars wide)");
308 drawString(0, 105, COLOR_BLACK, &bitstreamVeraSansMono9ptFontInfo, "123456789012345678901234567890");
312 /**************************************************************************/
313 void drawString(uint16_t x
, uint16_t y
, uint16_t color
, const FONT_INFO
*fontInfo
, char *str
)
315 uint16_t currentX
, charWidth
, characterToOutput
;
316 const FONT_CHAR_INFO
*charInfo
;
319 // set current x, y to that of requested
325 // get character to output
326 characterToOutput
= *str
;
329 charInfo
= fontInfo
->charInfo
;
331 // some fonts have character descriptors, some don't
332 if (charInfo
!= NULL
)
334 // get correct char offset
335 charInfo
+= (characterToOutput
- fontInfo
->startChar
);
337 // get width from char info
338 charWidth
= charInfo
->widthBits
;
340 // get offset from char info
341 charOffset
= charInfo
->offset
;
345 // if no char info, char width is always 5
348 // char offset - assume 5 * letter offset
349 charOffset
= (characterToOutput
- fontInfo
->startChar
) * 5;
352 // Send individual characters
353 // We need to manually calculate width in pages since this is screwy with variable width fonts
354 //uint8_t heightPages = charWidth % 8 ? charWidth / 8 : charWidth / 8 + 1;
355 drawCharBitmap(currentX
, y
, color
, &fontInfo
->data
[charOffset
], charWidth
, fontInfo
->height
);
358 currentX
+= charWidth
+ 1;
365 /**************************************************************************/
367 @brief Returns the width in pixels of a string when it is rendered
369 This method can be used to determine whether a string will fit
370 inside a specific area, or if it needs to be broken up into multiple
371 lines to be properly rendered on the screen.
373 This function only applied to bitmap fonts (which can have variable
374 widths). All smallfonts (if available) are fixed width and can
375 easily have their width calculated without costly functions like
379 Pointer to the FONT_INFO for the font that will be used
381 The string that will be rendered
383 /**************************************************************************/
384 uint16_t drawGetStringWidth(const FONT_INFO
*fontInfo
, char *str
)
388 uint32_t startChar
= fontInfo
->startChar
;
391 for (currChar
= *str
; currChar
; currChar
= *(++str
))
393 // if char info exists for the font, use width from there
394 if (fontInfo
->charInfo
!= NULL
)
396 width
+= fontInfo
->charInfo
[currChar
- startChar
].widthBits
+ 1;
404 /* return the wdith */
408 /**************************************************************************/
410 @brief Draws a bresenham line
413 Starting x co-ordinate
415 Starting y co-ordinate
421 Color used when drawing
423 /**************************************************************************/
424 void drawLine ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
426 drawLineDotted(x0
, y0
, x1
, y1
, 0, 1, color
);
429 /**************************************************************************/
431 @brief Draws a bresenham line with a fixed pattern of empty
434 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
437 Starting x co-ordinate
439 Starting y co-ordinate
445 The number of 'empty' pixels to render
447 The number of 'solid' pixels to render
449 Color used when drawing
451 /**************************************************************************/
452 void drawLineDotted ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t empty
, uint16_t solid
, uint16_t color
)
459 // If a negative y int was passed in it will overflow to 65K something
460 // Ugly, but drawCircleFilled() can pass in negative values so we need
461 // to check the values here
462 y0
= y0
> 65000 ? 0 : y0
;
463 y1
= y1
> 65000 ? 0 : y1
;
465 // Check if we can use the optimised horizontal line method
466 if ((y0
== y1
) && (empty
== 0))
468 lcdDrawHLine(x0
, x1
, y0
, color
);
472 // Check if we can use the optimised vertical line method.
473 // This can make a huge difference in performance, but may
474 // not work properly on every LCD controller:
475 if ((x0
== x1
) && (empty
== 0))
477 // Warning: This may actually be slower than drawing individual pixels on
478 // short lines ... Set a minimum line size to use the 'optimised' method
479 // (which changes the screen orientation) ?
480 lcdDrawVLine(x0
, y0
, y1
, color
);
484 // Draw non-horizontal or dotted line
488 int emptycount
, solidcount
;
490 if (dy
< 0) { dy
= -dy
; stepy
= -1; } else { stepy
= 1; }
491 if (dx
< 0) { dx
= -dx
; stepx
= -1; } else { stepx
= 1; }
492 dy
<<= 1; // dy is now 2*dy
493 dx
<<= 1; // dx is now 2*dx
498 drawPixel(x0
, y0
, color
); // always start with solid pixels
502 int fraction
= dy
- (dx
>> 1); // same as 2*dy - dx
508 fraction
-= dx
; // same as fraction -= 2*dx
511 fraction
+= dy
; // same as fraction -= 2*dy
514 // always draw a pixel ... no dotted line requested
515 drawPixel(x0
, y0
, color
);
519 // Draw solid pxiel and decrement counter
520 drawPixel(x0
, y0
, color
);
525 // Empty pixel ... don't draw anything an decrement counter
530 // Reset counters and draw solid pixel
533 drawPixel(x0
, y0
, color
);
540 int fraction
= dx
- (dy
>> 1);
552 // always draw a pixel ... no dotted line requested
553 drawPixel(x0
, y0
, color
);
557 // Draw solid pxiel and decrement counter
558 drawPixel(x0
, y0
, color
);
563 // Empty pixel ... don't draw anything an decrement counter
568 // Reset counters and draw solid pixel
571 drawPixel(x0
, y0
, color
);
578 /**************************************************************************/
580 @brief Draws a circle
582 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture7/circle.html
585 The horizontal center of the circle
587 The vertical center of the circle
589 The circle's radius in pixels
591 Color used when drawing
593 /**************************************************************************/
594 void drawCircle (uint16_t xCenter
, uint16_t yCenter
, uint16_t radius
, uint16_t color
)
598 int p
= (5 - radius
*4)/4;
600 drawCirclePoints(xCenter
, yCenter
, x
, y
, color
);
613 drawCirclePoints(xCenter
, yCenter
, x
, y
, color
);
617 /**************************************************************************/
619 @brief Draws a filled circle
622 The horizontal center of the circle
624 The vertical center of the circle
626 The circle's radius in pixels
628 Color used when drawing
630 /**************************************************************************/
631 void drawCircleFilled (uint16_t xCenter
, uint16_t yCenter
, uint16_t radius
, uint16_t color
)
633 int16_t f
= 1 - radius
;
635 int16_t ddF_y
= -2 * radius
;
638 int16_t xc_px
, yc_my
, xc_mx
, xc_py
, yc_mx
, xc_my
;
639 int16_t lcdWidth
= lcdGetWidth();
641 if (xCenter
< lcdWidth
) drawLine(xCenter
, yCenter
-radius
< 0 ? 0 : yCenter
-radius
, xCenter
, (yCenter
-radius
) + (2*radius
), color
);
662 // Make sure X positions are not negative or too large or the pixels will
663 // overflow. Y overflow is handled in drawLine().
664 if ((xc_px
< lcdWidth
) && (xc_px
>= 0)) drawLine(xc_px
, yc_my
, xc_px
, yc_my
+ 2*y
, color
);
665 if ((xc_mx
< lcdWidth
) && (xc_mx
>= 0)) drawLine(xc_mx
, yc_my
, xc_mx
, yc_my
+ 2*y
, color
);
666 if ((xc_py
< lcdWidth
) && (xc_py
>= 0)) drawLine(xc_py
, yc_mx
, xc_py
, yc_mx
+ 2*x
, color
);
667 if ((xc_my
< lcdWidth
) && (xc_my
>= 0)) drawLine(xc_my
, yc_mx
, xc_my
, yc_mx
+ 2*x
, color
);
671 /**************************************************************************/
673 @brief Draws a filled rounded corner
676 The horizontal center of the circle
678 The vertical center of the circle
680 The circle's radius in pixels
682 The position of the corner, which affects how it will
685 Color used when drawing
687 /**************************************************************************/
688 void drawCornerFilled (uint16_t xCenter
, uint16_t yCenter
, uint16_t radius
, drawCornerPosition_t position
, uint16_t color
)
690 int16_t f
= 1 - radius
;
692 int16_t ddF_y
= -2 * radius
;
695 int16_t xc_px
, yc_my
, xc_mx
, xc_py
, yc_mx
, xc_my
;
696 int16_t lcdWidth
= lcdGetWidth();
700 case DRAW_CORNERPOSITION_TOPRIGHT
:
701 case DRAW_CORNERPOSITION_TOPLEFT
:
702 if (xCenter
< lcdWidth
) drawLine(xCenter
, yCenter
-radius
< 0 ? 0 : yCenter
-radius
, xCenter
, yCenter
, color
);
704 case DRAW_CORNERPOSITION_BOTTOMRIGHT
:
705 case DRAW_CORNERPOSITION_BOTTOMLEFT
:
706 if (xCenter
< lcdWidth
) drawLine(xCenter
, yCenter
-radius
< 0 ? 0 : yCenter
, xCenter
, (yCenter
-radius
) + (2*radius
), color
);
731 case DRAW_CORNERPOSITION_TOPRIGHT
:
732 if ((xc_px
< lcdWidth
) && (xc_px
>= 0)) drawLine(xc_px
, yc_my
, xc_px
, yCenter
, color
);
733 if ((xc_py
< lcdWidth
) && (xc_py
>= 0)) drawLine(xc_py
, yc_mx
, xc_py
, yCenter
, color
);
735 case DRAW_CORNERPOSITION_BOTTOMRIGHT
:
736 if ((xc_px
< lcdWidth
) && (xc_px
>= 0)) drawLine(xc_px
, yCenter
, xc_px
, yc_my
+ 2*y
, color
);
737 if ((xc_py
< lcdWidth
) && (xc_py
>= 0)) drawLine(xc_py
, yCenter
, xc_py
, yc_mx
+ 2*x
, color
);
739 case DRAW_CORNERPOSITION_TOPLEFT
:
740 if ((xc_mx
< lcdWidth
) && (xc_mx
>= 0)) drawLine(xc_mx
, yc_my
, xc_mx
, yCenter
, color
);
741 if ((xc_my
< lcdWidth
) && (xc_my
>= 0)) drawLine(xc_my
, yc_mx
, xc_my
, yCenter
, color
);
743 case DRAW_CORNERPOSITION_BOTTOMLEFT
:
744 if ((xc_mx
< lcdWidth
) && (xc_mx
>= 0)) drawLine(xc_mx
, yCenter
, xc_mx
, yc_my
+ 2*y
, color
);
745 if ((xc_my
< lcdWidth
) && (xc_my
>= 0)) drawLine(xc_my
, yCenter
, xc_my
, yc_mx
+ 2*x
, color
);
751 /**************************************************************************/
753 @brief Draws a simple arrow of the specified width
756 X co-ordinate of the smallest point of the arrow
758 Y co-ordinate of the smallest point of the arrow
760 Total width/height of the arrow in pixels
762 The direction that the arrow is pointing
764 Color used when drawing
766 /**************************************************************************/
767 void drawArrow(uint16_t x
, uint16_t y
, uint16_t size
, drawDirection_t direction
, uint16_t color
)
769 drawPixel(x
, y
, color
);
779 case DRAW_DIRECTION_LEFT
:
780 for (i
= 1; i
<size
; i
++)
782 drawLine(x
+i
, y
-i
, x
+i
, y
+i
, color
);
785 case DRAW_DIRECTION_RIGHT
:
786 for (i
= 1; i
<size
; i
++)
788 drawLine(x
-i
, y
-i
, x
-i
, y
+i
, color
);
791 case DRAW_DIRECTION_UP
:
792 for (i
= 1; i
<size
; i
++)
794 drawLine(x
-i
, y
+i
, x
+i
, y
+i
, color
);
797 case DRAW_DIRECTION_DOWN
:
798 for (i
= 1; i
<size
; i
++)
800 drawLine(x
-i
, y
-i
, x
+i
, y
-i
, color
);
808 /**************************************************************************/
810 @brief Draws a simple (empty) rectangle
813 Starting x co-ordinate
815 Starting y co-ordinate
821 Color used when drawing
823 /**************************************************************************/
824 void drawRectangle ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
844 drawLine (x0
, y0
, x1
, y0
, color
);
845 drawLine (x1
, y0
, x1
, y1
, color
);
846 drawLine (x1
, y1
, x0
, y1
, color
);
847 drawLine (x0
, y1
, x0
, y0
, color
);
850 /**************************************************************************/
852 @brief Draws a filled rectangle
855 Starting x co-ordinate
857 Starting y co-ordinate
863 Color used when drawing
865 /**************************************************************************/
866 void drawRectangleFilled ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
888 for (height
= y0
; y1
> height
- 1; ++height
)
890 drawLine(x0
, height
, x1
, height
, color
);
894 /**************************************************************************/
896 @brief Draws a filled rectangle with rounded corners
899 Starting x co-ordinate
901 Starting y co-ordinate
907 Color used when drawing
909 Corner radius in pixels
911 Which corners to round
913 /**************************************************************************/
914 void drawRectangleRounded ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
, uint16_t radius
, drawRoundedCorners_t corners
)
919 if (corners
== DRAW_ROUNDEDCORNERS_NONE
)
921 drawRectangleFilled(x0
, y0
, x1
, y1
, color
);
935 if (radius
> height
/ 2)
942 drawRectangleFilled(x0
+ radius
, y0
, x1
- radius
, y1
, color
);
946 case DRAW_ROUNDEDCORNERS_ALL
:
947 drawCircleFilled(x0
+ radius
, y0
+ radius
, radius
, color
);
948 drawCircleFilled(x1
- radius
, y0
+ radius
, radius
, color
);
949 drawCircleFilled(x0
+ radius
, y1
- radius
, radius
, color
);
950 drawCircleFilled(x1
- radius
, y1
- radius
, radius
, color
);
951 if (radius
*2+1 < height
)
953 drawRectangleFilled(x0
, y0
+ radius
, x0
+ radius
, y1
- radius
, color
);
954 drawRectangleFilled(x1
- radius
, y0
+ radius
, x1
, y1
- radius
, color
);
957 case DRAW_ROUNDEDCORNERS_TOP
:
958 drawCircleFilled(x0
+ radius
, y0
+ radius
, radius
, color
);
959 drawCircleFilled(x1
- radius
, y0
+ radius
, radius
, color
);
960 drawRectangleFilled(x0
, y0
+ radius
, x0
+ radius
, y1
, color
);
961 drawRectangleFilled(x1
- radius
, y0
+ radius
, x1
, y1
, color
);
963 case DRAW_ROUNDEDCORNERS_BOTTOM
:
964 drawCircleFilled(x0
+ radius
, y1
- radius
, radius
, color
);
965 drawCircleFilled(x1
- radius
, y1
- radius
, radius
, color
);
966 drawRectangleFilled(x0
, y0
, x0
+ radius
, y1
- radius
, color
);
967 drawRectangleFilled(x1
- radius
, y0
, x1
, y1
- radius
, color
);
969 case DRAW_ROUNDEDCORNERS_LEFT
:
970 drawCircleFilled(x0
+ radius
, y0
+ radius
, radius
, color
);
971 drawCircleFilled(x0
+ radius
, y1
- radius
, radius
, color
);
972 if (radius
*2+1 < height
)
974 drawRectangleFilled(x0
, y0
+ radius
, x0
+ radius
, y1
- radius
, color
);
976 drawRectangleFilled(x1
- radius
, y0
, x1
, y1
, color
);
978 case DRAW_ROUNDEDCORNERS_RIGHT
:
979 drawCircleFilled(x1
- radius
, y0
+ radius
, radius
, color
);
980 drawCircleFilled(x1
- radius
, y1
- radius
, radius
, color
);
981 if (radius
*2+1 < height
)
983 drawRectangleFilled(x1
- radius
, y0
+ radius
, x1
, y1
- radius
, color
);
985 drawRectangleFilled(x0
, y0
, x0
+ radius
, y1
, color
);
992 /**************************************************************************/
994 @brief Draws a triangle
997 x co-ordinate for point 0
999 y co-ordinate for point 0
1001 x co-ordinate for point 1
1003 y co-ordinate for point 1
1005 x co-ordinate for point 2
1007 y co-ordinate for point 2
1009 Color used when drawing
1011 /**************************************************************************/
1012 void drawTriangle ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t x2
, uint16_t y2
, uint16_t color
)
1014 drawLine(x0
, y0
, x1
, y1
, color
);
1015 drawLine(x1
, y1
, x2
, y2
, color
);
1016 drawLine(x2
, y2
, x0
, y0
, color
);
1019 /**************************************************************************/
1021 @brief Draws a filled triangle
1024 x co-ordinate for point 0
1026 y co-ordinate for point 0
1028 x co-ordinate for point 1
1030 y co-ordinate for point 1
1032 x co-ordinate for point 2
1034 y co-ordinate for point 2
1042 // Draw a white triangle
1043 drawTriangleFilled ( 100, 10, 20, 120, 230, 290, COLOR_WHITE);
1044 // Draw black circles at each point of the triangle
1045 drawCircleFilled(100, 10, 2, COLOR_BLACK);
1046 drawCircleFilled(20, 120, 2, COLOR_BLACK);
1047 drawCircleFilled(230, 290, 2, COLOR_BLACK);
1051 /**************************************************************************/
1052 void drawTriangleFilled ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t x2
, uint16_t y2
, uint16_t color
)
1054 // Re-order vertices by ascending Y values (smallest first)
1056 drawSwap(y0
, y1
); drawSwap(x0
, x1
);
1059 drawSwap(y2
, y1
); drawSwap(x2
, x1
);
1062 drawSwap(y0
, y1
); drawSwap(x0
, x1
);
1065 int32_t dx1
, dx2
, dx3
; // Interpolation deltas
1066 int32_t sx1
, sx2
, sy
; // Scanline co-ordinates
1068 sx1
=sx2
=x0
* 1000; // Use fixed point math for x axis values
1071 // Calculate interpolation deltas
1072 if (y1
-y0
> 0) dx1
=((x1
-x0
)*1000)/(y1
-y0
);
1074 if (y2
-y0
> 0) dx2
=((x2
-x0
)*1000)/(y2
-y0
);
1076 if (y2
-y1
> 0) dx3
=((x2
-x1
)*1000)/(y2
-y1
);
1079 // Render scanlines (horizontal lines are the fastest rendering method)
1082 for(; sy
<=y1
; sy
++, sx1
+=dx2
, sx2
+=dx1
)
1084 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1088 for(; sy
<=y2
; sy
++, sx1
+=dx2
, sx2
+=dx3
)
1090 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1095 for(; sy
<=y1
; sy
++, sx1
+=dx1
, sx2
+=dx2
)
1097 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1101 for(; sy
<=y2
; sy
++, sx1
+=dx3
, sx2
+=dx2
)
1103 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1108 /**************************************************************************/
1110 @brief Converts a 24-bit RGB color to an equivalent 16-bit RGB565 value
1123 // Get 16-bit equivalent of 24-bit color
1124 uint16_t gray = drawRGB24toRGB565(0x33, 0x33, 0x33);
1128 /**************************************************************************/
1129 uint16_t drawRGB24toRGB565(uint8_t r
, uint8_t g
, uint8_t b
)
1131 return ((r
/ 8) << 11) | ((g
/ 4) << 5) | (b
/ 8);
1134 /**************************************************************************/
1136 @brief Converts a 16-bit RGB565 color to a standard 32-bit BGRA32
1137 color (with alpha set to 0xFF)
1146 // First convert 24-bit color to RGB565
1147 uint16_t rgb565 = drawRGB24toRGB565(0xFF, 0x00, 0x00);
1149 // Convert RGB565 color back to BGRA32
1150 uint32_t bgra32 = drawRGB565toBGRA32(rgb565);
1153 printf("BGRA32: 0x%08X R: %u G: %u B: %u A: %u \r\n",
1155 (bgra32 & 0x000000FF), // Blue
1156 (bgra32 & 0x0000FF00) >> 8, // Green
1157 (bgra32 & 0x00FF0000) >> 16, // Red
1158 (bgra32 & 0xFF000000) >> 24); // Alpha
1162 /**************************************************************************/
1163 uint32_t drawRGB565toBGRA32(uint16_t color
)
1165 uint32_t bits
= (uint32_t)color
;
1166 uint32_t blue
= bits
& 0x001F; // 5 bits blue
1167 uint32_t green
= bits
& 0x07E0; // 6 bits green
1168 uint32_t red
= bits
& 0xF800; // 5 bits red
1170 // Return shifted bits with alpha set to 0xFF
1171 return (red
<< 8) | (green
<< 5) | (blue
<< 3) | 0xFF000000;
1174 /**************************************************************************/
1176 @brief Reverses a 16-bit color from BGR to RGB
1178 /**************************************************************************/
1179 uint16_t drawBGR2RGB(uint16_t color
)
1183 b
= (color
>>0) & 0x1f;
1184 g
= (color
>>5) & 0x3f;
1185 r
= (color
>>11) & 0x1f;
1187 return( (b
<<11) + (g
<<5) + (r
<<0) );
1190 /**************************************************************************/
1192 @brief Draws a progress bar with rounded corners
1199 Total width of the progress bar in pixels
1201 Total height of the progress bar in pixels
1202 @param[in] borderCorners
1203 The type of rounded corners to render with the progress bar border
1204 @param[in] progressCorners
1205 The type of rounded corners to render with the inner progress bar
1206 @param[in] borderColor
1207 16-bit color for the outer border
1208 @param[in] borderFillColor
1209 16-bit color for the interior of the outer border
1210 @param[in] progressBorderColor
1211 16-bit color for the progress bar's border
1212 @param[in] progressFillColor
1213 16-bit color for the inner bar's fill
1215 Progress percentage (between 0 and 100)
1220 #include "drivers/lcd/tft/drawing.h"
1222 // Draw a the progress bar (150x15 pixels large, starting at X:10, Y:195
1223 // with rounded corners on the top and showing 72% progress)
1224 drawProgressBar(10, 195, 150, 15, DRAW_ROUNDEDCORNERS_TOP, DRAW_ROUNDEDCORNERS_TOP, COLOR_DARKERGRAY, COLOR_DARKGRAY, COLOR_LIMEGREENDIM, COLOR_LIMEGREEN, 72 );
1228 /**************************************************************************/
1229 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
)
1231 // Draw border with rounded corners
1232 drawRectangleRounded(x
, y
, x
+ width
, y
+ height
, borderColor
, 5, borderCorners
);
1233 drawRectangleRounded(x
+1, y
+1, x
+ width
- 1, y
+ height
- 1, borderFillColor
, 5, borderCorners
);
1236 if (progress
> 0 && progress
<= 100)
1238 // Calculate bar size
1240 bw
= (width
- 6); // bar at 100%
1241 if (progress
!= 100)
1243 bw
= (bw
* progress
) / 100;
1245 drawRectangleRounded(x
+ 3, y
+ 3, bw
+ x
+ 3, y
+ height
- 3, progressBorderColor
, 5, progressCorners
);
1246 drawRectangleRounded(x
+ 4, y
+ 4, bw
+ x
+ 3 - 1, y
+ height
- 4, progressFillColor
, 5, progressCorners
);
1250 /**************************************************************************/
1252 @brief Draws a simple button
1259 Total width of the button in pixels
1261 Total height of the button in pixels
1263 Pointer to the FONT_INFO used to render the button text
1264 @param[in] fontHeight
1265 The height in pixels of the font (used for centering)
1266 @param[in] borderclr
1267 The rgb565 border color
1269 The rgb565 background color
1271 The rgb565 font color
1273 The text to render on the button
1279 #include "drivers/lcd/tft/drawing.h"
1280 #include "drivers/lcd/tft/fonts/dejavusans9.h"
1282 // Draw two buttons using Vera Sans Bold 9
1283 drawButton(20, 195, 200, 35, &dejaVuSans9ptFontInfo, 7, COLOR_GRAY_80, COLOR_GRAY_80, COLOR_WHITE, "System Settings");
1284 drawButton(20, 235, 200, 35, &dejaVuSans9ptFontInfo, 7, COLOR_THEME_LIMEGREEN_DARKER, COLOR_THEME_LIMEGREEN_BASE, COLOR_BLACK, "System Settings");
1288 /**************************************************************************/
1289 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
)
1292 drawRectangleRounded(x
, y
, x
+ width
, y
+ height
, borderclr
, 5, DRAW_ROUNDEDCORNERS_ALL
);
1294 drawRectangleRounded(x
+2, y
+2, x
+width
-2, y
+height
-2, fillclr
, 5, DRAW_ROUNDEDCORNERS_ALL
);
1299 uint16_t textWidth
= drawGetStringWidth(&*fontInfo
, text
);
1300 uint16_t xStart
= x
+ (width
/ 2) - (textWidth
/ 2);
1301 uint16_t yStart
= y
+ (height
/ 2) - (fontHeight
/ 2) + 1;
1302 drawString(xStart
, yStart
, fontclr
, &*fontInfo
, text
);
1306 /**************************************************************************/
1308 @brief Renders a 16x16 monochrome icon using the supplied uint16_t
1312 The horizontal location to start rendering from
1314 The vertical location to start rendering from
1316 The RGB565 color to use when rendering the icon
1318 The uint16_t array containing the 16x16 image data
1324 #include "drivers/lcd/tft/drawing.h"
1325 #include "drivers/lcd/icons16.h"
1327 // Renders the info icon, which has two seperate parts ... the exterior
1328 // and a seperate interior mask if you want to fill the contents with a
1330 drawIcon16(132, 202, COLOR_BLUE, icons16_info);
1331 drawIcon16(132, 202, COLOR_WHITE, icons16_info_interior);
1335 /**************************************************************************/
1336 void drawIcon16(uint16_t x
, uint16_t y
, uint16_t color
, uint16_t icon
[])
1339 for (i
= 0; i
<16; i
++)
1341 if (icon
[i
] & (0X8000)) drawPixel(x
, y
+i
, color
);
1342 if (icon
[i
] & (0X4000)) drawPixel(x
+1, y
+i
, color
);
1343 if (icon
[i
] & (0X2000)) drawPixel(x
+2, y
+i
, color
);
1344 if (icon
[i
] & (0X1000)) drawPixel(x
+3, y
+i
, color
);
1345 if (icon
[i
] & (0X0800)) drawPixel(x
+4, y
+i
, color
);
1346 if (icon
[i
] & (0X0400)) drawPixel(x
+5, y
+i
, color
);
1347 if (icon
[i
] & (0X0200)) drawPixel(x
+6, y
+i
, color
);
1348 if (icon
[i
] & (0X0100)) drawPixel(x
+7, y
+i
, color
);
1349 if (icon
[i
] & (0X0080)) drawPixel(x
+8, y
+i
, color
);
1350 if (icon
[i
] & (0x0040)) drawPixel(x
+9, y
+i
, color
);
1351 if (icon
[i
] & (0X0020)) drawPixel(x
+10, y
+i
, color
);
1352 if (icon
[i
] & (0X0010)) drawPixel(x
+11, y
+i
, color
);
1353 if (icon
[i
] & (0X0008)) drawPixel(x
+12, y
+i
, color
);
1354 if (icon
[i
] & (0X0004)) drawPixel(x
+13, y
+i
, color
);
1355 if (icon
[i
] & (0X0002)) drawPixel(x
+14, y
+i
, color
);
1356 if (icon
[i
] & (0X0001)) drawPixel(x
+15, y
+i
, color
);
1361 /**************************************************************************/
1363 @brief Loads a 24-bit Windows bitmap image from an SD card and
1370 #include "drivers/lcd/tft/drawing.h"
1372 // Draw image.bmp (from the root folder) starting at pixel 0,0
1373 bmp_error_t error = drawBitmapImage(0, 0, "/image.bmp");
1379 case BMP_ERROR_SDINITFAIL:
1381 case BMP_ERROR_FILENOTFOUND:
1383 case BMP_ERROR_NOTABITMAP:
1384 // First two bytes of image not 'BM'
1386 case BMP_ERROR_INVALIDBITDEPTH:
1387 // Image is not 24-bits
1389 case BMP_ERROR_COMPRESSEDDATA:
1390 // Image contains compressed data
1392 case BMP_ERROR_INVALIDDIMENSIONS:
1393 // Width or Height is > LCD size
1395 case BMP_ERROR_PREMATUREEOF:
1396 // EOF unexpectedly reached in pixel data
1403 /**************************************************************************/
1404 bmp_error_t
drawBitmapImage(uint16_t x
, uint16_t y
, char *filename
)
1406 return bmpDrawBitmap(x
, y
, filename
);