NppClone/src/circle.cpp

147 lines
3.5 KiB
C++

#include <azur/gint/render.h>
uint8_t AZRP_SHADER_CIRCLE = -1;
static void azrp_shader_circle_configure(void)
{
azrp_set_uniforms(AZRP_SHADER_CIRCLE, (void *)azrp_width);
}
__attribute__((constructor))
static void register_shader(void)
{
extern azrp_shader_t azrp_shader_circle;
AZRP_SHADER_CIRCLE = azrp_register_shader(azrp_shader_circle, azrp_shader_circle_configure);
}
static int min(int x, int y)
{
return (x < y) ? x : y;
}
static int max(int x, int y)
{
return (x > y) ? x : y;
}
//---
#define TABLE_WIDTH 256
struct command {
uint8_t shader_id;
uint16_t color;
uint8_t curr_frag;
uint16_t NbPixels[14]; // Nunmber of pixels in each fragment
uint16_t DataPixelsX[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width
uint16_t DataPixelsY[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width
};
void AddPixelCircle( int16_t xp, int16_t yp, struct command *cmd )
{
if (xp >= 0 && xp < azrp_width && yp >= 0 && yp < azrp_height)
{
uint8_t cfrag = yp / azrp_frag_height;
uint16_t nbpixinfrag = cmd->NbPixels[ cfrag ];
uint16_t index = cfrag * TABLE_WIDTH + nbpixinfrag;
cmd->DataPixelsX[ index ] = xp;
cmd->DataPixelsY[ index ] = yp & 15;
cmd->NbPixels[ cfrag ]++;
}
}
void azrp_circle(int xc, int yc, uint16_t rad, uint16_t color)
{
prof_enter(azrp_perf_cmdgen);
int xmin = xc - rad;
int xmax = xc + rad;
int ymin = yc - rad;
int ymax = yc + rad;
// The circle is fully outside the screen
if ((xmax < 0) || (xmin >= azrp_width) || (ymax < 0) || (ymin >= azrp_height))
{
prof_leave(azrp_perf_cmdgen);
return;
}
int ytop = max( ymin, 0 );
int ybot = min( ymax, azrp_height-1 );
int frag_first = ytop / azrp_frag_height;
int frag_last = ybot / azrp_frag_height;
int frag_count = frag_last - frag_first + 1;
struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count);
if(!cmd) {
prof_leave(azrp_perf_cmdgen);
return;
}
cmd->shader_id = AZRP_SHADER_CIRCLE;
cmd->color = color;
cmd->curr_frag = frag_first;
// reset the point counters in each cell of the table
for( int i = 0; i < 14; i++ )
cmd->NbPixels[i]=0;
int x = 0;
int y = rad;
int m = 5 - 4*rad;
while (x <= y)
{
AddPixelCircle( xc+x, yc+y, cmd );
AddPixelCircle( xc+y, yc+x, cmd );
AddPixelCircle( xc-x, yc+y, cmd );
AddPixelCircle( xc-y, yc+x, cmd );
AddPixelCircle( xc+x, yc-y, cmd );
AddPixelCircle( xc+y, yc-x, cmd );
AddPixelCircle( xc-x, yc-y, cmd );
AddPixelCircle( xc-y, yc-x, cmd );
if (m > 0)
{
y--;
m -= 8*y;
}
x++;
m += 8*x + 4;
}
prof_leave(azrp_perf_cmdgen);
}
void azrp_shader_circle( void *uniforms, void *comnd, void *fragment )
{
struct command *cmd = (struct command *) comnd;
uint16_t *frag = (uint16_t *) fragment;
uint16_t *taille = (uint16_t *) cmd->NbPixels;
uint16_t *DX = (uint16_t *) cmd->DataPixelsX;
uint16_t *DY = (uint16_t *) cmd->DataPixelsY;
uint16_t nbpix = taille[ cmd->curr_frag ];
int BaseAdress = cmd->curr_frag * TABLE_WIDTH;
for( int i = 0; i < nbpix; i++ )
{
uint16_t X = DX[ BaseAdress + i ];
uint16_t Y = DY[ BaseAdress + i ];
frag[ azrp_width * Y + X ] = cmd->color;
}
cmd->curr_frag++;
}