Added SSD1331_COLORORDER_RGB/BGR flag
[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 Swaps values a and b
59 */
60 /**************************************************************************/
61 void drawSwap(uint32_t a, uint32_t b)
62 {
63 uint32_t t;
64 t = a;
65 a = b;
66 b = t;
67 }
68
69 /**************************************************************************/
70 /*!
71 @brief Draws a single bitmap character
72 */
73 /**************************************************************************/
74 void drawCharBitmap(const uint16_t xPixel, const uint16_t yPixel, uint16_t color, const char *glyph, uint8_t cols, uint8_t rows)
75 {
76 uint16_t currentY, currentX, indexIntoGlyph;
77 uint16_t _row, _col, _colPages;
78
79 // set initial current y
80 currentY = yPixel;
81 currentX = xPixel;
82
83 // Figure out how many columns worth of data we have
84 if (cols % 8)
85 _colPages = cols / 8 + 1;
86 else
87 _colPages = cols / 8;
88
89 for (_row = 0; _row < rows; _row++)
90 {
91 for (_col = 0; _col < _colPages; _col++)
92 {
93 if (_row == 0)
94 indexIntoGlyph = _col;
95 else
96 indexIntoGlyph = (_row * _colPages) + _col;
97
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);
109 }
110 }
111 }
112
113 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
114 /**************************************************************************/
115 /*!
116 @brief Draws a single smallfont character
117 */
118 /**************************************************************************/
119 void drawCharSmall(uint16_t x, uint16_t y, uint16_t color, uint8_t c, struct FONT_DEF font)
120 {
121 uint8_t col, column[font.u8Width];
122
123 // Check if the requested character is available
124 if ((c >= font.u8FirstChar) && (c <= font.u8LastChar))
125 {
126 // Retrieve appropriate columns from font data
127 for (col = 0; col < font.u8Width; col++)
128 {
129 column[col] = font.au8FontTable[((c - 32) * font.u8Width) + col]; // Get first column of appropriate character
130 }
131 }
132 else
133 {
134 // Requested character is not available in this font ... send a space instead
135 for (col = 0; col < font.u8Width; col++)
136 {
137 column[col] = 0xFF; // Send solid space
138 }
139 }
140
141 // Render each column
142 uint16_t xoffset, yoffset;
143 for (xoffset = 0; xoffset < font.u8Width; xoffset++)
144 {
145 for (yoffset = 0; yoffset < (font.u8Height + 1); yoffset++)
146 {
147 uint8_t bit = 0x00;
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)
150 if (bit)
151 {
152 drawPixel(x + xoffset, y + yoffset, color);
153 }
154 }
155 }
156 }
157 #endif
158
159 /**************************************************************************/
160 /*!
161 @brief Helper method to accurately draw individual circle points
162 */
163 /**************************************************************************/
164 void drawCirclePoints(int cx, int cy, int x, int y, uint16_t color)
165 {
166 if (x == 0)
167 {
168 drawPixel(cx, cy + y, color);
169 drawPixel(cx, cy - y, color);
170 drawPixel(cx + y, cy, color);
171 drawPixel(cx - y, cy, color);
172 }
173 else if (x == y)
174 {
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);
179 }
180 else if (x < y)
181 {
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);
190 }
191 }
192
193 /**************************************************************************/
194 /* */
195 /* ----------------------- Public Methods ------------------------------- */
196 /* */
197 /**************************************************************************/
198
199 /**************************************************************************/
200 /*!
201 @brief Draws a single pixel at the specified location
202
203 @param[in] x
204 Horizontal position
205 @param[in] y
206 Vertical position
207 @param[in] color
208 Color used when drawing
209 */
210 /**************************************************************************/
211 void drawPixel(uint16_t x, uint16_t y, uint16_t color)
212 {
213 if ((x >= lcdGetWidth()) || (y >= lcdGetHeight()))
214 {
215 // Pixel out of range
216 return;
217 }
218
219 // Redirect to LCD
220 lcdDrawPixel(x, y, color);
221 }
222
223 /**************************************************************************/
224 /*!
225 @brief Fills the screen with the specified color
226
227 @param[in] color
228 Color used when drawing
229 */
230 /**************************************************************************/
231 void drawFill(uint16_t color)
232 {
233 lcdFillRGB(color);
234 }
235
236 /**************************************************************************/
237 /*!
238 @brief Draws a simple color test pattern
239 */
240 /**************************************************************************/
241 void drawTestPattern(void)
242 {
243 lcdTest();
244 }
245
246 #if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
247 /**************************************************************************/
248 /*!
249 @brief Draws a string using a small font (6 of 8 pixels high).
250
251 @param[in] x
252 Starting x co-ordinate
253 @param[in] y
254 Starting y co-ordinate
255 @param[in] color
256 Color to use when rendering the font
257 @param[in] text
258 The string to render
259 @param[in] font
260 Pointer to the FONT_DEF to use when drawing the string
261
262 @section Example
263
264 @code
265
266 #include "drivers/lcd/fonts/smallfonts.h"
267
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);
270
271 @endcode
272 */
273 /**************************************************************************/
274 void drawStringSmall(uint16_t x, uint16_t y, uint16_t color, char* text, struct FONT_DEF font)
275 {
276 uint8_t l;
277 for (l = 0; l < strlen(text); l++)
278 {
279 drawCharSmall(x + (l * (font.u8Width + 1)), y, color, text[l], font);
280 }
281 }
282 #endif
283
284 /**************************************************************************/
285 /*!
286 @brief Draws a string using the supplied font
287
288 @param[in] x
289 Starting x co-ordinate
290 @param[in] y
291 Starting y co-ordinate
292 @param[in] color
293 Color to use when rendering the font
294 @param[in] fontInfo
295 Pointer to the FONT_INFO to use when drawing the string
296 @param[in] str
297 The string to render
298
299 @section Example
300
301 @code
302
303 #include "drivers/lcd/tft/fonts/veramono9.h"
304
305 drawString(0, 90, COLOR_BLACK, &bitstreamVeraSansMono9ptFontInfo, "Vera Mono 9 (30 chars wide)");
306 drawString(0, 105, COLOR_BLACK, &bitstreamVeraSansMono9ptFontInfo, "123456789012345678901234567890");
307
308 @endcode
309 */
310 /**************************************************************************/
311 void drawString(uint16_t x, uint16_t y, uint16_t color, const FONT_INFO *fontInfo, char *str)
312 {
313 uint16_t currentX, charWidth, characterToOutput;
314 const FONT_CHAR_INFO *charInfo;
315 uint16_t charOffset;
316
317 // set current x, y to that of requested
318 currentX = x;
319
320 // while not NULL
321 while (*str != '\0')
322 {
323 // get character to output
324 characterToOutput = *str;
325
326 // get char info
327 charInfo = fontInfo->charInfo;
328
329 // some fonts have character descriptors, some don't
330 if (charInfo != NULL)
331 {
332 // get correct char offset
333 charInfo += (characterToOutput - fontInfo->startChar);
334
335 // get width from char info
336 charWidth = charInfo->widthBits;
337
338 // get offset from char info
339 charOffset = charInfo->offset;
340 }
341 else
342 {
343 // if no char info, char width is always 5
344 charWidth = 5;
345
346 // char offset - assume 5 * letter offset
347 charOffset = (characterToOutput - fontInfo->startChar) * 5;
348 }
349
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);
354
355 // next char X
356 currentX += charWidth + 1;
357
358 // next char
359 str++;
360 }
361 }
362
363 /**************************************************************************/
364 /*!
365 @brief Returns the width in pixels of a string when it is rendered
366
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.
370
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
374 this one.
375
376 @param[in] fontInfo
377 Pointer to the FONT_INFO for the font that will be used
378 @param[in] str
379 The string that will be rendered
380 */
381 /**************************************************************************/
382 uint16_t drawGetStringWidth(const FONT_INFO *fontInfo, char *str)
383 {
384 uint16_t width = 0;
385 uint32_t currChar;
386 uint32_t startChar = fontInfo->startChar;
387
388 // until termination
389 for (currChar = *str; currChar; currChar = *(++str))
390 {
391 // if char info exists for the font, use width from there
392 if (fontInfo->charInfo != NULL)
393 {
394 width += fontInfo->charInfo[currChar - startChar].widthBits + 1;
395 }
396 else
397 {
398 width += 5 + 1;
399 }
400 }
401
402 /* return the width */
403 return width > 0 ? width - 1 : width;
404 }
405
406 /**************************************************************************/
407 /*!
408 @brief Draws a bresenham line
409
410 @param[in] x0
411 Starting x co-ordinate
412 @param[in] y0
413 Starting y co-ordinate
414 @param[in] x1
415 Ending x co-ordinate
416 @param[in] y1
417 Ending y co-ordinate
418 @param[in] color
419 Color used when drawing
420 */
421 /**************************************************************************/
422 void drawLine ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color )
423 {
424 drawLineDotted(x0, y0, x1, y1, 0, 1, color);
425 }
426
427 /**************************************************************************/
428 /*!
429 @brief Draws a bresenham line with a fixed pattern of empty
430 and solid pixels
431
432 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
433
434 @param[in] x0
435 Starting x co-ordinate
436 @param[in] y0
437 Starting y co-ordinate
438 @param[in] x1
439 Ending x co-ordinate
440 @param[in] y1
441 Ending y co-ordinate
442 @param[in] empty
443 The number of 'empty' pixels to render
444 @param[in] solid
445 The number of 'solid' pixels to render
446 @param[in] color
447 Color used when drawing
448 */
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 )
451 {
452 if (solid == 0)
453 {
454 return;
455 }
456
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;
462
463 // Check if we can use the optimised horizontal line method
464 if ((y0 == y1) && (empty == 0))
465 {
466 lcdDrawHLine(x0, x1, y0, color);
467 return;
468 }
469
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))
474 {
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);
479 return;
480 }
481
482 // Draw non-horizontal or dotted line
483 int dy = y1 - y0;
484 int dx = x1 - x0;
485 int stepx, stepy;
486 int emptycount, solidcount;
487
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
492
493 emptycount = empty;
494 solidcount = solid;
495
496 drawPixel(x0, y0, color); // always start with solid pixels
497 solidcount--;
498 if (dx > dy)
499 {
500 int fraction = dy - (dx >> 1); // same as 2*dy - dx
501 while (x0 != x1)
502 {
503 if (fraction >= 0)
504 {
505 y0 += stepy;
506 fraction -= dx; // same as fraction -= 2*dx
507 }
508 x0 += stepx;
509 fraction += dy; // same as fraction -= 2*dy
510 if (empty == 0)
511 {
512 // always draw a pixel ... no dotted line requested
513 drawPixel(x0, y0, color);
514 }
515 else if (solidcount)
516 {
517 // Draw solid pxiel and decrement counter
518 drawPixel(x0, y0, color);
519 solidcount--;
520 }
521 else if(emptycount)
522 {
523 // Empty pixel ... don't draw anything an decrement counter
524 emptycount--;
525 }
526 else
527 {
528 // Reset counters and draw solid pixel
529 emptycount = empty;
530 solidcount = solid;
531 drawPixel(x0, y0, color);
532 solidcount--;
533 }
534 }
535 }
536 else
537 {
538 int fraction = dx - (dy >> 1);
539 while (y0 != y1)
540 {
541 if (fraction >= 0)
542 {
543 x0 += stepx;
544 fraction -= dy;
545 }
546 y0 += stepy;
547 fraction += dx;
548 if (empty == 0)
549 {
550 // always draw a pixel ... no dotted line requested
551 drawPixel(x0, y0, color);
552 }
553 if (solidcount)
554 {
555 // Draw solid pxiel and decrement counter
556 drawPixel(x0, y0, color);
557 solidcount--;
558 }
559 else if(emptycount)
560 {
561 // Empty pixel ... don't draw anything an decrement counter
562 emptycount--;
563 }
564 else
565 {
566 // Reset counters and draw solid pixel
567 emptycount = empty;
568 solidcount = solid;
569 drawPixel(x0, y0, color);
570 solidcount--;
571 }
572 }
573 }
574 }
575
576 /**************************************************************************/
577 /*!
578 @brief Draws a circle
579
580 Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture7/circle.html
581
582 @param[in] xCenter
583 The horizontal center of the circle
584 @param[in] yCenter
585 The vertical center of the circle
586 @param[in] radius
587 The circle's radius in pixels
588 @param[in] color
589 Color used when drawing
590 */
591 /**************************************************************************/
592 void drawCircle (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint16_t color)
593 {
594 int x = 0;
595 int y = radius;
596 int p = (5 - radius*4)/4;
597
598 drawCirclePoints(xCenter, yCenter, x, y, color);
599 while (x < y)
600 {
601 x++;
602 if (p < 0)
603 {
604 p += 2*x+1;
605 }
606 else
607 {
608 y--;
609 p += 2*(x-y)+1;
610 }
611 drawCirclePoints(xCenter, yCenter, x, y, color);
612 }
613 }
614
615 /**************************************************************************/
616 /*!
617 @brief Draws a filled circle
618
619 @param[in] xCenter
620 The horizontal center of the circle
621 @param[in] yCenter
622 The vertical center of the circle
623 @param[in] radius
624 The circle's radius in pixels
625 @param[in] color
626 Color used when drawing
627 */
628 /**************************************************************************/
629 void drawCircleFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint16_t color)
630 {
631 int16_t f = 1 - radius;
632 int16_t ddF_x = 1;
633 int16_t ddF_y = -2 * radius;
634 int16_t x = 0;
635 int16_t y = radius;
636 int16_t xc_px, yc_my, xc_mx, xc_py, yc_mx, xc_my;
637 int16_t lcdWidth = lcdGetWidth();
638
639 if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter-radius, xCenter, (yCenter-radius) + (2*radius), color);
640
641 while (x<y)
642 {
643 if (f >= 0)
644 {
645 y--;
646 ddF_y += 2;
647 f += ddF_y;
648 }
649 x++;
650 ddF_x += 2;
651 f += ddF_x;
652
653 xc_px = xCenter+x;
654 xc_mx = xCenter-x;
655 xc_py = xCenter+y;
656 xc_my = xCenter-y;
657 yc_mx = yCenter-x;
658 yc_my = yCenter-y;
659
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);
666 }
667 }
668
669 /**************************************************************************/
670 /*!
671 @brief Draws a filled rounded corner
672
673 @param[in] xCenter
674 The horizontal center of the circle
675 @param[in] yCenter
676 The vertical center of the circle
677 @param[in] radius
678 The circle's radius in pixels
679 @param[in] position
680 The position of the corner, which affects how it will
681 be rendered
682 @param[in] color
683 Color used when drawing
684 */
685 /**************************************************************************/
686 void drawCornerFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, drawCornerPosition_t position, uint16_t color)
687 {
688 int16_t f = 1 - radius;
689 int16_t ddF_x = 1;
690 int16_t ddF_y = -2 * radius;
691 int16_t x = 0;
692 int16_t y = radius;
693 int16_t xc_px, yc_my, xc_mx, xc_py, yc_mx, xc_my;
694 int16_t lcdWidth = lcdGetWidth();
695
696 switch (position)
697 {
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);
701 break;
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);
705 break;
706 }
707
708 while (x<y)
709 {
710 if (f >= 0)
711 {
712 y--;
713 ddF_y += 2;
714 f += ddF_y;
715 }
716 x++;
717 ddF_x += 2;
718 f += ddF_x;
719
720 xc_px = xCenter+x;
721 xc_mx = xCenter-x;
722 xc_py = xCenter+y;
723 xc_my = xCenter-y;
724 yc_mx = yCenter-x;
725 yc_my = yCenter-y;
726
727 switch (position)
728 {
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);
732 break;
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);
736 break;
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);
740 break;
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);
744 break;
745 }
746 }
747 }
748
749 /**************************************************************************/
750 /*!
751 @brief Draws a simple arrow of the specified width
752
753 @param[in] x
754 X co-ordinate of the smallest point of the arrow
755 @param[in] y
756 Y co-ordinate of the smallest point of the arrow
757 @param[in] size
758 Total width/height of the arrow in pixels
759 @param[in] direction
760 The direction that the arrow is pointing
761 @param[in] color
762 Color used when drawing
763 */
764 /**************************************************************************/
765 void drawArrow(uint16_t x, uint16_t y, uint16_t size, drawDirection_t direction, uint16_t color)
766 {
767 drawPixel(x, y, color);
768
769 if (size == 1)
770 {
771 return;
772 }
773
774 uint32_t i;
775 switch (direction)
776 {
777 case DRAW_DIRECTION_LEFT:
778 for (i = 1; i<size; i++)
779 {
780 drawLine(x+i, y-i, x+i, y+i, color);
781 }
782 break;
783 case DRAW_DIRECTION_RIGHT:
784 for (i = 1; i<size; i++)
785 {
786 drawLine(x-i, y-i, x-i, y+i, color);
787 }
788 break;
789 case DRAW_DIRECTION_UP:
790 for (i = 1; i<size; i++)
791 {
792 drawLine(x-i, y+i, x+i, y+i, color);
793 }
794 break;
795 case DRAW_DIRECTION_DOWN:
796 for (i = 1; i<size; i++)
797 {
798 drawLine(x-i, y-i, x+i, y-i, color);
799 }
800 break;
801 default:
802 break;
803 }
804 }
805
806 /**************************************************************************/
807 /*!
808 @brief Draws a simple (empty) rectangle
809
810 @param[in] x0
811 Starting x co-ordinate
812 @param[in] y0
813 Starting y co-ordinate
814 @param[in] x1
815 Ending x co-ordinate
816 @param[in] y1
817 Ending y co-ordinate
818 @param[in] color
819 Color used when drawing
820 */
821 /**************************************************************************/
822 void drawRectangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
823 {
824 uint16_t x, y;
825
826 if (y1 < y0)
827 {
828 // Switch y1 and y0
829 y = y1;
830 y1 = y0;
831 y0 = y;
832 }
833
834 if (x1 < x0)
835 {
836 // Switch x1 and x0
837 x = x1;
838 x1 = x0;
839 x0 = x;
840 }
841
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);
846 }
847
848 /**************************************************************************/
849 /*!
850 @brief Draws a filled rectangle
851
852 @param[in] x0
853 Starting x co-ordinate
854 @param[in] y0
855 Starting y co-ordinate
856 @param[in] x1
857 Ending x co-ordinate
858 @param[in] y1
859 Ending y co-ordinate
860 @param[in] color
861 Color used when drawing
862 */
863 /**************************************************************************/
864 void drawRectangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
865 {
866 int height;
867 uint16_t x, y;
868
869 if (y1 < y0)
870 {
871 // Switch y1 and y0
872 y = y1;
873 y1 = y0;
874 y0 = y;
875 }
876
877 if (x1 < x0)
878 {
879 // Switch x1 and x0
880 x = x1;
881 x1 = x0;
882 x0 = x;
883 }
884
885 height = y1 - y0;
886 for (height = y0; y1 > height - 1; ++height)
887 {
888 drawLine(x0, height, x1, height, color);
889 }
890 }
891
892 /**************************************************************************/
893 /*!
894 @brief Draws a filled rectangle with rounded corners
895
896 @param[in] x0
897 Starting x co-ordinate
898 @param[in] y0
899 Starting y co-ordinate
900 @param[in] x1
901 Ending x co-ordinate
902 @param[in] y1
903 Ending y co-ordinate
904 @param[in] color
905 Color used when drawing
906 @param[in] radius
907 Corner radius in pixels
908 @param[in] corners
909 Which corners to round
910 */
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 )
913 {
914 int height;
915 uint16_t y;
916
917 if (corners == DRAW_ROUNDEDCORNERS_NONE)
918 {
919 drawRectangleFilled(x0, y0, x1, y1, color);
920 return;
921 }
922
923 // Calculate height
924 if (y1 < y0)
925 {
926 y = y1;
927 y1 = y0;
928 y0 = y;
929 }
930 height = y1 - y0;
931
932 // Check radius
933 if (radius > height / 2)
934 {
935 radius = height / 2;
936 }
937 radius -= 1;
938
939 // Draw body
940 drawRectangleFilled(x0 + radius, y0, x1 - radius, y1, color);
941
942 switch (corners)
943 {
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)
950 {
951 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
952 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
953 }
954 break;
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);
960 break;
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);
966 break;
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)
971 {
972 drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
973 }
974 drawRectangleFilled(x1 - radius, y0, x1, y1, color);
975 break;
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)
980 {
981 drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
982 }
983 drawRectangleFilled(x0, y0, x0 + radius, y1, color);
984 break;
985 default:
986 break;
987 }
988 }
989
990 /**************************************************************************/
991 /*!
992 @brief Draws a triangle
993
994 @param[in] x0
995 x co-ordinate for point 0
996 @param[in] y0
997 y co-ordinate for point 0
998 @param[in] x1
999 x co-ordinate for point 1
1000 @param[in] y1
1001 y co-ordinate for point 1
1002 @param[in] x2
1003 x co-ordinate for point 2
1004 @param[in] y2
1005 y co-ordinate for point 2
1006 @param[in] color
1007 Color used when drawing
1008 */
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)
1011 {
1012 drawLine(x0, y0, x1, y1, color);
1013 drawLine(x1, y1, x2, y2, color);
1014 drawLine(x2, y2, x0, y0, color);
1015 }
1016
1017 /**************************************************************************/
1018 /*!
1019 @brief Draws a filled triangle
1020
1021 @param[in] x0
1022 x co-ordinate for point 0
1023 @param[in] y0
1024 y co-ordinate for point 0
1025 @param[in] x1
1026 x co-ordinate for point 1
1027 @param[in] y1
1028 y co-ordinate for point 1
1029 @param[in] x2
1030 x co-ordinate for point 2
1031 @param[in] y2
1032 y co-ordinate for point 2
1033 @param[in] color
1034 Fill color
1035
1036 @section Example
1037
1038 @code
1039
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);
1046
1047 @endcode
1048 */
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)
1051 {
1052 // Re-order vertices by ascending Y values (smallest first)
1053 if (y0 > y1) {
1054 drawSwap(y0, y1); drawSwap(x0, x1);
1055 }
1056 if (y1 > y2) {
1057 drawSwap(y2, y1); drawSwap(x2, x1);
1058 }
1059 if (y0 > y1) {
1060 drawSwap(y0, y1); drawSwap(x0, x1);
1061 }
1062
1063 int32_t dx1, dx2, dx3; // Interpolation deltas
1064 int32_t sx1, sx2, sy; // Scanline co-ordinates
1065
1066 sx1=sx2=x0 * 1000; // Use fixed point math for x axis values
1067 sy=y0;
1068
1069 // Calculate interpolation deltas
1070 if (y1-y0 > 0) dx1=((x1-x0)*1000)/(y1-y0);
1071 else dx1=0;
1072 if (y2-y0 > 0) dx2=((x2-x0)*1000)/(y2-y0);
1073 else dx2=0;
1074 if (y2-y1 > 0) dx3=((x2-x1)*1000)/(y2-y1);
1075 else dx3=0;
1076
1077 // Render scanlines (horizontal lines are the fastest rendering method)
1078 if (dx1 > dx2)
1079 {
1080 for(; sy<=y1; sy++, sx1+=dx2, sx2+=dx1)
1081 {
1082 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1083 }
1084 sx2 = x1*1000;
1085 sy = y1;
1086 for(; sy<=y2; sy++, sx1+=dx2, sx2+=dx3)
1087 {
1088 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1089 }
1090 }
1091 else
1092 {
1093 for(; sy<=y1; sy++, sx1+=dx1, sx2+=dx2)
1094 {
1095 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1096 }
1097 sx1 = x1*1000;
1098 sy = y1;
1099 for(; sy<=y2; sy++, sx1+=dx3, sx2+=dx2)
1100 {
1101 drawLine(sx1/1000, sy, sx2/1000, sy, color);
1102 }
1103 }
1104 }
1105
1106 /**************************************************************************/
1107 /*!
1108 @brief Converts a 24-bit RGB color to an equivalent 16-bit RGB565 value
1109
1110 @param[in] r
1111 8-bit red
1112 @param[in] g
1113 8-bit green
1114 @param[in] b
1115 8-bit blue
1116
1117 @section Example
1118
1119 @code
1120
1121 // Get 16-bit equivalent of 24-bit color
1122 uint16_t gray = drawRGB24toRGB565(0x33, 0x33, 0x33);
1123
1124 @endcode
1125 */
1126 /**************************************************************************/
1127 uint16_t drawRGB24toRGB565(uint8_t r, uint8_t g, uint8_t b)
1128 {
1129 return ((r / 8) << 11) | ((g / 4) << 5) | (b / 8);
1130 }
1131
1132 /**************************************************************************/
1133 /*!
1134 @brief Converts a 16-bit RGB565 color to a standard 32-bit BGRA32
1135 color (with alpha set to 0xFF)
1136
1137 @param[in] color
1138 16-bit rgb565 color
1139
1140 @section Example
1141
1142 @code
1143
1144 // First convert 24-bit color to RGB565
1145 uint16_t rgb565 = drawRGB24toRGB565(0xFF, 0x00, 0x00);
1146
1147 // Convert RGB565 color back to BGRA32
1148 uint32_t bgra32 = drawRGB565toBGRA32(rgb565);
1149
1150 // Display results
1151 printf("BGRA32: 0x%08X R: %u G: %u B: %u A: %u \r\n",
1152 bgra32,
1153 (bgra32 & 0x000000FF), // Blue
1154 (bgra32 & 0x0000FF00) >> 8, // Green
1155 (bgra32 & 0x00FF0000) >> 16, // Red
1156 (bgra32 & 0xFF000000) >> 24); // Alpha
1157
1158 @endcode
1159 */
1160 /**************************************************************************/
1161 uint32_t drawRGB565toBGRA32(uint16_t color)
1162 {
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
1167
1168 // Return shifted bits with alpha set to 0xFF
1169 return (red << 8) | (green << 5) | (blue << 3) | 0xFF000000;
1170 }
1171
1172 /**************************************************************************/
1173 /*!
1174 @brief Reverses a 16-bit color from BGR to RGB
1175 */
1176 /**************************************************************************/
1177 uint16_t drawBGR2RGB(uint16_t color)
1178 {
1179 uint16_t r, g, b;
1180
1181 b = (color>>0) & 0x1f;
1182 g = (color>>5) & 0x3f;
1183 r = (color>>11) & 0x1f;
1184
1185 return( (b<<11) + (g<<5) + (r<<0) );
1186 }
1187
1188 /**************************************************************************/
1189 /*!
1190 @brief Draws a progress bar with rounded corners
1191
1192 @param[in] x
1193 Starting x location
1194 @param[in] y
1195 Starting y location
1196 @param[in] width
1197 Total width of the progress bar in pixels
1198 @param[in] height
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
1212 @param[in] progress
1213 Progress percentage (between 0 and 100)
1214
1215 @section Example
1216
1217 @code
1218 #include "drivers/lcd/tft/drawing.h"
1219
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 );
1223
1224 @endcode
1225 */
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 )
1228 {
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);
1232
1233 // Progress bar
1234 if (progress > 0 && progress <= 100)
1235 {
1236 // Calculate bar size
1237 uint16_t bw;
1238 bw = (width - 6); // bar at 100%
1239 if (progress != 100)
1240 {
1241 bw = (bw * progress) / 100;
1242 }
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);
1245 }
1246 }
1247
1248 /**************************************************************************/
1249 /*!
1250 @brief Draws a simple button
1251
1252 @param[in] x
1253 Starting x location
1254 @param[in] y
1255 Starting y location
1256 @param[in] width
1257 Total width of the button in pixels
1258 @param[in] height
1259 Total height of the button in pixels
1260 @param[in] fontInfo
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
1266 @param[in] fillclr
1267 The rgb565 background color
1268 @param[in] fontclr
1269 The rgb565 font color
1270 @param[in] text
1271 The text to render on the button
1272
1273 @section Example
1274
1275 @code
1276
1277 #include "drivers/lcd/tft/drawing.h"
1278 #include "drivers/lcd/tft/fonts/dejavusans9.h"
1279
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");
1283
1284 @endcode
1285 */
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)
1288 {
1289 // Border
1290 drawRectangleRounded(x, y, x + width, y + height, borderclr, 5, DRAW_ROUNDEDCORNERS_ALL);
1291 // Fill
1292 drawRectangleRounded(x+2, y+2, x+width-2, y+height-2, fillclr, 5, DRAW_ROUNDEDCORNERS_ALL);
1293
1294 // Render text
1295 if (text != NULL)
1296 {
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);
1301 }
1302 }
1303
1304 /**************************************************************************/
1305 /*!
1306 @brief Renders a 16x16 monochrome icon using the supplied uint16_t
1307 array.
1308
1309 @param[in] x
1310 The horizontal location to start rendering from
1311 @param[in] x
1312 The vertical location to start rendering from
1313 @param[in] color
1314 The RGB565 color to use when rendering the icon
1315 @param[in] icon
1316 The uint16_t array containing the 16x16 image data
1317
1318 @section Example
1319
1320 @code
1321
1322 #include "drivers/lcd/tft/drawing.h"
1323 #include "drivers/lcd/icons16.h"
1324
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
1327 // different color
1328 drawIcon16(132, 202, COLOR_BLUE, icons16_info);
1329 drawIcon16(132, 202, COLOR_WHITE, icons16_info_interior);
1330
1331 @endcode
1332 */
1333 /**************************************************************************/
1334 void drawIcon16(uint16_t x, uint16_t y, uint16_t color, uint16_t icon[])
1335 {
1336 int i;
1337 for (i = 0; i<16; i++)
1338 {
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);
1355 }
1356 }
1357
1358 #ifdef CFG_SDCARD
1359 /**************************************************************************/
1360 /*!
1361 @brief Loads a 24-bit Windows bitmap image from an SD card and
1362 renders it
1363
1364 @section Example
1365
1366 @code
1367
1368 #include "drivers/lcd/tft/drawing.h"
1369
1370 // Draw image.bmp (from the root folder) starting at pixel 0,0
1371 bmp_error_t error = drawBitmapImage(0, 0, "/image.bmp");
1372
1373 if (error)
1374 {
1375 switch (error)
1376 {
1377 case BMP_ERROR_SDINITFAIL:
1378 break;
1379 case BMP_ERROR_FILENOTFOUND:
1380 break;
1381 case BMP_ERROR_NOTABITMAP:
1382 // First two bytes of image not 'BM'
1383 break;
1384 case BMP_ERROR_INVALIDBITDEPTH:
1385 // Image is not 24-bits
1386 break;
1387 case BMP_ERROR_COMPRESSEDDATA:
1388 // Image contains compressed data
1389 break;
1390 case BMP_ERROR_INVALIDDIMENSIONS:
1391 // Width or Height is > LCD size
1392 break;
1393 case BMP_ERROR_PREMATUREEOF:
1394 // EOF unexpectedly reached in pixel data
1395 break;
1396 }
1397 }
1398
1399 @endcode
1400 */
1401 /**************************************************************************/
1402 bmp_error_t drawBitmapImage(uint16_t x, uint16_t y, char *filename)
1403 {
1404 return bmpDrawBitmap(x, y, filename);
1405 }
1406
1407 #endif
This page took 0.158958 seconds and 5 git commands to generate.