Compare commits

..

5 Commits

Author SHA1 Message Date
Matthias Clasen 5efa3400d9 xxx: Plug a memory leak in GtkPopover 2020-12-13 10:30:22 -05:00
Matthias Clasen 41c6bfec67 Fix gsk_spline_decompose_arc
For short segments (angle < tolerance), we were not
emitting any curve at all when decomposing arc.
2020-12-13 10:30:22 -05:00
Matthias Clasen 5a4d19644f pathbuilder: Misc docs improvements 2020-12-13 10:30:22 -05:00
Matthias Clasen c9e9f6184d path: Misc doc improvements 2020-12-13 10:30:22 -05:00
Matthias Clasen 3a3c16c475 Add gsk_path_measure_get_{path,tolerance}
These are just nice apis to have and avoid having to carry
these around as extra arguments in many places.

This was showing up as inconvenience in writing tests
for the measure apis.
2020-12-13 10:30:22 -05:00
8 changed files with 72 additions and 135 deletions
+27 -13
View File
@@ -464,12 +464,7 @@ gsk_rect_contour_get_winding (const GskContour *contour,
graphene_rect_init (&rect, self->x, self->y, self->width, self->height);
if (graphene_rect_contains_point (&rect, point))
{
if ((self->width > 0) != (self->height > 0))
return 1;
else
return -1;
}
return -1;
return 0;
}
@@ -792,10 +787,32 @@ gsk_circle_contour_get_winding (const GskContour *contour,
if (fabs (self->start_angle - self->end_angle) >= 360)
{
if (self->end_angle > self->start_angle)
return -1;
}
else
{
/* Check if the point and the midpoint are on the same side
* of the chord through start and end.
*/
double mid_angle = (self->end_angle - self->start_angle) / 2;
graphene_point_t start = GRAPHENE_POINT_INIT (self->center.x + cos (DEG_TO_RAD (self->start_angle)) * self->radius,
self->center.y + sin (DEG_TO_RAD (self->start_angle)) * self->radius);
graphene_point_t mid = GRAPHENE_POINT_INIT (self->center.x + cos (DEG_TO_RAD (mid_angle)) * self->radius,
self->center.y + sin (DEG_TO_RAD (mid_angle)) * self->radius);
graphene_point_t end = GRAPHENE_POINT_INIT (self->center.x + cos (DEG_TO_RAD (self->end_angle)) * self->radius,
self->center.y + sin (DEG_TO_RAD (self->end_angle)) * self->radius);
graphene_vec2_t n, m;
float a, b;
graphene_vec2_init (&n, start.y - end.y, end.x - start.x);
graphene_vec2_init (&m, mid.x, mid.y);
a = graphene_vec2_dot (&m, &n);
graphene_vec2_init (&m, point->x, point->y);
b = graphene_vec2_dot (&m, &n);
if ((a < 0) != (b < 0))
return -1;
else
return 1;
}
return 0;
@@ -1629,10 +1646,7 @@ gsk_contour_get_winding (const GskContour *self,
const graphene_point_t *point,
gboolean *on_edge)
{
if (gsk_contour_get_flags (self) & GSK_PATH_CLOSED)
return self->klass->get_winding (self, measure_data, point, on_edge);
return 0;
return self->klass->get_winding (self, measure_data, point, on_edge);
}
void
+9 -6
View File
@@ -212,7 +212,11 @@ gsk_path_get_contour (GskPath *path,
* Converts @self into a human-readable string representation suitable
* for printing.
*
* The string is compatible with SVG paths.
* The string is compatible with
* [SVG path syntax](https://www.w3.org/TR/SVG11/paths.html#PathData),
* with the exception that conic curves will generate a string of the
* form "O x1 y1, x2 y2, w" where x1, y1 is the control point, x2, y2
* is the end point, and w is the weight.
**/
void
gsk_path_print (GskPath *self,
@@ -301,7 +305,7 @@ gsk_path_to_cairo_add_op (GskPathOperation op,
* with Cairo.
*
* This may cause some suboptimal conversions to be performed as Cairo
* may not perform all features of #GskPath.
* may not support all features of #GskPath.
*
* This function does not clear the existing Cairo path. Call
* cairo_new_path() if you want this.
@@ -366,10 +370,9 @@ gsk_path_is_empty (GskPath *path)
* axis-aligned line.
*
* If the path is empty, %FALSE is returned and @bounds are set to
* graphene_rect_zero().
* This is different from the case where the path is a signle point at
* the origin, where the @bounds will also be set to the zero rectangle
* but 0 will be returned.
* graphene_rect_zero(). This is different from the case where the path
* is a single point at the origin, where the @bounds will also be set to
* the zero rectangle but 0 will be returned.
*
* Returns: %TRUE if the path has bounds, %FALSE if the path is known
* to be empty and have no bounds.
+1 -1
View File
@@ -706,7 +706,7 @@ gsk_path_builder_rel_conic_to (GskPathBuilder *builder,
* gsk_path_builder_close:
* @builder: a #GskPathBuilder
*
* Ends the current contour with a line back to the start point.
* Ends the current contour with a line back to the start point.
*
* Note that this is different from calling gsk_path_builder_line_to()
* with the start point in that the contour will be closed. A closed
+28
View File
@@ -166,6 +166,34 @@ gsk_path_measure_unref (GskPathMeasure *self)
g_free (self);
}
/**
* gsk_path_measure_get_path:
* @self: a #GskPathMeasure
*
* Returns the path that the measure was created for.
*
* Returns: (transfer none): the path of @self
*/
GskPath *
gsk_path_measure_get_path (GskPathMeasure *self)
{
return self->path;
}
/**
* gsk_path_measure_get_tolerance:
* @self: a #GskPathMeasure
*
* Returns the tolerance that the measure was created with.
*
* Returns: the tolerance of @self
*/
float
gsk_path_measure_get_tolerance (GskPathMeasure *self)
{
return self->tolerance;
}
/**
* gsk_path_measure_get_length:
* @self: a #GskPathMeasure
+5
View File
@@ -44,6 +44,11 @@ GskPathMeasure * gsk_path_measure_ref (GskPathMeasure
GDK_AVAILABLE_IN_ALL
void gsk_path_measure_unref (GskPathMeasure *self);
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_measure_get_path (GskPathMeasure *self);
GDK_AVAILABLE_IN_ALL
float gsk_path_measure_get_tolerance (GskPathMeasure *self);
GDK_AVAILABLE_IN_ALL
float gsk_path_measure_get_length (GskPathMeasure *self);
GDK_AVAILABLE_IN_ALL
+1 -1
View File
@@ -192,7 +192,7 @@ gsk_spline_decompose_arc (const graphene_point_t *center,
}
else if (ABS (step) < tolerance)
{
return TRUE;
return gsk_spline_decompose_arc_segment (center, radius, start_angle, end_angle, curve_func, user_data);
}
n_segments = arc_segments_needed (ABS (step), radius, tolerance);
+1
View File
@@ -1414,6 +1414,7 @@ create_arrow_render_node (GtkPopover *popover)
stroke = gsk_stroke_new (border.bottom + 1);
gtk_snapshot_push_stroke (snapshot, path, stroke);
gsk_stroke_free (stroke);
gsk_path_get_bounds (path, &bounds);
gtk_snapshot_append_color (snapshot, border_color, &bounds);
-114
View File
@@ -306,115 +306,6 @@ test_serialize_custom_contours (void)
gsk_path_unref (path1);
}
static void
test_in_fill_rect1 (void)
{
GskPathBuilder *builder;
GskPath *path;
GskPathMeasure *measure;
builder = gsk_path_builder_new ();
gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (0, 0, 100, 100));
path = gsk_path_builder_free_to_path (builder);
measure = gsk_path_measure_new (path);
g_assert_true (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_WINDING));
g_assert_true (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_EVEN_ODD));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (-50, 50), GSK_FILL_RULE_WINDING));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (-50, 50), GSK_FILL_RULE_EVEN_ODD));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, -50), GSK_FILL_RULE_WINDING));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, -50), GSK_FILL_RULE_EVEN_ODD));
gsk_path_measure_unref (measure);
gsk_path_unref (path);
}
static void
test_in_fill_rect2 (void)
{
GskPathBuilder *builder;
GskPath *path;
GskPathMeasure *measure;
builder = gsk_path_builder_new ();
gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (100, 0, -100, 100));
path = gsk_path_builder_free_to_path (builder);
measure = gsk_path_measure_new (path);
g_assert_true (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_WINDING));
g_assert_true (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_EVEN_ODD));
gsk_path_measure_unref (measure);
gsk_path_unref (path);
}
static void
test_in_fill_rect3 (void)
{
GskPathBuilder *builder;
GskPath *path;
GskPathMeasure *measure;
builder = gsk_path_builder_new ();
gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (0, 0, 100, 100));
gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (10, 10, 80, 80));
path = gsk_path_builder_free_to_path (builder);
measure = gsk_path_measure_new (path);
g_assert_true (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_WINDING));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_EVEN_ODD));
gsk_path_measure_unref (measure);
gsk_path_unref (path);
}
static void
test_in_fill_rect4 (void)
{
GskPathBuilder *builder;
GskPath *path;
GskPathMeasure *measure;
builder = gsk_path_builder_new ();
gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (0, 0, 100, 100));
gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (90, 10, -80, 80));
path = gsk_path_builder_free_to_path (builder);
measure = gsk_path_measure_new (path);
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_WINDING));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_EVEN_ODD));
gsk_path_measure_unref (measure);
gsk_path_unref (path);
}
static void
test_in_fill_circle (void)
{
GskPathBuilder *builder;
GskPath *path;
GskPathMeasure *measure;
builder = gsk_path_builder_new ();
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (50, 50), 50);
path = gsk_path_builder_free_to_path (builder);
measure = gsk_path_measure_new (path);
g_assert_true (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_WINDING));
g_assert_true (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (50, 50), GSK_FILL_RULE_EVEN_ODD));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (0, 0), GSK_FILL_RULE_WINDING));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (0, 0), GSK_FILL_RULE_EVEN_ODD));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (100, 100), GSK_FILL_RULE_WINDING));
g_assert_false (gsk_path_measure_in_fill (measure, &GRAPHENE_POINT_INIT (100, 100), GSK_FILL_RULE_EVEN_ODD));
gsk_path_measure_unref (measure);
gsk_path_unref (path);
}
int
main (int argc,
char *argv[])
@@ -423,11 +314,6 @@ main (int argc,
g_test_add_func ("/path/rsvg-parse", test_rsvg_parse);
g_test_add_func ("/path/serialize-custom-contours", test_serialize_custom_contours);
g_test_add_func ("/path/in-fill/rect1", test_in_fill_rect1);
g_test_add_func ("/path/in-fill/rect2", test_in_fill_rect2);
g_test_add_func ("/path/in-fill/rect3", test_in_fill_rect3);
g_test_add_func ("/path/in-fill/rect4", test_in_fill_rect4);
g_test_add_func ("/path/in-fill/circle", test_in_fill_circle);
return g_test_run ();
}