Better fix for rev. 4214 (inverse-fill and clipping). This fix avoids changing

the actual clipping bounds, which caused tiny differences in the scan converter.
Also adding a gm (which I should have the first time.)
Review URL: https://codereview.appspot.com/6297073

git-svn-id: http://skia.googlecode.com/svn/trunk@4227 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2012-06-11 17:30:33 +00:00
Родитель db15a420c3
Коммит 5ee6491b7a
3 изменённых файлов: 86 добавлений и 23 удалений

Просмотреть файл

@ -117,9 +117,7 @@ static const MakePathProc gProcs[] = {
#define N SK_ARRAY_COUNT(gProcs)
namespace skiagm {
class PathFillGM : public GM {
class PathFillGM : public skiagm::GM {
SkPath fPath[N];
SkScalar fDY[N];
public:
@ -128,16 +126,16 @@ public:
fDY[i] = gProcs[i](&fPath[i]);
}
}
protected:
virtual SkString onShortName() {
return SkString("pathfill");
}
virtual SkISize onISize() {
return make_isize(640, 480);
return SkISize::Make(640, 480);
}
virtual void onDraw(SkCanvas* canvas) {
SkPaint paint;
paint.setAntiAlias(true);
@ -147,14 +145,82 @@ protected:
canvas->translate(SkIntToScalar(0), fDY[i]);
}
}
private:
typedef GM INHERITED;
typedef skiagm::GM INHERITED;
};
// test inverse-fill w/ a clip that completely excludes the geometry
class PathInverseFillGM : public skiagm::GM {
SkPath fPath[N];
SkScalar fDY[N];
public:
PathInverseFillGM() {
for (size_t i = 0; i < N; i++) {
fDY[i] = gProcs[i](&fPath[i]);
}
}
protected:
virtual SkString onShortName() {
return SkString("pathinvfill");
}
virtual SkISize onISize() {
return SkISize::Make(450, 220);
}
static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint,
const SkRect* clip, SkScalar top, const SkScalar bottom) {
canvas->save();
if (clip) {
SkRect r = *clip;
r.fTop = top;
r.fBottom = bottom;
canvas->clipRect(r);
}
canvas->drawPath(path, paint);
canvas->restore();
}
virtual void onDraw(SkCanvas* canvas) {
SkPath path;
path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40));
path.toggleInverseFillType();
SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) };
canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
for (int doclip = 0; doclip <= 1; ++doclip) {
for (int aa = 0; aa <= 1; ++aa) {
SkPaint paint;
paint.setAntiAlias(SkToBool(aa));
canvas->save();
canvas->clipRect(clipR);
const SkRect* clipPtr = doclip ? &clipR : NULL;
show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY());
show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom);
canvas->restore();
canvas->translate(SkIntToScalar(110), 0);
}
}
}
private:
typedef skiagm::GM INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
static GM* MyFactory(void*) { return new PathFillGM; }
static GMRegistry reg(MyFactory);
static skiagm::GM* MyFactory(void*) { return new PathFillGM; }
static skiagm::GMRegistry reg(MyFactory);
static skiagm::GM* F1(void*) { return new PathInverseFillGM; }
static skiagm::GMRegistry gR1(F1);
}

Просмотреть файл

@ -15,7 +15,8 @@
class SkScanClipper {
public:
SkScanClipper(SkBlitter* blitter, const SkRegion* clip, const SkIRect& bounds);
SkScanClipper(SkBlitter* blitter, const SkRegion* clip, const SkIRect& bounds,
bool skipRejectTest = false);
SkBlitter* getBlitter() const { return fBlitter; }
const SkIRect* getClipRect() const { return fClipRect; }

Просмотреть файл

@ -540,22 +540,19 @@ void sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip)
///////////////////////////////////////////////////////////////////////////////
static const SkIRect gHugeIRect = {
SK_MinS32, SK_MinS32, SK_MaxS32, SK_MaxS32
};
/**
* If the caller is drawing an inverse-fill path, then it shouldn't pass a
* huge rect for ir, since the path draws "everywhere".
* If the caller is drawing an inverse-fill path, then it pass true for
* skipRejectTest, so we don't abort drawing just because the src bounds (ir)
* is outside of the clip.
*/
SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip,
const SkIRect& ir) {
const SkIRect& ir, bool skipRejectTest) {
fBlitter = NULL; // null means blit nothing
fClipRect = NULL;
if (clip) {
fClipRect = &clip->getBounds();
if (!SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out
if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out
return;
}
@ -618,8 +615,7 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
return;
}
SkScanClipper clipper(blitter, clipPtr,
path.isInverseFillType() ? gHugeIRect : ir);
SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType());
blitter = clipper.getBlitter();
if (blitter) {