354 lines
16 KiB
C
354 lines
16 KiB
C
/*
|
|
* Copyright © 2022 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Authors: Matthias Clasen <mclasen@redhat.com>
|
|
*/
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
typedef enum
|
|
{
|
|
OP_UNION,
|
|
OP_INTERSECTION,
|
|
OP_DIFFERENCE,
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
} Op;
|
|
|
|
static void
|
|
test_ops_simple (void)
|
|
{
|
|
struct {
|
|
const char *in1;
|
|
const char *in2;
|
|
Op op;
|
|
const char *out;
|
|
} tests[] = {
|
|
/* partially overlapping edge */
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 150 150 L 150 250 L 250 250 Z",
|
|
OP_UNION,
|
|
"M 100 100 L 100 200 L 150 200 L 150 250 L 250 250 L 200 200 L 150 150 L 100 100 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 150 150 L 150 250 L 250 250 Z",
|
|
OP_INTERSECTION,
|
|
"M 150 200 L 200 200 L 150 150 L 150 200 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 150 150 L 150 250 L 250 250 Z",
|
|
OP_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 150 200 L 150 150 L 100 100 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 150 150 L 150 250 L 250 250 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 150 200 L 150 150 L 100 100 Z M 200 200 L 150 200 L 150 250 "
|
|
"L 250 250 L 200 200 Z" },
|
|
/* two triangles in general position */
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 170 120 L 100 240 L 170 240 Z",
|
|
OP_UNION,
|
|
"M 100 100 L 100 200 L 123.33333587646484 200 L 100 240 L 170 240 L 170 200 L 200 200 "
|
|
"L 170 170 L 170 120 L 151.57894897460938 151.57894897460938 L 100 100 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 170 120 L 100 240 L 170 240 Z",
|
|
OP_INTERSECTION,
|
|
"M 123.33333587646484 200 L 170 200 L 170 170 L 151.57894897460938 151.57894897460938 "
|
|
"L 123.33332824707031 200 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 170 120 L 100 240 L 170 240 Z",
|
|
OP_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 123.33333587646484 200 L 151.57894897460938 151.57894897460938 "
|
|
"L 100 100 Z M 170 200 L 200 200 L 170 170 L 170 200 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 170 120 L 100 240 L 170 240 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 123.33333587646484 200 L 151.57894897460938 151.57894897460938 "
|
|
"L 100 100 Z M 170 200 L 123.33333587646484 200 L 100 240 L 170 240 L 170 200 Z "
|
|
"M 170 200 L 200 200 L 170 170 L 170 200 Z M 151.57894897460938 151.57894897460938 "
|
|
"L 170 170 L 170 120 L 151.57894897460938 151.57894897460938 Z" },
|
|
/* nested contours, oriented in opposite direction */
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 120 140 L 170 190 L 120 190 Z",
|
|
OP_UNION,
|
|
"M 100 100 L 100 200 L 200 200 L 100 100 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 120 140 L 170 190 L 120 190 Z",
|
|
OP_INTERSECTION,
|
|
"M 170 190 L 120 140 L 120 190 L 170 190 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 120 140 L 170 190 L 120 190 Z",
|
|
OP_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 200 200 L 100 100 Z M 120 140 L 170 190 L 120 190 L 120 140 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 120 140 L 170 190 L 120 190 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 200 200 L 100 100 Z M 120 140 L 170 190 L 120 190 L 120 140 Z" },
|
|
/* nested contours, oriented in opposite direction, other way around */
|
|
{ "M 100 100 L 200 200 L 100 200 Z",
|
|
"M 120 140 L 120 190 L 170 190 Z",
|
|
OP_UNION,
|
|
"M 200 200 L 100 100 L 100 200 L 200 200 Z" },
|
|
{ "M 100 100 L 200 200 L 100 200 Z",
|
|
"M 120 140 L 120 190 L 170 190 Z",
|
|
OP_INTERSECTION,
|
|
"M 120 140 L 120 190 L 170 190 L 120 140 Z" },
|
|
{ "M 100 100 L 200 200 L 100 200 Z",
|
|
"M 120 140 L 120 190 L 170 190 Z",
|
|
OP_DIFFERENCE,
|
|
"M 200 200 L 100 100 L 100 200 L 200 200 Z M 120 190 L 120 140 L 170 190 L 120 190 Z" },
|
|
{ "M 100 100 L 200 200 L 100 200 Z",
|
|
"M 120 140 L 120 190 L 170 190 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 200 200 L 100 100 L 100 200 L 200 200 Z M 120 190 L 120 140 L 170 190 L 120 190 Z" },
|
|
/* nested contours, oriented in the same direction */
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 120 140 L 120 190 L 170 190 Z",
|
|
OP_UNION,
|
|
"M 100 100 L 100 200 L 200 200 L 100 100 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 120 140 L 120 190 L 170 190 Z",
|
|
OP_INTERSECTION,
|
|
"M 120 140 L 120 190 L 170 190 L 120 140 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 120 140 L 120 190 L 170 190 Z",
|
|
OP_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 200 200 L 100 100 Z M 120 190 L 120 140 L 170 190 L 120 190 Z" },
|
|
{ "M 100 100 L 100 200 L 200 200 Z",
|
|
"M 120 140 L 120 190 L 170 190 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 200 200 L 100 100 Z M 120 190 L 120 140 L 170 190 L 120 190 Z" },
|
|
/* a 3-way intersection */
|
|
{ "M 100 200 L 150 104 L 145 104 L 200 200 Z",
|
|
"M 100 108.571 L 200 108.571 L 200 50 L 100 50 Z",
|
|
OP_UNION,
|
|
"M 147.61904907226562 108.57142639160156 L 100 200 L 200 200 "
|
|
"L 147.61904907226562 108.57142639160156 Z M 100 108.57099914550781 "
|
|
"L 147.61927795410156 108.57099914550781 L 200 108.57099914550781 L 200 50 "
|
|
"L 100 50 L 100 108.57099914550781 Z" },
|
|
{ "M 100 200 L 150 104 L 145 104 L 200 200 Z",
|
|
"M 100 108.571 L 200 108.571 L 200 50 L 100 50 Z",
|
|
OP_INTERSECTION,
|
|
"M 147.61904907226562 108.57142639160156 L 150 104 L 145 104 "
|
|
"L 147.61904907226562 108.57142639160156 Z" },
|
|
{ "M 100 200 L 150 104 L 145 104 L 200 200 Z",
|
|
"M 100 108.571 L 200 108.571 L 200 50 L 100 50 Z",
|
|
OP_DIFFERENCE,
|
|
"M 147.61904907226562 108.57142639160156 L 100 200 L 200 200 "
|
|
"L 147.61904907226562 108.57142639160156 Z" },
|
|
{ "M 100 200 L 150 104 L 145 104 L 200 200 Z",
|
|
"M 100 108.571 L 200 108.571 L 200 50 L 100 50 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 147.61904907226562 108.57142639160156 L 100 200 L 200 200 "
|
|
"L 147.61904907226562 108.57142639160156 Z M 150 104 "
|
|
"L 147.61904907226562 108.57142639160156 L 200 108.57099914550781 "
|
|
"L 200 50 L 100 50 L 100 108.57099914550781 L 147.61927795410156 108.57099914550781 "
|
|
"L 145 104 L 150 104 Z" },
|
|
/* touching quadratics */
|
|
{ "M 100 100 Q 150 200 200 100 Z",
|
|
"M 100 200 Q 150 100 200 200 Z",
|
|
OP_UNION,
|
|
"M 100 100 "
|
|
"C 116.65585327148438 133.31172180175781, 133.31172180175781 149.97837829589844, 149.96757507324219 149.99998474121094 "
|
|
"C 166.64505004882812 150.0216064453125, 183.32252502441406 133.35494995117188, 200 100 "
|
|
"L 100 100 "
|
|
"Z "
|
|
"M 149.96755981445312 149.99998474121094 "
|
|
"C 133.31172180175781 150.02162170410156, 116.65585327148438 166.68827819824219, 100 200 "
|
|
"L 200 200 "
|
|
"C 183.32252502441406 166.64505004882812, 166.64505004882812 149.9783935546875, 149.96757507324219 150.00001525878906 "
|
|
"Z" },
|
|
/* overlapping quadratics, two intersections, different orientations */
|
|
{ "M 100 100 Q 150 200 200 100 Z",
|
|
"M 100 180 Q 150 80 200 180 Z",
|
|
OP_UNION,
|
|
"M 100 100 "
|
|
"C 109.21287536621094 118.42575073242188, 118.42575073242188 131.75888061523438, 127.63862609863281 139.9993896484375 "
|
|
"C 118.42625427246094 148.24038696289062, 109.21312713623047 161.57374572753906, 100 180 "
|
|
"L 200 180 "
|
|
"C 190.78688049316406 161.57374572753906, 181.57374572753906 148.24038696289062, 172.36061096191406 139.99993896484375 "
|
|
"C 181.57373046875 131.75961303710938, 190.786865234375 118.42626190185547, 200 100 "
|
|
"L 100 100 "
|
|
"Z" },
|
|
{ "M 100 100 Q 150 200 200 100 Z",
|
|
"M 100 180 Q 150 80 200 180 Z",
|
|
OP_INTERSECTION,
|
|
"M 127.63862609863281 139.9993896484375 "
|
|
"C 142.54594421386719 153.33332824707031, 157.45327758789062 153.33355712890625, 172.360595703125 140.00006103515625 "
|
|
"C 157.45353698730469 126.66668701171875, 142.54646301269531 126.66668701171875, 127.63938903808594 139.99993896484375 "
|
|
"Z" },
|
|
{ "M 100 100 Q 150 200 200 100 Z",
|
|
"M 100 180 Q 150 80 200 180 Z",
|
|
OP_DIFFERENCE,
|
|
"M 100 100 "
|
|
"C 109.21287536621094 118.42575073242188, 118.42575073242188 131.75888061523438, 127.63862609863281 139.9993896484375 "
|
|
"C 142.54646301269531 126.66668701171875, 157.45353698730469 126.66668701171875, 172.36061096191406 139.99993896484375 "
|
|
"C 181.57373046875 131.75961303710938, 190.786865234375 118.42626190185547, 200 100 "
|
|
"L 100 100 Z" },
|
|
{ "M 100 100 Q 150 200 200 100 Z",
|
|
"M 100 180 Q 150 80 200 180 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 100 100 "
|
|
"C 109.21287536621094 118.42575073242188, 118.42575073242188 131.75888061523438, 127.63862609863281 139.9993896484375 "
|
|
"C 142.54646301269531 126.66668701171875, 157.45353698730469 126.66668701171875, 172.36061096191406 139.99993896484375 "
|
|
"C 181.57373046875 131.75961303710938, 190.786865234375 118.42626190185547, 200 100 "
|
|
"L 100 100 Z "
|
|
"M 172.36062622070312 140.00006103515625 "
|
|
"C 157.45327758789062 153.33355712890625, 142.54594421386719 153.33332824707031, 127.63862609863281 139.9993896484375 "
|
|
"C 118.42625427246094 148.24038696289062, 109.21312713623047 161.57374572753906, 100 180 "
|
|
"L 200 180 "
|
|
"C 190.78688049316406 161.57374572753906, 181.57374572753906 148.24038696289062, 172.36061096191406 139.99993896484375 "
|
|
"Z" },
|
|
/* overlapping quadratics, two intersections, same orientation */
|
|
{ "M 100 100 Q 150 200 200 100 Z",
|
|
"M 100 180 L 200 180 Q 150 80 100 180 Z",
|
|
OP_UNION,
|
|
"M 100 100 "
|
|
"C 109.21287536621094 118.42575073242188, 118.42575073242188 131.75888061523438, 127.63862609863281 139.9993896484375 "
|
|
"C 118.42626190185547 148.24037170410156, 109.21312713623047 161.57373046875, 100 180 "
|
|
"L 200 180 "
|
|
"C 190.78712463378906 161.57424926757812, 181.57424926757812 148.24111938476562, 172.36137390136719 140.00062561035156 "
|
|
"C 181.57373046875 131.75961303710938, 190.786865234375 118.42626190185547, 200 100 "
|
|
"L 100 100 Z" },
|
|
{ "M 100 100 Q 150 200 200 100 Z",
|
|
"M 100 180 L 200 180 Q 150 80 100 180 Z",
|
|
OP_INTERSECTION,
|
|
"M 127.63862609863281 139.9993896484375 "
|
|
"C 142.54594421386719 153.33332824707031, 157.45327758789062 153.33355712890625, 172.360595703125 140.00006103515625 "
|
|
"C 157.45405578613281 126.66668701171875, 142.54672241210938 126.66645812988281, 127.63939666748047 139.99992370605469 Z" },
|
|
{ "M 100 100 Q 150 200 200 100 Z",
|
|
"M 100 180 L 200 180 Q 150 80 100 180 Z",
|
|
OP_DIFFERENCE,
|
|
"M 100 100 "
|
|
"C 109.21287536621094 118.42575073242188, 118.42575073242188 131.75888061523438, 127.63862609863281 139.9993896484375 "
|
|
"C 142.54672241210938 126.66645812988281, 157.45405578613281 126.66668701171875, 172.36137390136719 140.00062561035156 "
|
|
"C 181.57373046875 131.75961303710938, 190.786865234375 118.42626190185547, 200 100 "
|
|
"L 100 100 Z" },
|
|
{ "M 100 100 Q 150 200 200 100 Z",
|
|
"M 100 180 L 200 180 Q 150 80 100 180 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 100 100 "
|
|
"C 109.21287536621094 118.42575073242188, 118.42575073242188 131.75888061523438, 127.63862609863281 139.9993896484375 "
|
|
"C 142.54672241210938 126.66645812988281, 157.45405578613281 126.66668701171875, 172.36137390136719 140.00062561035156 "
|
|
"C 181.57373046875 131.75961303710938, 190.786865234375 118.42626190185547, 200 100 "
|
|
"L 100 100 Z "
|
|
"M 172.36062622070312 140.00006103515625 "
|
|
"C 157.45327758789062 153.33355712890625, 142.54594421386719 153.33332824707031, 127.63862609863281 139.9993896484375 "
|
|
"C 118.42626190185547 148.24037170410156, 109.21312713623047 161.57373046875, 100 180 "
|
|
"L 200 180 "
|
|
"C 190.78712463378906 161.57424926757812, 181.57424926757812 148.24111938476562, 172.36137390136719 140.00062561035156 "
|
|
"Z" },
|
|
/* two polygons with near edges */
|
|
{ "M 100 100 L 100 200 L 400 200 L 400 100 Z",
|
|
"M 150 103 L 250 100 L 300 103 L 250 180 Z",
|
|
OP_UNION,
|
|
"M 100 100 L 100 200 L 400 200 L 400 100 L 250 100 L 100 100 Z" },
|
|
{ "M 100 100 L 100 200 L 400 200 L 400 100 Z",
|
|
"M 150 103 L 250 100 L 300 103 L 250 180 Z",
|
|
OP_INTERSECTION,
|
|
"M 250 100 L 150 103 L 250 180 L 300 103 L 250 100 Z" },
|
|
{ "M 100 100 L 100 200 L 400 200 L 400 100 Z",
|
|
"M 150 103 L 250 100 L 300 103 L 250 180 Z",
|
|
OP_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 400 200 L 400 100 L 250 100 L 300 103 L 250 180 L 150 103 L 250 100 L 100 100 Z" },
|
|
{ "M 100 100 L 100 200 L 400 200 L 400 100 Z",
|
|
"M 150 103 L 250 100 L 300 103 L 250 180 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 100 100 L 100 200 L 400 200 L 400 100 L 250 100 L 300 103 L 250 180 L 150 103 L 250 100 L 100 100 Z" },
|
|
/* Collinear line segments */
|
|
{ "M 100 100 L 200 100 L 250 100 L 100 200 Z",
|
|
"M 150 100 L 300 100 L 300 200 Z",
|
|
OP_UNION,
|
|
"M 150 100 L 100 100 L 100 200 L 200 133.33332824707031 L 300 200 L 300 100 L 250 100 "
|
|
"L 200 100 L 150 100 Z" },
|
|
{ "M 100 100 L 200 100 L 250 100 L 100 200 Z",
|
|
"M 150 100 L 300 100 L 300 200 Z",
|
|
OP_INTERSECTION,
|
|
"M 200 100 L 150 100 L 200 133.33332824707031 L 250 100 L 200 100 Z" },
|
|
{ "M 100 100 L 200 100 L 250 100 L 100 200 Z",
|
|
"M 150 100 L 300 100 L 300 200 Z",
|
|
OP_DIFFERENCE,
|
|
"M 150 100 L 100 100 L 100 200 L 200 133.33332824707031 L 150 100 Z" },
|
|
{ "M 100 100 L 200 100 L 250 100 L 100 200 Z",
|
|
"M 150 100 L 300 100 L 300 200 Z",
|
|
OP_SYMMETRIC_DIFFERENCE,
|
|
"M 150 100 L 100 100 L 100 200 L 200 133.33332824707031 L 150 100 Z "
|
|
"M 250 100 L 200 133.33332824707031 L 300 200 L 300 100 L 250 100 Z" },
|
|
/* a complicated intersection */
|
|
{ "M 175 100 L 175 400 L 300 400 L 300 100 z",
|
|
"M 100 100 C 200 200 200 300 100 400 L 0 400 C 233.35 300 233.35 200 0 100 Z",
|
|
OP_UNION,
|
|
"M 175 100 L 175 248.73167419433594 L 175 249.94822692871094 L 175 251.26628112792969 "
|
|
"L 175 400 L 300 400 L 300 100 L 175 100 Z "
|
|
"M 174.9906005859375 248.32115173339844 "
|
|
"C 174.437255859375 198.88076782226562, 149.44038391113281 149.44038391113281, 100 100 "
|
|
"L 0 100 "
|
|
"C 115.68845367431641 149.57722473144531, 174.02178955078125 199.15444946289062, 175 248.73167419433594 "
|
|
"Z "
|
|
"M 100 400 "
|
|
"C 149.44171142578125 350.55828857421875, 174.4385986328125 301.11660766601562, 174.99066162109375 251.67486572265625 "
|
|
"C 174.02340698242188 300.84420776367188, 115.69005584716797 350.42208862304688, 0 400 "
|
|
"L 100 400 "
|
|
"Z" },
|
|
};
|
|
|
|
for (int i = 0; i < G_N_ELEMENTS (tests); i++)
|
|
{
|
|
GskPath *p1, *p2, *p;
|
|
char *s;
|
|
|
|
if (g_test_verbose ())
|
|
g_test_message ("testcase %d op %d", i, tests[i].op);
|
|
|
|
p1 = gsk_path_parse (tests[i].in1);
|
|
p2 = gsk_path_parse (tests[i].in2);
|
|
switch (tests[i].op)
|
|
{
|
|
case OP_UNION:
|
|
p = gsk_path_union (p1, p2, GSK_FILL_RULE_WINDING);
|
|
break;
|
|
case OP_INTERSECTION:
|
|
p = gsk_path_intersection (p1, p2, GSK_FILL_RULE_WINDING);
|
|
break;
|
|
case OP_DIFFERENCE:
|
|
p = gsk_path_difference (p1, p2, GSK_FILL_RULE_WINDING);
|
|
break;
|
|
case OP_SYMMETRIC_DIFFERENCE:
|
|
p = gsk_path_symmetric_difference (p1, p2, GSK_FILL_RULE_WINDING);
|
|
break;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
g_assert_nonnull (p);
|
|
s = gsk_path_to_string (p);
|
|
g_assert_cmpstr (s, ==, tests[i].out);
|
|
|
|
g_free (s);
|
|
gsk_path_unref (p);
|
|
gsk_path_unref (p1);
|
|
gsk_path_unref (p2);
|
|
}
|
|
}
|
|
|
|
int
|
|
main (int argc,
|
|
char *argv[])
|
|
{
|
|
gtk_test_init (&argc, &argv, NULL);
|
|
|
|
g_test_add_func ("/ops/simple", test_ops_simple);
|
|
|
|
return g_test_run ();
|
|
}
|