Beispiel #1
0
static int
_cairo_pen_vertices_needed (double	    tolerance,
			    double	    radius,
			    cairo_matrix_t  *matrix)
{
    /* 
     * the pen is a circle that gets transformed to an ellipse by matrix.
     * compute major axis length for a pen with the specified radius.
     * we don't need the minor axis length.
     */
    
    double  major_axis = _cairo_matrix_transformed_circle_major_axis(matrix, radius);

    /*
     * compute number of vertices needed
     */
    int	    num_vertices;
    
    /* Where tolerance / M is > 1, we use 4 points */
    if (tolerance >= major_axis) {
	num_vertices = 4;
    } else {
	double delta = acos (1 - tolerance / major_axis);
	num_vertices = ceil (M_PI / delta);
	
	/* number of vertices must be even */
	if (num_vertices % 2)
	    num_vertices++;
    }
    return num_vertices;
}
Beispiel #2
0
int
_cairo_pen_vertices_needed (double	    tolerance,
			    double	    radius,
			    const cairo_matrix_t  *matrix)
{
    /*
     * the pen is a circle that gets transformed to an ellipse by matrix.
     * compute major axis length for a pen with the specified radius.
     * we don't need the minor axis length.
     */
    double major_axis = _cairo_matrix_transformed_circle_major_axis (matrix,
								     radius);
    int num_vertices;

    if (tolerance >= 4*major_axis) { /* XXX relaxed from 2*major for inkscape */
	num_vertices = 1;
    } else if (tolerance >= major_axis) {
	num_vertices = 4;
    } else {
	num_vertices = ceil (2*M_PI / acos (1 - tolerance / major_axis));

	/* number of vertices must be even */
	if (num_vertices % 2)
	    num_vertices++;

	/* And we must always have at least 4 vertices. */
	if (num_vertices < 4)
	    num_vertices = 4;
    }

    return num_vertices;
}
Beispiel #3
0
/*
 * Verifies if _cairo_stroke_style_dash_approximate should be used to generate
 * an approximation of the dash pattern in the specified style, when used for
 * stroking a path with the given CTM and tolerance.
 * Always %FALSE for non-dashed styles.
 */
cairo_bool_t
_cairo_stroke_style_dash_can_approximate (const cairo_stroke_style_t *style,
					  const cairo_matrix_t *ctm,
					  double tolerance)
{
    double period;

    if (! style->num_dashes)
        return FALSE;

    period = _cairo_stroke_style_dash_period (style);
    return _cairo_matrix_transformed_circle_major_axis (ctm, period) < tolerance;
}
Beispiel #4
0
static int
_arc_segments_needed (double	      angle,
		      double	      radius,
		      cairo_matrix_t *ctm,
		      double	      tolerance)
{
    double major_axis, max_angle;

    /* the error is amplified by at most the length of the
     * major axis of the circle; see cairo-pen.c for a more detailed analysis
     * of this. */
    major_axis = _cairo_matrix_transformed_circle_major_axis (ctm, radius);
    max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / major_axis);

    return ceil (fabs (angle) / max_angle);
}
Beispiel #5
0
/*
 * Create a 2-dashes approximation of a dashed style, by making the "on" and "off"
 * parts respect the original ratio.
 */
void
_cairo_stroke_style_dash_approximate (const cairo_stroke_style_t *style,
				      const cairo_matrix_t *ctm,
				      double tolerance,
				      double *dash_offset,
				      double *dashes,
				      unsigned int *num_dashes)
{
    double coverage, scale, offset;
    cairo_bool_t on = TRUE;
    unsigned int i = 0;

    coverage = _cairo_stroke_style_dash_stroked (style) / _cairo_stroke_style_dash_period (style);
    coverage = MIN (coverage, 1.0);
    scale = tolerance / _cairo_matrix_transformed_circle_major_axis (ctm, 1.0);

    /* We stop searching for a starting point as soon as the
     * offset reaches zero.  Otherwise when an initial dash
     * segment shrinks to zero it will be skipped over. */
    offset = style->dash_offset;
    while (offset > 0.0 && offset >= style->dash[i]) {
	offset -= style->dash[i];
	on = !on;
	if (++i == style->num_dashes)
	    i = 0;
    }

    *num_dashes = 2;

    /*
     * We want to create a new dash pattern with the same relative coverage,
     * but composed of just 2 elements with total length equal to scale.
     * Based on the formula in _cairo_stroke_style_dash_stroked:
     * scale * coverage = dashes[0] + cap_scale * MIN (dashes[1], line_width)
     *                  = MIN (dashes[0] + cap_scale * (scale - dashes[0]),
     *                         dashes[0] + cap_scale * line_width) = 
     *                  = MIN (dashes[0] * (1 - cap_scale) + cap_scale * scale,
     *	                       dashes[0] + cap_scale * line_width)
     *
     * Solving both cases we get:
     *   dashes[0] = scale * (coverage - cap_scale) / (1 - cap_scale)
     *	  when scale - dashes[0] <= line_width
     *	dashes[0] = scale * coverage - cap_scale * line_width
     *	  when scale - dashes[0] > line_width.
     *
     * Comparing the two cases we get:
     *   second > first
     *   second > scale * (coverage - cap_scale) / (1 - cap_scale)
     *   second - cap_scale * second - scale * coverage + scale * cap_scale > 0
     * 	 (scale * coverage - cap_scale * line_width) - cap_scale * second - scale * coverage + scale * cap_scale > 0
     *   - line_width - second + scale > 0
     *   scale - second > line_width
     * which is the condition for the second solution to be the valid one.
     * So when second > first, the second solution is the correct one (i.e.
     * the solution is always MAX (first, second).
     */

    printf("cairostroke-style.c part 2 clear");

    switch (style->line_cap) {
    default:
        ASSERT_NOT_REACHED;
	dashes[0] = 0.0;
	break;
	
    //TODO DONE add LINE_CAP_TRIANGULAR

    case CAIRO_LINE_CAP_BUTT:
        /* Simplified formula (substituting 0 for cap_scale): */
        dashes[0] = scale * coverage;
	break;

    case CAIRO_LINE_CAP_ROUND:
        dashes[0] = MAX(scale * (coverage - ROUND_MINSQ_APPROXIMATION) / (1.0 - ROUND_MINSQ_APPROXIMATION),
			scale * coverage - ROUND_MINSQ_APPROXIMATION * style->line_width);
	break;

    case CAIRO_LINE_CAP_TRIANGULAR:
        dashes[0] = MAX(scale * (coverage - 0.5) / (1.0 - 0.5),
			scale * coverage - 0.5 * style->line_width);
	break;


    case CAIRO_LINE_CAP_SQUARE:
        /*
	 * Special attention is needed to handle the case cap_scale == 1 (since the first solution
	 * is either indeterminate or -inf in this case). Since dash lengths are always >=0, using
	 * 0 as first solution always leads to the correct solution.
	 */
        dashes[0] = MAX(0.0, scale * coverage - style->line_width);
	break;
    }

    dashes[1] = scale - dashes[0];

    *dash_offset = on ? 0.0 : dashes[0];
}