예제 #1
0
static void test_cache(skiatest::Reporter* reporter, SkScaledImageCache& cache,
                       bool testPurge) {
    SkScaledImageCache::ID* id;

    SkBitmap bm[COUNT];

    const SkScalar scale = 2;
    for (int i = 0; i < COUNT; ++i) {
        make_bm(&bm[i], DIM, DIM);
    }

    for (int i = 0; i < COUNT; ++i) {
        SkBitmap tmp;

        SkScaledImageCache::ID* id = cache.findAndLock(bm[i], scale, scale, &tmp);
        REPORTER_ASSERT(reporter, NULL == id);

        make_bm(&tmp, DIM, DIM);
        id = cache.addAndLock(bm[i], scale, scale, tmp);
        REPORTER_ASSERT(reporter, NULL != id);

        SkBitmap tmp2;
        SkScaledImageCache::ID* id2 = cache.findAndLock(bm[i], scale, scale,
                                                        &tmp2);
        REPORTER_ASSERT(reporter, id == id2);
        REPORTER_ASSERT(reporter, tmp.pixelRef() == tmp2.pixelRef());
        REPORTER_ASSERT(reporter, tmp.width() == tmp2.width());
        REPORTER_ASSERT(reporter, tmp.height() == tmp2.height());
        cache.unlock(id2);

        cache.unlock(id);
    }

    if (testPurge) {
        // stress test, should trigger purges
        float incScale = 2;
        for (size_t i = 0; i < COUNT * 100; ++i) {
            incScale += 1;

            SkBitmap tmp;
            make_bm(&tmp, DIM, DIM);

            SkScaledImageCache::ID* id = cache.addAndLock(bm[0], incScale,
                                                          incScale, tmp);
            REPORTER_ASSERT(reporter, NULL != id);
            cache.unlock(id);
        }
    }

    // test the originals after all that purging
    for (int i = 0; i < COUNT; ++i) {
        SkBitmap tmp;
        id = cache.findAndLock(bm[i], scale, scale, &tmp);
        if (id) {
            cache.unlock(id);
        }
    }

    cache.setByteLimit(0);
}
예제 #2
0
    DitherView() {
        make_bm(&fBM);
        make_bm(&fBMPreDither);
        pre_dither(fBMPreDither);
        fBM.copyTo(&fBM16, kARGB_4444_SkColorType);

        fAngle = 0;

        this->setBGColor(0xFF181818);
    }
예제 #3
0
	DitherView() {
        make_bm(&fBM);
        make_bm(&fBMPreDither);
        pre_dither(fBMPreDither);
        fBM.copyTo(&fBM16, SkBitmap::kARGB_4444_Config);
        
        fAngle = 0;
        
        this->setBGColor(0xFF181818);
    }
예제 #4
0
static void test_bitmap_with_encoded_data(skiatest::Reporter* reporter) {
    // Create a bitmap that will be encoded.
    SkBitmap original;
    make_bm(&original, 100, 100, SK_ColorBLUE, true);
    SkDynamicMemoryWStream wStream;
    if (!SkImageEncoder::EncodeStream(&wStream, original, SkImageEncoder::kPNG_Type, 100)) {
        return;
    }
    SkAutoDataUnref data(wStream.copyToData());

    SkBitmap bm;
    bool installSuccess = SkDecodingImageGenerator::Install(data, &bm);
    REPORTER_ASSERT(reporter, installSuccess);

    // Write both bitmaps to pictures, and ensure that the resulting data streams are the same.
    // Flattening original will follow the old path of performing an encode, while flattening bm
    // will use the already encoded data.
    SkAutoDataUnref picture1(serialized_picture_from_bitmap(original));
    SkAutoDataUnref picture2(serialized_picture_from_bitmap(bm));
    REPORTER_ASSERT(reporter, picture1->equals(picture2));
    // Now test that a parse error was generated when trying to create a new SkPicture without
    // providing a function to decode the bitmap.
    ErrorContext context;
    context.fErrors = 0;
    context.fReporter = reporter;
    SkSetErrorCallback(assert_one_parse_error_cb, &context);
    SkMemoryStream pictureStream(picture1);
    SkClearLastError();
    SkAutoUnref pictureFromStream(SkPicture::CreateFromStream(&pictureStream, NULL));
    REPORTER_ASSERT(reporter, pictureFromStream.get() != NULL);
    SkClearLastError();
    SkSetErrorCallback(NULL, NULL);
}
static void show_bm(SkCanvas* canvas, int width, int height, SkColor color) {
    SkBitmap bm;
    make_bm(&bm, width, height, color);

    SkPaint paint;
    SkRect r;
    SkIRect ir;

    paint.setStyle(SkPaint::kStroke_Style);

    ir.set(0, 0, 128, 128);
    r.set(ir);

    canvas->save();
    canvas->clipRect(r);
    canvas->drawBitmap(bm, 0, 0, NULL);
    canvas->restore();
    canvas->drawRect(r, paint);

    r.offset(SkIntToScalar(150), 0);
    // exercises extract bitmap, but not shader
    canvas->drawBitmapRect(bm, &ir, r, NULL);
    canvas->drawRect(r, paint);

    r.offset(SkIntToScalar(150), 0);
    // exercises bitmapshader
    canvas->drawBitmapRect(bm, NULL, r, NULL);
    canvas->drawRect(r, paint);
}
    void onOnceBeforeDraw() override {
        for (size_t i = 0; i < SK_ARRAY_COUNT(fTallBmps); ++i) {
            int h = SkToInt((4 + i) * 1024);

            fTallBmps[i].fItemCnt = make_bm(&fTallBmps[i].fBmp, h);
        }
    }
예제 #7
0
파일: PictureTest.cpp 프로젝트: zwdsjl/skia
DEF_TEST(DontOptimizeSaveLayerDrawDrawRestore, reporter) {
    // This test is from crbug.com/344987.
    // The commands are:
    //   saveLayer with paint that modifies alpha
    //     drawBitmapRect
    //     drawBitmapRect
    //   restore
    // The bug was that this structure was modified so that:
    //  - The saveLayer and restore were eliminated
    //  - The alpha was only applied to the first drawBitmapRectToRect

    // This test draws blue and red squares inside a 50% transparent
    // layer.  Both colours should show up muted.
    // When the bug is present, the red square (the second bitmap)
    // shows upwith full opacity.

    SkBitmap blueBM;
    make_bm(&blueBM, 100, 100, SkColorSetARGB(255, 0, 0, 255), true);
    SkBitmap redBM;
    make_bm(&redBM, 100, 100, SkColorSetARGB(255, 255, 0, 0), true);
    SkPaint semiTransparent;
    semiTransparent.setAlpha(0x80);

    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(100, 100);
    canvas->drawARGB(0, 0, 0, 0);

    canvas->saveLayer(0, &semiTransparent);
    canvas->drawBitmap(blueBM, 25, 25);
    canvas->drawBitmap(redBM, 50, 50);
    canvas->restore();

    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());

    // Now replay the picture back on another canvas
    // and check a couple of its pixels.
    SkBitmap replayBM;
    make_bm(&replayBM, 100, 100, SK_ColorBLACK, false);
    SkCanvas replayCanvas(replayBM);
    picture->playback(&replayCanvas);
    replayCanvas.flush();

    // With the bug present, at (55, 55) we would get a fully opaque red
    // intead of a dark red.
    REPORTER_ASSERT(reporter, replayBM.getColor(30, 30) == 0xff000080);
    REPORTER_ASSERT(reporter, replayBM.getColor(55, 55) == 0xff800000);
}
예제 #8
0
    FilterView() {
        make_bm(&fBM8);
        fBM8.copyTo(&fBM4444, kARGB_4444_SkColorType);
        fBM8.copyTo(&fBM16, kRGB_565_SkColorType);
        fBM8.copyTo(&fBM32, kN32_SkColorType);

        this->setBGColor(0xFFDDDDDD);
    }
예제 #9
0
	FilterView() {
        make_bm(&fBM8);
        fBM8.copyTo(&fBM4444, SkBitmap::kARGB_4444_Config);
        fBM8.copyTo(&fBM16, SkBitmap::kRGB_565_Config);
        fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config);
        
        this->setBGColor(0xFFDDDDDD);
    }
예제 #10
0
 void init() {
     if (fOnce) {
         return;
     }
     fOnce = true;
     make_bm(&fBM8);
     fBM8.copyTo(&fBM4444, SkBitmap::kARGB_4444_Config);
     fBM8.copyTo(&fBM16, SkBitmap::kRGB_565_Config);
     fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config);
 }
