LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkRasterClipStack.h (source / functions) Hit Total Coverage
Test: output.info Lines: 84 93 90.3 %
Date: 2017-07-14 16:53:18 Functions: 24 25 96.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13