void SkPathStroker::finishContour(bool close, bool currIsLine) { if (fSegmentCount > 0) { SkPoint pt; if (close) { fJoiner(&fOuter, &fInner, fPrevUnitNormal, fPrevPt, fFirstUnitNormal, fRadius, fInvMiterLimit, fPrevIsLine, currIsLine); fOuter.close(); // now add fInner as its own contour fInner.getLastPt(&pt); fOuter.moveTo(pt.fX, pt.fY); fOuter.reversePathTo(fInner); fOuter.close(); } else { // add caps to start and end // cap the end fInner.getLastPt(&pt); fCapper(&fOuter, fPrevPt, fPrevNormal, pt, currIsLine ? &fInner : NULL); fOuter.reversePathTo(fInner); // cap the start fCapper(&fOuter, fFirstPt, -fFirstNormal, fFirstOuterPt, fPrevIsLine ? &fInner : NULL); fOuter.close(); } } fInner.reset(); fSegmentCount = -1; }
void SkPathStroker::finishContour(bool close, bool currIsLine) { if (fSegmentCount > 0) { SkPoint pt; if (close) { fJoiner(&fOuter, &fInner, fPrevUnitNormal, fPrevPt, fFirstUnitNormal, fRadius, fInvMiterLimit, fPrevIsLine, currIsLine); fOuter.close(); // now add fInner as its own contour fInner.getLastPt(&pt); fOuter.moveTo(pt.fX, pt.fY); fOuter.reversePathTo(fInner); fOuter.close(); } else { // add caps to start and end // cap the end fInner.getLastPt(&pt); fCapper(&fOuter, fPrevPt, fPrevNormal, pt, currIsLine ? &fInner : NULL); fOuter.reversePathTo(fInner); // cap the start fCapper(&fOuter, fFirstPt, -fFirstNormal, fFirstOuterPt, fPrevIsLine ? &fInner : NULL); fOuter.close(); } } // since we may re-use fInner, we rewind instead of reset, to save on // reallocating its internal storage. fInner.rewind(); fSegmentCount = -1; }
void draw(SkCanvas* canvas) { SkPath path; path.moveTo(100, 100); path.quadTo(100, 20, 20, 100); SkMatrix matrix; matrix.setRotate(36, 100, 100); path.transform(matrix); SkPoint last; path.getLastPt(&last); SkDebugf("last point: %g, %g\n", last.fX, last.fY); }
static void _update_path(mbe_t *mbe) { SkPath *path = mbe->path; SkPath *subpath = mbe->subpath; SkMatrix canvas_matrix; SkPoint point; MB_MATRIX_2_SKMATRIX(canvas_matrix, mbe->states->matrix); path->addPath(*subpath, canvas_matrix); subpath->getLastPt(&point); subpath->rewind(); subpath->moveTo(point); }
void mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, co_aix angle_start, co_aix angle_stop) { SkPoint point; SkPath *subpath = mbe->subpath; SkRect rect; SkScalar x0, y0; SkScalar ang_start, ang_stop; SkScalar sweep; SkScalar r; /* radius */ subpath->getLastPt(&point); x0 = point.fX; y0 = point.fX; r = CO_AIX_2_SKSCALAR(radius); ang_start = CO_AIX_2_SKSCALAR(angle_start * 180 / PI); ang_stop = CO_AIX_2_SKSCALAR(angle_stop * 180 / PI); /* Skia can only draw an arc in clockwise directly. We negative * start and stop point to draw the arc in the mirror along x-axis * in a sub-path. Then, the sub-path are reflected along x-axis, * again. We get a right path, and add it to the path of mbe_t. */ if(ang_start > ang_stop) { SkPath tmppath; SkMatrix matrix; co_aix reflect[6] = { 1, 0, 0, 0, -1, 0}; rect.set(-r, -r, r, r); sweep = ang_start - ang_stop; tmppath.arcTo(rect, -ang_start, sweep, false); reflect[2] = x; reflect[5] = y; MB_MATRIX_2_SKMATRIX(matrix, reflect); subpath->addPath(tmppath, matrix); } else { rect.set(x0 - r, y0 - r, x0 + r, y0 + r); sweep = ang_stop - ang_start; subpath->arcTo(rect, ang_start, sweep, false); } }
// quadApprox - makes an approximation, which we hope is faster static void quadApprox(SkPath &fPath, const SkPoint &p0, const SkPoint &p1, const SkPoint &p2) { //divide the cubic up into two cubics, then convert them into quadratics //define our points SkPoint c,j,k,l,m,n,o,p,q, mid; fPath.getLastPt(&c); midPt(j, p0, c); midPt(k, p0, p1); midPt(l, p1, p2); midPt(o, j, k); midPt(p, k, l); midPt(q, o, p); //compute the first half m.set(SkScalarHalf(3*j.fX - c.fX), SkScalarHalf(3*j.fY - c.fY)); n.set(SkScalarHalf(3*o.fX -q.fX), SkScalarHalf(3*o.fY - q.fY)); midPt(mid,m,n); fPath.quadTo(mid,q); c = q; //compute the second half m.set(SkScalarHalf(3*p.fX - c.fX), SkScalarHalf(3*p.fY - c.fY)); n.set(SkScalarHalf(3*l.fX -p2.fX),SkScalarHalf(3*l.fY -p2.fY)); midPt(mid,m,n); fPath.quadTo(mid,p2); }