GUACAMOLE-185: Clip copy/transfer operations to fit source as well as destination.

This commit is contained in:
Michael Jumper 2016-09-25 15:52:41 -07:00
parent 5d5fbb4d45
commit 2de7d017f5

View File

@ -1247,37 +1247,52 @@ void guac_common_surface_copy(guac_common_surface* src, int sx, int sy,
const guac_layer* src_layer = src->layer; const guac_layer* src_layer = src->layer;
const guac_layer* dst_layer = dst->layer; const guac_layer* dst_layer = dst->layer;
guac_common_rect rect; guac_common_rect srect;
guac_common_rect_init(&rect, dx, dy, w, h); guac_common_rect_init(&srect, sx, sy, w, h);
/* Clip operation */ /* Clip operation source rect */
__guac_common_clip_rect(dst, &rect, &sx, &sy); __guac_common_clip_rect(src, &srect, &dx, &dy);
if (rect.width <= 0 || rect.height <= 0) if (srect.width <= 0 || srect.height <= 0)
goto complete; goto complete;
/* Update backing surface first only if destination rect cannot intersect source rect */ guac_common_rect drect;
guac_common_rect_init(&drect, dx, dy,
srect.width, srect.height);
/* Clip operation destination rect */
__guac_common_clip_rect(dst, &drect, &srect.x, &srect.y);
if (drect.width <= 0 || drect.height <= 0)
goto complete;
/* NOTE: Being the last rectangle to be adjusted, only the width/height of
* drect is now correct! */
/* Update backing surface first only if drect cannot intersect srect */
if (src != dst) { if (src != dst) {
__guac_common_surface_transfer(src, &sx, &sy, GUAC_TRANSFER_BINARY_SRC, dst, &rect); __guac_common_surface_transfer(src, &srect.x, &srect.y,
if (rect.width <= 0 || rect.height <= 0) GUAC_TRANSFER_BINARY_SRC, dst, &drect);
if (drect.width <= 0 || drect.height <= 0)
goto complete; goto complete;
} }
/* Defer if combining */ /* Defer if combining */
if (__guac_common_should_combine(dst, &rect, 1)) if (__guac_common_should_combine(dst, &drect, 1))
__guac_common_mark_dirty(dst, &rect); __guac_common_mark_dirty(dst, &drect);
/* Otherwise, flush and draw immediately */ /* Otherwise, flush and draw immediately */
else { else {
__guac_common_surface_flush(dst); __guac_common_surface_flush(dst);
__guac_common_surface_flush(src); __guac_common_surface_flush(src);
guac_protocol_send_copy(socket, src_layer, sx, sy, rect.width, rect.height, guac_protocol_send_copy(socket, src_layer, srect.x, srect.y,
GUAC_COMP_OVER, dst_layer, rect.x, rect.y); drect.width, drect.height, GUAC_COMP_OVER, dst_layer,
drect.x, drect.y);
dst->realized = 1; dst->realized = 1;
} }
/* Update backing surface last if destination rect can intersect source rect */ /* Update backing surface last if drect can intersect srect */
if (src == dst) if (src == dst)
__guac_common_surface_transfer(src, &sx, &sy, GUAC_TRANSFER_BINARY_SRC, dst, &rect); __guac_common_surface_transfer(src, &sx, &sy,
GUAC_TRANSFER_BINARY_SRC, dst, &drect);
complete: complete:
@ -1300,37 +1315,49 @@ void guac_common_surface_transfer(guac_common_surface* src, int sx, int sy, int
const guac_layer* src_layer = src->layer; const guac_layer* src_layer = src->layer;
const guac_layer* dst_layer = dst->layer; const guac_layer* dst_layer = dst->layer;
guac_common_rect rect; guac_common_rect srect;
guac_common_rect_init(&rect, dx, dy, w, h); guac_common_rect_init(&srect, sx, sy, w, h);
/* Clip operation */ /* Clip operation source rect */
__guac_common_clip_rect(dst, &rect, &sx, &sy); __guac_common_clip_rect(src, &srect, &dx, &dy);
if (rect.width <= 0 || rect.height <= 0) if (srect.width <= 0 || srect.height <= 0)
goto complete; goto complete;
/* Update backing surface first only if destination rect cannot intersect source rect */ guac_common_rect drect;
guac_common_rect_init(&drect, dx, dy,
srect.width, srect.height);
/* Clip operation destination rect */
__guac_common_clip_rect(dst, &drect, &srect.x, &srect.y);
if (drect.width <= 0 || drect.height <= 0)
goto complete;
/* NOTE: Being the last rectangle to be adjusted, only the width/height of
* drect is now correct! */
/* Update backing surface first only if drect cannot intersect srect */
if (src != dst) { if (src != dst) {
__guac_common_surface_transfer(src, &sx, &sy, op, dst, &rect); __guac_common_surface_transfer(src, &srect.x, &srect.y, op, dst, &drect);
if (rect.width <= 0 || rect.height <= 0) if (drect.width <= 0 || drect.height <= 0)
goto complete; goto complete;
} }
/* Defer if combining */ /* Defer if combining */
if (__guac_common_should_combine(dst, &rect, 1)) if (__guac_common_should_combine(dst, &drect, 1))
__guac_common_mark_dirty(dst, &rect); __guac_common_mark_dirty(dst, &drect);
/* Otherwise, flush and draw immediately */ /* Otherwise, flush and draw immediately */
else { else {
__guac_common_surface_flush(dst); __guac_common_surface_flush(dst);
__guac_common_surface_flush(src); __guac_common_surface_flush(src);
guac_protocol_send_transfer(socket, src_layer, sx, sy, rect.width, guac_protocol_send_transfer(socket, src_layer, srect.x, srect.y,
rect.height, op, dst_layer, rect.x, rect.y); drect.width, drect.height, op, dst_layer, drect.x, drect.y);
dst->realized = 1; dst->realized = 1;
} }
/* Update backing surface last if destination rect can intersect source rect */ /* Update backing surface last if drect can intersect srect */
if (src == dst) if (src == dst)
__guac_common_surface_transfer(src, &sx, &sy, op, dst, &rect); __guac_common_surface_transfer(src, &srect.x, &srect.y, op, dst, &drect);
complete: complete: