42 : fViewMatrix(viewMatrix), fStroke(stroke) {
68 if (fQueueCount >= 2) {
77 for (; fIter != fEnd; ++fIter) {
78 SkASSERT(fQueueCount == 0 || fQueueCount == 1);
82 if (!this->finishOpenContour()) {
95 fLastDegenerateStrokePt =
pts;
99 if (fQueueCount == 1) {
102 fFirstPtsInContour =
pts;
103 fFirstWInContour =
w;
109 fLastDegenerateStrokePt =
pts;
112 if (
pts[0] != fFirstPtsInContour[0]) {
114 fClosePts = {
pts[0], fFirstPtsInContour[0]};
115 this->enqueue(
Verb::kLine, fClosePts.data(),
nullptr);
118 this->enqueue(fFirstVerbInContour, fFirstPtsInContour, fFirstWInContour);
120 fLastDegenerateStrokePt =
nullptr;
127 return this->finishOpenContour();
135 float w()
const {
return this->atW(1); }
140 return fFirstPtsInContour;
144 constexpr static int kQueueBufferCount = 8;
145 Verb atVerb(
int i)
const {
146 SkASSERT(0 <= i && i < fQueueCount);
147 return fVerbs[(fQueueFrontIdx + i) & (kQueueBufferCount - 1)];
149 Verb backVerb()
const {
150 return this->atVerb(fQueueCount - 1);
152 const SkPoint* atPts(
int i)
const {
153 SkASSERT(0 <= i && i < fQueueCount);
154 return fPts[(fQueueFrontIdx + i) & (kQueueBufferCount - 1)];
156 const SkPoint* backPts()
const {
157 return this->atPts(fQueueCount - 1);
159 float atW(
int i)
const {
160 SkASSERT(0 <= i && i < fQueueCount);
161 const float*
w = fW[(fQueueFrontIdx + i) & (kQueueBufferCount - 1)];
166 SkASSERT(fQueueCount < kQueueBufferCount);
167 int i = (fQueueFrontIdx + fQueueCount) & (kQueueBufferCount - 1);
182 bool finishOpenContour() {
186 switch (fStroke->
getCap()) {
197 this->enqueue(
Verb::kCircle, this->backPts() + backIdx,
nullptr);
198 this->enqueue(
Verb::kCircle, fFirstPtsInContour, fFirstWInContour);
202 this->fillSquareCapPoints();
204 this->enqueue(
Verb::kLine, fEndingCapPts.data(),
nullptr);
208 this->enqueue(
Verb::kLine, fBeginningCapPts.data(),
nullptr);
211 }
else if (fLastDegenerateStrokePt) {
219 switch (fStroke->
getCap()) {
225 this->enqueue(
Verb::kCircle, fLastDegenerateStrokePt,
nullptr);
229 fFirstPtsInContour = fLastDegenerateStrokePt;
230 fFirstWInContour =
nullptr;
248 float det =
a*
d -
b*c;
263 fEndingCapPts = {*fLastDegenerateStrokePt -
outset,
264 *fLastDegenerateStrokePt +
outset};
266 this->enqueue(
Verb::kLine, fEndingCapPts.data(),
nullptr);
271 fFirstPtsInContour = fEndingCapPts.data();
272 fFirstWInContour =
nullptr;
283 this->enqueue(fFirstVerbInContour, fFirstPtsInContour, fFirstWInContour);
285 fLastDegenerateStrokePt =
nullptr;
291 void fillSquareCapPoints() {
294 const SkPoint* lastPts = this->backPts();
295 Verb lastVerb = this->backVerb();
298 lastTangent = lastPts[3] - lastPts[2];
299 if (!lastTangent.
isZero()) {
305 lastTangent = lastPts[2] - lastPts[1];
306 if (!lastTangent.
isZero()) {
311 lastTangent = lastPts[1] - lastPts[0];
319 lastTangent *= (.5f * fStroke->
getWidth()) / lastTangent.
length();
322 lastTangent *= .5f / fViewMatrix->
mapVector(lastTangent.
fX, lastTangent.
fY).length();
325 fEndingCapPts = {lastPoint, lastPoint + lastTangent};
328 SkVector firstTangent = fFirstPtsInContour[1] - fFirstPtsInContour[0];
329 if (firstTangent.
isZero()) {
332 firstTangent = fFirstPtsInContour[2] - fFirstPtsInContour[0];
333 if (firstTangent.
isZero()) {
335 firstTangent = fFirstPtsInContour[3] - fFirstPtsInContour[0];
341 firstTangent *= (-.5f * fStroke->
getWidth()) / firstTangent.
length();
345 -.5f / fViewMatrix->
mapVector(firstTangent.
fX, firstTangent.
fY).length();
347 fBeginningCapPts = {fFirstPtsInContour[0] + firstTangent, fFirstPtsInContour[0]};
357 Verb fFirstVerbInContour;
358 const SkPoint* fFirstPtsInContour;
359 const float* fFirstWInContour;
360 const SkPoint* fLastDegenerateStrokePt =
nullptr;
363 Verb fVerbs[kQueueBufferCount];
364 const SkPoint* fPts[kQueueBufferCount];
365 const float* fW[kQueueBufferCount];
366 int fQueueFrontIdx = 0;
371 std::array<SkPoint, 2> fClosePts;
372 std::array<SkPoint, 2> fEndingCapPts;
373 std::array<SkPoint, 2> fBeginningCapPts;
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d