static void test_peephole() { SkRandom rand; for (int j = 0; j < 100; j++) { SkRandom rand2(rand); // remember the seed SkPicture picture; SkCanvas* canvas = picture.beginRecording(100, 100); for (int i = 0; i < 1000; ++i) { rand_op(canvas, rand); } picture.endRecording(); rand = rand2; } { SkPicture picture; SkCanvas* canvas = picture.beginRecording(100, 100); SkRect rect = SkRect::MakeWH(50, 50); for (int i = 0; i < 100; ++i) { canvas->save(); } while (canvas->getSaveCount() > 1) { canvas->clipRect(rect); canvas->restore(); } picture.endRecording(); } }
virtual void onDraw(SkCanvas* canvas) { this->drawBG(canvas); SkMatrix matrix; SkGroupShape* gs = new SkGroupShape; SkAutoUnref aur(gs); gs->appendShape(&fGroup); matrix.setScale(-SK_Scalar1, SK_Scalar1); matrix.postTranslate(SkIntToScalar(220), SkIntToScalar(240)); gs->appendShape(&fGroup, matrix); matrix.setTranslate(SkIntToScalar(240), 0); matrix.preScale(SK_Scalar1*2, SK_Scalar1*2); gs->appendShape(&fGroup, matrix); #if 1 SkPicture* pict = new SkPicture; SkCanvas* cv = pict->beginRecording(1000, 1000); cv->scale(SK_ScalarHalf, SK_ScalarHalf); gs->draw(cv); cv->translate(SkIntToScalar(680), SkIntToScalar(480)); cv->scale(-SK_Scalar1, SK_Scalar1); gs->draw(cv); pict->endRecording(); canvas->drawPicture(*pict); pict->unref(); #endif }
// Ensure that serializing an empty picture does not assert. Likewise only runs in debug mode. static void test_serializing_empty_picture() { SkPicture picture; picture.beginRecording(0, 0); picture.endRecording(); SkDynamicMemoryWStream stream; picture.serialize(&stream); }
static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer, jobject jstream, jbyteArray jstorage) { BaseLayerAndroid* baseLayer = (BaseLayerAndroid*) jbaseLayer; if (!baseLayer) return false; SkWStream *stream = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); #if USE(ACCELERATED_COMPOSITING) // SAMSUNG CHANGE >> White flickering issue. // WAS:stream->write32(baseLayer->getBackgroundColor().rgb()); stream->write32(baseLayer->getBackgroundColor()); // SAMSUNG CHANGE << #else stream->write32(0); #endif SkPicture picture; PictureSet* content = baseLayer->content(); baseLayer->drawCanvas(picture.beginRecording(content->width(), content->height(), SkPicture::kUsePathBoundsForClip_RecordingFlag)); picture.endRecording(); if (!stream) return false; picture.serialize(stream); int childCount = baseLayer->countChildren(); XLOG("BaseLayer has %d child(ren)", childCount); stream->write32(childCount); for (int i = 0; i < childCount; i++) { LayerAndroid* layer = static_cast<LayerAndroid*>(baseLayer->getChild(i)); serializeLayer(layer, stream); } delete stream; return true; }
virtual void onDraw(SkCanvas* canvas) { this->drawBG(canvas); SkMatrix saveM = *fMatrixRefs[3]; SkScalar c = SkIntToScalar(50); fMatrixRefs[3]->preRotate(SkIntToScalar(30), c, c); SkMatrix matrix; SkGroupShape* gs = new SkGroupShape; SkAutoUnref aur(gs); gs->appendShape(&fGroup); matrix.setScale(-SK_Scalar1, SK_Scalar1); matrix.postTranslate(SkIntToScalar(220), SkIntToScalar(240)); gs->appendShape(&fGroup, matrix); matrix.setTranslate(SkIntToScalar(240), 0); matrix.preScale(SK_Scalar1*2, SK_Scalar1*2); gs->appendShape(&fGroup, matrix); #if 0 canvas->drawShape(gs); #else SkPicture pict; SkCanvas* cv = pict.beginRecording(1000, 1000); cv->scale(SK_ScalarHalf, SK_ScalarHalf); cv->drawShape(gs); cv->translate(SkIntToScalar(680), SkIntToScalar(480)); cv->scale(-SK_Scalar1, SK_Scalar1); cv->drawShape(gs); pict.endRecording(); canvas->drawPicture(pict); #endif *fMatrixRefs[3] = saveM; }
// Ensure that deleting SkPicturePlayback does not assert. Asserts only fire in debug mode, so only // run in debug mode. static void test_deleting_empty_playback() { SkPicture picture; // Creates an SkPictureRecord picture.beginRecording(0, 0); // Turns that into an SkPicturePlayback picture.endRecording(); // Deletes the old SkPicturePlayback, and creates a new SkPictureRecord picture.beginRecording(0, 0); }
void PicturePileLayerContent::serialize(SkWStream* stream) { if (!stream) return; SkPicture picture; draw(picture.beginRecording(width(), height(), SkPicture::kUsePathBoundsForClip_RecordingFlag)); picture.endRecording(); picture.serialize(stream); }
// Return a picture with the bitmaps drawn at the specified positions. static SkPicture* record_bitmaps(const SkBitmap bm[], const SkPoint pos[], int count, DrawBitmapProc proc) { SkPicture* pic = new SkPicture; SkCanvas* canvas = pic->beginRecording(1000, 1000); for (int i = 0; i < count; ++i) { proc(canvas, bm[i], pos[i]); } pic->endRecording(); return pic; }
/** 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) { SkPicture* newPicture = this->createPicture(); SkCanvas* recorder = newPicture->beginRecording(fPicture->width(), fPicture->height(), this->recordFlags()); fPicture->draw(recorder); newPicture->endRecording(); fPicture->unref(); fPicture = newPicture; } }
// 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.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); SkPicture picture; SkCanvas* recordingCanvas = picture.beginRecording(100, 100); recordingCanvas->drawBitmap(bm, 0, 0); picture.endRecording(); SkCanvas canvas; canvas.drawPicture(picture); }
static SkPicture* LoadPdf(const char path[]) { SkAutoTDelete<SkPdfRenderer> renderer(SkPdfRenderer::CreateFromFile(path)); if (NULL == renderer.get()) { return NULL; } SkPicture* pic = SkNEW(SkPicture); SkCanvas* canvas = pic->beginRecording((int) renderer->MediaBox(0).width(), (int) renderer->MediaBox(0).height()); renderer->renderPage(0, canvas, renderer->MediaBox(0)); pic->endRecording(); return pic; }
static void bench_record(SkPicture* src, const char* name) { const SkMSec start = SkTime::GetMSecs(); const int width = src ? src->width() : FLAGS_nullSize; const int height = src ? src->height() : FLAGS_nullSize; for (int i = 0; i < FLAGS_loops; i++) { SkPicture dst; SkCanvas* canvas = dst.beginRecording(width, height, FLAGS_flags); if (src) src->draw(canvas); if (FLAGS_endRecording) dst.endRecording(); } const SkMSec elapsed = SkTime::GetMSecs() - start; const double msPerLoop = elapsed / (double)FLAGS_loops; printf("%.2g\t%s\n", msPerLoop, name); }
virtual void onDrawContent(SkCanvas* canvas) { drawSomething(canvas); SkPicture* pict = new SkPicture; SkAutoUnref aur(pict); drawSomething(pict->beginRecording(100, 100)); pict->endRecording(); canvas->save(); canvas->translate(SkIntToScalar(300), SkIntToScalar(50)); canvas->scale(-SK_Scalar1, -SK_Scalar1); canvas->translate(-SkIntToScalar(100), -SkIntToScalar(50)); canvas->drawPicture(*pict); canvas->restore(); canvas->save(); canvas->translate(SkIntToScalar(200), SkIntToScalar(150)); canvas->scale(SK_Scalar1, -SK_Scalar1); canvas->translate(0, -SkIntToScalar(50)); canvas->drawPicture(*pict); canvas->restore(); canvas->save(); canvas->translate(SkIntToScalar(100), SkIntToScalar(100)); canvas->scale(-SK_Scalar1, SK_Scalar1); canvas->translate(-SkIntToScalar(100), 0); canvas->drawPicture(*pict); canvas->restore(); #ifdef SK_DEVELOPER if (false) { SkDebugfDumper dumper; SkDumpCanvas dumpCanvas(&dumper); dumpCanvas.drawPicture(*pict); } #endif // test that we can re-record a subpicture, and see the results SkMWCRandom rand(SampleCode::GetAnimTime()); canvas->translate(SkIntToScalar(10), SkIntToScalar(250)); drawCircle(fSubPicture->beginRecording(50, 50), 25, rand.nextU() | 0xFF000000); canvas->drawPicture(*fPicture); delayInval(500); }
virtual void onDrawContent(SkCanvas* canvas) { SkScalar angle = SampleCode::GetAnimScalar(SkIntToScalar(180), SkIntToScalar(360)); SkMatrix saveM = *fMatrixRefs[3]; SkScalar c = SkIntToScalar(50); fMatrixRefs[3]->preRotate(angle, c, c); const SkScalar dx = 350; const SkScalar dy = 500; const int N = 1; for (int v = -N; v <= N; v++) { for (int h = -N; h <= N; h++) { SkAutoCanvasRestore acr(canvas, true); canvas->translate(h * dx, v * dy); SkMatrix matrix; SkGroupShape* gs = new SkGroupShape; SkAutoUnref aur(gs); gs->appendShape(&fGroup); matrix.setScale(-SK_Scalar1, SK_Scalar1); matrix.postTranslate(SkIntToScalar(220), SkIntToScalar(240)); gs->appendShape(&fGroup, matrix); matrix.setTranslate(SkIntToScalar(240), 0); matrix.preScale(SK_Scalar1*2, SK_Scalar1*2); gs->appendShape(&fGroup, matrix); #if 1 SkPicture* pict = new SkPicture; SkCanvas* cv = pict->beginRecording(1000, 1000); cv->scale(SK_ScalarHalf, SK_ScalarHalf); gs->draw(cv); cv->translate(SkIntToScalar(680), SkIntToScalar(480)); cv->scale(-SK_Scalar1, SK_Scalar1); gs->draw(cv); pict->endRecording(); drawpicture(canvas, *pict); pict->unref(); #endif }} *fMatrixRefs[3] = saveM; this->inval(NULL); }
virtual void onDraw(SkCanvas*) { int n = (int)(N * this->innerLoopScale()); n = SkMax32(1, n); for (int i = 0; i < n; i++) { SkPicture picture; SkCanvas* pCanvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT); recordCanvas(pCanvas); // we don't need to draw the picture as the endRecording step will // do the work of transferring the recorded content into a playback // object. picture.endRecording(); } }
void PicturePile::updatePicture(PicturePainter* painter, PictureContainer& pc) { /* The ref counting here is a bit unusual. What happens is begin/end recording * will ref/unref the recording canvas. However, 'canvas' might be pointing * at an SkNWayCanvas instead of the recording canvas, which needs to be * unref'd. Thus what we do is ref the recording canvas so that we can * always unref whatever canvas we have at the end. */ TRACE_METHOD(); SkPicture* picture = new SkPicture(); SkCanvas* canvas = picture->beginRecording(pc.area.width(), pc.area.height(), SkPicture::kUsePathBoundsForClip_RecordingFlag); SkSafeRef(canvas); canvas->translate(-pc.area.x(), -pc.area.y()); IntRect drawArea = pc.area; if (pc.prerendered.get()) { SkCanvas* prerender = painter->createPrerenderCanvas(pc.prerendered.get()); if (!prerender) { ALOGV("Failed to create prerendered for " INT_RECT_FORMAT, INT_RECT_ARGS(pc.prerendered->area)); pc.prerendered.clear(); } else { drawArea.unite(pc.prerendered->area); SkNWayCanvas* nwayCanvas = new SkNWayCanvas(drawArea.width(), drawArea.height()); nwayCanvas->translate(-drawArea.x(), -drawArea.y()); nwayCanvas->addCanvas(canvas); nwayCanvas->addCanvas(prerender); SkSafeUnref(canvas); SkSafeUnref(prerender); canvas = nwayCanvas; } } WebCore::PlatformGraphicsContextSkia pgc(canvas); WebCore::GraphicsContext gc(&pgc); ALOGV("painting picture: " INT_RECT_FORMAT, INT_RECT_ARGS(drawArea)); painter->paintContents(&gc, drawArea); SkSafeUnref(canvas); picture->endRecording(); SkSafeUnref(pc.picture); pc.picture = picture; pc.dirty = false; }
static void test_clone_empty(skiatest::Reporter* reporter) { // This is a regression test for crbug.com/172062 // Before the fix, we used to crash accessing a null pointer when we // had a picture with no paints. This test passes by not crashing. { SkPicture picture; picture.beginRecording(1, 1); picture.endRecording(); SkPicture* destPicture = picture.clone(); REPORTER_ASSERT(reporter, NULL != destPicture); destPicture->unref(); } { // Test without call to endRecording SkPicture picture; picture.beginRecording(1, 1); SkPicture* destPicture = picture.clone(); REPORTER_ASSERT(reporter, NULL != destPicture); destPicture->unref(); } }
virtual void onDraw(SkCanvas* canvas) { int offset = 35000; int extents = 1000; // We record a picture of huge vertical extents in which we clear the canvas to red, create // a 'extents' by 'extents' round rect clip at a vertical offset of 'offset', then draw // green into that. SkPicture pict; SkCanvas* rec = pict.beginRecording(100, offset + extents); rec->drawColor(0xffff0000); rec->save(); SkRect r = { SkIntToScalar(-extents), SkIntToScalar(offset - extents), SkIntToScalar(extents), SkIntToScalar(offset + extents) }; SkPath p; p.addRoundRect(r, 5, 5); rec->clipPath(p, SkRegion::kIntersect_Op, true); rec->drawColor(0xff00ff00); rec->restore(); pict.endRecording(); // Next we play that picture into another picture of the same size. SkPicture pict2; pict.draw(pict2.beginRecording(100, offset + extents)); pict2.endRecording(); // Finally we play the part of that second picture that should be green into the canvas. canvas->save(); canvas->translate(SkIntToScalar(extents / 2), SkIntToScalar(-(offset - extents / 2))); pict2.draw(canvas); canvas->restore(); // If the image is red, we erroneously decided the clipPath was empty and didn't record // the green drawColor, if it's green we're all good. }
/** * Called only by render_picture(). */ static bool render_picture_internal(const SkString& inputPath, const SkString* outputDir, sk_tools::PictureRenderer& renderer, SkBitmap** out) { SkString inputFilename; sk_tools::get_basename(&inputFilename, inputPath); SkString outputDirString; if (NULL != outputDir && outputDir->size() > 0 && !FLAGS_writeEncodedImages) { outputDirString.set(*outputDir); } SkFILEStream inputStream; inputStream.setPath(inputPath.c_str()); if (!inputStream.isValid()) { SkDebugf("Could not open file %s\n", inputPath.c_str()); return false; } SkPicture::InstallPixelRefProc proc; if (FLAGS_deferImageDecoding) { proc = &sk_tools::LazyDecodeBitmap; } else if (FLAGS_writeEncodedImages) { SkASSERT(!FLAGS_writePath.isEmpty()); reset_image_file_base_name(inputFilename); proc = &write_image_to_file; } else { proc = &SkImageDecoder::DecodeMemory; } SkDebugf("deserializing... %s\n", inputPath.c_str()); SkPicture* picture = SkPicture::CreateFromStream(&inputStream, proc); if (NULL == picture) { SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str()); return false; } while (FLAGS_bench_record) { const int kRecordFlags = 0; SkPicture other; picture->draw(other.beginRecording(picture->width(), picture->height(), kRecordFlags)); other.endRecording(); } for (int i = 0; i < FLAGS_clone; ++i) { SkPicture* clone = picture->clone(); SkDELETE(picture); picture = clone; } SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(), inputPath.c_str()); renderer.init(picture, &outputDirString, &inputFilename, FLAGS_writeChecksumBasedFilenames); if (FLAGS_preprocess) { if (NULL != renderer.getCanvas()) { renderer.getCanvas()->EXPERIMENTAL_optimize(picture); } } renderer.setup(); bool success = renderer.render(out); if (!success) { SkDebugf("Failed to render %s\n", inputFilename.c_str()); } renderer.end(); SkDELETE(picture); return success; }
// construct the pattern removed by the SkPictureRecord::remove_save_layer1 // optimization, i.e.: // SAVE_LAYER // DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_RECT // RESTORE // // saveLayerHasPaint - control if the saveLayer has a paint (the optimization // takes a different path if this is false) // dbmr2rHasPaint - control if the dbmr2r has a paint (the optimization // takes a different path if this is false) // colorsMatch - control if the saveLayer and dbmr2r paint colors // match (the optimization will fail if they do not) static SkPicture* create_save_layer_opt_1(SkTDArray<DrawType>* preOptPattern, SkTDArray<DrawType>* postOptPattern, const SkBitmap& checkerBoard, bool saveLayerHasPaint, bool dbmr2rHasPaint, bool colorsMatch) { // Create the pattern that should trigger the optimization preOptPattern->setCount(5); (*preOptPattern)[0] = SAVE; (*preOptPattern)[1] = SAVE_LAYER; (*preOptPattern)[2] = DRAW_BITMAP_RECT_TO_RECT; (*preOptPattern)[3] = RESTORE; (*preOptPattern)[4] = RESTORE; if (colorsMatch) { // Create the pattern that should appear after the optimization postOptPattern->setCount(5); (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw (*postOptPattern)[1] = SAVE; (*postOptPattern)[2] = DRAW_BITMAP_RECT_TO_RECT; (*postOptPattern)[3] = RESTORE; (*postOptPattern)[4] = RESTORE; } else { // Create the pattern that appears if the optimization doesn't fire postOptPattern->setCount(7); (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw (*postOptPattern)[1] = SAVE; (*postOptPattern)[2] = SAVE_LAYER; (*postOptPattern)[3] = DRAW_BITMAP_RECT_TO_RECT; (*postOptPattern)[4] = RESTORE; (*postOptPattern)[5] = RESTORE; (*postOptPattern)[6] = RESTORE; } SkPicture* result = new SkPicture; // have to disable the optimizations while generating the picture SkCanvas* canvas = result->beginRecording(100, 100, SkPicture::kDisableRecordOptimizations_RecordingFlag); SkPaint saveLayerPaint; saveLayerPaint.setColor(0xCC000000); // saveLayer's 'bounds' parameter must be NULL for this optimization if (saveLayerHasPaint) { canvas->saveLayer(NULL, &saveLayerPaint); } else { canvas->saveLayer(NULL, NULL); } SkRect rect = { 10, 10, 90, 90 }; // The dbmr2r's paint must be opaque SkPaint dbmr2rPaint; if (colorsMatch) { dbmr2rPaint.setColor(0xFF000000); } else { dbmr2rPaint.setColor(0xFFFF0000); } if (dbmr2rHasPaint) { canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, &dbmr2rPaint); } else { canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, NULL); } canvas->restore(); result->endRecording(); return result; }
static void endRecording(JNIEnv* env, jobject, jlong pictHandle) { SkPicture* pict = reinterpret_cast<SkPicture*>(pictHandle); pict->endRecording(); }
static int filter_picture(const SkString& inFile, const SkString& outFile) { SkAutoTDelete<SkPicture> inPicture; SkFILEStream inStream(inFile.c_str()); if (inStream.isValid()) { inPicture.reset(SkPicture::CreateFromStream(&inStream)); } if (NULL == inPicture.get()) { SkDebugf("Could not read file %s\n", inFile.c_str()); return -1; } int localCount[SK_ARRAY_COUNT(gOptTable)]; memset(localCount, 0, sizeof(localCount)); SkDebugCanvas debugCanvas(inPicture->width(), inPicture->height()); debugCanvas.setBounds(inPicture->width(), inPicture->height()); inPicture->draw(&debugCanvas); // delete the initial save and restore since replaying the commands will // re-add them if (debugCanvas.getSize() > 1) { debugCanvas.deleteDrawCommandAt(0); debugCanvas.deleteDrawCommandAt(debugCanvas.getSize()-1); } bool changed = true; int numBefore = debugCanvas.getSize(); while (changed) { changed = false; for (int i = 0; i < debugCanvas.getSize(); ++i) { for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) { if ((*gOptTable[opt].fCheck)(&debugCanvas, i)) { (*gOptTable[opt].fApply)(&debugCanvas, i); ++gOptTable[opt].fNumTimesApplied; ++localCount[opt]; if (debugCanvas.getSize() == i) { // the optimization removed all the remaining operations break; } opt = 0; // try all the opts all over again changed = true; } } } } int numAfter = debugCanvas.getSize(); if (!outFile.isEmpty()) { SkPicture outPicture; SkCanvas* canvas = outPicture.beginRecording(inPicture->width(), inPicture->height()); debugCanvas.draw(canvas); outPicture.endRecording(); SkFILEWStream outStream(outFile.c_str()); outPicture.serialize(&outStream); } bool someOptFired = false; for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) { if (0 != localCount[opt]) { SkDebugf("%d: %d ", opt, localCount[opt]); someOptFired = true; } } if (!someOptFired) { SkDebugf("No opts fired\n"); } else { SkDebugf("\t before: %d after: %d delta: %d\n", numBefore, numAfter, numBefore-numAfter); } return 0; }
static void test_collapse(skiatest::Reporter* reporter) { PFEmitStruct gStructure[] = { emit_struct0, emit_struct1, emit_struct2, emit_struct3 }; PFEmitBody gBody[] = { emit_body0, emit_body1, emit_body2, emit_body3 }; PFEmitMC gMCs[] = { emit_clip_and_mat, emit_mat_and_clip, emit_double_mat_and_clip, emit_mat_clip_clip }; for (size_t i = 0; i < SK_ARRAY_COUNT(gStructure); ++i) { for (size_t j = 0; j < SK_ARRAY_COUNT(gBody); ++j) { for (size_t k = 0; k < SK_ARRAY_COUNT(gMCs); ++k) { for (int l = 0; l < kMatTypeCount; ++l) { for (int m = 0; m < kClipTypeCount; ++m) { for (int n = 0; n < kNonSaveLayerDrawOpTypeCount; ++n) { #ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE static int testID = -1; ++testID; if (testID < -1) { continue; } SkDebugf("test: %d\n", testID); #endif SkTDArray<DrawType> expected, actual; SkPicture picture; // Note: beginRecording/endRecording add a save/restore pair SkCanvas* canvas = picture.beginRecording(100, 100); (*gStructure[i])(canvas, gMCs[k], (MatType) l, (ClipType) m, gBody[j], (DrawOpType) n, &expected); picture.endRecording(); gets_ops(picture, &actual); REPORTER_ASSERT(reporter, expected.count() == actual.count()); if (expected.count() != actual.count()) { #ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE print(expected, actual); #endif continue; } for (int i = 0; i < expected.count(); ++i) { REPORTER_ASSERT(reporter, expected[i] == actual[i]); #ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE if (expected[i] != actual[i]) { print(expected, actual); } #endif break; } } } } } } } }