856 lines
18 KiB
C
856 lines
18 KiB
C
|
|
/*
|
||
|
|
* graphicsLibrary.c
|
||
|
|
*
|
||
|
|
* Created on: Feb 12, 2022
|
||
|
|
* Author: Brian.Bailey
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <string.h>
|
||
|
|
#include <ctype.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <stdbool.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stddef.h>
|
||
|
|
#include <stdint.h>
|
||
|
|
|
||
|
|
#include "fsl_common.h"
|
||
|
|
|
||
|
|
#include "..\lcd.h"
|
||
|
|
#include "..\Fonts\fontLibrary.h"
|
||
|
|
#include "lcd.h"
|
||
|
|
|
||
|
|
#include "graphicsLibrary.h"
|
||
|
|
|
||
|
|
|
||
|
|
/*******************************************************************************
|
||
|
|
* Definitions
|
||
|
|
******************************************************************************/
|
||
|
|
|
||
|
|
#define BMP_WIDTH_INDEX 0 //Location of xSize in bitmap array
|
||
|
|
#define BMP_HEIGHT_INDEX 1 //Location of ySize in bitmap array
|
||
|
|
#define BMP_DATA_INDEX 2 //Location of data in bitmap array
|
||
|
|
|
||
|
|
#define ABS(x) ((x) > 0 ? (x) : -(x))
|
||
|
|
|
||
|
|
/*******************************************************************************
|
||
|
|
* Static Function Declarations
|
||
|
|
******************************************************************************/
|
||
|
|
|
||
|
|
static void DrawHLine(int16_t x0, int16_t y0, uint16_t width, LCD_DRAWMODE_t drawMode);
|
||
|
|
static void DrawVLine(int16_t x0, int16_t y0, uint16_t height, LCD_DRAWMODE_t drawMode);
|
||
|
|
static void xLine(int16_t x1, int16_t x2, int16_t y, LCD_DRAWMODE_t drawMode);
|
||
|
|
static void yLine(int16_t x, int16_t y1, int16_t y2, LCD_DRAWMODE_t drawMode);
|
||
|
|
|
||
|
|
/*******************************************************************************
|
||
|
|
* Static Functions
|
||
|
|
******************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Draw a horizontal line with given color
|
||
|
|
*/
|
||
|
|
static void DrawHLine(int16_t x0, int16_t y0, uint16_t width, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
for(int16_t x = x0; x < (x0+width); x++)
|
||
|
|
{
|
||
|
|
LCD_DrawPixel(x, y0, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Draw a vertical line with given color
|
||
|
|
*/
|
||
|
|
static void DrawVLine(int16_t x0, int16_t y0, uint16_t height, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
for(int16_t y = y0; y < (y0+height); y++)
|
||
|
|
{
|
||
|
|
LCD_DrawPixel(x0, y, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//Supporting functions for GL_DrawCircle2
|
||
|
|
static void xLine(int16_t x1, int16_t x2, int16_t y, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
while (x1 <= x2)
|
||
|
|
{
|
||
|
|
LCD_DrawPixel(x1++, y, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static void yLine(int16_t x, int16_t y1, int16_t y2, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
while (y1 <= y2)
|
||
|
|
{
|
||
|
|
LCD_DrawPixel(x, y1++, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*******************************************************************************
|
||
|
|
* Public Functions
|
||
|
|
******************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Draw a line using Bresenham's algorithm with given color. //ADD WIDTH
|
||
|
|
*/
|
||
|
|
void GL_DrawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t thickness, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
int16_t dx; //width
|
||
|
|
int16_t sx; //x increment direction
|
||
|
|
int16_t dy; //height
|
||
|
|
int16_t sy; //y increment direction
|
||
|
|
int16_t err;
|
||
|
|
int16_t e2;
|
||
|
|
int16_t widthOffsetLow; //line thickness low offset for perpendicular line
|
||
|
|
int16_t widthOffsetHigh; //line thickness high offset for perpendicular line
|
||
|
|
|
||
|
|
dx = ABS(x1 - x0);
|
||
|
|
sx = x0 < x1 ? 1 : -1;
|
||
|
|
dy = ABS(y1 - y0);
|
||
|
|
sy = y0 < y1 ? 1 : -1;
|
||
|
|
err = (dx > dy ? dx : -dy) / 2;
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
{
|
||
|
|
|
||
|
|
if (x0 == x1 && y0 == y1)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
//Draw a line perpendicular to the first with length "thickness"
|
||
|
|
widthOffsetLow = ((thickness-1)*-1) >> 1;
|
||
|
|
widthOffsetHigh = thickness >> 1;
|
||
|
|
|
||
|
|
for(int16_t i =widthOffsetLow; i <= widthOffsetHigh; i++)
|
||
|
|
{
|
||
|
|
if(dy > dx) //if line is more horizontal, draw horizontal line
|
||
|
|
{
|
||
|
|
LCD_DrawPixel(x0 + i, y0, drawMode);
|
||
|
|
}
|
||
|
|
else //vertical line
|
||
|
|
{
|
||
|
|
LCD_DrawPixel(x0, y0 + i, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
e2 = err + err;
|
||
|
|
|
||
|
|
if (e2 > -dx)
|
||
|
|
{
|
||
|
|
err -= dy;
|
||
|
|
x0 += sx;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (e2 < dy)
|
||
|
|
{
|
||
|
|
err += dx;
|
||
|
|
y0 += sy;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Draw a rectangle with given color and thickness.
|
||
|
|
* Corners will move outward with increasing thickness
|
||
|
|
*/
|
||
|
|
void GL_DrawRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t thickness, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
/* Make sure x0 is smaller than x1. */
|
||
|
|
if (x0 > x1)
|
||
|
|
{
|
||
|
|
x0 = x0 + x1;
|
||
|
|
x1 = x0 - x1;
|
||
|
|
x0 = x0 - x1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Make sure y0 is smaller than y1. */
|
||
|
|
if (y0 > y1)
|
||
|
|
{
|
||
|
|
y0 = y0 + y1;
|
||
|
|
y1 = y0 - y1;
|
||
|
|
y0 = y0 - y1;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint16_t width = x1 - x0 + 1;
|
||
|
|
uint16_t height = y1 - y0 + 1;
|
||
|
|
|
||
|
|
|
||
|
|
//Draw concentric rectangles to increase thickness
|
||
|
|
//This overwrites the corner pixels
|
||
|
|
int16_t thicknessOffsetLow = ((thickness-1)*-1) >> 1; //line thickness low offset
|
||
|
|
int16_t thicknessOffsetHigh = thickness >> 1; //line thickness high offset
|
||
|
|
for(int16_t i = thicknessOffsetLow; i <= thicknessOffsetHigh; i++)
|
||
|
|
{
|
||
|
|
DrawHLine(x0 + i, y0 + i, width + 2*i*-1, drawMode); //top horizontal
|
||
|
|
DrawHLine(x0 - i, y1 + i, width + 2*i, drawMode); //bottom horizontal
|
||
|
|
DrawVLine(x0 + i, y0 + i, height + 2*i*-1, drawMode); //left vertical
|
||
|
|
DrawVLine(x1 + i, y0 - i, height + 2*i, drawMode); //right vertical
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Draw a filled rectangle with given color.
|
||
|
|
*/
|
||
|
|
void GL_DrawFilledRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
/* Make sure x0 is smaller than x1. */
|
||
|
|
if (x0 > x1)
|
||
|
|
{
|
||
|
|
x0 = x0 + x1;
|
||
|
|
x1 = x0 - x1;
|
||
|
|
x0 = x0 - x1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Make sure y0 is smaller than y1. */
|
||
|
|
if (y0 > y1)
|
||
|
|
{
|
||
|
|
y0 = y0 + y1;
|
||
|
|
y1 = y0 - y1;
|
||
|
|
y0 = y0 - y1;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint16_t width = x1 - x0 + 1;
|
||
|
|
uint16_t height = y1 - y0 + 1;
|
||
|
|
|
||
|
|
for (uint16_t i = 0; i < height; i++)
|
||
|
|
{
|
||
|
|
DrawHLine(x0, y0 + i, width, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void GL_DrawCircle(int16_t xc, int16_t yc, int16_t r, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
int16_t x = 0;
|
||
|
|
int16_t y = r;
|
||
|
|
int16_t d = 3 - 2 * r;
|
||
|
|
|
||
|
|
LCD_DrawPixel(xc + x, yc + y, drawMode);
|
||
|
|
LCD_DrawPixel(xc - x, yc + y, drawMode);
|
||
|
|
LCD_DrawPixel(xc + x, yc - y, drawMode);
|
||
|
|
LCD_DrawPixel(xc - x, yc - y, drawMode);
|
||
|
|
LCD_DrawPixel(xc + y, yc + x, drawMode);
|
||
|
|
LCD_DrawPixel(xc - y, yc + x, drawMode);
|
||
|
|
LCD_DrawPixel(xc + y, yc - x, drawMode);
|
||
|
|
LCD_DrawPixel(xc - y, yc - x, drawMode);
|
||
|
|
|
||
|
|
while (y >= x)
|
||
|
|
{
|
||
|
|
x++;
|
||
|
|
|
||
|
|
if (d > 0)
|
||
|
|
{
|
||
|
|
y--;
|
||
|
|
d = d + 4 * (x - y) + 10;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
d = d + 4 * x + 6;
|
||
|
|
}
|
||
|
|
|
||
|
|
LCD_DrawPixel(xc + x, yc + y, drawMode);
|
||
|
|
LCD_DrawPixel(xc - x, yc + y, drawMode);
|
||
|
|
LCD_DrawPixel(xc + x, yc - y, drawMode);
|
||
|
|
LCD_DrawPixel(xc - x, yc - y, drawMode);
|
||
|
|
LCD_DrawPixel(xc + y, yc + x, drawMode);
|
||
|
|
LCD_DrawPixel(xc - y, yc + x, drawMode);
|
||
|
|
LCD_DrawPixel(xc + y, yc - x, drawMode);
|
||
|
|
LCD_DrawPixel(xc - y, yc - x, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//Draw two circles with fill between them (circle with thickness)
|
||
|
|
//uses midpoint circle algorithm
|
||
|
|
// from https://stackoverflow.com/questions/27755514/circle-with-thickness-drawing-algorithm
|
||
|
|
void GL_DrawCircle2(int16_t xc, int16_t yc, int16_t rInner, int16_t rOuter, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
if(rInner > rOuter) //exit if inner circle radius larger than rOuter
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
int16_t xo = rOuter; //rOuter circle radius
|
||
|
|
int16_t xi = rInner; //rInner circle radius
|
||
|
|
int16_t y = 0;
|
||
|
|
int16_t erro = 1 - xo; //rOuter circle error
|
||
|
|
int16_t erri = 1 - xi; //rInner circle error
|
||
|
|
|
||
|
|
while(xo >= y)
|
||
|
|
{
|
||
|
|
xLine(xc + xi, xc + xo, yc + y, drawMode);
|
||
|
|
yLine(xc + y, yc + xi, yc + xo, drawMode);
|
||
|
|
xLine(xc - xo, xc - xi, yc + y, drawMode);
|
||
|
|
yLine(xc - y, yc + xi, yc + xo, drawMode);
|
||
|
|
xLine(xc - xo, xc - xi, yc - y, drawMode);
|
||
|
|
yLine(xc - y, yc - xo, yc - xi, drawMode);
|
||
|
|
xLine(xc + xi, xc + xo, yc - y, drawMode);
|
||
|
|
yLine(xc + y, yc - xo, yc - xi, drawMode);
|
||
|
|
|
||
|
|
y++;
|
||
|
|
|
||
|
|
if (erro < 0)
|
||
|
|
{
|
||
|
|
erro += 2 * y + 1;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
xo--;
|
||
|
|
erro += 2 * (y - xo + 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (y > rInner)
|
||
|
|
{
|
||
|
|
xi = y;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (erri < 0)
|
||
|
|
{
|
||
|
|
erri += 2 * y + 1;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
xi--;
|
||
|
|
erri += 2 * (y - xi + 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void GL_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
int16_t x = 0;
|
||
|
|
int16_t y = r;
|
||
|
|
int16_t d = 3 - 2 * r;
|
||
|
|
|
||
|
|
while (y >= x)
|
||
|
|
{
|
||
|
|
DrawHLine(x0 - x, y0 + y, x * 2, drawMode);
|
||
|
|
DrawHLine(x0 - x, y0 - y, x * 2, drawMode);
|
||
|
|
DrawHLine(x0 - y, y0 + x, y * 2, drawMode);
|
||
|
|
DrawHLine(x0 - y, y0 - x, y * 2, drawMode);
|
||
|
|
x++;
|
||
|
|
|
||
|
|
if (d > 0)
|
||
|
|
{
|
||
|
|
y--;
|
||
|
|
d = d + 4 * (x - y) + 10;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
d = d + 4 * x + 6;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void GL_DrawEllipse(int16_t x0, int16_t y0, int16_t a, int16_t b,
|
||
|
|
LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
int16_t wx, wy;
|
||
|
|
int32_t xa, ya;
|
||
|
|
int32_t t;
|
||
|
|
int32_t asq = a * a;
|
||
|
|
int32_t bsq = b * b;
|
||
|
|
|
||
|
|
LCD_DrawPixel(x0, y0 + b, drawMode);
|
||
|
|
LCD_DrawPixel(x0, y0 - b, drawMode);
|
||
|
|
|
||
|
|
wx = 0;
|
||
|
|
wy = b;
|
||
|
|
xa = 0;
|
||
|
|
ya = asq * 2 * b;
|
||
|
|
t = asq / 4 - asq * b;
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
{
|
||
|
|
t += xa + bsq;
|
||
|
|
|
||
|
|
if (t >= 0)
|
||
|
|
{
|
||
|
|
ya -= asq * 2;
|
||
|
|
t -= ya;
|
||
|
|
wy--;
|
||
|
|
}
|
||
|
|
|
||
|
|
xa += bsq * 2;
|
||
|
|
wx++;
|
||
|
|
|
||
|
|
if (xa >= ya)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
LCD_DrawPixel(x0 + wx, y0 - wy, drawMode);
|
||
|
|
LCD_DrawPixel(x0 - wx, y0 - wy, drawMode);
|
||
|
|
LCD_DrawPixel(x0 + wx, y0 + wy, drawMode);
|
||
|
|
LCD_DrawPixel(x0 - wx, y0 + wy, drawMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
LCD_DrawPixel(x0 + a, y0, drawMode);
|
||
|
|
LCD_DrawPixel(x0 - a, y0, drawMode);
|
||
|
|
|
||
|
|
wx = a;
|
||
|
|
wy = 0;
|
||
|
|
xa = bsq * 2 * a;
|
||
|
|
|
||
|
|
ya = 0;
|
||
|
|
t = bsq / 4 - bsq * a;
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
{
|
||
|
|
t += ya + asq;
|
||
|
|
|
||
|
|
if (t >= 0)
|
||
|
|
{
|
||
|
|
xa -= bsq * 2;
|
||
|
|
t = t - xa;
|
||
|
|
wx--;
|
||
|
|
}
|
||
|
|
|
||
|
|
ya += asq * 2;
|
||
|
|
wy++;
|
||
|
|
|
||
|
|
if (ya > xa)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
LCD_DrawPixel(x0 + wx, y0 - wy, drawMode);
|
||
|
|
LCD_DrawPixel(x0 - wx, y0 - wy, drawMode);
|
||
|
|
LCD_DrawPixel(x0 + wx, y0 + wy, drawMode);
|
||
|
|
LCD_DrawPixel(x0 - wx, y0 + wy, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void GL_DrawFilledEllipse(int16_t x0, int16_t y0, int16_t a, int16_t b,
|
||
|
|
LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
int16_t wx, wy;
|
||
|
|
int32_t xa, ya;
|
||
|
|
int32_t t;
|
||
|
|
int32_t asq = a * a;
|
||
|
|
int32_t bsq = b * b;
|
||
|
|
|
||
|
|
LCD_DrawPixel(x0, y0 + b, drawMode);
|
||
|
|
LCD_DrawPixel(x0, y0 - b, drawMode);
|
||
|
|
|
||
|
|
wx = 0;
|
||
|
|
wy = b;
|
||
|
|
xa = 0;
|
||
|
|
ya = asq * 2 * b;
|
||
|
|
t = asq / 4 - asq * b;
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
{
|
||
|
|
t += xa + bsq;
|
||
|
|
|
||
|
|
if (t >= 0)
|
||
|
|
{
|
||
|
|
ya -= asq * 2;
|
||
|
|
t -= ya;
|
||
|
|
wy--;
|
||
|
|
}
|
||
|
|
|
||
|
|
xa += bsq * 2;
|
||
|
|
wx++;
|
||
|
|
|
||
|
|
if (xa >= ya)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
DrawHLine(x0 - wx, y0 - wy, wx * 2, drawMode);
|
||
|
|
DrawHLine(x0 - wx, y0 + wy, wx * 2, drawMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
DrawHLine(x0 - a, y0, a * 2, drawMode);
|
||
|
|
|
||
|
|
wx = a;
|
||
|
|
wy = 0;
|
||
|
|
xa = bsq * 2 * a;
|
||
|
|
|
||
|
|
ya = 0;
|
||
|
|
t = bsq / 4 - bsq * a;
|
||
|
|
|
||
|
|
while (1)
|
||
|
|
{
|
||
|
|
t += ya + asq;
|
||
|
|
|
||
|
|
if (t >= 0)
|
||
|
|
{
|
||
|
|
xa -= bsq * 2;
|
||
|
|
t = t - xa;
|
||
|
|
wx--;
|
||
|
|
}
|
||
|
|
|
||
|
|
ya += asq * 2;
|
||
|
|
wy++;
|
||
|
|
|
||
|
|
if (ya > xa)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
DrawHLine(x0 - wx, y0 - wy, wx * 2, drawMode);
|
||
|
|
DrawHLine(x0 - wx, y0 + wy, wx * 2, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void GL_DrawPolygon(int16_t numVertices, int16_t *vertices, int16_t thickness, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
for (int16_t i = 0; i < numVertices - 1; i++)
|
||
|
|
{
|
||
|
|
GL_DrawLine(vertices[(i << 1) + 0], vertices[(i << 1) + 1],
|
||
|
|
vertices[(i << 1) + 2], vertices[(i << 1) + 3], thickness, drawMode);
|
||
|
|
}
|
||
|
|
GL_DrawLine(vertices[0], vertices[1], vertices[(numVertices << 1) - 2],
|
||
|
|
vertices[(numVertices << 1) - 1], thickness, drawMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Adapted from http://alienryderflex.com/polygon_fill/ */
|
||
|
|
void GL_DrawFilledPolygon(int16_t numVertices, int16_t *vertices, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
uint16_t nodes[64];
|
||
|
|
int16_t y;
|
||
|
|
|
||
|
|
float x0;
|
||
|
|
float y0;
|
||
|
|
float x1;
|
||
|
|
float y1;
|
||
|
|
|
||
|
|
int16_t miny = LCD_HEIGHT_PIXELS;
|
||
|
|
int16_t maxy = 0;
|
||
|
|
|
||
|
|
for (uint8_t i = 0; i < numVertices; i++)
|
||
|
|
{
|
||
|
|
if (miny > vertices[(i << 1) + 1])
|
||
|
|
{
|
||
|
|
miny = vertices[(i << 1) + 1];
|
||
|
|
}
|
||
|
|
if (maxy < vertices[(i << 1) + 1])
|
||
|
|
{
|
||
|
|
maxy = vertices[(i << 1) + 1];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Loop through the rows of the image. */
|
||
|
|
for (y = miny; y < maxy; y++)
|
||
|
|
{
|
||
|
|
|
||
|
|
/* Build a list of nodes. */
|
||
|
|
int16_t count = 0;
|
||
|
|
int16_t j = numVertices - 1;
|
||
|
|
|
||
|
|
for (int16_t i = 0; i < numVertices; i++)
|
||
|
|
{
|
||
|
|
x0 = vertices[(i << 1) + 0];
|
||
|
|
y0 = vertices[(i << 1) + 1];
|
||
|
|
x1 = vertices[(j << 1) + 0];
|
||
|
|
y1 = vertices[(j << 1) + 1];
|
||
|
|
|
||
|
|
if ((y0 < (float) y && y1 >= (float) y)
|
||
|
|
|| (y1 < (float) y && y0 >= (float) y))
|
||
|
|
{
|
||
|
|
nodes[count] =
|
||
|
|
(int16_t) (x0 + (y - y0) / (y1 - y0) * (x1 - x0));
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
j = i;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Sort the nodes, via a simple “Bubble” sort. */
|
||
|
|
int16_t i = 0;
|
||
|
|
while (i < count - 1)
|
||
|
|
{
|
||
|
|
if (nodes[i] > nodes[i + 1])
|
||
|
|
{
|
||
|
|
int16_t swap = nodes[i];
|
||
|
|
nodes[i] = nodes[i + 1];
|
||
|
|
nodes[i + 1] = swap;
|
||
|
|
if (i)
|
||
|
|
{
|
||
|
|
i--;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Draw lines between nodes. */
|
||
|
|
for (int16_t i = 0; i < count; i += 2)
|
||
|
|
{
|
||
|
|
int16_t width = nodes[i + 1] - nodes[i];
|
||
|
|
DrawHLine(nodes[i], y, width, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void GL_DrawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t thickness, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
int16_t vertices[6] =
|
||
|
|
{ x0, y0, x1, y1, x2, y2 };
|
||
|
|
GL_DrawPolygon(3, vertices, thickness, drawMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void GL_DrawFilledTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
int16_t vertices[6] =
|
||
|
|
{ x0, y0, x1, y1, x2, y2 };
|
||
|
|
GL_DrawFilledPolygon(3, vertices, drawMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
void GL_DrawRoundedRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t r, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
|
||
|
|
uint16_t width, height;
|
||
|
|
int16_t x, y, d;
|
||
|
|
|
||
|
|
/* Make sure x0 is smaller than x1. */
|
||
|
|
if (x0 > x1)
|
||
|
|
{
|
||
|
|
x0 = x0 + x1;
|
||
|
|
x1 = x0 - x1;
|
||
|
|
x0 = x0 - x1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Make sure y0 is smaller than y1. */
|
||
|
|
if (y0 > y1)
|
||
|
|
{
|
||
|
|
y0 = y0 + y1;
|
||
|
|
y1 = y0 - y1;
|
||
|
|
y0 = y0 - y1;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/* Max radius is half of shortest edge. */
|
||
|
|
width = x1 - x0 + 1;
|
||
|
|
height = y1 - y0 + 1;
|
||
|
|
r = MIN(r, MIN(width / 2, height / 2));
|
||
|
|
|
||
|
|
DrawHLine(x0 + r, y0, width - 2 * r, drawMode);
|
||
|
|
DrawHLine(x0 + r, y1, width - 2 * r, drawMode);
|
||
|
|
DrawVLine(x0, y0 + r, height - 2 * r, drawMode);
|
||
|
|
DrawVLine(x1, y0 + r, height - 2 * r, drawMode);
|
||
|
|
|
||
|
|
x = 0;
|
||
|
|
y = r;
|
||
|
|
d = 3 - 2 * r;
|
||
|
|
|
||
|
|
while (y >= x)
|
||
|
|
{
|
||
|
|
x++;
|
||
|
|
|
||
|
|
if (d > 0)
|
||
|
|
{
|
||
|
|
y--;
|
||
|
|
d = d + 4 * (x - y) + 10;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
d = d + 4 * x + 6;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Top right */
|
||
|
|
LCD_DrawPixel(x1 - r + x, y0 + r - y, drawMode);
|
||
|
|
LCD_DrawPixel(x1 - r + y, y0 + r - x, drawMode);
|
||
|
|
|
||
|
|
/* Top left */
|
||
|
|
LCD_DrawPixel(x0 + r - x, y0 + r - y, drawMode);
|
||
|
|
LCD_DrawPixel(x0 + r - y, y0 + r - x, drawMode);
|
||
|
|
|
||
|
|
/* Bottom right */
|
||
|
|
LCD_DrawPixel(x1 - r + x, y1 - r + y, drawMode);
|
||
|
|
LCD_DrawPixel(x1 - r + y, y1 - r + x, drawMode);
|
||
|
|
|
||
|
|
/* Bottom left */
|
||
|
|
LCD_DrawPixel(x0 + r - x, y1 - r + y, drawMode);
|
||
|
|
LCD_DrawPixel(x0 + r - y, y1 - r + x, drawMode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
;
|
||
|
|
|
||
|
|
void GL_DrawFilledRoundedRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t r, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
|
||
|
|
uint16_t width, height;
|
||
|
|
int16_t rx0, ry0, rx1, x, y, d;
|
||
|
|
|
||
|
|
/* Make sure x0 is smaller than x1. */
|
||
|
|
if (x0 > x1)
|
||
|
|
{
|
||
|
|
x0 = x0 + x1;
|
||
|
|
x1 = x0 - x1;
|
||
|
|
x0 = x0 - x1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Make sure y0 is smaller than y1. */
|
||
|
|
if (y0 > y1)
|
||
|
|
{
|
||
|
|
y0 = y0 + y1;
|
||
|
|
y1 = y0 - y1;
|
||
|
|
y0 = y0 - y1;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/* Max radius is half of shortest edge. */
|
||
|
|
width = x1 - x0 + 1;
|
||
|
|
height = y1 - y0 + 1;
|
||
|
|
r = MIN(r, MIN(width / 2, height / 2));
|
||
|
|
|
||
|
|
x = 0;
|
||
|
|
y = r;
|
||
|
|
d = 3 - 2 * r;
|
||
|
|
|
||
|
|
while (y >= x)
|
||
|
|
{
|
||
|
|
x++;
|
||
|
|
|
||
|
|
if (d > 0)
|
||
|
|
{
|
||
|
|
y--;
|
||
|
|
d = d + 4 * (x - y) + 10;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
d = d + 4 * x + 6;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Top */
|
||
|
|
ry0 = y0 + r - x;
|
||
|
|
rx0 = x0 + r - y;
|
||
|
|
rx1 = x1 - r + y;
|
||
|
|
width = rx1 - rx0;
|
||
|
|
DrawHLine(rx0, ry0, width, drawMode);
|
||
|
|
|
||
|
|
ry0 = y0 + r - y;
|
||
|
|
rx0 = x0 + r - x;
|
||
|
|
rx1 = x1 - r + x;
|
||
|
|
width = rx1 - rx0;
|
||
|
|
DrawHLine(rx0, ry0, width, drawMode);
|
||
|
|
|
||
|
|
/* Bottom */
|
||
|
|
ry0 = y1 - r + y;
|
||
|
|
rx0 = x0 + r - x;
|
||
|
|
rx1 = x1 - r + x;
|
||
|
|
width = rx1 - rx0;
|
||
|
|
DrawHLine(rx0, ry0, width, drawMode);
|
||
|
|
|
||
|
|
ry0 = y1 - r + x;
|
||
|
|
rx0 = x0 + r - y;
|
||
|
|
rx1 = x1 - r + y;
|
||
|
|
width = rx1 - rx0;
|
||
|
|
DrawHLine(rx0, ry0, width, drawMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Center */
|
||
|
|
GL_DrawFilledRectangle(x0, y0 + r, x1, y1 - r, drawMode);
|
||
|
|
}
|
||
|
|
;
|
||
|
|
|
||
|
|
uint16_t GL_GetColorBitmapWidth(const uint16_t *bitmap)
|
||
|
|
{
|
||
|
|
return bitmap[BMP_WIDTH_INDEX];
|
||
|
|
}
|
||
|
|
|
||
|
|
uint16_t GL_GetColorBitmapHeight(const uint16_t *bitmap)
|
||
|
|
{
|
||
|
|
return bitmap[BMP_HEIGHT_INDEX];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Draw a bitmap in RGB565 color at the specified location
|
||
|
|
*
|
||
|
|
* \param *bitmap pointer to bitmap
|
||
|
|
* \param x0 x coordinate of bitmap (top left)
|
||
|
|
* \param y0 y coordinate of bitmap (top left)
|
||
|
|
* \return void
|
||
|
|
*/
|
||
|
|
void GL_DrawColorBitmap(const uint16_t *bitmap, uint16_t x0, uint16_t y0)
|
||
|
|
{
|
||
|
|
uint16_t xSize = bitmap[BMP_WIDTH_INDEX]; //bitmap width in pixels
|
||
|
|
uint16_t ySize = bitmap[BMP_HEIGHT_INDEX]; //bitmap height in pixels
|
||
|
|
bitmap += BMP_DATA_INDEX; //increment the bitmap pointer to the start of bitmap data
|
||
|
|
|
||
|
|
for (uint16_t y = 0; y < ySize; y++)
|
||
|
|
{
|
||
|
|
for (uint16_t x = 0; x < xSize; x++)
|
||
|
|
{
|
||
|
|
LCD_DrawPixel(x + x0, y + y0, bitmap[(y * xSize) + x]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
uint32_t GL_GetMonoBitmapWidth(const uint32_t *bitmap)
|
||
|
|
{
|
||
|
|
return bitmap[BMP_WIDTH_INDEX];
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
uint32_t GL_GetMonoBitmapHeight(const uint32_t *bitmap)
|
||
|
|
{
|
||
|
|
return bitmap[BMP_HEIGHT_INDEX];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Draw mono bitmap in a single RGB565 color at the specified location
|
||
|
|
* "1" pixels are drawn, "0" pixels are not drawn
|
||
|
|
*
|
||
|
|
* Data packed in uint16_t array, 1bpp, MSb first
|
||
|
|
*
|
||
|
|
* \param *bitmap pointer to bitmap
|
||
|
|
* \param x0 x coordinate of bitmap (top left)
|
||
|
|
* \param y0 y coordinate of bitmap (top left)
|
||
|
|
* \return void
|
||
|
|
*/
|
||
|
|
void GL_DrawMonoBitmap(const uint32_t *bitmap, uint16_t x0, uint16_t y0, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
uint32_t xSize = bitmap[BMP_WIDTH_INDEX]; //bitmap width in pixels
|
||
|
|
uint32_t ySize = bitmap[BMP_HEIGHT_INDEX]; //bitmap height in pixels
|
||
|
|
const uint32_t *pData = &bitmap[BMP_DATA_INDEX];//data starts @ bitmap[2]
|
||
|
|
|
||
|
|
uint32_t startingBitMask = 0x80000000; //32-bit data, MDb first
|
||
|
|
|
||
|
|
uint32_t bitMask = startingBitMask;
|
||
|
|
|
||
|
|
for (uint16_t y = 0; y < ySize; y++)
|
||
|
|
{
|
||
|
|
for (uint16_t x = 0; x < xSize; x++)
|
||
|
|
{
|
||
|
|
if (bitMask == 0)
|
||
|
|
{
|
||
|
|
bitMask = startingBitMask;
|
||
|
|
pData++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (*pData & bitMask)
|
||
|
|
{
|
||
|
|
LCD_DrawPixel(x + x0, y + y0, drawMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
bitMask = (bitMask >> 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Draw mono bitmap centered on screen
|
||
|
|
* \param *bitmap pointer to bitmap
|
||
|
|
* \param color color to draw bitmap
|
||
|
|
*/
|
||
|
|
void GL_DrawMonoBitmapCentered(const uint32_t *bitmap, LCD_DRAWMODE_t drawMode)
|
||
|
|
{
|
||
|
|
uint16_t x = LCD_X_MID - GL_GetMonoBitmapWidth(bitmap) / 2;
|
||
|
|
uint16_t y = LCD_Y_MID - GL_GetMonoBitmapHeight(bitmap) / 2;
|
||
|
|
GL_DrawMonoBitmap(bitmap, x, y, drawMode);
|
||
|
|
}
|
||
|
|
|