11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "Test.h"
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkAAClip.h"
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkCanvas.h"
111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkMask.h"
121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkPath.h"
131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkRandom.h"
141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool operator==(const SkMask& a, const SkMask& b) {
161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (a.fFormat != b.fFormat || a.fBounds != b.fBounds) {
171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!a.fImage && !b.fImage) {
201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return true;
211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!a.fImage || !b.fImage) {
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t wbytes = a.fBounds.width();
271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    switch (a.fFormat) {
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case SkMask::kBW_Format:
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            wbytes = (wbytes + 7) >> 3;
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case SkMask::kA8_Format:
321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case SkMask::k3D_Format:
331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case SkMask::kLCD16_Format:
351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            wbytes <<= 1;
361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case SkMask::kLCD32_Format:
381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case SkMask::kARGB32_Format:
391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            wbytes <<= 2;
401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        default:
421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkASSERT(!"unknown mask format");
431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            return false;
441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int h = a.fBounds.height();
471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char* aptr = (const char*)a.fImage;
481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char* bptr = (const char*)b.fImage;
491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int y = 0; y < h; ++y) {
501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (memcmp(aptr, bptr, wbytes)) {
511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            return false;
521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        aptr += wbytes;
541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bptr += wbytes;
551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void copyToMask(const SkRegion& rgn, SkMask* mask) {
601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    mask->fFormat = SkMask::kA8_Format;
611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (rgn.isEmpty()) {
631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        mask->fBounds.setEmpty();
641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        mask->fRowBytes = 0;
651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        mask->fImage = NULL;
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return;
671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    mask->fBounds = rgn.getBounds();
701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    mask->fRowBytes = mask->fBounds.width();
711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    mask->fImage = SkMask::AllocImage(mask->computeImageSize());
721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sk_bzero(mask->fImage, mask->computeImageSize());
731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBitmap bitmap;
751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bitmap.setConfig(SkBitmap::kA8_Config, mask->fBounds.width(),
761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                     mask->fBounds.height(), mask->fRowBytes);
771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bitmap.setPixels(mask->fImage);
781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // canvas expects its coordinate system to always be 0,0 in the top/left
801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // so we translate the rgn to match that before drawing into the mask.
811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //
821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRegion tmpRgn(rgn);
831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    tmpRgn.translate(-rgn.getBounds().fLeft, -rgn.getBounds().fTop);
841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkCanvas canvas(bitmap);
861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    canvas.clipRegion(tmpRgn);
871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    canvas.drawColor(SK_ColorBLACK);
881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkIRect rand_rect(SkRandom& rand, int n) {
911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int x = rand.nextS() % n;
921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int y = rand.nextS() % n;
931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int w = rand.nextU() % n;
941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int h = rand.nextU() % n;
951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkIRect::MakeXYWH(x, y, w, h);
961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void make_rand_rgn(SkRegion* rgn, SkRandom& rand) {
991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int count = rand.nextU() % 20;
1001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < count; ++i) {
1011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        rgn->op(rand_rect(rand, 100), SkRegion::kXOR_Op);
1021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool operator==(const SkRegion& rgn, const SkAAClip& aaclip) {
1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMask mask0, mask1;
1071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    copyToMask(rgn, &mask0);
1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    aaclip.copyToMask(&mask1);
1101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool eq = (mask0 == mask1);
1111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMask::FreeImage(mask0.fImage);
1131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMask::FreeImage(mask1.fImage);
1141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return eq;
1151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool equalsAAClip(const SkRegion& rgn) {
1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAAClip aaclip;
1191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    aaclip.setRegion(rgn);
1201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return rgn == aaclip;
1211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void setRgnToPath(SkRegion* rgn, const SkPath& path) {
1241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkIRect ir;
1251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    path.getBounds().round(&ir);
1261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    rgn->setPath(path, SkRegion(ir));
1271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// aaclip.setRegion should create idential masks to the region
1301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void test_rgn(skiatest::Reporter* reporter) {
1311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRandom rand;
1321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 1000; i++) {
1331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkRegion rgn;
1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        make_rand_rgn(&rgn, rand);
1351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        REPORTER_ASSERT(reporter, equalsAAClip(rgn));
1361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    {
1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkRegion rgn;
1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkPath path;
1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        path.addCircle(0, 0, SkIntToScalar(30));
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        setRgnToPath(&rgn, path);
1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        REPORTER_ASSERT(reporter, equalsAAClip(rgn));
1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        path.reset();
1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        path.moveTo(0, 0);
1471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        path.lineTo(SkIntToScalar(100), 0);
1481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        path.lineTo(SkIntToScalar(100 - 20), SkIntToScalar(20));
1491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        path.lineTo(SkIntToScalar(20), SkIntToScalar(20));
1501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        setRgnToPath(&rgn, path);
1511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        REPORTER_ASSERT(reporter, equalsAAClip(rgn));
1521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const SkRegion::Op gRgnOps[] = {
1561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRegion::kDifference_Op,
1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRegion::kIntersect_Op,
1581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRegion::kUnion_Op,
1591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRegion::kXOR_Op,
1601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRegion::kReverseDifference_Op,
1611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRegion::kReplace_Op
1621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger};
1631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const char* gRgnOpNames[] = {
1651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    "DIFF", "INTERSECT", "UNION", "XOR", "REVERSE_DIFF", "REPLACE"
1661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger};
1671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void imoveTo(SkPath& path, int x, int y) {
1691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    path.moveTo(SkIntToScalar(x), SkIntToScalar(y));
1701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void icubicTo(SkPath& path, int x0, int y0, int x1, int y1, int x2, int y2) {
1731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    path.cubicTo(SkIntToScalar(x0), SkIntToScalar(y0),
1741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkIntToScalar(x1), SkIntToScalar(y1),
1751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkIntToScalar(x2), SkIntToScalar(y2));
1761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void test_path_bounds(skiatest::Reporter* reporter) {
1791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPath path;
1801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAAClip clip;
1811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int height = 40;
1821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const SkScalar sheight = SkIntToScalar(height);
1831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    path.addOval(SkRect::MakeWH(sheight, sheight));
1851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, sheight == path.getBounds().height());
1861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    clip.setPath(path, NULL, true);
1871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, height == clip.getBounds().height());
1881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // this is the trimmed height of this cubic (with aa). The critical thing
1901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // for this test is that it is less than height, which represents just
1911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // the bounds of the path's control-points.
1921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //
1931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // This used to fail until we tracked the MinY in the BuilderBlitter.
1941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //
1951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int teardrop_height = 12;
1961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    path.reset();
1971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    imoveTo(path, 0, 20);
1981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    icubicTo(path, 40, 40, 40, 0, 0, 20);
1991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, sheight == path.getBounds().height());
2001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    clip.setPath(path, NULL, true);
2011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, teardrop_height == clip.getBounds().height());
2021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void test_empty(skiatest::Reporter* reporter) {
2051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAAClip clip0, clip1;
2061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip0.isEmpty());
2081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip0.getBounds().isEmpty());
2091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip1 == clip0);
2101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    clip0.translate(10, 10);    // should have no effect on empty
2121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip0.isEmpty());
2131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip0.getBounds().isEmpty());
2141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip1 == clip0);
2151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkIRect r = { 10, 10, 40, 50 };
2171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    clip0.setRect(r);
2181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, !clip0.isEmpty());
2191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, !clip0.getBounds().isEmpty());
2201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip0 != clip1);
2211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip0.getBounds() == r);
2221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    clip0.setEmpty();
2241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip0.isEmpty());
2251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip0.getBounds().isEmpty());
2261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, clip1 == clip0);
2271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMask mask;
2291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    mask.fImage = NULL;
2301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    clip0.copyToMask(&mask);
2311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, NULL == mask.fImage);
2321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    REPORTER_ASSERT(reporter, mask.fBounds.isEmpty());
2331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void rand_irect(SkIRect* r, int N, SkRandom& rand) {
2361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    r->setXYWH(0, 0, rand.nextU() % N, rand.nextU() % N);
2371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int dx = rand.nextU() % (2*N);
2381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int dy = rand.nextU() % (2*N);
2391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // use int dx,dy to make the subtract be signed
2401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    r->offset(N - dx, N - dy);
2411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void test_irect(skiatest::Reporter* reporter) {
2441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRandom rand;
2451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < 10000; i++) {
2471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkAAClip clip0, clip1;
2481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkRegion rgn0, rgn1;
2491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkIRect r0, r1;
2501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        rand_irect(&r0, 10, rand);
2521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        rand_irect(&r1, 10, rand);
2531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        clip0.setRect(r0);
2541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        clip1.setRect(r1);
2551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        rgn0.setRect(r0);
2561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        rgn1.setRect(r1);
2571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (size_t j = 0; j < SK_ARRAY_COUNT(gRgnOps); ++j) {
2581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkRegion::Op op = gRgnOps[j];
2591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkAAClip clip2;
2601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkRegion rgn2;
2611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            bool nonEmptyAA = clip2.op(clip0, clip1, op);
2621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            bool nonEmptyBW = rgn2.op(rgn0, rgn1, op);
2631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (nonEmptyAA != nonEmptyBW || clip2.getBounds() != rgn2.getBounds()) {
2641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkDebugf("[%d %d %d %d] %s [%d %d %d %d] = BW:[%d %d %d %d] AA:[%d %d %d %d]\n",
2651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         r0.fLeft, r0.fTop, r0.right(), r0.bottom(),
2661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         gRgnOpNames[j],
2671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         r1.fLeft, r1.fTop, r1.right(), r1.bottom(),
2681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         rgn2.getBounds().fLeft, rgn2.getBounds().fTop,
2691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         rgn2.getBounds().right(), rgn2.getBounds().bottom(),
2701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         clip2.getBounds().fLeft, clip2.getBounds().fTop,
2711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         clip2.getBounds().right(), clip2.getBounds().bottom());
2721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
2731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            REPORTER_ASSERT(reporter, nonEmptyAA == nonEmptyBW);
2741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            REPORTER_ASSERT(reporter, clip2.getBounds() == rgn2.getBounds());
2754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkMask maskBW, maskAA;
2774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            copyToMask(rgn2, &maskBW);
2784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            clip2.copyToMask(&maskAA);
2794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            REPORTER_ASSERT(reporter, maskBW == maskAA);
2801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
2811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic void test_path_with_hole(skiatest::Reporter* reporter) {
2854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    static const uint8_t gExpectedImage[] = {
2864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        0xFF, 0xFF, 0xFF, 0xFF,
2874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        0xFF, 0xFF, 0xFF, 0xFF,
2884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        0x00, 0x00, 0x00, 0x00,
2894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        0x00, 0x00, 0x00, 0x00,
2904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        0xFF, 0xFF, 0xFF, 0xFF,
2914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        0xFF, 0xFF, 0xFF, 0xFF,
2924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    };
2934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkMask expected;
2944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    expected.fBounds.set(0, 0, 4, 6);
2954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    expected.fRowBytes = 4;
2964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    expected.fFormat = SkMask::kA8_Format;
2974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    expected.fImage = (uint8_t*)gExpectedImage;
2984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkPath path;
3004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    path.addRect(SkRect::MakeXYWH(0, 0,
3014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  SkIntToScalar(4), SkIntToScalar(2)));
3024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    path.addRect(SkRect::MakeXYWH(0, SkIntToScalar(4),
3034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  SkIntToScalar(4), SkIntToScalar(2)));
3044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    for (int i = 0; i < 2; ++i) {
3064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkAAClip clip;
3074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        clip.setPath(path, NULL, 1 == i);
3084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkMask mask;
3104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        clip.copyToMask(&mask);
3114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        REPORTER_ASSERT(reporter, expected == mask);
3134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
3144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic void test_regressions(skiatest::Reporter* reporter) {
3174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // these should not assert in the debug build
3184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // bug was introduced in rev. 3209
3194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    {
3204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkAAClip clip;
3214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkRect r;
3224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        r.fLeft = SkFloatToScalar(129.892181);
3234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        r.fTop = SkFloatToScalar(10.3999996);
3244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        r.fRight = SkFloatToScalar(130.892181);
3254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        r.fBottom = SkFloatToScalar(20.3999996);
3264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        clip.setRect(r, true);
3274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
3284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void TestAAClip(skiatest::Reporter* reporter) {
3311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_empty(reporter);
3321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_path_bounds(reporter);
3331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_irect(reporter);
3341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    test_rgn(reporter);
3354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    test_path_with_hole(reporter);
3364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    test_regressions(reporter);
3371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "TestClassDef.h"
3401cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerDEFINE_TESTCLASS("AAClip", AAClipTestClass, TestAAClip)
341