Merge branch 'unstable' into clipboard
This commit is contained in:
commit
e691bfb51b
@ -47,12 +47,6 @@
|
|||||||
|
|
||||||
#define RDP_DEFAULT_PORT 3389
|
#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 {
|
typedef struct rdp_guac_client_data {
|
||||||
|
|
||||||
freerdp* rdp_inst;
|
freerdp* rdp_inst;
|
||||||
@ -60,8 +54,27 @@ typedef struct rdp_guac_client_data {
|
|||||||
|
|
||||||
int mouse_button_mask;
|
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;
|
const guac_layer* current_surface;
|
||||||
|
|
||||||
|
@ -54,8 +54,14 @@ typedef struct guac_rdp_bitmap {
|
|||||||
*/
|
*/
|
||||||
guac_layer* layer;
|
guac_layer* layer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of times a bitmap has been used.
|
||||||
|
*/
|
||||||
|
int used;
|
||||||
|
|
||||||
} guac_rdp_bitmap;
|
} 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_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_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);
|
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_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect);
|
||||||
void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette);
|
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_set_bounds(rdpContext* context, rdpBounds* bounds);
|
||||||
|
void guac_rdp_gdi_end_paint(rdpContext* context);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,9 +50,9 @@ typedef struct guac_rdp_glyph {
|
|||||||
rdpGlyph 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;
|
} guac_rdp_glyph;
|
||||||
|
|
||||||
|
@ -152,6 +152,7 @@ boolean rdp_freerdp_pre_connect(freerdp* instance) {
|
|||||||
xfree(pointer);
|
xfree(pointer);
|
||||||
|
|
||||||
/* Set up GDI */
|
/* Set up GDI */
|
||||||
|
instance->update->EndPaint = guac_rdp_gdi_end_paint;
|
||||||
instance->update->Palette = guac_rdp_gdi_palette_update;
|
instance->update->Palette = guac_rdp_gdi_palette_update;
|
||||||
instance->update->SetBounds = guac_rdp_gdi_set_bounds;
|
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->mouse_handler = rdp_guac_client_mouse_handler;
|
||||||
client->key_handler = rdp_guac_client_key_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;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -400,6 +397,17 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
|||||||
/* Send connection name */
|
/* Send connection name */
|
||||||
guac_protocol_send_name(client->socket, settings->window_title);
|
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 */
|
/* Success */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "rdp_bitmap.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_client* client = ((rdp_freerdp_context*) context)->client;
|
||||||
guac_socket* socket = client->socket;
|
guac_socket* socket = client->socket;
|
||||||
@ -61,9 +61,31 @@ void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) {
|
|||||||
/* Allocate buffer */
|
/* Allocate buffer */
|
||||||
guac_layer* buffer = guac_client_alloc_buffer(client);
|
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 */
|
/* Store buffer reference in bitmap */
|
||||||
((guac_rdp_bitmap*) bitmap)->layer = buffer;
|
((guac_rdp_bitmap*) bitmap)->layer = buffer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) {
|
||||||
|
|
||||||
/* Convert image data if present */
|
/* Convert image data if present */
|
||||||
if (bitmap->data != NULL) {
|
if (bitmap->data != NULL) {
|
||||||
|
|
||||||
@ -73,40 +95,21 @@ void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) {
|
|||||||
context->instance->settings->color_depth,
|
context->instance->settings->color_depth,
|
||||||
32, ((rdp_freerdp_context*) context)->clrconv);
|
32, ((rdp_freerdp_context*) context)->clrconv);
|
||||||
|
|
||||||
/* Create surface from image data */
|
/* Free existing image, if any */
|
||||||
cairo_surface_t* surface = cairo_image_surface_create_for_data(
|
if (image_buffer != bitmap->data)
|
||||||
image_buffer, CAIRO_FORMAT_RGB24,
|
free(bitmap->data);
|
||||||
bitmap->width, bitmap->height, 4*bitmap->width);
|
|
||||||
|
|
||||||
/* Send surface to buffer */
|
/* Store converted image in bitmap */
|
||||||
guac_protocol_send_png(socket, GUAC_COMP_SRC, buffer, 0, 0, surface);
|
bitmap->data = image_buffer;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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) {
|
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 width = bitmap->right - bitmap->left + 1;
|
||||||
int height = bitmap->bottom - bitmap->top + 1;
|
int height = bitmap->bottom - bitmap->top + 1;
|
||||||
|
|
||||||
guac_protocol_send_copy(socket,
|
/* If not cached, cache if necessary */
|
||||||
((guac_rdp_bitmap*) bitmap)->layer,
|
if (((guac_rdp_bitmap*) bitmap)->layer == NULL
|
||||||
0, 0, width, height,
|
&& ((guac_rdp_bitmap*) bitmap)->used >= 1)
|
||||||
GUAC_COMP_OVER,
|
guac_rdp_cache_bitmap(context, bitmap);
|
||||||
GUAC_DEFAULT_LAYER, bitmap->left, bitmap->top);
|
|
||||||
|
/* 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) {
|
void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap) {
|
||||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||||
|
|
||||||
/* Free layer, if any */
|
/* If cached, free buffer */
|
||||||
if (((guac_rdp_bitmap*) bitmap)->layer != NULL)
|
if (((guac_rdp_bitmap*) bitmap)->layer != NULL)
|
||||||
guac_client_free_buffer(client, ((guac_rdp_bitmap*) bitmap)->layer);
|
guac_client_free_buffer(client, ((guac_rdp_bitmap*) bitmap)->layer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, boolean primary) {
|
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)
|
if (primary)
|
||||||
((rdp_guac_client_data*) client->data)->current_surface
|
((rdp_guac_client_data*) client->data)->current_surface
|
||||||
= GUAC_DEFAULT_LAYER;
|
= 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
|
((rdp_guac_client_data*) client->data)->current_surface
|
||||||
= ((guac_rdp_bitmap*) bitmap)->layer;
|
= ((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) {
|
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_socket* socket = client->socket;
|
||||||
guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap;
|
guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap;
|
||||||
|
|
||||||
if (bitmap->layer != NULL) {
|
switch (memblt->bRop) {
|
||||||
|
|
||||||
switch (memblt->bRop) {
|
|
||||||
|
|
||||||
/* If blackness, send black rectangle */
|
/* If blackness, send black rectangle */
|
||||||
case 0x00:
|
case 0x00:
|
||||||
@ -180,12 +178,46 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
|
|||||||
|
|
||||||
/* If operation is just SRC, simply copy */
|
/* If operation is just SRC, simply copy */
|
||||||
case 0xCC:
|
case 0xCC:
|
||||||
guac_protocol_send_copy(socket,
|
|
||||||
bitmap->layer,
|
/* If not cached, cache if necessary */
|
||||||
memblt->nXSrc, memblt->nYSrc,
|
if (((guac_rdp_bitmap*) bitmap)->layer == NULL
|
||||||
memblt->nWidth, memblt->nHeight,
|
&& ((guac_rdp_bitmap*) bitmap)->used >= 1)
|
||||||
GUAC_COMP_OVER,
|
guac_rdp_cache_bitmap(context, memblt->bitmap);
|
||||||
current_layer, memblt->nLeftRect, memblt->nTopRect);
|
|
||||||
|
/* 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;
|
break;
|
||||||
|
|
||||||
/* If whiteness, send white rectangle */
|
/* If whiteness, send white rectangle */
|
||||||
@ -201,6 +233,11 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
|
|||||||
|
|
||||||
/* Otherwise, use transfer */
|
/* Otherwise, use transfer */
|
||||||
default:
|
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,
|
guac_protocol_send_transfer(socket,
|
||||||
bitmap->layer,
|
bitmap->layer,
|
||||||
memblt->nXSrc, memblt->nYSrc,
|
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),
|
guac_rdp_rop3_transfer_function(client, memblt->bRop),
|
||||||
current_layer, memblt->nLeftRect, memblt->nTopRect);
|
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 <freerdp/freerdp.h>
|
||||||
|
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
|
#include <guacamole/error.h>
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "rdp_glyph.h"
|
#include "rdp_glyph.h"
|
||||||
|
|
||||||
void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph) {
|
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 x, y, i;
|
||||||
int stride;
|
int stride;
|
||||||
unsigned char* image_buffer;
|
unsigned char* image_buffer;
|
||||||
@ -59,8 +55,6 @@ void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph) {
|
|||||||
int width = glyph->cx;
|
int width = glyph->cx;
|
||||||
int height = glyph->cy;
|
int height = glyph->cy;
|
||||||
|
|
||||||
cairo_surface_t* surface;
|
|
||||||
|
|
||||||
/* Init Cairo buffer */
|
/* Init Cairo buffer */
|
||||||
stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
|
stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
|
||||||
image_buffer = malloc(height*stride);
|
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);
|
/* Store glyph surface */
|
||||||
guac_protocol_send_png(socket, GUAC_COMP_SRC, layer, 0, 0, surface);
|
((guac_rdp_glyph*) glyph)->surface = cairo_image_surface_create_for_data(
|
||||||
guac_socket_flush(socket);
|
image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride);
|
||||||
|
|
||||||
/* Free surface */
|
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
free(image_buffer);
|
|
||||||
|
|
||||||
/* Store layer */
|
|
||||||
((guac_rdp_glyph*) glyph)->layer = layer;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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;
|
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;
|
||||||
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,
|
/* Do not attempt to draw glyphs if glyph drawing is not begun */
|
||||||
GUAC_COMP_ATOP, ((guac_rdp_glyph*) glyph)->layer,
|
if (guac_client_data->glyph_cairo == NULL)
|
||||||
guac_client_data->foreground.red,
|
return;
|
||||||
guac_client_data->foreground.green,
|
|
||||||
guac_client_data->foreground.blue,
|
|
||||||
255);
|
|
||||||
|
|
||||||
/* Draw glyph */
|
/* Use glyph as mask */
|
||||||
guac_protocol_send_copy(client->socket,
|
cairo_mask_surface(
|
||||||
((guac_rdp_glyph*) glyph)->layer, 0, 0, glyph->cx, glyph->cy,
|
guac_client_data->glyph_cairo,
|
||||||
GUAC_COMP_OVER, current_layer, x, y);
|
((guac_rdp_glyph*) glyph)->surface, x, y);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) {
|
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,
|
void guac_rdp_glyph_begindraw(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) {
|
||||||
|
|
||||||
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 =
|
||||||
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
|
(rdp_guac_client_data*) client->data;
|
||||||
|
|
||||||
bgcolor = freerdp_color_convert_var(bgcolor,
|
|
||||||
context->instance->settings->color_depth, 32,
|
|
||||||
((rdp_freerdp_context*) context)->clrconv);
|
|
||||||
|
|
||||||
|
/* Convert foreground color */
|
||||||
fgcolor = freerdp_color_convert_var(fgcolor,
|
fgcolor = freerdp_color_convert_var(fgcolor,
|
||||||
context->instance->settings->color_depth, 32,
|
context->instance->settings->color_depth, 32,
|
||||||
((rdp_freerdp_context*) context)->clrconv);
|
((rdp_freerdp_context*) context)->clrconv);
|
||||||
|
|
||||||
guac_client_data->foreground.blue = fgcolor & 0x0000FF;
|
/* Fill background with color if specified */
|
||||||
guac_client_data->foreground.green = (fgcolor & 0x00FF00) >> 8;
|
if (width != 0 && height != 0) {
|
||||||
guac_client_data->foreground.red = (fgcolor & 0xFF0000) >> 16;
|
|
||||||
|
|
||||||
guac_client_data->background.blue = bgcolor & 0x0000FF;
|
/* Prepare for opaque glyphs */
|
||||||
guac_client_data->background.green = (bgcolor & 0x00FF00) >> 8;
|
guac_client_data->glyph_surface =
|
||||||
guac_client_data->background.red = (bgcolor & 0xFF0000) >> 16;
|
guac_client_data->opaque_glyph_surface;
|
||||||
|
|
||||||
/* Paint background on destination */
|
/* Create cairo instance */
|
||||||
guac_protocol_send_rect(client->socket, current_layer,
|
guac_client_data->glyph_cairo = cairo_create(
|
||||||
x, y, width, height);
|
guac_client_data->glyph_surface);
|
||||||
|
|
||||||
guac_protocol_send_cfill(client->socket,
|
/* Convert background color */
|
||||||
GUAC_COMP_OVER, current_layer,
|
bgcolor = freerdp_color_convert_var(bgcolor,
|
||||||
guac_client_data->background.red,
|
context->instance->settings->color_depth, 32,
|
||||||
guac_client_data->background.green,
|
((rdp_freerdp_context*) context)->clrconv);
|
||||||
guac_client_data->background.blue,
|
|
||||||
255);
|
/* 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,
|
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) {
|
||||||
/* 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