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