diff --git a/src/third_party/skia/tests/AAClipTest.cpp b/src/third_party/skia/tests/AAClipTest.cpp
new file mode 100644
index 0000000..64e3784
--- /dev/null
+++ b/src/third_party/skia/tests/AAClipTest.cpp
@@ -0,0 +1,433 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkAAClip.h"
+#include "SkCanvas.h"
+#include "SkMask.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "Test.h"
+
+static bool operator==(const SkMask& a, const SkMask& b) {
+    if (a.fFormat != b.fFormat || a.fBounds != b.fBounds) {
+        return false;
+    }
+    if (!a.fImage && !b.fImage) {
+        return true;
+    }
+    if (!a.fImage || !b.fImage) {
+        return false;
+    }
+
+    size_t wbytes = a.fBounds.width();
+    switch (a.fFormat) {
+        case SkMask::kBW_Format:
+            wbytes = (wbytes + 7) >> 3;
+            break;
+        case SkMask::kA8_Format:
+        case SkMask::k3D_Format:
+            break;
+        case SkMask::kLCD16_Format:
+            wbytes <<= 1;
+            break;
+        case SkMask::kLCD32_Format:
+        case SkMask::kARGB32_Format:
+            wbytes <<= 2;
+            break;
+        default:
+            SkDEBUGFAIL("unknown mask format");
+            return false;
+    }
+
+    const int h = a.fBounds.height();
+    const char* aptr = (const char*)a.fImage;
+    const char* bptr = (const char*)b.fImage;
+    for (int y = 0; y < h; ++y) {
+        if (memcmp(aptr, bptr, wbytes)) {
+            return false;
+        }
+        aptr += wbytes;
+        bptr += wbytes;
+    }
+    return true;
+}
+
+static void copyToMask(const SkRegion& rgn, SkMask* mask) {
+    mask->fFormat = SkMask::kA8_Format;
+
+    if (rgn.isEmpty()) {
+        mask->fBounds.setEmpty();
+        mask->fRowBytes = 0;
+        mask->fImage = NULL;
+        return;
+    }
+
+    mask->fBounds = rgn.getBounds();
+    mask->fRowBytes = mask->fBounds.width();
+    mask->fImage = SkMask::AllocImage(mask->computeImageSize());
+    sk_bzero(mask->fImage, mask->computeImageSize());
+
+    SkImageInfo info = SkImageInfo::Make(mask->fBounds.width(),
+                                         mask->fBounds.height(),
+                                         kAlpha_8_SkColorType,
+                                         kPremul_SkAlphaType);
+    SkBitmap bitmap;
+    bitmap.installPixels(info, mask->fImage, mask->fRowBytes);
+
+    // canvas expects its coordinate system to always be 0,0 in the top/left
+    // so we translate the rgn to match that before drawing into the mask.
+    //
+    SkRegion tmpRgn(rgn);
+    tmpRgn.translate(-rgn.getBounds().fLeft, -rgn.getBounds().fTop);
+
+    SkCanvas canvas(bitmap);
+    canvas.clipRegion(tmpRgn);
+    canvas.drawColor(SK_ColorBLACK);
+}
+
+static SkIRect rand_rect(SkRandom& rand, int n) {
+    int x = rand.nextS() % n;
+    int y = rand.nextS() % n;
+    int w = rand.nextU() % n;
+    int h = rand.nextU() % n;
+    return SkIRect::MakeXYWH(x, y, w, h);
+}
+
+static void make_rand_rgn(SkRegion* rgn, SkRandom& rand) {
+    int count = rand.nextU() % 20;
+    for (int i = 0; i < count; ++i) {
+        rgn->op(rand_rect(rand, 100), SkRegion::kXOR_Op);
+    }
+}
+
+static bool operator==(const SkRegion& rgn, const SkAAClip& aaclip) {
+    SkMask mask0, mask1;
+
+    copyToMask(rgn, &mask0);
+    aaclip.copyToMask(&mask1);
+    bool eq = (mask0 == mask1);
+
+    SkMask::FreeImage(mask0.fImage);
+    SkMask::FreeImage(mask1.fImage);
+    return eq;
+}
+
+static bool equalsAAClip(const SkRegion& rgn) {
+    SkAAClip aaclip;
+    aaclip.setRegion(rgn);
+    return rgn == aaclip;
+}
+
+static void setRgnToPath(SkRegion* rgn, const SkPath& path) {
+    SkIRect ir;
+    path.getBounds().round(&ir);
+    rgn->setPath(path, SkRegion(ir));
+}
+
+// aaclip.setRegion should create idential masks to the region
+static void test_rgn(skiatest::Reporter* reporter) {
+    SkRandom rand;
+    for (int i = 0; i < 1000; i++) {
+        SkRegion rgn;
+        make_rand_rgn(&rgn, rand);
+        REPORTER_ASSERT(reporter, equalsAAClip(rgn));
+    }
+
+    {
+        SkRegion rgn;
+        SkPath path;
+        path.addCircle(0, 0, SkIntToScalar(30));
+        setRgnToPath(&rgn, path);
+        REPORTER_ASSERT(reporter, equalsAAClip(rgn));
+
+        path.reset();
+        path.moveTo(0, 0);
+        path.lineTo(SkIntToScalar(100), 0);
+        path.lineTo(SkIntToScalar(100 - 20), SkIntToScalar(20));
+        path.lineTo(SkIntToScalar(20), SkIntToScalar(20));
+        setRgnToPath(&rgn, path);
+        REPORTER_ASSERT(reporter, equalsAAClip(rgn));
+    }
+}
+
+static const SkRegion::Op gRgnOps[] = {
+    SkRegion::kDifference_Op,
+    SkRegion::kIntersect_Op,
+    SkRegion::kUnion_Op,
+    SkRegion::kXOR_Op,
+    SkRegion::kReverseDifference_Op,
+    SkRegion::kReplace_Op
+};
+
+static const char* gRgnOpNames[] = {
+    "DIFF", "INTERSECT", "UNION", "XOR", "REVERSE_DIFF", "REPLACE"
+};
+
+static void imoveTo(SkPath& path, int x, int y) {
+    path.moveTo(SkIntToScalar(x), SkIntToScalar(y));
+}
+
+static void icubicTo(SkPath& path, int x0, int y0, int x1, int y1, int x2, int y2) {
+    path.cubicTo(SkIntToScalar(x0), SkIntToScalar(y0),
+                 SkIntToScalar(x1), SkIntToScalar(y1),
+                 SkIntToScalar(x2), SkIntToScalar(y2));
+}
+
+static void test_path_bounds(skiatest::Reporter* reporter) {
+    SkPath path;
+    SkAAClip clip;
+    const int height = 40;
+    const SkScalar sheight = SkIntToScalar(height);
+
+    path.addOval(SkRect::MakeWH(sheight, sheight));
+    REPORTER_ASSERT(reporter, sheight == path.getBounds().height());
+    clip.setPath(path, NULL, true);
+    REPORTER_ASSERT(reporter, height == clip.getBounds().height());
+
+    // this is the trimmed height of this cubic (with aa). The critical thing
+    // for this test is that it is less than height, which represents just
+    // the bounds of the path's control-points.
+    //
+    // This used to fail until we tracked the MinY in the BuilderBlitter.
+    //
+    const int teardrop_height = 12;
+    path.reset();
+    imoveTo(path, 0, 20);
+    icubicTo(path, 40, 40, 40, 0, 0, 20);
+    REPORTER_ASSERT(reporter, sheight == path.getBounds().height());
+    clip.setPath(path, NULL, true);
+    REPORTER_ASSERT(reporter, teardrop_height == clip.getBounds().height());
+}
+
+static void test_empty(skiatest::Reporter* reporter) {
+    SkAAClip clip0, clip1;
+
+    REPORTER_ASSERT(reporter, clip0.isEmpty());
+    REPORTER_ASSERT(reporter, clip0.getBounds().isEmpty());
+    REPORTER_ASSERT(reporter, clip1 == clip0);
+
+    clip0.translate(10, 10);    // should have no effect on empty
+    REPORTER_ASSERT(reporter, clip0.isEmpty());
+    REPORTER_ASSERT(reporter, clip0.getBounds().isEmpty());
+    REPORTER_ASSERT(reporter, clip1 == clip0);
+
+    SkIRect r = { 10, 10, 40, 50 };
+    clip0.setRect(r);
+    REPORTER_ASSERT(reporter, !clip0.isEmpty());
+    REPORTER_ASSERT(reporter, !clip0.getBounds().isEmpty());
+    REPORTER_ASSERT(reporter, clip0 != clip1);
+    REPORTER_ASSERT(reporter, clip0.getBounds() == r);
+
+    clip0.setEmpty();
+    REPORTER_ASSERT(reporter, clip0.isEmpty());
+    REPORTER_ASSERT(reporter, clip0.getBounds().isEmpty());
+    REPORTER_ASSERT(reporter, clip1 == clip0);
+
+    SkMask mask;
+    mask.fImage = NULL;
+    clip0.copyToMask(&mask);
+    REPORTER_ASSERT(reporter, NULL == mask.fImage);
+    REPORTER_ASSERT(reporter, mask.fBounds.isEmpty());
+}
+
+static void rand_irect(SkIRect* r, int N, SkRandom& rand) {
+    r->setXYWH(0, 0, rand.nextU() % N, rand.nextU() % N);
+    int dx = rand.nextU() % (2*N);
+    int dy = rand.nextU() % (2*N);
+    // use int dx,dy to make the subtract be signed
+    r->offset(N - dx, N - dy);
+}
+
+static void test_irect(skiatest::Reporter* reporter) {
+    SkRandom rand;
+
+    for (int i = 0; i < 10000; i++) {
+        SkAAClip clip0, clip1;
+        SkRegion rgn0, rgn1;
+        SkIRect r0, r1;
+
+        rand_irect(&r0, 10, rand);
+        rand_irect(&r1, 10, rand);
+        clip0.setRect(r0);
+        clip1.setRect(r1);
+        rgn0.setRect(r0);
+        rgn1.setRect(r1);
+        for (size_t j = 0; j < SK_ARRAY_COUNT(gRgnOps); ++j) {
+            SkRegion::Op op = gRgnOps[j];
+            SkAAClip clip2;
+            SkRegion rgn2;
+            bool nonEmptyAA = clip2.op(clip0, clip1, op);
+            bool nonEmptyBW = rgn2.op(rgn0, rgn1, op);
+            if (nonEmptyAA != nonEmptyBW || clip2.getBounds() != rgn2.getBounds()) {
+                SkDebugf("[%d %d %d %d] %s [%d %d %d %d] = BW:[%d %d %d %d] AA:[%d %d %d %d]\n",
+                         r0.fLeft, r0.fTop, r0.right(), r0.bottom(),
+                         gRgnOpNames[j],
+                         r1.fLeft, r1.fTop, r1.right(), r1.bottom(),
+                         rgn2.getBounds().fLeft, rgn2.getBounds().fTop,
+                         rgn2.getBounds().right(), rgn2.getBounds().bottom(),
+                         clip2.getBounds().fLeft, clip2.getBounds().fTop,
+                         clip2.getBounds().right(), clip2.getBounds().bottom());
+            }
+            REPORTER_ASSERT(reporter, nonEmptyAA == nonEmptyBW);
+            REPORTER_ASSERT(reporter, clip2.getBounds() == rgn2.getBounds());
+
+            SkMask maskBW, maskAA;
+            copyToMask(rgn2, &maskBW);
+            clip2.copyToMask(&maskAA);
+            SkAutoMaskFreeImage freeBW(maskBW.fImage);
+            SkAutoMaskFreeImage freeAA(maskAA.fImage);
+            REPORTER_ASSERT(reporter, maskBW == maskAA);
+        }
+    }
+}
+
+static void test_path_with_hole(skiatest::Reporter* reporter) {
+    static const uint8_t gExpectedImage[] = {
+        0xFF, 0xFF, 0xFF, 0xFF,
+        0xFF, 0xFF, 0xFF, 0xFF,
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+        0xFF, 0xFF, 0xFF, 0xFF,
+        0xFF, 0xFF, 0xFF, 0xFF,
+    };
+    SkMask expected;
+    expected.fBounds.set(0, 0, 4, 6);
+    expected.fRowBytes = 4;
+    expected.fFormat = SkMask::kA8_Format;
+    expected.fImage = (uint8_t*)gExpectedImage;
+
+    SkPath path;
+    path.addRect(SkRect::MakeXYWH(0, 0,
+                                  SkIntToScalar(4), SkIntToScalar(2)));
+    path.addRect(SkRect::MakeXYWH(0, SkIntToScalar(4),
+                                  SkIntToScalar(4), SkIntToScalar(2)));
+
+    for (int i = 0; i < 2; ++i) {
+        SkAAClip clip;
+        clip.setPath(path, NULL, 1 == i);
+
+        SkMask mask;
+        clip.copyToMask(&mask);
+        SkAutoMaskFreeImage freeM(mask.fImage);
+
+        REPORTER_ASSERT(reporter, expected == mask);
+    }
+}
+
+static void test_really_a_rect(skiatest::Reporter* reporter) {
+    SkRRect rrect;
+    rrect.setRectXY(SkRect::MakeWH(100, 100), 5, 5);
+
+    SkPath path;
+    path.addRRect(rrect);
+
+    SkAAClip clip;
+    clip.setPath(path);
+
+    REPORTER_ASSERT(reporter, clip.getBounds() == SkIRect::MakeWH(100, 100));
+    REPORTER_ASSERT(reporter, !clip.isRect());
+
+    // This rect should intersect the clip, but slice-out all of the "soft" parts,
+    // leaving just a rect.
+    const SkIRect ir = SkIRect::MakeLTRB(10, -10, 50, 90);
+    
+    clip.op(ir, SkRegion::kIntersect_Op);
+
+    REPORTER_ASSERT(reporter, clip.getBounds() == SkIRect::MakeLTRB(10, 0, 50, 90));
+    // the clip recognized that that it is just a rect!
+    REPORTER_ASSERT(reporter, clip.isRect());
+}
+
+#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);
+    SkAutoMaskFreeImage aCleanUp(ma.fImage);
+    SkAutoMaskFreeImage bCleanUp(mb.fImage);
+
+    return ma == mb;
+}
+
+static void did_dx_affect(skiatest::Reporter* reporter, const SkScalar dx[],
+                          size_t count, bool changed) {
+    const SkISize baseSize = SkISize::Make(10, 10);
+    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, baseSize, SkRegion::kIntersect_Op, false);
+        r.offset(dx[i], 0);
+        rc1.op(r, baseSize, SkRegion::kIntersect_Op, true);
+        r.offset(-2*dx[i], 0);
+        rc2.op(r, baseSize, 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() {
+    // these should not assert in the debug build
+    // bug was introduced in rev. 3209
+    {
+        SkAAClip clip;
+        SkRect r;
+        r.fLeft = 129.892181f;
+        r.fTop = 10.3999996f;
+        r.fRight = 130.892181f;
+        r.fBottom = 20.3999996f;
+        clip.setRect(r, true);
+    }
+}
+
+DEF_TEST(AAClip, reporter) {
+    test_empty(reporter);
+    test_path_bounds(reporter);
+    test_irect(reporter);
+    test_rgn(reporter);
+    test_path_with_hole(reporter);
+    test_regressions();
+    test_nearly_integral(reporter);
+    test_really_a_rect(reporter);
+}
