/* * Copyright © 2013 Sam Spilsbury * * 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 (including the * next paragraph) 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. */ /* * Each vertex clipping test begins with a brief textual introduction using a * coordinate system with X growing right and Y growing down as a convention. */ #include "config.h" #include "weston-test-runner.h" #include "vertex-clipping.h" #define BOX(x1,y1,x2,y2) { { x1, y1 }, { x2, y2 } } #define BOX32(x1,y1,x2,y2) { x1, y1, x2, y2 } #define QUAD(x1,y1,x2,y2) { { x1, y1 }, { x2, y1 }, { x2, y2 }, { x1, y2 } } struct vertex_clip_test_data { union { struct clipper_vertex box[2]; /* Common clipping API. */ struct pixman_box32 box32; /* Pixman clipping API. */ }; struct clipper_vertex polygon[8]; struct clipper_vertex clipped[8]; int polygon_n; int clipped_n; bool aligned; }; /* Compare clipped vertices to expected vertices. While the clipper guarantees * correct winding order, it doesn't specify which vertex is emitted first. This * function takes care of finding the first expected vertex in the clipped array * before comparing the entire series. */ static void assert_vertices(const struct clipper_vertex *clipped, int clipped_n, const struct clipper_vertex *expected, int expected_n) { int first, i, j; /* Is the number of clipped vertices correct? */ assert(clipped_n == expected_n); for (first = 0; first < clipped_n; first++) if (clipper_float_difference(clipped[first].x, expected[0].x) == 0.0f && clipper_float_difference(clipped[first].y, expected[0].y) == 0.0f) break; /* Have we found the first expected vertex? */ assert(!clipped_n || first != clipped_n); /* Do the remaining vertices match? */ for (i = 1; i < clipped_n; i++) { j = (i + first) % clipped_n; assert(clipper_float_difference(clipped[j].x, expected[i].x) == 0.0f && clipper_float_difference(clipped[j].y, expected[i].y) == 0.0f); } } /* clipper_clip() tests: */ static const struct vertex_clip_test_data clip_expected_data[] = { /* Quad inside box. */ { .box = BOX (50.0f, 50.0f, 100.0f, 100.0f), .polygon = QUAD(51.0f, 51.0f, 99.0f, 99.0f), .clipped = QUAD(51.0f, 51.0f, 99.0f, 99.0f), .polygon_n = 4, .clipped_n = 4, }, /* Quad bottom edge outside of box. */ { .box = BOX (50.0f, 50.0f, 100.0f, 100.0f), .polygon = QUAD(51.0f, 51.0f, 99.0f, 101.0f), .clipped = QUAD(51.0f, 51.0f, 99.0f, 100.0f), .polygon_n = 4, .clipped_n = 4, }, /* Quad top edge outside of box. */ { .box = BOX (50.0f, 50.0f, 100.0f, 100.0f), .polygon = QUAD(51.0f, 49.0f, 99.0f, 99.0f), .clipped = QUAD(51.0f, 50.0f, 99.0f, 99.0f), .polygon_n = 4, .clipped_n = 4, }, /* Quad left edge outside of box. */ { .box = BOX (50.0f, 50.0f, 100.0f, 100.0f), .polygon = QUAD(49.0f, 51.0f, 99.0f, 99.0f), .clipped = QUAD(50.0f, 51.0f, 99.0f, 99.0f), .polygon_n = 4, .clipped_n = 4, }, /* Quad right edge outside of box. */ { .box = BOX (50.0f, 50.0f, 100.0f, 100.0f), .polygon = QUAD(51.0f, 51.0f, 101.0f, 99.0f), .clipped = QUAD(51.0f, 51.0f, 100.0f, 99.0f), .polygon_n = 4, .clipped_n = 4, }, /* Rotated quad with edges adjacent to box corners. */ { .box = BOX(50.0f, 50.0f, 100.0f, 100.0f), .polygon = {{ 25.0f, 75.0f}, {75.0f, 25.0f}, {125.0f, 75.0f}, {75.0f, 125.0f}}, .clipped = QUAD(50.0f, 50.0f, 100.0f, 100.0f), .polygon_n = 4, .clipped_n = 4, }, /* Rotated quad with edges cutting out box corners. */ { .box = BOX(50.0f, 50.0f, 100.0f, 100.0f), .polygon = {{ 37.5f, 75.0f}, { 75.0f, 37.5f}, {112.5f, 75.0f}, { 75.0f, 112.5f}}, .clipped = {{ 62.5f, 50.0f}, { 87.5f, 50.0f}, {100.0f, 62.5f}, {100.0f, 87.5f}, { 87.5f, 100.0f}, { 62.5f, 100.0f}, { 50.0f, 87.5f}, { 50.0f, 62.5f}}, .polygon_n = 4, .clipped_n = 8, }, /* Same as above using counter-clockwise winding. */ { .box = BOX(50.0f, 50.0f, 100.0f, 100.0f), .polygon = {{ 37.5f, 75.0f}, { 75.0f, 112.5f}, {112.5f, 75.0f}, { 75.0f, 37.5f}}, .clipped = {{ 62.5f, 50.0f}, { 50.0f, 62.5f}, { 50.0f, 87.5f}, { 62.5f, 100.0f}, { 87.5f, 100.0f}, {100.0f, 87.5f}, {100.0f, 62.5f}, { 87.5f, 50.0f}}, .polygon_n = 4, .clipped_n = 8, }, }; TEST_P(clip_expected, clip_expected_data) { struct vertex_clip_test_data *tdata = data; struct clipper_vertex clipped[8]; int clipped_n; clipped_n = clipper_clip(tdata->polygon, tdata->polygon_n, tdata->box, clipped); assert_vertices(clipped, clipped_n, tdata->clipped, tdata->clipped_n); } TEST(clip_size_too_high) { struct clipper_vertex polygon[8] = {}, box[2] = {}; assert(clipper_clip(polygon, 9, box, NULL) == -1); } /* clipper_quad_clip() tests: */ static const struct vertex_clip_test_data quad_clip_expected_data[] = { /* Aligned quad clipping with adjacent edges: */ /* Box top/left corner adjacent to polygon bottom/right corner. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-1.00f, -1.00f, -0.50f, -0.50f), .clipped_n = 0, }, /* Box top edge adjacent to polygon bottom edge. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-0.25f, -1.00f, 0.25f, -0.50f), .clipped_n = 0, }, /* Box top/right corner adjacent to polygon bottom/left corner. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD( 0.50f, -1.00f, 1.00f, -0.50f), .clipped_n = 0, }, /* Box left edge adjacent to polygon right edge. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-1.00f, -0.25f, -0.50f, 0.25f), .clipped_n = 0, }, /* Box right edge adjacent to polygon left edge. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD( 0.50f, -0.25f, 1.00f, 0.25f), .clipped_n = 0, }, /* Box bottom/left corner adjacent to polygon top/right corner. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-1.00f, 0.50f, -0.50f, 1.00f), .clipped_n = 0, }, /* Box bottom edge adjacent to polygon top edge. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-0.25f, 0.50f, 0.25f, 1.00f), .clipped_n = 0, }, /* Box bottom/right corner adjacent to polygon top/left corner. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD( 0.50f, 0.50f, 1.00f, 1.00f), .clipped_n = 0, }, /* Aligned quad clipping with intersecting edges: */ /* Box top/left corner intersects polygon bottom/right corner. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-0.75f, -0.75f, -0.25f, -0.25f), .clipped = QUAD(-0.50f, -0.50f, -0.25f, -0.25f), .clipped_n = 4, }, /* Box top edge intersects polygon bottom edge. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-0.25f, -0.75f, 0.25f, -0.25f), .clipped = QUAD(-0.25f, -0.50f, 0.25f, -0.25f), .clipped_n = 4, }, /* Box top/right corner intersects polygon bottom/left corner. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD( 0.25f, -0.75f, 0.75f, -0.25f), .clipped = QUAD( 0.25f, -0.50f, 0.50f, -0.25f), .clipped_n = 4, }, /* Box left edge intersects polygon right edge. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-0.75f, -0.25f, -0.25f, 0.25f), .clipped = QUAD(-0.50f, -0.25f, -0.25f, 0.25f), .clipped_n = 4, }, /* Box right edge intersects polygon left edge. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD( 0.25f, -0.25f, 0.75f, 0.25f), .clipped = QUAD( 0.25f, -0.25f, 0.50f, 0.25f), .clipped_n = 4, }, /* Box bottom/left corner intersects polygon top/right corner. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-0.75f, 0.25f, -0.25f, 0.75f), .clipped = QUAD(-0.50f, 0.25f, -0.25f, 0.50f), .clipped_n = 4, }, /* Box bottom edge intersects polygon top edge. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD(-0.25f, 0.25f, 0.25f, 0.75f), .clipped = QUAD(-0.25f, 0.25f, 0.25f, 0.50f), .clipped_n = 4, }, /* Box bottom/right corner intersects polygon top/left corner. */ { .aligned = true, .box = BOX (-0.50f, -0.50f, 0.50f, 0.50f), .polygon = QUAD( 0.25f, 0.25f, 0.75f, 0.75f), .clipped = QUAD( 0.25f, 0.25f, 0.50f, 0.50f), .clipped_n = 4, }, /* Rotated quad clipping with adjacent edges: */ /* Box top/left corner adjacent to polygon bottom corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.75f, -0.75f}, {-0.50f, -1.00f}, {-0.25f, -0.75f}, {-0.50f, -0.50f}}, .clipped_n = 0, }, /* Box top edge adjacent to polygon bottom corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.25f, -0.75f}, { 0.00f, -1.00f}, { 0.25f, -0.75f}, { 0.00f, -0.50f}}, .clipped_n = 0, }, /* Box top/right corner adjacent to polygon bottom corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{ 0.25f, -0.75f}, { 0.50f, -1.00f}, { 0.75f, -0.75f}, { 0.50f, -0.50f}}, .clipped_n = 0, }, /* Box left edge adjacent to polygon right corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-1.00f, 0.00f}, {-0.75f, -0.25f}, {-0.50f, 0.00f}, {-0.75f, 0.25f}}, .clipped_n = 0, }, /* Box right edge adjacent to polygon left corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{ 0.50f, 0.00f}, { 0.75f, -0.25f}, { 1.00f, 0.00f}, { 0.75f, 0.25f}}, .clipped_n = 0, }, /* Box bottom/left corner adjacent to polygon top corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.75f, 0.75f}, {-0.50f, 0.50f}, {-0.25f, 0.75f}, {-0.50f, 1.00f}}, .clipped_n = 0, }, /* Box bottom edge adjacent to polygon top corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.25f, 0.75f}, { 0.00f, 0.50f}, { 0.25f, 0.75f}, { 0.00f, 1.00f}}, .clipped_n = 0, }, /* Box bottom/right corner adjacent to polygon top corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{ 0.25f, 0.75f}, { 0.50f, 0.50f}, { 0.75f, 0.75f}, { 0.50f, 1.00f}}, .clipped_n = 0, }, /* Rotated quad clipping with slightly intersecting edges: */ /* Box top/left corner slightly intersects polygon bottom/right edge. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.75f, -0.50f}, {-0.50f, -0.75f}, {-0.25f, -0.50f}, {-0.50f, -0.25f}}, .clipped = {{-0.50f, -0.25f}, {-0.50f, -0.50f}, {-0.25f, -0.50f}}, .clipped_n = 3, }, /* Box top edge slightly intersects polygon bottom corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.25f, -0.50f}, { 0.00f, -0.75f}, { 0.25f, -0.50f}, { 0.00f, -0.25f}}, .clipped = {{-0.25f, -0.50f}, { 0.25f, -0.50f}, { 0.00f, -0.25f}}, .clipped_n = 3, }, /* Box top/right corner slightly intersects polygon bottom/left edge. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{ 0.25f, -0.50f}, { 0.50f, -0.75f}, { 0.75f, -0.50f}, { 0.50f, -0.25f}}, .clipped = {{ 0.25f, -0.50f}, { 0.50f, -0.50f}, { 0.50f, -0.25f}}, .clipped_n = 3, }, /* Box left edge slightly intersects polygon right corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.75f, 0.00f}, {-0.50f, -0.25f}, {-0.25f, 0.00f}, {-0.50f, 0.25f}}, .clipped = {{-0.50f, -0.25f}, {-0.25f, 0.00f}, {-0.50f, 0.25f}}, .clipped_n = 3, }, /* Box right edge slightly intersects polygon left corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{ 0.25f, 0.00f}, { 0.50f, -0.25f}, { 0.75f, 0.00f}, { 0.50f, 0.25f}}, .clipped = {{ 0.25f, 0.00f}, { 0.50f, -0.25f}, { 0.50f, 0.25f}}, .clipped_n = 3, }, /* Box bottom/left corner slightly intersects polygon top/right edge. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.75f, 0.50f}, {-0.50f, 0.25f}, {-0.25f, 0.50f}, {-0.50f, 0.75f}}, .clipped = {{-0.50f, 0.25f}, {-0.25f, 0.50f}, {-0.50f, 0.50f}}, .clipped_n = 3, }, /* Box bottom edge slightly intersects polygon top corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.25f, 0.50f}, { 0.00f, 0.25f}, { 0.25f, 0.50f}, { 0.00f, 0.75f}}, .clipped = {{-0.25f, 0.50f}, { 0.00f, 0.25f}, { 0.25f, 0.50f}}, .clipped_n = 3, }, /* Box bottom/right corner slightly intersects polygon top/left edge. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{ 0.25f, 0.50f}, { 0.50f, 0.25f}, { 0.75f, 0.50f}, { 0.50f, 0.75f}}, .clipped = {{ 0.25f, 0.50f}, { 0.50f, 0.25f}, { 0.50f, 0.50f}}, .clipped_n = 3, }, /* Rotated quad clipping with largely intersecting edges: */ /* Box top/left corner largely intersects polygon bottom/right edge. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.625f, -0.375f}, {-0.375f, -0.625f}, {-0.125f, -0.375f}, {-0.375f, -0.125f}}, .clipped = {{-0.500f, -0.500f}, {-0.250f, -0.500f}, {-0.125f, -0.375f}, {-0.375f, -0.125f}, {-0.500f, -0.250f}}, .clipped_n = 5, }, /* Box top edge largely intersects polygon bottom corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.250f, -0.375f}, { 0.000f, -0.625f}, { 0.250f, -0.375f}, { 0.000f, -0.125f}}, .clipped = {{-0.125f, -0.500f}, { 0.125f, -0.500f}, { 0.250f, -0.375f}, { 0.000f, -0.125f}, {-0.250f, -0.375f}}, .clipped_n = 5, }, /* Box top/right corner largely intersects polygon bottom/left edge. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{ 0.125f, -0.375f}, { 0.375f, -0.625f}, { 0.625f, -0.375f}, { 0.375f, -0.125f}}, .clipped = {{ 0.125f, -0.375f}, { 0.250f, -0.500f}, { 0.500f, -0.500f}, { 0.500f, -0.250f}, { 0.375f, -0.125f}}, .clipped_n = 5, }, /* Box left edge largely intersects polygon right corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.625f, 0.000f}, {-0.375f, -0.250f}, {-0.125f, 0.000f}, {-0.375f, 0.250f}}, .clipped = {{-0.500f, 0.125f}, {-0.500f, -0.125f}, {-0.375f, -0.250f}, {-0.125f, 0.000f}, {-0.375f, 0.250f}}, .clipped_n = 5, }, /* Box right edge largely intersects polygon left corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{ 0.125f, 0.000f}, { 0.375f, -0.250f}, { 0.625f, 0.000f}, { 0.375f, 0.250f}}, .clipped = {{ 0.125f, 0.000f}, { 0.375f, -0.250f}, { 0.500f, -0.125f}, { 0.500f, 0.125f}, { 0.375f, 0.250f}}, .clipped_n = 5, }, /* Box bottom/left corner largely intersects polygon top/right edge. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.625f, 0.375f}, {-0.375f, 0.125f}, {-0.125f, 0.375f}, {-0.375f, 0.625f}}, .clipped = {{-0.500f, 0.500f}, {-0.500f, 0.250f}, {-0.375f, 0.125f}, {-0.125f, 0.375f}, {-0.250f, 0.500f}}, .clipped_n = 5, }, /* Box bottom edge largely intersects polygon top corner. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.250f, 0.375f}, { 0.000f, 0.125f}, { 0.250f, 0.375f}, { 0.000f, 0.625f}}, .clipped = {{-0.125f, 0.500f}, {-0.250f, 0.375f}, { 0.000f, 0.125f}, { 0.250f, 0.375f}, { 0.125f, 0.500f}}, .clipped_n = 5, }, /* Box bottom/right corner largely intersects polygon top/left edge. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{ 0.125f, 0.375f}, { 0.375f, 0.125f}, { 0.625f, 0.375f}, { 0.375f, 0.625f}}, .clipped = {{ 0.125f, 0.375f}, { 0.375f, 0.125f}, { 0.500f, 0.250f}, { 0.500f, 0.500f}, { 0.250f, 0.500f}}, .clipped_n = 5, }, /* Box intersects entire smaller aligned quad of different winding * orders and first edge orientations: */ /* Clockwise winding and top/left initial vertex. */ { .aligned = true, .box = BOX(-0.50f, -0.50f, 0.50f, 0.50f), .polygon = {{-0.25f, -0.25f}, { 0.25f, -0.25f}, { 0.25f, 0.25f}, {-0.25f, 0.25f}}, .clipped = {{-0.25f, -0.25f}, { 0.25f, -0.25f}, { 0.25f, 0.25f}, {-0.25f, 0.25f}}, .clipped_n = 4, }, /* Clockwise winding and top/right initial vertex. */ { .aligned = true, .box = BOX(-0.50f, -0.50f, 0.50f, 0.50f), .polygon = {{ 0.25f, -0.25f}, { 0.25f, 0.25f}, {-0.25f, 0.25f}, {-0.25f, -0.25f}}, .clipped = {{ 0.25f, -0.25f}, { 0.25f, 0.25f}, {-0.25f, 0.25f}, {-0.25f, -0.25f}}, .clipped_n = 4, }, /* Clockwise winding and bottom/right initial vertex. */ { .aligned = true, .box = BOX(-0.50f, -0.50f, 0.50f, 0.50f), .polygon = {{ 0.25f, 0.25f}, {-0.25f, 0.25f}, {-0.25f, -0.25f}, { 0.25f, -0.25f}}, .clipped = {{ 0.25f, 0.25f}, {-0.25f, 0.25f}, {-0.25f, -0.25f}, { 0.25f, -0.25f}}, .clipped_n = 4, }, /* Clockwise winding and bottom/left initial vertex. */ { .aligned = true, .box = BOX(-0.50f, -0.50f, 0.50f, 0.50f), .polygon = {{-0.25f, 0.25f}, {-0.25f, -0.25f}, { 0.25f, -0.25f}, { 0.25f, 0.25f}}, .clipped = {{-0.25f, 0.25f}, {-0.25f, -0.25f}, { 0.25f, -0.25f}, { 0.25f, 0.25f}}, .clipped_n = 4, }, /* Counter-clockwise winding and top/left initial vertex. */ { .aligned = true, .box = BOX(-0.50f, -0.50f, 0.50f, 0.50f), .polygon = {{-0.25f, -0.25f}, {-0.25f, 0.25f}, { 0.25f, 0.25f}, { 0.25f, -0.25f}}, .clipped = {{-0.25f, -0.25f}, {-0.25f, 0.25f}, { 0.25f, 0.25f}, { 0.25f, -0.25f}}, .clipped_n = 4, }, /* Counter-clockwise winding and top/right initial vertex. */ { .aligned = true, .box = BOX(-0.50f, -0.50f, 0.50f, 0.50f), .polygon = {{ 0.25f, -0.25f}, {-0.25f, -0.25f}, {-0.25f, 0.25f}, { 0.25f, 0.25f}}, .clipped = {{ 0.25f, -0.25f}, {-0.25f, -0.25f}, {-0.25f, 0.25f}, { 0.25f, 0.25f}}, .clipped_n = 4, }, /* Counter-clockwise winding and bottom/right initial vertex. */ { .aligned = true, .box = BOX(-0.50f, -0.50f, 0.50f, 0.50f), .polygon = {{ 0.25f, 0.25f}, { 0.25f, -0.25f}, {-0.25f, -0.25f}, {-0.25f, 0.25f}}, .clipped = {{ 0.25f, 0.25f}, { 0.25f, -0.25f}, {-0.25f, -0.25f}, {-0.25f, 0.25f}}, .clipped_n = 4, }, /* Counter-clockwise winding and bottom/left initial vertex. */ { .aligned = true, .box = BOX(-0.50f, -0.50f, 0.50f, 0.50f), .polygon = {{-0.25f, 0.25f}, { 0.25f, 0.25f}, { 0.25f, -0.25f}, {-0.25f, -0.25f}}, .clipped = {{-0.25f, 0.25f}, { 0.25f, 0.25f}, { 0.25f, -0.25f}, {-0.25f, -0.25f}}, .clipped_n = 4, }, /* Miscellaneous cases: */ /* Box intersects entire same size aligned quad. */ { .aligned = true, .box = BOX (-0.5f, -0.5f, 0.5f, 0.5f), .polygon = QUAD(-0.5f, -0.5f, 0.5f, 0.5f), .clipped = QUAD(-0.5f, -0.5f, 0.5f, 0.5f), .clipped_n = 4, }, /* Box intersects entire rotated quad. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.5f, 0.0f}, { 0.0f, -0.5f}, { 0.5f, 0.0f}, { 0.0f, 0.5f}}, .clipped = {{-0.5f, 0.0f}, { 0.0f, -0.5f}, { 0.5f, 0.0f}, { 0.0f, 0.5f}}, .clipped_n = 4, }, /* Box intersects rotated quad cutting out the 4 corners. */ { .aligned = false, .box = BOX(-0.5f, -0.5f, 0.5f, 0.5f), .polygon = {{-0.75f, 0.00f}, { 0.00f, -0.75f}, { 0.75f, 0.00f}, { 0.00f, 0.75f}}, .clipped = {{-0.50f, 0.25f}, {-0.50f, -0.25f}, {-0.25f, -0.50f}, { 0.25f, -0.50f}, { 0.50f, -0.25f}, { 0.50f, 0.25f}, { 0.25f, 0.50f}, {-0.25f, 0.50f}}, .clipped_n = 8, }, }; TEST_P(quad_clip_expected, quad_clip_expected_data) { struct vertex_clip_test_data *tdata = data; struct clipper_vertex clipped[8]; struct clipper_quad quad; int clipped_n; clipper_quad_init(&quad, tdata->polygon, tdata->aligned); clipped_n = clipper_quad_clip(&quad, tdata->box, clipped); assert_vertices(clipped, clipped_n, tdata->clipped, tdata->clipped_n); } /* clipper_quad_clip_box32() tests: */ static const struct vertex_clip_test_data quad_clip_box32_expected_data[] = { /* Box bottom/right corner intersects polygon top/left corner. */ { .aligned = true, .box32 = BOX32(-3, -3, -1, -1), .polygon = QUAD (-2.5f, -2.5f, 2.5f, 2.5f), .clipped = QUAD (-2.5f, -2.5f, -1.0f, -1.0f), .clipped_n = 4, }, /* Box bottom/left corner intersects polygon top/right corner. */ { .aligned = true, .box32 = BOX32( 1, -3, 3, -1), .polygon = QUAD (-2.5f, -2.5f, 2.5f, 2.5f), .clipped = QUAD ( 1.0f, -2.5f, 2.5f, -1.0f), .clipped_n = 4, }, /* Box top/right corner intersects polygon bottom/left corner. */ { .aligned = true, .box32 = BOX32(-3, 1, -1, 3), .polygon = QUAD (-2.5f, -2.5f, 2.5f, 2.5f), .clipped = QUAD (-2.5f, 1.0f, -1.0f, 2.5f), .clipped_n = 4, }, /* Box top/left corner intersects polygon bottom/right corner. */ { .aligned = true, .box32 = BOX32( 1, 1, 3, 3), .polygon = QUAD (-2.5f, -2.5f, 2.5f, 2.5f), .clipped = QUAD ( 1.0f, 1.0f, 2.5f, 2.5f), .clipped_n = 4, }, }; TEST_P(quad_clip_box32_expected, quad_clip_box32_expected_data) { struct vertex_clip_test_data *tdata = data; struct clipper_vertex clipped[8]; struct clipper_quad quad; int clipped_n; clipper_quad_init(&quad, tdata->polygon, tdata->aligned); clipped_n = clipper_quad_clip_box32(&quad, &tdata->box32, clipped); assert_vertices(clipped, clipped_n, tdata->clipped, tdata->clipped_n); } /* clipper_float_difference() tests: */ TEST(float_difference_different) { assert(clipper_float_difference(1.0f, 0.0f) == 1.0f); } TEST(float_difference_same) { assert(clipper_float_difference(1.0f, 1.0f) == 0.0f); }