Much faster drawing method (complete).

This commit is contained in:
Michael Jumper 2011-08-18 18:09:20 -07:00
parent e5619531a6
commit 7b09948842
3 changed files with 109 additions and 39 deletions

View File

@ -93,6 +93,26 @@ struct ssh_guac_terminal {
*/ */
PangoFontDescription* font_desc; PangoFontDescription* font_desc;
/**
* Index of next glyph to create
*/
int next_glyph;
/**
* Index of locations for each glyph in the stroke and fill layers.
*/
int glyphs[256];
/**
* Color of glyphs in copy buffer
*/
int glyph_foreground;
/**
* Color of glyphs in copy buffer
*/
int glyph_background;
/** /**
* A single wide layer holding each glyph, with each glyph only * A single wide layer holding each glyph, with each glyph only
* colored with foreground color (background remains transparent). * colored with foreground color (background remains transparent).
@ -184,8 +204,10 @@ int ssh_guac_terminal_write(ssh_guac_terminal* term, const char* c, int size);
int ssh_guac_terminal_redraw_cursor(ssh_guac_terminal* term); int ssh_guac_terminal_redraw_cursor(ssh_guac_terminal* term);
int ssh_guac_terminal_set(ssh_guac_terminal* term, int row, int col, int ssh_guac_terminal_set_colors(ssh_guac_terminal* term,
char c, int foreground, int background); int foreground, int background);
int ssh_guac_terminal_set(ssh_guac_terminal* term, int row, int col, char c);
int ssh_guac_terminal_copy(ssh_guac_terminal* term, int ssh_guac_terminal_copy(ssh_guac_terminal* term,
int src_row, int src_col, int rows, int cols, int src_row, int src_col, int rows, int cols,

View File

@ -85,12 +85,16 @@ ssh_guac_terminal* ssh_guac_terminal_create(guac_client* client) {
ssh_guac_terminal* term = malloc(sizeof(ssh_guac_terminal)); ssh_guac_terminal* term = malloc(sizeof(ssh_guac_terminal));
term->client = client; term->client = client;
term->foreground = term->default_foreground = 7; /* White */ term->glyph_foreground = term->foreground = term->default_foreground = 7; /* White */
term->background = term->default_background = 0; /* Black */ term->glyph_background = term->background = term->default_background = 0; /* Black */
term->reverse = 0; /* Normal video */ term->reverse = 0; /* Normal video */
term->bold = 0; /* Normal intensity */ term->bold = 0; /* Normal intensity */
term->underscore = 0; /* No underline */ term->underscore = 0; /* No underline */
memset(term->glyphs, 0, sizeof(term->glyphs));
term->glyph_stroke = guac_client_alloc_buffer(client);
term->filled_glyphs = guac_client_alloc_buffer(client);
term->cursor_row = 0; term->cursor_row = 0;
term->cursor_col = 0; term->cursor_col = 0;
term->cursor_layer = guac_client_alloc_layer(client, 1); term->cursor_layer = guac_client_alloc_layer(client, 1);
@ -165,14 +169,18 @@ void ssh_guac_terminal_free(ssh_guac_terminal* term) {
/* STUB */ /* STUB */
} }
guac_layer* __ssh_guac_terminal_get_glyph(ssh_guac_terminal* term, char c) { int __ssh_guac_terminal_get_glyph(ssh_guac_terminal* term, char c) {
GUACIO* io = term->client->io; GUACIO* io = term->client->io;
guac_layer* glyph; int location;
/* Use default foreground color */ /* Use foreground color */
const ssh_guac_terminal_color* color = const ssh_guac_terminal_color* color =
&ssh_guac_terminal_palette[term->default_foreground]; &ssh_guac_terminal_palette[term->glyph_foreground];
/* Use background color */
const ssh_guac_terminal_color* background =
&ssh_guac_terminal_palette[term->glyph_background];
cairo_surface_t* surface; cairo_surface_t* surface;
cairo_t* cairo; cairo_t* cairo;
@ -181,7 +189,9 @@ guac_layer* __ssh_guac_terminal_get_glyph(ssh_guac_terminal* term, char c) {
/* Return glyph if exists */ /* Return glyph if exists */
if (term->glyphs[(int) c]) if (term->glyphs[(int) c])
return term->glyphs[(int) c]; return term->glyphs[(int) c] - 1;
location = term->next_glyph++;
/* Otherwise, draw glyph */ /* Otherwise, draw glyph */
surface = cairo_image_surface_create( surface = cairo_image_surface_create(
@ -208,16 +218,27 @@ guac_layer* __ssh_guac_terminal_get_glyph(ssh_guac_terminal* term, char c) {
g_object_unref(layout); g_object_unref(layout);
cairo_destroy(cairo); cairo_destroy(cairo);
/* Send glyph and save */ /* Send glyph and update filled flyphs */
glyph = guac_client_alloc_buffer(term->client); guac_send_png(io, GUAC_COMP_OVER, term->glyph_stroke, location * term->char_width, 0, surface);
guac_send_png(io, GUAC_COMP_OVER, glyph, 0, 0, surface);
term->glyphs[(int) c] = glyph; guac_send_rect(io, GUAC_COMP_SRC, term->filled_glyphs,
location * term->char_width, 0,
term->char_width, term->char_height,
background->red,
background->green,
background->blue,
0xFF);
guac_send_copy(io, term->glyph_stroke,
location * term->char_width, 0, term->char_width, term->char_height,
GUAC_COMP_OVER, term->filled_glyphs, location * term->char_width, 0);
term->glyphs[(int) c] = location+1;
guac_flush(io);
cairo_surface_destroy(surface); cairo_surface_destroy(surface);
/* Return glyph */ /* Return glyph */
return glyph; return location;
} }
@ -248,24 +269,17 @@ int ssh_guac_terminal_redraw_cursor(ssh_guac_terminal* term) {
} }
int ssh_guac_terminal_set(ssh_guac_terminal* term, int row, int col, int ssh_guac_terminal_set_colors(ssh_guac_terminal* term,
char c, int foreground, int background) { int foreground, int background) {
GUACIO* io = term->client->io; GUACIO* io = term->client->io;
guac_layer* glyph = __ssh_guac_terminal_get_glyph(term, c);
const ssh_guac_terminal_color* background_color; const ssh_guac_terminal_color* background_color;
/* Get background color */ /* Get background color */
background_color = &ssh_guac_terminal_palette[background]; background_color = &ssh_guac_terminal_palette[background];
guac_send_copy(io, /* If foreground different from current, colorize */
glyph, 0, 0, term->char_width, term->char_height, if (foreground != term->glyph_foreground) {
GUAC_COMP_SRC, GUAC_DEFAULT_LAYER,
term->char_width * col,
term->char_height * row);
/* If foreground different from default, colorize */
if (foreground != term->default_foreground) {
/* Get color */ /* Get color */
const ssh_guac_terminal_color* color = const ssh_guac_terminal_color* color =
@ -273,10 +287,10 @@ int ssh_guac_terminal_set(ssh_guac_terminal* term, int row, int col,
/* Colorize letter */ /* Colorize letter */
guac_send_rect(io, guac_send_rect(io,
GUAC_COMP_ATOP, GUAC_DEFAULT_LAYER, GUAC_COMP_ATOP, term->glyph_stroke,
term->char_width * col, term->char_height * row, 0, 0,
term->char_width, term->char_height, term->char_width * term->next_glyph, term->char_height,
color->red, color->red,
color->green, color->green,
@ -285,22 +299,53 @@ int ssh_guac_terminal_set(ssh_guac_terminal* term, int row, int col,
} }
/* Set background */ /* If any color change at all, update filled */
/*guac_send_rect(io, if (foreground != term->glyph_foreground || background != term->glyph_background) {
GUAC_COMP_ROVER, GUAC_DEFAULT_LAYER,
term->char_width * col, term->char_height * row, /* Set background */
term->char_width, term->char_height, guac_send_rect(io,
GUAC_COMP_SRC, term->filled_glyphs,
0, 0,
term->char_width * term->next_glyph, term->char_height,
background_color->red, background_color->red,
background_color->green, background_color->green,
background_color->blue, background_color->blue,
255);*/ 255);
/* Copy stroke */
guac_send_copy(io, term->glyph_stroke,
0, 0,
term->char_width * term->next_glyph, term->char_height,
GUAC_COMP_OVER, term->filled_glyphs,
0, 0);
}
term->glyph_foreground = foreground;
term->glyph_background = background;
return 0; return 0;
} }
int ssh_guac_terminal_set(ssh_guac_terminal* term, int row, int col, char c) {
GUACIO* io = term->client->io;
int location = __ssh_guac_terminal_get_glyph(term, c);
return guac_send_copy(io,
term->filled_glyphs,
location * term->char_width, 0, term->char_width, term->char_height,
GUAC_COMP_SRC, GUAC_DEFAULT_LAYER,
term->char_width * col,
term->char_height * row);
}
int ssh_guac_terminal_write(ssh_guac_terminal* term, const char* c, int size) { int ssh_guac_terminal_write(ssh_guac_terminal* term, const char* c, int size) {
while (size > 0) { while (size > 0) {

View File

@ -112,10 +112,13 @@ int ssh_guac_terminal_echo(ssh_guac_terminal* term, char c) {
if (term->bold && foreground <= 7) if (term->bold && foreground <= 7)
foreground += 8; foreground += 8;
ssh_guac_terminal_set_colors(term,
foreground, background);
ssh_guac_terminal_set(term, ssh_guac_terminal_set(term,
term->cursor_row, term->cursor_row,
term->cursor_col, term->cursor_col,
c, foreground, background); c);
/* Advance cursor */ /* Advance cursor */
term->cursor_col++; term->cursor_col++;