int xs_trans::_cmethod(double t) { int cntr, jj; long int xs, ys, xp, yp; double angp, angs; _rxx[0] = _xxin[0]; _ryy[0] = _yyin[0]; xs = _xxin[0]; ys = _yyin[0]; cntr = 1; xp = _xxin[1]; yp = _yyin[1]; angp = _angle(xp,yp,xs,ys); for (jj=2; jj<_num_pts; jj++) { angs = _angle(_xxin[jj],_yyin[jj], xs, ys); if ( fabs( (angs-angp) ) < t ) { /* skip */ xp = _xxin[jj]; yp = _yyin[jj]; } else { /* store */ _rxx[cntr] = xp; _ryy[cntr++] = yp; xs = xp; ys = yp; xp = _xxin[jj]; yp = _yyin[jj]; angp = _angle(xp, yp, xs, ys); } } /* always keep the last one */ _rxx[cntr] = _xxin[_num_pts-1]; _ryy[cntr++] = _yyin[_num_pts-1]; return cntr; }
/* * Convolve one subpath with a convex pen. The result is * a closed path. */ static void _twin_subpath_convolve (twin_path_t *path, twin_path_t *stroke, twin_path_t *pen) { twin_spoint_t *sp = stroke->points; twin_spoint_t *pp = pen->points; int ns = stroke->npoints; int np = pen->npoints; twin_spoint_t *sp0 = &sp[0]; twin_spoint_t *sp1 = &sp[1]; int start = _twin_path_leftpoint (pen, sp0, sp1); twin_spoint_t *spn1 = &sp[ns-1]; twin_spoint_t *spn2 = &sp[ns-2]; int ret = _twin_path_leftpoint (pen, spn1, spn2); int p; int s; int starget; int ptarget; int inc; int first; DBGOUT ("convolve stroke:\n"); for (s = 0; s < ns; s++) DBGOUT ("\ts%02d: %9.4f, %9.4f\n", s, F(sp[s].x), F(sp[s].y)); DBGOUT ("convolve pen:\n"); for (p = 0; p < np; p++) DBGOUT ("\tp%02d: %9.4f, %9.4f\n", p, F(pp[p].x), F(pp[p].y)); s = 0; p = start; DBGOUT ("start: "); DBGOUT ("s%02d (%9.4f, %9.4f), p%02d (%9.4f, %9.4f): %9.4f, %9.4f\n", s, F(sp[s].x), F(sp[s].y), p, F(pp[p].x), F(pp[p].y), F(sp[s].x + pp[p].x), F(sp[s].y + pp[p].y)); _twin_path_smove (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y); first = path->npoints - 1; /* step along the path first */ inc = 1; starget = ns-1; ptarget = ret; for (;;) { /* * Convolve the edges */ do { int sn = s + inc; int pn = (p == np - 1) ? 0 : p + 1; int pm = (p == 0) ? np - 1 : p - 1; /* * step along pen (forwards or backwards) or stroke as appropriate */ DBGOUT ("\tangles: stroke %9.4f +pen %9.4f -pen %9.4f\n", _angle (&sp[s], &sp[sn]), _angle (&pp[p], &pp[pn]), _angle (&pp[pm], &pp[p])); if (_around_order (&sp[s],&sp[sn],&pp[p],&pp[pn]) > 0) { DBGOUT ("+pen: "); p = pn; } else if (_around_order (&sp[s],&sp[sn],&pp[pm],&pp[p]) < 0) { DBGOUT ("-pen: "); p = pm; } else { DBGOUT ("stroke: "); s = sn; } DBGOUT ("s%02d (%9.4f, %9.4f), p%02d (%9.4f, %9.4f): %9.4f, %9.4f\n", s, F(sp[s].x), F(sp[s].y), p, F(pp[p].x), F(pp[p].y), F(sp[s].x + pp[p].x), F(sp[s].y + pp[p].y)); _twin_path_sdraw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y); } while (s != starget); /* * Finish this edge */ /* draw a cap */ switch (path->state.cap_style) { int pm; case TwinCapProjecting: /* * This draws a rough projecting cap using the * pen. * * First, project the line forward one pen radius * by finding the pen location halfway between the * two normals. * * Then, just add that to the normals themselves to * find the corners of the projecting cap. * * The result may have significant error, so overwrite * the existing corners with the new coordinates to * avoid a kink. */ if (p <= ptarget) pm = (ptarget + p) >> 1; else { pm = (ptarget + np + p) >> 1; if (pm >= np) pm -= np; } /* replace last point with corner of cap */ path->npoints--; _twin_path_sdraw (path, sp[s].x + pp[pm].x + pp[p].x, sp[s].y + pp[pm].y + pp[p].y); p = ptarget; if (inc == 1) { /* start next line at cap corner */ _twin_path_sdraw (path, sp[s].x + pp[pm].x + pp[p].x, sp[s].y + pp[pm].y + pp[p].y); } else { /* overwrite initial point */ path->points[first].x = sp[s].x + pp[pm].x + pp[p].x; path->points[first].y = sp[s].y + pp[pm].y + pp[p].y; } break; case TwinCapButt: p = ptarget-1; /* fall through … */ case TwinCapRound: while (p != ptarget) { if (++p == np) p = 0; DBGOUT("cap: "); DBGOUT ("s%02d (%9.4f, %9.4f), p%02d (%9.4f, %9.4f): %9.4f, %9.4f\n", s, F(sp[s].x), F(sp[s].y), p, F(pp[p].x), F(pp[p].y), F(sp[s].x + pp[p].x), F(sp[s].y + pp[p].y)); _twin_path_sdraw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y); } break; } if (inc == -1) break; /* reach the end of the path? Go back the other way now */ inc = -1; ptarget = start; starget = 0; }