[cairo] Add cairo_path_extents()

This new function gets the extents of the current path, whether
or not they would be inked by a 'fill'. It differs from
cairo_fill_extents() when the area enclosed by the path is 0.

Includes documentation and updated test.
This commit is contained in:
Brian Ewins 2007-11-16 22:43:43 +00:00 committed by Carl Worth
parent d923457c0f
commit 4177208be6
7 changed files with 87 additions and 10 deletions

View file

@ -326,6 +326,7 @@ cairo_text_path
cairo_rel_curve_to
cairo_rel_line_to
cairo_rel_move_to
cairo_path_extents
</SECTION>
<SECTION>

View file

@ -236,3 +236,13 @@ Creating paths and manipulating path data
@dy:
<!-- ##### FUNCTION cairo_path_extents ##### -->
<para>
</para>
@cr:
@x1:
@y1:
@x2:
@y2:

View file

@ -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,

View file

@ -1869,6 +1869,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

View file

@ -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);

View file

@ -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);

View file

@ -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);