Flutter Engine
The Flutter Engine
Public Member Functions | Protected Member Functions | Protected Attributes | Static Protected Attributes | List of all members
SkBaseShadowTessellator Class Reference
Inheritance diagram for SkBaseShadowTessellator:
SkAmbientShadowTessellator SkSpotShadowTessellator

Public Member Functions

 SkBaseShadowTessellator (const SkPoint3 &zPlaneParams, const SkRect &bounds, bool transparent)
 
virtual ~SkBaseShadowTessellator ()
 
sk_sp< SkVerticesreleaseVertices ()
 

Protected Member Functions

int vertexCount () const
 
int indexCount () const
 
bool accumulateCentroid (const SkPoint &c, const SkPoint &n)
 
bool checkConvexity (const SkPoint &p0, const SkPoint &p1, const SkPoint &p2)
 
void finishPathPolygon ()
 
bool computeConvexShadow (SkScalar inset, SkScalar outset, bool doClip)
 
void computeClipVectorsAndTestCentroid ()
 
bool clipUmbraPoint (const SkPoint &umbraPoint, const SkPoint &centroid, SkPoint *clipPoint)
 
void addEdge (const SkVector &nextPoint, const SkVector &nextNormal, SkColor umbraColor, const SkTDArray< SkPoint > &umbraPolygon, bool lastEdge, bool doClip)
 
bool addInnerPoint (const SkPoint &pathPoint, SkColor umbraColor, const SkTDArray< SkPoint > &umbraPolygon, int *currUmbraIndex)
 
int getClosestUmbraIndex (const SkPoint &point, const SkTDArray< SkPoint > &umbraPolygon)
 
bool computeConcaveShadow (SkScalar inset, SkScalar outset)
 
void stitchConcaveRings (const SkTDArray< SkPoint > &umbraPolygon, SkTDArray< int > *umbraIndices, const SkTDArray< SkPoint > &penumbraPolygon, SkTDArray< int > *penumbraIndices)
 
void handleLine (const SkPoint &p)
 
void handleLine (const SkMatrix &m, SkPoint *p)
 
void handleQuad (const SkPoint pts[3])
 
void handleQuad (const SkMatrix &m, SkPoint pts[3])
 
void handleCubic (const SkMatrix &m, SkPoint pts[4])
 
void handleConic (const SkMatrix &m, SkPoint pts[3], SkScalar w)
 
bool addArc (const SkVector &nextNormal, SkScalar offset, bool finishArc)
 
void appendTriangle (uint16_t index0, uint16_t index1, uint16_t index2)
 
void appendQuad (uint16_t index0, uint16_t index1, uint16_t index2, uint16_t index3)
 
SkScalar heightFunc (SkScalar x, SkScalar y)
 

Protected Attributes

SkPoint3 fZPlaneParams
 
SkTDArray< SkPointfPointBuffer
 
SkTDArray< SkPointfPositions
 
SkTDArray< SkColorfColors
 
SkTDArray< uint16_t > fIndices
 
SkTDArray< SkPointfPathPolygon
 
SkTDArray< SkPointfClipPolygon
 
SkTDArray< SkVectorfClipVectors
 
SkRect fPathBounds
 
SkPoint fCentroid
 
SkScalar fArea
 
SkScalar fLastArea
 
SkScalar fLastCross
 
int fFirstVertexIndex
 
SkVector fFirstOutset
 
SkPoint fFirstPoint
 
bool fSucceeded
 
bool fTransparent
 
bool fIsConvex
 
bool fValidUmbra
 
SkScalar fDirection
 
int fPrevUmbraIndex
 
int fCurrUmbraIndex
 
int fCurrClipIndex
 
bool fPrevUmbraOutside
 
bool fFirstUmbraOutside
 
SkVector fPrevOutset
 
SkPoint fPrevPoint
 

Static Protected Attributes

static constexpr auto kMinHeight = 0.1f
 
static constexpr auto kPenumbraColor = SK_ColorTRANSPARENT
 
static constexpr auto kUmbraColor = SK_ColorBLACK
 

Detailed Description

Base class

Definition at line 44 of file SkShadowTessellator.cpp.

Constructor & Destructor Documentation

◆ SkBaseShadowTessellator()

SkBaseShadowTessellator::SkBaseShadowTessellator ( const SkPoint3 zPlaneParams,
const SkRect bounds,
bool  transparent 
)

Definition at line 173 of file SkShadowTessellator.cpp.

175 : fZPlaneParams(zPlaneParams)
177 , fCentroid({0, 0})
178 , fArea(0)
179 , fLastArea(0)
180 , fLastCross(0)
182 , fSucceeded(false)
183 , fTransparent(transparent)
184 , fIsConvex(true)
185 , fValidUmbra(true)
186 , fDirection(1)
187 , fPrevUmbraIndex(-1)
188 , fCurrUmbraIndex(0)
189 , fCurrClipIndex(0)
190 , fPrevUmbraOutside(false)
191 , fFirstUmbraOutside(false) {
192 // child classes will set reserve for positions, colors and indices
193}
Optional< SkRect > bounds
Definition: SkRecords.h:189

◆ ~SkBaseShadowTessellator()

virtual SkBaseShadowTessellator::~SkBaseShadowTessellator ( )
inlinevirtual

Definition at line 47 of file SkShadowTessellator.cpp.

47{}

Member Function Documentation

◆ accumulateCentroid()

bool SkBaseShadowTessellator::accumulateCentroid ( const SkPoint c,
const SkPoint n 
)
protected

Definition at line 195 of file SkShadowTessellator.cpp.

