Merge pull request #64 from flangelo/adaptive_jpeg
GUAC-240: New rectangle helper methods and utilities which will be us…
This commit is contained in:
commit
a64ed2bf72
@ -80,3 +80,190 @@ void guac_common_rect_constrain(guac_common_rect* rect, const guac_common_rect*
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int guac_common_rect_expand_to_grid(int cell_size, guac_common_rect* rect,
|
||||||
|
const guac_common_rect* max_rect) {
|
||||||
|
|
||||||
|
/* Invalid cell_size received */
|
||||||
|
if (cell_size <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Nothing to do */
|
||||||
|
if (cell_size == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Calculate how much the rectangle must be adjusted to fit within the
|
||||||
|
* given cell size. */
|
||||||
|
int dw = cell_size - rect->width % cell_size;
|
||||||
|
int dh = cell_size - rect->height % cell_size;
|
||||||
|
|
||||||
|
int dx = dw / 2;
|
||||||
|
int dy = dh / 2;
|
||||||
|
|
||||||
|
/* Set initial extents of adjusted rectangle. */
|
||||||
|
int top = rect->y - dy;
|
||||||
|
int left = rect->x - dx;
|
||||||
|
int bottom = top + rect->height + dh;
|
||||||
|
int right = left + rect->width + dw;
|
||||||
|
|
||||||
|
/* The max rectangle */
|
||||||
|
int max_left = max_rect->x;
|
||||||
|
int max_top = max_rect->y;
|
||||||
|
int max_right = max_left + max_rect->width;
|
||||||
|
int max_bottom = max_top + max_rect->height;
|
||||||
|
|
||||||
|
/* If the adjusted rectangle has sides beyond the max rectangle, or is larger
|
||||||
|
* in any direction; shift or adjust the rectangle while trying to fit in
|
||||||
|
* the grid */
|
||||||
|
|
||||||
|
/* Adjust left/right */
|
||||||
|
if (right > max_right) {
|
||||||
|
|
||||||
|
/* shift to left */
|
||||||
|
dw = right - max_right;
|
||||||
|
right -= dw;
|
||||||
|
left -= dw;
|
||||||
|
|
||||||
|
/* clamp left if too far */
|
||||||
|
if (left < max_left) {
|
||||||
|
left = max_left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (left < max_left) {
|
||||||
|
|
||||||
|
/* shift to right */
|
||||||
|
dw = max_left - left;
|
||||||
|
left += dw;
|
||||||
|
right += dw;
|
||||||
|
|
||||||
|
/* clamp right if too far */
|
||||||
|
if (right > max_right) {
|
||||||
|
right = max_right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust top/bottom */
|
||||||
|
if (bottom > max_bottom) {
|
||||||
|
|
||||||
|
/* shift up */
|
||||||
|
dh = bottom - max_bottom;
|
||||||
|
bottom -= dh;
|
||||||
|
top -= dh;
|
||||||
|
|
||||||
|
/* clamp top if too far */
|
||||||
|
if (top < max_top) {
|
||||||
|
top = max_top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (top < max_top) {
|
||||||
|
|
||||||
|
/* shift down */
|
||||||
|
dh = max_top - top;
|
||||||
|
top += dh;
|
||||||
|
bottom += dh;
|
||||||
|
|
||||||
|
/* clamp bottom if too far */
|
||||||
|
if (bottom > max_bottom) {
|
||||||
|
bottom = max_bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Commit rect */
|
||||||
|
guac_common_rect_init(rect, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int guac_common_rect_intersects(const guac_common_rect* rect,
|
||||||
|
const guac_common_rect* other) {
|
||||||
|
|
||||||
|
/* Empty (no intersection) */
|
||||||
|
if (other->x + other->width < rect->x || rect->x + rect->width < other->x ||
|
||||||
|
other->y + other->height < rect->y || rect->y + rect->height < other->y) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Complete */
|
||||||
|
else if (other->x <= rect->x && (other->x + other->width) >= (rect->x + rect->width) &&
|
||||||
|
other->y <= rect->y && (other->y + other->height) >= (rect->y + rect->height)) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
/* Partial intersection */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int guac_common_rect_clip_and_split(guac_common_rect* rect,
|
||||||
|
const guac_common_rect* hole, guac_common_rect* split_rect) {
|
||||||
|
|
||||||
|
/* Only continue if the rectangles intersects */
|
||||||
|
if (!guac_common_rect_intersects(rect, hole))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int top, left, bottom, right;
|
||||||
|
|
||||||
|
/* Clip and split top */
|
||||||
|
if (rect->y < hole->y) {
|
||||||
|
top = rect->y;
|
||||||
|
left = rect->x;
|
||||||
|
bottom = hole->y;
|
||||||
|
right = rect->x + rect->width;
|
||||||
|
guac_common_rect_init(split_rect, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
/* Re-initialize original rect */
|
||||||
|
top = hole->y;
|
||||||
|
bottom = rect->y + rect->height;
|
||||||
|
guac_common_rect_init(rect, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clip and split left */
|
||||||
|
else if (rect->x < hole->x) {
|
||||||
|
top = rect->y;
|
||||||
|
left = rect->x;
|
||||||
|
bottom = rect->y + rect->height;
|
||||||
|
right = hole->x;
|
||||||
|
guac_common_rect_init(split_rect, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
/* Re-initialize original rect */
|
||||||
|
left = hole->x;
|
||||||
|
right = rect->x + rect->width;
|
||||||
|
guac_common_rect_init(rect, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clip and split bottom */
|
||||||
|
else if (rect->y + rect->height > hole->y + hole->height) {
|
||||||
|
top = hole->y + hole->height;
|
||||||
|
left = rect->x;
|
||||||
|
bottom = rect->y + rect->height;
|
||||||
|
right = rect->x + rect->width;
|
||||||
|
guac_common_rect_init(split_rect, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
/* Re-initialize original rect */
|
||||||
|
top = rect->y;
|
||||||
|
bottom = hole->y + hole->height;
|
||||||
|
guac_common_rect_init(rect, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clip and split right */
|
||||||
|
else if (rect->x + rect->width > hole->x + hole->width) {
|
||||||
|
top = rect->y;
|
||||||
|
left = hole->x + hole->width;
|
||||||
|
bottom = rect->y + rect->height;
|
||||||
|
right = rect->x + rect->width;
|
||||||
|
guac_common_rect_init(split_rect, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
/* Re-initialize original rect */
|
||||||
|
left = rect->x;
|
||||||
|
right = hole->x + hole->width;
|
||||||
|
guac_common_rect_init(rect, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -63,6 +63,27 @@ typedef struct guac_common_rect {
|
|||||||
*/
|
*/
|
||||||
void guac_common_rect_init(guac_common_rect* rect, int x, int y, int width, int height);
|
void guac_common_rect_init(guac_common_rect* rect, int x, int y, int width, int height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand the rectangle to fit an NxN grid.
|
||||||
|
*
|
||||||
|
* The rectangle will be shifted to the left and up, expanded and adjusted to
|
||||||
|
* fit within the max bounding rect.
|
||||||
|
*
|
||||||
|
* @param cell_size
|
||||||
|
* The (NxN) grid cell size.
|
||||||
|
*
|
||||||
|
* @param rect
|
||||||
|
* The rectangle to adjust.
|
||||||
|
*
|
||||||
|
* @param max_rect
|
||||||
|
* The bounding area in which the given rect can exist.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero on success, non-zero on error.
|
||||||
|
*/
|
||||||
|
int guac_common_rect_expand_to_grid(int cell_size, guac_common_rect* rect,
|
||||||
|
const guac_common_rect* max_rect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the given rect such that it contains at least the specified minimum
|
* Extend the given rect such that it contains at least the specified minimum
|
||||||
* rect.
|
* rect.
|
||||||
@ -81,5 +102,45 @@ void guac_common_rect_extend(guac_common_rect* rect, const guac_common_rect* min
|
|||||||
*/
|
*/
|
||||||
void guac_common_rect_constrain(guac_common_rect* rect, const guac_common_rect* max);
|
void guac_common_rect_constrain(guac_common_rect* rect, const guac_common_rect* max);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether a rectangle intersects another.
|
||||||
|
*
|
||||||
|
* @param rect
|
||||||
|
* Rectangle to check for intersection.
|
||||||
|
*
|
||||||
|
* @param other
|
||||||
|
* The other rectangle.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if no intersection, 1 if partial intersection,
|
||||||
|
* 2 if first rect is completely inside the other.
|
||||||
|
*/
|
||||||
|
int guac_common_rect_intersects(const guac_common_rect* rect,
|
||||||
|
const guac_common_rect* other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip and split a rectangle into rectangles which are not covered by the
|
||||||
|
* hole rectangle.
|
||||||
|
*
|
||||||
|
* This function will clip and split single edges when executed and must be
|
||||||
|
* invoked until it returns zero. The edges are handled counter-clockwise
|
||||||
|
* starting at the top edge.
|
||||||
|
*
|
||||||
|
* @param rect
|
||||||
|
* The rectangle to be split. This rectangle will be clipped by the
|
||||||
|
* split_rect.
|
||||||
|
*
|
||||||
|
* @param hole
|
||||||
|
* The rectangle which represents the hole.
|
||||||
|
*
|
||||||
|
* @param split_rect
|
||||||
|
* Resulting split rectangle.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero when no splits were done, non-zero when the rectangle was split.
|
||||||
|
*/
|
||||||
|
int guac_common_rect_clip_and_split(guac_common_rect* rect,
|
||||||
|
const guac_common_rect* hole, guac_common_rect* split_rect);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ test_libguac_SOURCES = \
|
|||||||
common/common_suite.c \
|
common/common_suite.c \
|
||||||
common/guac_iconv.c \
|
common/guac_iconv.c \
|
||||||
common/guac_string.c \
|
common/guac_string.c \
|
||||||
|
common/guac_rect.c \
|
||||||
protocol/suite.c \
|
protocol/suite.c \
|
||||||
protocol/base64_decode.c \
|
protocol/base64_decode.c \
|
||||||
protocol/instruction_parse.c \
|
protocol/instruction_parse.c \
|
||||||
|
@ -48,6 +48,7 @@ int register_common_suite() {
|
|||||||
if (
|
if (
|
||||||
CU_add_test(suite, "guac-iconv", test_guac_iconv) == NULL
|
CU_add_test(suite, "guac-iconv", test_guac_iconv) == NULL
|
||||||
|| CU_add_test(suite, "guac-string", test_guac_string) == NULL
|
|| CU_add_test(suite, "guac-string", test_guac_string) == NULL
|
||||||
|
|| CU_add_test(suite, "guac-rect", test_guac_rect) == NULL
|
||||||
) {
|
) {
|
||||||
CU_cleanup_registry();
|
CU_cleanup_registry();
|
||||||
return CU_get_error();
|
return CU_get_error();
|
||||||
|
@ -49,5 +49,10 @@ void test_guac_string();
|
|||||||
*/
|
*/
|
||||||
void test_guac_iconv();
|
void test_guac_iconv();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for rectangle calculation functions.
|
||||||
|
*/
|
||||||
|
void test_guac_rect();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
292
tests/common/guac_rect.c
Normal file
292
tests/common/guac_rect.c
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Glyptodon LLC
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "common_suite.h"
|
||||||
|
#include "guac_rect.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <CUnit/Basic.h>
|
||||||
|
|
||||||
|
void test_guac_rect() {
|
||||||
|
|
||||||
|
guac_common_rect max;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test init method
|
||||||
|
*/
|
||||||
|
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||||
|
CU_ASSERT_EQUAL(0, max.x);
|
||||||
|
CU_ASSERT_EQUAL(0, max.y);
|
||||||
|
CU_ASSERT_EQUAL(100, max.width);
|
||||||
|
CU_ASSERT_EQUAL(100, max.height);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test constrain method
|
||||||
|
*/
|
||||||
|
guac_common_rect rect;
|
||||||
|
guac_common_rect_init(&rect, -10, -10, 110, 110);
|
||||||
|
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||||
|
guac_common_rect_constrain(&rect, &max);
|
||||||
|
CU_ASSERT_EQUAL(0, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(0, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(100, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(100, rect.height);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test extend method
|
||||||
|
*/
|
||||||
|
guac_common_rect_init(&rect, 10, 10, 90, 90);
|
||||||
|
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||||
|
guac_common_rect_extend(&rect, &max);
|
||||||
|
CU_ASSERT_EQUAL(0, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(0, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(100, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(100, rect.height);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test adjust method
|
||||||
|
*/
|
||||||
|
int cell_size = 16;
|
||||||
|
|
||||||
|
/* Simple adjustment */
|
||||||
|
guac_common_rect_init(&rect, 0, 0, 25, 25);
|
||||||
|
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||||
|
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||||
|
CU_ASSERT_EQUAL(0, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(0, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(32, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(32, rect.height);
|
||||||
|
|
||||||
|
/* Adjustment with moving of rect */
|
||||||
|
guac_common_rect_init(&rect, 75, 75, 25, 25);
|
||||||
|
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||||
|
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||||
|
CU_ASSERT_EQUAL(max.width - 32, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(max.height - 32, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(32, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(32, rect.height);
|
||||||
|
|
||||||
|
guac_common_rect_init(&rect, -5, -5, 25, 25);
|
||||||
|
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||||
|
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||||
|
CU_ASSERT_EQUAL(0, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(0, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(32, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(32, rect.height);
|
||||||
|
|
||||||
|
/* Adjustment with moving and clamping of rect */
|
||||||
|
guac_common_rect_init(&rect, 0, 0, 25, 15);
|
||||||
|
guac_common_rect_init(&max, 0, 5, 32, 15);
|
||||||
|
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||||
|
CU_ASSERT_EQUAL(max.x, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(max.y, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(max.width, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(max.height, rect.height);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rectangle intersection tests
|
||||||
|
*/
|
||||||
|
guac_common_rect min;
|
||||||
|
guac_common_rect_init(&min, 10, 10, 10, 10);
|
||||||
|
|
||||||
|
/* Rectangle intersection - empty
|
||||||
|
* rectangle is outside */
|
||||||
|
guac_common_rect_init(&rect, 25, 25, 5, 5);
|
||||||
|
int res = guac_common_rect_intersects(&rect, &min);
|
||||||
|
CU_ASSERT_EQUAL(0, res);
|
||||||
|
|
||||||
|
/* Rectangle intersection - complete
|
||||||
|
* rectangle is completely inside */
|
||||||
|
guac_common_rect_init(&rect, 11, 11, 5, 5);
|
||||||
|
res = guac_common_rect_intersects(&rect, &min);
|
||||||
|
CU_ASSERT_EQUAL(2, res);
|
||||||
|
|
||||||
|
/* Rectangle intersection - partial
|
||||||
|
* rectangle intersects UL */
|
||||||
|
guac_common_rect_init(&rect, 8, 8, 5, 5);
|
||||||
|
res = guac_common_rect_intersects(&rect, &min);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
|
||||||
|
/* Rectangle intersection - partial
|
||||||
|
* rectangle intersects LR */
|
||||||
|
guac_common_rect_init(&rect, 18, 18, 5, 5);
|
||||||
|
res = guac_common_rect_intersects(&rect, &min);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
|
||||||
|
/* Rectangle intersection - complete
|
||||||
|
* rect intersects along UL but inside */
|
||||||
|
guac_common_rect_init(&rect, 10, 10, 5, 5);
|
||||||
|
res = guac_common_rect_intersects(&rect, &min);
|
||||||
|
CU_ASSERT_EQUAL(2, res);
|
||||||
|
|
||||||
|
/* Rectangle intersection - partial
|
||||||
|
* rectangle intersects along L but outside */
|
||||||
|
guac_common_rect_init(&rect, 5, 10, 5, 5);
|
||||||
|
res = guac_common_rect_intersects(&rect, &min);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
|
||||||
|
/* Rectangle intersection - complete
|
||||||
|
* rectangle intersects along LR but rest is inside */
|
||||||
|
guac_common_rect_init(&rect, 15, 15, 5, 5);
|
||||||
|
res = guac_common_rect_intersects(&rect, &min);
|
||||||
|
CU_ASSERT_EQUAL(2, res);
|
||||||
|
|
||||||
|
/* Rectangle intersection - partial
|
||||||
|
* rectangle intersects along R but rest is outside */
|
||||||
|
guac_common_rect_init(&rect, 20, 10, 5, 5);
|
||||||
|
res = guac_common_rect_intersects(&rect, &min);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
|
||||||
|
/* Rectangle intersection - partial
|
||||||
|
* rectangle encloses min; which is a partial intersection */
|
||||||
|
guac_common_rect_init(&rect, 5, 5, 20, 20);
|
||||||
|
res = guac_common_rect_intersects(&rect, &min);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic test of clip and split method
|
||||||
|
*/
|
||||||
|
guac_common_rect_init(&min, 10, 10, 10, 10);
|
||||||
|
guac_common_rect cut;
|
||||||
|
|
||||||
|
/* Clip top */
|
||||||
|
guac_common_rect_init(&rect, 10, 5, 10, 10);
|
||||||
|
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.x);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.y);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.width);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.height);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(10, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(5, rect.height);
|
||||||
|
|
||||||
|
/* Clip bottom */
|
||||||
|
guac_common_rect_init(&rect, 10, 15, 10, 10);
|
||||||
|
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.x);
|
||||||
|
CU_ASSERT_EQUAL(20, cut.y);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.width);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.height);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(10, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(15, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(5, rect.height);
|
||||||
|
|
||||||
|
/* Clip left */
|
||||||
|
guac_common_rect_init(&rect, 5, 10, 10, 10);
|
||||||
|
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.x);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.y);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.width);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.height);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(10, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(5, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.height);
|
||||||
|
|
||||||
|
/* Clip right */
|
||||||
|
guac_common_rect_init(&rect, 15, 10, 10, 10);
|
||||||
|
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
CU_ASSERT_EQUAL(20, cut.x);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.y);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.width);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.height);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(15, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(5, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.height);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test a rectangle which completely covers the hole.
|
||||||
|
* Clip and split until done.
|
||||||
|
*/
|
||||||
|
guac_common_rect_init(&rect, 5, 5, 20, 20);
|
||||||
|
|
||||||
|
/* Clip top */
|
||||||
|
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.x);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.y);
|
||||||
|
CU_ASSERT_EQUAL(20, cut.width);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.height);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(5, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(20, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(15, rect.height);
|
||||||
|
|
||||||
|
/* Clip left */
|
||||||
|
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.x);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.y);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.width);
|
||||||
|
CU_ASSERT_EQUAL(15, cut.height);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(10, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(15, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(15, rect.height);
|
||||||
|
|
||||||
|
/* Clip bottom */
|
||||||
|
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||||
|
CU_ASSERT_EQUAL(1, res);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.x);
|
||||||
|
CU_ASSERT_EQUAL(20, cut.y);
|
||||||
|
CU_ASSERT_EQUAL(15, cut.width);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.height);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(10, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(15, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.height);
|
||||||
|
|
||||||
|
/* Clip right */
|
||||||
|
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||||
|
CU_ASSERT_EQUAL(20, cut.x);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.y);
|
||||||
|
CU_ASSERT_EQUAL(5, cut.width);
|
||||||
|
CU_ASSERT_EQUAL(10, cut.height);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(10, rect.x);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.y);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.width);
|
||||||
|
CU_ASSERT_EQUAL(10, rect.height);
|
||||||
|
|
||||||
|
/* Make sure nothing is left to do */
|
||||||
|
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||||
|
CU_ASSERT_EQUAL(0, res);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user