interesct path bounds with clip bounds before initializing supersampler

BUG=skia:

Review URL: https://codereview.chromium.org/656473004
This commit is contained in:
reed 2014-10-15 08:52:00 -07:00 committed by Commit bot
parent 0e08fc17e4
commit bcba2c9f9f
2 changed files with 41 additions and 34 deletions

View File

@ -45,7 +45,7 @@
class BaseSuperBlitter : public SkBlitter {
public:
BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
const SkRegion& clip);
const SkRegion& clip, bool isInverse);
/// Must be explicitly defined on subclasses.
virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
@ -73,38 +73,44 @@ protected:
int fCurrY;
/// Initial y coordinate (top of bounds).
int fTop;
SkIRect fSectBounds;
};
BaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
const SkRegion& clip) {
fRealBlitter = realBlitter;
BaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlit, const SkIRect& ir, const SkRegion& clip,
bool isInverse) {
fRealBlitter = realBlit;
SkIRect sectBounds;
if (isInverse) {
sectBounds = clip.getBounds();
} else {
if (!sectBounds.intersect(ir, clip.getBounds())) {
sectBounds.setEmpty();
}
}
/*
* We use the clip bounds instead of the ir, since we may be asked to
* draw outside of the rect if we're a inverse filltype
*/
const int left = clip.getBounds().fLeft;
const int right = clip.getBounds().fRight;
const int left = sectBounds.left();
const int right = sectBounds.right();
fLeft = left;
fSuperLeft = left << SHIFT;
fWidth = right - left;
#if 0
fCurrIY = -1;
fCurrY = -1;
#else
fTop = ir.fTop;
fCurrIY = ir.fTop - 1;
fCurrY = (ir.fTop << SHIFT) - 1;
#endif
fTop = sectBounds.top();
fCurrIY = fTop - 1;
fCurrY = (fTop << SHIFT) - 1;
SkDEBUGCODE(fCurrX = -1;)
}
/// Run-length-encoded supersampling antialiased blitter.
class SuperBlitter : public BaseSuperBlitter {
public:
SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
const SkRegion& clip);
SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip, bool isInverse);
virtual ~SuperBlitter() {
this->flush();
@ -149,9 +155,10 @@ private:
int fOffsetX;
};
SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
const SkRegion& clip)
: BaseSuperBlitter(realBlitter, ir, clip) {
SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip,
bool isInverse)
: BaseSuperBlitter(realBlitter, ir, clip, isInverse)
{
fRunsToBuffer = realBlitter->requestRowsPreserved();
fRunsBuffer = realBlitter->allocBlitMemory(fRunsToBuffer * this->getRunsSz());
fCurrentRun = -1;
@ -398,8 +405,7 @@ void SuperBlitter::blitRect(int x, int y, int width, int height) {
/// Masked supersampling antialiased blitter.
class MaskSuperBlitter : public BaseSuperBlitter {
public:
MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
const SkRegion& clip);
MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion&, bool isInverse);
virtual ~MaskSuperBlitter() {
fRealBlitter->blitMask(fMask, fClipRect);
}
@ -437,10 +443,12 @@ private:
uint32_t fStorage[(kMAX_STORAGE >> 2) + 1];
};
MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
const SkRegion& clip)
: BaseSuperBlitter(realBlitter, ir, clip) {
MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip,
bool isInverse)
: BaseSuperBlitter(realBlitter, ir, clip, isInverse)
{
SkASSERT(CanHandleRect(ir));
SkASSERT(!isInverse);
fMask.fImage = (uint8_t*)fStorage;
fMask.fBounds = ir;
@ -628,6 +636,7 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
return;
}
const bool isInverse = path.isInverseFillType();
SkIRect ir;
if (!safeRoundOut(path.getBounds(), &ir, SK_MaxS32 >> SHIFT)) {
@ -638,7 +647,7 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
return;
}
if (ir.isEmpty()) {
if (path.isInverseFillType()) {
if (isInverse) {
blitter->blitRegion(origClip);
}
return;
@ -648,7 +657,7 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
// will overflow 32767 when << by SHIFT, we can't supersample,
// so draw without antialiasing.
SkIRect clippedIR;
if (path.isInverseFillType()) {
if (isInverse) {
// If the path is an inverse fill, it's going to fill the entire
// clip, and we care whether the entire clip exceeds our limits.
clippedIR = origClip.getBounds();
@ -685,7 +694,7 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
const SkIRect* clipRect = clipper.getClipRect();
if (clipper.getBlitter() == NULL) { // clipped out
if (path.isInverseFillType()) {
if (isInverse) {
blitter->blitRegion(*clipRgn);
}
return;
@ -694,7 +703,7 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
// now use the (possibly wrapped) blitter
blitter = clipper.getBlitter();
if (path.isInverseFillType()) {
if (isInverse) {
sk_blit_above(blitter, ir, *clipRgn);
}
@ -710,16 +719,16 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
// MaskSuperBlitter can't handle drawing outside of ir, so we can't use it
// if we're an inverse filltype
if (!path.isInverseFillType() && MaskSuperBlitter::CanHandleRect(ir) && !forceRLE) {
MaskSuperBlitter superBlit(blitter, ir, *clipRgn);
if (!isInverse && MaskSuperBlitter::CanHandleRect(ir) && !forceRLE) {
MaskSuperBlitter superBlit(blitter, ir, *clipRgn, isInverse);
SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop);
sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, *clipRgn);
} else {
SuperBlitter superBlit(blitter, ir, *clipRgn);
SuperBlitter superBlit(blitter, ir, *clipRgn, isInverse);
sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, *clipRgn);
}
if (path.isInverseFillType()) {
if (isInverse) {
sk_blit_below(blitter, ir, *clipRgn);
}
}

View File

@ -429,12 +429,10 @@ static void test_regressions() {
// Before the fix, the following code would assert in debug builds.
//
static void test_crbug_422693(skiatest::Reporter* reporter) {
#if 0
SkRasterClip rc(SkIRect::MakeLTRB(-25000, -25000, 25000, 25000));
SkPath path;
path.addCircle(50, 50, 50);
rc.op(path, rc.getBounds().size(), SkRegion::kIntersect_Op, true);
#endif
}
DEF_TEST(AAClip, reporter) {