195 {
196 if (duplicate_pt(curr, next)) {
197 return false;
198 }
199
201 SkVector v0 = curr - fPathPolygon[0];
202 SkVector v1 = next - fPathPolygon[0];
203 SkScalar quadArea = v0.cross(v1);
204 fCentroid.fX += (v0.fX + v1.fX) * quadArea;
205 fCentroid.fY += (v0.fY + v1.fY) * quadArea;
206 fArea += quadArea;
207 // convexity check
208 if (quadArea*fLastArea < 0) {
209 fIsConvex = false;
210 }
211 if (0 != quadArea) {
212 fLastArea = quadArea;
213 }
214
215 return true;
216}
static float next(float f)
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool duplicate_pt(const SkPoint &p0, const SkPoint &p1)
SkTDArray< SkPoint > fPathPolygon
bool empty() const
Definition: SkTDArray.h:135
float SkScalar
Definition: extension.cpp:12
float fX
x-axis value
Definition: SkPoint_impl.h:164
float cross(const SkVector &vec) const
Definition: SkPoint_impl.h:545
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ addArc()

bool SkBaseShadowTessellator::addArc ( const SkVector nextNormal,
SkScalar  offset,
bool  finishArc 
)
protected

Definition at line 862 of file SkShadowTessellator.cpp.

862 {
863 // fill in fan from previous quad
864 SkScalar rotSin, rotCos;
865 int numSteps;
866 if (!SkComputeRadialSteps(fPrevOutset, nextNormal, offset, &rotSin, &rotCos, &numSteps)) {
867 // recover as best we can
868 numSteps = 0;
869 }
870 SkVector prevNormal = fPrevOutset;
871 for (int i = 0; i < numSteps-1; ++i) {
872 SkVector currNormal;
873 currNormal.fX = prevNormal.fX*rotCos - prevNormal.fY*rotSin;
874 currNormal.fY = prevNormal.fY*rotCos + prevNormal.fX*rotSin;
875 fPositions.push_back(fPrevPoint + currNormal);
878
879 prevNormal = currNormal;
880 }
881 if (finishArc && numSteps) {
882 fPositions.push_back(fPrevPoint + nextNormal);
885 }
886 fPrevOutset = nextNormal;
887
888 return (numSteps > 0);
889}
bool SkComputeRadialSteps(const SkVector &v1, const SkVector &v2, SkScalar offset, SkScalar *rotSin, SkScalar *rotCos, int *n)
static constexpr auto kPenumbraColor
SkTDArray< SkPoint > fPositions
void appendTriangle(uint16_t index0, uint16_t index1, uint16_t index2)
SkTDArray< SkColor > fColors
int size() const
Definition: SkTDArray.h:138
void push_back(const T &v)
Definition: SkTDArray.h:219
SeparatedVector2 offset

◆ addEdge()

void SkBaseShadowTessellator::addEdge ( const SkVector nextPoint,
const SkVector nextNormal,
SkColor  umbraColor,
const SkTDArray< SkPoint > &  umbraPolygon,
bool  lastEdge,
bool  doClip 
)
protected

Definition at line 416 of file SkShadowTessellator.cpp.

418 {
419 // add next umbra point
420 int currUmbraIndex;
421 bool duplicate;
422 if (lastEdge) {
423 duplicate = false;
424 currUmbraIndex = fFirstVertexIndex;
425 fPrevPoint = nextPoint;
426 } else {
427 duplicate = this->addInnerPoint(nextPoint, umbraColor, umbraPolygon, &currUmbraIndex);
428 }
429 int prevPenumbraIndex = duplicate || (currUmbraIndex == fFirstVertexIndex)
430 ? fPositions.size() - 1
431 : fPositions.size() - 2;
432 if (!duplicate) {
433 // add to center fan if transparent or centroid showing
434 if (fTransparent) {
435 this->appendTriangle(0, fPrevUmbraIndex, currUmbraIndex);
436 // otherwise add to clip ring
437 } else if (doClip) {
438 SkPoint clipPoint;
439 bool isOutside = lastEdge ? fFirstUmbraOutside
440 : this->clipUmbraPoint(fPositions[currUmbraIndex], fCentroid,
441 &clipPoint);
442 if (isOutside) {
443 if (!lastEdge) {
444 fPositions.push_back(clipPoint);
445 fColors.push_back(umbraColor);
446 }
447 this->appendTriangle(fPrevUmbraIndex, currUmbraIndex, currUmbraIndex + 1);
448 if (fPrevUmbraOutside) {
449 // fill out quad
450 this->appendTriangle(fPrevUmbraIndex, currUmbraIndex + 1,
451 fPrevUmbraIndex + 1);
452 }
453 } else if (fPrevUmbraOutside) {
454 // add tri
455 this->appendTriangle(fPrevUmbraIndex, currUmbraIndex, fPrevUmbraIndex + 1);
456 }
457
458 fPrevUmbraOutside = isOutside;
459 }
460 }
461
462 // add next penumbra point and quad
463 SkPoint newPoint = nextPoint + nextNormal;
464 fPositions.push_back(newPoint);
466
467 if (!duplicate) {
468 this->appendTriangle(fPrevUmbraIndex, prevPenumbraIndex, currUmbraIndex);
469 }
470 this->appendTriangle(prevPenumbraIndex, fPositions.size() - 1, currUmbraIndex);
471
472 fPrevUmbraIndex = currUmbraIndex;
473 fPrevOutset = nextNormal;
474}
bool clipUmbraPoint(const SkPoint &umbraPoint, const SkPoint &centroid, SkPoint *clipPoint)
bool addInnerPoint(const SkPoint &pathPoint, SkColor umbraColor, const SkTDArray< SkPoint > &umbraPolygon, int *currUmbraIndex)

◆ addInnerPoint()

bool SkBaseShadowTessellator::addInnerPoint ( const SkPoint pathPoint,
SkColor  umbraColor,
const SkTDArray< SkPoint > &  umbraPolygon,
int currUmbraIndex 
)
protected

