1c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed/* 2c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed * Copyright 2017 Google Inc. 3c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed * 4c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed * Use of this source code is governed by a BSD-style license that can be 5c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed * found in the LICENSE file. 6c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed */ 7c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 8c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifndef SkRasterClipStack_DEFINED 9c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#define SkRasterClipStack_DEFINED 10c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 1120de615e3d02ff52c9a3c319ce35bcaace97be25Hal Canary#include "SkClipOp.h" 12c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#include "SkDeque.h" 13c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#include "SkRasterClip.h" 14c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 15c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reedtemplate <typename T> class SkTStack { 16c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reedpublic: 17c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkTStack(void* storage, size_t size) : fDeque(sizeof(T), storage, size), fTop(nullptr) {} 18c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed ~SkTStack() { 19c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed while (!fDeque.empty()) { 20c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed ((T*)fDeque.back())->~T(); 21c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fDeque.pop_back(); 22c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 23c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 24c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 25c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed bool empty() const { return fDeque.empty(); } 26c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 27c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed int count() const { return fDeque.count(); } 28c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 29c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed const T& top() const { 30c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(fTop); 31c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed return *fTop; 32c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 33c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 34c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed T& top() { 35c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(fTop); 36c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed return *fTop; 37c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 38c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 39c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed T* push_raw() { return (T*)fDeque.push_back(); } 40c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed T& push() { 41c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fTop = this->push_raw(); 42c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed new (fTop) T(); 43c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed return *fTop; 44c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 45c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed T& push(const T& src) { 46c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fTop = this->push_raw(); 47c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed new (fTop) T(src); 48c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed return *fTop; 49c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 50c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 51c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void pop() { 52c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fTop->~T(); 53c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fDeque.pop_back(); 54c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fTop = fDeque.empty() ? nullptr : (T*)fDeque.back(); 55c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 56c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 57c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reedprivate: 58c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkDeque fDeque; 59c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed T* fTop; 60c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed}; 61c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 62c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reedclass SkRasterClipStack : SkNoncopyable { 63c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed int fCounter = 0; 64c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reedpublic: 65c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkRasterClipStack(int width, int height) 66c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed : fStack(fStorage, sizeof(fStorage)) 67c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed , fRootBounds(SkIRect::MakeWH(width, height)) 68c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed { 69c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed Rec& rec = fStack.push(); 70c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed rec.fRC.setRect(fRootBounds); 71c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed rec.fDeferredCount = 0; 72c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(fStack.count() == 1); 73c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 74c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 75c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void setNewSize(int w, int h) { 7627d07f0acb85eea4062075dfbe9148ce12d92c66Mike Reed fRootBounds.setXYWH(0, 0, w, h); 77a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed 78a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed SkASSERT(fStack.count() == 1); 79a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed Rec& rec = fStack.top(); 80a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed SkASSERT(rec.fDeferredCount == 0); 81a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed rec.fRC.setRect(fRootBounds); 82c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 83c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 84c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed const SkRasterClip& rc() const { return fStack.top().fRC; } 85c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 86c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void save() { 87c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fCounter += 1; 88c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(fStack.top().fDeferredCount >= 0); 89c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fStack.top().fDeferredCount += 1; 90c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 91c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 92c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void restore() { 93c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fCounter -= 1; SkASSERT(fCounter >= 0); 94c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed if (--fStack.top().fDeferredCount < 0) { 95c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(fStack.top().fDeferredCount == -1); 96c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(fStack.count() > 1); 97c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fStack.pop(); 98c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 99c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 100c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 101c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void clipRect(const SkMatrix& ctm, const SkRect& rect, SkClipOp op, bool aa) { 102c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->writable_rc().op(rect, ctm, fRootBounds, (SkRegion::Op)op, aa); 103c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->trimIfExpanding(op); 104c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->validate(); 105c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 106c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 107c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void clipRRect(const SkMatrix& ctm, const SkRRect& rrect, SkClipOp op, bool aa) { 108c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->writable_rc().op(rrect, ctm, fRootBounds, (SkRegion::Op)op, aa); 109c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->trimIfExpanding(op); 110c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->validate(); 111c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 112c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 113c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void clipPath(const SkMatrix& ctm, const SkPath& path, SkClipOp op, bool aa) { 114c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->writable_rc().op(path, ctm, fRootBounds, (SkRegion::Op)op, aa); 115c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->trimIfExpanding(op); 116c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->validate(); 117c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 118c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 119c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void clipRegion(const SkRegion& rgn, SkClipOp op) { 120c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->writable_rc().op(rgn, (SkRegion::Op)op); 121c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->trimIfExpanding(op); 122c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->validate(); 123c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 124c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 125c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void setDeviceClipRestriction(SkIRect* mutableClipRestriction) { 126c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed this->writable_rc().setDeviceClipRestriction(mutableClipRestriction); 127c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 128c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 129c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void validate() const { 130c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_DEBUG 131c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed const SkRasterClip& clip = this->rc(); 132c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed if (fRootBounds.isEmpty()) { 133c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(clip.isEmpty()); 134c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } else if (!clip.isEmpty()) { 135c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(fRootBounds.contains(clip.getBounds())); 136c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 137c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif 138c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 139c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 140c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reedprivate: 141c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed struct Rec { 142c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkRasterClip fRC; 143c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed int fDeferredCount; // 0 for a "normal" entry 144c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed }; 145c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 146c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed enum { 147c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed ELEM_COUNT = 16, 148c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed PTR_COUNT = ELEM_COUNT * sizeof(Rec) / sizeof(void*) 149c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed }; 150c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void* fStorage[PTR_COUNT]; 151c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkTStack<Rec> fStack; 152c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkIRect fRootBounds; 153c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 154c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkRasterClip& writable_rc() { 155c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(fStack.top().fDeferredCount >= 0); 156c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed if (fStack.top().fDeferredCount > 0) { 157c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fStack.top().fDeferredCount -= 1; 158c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fStack.push(fStack.top()); 159c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fStack.top().fDeferredCount = 0; 160c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 161c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed return fStack.top().fRC; 162c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 163c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 164c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed void trimIfExpanding(SkClipOp op) { 165c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed if ((int)op > (int)SkClipOp::kIntersect) { 166c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed Rec& rec = fStack.top(); 167c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(rec.fDeferredCount == 0); 168c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed rec.fRC.op(fRootBounds, SkRegion::kIntersect_Op); 169c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 170c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 171c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed}; 172c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 173c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif 174