SkRasterClip.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * Copyright 2010 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #ifndef SkRasterClip_DEFINED
  8. #define SkRasterClip_DEFINED
  9. #include "include/core/SkRegion.h"
  10. #include "include/private/SkMacros.h"
  11. #include "src/core/SkAAClip.h"
  12. class SkRRect;
  13. class SkConservativeClip {
  14. SkIRect fBounds;
  15. const SkIRect* fClipRestrictionRect;
  16. inline void applyClipRestriction(SkRegion::Op op, SkIRect* bounds) {
  17. if (op >= SkRegion::kUnion_Op && fClipRestrictionRect
  18. && !fClipRestrictionRect->isEmpty()) {
  19. if (!bounds->intersect(*fClipRestrictionRect)) {
  20. bounds->setEmpty();
  21. }
  22. }
  23. }
  24. public:
  25. SkConservativeClip() : fBounds(SkIRect::MakeEmpty()), fClipRestrictionRect(nullptr) {}
  26. bool isEmpty() const { return fBounds.isEmpty(); }
  27. bool isRect() const { return true; }
  28. const SkIRect& getBounds() const { return fBounds; }
  29. void setEmpty() { fBounds.setEmpty(); }
  30. void setRect(const SkIRect& r) { fBounds = r; }
  31. void setDeviceClipRestriction(const SkIRect* rect) {
  32. fClipRestrictionRect = rect;
  33. }
  34. void opRect(const SkRect&, const SkMatrix&, const SkIRect& limit, SkRegion::Op, bool isAA);
  35. void opRRect(const SkRRect&, const SkMatrix&, const SkIRect& limit, SkRegion::Op, bool isAA);
  36. void opPath(const SkPath&, const SkMatrix&, const SkIRect& limit, SkRegion::Op, bool isAA);
  37. void opRegion(const SkRegion&, SkRegion::Op);
  38. void opIRect(const SkIRect&, SkRegion::Op);
  39. };
  40. /**
  41. * Wraps a SkRegion and SkAAClip, so we have a single object that can represent either our
  42. * BW or antialiased clips.
  43. *
  44. * This class is optimized for the raster backend of canvas, but can be expense to keep up2date,
  45. * so it supports a runtime option (force-conservative-rects) to turn it into a super-fast
  46. * rect-only tracker. The gpu backend uses this since it does not need the result (it uses
  47. * SkClipStack instead).
  48. */
  49. class SkRasterClip {
  50. public:
  51. SkRasterClip();
  52. SkRasterClip(const SkIRect&);
  53. SkRasterClip(const SkRegion&);
  54. SkRasterClip(const SkRasterClip&);
  55. ~SkRasterClip();
  56. // Only compares the current state. Does not compare isForceConservativeRects(), so that field
  57. // could be different but this could still return true.
  58. bool operator==(const SkRasterClip&) const;
  59. bool operator!=(const SkRasterClip& other) const {
  60. return !(*this == other);
  61. }
  62. bool isBW() const { return fIsBW; }
  63. bool isAA() const { return !fIsBW; }
  64. const SkRegion& bwRgn() const { SkASSERT(fIsBW); return fBW; }
  65. const SkAAClip& aaRgn() const { SkASSERT(!fIsBW); return fAA; }
  66. bool isEmpty() const {
  67. SkASSERT(this->computeIsEmpty() == fIsEmpty);
  68. return fIsEmpty;
  69. }
  70. bool isRect() const {
  71. SkASSERT(this->computeIsRect() == fIsRect);
  72. return fIsRect;
  73. }
  74. bool isComplex() const;
  75. const SkIRect& getBounds() const;
  76. bool setEmpty();
  77. bool setRect(const SkIRect&);
  78. bool op(const SkIRect&, SkRegion::Op);
  79. bool op(const SkRegion&, SkRegion::Op);
  80. bool op(const SkRect&, const SkMatrix& matrix, const SkIRect&, SkRegion::Op, bool doAA);
  81. bool op(const SkRRect&, const SkMatrix& matrix, const SkIRect&, SkRegion::Op, bool doAA);
  82. bool op(const SkPath&, const SkMatrix& matrix, const SkIRect&, SkRegion::Op, bool doAA);
  83. void translate(int dx, int dy, SkRasterClip* dst) const;
  84. void translate(int dx, int dy) {
  85. this->translate(dx, dy, this);
  86. }
  87. bool quickContains(const SkIRect& rect) const;
  88. bool quickContains(int left, int top, int right, int bottom) const {
  89. return quickContains(SkIRect::MakeLTRB(left, top, right, bottom));
  90. }
  91. /**
  92. * Return true if this region is empty, or if the specified rectangle does
  93. * not intersect the region. Returning false is not a guarantee that they
  94. * intersect, but returning true is a guarantee that they do not.
  95. */
  96. bool quickReject(const SkIRect& rect) const {
  97. return !SkIRect::Intersects(this->getBounds(), rect);
  98. }
  99. // hack for SkCanvas::getTotalClip
  100. const SkRegion& forceGetBW();
  101. #ifdef SK_DEBUG
  102. void validate() const;
  103. #else
  104. void validate() const {}
  105. #endif
  106. void setDeviceClipRestriction(const SkIRect* rect) {
  107. fClipRestrictionRect = rect;
  108. }
  109. private:
  110. SkRegion fBW;
  111. SkAAClip fAA;
  112. bool fIsBW;
  113. // these 2 are caches based on querying the right obj based on fIsBW
  114. bool fIsEmpty;
  115. bool fIsRect;
  116. const SkIRect* fClipRestrictionRect = nullptr;
  117. bool computeIsEmpty() const {
  118. return fIsBW ? fBW.isEmpty() : fAA.isEmpty();
  119. }
  120. bool computeIsRect() const {
  121. return fIsBW ? fBW.isRect() : fAA.isRect();
  122. }
  123. bool updateCacheAndReturnNonEmpty(bool detectAARect = true) {
  124. fIsEmpty = this->computeIsEmpty();
  125. // detect that our computed AA is really just a (hard-edged) rect
  126. if (detectAARect && !fIsEmpty && !fIsBW && fAA.isRect()) {
  127. fBW.setRect(fAA.getBounds());
  128. fAA.setEmpty(); // don't need this guy anymore
  129. fIsBW = true;
  130. }
  131. fIsRect = this->computeIsRect();
  132. return !fIsEmpty;
  133. }
  134. void convertToAA();
  135. bool setPath(const SkPath& path, const SkRegion& clip, bool doAA);
  136. bool setPath(const SkPath& path, const SkIRect& clip, bool doAA);
  137. bool op(const SkRasterClip&, SkRegion::Op);
  138. bool setConservativeRect(const SkRect& r, const SkIRect& clipR, bool isInverse);
  139. inline void applyClipRestriction(SkRegion::Op op, SkIRect* bounds) {
  140. if (op >= SkRegion::kUnion_Op && fClipRestrictionRect
  141. && !fClipRestrictionRect->isEmpty()) {
  142. if (!bounds->intersect(*fClipRestrictionRect)) {
  143. bounds->setEmpty();
  144. }
  145. }
  146. }
  147. inline void applyClipRestriction(SkRegion::Op op, SkRect* bounds) {
  148. if (op >= SkRegion::kUnion_Op && fClipRestrictionRect
  149. && !fClipRestrictionRect->isEmpty()) {
  150. if (!bounds->intersect(SkRect::Make(*fClipRestrictionRect))) {
  151. bounds->setEmpty();
  152. }
  153. }
  154. }
  155. };
  156. class SkAutoRasterClipValidate : SkNoncopyable {
  157. public:
  158. SkAutoRasterClipValidate(const SkRasterClip& rc) : fRC(rc) {
  159. fRC.validate();
  160. }
  161. ~SkAutoRasterClipValidate() {
  162. fRC.validate();
  163. }
  164. private:
  165. const SkRasterClip& fRC;
  166. };
  167. #define SkAutoRasterClipValidate(...) SK_REQUIRE_LOCAL_VAR(SkAutoRasterClipValidate)
  168. #ifdef SK_DEBUG
  169. #define AUTO_RASTERCLIP_VALIDATE(rc) SkAutoRasterClipValidate arcv(rc)
  170. #else
  171. #define AUTO_RASTERCLIP_VALIDATE(rc)
  172. #endif
  173. ///////////////////////////////////////////////////////////////////////////////
  174. /**
  175. * Encapsulates the logic of deciding if we need to change/wrap the blitter
  176. * for aaclipping. If so, getRgn and getBlitter return modified values. If
  177. * not, they return the raw blitter and (bw) clip region.
  178. *
  179. * We need to keep the constructor/destructor cost as small as possible, so we
  180. * can freely put this guy on the stack, and not pay too much for the case when
  181. * we're really BW anyways.
  182. */
  183. class SkAAClipBlitterWrapper {
  184. public:
  185. SkAAClipBlitterWrapper();
  186. SkAAClipBlitterWrapper(const SkRasterClip&, SkBlitter*);
  187. SkAAClipBlitterWrapper(const SkAAClip*, SkBlitter*);
  188. void init(const SkRasterClip&, SkBlitter*);
  189. const SkIRect& getBounds() const {
  190. SkASSERT(fClipRgn);
  191. return fClipRgn->getBounds();
  192. }
  193. const SkRegion& getRgn() const {
  194. SkASSERT(fClipRgn);
  195. return *fClipRgn;
  196. }
  197. SkBlitter* getBlitter() {
  198. SkASSERT(fBlitter);
  199. return fBlitter;
  200. }
  201. private:
  202. SkRegion fBWRgn;
  203. SkAAClipBlitter fAABlitter;
  204. // what we return
  205. const SkRegion* fClipRgn;
  206. SkBlitter* fBlitter;
  207. };
  208. #endif