Added SSD1331_COLORORDER_RGB/BGR flag
[hackover2013-badge-firmware.git] / drivers / lcd / tft / drawing.c
index 201df6c..e90a8e6 100644 (file)
 /*                                                                        */
 /**************************************************************************/
 
+/**************************************************************************/
+/*!
+    @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 uint8_t *glyph, uint8_t glyphHeightPages, uint8_t glyphWidthBits)
+void drawCharBitmap(const uint16_t xPixel, const uint16_t yPixel, uint16_t color, const char *glyph, uint8_t cols, uint8_t rows)
 {
-  uint16_t verticalPage, horizBit, currentY, currentX;
-  uint16_t indexIntoGlyph;
+  uint16_t currentY, currentX, indexIntoGlyph;
+  uint16_t _row, _col, _colPages;
 
   // set initial current y
   currentY = yPixel;
   currentX = xPixel;
 
-  // for each page of the glyph
-  for (verticalPage = glyphHeightPages; verticalPage > 0; --verticalPage)
+  // 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 each horizontol bit
-    for (horizBit = 0; horizBit < glyphWidthBits; ++horizBit)
+    for (_col = 0; _col < _colPages; _col++)
     {
-      // next byte
-      indexIntoGlyph = (glyphHeightPages * horizBit) + verticalPage - 1;
-      
-      currentX = xPixel + (horizBit);
+      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, currentY - 1, color);
-      if (glyph[indexIntoGlyph] & (0X20)) drawPixel(currentX, currentY - 2, color);
-      if (glyph[indexIntoGlyph] & (0X10)) drawPixel(currentX, currentY - 3, color);
-      if (glyph[indexIntoGlyph] & (0X08)) drawPixel(currentX, currentY - 4, color);
-      if (glyph[indexIntoGlyph] & (0X04)) drawPixel(currentX, currentY - 5, color);
-      if (glyph[indexIntoGlyph] & (0X02)) drawPixel(currentX, currentY - 6, color);
-      if (glyph[indexIntoGlyph] & (0X01)) drawPixel(currentX, currentY - 7, 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);
     }
-    // next line of pages
-    currentY += 8;
   }
 }
 
@@ -330,7 +348,9 @@ void drawString(uint16_t x, uint16_t y, uint16_t color, const FONT_INFO *fontInf
     }        
     
     // Send individual characters
-    drawCharBitmap(currentX, y, color, &fontInfo->data[charOffset], fontInfo->heightPages, charWidth);
+    // 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;
@@ -379,8 +399,8 @@ uint16_t drawGetStringWidth(const FONT_INFO *fontInfo, char *str)
     }
   }
 
-  /* return the wdith */
-  return width;
+  /* return the width */
+  return width > 0 ? width - 1 : width;
 }
 
 /**************************************************************************/
@@ -450,9 +470,6 @@ void drawLineDotted ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16
   // 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:
-  // ex.: drawCircleFilled(120, 160, 50, COLOR_RED);
-  //      = 678834 cycles using lcdDrawVLine w/ILI9328   =  9.43mS @ 72MHz
-  //      = 7546261 w/o lcdDrawVLine, setting each pixel = 104.8mS @ 72MHz
   if ((x0 == x1) && (empty == 0))
   {
     // Warning: This may actually be slower than drawing individual pixels on 
@@ -649,6 +666,86 @@ void drawCircleFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint
   }
 }
 
+/**************************************************************************/
+/*!
+    @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
@@ -919,7 +1016,7 @@ void drawTriangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t
 
 /**************************************************************************/
 /*!
-    @brief  Draws a triangle
+    @brief  Draws a filled triangle
 
     @param[in]  x0
                 x co-ordinate for point 0
@@ -952,7 +1049,16 @@ void drawTriangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t
 /**************************************************************************/
 void drawTriangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
 {
-  // ToDo: re-order vertices by ascending Y values (smallest first)
+  // 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
@@ -1169,11 +1275,11 @@ void drawProgressBar ( uint16_t x, uint16_t y, uint16_t width, uint16_t height,
     @code 
 
     #include "drivers/lcd/tft/drawing.h"  
-    #include "drivers/lcd/tft/fonts/dejavusansbold9.h"
+    #include "drivers/lcd/tft/fonts/dejavusans9.h"
 
     // Draw two buttons using Vera Sans Bold 9
-    drawButton(20, 195, 200, 35, &dejaVuSansBold9ptFontInfo, 7, COLOR_DARKERGRAY, COLOR_DARKERGRAY, COLOR_WHITE, "System Settings");
-    drawButton(20, 235, 200, 35, &dejaVuSansBold9ptFontInfo, 7, COLOR_LIMEGREENDIM, COLOR_LIMEGREEN, COLOR_BLACK, "System Settings");
+    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
 */
This page took 0.034347 seconds and 4 git commands to generate.