* 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
#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;
case 0:
/* Send black rectangle */
- guac_protocol_send_rect(client->socket,
- GUAC_COMP_OVER, current_layer,
+ guac_protocol_send_rect(client->socket, current_layer,
dstblt->nLeftRect, dstblt->nTopRect,
- dstblt->nWidth, dstblt->nHeight,
+ dstblt->nWidth, dstblt->nHeight);
+
+ guac_protocol_send_cfill(client->socket,
+ GUAC_COMP_OVER, current_layer,
0, 0, 0, 255);
+
break;
/* Unsupported ROP3 */
guac_socket* socket = client->socket;
guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap;
- guac_composite_mode cmode = GUAC_COMP_OVER;
+ switch (memblt->bRop) {
- if (memblt->bRop == 204) cmode = GUAC_COMP_OVER;
- else if (memblt->bRop == 238) cmode = GUAC_COMP_OR;
- else if (memblt->bRop == 136) cmode = GUAC_COMP_AND;
- else if (memblt->bRop == 102) cmode = GUAC_COMP_XOR2;
- else if (memblt->bRop == 187) cmode = GUAC_COMP_NOR;
- else
- {
- guac_client_log_info (client, "guac_rdp_gdi_memblt: UNSUPPORTED opcode = %d (0x%02X)", memblt->bRop, 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:
+
+ /* 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 */
+ 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:
+
+ /* If not available as a surface, make available. */
+ if (bitmap->layer == NULL)
+ guac_rdp_cache_bitmap(context, memblt->bitmap);
- if (bitmap->layer != NULL)
- guac_protocol_send_copy(socket,
- bitmap->layer,
- memblt->nXSrc, memblt->nYSrc, memblt->nWidth, memblt->nHeight,
- cmode,
- current_layer, memblt->nLeftRect, memblt->nTopRect);
+ 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);
+
+ /* Increment usage counter */
+ ((guac_rdp_bitmap*) bitmap)->used++;
+
+ }
}
const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface;
- guac_protocol_send_rect(client->socket,
- GUAC_COMP_OVER, current_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,
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_clip(
- client->socket,
- current_layer,
- bounds->left,
- bounds->top,
+ 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);
- /* Otherwise, reset clip */
- else
- guac_protocol_send_clip(
- client->socket,
- current_layer,
- 0, 0,
- context->instance->settings->width,
- context->instance->settings->height);
+ 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);
+}
+