1d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com/* 2d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com * Copyright 2010 Google Inc. 3d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com * 4d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com * Use of this source code is governed by a BSD-style license that can be 5d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com * found in the LICENSE file. 6d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com */ 7d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 8d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com#include "SkRasterClip.h" 9d954498c01ccf0417feacf89e45d0c62a06a813breed#include "SkPath.h" 10d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 1134f7e47a3593911d03307a08e5af625b218ceec3reed@google.comSkRasterClip::SkRasterClip(const SkRasterClip& src) { 12045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(src); 13fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 14d954498c01ccf0417feacf89e45d0c62a06a813breed fForceConservativeRects = src.fForceConservativeRects; 1534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com fIsBW = src.fIsBW; 1634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (fIsBW) { 1734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com fBW = src.fBW; 1834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } else { 1934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com fAA = src.fAA; 2034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 21a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com 22a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com fIsEmpty = src.isEmpty(); 23a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com fIsRect = src.isRect(); 24a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com SkDEBUGCODE(this->validate();) 2534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com} 2634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 27d954498c01ccf0417feacf89e45d0c62a06a813breedSkRasterClip::SkRasterClip(const SkIRect& bounds, bool forceConservativeRects) : fBW(bounds) { 28d954498c01ccf0417feacf89e45d0c62a06a813breed fForceConservativeRects = forceConservativeRects; 29ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com fIsBW = true; 30a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute 31a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com fIsRect = !fIsEmpty; 32a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com SkDEBUGCODE(this->validate();) 33ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com} 34ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com 35d954498c01ccf0417feacf89e45d0c62a06a813breedSkRasterClip::SkRasterClip(bool forceConservativeRects) { 36d954498c01ccf0417feacf89e45d0c62a06a813breed fForceConservativeRects = forceConservativeRects; 37d954498c01ccf0417feacf89e45d0c62a06a813breed fIsBW = true; 38d954498c01ccf0417feacf89e45d0c62a06a813breed fIsEmpty = true; 39d954498c01ccf0417feacf89e45d0c62a06a813breed fIsRect = false; 40d954498c01ccf0417feacf89e45d0c62a06a813breed SkDEBUGCODE(this->validate();) 41d954498c01ccf0417feacf89e45d0c62a06a813breed} 42d954498c01ccf0417feacf89e45d0c62a06a813breed 43045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comSkRasterClip::~SkRasterClip() { 44a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com SkDEBUGCODE(this->validate();) 45d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 46d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 47d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::isComplex() const { 48d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com return fIsBW ? fBW.isComplex() : !fAA.isEmpty(); 49d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 50d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 51d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.comconst SkIRect& SkRasterClip::getBounds() const { 52d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com return fIsBW ? fBW.getBounds() : fAA.getBounds(); 53d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 54d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 55d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::setEmpty() { 56045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 57045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 58d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com fIsBW = true; 59d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com fBW.setEmpty(); 60d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com fAA.setEmpty(); 61a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com fIsEmpty = true; 62a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com fIsRect = false; 63d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com return false; 64d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 65d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 66ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.combool SkRasterClip::setRect(const SkIRect& rect) { 67045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 68fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 69d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com fIsBW = true; 70d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com fAA.setEmpty(); 71a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com fIsRect = fBW.setRect(rect); 72a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com fIsEmpty = !fIsRect; 73a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com return fIsRect; 74d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 75d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 76d954498c01ccf0417feacf89e45d0c62a06a813breed///////////////////////////////////////////////////////////////////////////////////// 77d954498c01ccf0417feacf89e45d0c62a06a813breed 78d954498c01ccf0417feacf89e45d0c62a06a813breedbool SkRasterClip::setConservativeRect(const SkRect& r, const SkIRect& clipR, bool isInverse) { 79d954498c01ccf0417feacf89e45d0c62a06a813breed SkRegion::Op op; 80d954498c01ccf0417feacf89e45d0c62a06a813breed if (isInverse) { 81d954498c01ccf0417feacf89e45d0c62a06a813breed op = SkRegion::kDifference_Op; 82d954498c01ccf0417feacf89e45d0c62a06a813breed } else { 83d954498c01ccf0417feacf89e45d0c62a06a813breed op = SkRegion::kIntersect_Op; 84d954498c01ccf0417feacf89e45d0c62a06a813breed } 85d954498c01ccf0417feacf89e45d0c62a06a813breed fBW.setRect(clipR); 86b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed fBW.op(r.roundOut(), op); 87d954498c01ccf0417feacf89e45d0c62a06a813breed return this->updateCacheAndReturnNonEmpty(); 88d954498c01ccf0417feacf89e45d0c62a06a813breed} 89d954498c01ccf0417feacf89e45d0c62a06a813breed 90d954498c01ccf0417feacf89e45d0c62a06a813breed///////////////////////////////////////////////////////////////////////////////////// 91d954498c01ccf0417feacf89e45d0c62a06a813breed 92d954498c01ccf0417feacf89e45d0c62a06a813breedenum MutateResult { 93d954498c01ccf0417feacf89e45d0c62a06a813breed kDoNothing_MutateResult, 94d954498c01ccf0417feacf89e45d0c62a06a813breed kReplaceClippedAgainstGlobalBounds_MutateResult, 95d954498c01ccf0417feacf89e45d0c62a06a813breed kContinue_MutateResult, 96d954498c01ccf0417feacf89e45d0c62a06a813breed}; 97d954498c01ccf0417feacf89e45d0c62a06a813breed 98d954498c01ccf0417feacf89e45d0c62a06a813breedstatic MutateResult mutate_conservative_op(SkRegion::Op* op, bool inverseFilled) { 99d954498c01ccf0417feacf89e45d0c62a06a813breed if (inverseFilled) { 100d954498c01ccf0417feacf89e45d0c62a06a813breed switch (*op) { 101d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kIntersect_Op: 102d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kDifference_Op: 103d954498c01ccf0417feacf89e45d0c62a06a813breed // These ops can only shrink the current clip. So leaving 104d954498c01ccf0417feacf89e45d0c62a06a813breed // the clip unchanged conservatively respects the contract. 105d954498c01ccf0417feacf89e45d0c62a06a813breed return kDoNothing_MutateResult; 106d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kUnion_Op: 107d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kReplace_Op: 108d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kReverseDifference_Op: 109d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kXOR_Op: { 110d954498c01ccf0417feacf89e45d0c62a06a813breed // These ops can grow the current clip up to the extents of 111d954498c01ccf0417feacf89e45d0c62a06a813breed // the input clip, which is inverse filled, so we just set 112d954498c01ccf0417feacf89e45d0c62a06a813breed // the current clip to the device bounds. 113d954498c01ccf0417feacf89e45d0c62a06a813breed *op = SkRegion::kReplace_Op; 114d954498c01ccf0417feacf89e45d0c62a06a813breed return kReplaceClippedAgainstGlobalBounds_MutateResult; 115d954498c01ccf0417feacf89e45d0c62a06a813breed } 116d954498c01ccf0417feacf89e45d0c62a06a813breed } 117d954498c01ccf0417feacf89e45d0c62a06a813breed } else { 118d954498c01ccf0417feacf89e45d0c62a06a813breed // Not inverse filled 119d954498c01ccf0417feacf89e45d0c62a06a813breed switch (*op) { 120d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kIntersect_Op: 121d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kUnion_Op: 122d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kReplace_Op: 123d954498c01ccf0417feacf89e45d0c62a06a813breed return kContinue_MutateResult; 124d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kDifference_Op: 125d954498c01ccf0417feacf89e45d0c62a06a813breed // Difference can only shrink the current clip. 126d954498c01ccf0417feacf89e45d0c62a06a813breed // Leaving clip unchanged conservatively fullfills the contract. 127d954498c01ccf0417feacf89e45d0c62a06a813breed return kDoNothing_MutateResult; 128d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kReverseDifference_Op: 129d954498c01ccf0417feacf89e45d0c62a06a813breed // To reverse, we swap in the bounds with a replace op. 130d954498c01ccf0417feacf89e45d0c62a06a813breed // As with difference, leave it unchanged. 131d954498c01ccf0417feacf89e45d0c62a06a813breed *op = SkRegion::kReplace_Op; 132d954498c01ccf0417feacf89e45d0c62a06a813breed return kContinue_MutateResult; 133d954498c01ccf0417feacf89e45d0c62a06a813breed case SkRegion::kXOR_Op: 134d954498c01ccf0417feacf89e45d0c62a06a813breed // Be conservative, based on (A XOR B) always included in (A union B), 135d954498c01ccf0417feacf89e45d0c62a06a813breed // which is always included in (bounds(A) union bounds(B)) 136d954498c01ccf0417feacf89e45d0c62a06a813breed *op = SkRegion::kUnion_Op; 137d954498c01ccf0417feacf89e45d0c62a06a813breed return kContinue_MutateResult; 138d954498c01ccf0417feacf89e45d0c62a06a813breed } 139d954498c01ccf0417feacf89e45d0c62a06a813breed } 140d954498c01ccf0417feacf89e45d0c62a06a813breed SkFAIL("should not get here"); 141d954498c01ccf0417feacf89e45d0c62a06a813breed return kDoNothing_MutateResult; 142d954498c01ccf0417feacf89e45d0c62a06a813breed} 143d954498c01ccf0417feacf89e45d0c62a06a813breed 144d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) { 145045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 146045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 147d954498c01ccf0417feacf89e45d0c62a06a813breed if (fForceConservativeRects) { 148d954498c01ccf0417feacf89e45d0c62a06a813breed return this->setConservativeRect(path.getBounds(), clip.getBounds(), path.isInverseFillType()); 149d954498c01ccf0417feacf89e45d0c62a06a813breed } 150d954498c01ccf0417feacf89e45d0c62a06a813breed 151d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com if (this->isBW() && !doAA) { 152a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com (void)fBW.setPath(path, clip); 153d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com } else { 154897fc41934e6aecec62f89d093c93b917cfa5345reed@google.com // TODO: since we are going to over-write fAA completely (aren't we?) 155897fc41934e6aecec62f89d093c93b917cfa5345reed@google.com // we should just clear our BW data (if any) and set fIsAA=true 156d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com if (this->isBW()) { 157d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com this->convertToAA(); 158d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com } 159a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com (void)fAA.setPath(path, &clip, doAA); 160d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com } 161a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com return this->updateCacheAndReturnNonEmpty(); 162d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 163d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 164d64c9487135094c83f658319f53ea2005ecc08b2reedbool SkRasterClip::op(const SkPath& path, const SkISize& size, SkRegion::Op op, bool doAA) { 165d64c9487135094c83f658319f53ea2005ecc08b2reed // base is used to limit the size (and therefore memory allocation) of the 166d64c9487135094c83f658319f53ea2005ecc08b2reed // region that results from scan converting devPath. 167d64c9487135094c83f658319f53ea2005ecc08b2reed SkRegion base; 168d954498c01ccf0417feacf89e45d0c62a06a813breed 169d954498c01ccf0417feacf89e45d0c62a06a813breed if (fForceConservativeRects) { 170d954498c01ccf0417feacf89e45d0c62a06a813breed SkIRect ir; 171d954498c01ccf0417feacf89e45d0c62a06a813breed switch (mutate_conservative_op(&op, path.isInverseFillType())) { 172d954498c01ccf0417feacf89e45d0c62a06a813breed case kDoNothing_MutateResult: 173d954498c01ccf0417feacf89e45d0c62a06a813breed return !this->isEmpty(); 174d954498c01ccf0417feacf89e45d0c62a06a813breed case kReplaceClippedAgainstGlobalBounds_MutateResult: 175d954498c01ccf0417feacf89e45d0c62a06a813breed ir = SkIRect::MakeSize(size); 176d954498c01ccf0417feacf89e45d0c62a06a813breed break; 177d954498c01ccf0417feacf89e45d0c62a06a813breed case kContinue_MutateResult: 178b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed ir = path.getBounds().roundOut(); 179d954498c01ccf0417feacf89e45d0c62a06a813breed break; 180d954498c01ccf0417feacf89e45d0c62a06a813breed } 181d954498c01ccf0417feacf89e45d0c62a06a813breed return this->op(ir, op); 182d954498c01ccf0417feacf89e45d0c62a06a813breed } 183d954498c01ccf0417feacf89e45d0c62a06a813breed 184d64c9487135094c83f658319f53ea2005ecc08b2reed if (SkRegion::kIntersect_Op == op) { 185d64c9487135094c83f658319f53ea2005ecc08b2reed // since we are intersect, we can do better (tighter) with currRgn's 186d64c9487135094c83f658319f53ea2005ecc08b2reed // bounds, than just using the device. However, if currRgn is complex, 187d64c9487135094c83f658319f53ea2005ecc08b2reed // our region blitter may hork, so we do that case in two steps. 188d64c9487135094c83f658319f53ea2005ecc08b2reed if (this->isRect()) { 189d64c9487135094c83f658319f53ea2005ecc08b2reed // FIXME: we should also be able to do this when this->isBW(), 190d64c9487135094c83f658319f53ea2005ecc08b2reed // but relaxing the test above triggers GM asserts in 191d64c9487135094c83f658319f53ea2005ecc08b2reed // SkRgnBuilder::blitH(). We need to investigate what's going on. 192d64c9487135094c83f658319f53ea2005ecc08b2reed return this->setPath(path, this->bwRgn(), doAA); 193d64c9487135094c83f658319f53ea2005ecc08b2reed } else { 194d64c9487135094c83f658319f53ea2005ecc08b2reed base.setRect(this->getBounds()); 195d954498c01ccf0417feacf89e45d0c62a06a813breed SkRasterClip clip(fForceConservativeRects); 196d64c9487135094c83f658319f53ea2005ecc08b2reed clip.setPath(path, base, doAA); 197d64c9487135094c83f658319f53ea2005ecc08b2reed return this->op(clip, op); 198d64c9487135094c83f658319f53ea2005ecc08b2reed } 199d64c9487135094c83f658319f53ea2005ecc08b2reed } else { 200d64c9487135094c83f658319f53ea2005ecc08b2reed base.setRect(0, 0, size.width(), size.height()); 201d64c9487135094c83f658319f53ea2005ecc08b2reed 202d64c9487135094c83f658319f53ea2005ecc08b2reed if (SkRegion::kReplace_Op == op) { 203d64c9487135094c83f658319f53ea2005ecc08b2reed return this->setPath(path, base, doAA); 204d64c9487135094c83f658319f53ea2005ecc08b2reed } else { 205d954498c01ccf0417feacf89e45d0c62a06a813breed SkRasterClip clip(fForceConservativeRects); 206d64c9487135094c83f658319f53ea2005ecc08b2reed clip.setPath(path, base, doAA); 207d64c9487135094c83f658319f53ea2005ecc08b2reed return this->op(clip, op); 208d64c9487135094c83f658319f53ea2005ecc08b2reed } 209d64c9487135094c83f658319f53ea2005ecc08b2reed } 210d64c9487135094c83f658319f53ea2005ecc08b2reed} 211d64c9487135094c83f658319f53ea2005ecc08b2reed 212d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) { 213d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com SkRegion tmp; 214d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com tmp.setRect(clip); 215d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com return this->setPath(path, tmp, doAA); 216d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 217d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 218d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::op(const SkIRect& rect, SkRegion::Op op) { 219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 220fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 221a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com fIsBW ? fBW.op(rect, op) : fAA.op(rect, op); 222a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com return this->updateCacheAndReturnNonEmpty(); 223d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 224d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 225ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.combool SkRasterClip::op(const SkRegion& rgn, SkRegion::Op op) { 226045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 227fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 228ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com if (fIsBW) { 229a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com (void)fBW.op(rgn, op); 230ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com } else { 231ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com SkAAClip tmp; 232ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com tmp.setRegion(rgn); 233a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com (void)fAA.op(tmp, op); 234ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com } 235a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com return this->updateCacheAndReturnNonEmpty(); 236ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com} 237ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com 238d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) { 239045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 240045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.validate(); 241045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 242d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com if (this->isBW() && clip.isBW()) { 243a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com (void)fBW.op(clip.fBW, op); 244d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com } else { 245d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com SkAAClip tmp; 246d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com const SkAAClip* other; 247d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 248d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com if (this->isBW()) { 249d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com this->convertToAA(); 250d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com } 251d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com if (clip.isBW()) { 252d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com tmp.setRegion(clip.bwRgn()); 253d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com other = &tmp; 254d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com } else { 255d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com other = &clip.aaRgn(); 256d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com } 257a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com (void)fAA.op(*other, op); 258d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com } 259a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com return this->updateCacheAndReturnNonEmpty(); 260d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 261d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 26218c464b460d062142ab7198724431a4d2ad7070dreed@google.com/** 26318c464b460d062142ab7198724431a4d2ad7070dreed@google.com * Our antialiasing currently has a granularity of 1/4 of a pixel along each 26418c464b460d062142ab7198724431a4d2ad7070dreed@google.com * axis. Thus we can treat an axis coordinate as an integer if it differs 26518c464b460d062142ab7198724431a4d2ad7070dreed@google.com * from its nearest int by < half of that value (1.8 in this case). 26618c464b460d062142ab7198724431a4d2ad7070dreed@google.com */ 26718c464b460d062142ab7198724431a4d2ad7070dreed@google.comstatic bool nearly_integral(SkScalar x) { 26818c464b460d062142ab7198724431a4d2ad7070dreed@google.com static const SkScalar domain = SK_Scalar1 / 4; 26918c464b460d062142ab7198724431a4d2ad7070dreed@google.com static const SkScalar halfDomain = domain / 2; 27018c464b460d062142ab7198724431a4d2ad7070dreed@google.com 27118c464b460d062142ab7198724431a4d2ad7070dreed@google.com x += halfDomain; 27218c464b460d062142ab7198724431a4d2ad7070dreed@google.com return x - SkScalarFloorToScalar(x) < domain; 2730017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com} 2740017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com 275d954498c01ccf0417feacf89e45d0c62a06a813breedbool SkRasterClip::op(const SkRect& r, const SkISize& size, SkRegion::Op op, bool doAA) { 276045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 277fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 278d954498c01ccf0417feacf89e45d0c62a06a813breed if (fForceConservativeRects) { 279d954498c01ccf0417feacf89e45d0c62a06a813breed SkIRect ir; 280d954498c01ccf0417feacf89e45d0c62a06a813breed switch (mutate_conservative_op(&op, false)) { 281d954498c01ccf0417feacf89e45d0c62a06a813breed case kDoNothing_MutateResult: 282d954498c01ccf0417feacf89e45d0c62a06a813breed return !this->isEmpty(); 283d954498c01ccf0417feacf89e45d0c62a06a813breed case kReplaceClippedAgainstGlobalBounds_MutateResult: 284d954498c01ccf0417feacf89e45d0c62a06a813breed ir = SkIRect::MakeSize(size); 285d954498c01ccf0417feacf89e45d0c62a06a813breed break; 286d954498c01ccf0417feacf89e45d0c62a06a813breed case kContinue_MutateResult: 287b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed ir = r.roundOut(); 288d954498c01ccf0417feacf89e45d0c62a06a813breed break; 289d954498c01ccf0417feacf89e45d0c62a06a813breed } 290d954498c01ccf0417feacf89e45d0c62a06a813breed return this->op(ir, op); 291d954498c01ccf0417feacf89e45d0c62a06a813breed } 292d954498c01ccf0417feacf89e45d0c62a06a813breed 293420f74fa720272b1164eae55d7b6c10e07d41601reed@google.com if (fIsBW && doAA) { 29418c464b460d062142ab7198724431a4d2ad7070dreed@google.com // check that the rect really needs aa, or is it close enought to 29518c464b460d062142ab7198724431a4d2ad7070dreed@google.com // integer boundaries that we can just treat it as a BW rect? 29618c464b460d062142ab7198724431a4d2ad7070dreed@google.com if (nearly_integral(r.fLeft) && nearly_integral(r.fTop) && 29718c464b460d062142ab7198724431a4d2ad7070dreed@google.com nearly_integral(r.fRight) && nearly_integral(r.fBottom)) { 2980017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com doAA = false; 2990017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com } 3000017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com } 3010017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com 3020017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fIsBW && !doAA) { 3030017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkIRect ir; 3040017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com r.round(&ir); 305a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com (void)fBW.op(ir, op); 3060017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com } else { 3070017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fIsBW) { 3080017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com this->convertToAA(); 3090017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com } 310a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com (void)fAA.op(r, op, doAA); 3110017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com } 312a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com return this->updateCacheAndReturnNonEmpty(); 3130017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com} 3140017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com 31534f7e47a3593911d03307a08e5af625b218ceec3reed@google.comvoid SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const { 31634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (NULL == dst) { 31734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com return; 31834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 31934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 320045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 321fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 32234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (this->isEmpty()) { 32334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dst->setEmpty(); 32434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com return; 32534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 32634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (0 == (dx | dy)) { 32734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com *dst = *this; 32834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com return; 32934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 33034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 33134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dst->fIsBW = fIsBW; 33234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (fIsBW) { 33334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com fBW.translate(dx, dy, &dst->fBW); 33434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dst->fAA.setEmpty(); 33534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } else { 33634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com fAA.translate(dx, dy, &dst->fAA); 33734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dst->fBW.setEmpty(); 33834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 339a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com dst->updateCacheAndReturnNonEmpty(); 34034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com} 34134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 342045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkRasterClip::quickContains(const SkIRect& ir) const { 343045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return fIsBW ? fBW.quickContains(ir) : fAA.quickContains(ir); 344045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 345045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 34634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com/////////////////////////////////////////////////////////////////////////////// 34734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 348ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.comconst SkRegion& SkRasterClip::forceGetBW() { 349045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 350fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 351ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com if (!fIsBW) { 352ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com fBW.setRect(fAA.getBounds()); 353ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com } 354ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com return fBW; 355ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com} 356ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com 357d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.comvoid SkRasterClip::convertToAA() { 358045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_RASTERCLIP_VALIDATE(*this); 359d954498c01ccf0417feacf89e45d0c62a06a813breed 360d954498c01ccf0417feacf89e45d0c62a06a813breed SkASSERT(!fForceConservativeRects); 361d954498c01ccf0417feacf89e45d0c62a06a813breed 362d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com SkASSERT(fIsBW); 363d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com fAA.setRegion(fBW); 364d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com fIsBW = false; 365202ab2a5cabaf25a1e6ec47c0003da3213a79864reed 366202ab2a5cabaf25a1e6ec47c0003da3213a79864reed // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize" 367202ab2a5cabaf25a1e6ec47c0003da3213a79864reed // ourselves back to BW. 368202ab2a5cabaf25a1e6ec47c0003da3213a79864reed (void)this->updateCacheAndReturnNonEmpty(false); 369d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com} 370d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com 371045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG 372045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkRasterClip::validate() const { 373045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // can't ever assert that fBW is empty, since we may have called forceGetBW 374045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fIsBW) { 375045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fAA.isEmpty()); 376045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 377045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 378045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBW.validate(); 379045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fAA.validate(); 380a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com 381a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com SkASSERT(this->computeIsEmpty() == fIsEmpty); 382a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com SkASSERT(this->computeIsRect() == fIsRect); 383045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 384045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 385045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 386045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 387045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 388045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comSkAAClipBlitterWrapper::SkAAClipBlitterWrapper() { 389045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkDEBUGCODE(fClipRgn = NULL;) 390045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkDEBUGCODE(fBlitter = NULL;) 391045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 392045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 393045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comSkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkRasterClip& clip, 394045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter) { 395045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->init(clip, blitter); 396045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 397045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 398045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comSkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkAAClip* aaclip, 399045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter) { 400045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(blitter); 401045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(aaclip); 402045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBWRgn.setRect(aaclip->getBounds()); 403045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fAABlitter.init(blitter, aaclip); 404045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // now our return values 405045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClipRgn = &fBWRgn; 406045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter = &fAABlitter; 407045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 408045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 409045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitterWrapper::init(const SkRasterClip& clip, SkBlitter* blitter) { 410045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(blitter); 411045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (clip.isBW()) { 412045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClipRgn = &clip.bwRgn(); 413045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter = blitter; 414045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 415045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkAAClip& aaclip = clip.aaRgn(); 416045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBWRgn.setRect(aaclip.getBounds()); 417045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fAABlitter.init(blitter, &aaclip); 418045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // now our return values 419045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClipRgn = &fBWRgn; 420045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter = &fAABlitter; 421045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 422045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 423