summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/public/cairo-sections.txt1
-rw-r--r--doc/public/tmpl/cairo-paths.sgml10
-rw-r--r--src/cairo-gstate.c11
-rw-r--r--src/cairo.c30
-rw-r--r--src/cairo.h5
-rw-r--r--src/cairoint.h7
-rw-r--r--test/get-path-extents.c33
7 files changed, 87 insertions, 10 deletions
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index 44842717..88e9c8ae 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -326,6 +326,7 @@ cairo_text_path
cairo_rel_curve_to
cairo_rel_line_to
cairo_rel_move_to
+cairo_path_extents
</SECTION>
<SECTION>
diff --git a/doc/public/tmpl/cairo-paths.sgml b/doc/public/tmpl/cairo-paths.sgml
index 3be71a45..3d68342c 100644
--- a/doc/public/tmpl/cairo-paths.sgml
+++ b/doc/public/tmpl/cairo-paths.sgml
@@ -236,3 +236,13 @@ Creating paths and manipulating path data
@dy:
+<!-- ##### FUNCTION cairo_path_extents ##### -->
+<para>
+
+</para>
+
+@cr:
+@x1:
+@y1:
+@x2:
+@y2:
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 3577d845..a00a52c1 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -818,6 +818,17 @@ _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
}
*/
+void
+_cairo_gstate_path_extents (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
+ double *x1, double *y1,
+ double *x2, double *y2)
+{
+ _cairo_path_fixed_bounds (path, x1, y1, x2, y2, gstate->tolerance);
+
+ _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
+}
+
static cairo_status_t
_cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
diff --git a/src/cairo.c b/src/cairo.c
index 4a7aec11..42411cee 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1870,6 +1870,36 @@ cairo_close_path (cairo_t *cr)
slim_hidden_def(cairo_close_path);
/**
+ * cairo_path_extents:
+ * @cr: a cairo context
+ * @x1: left of the resulting extents
+ * @y1: top of the resulting extents
+ * @x2: right of the resulting extents
+ * @y2: bottom of the resulting extents
+ *
+ * Computes a bounding box in user coordinates covering the points
+ * on the current path. If the current path is empty,
+ * returns an empty rectangle (0,0, 0,0). Stroke parameters,
+ * surface dimensions and clipping are not taken into account. This
+ * will be the same as the value returned by cairo_fill_extents()
+ * unless the area enclosed by the path is empty.
+ *
+ * Since: 1.6
+ **/
+void
+cairo_path_extents (cairo_t *cr,
+ double *x1, double *y1, double *x2, double *y2)
+{
+ if (cr->status)
+ return;
+
+ _cairo_gstate_path_extents (cr->gstate,
+ cr->path,
+ x1, y1, x2, y2);
+}
+slim_hidden_def (cairo_path_extents);
+
+/**
* cairo_paint:
* @cr: a cairo context
*
diff --git a/src/cairo.h b/src/cairo.h
index 4c58c144..157b6e13 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -584,6 +584,11 @@ cairo_stroke_to_path (cairo_t *cr);
cairo_public void
cairo_close_path (cairo_t *cr);
+cairo_public void
+cairo_path_extents (cairo_t *cr,
+ double *x1, double *y1,
+ double *x2, double *y2);
+
/* Painting functions */
cairo_public void
cairo_paint (cairo_t *cr);
diff --git a/src/cairoint.h b/src/cairoint.h
index ea3c2b6f..7c1d2d50 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1005,6 +1005,12 @@ _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
double *x2, double *y2,
cairo_bool_t *is_tight);
+cairo_private void
+_cairo_gstate_path_extents (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
+ double *x1, double *y1,
+ double *x2, double *y2);
+
cairo_private cairo_status_t
_cairo_gstate_paint (cairo_gstate_t *gstate);
@@ -2220,6 +2226,7 @@ slim_hidden_proto (cairo_matrix_translate);
slim_hidden_proto (cairo_move_to);
slim_hidden_proto (cairo_new_path);
slim_hidden_proto (cairo_paint);
+slim_hidden_proto (cairo_path_extents);
slim_hidden_proto (cairo_pattern_create_for_surface);
slim_hidden_proto (cairo_pattern_create_rgb);
slim_hidden_proto (cairo_pattern_create_rgba);
diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index b20b13f2..a06e301d 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -36,7 +36,7 @@ cairo_test_t test = {
draw
};
-enum ExtentsType { FILL, STROKE };
+enum ExtentsType { FILL, STROKE, PATH };
enum Relation { EQUALS, APPROX_EQUALS, CONTAINS };
@@ -59,6 +59,10 @@ check_extents (const char *message, cairo_t *cr, enum ExtentsType type,
type_string = "stroke";
cairo_stroke_extents (cr, &ext_x1, &ext_y1, &ext_x2, &ext_y2);
break;
+ case PATH:
+ type_string = "path";
+ cairo_path_extents (cr, &ext_x1, &ext_y1, &ext_x2, &ext_y2);
+ break;
}
/* let empty rects match */
@@ -118,7 +122,8 @@ draw (cairo_t *cr, int width, int height)
phase = "No path";
if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
- !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0))
+ !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 0, 0, 0, 0))
ret = CAIRO_TEST_FAILURE;
cairo_save (cr2);
@@ -164,7 +169,8 @@ draw (cairo_t *cr, int width, int height)
cairo_move_to (cr2, 0, 180);
cairo_line_to (cr2, 750, 180);
if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
- !check_extents (phase, cr2, STROKE, EQUALS, -5, 175, 760, 10))
+ !check_extents (phase, cr2, STROKE, EQUALS, -5, 175, 760, 10) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 0, 180, 755, 0))
ret = CAIRO_TEST_FAILURE;
cairo_new_path (cr2);
cairo_restore (cr2);
@@ -173,7 +179,8 @@ draw (cairo_t *cr, int width, int height)
cairo_save (cr2);
cairo_rectangle (cr2, 10, 10, 80, 80);
if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 80, 80) ||
- !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 90, 90))
+ !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 90, 90) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 80, 80))
ret = CAIRO_TEST_FAILURE;
cairo_new_path (cr2);
cairo_restore (cr2);
@@ -183,7 +190,8 @@ draw (cairo_t *cr, int width, int height)
cairo_rectangle (cr2, 10, 10, 10, 10);
cairo_rectangle (cr2, 20, 20, 10, 10);
if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 20, 20) ||
- !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 30, 30))
+ !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 30, 30) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 20, 20))
ret = CAIRO_TEST_FAILURE;
cairo_new_path (cr2);
cairo_restore (cr2);
@@ -197,7 +205,8 @@ draw (cairo_t *cr, int width, int height)
/* miter joins protrude 5*(1+sqrt(2)) above the top-left corner and to
the right of the bottom-right corner */
if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 80, 80) ||
- !check_extents (phase, cr2, STROKE, CONTAINS, 0, 5, 95, 95))
+ !check_extents (phase, cr2, STROKE, CONTAINS, 0, 5, 95, 95) ||
+ !check_extents (phase, cr2, PATH, CONTAINS, 10, 10, 80, 80))
ret = CAIRO_TEST_FAILURE;
cairo_new_path (cr2);
cairo_restore (cr2);
@@ -240,7 +249,8 @@ draw (cairo_t *cr, int width, int height)
cairo_text_path (cr2, "The quick brown fox jumped over the lazy dog.");
cairo_set_line_width (cr2, 2.0);
if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, extents.width, extents.height) ||
- !check_extents (phase, cr2, STROKE, EQUALS, -1, -1, extents.width+2, extents.height+2))
+ !check_extents (phase, cr2, STROKE, EQUALS, -1, -1, extents.width+2, extents.height+2) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 0, 0, extents.width, extents.height))
ret = CAIRO_TEST_FAILURE;
cairo_new_path (cr2);
cairo_restore (cr2);
@@ -250,7 +260,8 @@ draw (cairo_t *cr, int width, int height)
cairo_scale (cr2, 2, 2);
cairo_rectangle (cr2, 5, 5, 40, 40);
if (!check_extents (phase, cr2, FILL, EQUALS, 5, 5, 40, 40) ||
- !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 50, 50))
+ !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 50, 50) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 5, 5, 40, 40))
ret = CAIRO_TEST_FAILURE;
cairo_new_path (cr2);
cairo_restore (cr2);
@@ -262,7 +273,8 @@ draw (cairo_t *cr, int width, int height)
cairo_rectangle (cr2, 5, 5, 40, 40);
cairo_restore (cr2);
if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 80, 80) ||
- !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 90, 90))
+ !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 90, 90) ||
+ !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 80, 80))
ret = CAIRO_TEST_FAILURE;
cairo_new_path (cr2);
cairo_restore (cr2);
@@ -281,7 +293,8 @@ draw (cairo_t *cr, int width, int height)
the largest axis-aligned square is a bit over 38 on either side of
the axes. */
if (!check_extents (phase, cr2, FILL, CONTAINS, -35, -35, 35, 35) ||
- !check_extents (phase, cr2, STROKE, CONTAINS, -38, -38, 38, 38))
+ !check_extents (phase, cr2, STROKE, CONTAINS, -38, -38, 38, 38) ||
+ !check_extents (phase, cr2, PATH, CONTAINS, -35, -35, 35, 35))
ret = CAIRO_TEST_FAILURE;
cairo_new_path (cr2);
cairo_restore (cr2);