예제 #11
0
 void init() {
     if (fOnce) {
         return;
     }
     fOnce = true;
     make_bm(&fBM8);
     fBM8.copyTo(&fBM4444, kARGB_4444_SkColorType);
     fBM8.copyTo(&fBM16, kRGB_565_SkColorType);
     fBM8.copyTo(&fBM32, kN32_SkColorType);
 }
예제 #12
0
// Allocate result to be large enough to hold subset, and then draw the picture
// into it, offsetting by subset's top/left corner.
static void draw(SkPicture* pic, const SkRect& subset, SkBitmap* result) {
    SkIRect ir;
    subset.roundOut(&ir);
    int w = ir.width();
    int h = ir.height();
    make_bm(result, w, h, 0, false);

    SkCanvas canvas(*result);
    canvas.translate(-SkIntToScalar(ir.left()), -SkIntToScalar(ir.top()));
    canvas.drawPicture(*pic);
}
	FilterView() {
        /*做一张bitmap, kIndex8_Config格式的2行2列
          依次转换成 其他3种格式的bitmap : 见结果图, 对应4行.*/
        make_bm(&fBM8);
        fBM8.copyTo(&fBM4444, SkBitmap::kARGB_4444_Config);
        fBM8.copyTo(&fBM16, SkBitmap::kRGB_565_Config);
        fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config);
        
        //设置背景色 为 灰色 : 见结果图
        this->setBGColor(0xFFDDDDDD);
    }
