static void test_cache(skiatest::Reporter* reporter, SkScaledImageCache& cache, bool testPurge) { SkScaledImageCache::ID* id; SkBitmap bm[COUNT]; const SkScalar scale = 2; for (int i = 0; i < COUNT; ++i) { make_bm(&bm[i], DIM, DIM); } for (int i = 0; i < COUNT; ++i) { SkBitmap tmp; SkScaledImageCache::ID* id = cache.findAndLock(bm[i], scale, scale, &tmp); REPORTER_ASSERT(reporter, NULL == id); make_bm(&tmp, DIM, DIM); id = cache.addAndLock(bm[i], scale, scale, tmp); REPORTER_ASSERT(reporter, NULL != id); SkBitmap tmp2; SkScaledImageCache::ID* id2 = cache.findAndLock(bm[i], scale, scale, &tmp2); REPORTER_ASSERT(reporter, id == id2); REPORTER_ASSERT(reporter, tmp.pixelRef() == tmp2.pixelRef()); REPORTER_ASSERT(reporter, tmp.width() == tmp2.width()); REPORTER_ASSERT(reporter, tmp.height() == tmp2.height()); cache.unlock(id2); cache.unlock(id); } if (testPurge) { // stress test, should trigger purges float incScale = 2; for (size_t i = 0; i < COUNT * 100; ++i) { incScale += 1; SkBitmap tmp; make_bm(&tmp, DIM, DIM); SkScaledImageCache::ID* id = cache.addAndLock(bm[0], incScale, incScale, tmp); REPORTER_ASSERT(reporter, NULL != id); cache.unlock(id); } } // test the originals after all that purging for (int i = 0; i < COUNT; ++i) { SkBitmap tmp; id = cache.findAndLock(bm[i], scale, scale, &tmp); if (id) { cache.unlock(id); } } cache.setByteLimit(0); }
DitherView() { make_bm(&fBM); make_bm(&fBMPreDither); pre_dither(fBMPreDither); fBM.copyTo(&fBM16, kARGB_4444_SkColorType); fAngle = 0; this->setBGColor(0xFF181818); }
DitherView() { make_bm(&fBM); make_bm(&fBMPreDither); pre_dither(fBMPreDither); fBM.copyTo(&fBM16, SkBitmap::kARGB_4444_Config); fAngle = 0; this->setBGColor(0xFF181818); }
static void test_bitmap_with_encoded_data(skiatest::Reporter* reporter) { // Create a bitmap that will be encoded. SkBitmap original; make_bm(&original, 100, 100, SK_ColorBLUE, true); SkDynamicMemoryWStream wStream; if (!SkImageEncoder::EncodeStream(&wStream, original, SkImageEncoder::kPNG_Type, 100)) { return; } SkAutoDataUnref data(wStream.copyToData()); SkBitmap bm; bool installSuccess = SkDecodingImageGenerator::Install(data, &bm); REPORTER_ASSERT(reporter, installSuccess); // Write both bitmaps to pictures, and ensure that the resulting data streams are the same. // Flattening original will follow the old path of performing an encode, while flattening bm // will use the already encoded data. SkAutoDataUnref picture1(serialized_picture_from_bitmap(original)); SkAutoDataUnref picture2(serialized_picture_from_bitmap(bm)); REPORTER_ASSERT(reporter, picture1->equals(picture2)); // Now test that a parse error was generated when trying to create a new SkPicture without // providing a function to decode the bitmap. ErrorContext context; context.fErrors = 0; context.fReporter = reporter; SkSetErrorCallback(assert_one_parse_error_cb, &context); SkMemoryStream pictureStream(picture1); SkClearLastError(); SkAutoUnref pictureFromStream(SkPicture::CreateFromStream(&pictureStream, NULL)); REPORTER_ASSERT(reporter, pictureFromStream.get() != NULL); SkClearLastError(); SkSetErrorCallback(NULL, NULL); }
static void show_bm(SkCanvas* canvas, int width, int height, SkColor color) { SkBitmap bm; make_bm(&bm, width, height, color); SkPaint paint; SkRect r; SkIRect ir; paint.setStyle(SkPaint::kStroke_Style); ir.set(0, 0, 128, 128); r.set(ir); canvas->save(); canvas->clipRect(r); canvas->drawBitmap(bm, 0, 0, NULL); canvas->restore(); canvas->drawRect(r, paint); r.offset(SkIntToScalar(150), 0); // exercises extract bitmap, but not shader canvas->drawBitmapRect(bm, &ir, r, NULL); canvas->drawRect(r, paint); r.offset(SkIntToScalar(150), 0); // exercises bitmapshader canvas->drawBitmapRect(bm, NULL, r, NULL); canvas->drawRect(r, paint); }
void onOnceBeforeDraw() override { for (size_t i = 0; i < SK_ARRAY_COUNT(fTallBmps); ++i) { int h = SkToInt((4 + i) * 1024); fTallBmps[i].fItemCnt = make_bm(&fTallBmps[i].fBmp, h); } }
DEF_TEST(DontOptimizeSaveLayerDrawDrawRestore, reporter) { // This test is from crbug.com/344987. // The commands are: // saveLayer with paint that modifies alpha // drawBitmapRect // drawBitmapRect // restore // The bug was that this structure was modified so that: // - The saveLayer and restore were eliminated // - The alpha was only applied to the first drawBitmapRectToRect // This test draws blue and red squares inside a 50% transparent // layer. Both colours should show up muted. // When the bug is present, the red square (the second bitmap) // shows upwith full opacity. SkBitmap blueBM; make_bm(&blueBM, 100, 100, SkColorSetARGB(255, 0, 0, 255), true); SkBitmap redBM; make_bm(&redBM, 100, 100, SkColorSetARGB(255, 255, 0, 0), true); SkPaint semiTransparent; semiTransparent.setAlpha(0x80); SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(100, 100); canvas->drawARGB(0, 0, 0, 0); canvas->saveLayer(0, &semiTransparent); canvas->drawBitmap(blueBM, 25, 25); canvas->drawBitmap(redBM, 50, 50); canvas->restore(); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); // Now replay the picture back on another canvas // and check a couple of its pixels. SkBitmap replayBM; make_bm(&replayBM, 100, 100, SK_ColorBLACK, false); SkCanvas replayCanvas(replayBM); picture->playback(&replayCanvas); replayCanvas.flush(); // With the bug present, at (55, 55) we would get a fully opaque red // intead of a dark red. REPORTER_ASSERT(reporter, replayBM.getColor(30, 30) == 0xff000080); REPORTER_ASSERT(reporter, replayBM.getColor(55, 55) == 0xff800000); }
FilterView() { make_bm(&fBM8); fBM8.copyTo(&fBM4444, kARGB_4444_SkColorType); fBM8.copyTo(&fBM16, kRGB_565_SkColorType); fBM8.copyTo(&fBM32, kN32_SkColorType); this->setBGColor(0xFFDDDDDD); }
FilterView() { make_bm(&fBM8); fBM8.copyTo(&fBM4444, SkBitmap::kARGB_4444_Config); fBM8.copyTo(&fBM16, SkBitmap::kRGB_565_Config); fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config); this->setBGColor(0xFFDDDDDD); }
void init() { if (fOnce) { return; } fOnce = true; make_bm(&fBM8); fBM8.copyTo(&fBM4444, SkBitmap::kARGB_4444_Config); fBM8.copyTo(&fBM16, SkBitmap::kRGB_565_Config); fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config); }
void init() { if (fOnce) { return; } fOnce = true; make_bm(&fBM8); fBM8.copyTo(&fBM4444, kARGB_4444_SkColorType); fBM8.copyTo(&fBM16, kRGB_565_SkColorType); fBM8.copyTo(&fBM32, kN32_SkColorType); }
// Allocate result to be large enough to hold subset, and then draw the picture // into it, offsetting by subset's top/left corner. static void draw(SkPicture* pic, const SkRect& subset, SkBitmap* result) { SkIRect ir; subset.roundOut(&ir); int w = ir.width(); int h = ir.height(); make_bm(result, w, h, 0, false); SkCanvas canvas(*result); canvas.translate(-SkIntToScalar(ir.left()), -SkIntToScalar(ir.top())); canvas.drawPicture(*pic); }
FilterView() { /*做一张bitmap, kIndex8_Config格式的2行2列 依次转换成 其他3种格式的bitmap : 见结果图, 对应4行.*/ make_bm(&fBM8); fBM8.copyTo(&fBM4444, SkBitmap::kARGB_4444_Config); fBM8.copyTo(&fBM16, SkBitmap::kRGB_565_Config); fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config); //设置背景色 为 灰色 : 见结果图 this->setBGColor(0xFFDDDDDD); }
static SkBitmap make_arith(const SkBitmap& src, const SkBitmap& dst, const SkScalar k[]) { SkBitmap bm = make_bm(); SkCanvas canvas(bm); SkPaint paint; canvas.drawBitmap(dst, 0, 0, NULL); SkXfermode* xfer = SkArithmeticMode::Create(k[0], k[1], k[2], k[3]); paint.setXfermode(xfer)->unref(); canvas.drawBitmap(src, 0, 0, &paint); return bm; }
DEF_TEST(Picture_EncodedData, reporter) { // Create a bitmap that will be encoded. SkBitmap original; make_bm(&original, 100, 100, SK_ColorBLUE, true); SkDynamicMemoryWStream wStream; if (!SkImageEncoder::EncodeStream(&wStream, original, SkImageEncoder::kPNG_Type, 100)) { return; } SkAutoDataUnref data(wStream.copyToData()); SkBitmap bm; bool installSuccess = SkDEPRECATED_InstallDiscardablePixelRef(data, &bm); REPORTER_ASSERT(reporter, installSuccess); // Write both bitmaps to pictures, and ensure that the resulting data streams are the same. // Flattening original will follow the old path of performing an encode, while flattening bm // will use the already encoded data. SkAutoDataUnref picture1(serialized_picture_from_bitmap(original)); SkAutoDataUnref picture2(serialized_picture_from_bitmap(bm)); REPORTER_ASSERT(reporter, picture1->equals(picture2)); // Now test that a parse error was generated when trying to create a new SkPicture without // providing a function to decode the bitmap. ErrorContext context; context.fErrors = 0; context.fReporter = reporter; SkSetErrorCallback(assert_one_parse_error_cb, &context); SkMemoryStream pictureStream(picture1); SkClearLastError(); sk_sp<SkPicture> pictureFromStream(SkPicture::MakeFromStream(&pictureStream, nullptr)); REPORTER_ASSERT(reporter, pictureFromStream.get() != nullptr); SkClearLastError(); SkSetErrorCallback(nullptr, nullptr); // Test that using the version of CreateFromStream that just takes a stream also decodes the // bitmap. Drawing this picture should look exactly like the original bitmap. SkMD5::Digest referenceDigest; md5(original, &referenceDigest); SkBitmap dst; dst.allocPixels(original.info()); dst.eraseColor(SK_ColorRED); SkCanvas canvas(dst); pictureStream.rewind(); pictureFromStream = SkPicture::MakeFromStream(&pictureStream); canvas.drawPicture(pictureFromStream.get()); SkMD5::Digest digest2; md5(dst, &digest2); REPORTER_ASSERT(reporter, referenceDigest == digest2); }
static SkBitmap make_dst() { SkBitmap bm = make_bm(); SkCanvas canvas(bm); SkPaint paint; SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} }; SkColor colors[] = { SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN, sk_tool_utils::color_to_565(SK_ColorGRAY) }; paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); canvas.drawPaint(paint); return bm; }
static SkBitmap make_src() { SkBitmap bm = make_bm(); SkCanvas canvas(bm); SkPaint paint; SkPoint pts[] = { {0, 0}, {SkIntToScalar(WW), SkIntToScalar(HH)} }; SkColor colors[] = { SK_ColorTRANSPARENT, SK_ColorGREEN, SK_ColorCYAN, SK_ColorRED, SK_ColorMAGENTA, SK_ColorWHITE, }; paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); canvas.drawPaint(paint); return bm; }
static SkBitmap make_dst() { SkBitmap bm = make_bm(); SkCanvas canvas(bm); SkPaint paint; SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} }; SkColor colors[] = { SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN, SK_ColorGRAY }; SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode); paint.setShader(s)->unref(); canvas.drawPaint(paint); return bm; }
// This creates a close, but imperfect concatenation of // scaling the image up by its dst-rect // scaling the image down by the matrix' scale // The bug was that for cases like this, we were incorrectly trying to take a // fast-path in the bitmapshader, but ended up drawing the last col of pixels // twice. The fix resulted in (a) not taking the fast-path, but (b) drawing // the image correctly. // static void test_bitmaprect(SkCanvas* canvas) { SkBitmap bm; make_bm(&bm); canvas->drawBitmap(bm, 150, 45, NULL); SkScalar scale = 0.472560018f; canvas->save(); canvas->scale(scale, scale); canvas->drawBitmapRectToRect(bm, NULL, SkRect::MakeXYWH(100, 100, 128, 128), NULL); canvas->restore(); canvas->scale(-1, 1); canvas->drawBitmap(bm, -310, 45, NULL); }
void onDraw(SkCanvas* canvas) override { SkPaint paint; SkBitmap bm = make_bm(); canvas->drawBitmap(bm, 10, 10, &paint); const SkScalar dir[] = { 1, 1, 1 }; paint.setMaskFilter(SkBlurMaskFilter::MakeEmboss(3, dir, 0.3f, 0.1f)); canvas->translate(bm.width() + SkIntToScalar(10), 0); canvas->drawBitmap(bm, 10, 10, &paint); // this combination of emboss+colorfilter used to crash -- so we exercise it to // confirm that we have a fix. paint.setColorFilter(SkColorFilter::MakeModeFilter(0xFFFF0000, SkBlendMode::kSrcATop)); canvas->translate(bm.width() + SkIntToScalar(10), 0); canvas->drawBitmap(bm, 10, 10, &paint); }
void onDraw(SkCanvas* canvas) override { SkBitmap bm; make_bm(&bm); int dx = 10; int dy = 10; SkScalar sigma = 8; SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(sigma, sigma)); draw_2_bitmaps(canvas, bm, false, dx, dy); dy += bm.height() + 20; draw_2_bitmaps(canvas, bm, false, dx, dy, filter); dy += bm.height() + 20; draw_2_bitmaps(canvas, bm, true, dx, dy); dy += bm.height() + 20; draw_2_bitmaps(canvas, bm, true, dx, dy, filter); }
void onDraw(SkCanvas* canvas) override { SkBitmap bm; make_bm(&bm); int dx = 10; int dy = 10; SkScalar sigma = 8; sk_sp<SkImageFilter> filter(SkBlurImageFilter::Make(sigma, sigma, nullptr)); draw_1_bitmap(canvas, bm, false, dx, dy, nullptr); dy += bm.height() + 20; draw_1_bitmap(canvas, bm, false, dx, dy, filter); dy += bm.height() + 20; draw_1_bitmap(canvas, bm, true, dx, dy, nullptr); dy += bm.height() + 20; draw_1_bitmap(canvas, bm, true, dx, dy, filter); }
static void test_hierarchical(skiatest::Reporter* reporter) { SkBitmap bm; make_bm(&bm, 10, 10, SK_ColorRED, true); SkPictureRecorder recorder; recorder.beginRecording(10, 10); sk_sp<SkPicture> childPlain(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, !childPlain->willPlayBackBitmaps()); // 0 recorder.beginRecording(10, 10)->drawBitmap(bm, 0, 0); sk_sp<SkPicture> childWithBitmap(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, childWithBitmap->willPlayBackBitmaps()); // 1 { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->drawPicture(childPlain); sk_sp<SkPicture> parentPP(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, !parentPP->willPlayBackBitmaps()); // 0 } { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->drawPicture(childWithBitmap); sk_sp<SkPicture> parentPWB(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, parentPWB->willPlayBackBitmaps()); // 1 } { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->drawBitmap(bm, 0, 0); canvas->drawPicture(childPlain); sk_sp<SkPicture> parentWBP(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, parentWBP->willPlayBackBitmaps()); // 1 } { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->drawBitmap(bm, 0, 0); canvas->drawPicture(childWithBitmap); sk_sp<SkPicture> parentWBWB(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, parentWBWB->willPlayBackBitmaps()); // 2 } }
// Test out SkPictureRecorder::partialReplay DEF_TEST(PictureRecorder_replay, reporter) { // check save/saveLayer state { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->saveLayer(nullptr, nullptr); sk_sp<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder)); // The extra save and restore comes from the Copy process. check_save_state(reporter, copy.get(), 2, 1, 3); canvas->saveLayer(nullptr, nullptr); sk_sp<SkPicture> final(recorder.finishRecordingAsPicture()); check_save_state(reporter, final.get(), 1, 2, 3); // The copy shouldn't pick up any operations added after it was made check_save_state(reporter, copy.get(), 2, 1, 3); } // (partially) check leakage of draw ops { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(10, 10); SkRect r = SkRect::MakeWH(5, 5); SkPaint p; canvas->drawRect(r, p); sk_sp<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder)); REPORTER_ASSERT(reporter, !copy->willPlayBackBitmaps()); SkBitmap bm; make_bm(&bm, 10, 10, SK_ColorRED, true); r.offset(5.0f, 5.0f); canvas->drawBitmapRect(bm, r, nullptr); sk_sp<SkPicture> final(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, final->willPlayBackBitmaps()); REPORTER_ASSERT(reporter, copy->uniqueID() != final->uniqueID()); // The snapshot shouldn't pick up any operations added after it was made REPORTER_ASSERT(reporter, !copy->willPlayBackBitmaps()); } // Recreate the Android partialReplay test case { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(4, 3, nullptr, 0); create_imbalance(canvas); int expectedSaveCount = canvas->getSaveCount(); sk_sp<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder)); check_balance(reporter, copy.get()); REPORTER_ASSERT(reporter, expectedSaveCount = canvas->getSaveCount()); // End the recording of source to test the picture finalization // process isn't complicated by the partialReplay step sk_sp<SkPicture> final(recorder.finishRecordingAsPicture()); } }
FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry)) { }
void onOnceBeforeDraw() override { make_bm(&fBM32); ToolUtils::copy_to(&fBM4444, kARGB_4444_SkColorType, fBM32); ToolUtils::copy_to(&fBM16, kRGB_565_SkColorType, fBM32); }
void onOnceBeforeDraw() override { make_bm(&fBM8); fBM8.copyTo(&fBM4444, kARGB_4444_SkColorType); fBM8.copyTo(&fBM16, kRGB_565_SkColorType); fBM8.copyTo(&fBM32, kN32_SkColorType); }
static void test_gatherpixelrefs(skiatest::Reporter* reporter) { const int IW = 8; const int IH = IW; const SkScalar W = SkIntToScalar(IW); const SkScalar H = W; static const int N = 4; SkBitmap bm[N]; SkPixelRef* refs[N]; const SkPoint pos[] = { { 0, 0 }, { W, 0 }, { 0, H }, { W, H } }; // Our convention is that the color components contain the index of their // corresponding bitmap/pixelref for (int i = 0; i < N; ++i) { make_bm(&bm[i], IW, IH, SkColorSetARGB(0xFF, i, i, i), true); refs[i] = bm[i].pixelRef(); } static const DrawBitmapProc procs[] = { drawbitmap_proc, drawbitmaprect_proc, drawshader_proc }; SkRandom rand; for (size_t k = 0; k < SK_ARRAY_COUNT(procs); ++k) { SkAutoTUnref<SkPicture> pic(record_bitmaps(bm, pos, N, procs[k])); REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0); // quick check for a small piece of each quadrant, which should just // contain 1 bitmap. for (size_t i = 0; i < SK_ARRAY_COUNT(pos); ++i) { SkRect r; r.set(2, 2, W - 2, H - 2); r.offset(pos[i].fX, pos[i].fY); SkAutoDataUnref data(SkPictureUtils::GatherPixelRefs(pic, r)); REPORTER_ASSERT(reporter, data); if (data) { int count = static_cast<int>(data->size() / sizeof(SkPixelRef*)); REPORTER_ASSERT(reporter, 1 == count); REPORTER_ASSERT(reporter, *(SkPixelRef**)data->data() == refs[i]); } } // Test a bunch of random (mostly) rects, and compare the gather results // with a deduced list of refs by looking at the colors drawn. for (int j = 0; j < 100; ++j) { SkRect r; rand_rect(&r, rand, 2*W, 2*H); SkBitmap result; draw(pic, r, &result); SkTDArray<SkPixelRef*> array; SkData* data = SkPictureUtils::GatherPixelRefs(pic, r); size_t dataSize = data ? data->size() : 0; int gatherCount = static_cast<int>(dataSize / sizeof(SkPixelRef*)); SkASSERT(gatherCount * sizeof(SkPixelRef*) == dataSize); SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL; SkAutoDataUnref adu(data); gather_from_colors(result, refs, N, &array); /* * GatherPixelRefs is conservative, so it can return more bitmaps * that we actually can see (usually because of conservative bounds * inflation for antialiasing). Thus our check here is only that * Gather didn't miss any that we actually saw. Even that isn't * a strict requirement on Gather, which is meant to be quick and * only mostly-correct, but at the moment this test should work. */ for (int i = 0; i < array.count(); ++i) { bool found = find(gatherRefs, array[i], gatherCount); REPORTER_ASSERT(reporter, found); #if 0 // enable this block of code to debug failures, as it will rerun // the case that failed. if (!found) { SkData* data = SkPictureUtils::GatherPixelRefs(pic, r); size_t dataSize = data ? data->size() : 0; } #endif } } } }