Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 #include "Test.h"
      8 #include "SkCanvas.h"
      9 #include "SkColorPriv.h"
     10 #include "SkData.h"
     11 #include "SkError.h"
     12 #include "SkPaint.h"
     13 #include "SkPicture.h"
     14 #include "SkRandom.h"
     15 #include "SkRRect.h"
     16 #include "SkShader.h"
     17 #include "SkStream.h"
     18 
     19 #include "SkPictureUtils.h"
     20 
     21 static void make_bm(SkBitmap* bm, int w, int h, SkColor color, bool immutable) {
     22     bm->setConfig(SkBitmap::kARGB_8888_Config, w, h);
     23     bm->allocPixels();
     24     bm->eraseColor(color);
     25     if (immutable) {
     26         bm->setImmutable();
     27     }
     28 }
     29 
     30 typedef void (*DrawBitmapProc)(SkCanvas*, const SkBitmap&, const SkPoint&);
     31 
     32 static void drawbitmap_proc(SkCanvas* canvas, const SkBitmap& bm,
     33                             const SkPoint& pos) {
     34     canvas->drawBitmap(bm, pos.fX, pos.fY, NULL);
     35 }
     36 
     37 static void drawbitmaprect_proc(SkCanvas* canvas, const SkBitmap& bm,
     38                                 const SkPoint& pos) {
     39     SkRect r = {
     40         0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height())
     41     };
     42     r.offset(pos.fX, pos.fY);
     43     canvas->drawBitmapRectToRect(bm, NULL, r, NULL);
     44 }
     45 
     46 static void drawshader_proc(SkCanvas* canvas, const SkBitmap& bm,
     47                             const SkPoint& pos) {
     48     SkRect r = {
     49         0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height())
     50     };
     51     r.offset(pos.fX, pos.fY);
     52 
     53     SkShader* s = SkShader::CreateBitmapShader(bm,
     54                                                SkShader::kClamp_TileMode,
     55                                                SkShader::kClamp_TileMode);
     56     SkPaint paint;
     57     paint.setShader(s)->unref();
     58     canvas->drawRect(r, paint);
     59     canvas->drawOval(r, paint);
     60     SkRRect rr;
     61     rr.setRectXY(r, 10, 10);
     62     canvas->drawRRect(rr, paint);
     63 }
     64 
     65 // Return a picture with the bitmaps drawn at the specified positions.
     66 static SkPicture* record_bitmaps(const SkBitmap bm[], const SkPoint pos[],
     67                                  int count, DrawBitmapProc proc) {
     68     SkPicture* pic = new SkPicture;
     69     SkCanvas* canvas = pic->beginRecording(1000, 1000);
     70     for (int i = 0; i < count; ++i) {
     71         proc(canvas, bm[i], pos[i]);
     72     }
     73     pic->endRecording();
     74     return pic;
     75 }
     76 
     77 static void rand_rect(SkRect* rect, SkMWCRandom& rand, SkScalar W, SkScalar H) {
     78     rect->fLeft   = rand.nextRangeScalar(-W, 2*W);
     79     rect->fTop    = rand.nextRangeScalar(-H, 2*H);
     80     rect->fRight  = rect->fLeft + rand.nextRangeScalar(0, W);
     81     rect->fBottom = rect->fTop + rand.nextRangeScalar(0, H);
     82 
     83     // we integralize rect to make our tests more predictable, since Gather is
     84     // a little sloppy.
     85     SkIRect ir;
     86     rect->round(&ir);
     87     rect->set(ir);
     88 }
     89 
     90 // Allocate result to be large enough to hold subset, and then draw the picture
     91 // into it, offsetting by subset's top/left corner.
     92 static void draw(SkPicture* pic, const SkRect& subset, SkBitmap* result) {
     93     SkIRect ir;
     94     subset.roundOut(&ir);
     95     int w = ir.width();
     96     int h = ir.height();
     97     make_bm(result, w, h, 0, false);
     98 
     99     SkCanvas canvas(*result);
    100     canvas.translate(-SkIntToScalar(ir.left()), -SkIntToScalar(ir.top()));
    101     canvas.drawPicture(*pic);
    102 }
    103 
    104 template <typename T> int find_index(const T* array, T elem, int count) {
    105     for (int i = 0; i < count; ++i) {
    106         if (array[i] == elem) {
    107             return i;
    108         }
    109     }
    110     return -1;
    111 }
    112 
    113 // Return true if 'ref' is found in array[]
    114 static bool find(SkPixelRef const * const * array, SkPixelRef const * ref, int count) {
    115     return find_index<const SkPixelRef*>(array, ref, count) >= 0;
    116 }
    117 
    118 // Look at each pixel in bm, and if its color appears in colors[], find the
    119 // corresponding value in refs[] and append that ref into array, skipping
    120 // duplicates of the same value.
    121 static void gather_from_colors(const SkBitmap& bm, SkPixelRef* const refs[],
    122                                int count, SkTDArray<SkPixelRef*>* array) {
    123     // Since we only want to return unique values in array, when we scan we just
    124     // set a bit for each index'd color found. In practice we only have a few
    125     // distinct colors, so we just use an int's bits as our array. Hence the
    126     // assert that count <= number-of-bits-in-our-int.
    127     SkASSERT((unsigned)count <= 32);
    128     uint32_t bitarray = 0;
    129 
    130     SkAutoLockPixels alp(bm);
    131 
    132     for (int y = 0; y < bm.height(); ++y) {
    133         for (int x = 0; x < bm.width(); ++x) {
    134             SkPMColor pmc = *bm.getAddr32(x, y);
    135             // the only good case where the color is not found would be if
    136             // the color is transparent, meaning no bitmap was drawn in that
    137             // pixel.
    138             if (pmc) {
    139                 uint32_t index = SkGetPackedR32(pmc);
    140                 SkASSERT(SkGetPackedG32(pmc) == index);
    141                 SkASSERT(SkGetPackedB32(pmc) == index);
    142                 SkASSERT(static_cast<int>(index) < count);
    143                 bitarray |= 1 << index;
    144             }
    145         }
    146     }
    147 
    148     for (int i = 0; i < count; ++i) {
    149         if (bitarray & (1 << i)) {
    150             *array->append() = refs[i];
    151         }
    152     }
    153 }
    154 
    155 static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
    156     const int IW = 8;
    157     const int IH = IW;
    158     const SkScalar W = SkIntToScalar(IW);
    159     const SkScalar H = W;
    160 
    161     static const int N = 4;
    162     SkBitmap bm[N];
    163     SkPixelRef* refs[N];
    164 
    165     const SkPoint pos[] = {
    166         { 0, 0 }, { W, 0 }, { 0, H }, { W, H }
    167     };
    168 
    169     // Our convention is that the color components contain the index of their
    170     // corresponding bitmap/pixelref
    171     for (int i = 0; i < N; ++i) {
    172         make_bm(&bm[i], IW, IH, SkColorSetARGB(0xFF, i, i, i), true);
    173         refs[i] = bm[i].pixelRef();
    174     }
    175 
    176     static const DrawBitmapProc procs[] = {
    177         drawbitmap_proc, drawbitmaprect_proc, drawshader_proc
    178     };
    179 
    180     SkMWCRandom rand;
    181     for (size_t k = 0; k < SK_ARRAY_COUNT(procs); ++k) {
    182         SkAutoTUnref<SkPicture> pic(record_bitmaps(bm, pos, N, procs[k]));
    183 
    184         // quick check for a small piece of each quadrant, which should just
    185         // contain 1 bitmap.
    186         for (size_t  i = 0; i < SK_ARRAY_COUNT(pos); ++i) {
    187             SkRect r;
    188             r.set(2, 2, W - 2, H - 2);
    189             r.offset(pos[i].fX, pos[i].fY);
    190             SkAutoDataUnref data(SkPictureUtils::GatherPixelRefs(pic, r));
    191             REPORTER_ASSERT(reporter, data);
    192             if (data) {
    193                 int count = data->size() / sizeof(SkPixelRef*);
    194                 REPORTER_ASSERT(reporter, 1 == count);
    195                 REPORTER_ASSERT(reporter, *(SkPixelRef**)data->data() == refs[i]);
    196             }
    197         }
    198 
    199         // Test a bunch of random (mostly) rects, and compare the gather results
    200         // with a deduced list of refs by looking at the colors drawn.
    201         for (int j = 0; j < 100; ++j) {
    202             SkRect r;
    203             rand_rect(&r, rand, 2*W, 2*H);
    204 
    205             SkBitmap result;
    206             draw(pic, r, &result);
    207             SkTDArray<SkPixelRef*> array;
    208 
    209             SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
    210             size_t dataSize = data ? data->size() : 0;
    211             int gatherCount = dataSize / sizeof(SkPixelRef*);
    212             SkASSERT(gatherCount * sizeof(SkPixelRef*) == dataSize);
    213             SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL;
    214             SkAutoDataUnref adu(data);
    215 
    216             gather_from_colors(result, refs, N, &array);
    217 
    218             /*
    219              *  GatherPixelRefs is conservative, so it can return more bitmaps
    220              *  that we actually can see (usually because of conservative bounds
    221              *  inflation for antialiasing). Thus our check here is only that
    222              *  Gather didn't miss any that we actually saw. Even that isn't
    223              *  a strict requirement on Gather, which is meant to be quick and
    224              *  only mostly-correct, but at the moment this test should work.
    225              */
    226             for (int i = 0; i < array.count(); ++i) {
    227                 bool found = find(gatherRefs, array[i], gatherCount);
    228                 REPORTER_ASSERT(reporter, found);
    229 #if 0
    230                 // enable this block of code to debug failures, as it will rerun
    231                 // the case that failed.
    232                 if (!found) {
    233                     SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
    234                     size_t dataSize = data ? data->size() : 0;
    235                 }
    236 #endif
    237             }
    238         }
    239     }
    240 }
    241 
    242 #ifdef SK_DEBUG
    243 // Ensure that deleting SkPicturePlayback does not assert. Asserts only fire in debug mode, so only
    244 // run in debug mode.
    245 static void test_deleting_empty_playback() {
    246     SkPicture picture;
    247     // Creates an SkPictureRecord
    248     picture.beginRecording(0, 0);
    249     // Turns that into an SkPicturePlayback
    250     picture.endRecording();
    251     // Deletes the old SkPicturePlayback, and creates a new SkPictureRecord
    252     picture.beginRecording(0, 0);
    253 }
    254 
    255 // Ensure that serializing an empty picture does not assert. Likewise only runs in debug mode.
    256 static void test_serializing_empty_picture() {
    257     SkPicture picture;
    258     picture.beginRecording(0, 0);
    259     picture.endRecording();
    260     SkDynamicMemoryWStream stream;
    261     picture.serialize(&stream);
    262 }
    263 #endif
    264 
    265 static void rand_op(SkCanvas* canvas, SkMWCRandom& rand) {
    266     SkPaint paint;
    267     SkRect rect = SkRect::MakeWH(50, 50);
    268 
    269     SkScalar unit = rand.nextUScalar1();
    270     if (unit <= 0.3) {
    271 //        SkDebugf("save\n");
    272         canvas->save();
    273     } else if (unit <= 0.6) {
    274 //        SkDebugf("restore\n");
    275         canvas->restore();
    276     } else if (unit <= 0.9) {
    277 //        SkDebugf("clip\n");
    278         canvas->clipRect(rect);
    279     } else {
    280 //        SkDebugf("draw\n");
    281         canvas->drawPaint(paint);
    282     }
    283 }
    284 
    285 static void test_peephole() {
    286     SkMWCRandom rand;
    287 
    288     for (int j = 0; j < 100; j++) {
    289         SkMWCRandom rand2(rand); // remember the seed
    290 
    291         SkPicture picture;
    292         SkCanvas* canvas = picture.beginRecording(100, 100);
    293 
    294         for (int i = 0; i < 1000; ++i) {
    295             rand_op(canvas, rand);
    296         }
    297         picture.endRecording();
    298 
    299         rand = rand2;
    300     }
    301 
    302     {
    303         SkPicture picture;
    304         SkCanvas* canvas = picture.beginRecording(100, 100);
    305         SkRect rect = SkRect::MakeWH(50, 50);
    306 
    307         for (int i = 0; i < 100; ++i) {
    308             canvas->save();
    309         }
    310         while (canvas->getSaveCount() > 1) {
    311             canvas->clipRect(rect);
    312             canvas->restore();
    313         }
    314         picture.endRecording();
    315     }
    316 }
    317 
    318 #ifndef SK_DEBUG
    319 // Only test this is in release mode. We deliberately crash in debug mode, since a valid caller
    320 // should never do this.
    321 static void test_bad_bitmap() {
    322     // This bitmap has a width and height but no pixels. As a result, attempting to record it will
    323     // fail.
    324     SkBitmap bm;
    325     bm.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
    326     SkPicture picture;
    327     SkCanvas* recordingCanvas = picture.beginRecording(100, 100);
    328     recordingCanvas->drawBitmap(bm, 0, 0);
    329     picture.endRecording();
    330 
    331     SkCanvas canvas;
    332     canvas.drawPicture(picture);
    333 }
    334 #endif
    335 
    336 #include "SkData.h"
    337 #include "SkImageRef_GlobalPool.h"
    338 // Class to test SkPixelRef::onRefEncodedData, since there are currently no implementations in skia.
    339 class SkDataImageRef : public SkImageRef_GlobalPool {
    340 
    341 public:
    342     SkDataImageRef(SkMemoryStream* stream)
    343         : SkImageRef_GlobalPool(stream, SkBitmap::kNo_Config) {
    344         SkASSERT(stream != NULL);
    345         fData = stream->copyToData();
    346         this->setImmutable();
    347     }
    348 
    349     ~SkDataImageRef() {
    350         fData->unref();
    351     }
    352 
    353     virtual SkData* onRefEncodedData() SK_OVERRIDE {
    354         fData->ref();
    355         return fData;
    356     }
    357 
    358 private:
    359     SkData* fData;
    360 };
    361 
    362 #include "SkImageEncoder.h"
    363 
    364 static SkData* encode_bitmap_to_data(size_t* offset, const SkBitmap& bm) {
    365     *offset = 0;
    366     return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100);
    367 }
    368 
    369 static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) {
    370     SkPicture picture;
    371     SkCanvas* canvas = picture.beginRecording(bitmap.width(), bitmap.height());
    372     canvas->drawBitmap(bitmap, 0, 0);
    373     SkDynamicMemoryWStream wStream;
    374     picture.serialize(&wStream, &encode_bitmap_to_data);
    375     return wStream.copyToData();
    376 }
    377 
    378 struct ErrorContext {
    379     int fErrors;
    380     skiatest::Reporter* fReporter;
    381 };
    382 
    383 static void assert_one_parse_error_cb(SkError error, void* context) {
    384     ErrorContext* errorContext = static_cast<ErrorContext*>(context);
    385     errorContext->fErrors++;
    386     // This test only expects one error, and that is a kParseError. If there are others,
    387     // there is some unknown problem.
    388     REPORTER_ASSERT_MESSAGE(errorContext->fReporter, 1 == errorContext->fErrors,
    389                             "This threw more errors than expected.");
    390     REPORTER_ASSERT_MESSAGE(errorContext->fReporter, kParseError_SkError == error,
    391                             SkGetLastErrorString());
    392 }
    393 
    394 static void test_bitmap_with_encoded_data(skiatest::Reporter* reporter) {
    395     // Create a bitmap that will be encoded.
    396     SkBitmap original;
    397     make_bm(&original, 100, 100, SK_ColorBLUE, true);
    398     SkDynamicMemoryWStream wStream;
    399     if (!SkImageEncoder::EncodeStream(&wStream, original, SkImageEncoder::kPNG_Type, 100)) {
    400         return;
    401     }
    402     SkAutoDataUnref data(wStream.copyToData());
    403     SkMemoryStream memStream;
    404     memStream.setData(data);
    405 
    406     // Use the encoded bitmap as the data for an image ref.
    407     SkBitmap bm;
    408     SkAutoTUnref<SkDataImageRef> imageRef(SkNEW_ARGS(SkDataImageRef, (&memStream)));
    409     imageRef->getInfo(&bm);
    410     bm.setPixelRef(imageRef);
    411 
    412     // Write both bitmaps to pictures, and ensure that the resulting data streams are the same.
    413     // Flattening original will follow the old path of performing an encode, while flattening bm
    414     // will use the already encoded data.
    415     SkAutoDataUnref picture1(serialized_picture_from_bitmap(original));
    416     SkAutoDataUnref picture2(serialized_picture_from_bitmap(bm));
    417     REPORTER_ASSERT(reporter, picture1->equals(picture2));
    418     // Now test that a parse error was generated when trying to create a new SkPicture without
    419     // providing a function to decode the bitmap.
    420     ErrorContext context;
    421     context.fErrors = 0;
    422     context.fReporter = reporter;
    423     SkSetErrorCallback(assert_one_parse_error_cb, &context);
    424     SkMemoryStream pictureStream(picture1);
    425     SkClearLastError();
    426     SkAutoUnref pictureFromStream(SkPicture::CreateFromStream(&pictureStream, NULL));
    427     REPORTER_ASSERT(reporter, pictureFromStream.get() != NULL);
    428     SkClearLastError();
    429     SkSetErrorCallback(NULL, NULL);
    430 }
    431 
    432 static void test_clone_empty(skiatest::Reporter* reporter) {
    433     // This is a regression test for crbug.com/172062
    434     // Before the fix, we used to crash accessing a null pointer when we
    435     // had a picture with no paints. This test passes by not crashing.
    436     {
    437         SkPicture picture;
    438         picture.beginRecording(1, 1);
    439         picture.endRecording();
    440         SkPicture* destPicture = picture.clone();
    441         REPORTER_ASSERT(reporter, NULL != destPicture);
    442         destPicture->unref();
    443     }
    444     {
    445         // Test without call to endRecording
    446         SkPicture picture;
    447         picture.beginRecording(1, 1);
    448         SkPicture* destPicture = picture.clone();
    449         REPORTER_ASSERT(reporter, NULL != destPicture);
    450         destPicture->unref();
    451     }
    452 }
    453 
    454 static void test_clip_bound_opt(skiatest::Reporter* reporter) {
    455     // Test for crbug.com/229011
    456     SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(4), SkIntToScalar(4),
    457                                     SkIntToScalar(2), SkIntToScalar(2));
    458     SkRect rect2 = SkRect::MakeXYWH(SkIntToScalar(7), SkIntToScalar(7),
    459                                     SkIntToScalar(1), SkIntToScalar(1));
    460     SkRect rect3 = SkRect::MakeXYWH(SkIntToScalar(6), SkIntToScalar(6),
    461                                     SkIntToScalar(1), SkIntToScalar(1));
    462 
    463     SkPath invPath;
    464     invPath.addOval(rect1);
    465     invPath.setFillType(SkPath::kInverseEvenOdd_FillType);
    466     SkPath path;
    467     path.addOval(rect2);
    468     SkPath path2;
    469     path2.addOval(rect3);
    470     SkIRect clipBounds;
    471     // Minimalist test set for 100% code coverage of
    472     // SkPictureRecord::updateClipConservativelyUsingBounds
    473     {
    474         SkPicture picture;
    475         SkCanvas* canvas = picture.beginRecording(10, 10,
    476             SkPicture::kUsePathBoundsForClip_RecordingFlag);
    477         canvas->clipPath(invPath, SkRegion::kIntersect_Op);
    478         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
    479         REPORTER_ASSERT(reporter, true == nonEmpty);
    480         REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft);
    481         REPORTER_ASSERT(reporter, 0 == clipBounds.fTop);
    482         REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom);
    483         REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
    484     }
    485     {
    486         SkPicture picture;
    487         SkCanvas* canvas = picture.beginRecording(10, 10,
    488             SkPicture::kUsePathBoundsForClip_RecordingFlag);
    489         canvas->clipPath(path, SkRegion::kIntersect_Op);
    490         canvas->clipPath(invPath, SkRegion::kIntersect_Op);
    491         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
    492         REPORTER_ASSERT(reporter, true == nonEmpty);
    493         REPORTER_ASSERT(reporter, 7 == clipBounds.fLeft);
    494         REPORTER_ASSERT(reporter, 7 == clipBounds.fTop);
    495         REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom);
    496         REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
    497     }
    498     {
    499         SkPicture picture;
    500         SkCanvas* canvas = picture.beginRecording(10, 10,
    501             SkPicture::kUsePathBoundsForClip_RecordingFlag);
    502         canvas->clipPath(path, SkRegion::kIntersect_Op);
    503         canvas->clipPath(invPath, SkRegion::kUnion_Op);
    504         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
    505         REPORTER_ASSERT(reporter, true == nonEmpty);
    506         REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft);
    507         REPORTER_ASSERT(reporter, 0 == clipBounds.fTop);
    508         REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom);
    509         REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
    510     }
    511     {
    512         SkPicture picture;
    513         SkCanvas* canvas = picture.beginRecording(10, 10,
    514             SkPicture::kUsePathBoundsForClip_RecordingFlag);
    515         canvas->clipPath(path, SkRegion::kDifference_Op);
    516         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
    517         REPORTER_ASSERT(reporter, true == nonEmpty);
    518         REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft);
    519         REPORTER_ASSERT(reporter, 0 == clipBounds.fTop);
    520         REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom);
    521         REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
    522     }
    523     {
    524         SkPicture picture;
    525         SkCanvas* canvas = picture.beginRecording(10, 10,
    526             SkPicture::kUsePathBoundsForClip_RecordingFlag);
    527         canvas->clipPath(path, SkRegion::kReverseDifference_Op);
    528         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
    529         // True clip is actually empty in this case, but the best
    530         // determination we can make using only bounds as input is that the
    531         // clip is included in the bounds of 'path'.
    532         REPORTER_ASSERT(reporter, true == nonEmpty);
    533         REPORTER_ASSERT(reporter, 7 == clipBounds.fLeft);
    534         REPORTER_ASSERT(reporter, 7 == clipBounds.fTop);
    535         REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom);
    536         REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
    537     }
    538     {
    539         SkPicture picture;
    540         SkCanvas* canvas = picture.beginRecording(10, 10,
    541             SkPicture::kUsePathBoundsForClip_RecordingFlag);
    542         canvas->clipPath(path, SkRegion::kIntersect_Op);
    543         canvas->clipPath(path2, SkRegion::kXOR_Op);
    544         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
    545         REPORTER_ASSERT(reporter, true == nonEmpty);
    546         REPORTER_ASSERT(reporter, 6 == clipBounds.fLeft);
    547         REPORTER_ASSERT(reporter, 6 == clipBounds.fTop);
    548         REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom);
    549         REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
    550     }
    551 }
    552 
    553 static void TestPicture(skiatest::Reporter* reporter) {
    554 #ifdef SK_DEBUG
    555     test_deleting_empty_playback();
    556     test_serializing_empty_picture();
    557 #else
    558     test_bad_bitmap();
    559 #endif
    560     test_peephole();
    561     test_gatherpixelrefs(reporter);
    562     test_bitmap_with_encoded_data(reporter);
    563     test_clone_empty(reporter);
    564     test_clip_bound_opt(reporter);
    565 }
    566 
    567 #include "TestClassDef.h"
    568 DEFINE_TESTCLASS("Pictures", PictureTestClass, TestPicture)
    569