예제 #14
0
파일: arithmode.cpp 프로젝트: bunhere/skia
static SkBitmap make_arith(const SkBitmap& src, const SkBitmap& dst,
                           const SkScalar k[]) {
    SkBitmap bm = make_bm();
    SkCanvas canvas(bm);
    SkPaint paint;
    canvas.drawBitmap(dst, 0, 0, NULL);
    SkXfermode* xfer = SkArithmeticMode::Create(k[0], k[1], k[2], k[3]);
    paint.setXfermode(xfer)->unref();
    canvas.drawBitmap(src, 0, 0, &paint);
    return bm;
}
예제 #15
0
파일: PictureTest.cpp 프로젝트: zwdsjl/skia
DEF_TEST(Picture_EncodedData, reporter) {
    // Create a bitmap that will be encoded.
    SkBitmap original;
    make_bm(&original, 100, 100, SK_ColorBLUE, true);
    SkDynamicMemoryWStream wStream;
    if (!SkImageEncoder::EncodeStream(&wStream, original, SkImageEncoder::kPNG_Type, 100)) {
        return;
    }
    SkAutoDataUnref data(wStream.copyToData());

    SkBitmap bm;
    bool installSuccess = SkDEPRECATED_InstallDiscardablePixelRef(data, &bm);
    REPORTER_ASSERT(reporter, installSuccess);

    // Write both bitmaps to pictures, and ensure that the resulting data streams are the same.
    // Flattening original will follow the old path of performing an encode, while flattening bm
    // will use the already encoded data.
    SkAutoDataUnref picture1(serialized_picture_from_bitmap(original));
    SkAutoDataUnref picture2(serialized_picture_from_bitmap(bm));
    REPORTER_ASSERT(reporter, picture1->equals(picture2));

    // Now test that a parse error was generated when trying to create a new SkPicture without
    // providing a function to decode the bitmap.
    ErrorContext context;
    context.fErrors = 0;
    context.fReporter = reporter;
    SkSetErrorCallback(assert_one_parse_error_cb, &context);
    SkMemoryStream pictureStream(picture1);
    SkClearLastError();
    sk_sp<SkPicture> pictureFromStream(SkPicture::MakeFromStream(&pictureStream, nullptr));
    REPORTER_ASSERT(reporter, pictureFromStream.get() != nullptr);
    SkClearLastError();
    SkSetErrorCallback(nullptr, nullptr);

    // Test that using the version of CreateFromStream that just takes a stream also decodes the
    // bitmap. Drawing this picture should look exactly like the original bitmap.
    SkMD5::Digest referenceDigest;
    md5(original, &referenceDigest);

    SkBitmap dst;
    dst.allocPixels(original.info());
    dst.eraseColor(SK_ColorRED);
    SkCanvas canvas(dst);

    pictureStream.rewind();
    pictureFromStream = SkPicture::MakeFromStream(&pictureStream);
    canvas.drawPicture(pictureFromStream.get());

    SkMD5::Digest digest2;
    md5(dst, &digest2);
    REPORTER_ASSERT(reporter, referenceDigest == digest2);
}
예제 #16
0
static SkBitmap make_dst() {
    SkBitmap bm = make_bm();
    SkCanvas canvas(bm);
    SkPaint paint;
    SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} };
    SkColor colors[] = {
        SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN,
        sk_tool_utils::color_to_565(SK_ColorGRAY)
    };
    paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
                                                 SkShader::kClamp_TileMode));
    canvas.drawPaint(paint);
    return bm;
}
예제 #17
0
static SkBitmap make_src() {
    SkBitmap bm = make_bm();
    SkCanvas canvas(bm);
    SkPaint paint;
    SkPoint pts[] = { {0, 0}, {SkIntToScalar(WW), SkIntToScalar(HH)} };
    SkColor colors[] = {
        SK_ColorTRANSPARENT, SK_ColorGREEN, SK_ColorCYAN,
        SK_ColorRED, SK_ColorMAGENTA, SK_ColorWHITE,
    };
    paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
                                                 SkShader::kClamp_TileMode));
    canvas.drawPaint(paint);
    return bm;
}
예제 #18
0
파일: arithmode.cpp 프로젝트: bunhere/skia
static SkBitmap make_dst() {
    SkBitmap bm = make_bm();
    SkCanvas canvas(bm);
    SkPaint paint;
    SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} };
    SkColor colors[] = {
        SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN, SK_ColorGRAY
    };
    SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors),
                                                 SkShader::kClamp_TileMode);
    paint.setShader(s)->unref();
    canvas.drawPaint(paint);
    return bm;
}
예제 #19
0
// This creates a close, but imperfect concatenation of
//      scaling the image up by its dst-rect
//      scaling the image down by the matrix' scale
//  The bug was that for cases like this, we were incorrectly trying to take a
//  fast-path in the bitmapshader, but ended up drawing the last col of pixels
//  twice. The fix resulted in (a) not taking the fast-path, but (b) drawing
//  the image correctly.
//
static void test_bitmaprect(SkCanvas* canvas) {
    SkBitmap bm;
    make_bm(&bm);

    canvas->drawBitmap(bm, 150, 45, NULL);

    SkScalar scale = 0.472560018f;
    canvas->save();
    canvas->scale(scale, scale);
    canvas->drawBitmapRectToRect(bm, NULL, SkRect::MakeXYWH(100, 100, 128, 128), NULL);
    canvas->restore();

    canvas->scale(-1, 1);
    canvas->drawBitmap(bm, -310, 45, NULL);
}
예제 #20
0
파일: emboss.cpp 프로젝트: aseprite/skia
    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;
        SkBitmap bm = make_bm();
        canvas->drawBitmap(bm, 10, 10, &paint);

        const SkScalar dir[] = { 1, 1, 1 };
        paint.setMaskFilter(SkBlurMaskFilter::MakeEmboss(3, dir, 0.3f, 0.1f));
        canvas->translate(bm.width() + SkIntToScalar(10), 0);
        canvas->drawBitmap(bm, 10, 10, &paint);

        // this combination of emboss+colorfilter used to crash -- so we exercise it to
        // confirm that we have a fix.
        paint.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop));
        canvas->translate(bm.width() + SkIntToScalar(10), 0);
        canvas->drawBitmap(bm, 10, 10, &paint);
    }
예제 #21
0
    void onDraw(SkCanvas* canvas) override {
        SkBitmap bm;
        make_bm(&bm);

        int dx = 10;
        int dy = 10;

        SkScalar sigma = 8;
        SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(sigma, sigma));

        draw_2_bitmaps(canvas, bm, false, dx, dy);
        dy += bm.height() + 20;
        draw_2_bitmaps(canvas, bm, false, dx, dy, filter);
        dy += bm.height() + 20;
        draw_2_bitmaps(canvas, bm, true, dx, dy);
        dy += bm.height() + 20;
        draw_2_bitmaps(canvas, bm, true, dx, dy, filter);
    }
예제 #22
0
    void onDraw(SkCanvas* canvas) override {
        SkBitmap bm;
        make_bm(&bm);

        int dx = 10;
        int dy = 10;

        SkScalar sigma = 8;
        sk_sp<SkImageFilter> filter(SkBlurImageFilter::Make(sigma, sigma, nullptr));

        draw_1_bitmap(canvas, bm, false, dx, dy, nullptr);
        dy += bm.height() + 20;
        draw_1_bitmap(canvas, bm, false, dx, dy, filter);
        dy += bm.height() + 20;
        draw_1_bitmap(canvas, bm, true, dx, dy, nullptr);
        dy += bm.height() + 20;
        draw_1_bitmap(canvas, bm, true, dx, dy, filter);
    }
예제 #23
0
파일: PictureTest.cpp 프로젝트: zwdsjl/skia
static void test_hierarchical(skiatest::Reporter* reporter) {
    SkBitmap bm;
    make_bm(&bm, 10, 10, SK_ColorRED, true);

    SkPictureRecorder recorder;

    recorder.beginRecording(10, 10);
    sk_sp<SkPicture> childPlain(recorder.finishRecordingAsPicture());
    REPORTER_ASSERT(reporter, !childPlain->willPlayBackBitmaps()); // 0

    recorder.beginRecording(10, 10)->drawBitmap(bm, 0, 0);
    sk_sp<SkPicture> childWithBitmap(recorder.finishRecordingAsPicture());
    REPORTER_ASSERT(reporter, childWithBitmap->willPlayBackBitmaps()); // 1

    {
        SkCanvas* canvas = recorder.beginRecording(10, 10);
        canvas->drawPicture(childPlain);
        sk_sp<SkPicture> parentPP(recorder.finishRecordingAsPicture());
        REPORTER_ASSERT(reporter, !parentPP->willPlayBackBitmaps()); // 0
    }
    {
        SkCanvas* canvas = recorder.beginRecording(10, 10);
        canvas->drawPicture(childWithBitmap);
        sk_sp<SkPicture> parentPWB(recorder.finishRecordingAsPicture());
        REPORTER_ASSERT(reporter, parentPWB->willPlayBackBitmaps()); // 1
    }
    {
        SkCanvas* canvas = recorder.beginRecording(10, 10);
        canvas->drawBitmap(bm, 0, 0);
        canvas->drawPicture(childPlain);
        sk_sp<SkPicture> parentWBP(recorder.finishRecordingAsPicture());
        REPORTER_ASSERT(reporter, parentWBP->willPlayBackBitmaps()); // 1
    }
    {
        SkCanvas* canvas = recorder.beginRecording(10, 10);
        canvas->drawBitmap(bm, 0, 0);
        canvas->drawPicture(childWithBitmap);
        sk_sp<SkPicture> parentWBWB(recorder.finishRecordingAsPicture());
        REPORTER_ASSERT(reporter, parentWBWB->willPlayBackBitmaps()); // 2
    }
}
예제 #24
0
파일: PictureTest.cpp 프로젝트: zwdsjl/skia
// Test out SkPictureRecorder::partialReplay
DEF_TEST(PictureRecorder_replay, reporter) {
    // check save/saveLayer state
    {
        SkPictureRecorder recorder;

        SkCanvas* canvas = recorder.beginRecording(10, 10);

        canvas->saveLayer(nullptr, nullptr);

        sk_sp<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder));

        // The extra save and restore comes from the Copy process.
        check_save_state(reporter, copy.get(), 2, 1, 3);

        canvas->saveLayer(nullptr, nullptr);

        sk_sp<SkPicture> final(recorder.finishRecordingAsPicture());

        check_save_state(reporter, final.get(), 1, 2, 3);

        // The copy shouldn't pick up any operations added after it was made
        check_save_state(reporter, copy.get(), 2, 1, 3);
    }

    // (partially) check leakage of draw ops
    {
        SkPictureRecorder recorder;

        SkCanvas* canvas = recorder.beginRecording(10, 10);

        SkRect r = SkRect::MakeWH(5, 5);
        SkPaint p;

        canvas->drawRect(r, p);

        sk_sp<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder));

        REPORTER_ASSERT(reporter, !copy->willPlayBackBitmaps());

        SkBitmap bm;
        make_bm(&bm, 10, 10, SK_ColorRED, true);

        r.offset(5.0f, 5.0f);
        canvas->drawBitmapRect(bm, r, nullptr);

        sk_sp<SkPicture> final(recorder.finishRecordingAsPicture());
        REPORTER_ASSERT(reporter, final->willPlayBackBitmaps());

        REPORTER_ASSERT(reporter, copy->uniqueID() != final->uniqueID());

        // The snapshot shouldn't pick up any operations added after it was made
        REPORTER_ASSERT(reporter, !copy->willPlayBackBitmaps());
    }

    // Recreate the Android partialReplay test case
    {
        SkPictureRecorder recorder;

        SkCanvas* canvas = recorder.beginRecording(4, 3, nullptr, 0);
        create_imbalance(canvas);

        int expectedSaveCount = canvas->getSaveCount();

        sk_sp<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder));
        check_balance(reporter, copy.get());

        REPORTER_ASSERT(reporter, expectedSaveCount = canvas->getSaveCount());

        // End the recording of source to test the picture finalization
        // process isn't complicated by the partialReplay step
        sk_sp<SkPicture> final(recorder.finishRecordingAsPicture());
    }
}
예제 #25
0
 FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry)) {
 }
예제 #26
0
 void onOnceBeforeDraw() override {
     make_bm(&fBM32);
     ToolUtils::copy_to(&fBM4444, kARGB_4444_SkColorType, fBM32);
     ToolUtils::copy_to(&fBM16, kRGB_565_SkColorType, fBM32);
 }
예제 #27
0
 void onOnceBeforeDraw() override {
     make_bm(&fBM8);
     fBM8.copyTo(&fBM4444, kARGB_4444_SkColorType);
     fBM8.copyTo(&fBM16, kRGB_565_SkColorType);
     fBM8.copyTo(&fBM32, kN32_SkColorType);
 }
예제 #28
0
static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
    const int IW = 8;
    const int IH = IW;
    const SkScalar W = SkIntToScalar(IW);
    const SkScalar H = W;

    static const int N = 4;
    SkBitmap bm[N];
    SkPixelRef* refs[N];

    const SkPoint pos[] = {
        { 0, 0 }, { W, 0 }, { 0, H }, { W, H }
    };

    // Our convention is that the color components contain the index of their
    // corresponding bitmap/pixelref
    for (int i = 0; i < N; ++i) {
        make_bm(&bm[i], IW, IH, SkColorSetARGB(0xFF, i, i, i), true);
        refs[i] = bm[i].pixelRef();
    }

    static const DrawBitmapProc procs[] = {
        drawbitmap_proc, drawbitmaprect_proc, drawshader_proc
    };

    SkRandom rand;
    for (size_t k = 0; k < SK_ARRAY_COUNT(procs); ++k) {
        SkAutoTUnref<SkPicture> pic(record_bitmaps(bm, pos, N, procs[k]));

        REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0);
        // quick check for a small piece of each quadrant, which should just
        // contain 1 bitmap.
        for (size_t  i = 0; i < SK_ARRAY_COUNT(pos); ++i) {
            SkRect r;
            r.set(2, 2, W - 2, H - 2);
            r.offset(pos[i].fX, pos[i].fY);
            SkAutoDataUnref data(SkPictureUtils::GatherPixelRefs(pic, r));
            REPORTER_ASSERT(reporter, data);
            if (data) {
                int count = static_cast<int>(data->size() / sizeof(SkPixelRef*));
                REPORTER_ASSERT(reporter, 1 == count);
                REPORTER_ASSERT(reporter, *(SkPixelRef**)data->data() == refs[i]);
            }
        }

        // Test a bunch of random (mostly) rects, and compare the gather results
        // with a deduced list of refs by looking at the colors drawn.
        for (int j = 0; j < 100; ++j) {
            SkRect r;
            rand_rect(&r, rand, 2*W, 2*H);

            SkBitmap result;
            draw(pic, r, &result);
            SkTDArray<SkPixelRef*> array;

            SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
            size_t dataSize = data ? data->size() : 0;
            int gatherCount = static_cast<int>(dataSize / sizeof(SkPixelRef*));
            SkASSERT(gatherCount * sizeof(SkPixelRef*) == dataSize);
            SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL;
            SkAutoDataUnref adu(data);

            gather_from_colors(result, refs, N, &array);

            /*
             *  GatherPixelRefs is conservative, so it can return more bitmaps
             *  that we actually can see (usually because of conservative bounds
             *  inflation for antialiasing). Thus our check here is only that
             *  Gather didn't miss any that we actually saw. Even that isn't
             *  a strict requirement on Gather, which is meant to be quick and
             *  only mostly-correct, but at the moment this test should work.
             */
            for (int i = 0; i < array.count(); ++i) {
                bool found = find(gatherRefs, array[i], gatherCount);
                REPORTER_ASSERT(reporter, found);
#if 0
                // enable this block of code to debug failures, as it will rerun
                // the case that failed.
                if (!found) {
                    SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
                    size_t dataSize = data ? data->size() : 0;
                }
#endif
            }
        }
    }
}