/*
 * Display_Shapes.c
 *
 * Created: Mon Jul 19 2021 17:57:03
 *  Author Chris
 */
#include "Display_Shapes.h"
#include "Display_Color.h"
#include "Display_Objects.h"
#include "Round_Corners_Lookup_Table.h"

#include "hardware/dma.h"

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>


// ============================================================================================
// Defines
#define CORNER_TOP_LEFT             0x01
#define CORNER_TOP_RIGHT            0x02  
#define CORNER_BOTTOM_RIGHT         0x04  // Fixed: was incorrectly 0x08
#define CORNER_BOTTOM_LEFT          0x08  // Fixed: was incorrectly 0x04

#define DEG2RAD						(float)(M_PI / 180)


// ============================================================================================
// Variables
static Display_Image_Buffer**   _Current_Buffer;

static int 						_DMA_Channel_Fill_Screen;
static dma_channel_config 		_DMA_Config_Fill_Screen;

static int 						_DMA_Channel_Drawing;
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);
void Display_Shapes_Draw_Circle_Helper_Filled(int16_t x0, int16_t y0, uint16_t radius, uint8_t corners, int16_t delta, Display_Color color);


/*******************************************************************
	Functions
*******************************************************************/
void Display_Shapes_Init(Display_Image_Buffer** current_buffer)
{
	_Current_Buffer = current_buffer;
	
	_DMA_Channel_Fill_Screen = dma_claim_unused_channel(true);
	_DMA_Config_Fill_Screen = dma_channel_get_default_config(_DMA_Channel_Fill_Screen);
    channel_config_set_transfer_data_size(&_DMA_Config_Fill_Screen, DMA_SIZE_32);
    channel_config_set_read_increment(&_DMA_Config_Fill_Screen, false);
    channel_config_set_write_increment(&_DMA_Config_Fill_Screen, true);


	_DMA_Channel_Drawing = dma_claim_unused_channel(true);
	_DMA_Config_Drawing = dma_channel_get_default_config(_DMA_Channel_Drawing);
    channel_config_set_transfer_data_size(&_DMA_Config_Drawing, DMA_SIZE_32);
    channel_config_set_read_increment(&_DMA_Config_Drawing, false);
    channel_config_set_write_increment(&_DMA_Config_Drawing, true);
}

void Display_Shapes_Fill_Screen(Display_Color color)
{
	static uint32_t Clear_Value;
    Clear_Value = (color << 16) | color; // Duplicate 16-bit value
    
    dma_channel_configure(_DMA_Channel_Fill_Screen, &_DMA_Config_Fill_Screen, (*_Current_Buffer)->Dim_1, &Clear_Value, DISPLAY_IMAGE_BUFFER_PIXEL_SIZE/2, false); // Half the transfers
    dma_channel_start(_DMA_Channel_Fill_Screen);
    dma_channel_wait_for_finish_blocking(_DMA_Channel_Fill_Screen);
}

void Display_Shapes_Draw_Pixel_Safe(int16_t x, int16_t y, Display_Color color)
{
	if(x >= 0 && x < DISPLAY_WIDTH && y >= 0 && y < DISPLAY_HEIGHT)
	{
		(*_Current_Buffer)->Dim_2[y][x] = color;
	}
}

void Display_Shapes_Draw_HLine(int16_t x, int16_t y, uint16_t width, uint16_t thickness, Display_Color color)
{
	Display_Shapes_Draw_Rect_Filled(x, y, width, thickness, color);
}

void Display_Shapes_Draw_VLine(int16_t x, int16_t y, uint16_t height, uint16_t thickness, Display_Color color)
{
	Display_Shapes_Draw_Rect_Filled(x, y, thickness, height, color);
}

