static SkScalar quad_folded_len(const SkPoint pts[3]) { SkScalar t = SkFindQuadMaxCurvature(pts); SkPoint pt = SkEvalQuadAt(pts, t); SkVector a = pts[2] - pt; SkScalar result = a.length(); if (0 != t) { SkVector b = pts[0] - pt; result += b.length(); } SkASSERT(SkScalarIsFinite(result)); return result; }
static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, const SkMatrix& viewMatrix, const SkPoint pts[2]) { SkVector vecSrc = pts[1] - pts[0]; SkScalar magSrc = vecSrc.length(); SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0; vecSrc.scale(invSrc); SkVector vecSrcPerp; vecSrc.rotateCW(&vecSrcPerp); viewMatrix.mapVectors(&vecSrc, 1); viewMatrix.mapVectors(&vecSrcPerp, 1); // parallelScale tells how much to scale along the line parallel to the dash line // perpScale tells how much to scale in the direction perpendicular to the dash line *parallelScale = vecSrc.length(); *perpScale = vecSrcPerp.length(); }
static void unitToPointsMatrix(const SkPoint pts[2], SkMatrix* matrix) { SkVector vec = pts[1] - pts[0]; SkScalar mag = vec.length(); SkScalar inv = mag ? SkScalarInvert(mag) : 0; vec.scale(inv); matrix->setSinCos(vec.fY, vec.fX); matrix->preTranslate(pts[0].fX, pts[0].fY); matrix->preScale(mag, mag); }
static void pts_to_unit_matrix(const SkPoint pts[2], SkMatrix* matrix) { SkVector vec = pts[1] - pts[0]; SkScalar mag = vec.length(); SkScalar inv = mag ? SkScalarInvert(mag) : 0; vec.scale(inv); matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); matrix->postTranslate(-pts[0].fX, -pts[0].fY); matrix->postScale(inv, inv); }
static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) { SkVector vec = pts[1] - pts[0]; const float mag = vec.length(); const float inv = mag ? 1.0f / mag : 0; vec.scale(inv); matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); matrix->postTranslate(-pts[0].fX, -pts[0].fY); matrix->postScale(inv, inv); }
static SkMatrix pts_to_unit_matrix(const SkPoint pts[2]) { SkVector vec = pts[1] - pts[0]; SkScalar mag = vec.length(); SkScalar inv = mag ? SkScalarInvert(mag) : 0; vec.scale(inv); SkMatrix matrix; matrix.setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); matrix.postTranslate(-pts[0].fX, -pts[0].fY); matrix.postScale(inv, inv); return matrix; }
// calculates the rotation needed to aligned pts to the x axis with pts[0] < pts[1] // Stores the rotation matrix in rotMatrix, and the mapped points in ptsRot static void align_to_x_axis(const SkPoint pts[2], SkMatrix* rotMatrix, SkPoint ptsRot[2] = NULL) { SkVector vec = pts[1] - pts[0]; SkScalar mag = vec.length(); SkScalar inv = mag ? SkScalarInvert(mag) : 0; vec.scale(inv); rotMatrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); if (ptsRot) { rotMatrix->mapPoints(ptsRot, pts, 2); // correction for numerical issues if map doesn't make ptsRot exactly horizontal ptsRot[1].fY = pts[0].fY; } }
static void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices]) { SkASSERT(!toDevice == !toSrc); // original quad is specified by tri a,b,c SkPoint a = qpts[0]; SkPoint b = qpts[1]; SkPoint c = qpts[2]; if (toDevice) { toDevice->mapPoints(&a, 1); toDevice->mapPoints(&b, 1); toDevice->mapPoints(&c, 1); } // make a new poly where we replace a and c by a 1-pixel wide edges orthog // to edges ab and bc: // // before | after // | b0 // b | // | // | a0 c0 // a c | a1 c1 // // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c, // respectively. BezierVertex& a0 = verts[0]; BezierVertex& a1 = verts[1]; BezierVertex& b0 = verts[2]; BezierVertex& c0 = verts[3]; BezierVertex& c1 = verts[4]; SkVector ab = b; ab -= a; SkVector ac = c; ac -= a; SkVector cb = b; cb -= c; // We should have already handled degenerates SkASSERT(ab.length() > 0 && cb.length() > 0); ab.normalize(); SkVector abN; abN.setOrthog(ab, SkVector::kLeft_Side); if (abN.dot(ac) > 0) { abN.negate(); } cb.normalize(); SkVector cbN; cbN.setOrthog(cb, SkVector::kLeft_Side); if (cbN.dot(ac) < 0) { cbN.negate(); } a0.fPos = a; a0.fPos += abN; a1.fPos = a; a1.fPos -= abN; c0.fPos = c; c0.fPos += cbN; c1.fPos = c; c1.fPos -= cbN; intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); if (toSrc) { toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kQuadNumVertices); } }