X-Git-Url: http://git.alex.org.uk diff --git a/src/rdp_gdi.c b/src/rdp_gdi.c index 5e5ea20..7153f4b 100644 --- a/src/rdp_gdi.c +++ b/src/rdp_gdi.c @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Matt Hortman * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -40,10 +41,96 @@ #include #include "client.h" +#include "rdp_bitmap.h" + +guac_transfer_function guac_rdp_rop3_transfer_function(guac_client* client, + int rop3) { + + /* Translate supported ROP3 opcodes into composite modes */ + switch (rop3) { + + /* "DSon" !(src | dest) */ + case 0x11: return GUAC_TRANSFER_BINARY_NOR; + + /* "DSna" !src & dest */ + case 0x22: return GUAC_TRANSFER_BINARY_NSRC_AND; + + /* "Sn" !src */ + case 0x33: return GUAC_TRANSFER_BINARY_NSRC; + + /* "SDna" (src & !dest) */ + case 0x44: return GUAC_TRANSFER_BINARY_NDEST_AND; + + /* "Dn" !dest */ + case 0x55: return GUAC_TRANSFER_BINARY_NDEST; + + /* "SRCINVERT" (src ^ dest) */ + case 0x66: return GUAC_TRANSFER_BINARY_XOR; + + /* "DSan" !(src & dest) */ + case 0x77: return GUAC_TRANSFER_BINARY_NAND; + + /* "SRCAND" (src & dest) */ + case 0x88: return GUAC_TRANSFER_BINARY_AND; + + /* "DSxn" !(src ^ dest) */ + case 0x99: return GUAC_TRANSFER_BINARY_XNOR; + + /* "MERGEPAINT" (!src | dest)*/ + case 0xBB: return GUAC_TRANSFER_BINARY_NSRC_OR; + + /* "SDno" (src | !dest) */ + case 0xDD: return GUAC_TRANSFER_BINARY_NDEST_OR; + + /* "SRCPAINT" (src | dest) */ + case 0xEE: return GUAC_TRANSFER_BINARY_OR; + + /* 0x00 = "BLACKNESS" (0) */ + /* 0xAA = "NOP" (dest) */ + /* 0xCC = "SRCCOPY" (src) */ + /* 0xFF = "WHITENESS" (1) */ + + } + + /* Log warning if ROP3 opcode not supported */ + guac_client_log_info (client, "guac_rdp_rop3_transfer_function: " + "UNSUPPORTED opcode = 0x%02X", rop3); + + /* Default to BINARY_SRC */ + return GUAC_TRANSFER_BINARY_SRC; + +} void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) { + guac_client* client = ((rdp_freerdp_context*) context)->client; - guac_client_log_info(client, "guac_rdp_gdi_dstblt()"); + const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; + + switch (dstblt->bRop) { + + /* Blackness */ + case 0: + + /* Send black rectangle */ + guac_protocol_send_rect(client->socket, current_layer, + dstblt->nLeftRect, dstblt->nTopRect, + dstblt->nWidth, dstblt->nHeight); + + guac_protocol_send_cfill(client->socket, + GUAC_COMP_OVER, current_layer, + 0, 0, 0, 255); + + break; + + /* Unsupported ROP3 */ + default: + guac_client_log_info(client, + "guac_rdp_gdi_dstblt(rop3=%i)", dstblt->bRop); + + } + + + } void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { @@ -52,25 +139,96 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { } void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) { + guac_client* client = ((rdp_freerdp_context*) context)->client; - guac_client_log_info(client, "guac_rdp_gdi_scrblt()"); + const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; + + /* Copy screen rect to current surface */ + guac_protocol_send_copy(client->socket, + GUAC_DEFAULT_LAYER, + scrblt->nXSrc, scrblt->nYSrc, scrblt->nWidth, scrblt->nHeight, + GUAC_COMP_OVER, current_layer, + scrblt->nLeftRect, scrblt->nTopRect); + } void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { + guac_client* client = ((rdp_freerdp_context*) context)->client; - guac_client_log_info(client, "guac_rdp_gdi_memblt()"); + const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; + guac_socket* socket = client->socket; + guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap; + + if (bitmap->layer != NULL) { + + switch (memblt->bRop) { + + /* If blackness, send black rectangle */ + case 0x00: + guac_protocol_send_rect(client->socket, current_layer, + memblt->nLeftRect, memblt->nTopRect, + memblt->nWidth, memblt->nHeight); + + guac_protocol_send_cfill(client->socket, + GUAC_COMP_OVER, current_layer, + 0x00, 0x00, 0x00, 0xFF); + break; + + /* If NOP, do nothing */ + case 0xAA: + break; + + /* 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); + break; + + /* If whiteness, send white rectangle */ + case 0xFF: + guac_protocol_send_rect(client->socket, current_layer, + memblt->nLeftRect, memblt->nTopRect, + memblt->nWidth, memblt->nHeight); + + guac_protocol_send_cfill(client->socket, + GUAC_COMP_OVER, current_layer, + 0xFF, 0xFF, 0xFF, 0xFF); + break; + + /* Otherwise, use transfer */ + default: + guac_protocol_send_transfer(socket, + bitmap->layer, + memblt->nXSrc, memblt->nYSrc, + memblt->nWidth, memblt->nHeight, + guac_rdp_rop3_transfer_function(client, memblt->bRop), + current_layer, memblt->nLeftRect, memblt->nTopRect); + + } + + } /* end if layer not NULL */ + } void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) { guac_client* client = ((rdp_freerdp_context*) context)->client; - uint32 color = freerdp_color_convert(opaque_rect->color, - context->instance->settings->color_depth, 32, &guac_rdp_clrconv); + uint32 color = freerdp_color_convert_var(opaque_rect->color, + context->instance->settings->color_depth, 32, + ((rdp_freerdp_context*) context)->clrconv); + + const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; - guac_protocol_send_rect(client->socket, - GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, + guac_protocol_send_rect(client->socket, current_layer, opaque_rect->nLeftRect, opaque_rect->nTopRect, - opaque_rect->nWidth, opaque_rect->nHeight, + opaque_rect->nWidth, opaque_rect->nHeight); + + guac_protocol_send_cfill(client->socket, + GUAC_COMP_OVER, current_layer, (color >> 16) & 0xFF, (color >> 8 ) & 0xFF, (color ) & 0xFF, @@ -78,4 +236,36 @@ void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect } +void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette) { + + CLRCONV* clrconv = ((rdp_freerdp_context*) context)->clrconv; + clrconv->palette->count = palette->number; + clrconv->palette->entries = palette->entries; + +} + +void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; + + /* Reset clip */ + guac_protocol_send_reset(client->socket, current_layer); + + /* Set clip if specified */ + if (bounds != NULL) { + guac_protocol_send_rect(client->socket, current_layer, + bounds->left, bounds->top, + bounds->right - bounds->left + 1, + bounds->bottom - bounds->top + 1); + + guac_protocol_send_clip(client->socket, current_layer); + } + +} + +void guac_rdp_gdi_end_paint(rdpContext* context) { + guac_client* client = ((rdp_freerdp_context*) context)->client; + guac_socket_flush(client->socket); +}