void Display_Shapes_Draw_Line_XY(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t thickness, Display_Color color)
{
	int16_t Temp;
	
	if(y0 == y1)
	{
		if(x1 > x0)
		{
			Display_Shapes_Draw_HLine(x0, y0, x1 - x0 + 1, thickness, color);
		}
		else if (x1 < x0)
		{
			Display_Shapes_Draw_HLine(x1, y0, x0 - x1 + 1, thickness, color);
		}
		else
		{
			Display_Shapes_Draw_Circle_Filled(x0, y0, thickness, color);
		}
		return;
	}
	else if(x0 == x1)
	{
		if(y1 > y0)
		{
			Display_Shapes_Draw_VLine(x0, y0, y1 - y0 + 1, thickness, color);
		}
		else
		{
			Display_Shapes_Draw_VLine(x0, y1, y0 - y1 + 1, thickness, color);
		}
		return;
	}

	bool Steep = abs(y1 - y0) > abs(x1 - x0);
	if(Steep == true)
	{
		Temp = x0; x0 = y0; y0 = Temp;
		Temp = x1; x1 = y1; y1 = Temp;
	}
	if(x0 > x1)
	{
		Temp = x0; x0 = x1; x1 = Temp;
		Temp = y0; y0 = y1; y1 = Temp;
	}

	int16_t dx, dy;
	dx = x1 - x0;
	dy = abs(y1 - y0);

	int16_t err = dx / 2;
	int16_t ystep;

	if (y0 < y1)
	{
		ystep = 1;
	}
	else 
	{
		ystep = -1;
	}

	int16_t xbegin = x0;
	if(Steep == true)
	{
		for (; x0<=x1; x0++)
		{
			err -= dy;
			if (err < 0)
			{
				int16_t len = x0 - xbegin;
				if (len>1)
				{
					Display_Shapes_Draw_VLine(y0, xbegin, len + 1, thickness, color);
				}
				else
				{
					if(thickness == 1)
						Display_Shapes_Draw_Pixel_Safe(y0, x0, color);
					else
						Display_Shapes_Draw_Circle_Filled(y0, x0, thickness >> 1, color);
				}
				xbegin = x0 + 1;
				y0 += ystep;
				err += dx;
			}
		}
		if (x0 > xbegin + 1)
		{
			Display_Shapes_Draw_VLine(y0, xbegin, x0 - xbegin, thickness, color);
		}

	}
	else
	{
		for (; x0<=x1; x0++)
		{
			err -= dy;
			if (err < 0)
			{
				int16_t len = x0 - xbegin;
				if (len>1)
				{
					Display_Shapes_Draw_HLine(xbegin, y0, len + 1, thickness, color);
				}
				else
				{
					if(thickness == 1)
						Display_Shapes_Draw_Pixel_Safe(x0, y0, color);
					else
						Display_Shapes_Draw_Circle_Filled(x0, y0, thickness >> 1, color);
				}
				xbegin = x0 + 1;
				y0 += ystep;
				err += dx;
			}
		}
		if (x0 > xbegin + 1)
		{
			Display_Shapes_Draw_HLine(xbegin, y0, x0 - xbegin, thickness, color);
		}
	}
}

void Display_Shapes_Draw_Line_Rad(int16_t x, int16_t y, float angle, uint16_t radius_start, uint16_t radius_end, uint16_t thickness, Display_Color color)
{
	int16_t X0 = x + cos(angle * DEG2RAD) * radius_start;
	int16_t Y0 = y + sin(angle * DEG2RAD) * radius_start;

	int16_t X1 = x + cos(angle * DEG2RAD) * radius_end;
	int16_t Y1 = y + sin(angle * DEG2RAD) * radius_end;

	Display_Shapes_Draw_Line_XY(X0, Y0, X1, Y1, thickness, color);
}

