bool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, const SkIRect& bounds, SkRegion::Op op, bool doAA) { AUTO_RASTERCLIP_VALIDATE(*this); if (fForceConservativeRects) { SkIRect ir; switch (mutate_conservative_op(&op, path.isInverseFillType())) { case kDoNothing_MutateResult: return !this->isEmpty(); case kReplaceClippedAgainstGlobalBounds_MutateResult: ir = bounds; break; case kContinue_MutateResult: { SkRect bounds = path.getBounds(); matrix.mapRect(&bounds); ir = bounds.roundOut(); break; } } return this->op(ir, op); } // base is used to limit the size (and therefore memory allocation) of the // region that results from scan converting devPath. SkRegion base; SkPath devPath; if (matrix.isIdentity()) { devPath = path; } else { path.transform(matrix, &devPath); devPath.setIsVolatile(true); } if (SkRegion::kIntersect_Op == op) { // since we are intersect, we can do better (tighter) with currRgn's // bounds, than just using the device. However, if currRgn is complex, // our region blitter may hork, so we do that case in two steps. if (this->isRect()) { // FIXME: we should also be able to do this when this->isBW(), // but relaxing the test above triggers GM asserts in // SkRgnBuilder::blitH(). We need to investigate what's going on. return this->setPath(devPath, this->bwRgn(), doAA); } else { base.setRect(this->getBounds()); SkRasterClip clip(fForceConservativeRects); clip.setPath(devPath, base, doAA); return this->op(clip, op); } } else { base.setRect(bounds); if (SkRegion::kReplace_Op == op) { return this->setPath(devPath, base, doAA); } else { SkRasterClip clip(fForceConservativeRects); clip.setPath(devPath, base, doAA); return this->op(clip, op); } } }
bool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, const SkIRect& bounds, SkRegion::Op op, bool doAA) { AUTO_RASTERCLIP_VALIDATE(*this); SkRect devRect; if (fForceConservativeRects) { SkIRect ir; switch (mutate_conservative_op(&op, false)) { case kDoNothing_MutateResult: return !this->isEmpty(); case kReplaceClippedAgainstGlobalBounds_MutateResult: ir = bounds; break; case kContinue_MutateResult: matrix.mapRect(&devRect, localRect); ir = devRect.roundOut(); break; } return this->op(ir, op); } const bool isScaleTrans = matrix.isScaleTranslate(); if (!isScaleTrans) { SkPath path; path.addRect(localRect); path.setIsVolatile(true); return this->op(path, matrix, bounds, op, doAA); } matrix.mapRect(&devRect, localRect); if (fIsBW && doAA) { // check that the rect really needs aa, or is it close enought to // integer boundaries that we can just treat it as a BW rect? if (nearly_integral(devRect.fLeft) && nearly_integral(devRect.fTop) && nearly_integral(devRect.fRight) && nearly_integral(devRect.fBottom)) { doAA = false; } } if (fIsBW && !doAA) { SkIRect ir; devRect.round(&ir); (void)fBW.op(ir, op); } else { if (fIsBW) { this->convertToAA(); } (void)fAA.op(devRect, op, doAA); } return this->updateCacheAndReturnNonEmpty(); }
bool SkRasterClip::op(const SkPath& path, const SkISize& size, SkRegion::Op op, bool doAA) { // base is used to limit the size (and therefore memory allocation) of the // region that results from scan converting devPath. SkRegion base; if (fForceConservativeRects) { SkIRect ir; switch (mutate_conservative_op(&op, path.isInverseFillType())) { case kDoNothing_MutateResult: return !this->isEmpty(); case kReplaceClippedAgainstGlobalBounds_MutateResult: ir = SkIRect::MakeSize(size); break; case kContinue_MutateResult: ir = path.getBounds().roundOut(); break; } return this->op(ir, op); } if (SkRegion::kIntersect_Op == op) { // since we are intersect, we can do better (tighter) with currRgn's // bounds, than just using the device. However, if currRgn is complex, // our region blitter may hork, so we do that case in two steps. if (this->isRect()) { // FIXME: we should also be able to do this when this->isBW(), // but relaxing the test above triggers GM asserts in // SkRgnBuilder::blitH(). We need to investigate what's going on. return this->setPath(path, this->bwRgn(), doAA); } else { base.setRect(this->getBounds()); SkRasterClip clip(fForceConservativeRects); clip.setPath(path, base, doAA); return this->op(clip, op); } } else { base.setRect(0, 0, size.width(), size.height()); if (SkRegion::kReplace_Op == op) { return this->setPath(path, base, doAA); } else { SkRasterClip clip(fForceConservativeRects); clip.setPath(path, base, doAA); return this->op(clip, op); } } }
void SkConservativeClip::opRect(const SkRect& localRect, const SkMatrix& ctm, const SkIRect& devBounds, SkRegion::Op op, bool doAA) { SkIRect ir; switch (mutate_conservative_op(&op, false)) { case kDoNothing_MutateResult: return; case kReplaceClippedAgainstGlobalBounds_MutateResult: ir = devBounds; break; case kContinue_MutateResult: { SkRect devRect; ctm.mapRect(&devRect, localRect); ir = doAA ? devRect.roundOut() : devRect.round(); } break; } this->opIRect(ir, op); }
void SkConservativeClip::opPath(const SkPath& path, const SkMatrix& ctm, const SkIRect& devBounds, SkRegion::Op op, bool doAA) { SkIRect ir; switch (mutate_conservative_op(&op, path.isInverseFillType())) { case kDoNothing_MutateResult: return; case kReplaceClippedAgainstGlobalBounds_MutateResult: ir = devBounds; break; case kContinue_MutateResult: { SkRect bounds = path.getBounds(); ctm.mapRect(&bounds); ir = bounds.roundOut(); break; } } return this->opIRect(ir, op); }
bool SkRasterClip::op(const SkRect& r, const SkISize& size, SkRegion::Op op, bool doAA) { AUTO_RASTERCLIP_VALIDATE(*this); if (fForceConservativeRects) { SkIRect ir; switch (mutate_conservative_op(&op, false)) { case kDoNothing_MutateResult: return !this->isEmpty(); case kReplaceClippedAgainstGlobalBounds_MutateResult: ir = SkIRect::MakeSize(size); break; case kContinue_MutateResult: ir = r.roundOut(); break; } return this->op(ir, op); } if (fIsBW && doAA) { // check that the rect really needs aa, or is it close enought to // integer boundaries that we can just treat it as a BW rect? if (nearly_integral(r.fLeft) && nearly_integral(r.fTop) && nearly_integral(r.fRight) && nearly_integral(r.fBottom)) { doAA = false; } } if (fIsBW && !doAA) { SkIRect ir; r.round(&ir); (void)fBW.op(ir, op); } else { if (fIsBW) { this->convertToAA(); } (void)fAA.op(r, op, doAA); } return this->updateCacheAndReturnNonEmpty(); }