glyph.c (5269B)
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 "color.h" 21#include "common/surface.h" 22#include "config.h" 23#include "glyph.h" 24#include "rdp.h" 25 26#include <freerdp/freerdp.h> 27#include <guacamole/client.h> 28#include <guacamole/mem.h> 29#include <winpr/wtypes.h> 30 31#include <stdint.h> 32#include <stdlib.h> 33 34/* Define cairo_format_stride_for_width() if missing */ 35#ifndef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH 36#define cairo_format_stride_for_width(format, width) (width*4) 37#endif 38 39BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph) { 40 41 int x, y, i; 42 int stride; 43 unsigned char* image_buffer; 44 unsigned char* image_buffer_row; 45 46 unsigned char* data = glyph->aj; 47 int width = glyph->cx; 48 int height = glyph->cy; 49 50 /* Init Cairo buffer */ 51 stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); 52 image_buffer = guac_mem_alloc(height, stride); 53 image_buffer_row = image_buffer; 54 55 /* Copy image data from image data to buffer */ 56 for (y = 0; y<height; y++) { 57 58 unsigned int* image_buffer_current; 59 60 /* Get current buffer row, advance to next */ 61 image_buffer_current = (unsigned int*) image_buffer_row; 62 image_buffer_row += stride; 63 64 for (x = 0; x<width;) { 65 66 /* Get byte from image data */ 67 unsigned int v = *(data++); 68 69 /* Read bits, write pixels */ 70 for (i = 0; i<8 && x<width; i++, x++) { 71 72 /* Output RGB */ 73 if (v & 0x80) 74 *(image_buffer_current++) = 0xFF000000; 75 else 76 *(image_buffer_current++) = 0x00000000; 77 78 /* Next bit */ 79 v <<= 1; 80 81 } 82 83 } 84 } 85 86 /* Store glyph surface */ 87 ((guac_rdp_glyph*) glyph)->surface = cairo_image_surface_create_for_data( 88 image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride); 89 90 return TRUE; 91 92} 93 94BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, 95 GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, 96 GLYPH_CALLBACK_INT32 w, GLYPH_CALLBACK_INT32 h, 97 GLYPH_CALLBACK_INT32 sx, GLYPH_CALLBACK_INT32 sy, 98 BOOL redundant) { 99 100 guac_client* client = ((rdp_freerdp_context*) context)->client; 101 guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; 102 guac_common_surface* current_surface = rdp_client->current_surface; 103 uint32_t fgcolor = rdp_client->glyph_color; 104 105 /* Paint with glyph as mask */ 106 guac_common_surface_paint(current_surface, x, y, ((guac_rdp_glyph*) glyph)->surface, 107 (fgcolor & 0xFF0000) >> 16, 108 (fgcolor & 0x00FF00) >> 8, 109 fgcolor & 0x0000FF); 110 111 return TRUE; 112 113} 114 115void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) { 116 117 unsigned char* image_buffer = cairo_image_surface_get_data( 118 ((guac_rdp_glyph*) glyph)->surface); 119 120 /* Free surface */ 121 cairo_surface_destroy(((guac_rdp_glyph*) glyph)->surface); 122 guac_mem_free(image_buffer); 123 124 /* NOTE: FreeRDP-allocated memory for the rdpGlyph will NOT be 125 * automatically released after this free handler is invoked, thus we must 126 * do so manually here */ 127 128 free(glyph->aj); 129 free(glyph); 130 131} 132 133BOOL guac_rdp_glyph_begindraw(rdpContext* context, 134 GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, 135 GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, 136 UINT32 fgcolor, UINT32 bgcolor, BOOL redundant) { 137 138 guac_client* client = ((rdp_freerdp_context*) context)->client; 139 guac_rdp_client* rdp_client = 140 (guac_rdp_client*) client->data; 141 142 /* Fill background with color if specified */ 143 if (width != 0 && height != 0 && !redundant) { 144 145 /* Convert background color */ 146 bgcolor = guac_rdp_convert_color(context, bgcolor); 147 148 guac_common_surface_set(rdp_client->current_surface, 149 x, y, width, height, 150 (bgcolor & 0xFF0000) >> 16, 151 (bgcolor & 0x00FF00) >> 8, 152 (bgcolor & 0x0000FF), 153 0xFF); 154 155 } 156 157 /* Convert foreground color */ 158 rdp_client->glyph_color = guac_rdp_convert_color(context, fgcolor); 159 160 return TRUE; 161 162} 163 164BOOL guac_rdp_glyph_enddraw(rdpContext* context, 165 GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, 166 GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, 167 UINT32 fgcolor, UINT32 bgcolor) { 168 /* IGNORE */ 169 return TRUE; 170} 171