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