[cairo] cairo_new_sub_path: Making cairo_arc easier to use and more

Behdad Esfahbod behdad at cs.toronto.edu
Sat Jan 21 07:43:09 PST 2006


Carl,

Thanks for the lengthy message.  I'm all with your approach.
The only question I have is whether cairo_close_path starts a new
sub path or not.  Most of the time the user wants it to do, but
if it does, there is no way to prevent it from doing that.  So I
guess it should not start a new sub path and leave that to the
user.

As for the name, I prefer something like cairo_disjoin_path.

And while you're at it, take a look at the arc_to patch too :).


Cheers,
behdad



On Fri, 20 Jan 2006, Carl Worth wrote:

> There's been a long-time annoyance with cairo_arc. This function
> always appends a line segment from the current point (if any) to the
> beginning of the arc.
>
> When the line segment is desired, (such as in the simplest way of
> doing a rounded rectangle with four calls to cairo_arc and a
> cairo_close_path), this is very convenient and fits in well with all
> the path-appending functions.
>
> When the line segment is not desired it is pretty painful to avoid,
> (it requires doing a cairo_move_to, which requires some trig. to get
> the right coordinates and brings the fear that some round-off error
> might introduce an errant miter sticking out from the tiny line
> segment that shouldn't be there, etc.).
>
> One way to try to fix this would be to add a variant of cairo_arc that
> doesn't do the initial line segment. But the naming possibilities are
> grim (cairo_arc_without_line_to ? cairo_arc_with_implicit_move_to ?
> cairo_arc_disconnected? etc.) and there's a bit of API explosion since
> we already have cairo_arc and cairo_arc_negative (and we've imagined
> cairo_arc_to as well.... oops there's even an old patch I need to
> finish reviewing that adds that).
>
> So, I'd like to propose an alternate solution. We already have one
> state in which cairo_arc does not do an initial line_to. That is when
> there is no current point. Currently this state is only possible when
> there is no path at all. My proposal is to add a new function which
> has as its only effect the elimination of the current point. The
> proposed function is:
>
> 	cairo_public void
> 	cairo_new_sub_path (cairo_t *cr);
>
> Once I hit on this idea, I found that it also unifies and generalizes
> an existing (rather hidden) feature of cairo. It has long been the
> case that if there is no current point, a call to cairo_line_to would
> be treated as a call to cairo_move_to instead, (contrast with
> PostScript where a lineto with no current point is an error).
>
> The motivation for this behavior is that it avoids requiring a
> special-case for the first coordinate when looping over a sequence of
> points, for example. Taking advantage of this feature can often mean
> slightly less state management in the application since things like:
>
> 	if (has_current_point)
> 	    cairo_line_to (cr, x, y);
> 	else
> 	    cairo_move_to (cr, x, y);
>
> can become:
>
> 	cairo_move_to (cr, x, y);
>
> and all the code to keep track of has_current_point disappears.
>
> I had never documented this little quirk of cairo's implementation,
> since it seemed like a nasty little kludge that I had thrown in to
> support my own lazy programming practices.
>
> But, with the addition of cairo_new_sub_path, I'd like to upgrade this
> to a solid feature. Now, the feature would be more generally
> available, since it could be relied upon at the beginning of any new
> sub-path, and not only when starting with an empty path. (So the lazy
> style of doing just cairo_line_to is now available for a nested loop
> of many polygons instead of just a single polygon).
>
> Additionally, the feature generalizes so that all path-appending
> functions (except for the relative functions for which the
> no-current-point state remains an error), consistently handle the
> no-current-point state by inserting an implicit move_to to the initial
> coordinate.
>
> If that all sounds confusing, please take a look at the new
> documentation in the attached patch. It should be easy to grasp, and I
> think it's quite a bit shorter than this rambling message.
>
> Finally, even if we reject this new API, there's a lot of good stuff
> in this patch. Previously, the "magic" feature of line_to was handled
> too late, while replaying the path, so various backends had to deal
> with this, and several uses of the path, (such as cairo_copy_path),
> did not get a consistent view.
>
> Now, with this patch, the handling of no-current-point is taken care
> of up front. Many of the downstream users of the path internal to
> cairo are greatly simplified since their current point state management
> can be eliminated. Similarly, application use of cairo_copy_path
> (after this patch at least) will need not worry about no-current-point state
> management since the new path guarantees that no such situation will
> ever occur in a path that can be retrieved from cairo.
>
> I've also included a new test for the test suite that demonstrates
> cairo_line_to, cairo_curve_to, and cairo_arc all taking advantage of
> cairo_new_sub_path.
>
> I'm pretty happy with this. But I'm also interested in feedback,
> (particularly if anyone has any comments on the new_sub_path naming).
>
> Thanks,
>
> -Carl
>
>

--behdad
http://behdad.org/

"Commandment Three says Do Not Kill, Amendment Two says Blood Will Spill"
	-- Dan Bern, "New American Language"


More information about the cairo mailing list