[cairo] Inconsistent close_path behavior in cairo_path_copy_flat/cairo_stroke

T Rowley tor at cs.brown.edu
Wed Aug 16 14:46:08 PDT 2006


_cpdp_close_path (used by cairo_path_copy_flat) behaves differently than 
  normal stroking.  In a normal stroke, _cairo_stroker_close_path 
inserts a line_to so the current point is set to the first point of the 
subpath.  _cpdp_close_path on the other hand sets the current point to 
0,0.  This causes a problem if curve_to is called after a close_path. 
The attached testcase illustrates the problem we're seeing.
-------------- next part --------------
#include "cairo-test.h"

int
main (void)
{
    cairo_surface_t *surface;
    cairo_t *ctx;
    cairo_path_t *path;
    cairo_path_data_t *data;
    int i;
    float length, startx, starty, x, y;

    length = startx = starty = x = y = 0;

    cairo_test_init ("flatten-close");

    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
    ctx = cairo_create (surface);

    /* Draw two lines, a horizontal one via line_to and close_path,
     * and then a vertial one using curve_to with control points at
     * the endpoints.
     */
    cairo_move_to (ctx, 100, 100);
    cairo_line_to (ctx, 150, 100);
    cairo_close_path (ctx);
    /* Drawing normally with cairo_stroke, the behavior is as if
     * "cairo_move_to (ctx, 100, 100)" was here.
     *
     * For flattened paths, _cpdp_close_path sets the current point to
     * (0,0) so it's as if a "cairo_move_to (ctx, 0, 0)" is here.
     */
    cairo_curve_to (ctx, 100, 100, 100,50, 100,50);

    path = cairo_copy_path_flat (ctx);
    for (i=0; i < path->num_data; i += path->data[i].header.length) {
      data = &path->data[i];
      switch (data->header.type) {
	case CAIRO_PATH_MOVE_TO:
	  startx = x = data[1].point.x;
	  starty = y = data[1].point.y;
	  cairo_test_log ("move_to %f %f\n", x, y);
	  break;
	case CAIRO_PATH_LINE_TO:
	{
	  float dx = data[1].point.x - x;
	  float dy = data[1].point.y - y;
	  length += sqrt(dx * dx + dy * dy);
	  x = data[1].point.x;
	  y = data[1].point.y;
	  cairo_test_log ("line_to %f %f\n", x, y);
	  break;
	}
	case CAIRO_PATH_CURVE_TO:
	  break;
	case CAIRO_PATH_CLOSE_PATH:
	{
	  float dx = startx - x;
	  float dy = starty - y;
	  length += sqrt(dx * dx + dy * dy);
	  x = startx;
	  y = starty;
	  cairo_test_log ("close_path\n");
	  break;
	}
      }
    }

    cairo_path_destroy(path);
    cairo_destroy(ctx);
    cairo_surface_destroy(surface);

    cairo_test_log ("length %f\n", length);
    if (length != 150.0)
      return CAIRO_TEST_FAILURE;

    return CAIRO_TEST_SUCCESS;
}


More information about the cairo mailing list