blob: 882854dc695bfb2cf95de1a90a7ab551b69b55ba [file] [log] [blame]
/*
* Copyright 2019 Google LLC.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/tessellate/GrCenterWedgePatchGen.h"
#include "include/core/SkPath.h"
#include "src/core/SkPathPriv.h"
static SkPoint lerp(const SkPoint& a, const SkPoint& b, float T) {
return a * (1 - T) + b * T;
}
int GrCenterWedgePatchGen::walkPath(std::array<SkPoint, 5>* wedgeData,
SkTArray<SkPoint, true>* contourMidpoints) {
fWedgeData = (std::array<SkPoint, 5>*)wedgeData;
fContourMidpoints = contourMidpoints;
fLastPt = {0,0};
fCurrContourInitialPatchCount = 0;
if (fWedgeData) {
fCurrContourMidpoint = fContourMidpoints->begin();
} else {
SkASSERT(fContourMidpoints->empty());
fCurrContourFanPtsSum = {0,0};
}
fNumWedges = 0;
const SkPoint* pts = SkPathPriv::PointData(fPath);
SkPoint contourStartPt = {0,0};
int ptsIdx = 0;
for (SkPath::Verb verb : SkPathPriv::Verbs(fPath)) {
switch (verb) {
case SkPath::kMove_Verb:
this->close(contourStartPt);
contourStartPt = fLastPt = pts[ptsIdx++];
continue;
case SkPath::kClose_Verb:
fLastPt = this->close(contourStartPt);
continue;
case SkPath::kLine_Verb:
fLastPt = this->lineTo(pts[ptsIdx++]);
continue;
case SkPath::kQuad_Verb:
fLastPt = this->quadraticTo(pts[ptsIdx], pts[ptsIdx + 1]);
ptsIdx += 2;
continue;
case SkPath::kCubic_Verb:
fLastPt = this->cubicTo(pts[ptsIdx], pts[ptsIdx + 1], pts[ptsIdx + 2]);
ptsIdx += 3;
continue;
case SkPath::kConic_Verb:
// TODO: Eventually we want to use rational cubic wedges in order to support
// perspective and conics.
default:
SK_ABORT("Unexpected path verb.");
}
}
this->close(contourStartPt);
SkASSERT(!fWedgeData || fCurrContourMidpoint == fContourMidpoints->end());
return fNumWedges;
}
inline SkPoint GrCenterWedgePatchGen::lineTo(const SkPoint& p1) {
if (fWedgeData) {
fWedgeData[fNumWedges] = {
fLastPt, lerp(fLastPt, p1, 1/3.f), lerp(fLastPt, p1, 2/3.f), p1,
*fCurrContourMidpoint};
} else {
fCurrContourFanPtsSum += p1;
}
++fNumWedges;
return p1;
}
inline SkPoint GrCenterWedgePatchGen::quadraticTo(const SkPoint& p1, const SkPoint& p2) {
if (fWedgeData) {
fWedgeData[fNumWedges] = {
fLastPt, lerp(fLastPt, p1, 2/3.f), lerp(p1, p2, 1/3.f), p2, *fCurrContourMidpoint};
} else {
fCurrContourFanPtsSum += p2;
}
++fNumWedges;
return p2;
}
inline SkPoint GrCenterWedgePatchGen::cubicTo(const SkPoint& p1, const SkPoint& p2,
const SkPoint& p3) {
if (fWedgeData) {
fWedgeData[fNumWedges] = {fLastPt, p1, p2, p3, *fCurrContourMidpoint};
} else {
fCurrContourFanPtsSum += p3;
}
++fNumWedges;
return p3;
}
inline SkPoint GrCenterWedgePatchGen::close(const SkPoint& startPt) {
if (fLastPt != startPt) {
this->lineTo(startPt);
}
if (fWedgeData) {
++fCurrContourMidpoint;
} else {
int numPatchesInContour = fNumWedges - fCurrContourInitialPatchCount;
fContourMidpoints->push_back(fCurrContourFanPtsSum * (1.f/numPatchesInContour));
fCurrContourInitialPatchCount = fNumWedges;
fCurrContourFanPtsSum = {0,0};
}
return startPt;
}