// getRecordingCanvas() should return a SkCanvas when recording, null when not recording. DEF_TEST(Picture_getRecordingCanvas, r) { SkPictureRecorder rec; REPORTER_ASSERT(r, !rec.getRecordingCanvas()); for (int i = 0; i < 3; i++) { rec.beginRecording(100, 100); REPORTER_ASSERT(r, rec.getRecordingCanvas()); rec.finishRecordingAsPicture(); REPORTER_ASSERT(r, !rec.getRecordingCanvas()); } }
void draw(SkCanvas* canvas) { SkPictureRecorder recorder; SkCanvas* pictureCanvas = recorder.beginRecording({0, 0, 256, 256}); SkPaint paint; pictureCanvas->drawRect(SkRect::MakeWH(200, 200), paint); paint.setColor(SK_ColorWHITE); pictureCanvas->drawRect(SkRect::MakeLTRB(20, 20, 180, 180), paint); sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); picture->playback(canvas); }
// Test out the layer replacement functionality with and w/o a BBH void test_replacements(skiatest::Reporter* r, GrContext* context, bool doReplace) { sk_sp<SkPicture> pic; { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight)); SkPaint paint; canvas->saveLayer(nullptr, &paint); canvas->clear(SK_ColorRED); canvas->restore(); canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)), SkPaint()); pic = recorder.finishRecordingAsPicture(); } SkAutoTUnref<GrTexture> texture; SkPaint paint; GrLayerCache* layerCache = context->getLayerCache(); if (doReplace) { int key[1] = { 0 }; GrCachedLayer* layer = layerCache->findLayerOrCreate(pic->uniqueID(), 0, 2, SkIRect::MakeWH(kWidth, kHeight), SkIRect::MakeWH(kWidth, kHeight), SkMatrix::I(), key, 1, &paint); GrSurfaceDesc desc; desc.fConfig = kSkia8888_GrPixelConfig; desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fWidth = kWidth; desc.fHeight = kHeight; desc.fSampleCnt = 0; // Giving the texture some initial data so the Gpu (specifically vulkan) does not complain // when reading from an uninitialized texture. SkAutoTMalloc<uint32_t> srcBuffer(kWidth*kHeight); memset(srcBuffer.get(), 0, kWidth*kHeight*sizeof(uint32_t)); texture.reset(context->textureProvider()->createTexture( desc, SkBudgeted::kNo, srcBuffer.get(), 0)); layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight), false); } SkRecord rerecord; SkRecorder canvas(&rerecord, kWidth, kHeight); GrRecordReplaceDraw(pic.get(), &canvas, layerCache, SkMatrix::I(), nullptr/*callback*/); int numLayers = count_instances_of_type<SkRecords::SaveLayer>(rerecord); if (doReplace) { REPORTER_ASSERT(r, 0 == numLayers); } else { REPORTER_ASSERT(r, 1 == numLayers); } }
static void test_typeface(skiatest::Reporter* reporter) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(10, 10); SkPaint paint; paint.setTypeface(SkTypeface::CreateFromName("Arial", SkTypeface::kItalic)); canvas->drawText("Q", 1, 0, 10, paint); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, picture->hasText()); SkDynamicMemoryWStream stream; picture->serialize(&stream); }
void LinkHighlight::paintContents(WebDisplayItemList* webDisplayItemList, const WebRect& webClipRect, WebContentLayerClient::PaintingControlSetting paintingControl) { if (!m_node || !m_node->layoutObject()) return; SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(webClipRect.width, webClipRect.height); canvas->translate(-webClipRect.x, -webClipRect.y); paintContents(canvas, webClipRect, paintingControl); webDisplayItemList->appendDrawingItem(recorder.endRecording()); }
static void DrawPictureTestStep(SkCanvas* canvas, const TestData& d, skiatest::Reporter*, CanvasTestStep*) { SkPictureRecorder recorder; SkCanvas* testCanvas = recorder.beginRecording(SkIntToScalar(d.fWidth), SkIntToScalar(d.fHeight), nullptr, 0); testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1)); testCanvas->clipRect(d.fRect); testCanvas->drawRect(d.fRect, d.fPaint); canvas->drawPicture(recorder.finishRecordingAsPicture()); }
SkPicture* SkDrawable::onNewPictureSnapshot() { SkPictureRecorder recorder; const SkRect bounds = this->getBounds(); SkCanvas* canvas = recorder.beginRecording(bounds, nullptr, 0); this->draw(canvas); if (false) { draw_bbox(canvas, bounds); } return recorder.endRecording(); }
static SkPicture* rerecord_with_tilegrid(SkPicture& src) { SkTileGridFactory::TileGridInfo info; info.fTileInterval.set(FLAGS_tile, FLAGS_tile); info.fMargin.setEmpty(); info.fOffset.setZero(); SkTileGridFactory factory(info); SkPictureRecorder recorder; src.draw(recorder.beginRecording(src.width(), src.height(), &factory)); return recorder.endRecording(); }
sk_sp<SkPicture> SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* data, const SkReadBuffer* buffer) { if (!data) { return nullptr; } SkPicturePlayback playback(data); SkPictureRecorder r; playback.draw(r.beginRecording(info.fCullRect), nullptr/*no callback*/, buffer); return r.finishRecordingAsPicture(); }
static sk_sp<SkPicture> make_picture(sk_sp<SkTypeface> tf0, sk_sp<SkTypeface> tf1) { SkPictureRecorder rec; SkCanvas* canvas = rec.beginRecording(100, 100); SkPaint paint; SkFont font; font.setTypeface(tf0); canvas->drawString("hello", 0, 0, font, paint); font.setTypeface(tf1); canvas->drawString("hello", 0, 0, font, paint); font.setTypeface(tf0); canvas->drawString("hello", 0, 0, font, paint); font.setTypeface(tf1); canvas->drawString("hello", 0, 0, font, paint); return rec.finishRecordingAsPicture(); }
DEF_TEST(serial_procs_image, reporter) { auto src_img = GetResourceAsImage("images/mandrill_128.png"); const char magic_str[] = "magic signature"; const SkSerialImageProc sprocs[] = { [](SkImage* img, void* ctx) -> sk_sp<SkData> { return nullptr; }, [](SkImage* img, void* ctx) { return img->encodeToData(); }, [](SkImage* img, void* ctx) { return SkData::MakeWithCString(((State*)ctx)->fStr); }, }; const SkDeserialImageProc dprocs[] = { [](const void* data, size_t length, void*) -> sk_sp<SkImage> { return nullptr; }, [](const void* data, size_t length, void*) { return SkImage::MakeFromEncoded(SkData::MakeWithCopy(data, length)); }, [](const void* data, size_t length, void* ctx) -> sk_sp<SkImage> { State* state = (State*)ctx; if (length != strlen(state->fStr)+1 || memcmp(data, state->fStr, length)) { return nullptr; } return sk_ref_sp(state->fImg); }, }; sk_sp<SkPicture> pic; { SkPictureRecorder rec; SkCanvas* canvas = rec.beginRecording(128, 128); canvas->drawImage(src_img, 0, 0, nullptr); pic = rec.finishRecordingAsPicture(); } State state = { magic_str, src_img.get() }; SkSerialProcs sproc; sproc.fImageCtx = &state; SkDeserialProcs dproc; dproc.fImageCtx = &state; for (size_t i = 0; i < SK_ARRAY_COUNT(sprocs); ++i) { sproc.fImageProc = sprocs[i]; auto data = pic->serialize(&sproc); REPORTER_ASSERT(reporter, data); dproc.fImageProc = dprocs[i]; auto new_pic = SkPicture::MakeFromData(data.get(), &dproc); REPORTER_ASSERT(reporter, data); auto dst_img = picture_to_image(new_pic); REPORTER_ASSERT(reporter, ToolUtils::equal_pixels(src_img.get(), dst_img.get())); } }
/** Converts fPicture to a picture that uses a BBoxHierarchy. * PictureRenderer subclasses that are used to test picture playback * should call this method during init. */ void PictureRenderer::buildBBoxHierarchy() { SkASSERT(NULL != fPicture); if (kNone_BBoxHierarchyType != fBBoxHierarchyType && NULL != fPicture) { SkAutoTDelete<SkBBHFactory> factory(this->getFactory()); SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(fPicture->width(), fPicture->height(), factory.get(), this->recordFlags()); fPicture->draw(canvas); fPicture.reset(recorder.endRecording()); } }
HTView() { SkRandom rand; SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(SkRect::MakeWH(W, H)); for (int i = 0; i < N; ++i) { fArray[i].fDrawable = new HTDrawable(rand); canvas->drawDrawable(fArray[i].fDrawable); fArray[i].fDrawable->unref(); } fRoot = recorder.finishRecordingAsDrawable(); }
void RecordingBench::onDraw(const int loops, SkCanvas*) { SkRTreeFactory factory; const SkScalar w = fSrc->cullRect().width(), h = fSrc->cullRect().height(); for (int i = 0; i < loops; i++) { SkPictureRecorder recorder; fSrc->playback(recorder.beginRecording(w, h, fUseBBH ? &factory : NULL, SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag)); SkSafeUnref(recorder.endRecording()); } }
void makePicture() { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(100, 100); canvas->clear(0x00000000); SkPaint paint; paint.setAntiAlias(true); paint.setColor(0xFFFFFFFF); paint.setTextSize(SkIntToScalar(96)); const char* str = "e"; canvas->drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint); fPicture.reset(recorder.endRecording()); }
static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); canvas->drawBitmap(bitmap, 0, 0); SkAutoTUnref<SkPicture> picture(recorder.endRecording()); SkDynamicMemoryWStream wStream; sk_tool_utils::PngPixelSerializer serializer; picture->serialize(&wStream, &serializer); return wStream.copyToData(); }
static void DrawPictureTestStep(SkCanvas* canvas, const TestData& d, skiatest::Reporter*, CanvasTestStep*) { SkPictureRecorder recorder; SkCanvas* testCanvas = recorder.beginRecording(SkIntToScalar(d.fWidth), SkIntToScalar(d.fHeight), NULL, 0); testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1)); testCanvas->clipRect(d.fRect); testCanvas->drawRect(d.fRect, d.fPaint); SkAutoTUnref<SkPicture> testPicture(recorder.endRecording()); canvas->drawPicture(testPicture); }
void run(SkBBHFactory* factory, skiatest::Reporter* reporter) { SkCanvas playbackCanvas(fResultBitmap); playbackCanvas.clear(SK_ColorGREEN); SkPictureRecorder recorder; SkCanvas* recordCanvas = recorder.beginRecording(SkIntToScalar(fPictureWidth), SkIntToScalar(fPictureHeight), factory); this->doTest(playbackCanvas, *recordCanvas); SkAutoTUnref<SkPicture> picture(recorder.endRecording()); playbackCanvas.drawPicture(picture); REPORTER_ASSERT(reporter, SK_ColorGREEN == fResultBitmap.getColor(0, 0)); }
// For a while willPlayBackBitmaps() ignored SkImages and just looked for SkBitmaps. static void test_images_are_found_by_willPlayBackBitmaps(skiatest::Reporter* reporter) { // We just need _some_ SkImage const SkPMColor pixel = 0; const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); sk_sp<SkImage> image(SkImage::MakeRasterCopy(SkPixmap(info, &pixel, sizeof(pixel)))); SkPictureRecorder recorder; recorder.beginRecording(100,100)->drawImage(image, 0,0); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, picture->willPlayBackBitmaps()); }
void onOnceBeforeDraw() override { SkPictureRecorder recorder; SkCanvas* pictureCanvas = recorder.beginRecording(kPictureSize, kPictureSize); draw_scene(pictureCanvas, kPictureSize); SkAutoTUnref<SkPicture> picture(recorder.endRecording()); SkPoint offset = SkPoint::Make(100, 100); pictureCanvas = recorder.beginRecording(SkRect::MakeXYWH(offset.x(), offset.y(), kPictureSize, kPictureSize)); pictureCanvas->translate(offset.x(), offset.y()); draw_scene(pictureCanvas, kPictureSize); SkAutoTUnref<SkPicture> offsetPicture(recorder.endRecording()); for (unsigned i = 0; i < SK_ARRAY_COUNT(tiles); ++i) { SkRect tile = SkRect::MakeXYWH(tiles[i].x * kPictureSize, tiles[i].y * kPictureSize, tiles[i].w * kPictureSize, tiles[i].h * kPictureSize); SkMatrix localMatrix; localMatrix.setTranslate(tiles[i].offsetX * kPictureSize, tiles[i].offsetY * kPictureSize); localMatrix.postScale(kFillSize / (2 * kPictureSize), kFillSize / (2 * kPictureSize)); SkPicture* picturePtr = picture.get(); SkRect* tilePtr = &tile; if (tile == SkRect::MakeWH(kPictureSize, kPictureSize)) { // When the tile == picture bounds, exercise the picture + offset path. picturePtr = offsetPicture.get(); tilePtr = NULL; } fShaders[i].reset(SkShader::CreatePictureShader(picturePtr, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix, tilePtr)); } }
int tool_main(int argc, char** argv) { SkCommandLineFlags::Parse(argc, argv); for (int i = 0; i < FLAGS_skps.count(); i++) { if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) { continue; } SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(FLAGS_skps[i])); if (!stream) { SkDebugf("Could not read %s.\n", FLAGS_skps[i]); return 1; } SkAutoTUnref<SkPicture> src( SkPicture::CreateFromStream(stream, sk_tools::LazyDecodeBitmap)); if (!src) { SkDebugf("Could not read %s as an SkPicture.\n", FLAGS_skps[i]); return 1; } const int w = SkScalarCeilToInt(src->cullRect().width()); const int h = SkScalarCeilToInt(src->cullRect().height()); SkRecord record; SkRecorder canvas(&record, w, h); src->playback(&canvas); if (FLAGS_optimize) { SkRecordOptimize(&record); } if (FLAGS_optimize2) { SkRecordOptimize2(&record); } dump(FLAGS_skps[i], w, h, record); if (FLAGS_write.count() > 0) { SkPictureRecorder r; SkRecordDraw(record, r.beginRecording(SkRect::MakeIWH(w, h)), nullptr, nullptr, 0, nullptr, nullptr); SkAutoTUnref<SkPicture> dst(r.endRecording()); SkFILEWStream ostream(FLAGS_write[0]); dst->serialize(&ostream); } } return 0; }
static sk_sp<SkPicture> make_picture() { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(100, 100, nullptr, 0); canvas->clear(SK_ColorBLACK); SkPaint paint; paint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&paint); paint.setColor(0xFFFFFFFF); paint.setTextSize(SkIntToScalar(96)); const char* str = "e"; canvas->drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint); return recorder.finishRecordingAsPicture(); }
PassRefPtr<SkImage> SVGImage::imageForCurrentFrameForContainer(const KURL& url) { if (!m_page) return nullptr; SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(width(), height()); drawForContainer(canvas, SkPaint(), FloatSize(size()), 1, rect(), rect(), url); RefPtr<SkPicture> picture = adoptRef(recorder.endRecording()); return adoptRef( SkImage::NewFromPicture(picture.get(), SkISize::Make(width(), height()), nullptr, nullptr)); }
void onOnceBeforeDraw() override { // Build the picture. SkPictureRecorder recorder; SkCanvas* pictureCanvas = recorder.beginRecording(fTileSize, fTileSize, NULL, 0); this->drawTile(pictureCanvas); fPicture.reset(recorder.endRecording()); // Build a reference bitmap. fBitmap.allocN32Pixels(SkScalarCeilToInt(fTileSize), SkScalarCeilToInt(fTileSize)); fBitmap.eraseColor(SK_ColorTRANSPARENT); SkCanvas bitmapCanvas(fBitmap); this->drawTile(&bitmapCanvas); }
static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); canvas->drawBitmap(bitmap, 0, 0); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); SkDynamicMemoryWStream wStream; SkAutoTUnref<SkPixelSerializer> serializer( SkImageEncoder::CreatePixelSerializer()); picture->serialize(&wStream, serializer); return wStream.copyToData(); }
// Only test this is in release mode. We deliberately crash in debug mode, since a valid caller // should never do this. static void test_bad_bitmap() { // This bitmap has a width and height but no pixels. As a result, attempting to record it will // fail. SkBitmap bm; bm.setInfo(SkImageInfo::MakeN32Premul(100, 100)); SkPictureRecorder recorder; SkCanvas* recordingCanvas = recorder.beginRecording(100, 100); recordingCanvas->drawBitmap(bm, 0, 0); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); SkCanvas canvas; canvas.drawPicture(picture); }
// Create a picture that consists of a single large layer that is tiled // with hexagons. // This is intended to exercise the layer hoisting code's clip handling (in // tile mode). static const SkPicture* make_single_layer_hex_plane_picture() { // Create a hexagon with its center at the origin SkPath hex = make_hex_path(0, 0); SkPaint whiteFill; whiteFill.setStyle(SkPaint::kFill_Style); whiteFill.setColor(SK_ColorWHITE); SkPaint greyFill; greyFill.setStyle(SkPaint::kFill_Style); greyFill.setColor(sk_tool_utils::color_to_565(SK_ColorLTGRAY)); SkPaint stroke; stroke.setStyle(SkPaint::kStroke_Style); stroke.setStrokeWidth(3); SkPictureRecorder recorder; SkRTreeFactory bbhFactory; static const SkScalar kBig = 10000.0f; SkCanvas* canvas = recorder.beginRecording(kBig, kBig, &bbhFactory, SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); canvas->saveLayer(nullptr, nullptr); SkScalar xPos = 0.0f, yPos = 0.0f; for (int y = 0; yPos < kBig; ++y) { xPos = 0; for (int x = 0; xPos < kBig; ++x) { canvas->save(); canvas->translate(xPos, yPos + ((x % 2) ? kRoot3Over2 * kHexSide : 0)); // The color of the filled hex is swapped to yield a different // pattern in each tile. This allows an error in layer hoisting (e.g., // the clip isn't blocking cache reuse) to cause a visual discrepancy. canvas->drawPath(hex, ((x+y) % 3) ? whiteFill : greyFill); canvas->drawPath(hex, stroke); canvas->restore(); xPos += 1.5f * kHexSide; } yPos += 2 * kHexSide * kRoot3Over2; } canvas->restore(); return recorder.endRecording(); }
virtual void onDraw(int loops, SkCanvas* canvas) { SkPictureRecorder recorder; SkCanvas* pCanvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, nullptr, 0); this->recordCanvas(pCanvas); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); const SkPoint translateDelta = getTranslateDelta(loops); for (int i = 0; i < loops; i++) { picture->playback(canvas); canvas->translate(translateDelta.fX, translateDelta.fY); } }
void draw(SkCanvas* canvas) { SkPictureRecorder recorder; SkCanvas* pictureCanvas = recorder.beginRecording({0, 0, 256, 256}); SkPaint paint; pictureCanvas->drawRect(SkRect::MakeWH(200, 200), paint); paint.setColor(SK_ColorWHITE); pictureCanvas->drawRect(SkRect::MakeLTRB(20, 20, 180, 180), paint); sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); SkDynamicMemoryWStream writableStream; picture->serialize(&writableStream); std::unique_ptr<SkStreamAsset> readableStream = writableStream.detachAsStream(); sk_sp<SkPicture> copy = SkPicture::MakeFromStream(readableStream.get()); copy->playback(canvas); }
int tool_main(int argc, char** argv) { #if SK_SUPPORT_GPU SkCommandLineFlags::SetUsage("Reports on an skp file's suitability for GPU rasterization"); SkCommandLineFlags::Parse(argc, argv); if (FLAGS_readFile.count() != 1) { if (!FLAGS_quiet) { SkDebugf("Missing input file\n"); } return kError; } SkFILEStream inputStream(FLAGS_readFile[0]); if (!inputStream.isValid()) { if (!FLAGS_quiet) { SkDebugf("Couldn't open file\n"); } return kError; } SkPicture::InstallPixelRefProc proc = &sk_tools::LazyDecodeBitmap; SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&inputStream, proc)); if (NULL == picture.get()) { if (!FLAGS_quiet) { SkDebugf("Could not read the SkPicture\n"); } return kError; } // The SkPicture tracking information is only generated during recording // an isn't serialized. Replay the picture to regenerated the tracking data. SkPictureRecorder recorder; picture->playback(recorder.beginRecording(picture->cullRect().width(), picture->cullRect().height(), NULL, 0)); SkAutoTUnref<SkPicture> recorded(recorder.endRecording()); if (recorded->suitableForGpuRasterization(NULL)) { SkDebugf("suitable\n"); } else { SkDebugf("unsuitable\n"); } return kSuccess; #else SkDebugf("gpuveto is only useful when GPU rendering is enabled\n"); return kError; #endif }