/* * 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() : fRequiresAA(false) { 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; fRequiresAA = src.fRequiresAA; return *this; } void GrClip::setEmpty() { fList.reset(); fConservativeBounds.setEmpty(); fConservativeBoundsValid = true; fRequiresAA = false; } 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; fList.back().fDoAA = false; 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; fList.back().fDoAA = false; 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(); fRequiresAA = false; 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(); e.fDoAA = iter->getDoAA(); if (e.fDoAA) { fRequiresAA = true; } // 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; } }