Definition at line 508 of file SkShadowTessellator.cpp.

510 {
511 SkPoint umbraPoint;
512 if (!fValidUmbra) {
513 SkVector v = fCentroid - pathPoint;
514 v *= 0.95f;
515 umbraPoint = pathPoint + v;
516 } else {
517 umbraPoint = umbraPolygon[this->getClosestUmbraIndex(pathPoint, umbraPolygon)];
518 }
519
520 fPrevPoint = pathPoint;
521
522 // merge "close" points
523 if (fPrevUmbraIndex == -1 ||
524 !duplicate_pt(umbraPoint, fPositions[fPrevUmbraIndex])) {
525 // if we've wrapped around, don't add a new point
526 if (fPrevUmbraIndex >= 0 && duplicate_pt(umbraPoint, fPositions[fFirstVertexIndex])) {
527 *currUmbraIndex = fFirstVertexIndex;
528 } else {
529 *currUmbraIndex = fPositions.size();
530 fPositions.push_back(umbraPoint);
531 fColors.push_back(umbraColor);
532 }
533 return false;
534 } else {
535 *currUmbraIndex = fPrevUmbraIndex;
536 return true;
537 }
538}
int getClosestUmbraIndex(const SkPoint &point, const SkTDArray< SkPoint > &umbraPolygon)

◆ appendQuad()

void SkBaseShadowTessellator::appendQuad ( uint16_t  index0,
uint16_t  index1,
uint16_t  index2,
uint16_t  index3 
)
protected

Definition at line 899 of file SkShadowTessellator.cpp.

900 {
901 auto indices = fIndices.append(6);
902
903 indices[0] = index0;
904 indices[1] = index1;
905 indices[2] = index2;
906
907 indices[3] = index2;
908 indices[4] = index1;
909 indices[5] = index3;
910}
SkTDArray< uint16_t > fIndices
T * append()
Definition: SkTDArray.h:191

◆ appendTriangle()

void SkBaseShadowTessellator::appendTriangle ( uint16_t  index0,
uint16_t  index1,
uint16_t  index2 
)
protected

Definition at line 891 of file SkShadowTessellator.cpp.

891 {
892 auto indices = fIndices.append(3);
893
894 indices[0] = index0;
895 indices[1] = index1;
896 indices[2] = index2;
897}

◆ checkConvexity()

bool SkBaseShadowTessellator::checkConvexity ( const SkPoint p0,
const SkPoint p1,
const SkPoint p2 
)
protected

Definition at line 218 of file SkShadowTessellator.cpp.

220 {
221 SkScalar cross = perp_dot(p0, p1, p2);
222 // skip collinear point
224 return false;
225 }
226
227 // check for convexity
228 if (fLastCross*cross < 0) {
229 fIsConvex = false;
230 }
231 if (0 != cross) {
233 }
234
235 return true;
236}
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
static SkScalar perp_dot(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2)
int64_t cross(Point d0, Point d1)
Definition: Myers.cpp:55

◆ clipUmbraPoint()

bool SkBaseShadowTessellator::clipUmbraPoint ( const SkPoint umbraPoint,
const SkPoint centroid,
SkPoint clipPoint 
)
protected

Definition at line 476 of file SkShadowTessellator.cpp.

477 {
478 SkVector segmentVector = centroid - umbraPoint;
479
480 int startClipPoint = fCurrClipIndex;
481 do {
482 SkVector dp = umbraPoint - fClipPolygon[fCurrClipIndex];
483 SkScalar denom = fClipVectors[fCurrClipIndex].cross(segmentVector);
484 SkScalar t_num = dp.cross(segmentVector);
485 // if line segments are nearly parallel
486 if (SkScalarNearlyZero(denom)) {
487 // and collinear
488 if (SkScalarNearlyZero(t_num)) {
489 return false;
490 }
491 // otherwise are separate, will try the next poly segment
492 // else if crossing lies within poly segment
493 } else if (t_num >= 0 && t_num <= denom) {
495 // if umbra point is inside the clip polygon
496 if (s_num >= 0 && s_num <= denom) {
497 segmentVector *= s_num / denom;
498 *clipPoint = umbraPoint + segmentVector;
499 return true;
500 }
501 }
503 } while (fCurrClipIndex != startClipPoint);
504
505 return false;
506}
SkTDArray< SkPoint > fClipPolygon
SkTDArray< SkVector > fClipVectors

◆ computeClipVectorsAndTestCentroid()

void SkBaseShadowTessellator::computeClipVectorsAndTestCentroid ( )
protected

Definition at line 387 of file SkShadowTessellator.cpp.

387 {
388 SkASSERT(fClipPolygon.size() >= 3);
390
391 // init clip vectors
394 fClipVectors.push_back(v0);
395
396 // init centroid check
397 bool hiddenCentroid = true;
398 v1 = fCentroid - fClipPolygon[0];
399 SkScalar initCross = v0.cross(v1);
400
401 for (int p = 1; p < fClipPolygon.size(); ++p) {
402 // add to clip vectors
403 v0 = fClipPolygon[(p + 1) % fClipPolygon.size()] - fClipPolygon[p];
404 fClipVectors.push_back(v0);
405 // Determine if transformed centroid is inside clipPolygon.
406 v1 = fCentroid - fClipPolygon[p];
407 if (initCross*v0.cross(v1) <= 0) {
408 hiddenCentroid = false;
409 }
410 }
412
413 fTransparent = fTransparent || !hiddenCentroid;
414}

◆ computeConcaveShadow()

bool SkBaseShadowTessellator::computeConcaveShadow ( SkScalar  inset,
SkScalar  outset 
)
protected

Definition at line 570 of file SkShadowTessellator.cpp.

