/*
* 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;
}
}