[cairo] Extents of degenerate paths

T Rowley tor at cs.brown.edu
Mon May 7 11:46:33 PDT 2007


In Mozilla SVG, I've run across the case where the code needs to check 
the extents of a single diagonal line.  With stroke_width set to zero I 
get back 0,0,0,0 rather than the a tight bounding box for the line.

Investigating other cases I see similar results - testcase code 
attached.  While the fill extent cases could be argued correct in 
returning 0,0,0,0 (should be documented if this is the intended result), 
it seems that the line extents should be a bounding box for the path.

-------------- next part --------------
#include "cairo-test.h"

int
check_extent (cairo_t *cr, int do_fill, char *test,
	      double xmin, double ymin, double xmax, double ymax)
{
  double a, b, c, d;
  if (do_fill)
    cairo_fill_extents(cr, &a, &b, &c, &d);
  else
    cairo_stroke_extents(cr, &a, &b, &c, &d);

  if (a != xmin || b != ymin || c != xmax || d != ymax) {
    cairo_test_log ("%s failed\n\texpected: %f %f %f %f\n\tmeasured: %f %f %f %f\n",
		    test, xmin, ymin, xmax, ymax, a, b, c, d);
    return CAIRO_TEST_FAILURE;
  }  else {
    cairo_test_log ("%s passed\n", test);
    return CAIRO_TEST_SUCCESS;
  }
}

int
main (void)
{
    int x,y;
    int width = 10;
    int height = 10;

    cairo_surface_t *surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
    cairo_t *cr = cairo_create (surf);

    int status = CAIRO_TEST_SUCCESS;
    char const * description =
	"Test that extent checking on degenerate paths gives correct results";

    cairo_test_init ("degenerate-extent");
    cairo_test_log ("%s\n", description);
    printf ("%s\n", description);

    cairo_set_line_width (cr, 0);

    cairo_new_path (cr);
    cairo_move_to (cr, 5, 5);
    status |= check_extent (cr, TRUE, "fill - single moveto", 5, 5, 5, 5);
    status |= check_extent (cr, FALSE, "stroke - single moveto", 5, 5, 5, 5);

    cairo_new_path (cr);
    cairo_move_to (cr, 5, 5);
    cairo_line_to (cr, 5, 5);
    status |= check_extent (cr, TRUE, "fill - null lineto", 5, 5, 5, 5);
    status |= check_extent (cr, FALSE, "stroke - null lineto", 5, 5, 5, 5);

    cairo_new_path (cr);
    cairo_move_to (cr, 5, 0);
    cairo_line_to (cr, 5, 10);
    status |= check_extent (cr, TRUE, "fill - vertical line", 5, 0, 5, 10);
    status |= check_extent (cr, FALSE, "stroke - vertical line", 5, 0, 5, 10);

    cairo_new_path (cr);
    cairo_move_to (cr, 0, 5);
    cairo_line_to (cr, 10, 5);
    status |= check_extent (cr, TRUE, "fill - horizontal line", 0, 5, 10, 5);
    status |= check_extent (cr, FALSE, "stroke - horizontal line", 0, 5, 10, 5);

    cairo_new_path (cr);
    cairo_move_to (cr, 0, 0);
    cairo_line_to (cr, 10, 10);
    status |= check_extent (cr, TRUE, "fill - diagonal line", 0, 0, 10, 10);
    status |= check_extent (cr, FALSE, "stroke - diagonal line", 0, 0, 10, 10);

    cairo_new_path (cr);
    cairo_rectangle (cr, 5, 5, 0, 0);
    status |= check_extent (cr, TRUE, "fill - null rectangle", 5, 5, 5, 5);
    status |= check_extent (cr, FALSE, "stroke - null rectangle", 5, 5, 5, 5);

    cairo_destroy (cr);
    cairo_surface_destroy (surf);

    return status;
}


More information about the cairo mailing list