void twin_path_draw (twin_path_t *path, twin_fixed_t x, twin_fixed_t y) { _twin_path_sdraw (path, _twin_matrix_x (&path->state.matrix, x, y), _twin_matrix_y (&path->state.matrix, x, y)); }
void twin_path_rdraw (twin_path_t *path, twin_fixed_t dx, twin_fixed_t dy) { twin_spoint_t here = _twin_path_current_spoint (path); _twin_path_sdraw (path, here.x + _twin_matrix_dx (&path->state.matrix, dx, dy), here.y + _twin_matrix_dy (&path->state.matrix, dx, dy)); }
void _twin_path_smove (twin_path_t *path, twin_sfixed_t x, twin_sfixed_t y) { switch (_twin_current_subpath_len (path)) { default: _twin_path_sfinish (path); case 0: _twin_path_sdraw (path, x, y); break; case 1: path->points[path->npoints-1].x = x; path->points[path->npoints-1].y = y; break; } }
void twin_path_close (twin_path_t *path) { twin_spoint_t f; switch (_twin_current_subpath_len(path)) { case 0: case 1: break; default: f = _twin_path_subpath_first_spoint (path); _twin_path_sdraw (path, f.x, f.y); break; } }
void twin_path_append (twin_path_t *dst, twin_path_t *src) { int p; int s = 0; for (p = 0; p < src->npoints; p++) { if (s < src->nsublen && p == src->sublen[s]) { _twin_path_sfinish (dst); s++; } _twin_path_sdraw (dst, src->points[p].x, src->points[p].y); } }
/* * Convert the hull structure back to a simple path */ static twin_path_t * _twin_hull_to_path (twin_hull_t *hull, int num_hull) { twin_path_t *path = twin_path_create (); int i; DBGMSG (("convex hull\n")); for (i = 0; i < num_hull; i++) { DBGMSG (("\t%d: %9.4f, %9.4f %c\n", i, S(hull[i].point.x), S(hull[i].point.y), hull[i].discard ? '*' : ' ')); if (hull[i].discard) continue; _twin_path_sdraw (path, hull[i].point.x, hull[i].point.y); } return path; }
/* * 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; }