# [cairo] perf: long dashed lines

Sun Feb 3 13:20:13 PST 2008

```On Feb 3, 2008, at 11:20 AM, Behdad Esfahbod wrote:
>
> Generally looks good.
>
> Line width is in user-space.  Though we've wanted to change that to be
> locked at set_line_width() time.
>
> As for the assumption, at least for miter joins it should be
> (miter_limit * line_width).

Ok, will fix that, based on Bertram's email.

> I also want to see check_segment to something better.  Like,
> may_intersect for example.  Or would that be may_not_intersect?
>
> The intersect and point_in_box functions need to move somewhere else
> where they belong, and renamed to _cairo_box_*().

Yeah, I stuck them here because there really didn't seem to be a good
place -- should I just create a cairo-geometry.c ?  Or a cairo-box.c,
and do _cairo_box_contains_point and _cairo_box_intersects_line or
somesuch?

> +    cairo_matrix_transform_distance (ctm_inverse, &dx0, &dy0);
> +    mag = sqrt (dx0 * dx0 + dy0 * dy0);
> +    if (mag < 1e-12) {
> +       if (mag_out)
> +           *mag_out = 0.0;
> +       return FALSE;
> +    }
>
> mag is in user space, you shouldn't make such size assumptions on
> it.  I
> suggest reworking it a bit such that we have the fixed values there
> too,
> then you can check fixed ints for zero.  Or just check dx0 and dy0
> before the transformation.

Well, should I just check for exact 0?  It seems that we should at
least use an epsilon value that's smaller than the smallest number we
can represent in fixed point.  But I'll go and replace the check with
dx0 == 0.0 and dy0 == 0.0 before the sqrt.  I wasn't too worried about
this sqrt since it's only called once per line segment, but you're
right, if we can avoid it we should.  Can't do this whole calculation
in fixed point though as there's a bunch of floating point math,
mainly in _compute_face.  Not sure if it needs that full precision, or
if we should go and convert this to fixed.  That can be done as a
followup patch, though.

One more question that I had -- in _cairo_stroker_curve_to, I have:

/* XXX -- if either of these return FALSE, we shouldn't have a
corresponding face, right? */
_compute_normalized_device_slope (&initial_slope_dx,
&initial_slope_dy, stroker->ctm_inverse, NULL);
_compute_normalized_device_slope (&final_slope_dx,
&final_slope_dy, stroker->ctm_inverse, NULL);

_compute_face (a, initial_slope_dx, initial_slope_dy, stroker,
&start);
_compute_face (d, final_slope_dx, final_slope_dy, stroker, &end);

This is broken, but I'm not sure what I should do in this case.  If
_compute_normalized returns FALSE, should I just generate a degenerate
face for start/end?  As written right now, we'll end up with a bogus
dx,dy (well, they'll be the untransformed slope), and that's not
right :)