Merge branch 'unstable' into clipboard
This commit is contained in:
commit
e691bfb51b
@ -47,12 +47,6 @@
|
||||
|
||||
#define RDP_DEFAULT_PORT 3389
|
||||
|
||||
typedef struct guac_rdp_color {
|
||||
int red;
|
||||
int green;
|
||||
int blue;
|
||||
} guac_rdp_color;
|
||||
|
||||
typedef struct rdp_guac_client_data {
|
||||
|
||||
freerdp* rdp_inst;
|
||||
@ -60,8 +54,27 @@ typedef struct rdp_guac_client_data {
|
||||
|
||||
int mouse_button_mask;
|
||||
|
||||
guac_rdp_color foreground;
|
||||
guac_rdp_color background;
|
||||
/**
|
||||
* Cairo surface which will receive all TRANSPARENT glyphs.
|
||||
*/
|
||||
cairo_surface_t* trans_glyph_surface;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
const guac_layer* current_surface;
|
||||
|
||||
|
@ -54,8 +54,14 @@ typedef struct guac_rdp_bitmap {
|
||||
*/
|
||||
guac_layer* layer;
|
||||
|
||||
/**
|
||||
* The number of times a bitmap has been used.
|
||||
*/
|
||||
int used;
|
||||
|
||||
} guac_rdp_bitmap;
|
||||
|
||||
void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap);
|
||||
void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap);
|
||||
void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed);
|
||||
void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap);
|
||||
|
@ -51,5 +51,6 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt);
|
||||
void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect);
|
||||
void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette);
|
||||
void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds);
|
||||
void guac_rdp_gdi_end_paint(rdpContext* context);
|
||||
|
||||
#endif
|
||||
|
@ -50,9 +50,9 @@ typedef struct guac_rdp_glyph {
|
||||
rdpGlyph glyph;
|
||||
|
||||
/**
|
||||
* Guacamole layer containing cached image data.
|
||||
* Cairo surface layer containing cached image data.
|
||||
*/
|
||||
guac_layer* layer;
|
||||
cairo_surface_t* surface;
|
||||
|
||||
} guac_rdp_glyph;
|
||||
|
||||
|
@ -152,6 +152,7 @@ boolean rdp_freerdp_pre_connect(freerdp* instance) {
|
||||
xfree(pointer);
|
||||
|
||||
/* Set up GDI */
|
||||
instance->update->EndPaint = guac_rdp_gdi_end_paint;
|
||||
instance->update->Palette = guac_rdp_gdi_palette_update;
|
||||
instance->update->SetBounds = guac_rdp_gdi_set_bounds;
|
||||
|
||||
@ -199,10 +200,6 @@ boolean rdp_freerdp_post_connect(freerdp* instance) {
|
||||
client->mouse_handler = rdp_guac_client_mouse_handler;
|
||||
client->key_handler = rdp_guac_client_key_handler;
|
||||
|
||||
/* Send size */
|
||||
guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER,
|
||||
instance->settings->width, instance->settings->height);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
@ -400,6 +397,17 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
||||
/* Send connection name */
|
||||
guac_protocol_send_name(client->socket, settings->window_title);
|
||||
|
||||
/* Send size */
|
||||
guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER,
|
||||
settings->width, settings->height);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
|
||||
|
@ -53,7 +53,7 @@
|
||||
#include "client.h"
|
||||
#include "rdp_bitmap.h"
|
||||
|
||||
void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) {
|
||||
void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_socket* socket = client->socket;
|
||||
@ -61,9 +61,31 @@ void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) {
|
||||
/* Allocate buffer */
|
||||
guac_layer* buffer = guac_client_alloc_buffer(client);
|
||||
|
||||
/* Cache image data if present */
|
||||
if (bitmap->data != NULL) {
|
||||
|
||||
/* Create surface from image data */
|
||||
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
||||
bitmap->data, CAIRO_FORMAT_RGB24,
|
||||
bitmap->width, bitmap->height, 4*bitmap->width);
|
||||
|
||||
/* Send surface to buffer */
|
||||
guac_protocol_send_png(socket,
|
||||
GUAC_COMP_SRC, buffer, 0, 0, surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
}
|
||||
|
||||
/* Store buffer reference in bitmap */
|
||||
((guac_rdp_bitmap*) bitmap)->layer = buffer;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) {
|
||||
|
||||
/* Convert image data if present */
|
||||
if (bitmap->data != NULL) {
|
||||
|
||||
@ -73,40 +95,21 @@ void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) {
|
||||
context->instance->settings->color_depth,
|
||||
32, ((rdp_freerdp_context*) context)->clrconv);
|
||||
|
||||
/* Create surface from image data */
|
||||
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
||||
image_buffer, CAIRO_FORMAT_RGB24,
|
||||
bitmap->width, bitmap->height, 4*bitmap->width);
|
||||
/* Free existing image, if any */
|
||||
if (image_buffer != bitmap->data)
|
||||
free(bitmap->data);
|
||||
|
||||
/* Send surface to buffer */
|
||||
guac_protocol_send_png(socket, GUAC_COMP_SRC, buffer, 0, 0, surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
/* If ephemeral, just free image data */
|
||||
if (!bitmap->ephemeral) {
|
||||
|
||||
/* Free image data if actually alloated */
|
||||
if (image_buffer != bitmap->data)
|
||||
free(image_buffer);
|
||||
|
||||
}
|
||||
|
||||
/* Otherwise, store converted image in bitmap, free any existing */
|
||||
else {
|
||||
|
||||
/* Free existing image, if any */
|
||||
if (image_buffer != bitmap->data)
|
||||
free(bitmap->data);
|
||||
|
||||
/* Store converted image in bitmap */
|
||||
bitmap->data = image_buffer;
|
||||
|
||||
}
|
||||
/* Store converted image in bitmap */
|
||||
bitmap->data = image_buffer;
|
||||
|
||||
}
|
||||
|
||||
/* No corresponding layer yet - caching is deferred. */
|
||||
((guac_rdp_bitmap*) bitmap)->layer = NULL;
|
||||
|
||||
/* Start at zero usage */
|
||||
((guac_rdp_bitmap*) bitmap)->used = 0;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) {
|
||||
@ -117,20 +120,49 @@ void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) {
|
||||
int width = bitmap->right - bitmap->left + 1;
|
||||
int height = bitmap->bottom - bitmap->top + 1;
|
||||
|
||||
guac_protocol_send_copy(socket,
|
||||
((guac_rdp_bitmap*) bitmap)->layer,
|
||||
0, 0, width, height,
|
||||
GUAC_COMP_OVER,
|
||||
GUAC_DEFAULT_LAYER, bitmap->left, bitmap->top);
|
||||
/* If not cached, cache if necessary */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer == NULL
|
||||
&& ((guac_rdp_bitmap*) bitmap)->used >= 1)
|
||||
guac_rdp_cache_bitmap(context, bitmap);
|
||||
|
||||
/* If cached, retrieve from cache */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer != NULL)
|
||||
guac_protocol_send_copy(socket,
|
||||
((guac_rdp_bitmap*) bitmap)->layer,
|
||||
0, 0, width, height,
|
||||
GUAC_COMP_OVER,
|
||||
GUAC_DEFAULT_LAYER, bitmap->left, bitmap->top);
|
||||
|
||||
/* Otherwise, draw with stored image data */
|
||||
else if (bitmap->data != NULL) {
|
||||
|
||||
/* Create surface from image data */
|
||||
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
||||
bitmap->data, CAIRO_FORMAT_RGB24,
|
||||
width, height, 4*bitmap->width);
|
||||
|
||||
/* Send surface to buffer */
|
||||
guac_protocol_send_png(socket,
|
||||
GUAC_COMP_OVER, GUAC_DEFAULT_LAYER,
|
||||
bitmap->left, bitmap->top, surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
}
|
||||
|
||||
/* Increment usage counter */
|
||||
((guac_rdp_bitmap*) bitmap)->used++;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap) {
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
|
||||
/* Free layer, if any */
|
||||
/* If cached, free buffer */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer != NULL)
|
||||
guac_client_free_buffer(client, ((guac_rdp_bitmap*) bitmap)->layer);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, boolean primary) {
|
||||
@ -139,10 +171,18 @@ void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, boolean
|
||||
if (primary)
|
||||
((rdp_guac_client_data*) client->data)->current_surface
|
||||
= GUAC_DEFAULT_LAYER;
|
||||
else
|
||||
|
||||
else {
|
||||
|
||||
/* If not available as a surface, make available. */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer == NULL)
|
||||
guac_rdp_cache_bitmap(context, bitmap);
|
||||
|
||||
((rdp_guac_client_data*) client->data)->current_surface
|
||||
= ((guac_rdp_bitmap*) bitmap)->layer;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed) {
|
||||
|
@ -159,9 +159,7 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
|
||||
guac_socket* socket = client->socket;
|
||||
guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap;
|
||||
|
||||
if (bitmap->layer != NULL) {
|
||||
|
||||
switch (memblt->bRop) {
|
||||
switch (memblt->bRop) {
|
||||
|
||||
/* If blackness, send black rectangle */
|
||||
case 0x00:
|
||||
@ -180,12 +178,46 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
|
||||
|
||||
/* If operation is just SRC, simply copy */
|
||||
case 0xCC:
|
||||
guac_protocol_send_copy(socket,
|
||||
bitmap->layer,
|
||||
memblt->nXSrc, memblt->nYSrc,
|
||||
memblt->nWidth, memblt->nHeight,
|
||||
GUAC_COMP_OVER,
|
||||
current_layer, memblt->nLeftRect, memblt->nTopRect);
|
||||
|
||||
/* If not cached, cache if necessary */
|
||||
if (((guac_rdp_bitmap*) bitmap)->layer == NULL
|
||||
&& ((guac_rdp_bitmap*) bitmap)->used >= 1)
|
||||
guac_rdp_cache_bitmap(context, memblt->bitmap);
|
||||
|
||||
/* If not cached, send as PNG */
|
||||
if (bitmap->layer == NULL) {
|
||||
if (memblt->bitmap->data != NULL) {
|
||||
|
||||
/* Create surface from image data */
|
||||
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
||||
memblt->bitmap->data + 4*(memblt->nXSrc + memblt->nYSrc*memblt->bitmap->width),
|
||||
CAIRO_FORMAT_RGB24,
|
||||
memblt->nWidth, memblt->nHeight,
|
||||
4*memblt->bitmap->width);
|
||||
|
||||
/* Send surface to buffer */
|
||||
guac_protocol_send_png(socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
memblt->nLeftRect, memblt->nTopRect, surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, copy */
|
||||
else
|
||||
guac_protocol_send_copy(socket,
|
||||
bitmap->layer,
|
||||
memblt->nXSrc, memblt->nYSrc,
|
||||
memblt->nWidth, memblt->nHeight,
|
||||
GUAC_COMP_OVER,
|
||||
current_layer, memblt->nLeftRect, memblt->nTopRect);
|
||||
|
||||
/* Increment usage counter */
|
||||
((guac_rdp_bitmap*) bitmap)->used++;
|
||||
|
||||
break;
|
||||
|
||||
/* If whiteness, send white rectangle */
|
||||
@ -201,6 +233,11 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
|
||||
|
||||
/* Otherwise, use transfer */
|
||||
default:
|
||||
|
||||
/* If not available as a surface, make available. */
|
||||
if (bitmap->layer == NULL)
|
||||
guac_rdp_cache_bitmap(context, memblt->bitmap);
|
||||
|
||||
guac_protocol_send_transfer(socket,
|
||||
bitmap->layer,
|
||||
memblt->nXSrc, memblt->nYSrc,
|
||||
@ -208,9 +245,10 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
|
||||
guac_rdp_rop3_transfer_function(client, memblt->bRop),
|
||||
current_layer, memblt->nLeftRect, memblt->nTopRect);
|
||||
|
||||
}
|
||||
/* Increment usage counter */
|
||||
((guac_rdp_bitmap*) bitmap)->used++;
|
||||
|
||||
} /* end if layer not NULL */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -264,3 +302,8 @@ void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) {
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_gdi_end_paint(rdpContext* context) {
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_socket_flush(client->socket);
|
||||
}
|
||||
|
||||
|
@ -39,17 +39,13 @@
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/error.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "rdp_glyph.h"
|
||||
|
||||
void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph) {
|
||||
|
||||
/* Allocate buffer */
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_socket* socket = client->socket;
|
||||
guac_layer* layer = guac_client_alloc_buffer(client);
|
||||
|
||||
int x, y, i;
|
||||
int stride;
|
||||
unsigned char* image_buffer;
|
||||
@ -59,8 +55,6 @@ void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph) {
|
||||
int width = glyph->cx;
|
||||
int height = glyph->cy;
|
||||
|
||||
cairo_surface_t* surface;
|
||||
|
||||
/* Init Cairo buffer */
|
||||
stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
|
||||
image_buffer = malloc(height*stride);
|
||||
@ -97,16 +91,9 @@ void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph) {
|
||||
}
|
||||
}
|
||||
|
||||
surface = cairo_image_surface_create_for_data(image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride);
|
||||
guac_protocol_send_png(socket, GUAC_COMP_SRC, layer, 0, 0, surface);
|
||||
guac_socket_flush(socket);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(surface);
|
||||
free(image_buffer);
|
||||
|
||||
/* Store layer */
|
||||
((guac_rdp_glyph*) glyph)->layer = layer;
|
||||
/* Store glyph surface */
|
||||
((guac_rdp_glyph*) glyph)->surface = cairo_image_surface_create_for_data(
|
||||
image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride);
|
||||
|
||||
}
|
||||
|
||||
@ -114,69 +101,139 @@ void guac_rdp_glyph_draw(rdpContext* context, rdpGlyph* glyph, int x, int y) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
|
||||
|
||||
/* Colorize glyph */
|
||||
guac_protocol_send_rect(client->socket, ((guac_rdp_glyph*) glyph)->layer,
|
||||
0, 0, glyph->cx, glyph->cy);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_ATOP, ((guac_rdp_glyph*) glyph)->layer,
|
||||
guac_client_data->foreground.red,
|
||||
guac_client_data->foreground.green,
|
||||
guac_client_data->foreground.blue,
|
||||
255);
|
||||
/* Do not attempt to draw glyphs if glyph drawing is not begun */
|
||||
if (guac_client_data->glyph_cairo == NULL)
|
||||
return;
|
||||
|
||||
/* Draw glyph */
|
||||
guac_protocol_send_copy(client->socket,
|
||||
((guac_rdp_glyph*) glyph)->layer, 0, 0, glyph->cx, glyph->cy,
|
||||
GUAC_COMP_OVER, current_layer, x, y);
|
||||
/* Use glyph as mask */
|
||||
cairo_mask_surface(
|
||||
guac_client_data->glyph_cairo,
|
||||
((guac_rdp_glyph*) glyph)->surface, x, y);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) {
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
guac_client_free_buffer(client, ((guac_rdp_glyph*) glyph)->layer);
|
||||
|
||||
unsigned char* image_buffer = cairo_image_surface_get_data(
|
||||
((guac_rdp_glyph*) glyph)->surface);
|
||||
|
||||
/* Free surface */
|
||||
cairo_surface_destroy(((guac_rdp_glyph*) glyph)->surface);
|
||||
free(image_buffer);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_glyph_begindraw(rdpContext* context,
|
||||
int x, int y, int width, int height, uint32 fgcolor, uint32 bgcolor) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
|
||||
|
||||
bgcolor = freerdp_color_convert_var(bgcolor,
|
||||
context->instance->settings->color_depth, 32,
|
||||
((rdp_freerdp_context*) context)->clrconv);
|
||||
rdp_guac_client_data* guac_client_data =
|
||||
(rdp_guac_client_data*) client->data;
|
||||
|
||||
/* Convert foreground color */
|
||||
fgcolor = freerdp_color_convert_var(fgcolor,
|
||||
context->instance->settings->color_depth, 32,
|
||||
((rdp_freerdp_context*) context)->clrconv);
|
||||
|
||||
guac_client_data->foreground.blue = fgcolor & 0x0000FF;
|
||||
guac_client_data->foreground.green = (fgcolor & 0x00FF00) >> 8;
|
||||
guac_client_data->foreground.red = (fgcolor & 0xFF0000) >> 16;
|
||||
/* Fill background with color if specified */
|
||||
if (width != 0 && height != 0) {
|
||||
|
||||
guac_client_data->background.blue = bgcolor & 0x0000FF;
|
||||
guac_client_data->background.green = (bgcolor & 0x00FF00) >> 8;
|
||||
guac_client_data->background.red = (bgcolor & 0xFF0000) >> 16;
|
||||
/* Prepare for opaque glyphs */
|
||||
guac_client_data->glyph_surface =
|
||||
guac_client_data->opaque_glyph_surface;
|
||||
|
||||
/* Paint background on destination */
|
||||
guac_protocol_send_rect(client->socket, current_layer,
|
||||
x, y, width, height);
|
||||
/* Create cairo instance */
|
||||
guac_client_data->glyph_cairo = cairo_create(
|
||||
guac_client_data->glyph_surface);
|
||||
|
||||
guac_protocol_send_cfill(client->socket,
|
||||
GUAC_COMP_OVER, current_layer,
|
||||
guac_client_data->background.red,
|
||||
guac_client_data->background.green,
|
||||
guac_client_data->background.blue,
|
||||
255);
|
||||
/* Convert background color */
|
||||
bgcolor = freerdp_color_convert_var(bgcolor,
|
||||
context->instance->settings->color_depth, 32,
|
||||
((rdp_freerdp_context*) context)->clrconv);
|
||||
|
||||
/* Fill background */
|
||||
cairo_rectangle(guac_client_data->glyph_cairo,
|
||||
x, y, width, height);
|
||||
|
||||
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 */
|
||||
else {
|
||||
|
||||
/* 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,
|
||||
int x, int y, int width, int height, uint32 fgcolor, uint32 bgcolor) {
|
||||
/* UNUSED */
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data;
|
||||
const guac_layer* current_layer = ((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 layer */
|
||||
guac_protocol_send_png(client->socket,
|
||||
GUAC_COMP_OVER, current_layer, 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