static void center_of_mass(const SegmentArray& segments, SkPoint* c) { SkScalar area = 0; SkPoint center = {0, 0}; int count = segments.count(); SkPoint p0 = {0, 0}; if (count > 2) { // We translate the polygon so that the first point is at the origin. // This avoids some precision issues with small area polygons far away // from the origin. p0 = segments[0].endPt(); SkPoint pi; SkPoint pj; // the first and last iteration of the below loop would compute // zeros since the starting / ending point is (0,0). So instead we start // at i=1 and make the last iteration i=count-2. pj = segments[1].endPt() - p0; for (int i = 1; i < count - 1; ++i) { pi = pj; const SkPoint pj = segments[i + 1].endPt() - p0; SkScalar t = SkScalarMul(pi.fX, pj.fY) - SkScalarMul(pj.fX, pi.fY); area += t; center.fX += (pi.fX + pj.fX) * t; center.fY += (pi.fY + pj.fY) * t; } } // If the poly has no area then we instead return the average of // its points. if (SkScalarNearlyZero(area)) { SkPoint avg; avg.set(0, 0); for (int i = 0; i < count; ++i) { const SkPoint& pt = segments[i].endPt(); avg.fX += pt.fX; avg.fY += pt.fY; } SkScalar denom = SK_Scalar1 / count; avg.scale(denom); *c = avg; } else { area *= 3; area = SkScalarDiv(SK_Scalar1, area); center.fX = SkScalarMul(center.fX, area); center.fY = SkScalarMul(center.fY, area); // undo the translate of p0 to the origin. *c = center + p0; } SkASSERT(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY)); }
static void create_vertices(const SegmentArray& segments, const SkPoint& fanPt, DrawArray* draws, QuadVertex* verts, uint16_t* idxs) { Draw* draw = &draws->push_back(); // alias just to make vert/index assignments easier to read. int* v = &draw->fVertexCnt; int* i = &draw->fIndexCnt; int count = segments.count(); for (int a = 0; a < count; ++a) { const Segment& sega = segments[a]; int b = (a + 1) % count; const Segment& segb = segments[b]; // Check whether adding the verts for this segment to the current draw would cause index // values to overflow. int vCount = 4; if (Segment::kLine == segb.fType) { vCount += 5; } else { vCount += 6; } if (draw->fVertexCnt + vCount > (1 << 16)) { verts += *v; idxs += *i; draw = &draws->push_back(); v = &draw->fVertexCnt; i = &draw->fIndexCnt; } // FIXME: These tris are inset in the 1 unit arc around the corner verts[*v + 0].fPos = sega.endPt(); verts[*v + 1].fPos = verts[*v + 0].fPos + sega.endNorm(); verts[*v + 2].fPos = verts[*v + 0].fPos + segb.fMid; verts[*v + 3].fPos = verts[*v + 0].fPos + segb.fNorms[0]; verts[*v + 0].fUV.set(0,0); verts[*v + 1].fUV.set(0,-SK_Scalar1); verts[*v + 2].fUV.set(0,-SK_Scalar1); verts[*v + 3].fUV.set(0,-SK_Scalar1); verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1; verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1; verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1; verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1; idxs[*i + 0] = *v + 0; idxs[*i + 1] = *v + 2; idxs[*i + 2] = *v + 1; idxs[*i + 3] = *v + 0; idxs[*i + 4] = *v + 3; idxs[*i + 5] = *v + 2; *v += 4; *i += 6; if (Segment::kLine == segb.fType) { verts[*v + 0].fPos = fanPt; verts[*v + 1].fPos = sega.endPt(); verts[*v + 2].fPos = segb.fPts[0]; verts[*v + 3].fPos = verts[*v + 1].fPos + segb.fNorms[0]; verts[*v + 4].fPos = verts[*v + 2].fPos + segb.fNorms[0]; // we draw the line edge as a degenerate quad (u is 0, v is the // signed distance to the edge) SkScalar dist = fanPt.distanceToLineBetween(verts[*v + 1].fPos, verts[*v + 2].fPos); verts[*v + 0].fUV.set(0, dist); verts[*v + 1].fUV.set(0, 0); verts[*v + 2].fUV.set(0, 0); verts[*v + 3].fUV.set(0, -SK_Scalar1); verts[*v + 4].fUV.set(0, -SK_Scalar1); verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1; verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1; verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1; verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1; verts[*v + 4].fD0 = verts[*v + 4].fD1 = -SK_Scalar1; idxs[*i + 0] = *v + 0; idxs[*i + 1] = *v + 2; idxs[*i + 2] = *v + 1; idxs[*i + 3] = *v + 3; idxs[*i + 4] = *v + 1; idxs[*i + 5] = *v + 2; idxs[*i + 6] = *v + 4; idxs[*i + 7] = *v + 3; idxs[*i + 8] = *v + 2; *v += 5; *i += 9; } else { SkPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]}; SkVector midVec = segb.fNorms[0] + segb.fNorms[1]; midVec.normalize(); verts[*v + 0].fPos = fanPt; verts[*v + 1].fPos = qpts[0]; verts[*v + 2].fPos = qpts[2]; verts[*v + 3].fPos = qpts[0] + segb.fNorms[0]; verts[*v + 4].fPos = qpts[2] + segb.fNorms[1]; verts[*v + 5].fPos = qpts[1] + midVec; SkScalar c = segb.fNorms[0].dot(qpts[0]); verts[*v + 0].fD0 = -segb.fNorms[0].dot(fanPt) + c; verts[*v + 1].fD0 = 0.f; verts[*v + 2].fD0 = -segb.fNorms[0].dot(qpts[2]) + c; verts[*v + 3].fD0 = -SK_ScalarMax/100; verts[*v + 4].fD0 = -SK_ScalarMax/100; verts[*v + 5].fD0 = -SK_ScalarMax/100; c = segb.fNorms[1].dot(qpts[2]); verts[*v + 0].fD1 = -segb.fNorms[1].dot(fanPt) + c; verts[*v + 1].fD1 = -segb.fNorms[1].dot(qpts[0]) + c; verts[*v + 2].fD1 = 0.f; verts[*v + 3].fD1 = -SK_ScalarMax/100; verts[*v + 4].fD1 = -SK_ScalarMax/100; verts[*v + 5].fD1 = -SK_ScalarMax/100; GrPathUtils::QuadUVMatrix toUV(qpts); toUV.apply<6, sizeof(QuadVertex), sizeof(SkPoint)>(verts + *v); idxs[*i + 0] = *v + 3; idxs[*i + 1] = *v + 1; idxs[*i + 2] = *v + 2; idxs[*i + 3] = *v + 4; idxs[*i + 4] = *v + 3; idxs[*i + 5] = *v + 2; idxs[*i + 6] = *v + 5; idxs[*i + 7] = *v + 3; idxs[*i + 8] = *v + 4; idxs[*i + 9] = *v + 0; idxs[*i + 10] = *v + 2; idxs[*i + 11] = *v + 1; *v += 6; *i += 12; } } }