Fix mask overflow caused by edge drift

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4797

Change-Id: Ica1568b67c1e1ce4aae2bdaba2c5b1f2155d1382
Reviewed-on: https://skia-review.googlesource.com/4797
Reviewed-by: Cary Clark <caryclark@google.com>
This commit is contained in:
Yuqian Li 2016-11-16 13:07:57 -05:00
parent 721625b25e
commit 20079a94e8
3 changed files with 31 additions and 2 deletions

View File

@ -44,7 +44,7 @@ struct SkAnalyticEdge {
static inline SkFixed snapY(SkFixed y, int accuracy = kDefaultAccuracy) {
// This approach is safer than left shift, round, then right shift
return (y + (SK_Fixed1 >> (accuracy + 1))) >> (16 - accuracy) << (16 - accuracy);
return ((unsigned)y + (SK_Fixed1 >> (accuracy + 1))) >> (16 - accuracy) << (16 - accuracy);
}
// Update fX, fY of this edge so fY = y

View File

@ -1204,8 +1204,18 @@ void aaa_fill_path(const SkPath& path, const SkIRect& clipRect, AdditiveBlitter*
if (!path.isInverseFillType() && path.isConvex()) {
SkASSERT(count >= 2); // convex walker does not handle missing right edges
SkFixed leftBound = SkIntToFixed(rect.fLeft);
SkFixed rightBound = SkIntToFixed(rect.fRight);
if (isUsingMask) {
// If we're using mask, then we have to limit the bound within the path bounds.
// Otherwise, the edge drift may access an invalid address inside the mask.
SkIRect ir;
path.getBounds().roundOut(&ir);
leftBound = SkTMax(leftBound, SkIntToFixed(ir.fLeft));
rightBound = SkTMin(rightBound, SkIntToFixed(ir.fRight));
}
aaa_walk_convex_edges(&headEdge, blitter, start_y, stop_y,
rect.fLeft << 16, rect.fRight << 16, isUsingMask);
leftBound, rightBound, isUsingMask);
} else {
SkFAIL("Concave AAA is not yet implemented!");
}

View File

@ -198,6 +198,24 @@ static void test_fuzz_crbug_662780() {
canvas->drawRectCoords(0, 0, 250, 250, paint);
}
static void test_mask_overflow() {
auto surface(SkSurface::MakeRasterN32Premul(500, 500));
SkCanvas* canvas = surface->getCanvas();
SkPaint paint;
paint.setAntiAlias(true);
SkPath path;
path.moveTo(SkBits2Float(0x43e28000), SkBits2Float(0x43aa8000)); // 453, 341
path.lineTo(SkBits2Float(0x43de6000), SkBits2Float(0x43aa8000)); // 444.75f, 341
// 440.47f, 341, 437, 344.47f, 437, 348.75f
path.cubicTo(SkBits2Float(0x43dc3c29), SkBits2Float(0x43aa8000),
SkBits2Float(0x43da8000), SkBits2Float(0x43ac3c29),
SkBits2Float(0x43da8000), SkBits2Float(0x43ae6000));
path.lineTo(SkBits2Float(0x43da8000), SkBits2Float(0x43b18000)); // 437, 355
path.lineTo(SkBits2Float(0x43e28000), SkBits2Float(0x43b18000)); // 453, 355
path.lineTo(SkBits2Float(0x43e28000), SkBits2Float(0x43aa8000)); // 453, 341
canvas->drawPath(path, paint);
}
/**
* In debug mode, this path was causing an assertion to fail in
* SkPathStroker::preJoinTo() and, in Release, the use of an unitialized value.
@ -4359,6 +4377,7 @@ DEF_TEST(Paths, reporter) {
test_fuzz_crbug_662952(reporter);
test_fuzz_crbug_662730(reporter);
test_fuzz_crbug_662780();
test_mask_overflow();
SkTSize<SkScalar>::Make(3,4);