cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

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