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();
73 return fDeviceSpaceRRect == element.fDeviceSpaceRRect;
87 switch (fDeviceSpaceType) {
90 return fDeviceSpaceRRect.getBounds();
92 return fDeviceSpacePath->getBounds();
93 case DeviceSpaceType::kShader:
107 switch (fDeviceSpaceType) {
109 return this->getDeviceSpaceRect().contains(
rect);
111 return fDeviceSpaceRRect.contains(
rect);
113 return fDeviceSpacePath->conservativelyContainsRect(
rect);
115 case DeviceSpaceType::kShader:
124 switch (fDeviceSpaceType) {
131 return fDeviceSpacePath->conservativelyContainsRect(
rrect.
getBounds());
133 case DeviceSpaceType::kShader:
142 switch (fDeviceSpaceType) {
144 fDeviceSpacePath.init();
145 fDeviceSpacePath->addRect(this->getDeviceSpaceRect());
150 fDeviceSpacePath.init();
151 fDeviceSpacePath->addRRect(fDeviceSpaceRRect);
156 fDeviceSpacePath->toggleInverseFillType();
158 case DeviceSpaceType::kShader:
167void SkClipStack::Element::initCommon(
int saveCount,
SkClipOp op,
bool doAA) {
168 fSaveCount = saveCount;
175 fFiniteBound.setEmpty();
176 fIsIntersectionOfRects =
false;
182 if (
m.rectStaysRect()) {
184 m.mapRect(&devRect,
rect);
185 fDeviceSpaceRRect.setRect(devRect);
187 this->initCommon(saveCount, op, doAA);
192 path.setIsVolatile(
true);
193 this->initAsPath(saveCount,
path,
m, op, doAA);
205 this->initCommon(saveCount, op, doAA);
210 path.setIsVolatile(
true);
211 this->initAsPath(saveCount,
path,
m, op, doAA);
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);
235 path.transform(
m, fDeviceSpacePath.init());
236 fDeviceSpacePath->setIsVolatile(
true);
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);
256 switch (fDeviceSpaceType) {
262 path->addRect(this->getDeviceSpaceRect());
266 path->addRRect(fDeviceSpaceRRect);
269 *
path = *fDeviceSpacePath;
271 case DeviceSpaceType::kShader:
276 path->setIsVolatile(
true);
279void SkClipStack::Element::setEmpty() {
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 {
308 return fSaveCount == saveCount &&
313bool SkClipStack::Element::rectRectIntersectAllowed(
const SkRect& newR,
bool newAA)
const {
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) {
424 fFiniteBound = this->getDeviceSpaceRect();
427 if (this->isReplaceOp() ||
430 prior->rectRectIntersectAllowed(this->getDeviceSpaceRect(), fDoAA))) {
431 fIsIntersectionOfRects =
true;
435 fFiniteBound = fDeviceSpaceRRect.getBounds();
439 fFiniteBound = fDeviceSpacePath->getBounds();
441 if (fDeviceSpacePath->isInverseFillType()) {
447 case DeviceSpaceType::kShader:
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) {
706 if (
Element::DeviceSpaceType::kShader == element.getDeviceSpaceType()) {
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);
749 this->pushElement(element);
754 this->pushElement(element);
760 this->pushElement(element);
764 Element element(fSaveCount, std::move(shader));
765 this->pushElement(element);
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);
881 if (back->fIsIntersectionOfRects && back->fFiniteBoundType == BoundsType::kNormal_BoundsType) {
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()) {
957 static const char* kTypeStrings[] = {
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) {
980 this->getDeviceSpaceRect().dump();
984 this->getDeviceSpaceRRect().dump();
988 this->getDeviceSpacePath().dump(
nullptr,
false);
990 case DeviceSpaceType::kShader:
999 while ((
e = iter.next())) {
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
std::unique_ptr< SkLatticeIter > fIter
static float next(float f)
#define SkDEBUGFAIL(message)
static const int kDefaultElementAllocCnt
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
SkShaderBase * as_SB(SkShader *shader)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
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)
unsigned useCenter Optional< SkMatrix > matrix
sk_sp< SkBlender > blender SkRect rect
SK_API sk_sp< SkShader > Blend(SkBlendMode mode, sk_sp< SkShader > dst, sk_sp< SkShader > src)
constexpr std::array< std::array< float, 2 >, 2 > kRect
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
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
constexpr bool contains(std::string_view str, std::string_view needle)
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)