Add anti-aliased line drawer (slow, but effective)
This commit is contained in:
parent
85db6525a8
commit
06a7ca8cd9
@ -20,6 +20,7 @@
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include <sched.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <toaru/yutani.h>
|
||||
#include <toaru/graphics.h>
|
||||
@ -30,11 +31,16 @@ static yutani_t * yctx;
|
||||
static yutani_window_t * wina;
|
||||
static gfx_context_t * ctx;
|
||||
static int should_exit = 0;
|
||||
static int thick = 0;
|
||||
|
||||
void * draw_thread(void * garbage) {
|
||||
(void)garbage;
|
||||
while (!should_exit) {
|
||||
draw_line(ctx, rand() % width, rand() % width, rand() % height, rand() % height, rgb(rand() % 255,rand() % 255,rand() % 255));
|
||||
if (thick) {
|
||||
draw_line_aa(ctx, rand() % width, rand() % width, rand() % height, rand() % height, rgb(rand() % 255,rand() % 255,rand() % 255), (float)thick);
|
||||
} else {
|
||||
draw_line(ctx, rand() % width, rand() % width, rand() % height, rand() % height, rgb(rand() % 255,rand() % 255,rand() % 255));
|
||||
}
|
||||
yutani_flip(yctx, wina);
|
||||
usleep(16666);
|
||||
}
|
||||
@ -42,6 +48,18 @@ void * draw_thread(void * garbage) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void show_usage(char * argv[]) {
|
||||
printf(
|
||||
"drawlines - graphical demo, draws lines randomly\n"
|
||||
"\n"
|
||||
"usage: %s [-t thickness]\n"
|
||||
"\n"
|
||||
" -t \033[3mdraw with anti-aliasing and the specified thickness\033[0m\n"
|
||||
" -? \033[3mshow this help text\033[0m\n"
|
||||
"\n", argv[0]);
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char ** argv) {
|
||||
left = 100;
|
||||
top = 100;
|
||||
@ -50,6 +68,18 @@ int main (int argc, char ** argv) {
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
int c;
|
||||
while ((c = getopt(argc, argv, "t:?")) != -1) {
|
||||
switch (c) {
|
||||
case 't':
|
||||
thick = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
show_usage(argv);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
yctx = yutani_init();
|
||||
if (!yctx) {
|
||||
fprintf(stderr, "%s: failed to connect to compositor\n", argv[0]);
|
||||
|
@ -93,3 +93,16 @@ extern uint32_t getBilinearFilteredPixelColor(sprite_t * tex, double u, double v
|
||||
extern uint32_t interp_colors(uint32_t bottom, uint32_t top, uint8_t interp);
|
||||
extern void draw_rounded_rectangle(gfx_context_t * ctx, int32_t x, int32_t y, uint16_t width, uint16_t height, int radius, uint32_t color);
|
||||
extern void draw_rectangle(gfx_context_t * ctx, int32_t x, int32_t y, uint16_t width, uint16_t height, uint32_t color);
|
||||
|
||||
struct gfx_point {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
extern float gfx_point_distance(struct gfx_point * a, struct gfx_point * b);
|
||||
extern float gfx_point_distance_squared(struct gfx_point * a, struct gfx_point * b);
|
||||
extern float gfx_point_dot(struct gfx_point * a, struct gfx_point * b);
|
||||
extern struct gfx_point gfx_point_sub(struct gfx_point * a, struct gfx_point * b);
|
||||
extern struct gfx_point gfx_point_add(struct gfx_point * a, struct gfx_point * b);
|
||||
extern float gfx_line_distance(struct gfx_point * p, struct gfx_point * v, struct gfx_point * w);
|
||||
extern void draw_line_aa(gfx_context_t * ctx, int x_1, int x_2, int y_1, int y_2, uint32_t color, float thickness);
|
||||
|
@ -797,9 +797,73 @@ void draw_rounded_rectangle(gfx_context_t * ctx, int32_t x, int32_t y, uint16_t
|
||||
GFX(ctx, _x, _y) = alpha_blend_rgba(GFX(ctx, _x, _y), c);
|
||||
GFX(ctx, _x, _z) = alpha_blend_rgba(GFX(ctx, _x, _z), c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float gfx_point_distance(struct gfx_point * a, struct gfx_point * b) {
|
||||
return sqrt((a->x - b->x) * (a->x - b->x) + (a->y - b->y) * (a->y - b->y));
|
||||
}
|
||||
|
||||
float gfx_point_distance_squared(struct gfx_point * a, struct gfx_point * b) {
|
||||
return (a->x - b->x) * (a->x - b->x) + (a->y - b->y) * (a->y - b->y);
|
||||
}
|
||||
|
||||
float gfx_point_dot(struct gfx_point * a, struct gfx_point * b) {
|
||||
return (a->x * b->x) + (a->y * b->y);
|
||||
}
|
||||
|
||||
struct gfx_point gfx_point_sub(struct gfx_point * a, struct gfx_point * b) {
|
||||
struct gfx_point p = {a->x - b->x, a->y - b->y};
|
||||
return p;
|
||||
}
|
||||
|
||||
struct gfx_point gfx_point_add(struct gfx_point * a, struct gfx_point * b) {
|
||||
struct gfx_point p = {a->x + b->x, a->y + b->y};
|
||||
return p;
|
||||
}
|
||||
|
||||
#define fmax(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define fmin(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
float gfx_line_distance(struct gfx_point * p, struct gfx_point * v, struct gfx_point * w) {
|
||||
float lengthlength = gfx_point_distance_squared(v,w);
|
||||
|
||||
if (lengthlength == 0.0) return gfx_point_distance(p, v); /* point */
|
||||
|
||||
struct gfx_point p_v = gfx_point_sub(p,v);
|
||||
struct gfx_point w_v = gfx_point_sub(w,v);
|
||||
float tmp = gfx_point_dot(&p_v,&w_v) / lengthlength;
|
||||
tmp = fmin(1.0,tmp);
|
||||
float t = fmax(0.0, tmp);
|
||||
|
||||
w_v.x *= t;
|
||||
w_v.y *= t;
|
||||
|
||||
struct gfx_point v_t = gfx_point_add(v, &w_v);
|
||||
return gfx_point_distance(p, &v_t);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is slow, but it works...
|
||||
*
|
||||
* Maybe acceptable for baked UI elements?
|
||||
*/
|
||||
void draw_line_aa(gfx_context_t * ctx, int x_1, int x_2, int y_1, int y_2, uint32_t color, float thickness) {
|
||||
struct gfx_point v = {(float)x_1, (float)y_1};
|
||||
struct gfx_point w = {(float)x_2, (float)y_2};
|
||||
|
||||
for (int y = 0; y < ctx->height; ++y) {
|
||||
for (int x = 0; x < ctx->width; ++x) {
|
||||
struct gfx_point p = {x,y};
|
||||
float d = gfx_line_distance(&p,&v,&w);
|
||||
if (d < thickness + 0.5) {
|
||||
if (d < thickness - 0.5) {
|
||||
GFX(ctx,x,y) = color;
|
||||
} else {
|
||||
uint32_t f_color = rgb(255 * (1.0 - (d - thickness + 0.5)), 0, 0);
|
||||
GFX(ctx,x,y) = alpha_blend(GFX(ctx,x,y), color, f_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user