26 fDeviceSpacePath.
reset();
31 fDeviceSpacePath.
reset();
33 fDeviceSpaceRRect = that.fDeviceSpaceRRect;
40 fDeviceSpacePath.
reset();
41 fShader = that.fShader;
45 fSaveCount = that.fSaveCount;
47 fDeviceSpaceType = that.fDeviceSpaceType;
49 fIsReplace = that.fIsReplace;
50 fFiniteBoundType = that.fFiniteBoundType;
51 fFiniteBound = that.fFiniteBound;
52 fIsIntersectionOfRects = that.fIsIntersectionOfRects;
59 if (
this == &element) {
62 if (fOp != element.fOp || fDeviceSpaceType != element.fDeviceSpaceType ||
63 fDoAA != element.fDoAA || fIsReplace != element.fIsReplace ||
64 fSaveCount != element.fSaveCount) {
67 switch (fDeviceSpaceType) {
68 case DeviceSpaceType::kShader:
69 return this->getShader() == element.
getShader();
70 case DeviceSpaceType::kPath:
72 case DeviceSpaceType::kRRect:
73 return fDeviceSpaceRRect == element.fDeviceSpaceRRect;
74 case DeviceSpaceType::kRect:
76 case DeviceSpaceType::kEmpty:
85 static const SkRect kEmpty = {0, 0, 0, 0};
87 switch (fDeviceSpaceType) {
88 case DeviceSpaceType::kRect:
89 case DeviceSpaceType::kRRect:
90 return fDeviceSpaceRRect.getBounds();
91 case DeviceSpaceType::kPath:
92 return fDeviceSpacePath->getBounds();
93 case DeviceSpaceType::kShader:
98 case DeviceSpaceType::kEmpty:
107 switch (fDeviceSpaceType) {
108 case DeviceSpaceType::kRect:
109 return this->getDeviceSpaceRect().contains(rect);
110 case DeviceSpaceType::kRRect:
111 return fDeviceSpaceRRect.contains(rect);
112 case DeviceSpaceType::kPath:
113 return fDeviceSpacePath->conservativelyContainsRect(rect);
114 case DeviceSpaceType::kEmpty:
115 case DeviceSpaceType::kShader:
124 switch (fDeviceSpaceType) {
125 case DeviceSpaceType::kRect:
126 return this->getDeviceSpaceRect().contains(rrect.
getBounds());
127 case DeviceSpaceType::kRRect:
129 return fDeviceSpaceRRect.contains(rrect.
getBounds()) || rrect == fDeviceSpaceRRect;
130 case DeviceSpaceType::kPath:
131 return fDeviceSpacePath->conservativelyContainsRect(rrect.
getBounds());
132 case DeviceSpaceType::kEmpty:
133 case DeviceSpaceType::kShader:
142 switch (fDeviceSpaceType) {
143 case DeviceSpaceType::kRect:
144 fDeviceSpacePath.init();
145 fDeviceSpacePath->addRect(this->getDeviceSpaceRect());
147 fDeviceSpaceType = DeviceSpaceType::kPath;
149 case DeviceSpaceType::kRRect:
150 fDeviceSpacePath.init();
151 fDeviceSpacePath->addRRect(fDeviceSpaceRRect);
153 fDeviceSpaceType = DeviceSpaceType::kPath;
155 case DeviceSpaceType::kPath:
156 fDeviceSpacePath->toggleInverseFillType();
158 case DeviceSpaceType::kShader:
161 case DeviceSpaceType::kEmpty:
167void SkClipStack::Element::initCommon(
int saveCount,
SkClipOp op,
bool doAA) {
168 fSaveCount = saveCount;
175 fFiniteBound.setEmpty();
176 fIsIntersectionOfRects =
false;
180void SkClipStack::Element::initRect(
int saveCount,
const SkRect& rect,
const SkMatrix& m,
182 if (m.rectStaysRect()) {
184 m.mapRect(&devRect, rect);
185 fDeviceSpaceRRect.setRect(devRect);
186 fDeviceSpaceType = DeviceSpaceType::kRect;
187 this->initCommon(saveCount, op, doAA);
192 path.setIsVolatile(
true);
193 this->initAsPath(saveCount, path, m, op, doAA);
196void SkClipStack::Element::initRRect(
int saveCount,
const SkRRect& rrect,
const SkMatrix& m,
201 fDeviceSpaceType = DeviceSpaceType::kRect;
203 fDeviceSpaceType = DeviceSpaceType::kRRect;
205 this->initCommon(saveCount, op, doAA);
209 path.addRRect(rrect);
210 path.setIsVolatile(
true);
211 this->initAsPath(saveCount, path, m, op, doAA);
214void SkClipStack::Element::initPath(
int saveCount,
const SkPath& path,
const SkMatrix& m,
216 if (!
path.isInverseFillType()) {
218 if (
path.isRect(&r)) {
219 this->initRect(saveCount, r, m, op, doAA);
223 if (
path.isOval(&ovalRect)) {
226 this->initRRect(saveCount, rrect, m, op, doAA);
230 this->initAsPath(saveCount, path, m, op, doAA);
233void SkClipStack::Element::initAsPath(
int saveCount,
const SkPath& path,
const SkMatrix& m,
235 path.transform(m, fDeviceSpacePath.init());
236 fDeviceSpacePath->setIsVolatile(
true);
237 fDeviceSpaceType = DeviceSpaceType::kPath;
238 this->initCommon(saveCount, op, doAA);
241void SkClipStack::Element::initShader(
int saveCount,
sk_sp<SkShader> shader) {
243 fDeviceSpaceType = DeviceSpaceType::kShader;
244 fShader = std::move(shader);
248void SkClipStack::Element::initReplaceRect(
int saveCount,
const SkRect& rect,
bool doAA) {
249 fDeviceSpaceRRect.setRect(rect);
250 fDeviceSpaceType = DeviceSpaceType::kRect;
256 switch (fDeviceSpaceType) {
257 case DeviceSpaceType::kEmpty:
260 case DeviceSpaceType::kRect:
262 path->addRect(this->getDeviceSpaceRect());
264 case DeviceSpaceType::kRRect:
266 path->addRRect(fDeviceSpaceRRect);
268 case DeviceSpaceType::kPath:
269 *path = *fDeviceSpacePath;
271 case DeviceSpaceType::kShader:
276 path->setIsVolatile(
true);
279void SkClipStack::Element::setEmpty() {
280 fDeviceSpaceType = DeviceSpaceType::kEmpty;
281 fFiniteBound.setEmpty();
283 fIsIntersectionOfRects =
false;
284 fDeviceSpaceRRect.setEmpty();
285 fDeviceSpacePath.reset();
291void SkClipStack::Element::checkEmpty()
const {
296 SkASSERT(fDeviceSpaceRRect.isEmpty());
297 SkASSERT(!fDeviceSpacePath.isValid());
301bool SkClipStack::Element::canBeIntersectedInPlace(
int saveCount,
SkClipOp op)
const {
302 if (DeviceSpaceType::kEmpty == fDeviceSpaceType &&
308 return fSaveCount == saveCount &&
313bool SkClipStack::Element::rectRectIntersectAllowed(
const SkRect& newR,
bool newAA)
const {
314 SkASSERT(DeviceSpaceType::kRect == fDeviceSpaceType);
316 if (fDoAA == newAA) {
321 if (!SkRect::Intersects(this->getDeviceSpaceRect(), newR)) {
326 if (this->getDeviceSpaceRect().
contains(newR)) {
341void SkClipStack::Element::combineBoundsDiff(FillCombo combination,
const SkRect& prevFinite) {
342 switch (combination) {
343 case kInvPrev_InvCur_FillCombo:
350 case kInvPrev_Cur_FillCombo:
354 fFiniteBound.join(prevFinite);
357 case kPrev_InvCur_FillCombo:
361 if (!fFiniteBound.intersect(prevFinite)) {
362 fFiniteBound.setEmpty();
367 case kPrev_Cur_FillCombo:
375 fFiniteBound = prevFinite;
378 SkDEBUGFAIL(
"SkClipStack::Element::combineBoundsDiff Invalid fill combination");
384void SkClipStack::Element::combineBoundsIntersection(
int combination,
const SkRect& prevFinite) {
386 switch (combination) {
387 case kInvPrev_InvCur_FillCombo:
390 fFiniteBound.join(prevFinite);
393 case kInvPrev_Cur_FillCombo:
397 case kPrev_InvCur_FillCombo:
400 fFiniteBound = prevFinite;
403 case kPrev_Cur_FillCombo:
404 if (!fFiniteBound.intersect(prevFinite)) {
409 SkDEBUGFAIL(
"SkClipStack::Element::combineBoundsIntersection Invalid fill combination");
414void SkClipStack::Element::updateBoundAndGenID(
const Element* prior) {
417 fGenID = GetNextGenID();
421 fIsIntersectionOfRects =
false;
422 switch (fDeviceSpaceType) {
423 case DeviceSpaceType::kRect:
424 fFiniteBound = this->getDeviceSpaceRect();
427 if (this->isReplaceOp() ||
430 prior->rectRectIntersectAllowed(this->getDeviceSpaceRect(), fDoAA))) {
431 fIsIntersectionOfRects =
true;
434 case DeviceSpaceType::kRRect:
435 fFiniteBound = fDeviceSpaceRRect.getBounds();
438 case DeviceSpaceType::kPath:
439 fFiniteBound = fDeviceSpacePath->getBounds();
441 if (fDeviceSpacePath->isInverseFillType()) {
447 case DeviceSpaceType::kShader:
455 case DeviceSpaceType::kEmpty:
456 SkDEBUGFAIL(
"We shouldn't get here with an empty element.");
465 if (
nullptr == prior) {
470 prevFinite = prior->fFiniteBound;
471 prevType = prior->fFiniteBoundType;
474 FillCombo combination = kPrev_Cur_FillCombo;
476 combination = (FillCombo) (combination | 0x01);
479 combination = (FillCombo) (combination | 0x02);
482 SkASSERT(kInvPrev_InvCur_FillCombo == combination ||
483 kInvPrev_Cur_FillCombo == combination ||
484 kPrev_InvCur_FillCombo == combination ||
485 kPrev_Cur_FillCombo == combination);
488 if (!this->isReplaceOp()) {
491 this->combineBoundsDiff(combination, prevFinite);
494 this->combineBoundsIntersection(combination, prevFinite);
535 fSaveCount =
b.fSaveCount;
550 if (fSaveCount !=
b.fSaveCount ||
551 fDeque.
count() !=
b.fDeque.count()) {
559 while (myElement !=
nullptr && bElement !=
nullptr) {
560 if (*myElement != *bElement) {
566 return myElement ==
nullptr && bElement ==
nullptr;
572 while (!fDeque.
empty()) {
587 restoreTo(fSaveCount);
590void SkClipStack::restoreTo(
int saveCount) {
591 while (!fDeque.
empty()) {
593 if (element->fSaveCount <= saveCount) {
617 bool* isIntersectionOfRects)
const {
618 SkASSERT(canvFiniteBound && boundType);
622 if (
nullptr == element) {
626 if (isIntersectionOfRects) {
627 *isIntersectionOfRects =
false;
632 *canvFiniteBound = element->fFiniteBound;
633 *boundType = element->fFiniteBoundType;
634 if (isIntersectionOfRects) {
635 *isIntersectionOfRects = element->fIsIntersectionOfRects;
639bool SkClipStack::internalQuickContains(
const SkRect& rect)
const {
641 const Element* element = iter.prev();
642 while (element !=
nullptr) {
647 if (element->isInverseFilled()) {
649 if (SkRect::Intersects(element->getBounds(), rect)) {
653 if (!element->contains(rect)) {
657 if (element->isReplaceOp()) {
660 element = iter.prev();
665bool SkClipStack::internalQuickContains(
const SkRRect& rrect)
const {
667 const Element* element = iter.prev();
668 while (element !=
nullptr) {
673 if (element->isInverseFilled()) {
675 if (SkRect::Intersects(element->getBounds(),
rrect.
getBounds())) {
679 if (!element->contains(rrect)) {
683 if (element->isReplaceOp()) {
686 element = iter.prev();
691void SkClipStack::pushElement(
const Element& element) {
697 if (element.isReplaceOp()) {
698 this->restoreTo(fSaveCount - 1);
700 }
else if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) {
701 switch (prior->fDeviceSpaceType) {
708 element.fShader, prior->fShader);
710 prior->updateBoundAndGenID(priorPrior);
716 if (prior->rectRectIntersectAllowed(element.getDeviceSpaceRect(),
719 if (!isectRect.
intersect(prior->getDeviceSpaceRect(),
720 element.getDeviceSpaceRect())) {
725 prior->fDeviceSpaceRRect.setRect(isectRect);
726 prior->fDoAA = element.isAA();
728 prior->updateBoundAndGenID(priorPrior);
735 if (!SkRect::Intersects(prior->getBounds(), element.getBounds())) {
744 newElement->updateBoundAndGenID(prior);
748 Element element(fSaveCount, rrect, matrix, op, doAA);
749 this->pushElement(element);
753 Element element(fSaveCount, rect, matrix, op, doAA);
754 this->pushElement(element);
759 Element element(fSaveCount, path, matrix, op, doAA);
760 this->pushElement(element);
764 Element element(fSaveCount, std::move(shader));
765 this->pushElement(element);
769 Element element(fSaveCount, rect, doAA);
770 this->pushElement(element);
791 this->
reset(stack, startLoc);
803 if (
nullptr == fStack) {
815 if (op == element->fOp) {
822 if (
nullptr ==
fIter.next()) {
832 if (
nullptr == element) {
851 bool* isIntersectionOfRects)
const {
861 this->
getBounds(&temp, &boundType, isIntersectionOfRects);
882 rrect->
setRect(back->fFiniteBound);
904 int cnt = fDeque.
count();
914 !prior->contains(backBounds)) {
917 if (prior->isReplaceOp()) {
929uint32_t SkClipStack::GetNextGenID() {
931 static const uint32_t kFirstUnreservedGenID = 3;
932 static std::atomic<uint32_t> nextID{kFirstUnreservedGenID};
936 id = nextID.fetch_add(1, std::memory_order_relaxed);
937 }
while (
id < kFirstUnreservedGenID);
942 if (fDeque.
empty()) {
956void SkClipStack::Element::dump()
const {
957 static const char* kTypeStrings[] = {
964 static_assert(0 ==
static_cast<int>(DeviceSpaceType::kEmpty),
"enum mismatch");
965 static_assert(1 ==
static_cast<int>(DeviceSpaceType::kRect),
"enum mismatch");
966 static_assert(2 ==
static_cast<int>(DeviceSpaceType::kRRect),
"enum mismatch");
967 static_assert(3 ==
static_cast<int>(DeviceSpaceType::kPath),
"enum mismatch");
968 static_assert(4 ==
static_cast<int>(DeviceSpaceType::kShader),
"enum mismatch");
969 static_assert(std::size(kTypeStrings) == kTypeCnt,
"enum mismatch");
971 const char* opName = this->isReplaceOp() ?
"replace" :
973 SkDebugf(
"Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[(
int)fDeviceSpaceType],
974 opName, (fDoAA ?
"yes" :
"no"), fSaveCount);
975 switch (fDeviceSpaceType) {
976 case DeviceSpaceType::kEmpty:
979 case DeviceSpaceType::kRect:
980 this->getDeviceSpaceRect().dump();
983 case DeviceSpaceType::kRRect:
984 this->getDeviceSpaceRRect().dump();
987 case DeviceSpaceType::kPath:
988 this->getDeviceSpacePath().dump(
nullptr,
false);
990 case DeviceSpaceType::kShader:
996void SkClipStack::dump()
const {
999 while ((e = iter.next())) {
std::unique_ptr< SkLatticeIter > fIter
static float next(float f)
#define SkAssertResult(cond)
#define SkDEBUGFAIL(message)
static const int kDefaultElementAllocCnt
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool contains(const SkRect &r, SkPoint p)
SkShaderBase * as_SB(SkShader *shader)
const SkShader * getShader() const
@ kPath
This element does not have geometry, but applies a shader to the clip.
@ kEmpty
This element makes the clip empty (regardless of previous elements).
@ kRect
This element combines a device space round-rect with the current clip.
@ kRRect
This element combines a device space path with the current clip.
uint32_t getGenID() const
const SkRect & getDeviceSpaceRect() const
Call if getDeviceSpaceType() is kShader to get a reference to the clip shader.
bool isAA() const
Inverts the fill of the clip shape. Note that a kEmpty element remains kEmpty.
void invertShapeFillType()
DeviceSpaceType getDeviceSpaceType() const
Call to get the save count associated with this clip element.
const SkPath & getDeviceSpacePath() const
Call if getDeviceSpaceType() is kRRect to get the round-rect.
bool operator==(const Element &element) const
const SkRRect & asDeviceSpaceRRect() const
const SkRect & getBounds() const
bool contains(const SkRect &rect) const
bool isReplaceOp() const
Call to get the element as a path, regardless of its type.
void asDeviceSpacePath(SkPath *path) const
Call if getType() is not kPath to get the element as a round rect.
void reset(const SkClipStack &stack, IterStart startLoc)
const Element * skipToTopmost(SkClipOp op)
void clipRect(const SkRect &, const SkMatrix &matrix, SkClipOp, bool doAA)
void clipShader(sk_sp< SkShader >)
bool isRRect(const SkRect &bounds, SkRRect *rrect, bool *aa) const
static const uint32_t kEmptyGenID
void clipRRect(const SkRRect &, const SkMatrix &matrix, SkClipOp, bool doAA)
void getBounds(SkRect *canvFiniteBound, BoundsType *boundType, bool *isIntersectionOfRects=nullptr) const
bool isEmpty(const SkIRect &deviceBounds) const
void getConservativeBounds(int offsetX, int offsetY, int maxWidth, int maxHeight, SkRect *devBounds, bool *isIntersectionOfRects=nullptr) const
bool operator==(const SkClipStack &b) const
SkClipStack & operator=(const SkClipStack &b)
uint32_t getTopmostGenID() const
static const uint32_t kInvalidGenID
static const uint32_t kWideOpenGenID
void clipPath(const SkPath &, const SkMatrix &matrix, SkClipOp, bool doAA)
SkRect bounds(const SkIRect &deviceBounds) const
void replaceClip(const SkRect &devRect, bool doAA)
const void * back() const
const SkRect & rect() const
@ kEmpty_Type
zero width or height
@ kRect_Type
non-zero width and height, and zeroed radii
bool transform(const SkMatrix &matrix, SkRRect *dst) const
void setOval(const SkRect &oval)
const SkRect & getBounds() const
void setRect(const SkRect &rect)
static SkRect MakeLargeS32()
sk_sp< SkShader > makeInvertAlpha() const
void reset(T *ptr=nullptr)
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
static SkRect Make(const SkISize &size)
static constexpr SkRect MakeEmpty()
bool intersect(const SkRect &r)
void offset(float dx, float dy)
void setLTRB(float left, float top, float right, float bottom)