GUAC-667: Draw glyphs directly to surface.

This commit is contained in:
Michael Jumper 2014-05-05 00:28:07 -07:00
parent 3554e88efa
commit c5ada6631c
4 changed files with 18 additions and 122 deletions

View File

@ -705,13 +705,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
/* Send connection name */ /* Send connection name */
guac_protocol_send_name(client->socket, settings->hostname); guac_protocol_send_name(client->socket, settings->hostname);
/* Create glyph surfaces */
guac_client_data->opaque_glyph_surface = cairo_image_surface_create(
CAIRO_FORMAT_RGB24, settings->width, settings->height);
guac_client_data->trans_glyph_surface = cairo_image_surface_create(
CAIRO_FORMAT_ARGB32, settings->width, settings->height);
/* Create default surface */ /* Create default surface */
guac_client_data->default_surface = guac_common_surface_alloc(client->socket, GUAC_DEFAULT_LAYER, guac_client_data->default_surface = guac_common_surface_alloc(client->socket, GUAC_DEFAULT_LAYER,
settings->width, settings->height); settings->width, settings->height);

View File

@ -34,6 +34,7 @@
#include "rdp_settings.h" #include "rdp_settings.h"
#include <pthread.h> #include <pthread.h>
#include <stdint.h>
#include <cairo/cairo.h> #include <cairo/cairo.h>
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
@ -99,26 +100,9 @@ typedef struct rdp_guac_client_data {
int mouse_button_mask; int mouse_button_mask;
/** /**
* Cairo surface which will receive all TRANSPARENT glyphs. * Foreground color for any future glyphs.
*/ */
cairo_surface_t* trans_glyph_surface; uint32_t glyph_color;
/**
* Cairo surface which will receive all OPAQUE glyphs.
*/
cairo_surface_t* opaque_glyph_surface;
/**
* The current Cairo surface which will receive all drawn glyphs,
* depending on whether we are currently drawing transparent or
* opaque glyphs.
*/
cairo_surface_t* glyph_surface;
/**
* Cairo instance for drawing to the current glyph surface.
*/
cairo_t* glyph_cairo;
/** /**
* The display. * The display.

View File

@ -94,8 +94,6 @@ int rdp_guac_client_free_handler(guac_client* client) {
/* Free client data */ /* Free client data */
guac_common_clipboard_free(guac_client_data->clipboard); guac_common_clipboard_free(guac_client_data->clipboard);
guac_common_surface_free(guac_client_data->default_surface); guac_common_surface_free(guac_client_data->default_surface);
cairo_surface_destroy(guac_client_data->opaque_glyph_surface);
cairo_surface_destroy(guac_client_data->trans_glyph_surface);
free(guac_client_data); free(guac_client_data);
return 0; return 0;

View File

@ -100,15 +100,14 @@ void guac_rdp_glyph_draw(rdpContext* context, rdpGlyph* glyph, int x, int y) {
guac_client* client = ((rdp_freerdp_context*) context)->client; guac_client* client = ((rdp_freerdp_context*) context)->client;
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data; rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
guac_common_surface* current_surface = guac_client_data->current_surface;
uint32_t fgcolor = guac_client_data->glyph_color;
/* Do not attempt to draw glyphs if glyph drawing is not begun */ /* Paint with glyph as mask */
if (guac_client_data->glyph_cairo == NULL) guac_common_surface_paint(current_surface, x, y, ((guac_rdp_glyph*) glyph)->surface,
return; (fgcolor & 0xFF0000) >> 16,
(fgcolor & 0x00FF00) >> 8,
/* Use glyph as mask */ fgcolor & 0x0000FF);
cairo_mask_surface(
guac_client_data->glyph_cairo,
((guac_rdp_glyph*) glyph)->surface, x, y);
} }
@ -130,107 +129,29 @@ void guac_rdp_glyph_begindraw(rdpContext* context,
rdp_guac_client_data* guac_client_data = rdp_guac_client_data* guac_client_data =
(rdp_guac_client_data*) client->data; (rdp_guac_client_data*) client->data;
/* Convert foreground color */
fgcolor = freerdp_color_convert_var(fgcolor,
guac_client_data->settings.color_depth, 32,
((rdp_freerdp_context*) context)->clrconv);
/* Fill background with color if specified */ /* Fill background with color if specified */
if (width != 0 && height != 0) { if (width != 0 && height != 0) {
/* Prepare for opaque glyphs */
guac_client_data->glyph_surface =
guac_client_data->opaque_glyph_surface;
/* Create cairo instance */
guac_client_data->glyph_cairo = cairo_create(
guac_client_data->glyph_surface);
/* Convert background color */ /* Convert background color */
bgcolor = freerdp_color_convert_var(bgcolor, bgcolor = freerdp_color_convert_var(bgcolor,
guac_client_data->settings.color_depth, 32, guac_client_data->settings.color_depth, 32,
((rdp_freerdp_context*) context)->clrconv); ((rdp_freerdp_context*) context)->clrconv);
/* Fill background */ guac_common_surface_rect(guac_client_data->current_surface, x, y, width, height,
cairo_rectangle(guac_client_data->glyph_cairo, (bgcolor & 0xFF0000) >> 16,
x, y, width, height); (bgcolor & 0x00FF00) >> 8,
bgcolor & 0x0000FF);
cairo_set_source_rgb(guac_client_data->glyph_cairo,
((bgcolor & 0xFF0000) >> 16) / 255.0,
((bgcolor & 0x00FF00) >> 8 ) / 255.0,
( bgcolor & 0x0000FF ) / 255.0);
cairo_fill(guac_client_data->glyph_cairo);
} }
/* Otherwise, prepare for transparent glyphs */ /* Convert foreground color */
else { guac_client_data->glyph_color = freerdp_color_convert_var(fgcolor,
guac_client_data->settings.color_depth, 32, ((rdp_freerdp_context*) context)->clrconv);
/* Select transparent glyph surface */
guac_client_data->glyph_surface =
guac_client_data->trans_glyph_surface;
guac_client_data->glyph_cairo = cairo_create(
guac_client_data->glyph_surface);
/* Clear surface */
cairo_set_operator(guac_client_data->glyph_cairo,
CAIRO_OPERATOR_SOURCE);
cairo_set_source_rgba(guac_client_data->glyph_cairo, 0, 0, 0, 0);
cairo_paint(guac_client_data->glyph_cairo);
/* Restore operator */
cairo_set_operator(guac_client_data->glyph_cairo,
CAIRO_OPERATOR_OVER);
}
/* Prepare for glyph drawing */
cairo_set_source_rgb(guac_client_data->glyph_cairo,
((fgcolor & 0xFF0000) >> 16) / 255.0,
((fgcolor & 0x00FF00) >> 8 ) / 255.0,
( fgcolor & 0x0000FF ) / 255.0);
} }
void guac_rdp_glyph_enddraw(rdpContext* context, void guac_rdp_glyph_enddraw(rdpContext* context,
int x, int y, int width, int height, UINT32 fgcolor, UINT32 bgcolor) { int x, int y, int width, int height, UINT32 fgcolor, UINT32 bgcolor) {
/* IGNORE */
guac_client* client = ((rdp_freerdp_context*) context)->client;
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
guac_common_surface* current_surface = ((rdp_guac_client_data*) client->data)->current_surface;
/* Use glyph surface to provide image data for glyph rectangle */
cairo_surface_t* glyph_surface = guac_client_data->glyph_surface;
int stride = cairo_image_surface_get_stride(glyph_surface);
/* Calculate bounds */
int max_width = cairo_image_surface_get_width(glyph_surface) - x;
int max_height = cairo_image_surface_get_height(glyph_surface) - y;
/* Ensure dimensions of glyph do not exceed bounds */
if (width > max_width) width = max_width;
if (height > max_height) height = max_height;
/* Ensure data is ready */
cairo_surface_flush(glyph_surface);
/* Create surface for subsection with text */
cairo_surface_t* surface = cairo_image_surface_create_for_data(
cairo_image_surface_get_data(glyph_surface) + 4*x + y*stride,
cairo_image_surface_get_format(glyph_surface),
width, height, stride);
/* Send surface with all glyphs to current surface */
guac_common_surface_draw(current_surface, x, y, surface);
/* Destroy surface */
cairo_surface_destroy(surface);
/* Destroy cairo instance */
cairo_destroy(guac_client_data->glyph_cairo);
} }