in src/common/surface.c [1131:1224]
static void __guac_common_surface_transfer(guac_common_surface* src, int* sx, int* sy,
guac_transfer_function op,
guac_common_surface* dst, guac_common_rect* rect) {
unsigned char* src_buffer = src->buffer;
unsigned char* dst_buffer = dst->buffer;
int x, y;
int src_stride, dst_stride;
int step = 1;
int min_x = rect->width - 1;
int min_y = rect->height - 1;
int max_x = 0;
int max_y = 0;
int orig_x = rect->x;
int orig_y = rect->y;
/* Copy forwards only if destination is in a different surface or is before source */
if (src != dst || rect->y < *sy || (rect->y == *sy && rect->x < *sx)) {
src_buffer += src->stride * (*sy) + 4 * (*sx);
dst_buffer += (dst->stride * rect->y) + (4 * rect->x);
src_stride = src->stride;
dst_stride = dst->stride;
step = 1;
}
/* Otherwise, copy backwards */
else {
src_buffer += src->stride * (*sy + rect->height - 1) + 4 * (*sx + rect->width - 1);
dst_buffer += dst->stride * (rect->y + rect->height - 1) + 4 * (rect->x + rect->width - 1);
src_stride = -src->stride;
dst_stride = -dst->stride;
step = -1;
}
/* 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;
/* Transfer each pixel in row */
for (x=0; x < rect->width; x++) {
if (__guac_common_surface_transfer_int(op, src_current, dst_current)) {
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;
}
src_current += step;
dst_current += step;
}
/* Next row */
src_buffer += src_stride;
dst_buffer += dst_stride;
}
/* Translate X coordinate space of moving backwards */
if (step < 0) {
int old_max_x = max_x;
max_x = rect->width - 1 - min_x;
min_x = rect->width - 1 - old_max_x;
}
/* Translate Y coordinate space of moving backwards */
if (dst_stride < 0) {
int old_max_y = max_y;
max_y = rect->height - 1 - min_y;
min_y = rect->height - 1 - old_max_y;
}
/* 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;
}