570 {
572 return false;
573 }
574
575 // shouldn't inset more than the half bounds of the polygon
578 // generate inner ring
579 SkTDArray<SkPoint> umbraPolygon;
580 SkTDArray<int> umbraIndices;
581 umbraIndices.reserve(fPathPolygon.size());
583 &umbraPolygon, &umbraIndices)) {
584 // TODO: figure out how to handle this case
585 return false;
586 }
587
588 // generate outer ring
589 SkTDArray<SkPoint> penumbraPolygon;
590 SkTDArray<int> penumbraIndices;
591 penumbraPolygon.reserve(umbraPolygon.size());
592 penumbraIndices.reserve(umbraPolygon.size());
594 &penumbraPolygon, &penumbraIndices)) {
595 // TODO: figure out how to handle this case
596 return false;
597 }
598
599 if (umbraPolygon.empty() || penumbraPolygon.empty()) {
600 return false;
601 }
602
603 // attach the rings together
604 this->stitchConcaveRings(umbraPolygon, &umbraIndices, penumbraPolygon, &penumbraIndices);
605
606 return true;
607}
static const int outset
Definition: BlurTest.cpp:58
bool SkOffsetSimplePolygon(const SkPoint *inputPolygonVerts, int inputPolygonSize, const SkRect &bounds, SkScalar offset, SkTDArray< SkPoint > *offsetPolygon, SkTDArray< int > *polygonIndices)
bool SkIsSimplePolygon(const SkPoint *polygon, int polygonSize)
static T SkTAbs(T value)
Definition: SkTemplates.h:43
void stitchConcaveRings(const SkTDArray< SkPoint > &umbraPolygon, SkTDArray< int > *umbraIndices, const SkTDArray< SkPoint > &penumbraPolygon, SkTDArray< int > *penumbraIndices)
static constexpr float HalfWidth(const SkRect &r)
Definition: SkRectPriv.h:62
static constexpr float HalfHeight(const SkRect &r)
Definition: SkRectPriv.h:66
void reserve(int n)
Definition: SkTDArray.h:187
static float min(float r, float g, float b)
Definition: hsl.cpp:48
static SkRect inset(const SkRect &r)

◆ computeConvexShadow()

bool SkBaseShadowTessellator::computeConvexShadow ( SkScalar  inset,
SkScalar  outset,
bool  doClip 
)
protected

Definition at line 263 of file SkShadowTessellator.cpp.

263 {
264 if (doClip) {
266 }
267
268 // adjust inset distance and umbra color if necessary
269 auto umbraColor = kUmbraColor;
271 fPathPolygon[0],
272 fPathPolygon[1]);
274 bounds.setBounds(&fPathPolygon[0], fPathPolygon.size());
275 for (int i = 1; i < fPathPolygon.size(); ++i) {
276 int j = i + 1;
277 if (i == fPathPolygon.size() - 1) {
278 j = 0;
279 }
280 SkPoint currPoint = fPathPolygon[i];
281 SkPoint nextPoint = fPathPolygon[j];
283 nextPoint);
284 if (distSq < minDistSq) {
285 minDistSq = distSq;
286 }
287 }
288
289 SkTDArray<SkPoint> insetPolygon;
291 static constexpr auto kTolerance = 1.0e-2f;
292 if (minDistSq < (inset + kTolerance)*(inset + kTolerance)) {
293 // if the umbra would collapse, we back off a bit on inner blur and adjust the alpha
294 auto newInset = SkScalarSqrt(minDistSq) - kTolerance;
295 auto ratio = 128 * (newInset / inset + 1);
296 SkASSERT(SkIsFinite(ratio));
297 // they aren't PMColors, but the interpolation algorithm is the same
298 umbraColor = SkPMLerp(kUmbraColor, kPenumbraColor, (unsigned)ratio);
299 inset = newInset;
300 }
301
302 // generate inner ring
304 &insetPolygon)) {
305 // not ideal, but in this case we'll inset using the centroid
306 fValidUmbra = false;
307 }
308 }
309 const SkTDArray<SkPoint>& umbraPolygon = (inset > SK_ScalarNearlyZero) ? insetPolygon
310 : fPathPolygon;
311
312 // walk around the path polygon, generate outer ring and connect to inner ring
313 if (fTransparent) {
315 fColors.push_back(umbraColor);
316 }
317 fCurrUmbraIndex = 0;
318
319 // initial setup
320 // add first quad
321 int polyCount = fPathPolygon.size();
322 if (!compute_normal(fPathPolygon[polyCount - 1], fPathPolygon[0], fDirection, &fFirstOutset)) {
323 // polygon should be sanitized by this point, so this is unrecoverable
324 return false;
325 }
326
328 fFirstPoint = fPathPolygon[polyCount - 1];
332 fPrevUmbraIndex = -1;
333
334 this->addInnerPoint(fFirstPoint, umbraColor, umbraPolygon, &fPrevUmbraIndex);
335
336 if (!fTransparent && doClip) {
337 SkPoint clipPoint;
338 bool isOutside = this->clipUmbraPoint(fPositions[fFirstVertexIndex],
339 fCentroid, &clipPoint);
340 if (isOutside) {
341 fPositions.push_back(clipPoint);
342 fColors.push_back(umbraColor);
343 }
344 fPrevUmbraOutside = isOutside;
345 fFirstUmbraOutside = isOutside;
346 }
347
348 SkPoint newPoint = fFirstPoint + fFirstOutset;
349 fPositions.push_back(newPoint);
351 this->addEdge(fPathPolygon[0], fFirstOutset, umbraColor, umbraPolygon, false, doClip);
352
353 for (int i = 1; i < polyCount; ++i) {
356 return false;
357 }
358 normal *= outset;
359 this->addArc(normal, outset, true);
360 this->addEdge(fPathPolygon[i], normal, umbraColor, umbraPolygon,
361 i == polyCount - 1, doClip);
362 }
363 SkASSERT(this->indexCount());
364
365 // final fan
366 SkASSERT(fPositions.size() >= 3);
367 if (this->addArc(fFirstOutset, outset, false)) {
368 if (fFirstUmbraOutside) {
371 } else {
374 }
375 } else {
376 // no arc added, fix up by setting first penumbra point position to last one
377 if (fFirstUmbraOutside) {
379 } else {
381 }
382 }
383
384 return true;
385}
static constexpr float kTolerance
Definition: GrQuadUtils.cpp:29
static SkPMColor SkPMLerp(SkPMColor src, SkPMColor dst, unsigned scale)
Definition: SkColorData.h:270
static bool SkIsFinite(T x, Pack... values)
bool SkInsetConvexPolygon(const SkPoint *inputPolygonVerts, int inputPolygonSize, SkScalar inset, SkTDArray< SkPoint > *insetPolygon)
#define SK_ScalarNearlyZero
Definition: SkScalar.h:99
#define SkScalarSqrt(x)
Definition: SkScalar.h:42
static bool compute_normal(const SkPoint &p0, const SkPoint &p1, SkScalar dir, SkVector *newNormal)
static constexpr auto kUmbraColor
void addEdge(const SkVector &nextPoint, const SkVector &nextNormal, SkColor umbraColor, const SkTDArray< SkPoint > &umbraPolygon, bool lastEdge, bool doClip)
bool addArc(const SkVector &nextNormal, SkScalar offset, bool finishArc)
static SkScalar DistanceToLineSegmentBetweenSqd(const SkPoint &pt, const SkPoint &a, const SkPoint &b)
Definition: SkPoint.cpp:126