void Display_Shapes_Draw_Rect_Frame(int16_t x, int16_t y, uint16_t width, uint16_t height, uint16_t thickness, Display_Color 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

	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)
{
	// Early bounds checking
    if (x >= DISPLAY_WIDTH || y >= DISPLAY_HEIGHT || x + width <= 0 || y + height <= 0) {
        return;
    }
	
	// Clip to screen bounds
    int16_t Start_X = (x < 0) ? 0 : x;
    int16_t Start_Y = (y < 0) ? 0 : y;
    int16_t End_X = (x + width > DISPLAY_WIDTH) ? DISPLAY_WIDTH : x + width;
    int16_t End_Y = (y + height > DISPLAY_HEIGHT) ? DISPLAY_HEIGHT : y + height;

	uint16_t Clipped_Width = End_X - Start_X;
    uint16_t Clipped_Height = End_Y - Start_Y;
    
    if (Clipped_Width == 0 || Clipped_Height == 0) {
        return;
    }

	// 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];

		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 || radius == 0) {
        return;
    }
	
    if(thickness == 1) {
        Display_Shapes_Draw_Circle_Frame_1(center_x, center_y, radius, color);
        return;
    }
    
    uint16_t Inner_Radius = radius - thickness;
    

    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);

    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)
{
	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);

    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)
{
    // Validate input parameters
    if (width < 2 || height < 2 || thickness == 0) {
        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;
    }
    
    // For no radius, draw a regular Rectangle Frame
    if (radius == 0) {
        Display_Shapes_Draw_Rect_Frame(x, y, width, height, thickness, color);
        return;
    }
    
    // Calculate inner rectangle dimensions
    int16_t Inner_Width = width - 2 * thickness;
    int16_t Inner_Height = height - 2 * thickness;
    
    // 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);
    
    // 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);
    }
}

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;

    if (radius > Max_Radius) {
        radius = Max_Radius;
    }

    // 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);
    }

    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)
{
	if (thickness == 0 || radius == 0) {
        return;
    }
	
	// Normalize angles to 0-360 range
    while (angle_start 	< 	0.0f) 	angle_start += 360.0f;
    while (angle_start 	>= 	360.0f) angle_start -= 360.0f;
    while (angle_end 	< 	0.0f) 	angle_end += 360.0f;
    while (angle_end 	>= 	360.0f) angle_end -= 360.0f;
    
    // Handle case where arc crosses 0° boundary
	while(angle_end < angle_start) {
		angle_end += 360;
	}
	
	if(steps == ARC_FRAME_AUTO_STEPS)
	{
		float Arc_Length = angle_end - angle_start;
    	steps = (uint16_t)(Arc_Length * 2.0f); 	// 2 Steps per Degree

		// Minimum steps for small arcs
		if (steps < 8) {
			steps = 8;
		}
	}			

	float Angle_Step = (float)(angle_end - angle_start) / (float)steps;
	 
    for (float i = angle_start; i <= angle_end; i = i + Angle_Step)
    {
	
		if(thickness == 1) {
            Display_Shapes_Draw_Pixel_Safe(center_x + cos(i*DEG2RAD) * radius, center_y + sin(i*DEG2RAD) * radius, color);
        }
        else {
			Display_Shapes_Draw_Circle_Filled(center_x + cos(i*DEG2RAD) * radius, center_y + sin(i*DEG2RAD) * radius, thickness >> 1, color);
		}
    }
}

