From a0197ee2c2fb21dcd1fd8f81033bd08296ecc7a2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 27 Feb 2016 10:07:55 -0800 Subject: [PATCH] GUAC-236: Implement buffer resize. --- src/guacenc/buffer.c | 66 +++++++++++++++++++++++++++++++++++++++++++- src/guacenc/buffer.h | 20 ++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/guacenc/buffer.c b/src/guacenc/buffer.c index 56cc409b..999893f9 100644 --- a/src/guacenc/buffer.c +++ b/src/guacenc/buffer.c @@ -23,22 +23,86 @@ #include "config.h" #include "buffer.h" +#include + #include guacenc_buffer* guacenc_buffer_alloc() { return calloc(1, sizeof(guacenc_buffer)); } +/** + * Frees the underlying image data, surface, and graphics context of the given + * buffer, marking each as unallocated. + * + * @param buffer + * The guacenc_buffer whose image data, surface, and graphics context + * should be freed. + */ +static void guacenc_buffer_free_image(guacenc_buffer* buffer) { + + /* Free graphics context */ + if (buffer->cairo != NULL) { + cairo_destroy(buffer->cairo); + buffer->cairo = NULL; + } + + /* Free Cairo surface */ + if (buffer->surface != NULL) { + cairo_surface_destroy(buffer->surface); + buffer->surface = NULL; + } + + /* Free image data (previously wrapped by Cairo surface */ + free(buffer->image); + buffer->image = NULL; + +} + void guacenc_buffer_free(guacenc_buffer* buffer) { + guacenc_buffer_free_image(buffer); free(buffer); } int guacenc_buffer_resize(guacenc_buffer* buffer, int width, int height) { - /* STUB */ + /* Simply deallocate if new image has absolutely no pixels */ + if (width == 0 || height == 0) { + guacenc_buffer_free_image(buffer); + buffer->width = width; + buffer->height = height; + buffer->stride = 0; + return 0; + } + /* Allocate data for new image */ + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); + unsigned char* image = calloc(1, stride*height); + + /* Wrap data in surface */ + cairo_surface_t* surface = cairo_image_surface_create_for_data(image, + CAIRO_FORMAT_ARGB32, width, height, stride); + + /* Obtain graphics context of new surface */ + cairo_t* cairo = cairo_create(surface); + + /* Copy old surface, if defined */ + if (buffer->surface != NULL) { + cairo_set_source_surface(cairo, buffer->surface, 0, 0); + cairo_paint(cairo); + cairo_set_source_rgba(cairo, 0.0, 0.0, 0.0, 1.0); + } + + /* Update properties */ buffer->width = width; buffer->height = height; + buffer->stride = stride; + + /* Replace old image */ + guacenc_buffer_free_image(buffer); + buffer->image = image; + buffer->surface = surface; + buffer->cairo = cairo; return 0; diff --git a/src/guacenc/buffer.h b/src/guacenc/buffer.h index ed6f6ac2..d2d7f152 100644 --- a/src/guacenc/buffer.h +++ b/src/guacenc/buffer.h @@ -25,6 +25,8 @@ #include "config.h" +#include + /** * The image and size storage for either a buffer (a Guacamole layer with a * negative index) or a layer (a Guacamole layer with a non-negative index). @@ -46,6 +48,24 @@ typedef struct guacenc_buffer { */ int stride; + /** + * The underlying image data of this surface. If the width or height of + * this surface are 0, this will be NULL. + */ + unsigned char* image; + + /** + * The Cairo surface wrapping the underlying image data of this surface. If + * the width or height of this surface are 0, this will be NULL. + */ + cairo_surface_t* surface; + + /** + * The current graphics context of the Cairo surface. If the width or + * height of this surface are 0, this will be NULL. + */ + cairo_t* cairo; + } guacenc_buffer; /**