cursor.c (4111B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#include "config.h" 21 22#include "client.h" 23#include "common/cursor.h" 24#include "common/display.h" 25#include "common/surface.h" 26#include "vnc.h" 27 28#include <cairo/cairo.h> 29#include <guacamole/client.h> 30#include <guacamole/layer.h> 31#include <guacamole/mem.h> 32#include <guacamole/protocol.h> 33#include <guacamole/socket.h> 34#include <rfb/rfbclient.h> 35#include <rfb/rfbproto.h> 36 37/* Define cairo_format_stride_for_width() if missing */ 38#ifndef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH 39#define cairo_format_stride_for_width(format, width) (width*4) 40#endif 41 42#include <stdarg.h> 43#include <stdio.h> 44#include <stdint.h> 45#include <stdlib.h> 46#include <syslog.h> 47 48void guac_vnc_cursor(rfbClient* client, int x, int y, int w, int h, int bpp) { 49 50 guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY); 51 guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data; 52 53 /* Cairo image buffer */ 54 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w); 55 unsigned char* buffer = guac_mem_alloc(h, stride); 56 unsigned char* buffer_row_current = buffer; 57 58 /* VNC image buffer */ 59 unsigned int fb_stride = bpp * w; 60 unsigned char* fb_row_current = client->rcSource; 61 unsigned char* fb_mask = client->rcMask; 62 63 int dx, dy; 64 65 /* Copy image data from VNC client to RGBA buffer */ 66 for (dy = 0; dy<h; dy++) { 67 68 unsigned int* buffer_current; 69 unsigned char* fb_current; 70 71 /* Get current buffer row, advance to next */ 72 buffer_current = (unsigned int*) buffer_row_current; 73 buffer_row_current += stride; 74 75 /* Get current framebuffer row, advance to next */ 76 fb_current = fb_row_current; 77 fb_row_current += fb_stride; 78 79 for (dx = 0; dx<w; dx++) { 80 81 unsigned char alpha, red, green, blue; 82 unsigned int v; 83 84 /* Read current pixel value */ 85 switch (bpp) { 86 case 4: 87 v = *((uint32_t*) fb_current); 88 break; 89 90 case 2: 91 v = *((uint16_t*) fb_current); 92 break; 93 94 default: 95 v = *((uint8_t*) fb_current); 96 } 97 98 /* Translate mask to alpha */ 99 if (*(fb_mask++)) alpha = 0xFF; 100 else alpha = 0x00; 101 102 /* Translate value to RGB */ 103 red = (v >> client->format.redShift) * 0x100 / (client->format.redMax + 1); 104 green = (v >> client->format.greenShift) * 0x100 / (client->format.greenMax+ 1); 105 blue = (v >> client->format.blueShift) * 0x100 / (client->format.blueMax + 1); 106 107 /* Output ARGB */ 108 if (vnc_client->settings->swap_red_blue) 109 *(buffer_current++) = (alpha << 24) | (blue << 16) | (green << 8) | red; 110 else 111 *(buffer_current++) = (alpha << 24) | (red << 16) | (green << 8) | blue; 112 113 /* Next VNC pixel */ 114 fb_current += bpp; 115 116 } 117 } 118 119 /* Update stored cursor information */ 120 guac_common_cursor_set_argb(vnc_client->display->cursor, x, y, 121 buffer, w, h, stride); 122 123 /* Free surface */ 124 guac_mem_free(buffer); 125 126 /* libvncclient does not free rcMask as it does rcSource */ 127 free(client->rcMask); 128} 129