diff --git a/protocols/vnc/src/vnc_client.c b/protocols/vnc/src/vnc_client.c index 5e237bf2..7be32aa6 100644 --- a/protocols/vnc/src/vnc_client.c +++ b/protocols/vnc/src/vnc_client.c @@ -93,10 +93,15 @@ void guac_vnc_cursor(rfbClient* client, int x, int y, int w, int h, int bpp) { /* Copy image data from VNC client to RGBA buffer */ for (dy = 0; dyrcMask); } @@ -149,15 +158,16 @@ void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) { guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); GUACIO* io = gc->io; - png_byte** png_buffer = ((vnc_guac_client_data*) gc->data)->png_buffer; - png_byte* row; - png_byte** png_row_current = png_buffer; + /* Cairo image buffer */ + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w); + unsigned char* buffer = malloc(h*stride); + unsigned char* buffer_row_current = buffer; + cairo_surface_t* surface; unsigned int bpp = client->format.bitsPerPixel/8; - unsigned int bytesPerRow = bpp * client->width; - unsigned char* fb_row_current = client->frameBuffer + (y * bytesPerRow) + (x * bpp); - unsigned char* fb_row; + unsigned int fb_stride = bpp * client->width; + unsigned char* fb_row_current = client->frameBuffer + (y * fb_stride) + (x * bpp); unsigned int v; /* Ignore extra update if already handled by copyrect */ @@ -169,37 +179,51 @@ void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) { /* Copy image data from VNC client to PNG */ for (dy = y; dy> client->format.redShift) * 256 / (client->format.redMax+1); - *(row++) = (v >> client->format.greenShift) * 256 / (client->format.greenMax+1); - *(row++) = (v >> client->format.blueShift) * 256 / (client->format.blueMax+1); + /* Output RGB */ - fb_row += bpp; + buffer_current++; /* High 8 bits unused in Cairo's RGB24 */ + *(buffer_current++) = (v >> client->format.redShift) * 0x100 / (client->format.redMax + 1); + *(buffer_current++) = (v >> client->format.greenShift) * 0x100 / (client->format.greenMax + 1); + *(buffer_current++) = (v >> client->format.blueShift) * 0x100 / (client->format.blueMax + 1); + + fb_current += bpp; } } /* For now, only use layer 0 */ - guac_send_png(io, 0, x, y, png_buffer, w, h); + surface = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_RGB24, w, h, stride); + guac_send_png(io, 0, x, y, surface); + + /* Free surface */ + cairo_surface_destroy(surface); + free(buffer); }