/* * Copyright 2010 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrClip_DEFINED #define GrClip_DEFINED #include "GrClipIterator.h" #include "GrRect.h" #include "SkPath.h" #include "SkTArray.h" class GrClip { public: GrClip(); GrClip(const GrClip& src); /** * If specified, the conservativeBounds parameter already takes (tx,ty) * into account. */ GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty, const GrRect* conservativeBounds = NULL); GrClip(const GrIRect& rect); GrClip(const GrRect& rect); ~GrClip(); GrClip& operator=(const GrClip& src); bool hasConservativeBounds() const { return fConservativeBoundsValid; } const GrRect& getConservativeBounds() const { return fConservativeBounds; } bool requiresAA() const { return fRequiresAA; } int getElementCount() const { return fList.count(); } GrClipType getElementType(int i) const { return fList[i].fType; } const SkPath& getPath(int i) const { GrAssert(kPath_ClipType == fList[i].fType); return fList[i].fPath; } GrPathFill getPathFill(int i) const { GrAssert(kPath_ClipType == fList[i].fType); return fList[i].fPathFill; } const GrRect& getRect(int i) const { GrAssert(kRect_ClipType == fList[i].fType); return fList[i].fRect; } SkRegion::Op getOp(int i) const { return fList[i].fOp; } bool getDoAA(int i) const { return fList[i].fDoAA; } bool isRect() const { if (1 == fList.count() && kRect_ClipType == fList[0].fType && (SkRegion::kIntersect_Op == fList[0].fOp || SkRegion::kReplace_Op == fList[0].fOp)) { // if we determined that the clip is a single rect // we ought to have also used that rect as the bounds. GrAssert(fConservativeBoundsValid); GrAssert(fConservativeBounds == fList[0].fRect); return true; } else { return false; } } // FIXME: This word "empty" is confusing. It means that the clip has no // elements (it is the infinite plane) not that it has no area. bool isEmpty() const { return 0 == fList.count(); } /** * Resets this clip to be empty */ void setEmpty(); /** * If specified, the bounds parameter already takes (tx,ty) into account. */ void setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty, const GrRect* conservativeBounds = NULL); void setFromRect(const GrRect& rect); void setFromIRect(const GrIRect& rect); friend bool operator==(const GrClip& a, const GrClip& b) { if (a.fList.count() != b.fList.count()) { return false; } int count = a.fList.count(); for (int i = 0; i < count; ++i) { if (a.fList[i] != b.fList[i]) { return false; } } return true; } friend bool operator!=(const GrClip& a, const GrClip& b) { return !(a == b); } private: struct Element { GrClipType fType; GrRect fRect; SkPath fPath; GrPathFill fPathFill; SkRegion::Op fOp; bool fDoAA; bool operator ==(const Element& e) const { if (e.fType != fType || e.fOp != fOp || e.fDoAA != fDoAA) { return false; } switch (fType) { case kRect_ClipType: return fRect == e.fRect; case kPath_ClipType: return fPath == e.fPath; default: GrCrash("Unknown clip element type."); return false; // suppress warning } } bool operator !=(const Element& e) const { return !(*this == e); } }; GrRect fConservativeBounds; bool fConservativeBoundsValid; bool fRequiresAA; enum { kPreAllocElements = 4, }; SkSTArray fList; }; #endif