зеркало из https://github.com/mozilla/moz-skia.git
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:
Родитель
db15a420c3
Коммит
5ee6491b7a
|
@ -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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче