diff options
Diffstat (limited to 'src/gpu/GrClip.cpp')
-rw-r--r-- | src/gpu/GrClip.cpp | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/gpu/GrClip.cpp b/src/gpu/GrClip.cpp new file mode 100644 index 0000000000..a02d9f4504 --- /dev/null +++ b/src/gpu/GrClip.cpp @@ -0,0 +1,145 @@ + +/* + * Copyright 2010 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + + +#include "GrClip.h" + +GrClip::GrClip() { + fConservativeBounds.setEmpty(); + fConservativeBoundsValid = true; +} + +GrClip::GrClip(const GrClip& src) { + *this = src; +} + +GrClip::GrClip(const GrIRect& rect) { + this->setFromIRect(rect); +} + +GrClip::GrClip(const GrRect& rect) { + this->setFromRect(rect); +} + +GrClip::GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty, + const GrRect* bounds) { + this->setFromIterator(iter, tx, ty, bounds); +} + +GrClip::~GrClip() {} + +GrClip& GrClip::operator=(const GrClip& src) { + fList = src.fList; + fConservativeBounds = src.fConservativeBounds; + fConservativeBoundsValid = src.fConservativeBoundsValid; + return *this; +} + +void GrClip::setEmpty() { + fList.reset(); + fConservativeBounds.setEmpty(); + fConservativeBoundsValid = true; +} + +void GrClip::setFromRect(const GrRect& r) { + fList.reset(); + if (r.isEmpty()) { + // use a canonical empty rect for == testing. + setEmpty(); + } else { + fList.push_back(); + fList.back().fRect = r; + fList.back().fType = kRect_ClipType; + fList.back().fOp = kReplace_SetOp; + fConservativeBounds = r; + fConservativeBoundsValid = true; + } +} + +void GrClip::setFromIRect(const GrIRect& r) { + fList.reset(); + if (r.isEmpty()) { + // use a canonical empty rect for == testing. + setEmpty(); + } else { + fList.push_back(); + fList.back().fRect.set(r); + fList.back().fType = kRect_ClipType; + fList.back().fOp = kReplace_SetOp; + fConservativeBounds.set(r); + fConservativeBoundsValid = true; + } +} + +static void intersectWith(SkRect* dst, const SkRect& src) { + if (!dst->intersect(src)) { + dst->setEmpty(); + } +} + +void GrClip::setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty, + const GrRect* conservativeBounds) { + fList.reset(); + + int rectCount = 0; + + // compute bounds for common case of series of intersecting rects. + bool isectRectValid = true; + + if (iter) { + for (iter->rewind(); !iter->isDone(); iter->next()) { + Element& e = fList.push_back(); + e.fType = iter->getType(); + e.fOp = iter->getOp(); + // iterators should not emit replace + GrAssert(kReplace_SetOp != e.fOp); + switch (e.fType) { + case kRect_ClipType: + iter->getRect(&e.fRect); + if (tx || ty) { + e.fRect.offset(tx, ty); + } + ++rectCount; + if (isectRectValid) { + if (kIntersect_SetOp == e.fOp) { + GrAssert(fList.count() <= 2); + if (fList.count() > 1) { + GrAssert(2 == rectCount); + rectCount = 1; + fList.pop_back(); + GrAssert(kRect_ClipType == fList.back().fType); + intersectWith(&fList.back().fRect, e.fRect); + } + } else { + isectRectValid = false; + } + } + break; + case kPath_ClipType: + e.fPath = *iter->getPath(); + if (tx || ty) { + e.fPath.offset(tx, ty); + } + e.fPathFill = iter->getPathFill(); + isectRectValid = false; + break; + default: + GrCrash("Unknown clip element type."); + } + } + } + fConservativeBoundsValid = false; + if (isectRectValid && rectCount) { + fConservativeBounds = fList[0].fRect; + fConservativeBoundsValid = true; + } else if (NULL != conservativeBounds) { + fConservativeBounds = *conservativeBounds; + fConservativeBoundsValid = true; + } +} |