third_party/cairo/src/cairo-stroke-style.c
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).
     */
    switch (style->line_cap) {
    default:
        ASSERT_NOT_REACHED;
	dashes[0] = 0.0;
	break;

    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_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];
}
/*
 * Create a 2-dashes approximation of a dashed style, by making the "on" and "off"
 * parts respect the original ratio.
 */
Create a 2-dashes approximation of a dashed style, by making the "on" and "off"
parts respect the original ratio.
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);
    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;
    switch (style->line_cap) {
    default:
        ASSERT_NOT_REACHED;
	dashes[0] = 0.0;
	break;
    case CAIRO_LINE_CAP_BUTT:
        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_SQUARE:
        dashes[0] = MAX(0.0, scale * coverage - style->line_width);
	break;
    }
    dashes[1] = scale - dashes[0];
    *dash_offset = on ? 0.0 : dashes[0];
}
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 ) ; 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 ; switch ( style -> line_cap ) { default : ASSERT_NOT_REACHED ; dashes [ 0 ] = 0.0 ; break ; case CAIRO_LINE_CAP_BUTT : 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_SQUARE : dashes [ 0 ] = MAX ( 0.0 , scale * coverage - style -> line_width ) ; break ; } dashes [ 1 ] = scale - dashes [ 0 ] ; * dash_offset = on ? 0.0 : dashes [ 0 ] ; }
Create a 2-dashes approximation of a dashed style, by making the "on" and "off"
 parts respect the original ratio.
Create a 2 - dashes approximation of a dashed style by making the " on " and " off " parts respect the original ratio .
/* 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. */ /*
     * 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).
     */ /* Simplified formula (substituting 0 for cap_scale): */ /*
	 * 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.
	 */