Example #1
0
// 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());
    }
}
Example #2
0
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);
}
Example #3
0
// 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);
    }
}
Example #4
0
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());
}
Example #6
0
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());
}
Example #7
0
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();
}
Example #8
0
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();
}
Example #9
0
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();
}
Example #10
0
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();
}
Example #11
0
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()));
    }
}
Example #12
0
/** 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());
    }
}
Example #13
0
    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();
    }
Example #14
0
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());
    }
}
Example #15
0
 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());
 }
Example #16
0
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();
}
Example #17
0
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);
}
Example #18
0
 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));
 }
Example #19
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());
}
Example #20
0
    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));
        }
    }
Example #21
0
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;
}
Example #22
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();
}
Example #23
0
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));
}
Example #24
0
    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);
    }
Example #25
0
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();
}
Example #26
0
// 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();
}
Example #28
0
    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);
}
Example #30
0
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
}