Batch up drawing glyphs

dev
Kristian Høgsberg 14 years ago
parent 7ae6b1a27d
commit 1d3e93922d
  1. 107
      clients/terminal.c

@ -461,16 +461,19 @@ terminal_get_attr_row(struct terminal *terminal, int row)
return &terminal->data_attr[index * terminal->width]; return &terminal->data_attr[index * terminal->width];
} }
struct decoded_attr { union decoded_attr {
int foreground; struct {
int background; unsigned char foreground;
int bold; unsigned char background;
int underline; unsigned char bold;
unsigned char underline;
};
uint32_t key;
}; };
static void static void
terminal_decode_attr(struct terminal *terminal, int row, int col, terminal_decode_attr(struct terminal *terminal, int row, int col,
struct decoded_attr *decoded) union decoded_attr *decoded)
{ {
struct attr attr; struct attr attr;
int foreground, background, tmp; int foreground, background, tmp;
@ -744,6 +747,69 @@ terminal_set_color(struct terminal *terminal, cairo_t *cr, int index)
terminal->color_table[index].a); terminal->color_table[index].a);
} }
struct glyph_run {
struct terminal *terminal;
cairo_t *cr;
int count;
union decoded_attr attr;
cairo_glyph_t glyphs[256], *g;
};
static void
glyph_run_init(struct glyph_run *run, struct terminal *terminal, cairo_t *cr)
{
run->terminal = terminal;
run->cr = cr;
run->g = run->glyphs;
run->count = 0;
run->attr.key = 0;
}
static void
glyph_run_flush(struct glyph_run *run, union decoded_attr attr)
{
cairo_scaled_font_t *font;
if (run->count == 0)
run->attr = attr;
if (run->count > ARRAY_LENGTH(run->glyphs) - 10 ||
(attr.key != run->attr.key)) {
if (run->attr.bold)
font = run->terminal->font_bold;
else
font = run->terminal->font_normal;
cairo_set_scaled_font(run->cr, font);
terminal_set_color(run->terminal, run->cr,
run->attr.foreground);
cairo_show_glyphs (run->cr, run->glyphs, run->count);
run->g = run->glyphs;
run->count = 0;
}
}
static void
glyph_run_add(struct glyph_run *run, int x, int y, union utf8_char *c)
{
int num_glyphs;
cairo_scaled_font_t *font;
num_glyphs = ARRAY_LENGTH(run->glyphs) - run->count;
if (run->attr.bold)
font = run->terminal->font_bold;
else
font = run->terminal->font_normal;
cairo_move_to(run->cr, x, y);
cairo_scaled_font_text_to_glyphs (font, x, y,
(char *) c->byte, 4,
&run->g, &num_glyphs,
NULL, NULL, NULL);
run->g += num_glyphs;
run->count += num_glyphs;
}
static void static void
terminal_draw_contents(struct terminal *terminal) terminal_draw_contents(struct terminal *terminal)
{ {
@ -753,13 +819,11 @@ terminal_draw_contents(struct terminal *terminal)
int top_margin, side_margin; int top_margin, side_margin;
int row, col; int row, col;
union utf8_char *p_row; union utf8_char *p_row;
struct decoded_attr attr; union decoded_attr attr;
int text_x, text_y; int text_x, text_y;
cairo_surface_t *surface; cairo_surface_t *surface;
double d; double d;
int num_glyphs; struct glyph_run run;
cairo_scaled_font_t *font;
cairo_glyph_t glyphs[256], *g;
window_get_child_allocation(terminal->window, &allocation); window_get_child_allocation(terminal->window, &allocation);
@ -801,18 +865,15 @@ terminal_draw_contents(struct terminal *terminal)
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
/* paint the foreground */ /* paint the foreground */
glyph_run_init(&run, terminal, cr);
for (row = 0; row < terminal->height; row++) { for (row = 0; row < terminal->height; row++) {
p_row = terminal_get_row(terminal, row); p_row = terminal_get_row(terminal, row);
for (col = 0; col < terminal->width; col++) { for (col = 0; col < terminal->width; col++) {
/* get the attributes for this character cell */ /* get the attributes for this character cell */
terminal_decode_attr(terminal, row, col, &attr); terminal_decode_attr(terminal, row, col, &attr);
if (attr.bold) glyph_run_flush(&run, attr);
font = terminal->font_bold;
else
font = terminal->font_normal;
cairo_set_scaled_font(cr, font);
terminal_set_color(terminal, cr, attr.foreground);
text_x = side_margin + col * extents.max_x_advance; text_x = side_margin + col * extents.max_x_advance;
text_y = top_margin + extents.ascent + row * extents.height; text_y = top_margin + extents.ascent + row * extents.height;
if (attr.underline) { if (attr.underline) {
@ -820,18 +881,14 @@ terminal_draw_contents(struct terminal *terminal)
cairo_line_to(cr, text_x + extents.max_x_advance, (double) text_y + 1.5); cairo_line_to(cr, text_x + extents.max_x_advance, (double) text_y + 1.5);
cairo_stroke(cr); cairo_stroke(cr);
} }
cairo_move_to(cr, text_x, text_y);
glyph_run_add(&run, text_x, text_y, &p_row[col]);
g = glyphs;
num_glyphs = ARRAY_LENGTH(glyphs);
cairo_scaled_font_text_to_glyphs (font, text_x, text_y,
(char *) p_row[col].byte, 4,
&g, &num_glyphs,
NULL, NULL, NULL);
cairo_show_glyphs (cr, g, num_glyphs);
} }
} }
attr.key = ~0;
glyph_run_flush(&run, attr);
if ((terminal->mode & MODE_SHOW_CURSOR) && !terminal->focused) { if ((terminal->mode & MODE_SHOW_CURSOR) && !terminal->focused) {
d = 0.5; d = 0.5;

Loading…
Cancel
Save