GUAC-667: Draw glyphs directly to surface.
This commit is contained in:
parent
3554e88efa
commit
c5ada6631c
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user