◆ finishPathPolygon()

void SkBaseShadowTessellator::finishPathPolygon ( )
protected

Definition at line 238 of file SkShadowTessellator.cpp.

238 {
239 if (fPathPolygon.size() > 1) {
241 // remove coincident point
243 }
244 }
245
246 if (fPathPolygon.size() > 2) {
247 // do this before the final convexity check, so we use the correct fPathPolygon[0]
252 fPathPolygon[0])) {
253 // remove collinear point
256 }
257 }
258
259 // if area is positive, winding is ccw
260 fDirection = fArea > 0 ? -1 : 1;
261}
static constexpr float sk_ieee_float_divide(float numer, float denom)
bool accumulateCentroid(const SkPoint &c, const SkPoint &n)
bool checkConvexity(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2)
void pop_back()
Definition: SkTDArray.h:223

◆ getClosestUmbraIndex()

int SkBaseShadowTessellator::getClosestUmbraIndex ( const SkPoint point,
const SkTDArray< SkPoint > &  umbraPolygon 
)
protected

Definition at line 540 of file SkShadowTessellator.cpp.

541 {
542 SkScalar minDistance = SkPointPriv::DistanceToSqd(p, umbraPolygon[fCurrUmbraIndex]);
543 int index = fCurrUmbraIndex;
544 int dir = 1;
545 int next = (index + dir) % umbraPolygon.size();
546
547 // init travel direction
549 if (distance < minDistance) {
550 index = next;
551 minDistance = distance;
552 } else {
553 dir = umbraPolygon.size() - 1;
554 }
555
556 // iterate until we find a point that increases the distance
557 next = (index + dir) % umbraPolygon.size();
558 distance = SkPointPriv::DistanceToSqd(p, umbraPolygon[next]);
559 while (distance < minDistance) {
560 index = next;
561 minDistance = distance;
562 next = (index + dir) % umbraPolygon.size();
563 distance = SkPointPriv::DistanceToSqd(p, umbraPolygon[next]);
564 }
565
566 fCurrUmbraIndex = index;
567 return index;
568}
static SkScalar DistanceToSqd(const SkPoint &pt, const SkPoint &a)
Definition: SkPointPriv.h:48
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 to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145

◆ handleConic()

void SkBaseShadowTessellator::handleConic ( const SkMatrix m,
SkPoint  pts[3],
SkScalar  w 
)
protected

Definition at line 842 of file SkShadowTessellator.cpp.

842 {
843 if (m.hasPerspective()) {
844 w = SkConic::TransformW(pts, w, m);
845 }
846 m.mapPoints(pts, 3);
847 SkAutoConicToQuads quadder;
848 const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance);
849 SkPoint lastPoint = *(quads++);
850 int count = quadder.countQuads();
851 for (int i = 0; i < count; ++i) {
852 SkPoint quadPts[3];
853 quadPts[0] = lastPoint;
854 quadPts[1] = quads[0];
855 quadPts[2] = i == count - 1 ? pts[2] : quads[1];
856 this->handleQuad(quadPts);
857 lastPoint = quadPts[2];
858 quads += 2;
859 }
860}
int count
Definition: FontMgrTest.cpp:50
static constexpr SkScalar kConicTolerance
const SkPoint * computeQuads(const SkConic &conic, SkScalar tol)
Definition: SkGeometry.h:524
int countQuads() const
Definition: SkGeometry.h:539
void handleQuad(const SkPoint pts[3])
SkScalar w
static SkScalar TransformW(const SkPoint[3], SkScalar w, const SkMatrix &)

◆ handleCubic()

void SkBaseShadowTessellator::handleCubic ( const SkMatrix m,
SkPoint  pts[4] 
)
protected

Definition at line 821 of file SkShadowTessellator.cpp.

