See changelog v0.9.8
[hackover2013-badge-firmware.git] / drivers / displays / tft / drawing.c
diff --git a/drivers/displays/tft/drawing.c b/drivers/displays/tft/drawing.c
new file mode 100644 (file)
index 0000000..5e1f0e9
--- /dev/null
@@ -0,0 +1,1407 @@
+/**************************************************************************/
+/*! 
+    @file     drawing.c
+    @author   K. Townsend (microBuilder.eu)
+
+    drawLine and drawCircle adapted from a tutorial by Leonard McMillan:
+    http://www.cs.unc.edu/~mcmillan/
+
+    drawString based on an example from Eran Duchan:
+    http://www.pavius.net/downloads/tools/53-the-dot-factory
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2010, microBuilder SARL
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#include <string.h>
+
+#include "drawing.h"
+
+#ifdef CFG_SDCARD
+  #include "bmp.h"
+#endif
+
+/**************************************************************************/
+/*                                                                        */
+/* ----------------------- Private Methods ------------------------------ */
+/*                                                                        */
+/**************************************************************************/
+
+/**************************************************************************/
+/*!
+    @brief  Swaps values a and b
+*/
+/**************************************************************************/
+void drawSwap(uint32_t a, uint32_t b)
+{
+  uint32_t t;
+  t = a;
+  a = b;
+  b = t;
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a single bitmap character
+*/
+/**************************************************************************/
+void drawCharBitmap(const uint16_t xPixel, const uint16_t yPixel, uint16_t color, const char *glyph, uint8_t cols, uint8_t rows)
+{
+  uint16_t currentY, currentX, indexIntoGlyph;
+  uint16_t _row, _col, _colPages;
+
+  // set initial current y
+  currentY = yPixel;
+  currentX = xPixel;
+
+  // Figure out how many columns worth of data we have
+  if (cols % 8)
+    _colPages = cols / 8 + 1;
+  else
+    _colPages = cols / 8;
+
+  for (_row = 0; _row < rows; _row++)
+  {
+    for (_col = 0; _col < _colPages; _col++)
+    {
+      if (_row == 0)
+        indexIntoGlyph = _col;
+      else
+        indexIntoGlyph = (_row * _colPages) + _col;
+
+      currentY = yPixel + _row;
+      currentX = xPixel + (_col*8);
+      // send the data byte
+      if (glyph[indexIntoGlyph] & (0X80)) drawPixel(currentX, currentY, color);
+      if (glyph[indexIntoGlyph] & (0X40)) drawPixel(currentX+1, currentY, color);
+      if (glyph[indexIntoGlyph] & (0X20)) drawPixel(currentX+2, currentY, color);
+      if (glyph[indexIntoGlyph] & (0X10)) drawPixel(currentX+3, currentY, color);
+      if (glyph[indexIntoGlyph] & (0X08)) drawPixel(currentX+4, currentY, color);
+      if (glyph[indexIntoGlyph] & (0X04)) drawPixel(currentX+5, currentY, color);
+      if (glyph[indexIntoGlyph] & (0X02)) drawPixel(currentX+6, currentY, color);
+      if (glyph[indexIntoGlyph] & (0X01)) drawPixel(currentX+7, currentY, color);
+    }
+  }
+}
+
+#if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
+/**************************************************************************/
+/*!
+    @brief  Draws a single smallfont character
+*/
+/**************************************************************************/
+void drawCharSmall(uint16_t x, uint16_t y, uint16_t color, uint8_t c, struct FONT_DEF font)
+{
+  uint8_t col, column[font.u8Width];
+
+  // Check if the requested character is available
+  if ((c >= font.u8FirstChar) && (c <= font.u8LastChar))
+  {
+    // Retrieve appropriate columns from font data
+    for (col = 0; col < font.u8Width; col++)
+    {
+      column[col] = font.au8FontTable[((c - 32) * font.u8Width) + col];    // Get first column of appropriate character
+    }
+  }
+  else
+  {    
+    // Requested character is not available in this font ... send a space instead
+    for (col = 0; col < font.u8Width; col++)
+    {
+      column[col] = 0xFF;    // Send solid space
+    }
+  }
+
+  // Render each column
+  uint16_t xoffset, yoffset;
+  for (xoffset = 0; xoffset < font.u8Width; xoffset++)
+  {
+    for (yoffset = 0; yoffset < (font.u8Height + 1); yoffset++)
+    {
+      uint8_t bit = 0x00;
+      bit = (column[xoffset] << (8 - (yoffset + 1)));     // Shift current row bit left
+      bit = (bit >> 7);                     // Shift current row but right (results in 0x01 for black, and 0x00 for white)
+      if (bit)
+      {
+        drawPixel(x + xoffset, y + yoffset, color);
+      }
+    }
+  }
+}
+#endif
+
+/**************************************************************************/
+/*!
+    @brief  Helper method to accurately draw individual circle points
+*/
+/**************************************************************************/
+void drawCirclePoints(int cx, int cy, int x, int y, uint16_t color)
+{    
+  if (x == 0) 
+  {
+      drawPixel(cx, cy + y, color);
+      drawPixel(cx, cy - y, color);
+      drawPixel(cx + y, cy, color);
+      drawPixel(cx - y, cy, color);
+  } 
+  else if (x == y) 
+  {
+      drawPixel(cx + x, cy + y, color);
+      drawPixel(cx - x, cy + y, color);
+      drawPixel(cx + x, cy - y, color);
+      drawPixel(cx - x, cy - y, color);
+  } 
+  else if (x < y) 
+  {
+      drawPixel(cx + x, cy + y, color);
+      drawPixel(cx - x, cy + y, color);
+      drawPixel(cx + x, cy - y, color);
+      drawPixel(cx - x, cy - y, color);
+      drawPixel(cx + y, cy + x, color);
+      drawPixel(cx - y, cy + x, color);
+      drawPixel(cx + y, cy - x, color);
+      drawPixel(cx - y, cy - x, color);
+  }
+}
+
+/**************************************************************************/
+/*                                                                        */
+/* ----------------------- Public Methods ------------------------------- */
+/*                                                                        */
+/**************************************************************************/
+
+/**************************************************************************/
+/*!
+    @brief  Draws a single pixel at the specified location
+
+    @param[in]  x
+                Horizontal position
+    @param[in]  y
+                Vertical position
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawPixel(uint16_t x, uint16_t y, uint16_t color)
+{
+  if ((x >= lcdGetWidth()) || (y >= lcdGetHeight()))
+  {
+    // Pixel out of range
+    return;
+  }
+
+  // Redirect to LCD
+  lcdDrawPixel(x, y, color);
+}
+
+/**************************************************************************/
+/*!
+    @brief  Fills the screen with the specified color
+
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawFill(uint16_t color)
+{
+  lcdFillRGB(color);
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a simple color test pattern
+*/
+/**************************************************************************/
+void drawTestPattern(void)
+{
+  lcdTest();
+}
+
+#if defined CFG_TFTLCD_INCLUDESMALLFONTS & CFG_TFTLCD_INCLUDESMALLFONTS == 1
+/**************************************************************************/
+/*!
+    @brief  Draws a string using a small font (6 of 8 pixels high).
+
+    @param[in]  x
+                Starting x co-ordinate
+    @param[in]  y
+                Starting y co-ordinate
+    @param[in]  color
+                Color to use when rendering the font
+    @param[in]  text
+                The string to render
+    @param[in]  font
+                Pointer to the FONT_DEF to use when drawing the string
+
+    @section Example
+
+    @code 
+
+    #include "drivers/displays/fonts/smallfonts.h"
+    
+    drawStringSmall(1, 210, COLOR_WHITE, "5x8 System (Max 40 Characters)", Font_System5x8);
+    drawStringSmall(1, 220, COLOR_WHITE, "7x8 System (Max 30 Characters)", Font_System7x8);
+
+    @endcode
+*/
+/**************************************************************************/
+void drawStringSmall(uint16_t x, uint16_t y, uint16_t color, char* text, struct FONT_DEF font)
+{
+  uint8_t l;
+  for (l = 0; l < strlen(text); l++)
+  {
+    drawCharSmall(x + (l * (font.u8Width + 1)), y, color, text[l], font);
+  }
+}
+#endif
+
+/**************************************************************************/
+/*!
+    @brief  Draws a string using the supplied font
+
+    @param[in]  x
+                Starting x co-ordinate
+    @param[in]  y
+                Starting y co-ordinate
+    @param[in]  color
+                Color to use when rendering the font
+    @param[in]  fontInfo
+                Pointer to the FONT_INFO to use when drawing the string
+    @param[in]  str
+                The string to render
+
+    @section Example
+
+    @code 
+
+    #include "drivers/displays/tft/fonts/dejavusans9.h"
+    
+    drawString(0, 90,  COLOR_BLACK, &dejaVuSans9ptFontInfo, "DejaVu Sans 9");
+    drawString(0, 105, COLOR_BLACK, &dejaVuSans9ptFontInfo, "123456789012345678901234567890");
+
+    @endcode
+*/
+/**************************************************************************/
+void drawString(uint16_t x, uint16_t y, uint16_t color, const FONT_INFO *fontInfo, char *str)
+{
+  uint16_t currentX, charWidth, characterToOutput;
+  const FONT_CHAR_INFO *charInfo;
+  uint16_t charOffset;
+
+  // set current x, y to that of requested
+  currentX = x;
+
+  // while not NULL
+  while (*str != '\0')
+  {
+    // get character to output
+    characterToOutput = *str;
+    
+    // get char info
+    charInfo = fontInfo->charInfo;
+    
+    // some fonts have character descriptors, some don't
+    if (charInfo != NULL)
+    {
+      // get correct char offset
+      charInfo += (characterToOutput - fontInfo->startChar);
+      
+      // get width from char info
+      charWidth = charInfo->widthBits;
+      
+      // get offset from char info
+      charOffset = charInfo->offset;
+    }        
+    else
+    {
+      // if no char info, char width is always 5
+      charWidth = 5;
+      
+      // char offset - assume 5 * letter offset
+      charOffset = (characterToOutput - fontInfo->startChar) * 5;
+    }        
+    
+    // Send individual characters
+    // We need to manually calculate width in pages since this is screwy with variable width fonts
+    //uint8_t heightPages = charWidth % 8 ? charWidth / 8 : charWidth / 8 + 1;
+    drawCharBitmap(currentX, y, color, (const char *)(&fontInfo->data[charOffset]), charWidth, fontInfo->height);
+
+    // next char X
+    currentX += charWidth + 1;
+    
+    // next char
+    str++;
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Returns the width in pixels of a string when it is rendered
+
+    This method can be used to determine whether a string will fit
+    inside a specific area, or if it needs to be broken up into multiple
+    lines to be properly rendered on the screen.
+
+    This function only applied to bitmap fonts (which can have variable
+    widths).  All smallfonts (if available) are fixed width and can
+    easily have their width calculated without costly functions like
+    this one.
+
+    @param[in]  fontInfo
+                Pointer to the FONT_INFO for the font that will be used
+    @param[in]  str
+                The string that will be rendered
+*/
+/**************************************************************************/
+uint16_t drawGetStringWidth(const FONT_INFO *fontInfo, char *str)
+{
+  uint16_t width = 0;
+  uint32_t currChar;
+  uint32_t startChar = fontInfo->startChar;
+
+  // until termination
+  for (currChar = *str; currChar; currChar = *(++str))
+  {
+    // if char info exists for the font, use width from there
+    if (fontInfo->charInfo != NULL)
+    {
+      width += fontInfo->charInfo[currChar - startChar].widthBits + 1;
+    }
+    else
+    {
+      width += 5 + 1;
+    }
+  }
+
+  /* return the width */
+  return width > 0 ? width - 1 : width;
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a bresenham line
+
+    @param[in]  x0
+                Starting x co-ordinate
+    @param[in]  y0
+                Starting y co-ordinate
+    @param[in]  x1
+                Ending x co-ordinate
+    @param[in]  y1
+                Ending y co-ordinate
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawLine ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color )
+{
+  drawLineDotted(x0, y0, x1, y1, 0, 1, color);
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a bresenham line with a fixed pattern of empty
+            and solid pixels
+
+    Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
+
+    @param[in]  x0
+                Starting x co-ordinate
+    @param[in]  y0
+                Starting y co-ordinate
+    @param[in]  x1
+                Ending x co-ordinate
+    @param[in]  y1
+                Ending y co-ordinate
+    @param[in]  empty
+                The number of 'empty' pixels to render
+    @param[in]  solid
+                The number of 'solid' pixels to render
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawLineDotted ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t empty, uint16_t solid, uint16_t color )
+{
+  if (solid == 0)
+  {
+    return;
+  }
+
+  // If a negative y int was passed in it will overflow to 65K something
+  // Ugly, but drawCircleFilled() can pass in negative values so we need
+  // to check the values here
+  y0 = y0 > 65000 ? 0 : y0;
+  y1 = y1 > 65000 ? 0 : y1;
+
+  // Check if we can use the optimised horizontal line method
+  if ((y0 == y1) && (empty == 0))
+  {
+    lcdDrawHLine(x0, x1, y0, color);
+    return;
+  }
+
+  // Check if we can use the optimised vertical line method.
+  // This can make a huge difference in performance, but may
+  // not work properly on every LCD controller:
+  if ((x0 == x1) && (empty == 0))
+  {
+    // Warning: This may actually be slower than drawing individual pixels on 
+    // short lines ... Set a minimum line size to use the 'optimised' method
+    // (which changes the screen orientation) ?
+    lcdDrawVLine(x0, y0, y1, color);
+    return;
+  }
+
+  // Draw non-horizontal or dotted line
+  int dy = y1 - y0;
+  int dx = x1 - x0;
+  int stepx, stepy;
+  int emptycount, solidcount;
+
+  if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }
+  if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }
+  dy <<= 1;                               // dy is now 2*dy
+  dx <<= 1;                               // dx is now 2*dx
+
+  emptycount = empty;
+  solidcount = solid;
+
+  drawPixel(x0, y0, color);               // always start with solid pixels
+  solidcount--;
+  if (dx > dy) 
+  {
+    int fraction = dy - (dx >> 1);        // same as 2*dy - dx
+    while (x0 != x1) 
+    {
+      if (fraction >= 0) 
+      {
+        y0 += stepy;
+        fraction -= dx;                   // same as fraction -= 2*dx
+      }
+      x0 += stepx;
+      fraction += dy;                     // same as fraction -= 2*dy
+      if (empty == 0)
+      {
+        // always draw a pixel ... no dotted line requested
+        drawPixel(x0, y0, color);
+      }
+      else if (solidcount)
+      {
+        // Draw solid pxiel and decrement counter
+        drawPixel(x0, y0, color);
+        solidcount--;
+      }
+      else if(emptycount)
+      {
+        // Empty pixel ... don't draw anything an decrement counter
+        emptycount--;
+      }
+      else
+      {
+        // Reset counters and draw solid pixel
+        emptycount = empty;
+        solidcount = solid;
+        drawPixel(x0, y0, color);
+        solidcount--;
+      }
+    }
+  } 
+  else 
+  {
+    int fraction = dx - (dy >> 1);
+    while (y0 != y1) 
+    {
+      if (fraction >= 0) 
+      {
+        x0 += stepx;
+        fraction -= dy;
+      }
+      y0 += stepy;
+      fraction += dx;
+      if (empty == 0)
+      {
+        // always draw a pixel ... no dotted line requested
+        drawPixel(x0, y0, color);
+      }
+      if (solidcount)
+      {
+        // Draw solid pxiel and decrement counter
+        drawPixel(x0, y0, color);
+        solidcount--;
+      }
+      else if(emptycount)
+      {
+        // Empty pixel ... don't draw anything an decrement counter
+        emptycount--;
+      }
+      else
+      {
+        // Reset counters and draw solid pixel
+        emptycount = empty;
+        solidcount = solid;
+        drawPixel(x0, y0, color);
+        solidcount--;
+      }
+    }
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a circle
+
+    Based on: http://www.cs.unc.edu/~mcmillan/comp136/Lecture7/circle.html
+
+    @param[in]  xCenter
+                The horizontal center of the circle
+    @param[in]  yCenter
+                The vertical center of the circle
+    @param[in]  radius
+                The circle's radius in pixels
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawCircle (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint16_t color)
+{
+  int x = 0;
+  int y = radius;
+  int p = (5 - radius*4)/4;
+
+  drawCirclePoints(xCenter, yCenter, x, y, color);
+  while (x < y) 
+  {
+    x++;
+    if (p < 0) 
+    {
+      p += 2*x+1;
+    } 
+    else 
+    {
+      y--;
+      p += 2*(x-y)+1;
+    }
+    drawCirclePoints(xCenter, yCenter, x, y, color);
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a filled circle
+
+    @param[in]  xCenter
+                The horizontal center of the circle
+    @param[in]  yCenter
+                The vertical center of the circle
+    @param[in]  radius
+                The circle's radius in pixels
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawCircleFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint16_t color)
+{
+  int16_t f = 1 - radius;
+  int16_t ddF_x = 1;
+  int16_t ddF_y = -2 * radius;
+  int16_t x = 0;
+  int16_t y = radius;
+  int16_t xc_px, yc_my, xc_mx, xc_py, yc_mx, xc_my;
+  int16_t lcdWidth = lcdGetWidth();
+
+  if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter-radius, xCenter, (yCenter-radius) + (2*radius), color);
+  
+  while (x<y) 
+  {
+    if (f >= 0) 
+    {
+      y--;
+      ddF_y += 2;
+      f += ddF_y;
+    }
+    x++;
+    ddF_x += 2;
+    f += ddF_x;
+
+    xc_px = xCenter+x;
+    xc_mx = xCenter-x;
+    xc_py = xCenter+y;
+    xc_my = xCenter-y;
+    yc_mx = yCenter-x;
+    yc_my = yCenter-y;
+
+    // Make sure X positions are not negative or too large or the pixels will
+    // overflow.  Y overflow is handled in drawLine().
+    if ((xc_px < lcdWidth) && (xc_px >= 0)) drawLine(xc_px, yc_my, xc_px, yc_my + 2*y, color);
+    if ((xc_mx < lcdWidth) && (xc_mx >= 0)) drawLine(xc_mx, yc_my, xc_mx, yc_my + 2*y, color);
+    if ((xc_py < lcdWidth) && (xc_py >= 0)) drawLine(xc_py, yc_mx, xc_py, yc_mx + 2*x, color);
+    if ((xc_my < lcdWidth) && (xc_my >= 0)) drawLine(xc_my, yc_mx, xc_my, yc_mx + 2*x, color);
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a filled rounded corner
+
+    @param[in]  xCenter
+                The horizontal center of the circle
+    @param[in]  yCenter
+                The vertical center of the circle
+    @param[in]  radius
+                The circle's radius in pixels
+    @param[in]  position
+                The position of the corner, which affects how it will
+                be rendered
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawCornerFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, drawCornerPosition_t position, uint16_t color)
+{
+  int16_t f = 1 - radius;
+  int16_t ddF_x = 1;
+  int16_t ddF_y = -2 * radius;
+  int16_t x = 0;
+  int16_t y = radius;
+  int16_t xc_px, yc_my, xc_mx, xc_py, yc_mx, xc_my;
+  int16_t lcdWidth = lcdGetWidth();
+
+  switch (position)
+  {
+    case DRAW_CORNERPOSITION_TOPRIGHT:
+    case DRAW_CORNERPOSITION_TOPLEFT:
+      if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter-radius, xCenter, yCenter, color);
+      break;
+    case DRAW_CORNERPOSITION_BOTTOMRIGHT:
+    case DRAW_CORNERPOSITION_BOTTOMLEFT:
+      if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter, xCenter, (yCenter-radius) + (2*radius), color);
+      break;
+  }
+  
+  while (x<y) 
+  {
+    if (f >= 0) 
+    {
+      y--;
+      ddF_y += 2;
+      f += ddF_y;
+    }
+    x++;
+    ddF_x += 2;
+    f += ddF_x;
+
+    xc_px = xCenter+x;
+    xc_mx = xCenter-x;
+    xc_py = xCenter+y;
+    xc_my = xCenter-y;
+    yc_mx = yCenter-x;
+    yc_my = yCenter-y;
+
+    switch (position)
+    {
+      case DRAW_CORNERPOSITION_TOPRIGHT:
+        if ((xc_px < lcdWidth) && (xc_px >= 0)) drawLine(xc_px, yc_my, xc_px, yCenter, color);
+        if ((xc_py < lcdWidth) && (xc_py >= 0)) drawLine(xc_py, yc_mx, xc_py, yCenter, color);
+        break;
+      case DRAW_CORNERPOSITION_BOTTOMRIGHT:
+        if ((xc_px < lcdWidth) && (xc_px >= 0)) drawLine(xc_px, yCenter, xc_px, yc_my + 2*y, color);
+        if ((xc_py < lcdWidth) && (xc_py >= 0)) drawLine(xc_py, yCenter, xc_py, yc_mx + 2*x, color);
+        break;
+      case DRAW_CORNERPOSITION_TOPLEFT:
+        if ((xc_mx < lcdWidth) && (xc_mx >= 0)) drawLine(xc_mx, yc_my, xc_mx, yCenter, color);
+        if ((xc_my < lcdWidth) && (xc_my >= 0)) drawLine(xc_my, yc_mx, xc_my, yCenter, color);
+        break;
+      case DRAW_CORNERPOSITION_BOTTOMLEFT:
+        if ((xc_mx < lcdWidth) && (xc_mx >= 0)) drawLine(xc_mx, yCenter, xc_mx, yc_my + 2*y, color);
+        if ((xc_my < lcdWidth) && (xc_my >= 0)) drawLine(xc_my, yCenter, xc_my, yc_mx + 2*x, color);
+        break;
+    }
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a simple arrow of the specified width
+
+    @param[in]  x
+                X co-ordinate of the smallest point of the arrow
+    @param[in]  y
+                Y co-ordinate of the smallest point of the arrow
+    @param[in]  size
+                Total width/height of the arrow in pixels
+    @param[in]  direction
+                The direction that the arrow is pointing
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawArrow(uint16_t x, uint16_t y, uint16_t size, drawDirection_t direction, uint16_t color)
+{
+  drawPixel(x, y, color);
+
+  if (size == 1)
+  {
+    return;
+  }
+
+  uint32_t i;
+  switch (direction)
+  {
+    case DRAW_DIRECTION_LEFT:
+      for (i = 1; i<size; i++)
+      {
+        drawLine(x+i, y-i, x+i, y+i, color);
+      }
+      break;
+    case DRAW_DIRECTION_RIGHT:
+      for (i = 1; i<size; i++)
+      {
+        drawLine(x-i, y-i, x-i, y+i, color);
+      }
+      break;
+    case DRAW_DIRECTION_UP:
+      for (i = 1; i<size; i++)
+      {
+        drawLine(x-i, y+i, x+i, y+i, color);
+      }
+      break;
+    case DRAW_DIRECTION_DOWN:
+      for (i = 1; i<size; i++)
+      {
+        drawLine(x-i, y-i, x+i, y-i, color);
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a simple (empty) rectangle
+
+    @param[in]  x0
+                Starting x co-ordinate
+    @param[in]  y0
+                Starting y co-ordinate
+    @param[in]  x1
+                Ending x co-ordinate
+    @param[in]  y1
+                Ending y co-ordinate
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawRectangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
+{
+  uint16_t x, y;
+
+  if (y1 < y0)
+  {
+    // Switch y1 and y0
+    y = y1;
+    y1 = y0;
+    y0 = y;
+  }
+
+  if (x1 < x0)
+  {
+    // Switch x1 and x0
+    x = x1;
+    x1 = x0;
+    x0 = x;
+  }
+
+  drawLine (x0, y0, x1, y0, color);
+  drawLine (x1, y0, x1, y1, color);
+  drawLine (x1, y1, x0, y1, color);
+  drawLine (x0, y1, x0, y0, color);
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a filled rectangle
+
+    @param[in]  x0
+                Starting x co-ordinate
+    @param[in]  y0
+                Starting y co-ordinate
+    @param[in]  x1
+                Ending x co-ordinate
+    @param[in]  y1
+                Ending y co-ordinate
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawRectangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color)
+{
+  int height;
+  uint16_t x, y;
+
+  if (y1 < y0)
+  {
+    // Switch y1 and y0
+    y = y1;
+    y1 = y0;
+    y0 = y;
+  }
+
+  if (x1 < x0)
+  {
+    // Switch x1 and x0
+    x = x1;
+    x1 = x0;
+    x0 = x;
+  }
+
+  height = y1 - y0;
+  for (height = y0; y1 > height - 1; ++height)
+  {
+    drawLine(x0, height, x1, height, color);
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a filled rectangle with rounded corners
+
+    @param[in]  x0
+                Starting x co-ordinate
+    @param[in]  y0
+                Starting y co-ordinate
+    @param[in]  x1
+                Ending x co-ordinate
+    @param[in]  y1
+                Ending y co-ordinate
+    @param[in]  color
+                Color used when drawing
+    @param[in]  radius
+                Corner radius in pixels
+    @param[in]  corners
+                Which corners to round
+*/
+/**************************************************************************/
+void drawRectangleRounded ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color, uint16_t radius, drawRoundedCorners_t corners )
+{
+  int height;
+  uint16_t y;
+
+  if (corners == DRAW_ROUNDEDCORNERS_NONE)
+  {
+    drawRectangleFilled(x0, y0, x1, y1, color);
+    return;
+  }
+
+  // Calculate height
+  if (y1 < y0)
+  {
+    y = y1;
+    y1 = y0;
+    y0 = y;
+  }
+  height = y1 - y0;
+
+  // Check radius
+  if (radius > height / 2)
+  {
+    radius = height / 2;
+  }
+  radius -= 1;
+
+  // Draw body  
+  drawRectangleFilled(x0 + radius, y0, x1 - radius, y1, color);
+
+  switch (corners)
+  {
+    case DRAW_ROUNDEDCORNERS_ALL:
+      drawCircleFilled(x0 + radius, y0 + radius, radius, color);
+      drawCircleFilled(x1 - radius, y0 + radius, radius, color);
+      drawCircleFilled(x0 + radius, y1 - radius, radius, color);
+      drawCircleFilled(x1 - radius, y1 - radius, radius, color);
+      if (radius*2+1 < height)
+      {
+        drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
+        drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
+      }
+      break;
+    case DRAW_ROUNDEDCORNERS_TOP:
+      drawCircleFilled(x0 + radius, y0 + radius, radius, color);
+      drawCircleFilled(x1 - radius, y0 + radius, radius, color);
+      drawRectangleFilled(x0, y0 + radius, x0 + radius, y1, color); 
+      drawRectangleFilled(x1 - radius, y0 + radius, x1, y1, color); 
+      break;
+    case DRAW_ROUNDEDCORNERS_BOTTOM:
+      drawCircleFilled(x0 + radius, y1 - radius, radius, color);
+      drawCircleFilled(x1 - radius, y1 - radius, radius, color);
+      drawRectangleFilled(x0, y0, x0 + radius, y1 - radius, color);
+      drawRectangleFilled(x1 - radius, y0, x1, y1 - radius, color);
+      break;
+    case DRAW_ROUNDEDCORNERS_LEFT:
+      drawCircleFilled(x0 + radius, y0 + radius, radius, color);
+      drawCircleFilled(x0 + radius, y1 - radius, radius, color);
+      if (radius*2+1 < height)
+      {
+        drawRectangleFilled(x0, y0 + radius, x0 + radius, y1 - radius, color);
+      }
+      drawRectangleFilled(x1 - radius, y0, x1, y1, color);
+      break;
+    case DRAW_ROUNDEDCORNERS_RIGHT:
+      drawCircleFilled(x1 - radius, y0 + radius, radius, color);
+      drawCircleFilled(x1 - radius, y1 - radius, radius, color);
+      if (radius*2+1 < height)
+      {
+        drawRectangleFilled(x1 - radius, y0 + radius, x1, y1 - radius, color);
+      }
+      drawRectangleFilled(x0, y0, x0 + radius, y1, color);
+      break;
+    default:
+      break;
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a triangle
+
+    @param[in]  x0
+                x co-ordinate for point 0
+    @param[in]  y0
+                y co-ordinate for point 0
+    @param[in]  x1
+                x co-ordinate for point 1
+    @param[in]  y1
+                y co-ordinate for point 1
+    @param[in]  x2
+                x co-ordinate for point 2
+    @param[in]  y2
+                y co-ordinate for point 2
+    @param[in]  color
+                Color used when drawing
+*/
+/**************************************************************************/
+void drawTriangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
+{
+  drawLine(x0, y0, x1, y1, color);
+  drawLine(x1, y1, x2, y2, color);
+  drawLine(x2, y2, x0, y0, color);  
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a filled triangle
+
+    @param[in]  x0
+                x co-ordinate for point 0
+    @param[in]  y0
+                y co-ordinate for point 0
+    @param[in]  x1
+                x co-ordinate for point 1
+    @param[in]  y1
+                y co-ordinate for point 1
+    @param[in]  x2
+                x co-ordinate for point 2
+    @param[in]  y2
+                y co-ordinate for point 2
+    @param[in]  color
+                Fill color
+
+    @section Example
+
+    @code
+
+    // Draw a white triangle
+    drawTriangleFilled ( 100, 10, 20, 120, 230, 290, COLOR_WHITE);
+    // Draw black circles at each point of the triangle
+    drawCircleFilled(100, 10, 2, COLOR_BLACK);
+    drawCircleFilled(20, 120, 2, COLOR_BLACK);
+    drawCircleFilled(230, 290, 2, COLOR_BLACK);
+
+    @endcode
+*/
+/**************************************************************************/
+void drawTriangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
+{
+  // Re-order vertices by ascending Y values (smallest first)
+  if (y0 > y1) {
+    drawSwap(y0, y1); drawSwap(x0, x1);
+  }
+  if (y1 > y2) {
+    drawSwap(y2, y1); drawSwap(x2, x1);
+  }
+  if (y0 > y1) {
+    drawSwap(y0, y1); drawSwap(x0, x1);
+  }
+
+  int32_t dx1, dx2, dx3;    // Interpolation deltas
+  int32_t sx1, sx2, sy;     // Scanline co-ordinates
+
+  sx1=sx2=x0 * 1000;        // Use fixed point math for x axis values
+  sy=y0;
+
+  // Calculate interpolation deltas
+  if (y1-y0 > 0) dx1=((x1-x0)*1000)/(y1-y0);
+    else dx1=0;
+  if (y2-y0 > 0) dx2=((x2-x0)*1000)/(y2-y0);
+    else dx2=0;
+  if (y2-y1 > 0) dx3=((x2-x1)*1000)/(y2-y1);
+    else dx3=0;
+
+  // Render scanlines (horizontal lines are the fastest rendering method)
+  if (dx1 > dx2) 
+  {
+    for(; sy<=y1; sy++, sx1+=dx2, sx2+=dx1)
+    {
+      drawLine(sx1/1000, sy, sx2/1000, sy, color);
+    }
+    sx2 = x1*1000;
+    sy = y1;
+    for(; sy<=y2; sy++, sx1+=dx2, sx2+=dx3)
+    {
+      drawLine(sx1/1000, sy, sx2/1000, sy, color);
+    }
+  } 
+  else 
+  {
+    for(; sy<=y1; sy++, sx1+=dx1, sx2+=dx2)
+    {
+      drawLine(sx1/1000, sy, sx2/1000, sy, color);
+    }
+    sx1 = x1*1000;
+    sy = y1;
+    for(; sy<=y2; sy++, sx1+=dx3, sx2+=dx2)
+    {
+      drawLine(sx1/1000, sy, sx2/1000, sy, color);
+    }
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Converts a 24-bit RGB color to an equivalent 16-bit RGB565 value
+
+    @param[in]  r
+                8-bit red
+    @param[in]  g
+                8-bit green
+    @param[in]  b
+                8-bit blue
+
+    @section Example
+
+    @code 
+
+    // Get 16-bit equivalent of 24-bit color
+    uint16_t gray = drawRGB24toRGB565(0x33, 0x33, 0x33);
+
+    @endcode
+*/
+/**************************************************************************/
+uint16_t drawRGB24toRGB565(uint8_t r, uint8_t g, uint8_t b)
+{
+  return ((r / 8) << 11) | ((g / 4) << 5) | (b / 8);
+}
+
+/**************************************************************************/
+/*!
+    @brief  Converts a 16-bit RGB565 color to a standard 32-bit BGRA32
+            color (with alpha set to 0xFF)
+
+    @param[in]  color
+                16-bit rgb565 color
+
+    @section Example
+
+    @code 
+
+    // First convert 24-bit color to RGB565
+    uint16_t rgb565 = drawRGB24toRGB565(0xFF, 0x00, 0x00);
+  
+    // Convert RGB565 color back to BGRA32
+    uint32_t bgra32 = drawRGB565toBGRA32(rgb565);
+  
+    // Display results
+    printf("BGRA32: 0x%08X R: %u G: %u B: %u A: %u \r\n", 
+        bgra32, 
+        (bgra32 & 0x000000FF),        // Blue
+        (bgra32 & 0x0000FF00) >> 8,   // Green
+        (bgra32 & 0x00FF0000) >> 16,  // Red
+        (bgra32 & 0xFF000000) >> 24); // Alpha
+
+    @endcode
+*/
+/**************************************************************************/
+uint32_t drawRGB565toBGRA32(uint16_t color)
+{
+  uint32_t bits = (uint32_t)color;
+  uint32_t blue = bits & 0x001F;     // 5 bits blue
+  uint32_t green = bits & 0x07E0;    // 6 bits green
+  uint32_t red = bits & 0xF800;      // 5 bits red
+
+  // Return shifted bits with alpha set to 0xFF
+  return (red << 8) | (green << 5) | (blue << 3) | 0xFF000000;
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Reverses a 16-bit color from BGR to RGB
+*/
+/**************************************************************************/
+uint16_t drawBGR2RGB(uint16_t color)
+{   
+  uint16_t r, g, b;   
+   
+  b = (color>>0)  & 0x1f;   
+  g = (color>>5)  & 0x3f;   
+  r = (color>>11) & 0x1f;   
+     
+  return( (b<<11) + (g<<5) + (r<<0) );
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a progress bar with rounded corners
+
+    @param[in]  x
+                Starting x location
+    @param[in]  y
+                Starting y location
+    @param[in]  width
+                Total width of the progress bar in pixels
+    @param[in]  height
+                Total height of the progress bar in pixels
+    @param[in]  borderCorners
+                The type of rounded corners to render with the progress bar border
+    @param[in]  progressCorners
+                The type of rounded corners to render with the inner progress bar
+    @param[in]  borderColor
+                16-bit color for the outer border
+    @param[in]  borderFillColor
+                16-bit color for the interior of the outer border
+    @param[in]  progressBorderColor
+                16-bit color for the progress bar's border
+    @param[in]  progressFillColor
+                16-bit color for the inner bar's fill
+    @param[in]  progress
+                Progress percentage (between 0 and 100)
+
+    @section Example
+
+    @code 
+    #include "drivers/displays/tft/drawing.h"
+
+    // Draw a the progress bar (150x15 pixels large, starting at X:10, Y:195
+    // with rounded corners on the top and showing 72% progress)
+    drawProgressBar(10, 195, 150, 15, DRAW_ROUNDEDCORNERS_TOP, DRAW_ROUNDEDCORNERS_TOP, COLOR_DARKERGRAY, COLOR_DARKGRAY, COLOR_LIMEGREENDIM, COLOR_LIMEGREEN, 72 );
+
+    @endcode
+*/
+/**************************************************************************/
+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 )
+{
+  // Draw border with rounded corners
+  drawRectangleRounded(x, y, x + width, y + height, borderColor, 5, borderCorners);
+  drawRectangleRounded(x+1, y+1, x + width - 1, y + height - 1, borderFillColor, 5, borderCorners);
+
+  // Progress bar
+  if (progress > 0 && progress <= 100)
+  {
+    // Calculate bar size
+    uint16_t bw;
+    bw = (width - 6);   // bar at 100%
+    if (progress != 100)
+    {
+      bw = (bw * progress) / 100;
+    } 
+    drawRectangleRounded(x + 3, y + 3, bw + x + 3, y + height - 3, progressBorderColor, 5, progressCorners);
+    drawRectangleRounded(x + 4, y + 4, bw + x + 3 - 1, y + height - 4, progressFillColor, 5, progressCorners);
+  }
+}
+
+/**************************************************************************/
+/*!
+    @brief  Draws a simple button
+
+    @param[in]  x
+                Starting x location
+    @param[in]  y
+                Starting y location
+    @param[in]  width
+                Total width of the button in pixels
+    @param[in]  height
+                Total height of the button in pixels
+    @param[in]  fontInfo
+                Pointer to the FONT_INFO used to render the button text
+    @param[in]  fontHeight
+                The height in pixels of the font (used for centering)
+    @param[in]  borderclr
+                The rgb565 border color
+    @param[in]  fillclr
+                The rgb565 background color
+    @param[in]  fontclr
+                The rgb565 font color
+    @param[in]  text
+                The text to render on the button
+
+    @section Example
+
+    @code 
+
+    #include "drivers/displays/tft/drawing.h"  
+    #include "drivers/displays/tft/fonts/dejavusans9.h"
+
+    // Draw two buttons using Vera Sans Bold 9
+    drawButton(20, 195, 200, 35, &dejaVuSans9ptFontInfo, 7, COLOR_GRAY_80, COLOR_GRAY_80, COLOR_WHITE, "System Settings");
+    drawButton(20, 235, 200, 35, &dejaVuSans9ptFontInfo, 7, COLOR_THEME_LIMEGREEN_DARKER, COLOR_THEME_LIMEGREEN_BASE, COLOR_BLACK, "System Settings");
+
+    @endcode
+*/
+/**************************************************************************/
+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)
+{
+  // Border
+  drawRectangleRounded(x, y, x + width, y + height, borderclr, 5, DRAW_ROUNDEDCORNERS_ALL);
+  // Fill
+  drawRectangleRounded(x+2, y+2, x+width-2, y+height-2, fillclr, 5, DRAW_ROUNDEDCORNERS_ALL);
+
+  // Render text
+  if (text != NULL)
+  {
+    uint16_t textWidth = drawGetStringWidth(&*fontInfo, text);
+    uint16_t xStart = x + (width / 2) - (textWidth / 2);
+    uint16_t yStart = y + (height / 2) - (fontHeight / 2) + 1;
+    drawString(xStart, yStart, fontclr, &*fontInfo, text);
+  }
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Renders a 16x16 monochrome icon using the supplied uint16_t
+            array.
+
+    @param[in]  x
+                The horizontal location to start rendering from
+    @param[in]  x
+                The vertical location to start rendering from
+    @param[in]  color
+                The RGB565 color to use when rendering the icon
+    @param[in]  icon
+                The uint16_t array containing the 16x16 image data
+
+    @section Example
+
+    @code 
+
+    #include "drivers/displays/tft/drawing.h"  
+    #include "drivers/displays/icons16.h"
+
+    // Renders the info icon, which has two seperate parts ... the exterior
+    // and a seperate interior mask if you want to fill the contents with a
+    // different color
+    drawIcon16(132, 202, COLOR_BLUE, icons16_info);
+    drawIcon16(132, 202, COLOR_WHITE, icons16_info_interior);
+
+    @endcode
+*/
+/**************************************************************************/
+void drawIcon16(uint16_t x, uint16_t y, uint16_t color, uint16_t icon[])
+{
+  int i;
+  for (i = 0; i<16; i++)
+  {
+    if (icon[i] & (0X8000)) drawPixel(x, y+i, color);
+    if (icon[i] & (0X4000)) drawPixel(x+1, y+i, color);
+    if (icon[i] & (0X2000)) drawPixel(x+2, y+i, color);
+    if (icon[i] & (0X1000)) drawPixel(x+3, y+i, color);
+    if (icon[i] & (0X0800)) drawPixel(x+4, y+i, color);
+    if (icon[i] & (0X0400)) drawPixel(x+5, y+i, color);
+    if (icon[i] & (0X0200)) drawPixel(x+6, y+i, color);
+    if (icon[i] & (0X0100)) drawPixel(x+7, y+i, color);
+    if (icon[i] & (0X0080)) drawPixel(x+8, y+i, color);
+    if (icon[i] & (0x0040)) drawPixel(x+9, y+i, color);
+    if (icon[i] & (0X0020)) drawPixel(x+10, y+i, color);
+    if (icon[i] & (0X0010)) drawPixel(x+11, y+i, color);
+    if (icon[i] & (0X0008)) drawPixel(x+12, y+i, color);
+    if (icon[i] & (0X0004)) drawPixel(x+13, y+i, color);
+    if (icon[i] & (0X0002)) drawPixel(x+14, y+i, color);
+    if (icon[i] & (0X0001)) drawPixel(x+15, y+i, color);
+  }
+}
+
+#ifdef CFG_SDCARD
+/**************************************************************************/
+/*!
+    @brief  Loads a 24-bit Windows bitmap image from an SD card and
+            renders it
+
+    @section Example
+
+    @code 
+
+    #include "drivers/displays/tft/drawing.h"
+
+    // Draw image.bmp (from the root folder) starting at pixel 0,0
+    bmp_error_t error = drawBitmapImage(0, 0, "/image.bmp");
+
+    if (error)
+    {
+      switch (error)
+      {
+        case BMP_ERROR_SDINITFAIL:
+          break;
+        case BMP_ERROR_FILENOTFOUND:
+          break;
+        case BMP_ERROR_NOTABITMAP:
+          // First two bytes of image not 'BM'
+          break;
+        case BMP_ERROR_INVALIDBITDEPTH:
+          // Image is not 24-bits
+          break;
+        case BMP_ERROR_COMPRESSEDDATA:
+          // Image contains compressed data
+          break;
+        case BMP_ERROR_INVALIDDIMENSIONS:
+          // Width or Height is > LCD size
+          break;
+        case BMP_ERROR_PREMATUREEOF:
+          // EOF unexpectedly reached in pixel data
+          break;
+      }
+    }
+        
+    @endcode
+*/
+/**************************************************************************/
+bmp_error_t drawBitmapImage(uint16_t x, uint16_t y, char *filename)
+{
+  return bmpDrawBitmap(x, y, filename);
+}
+
+#endif
This page took 0.045684 seconds and 4 git commands to generate.