in src/protocols/rdp/gdi.c [236:328]
BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
guac_client* client = ((rdp_freerdp_context*) context)->client;
guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface;
guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap;
int x = memblt->nLeftRect;
int y = memblt->nTopRect;
int w = memblt->nWidth;
int h = memblt->nHeight;
int x_src = memblt->nXSrc;
int y_src = memblt->nYSrc;
/* Make sure that the received bitmap is not NULL before processing */
if (bitmap == NULL) {
guac_client_log(client, GUAC_LOG_INFO, "NULL bitmap found in memblt instruction.");
return TRUE;
}
switch (memblt->bRop) {
/* If blackness, send black rectangle */
case 0x00:
guac_common_surface_set(current_surface, x, y, w, h,
0x00, 0x00, 0x00, 0xFF);
break;
/* If NOP, do nothing */
case 0xAA:
break;
/* If operation is just SRC, simply copy */
case 0xCC:
/* If not cached, cache if necessary */
if (bitmap->layer == NULL && 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*(x_src + y_src*memblt->bitmap->width),
CAIRO_FORMAT_RGB24, w, h, 4*memblt->bitmap->width);
/* Send surface to buffer */
guac_common_surface_draw(current_surface, x, y, surface);
/* Free surface */
cairo_surface_destroy(surface);
}
}
/* Otherwise, copy */
else
guac_common_surface_copy(bitmap->layer->surface,
x_src, y_src, w, h, current_surface, x, y);
/* Increment usage counter */
((guac_rdp_bitmap*) bitmap)->used++;
break;
/* If whiteness, send white rectangle */
case 0xFF:
guac_common_surface_set(current_surface, x, y, w, h,
0xFF, 0xFF, 0xFF, 0xFF);
break;
/* Otherwise, use transfer */
default:
/* If not available as a surface, make available. */
if (bitmap->layer == NULL)
guac_rdp_cache_bitmap(context, memblt->bitmap);
guac_common_surface_transfer(bitmap->layer->surface,
x_src, y_src, w, h,
guac_rdp_rop3_transfer_function(client, memblt->bRop),
current_surface, x, y);
/* Increment usage counter */
((guac_rdp_bitmap*) bitmap)->used++;
}
return TRUE;
}