update the nearly_integral calculation to be (a) faster, and (b) to correctly
identify that the AA granularity is 1/4 of a pixel, not 1/16 (along an axis). git-svn-id: http://skia.googlecode.com/svn/trunk@3919 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
5adf9b2e98
commit
18c464b460
@ -150,21 +150,27 @@ bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) {
|
||||
return this->updateCacheAndReturnNonEmpty();
|
||||
}
|
||||
|
||||
// return true if x is nearly integral (within 1/16) since that is the highest
|
||||
// precision our aa code can have.
|
||||
static bool is_integral(SkScalar x) {
|
||||
int ix = SkScalarRoundToInt(x);
|
||||
SkScalar sx = SkIntToScalar(ix);
|
||||
return SkScalarAbs(sx - x) < (SK_Scalar1 / 16);
|
||||
/**
|
||||
* Our antialiasing currently has a granularity of 1/4 of a pixel along each
|
||||
* axis. Thus we can treat an axis coordinate as an integer if it differs
|
||||
* from its nearest int by < half of that value (1.8 in this case).
|
||||
*/
|
||||
static bool nearly_integral(SkScalar x) {
|
||||
static const SkScalar domain = SK_Scalar1 / 4;
|
||||
static const SkScalar halfDomain = domain / 2;
|
||||
|
||||
x += halfDomain;
|
||||
return x - SkScalarFloorToScalar(x) < domain;
|
||||
}
|
||||
|
||||
bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) {
|
||||
AUTO_RASTERCLIP_VALIDATE(*this);
|
||||
|
||||
if (fIsBW && doAA) {
|
||||
// check that the rect really needs aa
|
||||
if (is_integral(r.fLeft) && is_integral(r.fTop) &&
|
||||
is_integral(r.fRight) && is_integral(r.fBottom)) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
@ -316,6 +316,67 @@ static void test_path_with_hole(skiatest::Reporter* reporter) {
|
||||
}
|
||||
}
|
||||
|
||||
#include "SkRasterClip.h"
|
||||
|
||||
static void copyToMask(const SkRasterClip& rc, SkMask* mask) {
|
||||
if (rc.isAA()) {
|
||||
rc.aaRgn().copyToMask(mask);
|
||||
} else {
|
||||
copyToMask(rc.bwRgn(), mask);
|
||||
}
|
||||
}
|
||||
|
||||
static bool operator==(const SkRasterClip& a, const SkRasterClip& b) {
|
||||
if (a.isEmpty()) {
|
||||
return b.isEmpty();
|
||||
}
|
||||
if (b.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkMask ma, mb;
|
||||
copyToMask(a, &ma);
|
||||
copyToMask(b, &mb);
|
||||
return ma == mb;
|
||||
}
|
||||
|
||||
static void did_dx_affect(skiatest::Reporter* reporter, const SkScalar dx[],
|
||||
size_t count, bool changed) {
|
||||
SkIRect ir = { 0, 0, 10, 10 };
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
SkRect r;
|
||||
r.set(ir);
|
||||
|
||||
SkRasterClip rc0(ir);
|
||||
SkRasterClip rc1(ir);
|
||||
SkRasterClip rc2(ir);
|
||||
|
||||
rc0.op(r, SkRegion::kIntersect_Op, false);
|
||||
r.offset(dx[i], 0);
|
||||
rc1.op(r, SkRegion::kIntersect_Op, true);
|
||||
r.offset(-2*dx[i], 0);
|
||||
rc2.op(r, SkRegion::kIntersect_Op, true);
|
||||
|
||||
REPORTER_ASSERT(reporter, changed != (rc0 == rc1));
|
||||
REPORTER_ASSERT(reporter, changed != (rc0 == rc2));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_nearly_integral(skiatest::Reporter* reporter) {
|
||||
// All of these should generate equivalent rasterclips
|
||||
|
||||
static const SkScalar gSafeX[] = {
|
||||
0, SK_Scalar1/1000, SK_Scalar1/100, SK_Scalar1/10,
|
||||
};
|
||||
did_dx_affect(reporter, gSafeX, SK_ARRAY_COUNT(gSafeX), false);
|
||||
|
||||
static const SkScalar gUnsafeX[] = {
|
||||
SK_Scalar1/4, SK_Scalar1/3,
|
||||
};
|
||||
did_dx_affect(reporter, gUnsafeX, SK_ARRAY_COUNT(gUnsafeX), true);
|
||||
}
|
||||
|
||||
static void test_regressions(skiatest::Reporter* reporter) {
|
||||
// these should not assert in the debug build
|
||||
// bug was introduced in rev. 3209
|
||||
@ -337,6 +398,7 @@ static void TestAAClip(skiatest::Reporter* reporter) {
|
||||
test_rgn(reporter);
|
||||
test_path_with_hole(reporter);
|
||||
test_regressions(reporter);
|
||||
test_nearly_integral(reporter);
|
||||
}
|
||||
|
||||
#include "TestClassDef.h"
|
||||
|
Loading…
Reference in New Issue
Block a user