void Display_Shapes_Draw_Glow_Circle(int16_t center_x, int16_t center_y, uint16_t radius, Display_Color core_color, Display_Color glow_color)
{
    // Draw a circle with a subtle glow effect
    // Core circle with gradually fading outer ring
    
    if (radius == 0) {
        return;
    }
    
    // Define glow parameters
    uint16_t Glow_Radius = radius + 4; // Glow extends 4 pixels beyond core
    uint16_t Core_Radius = radius;
    
    // Draw glow layers from outside to inside for proper alpha blending effect
    for (uint16_t Layer = Glow_Radius; Layer > Core_Radius; Layer--) {
        // Calculate glow intensity based on distance from core
        float Distance_From_Core = (float)(Layer - Core_Radius);
        float Max_Glow_Distance = (float)(Glow_Radius - Core_Radius);
        float Glow_Intensity = 1.0f - (Distance_From_Core / Max_Glow_Distance);
        
        // Apply easing curve for more natural glow falloff
        Glow_Intensity = Glow_Intensity * Glow_Intensity; // Quadratic falloff
        
        // Blend glow color with background (assuming dark background)
        Display_Color Layer_Color = Display_Color_Interpolate_Float(
            Display_Objects_Background_Color_Get(), 
            glow_color, 
            Glow_Intensity * 0.3f // Max 30% glow intensity
        );
        
        // Draw this glow layer as a thin circle frame
        Display_Shapes_Draw_Circle_Frame(center_x, center_y, Layer, 1, Layer_Color);
    }
    
    // Draw the solid core circle
    Display_Shapes_Draw_Circle_Filled(center_x, center_y, Core_Radius, core_color);
    
    // Add a subtle highlight for 3D effect (optional)
    if (Core_Radius > 3) {
        // Small highlight offset towards top-left
        int16_t Highlight_X = center_x - (Core_Radius / 3);
        int16_t Highlight_Y = center_y - (Core_Radius / 3);
        uint16_t Highlight_Radius = Core_Radius / 3;
        
        Display_Color Highlight_Color = Display_Color_Interpolate_Float(
            core_color, 
            DISPLAY_COLOR_WHITE, 
            0.4f // 40% white blend for highlight
        );
        
        Display_Shapes_Draw_Circle_Filled(Highlight_X, Highlight_Y, Highlight_Radius, Highlight_Color);
    }
}

Coordinates Display_Shapes_Polar_To_XY(int16_t origin_x, int16_t origin_y, float angle, uint16_t radius)
{
	Coordinates Return_Value = { .X = origin_x, .Y = origin_y };

	Return_Value.X += cos(angle * DEG2RAD) * radius;
	Return_Value.Y += sin(angle * DEG2RAD) * radius;

	return Return_Value;
}


