static void pgm_path(potrace_curve_t *curve, trans_t t, render_t *rm) { dpoint_t *c, c1[3]; int i; int m = curve->n; c = curve->c[m-1]; c1[2] = trans(c[2], t); render_moveto(rm, c1[2].x, c1[2].y); for (i=0; i<m; i++) { c = curve->c[i]; switch (curve->tag[i]) { case POTRACE_CORNER: c1[1] = trans(c[1], t); c1[2] = trans(c[2], t); render_lineto(rm, c1[1].x, c1[1].y); render_lineto(rm, c1[2].x, c1[2].y); break; case POTRACE_CURVETO: c1[0] = trans(c[0], t); c1[1] = trans(c[1], t); c1[2] = trans(c[2], t); render_curveto(rm, c1[0].x, c1[0].y, c1[1].x, c1[1].y, c1[2].x, c1[2].y); break; } } }
/* render a Bezier curve. */ void render_curveto( render_t* rm, double x2, double y2, double x3, double y3, double x4, double y4 ) { double x1, y1, dd0, dd1, dd, delta, e2, epsilon, t; x1 = rm->x1; /* starting point */ y1 = rm->y1; /* we approximate the curve by small line segments. The interval * size, epsilon, is determined on the fly so that the distance * between the true curve and its approximation does not exceed the * desired accuracy delta. */ delta = .1; /* desired accuracy, in pixels */ /* let dd = maximal value of 2nd derivative over curve - this must * occur at an endpoint. */ dd0 = sq( x1 - 2 * x2 + x3 ) + sq( y1 - 2 * y2 + y3 ); dd1 = sq( x2 - 2 * x3 + x4 ) + sq( y2 - 2 * y3 + y4 ); dd = 6 * sqrt( max( dd0, dd1 ) ); e2 = 8 * delta <= dd ? 8 * delta / dd : 1; epsilon = sqrt( e2 ); /* necessary interval size */ for( t = epsilon; t<1; t += epsilon ) { render_lineto( rm, x1 * cu( 1 - t ) + 3 * x2 * sq( 1 - t ) * t + 3 * x3 * (1 - t) * sq( t ) + x4 * cu( t ), y1 * cu( 1 - t ) + 3 * y2 * sq( 1 - t ) * t + 3 * y3 * (1 - t) * sq( t ) + y4 * cu( t ) ); } render_lineto( rm, x4, y4 ); }
/* close path */ void render_close( render_t* rm ) { if( rm->x0 != rm->x1 || rm->y0 != rm->y1 ) { render_lineto( rm, rm->x0, rm->y0 ); } GM_INC( rm->gm, rm->x0i, rm->y0i, (rm->a0 + rm->a1) * 255 ); /* assert (rm->x0i != rm->x1i || rm->y0i != rm->y1i); */ /* the persistent state is now undefined */ }