821 {
822 m.mapPoints(pts, 4);
823#if defined(SK_GANESH)
824 // TODO: Pull PathUtils out of Ganesh?
826 fPointBuffer.resize(maxCount);
828 int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3],
829 kCubicToleranceSqd, &target, maxCount);
831 for (int i = 0; i < count; i++) {
832 this->handleLine(fPointBuffer[i]);
833 }
834#else
835 // for now, just to draw something
836 this->handleLine(pts[1]);
837 this->handleLine(pts[2]);
838 this->handleLine(pts[3]);
839#endif
840}
static constexpr SkScalar kCubicToleranceSqd
static constexpr SkScalar kCubicTolerance
void handleLine(const SkPoint &p)
SkTDArray< SkPoint > fPointBuffer
T * begin()
Definition: SkTDArray.h:150
void resize(int count)
Definition: SkTDArray.h:183
uint32_t * target
uint32_t generateCubicPoints(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, const SkPoint &p3, SkScalar tolSqd, SkPoint **points, uint32_t pointsLeft)
uint32_t cubicPointCount(const SkPoint points[], SkScalar tol)

◆ handleLine() [1/2]

void SkBaseShadowTessellator::handleLine ( const SkMatrix m,
SkPoint p 
)
protected

Definition at line 785 of file SkShadowTessellator.cpp.

785 {
786 m.mapPoints(p, 1);
787
788 this->handleLine(*p);
789}

◆ handleLine() [2/2]

void SkBaseShadowTessellator::handleLine ( const SkPoint p)
protected

Definition at line 758 of file SkShadowTessellator.cpp.

758 {
759 SkPoint pSanitized;
760 sanitize_point(p, &pSanitized);
761
762 if (!fPathPolygon.empty()) {
763 if (!this->accumulateCentroid(fPathPolygon[fPathPolygon.size() - 1], pSanitized)) {
764 // skip coincident point
765 return;
766 }
767 }
768
769 if (fPathPolygon.size() > 1) {
772 pSanitized)) {
773 // remove collinear point
775 // it's possible that the previous point is coincident with the new one now
776 if (duplicate_pt(fPathPolygon[fPathPolygon.size() - 1], pSanitized)) {
778 }
779 }
780 }
781
782 fPathPolygon.push_back(pSanitized);
783}
static void sanitize_point(const SkPoint &in, SkPoint *out)

◆ handleQuad() [1/2]

void SkBaseShadowTessellator::handleQuad ( const SkMatrix m,
SkPoint  pts[3] 
)
protected

Definition at line 816 of file SkShadowTessellator.cpp.

816 {
817 m.mapPoints(pts, 3);
818 this->handleQuad(pts);
819}

◆ handleQuad() [2/2]

void SkBaseShadowTessellator::handleQuad ( const SkPoint  pts[3])
protected

Definition at line 791 of file SkShadowTessellator.cpp.

791 {
792#if defined(SK_GANESH)
793 // check for degeneracy
794 SkVector v0 = pts[1] - pts[0];
795 SkVector v1 = pts[2] - pts[0];
796 if (SkScalarNearlyZero(v0.cross(v1))) {
797 return;
798 }
799 // TODO: Pull PathUtils out of Ganesh?
801 fPointBuffer.resize(maxCount);
803 int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2],
804 kQuadToleranceSqd, &target, maxCount);
806 for (int i = 0; i < count; i++) {
807 this->handleLine(fPointBuffer[i]);
808 }
809#else
810 // for now, just to draw something
811 this->handleLine(pts[1]);
812 this->handleLine(pts[2]);
813#endif
814}
static constexpr SkScalar kQuadTolerance
static constexpr SkScalar kQuadToleranceSqd
uint32_t quadraticPointCount(const SkPoint points[], SkScalar tol)
Definition: GrPathUtils.cpp:73
uint32_t generateQuadraticPoints(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, SkScalar tolSqd, SkPoint **points, uint32_t pointsLeft)
Definition: GrPathUtils.cpp:78

◆ heightFunc()

SkScalar SkBaseShadowTessellator::heightFunc ( SkScalar  x,
SkScalar  y 
)
inlineprotected

Definition at line 103 of file SkShadowTessellator.cpp.

103 {
105 }
double y
double x
SkScalar fX
Definition: SkPoint3.h:16
SkScalar fZ
Definition: SkPoint3.h:16
SkScalar fY
Definition: SkPoint3.h:16

◆ indexCount()

int SkBaseShadowTessellator::indexCount ( ) const
inlineprotected

Definition at line 64 of file SkShadowTessellator.cpp.

64{ return fIndices.size(); }

◆ releaseVertices()

sk_sp< SkVertices > SkBaseShadowTessellator::releaseVertices ( )
inline

Definition at line 49 of file SkShadowTessellator.cpp.

49 {
50 if (!fSucceeded) {
51 return nullptr;
52 }
54 fPositions.begin(), nullptr, fColors.begin(),
55 this->indexCount(), fIndices.begin());
56 }
static sk_sp< SkVertices > MakeCopy(VertexMode mode, int vertexCount, const SkPoint positions[], const SkPoint texs[], const SkColor colors[], int indexCount, const uint16_t indices[])
Definition: SkVertices.cpp:200
@ kTriangles_VertexMode
Definition: SkVertices.h:31

◆ stitchConcaveRings()

void SkBaseShadowTessellator::stitchConcaveRings ( const SkTDArray< SkPoint > &  umbraPolygon,
SkTDArray< int > *  umbraIndices,
const SkTDArray< SkPoint > &  penumbraPolygon,
SkTDArray< int > *  penumbraIndices 
)
protected

Definition at line 609 of file SkShadowTessellator.cpp.

