/* */
/**************************************************************************/
+/**************************************************************************/
+/*!
+ @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 uint8_t *glyph, uint8_t cols, uint8_t rows)
{
uint16_t verticalPage, horizBit, currentY, currentX;
uint16_t 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;
}
}
}
// 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, &fontInfo->data[charOffset], charWidth, fontInfo->height);
// next char X
currentX += charWidth + 1;
// 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
}
}
+/**************************************************************************/
+/*!
+ @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
}
}
+/**************************************************************************/
+/*!
+ @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
r = (color>>11) & 0x1f;
return( (b<<11) + (g<<5) + (r<<0) );
-}
+}
/**************************************************************************/
/*!
@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
*/
/**************************************************************************/
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)
{
- uint16_t border, fill, font, activeborder, activefill, activefont;
-
- // Set colors
- border = COLOR_GRAY_30;
- fill = COLOR_GRAY_30;
- font = COLOR_WHITE;
- activeborder = COLOR_THEME_DEFAULT_DARKER;
- activefill = COLOR_THEME_DEFAULT_BASE;
- activefont = COLOR_BLACK;
-
// Border
drawRectangleRounded(x, y, x + width, y + height, borderclr, 5, DRAW_ROUNDEDCORNERS_ALL);
// Fill
void drawIcon16(uint16_t x, uint16_t y, uint16_t color, uint16_t icon[])
{
int i;
- uint16_t row;
for (i = 0; i<16; i++)
{
if (icon[i] & (0X8000)) drawPixel(x, y+i, color);