/*******************************************************************
	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
    @param    x0   Center-point x coordinate
    @param    y0   Center-point y coordinate
    @param    r   Radius of circle
    @param    cornername  Mask bit #1 or bit #2 to indicate which quarters of the circle we're doing
    @param    color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void Display_Shapes_Draw_Circle_Helper(int16_t x0, int16_t y0, uint16_t radius, uint16_t thickness, uint8_t cornername, Display_Color 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;

	while (x < y)
	{
		if (f >= 0)
		{
			y--;
			ddF_y += 2;
			f += ddF_y;
		}
		x++;
		ddF_x += 2;
		f += ddF_x;
		
		if (cornername & CORNER_BOTTOM_RIGHT)
		{
			Display_Shapes_Draw_Circle_Filled(x0 + x, y0 + y, thickness >> 1, color);
			Display_Shapes_Draw_Circle_Filled(x0 + y, y0 + x, thickness >> 1, color);
		}

		if (cornername & CORNER_TOP_RIGHT)
		{
			Display_Shapes_Draw_Circle_Filled(x0 + x, y0 - y, thickness >> 1, color);
			Display_Shapes_Draw_Circle_Filled(x0 + y, y0 - x, thickness >> 1, color);
		}

		if (cornername & CORNER_BOTTOM_LEFT)
		{
			Display_Shapes_Draw_Circle_Filled(x0 - x, y0 + y, thickness >> 1, color);
			Display_Shapes_Draw_Circle_Filled(x0 - y, y0 + x, thickness >> 1, color);
		}

		if (cornername & CORNER_TOP_LEFT)
		{
			Display_Shapes_Draw_Circle_Filled(x0 - x, y0 - y, thickness >> 1, color);
			Display_Shapes_Draw_Circle_Filled(x0 - y, y0 - x, thickness >> 1, 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)
{
    if (radius == 0) return;
    
    // For thickness of 1, use single pixel drawing
    if (thickness == 1) {
        Display_Shapes_Draw_Circle_Helper_Single_Pixel(x0, y0, radius, cornername, color);
        return;
    }
    
    // For thicker lines, draw multiple concentric quarter-circles
    // This ensures consistent thickness with the straight edges
    for (uint16_t t = 0; t < thickness; t++) {
        uint16_t current_radius = radius - t;
        if (current_radius == 0) break;
        
        Display_Shapes_Draw_Circle_Helper_Single_Pixel(x0, y0, current_radius, cornername, color);
    }
}

void Display_Shapes_Draw_Circle_Helper_Single_Pixel(int16_t x0, int16_t y0, uint16_t radius, uint8_t cornername, Display_Color color)
{
    if (radius == 0) return;
    
    // Use Bresenham's circle algorithm for single pixel drawing
    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;
        
        // Draw quarter-circle segments based on corner mask - single pixels only
        if (cornername & CORNER_TOP_LEFT) {
            Display_Shapes_Draw_Pixel_Safe(x0 - x, y0 - y, color);
            Display_Shapes_Draw_Pixel_Safe(x0 - y, y0 - x, color);
        }
        
        if (cornername & CORNER_TOP_RIGHT) {
            Display_Shapes_Draw_Pixel_Safe(0 + x, y0 - y, color);
            Display_Shapes_Draw_Pixel_Safe(x0 + y, y0 - x, color);
        }
        
        if (cornername & CORNER_BOTTOM_RIGHT) {
            Display_Shapes_Draw_Pixel_Safe(x0 + x, y0 + y, color);
            Display_Shapes_Draw_Pixel_Safe(x0 + y, y0 + x, color);
        }
        
        if (cornername & CORNER_BOTTOM_LEFT) {
            Display_Shapes_Draw_Pixel_Safe(x0 - x, y0 + y, color);
            Display_Shapes_Draw_Pixel_Safe(x0 - y, y0 + x, color);
        }
    }
}

/**************************************************************************/
/*!
    @brief  Quarter-circle drawer with fill, used for circles and roundrects
    @param  x0       Center-point x coordinate
    @param  y0       Center-point y coordinate
    @param  r        Radius of circle
    @param  corners  Mask bits indicating which quarters we're doing
    @param  delta    Offset from center-point, used for round-rects
    @param  color    16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void Display_Shapes_Draw_Circle_Helper_Filled(int16_t x0, int16_t y0, uint16_t radius, uint8_t corners, int16_t delta, Display_Color 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 px 		= x;
	int16_t py 		= y;

	delta++; // Avoid some +1's in the loop

	while (x < y)
	{
		if (f >= 0)
		{
			y--;
			ddF_y += 2;
			f += ddF_y;
		}
		x++;
		ddF_x += 2;
		f += ddF_x;

		// These checks avoid double-drawing certain lines, important
		// for the SSD1306 library which has an INVERT drawing mode.
		if (x < (y + 1))
		{
			if (corners & CORNER_TOP_LEFT) {
				Display_Shapes_Draw_VLine(x0 + x, y0 - y, 2 * y + delta, 1, color);
				// writeFastVLine(x0 + x, y0 - y, 2 * y + delta, color);
			}
			if (corners & CORNER_TOP_RIGHT) {
				Display_Shapes_Draw_VLine(x0 - x, y0 - y, 2 * y + delta, 1, color);
				// writeFastVLine(x0 - x, y0 - y, 2 * y + delta, color);
			}
		}

		if (y != py)
		{
			if (corners & CORNER_TOP_LEFT) {
				Display_Shapes_Draw_VLine(x0 + py, y0 - px, 2 * px + delta, 1, color);
				// writeFastVLine(x0 + py, y0 - px, 2 * px + delta, color);
			}
			if (corners & CORNER_TOP_RIGHT) {
				Display_Shapes_Draw_VLine(x0 - py, y0 - px, 2 * px + delta, 1, color);
				// writeFastVLine(x0 - py, y0 - px, 2 * px + delta, color);
			}
			py = y;
		}
		px = x;
	}
}