612 {
613 // TODO: only create and fill indexMap when fTransparent is true?
614 AutoSTMalloc<64, uint16_t> indexMap(umbraPolygon.size());
615
616 // find minimum indices
617 int minIndex = 0;
618 int min = (*penumbraIndices)[0];
619 for (int i = 1; i < (*penumbraIndices).size(); ++i) {
620 if ((*penumbraIndices)[i] < min) {
621 min = (*penumbraIndices)[i];
622 minIndex = i;
623 }
624 }
625 int currPenumbra = minIndex;
626
627 minIndex = 0;
628 min = (*umbraIndices)[0];
629 for (int i = 1; i < (*umbraIndices).size(); ++i) {
630 if ((*umbraIndices)[i] < min) {
631 min = (*umbraIndices)[i];
632 minIndex = i;
633 }
634 }
635 int currUmbra = minIndex;
636
637 // now find a case where the indices are equal (there should be at least one)
638 int maxPenumbraIndex = fPathPolygon.size() - 1;
639 int maxUmbraIndex = fPathPolygon.size() - 1;
640 while ((*penumbraIndices)[currPenumbra] != (*umbraIndices)[currUmbra]) {
641 if ((*penumbraIndices)[currPenumbra] < (*umbraIndices)[currUmbra]) {
642 (*penumbraIndices)[currPenumbra] += fPathPolygon.size();
643 maxPenumbraIndex = (*penumbraIndices)[currPenumbra];
644 currPenumbra = (currPenumbra + 1) % penumbraPolygon.size();
645 } else {
646 (*umbraIndices)[currUmbra] += fPathPolygon.size();
647 maxUmbraIndex = (*umbraIndices)[currUmbra];
648 currUmbra = (currUmbra + 1) % umbraPolygon.size();
649 }
650 }
651
652 fPositions.push_back(penumbraPolygon[currPenumbra]);
654 int prevPenumbraIndex = 0;
655 fPositions.push_back(umbraPolygon[currUmbra]);
657 fPrevUmbraIndex = 1;
658 indexMap[currUmbra] = 1;
659
660 int nextPenumbra = (currPenumbra + 1) % penumbraPolygon.size();
661 int nextUmbra = (currUmbra + 1) % umbraPolygon.size();
662 while ((*penumbraIndices)[nextPenumbra] <= maxPenumbraIndex ||
663 (*umbraIndices)[nextUmbra] <= maxUmbraIndex) {
664
665 if ((*umbraIndices)[nextUmbra] == (*penumbraIndices)[nextPenumbra]) {
666 // advance both one step
667 fPositions.push_back(penumbraPolygon[nextPenumbra]);
669 int currPenumbraIndex = fPositions.size() - 1;
670
671 fPositions.push_back(umbraPolygon[nextUmbra]);
673 int currUmbraIndex = fPositions.size() - 1;
674 indexMap[nextUmbra] = currUmbraIndex;
675
676 this->appendQuad(prevPenumbraIndex, currPenumbraIndex,
677 fPrevUmbraIndex, currUmbraIndex);
678
679 prevPenumbraIndex = currPenumbraIndex;
680 (*penumbraIndices)[currPenumbra] += fPathPolygon.size();
681 currPenumbra = nextPenumbra;
682 nextPenumbra = (currPenumbra + 1) % penumbraPolygon.size();
683
684 fPrevUmbraIndex = currUmbraIndex;
685 (*umbraIndices)[currUmbra] += fPathPolygon.size();
686 currUmbra = nextUmbra;
687 nextUmbra = (currUmbra + 1) % umbraPolygon.size();
688 }
689
690 while ((*penumbraIndices)[nextPenumbra] < (*umbraIndices)[nextUmbra] &&
691 (*penumbraIndices)[nextPenumbra] <= maxPenumbraIndex) {
692 // fill out penumbra arc
693 fPositions.push_back(penumbraPolygon[nextPenumbra]);
695 int currPenumbraIndex = fPositions.size() - 1;
696
697 this->appendTriangle(prevPenumbraIndex, currPenumbraIndex, fPrevUmbraIndex);
698
699 prevPenumbraIndex = currPenumbraIndex;
700 // this ensures the ordering when we wrap around
701 (*penumbraIndices)[currPenumbra] += fPathPolygon.size();
702 currPenumbra = nextPenumbra;
703 nextPenumbra = (currPenumbra + 1) % penumbraPolygon.size();
704 }
705
706 while ((*umbraIndices)[nextUmbra] < (*penumbraIndices)[nextPenumbra] &&
707 (*umbraIndices)[nextUmbra] <= maxUmbraIndex) {
708 // fill out umbra arc
709 fPositions.push_back(umbraPolygon[nextUmbra]);
711 int currUmbraIndex = fPositions.size() - 1;
712 indexMap[nextUmbra] = currUmbraIndex;
713
714 this->appendTriangle(fPrevUmbraIndex, prevPenumbraIndex, currUmbraIndex);
715
716 fPrevUmbraIndex = currUmbraIndex;
717 // this ensures the ordering when we wrap around
718 (*umbraIndices)[currUmbra] += fPathPolygon.size();
719 currUmbra = nextUmbra;
720 nextUmbra = (currUmbra + 1) % umbraPolygon.size();
721 }
722 }
723 // finish up by advancing both one step
724 fPositions.push_back(penumbraPolygon[nextPenumbra]);
726 int currPenumbraIndex = fPositions.size() - 1;
727
728 fPositions.push_back(umbraPolygon[nextUmbra]);
730 int currUmbraIndex = fPositions.size() - 1;
731 indexMap[nextUmbra] = currUmbraIndex;
732
733 this->appendQuad(prevPenumbraIndex, currPenumbraIndex,
734 fPrevUmbraIndex, currUmbraIndex);
735
736 if (fTransparent) {
737 SkTriangulateSimplePolygon(umbraPolygon.begin(), indexMap, umbraPolygon.size(),
738 &fIndices);
739 }
740}
bool SkTriangulateSimplePolygon(const SkPoint *polygonVerts, uint16_t *indexMap, int polygonSize, SkTDArray< uint16_t > *triangleIndices)
void appendQuad(uint16_t index0, uint16_t index1, uint16_t index2, uint16_t index3)

