- Fixed drawing of round objects (Circles, Rounded Rects) using a lookup table
- Added function to read out the display_buffer via USB-Serial - Added basic structure and files for later complete firmware (still in progress) - Added Doc folder with schematic in it - Added Python script and batch file to read out the display buffer and open the image in gimp
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include "Display_Shapes.h"
|
||||
#include "Display_Color.h"
|
||||
#include "Display_Objects.h"
|
||||
#include "Round_Corners_Lookup_Table.h"
|
||||
|
||||
#include "hardware/dma.h"
|
||||
|
||||
@@ -27,8 +28,6 @@
|
||||
|
||||
#define DEG2RAD (float)(M_PI / 180)
|
||||
|
||||
#define RECT_WIDTH_DMA_THRESHOLD 16
|
||||
|
||||
|
||||
// ============================================================================================
|
||||
// Variables
|
||||
@@ -43,6 +42,9 @@ static dma_channel_config _DMA_Config_Drawing;
|
||||
|
||||
// ============================================================================================
|
||||
// Function Declarations
|
||||
void Display_Shapes_Draw_Rounded_Rect_Frame_1 (int16_t x, int16_t y, uint16_t width, uint16_t height, uint16_t radius, Display_Color color);
|
||||
void Display_Shapes_Draw_Circle_Frame_1 (int16_t center_x, int16_t center_y, uint16_t radius, Display_Color color);
|
||||
|
||||
void Display_Shapes_Draw_Circle_Helper(int16_t x0, int16_t y0, uint16_t radius, uint16_t thickness, uint8_t cornername, Display_Color color);
|
||||
void Display_Shapes_Draw_Circle_Helper_Improved(int16_t x0, int16_t y0, uint16_t radius, uint16_t thickness, uint8_t cornername, Display_Color color);
|
||||
void Display_Shapes_Draw_Circle_Helper_Single_Pixel(int16_t x0, int16_t y0, uint16_t radius, uint8_t cornername, Display_Color color);
|
||||
@@ -234,11 +236,21 @@ void Display_Shapes_Draw_Line_Rad(int16_t x, int16_t y, float angle, uint16_t ra
|
||||
|
||||
void Display_Shapes_Draw_Rect_Frame(int16_t x, int16_t y, uint16_t width, uint16_t height, uint16_t thickness, Display_Color color)
|
||||
{
|
||||
Display_Shapes_Draw_HLine(x , y , width , thickness, color);
|
||||
Display_Shapes_Draw_HLine(x , y + height, width + thickness , thickness, color);
|
||||
// The Rectangle Frame stays within the given height and width. Meaning the Border is drawn inside the width an height.
|
||||
// For Example:
|
||||
// If you specify a width = 50 and height = 30 with a thickness = 3, the
|
||||
// inside area will be (50 - 2*3) x (30 - 2*3) = 44x24 pixels
|
||||
|
||||
Display_Shapes_Draw_VLine(x , y , height , thickness, color);
|
||||
Display_Shapes_Draw_VLine(x + width , y , height + thickness, thickness, color);
|
||||
int16_t X_Left = x;
|
||||
int16_t X_Right = x + width - thickness;
|
||||
int16_t Y_Top = y;
|
||||
int16_t Y_Bottom = y + height - thickness;
|
||||
|
||||
Display_Shapes_Draw_HLine(X_Left, Y_Top , width , thickness, color);
|
||||
Display_Shapes_Draw_HLine(X_Left, Y_Bottom , width , thickness, color);
|
||||
|
||||
Display_Shapes_Draw_VLine(X_Left , Y_Top, height, thickness, color);
|
||||
Display_Shapes_Draw_VLine(X_Right , Y_Top, height, thickness, color);
|
||||
}
|
||||
|
||||
void Display_Shapes_Draw_Rect_Filled(int16_t x, int16_t y, uint16_t width, uint16_t height, Display_Color color)
|
||||
@@ -261,143 +273,119 @@ void Display_Shapes_Draw_Rect_Filled(int16_t x, int16_t y, uint16_t width, uint1
|
||||
return;
|
||||
}
|
||||
|
||||
// For wide rectangles, use DMA for each horizontal row (memory-contiguous)
|
||||
if (Clipped_Width >= RECT_WIDTH_DMA_THRESHOLD) // DMA threshold for width
|
||||
// For narrow rectangles, use optimized nested loop
|
||||
for (int16_t row = Start_Y; row < End_Y; row++)
|
||||
{
|
||||
static uint32_t Fill_Value;
|
||||
Fill_Value = (color << 16) | color; // Pack two 16-bit values
|
||||
|
||||
for (int16_t row = Start_Y; row < End_Y; row++) {
|
||||
// Calculate destination address for this row
|
||||
Display_Color* Dst = &(*_Current_Buffer)->Dim_2[row][Start_X];
|
||||
|
||||
// Use DMA for horizontal row fill (contiguous memory)
|
||||
dma_channel_configure(_DMA_Channel_Drawing, &_DMA_Config_Drawing, Dst, &Fill_Value, Clipped_Width / 2, false);
|
||||
dma_channel_start(_DMA_Channel_Drawing);
|
||||
dma_channel_wait_for_finish_blocking(_DMA_Channel_Drawing);
|
||||
|
||||
// Handle odd width
|
||||
if (Clipped_Width & 1) {
|
||||
(*_Current_Buffer)->Dim_2[row][End_X - 1] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For narrow rectangles, use optimized nested loop
|
||||
for (int16_t row = Start_Y; row < End_Y; row++)
|
||||
{
|
||||
// Each row is contiguous in memory - cache friendly
|
||||
Display_Color* Row_Ptr = &(*_Current_Buffer)->Dim_2[row][Start_X];
|
||||
// Each row is contiguous in memory - cache friendly
|
||||
Display_Color* Row_Ptr = &(*_Current_Buffer)->Dim_2[row][Start_X];
|
||||
|
||||
for (int16_t col = 0; col < Clipped_Width; col++)
|
||||
{
|
||||
Row_Ptr[col] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int16_t col = 0; col < Clipped_Width; col++)
|
||||
{
|
||||
Row_Ptr[col] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Display_Shapes_Draw_Circle_Frame(int16_t center_x, int16_t center_y, uint16_t radius, uint16_t thickness, Display_Color color)
|
||||
{
|
||||
if(thickness == 0) {
|
||||
return;
|
||||
}
|
||||
if (thickness == 0 || radius == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t f = 1 - radius;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * radius;
|
||||
int16_t X = 0;
|
||||
int16_t Y = radius;
|
||||
if(thickness == 1) {
|
||||
Display_Shapes_Draw_Circle_Frame_1(center_x, center_y, radius, color);
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t Inner_Radius = radius - thickness;
|
||||
|
||||
|
||||
if(thickness == 1)
|
||||
{
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x , center_y+radius , color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x , center_y-radius , color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x+radius , center_y , color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x-radius , center_y , color);
|
||||
}
|
||||
else
|
||||
{
|
||||
Display_Shapes_Draw_Circle_Filled(center_x , center_y+radius , thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x , center_y-radius , thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x+radius , center_y , thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x-radius , center_y , thickness >> 1, color);
|
||||
}
|
||||
|
||||
while (X<Y)
|
||||
{
|
||||
if (f >= 0)
|
||||
{
|
||||
Y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
X++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
Display_Shapes_Draw_HLine(center_x - radius , center_y - 1, thickness, 2, color);
|
||||
Display_Shapes_Draw_HLine(center_x + radius - thickness , center_y - 1, thickness, 2, color);
|
||||
|
||||
if(thickness == 1)
|
||||
{
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x + X, center_y + Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x - X, center_y + Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x + X, center_y - Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x - X, center_y - Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x + Y, center_y + X, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x - Y, center_y + X, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x + Y, center_y - X, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x - Y, center_y - X, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
Display_Shapes_Draw_Circle_Filled(center_x + X, center_y + Y, thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x - X, center_y + Y, thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x + X, center_y - Y, thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x - X, center_y - Y, thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x + Y, center_y + X, thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x - Y, center_y + X, thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x + Y, center_y - X, thickness >> 1, color);
|
||||
Display_Shapes_Draw_Circle_Filled(center_x - Y, center_y - X, thickness >> 1, color);
|
||||
}
|
||||
}
|
||||
Display_Shapes_Draw_VLine(center_x - 1, center_y - radius , thickness, 2, color);
|
||||
Display_Shapes_Draw_VLine(center_x - 1, center_y + radius - thickness , thickness, 2, color);
|
||||
|
||||
const uint8_t* Outer_Data = _Corner_Lookup_Tables[radius].Data;
|
||||
uint8_t Outer_Size = _Corner_Lookup_Tables[radius].Size;
|
||||
|
||||
const uint8_t* Inner_Data = _Corner_Lookup_Tables[Inner_Radius].Data;
|
||||
uint8_t Inner_Size = _Corner_Lookup_Tables[Inner_Radius].Size;
|
||||
|
||||
// Draw frame using lookup table data
|
||||
for (uint8_t i = 0; i < Outer_Size; i++)
|
||||
{
|
||||
int16_t Outer_X_Offset = Outer_Data[i];
|
||||
int16_t Y_Offset = i;
|
||||
|
||||
uint16_t Line_Width = 0;
|
||||
|
||||
if (i < thickness) {
|
||||
// Full outer circle width for top/bottom thickness rows
|
||||
Line_Width = radius - Outer_X_Offset;
|
||||
} else {
|
||||
// Frame width = outer - inner
|
||||
uint8_t Inner_Index = i - thickness;
|
||||
if (Inner_Index < Inner_Size) {
|
||||
int16_t Inner_X_Offset = Inner_Data[Inner_Index];
|
||||
Line_Width = (radius - Outer_X_Offset) - (Inner_Radius - Inner_X_Offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (Line_Width > 0) {
|
||||
int16_t Top_Y = center_y - radius + Y_Offset - 1;
|
||||
int16_t Bottom_Y = center_y + radius - Y_Offset;
|
||||
|
||||
// Left side of frame
|
||||
int16_t Left_X = center_x - (radius - Outer_X_Offset) - 1;
|
||||
Display_Shapes_Draw_HLine(Left_X, Top_Y, Line_Width, 1, color);
|
||||
|
||||
if (Y_Offset > 0) {
|
||||
Display_Shapes_Draw_HLine(Left_X, Bottom_Y, Line_Width, 1, color);
|
||||
}
|
||||
|
||||
// Right side of frame
|
||||
int16_t Right_X = center_x + (radius - Outer_X_Offset) - Line_Width + 1;
|
||||
Display_Shapes_Draw_HLine(Right_X, Top_Y, Line_Width, 1, color);
|
||||
|
||||
if (Y_Offset > 0) {
|
||||
Display_Shapes_Draw_HLine(Right_X, Bottom_Y, Line_Width, 1, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Display_Shapes_Draw_Circle_Filled(int16_t center_x, int16_t center_y, uint16_t radius, Display_Color color)
|
||||
{
|
||||
Display_Shapes_Draw_VLine(center_x, center_y-radius, 2*radius+1, 1, color);
|
||||
if (radius == 0) {
|
||||
Display_Shapes_Draw_Pixel_Safe(center_x, center_y, color);
|
||||
return;
|
||||
}
|
||||
|
||||
Display_Shapes_Draw_HLine(center_x - radius, center_y - 1, 2*radius, 2, color);
|
||||
|
||||
uint8_t Corner_Name = 3;
|
||||
int16_t Delta = 0;
|
||||
|
||||
int16_t f = 1 - radius;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * radius;
|
||||
int16_t X = 0;
|
||||
int16_t Y = radius;
|
||||
|
||||
while(X<Y)
|
||||
{
|
||||
if(f >= 0)
|
||||
{
|
||||
Y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
X++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
if ((Corner_Name & 0x1) > 0)
|
||||
{
|
||||
Display_Shapes_Draw_VLine(center_x+X, center_y-Y, 2*Y+1+Delta, 1, color);
|
||||
Display_Shapes_Draw_VLine(center_x+Y, center_y-X, 2*X+1+Delta, 1, color);
|
||||
}
|
||||
if ((Corner_Name & 0x2)>0)
|
||||
{
|
||||
Display_Shapes_Draw_VLine(center_x-X, center_y-Y, 2*Y+1+Delta, 1, color);
|
||||
Display_Shapes_Draw_VLine(center_x-Y, center_y-X, 2*X+1+Delta, 1, color);
|
||||
}
|
||||
}
|
||||
const uint8_t* Data = _Corner_Lookup_Tables[radius].Data;
|
||||
uint8_t Size = _Corner_Lookup_Tables[radius].Size;
|
||||
|
||||
// Draw horizontal lines using lookup table data
|
||||
for (uint8_t i = 0; i < Size; i++)
|
||||
{
|
||||
int16_t X_Offset = Data[i];
|
||||
int16_t Y_Offset = i;
|
||||
|
||||
// Calculate line width for this Y position
|
||||
uint16_t Line_Width = 2 * (radius - X_Offset) + 2;
|
||||
|
||||
// Draw upper and lower horizontal lines
|
||||
int16_t Top_Y = center_y - radius + Y_Offset - 0;
|
||||
int16_t Bottom_Y = center_y + radius - Y_Offset;
|
||||
int16_t Start_X = center_x - (radius - X_Offset) - 1;
|
||||
|
||||
Display_Shapes_Draw_HLine(Start_X, Top_Y, Line_Width, 1, color);
|
||||
if (Y_Offset > 0) { // Avoid drawing center line twice
|
||||
Display_Shapes_Draw_HLine(Start_X, Bottom_Y, Line_Width, 1, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Display_Shapes_Draw_Round_Rect_Frame(int16_t x, int16_t y, uint16_t width, uint16_t height, uint16_t radius, uint16_t thickness, Display_Color color)
|
||||
@@ -407,61 +395,110 @@ void Display_Shapes_Draw_Round_Rect_Frame(int16_t x, int16_t y, uint16_t width,
|
||||
return;
|
||||
}
|
||||
|
||||
if(thickness == 1) {
|
||||
Display_Shapes_Draw_Rounded_Rect_Frame_1(x, y, width, height, radius, color);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clamp radius to maximum possible value
|
||||
uint16_t max_radius = ((width < height) ? width : height) / 2;
|
||||
if (radius > max_radius) {
|
||||
radius = max_radius;
|
||||
uint16_t Max_Radius = ((width < height) ? width : height) / 2;
|
||||
if (radius > Max_Radius) {
|
||||
radius = Max_Radius;
|
||||
}
|
||||
|
||||
// For very small rectangles, just draw a filled rectangle
|
||||
if (radius == 0 || width <= 2*radius || height <= 2*radius) {
|
||||
// For no radius, draw a regular Rectangle Frame
|
||||
if (radius == 0) {
|
||||
Display_Shapes_Draw_Rect_Frame(x, y, width, height, thickness, color);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw the straight edges (avoiding corners)
|
||||
// Top edge
|
||||
if (width > 2 * radius) {
|
||||
Display_Shapes_Draw_HLine(x + radius, y, width - 2 * radius, thickness, color);
|
||||
}
|
||||
// Calculate inner rectangle dimensions
|
||||
int16_t Inner_Width = width - 2 * thickness;
|
||||
int16_t Inner_Height = height - 2 * thickness;
|
||||
|
||||
// Bottom edge
|
||||
if (width > 2 * radius) {
|
||||
Display_Shapes_Draw_HLine(x + radius, y + height - thickness, width - 2 * radius, thickness, color);
|
||||
}
|
||||
// Calculate inner radius (ensuring it's valid)
|
||||
uint16_t Inner_Radius = (radius > thickness) ? radius - thickness : 0;
|
||||
uint16_t Outer_Radius = radius;
|
||||
|
||||
const uint8_t* Outer_Data = _Corner_Lookup_Tables[Outer_Radius].Data;
|
||||
uint8_t Outer_Size = _Corner_Lookup_Tables[Outer_Radius].Size;
|
||||
|
||||
const uint8_t* Inner_Data = _Corner_Lookup_Tables[Inner_Radius].Data;
|
||||
uint8_t Inner_Size = _Corner_Lookup_Tables[Inner_Radius].Size;
|
||||
|
||||
// Draw straight edges
|
||||
Display_Shapes_Draw_HLine(x + radius , y , width - 2 * radius, thickness, color);
|
||||
Display_Shapes_Draw_HLine(x + radius , y + height - thickness, width - 2 * radius, thickness, color);
|
||||
Display_Shapes_Draw_VLine(x , y + radius , height - 2 * radius, thickness, color);
|
||||
Display_Shapes_Draw_VLine(x + width - thickness , y + radius , height - 2 * radius, thickness, color);
|
||||
|
||||
// Left edge
|
||||
if (height > 2 * radius) {
|
||||
Display_Shapes_Draw_VLine(x, y + radius, height - 2 * radius, thickness, color);
|
||||
// Draw corner regions
|
||||
for (uint8_t i = 0; i < Outer_Size; i++)
|
||||
{
|
||||
int16_t Outer_X_Offset = Outer_Data[i];
|
||||
|
||||
// Calculate corner positions for outer edge
|
||||
int16_t TL_Outer_X = x + Outer_X_Offset;
|
||||
int16_t TR_Outer_X = x + width - 1 - Outer_X_Offset;
|
||||
int16_t BL_Outer_X = x + Outer_X_Offset;
|
||||
int16_t BR_Outer_X = x + width - 1 - Outer_X_Offset;
|
||||
|
||||
int16_t Top_Y = y + i;
|
||||
int16_t Bottom_Y = y + height - 1 - i;
|
||||
|
||||
uint16_t Line_Width = 0;
|
||||
|
||||
if(i < thickness) {
|
||||
Line_Width = Outer_Radius - Outer_X_Offset;
|
||||
} else {
|
||||
uint8_t Inner_Radius_Index = i - thickness;
|
||||
int16_t Inner_X_Offset = Inner_Data[Inner_Radius_Index];
|
||||
|
||||
Line_Width = (Outer_Radius - Outer_X_Offset) - (Inner_Radius - Inner_X_Offset);
|
||||
}
|
||||
|
||||
Display_Shapes_Draw_HLine(TL_Outer_X, Top_Y , Line_Width, 1, color);
|
||||
Display_Shapes_Draw_HLine(BL_Outer_X, Bottom_Y , Line_Width, 1, color);
|
||||
|
||||
Display_Shapes_Draw_HLine(TR_Outer_X - Line_Width + 1, Top_Y , Line_Width, 1, color);
|
||||
Display_Shapes_Draw_HLine(BR_Outer_X - Line_Width + 1, Bottom_Y , Line_Width, 1, color);
|
||||
}
|
||||
|
||||
// Right edge
|
||||
if (height > 2 * radius) {
|
||||
Display_Shapes_Draw_VLine(x + width - thickness, y + radius, height - 2 * radius, thickness, color);
|
||||
}
|
||||
|
||||
// Draw the four corner arcs with corrected positioning
|
||||
Display_Shapes_Draw_Circle_Helper_Improved(x + radius, y + radius, radius, thickness, CORNER_TOP_LEFT, color); // Top-left corner
|
||||
Display_Shapes_Draw_Circle_Helper_Improved(x + width - radius - 1, y + radius, radius, thickness, CORNER_TOP_RIGHT, color); // Top-right corner
|
||||
Display_Shapes_Draw_Circle_Helper_Improved(x + width - radius - 1, y + height - radius - 1, radius, thickness, CORNER_BOTTOM_RIGHT, color); // Bottom-right corner
|
||||
Display_Shapes_Draw_Circle_Helper_Improved(x + radius, y + height - radius - 1, radius, thickness, CORNER_BOTTOM_LEFT, color); // Bottom-left corner
|
||||
}
|
||||
|
||||
void Display_Shapes_Draw_Round_Rect_Filled(int16_t x, int16_t y, uint16_t width, uint16_t height, uint16_t radius, Display_Color color)
|
||||
{
|
||||
uint16_t Max_Radius = ((width < height) ? width : height) / 2; // 1/2 minor axis
|
||||
uint16_t Max_Radius = ((width < height) ? width : height) / 2;
|
||||
|
||||
if (radius > Max_Radius)
|
||||
{
|
||||
radius = Max_Radius;
|
||||
}
|
||||
if (radius > Max_Radius) {
|
||||
radius = Max_Radius;
|
||||
}
|
||||
|
||||
// Smarter Version
|
||||
Display_Shapes_Draw_Rect_Filled(x + radius, y, width - 2 * radius, height, color);
|
||||
// Draw the main body rectangle (excluding corner regions)
|
||||
if (height > 2 * radius) {
|
||||
Display_Shapes_Draw_Rect_Filled(x, y + radius, width, height - 2 * radius, color);
|
||||
}
|
||||
|
||||
// Draw Four Corners
|
||||
Display_Shapes_Draw_Circle_Helper_Filled(x + width - radius - 1 , y + radius, radius, 1, height - 2 * radius - 1, color);
|
||||
Display_Shapes_Draw_Circle_Helper_Filled(x + radius , y + radius, radius, 2, height - 2 * radius - 1, color);
|
||||
const uint8_t* Data = _Corner_Lookup_Tables[radius].Data;
|
||||
uint8_t Size = _Corner_Lookup_Tables[radius].Size;
|
||||
|
||||
// Draw corner regions using lookup table
|
||||
for (uint8_t i = 0; i < Size; i++)
|
||||
{
|
||||
int16_t X_Offset = Data[i];
|
||||
|
||||
// Calculate Y positions for top and bottom
|
||||
int16_t Top_Y = y + i;
|
||||
int16_t Bottom_Y = y + height - 1 - i;
|
||||
|
||||
// Calculate line width for this Y position
|
||||
uint16_t Line_Width = width - 2 * X_Offset;
|
||||
|
||||
// Draw Top Corners
|
||||
Display_Shapes_Draw_HLine(x + X_Offset, Top_Y, Line_Width, 1, color);
|
||||
|
||||
// Draw Bottom Corners
|
||||
Display_Shapes_Draw_HLine(x + X_Offset, Bottom_Y, Line_Width, 1, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Display_Shapes_Draw_Arc_Frame(int16_t center_x, int16_t center_y, int16_t radius, uint16_t thickness, float angle_start, float angle_end, uint16_t steps, Display_Color color)
|
||||
@@ -574,6 +611,119 @@ Coordinates Display_Shapes_Polar_To_XY(int16_t origin_x, int16_t origin_y, float
|
||||
/*******************************************************************
|
||||
Internal Functions
|
||||
*******************************************************************/
|
||||
void Display_Shapes_Draw_Rounded_Rect_Frame_1(int16_t x, int16_t y, uint16_t width, uint16_t height, uint16_t radius, Display_Color color)
|
||||
{
|
||||
// Validate input parameters
|
||||
if (width < 2 || height < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clamp radius to maximum possible value
|
||||
uint16_t Max_Radius = ((width < height) ? width : height) / 2;
|
||||
if (radius > Max_Radius) {
|
||||
radius = Max_Radius;
|
||||
}
|
||||
|
||||
// For no radius, draw a regular Rectangle Frame
|
||||
if (radius == 0) {
|
||||
Display_Shapes_Draw_Rect_Frame(x, y, width, height, 1, color);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw straight edges
|
||||
Display_Shapes_Draw_HLine(x + radius , y , width - 2 * radius, 1, color);
|
||||
Display_Shapes_Draw_HLine(x + radius , y + height - 1, width - 2 * radius, 1, color);
|
||||
Display_Shapes_Draw_VLine(x , y + radius , height - 2 * radius, 1, color);
|
||||
Display_Shapes_Draw_VLine(x + width - 1 , y + radius , height - 2 * radius, 1, color);
|
||||
|
||||
const uint8_t* Data = _Corner_Lookup_Tables[radius].Data;
|
||||
uint8_t Size = _Corner_Lookup_Tables[radius].Size;
|
||||
|
||||
int16_t Last_X = Data[0];
|
||||
|
||||
// Draw corners with gap filling
|
||||
for (uint8_t i = 0; i <Size; i++)
|
||||
{
|
||||
int16_t Current_X = Data[i];
|
||||
int16_t X_Step = Last_X - Current_X;
|
||||
|
||||
// Calculate positions for all four corners
|
||||
int16_t TL_X = x + Current_X;
|
||||
int16_t TL_Y = y + i;
|
||||
|
||||
int16_t TR_X = x + width - 1 - Current_X;
|
||||
int16_t TR_Y = y + i;
|
||||
|
||||
int16_t BL_X = x + Current_X;
|
||||
int16_t BL_Y = y + height - 1 - i;
|
||||
|
||||
int16_t BR_X = x + width - 1 - Current_X;
|
||||
int16_t BR_Y = y + height - 1 - i;
|
||||
|
||||
if(X_Step > 1) {
|
||||
Display_Shapes_Draw_HLine(TL_X, TL_Y, X_Step, 1, color);
|
||||
Display_Shapes_Draw_HLine(BL_X, BL_Y, X_Step, 1, color);
|
||||
Display_Shapes_Draw_HLine(TR_X - X_Step + 1, TR_Y, X_Step, 1, color);
|
||||
Display_Shapes_Draw_HLine(BR_X - X_Step + 1, BR_Y, X_Step, 1, color);
|
||||
}
|
||||
else {
|
||||
Display_Shapes_Draw_Pixel_Safe(TL_X, TL_Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(BL_X, BL_Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(TR_X, TR_Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(BR_X, BR_Y, color);
|
||||
}
|
||||
|
||||
Last_X = Data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Display_Shapes_Draw_Circle_Frame_1(int16_t center_x, int16_t center_y, uint16_t radius, Display_Color color)
|
||||
{
|
||||
if(radius == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t* Data = _Corner_Lookup_Tables[radius].Data;
|
||||
uint8_t Size = _Corner_Lookup_Tables[radius].Size;
|
||||
|
||||
int16_t Last_X = Data[0];
|
||||
|
||||
// Draw corners with gap filling
|
||||
for (uint8_t i = 0; i <Size; i++)
|
||||
{
|
||||
int16_t Current_X = Data[i];
|
||||
int16_t X_Step = Last_X - Current_X;
|
||||
|
||||
// Calculate positions for all four corners
|
||||
int16_t TL_X = center_x - radius + Current_X - 1;
|
||||
int16_t TL_Y = center_y - radius + i;
|
||||
|
||||
int16_t TR_X = center_x + radius - Current_X;
|
||||
int16_t TR_Y = TL_Y;
|
||||
|
||||
int16_t BL_X = TL_X;
|
||||
int16_t BL_Y = center_y + radius - i - 1;
|
||||
|
||||
int16_t BR_X = TR_X;
|
||||
int16_t BR_Y = BL_Y;
|
||||
|
||||
if(X_Step > 1) {
|
||||
Display_Shapes_Draw_HLine(TL_X, TL_Y, X_Step, 1, color);
|
||||
Display_Shapes_Draw_HLine(BL_X, BL_Y, X_Step, 1, color);
|
||||
Display_Shapes_Draw_HLine(TR_X - X_Step + 1, TR_Y, X_Step, 1, color);
|
||||
Display_Shapes_Draw_HLine(BR_X - X_Step + 1, BR_Y, X_Step, 1, color);
|
||||
}
|
||||
else {
|
||||
Display_Shapes_Draw_Pixel_Safe(TL_X, TL_Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(BL_X, BL_Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(TR_X, TR_Y, color);
|
||||
Display_Shapes_Draw_Pixel_Safe(BR_X, BR_Y, color);
|
||||
}
|
||||
|
||||
Last_X = Data[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Quarter-circle drawer, used to do circles and roundrects
|
||||
|
||||
Reference in New Issue
Block a user