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 char *glyph
, uint8_t cols
, uint8_t rows
)
76 uint16_t currentY
, currentX
, indexIntoGlyph
;
77 uint16_t _row
, _col
, _colPages
;
79 // set initial current y
83 // Figure out how many columns worth of data we have
85 _colPages
= cols
/ 8 + 1;
89 for (_row
= 0; _row
< rows
; _row
++)
91 for (_col
= 0; _col
< _colPages
; _col
++)
94 indexIntoGlyph
= _col
;
96 indexIntoGlyph
= (_row
* _colPages
) + _col
;
98 currentY
= yPixel
+ _row
;
99 currentX
= xPixel
+ (_col
*8);
100 // send the data byte
101 if (glyph
[indexIntoGlyph
] & (0X80)) drawPixel(currentX
, currentY
, color
);
102 if (glyph
[indexIntoGlyph
] & (0X40)) drawPixel(currentX
+1, currentY
, color
);
103 if (glyph
[indexIntoGlyph
] & (0X20)) drawPixel(currentX
+2, currentY
, color
);
104 if (glyph
[indexIntoGlyph
] & (0X10)) drawPixel(currentX
+3, currentY
, color
);
105 if (glyph
[indexIntoGlyph
] & (0X08)) drawPixel(currentX
+4, currentY
, color
);
106 if (glyph
[indexIntoGlyph
] & (0X04)) drawPixel(currentX
+5, currentY
, color
);
107 if (glyph
[indexIntoGlyph
] & (0X02)) drawPixel(currentX
+6, currentY
, color
);
108 if (glyph
[indexIntoGlyph
] & (0X01)) drawPixel(currentX
+7, currentY
, color
);
113 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
114 /**************************************************************************/
116 @brief Draws a single smallfont character
118 /**************************************************************************/
119 void drawCharSmall(uint16_t x
, uint16_t y
, uint16_t color
, uint8_t c
, struct FONT_DEF font
)
121 uint8_t col
, column
[font
.u8Width
];
123 // Check if the requested character is available
124 if ((c
>= font
.u8FirstChar
) && (c
<= font
.u8LastChar
))
126 // Retrieve appropriate columns from font data
127 for (col
= 0; col
< font
.u8Width
; col
++)
129 column
[col
] = font
.au8FontTable
[((c
- 32) * font
.u8Width
) + col
]; // Get first column of appropriate character
134 // Requested character is not available in this font ... send a space instead
135 for (col
= 0; col
< font
.u8Width
; col
++)
137 column
[col
] = 0xFF; // Send solid space
141 // Render each column
142 uint16_t xoffset
, yoffset
;
143 for (xoffset
= 0; xoffset
< font
.u8Width
; xoffset
++)
145 for (yoffset
= 0; yoffset
< (font
.u8Height
+ 1); yoffset
++)
148 bit
= (column
[xoffset
] << (8 - (yoffset
+ 1))); // Shift current row bit left
149 bit
= (bit
>> 7); // Shift current row but right (results in 0x01 for black, and 0x00 for white)
152 drawPixel(x
+ xoffset
, y
+ yoffset
, color
);
159 /**************************************************************************/
161 @brief Helper method to accurately draw individual circle points
163 /**************************************************************************/
164 void drawCirclePoints(int cx
, int cy
, int x
, int y
, uint16_t color
)
168 drawPixel(cx
, cy
+ y
, color
);
169 drawPixel(cx
, cy
- y
, color
);
170 drawPixel(cx
+ y
, cy
, color
);
171 drawPixel(cx
- y
, cy
, color
);
175 drawPixel(cx
+ x
, cy
+ y
, color
);
176 drawPixel(cx
- x
, cy
+ y
, color
);
177 drawPixel(cx
+ x
, cy
- y
, color
);
178 drawPixel(cx
- x
, cy
- y
, color
);
182 drawPixel(cx
+ x
, cy
+ y
, color
);
183 drawPixel(cx
- x
, cy
+ y
, color
);
184 drawPixel(cx
+ x
, cy
- y
, color
);
185 drawPixel(cx
- x
, cy
- y
, color
);
186 drawPixel(cx
+ y
, cy
+ x
, color
);
187 drawPixel(cx
- y
, cy
+ x
, color
);
188 drawPixel(cx
+ y
, cy
- x
, color
);
189 drawPixel(cx
- y
, cy
- x
, color
);
193 /**************************************************************************/
195 /* ----------------------- Public Methods ------------------------------- */
197 /**************************************************************************/
199 /**************************************************************************/
201 @brief Draws a single pixel at the specified location
208 Color used when drawing
210 /**************************************************************************/
211 void drawPixel(uint16_t x
, uint16_t y
, uint16_t color
)
213 if ((x
>= lcdGetWidth()) || (y
>= lcdGetHeight()))
215 // Pixel out of range
220 lcdDrawPixel(x
, y
, color
);
223 /**************************************************************************/
225 @brief Fills the screen with the specified color
228 Color used when drawing
230 /**************************************************************************/
231 void drawFill(uint16_t color
)
236 /**************************************************************************/
238 @brief Draws a simple color test pattern
240 /**************************************************************************/
241 void drawTestPattern(void)
246 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
247 /**************************************************************************/
249 @brief Draws a string using a small font (6 of 8 pixels high).
252 Starting x co-ordinate
254 Starting y co-ordinate
256 Color to use when rendering the font
260 Pointer to the FONT_DEF to use when drawing the string
266 #include "drivers/displays/fonts/smallfonts.h"
268 drawStringSmall(1, 210, COLOR_WHITE, "5x8 System (Max 40 Characters)", Font_System5x8);
269 drawStringSmall(1, 220, COLOR_WHITE, "7x8 System (Max 30 Characters)", Font_System7x8);
273 /**************************************************************************/
274 void drawStringSmall(uint16_t x
, uint16_t y
, uint16_t color
, char* text
, struct FONT_DEF font
)
277 for (l
= 0; l
< strlen(text
); l
++)
279 drawCharSmall(x
+ (l
* (font
.u8Width
+ 1)), y
, color
, text
[l
], font
);
284 /**************************************************************************/
286 @brief Draws a string using the supplied font
289 Starting x co-ordinate
291 Starting y co-ordinate
293 Color to use when rendering the font
295 Pointer to the FONT_INFO to use when drawing the string
303 #include "drivers/displays/tft/fonts/dejavusans9.h"
305 drawString(0, 90, COLOR_BLACK, &dejaVuSans9ptFontInfo, "DejaVu Sans 9");
306 drawString(0, 105, COLOR_BLACK, &dejaVuSans9ptFontInfo, "123456789012345678901234567890");
310 /**************************************************************************/
311 void drawString(uint16_t x
, uint16_t y
, uint16_t color
, const FONT_INFO
*fontInfo
, char *str
)
313 uint16_t currentX
, charWidth
, characterToOutput
;
314 const FONT_CHAR_INFO
*charInfo
;
317 // set current x, y to that of requested
323 // get character to output
324 characterToOutput
= *str
;
327 charInfo
= fontInfo
->charInfo
;
329 // some fonts have character descriptors, some don't
330 if (charInfo
!= NULL
)
332 // get correct char offset
333 charInfo
+= (characterToOutput
- fontInfo
->startChar
);
335 // get width from char info
336 charWidth
= charInfo
->widthBits
;
338 // get offset from char info
339 charOffset
= charInfo
->offset
;
343 // if no char info, char width is always 5
346 // char offset - assume 5 * letter offset
347 charOffset
= (characterToOutput
- fontInfo
->startChar
) * 5;
350 // Send individual characters
351 // We need to manually calculate width in pages since this is screwy with variable width fonts
352 //uint8_t heightPages = charWidth % 8 ? charWidth / 8 : charWidth / 8 + 1;
353 drawCharBitmap(currentX
, y
, color
, (const char *)(&fontInfo
->data
[charOffset
]), charWidth
, fontInfo
->height
);
356 currentX
+= charWidth
+ 1;
363 /**************************************************************************/
365 @brief Returns the width in pixels of a string when it is rendered
367 This method can be used to determine whether a string will fit
368 inside a specific area, or if it needs to be broken up into multiple
369 lines to be properly rendered on the screen.
371 This function only applied to bitmap fonts (which can have variable
372 widths). All smallfonts (if available) are fixed width and can
373 easily have their width calculated without costly functions like
377 Pointer to the FONT_INFO for the font that will be used
379 The string that will be rendered
381 /**************************************************************************/
382 uint16_t drawGetStringWidth(const FONT_INFO
*fontInfo
, char *str
)
386 uint32_t startChar
= fontInfo
->startChar
;
389 for (currChar
= *str
; currChar
; currChar
= *(++str
))
391 // if char info exists for the font, use width from there
392 if (fontInfo
->charInfo
!= NULL
)
394 width
+= fontInfo
->charInfo
[currChar
- startChar
].widthBits
+ 1;
402 /* return the width */
403 return width
> 0 ? width
- 1 : width
;
406 /**************************************************************************/
408 @brief Draws a bresenham line
411 Starting x co-ordinate
413 Starting y co-ordinate
419 Color used when drawing
421 /**************************************************************************/
422 void drawLine ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
424 drawLineDotted(x0
, y0
, x1
, y1
, 0, 1, color
);
427 /**************************************************************************/
429 @brief Draws a bresenham line with a fixed pattern of empty
432 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
435 Starting x co-ordinate
437 Starting y co-ordinate
443 The number of 'empty' pixels to render
445 The number of 'solid' pixels to render
447 Color used when drawing
449 /**************************************************************************/
450 void drawLineDotted ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t empty
, uint16_t solid
, uint16_t color
)
457 // If a negative y int was passed in it will overflow to 65K something
458 // Ugly, but drawCircleFilled() can pass in negative values so we need
459 // to check the values here
460 y0
= y0
> 65000 ? 0 : y0
;
461 y1
= y1
> 65000 ? 0 : y1
;
463 // Check if we can use the optimised horizontal line method
464 if ((y0
== y1
) && (empty
== 0))
466 lcdDrawHLine(x0
, x1
, y0
, color
);
470 // Check if we can use the optimised vertical line method.
471 // This can make a huge difference in performance, but may
472 // not work properly on every LCD controller:
473 if ((x0
== x1
) && (empty
== 0))
475 // Warning: This may actually be slower than drawing individual pixels on
476 // short lines ... Set a minimum line size to use the 'optimised' method
477 // (which changes the screen orientation) ?
478 lcdDrawVLine(x0
, y0
, y1
, color
);
482 // Draw non-horizontal or dotted line
486 int emptycount
, solidcount
;
488 if (dy
< 0) { dy
= -dy
; stepy
= -1; } else { stepy
= 1; }
489 if (dx
< 0) { dx
= -dx
; stepx
= -1; } else { stepx
= 1; }
490 dy
<<= 1; // dy is now 2*dy
491 dx
<<= 1; // dx is now 2*dx
496 drawPixel(x0
, y0
, color
); // always start with solid pixels
500 int fraction
= dy
- (dx
>> 1); // same as 2*dy - dx
506 fraction
-= dx
; // same as fraction -= 2*dx
509 fraction
+= dy
; // same as fraction -= 2*dy
512 // always draw a pixel ... no dotted line requested
513 drawPixel(x0
, y0
, color
);
517 // Draw solid pxiel and decrement counter
518 drawPixel(x0
, y0
, color
);
523 // Empty pixel ... don't draw anything an decrement counter
528 // Reset counters and draw solid pixel
531 drawPixel(x0
, y0
, color
);
538 int fraction
= dx
- (dy
>> 1);
550 // always draw a pixel ... no dotted line requested
551 drawPixel(x0
, y0
, color
);
555 // Draw solid pxiel and decrement counter
556 drawPixel(x0
, y0
, color
);
561 // Empty pixel ... don't draw anything an decrement counter
566 // Reset counters and draw solid pixel
569 drawPixel(x0
, y0
, color
);
576 /**************************************************************************/
578 @brief Draws a circle
580 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture7/circle.html
583 The horizontal center of the circle
585 The vertical center of the circle
587 The circle's radius in pixels
589 Color used when drawing
591 /**************************************************************************/
592 void drawCircle (uint16_t xCenter
, uint16_t yCenter
, uint16_t radius
, uint16_t color
)
596 int p
= (5 - radius
*4)/4;
598 drawCirclePoints(xCenter
, yCenter
, x
, y
, color
);
611 drawCirclePoints(xCenter
, yCenter
, x
, y
, color
);
615 /**************************************************************************/
617 @brief Draws a filled circle
620 The horizontal center of the circle
622 The vertical center of the circle
624 The circle's radius in pixels
626 Color used when drawing
628 /**************************************************************************/
629 void drawCircleFilled (uint16_t xCenter
, uint16_t yCenter
, uint16_t radius
, uint16_t color
)
631 int16_t f
= 1 - radius
;
633 int16_t ddF_y
= -2 * radius
;
636 int16_t xc_px
, yc_my
, xc_mx
, xc_py
, yc_mx
, xc_my
;
637 int16_t lcdWidth
= lcdGetWidth();
639 if (xCenter
< lcdWidth
) drawLine(xCenter
, yCenter
-radius
< 0 ? 0 : yCenter
-radius
, xCenter
, (yCenter
-radius
) + (2*radius
), color
);
660 // Make sure X positions are not negative or too large or the pixels will
661 // overflow. Y overflow is handled in drawLine().
662 if ((xc_px
< lcdWidth
) && (xc_px
>= 0)) drawLine(xc_px
, yc_my
, xc_px
, yc_my
+ 2*y
, color
);
663 if ((xc_mx
< lcdWidth
) && (xc_mx
>= 0)) drawLine(xc_mx
, yc_my
, xc_mx
, yc_my
+ 2*y
, color
);
664 if ((xc_py
< lcdWidth
) && (xc_py
>= 0)) drawLine(xc_py
, yc_mx
, xc_py
, yc_mx
+ 2*x
, color
);
665 if ((xc_my
< lcdWidth
) && (xc_my
>= 0)) drawLine(xc_my
, yc_mx
, xc_my
, yc_mx
+ 2*x
, color
);
669 /**************************************************************************/
671 @brief Draws a filled rounded corner
674 The horizontal center of the circle
676 The vertical center of the circle
678 The circle's radius in pixels
680 The position of the corner, which affects how it will
683 Color used when drawing
685 /**************************************************************************/
686 void drawCornerFilled (uint16_t xCenter
, uint16_t yCenter
, uint16_t radius
, drawCornerPosition_t position
, uint16_t color
)
688 int16_t f
= 1 - radius
;
690 int16_t ddF_y
= -2 * radius
;
693 int16_t xc_px
, yc_my
, xc_mx
, xc_py
, yc_mx
, xc_my
;
694 int16_t lcdWidth
= lcdGetWidth();
698 case DRAW_CORNERPOSITION_TOPRIGHT
:
699 case DRAW_CORNERPOSITION_TOPLEFT
:
700 if (xCenter
< lcdWidth
) drawLine(xCenter
, yCenter
-radius
< 0 ? 0 : yCenter
-radius
, xCenter
, yCenter
, color
);
702 case DRAW_CORNERPOSITION_BOTTOMRIGHT
:
703 case DRAW_CORNERPOSITION_BOTTOMLEFT
:
704 if (xCenter
< lcdWidth
) drawLine(xCenter
, yCenter
-radius
< 0 ? 0 : yCenter
, xCenter
, (yCenter
-radius
) + (2*radius
), color
);
729 case DRAW_CORNERPOSITION_TOPRIGHT
:
730 if ((xc_px
< lcdWidth
) && (xc_px
>= 0)) drawLine(xc_px
, yc_my
, xc_px
, yCenter
, color
);
731 if ((xc_py
< lcdWidth
) && (xc_py
>= 0)) drawLine(xc_py
, yc_mx
, xc_py
, yCenter
, color
);
733 case DRAW_CORNERPOSITION_BOTTOMRIGHT
:
734 if ((xc_px
< lcdWidth
) && (xc_px
>= 0)) drawLine(xc_px
, yCenter
, xc_px
, yc_my
+ 2*y
, color
);
735 if ((xc_py
< lcdWidth
) && (xc_py
>= 0)) drawLine(xc_py
, yCenter
, xc_py
, yc_mx
+ 2*x
, color
);
737 case DRAW_CORNERPOSITION_TOPLEFT
:
738 if ((xc_mx
< lcdWidth
) && (xc_mx
>= 0)) drawLine(xc_mx
, yc_my
, xc_mx
, yCenter
, color
);
739 if ((xc_my
< lcdWidth
) && (xc_my
>= 0)) drawLine(xc_my
, yc_mx
, xc_my
, yCenter
, color
);
741 case DRAW_CORNERPOSITION_BOTTOMLEFT
:
742 if ((xc_mx
< lcdWidth
) && (xc_mx
>= 0)) drawLine(xc_mx
, yCenter
, xc_mx
, yc_my
+ 2*y
, color
);
743 if ((xc_my
< lcdWidth
) && (xc_my
>= 0)) drawLine(xc_my
, yCenter
, xc_my
, yc_mx
+ 2*x
, color
);
749 /**************************************************************************/
751 @brief Draws a simple arrow of the specified width
754 X co-ordinate of the smallest point of the arrow
756 Y co-ordinate of the smallest point of the arrow
758 Total width/height of the arrow in pixels
760 The direction that the arrow is pointing
762 Color used when drawing
764 /**************************************************************************/
765 void drawArrow(uint16_t x
, uint16_t y
, uint16_t size
, drawDirection_t direction
, uint16_t color
)
767 drawPixel(x
, y
, color
);
777 case DRAW_DIRECTION_LEFT
:
778 for (i
= 1; i
<size
; i
++)
780 drawLine(x
+i
, y
-i
, x
+i
, y
+i
, color
);
783 case DRAW_DIRECTION_RIGHT
:
784 for (i
= 1; i
<size
; i
++)
786 drawLine(x
-i
, y
-i
, x
-i
, y
+i
, color
);
789 case DRAW_DIRECTION_UP
:
790 for (i
= 1; i
<size
; i
++)
792 drawLine(x
-i
, y
+i
, x
+i
, y
+i
, color
);
795 case DRAW_DIRECTION_DOWN
:
796 for (i
= 1; i
<size
; i
++)
798 drawLine(x
-i
, y
-i
, x
+i
, y
-i
, color
);
806 /**************************************************************************/
808 @brief Draws a simple (empty) rectangle
811 Starting x co-ordinate
813 Starting y co-ordinate
819 Color used when drawing
821 /**************************************************************************/
822 void drawRectangle ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
842 drawLine (x0
, y0
, x1
, y0
, color
);
843 drawLine (x1
, y0
, x1
, y1
, color
);
844 drawLine (x1
, y1
, x0
, y1
, color
);
845 drawLine (x0
, y1
, x0
, y0
, color
);
848 /**************************************************************************/
850 @brief Draws a filled rectangle
853 Starting x co-ordinate
855 Starting y co-ordinate
861 Color used when drawing
863 /**************************************************************************/
864 void drawRectangleFilled ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
)
886 for (height
= y0
; y1
> height
- 1; ++height
)
888 drawLine(x0
, height
, x1
, height
, color
);
892 /**************************************************************************/
894 @brief Draws a filled rectangle with rounded corners
897 Starting x co-ordinate
899 Starting y co-ordinate
905 Color used when drawing
907 Corner radius in pixels
909 Which corners to round
911 /**************************************************************************/
912 void drawRectangleRounded ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t color
, uint16_t radius
, drawRoundedCorners_t corners
)
917 if (corners
== DRAW_ROUNDEDCORNERS_NONE
)
919 drawRectangleFilled(x0
, y0
, x1
, y1
, color
);
933 if (radius
> height
/ 2)
940 drawRectangleFilled(x0
+ radius
, y0
, x1
- radius
, y1
, color
);
944 case DRAW_ROUNDEDCORNERS_ALL
:
945 drawCircleFilled(x0
+ radius
, y0
+ radius
, radius
, color
);
946 drawCircleFilled(x1
- radius
, y0
+ radius
, radius
, color
);
947 drawCircleFilled(x0
+ radius
, y1
- radius
, radius
, color
);
948 drawCircleFilled(x1
- radius
, y1
- radius
, radius
, color
);
949 if (radius
*2+1 < height
)
951 drawRectangleFilled(x0
, y0
+ radius
, x0
+ radius
, y1
- radius
, color
);
952 drawRectangleFilled(x1
- radius
, y0
+ radius
, x1
, y1
- radius
, color
);
955 case DRAW_ROUNDEDCORNERS_TOP
:
956 drawCircleFilled(x0
+ radius
, y0
+ radius
, radius
, color
);
957 drawCircleFilled(x1
- radius
, y0
+ radius
, radius
, color
);
958 drawRectangleFilled(x0
, y0
+ radius
, x0
+ radius
, y1
, color
);
959 drawRectangleFilled(x1
- radius
, y0
+ radius
, x1
, y1
, color
);
961 case DRAW_ROUNDEDCORNERS_BOTTOM
:
962 drawCircleFilled(x0
+ radius
, y1
- radius
, radius
, color
);
963 drawCircleFilled(x1
- radius
, y1
- radius
, radius
, color
);
964 drawRectangleFilled(x0
, y0
, x0
+ radius
, y1
- radius
, color
);
965 drawRectangleFilled(x1
- radius
, y0
, x1
, y1
- radius
, color
);
967 case DRAW_ROUNDEDCORNERS_LEFT
:
968 drawCircleFilled(x0
+ radius
, y0
+ radius
, radius
, color
);
969 drawCircleFilled(x0
+ radius
, y1
- radius
, radius
, color
);
970 if (radius
*2+1 < height
)
972 drawRectangleFilled(x0
, y0
+ radius
, x0
+ radius
, y1
- radius
, color
);
974 drawRectangleFilled(x1
- radius
, y0
, x1
, y1
, color
);
976 case DRAW_ROUNDEDCORNERS_RIGHT
:
977 drawCircleFilled(x1
- radius
, y0
+ radius
, radius
, color
);
978 drawCircleFilled(x1
- radius
, y1
- radius
, radius
, color
);
979 if (radius
*2+1 < height
)
981 drawRectangleFilled(x1
- radius
, y0
+ radius
, x1
, y1
- radius
, color
);
983 drawRectangleFilled(x0
, y0
, x0
+ radius
, y1
, color
);
990 /**************************************************************************/
992 @brief Draws a triangle
995 x co-ordinate for point 0
997 y co-ordinate for point 0
999 x co-ordinate for point 1
1001 y co-ordinate for point 1
1003 x co-ordinate for point 2
1005 y co-ordinate for point 2
1007 Color used when drawing
1009 /**************************************************************************/
1010 void drawTriangle ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t x2
, uint16_t y2
, uint16_t color
)
1012 drawLine(x0
, y0
, x1
, y1
, color
);
1013 drawLine(x1
, y1
, x2
, y2
, color
);
1014 drawLine(x2
, y2
, x0
, y0
, color
);
1017 /**************************************************************************/
1019 @brief Draws a filled triangle
1022 x co-ordinate for point 0
1024 y co-ordinate for point 0
1026 x co-ordinate for point 1
1028 y co-ordinate for point 1
1030 x co-ordinate for point 2
1032 y co-ordinate for point 2
1040 // Draw a white triangle
1041 drawTriangleFilled ( 100, 10, 20, 120, 230, 290, COLOR_WHITE);
1042 // Draw black circles at each point of the triangle
1043 drawCircleFilled(100, 10, 2, COLOR_BLACK);
1044 drawCircleFilled(20, 120, 2, COLOR_BLACK);
1045 drawCircleFilled(230, 290, 2, COLOR_BLACK);
1049 /**************************************************************************/
1050 void drawTriangleFilled ( uint16_t x0
, uint16_t y0
, uint16_t x1
, uint16_t y1
, uint16_t x2
, uint16_t y2
, uint16_t color
)
1052 // Re-order vertices by ascending Y values (smallest first)
1054 drawSwap(y0
, y1
); drawSwap(x0
, x1
);
1057 drawSwap(y2
, y1
); drawSwap(x2
, x1
);
1060 drawSwap(y0
, y1
); drawSwap(x0
, x1
);
1063 int32_t dx1
, dx2
, dx3
; // Interpolation deltas
1064 int32_t sx1
, sx2
, sy
; // Scanline co-ordinates
1066 sx1
=sx2
=x0
* 1000; // Use fixed point math for x axis values
1069 // Calculate interpolation deltas
1070 if (y1
-y0
> 0) dx1
=((x1
-x0
)*1000)/(y1
-y0
);
1072 if (y2
-y0
> 0) dx2
=((x2
-x0
)*1000)/(y2
-y0
);
1074 if (y2
-y1
> 0) dx3
=((x2
-x1
)*1000)/(y2
-y1
);
1077 // Render scanlines (horizontal lines are the fastest rendering method)
1080 for(; sy
<=y1
; sy
++, sx1
+=dx2
, sx2
+=dx1
)
1082 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1086 for(; sy
<=y2
; sy
++, sx1
+=dx2
, sx2
+=dx3
)
1088 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1093 for(; sy
<=y1
; sy
++, sx1
+=dx1
, sx2
+=dx2
)
1095 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1099 for(; sy
<=y2
; sy
++, sx1
+=dx3
, sx2
+=dx2
)
1101 drawLine(sx1
/1000, sy
, sx2
/1000, sy
, color
);
1106 /**************************************************************************/
1108 @brief Converts a 24-bit RGB color to an equivalent 16-bit RGB565 value
1121 // Get 16-bit equivalent of 24-bit color
1122 uint16_t gray = drawRGB24toRGB565(0x33, 0x33, 0x33);
1126 /**************************************************************************/
1127 uint16_t drawRGB24toRGB565(uint8_t r
, uint8_t g
, uint8_t b
)
1129 return ((r
/ 8) << 11) | ((g
/ 4) << 5) | (b
/ 8);
1132 /**************************************************************************/
1134 @brief Converts a 16-bit RGB565 color to a standard 32-bit BGRA32
1135 color (with alpha set to 0xFF)
1144 // First convert 24-bit color to RGB565
1145 uint16_t rgb565 = drawRGB24toRGB565(0xFF, 0x00, 0x00);
1147 // Convert RGB565 color back to BGRA32
1148 uint32_t bgra32 = drawRGB565toBGRA32(rgb565);
1151 printf("BGRA32: 0x%08X R: %u G: %u B: %u A: %u \r\n",
1153 (bgra32 & 0x000000FF), // Blue
1154 (bgra32 & 0x0000FF00) >> 8, // Green
1155 (bgra32 & 0x00FF0000) >> 16, // Red
1156 (bgra32 & 0xFF000000) >> 24); // Alpha
1160 /**************************************************************************/
1161 uint32_t drawRGB565toBGRA32(uint16_t color
)
1163 uint32_t bits
= (uint32_t)color
;
1164 uint32_t blue
= bits
& 0x001F; // 5 bits blue
1165 uint32_t green
= bits
& 0x07E0; // 6 bits green
1166 uint32_t red
= bits
& 0xF800; // 5 bits red
1168 // Return shifted bits with alpha set to 0xFF
1169 return (red
<< 8) | (green
<< 5) | (blue
<< 3) | 0xFF000000;
1172 /**************************************************************************/
1174 @brief Reverses a 16-bit color from BGR to RGB
1176 /**************************************************************************/
1177 uint16_t drawBGR2RGB(uint16_t color
)
1181 b
= (color
>>0) & 0x1f;
1182 g
= (color
>>5) & 0x3f;
1183 r
= (color
>>11) & 0x1f;
1185 return( (b
<<11) + (g
<<5) + (r
<<0) );
1188 /**************************************************************************/
1190 @brief Draws a progress bar with rounded corners
1197 Total width of the progress bar in pixels
1199 Total height of the progress bar in pixels
1200 @param[in] borderCorners
1201 The type of rounded corners to render with the progress bar border
1202 @param[in] progressCorners
1203 The type of rounded corners to render with the inner progress bar
1204 @param[in] borderColor
1205 16-bit color for the outer border
1206 @param[in] borderFillColor
1207 16-bit color for the interior of the outer border
1208 @param[in] progressBorderColor
1209 16-bit color for the progress bar's border
1210 @param[in] progressFillColor
1211 16-bit color for the inner bar's fill
1213 Progress percentage (between 0 and 100)
1218 #include "drivers/displays/tft/drawing.h"
1220 // Draw a the progress bar (150x15 pixels large, starting at X:10, Y:195
1221 // with rounded corners on the top and showing 72% progress)
1222 drawProgressBar(10, 195, 150, 15, DRAW_ROUNDEDCORNERS_TOP, DRAW_ROUNDEDCORNERS_TOP, COLOR_DARKERGRAY, COLOR_DARKGRAY, COLOR_LIMEGREENDIM, COLOR_LIMEGREEN, 72 );
1226 /**************************************************************************/
1227 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
)
1229 // Draw border with rounded corners
1230 drawRectangleRounded(x
, y
, x
+ width
, y
+ height
, borderColor
, 5, borderCorners
);
1231 drawRectangleRounded(x
+1, y
+1, x
+ width
- 1, y
+ height
- 1, borderFillColor
, 5, borderCorners
);
1234 if (progress
> 0 && progress
<= 100)
1236 // Calculate bar size
1238 bw
= (width
- 6); // bar at 100%
1239 if (progress
!= 100)
1241 bw
= (bw
* progress
) / 100;
1243 drawRectangleRounded(x
+ 3, y
+ 3, bw
+ x
+ 3, y
+ height
- 3, progressBorderColor
, 5, progressCorners
);
1244 drawRectangleRounded(x
+ 4, y
+ 4, bw
+ x
+ 3 - 1, y
+ height
- 4, progressFillColor
, 5, progressCorners
);
1248 /**************************************************************************/
1250 @brief Draws a simple button
1257 Total width of the button in pixels
1259 Total height of the button in pixels
1261 Pointer to the FONT_INFO used to render the button text
1262 @param[in] fontHeight
1263 The height in pixels of the font (used for centering)
1264 @param[in] borderclr
1265 The rgb565 border color
1267 The rgb565 background color
1269 The rgb565 font color
1271 The text to render on the button
1277 #include "drivers/displays/tft/drawing.h"
1278 #include "drivers/displays/tft/fonts/dejavusans9.h"
1280 // Draw two buttons using Vera Sans Bold 9
1281 drawButton(20, 195, 200, 35, &dejaVuSans9ptFontInfo, 7, COLOR_GRAY_80, COLOR_GRAY_80, COLOR_WHITE, "System Settings");
1282 drawButton(20, 235, 200, 35, &dejaVuSans9ptFontInfo, 7, COLOR_THEME_LIMEGREEN_DARKER, COLOR_THEME_LIMEGREEN_BASE, COLOR_BLACK, "System Settings");
1286 /**************************************************************************/
1287 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
)
1290 drawRectangleRounded(x
, y
, x
+ width
, y
+ height
, borderclr
, 5, DRAW_ROUNDEDCORNERS_ALL
);
1292 drawRectangleRounded(x
+2, y
+2, x
+width
-2, y
+height
-2, fillclr
, 5, DRAW_ROUNDEDCORNERS_ALL
);
1297 uint16_t textWidth
= drawGetStringWidth(&*fontInfo
, text
);
1298 uint16_t xStart
= x
+ (width
/ 2) - (textWidth
/ 2);
1299 uint16_t yStart
= y
+ (height
/ 2) - (fontHeight
/ 2) + 1;
1300 drawString(xStart
, yStart
, fontclr
, &*fontInfo
, text
);
1304 /**************************************************************************/
1306 @brief Renders a 16x16 monochrome icon using the supplied uint16_t
1310 The horizontal location to start rendering from
1312 The vertical location to start rendering from
1314 The RGB565 color to use when rendering the icon
1316 The uint16_t array containing the 16x16 image data
1322 #include "drivers/displays/tft/drawing.h"
1323 #include "drivers/displays/icons16.h"
1325 // Renders the info icon, which has two seperate parts ... the exterior
1326 // and a seperate interior mask if you want to fill the contents with a
1328 drawIcon16(132, 202, COLOR_BLUE, icons16_info);
1329 drawIcon16(132, 202, COLOR_WHITE, icons16_info_interior);
1333 /**************************************************************************/
1334 void drawIcon16(uint16_t x
, uint16_t y
, uint16_t color
, uint16_t icon
[])
1337 for (i
= 0; i
<16; i
++)
1339 if (icon
[i
] & (0X8000)) drawPixel(x
, y
+i
, color
);
1340 if (icon
[i
] & (0X4000)) drawPixel(x
+1, y
+i
, color
);
1341 if (icon
[i
] & (0X2000)) drawPixel(x
+2, y
+i
, color
);
1342 if (icon
[i
] & (0X1000)) drawPixel(x
+3, y
+i
, color
);
1343 if (icon
[i
] & (0X0800)) drawPixel(x
+4, y
+i
, color
);
1344 if (icon
[i
] & (0X0400)) drawPixel(x
+5, y
+i
, color
);
1345 if (icon
[i
] & (0X0200)) drawPixel(x
+6, y
+i
, color
);
1346 if (icon
[i
] & (0X0100)) drawPixel(x
+7, y
+i
, color
);
1347 if (icon
[i
] & (0X0080)) drawPixel(x
+8, y
+i
, color
);
1348 if (icon
[i
] & (0x0040)) drawPixel(x
+9, y
+i
, color
);
1349 if (icon
[i
] & (0X0020)) drawPixel(x
+10, y
+i
, color
);
1350 if (icon
[i
] & (0X0010)) drawPixel(x
+11, y
+i
, color
);
1351 if (icon
[i
] & (0X0008)) drawPixel(x
+12, y
+i
, color
);
1352 if (icon
[i
] & (0X0004)) drawPixel(x
+13, y
+i
, color
);
1353 if (icon
[i
] & (0X0002)) drawPixel(x
+14, y
+i
, color
);
1354 if (icon
[i
] & (0X0001)) drawPixel(x
+15, y
+i
, color
);
1359 /**************************************************************************/
1361 @brief Loads a 24-bit Windows bitmap image from an SD card and
1368 #include "drivers/displays/tft/drawing.h"
1370 // Draw image.bmp (from the root folder) starting at pixel 0,0
1371 bmp_error_t error = drawBitmapImage(0, 0, "/image.bmp");
1377 case BMP_ERROR_SDINITFAIL:
1379 case BMP_ERROR_FILENOTFOUND:
1381 case BMP_ERROR_NOTABITMAP:
1382 // First two bytes of image not 'BM'
1384 case BMP_ERROR_INVALIDBITDEPTH:
1385 // Image is not 24-bits
1387 case BMP_ERROR_COMPRESSEDDATA:
1388 // Image contains compressed data
1390 case BMP_ERROR_INVALIDDIMENSIONS:
1391 // Width or Height is > LCD size
1393 case BMP_ERROR_PREMATUREEOF:
1394 // EOF unexpectedly reached in pixel data
1401 /**************************************************************************/
1402 bmp_error_t
drawBitmapImage(uint16_t x
, uint16_t y
, char *filename
)
1404 return bmpDrawBitmap(x
, y
, filename
);