# [cairo] Questions and optimizations in cairo-arc

Carl Worth cworth at cworth.org
Tue Jul 26 10:31:41 PDT 2005

```On Tue, 26 Jul 2005 06:42:27 -0400 (EDT), Behdad Esfahbod wrote:
> I was looking at the cairo-arc.c source code and performed some
> trivial optimizations.  Patch attached.

Have you done any benchmarking to justify these changes? The inlining
of _cairo_arc_segment does make the code harder to read so it's not
something I want to do without justification.

> /* XXX: NYI
> void
> cairo_arc_to (cairo_t *cr,
>               double x1, double y1,
>               double x2, double y2,
> */

This comes from PostScript's arct operator. The two points actually
form two tangent lines---one from the current point to (x1,y1) and one
from (x1,y1) to (x2,y2). These are not points on the spline at all.

See the PostScript Language Reference Manual for a more detailed
explanation.

> but I cannot make any sense of it.  AFAIU the '_to' functions are
> use the current point.  Then with x1,y1 and x2,y2 we would have
> three points and there is a unique arc starting at current point,
> passing x1,y1 and ending at x2,y2.  No need for radius.

That wouldn't work. Given three arbitrary points in the plane there is
not necessarily any arc that passes through all three points.

>   - This is not the '_to' version of cairo_arc.  A '_to' version
> of cairo_arc makes no sense, since cairo_arc does not get an
> starting point.

I don't follow you here. There aren't '_to' versions of any functions
in cairo. We have move_to, line_to, and curve_to, but never any
variants of those without the '_to'.

And cairo_arc does indeed get a starting point. It draws a line from
the current point to the initial point on the arc. The proposed
cairo_arc_to would do the same.

>   - This definition of cairo_arc_to is hardly useful, since you
> need to know a point on the arc, which is not quite obvious.

This is actually a problem with the current cairo_arc as well. If the
initial line_to is not desired, the application must manually compute
the starting point of the arc and call cairo_move_to. I would still
like to come up with some API addition to make this simpler, but I
haven't decided any totally satisfactory names yet.

Would it be cairo_arc_with_move_to ? cairo_arc_negative_with_move_to
? Those are getting awkwardly long. We could add cairo_arc_move_to
that just computes the initial move_to for either cairo_arc or
cairo_arc_negative, but then the user has to repeat all 6 arguments
again.

Maybe cairo_move_to_arc and cairo_move_to_arc_negative? That drops the
"with_" so is a bit shorter, and it also expresses the two operations
in the order they would be performed, (eg. this is a helper for
cairo_move_to and cairo_arc in sequence). The worst drawback is that
these functions won't alphabetize next to cairo_arc, but maybe we just
live with that?

>   - Are these path-modifying operations only allowed to query the
> current point, or the already-built parts of the path too?  I'm
> thinking about metapost-style features, like drawing smooth
> paths, computing the control points of the bezier, etc.  And then
> you can actually uniquely and smoothly arc_to any point, given

We can add any other path primitives we would like to. But my current
inclination is to just provide the cubic Bézier spline primitive and
allow applications or libraries on top of cairo to do other more
interesting things. It should be very easy to build MetaPost-like
operations, (eg. enter and leave path vertices at specified angles),
on top of the cubic Bézier primitive in cairo.

>   - Is there any interest in developing abovementioned features?
> I understand that cairo is not metafont/metapost, but having
> these features helps a lot when you actually write code using
> cairo manually, in contrast to when cairo is used as a backend to
> something like a viewer or editor, for example.

Please feel free to experiment and show us what you come up with.

>   - One more thing that I find useful is functions that get a
> path and produce another path.  One useful example would be a
> function that give a path and pen, computes the outline of the
> stroke.  Another one is a function that given a path, outputs
> another path that uses arcs of (at most) some radius instead of
> sharp joints.  Then for example you can filter the path from
> cairo_rectangle to get a rectangle with round edges, etc...  Any
> thoughts about how useful these may be?  Intersecting paths comes
> to my mind too, and union, etc...

It's always been planned to provide the function to give the outline
formed by stroking a path with the current pen, (cairo_stroke_to_path
is the current proposed name). More elaborate path transformations can
be obtained manually with cairo_copy_path, and there are some examples
of interesting applications of this around, (eg. cairo-demo/kapow and
pycairo/examples/warpedtext.py).

As for the set-theoretic operations on paths. This would be very
useful, but is a "hard" problem that we don't have a solution for yet
within cairo. If we do end up writing the necessary code for this,
I think it might make sense to split it out as a supporting geometry
library under cairo, (since it would be quite useful for other things
besides cairo).

>   - One more thing that I noticed is that in many places in the
> code we(well, you :-) need to compute both sin and cos of the
> same angle.  Most FPUs have a single instruction for doing this,
> and glibc has a function for it too: sincos(3).  I think it's
> worth using that.  Fortunately a simple implementation with no
> drawback is possible:
>
> #if HAVE_SINCOS
> #  define _cairo_sincos(angle,s,c) sincos((angle), (s), (c))
> #else
> #  define _cairo_sincos(angle,s,c) \
>      do { *(s) = sin(angle); *(c) = cos(angle); } while (0)
> #endif

Please feel free to put a patch together for this change alone, (along
with the necessary configure magic to define HAVE_SINCOS
appropriately).