Home | History | Annotate | Download | only in core
      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 
      8 #include "SkRasterClip.h"
      9 
     10 
     11 SkRasterClip::SkRasterClip() {
     12     fIsBW = true;
     13 }
     14 
     15 SkRasterClip::SkRasterClip(const SkRasterClip& src) {
     16     AUTO_RASTERCLIP_VALIDATE(src);
     17 
     18     fIsBW = src.fIsBW;
     19     if (fIsBW) {
     20         fBW = src.fBW;
     21     } else {
     22         fAA = src.fAA;
     23     }
     24 }
     25 
     26 SkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) {
     27     fIsBW = true;
     28 }
     29 
     30 SkRasterClip::~SkRasterClip() {
     31     AUTO_RASTERCLIP_VALIDATE(*this);
     32 }
     33 
     34 bool SkRasterClip::isEmpty() const {
     35     return fIsBW ? fBW.isEmpty() : fAA.isEmpty();
     36 }
     37 
     38 bool SkRasterClip::isRect() const {
     39     return fIsBW ? fBW.isRect() : false;
     40 }
     41 
     42 bool SkRasterClip::isComplex() const {
     43     return fIsBW ? fBW.isComplex() : !fAA.isEmpty();
     44 }
     45 
     46 const SkIRect& SkRasterClip::getBounds() const {
     47     return fIsBW ? fBW.getBounds() : fAA.getBounds();
     48 }
     49 
     50 bool SkRasterClip::setEmpty() {
     51     AUTO_RASTERCLIP_VALIDATE(*this);
     52 
     53     fIsBW = true;
     54     fBW.setEmpty();
     55     fAA.setEmpty();
     56     return false;
     57 }
     58 
     59 bool SkRasterClip::setRect(const SkIRect& rect) {
     60     AUTO_RASTERCLIP_VALIDATE(*this);
     61 
     62     fIsBW = true;
     63     fAA.setEmpty();
     64     return fBW.setRect(rect);
     65 }
     66 
     67 bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) {
     68     AUTO_RASTERCLIP_VALIDATE(*this);
     69 
     70     if (this->isBW() && !doAA) {
     71         return fBW.setPath(path, clip);
     72     } else {
     73         // TODO: since we are going to over-write fAA completely (aren't we?)
     74         // we should just clear our BW data (if any) and set fIsAA=true
     75         if (this->isBW()) {
     76             this->convertToAA();
     77         }
     78         return fAA.setPath(path, &clip, doAA);
     79     }
     80 }
     81 
     82 bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) {
     83     SkRegion tmp;
     84     tmp.setRect(clip);
     85     return this->setPath(path, tmp, doAA);
     86 }
     87 
     88 bool SkRasterClip::setPath(const SkPath& path, const SkRasterClip& clip,
     89                            bool doAA) {
     90     if (clip.isBW()) {
     91         return this->setPath(path, clip.bwRgn(), doAA);
     92     } else {
     93         SkRegion tmp;
     94         tmp.setRect(clip.getBounds());
     95         if (!this->setPath(path, clip, doAA)) {
     96             return false;
     97         }
     98         return this->op(clip, SkRegion::kIntersect_Op);
     99     }
    100 }
    101 
    102 bool SkRasterClip::op(const SkIRect& rect, SkRegion::Op op) {
    103     AUTO_RASTERCLIP_VALIDATE(*this);
    104 
    105     return fIsBW ? fBW.op(rect, op) : fAA.op(rect, op);
    106 }
    107 
    108 bool SkRasterClip::op(const SkRegion& rgn, SkRegion::Op op) {
    109     AUTO_RASTERCLIP_VALIDATE(*this);
    110 
    111     if (fIsBW) {
    112         return fBW.op(rgn, op);
    113     } else {
    114         SkAAClip tmp;
    115         tmp.setRegion(rgn);
    116         return fAA.op(tmp, op);
    117     }
    118 }
    119 
    120 bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) {
    121     AUTO_RASTERCLIP_VALIDATE(*this);
    122     clip.validate();
    123 
    124     if (this->isBW() && clip.isBW()) {
    125         return fBW.op(clip.fBW, op);
    126     } else {
    127         SkAAClip tmp;
    128         const SkAAClip* other;
    129 
    130         if (this->isBW()) {
    131             this->convertToAA();
    132         }
    133         if (clip.isBW()) {
    134             tmp.setRegion(clip.bwRgn());
    135             other = &tmp;
    136         } else {
    137             other = &clip.aaRgn();
    138         }
    139         return fAA.op(*other, op);
    140     }
    141 }
    142 
    143 // return true if x is nearly integral (within 1/16) since that is the highest
    144 // precision our aa code can have.
    145 static bool is_integral(SkScalar x) {
    146     int ix = SkScalarRoundToInt(x);
    147     SkScalar sx = SkIntToScalar(ix);
    148     return SkScalarAbs(sx - x) < (SK_Scalar1 / 16);
    149 }
    150 
    151 bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) {
    152     AUTO_RASTERCLIP_VALIDATE(*this);
    153 
    154     if (doAA) {
    155         // check that the rect really needs aa
    156         if (is_integral(r.fLeft) && is_integral(r.fTop) &&
    157             is_integral(r.fRight) && is_integral(r.fBottom)) {
    158             doAA = false;
    159         }
    160     }
    161 
    162     if (fIsBW && !doAA) {
    163         SkIRect ir;
    164         r.round(&ir);
    165         return fBW.op(ir, op);
    166     } else {
    167         if (fIsBW) {
    168             this->convertToAA();
    169         }
    170         return fAA.op(r, op, doAA);
    171     }
    172 }
    173 
    174 void SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const {
    175     if (NULL == dst) {
    176         return;
    177     }
    178 
    179     AUTO_RASTERCLIP_VALIDATE(*this);
    180 
    181     if (this->isEmpty()) {
    182         dst->setEmpty();
    183         return;
    184     }
    185     if (0 == (dx | dy)) {
    186         *dst = *this;
    187         return;
    188     }
    189 
    190     dst->fIsBW = fIsBW;
    191     if (fIsBW) {
    192         fBW.translate(dx, dy, &dst->fBW);
    193         dst->fAA.setEmpty();
    194     } else {
    195         fAA.translate(dx, dy, &dst->fAA);
    196         dst->fBW.setEmpty();
    197     }
    198 }
    199 
    200 bool SkRasterClip::quickContains(const SkIRect& ir) const {
    201     return fIsBW ? fBW.quickContains(ir) : fAA.quickContains(ir);
    202 }
    203 
    204 ///////////////////////////////////////////////////////////////////////////////
    205 
    206 const SkRegion& SkRasterClip::forceGetBW() {
    207     AUTO_RASTERCLIP_VALIDATE(*this);
    208 
    209     if (!fIsBW) {
    210         fBW.setRect(fAA.getBounds());
    211     }
    212     return fBW;
    213 }
    214 
    215 void SkRasterClip::convertToAA() {
    216     AUTO_RASTERCLIP_VALIDATE(*this);
    217 
    218     SkASSERT(fIsBW);
    219     fAA.setRegion(fBW);
    220     fIsBW = false;
    221 }
    222 
    223 #ifdef SK_DEBUG
    224 void SkRasterClip::validate() const {
    225     // can't ever assert that fBW is empty, since we may have called forceGetBW
    226     if (fIsBW) {
    227         SkASSERT(fAA.isEmpty());
    228     }
    229 
    230     fBW.validate();
    231     fAA.validate();
    232 }
    233 #endif
    234 
    235 ///////////////////////////////////////////////////////////////////////////////
    236 
    237 SkAAClipBlitterWrapper::SkAAClipBlitterWrapper() {
    238     SkDEBUGCODE(fClipRgn = NULL;)
    239     SkDEBUGCODE(fBlitter = NULL;)
    240 }
    241 
    242 SkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkRasterClip& clip,
    243                                                SkBlitter* blitter) {
    244     this->init(clip, blitter);
    245 }
    246 
    247 SkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkAAClip* aaclip,
    248                                                SkBlitter* blitter) {
    249     SkASSERT(blitter);
    250     SkASSERT(aaclip);
    251     fBWRgn.setRect(aaclip->getBounds());
    252     fAABlitter.init(blitter, aaclip);
    253     // now our return values
    254     fClipRgn = &fBWRgn;
    255     fBlitter = &fAABlitter;
    256 }
    257 
    258 void SkAAClipBlitterWrapper::init(const SkRasterClip& clip, SkBlitter* blitter) {
    259     SkASSERT(blitter);
    260     if (clip.isBW()) {
    261         fClipRgn = &clip.bwRgn();
    262         fBlitter = blitter;
    263     } else {
    264         const SkAAClip& aaclip = clip.aaRgn();
    265         fBWRgn.setRect(aaclip.getBounds());
    266         fAABlitter.init(blitter, &aaclip);
    267         // now our return values
    268         fClipRgn = &fBWRgn;
    269         fBlitter = &fAABlitter;
    270     }
    271 }
    272 
    273