8#ifndef skgpu_tessellate_StrokeIterator_DEFINED
9#define skgpu_tessellate_StrokeIterator_DEFINED
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 {
147 return fVerbs[(fQueueFrontIdx +
i) & (kQueueBufferCount - 1)];
149 Verb backVerb()
const {
150 return this->atVerb(fQueueCount - 1);
154 return fPts[(fQueueFrontIdx +
i) & (kQueueBufferCount - 1)];
156 const SkPoint* backPts()
const {
157 return this->atPts(fQueueCount - 1);
159 float atW(
int i)
const {
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;
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
SkScalar getSkewY() const
SkScalar getSkewX() const
SkScalar getScaleX() const
SkScalar getScaleY() const
bool hasPerspective() const
void mapVector(SkScalar dx, SkScalar dy, SkVector *result) const
@ kButt_Cap
no stroke extension
static int PtsInIter(unsigned verb)
SkPath::RangeIter RangeIter
bool isHairlineStyle() const
SkScalar getWidth() const
SkPaint::Cap getCap() const
Verb firstVerbInContour() const
const SkPoint * prevPts() const
const SkPoint * pts() const
StrokeIterator(const SkPath &path, const SkStrokeRec *stroke, const SkMatrix *viewMatrix)
static constexpr bool IsVerbGeometric(Verb verb)
const SkPoint * firstPtsInContour() const
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
SkPath::RangeIter begin()