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; }