Skip to content
Merged
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
4 changes: 4 additions & 0 deletions src/tsm/libtsm-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ struct tsm_screen {
bool sel_active;
struct selection_pos sel_start;
struct selection_pos sel_end;

/* draw2 interface */
struct tsm_screen_cell *cells;
unsigned int cells_count;
};

void screen_cell_init(struct tsm_screen *con, struct cell *cell);
Expand Down
27 changes: 27 additions & 0 deletions src/tsm/libtsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,31 @@ struct tsm_screen_attr {
unsigned int blink : 1; /* blinking character */
};

/* Attributes that alter the glyph shape */
typedef union{
struct {
uint8_t bold : 1;
uint8_t italic : 1;
uint8_t underline : 1;
uint8_t blink : 1;
uint8_t reserved : 5;
};
uint8_t u8;
} tsm_screen_attr2_t;

struct tsm_screen_color {
uint8_t r; /* red */
uint8_t g; /* green */
uint8_t b; /* blue */
};

struct tsm_screen_cell {
uint32_t ch; /* character */
struct tsm_screen_color fg; /* foreground color */
struct tsm_screen_color bg; /* background color */
tsm_screen_attr2_t attr2; /* glyph attributes */
};

typedef int (*tsm_screen_draw_cb) (struct tsm_screen *con,
uint64_t id,
const uint32_t *ch,
Expand Down Expand Up @@ -268,6 +293,8 @@ int tsm_screen_selection_copy(struct tsm_screen *con, char **out);
tsm_age_t tsm_screen_draw(struct tsm_screen *con, tsm_screen_draw_cb draw_cb,
void *data);

const struct tsm_screen_cell *tsm_screen_draw2(struct tsm_screen *con);

/** @} */

/**
Expand Down
5 changes: 5 additions & 0 deletions src/tsm/libtsm.sym
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,8 @@ global:
tsm_vte_set_bell_cb;
tsm_vte_set_led_cb;
} LIBTSM_4_4;

LIBTSM_4_6 {
global:
tsm_screen_draw2;
} LIBTSM_4_5;
102 changes: 101 additions & 1 deletion src/tsm/tsm-render.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
* yourself.
*/

#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
Expand Down Expand Up @@ -193,3 +192,104 @@ tsm_age_t tsm_screen_draw(struct tsm_screen *con, tsm_screen_draw_cb draw_cb,
return con->age_cnt;
}
}

/*
* tsm_screen_draw2 returns a pointer to a table of tsm_screen_cell, one for each cell on the screen.
* It uses a bit more memory, but should be much faster, as each cell is only 12 bytes.
* The caller can read the table, until the next call to tsm_screen_draw2, or until con is destroyed.
*/
SHL_EXPORT
const struct tsm_screen_cell *tsm_screen_draw2(struct tsm_screen *con)
{
unsigned int i, j, k;
struct line *line, *next_line = NULL;
struct cell *cell, empty;
struct tsm_screen_cell *out;
bool in_sel = false, sel_start = false, sel_end = false;
bool inverse = false;

if (!con)
return NULL;

if (con->cells_count < con->size_x * con->size_y) {
free(con->cells);
con->cells_count = 0;
con->cells = malloc(con->size_x * con->size_y * sizeof(struct tsm_screen_cell));
if (!con->cells)
return NULL;
con->cells_count = con->size_x * con->size_y;
memset(con->cells, 0, con->cells_count * sizeof(struct tsm_screen_cell));
}

screen_cell_init(con, &empty);

/* push each character into rendering pipeline */
k = 0;
next_line = con->sb.pos;

if (con->sel_active) {
if (!con->sel_start.line && con->sel_end.line)
in_sel = true;

if (is_in_scrollback(&con->sel_start)
&& (!con->sb.pos || con->sel_start.line->sb_id < con->sb.pos->sb_id))
in_sel = !in_sel;
if (is_in_scrollback(&con->sel_end)
&& (!con->sb.pos || con->sel_end.line->sb_id < con->sb.pos->sb_id))
in_sel = !in_sel;
}

for (i = 0; i < con->size_y; ++i) {
if (next_line) {
line = next_line;
next_line = shl_dlist_next(next_line, &con->sb.list, list);
} else {
line = con->lines[k];
k++;
}

if (con->sel_active) {
sel_start = (con->sel_start.line == line);
sel_end = (con->sel_end.line == line);
}

for (j = 0; j < con->size_x; ++j) {
out = &con->cells[i * con->size_x + j];
/* don't handle multiple codepoints yet */
if (j < line->size && line->cells[j].ch <= TSM_UCS4_MAX)
cell = &line->cells[j];
else
cell = &empty;
out->ch = cell->ch ? cell->ch : ' ';
out->attr2.bold = cell->attr.bold;
out->attr2.italic = cell->attr.italic;
out->attr2.underline = cell->attr.underline;
out->attr2.blink = cell->attr.blink;

if (sel_start && j == con->sel_start.x)
in_sel = !in_sel;

/* Inverse logic, cell attribute, selection, and whole screen inverse */
inverse = cell->attr.inverse ^ in_sel ^ (con->flags & TSM_SCREEN_INVERSE);

if (inverse) {
out->fg.r = cell->attr.br;
out->fg.g = cell->attr.bg;
out->fg.b = cell->attr.bb;
out->bg.r = cell->attr.fr;
out->bg.g = cell->attr.fg;
out->bg.b = cell->attr.fb;
} else {
out->fg.r = cell->attr.fr;
out->fg.g = cell->attr.fg;
out->fg.b = cell->attr.fb;
out->bg.r = cell->attr.br;
out->bg.g = cell->attr.bg;
out->bg.b = cell->attr.bb;
}
if (sel_end && j == con->sel_end.x)
in_sel = !in_sel;
}
}
return con->cells;
}
1 change: 1 addition & 0 deletions src/tsm/tsm-screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@ void tsm_screen_unref(struct tsm_screen *con)
free(con->alt_lines);
free(con->tab_ruler);
tsm_symbol_table_unref(con->sym_table);
free(con->cells);
free(con);
}

Expand Down
Loading