◆ vertexCount()

int SkBaseShadowTessellator::vertexCount ( ) const
inlineprotected

Definition at line 63 of file SkShadowTessellator.cpp.

63{ return fPositions.size(); }

Member Data Documentation

◆ fArea

SkScalar SkBaseShadowTessellator::fArea
protected

Definition at line 122 of file SkShadowTessellator.cpp.

◆ fCentroid

SkPoint SkBaseShadowTessellator::fCentroid
protected

Definition at line 121 of file SkShadowTessellator.cpp.

◆ fClipPolygon

SkTDArray<SkPoint> SkBaseShadowTessellator::fClipPolygon
protected

Definition at line 117 of file SkShadowTessellator.cpp.

◆ fClipVectors

SkTDArray<SkVector> SkBaseShadowTessellator::fClipVectors
protected

Definition at line 118 of file SkShadowTessellator.cpp.

◆ fColors

SkTDArray<SkColor> SkBaseShadowTessellator::fColors
protected

Definition at line 113 of file SkShadowTessellator.cpp.

◆ fCurrClipIndex

int SkBaseShadowTessellator::fCurrClipIndex
protected

Definition at line 138 of file SkShadowTessellator.cpp.

◆ fCurrUmbraIndex

int SkBaseShadowTessellator::fCurrUmbraIndex
protected

Definition at line 137 of file SkShadowTessellator.cpp.

◆ fDirection

SkScalar SkBaseShadowTessellator::fDirection
protected

Definition at line 135 of file SkShadowTessellator.cpp.

◆ fFirstOutset

SkVector SkBaseShadowTessellator::fFirstOutset
protected

Definition at line 127 of file SkShadowTessellator.cpp.

◆ fFirstPoint

SkPoint SkBaseShadowTessellator::fFirstPoint
protected

Definition at line 128 of file SkShadowTessellator.cpp.

◆ fFirstUmbraOutside

bool SkBaseShadowTessellator::fFirstUmbraOutside
protected

Definition at line 140 of file SkShadowTessellator.cpp.

◆ fFirstVertexIndex

int SkBaseShadowTessellator::fFirstVertexIndex
protected

Definition at line 126 of file SkShadowTessellator.cpp.

◆ fIndices

SkTDArray<uint16_t> SkBaseShadowTessellator::fIndices
protected

Definition at line 114 of file SkShadowTessellator.cpp.

◆ fIsConvex

bool SkBaseShadowTessellator::fIsConvex
protected

Definition at line 132 of file SkShadowTessellator.cpp.

◆ fLastArea

SkScalar SkBaseShadowTessellator::fLastArea
protected

Definition at line 123 of file SkShadowTessellator.cpp.

◆ fLastCross

SkScalar SkBaseShadowTessellator::fLastCross
protected

Definition at line 124 of file SkShadowTessellator.cpp.

◆ fPathBounds

SkRect SkBaseShadowTessellator::fPathBounds
protected

Definition at line 120 of file SkShadowTessellator.cpp.

◆ fPathPolygon

SkTDArray<SkPoint> SkBaseShadowTessellator::fPathPolygon
protected

Definition at line 116 of file SkShadowTessellator.cpp.

◆ fPointBuffer

SkTDArray<SkPoint> SkBaseShadowTessellator::fPointBuffer
protected

Definition at line 110 of file SkShadowTessellator.cpp.

◆ fPositions

SkTDArray<SkPoint> SkBaseShadowTessellator::fPositions
protected

Definition at line 112 of file SkShadowTessellator.cpp.

◆ fPrevOutset

SkVector SkBaseShadowTessellator::fPrevOutset
protected

Definition at line 141 of file SkShadowTessellator.cpp.

◆ fPrevPoint

SkPoint SkBaseShadowTessellator::fPrevPoint
protected

Definition at line 142 of file SkShadowTessellator.cpp.

◆ fPrevUmbraIndex

int SkBaseShadowTessellator::fPrevUmbraIndex
protected

Definition at line 136 of file SkShadowTessellator.cpp.

◆ fPrevUmbraOutside

bool SkBaseShadowTessellator::fPrevUmbraOutside
protected

Definition at line 139 of file SkShadowTessellator.cpp.

◆ fSucceeded

bool SkBaseShadowTessellator::fSucceeded
protected

Definition at line 130 of file SkShadowTessellator.cpp.

◆ fTransparent

bool SkBaseShadowTessellator::fTransparent
protected

Definition at line 131 of file SkShadowTessellator.cpp.

◆ fValidUmbra

bool SkBaseShadowTessellator::fValidUmbra
protected

Definition at line 133 of file SkShadowTessellator.cpp.

◆ fZPlaneParams

SkPoint3 SkBaseShadowTessellator::fZPlaneParams
protected

Definition at line 107 of file SkShadowTessellator.cpp.

◆ kMinHeight

constexpr auto SkBaseShadowTessellator::kMinHeight = 0.1f
inlinestaticconstexprprotected

Definition at line 59 of file SkShadowTessellator.cpp.

◆ kPenumbraColor

constexpr auto SkBaseShadowTessellator::kPenumbraColor = SK_ColorTRANSPARENT
inlinestaticconstexprprotected

Definition at line 60 of file SkShadowTessellator.cpp.

◆ kUmbraColor

constexpr auto SkBaseShadowTessellator::kUmbraColor = SK_ColorBLACK
inlinestaticconstexprprotected

Definition at line 61 of file SkShadowTessellator.cpp.


The documentation for this class was generated from the following file: