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 
      8 #include "SkBBoxHierarchy.h"
      9 #include "SkBlurImageFilter.h"
     10 #include "SkCanvas.h"
     11 #include "SkColorPriv.h"
     12 #include "SkDashPathEffect.h"
     13 #include "SkData.h"
     14 #include "SkDecodingImageGenerator.h"
     15 #include "SkError.h"
     16 #include "SkImageEncoder.h"
     17 #include "SkImageGenerator.h"
     18 #include "SkPaint.h"
     19 #include "SkPicture.h"
     20 #include "SkPictureRecorder.h"
     21 #include "SkPictureUtils.h"
     22 #include "SkPixelRef.h"
     23 #include "SkRRect.h"
     24 #include "SkRandom.h"
     25 #include "SkShader.h"
     26 #include "SkStream.h"
     27 
     28 #if SK_SUPPORT_GPU
     29 #include "SkSurface.h"
     30 #include "GrContextFactory.h"
     31 #include "GrPictureUtils.h"
     32 #endif
     33 #include "Test.h"
     34 
     35 #include "SkLumaColorFilter.h"
     36 #include "SkColorFilterImageFilter.h"
     37 
     38 static const int gColorScale = 30;
     39 static const int gColorOffset = 60;
     40 
     41 static void make_bm(SkBitmap* bm, int w, int h, SkColor color, bool immutable) {
     42     bm->allocN32Pixels(w, h);
     43     bm->eraseColor(color);
     44     if (immutable) {
     45         bm->setImmutable();
     46     }
     47 }
     48 
     49 static void make_checkerboard(SkBitmap* bm, int w, int h, bool immutable) {
     50     SkASSERT(w % 2 == 0);
     51     SkASSERT(h % 2 == 0);
     52     bm->allocPixels(SkImageInfo::Make(w, h, kAlpha_8_SkColorType,
     53                                       kPremul_SkAlphaType));
     54     SkAutoLockPixels lock(*bm);
     55     for (int y = 0; y < h; y += 2) {
     56         uint8_t* s = bm->getAddr8(0, y);
     57         for (int x = 0; x < w; x += 2) {
     58             *s++ = 0xFF;
     59             *s++ = 0x00;
     60         }
     61         s = bm->getAddr8(0, y + 1);
     62         for (int x = 0; x < w; x += 2) {
     63             *s++ = 0x00;
     64             *s++ = 0xFF;
     65         }
     66     }
     67     if (immutable) {
     68         bm->setImmutable();
     69     }
     70 }
     71 
     72 static void init_paint(SkPaint* paint, const SkBitmap &bm) {
     73     SkShader* shader = SkShader::CreateBitmapShader(bm,
     74                                                     SkShader::kClamp_TileMode,
     75                                                     SkShader::kClamp_TileMode);
     76     paint->setShader(shader)->unref();
     77 }
     78 
     79 typedef void (*DrawBitmapProc)(SkCanvas*, const SkBitmap&,
     80                                const SkBitmap&, const SkPoint&,
     81                                SkTDArray<SkPixelRef*>* usedPixRefs);
     82 
     83 static void drawpaint_proc(SkCanvas* canvas, const SkBitmap& bm,
     84                            const SkBitmap& altBM, const SkPoint& pos,
     85                            SkTDArray<SkPixelRef*>* usedPixRefs) {
     86     SkPaint paint;
     87     init_paint(&paint, bm);
     88 
     89     canvas->drawPaint(paint);
     90     *usedPixRefs->append() = bm.pixelRef();
     91 }
     92 
     93 static void drawpoints_proc(SkCanvas* canvas, const SkBitmap& bm,
     94                             const SkBitmap& altBM, const SkPoint& pos,
     95                             SkTDArray<SkPixelRef*>* usedPixRefs) {
     96     SkPaint paint;
     97     init_paint(&paint, bm);
     98 
     99     // draw a rect
    100     SkPoint points[5] = {
    101         { pos.fX, pos.fY },
    102         { pos.fX + bm.width() - 1, pos.fY },
    103         { pos.fX + bm.width() - 1, pos.fY + bm.height() - 1 },
    104         { pos.fX, pos.fY + bm.height() - 1 },
    105         { pos.fX, pos.fY },
    106     };
    107 
    108     canvas->drawPoints(SkCanvas::kPolygon_PointMode, 5, points, paint);
    109     *usedPixRefs->append() = bm.pixelRef();
    110 }
    111 
    112 static void drawrect_proc(SkCanvas* canvas, const SkBitmap& bm,
    113                           const SkBitmap& altBM, const SkPoint& pos,
    114                           SkTDArray<SkPixelRef*>* usedPixRefs) {
    115     SkPaint paint;
    116     init_paint(&paint, bm);
    117 
    118     SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
    119     r.offset(pos.fX, pos.fY);
    120 
    121     canvas->drawRect(r, paint);
    122     *usedPixRefs->append() = bm.pixelRef();
    123 }
    124 
    125 static void drawoval_proc(SkCanvas* canvas, const SkBitmap& bm,
    126                           const SkBitmap& altBM, const SkPoint& pos,
    127                           SkTDArray<SkPixelRef*>* usedPixRefs) {
    128     SkPaint paint;
    129     init_paint(&paint, bm);
    130 
    131     SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
    132     r.offset(pos.fX, pos.fY);
    133 
    134     canvas->drawOval(r, paint);
    135     *usedPixRefs->append() = bm.pixelRef();
    136 }
    137 
    138 static void drawrrect_proc(SkCanvas* canvas, const SkBitmap& bm,
    139                            const SkBitmap& altBM, const SkPoint& pos,
    140                            SkTDArray<SkPixelRef*>* usedPixRefs) {
    141     SkPaint paint;
    142     init_paint(&paint, bm);
    143 
    144     SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
    145     r.offset(pos.fX, pos.fY);
    146 
    147     SkRRect rr;
    148     rr.setRectXY(r, SkIntToScalar(bm.width())/4, SkIntToScalar(bm.height())/4);
    149     canvas->drawRRect(rr, paint);
    150     *usedPixRefs->append() = bm.pixelRef();
    151 }
    152 
    153 static void drawpath_proc(SkCanvas* canvas, const SkBitmap& bm,
    154                           const SkBitmap& altBM, const SkPoint& pos,
    155                           SkTDArray<SkPixelRef*>* usedPixRefs) {
    156     SkPaint paint;
    157     init_paint(&paint, bm);
    158 
    159     SkPath path;
    160     path.lineTo(bm.width()/2.0f, SkIntToScalar(bm.height()));
    161     path.lineTo(SkIntToScalar(bm.width()), 0);
    162     path.close();
    163     path.offset(pos.fX, pos.fY);
    164 
    165     canvas->drawPath(path, paint);
    166     *usedPixRefs->append() = bm.pixelRef();
    167 }
    168 
    169 static void drawbitmap_proc(SkCanvas* canvas, const SkBitmap& bm,
    170                             const SkBitmap& altBM, const SkPoint& pos,
    171                             SkTDArray<SkPixelRef*>* usedPixRefs) {
    172     canvas->drawBitmap(bm, pos.fX, pos.fY, NULL);
    173     *usedPixRefs->append() = bm.pixelRef();
    174 }
    175 
    176 static void drawbitmap_withshader_proc(SkCanvas* canvas, const SkBitmap& bm,
    177                                        const SkBitmap& altBM, const SkPoint& pos,
    178                                        SkTDArray<SkPixelRef*>* usedPixRefs) {
    179     SkPaint paint;
    180     init_paint(&paint, bm);
    181 
    182     // The bitmap in the paint is ignored unless we're drawing an A8 bitmap
    183     canvas->drawBitmap(altBM, pos.fX, pos.fY, &paint);
    184     *usedPixRefs->append() = bm.pixelRef();
    185     *usedPixRefs->append() = altBM.pixelRef();
    186 }
    187 
    188 static void drawsprite_proc(SkCanvas* canvas, const SkBitmap& bm,
    189                             const SkBitmap& altBM, const SkPoint& pos,
    190                             SkTDArray<SkPixelRef*>* usedPixRefs) {
    191     const SkMatrix& ctm = canvas->getTotalMatrix();
    192 
    193     SkPoint p(pos);
    194     ctm.mapPoints(&p, 1);
    195 
    196     canvas->drawSprite(bm, (int)p.fX, (int)p.fY, NULL);
    197     *usedPixRefs->append() = bm.pixelRef();
    198 }
    199 
    200 #if 0
    201 // Although specifiable, this case doesn't seem to make sense (i.e., the
    202 // bitmap in the shader is never used).
    203 static void drawsprite_withshader_proc(SkCanvas* canvas, const SkBitmap& bm,
    204                                        const SkBitmap& altBM, const SkPoint& pos,
    205                                        SkTDArray<SkPixelRef*>* usedPixRefs) {
    206     SkPaint paint;
    207     init_paint(&paint, bm);
    208 
    209     const SkMatrix& ctm = canvas->getTotalMatrix();
    210 
    211     SkPoint p(pos);
    212     ctm.mapPoints(&p, 1);
    213 
    214     canvas->drawSprite(altBM, (int)p.fX, (int)p.fY, &paint);
    215     *usedPixRefs->append() = bm.pixelRef();
    216     *usedPixRefs->append() = altBM.pixelRef();
    217 }
    218 #endif
    219 
    220 static void drawbitmaprect_proc(SkCanvas* canvas, const SkBitmap& bm,
    221                                 const SkBitmap& altBM, const SkPoint& pos,
    222                                 SkTDArray<SkPixelRef*>* usedPixRefs) {
    223     SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
    224 
    225     r.offset(pos.fX, pos.fY);
    226     canvas->drawBitmapRectToRect(bm, NULL, r, NULL);
    227     *usedPixRefs->append() = bm.pixelRef();
    228 }
    229 
    230 static void drawbitmaprect_withshader_proc(SkCanvas* canvas,
    231                                            const SkBitmap& bm,
    232                                            const SkBitmap& altBM,
    233                                            const SkPoint& pos,
    234                                            SkTDArray<SkPixelRef*>* usedPixRefs) {
    235     SkPaint paint;
    236     init_paint(&paint, bm);
    237 
    238     SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
    239     r.offset(pos.fX, pos.fY);
    240 
    241     // The bitmap in the paint is ignored unless we're drawing an A8 bitmap
    242     canvas->drawBitmapRectToRect(altBM, NULL, r, &paint);
    243     *usedPixRefs->append() = bm.pixelRef();
    244     *usedPixRefs->append() = altBM.pixelRef();
    245 }
    246 
    247 static void drawtext_proc(SkCanvas* canvas, const SkBitmap& bm,
    248                           const SkBitmap& altBM, const SkPoint& pos,
    249                           SkTDArray<SkPixelRef*>* usedPixRefs) {
    250     SkPaint paint;
    251     init_paint(&paint, bm);
    252     paint.setTextSize(SkIntToScalar(1.5*bm.width()));
    253 
    254     canvas->drawText("0", 1, pos.fX, pos.fY+bm.width(), paint);
    255     *usedPixRefs->append() = bm.pixelRef();
    256 }
    257 
    258 static void drawpostext_proc(SkCanvas* canvas, const SkBitmap& bm,
    259                              const SkBitmap& altBM, const SkPoint& pos,
    260                              SkTDArray<SkPixelRef*>* usedPixRefs) {
    261     SkPaint paint;
    262     init_paint(&paint, bm);
    263     paint.setTextSize(SkIntToScalar(1.5*bm.width()));
    264 
    265     SkPoint point = { pos.fX, pos.fY + bm.height() };
    266     canvas->drawPosText("O", 1, &point, paint);
    267     *usedPixRefs->append() = bm.pixelRef();
    268 }
    269 
    270 static void drawtextonpath_proc(SkCanvas* canvas, const SkBitmap& bm,
    271                                 const SkBitmap& altBM, const SkPoint& pos,
    272                                 SkTDArray<SkPixelRef*>* usedPixRefs) {
    273     SkPaint paint;
    274 
    275     init_paint(&paint, bm);
    276     paint.setTextSize(SkIntToScalar(1.5*bm.width()));
    277 
    278     SkPath path;
    279     path.lineTo(SkIntToScalar(bm.width()), 0);
    280     path.offset(pos.fX, pos.fY+bm.height());
    281 
    282     canvas->drawTextOnPath("O", 1, path, NULL, paint);
    283     *usedPixRefs->append() = bm.pixelRef();
    284 }
    285 
    286 static void drawverts_proc(SkCanvas* canvas, const SkBitmap& bm,
    287                            const SkBitmap& altBM, const SkPoint& pos,
    288                            SkTDArray<SkPixelRef*>* usedPixRefs) {
    289     SkPaint paint;
    290     init_paint(&paint, bm);
    291 
    292     SkPoint verts[4] = {
    293         { pos.fX, pos.fY },
    294         { pos.fX + bm.width(), pos.fY },
    295         { pos.fX + bm.width(), pos.fY + bm.height() },
    296         { pos.fX, pos.fY + bm.height() }
    297     };
    298     SkPoint texs[4] = { { 0, 0 },
    299                         { SkIntToScalar(bm.width()), 0 },
    300                         { SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) },
    301                         { 0, SkIntToScalar(bm.height()) } };
    302     uint16_t indices[6] = { 0, 1, 2, 0, 2, 3 };
    303 
    304     canvas->drawVertices(SkCanvas::kTriangles_VertexMode, 4, verts, texs, NULL, NULL,
    305                          indices, 6, paint);
    306     *usedPixRefs->append() = bm.pixelRef();
    307 }
    308 
    309 // Return a picture with the bitmaps drawn at the specified positions.
    310 static SkPicture* record_bitmaps(const SkBitmap bm[],
    311                                  const SkPoint pos[],
    312                                  SkTDArray<SkPixelRef*> analytic[],
    313                                  int count,
    314                                  DrawBitmapProc proc) {
    315     SkPictureRecorder recorder;
    316     SkCanvas* canvas = recorder.beginRecording(1000, 1000);
    317     for (int i = 0; i < count; ++i) {
    318         analytic[i].rewind();
    319         canvas->save();
    320         SkRect clipRect = SkRect::MakeXYWH(pos[i].fX, pos[i].fY,
    321                                            SkIntToScalar(bm[i].width()),
    322                                            SkIntToScalar(bm[i].height()));
    323         canvas->clipRect(clipRect, SkRegion::kIntersect_Op);
    324         proc(canvas, bm[i], bm[count+i], pos[i], &analytic[i]);
    325         canvas->restore();
    326     }
    327     return recorder.endRecording();
    328 }
    329 
    330 static void rand_rect(SkRect* rect, SkRandom& rand, SkScalar W, SkScalar H) {
    331     rect->fLeft   = rand.nextRangeScalar(-W, 2*W);
    332     rect->fTop    = rand.nextRangeScalar(-H, 2*H);
    333     rect->fRight  = rect->fLeft + rand.nextRangeScalar(0, W);
    334     rect->fBottom = rect->fTop + rand.nextRangeScalar(0, H);
    335 
    336     // we integralize rect to make our tests more predictable, since Gather is
    337     // a little sloppy.
    338     SkIRect ir;
    339     rect->round(&ir);
    340     rect->set(ir);
    341 }
    342 
    343 static void draw(SkPicture* pic, int width, int height, SkBitmap* result) {
    344     make_bm(result, width, height, SK_ColorBLACK, false);
    345 
    346     SkCanvas canvas(*result);
    347     canvas.drawPicture(pic);
    348 }
    349 
    350 template <typename T> int find_index(const T* array, T elem, int count) {
    351     for (int i = 0; i < count; ++i) {
    352         if (array[i] == elem) {
    353             return i;
    354         }
    355     }
    356     return -1;
    357 }
    358 
    359 // Return true if 'ref' is found in array[]
    360 static bool find(SkPixelRef const * const * array, SkPixelRef const * ref, int count) {
    361     return find_index<const SkPixelRef*>(array, ref, count) >= 0;
    362 }
    363 
    364 // Look at each pixel that is inside 'subset', and if its color appears in
    365 // colors[], find the corresponding value in refs[] and append that ref into
    366 // array, skipping duplicates of the same value.
    367 // Note that gathering pixelRefs from rendered colors suffers from the problem
    368 // that multiple simultaneous textures (e.g., A8 for alpha and 8888 for color)
    369 // isn't easy to reconstruct.
    370 static void gather_from_image(const SkBitmap& bm, SkPixelRef* const refs[],
    371                               int count, SkTDArray<SkPixelRef*>* array,
    372                               const SkRect& subset) {
    373     SkIRect ir;
    374     subset.roundOut(&ir);
    375 
    376     if (!ir.intersect(0, 0, bm.width()-1, bm.height()-1)) {
    377         return;
    378     }
    379 
    380     // Since we only want to return unique values in array, when we scan we just
    381     // set a bit for each index'd color found. In practice we only have a few
    382     // distinct colors, so we just use an int's bits as our array. Hence the
    383     // assert that count <= number-of-bits-in-our-int.
    384     SkASSERT((unsigned)count <= 32);
    385     uint32_t bitarray = 0;
    386 
    387     SkAutoLockPixels alp(bm);
    388 
    389     for (int y = ir.fTop; y < ir.fBottom; ++y) {
    390         for (int x = ir.fLeft; x < ir.fRight; ++x) {
    391             SkPMColor pmc = *bm.getAddr32(x, y);
    392             // the only good case where the color is not found would be if
    393             // the color is transparent, meaning no bitmap was drawn in that
    394             // pixel.
    395             if (pmc) {
    396                 uint32_t index = SkGetPackedR32(pmc);
    397                 SkASSERT(SkGetPackedG32(pmc) == index);
    398                 SkASSERT(SkGetPackedB32(pmc) == index);
    399                 if (0 == index) {
    400                     continue;           // background color
    401                 }
    402                 SkASSERT(0 == (index - gColorOffset) % gColorScale);
    403                 index = (index - gColorOffset) / gColorScale;
    404                 SkASSERT(static_cast<int>(index) < count);
    405                 bitarray |= 1 << index;
    406             }
    407         }
    408     }
    409 
    410     for (int i = 0; i < count; ++i) {
    411         if (bitarray & (1 << i)) {
    412             *array->append() = refs[i];
    413         }
    414     }
    415 }
    416 
    417 static void gather_from_analytic(const SkPoint pos[], SkScalar w, SkScalar h,
    418                                  const SkTDArray<SkPixelRef*> analytic[],
    419                                  int count,
    420                                  SkTDArray<SkPixelRef*>* result,
    421                                  const SkRect& subset) {
    422     for (int i = 0; i < count; ++i) {
    423         SkRect rect = SkRect::MakeXYWH(pos[i].fX, pos[i].fY, w, h);
    424 
    425         if (SkRect::Intersects(subset, rect)) {
    426             result->append(analytic[i].count(), analytic[i].begin());
    427         }
    428     }
    429 }
    430 
    431 
    432 static const struct {
    433     const DrawBitmapProc proc;
    434     const char* const desc;
    435 } gProcs[] = {
    436     {drawpaint_proc, "drawpaint"},
    437     {drawpoints_proc, "drawpoints"},
    438     {drawrect_proc, "drawrect"},
    439     {drawoval_proc, "drawoval"},
    440     {drawrrect_proc, "drawrrect"},
    441     {drawpath_proc, "drawpath"},
    442     {drawbitmap_proc, "drawbitmap"},
    443     {drawbitmap_withshader_proc, "drawbitmap_withshader"},
    444     {drawsprite_proc, "drawsprite"},
    445 #if 0
    446     {drawsprite_withshader_proc, "drawsprite_withshader"},
    447 #endif
    448     {drawbitmaprect_proc, "drawbitmaprect"},
    449     {drawbitmaprect_withshader_proc, "drawbitmaprect_withshader"},
    450     {drawtext_proc, "drawtext"},
    451     {drawpostext_proc, "drawpostext"},
    452     {drawtextonpath_proc, "drawtextonpath"},
    453     {drawverts_proc, "drawverts"},
    454 };
    455 
    456 static void create_textures(SkBitmap* bm, SkPixelRef** refs, int num, int w, int h) {
    457     // Our convention is that the color components contain an encoding of
    458     // the index of their corresponding bitmap/pixelref. (0,0,0,0) is
    459     // reserved for the background
    460     for (int i = 0; i < num; ++i) {
    461         make_bm(&bm[i], w, h,
    462                 SkColorSetARGB(0xFF,
    463                                gColorScale*i+gColorOffset,
    464                                gColorScale*i+gColorOffset,
    465                                gColorScale*i+gColorOffset),
    466                 true);
    467         refs[i] = bm[i].pixelRef();
    468     }
    469 
    470     // The A8 alternate bitmaps are all BW checkerboards
    471     for (int i = 0; i < num; ++i) {
    472         make_checkerboard(&bm[num+i], w, h, true);
    473         refs[num+i] = bm[num+i].pixelRef();
    474     }
    475 }
    476 
    477 static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
    478     const int IW = 32;
    479     const int IH = IW;
    480     const SkScalar W = SkIntToScalar(IW);
    481     const SkScalar H = W;
    482 
    483     static const int N = 4;
    484     SkBitmap bm[2*N];
    485     SkPixelRef* refs[2*N];
    486     SkTDArray<SkPixelRef*> analytic[N];
    487 
    488     const SkPoint pos[N] = {
    489         { 0, 0 }, { W, 0 }, { 0, H }, { W, H }
    490     };
    491 
    492     create_textures(bm, refs, N, IW, IH);
    493 
    494     SkRandom rand;
    495     for (size_t k = 0; k < SK_ARRAY_COUNT(gProcs); ++k) {
    496         SkAutoTUnref<SkPicture> pic(
    497             record_bitmaps(bm, pos, analytic, N, gProcs[k].proc));
    498 
    499         REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0);
    500         // quick check for a small piece of each quadrant, which should just
    501         // contain 1 or 2 bitmaps.
    502         for (size_t  i = 0; i < SK_ARRAY_COUNT(pos); ++i) {
    503             SkRect r;
    504             r.set(2, 2, W - 2, H - 2);
    505             r.offset(pos[i].fX, pos[i].fY);
    506             SkAutoDataUnref data(SkPictureUtils::GatherPixelRefs(pic, r));
    507             if (!data) {
    508                 ERRORF(reporter, "SkPictureUtils::GatherPixelRefs returned "
    509                        "NULL for %s.", gProcs[k].desc);
    510                 continue;
    511             }
    512             SkPixelRef** gatheredRefs = (SkPixelRef**)data->data();
    513             int count = static_cast<int>(data->size() / sizeof(SkPixelRef*));
    514             REPORTER_ASSERT(reporter, 1 == count || 2 == count);
    515             if (1 == count) {
    516                 REPORTER_ASSERT(reporter, gatheredRefs[0] == refs[i]);
    517             } else if (2 == count) {
    518                 REPORTER_ASSERT(reporter,
    519                     (gatheredRefs[0] == refs[i] && gatheredRefs[1] == refs[i+N]) ||
    520                     (gatheredRefs[1] == refs[i] && gatheredRefs[0] == refs[i+N]));
    521             }
    522         }
    523 
    524         SkBitmap image;
    525         draw(pic, 2*IW, 2*IH, &image);
    526 
    527         // Test a bunch of random (mostly) rects, and compare the gather results
    528         // with a deduced list of refs by looking at the colors drawn.
    529         for (int j = 0; j < 100; ++j) {
    530             SkRect r;
    531             rand_rect(&r, rand, 2*W, 2*H);
    532 
    533             SkTDArray<SkPixelRef*> fromImage;
    534             gather_from_image(image, refs, N, &fromImage, r);
    535 
    536             SkTDArray<SkPixelRef*> fromAnalytic;
    537             gather_from_analytic(pos, W, H, analytic, N, &fromAnalytic, r);
    538 
    539             SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
    540             size_t dataSize = data ? data->size() : 0;
    541             int gatherCount = static_cast<int>(dataSize / sizeof(SkPixelRef*));
    542             SkASSERT(gatherCount * sizeof(SkPixelRef*) == dataSize);
    543             SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL;
    544             SkAutoDataUnref adu(data);
    545 
    546             // Everything that we saw drawn should appear in the analytic list
    547             // but the analytic list may contain some pixelRefs that were not
    548             // seen in the image (e.g., A8 textures used as masks)
    549             for (int i = 0; i < fromImage.count(); ++i) {
    550                 if (-1 == fromAnalytic.find(fromImage[i])) {
    551                     ERRORF(reporter, "PixelRef missing %d %s",
    552                            i, gProcs[k].desc);
    553                 }
    554             }
    555 
    556             /*
    557              *  GatherPixelRefs is conservative, so it can return more bitmaps
    558              *  than are strictly required. Thus our check here is only that
    559              *  Gather didn't miss any that we actually needed. Even that isn't
    560              *  a strict requirement on Gather, which is meant to be quick and
    561              *  only mostly-correct, but at the moment this test should work.
    562              */
    563             for (int i = 0; i < fromAnalytic.count(); ++i) {
    564                 bool found = find(gatherRefs, fromAnalytic[i], gatherCount);
    565                 if (!found) {
    566                     ERRORF(reporter, "PixelRef missing %d %s",
    567                            i, gProcs[k].desc);
    568                 }
    569 #if 0
    570                 // enable this block of code to debug failures, as it will rerun
    571                 // the case that failed.
    572                 if (!found) {
    573                     SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
    574                     size_t dataSize = data ? data->size() : 0;
    575                 }
    576 #endif
    577             }
    578         }
    579     }
    580 }
    581 
    582 #define GENERATE_CANVAS(recorder, x) \
    583     (x) ? recorder.EXPERIMENTAL_beginRecording(100, 100) \
    584         : recorder.  DEPRECATED_beginRecording(100,100);
    585 
    586 /* Hit a few SkPicture::Analysis cases not handled elsewhere. */
    587 static void test_analysis(skiatest::Reporter* reporter, bool useNewPath) {
    588     SkPictureRecorder recorder;
    589 
    590     SkCanvas* canvas = GENERATE_CANVAS(recorder, useNewPath);
    591     {
    592         canvas->drawRect(SkRect::MakeWH(10, 10), SkPaint ());
    593     }
    594     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    595     REPORTER_ASSERT(reporter, !picture->willPlayBackBitmaps());
    596 
    597     canvas = GENERATE_CANVAS(recorder, useNewPath);
    598     {
    599         SkPaint paint;
    600         // CreateBitmapShader is too smart for us; an empty (or 1x1) bitmap shader
    601         // gets optimized into a non-bitmap form, so we create a 2x2 bitmap here.
    602         SkBitmap bitmap;
    603         bitmap.allocPixels(SkImageInfo::MakeN32Premul(2, 2));
    604         bitmap.eraseColor(SK_ColorBLUE);
    605         *(bitmap.getAddr32(0, 0)) = SK_ColorGREEN;
    606         SkShader* shader = SkShader::CreateBitmapShader(bitmap, SkShader::kClamp_TileMode,
    607                                                         SkShader::kClamp_TileMode);
    608         paint.setShader(shader)->unref();
    609         REPORTER_ASSERT(reporter,
    610                         shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType);
    611 
    612         canvas->drawRect(SkRect::MakeWH(10, 10), paint);
    613     }
    614     picture.reset(recorder.endRecording());
    615     REPORTER_ASSERT(reporter, picture->willPlayBackBitmaps());
    616 }
    617 
    618 
    619 static void test_gatherpixelrefsandrects(skiatest::Reporter* reporter) {
    620     const int IW = 32;
    621     const int IH = IW;
    622     const SkScalar W = SkIntToScalar(IW);
    623     const SkScalar H = W;
    624 
    625     static const int N = 4;
    626     SkBitmap bm[2*N];
    627     SkPixelRef* refs[2*N];
    628     SkTDArray<SkPixelRef*> analytic[N];
    629 
    630     const SkPoint pos[N] = {
    631         { 0, 0 }, { W, 0 }, { 0, H }, { W, H }
    632     };
    633 
    634     create_textures(bm, refs, N, IW, IH);
    635 
    636     SkRandom rand;
    637     for (size_t k = 0; k < SK_ARRAY_COUNT(gProcs); ++k) {
    638         SkAutoTUnref<SkPicture> pic(
    639             record_bitmaps(bm, pos, analytic, N, gProcs[k].proc));
    640 
    641         REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0);
    642 
    643         SkAutoTUnref<SkPictureUtils::SkPixelRefContainer> prCont(
    644                                 new SkPictureUtils::SkPixelRefsAndRectsList);
    645 
    646         SkPictureUtils::GatherPixelRefsAndRects(pic, prCont);
    647 
    648         // quick check for a small piece of each quadrant, which should just
    649         // contain 1 or 2 bitmaps.
    650         for (size_t  i = 0; i < SK_ARRAY_COUNT(pos); ++i) {
    651             SkRect r;
    652             r.set(2, 2, W - 2, H - 2);
    653             r.offset(pos[i].fX, pos[i].fY);
    654 
    655             SkTDArray<SkPixelRef*> gatheredRefs;
    656             prCont->query(r, &gatheredRefs);
    657 
    658             int count = gatheredRefs.count();
    659             REPORTER_ASSERT(reporter, 1 == count || 2 == count);
    660             if (1 == count) {
    661                 REPORTER_ASSERT(reporter, gatheredRefs[0] == refs[i]);
    662             } else if (2 == count) {
    663                 REPORTER_ASSERT(reporter,
    664                     (gatheredRefs[0] == refs[i] && gatheredRefs[1] == refs[i+N]) ||
    665                     (gatheredRefs[1] == refs[i] && gatheredRefs[0] == refs[i+N]));
    666             }
    667         }
    668 
    669         SkBitmap image;
    670         draw(pic, 2*IW, 2*IH, &image);
    671 
    672         // Test a bunch of random (mostly) rects, and compare the gather results
    673         // with the analytic results and the pixel refs seen in a rendering.
    674         for (int j = 0; j < 100; ++j) {
    675             SkRect r;
    676             rand_rect(&r, rand, 2*W, 2*H);
    677 
    678             SkTDArray<SkPixelRef*> fromImage;
    679             gather_from_image(image, refs, N, &fromImage, r);
    680 
    681             SkTDArray<SkPixelRef*> fromAnalytic;
    682             gather_from_analytic(pos, W, H, analytic, N, &fromAnalytic, r);
    683 
    684             SkTDArray<SkPixelRef*> gatheredRefs;
    685             prCont->query(r, &gatheredRefs);
    686 
    687             // Everything that we saw drawn should appear in the analytic list
    688             // but the analytic list may contain some pixelRefs that were not
    689             // seen in the image (e.g., A8 textures used as masks)
    690             for (int i = 0; i < fromImage.count(); ++i) {
    691                 REPORTER_ASSERT(reporter, -1 != fromAnalytic.find(fromImage[i]));
    692             }
    693 
    694             // Everything in the analytic list should appear in the gathered
    695             // list.
    696             for (int i = 0; i < fromAnalytic.count(); ++i) {
    697                 REPORTER_ASSERT(reporter, -1 != gatheredRefs.find(fromAnalytic[i]));
    698             }
    699         }
    700     }
    701 }
    702 
    703 #ifdef SK_DEBUG
    704 // Ensure that deleting an empty SkPicture does not assert. Asserts only fire
    705 // in debug mode, so only run in debug mode.
    706 static void test_deleting_empty_picture() {
    707     SkPictureRecorder recorder;
    708     // Creates an SkPictureRecord
    709     recorder.beginRecording(0, 0);
    710     // Turns that into an SkPicture
    711     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    712     // Ceates a new SkPictureRecord
    713     recorder.beginRecording(0, 0);
    714 }
    715 
    716 // Ensure that serializing an empty picture does not assert. Likewise only runs in debug mode.
    717 static void test_serializing_empty_picture() {
    718     SkPictureRecorder recorder;
    719     recorder.beginRecording(0, 0);
    720     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    721     SkDynamicMemoryWStream stream;
    722     picture->serialize(&stream);
    723 }
    724 #endif
    725 
    726 static void rand_op(SkCanvas* canvas, SkRandom& rand) {
    727     SkPaint paint;
    728     SkRect rect = SkRect::MakeWH(50, 50);
    729 
    730     SkScalar unit = rand.nextUScalar1();
    731     if (unit <= 0.3) {
    732 //        SkDebugf("save\n");
    733         canvas->save();
    734     } else if (unit <= 0.6) {
    735 //        SkDebugf("restore\n");
    736         canvas->restore();
    737     } else if (unit <= 0.9) {
    738 //        SkDebugf("clip\n");
    739         canvas->clipRect(rect);
    740     } else {
    741 //        SkDebugf("draw\n");
    742         canvas->drawPaint(paint);
    743     }
    744 }
    745 
    746 #if SK_SUPPORT_GPU
    747 
    748 static void test_gpu_veto(skiatest::Reporter* reporter,
    749                           bool useNewPath) {
    750 
    751     SkPictureRecorder recorder;
    752 
    753     SkCanvas* canvas = GENERATE_CANVAS(recorder, useNewPath);
    754     {
    755         SkPath path;
    756         path.moveTo(0, 0);
    757         path.lineTo(50, 50);
    758 
    759         SkScalar intervals[] = { 1.0f, 1.0f };
    760         SkAutoTUnref<SkDashPathEffect> dash(SkDashPathEffect::Create(intervals, 2, 0));
    761 
    762         SkPaint paint;
    763         paint.setStyle(SkPaint::kStroke_Style);
    764         paint.setPathEffect(dash);
    765 
    766         canvas->drawPath(path, paint);
    767     }
    768     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    769     // path effects currently render an SkPicture undesireable for GPU rendering
    770 
    771     const char *reason = NULL;
    772     REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(NULL, &reason));
    773     REPORTER_ASSERT(reporter, reason);
    774 
    775     canvas = GENERATE_CANVAS(recorder, useNewPath);
    776     {
    777         SkPath path;
    778 
    779         path.moveTo(0, 0);
    780         path.lineTo(0, 50);
    781         path.lineTo(25, 25);
    782         path.lineTo(50, 50);
    783         path.lineTo(50, 0);
    784         path.close();
    785         REPORTER_ASSERT(reporter, !path.isConvex());
    786 
    787         SkPaint paint;
    788         paint.setAntiAlias(true);
    789         for (int i = 0; i < 50; ++i) {
    790             canvas->drawPath(path, paint);
    791         }
    792     }
    793     picture.reset(recorder.endRecording());
    794     // A lot of AA concave paths currently render an SkPicture undesireable for GPU rendering
    795     REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(NULL));
    796 
    797     canvas = GENERATE_CANVAS(recorder, useNewPath);
    798     {
    799         SkPath path;
    800 
    801         path.moveTo(0, 0);
    802         path.lineTo(0, 50);
    803         path.lineTo(25, 25);
    804         path.lineTo(50, 50);
    805         path.lineTo(50, 0);
    806         path.close();
    807         REPORTER_ASSERT(reporter, !path.isConvex());
    808 
    809         SkPaint paint;
    810         paint.setAntiAlias(true);
    811         paint.setStyle(SkPaint::kStroke_Style);
    812         paint.setStrokeWidth(0);
    813         for (int i = 0; i < 50; ++i) {
    814             canvas->drawPath(path, paint);
    815         }
    816     }
    817     picture.reset(recorder.endRecording());
    818     // hairline stroked AA concave paths are fine for GPU rendering
    819     REPORTER_ASSERT(reporter, picture->suitableForGpuRasterization(NULL));
    820 
    821     canvas = GENERATE_CANVAS(recorder, useNewPath);
    822     {
    823         SkPaint paint;
    824         SkScalar intervals [] = { 10, 20 };
    825         SkPathEffect* pe = SkDashPathEffect::Create(intervals, 2, 25);
    826         paint.setPathEffect(pe)->unref();
    827 
    828         SkPoint points [2] = { { 0, 0 }, { 100, 0 } };
    829         canvas->drawPoints(SkCanvas::kLines_PointMode, 2, points, paint);
    830     }
    831     picture.reset(recorder.endRecording());
    832     // fast-path dashed effects are fine for GPU rendering ...
    833     REPORTER_ASSERT(reporter, picture->suitableForGpuRasterization(NULL));
    834 
    835     canvas = GENERATE_CANVAS(recorder, useNewPath);
    836     {
    837         SkPaint paint;
    838         SkScalar intervals [] = { 10, 20 };
    839         SkPathEffect* pe = SkDashPathEffect::Create(intervals, 2, 25);
    840         paint.setPathEffect(pe)->unref();
    841 
    842         canvas->drawRect(SkRect::MakeWH(10, 10), paint);
    843     }
    844     picture.reset(recorder.endRecording());
    845     // ... but only when applied to drawPoint() calls
    846     REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(NULL));
    847 
    848     // Nest the previous picture inside a new one.
    849     // This doesn't work in the old backend.
    850     if (useNewPath) {
    851         canvas = GENERATE_CANVAS(recorder, useNewPath);
    852         {
    853             canvas->drawPicture(picture.get());
    854         }
    855         picture.reset(recorder.endRecording());
    856         REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(NULL));
    857     }
    858 }
    859 
    860 #undef GENERATE_CANVAS
    861 
    862 static void test_gpu_picture_optimization(skiatest::Reporter* reporter,
    863                                           GrContextFactory* factory) {
    864     for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
    865         GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
    866 
    867         if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
    868             continue;
    869         }
    870 
    871         GrContext* context = factory->get(glCtxType);
    872 
    873         if (NULL == context) {
    874             continue;
    875         }
    876 
    877         static const int kWidth = 100;
    878         static const int kHeight = 100;
    879 
    880         SkAutoTUnref<SkPicture> pict, child;
    881 
    882         {
    883             SkPictureRecorder recorder;
    884 
    885             SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
    886 
    887             c->saveLayer(NULL, NULL);
    888             c->restore();
    889 
    890             child.reset(recorder.endRecording());
    891         }
    892 
    893         // create a picture with the structure:
    894         // 1)
    895         //      SaveLayer
    896         //      Restore
    897         // 2)
    898         //      SaveLayer
    899         //          Translate
    900         //          SaveLayer w/ bound
    901         //          Restore
    902         //      Restore
    903         // 3)
    904         //      SaveLayer w/ copyable paint
    905         //      Restore
    906         // 4)
    907         //      SaveLayer
    908         //          DrawPicture (which has a SaveLayer/Restore pair)
    909         //      Restore
    910         // 5)
    911         //      SaveLayer
    912         //          DrawPicture with Matrix & Paint (with SaveLayer/Restore pair)
    913         //      Restore
    914         {
    915             SkPictureRecorder recorder;
    916 
    917             SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth),
    918                                                   SkIntToScalar(kHeight));
    919             // 1)
    920             c->saveLayer(NULL, NULL); // layer #0
    921             c->restore();
    922 
    923             // 2)
    924             c->saveLayer(NULL, NULL); // layer #1
    925                 c->translate(kWidth/2.0f, kHeight/2.0f);
    926                 SkRect r = SkRect::MakeXYWH(0, 0, kWidth/2, kHeight/2);
    927                 c->saveLayer(&r, NULL); // layer #2
    928                 c->restore();
    929             c->restore();
    930 
    931             // 3)
    932             {
    933                 SkPaint p;
    934                 p.setColor(SK_ColorRED);
    935                 c->saveLayer(NULL, &p); // layer #3
    936                 c->restore();
    937             }
    938 
    939             SkPaint layerPaint;
    940             layerPaint.setColor(SK_ColorRED);  // Non-alpha only to avoid SaveLayerDrawRestoreNooper
    941             // 4)
    942             {
    943                 c->saveLayer(NULL, &layerPaint);  // layer #4
    944                     c->drawPicture(child);  // layer #5 inside picture
    945                 c->restore();
    946             }
    947             // 5
    948             {
    949                 SkPaint picturePaint;
    950                 SkMatrix trans;
    951                 trans.setTranslate(10, 10);
    952 
    953                 c->saveLayer(NULL, &layerPaint);  // layer #6
    954                     c->drawPicture(child, &trans, &picturePaint); // layer #7 inside picture
    955                 c->restore();
    956             }
    957 
    958             pict.reset(recorder.endRecording());
    959         }
    960 
    961         // Now test out the SaveLayer extraction
    962         {
    963             SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
    964 
    965             SkAutoTUnref<SkSurface> surface(SkSurface::NewScratchRenderTarget(context, info));
    966 
    967             SkCanvas* canvas = surface->getCanvas();
    968 
    969             canvas->EXPERIMENTAL_optimize(pict);
    970 
    971             SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
    972 
    973             const SkPicture::AccelData* data = pict->EXPERIMENTAL_getAccelData(key);
    974             REPORTER_ASSERT(reporter, data);
    975 
    976             const GrAccelData *gpuData = static_cast<const GrAccelData*>(data);
    977             REPORTER_ASSERT(reporter, 8 == gpuData->numSaveLayers());
    978 
    979             const GrAccelData::SaveLayerInfo& info0 = gpuData->saveLayerInfo(0);
    980             // The parent/child layers appear in reverse order
    981             const GrAccelData::SaveLayerInfo& info1 = gpuData->saveLayerInfo(2);
    982             const GrAccelData::SaveLayerInfo& info2 = gpuData->saveLayerInfo(1);
    983 
    984             const GrAccelData::SaveLayerInfo& info3 = gpuData->saveLayerInfo(3);
    985 
    986             // The parent/child layers appear in reverse order
    987             const GrAccelData::SaveLayerInfo& info4 = gpuData->saveLayerInfo(5);
    988             const GrAccelData::SaveLayerInfo& info5 = gpuData->saveLayerInfo(4);
    989 
    990             // The parent/child layers appear in reverse order
    991             const GrAccelData::SaveLayerInfo& info6 = gpuData->saveLayerInfo(7);
    992             const GrAccelData::SaveLayerInfo& info7 = gpuData->saveLayerInfo(6);
    993 
    994             REPORTER_ASSERT(reporter, info0.fValid);
    995             REPORTER_ASSERT(reporter, NULL == info0.fPicture);
    996             REPORTER_ASSERT(reporter, kWidth == info0.fSize.fWidth &&
    997                                       kHeight == info0.fSize.fHeight);
    998             REPORTER_ASSERT(reporter, info0.fOriginXform.isIdentity());
    999             REPORTER_ASSERT(reporter, 0 == info0.fOffset.fX && 0 == info0.fOffset.fY);
   1000             REPORTER_ASSERT(reporter, NULL == info0.fPaint);
   1001             REPORTER_ASSERT(reporter, !info0.fIsNested && !info0.fHasNestedLayers);
   1002 
   1003             REPORTER_ASSERT(reporter, info1.fValid);
   1004             REPORTER_ASSERT(reporter, NULL == info1.fPicture);
   1005             REPORTER_ASSERT(reporter, kWidth == info1.fSize.fWidth &&
   1006                                       kHeight == info1.fSize.fHeight);
   1007             REPORTER_ASSERT(reporter, info1.fOriginXform.isIdentity());
   1008             REPORTER_ASSERT(reporter, 0 == info1.fOffset.fX && 0 == info1.fOffset.fY);
   1009             REPORTER_ASSERT(reporter, NULL == info1.fPaint);
   1010             REPORTER_ASSERT(reporter, !info1.fIsNested &&
   1011                                       info1.fHasNestedLayers); // has a nested SL
   1012 
   1013             REPORTER_ASSERT(reporter, info2.fValid);
   1014             REPORTER_ASSERT(reporter, NULL == info2.fPicture);
   1015             REPORTER_ASSERT(reporter, kWidth / 2 == info2.fSize.fWidth &&
   1016                                       kHeight/2 == info2.fSize.fHeight); // bound reduces size
   1017             REPORTER_ASSERT(reporter, !info2.fOriginXform.isIdentity());
   1018             REPORTER_ASSERT(reporter, kWidth/2 == info2.fOffset.fX &&   // translated
   1019                                       kHeight/2 == info2.fOffset.fY);
   1020             REPORTER_ASSERT(reporter, NULL == info1.fPaint);
   1021             REPORTER_ASSERT(reporter, info2.fIsNested && !info2.fHasNestedLayers); // is nested
   1022 
   1023             REPORTER_ASSERT(reporter, info3.fValid);
   1024             REPORTER_ASSERT(reporter, NULL == info3.fPicture);
   1025             REPORTER_ASSERT(reporter, kWidth == info3.fSize.fWidth &&
   1026                                       kHeight == info3.fSize.fHeight);
   1027             REPORTER_ASSERT(reporter, info3.fOriginXform.isIdentity());
   1028             REPORTER_ASSERT(reporter, 0 == info3.fOffset.fX && 0 == info3.fOffset.fY);
   1029             REPORTER_ASSERT(reporter, info3.fPaint);
   1030             REPORTER_ASSERT(reporter, !info3.fIsNested && !info3.fHasNestedLayers);
   1031 
   1032             REPORTER_ASSERT(reporter, info4.fValid);
   1033             REPORTER_ASSERT(reporter, NULL == info4.fPicture);
   1034             REPORTER_ASSERT(reporter, kWidth == info4.fSize.fWidth &&
   1035                                       kHeight == info4.fSize.fHeight);
   1036             REPORTER_ASSERT(reporter, 0 == info4.fOffset.fX && 0 == info4.fOffset.fY);
   1037             REPORTER_ASSERT(reporter, info4.fOriginXform.isIdentity());
   1038             REPORTER_ASSERT(reporter, info4.fPaint);
   1039             REPORTER_ASSERT(reporter, !info4.fIsNested &&
   1040                                       info4.fHasNestedLayers); // has a nested SL
   1041 
   1042             REPORTER_ASSERT(reporter, info5.fValid);
   1043             REPORTER_ASSERT(reporter, child == info5.fPicture); // in a child picture
   1044             REPORTER_ASSERT(reporter, kWidth == info5.fSize.fWidth &&
   1045                                       kHeight == info5.fSize.fHeight);
   1046             REPORTER_ASSERT(reporter, 0 == info5.fOffset.fX && 0 == info5.fOffset.fY);
   1047             REPORTER_ASSERT(reporter, info5.fOriginXform.isIdentity());
   1048             REPORTER_ASSERT(reporter, NULL == info5.fPaint);
   1049             REPORTER_ASSERT(reporter, info5.fIsNested && !info5.fHasNestedLayers); // is nested
   1050 
   1051             REPORTER_ASSERT(reporter, info6.fValid);
   1052             REPORTER_ASSERT(reporter, NULL == info6.fPicture);
   1053             REPORTER_ASSERT(reporter, kWidth == info6.fSize.fWidth &&
   1054                                       kHeight == info6.fSize.fHeight);
   1055             REPORTER_ASSERT(reporter, 0 == info6.fOffset.fX && 0 == info6.fOffset.fY);
   1056             REPORTER_ASSERT(reporter, info6.fOriginXform.isIdentity());
   1057             REPORTER_ASSERT(reporter, info6.fPaint);
   1058             REPORTER_ASSERT(reporter, !info6.fIsNested &&
   1059                                       info6.fHasNestedLayers); // has a nested SL
   1060 
   1061             REPORTER_ASSERT(reporter, info7.fValid);
   1062             REPORTER_ASSERT(reporter, child == info7.fPicture); // in a child picture
   1063             REPORTER_ASSERT(reporter, kWidth == info7.fSize.fWidth &&
   1064                                       kHeight == info7.fSize.fHeight);
   1065             REPORTER_ASSERT(reporter, 0 == info7.fOffset.fX && 0 == info7.fOffset.fY);
   1066             REPORTER_ASSERT(reporter, info7.fOriginXform.isIdentity());
   1067             REPORTER_ASSERT(reporter, NULL == info7.fPaint);
   1068             REPORTER_ASSERT(reporter, info7.fIsNested && !info7.fHasNestedLayers); // is nested
   1069         }
   1070     }
   1071 }
   1072 
   1073 #endif
   1074 
   1075 static void test_has_text(skiatest::Reporter* reporter, bool useNewPath) {
   1076     SkPictureRecorder recorder;
   1077 #define BEGIN_RECORDING useNewPath ? recorder.EXPERIMENTAL_beginRecording(100, 100) \
   1078                                    : recorder.  DEPRECATED_beginRecording(100, 100)
   1079 
   1080     SkCanvas* canvas = BEGIN_RECORDING;
   1081     {
   1082         canvas->drawRect(SkRect::MakeWH(20, 20), SkPaint());
   1083     }
   1084     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1085     REPORTER_ASSERT(reporter, !picture->hasText());
   1086 
   1087     SkPoint point = SkPoint::Make(10, 10);
   1088     canvas = BEGIN_RECORDING;
   1089     {
   1090         canvas->drawText("Q", 1, point.fX, point.fY, SkPaint());
   1091     }
   1092     picture.reset(recorder.endRecording());
   1093     REPORTER_ASSERT(reporter, picture->hasText());
   1094 
   1095     canvas = BEGIN_RECORDING;
   1096     {
   1097         canvas->drawPosText("Q", 1, &point, SkPaint());
   1098     }
   1099     picture.reset(recorder.endRecording());
   1100     REPORTER_ASSERT(reporter, picture->hasText());
   1101 
   1102     canvas = BEGIN_RECORDING;
   1103     {
   1104         canvas->drawPosTextH("Q", 1, &point.fX, point.fY, SkPaint());
   1105     }
   1106     picture.reset(recorder.endRecording());
   1107     REPORTER_ASSERT(reporter, picture->hasText());
   1108 
   1109     canvas = BEGIN_RECORDING;
   1110     {
   1111         SkPath path;
   1112         path.moveTo(0, 0);
   1113         path.lineTo(50, 50);
   1114 
   1115         canvas->drawTextOnPathHV("Q", 1, path, point.fX, point.fY, SkPaint());
   1116     }
   1117     picture.reset(recorder.endRecording());
   1118     REPORTER_ASSERT(reporter, picture->hasText());
   1119 
   1120     canvas = BEGIN_RECORDING;
   1121     {
   1122         SkPath path;
   1123         path.moveTo(0, 0);
   1124         path.lineTo(50, 50);
   1125 
   1126         canvas->drawTextOnPath("Q", 1, path, NULL, SkPaint());
   1127     }
   1128     picture.reset(recorder.endRecording());
   1129     REPORTER_ASSERT(reporter, picture->hasText());
   1130 
   1131     // Nest the previous picture inside a new one.
   1132     // This doesn't work in the old backend.
   1133     if (useNewPath) {
   1134         canvas = BEGIN_RECORDING;
   1135         {
   1136             canvas->drawPicture(picture.get());
   1137         }
   1138         picture.reset(recorder.endRecording());
   1139         REPORTER_ASSERT(reporter, picture->hasText());
   1140     }
   1141 #undef BEGIN_RECORDING
   1142 }
   1143 
   1144 static void set_canvas_to_save_count_4(SkCanvas* canvas) {
   1145     canvas->restoreToCount(1);
   1146     canvas->save();
   1147     canvas->save();
   1148     canvas->save();
   1149 }
   1150 
   1151 /**
   1152  * A canvas that records the number of saves, saveLayers and restores.
   1153  */
   1154 class SaveCountingCanvas : public SkCanvas {
   1155 public:
   1156     SaveCountingCanvas(int width, int height)
   1157         : INHERITED(width, height)
   1158         , fSaveCount(0)
   1159         , fSaveLayerCount(0)
   1160         , fRestoreCount(0){
   1161     }
   1162 
   1163     virtual SaveLayerStrategy willSaveLayer(const SkRect* bounds, const SkPaint* paint,
   1164                                             SaveFlags flags) SK_OVERRIDE {
   1165         ++fSaveLayerCount;
   1166         return this->INHERITED::willSaveLayer(bounds, paint, flags);
   1167     }
   1168 
   1169     virtual void willSave() SK_OVERRIDE {
   1170         ++fSaveCount;
   1171         this->INHERITED::willSave();
   1172     }
   1173 
   1174     virtual void willRestore() SK_OVERRIDE {
   1175         ++fRestoreCount;
   1176         this->INHERITED::willRestore();
   1177     }
   1178 
   1179     unsigned int getSaveCount() const { return fSaveCount; }
   1180     unsigned int getSaveLayerCount() const { return fSaveLayerCount; }
   1181     unsigned int getRestoreCount() const { return fRestoreCount; }
   1182 
   1183 private:
   1184     unsigned int fSaveCount;
   1185     unsigned int fSaveLayerCount;
   1186     unsigned int fRestoreCount;
   1187 
   1188     typedef SkCanvas INHERITED;
   1189 };
   1190 
   1191 void check_save_state(skiatest::Reporter* reporter, SkPicture* picture,
   1192                       unsigned int numSaves, unsigned int numSaveLayers,
   1193                       unsigned int numRestores) {
   1194     SaveCountingCanvas canvas(SkScalarCeilToInt(picture->cullRect().width()),
   1195                               SkScalarCeilToInt(picture->cullRect().height()));
   1196 
   1197     picture->playback(&canvas);
   1198 
   1199     // Optimizations may have removed these,
   1200     // so expect to have seen no more than num{Saves,SaveLayers,Restores}.
   1201     REPORTER_ASSERT(reporter, numSaves >= canvas.getSaveCount());
   1202     REPORTER_ASSERT(reporter, numSaveLayers >= canvas.getSaveLayerCount());
   1203     REPORTER_ASSERT(reporter, numRestores >= canvas.getRestoreCount());
   1204 }
   1205 
   1206 // This class exists so SkPicture can friend it and give it access to
   1207 // the 'partialReplay' method.
   1208 class SkPictureRecorderReplayTester {
   1209 public:
   1210     static SkPicture* Copy(SkPictureRecorder* recorder) {
   1211         SkPictureRecorder recorder2;
   1212 
   1213         SkCanvas* canvas = recorder2.beginRecording(10, 10);
   1214 
   1215         recorder->partialReplay(canvas);
   1216 
   1217         return recorder2.endRecording();
   1218     }
   1219 };
   1220 
   1221 static void create_imbalance(SkCanvas* canvas) {
   1222     SkRect clipRect = SkRect::MakeWH(2, 2);
   1223     SkRect drawRect = SkRect::MakeWH(10, 10);
   1224     canvas->save();
   1225         canvas->clipRect(clipRect, SkRegion::kReplace_Op);
   1226         canvas->translate(1.0f, 1.0f);
   1227         SkPaint p;
   1228         p.setColor(SK_ColorGREEN);
   1229         canvas->drawRect(drawRect, p);
   1230     // no restore
   1231 }
   1232 
   1233 // This tests that replaying a potentially unbalanced picture into a canvas
   1234 // doesn't affect the canvas' save count or matrix/clip state.
   1235 static void check_balance(skiatest::Reporter* reporter, SkPicture* picture) {
   1236     SkBitmap bm;
   1237     bm.allocN32Pixels(4, 3);
   1238     SkCanvas canvas(bm);
   1239 
   1240     int beforeSaveCount = canvas.getSaveCount();
   1241 
   1242     SkMatrix beforeMatrix = canvas.getTotalMatrix();
   1243 
   1244     SkRect beforeClip;
   1245 
   1246     canvas.getClipBounds(&beforeClip);
   1247 
   1248     canvas.drawPicture(picture);
   1249 
   1250     REPORTER_ASSERT(reporter, beforeSaveCount == canvas.getSaveCount());
   1251     REPORTER_ASSERT(reporter, beforeMatrix == canvas.getTotalMatrix());
   1252 
   1253     SkRect afterClip;
   1254 
   1255     canvas.getClipBounds(&afterClip);
   1256 
   1257     REPORTER_ASSERT(reporter, afterClip == beforeClip);
   1258 }
   1259 
   1260 // Test out SkPictureRecorder::partialReplay
   1261 DEF_TEST(PictureRecorder_replay, reporter) {
   1262     // check save/saveLayer state
   1263     {
   1264         SkPictureRecorder recorder;
   1265 
   1266         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1267 
   1268         canvas->saveLayer(NULL, NULL);
   1269 
   1270         SkAutoTUnref<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder));
   1271 
   1272         // The extra save and restore comes from the Copy process.
   1273         check_save_state(reporter, copy, 2, 1, 3);
   1274 
   1275         canvas->saveLayer(NULL, NULL);
   1276 
   1277         SkAutoTUnref<SkPicture> final(recorder.endRecording());
   1278 
   1279         check_save_state(reporter, final, 1, 2, 3);
   1280 
   1281         // The copy shouldn't pick up any operations added after it was made
   1282         check_save_state(reporter, copy, 2, 1, 3);
   1283     }
   1284 
   1285     // (partially) check leakage of draw ops
   1286     {
   1287         SkPictureRecorder recorder;
   1288 
   1289         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1290 
   1291         SkRect r = SkRect::MakeWH(5, 5);
   1292         SkPaint p;
   1293 
   1294         canvas->drawRect(r, p);
   1295 
   1296         SkAutoTUnref<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder));
   1297 
   1298         REPORTER_ASSERT(reporter, !copy->willPlayBackBitmaps());
   1299 
   1300         SkBitmap bm;
   1301         make_bm(&bm, 10, 10, SK_ColorRED, true);
   1302 
   1303         r.offset(5.0f, 5.0f);
   1304         canvas->drawBitmapRectToRect(bm, NULL, r);
   1305 
   1306         SkAutoTUnref<SkPicture> final(recorder.endRecording());
   1307         REPORTER_ASSERT(reporter, final->willPlayBackBitmaps());
   1308 
   1309         REPORTER_ASSERT(reporter, copy->uniqueID() != final->uniqueID());
   1310 
   1311         // The snapshot shouldn't pick up any operations added after it was made
   1312         REPORTER_ASSERT(reporter, !copy->willPlayBackBitmaps());
   1313     }
   1314 
   1315     // Recreate the Android partialReplay test case
   1316     {
   1317         SkPictureRecorder recorder;
   1318 
   1319         SkCanvas* canvas = recorder.beginRecording(4, 3, NULL, 0);
   1320         create_imbalance(canvas);
   1321 
   1322         int expectedSaveCount = canvas->getSaveCount();
   1323 
   1324         SkAutoTUnref<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder));
   1325         check_balance(reporter, copy);
   1326 
   1327         REPORTER_ASSERT(reporter, expectedSaveCount = canvas->getSaveCount());
   1328 
   1329         // End the recording of source to test the picture finalization
   1330         // process isn't complicated by the partialReplay step
   1331         SkAutoTUnref<SkPicture> final(recorder.endRecording());
   1332     }
   1333 }
   1334 
   1335 static void test_unbalanced_save_restores(skiatest::Reporter* reporter) {
   1336     SkCanvas testCanvas(100, 100);
   1337     set_canvas_to_save_count_4(&testCanvas);
   1338 
   1339     REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
   1340 
   1341     SkPaint paint;
   1342     SkRect rect = SkRect::MakeLTRB(-10000000, -10000000, 10000000, 10000000);
   1343 
   1344     SkPictureRecorder recorder;
   1345 
   1346     {
   1347         // Create picture with 2 unbalanced saves
   1348         SkCanvas* canvas = recorder.beginRecording(100, 100);
   1349         canvas->save();
   1350         canvas->translate(10, 10);
   1351         canvas->drawRect(rect, paint);
   1352         canvas->save();
   1353         canvas->translate(10, 10);
   1354         canvas->drawRect(rect, paint);
   1355         SkAutoTUnref<SkPicture> extraSavePicture(recorder.endRecording());
   1356 
   1357         testCanvas.drawPicture(extraSavePicture);
   1358         REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
   1359     }
   1360 
   1361     set_canvas_to_save_count_4(&testCanvas);
   1362 
   1363     {
   1364         // Create picture with 2 unbalanced restores
   1365         SkCanvas* canvas = recorder.beginRecording(100, 100);
   1366         canvas->save();
   1367         canvas->translate(10, 10);
   1368         canvas->drawRect(rect, paint);
   1369         canvas->save();
   1370         canvas->translate(10, 10);
   1371         canvas->drawRect(rect, paint);
   1372         canvas->restore();
   1373         canvas->restore();
   1374         canvas->restore();
   1375         canvas->restore();
   1376         SkAutoTUnref<SkPicture> extraRestorePicture(recorder.endRecording());
   1377 
   1378         testCanvas.drawPicture(extraRestorePicture);
   1379         REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
   1380     }
   1381 
   1382     set_canvas_to_save_count_4(&testCanvas);
   1383 
   1384     {
   1385         SkCanvas* canvas = recorder.beginRecording(100, 100);
   1386         canvas->translate(10, 10);
   1387         canvas->drawRect(rect, paint);
   1388         SkAutoTUnref<SkPicture> noSavePicture(recorder.endRecording());
   1389 
   1390         testCanvas.drawPicture(noSavePicture);
   1391         REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
   1392         REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity());
   1393     }
   1394 }
   1395 
   1396 static void test_peephole() {
   1397     SkRandom rand;
   1398 
   1399     SkPictureRecorder recorder;
   1400 
   1401     for (int j = 0; j < 100; j++) {
   1402         SkRandom rand2(rand); // remember the seed
   1403 
   1404         SkCanvas* canvas = recorder.beginRecording(100, 100);
   1405 
   1406         for (int i = 0; i < 1000; ++i) {
   1407             rand_op(canvas, rand);
   1408         }
   1409         SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1410 
   1411         rand = rand2;
   1412     }
   1413 
   1414     {
   1415         SkCanvas* canvas = recorder.beginRecording(100, 100);
   1416         SkRect rect = SkRect::MakeWH(50, 50);
   1417 
   1418         for (int i = 0; i < 100; ++i) {
   1419             canvas->save();
   1420         }
   1421         while (canvas->getSaveCount() > 1) {
   1422             canvas->clipRect(rect);
   1423             canvas->restore();
   1424         }
   1425         SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1426     }
   1427 }
   1428 
   1429 #ifndef SK_DEBUG
   1430 // Only test this is in release mode. We deliberately crash in debug mode, since a valid caller
   1431 // should never do this.
   1432 static void test_bad_bitmap() {
   1433     // This bitmap has a width and height but no pixels. As a result, attempting to record it will
   1434     // fail.
   1435     SkBitmap bm;
   1436     bm.setInfo(SkImageInfo::MakeN32Premul(100, 100));
   1437     SkPictureRecorder recorder;
   1438     SkCanvas* recordingCanvas = recorder.beginRecording(100, 100);
   1439     recordingCanvas->drawBitmap(bm, 0, 0);
   1440     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1441 
   1442     SkCanvas canvas;
   1443     canvas.drawPicture(picture);
   1444 }
   1445 #endif
   1446 
   1447 static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) {
   1448     return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100);
   1449 }
   1450 
   1451 static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) {
   1452     SkPictureRecorder recorder;
   1453     SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bitmap.width()),
   1454                                                SkIntToScalar(bitmap.height()));
   1455     canvas->drawBitmap(bitmap, 0, 0);
   1456     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1457 
   1458     SkDynamicMemoryWStream wStream;
   1459     picture->serialize(&wStream, &encode_bitmap_to_data);
   1460     return wStream.copyToData();
   1461 }
   1462 
   1463 struct ErrorContext {
   1464     int fErrors;
   1465     skiatest::Reporter* fReporter;
   1466 };
   1467 
   1468 static void assert_one_parse_error_cb(SkError error, void* context) {
   1469     ErrorContext* errorContext = static_cast<ErrorContext*>(context);
   1470     errorContext->fErrors++;
   1471     // This test only expects one error, and that is a kParseError. If there are others,
   1472     // there is some unknown problem.
   1473     REPORTER_ASSERT_MESSAGE(errorContext->fReporter, 1 == errorContext->fErrors,
   1474                             "This threw more errors than expected.");
   1475     REPORTER_ASSERT_MESSAGE(errorContext->fReporter, kParseError_SkError == error,
   1476                             SkGetLastErrorString());
   1477 }
   1478 
   1479 static void test_bitmap_with_encoded_data(skiatest::Reporter* reporter) {
   1480     // Create a bitmap that will be encoded.
   1481     SkBitmap original;
   1482     make_bm(&original, 100, 100, SK_ColorBLUE, true);
   1483     SkDynamicMemoryWStream wStream;
   1484     if (!SkImageEncoder::EncodeStream(&wStream, original, SkImageEncoder::kPNG_Type, 100)) {
   1485         return;
   1486     }
   1487     SkAutoDataUnref data(wStream.copyToData());
   1488 
   1489     SkBitmap bm;
   1490     bool installSuccess = SkInstallDiscardablePixelRef(
   1491          SkDecodingImageGenerator::Create(data, SkDecodingImageGenerator::Options()), &bm);
   1492     REPORTER_ASSERT(reporter, installSuccess);
   1493 
   1494     // Write both bitmaps to pictures, and ensure that the resulting data streams are the same.
   1495     // Flattening original will follow the old path of performing an encode, while flattening bm
   1496     // will use the already encoded data.
   1497     SkAutoDataUnref picture1(serialized_picture_from_bitmap(original));
   1498     SkAutoDataUnref picture2(serialized_picture_from_bitmap(bm));
   1499     REPORTER_ASSERT(reporter, picture1->equals(picture2));
   1500     // Now test that a parse error was generated when trying to create a new SkPicture without
   1501     // providing a function to decode the bitmap.
   1502     ErrorContext context;
   1503     context.fErrors = 0;
   1504     context.fReporter = reporter;
   1505     SkSetErrorCallback(assert_one_parse_error_cb, &context);
   1506     SkMemoryStream pictureStream(picture1);
   1507     SkClearLastError();
   1508     SkAutoUnref pictureFromStream(SkPicture::CreateFromStream(&pictureStream, NULL));
   1509     REPORTER_ASSERT(reporter, pictureFromStream.get() != NULL);
   1510     SkClearLastError();
   1511     SkSetErrorCallback(NULL, NULL);
   1512 }
   1513 
   1514 static void test_draw_empty(skiatest::Reporter* reporter) {
   1515     SkBitmap result;
   1516     make_bm(&result, 2, 2, SK_ColorBLACK, false);
   1517 
   1518     SkCanvas canvas(result);
   1519 
   1520     {
   1521         // stock SkPicture
   1522         SkPictureRecorder recorder;
   1523         recorder.beginRecording(1, 1);
   1524         SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1525 
   1526         canvas.drawPicture(picture);
   1527     }
   1528 
   1529     {
   1530         // tile grid
   1531         SkTileGridFactory::TileGridInfo gridInfo;
   1532         gridInfo.fMargin.setEmpty();
   1533         gridInfo.fOffset.setZero();
   1534         gridInfo.fTileInterval.set(1, 1);
   1535 
   1536         SkTileGridFactory factory(gridInfo);
   1537         SkPictureRecorder recorder;
   1538         recorder.beginRecording(1, 1, &factory);
   1539         SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1540 
   1541         canvas.drawPicture(picture);
   1542     }
   1543 
   1544     {
   1545         // RTree
   1546         SkRTreeFactory factory;
   1547         SkPictureRecorder recorder;
   1548         recorder.beginRecording(1, 1, &factory);
   1549         SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1550 
   1551         canvas.drawPicture(picture);
   1552     }
   1553 }
   1554 
   1555 static void test_clip_bound_opt(skiatest::Reporter* reporter) {
   1556     // Test for crbug.com/229011
   1557     SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(4), SkIntToScalar(4),
   1558                                     SkIntToScalar(2), SkIntToScalar(2));
   1559     SkRect rect2 = SkRect::MakeXYWH(SkIntToScalar(7), SkIntToScalar(7),
   1560                                     SkIntToScalar(1), SkIntToScalar(1));
   1561     SkRect rect3 = SkRect::MakeXYWH(SkIntToScalar(6), SkIntToScalar(6),
   1562                                     SkIntToScalar(1), SkIntToScalar(1));
   1563 
   1564     SkPath invPath;
   1565     invPath.addOval(rect1);
   1566     invPath.setFillType(SkPath::kInverseEvenOdd_FillType);
   1567     SkPath path;
   1568     path.addOval(rect2);
   1569     SkPath path2;
   1570     path2.addOval(rect3);
   1571     SkIRect clipBounds;
   1572     SkPictureRecorder recorder;
   1573 
   1574     // Testing conservative-raster-clip that is enabled by PictureRecord
   1575     {
   1576         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1577         canvas->clipPath(invPath, SkRegion::kIntersect_Op);
   1578         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
   1579         REPORTER_ASSERT(reporter, true == nonEmpty);
   1580         REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft);
   1581         REPORTER_ASSERT(reporter, 0 == clipBounds.fTop);
   1582         REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom);
   1583         REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
   1584     }
   1585     {
   1586         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1587         canvas->clipPath(path, SkRegion::kIntersect_Op);
   1588         canvas->clipPath(invPath, SkRegion::kIntersect_Op);
   1589         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
   1590         REPORTER_ASSERT(reporter, true == nonEmpty);
   1591         REPORTER_ASSERT(reporter, 7 == clipBounds.fLeft);
   1592         REPORTER_ASSERT(reporter, 7 == clipBounds.fTop);
   1593         REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom);
   1594         REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
   1595     }
   1596     {
   1597         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1598         canvas->clipPath(path, SkRegion::kIntersect_Op);
   1599         canvas->clipPath(invPath, SkRegion::kUnion_Op);
   1600         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
   1601         REPORTER_ASSERT(reporter, true == nonEmpty);
   1602         REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft);
   1603         REPORTER_ASSERT(reporter, 0 == clipBounds.fTop);
   1604         REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom);
   1605         REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
   1606     }
   1607     {
   1608         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1609         canvas->clipPath(path, SkRegion::kDifference_Op);
   1610         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
   1611         REPORTER_ASSERT(reporter, true == nonEmpty);
   1612         REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft);
   1613         REPORTER_ASSERT(reporter, 0 == clipBounds.fTop);
   1614         REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom);
   1615         REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
   1616     }
   1617     {
   1618         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1619         canvas->clipPath(path, SkRegion::kReverseDifference_Op);
   1620         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
   1621         // True clip is actually empty in this case, but the best
   1622         // determination we can make using only bounds as input is that the
   1623         // clip is included in the bounds of 'path'.
   1624         REPORTER_ASSERT(reporter, true == nonEmpty);
   1625         REPORTER_ASSERT(reporter, 7 == clipBounds.fLeft);
   1626         REPORTER_ASSERT(reporter, 7 == clipBounds.fTop);
   1627         REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom);
   1628         REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
   1629     }
   1630     {
   1631         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1632         canvas->clipPath(path, SkRegion::kIntersect_Op);
   1633         canvas->clipPath(path2, SkRegion::kXOR_Op);
   1634         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
   1635         REPORTER_ASSERT(reporter, true == nonEmpty);
   1636         REPORTER_ASSERT(reporter, 6 == clipBounds.fLeft);
   1637         REPORTER_ASSERT(reporter, 6 == clipBounds.fTop);
   1638         REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom);
   1639         REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
   1640     }
   1641 }
   1642 
   1643 /**
   1644  * A canvas that records the number of clip commands.
   1645  */
   1646 class ClipCountingCanvas : public SkCanvas {
   1647 public:
   1648     ClipCountingCanvas(int width, int height)
   1649         : INHERITED(width, height)
   1650         , fClipCount(0){
   1651     }
   1652 
   1653     virtual void onClipRect(const SkRect& r,
   1654                             SkRegion::Op op,
   1655                             ClipEdgeStyle edgeStyle) SK_OVERRIDE {
   1656         fClipCount += 1;
   1657         this->INHERITED::onClipRect(r, op, edgeStyle);
   1658     }
   1659 
   1660     virtual void onClipRRect(const SkRRect& rrect,
   1661                              SkRegion::Op op,
   1662                              ClipEdgeStyle edgeStyle)SK_OVERRIDE {
   1663         fClipCount += 1;
   1664         this->INHERITED::onClipRRect(rrect, op, edgeStyle);
   1665     }
   1666 
   1667     virtual void onClipPath(const SkPath& path,
   1668                             SkRegion::Op op,
   1669                             ClipEdgeStyle edgeStyle) SK_OVERRIDE {
   1670         fClipCount += 1;
   1671         this->INHERITED::onClipPath(path, op, edgeStyle);
   1672     }
   1673 
   1674     virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) SK_OVERRIDE {
   1675         fClipCount += 1;
   1676         this->INHERITED::onClipRegion(deviceRgn, op);
   1677     }
   1678 
   1679     unsigned getClipCount() const { return fClipCount; }
   1680 
   1681 private:
   1682     unsigned fClipCount;
   1683 
   1684     typedef SkCanvas INHERITED;
   1685 };
   1686 
   1687 static void test_clip_expansion(skiatest::Reporter* reporter) {
   1688     SkPictureRecorder recorder;
   1689     SkCanvas* canvas = recorder.beginRecording(10, 10);
   1690 
   1691     canvas->clipRect(SkRect::MakeEmpty(), SkRegion::kReplace_Op);
   1692     // The following expanding clip should not be skipped.
   1693     canvas->clipRect(SkRect::MakeXYWH(4, 4, 3, 3), SkRegion::kUnion_Op);
   1694     // Draw something so the optimizer doesn't just fold the world.
   1695     SkPaint p;
   1696     p.setColor(SK_ColorBLUE);
   1697     canvas->drawPaint(p);
   1698     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1699 
   1700     ClipCountingCanvas testCanvas(10, 10);
   1701     picture->playback(&testCanvas);
   1702 
   1703     // Both clips should be present on playback.
   1704     REPORTER_ASSERT(reporter, testCanvas.getClipCount() == 2);
   1705 }
   1706 
   1707 static void test_hierarchical(skiatest::Reporter* reporter) {
   1708     SkBitmap bm;
   1709     make_bm(&bm, 10, 10, SK_ColorRED, true);
   1710 
   1711     SkPictureRecorder recorder;
   1712 
   1713     recorder.beginRecording(10, 10);
   1714     SkAutoTUnref<SkPicture> childPlain(recorder.endRecording());
   1715     REPORTER_ASSERT(reporter, !childPlain->willPlayBackBitmaps()); // 0
   1716 
   1717     recorder.beginRecording(10, 10)->drawBitmap(bm, 0, 0);
   1718     SkAutoTUnref<SkPicture> childWithBitmap(recorder.endRecording());
   1719     REPORTER_ASSERT(reporter, childWithBitmap->willPlayBackBitmaps()); // 1
   1720 
   1721     {
   1722         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1723         canvas->drawPicture(childPlain);
   1724         SkAutoTUnref<SkPicture> parentPP(recorder.endRecording());
   1725         REPORTER_ASSERT(reporter, !parentPP->willPlayBackBitmaps()); // 0
   1726     }
   1727     {
   1728         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1729         canvas->drawPicture(childWithBitmap);
   1730         SkAutoTUnref<SkPicture> parentPWB(recorder.endRecording());
   1731         REPORTER_ASSERT(reporter, parentPWB->willPlayBackBitmaps()); // 1
   1732     }
   1733     {
   1734         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1735         canvas->drawBitmap(bm, 0, 0);
   1736         canvas->drawPicture(childPlain);
   1737         SkAutoTUnref<SkPicture> parentWBP(recorder.endRecording());
   1738         REPORTER_ASSERT(reporter, parentWBP->willPlayBackBitmaps()); // 1
   1739     }
   1740     {
   1741         SkCanvas* canvas = recorder.beginRecording(10, 10);
   1742         canvas->drawBitmap(bm, 0, 0);
   1743         canvas->drawPicture(childWithBitmap);
   1744         SkAutoTUnref<SkPicture> parentWBWB(recorder.endRecording());
   1745         REPORTER_ASSERT(reporter, parentWBWB->willPlayBackBitmaps()); // 2
   1746     }
   1747 }
   1748 
   1749 static void test_gen_id(skiatest::Reporter* reporter) {
   1750 
   1751     SkPictureRecorder recorder;
   1752     recorder.beginRecording(0, 0);
   1753     SkAutoTUnref<SkPicture> empty(recorder.endRecording());
   1754 
   1755     // Empty pictures should still have a valid ID
   1756     REPORTER_ASSERT(reporter, empty->uniqueID() != SK_InvalidGenID);
   1757 
   1758     SkCanvas* canvas = recorder.beginRecording(1, 1);
   1759     canvas->drawARGB(255, 255, 255, 255);
   1760     SkAutoTUnref<SkPicture> hasData(recorder.endRecording());
   1761     // picture should have a non-zero id after recording
   1762     REPORTER_ASSERT(reporter, hasData->uniqueID() != SK_InvalidGenID);
   1763 
   1764     // both pictures should have different ids
   1765     REPORTER_ASSERT(reporter, hasData->uniqueID() != empty->uniqueID());
   1766 }
   1767 
   1768 DEF_TEST(Picture, reporter) {
   1769 #ifdef SK_DEBUG
   1770     test_deleting_empty_picture();
   1771     test_serializing_empty_picture();
   1772 #else
   1773     test_bad_bitmap();
   1774 #endif
   1775     test_unbalanced_save_restores(reporter);
   1776     test_peephole();
   1777 #if SK_SUPPORT_GPU
   1778     test_gpu_veto(reporter, false);
   1779     test_gpu_veto(reporter, true);
   1780 #endif
   1781     test_has_text(reporter, false);
   1782     test_has_text(reporter, true);
   1783     test_analysis(reporter, false);
   1784     test_analysis(reporter, true);
   1785     test_gatherpixelrefs(reporter);
   1786     test_gatherpixelrefsandrects(reporter);
   1787     test_bitmap_with_encoded_data(reporter);
   1788     test_draw_empty(reporter);
   1789     test_clip_bound_opt(reporter);
   1790     test_clip_expansion(reporter);
   1791     test_hierarchical(reporter);
   1792     test_gen_id(reporter);
   1793 }
   1794 
   1795 #if SK_SUPPORT_GPU
   1796 DEF_GPUTEST(GPUPicture, reporter, factory) {
   1797     test_gpu_picture_optimization(reporter, factory);
   1798 }
   1799 #endif
   1800 
   1801 static void draw_bitmaps(const SkBitmap bitmap, SkCanvas* canvas) {
   1802     const SkPaint paint;
   1803     const SkRect rect = { 5.0f, 5.0f, 8.0f, 8.0f };
   1804     const SkIRect irect =  { 2, 2, 3, 3 };
   1805 
   1806     // Don't care what these record, as long as they're legal.
   1807     canvas->drawBitmap(bitmap, 0.0f, 0.0f, &paint);
   1808     canvas->drawBitmapRectToRect(bitmap, &rect, rect, &paint, SkCanvas::kNone_DrawBitmapRectFlag);
   1809     canvas->drawBitmapMatrix(bitmap, SkMatrix::I(), &paint);
   1810     canvas->drawBitmapNine(bitmap, irect, rect, &paint);
   1811     canvas->drawSprite(bitmap, 1, 1);
   1812 }
   1813 
   1814 static void test_draw_bitmaps(SkCanvas* canvas) {
   1815     SkBitmap empty;
   1816     draw_bitmaps(empty, canvas);
   1817     empty.setInfo(SkImageInfo::MakeN32Premul(10, 10));
   1818     draw_bitmaps(empty, canvas);
   1819 }
   1820 
   1821 DEF_TEST(Picture_EmptyBitmap, r) {
   1822     SkPictureRecorder recorder;
   1823     test_draw_bitmaps(recorder.beginRecording(10, 10));
   1824     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1825 }
   1826 
   1827 DEF_TEST(Canvas_EmptyBitmap, r) {
   1828     SkBitmap dst;
   1829     dst.allocN32Pixels(10, 10);
   1830     SkCanvas canvas(dst);
   1831 
   1832     test_draw_bitmaps(&canvas);
   1833 }
   1834 
   1835 DEF_TEST(DontOptimizeSaveLayerDrawDrawRestore, reporter) {
   1836     // This test is from crbug.com/344987.
   1837     // The commands are:
   1838     //   saveLayer with paint that modifies alpha
   1839     //     drawBitmapRectToRect
   1840     //     drawBitmapRectToRect
   1841     //   restore
   1842     // The bug was that this structure was modified so that:
   1843     //  - The saveLayer and restore were eliminated
   1844     //  - The alpha was only applied to the first drawBitmapRectToRect
   1845 
   1846     // This test draws blue and red squares inside a 50% transparent
   1847     // layer.  Both colours should show up muted.
   1848     // When the bug is present, the red square (the second bitmap)
   1849     // shows upwith full opacity.
   1850 
   1851     SkBitmap blueBM;
   1852     make_bm(&blueBM, 100, 100, SkColorSetARGB(255, 0, 0, 255), true);
   1853     SkBitmap redBM;
   1854     make_bm(&redBM, 100, 100, SkColorSetARGB(255, 255, 0, 0), true);
   1855     SkPaint semiTransparent;
   1856     semiTransparent.setAlpha(0x80);
   1857 
   1858     SkPictureRecorder recorder;
   1859     SkCanvas* canvas = recorder.beginRecording(100, 100);
   1860     canvas->drawARGB(0, 0, 0, 0);
   1861 
   1862     canvas->saveLayer(0, &semiTransparent);
   1863     canvas->drawBitmap(blueBM, 25, 25);
   1864     canvas->drawBitmap(redBM, 50, 50);
   1865     canvas->restore();
   1866 
   1867     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
   1868 
   1869     // Now replay the picture back on another canvas
   1870     // and check a couple of its pixels.
   1871     SkBitmap replayBM;
   1872     make_bm(&replayBM, 100, 100, SK_ColorBLACK, false);
   1873     SkCanvas replayCanvas(replayBM);
   1874     picture->playback(&replayCanvas);
   1875     replayCanvas.flush();
   1876 
   1877     // With the bug present, at (55, 55) we would get a fully opaque red
   1878     // intead of a dark red.
   1879     REPORTER_ASSERT(reporter, replayBM.getColor(30, 30) == 0xff000080);
   1880     REPORTER_ASSERT(reporter, replayBM.getColor(55, 55) == 0xff800000);
   1881 }
   1882 
   1883 struct CountingBBH : public SkBBoxHierarchy {
   1884     mutable int searchCalls;
   1885 
   1886     CountingBBH() : searchCalls(0) {}
   1887 
   1888     virtual void search(const SkRect& query, SkTDArray<void*>* results) const {
   1889         this->searchCalls++;
   1890     }
   1891 
   1892     // All other methods unimplemented.
   1893     virtual void insert(void* data, const SkRect& bounds, bool defer) {}
   1894     virtual void flushDeferredInserts() {}
   1895     virtual void clear() {}
   1896     virtual int getCount() const { return 0; }
   1897     virtual int getDepth() const { return 0; }
   1898     virtual void rewindInserts() {}
   1899 };
   1900 
   1901 class SpoonFedBBHFactory : public SkBBHFactory {
   1902 public:
   1903     explicit SpoonFedBBHFactory(SkBBoxHierarchy* bbh) : fBBH(bbh) {}
   1904     virtual SkBBoxHierarchy* operator()(int width, int height) const {
   1905         return SkRef(fBBH);
   1906     }
   1907 private:
   1908     SkBBoxHierarchy* fBBH;
   1909 };
   1910 
   1911 // When the canvas clip covers the full picture, we don't need to call the BBH.
   1912 DEF_TEST(Picture_SkipBBH, r) {
   1913     CountingBBH bbh;
   1914     SpoonFedBBHFactory factory(&bbh);
   1915 
   1916     SkPictureRecorder recorder;
   1917     recorder.beginRecording(320, 240, &factory);
   1918     SkAutoTUnref<const SkPicture> picture(recorder.endRecording());
   1919 
   1920     SkCanvas big(640, 480), small(300, 200);
   1921 
   1922     picture->playback(&big);
   1923     REPORTER_ASSERT(r, bbh.searchCalls == 0);
   1924 
   1925     picture->playback(&small);
   1926     REPORTER_ASSERT(r, bbh.searchCalls == 1);
   1927 }
   1928 
   1929 DEF_TEST(Picture_BitmapLeak, r) {
   1930     SkBitmap mut, immut;
   1931     mut.allocN32Pixels(300, 200);
   1932     immut.allocN32Pixels(300, 200);
   1933     immut.setImmutable();
   1934     SkASSERT(!mut.isImmutable());
   1935     SkASSERT(immut.isImmutable());
   1936 
   1937     // No one can hold a ref on our pixels yet.
   1938     REPORTER_ASSERT(r, mut.pixelRef()->unique());
   1939     REPORTER_ASSERT(r, immut.pixelRef()->unique());
   1940 
   1941     SkPictureRecorder rec;
   1942     SkCanvas* canvas = rec.beginRecording(1920, 1200);
   1943         canvas->drawBitmap(mut, 0, 0);
   1944         canvas->drawBitmap(immut, 800, 600);
   1945     SkAutoTDelete<const SkPicture> pic(rec.endRecording());
   1946 
   1947     // The picture shares the immutable pixels but copies the mutable ones.
   1948     REPORTER_ASSERT(r, mut.pixelRef()->unique());
   1949     REPORTER_ASSERT(r, !immut.pixelRef()->unique());
   1950 
   1951     // When the picture goes away, it's just our bitmaps holding the refs.
   1952     pic.reset(NULL);
   1953     REPORTER_ASSERT(r, mut.pixelRef()->unique());
   1954     REPORTER_ASSERT(r, immut.pixelRef()->unique());
   1955 }
   1956