Home | History | Annotate | Download | only in src
      1 /*
      2     Copyright 2010 Google Inc.
      3 
      4     Licensed under the Apache License, Version 2.0 (the "License");
      5     you may not use this file except in compliance with the License.
      6     You may obtain a copy of the License at
      7 
      8          http://www.apache.org/licenses/LICENSE-2.0
      9 
     10     Unless required by applicable law or agreed to in writing, software
     11     distributed under the License is distributed on an "AS IS" BASIS,
     12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13     See the License for the specific language governing permissions and
     14     limitations under the License.
     15  */
     16 
     17 
     18 #include "GrClip.h"
     19 
     20 GrClip::GrClip()
     21     : fList(&fListStorage) {
     22     fConservativeBounds.setEmpty();
     23     fConservativeBoundsValid = true;
     24 }
     25 
     26 GrClip::GrClip(const GrClip& src)
     27     : fList(&fListStorage) {
     28     *this = src;
     29 }
     30 
     31 GrClip::GrClip(const GrIRect& rect)
     32     : fList(&fListStorage) {
     33     this->setFromIRect(rect);
     34 }
     35 
     36 GrClip::GrClip(const GrRect& rect)
     37     : fList(&fListStorage) {
     38     this->setFromRect(rect);
     39 }
     40 
     41 GrClip::GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty,
     42                const GrRect* bounds)
     43     : fList(&fListStorage) {
     44     this->setFromIterator(iter, tx, ty, bounds);
     45 }
     46 
     47 GrClip::~GrClip() {}
     48 
     49 GrClip& GrClip::operator=(const GrClip& src) {
     50     fList = src.fList;
     51     fConservativeBounds = src.fConservativeBounds;
     52     fConservativeBoundsValid = src.fConservativeBoundsValid;
     53     return *this;
     54 }
     55 
     56 void GrClip::setEmpty() {
     57     fList.reset();
     58     fConservativeBounds.setEmpty();
     59     fConservativeBoundsValid = true;
     60 }
     61 
     62 void GrClip::setFromRect(const GrRect& r) {
     63     fList.reset();
     64     if (r.isEmpty()) {
     65         // use a canonical empty rect for == testing.
     66         setEmpty();
     67     } else {
     68         fList.push_back();
     69         fList.back().fRect = r;
     70         fList.back().fType = kRect_ClipType;
     71         fConservativeBounds = r;
     72         fConservativeBoundsValid = true;
     73     }
     74 }
     75 
     76 void GrClip::setFromIRect(const GrIRect& r) {
     77     fList.reset();
     78     if (r.isEmpty()) {
     79         // use a canonical empty rect for == testing.
     80         setEmpty();
     81     } else {
     82         fList.push_back();
     83         fList.back().fRect.set(r);
     84         fList.back().fType = kRect_ClipType;
     85         fConservativeBounds.set(r);
     86         fConservativeBoundsValid = true;
     87     }
     88 }
     89 
     90 static void intersectWith(SkRect* dst, const SkRect& src) {
     91     if (!dst->intersect(src)) {
     92         dst->setEmpty();
     93     }
     94 }
     95 
     96 void GrClip::setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty,
     97                              const GrRect* conservativeBounds) {
     98     fList.reset();
     99 
    100     int rectCount = 0;
    101 
    102     // compute bounds for common case of series of intersecting rects.
    103     bool isectRectValid = true;
    104 
    105     if (iter) {
    106         for (iter->rewind(); !iter->isDone(); iter->next()) {
    107             Element& e = fList.push_back();
    108             e.fType = iter->getType();
    109             e.fOp = iter->getOp();
    110             // iterators should not emit replace
    111             GrAssert(kReplace_SetOp != e.fOp);
    112             switch (e.fType) {
    113                 case kRect_ClipType:
    114                     iter->getRect(&e.fRect);
    115                     if (tx || ty) {
    116                         e.fRect.offset(tx, ty);
    117                     }
    118                     ++rectCount;
    119                     if (isectRectValid) {
    120                         if (1 == rectCount || kIntersect_SetOp == e.fOp) {
    121                             GrAssert(fList.count() <= 2);
    122                             if (fList.count() > 1) {
    123                                 GrAssert(2 == rectCount);
    124                                 rectCount = 1;
    125                                 fList.pop_back();
    126                                 GrAssert(kRect_ClipType == fList.back().fType);
    127                                 intersectWith(&fList.back().fRect, e.fRect);
    128                             }
    129                         } else {
    130                             isectRectValid = false;
    131                         }
    132                     }
    133                     break;
    134                 case kPath_ClipType:
    135                     e.fPath = *iter->getPath();
    136                     if (tx || ty) {
    137                         e.fPath.offset(tx, ty);
    138                     }
    139                     e.fPathFill = iter->getPathFill();
    140                     isectRectValid = false;
    141                     break;
    142                 default:
    143                     GrCrash("Unknown clip element type.");
    144             }
    145         }
    146     }
    147     fConservativeBoundsValid = false;
    148     if (isectRectValid) {
    149         fConservativeBoundsValid = true;
    150         if (rectCount > 0) {
    151             fConservativeBounds = fList[0].fRect;
    152         } else {
    153             fConservativeBounds.setEmpty();
    154         }
    155     } else if (NULL != conservativeBounds) {
    156         fConservativeBounds = *conservativeBounds;
    157         fConservativeBoundsValid = true;
    158     }
    159 }
    160