Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ project(vtrenderlib C)

add_library(vtrenderlib STATIC vtrenderlib.c)

target_compile_options(vtrenderlib PRIVATE -Wall -Wextra -Werror)

# Public include directory for consumers
target_include_directories(vtrenderlib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

Expand Down
4 changes: 2 additions & 2 deletions demos/boids/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ struct vt_boid
int cur_heading_time;

// rendering data
enum vtr_color color;
vtr_fgcolor_t color;
struct vec2f trail[VT_BOID_TRAIL_SIZE];
size_t trail_idx;
size_t trail_len;
Expand Down Expand Up @@ -241,7 +241,7 @@ static void debug_print(uint16_t row, uint16_t col, const char* fmt, ...)
va_end(args);
}

static void debug_vec(struct vec2f origin, struct vec2f vec, float scale, enum vtr_color fgc)
static void debug_vec(struct vec2f origin, struct vec2f vec, float scale, vtr_fgcolor_t fgc)
{
struct vtr_vertex start = vec2f_project(origin);
struct vtr_vertex end = vec2f_project(vec2f_mul_add(origin, vec, scale));
Expand Down
67 changes: 47 additions & 20 deletions vtrenderlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
// - VT/xterm escape sequences work in the same manner:
// 1. Shell/app: 0x1B 0x5B 0x33 0x31 0x6D # ESC [ 3 1 m → “set foreground color to red” -> written to PTY slave via STDOUT_FILENO
// 2. Kernel PTY layer: handles line discipline, raw mode (bytes pass through unchanged) vs canonical mode (control chars handled),
// forwards data to PTY slave.
// 3. Terminal emulator: reads data from PTY slave, recognizes `ESC [ 31 m`, changes rendering color, paints to the screen.
// forwards data to PTY master.
// 3. Terminal emulator: reads data from PTY master, recognizes `ESC [ 31 m`, changes rendering color, paints to the screen.
//

//
Expand Down Expand Up @@ -261,7 +261,7 @@ struct vtr_canvas* vtr_canvas_create(int ttyfd)
static int sendseq(int ttyfd, const char* seq, size_t nbytes)
{
ssize_t res = write(ttyfd, seq, nbytes);
if (res == -1 || res != nbytes) {
if (res == -1 || (size_t)res != nbytes) {
return -1;
}

Expand Down Expand Up @@ -406,7 +406,7 @@ static size_t set_pos_s(char* seq, size_t seqcap, uint16_t row, uint16_t col)
return nwritten;
}

static size_t draw_cell_s(char* seq, size_t seqcap, uint8_t mask)
static size_t draw_cell_s(char* seq, __attribute__((unused)) size_t seqcap, uint8_t mask)
{
assert(seqcap >= 3);

Expand All @@ -417,21 +417,46 @@ static size_t draw_cell_s(char* seq, size_t seqcap, uint8_t mask)
return 3;
}

static size_t set_foreground_color_s(char* seq, size_t seqcap, uint8_t fgc)
static size_t u8_to_dec(char* dst, uint8_t v)
{
if (v >= 100) {
dst[0] = '0' + v / 100;
dst[1] = '0' + (v / 10) % 10;
dst[2] = '0' + v % 10;
return 3;
}
if (v >= 10) {
dst[0] = '0' + v / 10;
dst[1] = '0' + v % 10;
return 2;
}
dst[0] = '0' + v;
return 1;
}

static size_t set_foreground_color_s(char* seq, __attribute__((unused)) size_t seqcap, uint8_t fgc)
{
assert(fgc >= VTR_COLOR_DEFAULT && fgc < VTR_COLOR_TOTAL);
assert(seqcap >= 5);

seq[0] = 0x1b;
seq[1] = '[';
seq[2] = '3';
seq[3] = (fgc == VTR_COLOR_DEFAULT ? '9' : '0' + fgc - 1);
seq[4] = 'm';

return 5;
if (fgc < VTR_COLOR_SGR8_TOTAL) {
seq[3] = (fgc == VTR_COLOR_DEFAULT ? '9' : '0' + fgc - 1);
seq[4] = 'm';
return 5;
}
assert(seqcap >= 11);
seq[3] = '8';
seq[4] = ';';
seq[5] = '5';
seq[6] = ';';
size_t n = u8_to_dec(&seq[7], fgc - 1);
seq[7 + n] = 'm';
return 8 + n;
}

static size_t put_char_s(char* seq, size_t seqcap, char chr)
static size_t put_char_s(char* seq, __attribute__((unused)) size_t seqcap, char chr)
{
assert(seqcap >= 1);
seq[0] = chr;
Expand Down Expand Up @@ -517,7 +542,7 @@ int vtr_swap_buffers(struct vtr_canvas* vt)
return sendseq(vt->fd, vt->seqlist, seqlen);
}

static void render_dot(struct vtr_stencil_buf* sb, uint16_t x, uint16_t y, enum vtr_color fgc)
static void render_dot(struct vtr_stencil_buf* sb, uint16_t x, uint16_t y, vtr_fgcolor_t fgc)
{
assert(x < sb->xdots && y < sb->ydots);

Expand Down Expand Up @@ -546,7 +571,7 @@ void vtr_render_dot(struct vtr_canvas* vt, int x, int y)
vtr_render_dotc(vt, x, y, VTR_COLOR_DEFAULT);
}

void vtr_render_dotc(struct vtr_canvas* vt, int x, int y, enum vtr_color fgc)
void vtr_render_dotc(struct vtr_canvas* vt, int x, int y, vtr_fgcolor_t fgc)
{
if (point_test(vt, x, y)) {
render_dot(vt->cur_sb, x, y, fgc);
Expand All @@ -562,12 +587,12 @@ static float calc_slope(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1)
return (x1 == x0 ? INFINITY : ((float)y1 - y0) / ((float)x1 - x0));
}

static void scan_line(struct vtr_stencil_buf* sb, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, enum vtr_color fgc)
static void scan_line(struct vtr_stencil_buf* sb, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, vtr_fgcolor_t fgc)
{
assert(x0 >= 0 && x0 < sb->xdots);
assert(x1 >= 0 && x1 < sb->xdots);
assert(y0 >= 0 && y0 < sb->ydots);
assert(y1 >= 0 && y1 < sb->ydots);
assert(x0 < sb->xdots);
assert(x1 < sb->xdots);
assert(y0 < sb->ydots);
assert(y1 < sb->ydots);

float m = calc_slope(x0, y0, x1, y1);
int hdir = (x0 < x1 ? 1 : -1);
Expand Down Expand Up @@ -637,7 +662,7 @@ void vtr_scan_line(struct vtr_canvas* vt, int x0, int y0, int x1, int y1)
vtr_scan_linec(vt, x0, y0, x1, y1, VTR_COLOR_DEFAULT);
}

void vtr_scan_linec(struct vtr_canvas* vt, int x0, int y0, int x1, int y1, enum vtr_color fgc)
void vtr_scan_linec(struct vtr_canvas* vt, int x0, int y0, int x1, int y1, vtr_fgcolor_t fgc)
{
int dx = x1 - x0, dy = y1 - y0;
int xmin = 0, ymin = 0;
Expand Down Expand Up @@ -688,7 +713,7 @@ int vtr_trace_poly(struct vtr_canvas* vt, size_t nvertices, const struct vtr_ver
return vtr_trace_polyc(vt, nvertices, vlist, VTR_COLOR_DEFAULT);
}

int vtr_trace_polyc(struct vtr_canvas* vt, size_t nvertices, const struct vtr_vertex* vlist, enum vtr_color fgc)
int vtr_trace_polyc(struct vtr_canvas* vt, size_t nvertices, const struct vtr_vertex* vlist, vtr_fgcolor_t fgc)
{
assert(vt);
assert(vlist);
Expand Down Expand Up @@ -761,7 +786,9 @@ int vtr_trace_polyc(struct vtr_canvas* vt, size_t nvertices, const struct vtr_ve
// Intercepts can repeat if 2 edges meet at current y, ignore that
switch(ncepts) {
case 2: if (xcepts[1] == xcept) continue;
/* fallthrough */
case 1: if (xcepts[0] == xcept) continue;
/* fallthrough */
case 0: break;
}

Expand Down
19 changes: 15 additions & 4 deletions vtrenderlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,27 +77,38 @@ enum vtr_color
VTR_COLOR_CYAN,
VTR_COLOR_WHITE,

VTR_COLOR_TOTAL // always last
VTR_COLOR_SGR8_TOTAL // always last
};

/*
* Foreground color type. Accepts enum vtr_color or VTR_COLOR256(idx) values.
*/
typedef uint8_t vtr_fgcolor_t;

/*
* 256-color palette (ITU-T T.416 / ISO/IEC 8613-6).
* Index 255 (light grey) is mapped to VTR_COLOR_WHITE since 0 is reserved for VTR_COLOR_DEFAULT.
*/
#define VTR_COLOR256(_idx) ((vtr_fgcolor_t)((_idx) >= 255 ? VTR_COLOR_WHITE : (_idx) + 1))

/**
* Render a dot at given VT coordinates.
*/
void vtr_render_dot(struct vtr_canvas* vt, int x, int y);
void vtr_render_dotc(struct vtr_canvas* vt, int x, int y, enum vtr_color fgc);
void vtr_render_dotc(struct vtr_canvas* vt, int x, int y, vtr_fgcolor_t fgc);

/**
* Scan a line given two dot coordinates.
*/
void vtr_scan_line(struct vtr_canvas* vt, int x0, int y0, int x1, int y1);
void vtr_scan_linec(struct vtr_canvas* vt, int x0, int y0, int x1, int y1, enum vtr_color fgc);
void vtr_scan_linec(struct vtr_canvas* vt, int x0, int y0, int x1, int y1, vtr_fgcolor_t fgc);

/**
* Trace a polygon path given a list of vertices.
* The last vertex is traced back to the first one and the resulting polygon filled.
*/
int vtr_trace_poly(struct vtr_canvas* vt, size_t nvertices, const struct vtr_vertex* vertexlist);
int vtr_trace_polyc(struct vtr_canvas* vt, size_t nvertices, const struct vtr_vertex* vertexlist, enum vtr_color fgc);
int vtr_trace_polyc(struct vtr_canvas* vt, size_t nvertices, const struct vtr_vertex* vertexlist, vtr_fgcolor_t fgc);

/**
* Print some text at the specified location.
Expand Down