Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / tests / PictureTest.cpp
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 }