Various changes for smartlcd boards
[hackover2013-badge-firmware.git] / drivers / lcd / tft / drawing.c
1 /**************************************************************************/
2 /*!
3 @file drawing.c
4 @author K. Townsend (microBuilder.eu)
5
6 drawLine and drawCircle adapted from a tutorial by Leonard McMillan:
7 http://www.cs.unc.edu/~mcmillan/
8
9 drawString based on an example from Eran Duchan:
10 http://www.pavius.net/downloads/tools/53-the-dot-factory
11
12 @section LICENSE
13
14 Software License Agreement (BSD License)
15
16 Copyright (c) 2010, microBuilder SARL
17 All rights reserved.
18
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.
29
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.
40 */
41 /**************************************************************************/
42 #include <string.h>
43
44 #include "drawing.h"
45
46 #ifdef CFG_SDCARD
47 #include "bmp.h"
48 #endif
49
50 /**************************************************************************/
51 /* */
52 /* ----------------------- Private Methods ------------------------------ */
53 /* */
54 /**************************************************************************/
55
56 /**************************************************************************/
57 /*!
58 @brief Draws a single bitmap character
59 */
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)
62 {
63 uint16_t verticalPage, horizBit, currentY, currentX;
64 uint16_t indexIntoGlyph;
65
66 // set initial current y
67 currentY = yPixel;
68 currentX = xPixel;
69
70 // for each page of the glyph
71 for (verticalPage = glyphHeightPages; verticalPage > 0; --verticalPage)
72 {
73 // for each horizontol bit
74 for (horizBit = 0; horizBit < glyphWidthBits; ++horizBit)
75 {
76 // next byte
77 indexIntoGlyph = (glyphHeightPages * horizBit) + verticalPage - 1;
78
79 currentX = xPixel + (horizBit);
80 // send the data byte
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);
89 }
90 // next line of pages
91 currentY += 8;
92 }
93 }
94
95 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
96 /**************************************************************************/
97 /*!
98 @brief Draws a single smallfont character
99 */
100 /**************************************************************************/
101 void drawCharSmall(uint16_t x, uint16_t y, uint16_t color, uint8_t c, struct FONT_DEF font)
102 {
103 uint8_t col, column[font.u8Width];
104
105 // Check if the requested character is available
106 if ((c >= font.u8FirstChar) && (c <= font.u8LastChar))
107 {
108 // Retrieve appropriate columns from font data
109 for (col = 0; col < font.u8Width; col++)
110 {
111 column[col] = font.au8FontTable[((c - 32) * font.u8Width) + col]; // Get first column of appropriate character
112 }
113 }
114 else
115 {
116 // Requested character is not available in this font ... send a space instead
117 for (col = 0; col < font.u8Width; col++)
118 {
119 column[col] = 0xFF; // Send solid space
120 }
121 }
122
123 // Render each column
124 uint16_t xoffset, yoffset;
125 for (xoffset = 0; xoffset < font.u8Width; xoffset++)
126 {
127 for (yoffset = 0; yoffset < (font.u8Height + 1); yoffset++)
128 {
129 uint8_t bit = 0x00;
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)
132 if (bit)
133 {
134 drawPixel(x + xoffset, y + yoffset, color);
135 }
136 }
137 }
138 }
139 #endif
140
141 /**************************************************************************/
142 /*!
143 @brief Helper method to accurately draw individual circle points
144 */
145 /**************************************************************************/
146 void drawCirclePoints(int cx, int cy, int x, int y, uint16_t color)
147 {
148 if (x == 0)
149 {
150 drawPixel(cx, cy + y, color);
151 drawPixel(cx, cy - y, color);
152 drawPixel(cx + y, cy, color);
153 drawPixel(cx - y, cy, color);
154 }
155 else if (x == y)
156 {
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);
161 }
162 else if (x < y)
163 {
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);
172 }
173 }
174
175 /**************************************************************************/
176 /* */
177 /* ----------------------- Public Methods ------------------------------- */
178 /* */
179 /**************************************************************************/
180
181 /**************************************************************************/
182 /*!
183 @brief Draws a single pixel at the specified location
184
185 @param[in] x
186 Horizontal position
187 @param[in] y
188 Vertical position
189 @param[in] color
190 Color used when drawing
191 */
192 /**************************************************************************/
193 void drawPixel(uint16_t x, uint16_t y, uint16_t color)
194 {
195 if ((x >= lcdGetWidth()) || (y >= lcdGetHeight()))
196 {
197 // Pixel out of range
198 return;
199 }
200
201 // Redirect to LCD
202 lcdDrawPixel(x, y, color);
203 }
204
205 /**************************************************************************/
206 /*!
207 @brief Fills the screen with the specified color
208
209 @param[in] color
210 Color used when drawing
211 */
212 /**************************************************************************/
213 void drawFill(uint16_t color)
214 {
215 lcdFillRGB(color);
216 }
217
218 /**************************************************************************/
219 /*!
220 @brief Draws a simple color test pattern
221 */
222 /**************************************************************************/
223 void drawTestPattern(void)
224 {
225 lcdTest();
226 }
227
228 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
229 /**************************************************************************/
230 /*!
231 @brief Draws a string using a small font (6 of 8 pixels high).
232
233 @param[in] x
234 Starting x co-ordinate
235 @param[in] y
236 Starting y co-ordinate
237 @param[in] color
238 Color to use when rendering the font
239 @param[in] text
240 The string to render
241 @param[in] font
242 Pointer to the FONT_DEF to use when drawing the string
243
244 @section Example
245
246 @code
247
248 #include "drivers/lcd/fonts/smallfonts.h"
249
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);
252
253 @endcode
254 */
255 /**************************************************************************/
256 void drawStringSmall(uint16_t x, uint16_t y, uint16_t color, char* text, struct FONT_DEF font)
257 {
258 uint8_t l;
259 for (l = 0; l < strlen(text); l++)
260 {
261 drawCharSmall(x + (l * (font.u8Width + 1)), y, color, text[l], font);
262 }
263 }
264 #endif
265
266 /**************************************************************************/
267 /*!
268 @brief Draws a string using the supplied font
269
270 @param[in] x
271 Starting x co-ordinate
272 @param[in] y
273 Starting y co-ordinate
274 @param[in] color
275 Color to use when rendering the font
276 @param[in] fontInfo
277 Pointer to the FONT_INFO to use when drawing the string
278 @param[in] str
279 The string to render
280
281 @section Example
282
283 @code
284
285 #include "drivers/lcd/tft/fonts/veramono9.h"
286
287 drawString(0, 90, COLOR_BLACK, &bitstreamVeraSansMono9ptFontInfo, "Vera Mono 9 (30 chars wide)");
288 drawString(0, 105, COLOR_BLACK, &bitstreamVeraSansMono9ptFontInfo, "123456789012345678901234567890");
289
290 @endcode
291 */
292 /**************************************************************************/
293 void drawString(uint16_t x, uint16_t y, uint16_t color, const FONT_INFO *fontInfo, char *str)
294 {
295 uint16_t currentX, charWidth, characterToOutput;
296 const FONT_CHAR_INFO *charInfo;
297 uint16_t charOffset;
298
299 // set current x, y to that of requested
300 currentX = x;
301
302 // while not NULL
303 while (*str != '\0')
304 {
305 // get character to output
306 characterToOutput = *str;
307
308 // get char info
309 charInfo = fontInfo->charInfo;
310
311 // some fonts have character descriptors, some don't
312 if (charInfo != NULL)
313 {
314 // get correct char offset
315 charInfo += (characterToOutput - fontInfo->startChar);
316
317 // get width from char info
318 charWidth = charInfo->widthBits;
319
320 // get offset from char info
321 charOffset = charInfo->offset;
322 }
323 else
324 {
325 // if no char info, char width is always 5
326 charWidth = 5;
327
328 // char offset - assume 5 * letter offset
329 charOffset = (characterToOutput - fontInfo->startChar) * 5;
330 }
331
332 // Send individual characters
333 drawCharBitmap(currentX, y, color, &fontInfo->data[charOffset], fontInfo->heightPages, charWidth);
334
335 // next char X
336 currentX += charWidth + 1;
337
338 // next char
339 str++;
340 }
341 }
342
343 /**************************************************************************/
344 /*!
345 @brief Returns the width in pixels of a string when it is rendered
346
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.
350
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
354 this one.
355
356 @param[in] fontInfo
357 Pointer to the FONT_INFO for the font that will be used
358 @param[in] str
359 The string that will be rendered
360 */
361 /**************************************************************************/
362 uint16_t drawGetStringWidth(const FONT_INFO *fontInfo, char *str)
363 {
364 uint16_t width = 0;
365 uint32_t currChar;
366 uint32_t startChar = fontInfo->startChar;
367
368 // until termination
369 for (currChar = *str; currChar; currChar = *(++str))
370 {
371 // if char info exists for the font, use width from there
372 if (fontInfo->charInfo != NULL)
373 {
374 width += fontInfo->charInfo[currChar - startChar].widthBits + 1;
375 }
376 else
377 {
378 width += 5 + 1;
379 }
380 }
381
382 /* return the wdith */
383 return width;
384 }
385
386 /**************************************************************************/
387 /*!
388 @brief Draws a bresenham line
389
390 @param[in] x0
391 Starting x co-ordinate
392 @param[in] y0
393 Starting y co-ordinate
394 @param[in] x1
395 Ending x co-ordinate
396 @param[in] y1
397 Ending y co-ordinate
398 @param[in] color
399 Color used when drawing
400 */
401 /**************************************************************************/
402 void drawLine ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color )
403 {
404 drawLineDotted(x0, y0, x1, y1, 0, 1, color);
405 }
406
407 /**************************************************************************/
408 /*!
409 @brief Draws a bresenham line with a fixed pattern of empty
410 and solid pixels
411
412 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
413
414 @param[in] x0
415 Starting x co-ordinate
416 @param[in] y0
417 Starting y co-ordinate
418 @param[in] x1
419 Ending x co-ordinate
420 @param[in] y1
421 Ending y co-ordinate
422 @param[in] empty
423 The number of 'empty' pixels to render
424 @param[in] solid
425 The number of 'solid' pixels to render
426 @param[in] color
427 Color used when drawing
428 */
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 )
431 {
432 if (solid == 0)
433 {
434 return;
435 }
436
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;
442
443 // Check if we can use the optimised horizontal line method
444 if ((y0 == y1) && (empty == 0))
445 {
446 lcdDrawHLine(x0, x1, y0, color);
447 return;
448 }
449
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))
457 {
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);
462 return;
463 }
464
465 // Draw non-horizontal or dotted line
466 int dy = y1 - y0;
467 int dx = x1 - x0;
468 int stepx, stepy;
469 int emptycount, solidcount;
470
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
475
476 emptycount = empty;
477 solidcount = solid;
478
479 drawPixel(x0, y0, color); // always start with solid pixels
480 solidcount--;
481 if (dx > dy)
482 {
483 int fraction = dy - (dx >> 1); // same as 2*dy - dx
484 while (x0 != x1)
485 {
486 if (fraction >= 0)
487 {
488 y0 += stepy;
489 fraction -= dx; // same as fraction -= 2*dx
490 }
491 x0 += stepx;
492 fraction += dy; // same as fraction -= 2*dy
493 if (empty == 0)
494 {
495 // always draw a pixel ... no dotted line requested
496 drawPixel(x0, y0, color);
497 }
498 else if (solidcount)
499 {
500 // Draw solid pxiel and decrement counter
501 drawPixel(x0, y0, color);
502 solidcount--;
503 }
504 else if(emptycount)
505 {
506 // Empty pixel ... don't draw anything an decrement counter
507 emptycount--;
508 }
509 else
510 {
511 // Reset counters and draw solid pixel
512 emptycount = empty;
513 solidcount = solid;
514 drawPixel(x0, y0, color);
515 solidcount--;
516 }
517 }
518 }
519 else
520 {
521 int fraction = dx - (dy >> 1);
522 while (y0 != y1)
523 {
524 if (fraction >= 0)
525 {
526 x0 += stepx;
527 fraction -= dy;
528 }
529 y0 += stepy;
530 fraction += dx;
531 if (empty == 0)
532 {
533 // always draw a pixel ... no dotted line requested
534 drawPixel(x0, y0, color);
535 }
536 if (solidcount)
537 {
538 // Draw solid pxiel and decrement counter
539 drawPixel(x0, y0, color);
540 solidcount--;
541 }
542 else if(emptycount)
543 {
544 // Empty pixel ... don't draw anything an decrement counter
545 emptycount--;
546 }
547 else
548 {
549 // Reset counters and draw solid pixel
550 emptycount = empty;
551 solidcount = solid;
552 drawPixel(x0, y0, color);
553 solidcount--;
554 }
555 }
556 }
557 }
558
559 /**************************************************************************/
560 /*!
561 @brief Draws a circle
562
563 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture7/circle.html
564
565 @param[in] xCenter
566 The horizontal center of the circle
567 @param[in] yCenter
568 The vertical center of the circle
569 @param[in] radius
570 The circle's radius in pixels
571 @param[in] color
572 Color used when drawing
573 */
574 /**************************************************************************/
575 void drawCircle (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint16_t color)
576 {
577 int x = 0;
578 int y = radius;
579 int p = (5 - radius*4)/4;
580
581 drawCirclePoints(xCenter, yCenter, x, y, color);
582 while (x < y)
583 {
584 x++;
585 if (p < 0)
586 {
587 p += 2*x+1;
588 }
589 else
590 {
591 y--;
592 p += 2*(x-y)+1;
593 }
594 drawCirclePoints(xCenter, yCenter, x, y, color);
595 }
596 }
597
598 /**************************************************************************/
599 /*!
600 @brief Draws a filled circle
601
602 @param[in] xCenter
603 The horizontal center of the circle
604 @param[in] yCenter
605 The vertical center of the circle
606 @param[in] radius
607 The circle's radius in pixels
608 @param[in] color
609 Color used when drawing
610 */
611 /**************************************************************************/
612 void drawCircleFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint16_t color)
613 {
614 int16_t f = 1 - radius;
615 int16_t ddF_x = 1;
616 int16_t ddF_y = -2 * radius;
617 int16_t x = 0;
618 int16_t y = radius;
619 int16_t xc_px, yc_my, xc_mx, xc_py, yc_mx, xc_my;
620 int16_t lcdWidth = lcdGetWidth();
621
622 if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter-radius, xCenter, (yCenter-radius) + (2*radius), color);
623
624 while (x<y)
625 {
626 if (f >= 0)
627 {
628 y--;
629 ddF_y += 2;
630 f += ddF_y;
631 }
632 x++;
633 ddF_x += 2;
634 f += ddF_x;
635
636 xc_px = xCenter+x;
637 xc_mx = xCenter-x;
638 xc_py = xCenter+y;
639 xc_my = xCenter-y;
640 yc_mx = yCenter-x;
641 yc_my = yCenter-y;
642
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);
649 }
650 }
651
652 /**************************************************************************/
653 /*!
654 @brief Draws a simple arrow of the specified width
655
656 @param[in] x
657 X co-ordinate of the smallest point of the arrow
658 @param[in] y
659 Y co-ordinate of the smallest point of the arrow
660 @param[in] size
661 Total width/height of the arrow in pixels
662 @param[in] direction
663 The direction that the arrow is pointing
664 @param[in] color
665 Color used when drawing
666 */
667 /**************************************************************************/
668 void drawArrow(uint16_t x, uint16_t y, uint16_t size, drawDirection_t direction, uint16_t color)
669 {
670 drawPixel(x, y, color);
671
672 if (size == 1)
673 {
674 return;
675 }
676
677 uint32_t i;
678 switch (direction)
679 {
680 case DRAW_DIRECTION_LEFT:
681 for (i = 1; i<size; i++)
682 {
683 drawLine(x+i, y-i, x+i, y+i, color);
684 }
685 break;
686 case DRAW_DIRECTION_RIGHT:
687 for (i = 1; i<size; i++)
688 {
689 drawLine(x-i, y-i, x-i, y+i, color);
690 }
691 break;
692 case DRAW_DIRECTION_UP:
693 for (i = 1; i<size; i++)
694 {
695 drawLine(x-i, y+i, x+i, y+i, color);
696 }
697 break;
698 case DRAW_DIRECTION_DOWN:
699 for (i = 1; i<size; i++)
700 {
701 drawLine(x-i, y-i, x+i, y-i, color);
702 }
703 break;
704 default:
705 break;
706 }
707 }
708
709 /**************************************************************************/
710 /*!
711 @brief Draws a simple (empty) rectangle
712
713 @param[in] x0
714 Starting x co-ordinate
715 @param[in] y0
716 Starting y co-ordinate
717 @param[in] x1
718 Ending x co-ordinate
719 @param[in] y1
720 Ending y co-ordinate
721 @param[in] color
722 Color used when drawing
723 */
724 /**************************************************************************/
725 void drawRectangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
726 {
727 uint16_t x, y;
728
729 if (y1 < y0)
730 {
731 // Switch y1 and y0
732 y = y1;
733 y1 = y0;
734 y0 = y;
735 }
736
737 if (x1 < x0)
738 {
739 // Switch x1 and x0
740 x = x1;
741 x1 = x0;
742 x0 = x;
743 }
744
745 drawLine (x0, y0, x1, y0, color);
746 drawLine (x1, y0, x1, y1, color);
747 drawLine (x1, y1, x0, y1, color);
748 drawLine (x0, y1, x0, y0, color);
749 }
750
751 /**************************************************************************/
752 /*!
753 @brief Draws a filled rectangle
754
755 @param[in] x0
756 Starting x co-ordinate
757 @param[in] y0
758 Starting y co-ordinate
759 @param[in] x1
760 Ending x co-ordinate
761 @param[in] y1
762 Ending y co-ordinate
763 @param[in] color
764 Color used when drawing
765 */
766 /**************************************************************************/
767 void drawRectangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
768 {
769 int height;
770 uint16_t x, y;
771
772 if (y1 < y0)
773 {
774 // Switch y1 and y0
775 y = y1;
776 y1 = y0;
777 y0 = y;
778 }
779
780 if (x1 < x0)
781 {
782 // Switch x1 and x0
783 x = x1;
784 x1 = x0;
785 x0 = x;
786 }
787
788 height = y1 - y0;
789 for (height = y0; y1 > height - 1; ++height)
790 {
791 drawLine(x0, height, x1, height, color);
792 }
793 }
794
795 /**************************************************************************/
796 /*!
797 @brief Draws a filled rectangle with rounded corners
798
799 @param[in] x0
800 Starting x co-ordinate
801 @param[in] y0
802 Starting y co-ordinate
803 @param[in] x1
804 Ending x co-ordinate
805 @param[in] y1
806 Ending y co-ordinate
807 @param[in] color
808 Color used when drawing
809 @param[in] radius
810 Corner radius in pixels
811 @param[in] corners
812 Which corners to round
813 */
814 /**************************************************************************/
815 void drawRectangleRounded ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color, uint16_t radius, drawRoundedCorners_t corners )
816 {
817 int height;
818 uint16_t y;
819
820 if (corners == DRAW_ROUNDEDCORNERS_NONE)
821 {
822 drawRectangleFilled(x0, y0, x1, y1, color);
823 return;
824 }
825
826 // Calculate height
827 if (y1 < y0)
828 {
829 y = y1;
830 y1 = y0;
831 y0 = y;
832 }
833 height = y1 - y0;
834
835 // Check radius
836 if (radius > height / 2)
837 {
838 radius = height / 2;
839 }
840 radius -= 1;
841
842 // Draw body
843 drawRectangleFilled(x0 + radius, y0, x1 - radius, y1, color);
844
845 switch (corners)
846 {
847 case DRAW_ROUNDEDCORNERS_ALL:
848 drawCircleFilled(x0 + radius, y0 + radius, radius, color);
849 drawCircleFilled(x1 - radius, y0 + radius, radius, color);
850 drawCircleFilled(x0 + radius, y1 - radius, radius, color);
851 drawCircleFilled(x1 - radius, y1 - radius, radius, color);
852 if (radius*2+1 < height)
853 {
854 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
855 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
856 }
857 break;
858 case DRAW_ROUNDEDCORNERS_TOP:
859 drawCircleFilled(x0 + radius, y0 + radius, radius, color);
860 drawCircleFilled(x1 - radius, y0 + radius, radius, color);
861 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1, color);
862 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1, color);
863 break;
864 case DRAW_ROUNDEDCORNERS_BOTTOM:
865 drawCircleFilled(x0 + radius, y1 - radius, radius, color);
866 drawCircleFilled(x1 - radius, y1 - radius, radius, color);
867 drawRectangleFilled(x0, y0, x0 + radius, y1 - radius, color);
868 drawRectangleFilled(x1 - radius, y0, x1, y1 - radius, color);
869 break;
870 case DRAW_ROUNDEDCORNERS_LEFT:
871 drawCircleFilled(x0 + radius, y0 + radius, radius, color);
872 drawCircleFilled(x0 + radius, y1 - radius, radius, color);
873 if (radius*2+1 < height)
874 {
875 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
876 }
877 drawRectangleFilled(x1 - radius, y0, x1, y1, color);
878 break;
879 case DRAW_ROUNDEDCORNERS_RIGHT:
880 drawCircleFilled(x1 - radius, y0 + radius, radius, color);
881 drawCircleFilled(x1 - radius, y1 - radius, radius, color);
882 if (radius*2+1 < height)
883 {
884 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
885 }
886 drawRectangleFilled(x0, y0, x0 + radius, y1, color);
887 break;
888 default:
889 break;
890 }
891 }
892
893 /**************************************************************************/
894 /*!
895 @brief Converts a 24-bit RGB color to an equivalent 16-bit RGB565 value
896
897 @param[in] r
898 8-bit red
899 @param[in] g
900 8-bit green
901 @param[in] b
902 8-bit blue
903
904 @section Example
905
906 @code
907
908 // Get 16-bit equivalent of 24-bit color
909 uint16_t gray = drawRGB24toRGB565(0x33, 0x33, 0x33);
910
911 @endcode
912 */
913 /**************************************************************************/
914 uint16_t drawRGB24toRGB565(uint8_t r, uint8_t g, uint8_t b)
915 {
916 return ((r / 8) << 11) | ((g / 4) << 5) | (b / 8);
917 }
918
919 /**************************************************************************/
920 /*!
921 @brief Converts a 16-bit RGB565 color to a standard 32-bit BGRA32
922 color (with alpha set to 0xFF)
923
924 @param[in] color
925 16-bit rgb565 color
926
927 @section Example
928
929 @code
930
931 // First convert 24-bit color to RGB565
932 uint16_t rgb565 = drawRGB24toRGB565(0xFF, 0x00, 0x00);
933
934 // Convert RGB565 color back to BGRA32
935 uint32_t bgra32 = drawRGB565toBGRA32(rgb565);
936
937 // Display results
938 printf("BGRA32: 0x%08X R: %u G: %u B: %u A: %u \r\n",
939 bgra32,
940 (bgra32 & 0x000000FF), // Blue
941 (bgra32 & 0x0000FF00) >> 8, // Green
942 (bgra32 & 0x00FF0000) >> 16, // Red
943 (bgra32 & 0xFF000000) >> 24); // Alpha
944
945 @endcode
946 */
947 /**************************************************************************/
948 uint32_t drawRGB565toBGRA32(uint16_t color)
949 {
950 uint32_t bits = (uint32_t)color;
951 uint32_t blue = bits & 0x001F; // 5 bits blue
952 uint32_t green = bits & 0x07E0; // 6 bits green
953 uint32_t red = bits & 0xF800; // 5 bits red
954
955 // Return shifted bits with alpha set to 0xFF
956 return (red << 8) | (green << 5) | (blue << 3) | 0xFF000000;
957 }
958
959 /**************************************************************************/
960 /*!
961 @brief Reverses a 16-bit color from BGR to RGB
962 */
963 /**************************************************************************/
964 uint16_t drawBGR2RGB(uint16_t color)
965 {
966 uint16_t r, g, b;
967
968 b = (color>>0) & 0x1f;
969 g = (color>>5) & 0x3f;
970 r = (color>>11) & 0x1f;
971
972 return( (b<<11) + (g<<5) + (r<<0) );
973 }
974
975 /**************************************************************************/
976 /*!
977 @brief Draws a progress bar with rounded corners
978
979 @param[in] x
980 Starting x location
981 @param[in] y
982 Starting y location
983 @param[in] width
984 Total width of the progress bar in pixels
985 @param[in] height
986 Total height of the progress bar in pixels
987 @param[in] borderCorners
988 The type of rounded corners to render with the progress bar border
989 @param[in] progressCorners
990 The type of rounded corners to render with the inner progress bar
991 @param[in] borderColor
992 16-bit color for the outer border
993 @param[in] borderFillColor
994 16-bit color for the interior of the outer border
995 @param[in] progressBorderColor
996 16-bit color for the progress bar's border
997 @param[in] progressFillColor
998 16-bit color for the inner bar's fill
999 @param[in] progress
1000 Progress percentage (between 0 and 100)
1001
1002 @section Example
1003
1004 @code
1005 #include "drivers/lcd/tft/drawing.h"
1006
1007 // Draw a the progress bar (150x15 pixels large, starting at X:10, Y:195
1008 // with rounded corners on the top and showing 72% progress)
1009 drawProgressBar(10, 195, 150, 15, DRAW_ROUNDEDCORNERS_TOP, DRAW_ROUNDEDCORNERS_TOP, COLOR_DARKERGRAY, COLOR_DARKGRAY, COLOR_LIMEGREENDIM, COLOR_LIMEGREEN, 72 );
1010
1011 @endcode
1012 */
1013 /**************************************************************************/
1014 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 )
1015 {
1016 // Draw border with rounded corners
1017 drawRectangleRounded(x, y, x + width, y + height, borderColor, 5, borderCorners);
1018 drawRectangleRounded(x+1, y+1, x + width - 1, y + height - 1, borderFillColor, 5, borderCorners);
1019
1020 // Progress bar
1021 if (progress > 0 && progress <= 100)
1022 {
1023 // Calculate bar size
1024 uint16_t bw;
1025 bw = (width - 6); // bar at 100%
1026 if (progress != 100)
1027 {
1028 bw = (bw * progress) / 100;
1029 }
1030 drawRectangleRounded(x + 3, y + 3, bw + x + 3, y + height - 3, progressBorderColor, 5, progressCorners);
1031 drawRectangleRounded(x + 4, y + 4, bw + x + 3 - 1, y + height - 4, progressFillColor, 5, progressCorners);
1032 }
1033 }
1034
1035 /**************************************************************************/
1036 /*!
1037 @brief Draws a simple button
1038
1039 @param[in] x
1040 Starting x location
1041 @param[in] y
1042 Starting y location
1043 @param[in] width
1044 Total width of the button in pixels
1045 @param[in] height
1046 Total height of the button in pixels
1047 @param[in] fontInfo
1048 Pointer to the FONT_INFO used to render the button text
1049 @param[in] fontHeight
1050 The height in pixels of the font (used for centering)
1051 @param[in] borderclr
1052 The rgb565 border color
1053 @param[in] fillclr
1054 The rgb565 background color
1055 @param[in] fontclr
1056 The rgb565 font color
1057 @param[in] text
1058 The text to render on the button
1059
1060 @section Example
1061
1062 @code
1063
1064 #include "drivers/lcd/tft/drawing.h"
1065 #include "drivers/lcd/tft/fonts/dejavusansbold9.h"
1066
1067 // Draw two buttons using Vera Sans Bold 9
1068 drawButton(20, 195, 200, 35, &dejaVuSansBold9ptFontInfo, 7, COLOR_DARKERGRAY, COLOR_DARKERGRAY, COLOR_WHITE, "System Settings");
1069 drawButton(20, 235, 200, 35, &dejaVuSansBold9ptFontInfo, 7, COLOR_LIMEGREENDIM, COLOR_LIMEGREEN, COLOR_BLACK, "System Settings");
1070
1071 @endcode
1072 */
1073 /**************************************************************************/
1074 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)
1075 {
1076 uint16_t border, fill, font, activeborder, activefill, activefont;
1077
1078 // Set colors
1079 border = COLOR_GRAY_30;
1080 fill = COLOR_GRAY_30;
1081 font = COLOR_WHITE;
1082 activeborder = COLOR_THEME_DEFAULT_DARKER;
1083 activefill = COLOR_THEME_DEFAULT_BASE;
1084 activefont = COLOR_BLACK;
1085
1086 // Border
1087 drawRectangleRounded(x, y, x + width, y + height, borderclr, 5, DRAW_ROUNDEDCORNERS_ALL);
1088 // Fill
1089 drawRectangleRounded(x+2, y+2, x+width-2, y+height-2, fillclr, 5, DRAW_ROUNDEDCORNERS_ALL);
1090
1091 // Render text
1092 if (text != NULL)
1093 {
1094 uint16_t textWidth = drawGetStringWidth(&*fontInfo, text);
1095 uint16_t xStart = x + (width / 2) - (textWidth / 2);
1096 uint16_t yStart = y + (height / 2) - (fontHeight / 2) + 1;
1097 drawString(xStart, yStart, fontclr, &*fontInfo, text);
1098 }
1099 }
1100
1101 /**************************************************************************/
1102 /*!
1103 @brief Renders a 16x16 monochrome icon using the supplied uint16_t
1104 array.
1105
1106 @param[in] x
1107 The horizontal location to start rendering from
1108 @param[in] x
1109 The vertical location to start rendering from
1110 @param[in] color
1111 The RGB565 color to use when rendering the icon
1112 @param[in] icon
1113 The uint16_t array containing the 16x16 image data
1114
1115 @section Example
1116
1117 @code
1118
1119 #include "drivers/lcd/tft/drawing.h"
1120 #include "drivers/lcd/icons16.h"
1121
1122 // Renders the info icon, which has two seperate parts ... the exterior
1123 // and a seperate interior mask if you want to fill the contents with a
1124 // different color
1125 drawIcon16(132, 202, COLOR_BLUE, icons16_info);
1126 drawIcon16(132, 202, COLOR_WHITE, icons16_info_interior);
1127
1128 @endcode
1129 */
1130 /**************************************************************************/
1131 void drawIcon16(uint16_t x, uint16_t y, uint16_t color, uint16_t icon[])
1132 {
1133 int i;
1134 for (i = 0; i<16; i++)
1135 {
1136 if (icon[i] & (0X8000)) drawPixel(x, y+i, color);
1137 if (icon[i] & (0X4000)) drawPixel(x+1, y+i, color);
1138 if (icon[i] & (0X2000)) drawPixel(x+2, y+i, color);
1139 if (icon[i] & (0X1000)) drawPixel(x+3, y+i, color);
1140 if (icon[i] & (0X0800)) drawPixel(x+4, y+i, color);
1141 if (icon[i] & (0X0400)) drawPixel(x+5, y+i, color);
1142 if (icon[i] & (0X0200)) drawPixel(x+6, y+i, color);
1143 if (icon[i] & (0X0100)) drawPixel(x+7, y+i, color);
1144 if (icon[i] & (0X0080)) drawPixel(x+8, y+i, color);
1145 if (icon[i] & (0x0040)) drawPixel(x+9, y+i, color);
1146 if (icon[i] & (0X0020)) drawPixel(x+10, y+i, color);
1147 if (icon[i] & (0X0010)) drawPixel(x+11, y+i, color);
1148 if (icon[i] & (0X0008)) drawPixel(x+12, y+i, color);
1149 if (icon[i] & (0X0004)) drawPixel(x+13, y+i, color);
1150 if (icon[i] & (0X0002)) drawPixel(x+14, y+i, color);
1151 if (icon[i] & (0X0001)) drawPixel(x+15, y+i, color);
1152 }
1153 }
1154
1155 #ifdef CFG_SDCARD
1156 /**************************************************************************/
1157 /*!
1158 @brief Loads a 24-bit Windows bitmap image from an SD card and
1159 renders it
1160
1161 @section Example
1162
1163 @code
1164
1165 #include "drivers/lcd/tft/drawing.h"
1166
1167 // Draw image.bmp (from the root folder) starting at pixel 0,0
1168 bmp_error_t error = drawBitmapImage(0, 0, "/image.bmp");
1169
1170 if (error)
1171 {
1172 switch (error)
1173 {
1174 case BMP_ERROR_SDINITFAIL:
1175 break;
1176 case BMP_ERROR_FILENOTFOUND:
1177 break;
1178 case BMP_ERROR_NOTABITMAP:
1179 // First two bytes of image not 'BM'
1180 break;
1181 case BMP_ERROR_INVALIDBITDEPTH:
1182 // Image is not 24-bits
1183 break;
1184 case BMP_ERROR_COMPRESSEDDATA:
1185 // Image contains compressed data
1186 break;
1187 case BMP_ERROR_INVALIDDIMENSIONS:
1188 // Width or Height is > LCD size
1189 break;
1190 case BMP_ERROR_PREMATUREEOF:
1191 // EOF unexpectedly reached in pixel data
1192 break;
1193 }
1194 }
1195
1196 @endcode
1197 */
1198 /**************************************************************************/
1199 bmp_error_t drawBitmapImage(uint16_t x, uint16_t y, char *filename)
1200 {
1201 return bmpDrawBitmap(x, y, filename);
1202 }
1203
1204 #endif
This page took 0.132008 seconds and 5 git commands to generate.