in src/common/surface.c [981:1063]
static void __guac_common_surface_put(unsigned char* src_buffer, int src_stride,
int* sx, int* sy,
guac_common_surface* dst, guac_common_rect* rect,
int opaque) {
unsigned char* dst_buffer = dst->buffer;
int dst_stride = dst->stride;
int x, y;
int min_x = rect->width;
int min_y = rect->height;
int max_x = 0;
int max_y = 0;
int orig_x = rect->x;
int orig_y = rect->y;
src_buffer += src_stride * (*sy) + 4 * (*sx);
dst_buffer += (dst_stride * rect->y) + (4 * rect->x);
/* For each row */
for (y=0; y < rect->height; y++) {
uint32_t* src_current = (uint32_t*) src_buffer;
uint32_t* dst_current = (uint32_t*) dst_buffer;
/* Copy row */
for (x=0; x < rect->width; x++) {
uint32_t color;
/* Get source and destination color values */
uint32_t src_color = *src_current;
uint32_t dst_color = *dst_current;
/* Ignore alpha channel if opaque */
if (opaque)
color = src_color | 0xFF000000;
/* Otherwise, perform alpha blending operation */
else
color = guac_common_surface_argb_blend(dst_color, src_color);
/* If the destination color is changing, update rectangle bounds
* and store the new color */
if (dst_color != color) {
if (x < min_x) min_x = x;
if (y < min_y) min_y = y;
if (x > max_x) max_x = x;
if (y > max_y) max_y = y;
*dst_current = color;
}
/* Advance to next pixel */
src_current++;
dst_current++;
}
/* Next row */
src_buffer += src_stride;
dst_buffer += dst_stride;
}
/* Restrict destination rect to only updated pixels */
if (max_x >= min_x && max_y >= min_y) {
rect->x += min_x;
rect->y += min_y;
rect->width = max_x - min_x + 1;
rect->height = max_y - min_y + 1;
}
else {
rect->width = 0;
rect->height = 0;
}
/* Update source X/Y */
*sx += rect->x - orig_x;
*sy += rect->y - orig_y;
}