Example #1
0
/* Hit a few SkPicture::Analysis cases not handled elsewhere. */
static void test_analysis(skiatest::Reporter* reporter) {
    SkPictureRecorder recorder;

    SkCanvas* canvas = recorder.beginRecording(100, 100);
    {
        canvas->drawRect(SkRect::MakeWH(10, 10), SkPaint ());
    }
    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    REPORTER_ASSERT(reporter, !picture->willPlayBackBitmaps());

    canvas = recorder.beginRecording(100, 100);
    {
        SkPaint paint;
        // CreateBitmapShader is too smart for us; an empty (or 1x1) bitmap shader
        // gets optimized into a non-bitmap form, so we create a 2x2 bitmap here.
        SkBitmap bitmap;
        bitmap.allocPixels(SkImageInfo::MakeN32Premul(2, 2));
        bitmap.eraseColor(SK_ColorBLUE);
        *(bitmap.getAddr32(0, 0)) = SK_ColorGREEN;
        SkShader* shader = SkShader::CreateBitmapShader(bitmap, SkShader::kClamp_TileMode,
                                                        SkShader::kClamp_TileMode);
        paint.setShader(shader)->unref();
        REPORTER_ASSERT(reporter,
                        shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType);

        canvas->drawRect(SkRect::MakeWH(10, 10), paint);
    }
    picture.reset(recorder.endRecording());
    REPORTER_ASSERT(reporter, picture->willPlayBackBitmaps());
}
Example #2
0
    PictureView() {

        fBitmap = load_bitmap();

        SkPictureRecorder recorder;

        recorder.beginRecording(100, 100, NULL, 0);
        fSubPicture = recorder.endRecording();

        SkCanvas* canvas = recorder.beginRecording(100, 100, NULL, 0);
        SkPaint paint;
        paint.setAntiAlias(true);

        canvas->drawBitmap(fBitmap, 0, 0, NULL);

        drawCircle(canvas, 50, SK_ColorBLACK);
        canvas->drawPicture(fSubPicture);
        canvas->translate(SkIntToScalar(50), 0);
        canvas->drawPicture(fSubPicture);
        canvas->translate(0, SkIntToScalar(50));
        canvas->drawPicture(fSubPicture);
        canvas->translate(SkIntToScalar(-50), 0);
        canvas->drawPicture(fSubPicture);

        fPicture = recorder.endRecording();

        // fPicture now has (4) references to fSubPicture. We can release our ref,
        // and just unref fPicture in our destructor, and it will in turn take care of
        // the other references to fSubPicture
        fSubPicture->unref();
    }
Example #3
0
static void test_unbalanced_save_restores(skiatest::Reporter* reporter) {
    SkCanvas testCanvas(100, 100);
    set_canvas_to_save_count_4(&testCanvas);

    REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());

    SkPaint paint;
    SkRect rect = SkRect::MakeLTRB(-10000000, -10000000, 10000000, 10000000);

    SkPictureRecorder recorder;

    {
        // Create picture with 2 unbalanced saves
        SkCanvas* canvas = recorder.beginRecording(100, 100);
        canvas->save();
        canvas->translate(10, 10);
        canvas->drawRect(rect, paint);
        canvas->save();
        canvas->translate(10, 10);
        canvas->drawRect(rect, paint);
        SkAutoTUnref<SkPicture> extraSavePicture(recorder.endRecording());

        testCanvas.drawPicture(extraSavePicture);
        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
    }

    set_canvas_to_save_count_4(&testCanvas);

    {
        // Create picture with 2 unbalanced restores
        SkCanvas* canvas = recorder.beginRecording(100, 100);
        canvas->save();
        canvas->translate(10, 10);
        canvas->drawRect(rect, paint);
        canvas->save();
        canvas->translate(10, 10);
        canvas->drawRect(rect, paint);
        canvas->restore();
        canvas->restore();
        canvas->restore();
        canvas->restore();
        SkAutoTUnref<SkPicture> extraRestorePicture(recorder.endRecording());

        testCanvas.drawPicture(extraRestorePicture);
        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
    }

    set_canvas_to_save_count_4(&testCanvas);

    {
        SkCanvas* canvas = recorder.beginRecording(100, 100);
        canvas->translate(10, 10);
        canvas->drawRect(rect, paint);
        SkAutoTUnref<SkPicture> noSavePicture(recorder.endRecording());

        testCanvas.drawPicture(noSavePicture);
        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
        REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity());
    }
}
TEST_F(DeferredImageDecoderTest, drawIntoSkPictureProgressive)
{
    RefPtr<SharedBuffer> partialData = SharedBuffer::create(m_data->data(), m_data->size() - 10);

    // Received only half the file.
    m_lazyDecoder->setData(*partialData, false);
    RefPtr<NativeImageSkia> image = m_lazyDecoder->frameBufferAtIndex(0)->asNewNativeImage();
    SkPictureRecorder recorder;
    SkCanvas* tempCanvas = recorder.beginRecording(100, 100, 0, 0);
    tempCanvas->drawBitmap(image->bitmap(), 0, 0);
    RefPtr<SkPicture> picture = adoptRef(recorder.endRecording());
    m_surface->getCanvas()->drawPicture(picture.get());

    // Fully received the file and draw the SkPicture again.
    m_lazyDecoder->setData(*m_data, true);
    image = m_lazyDecoder->frameBufferAtIndex(0)->asNewNativeImage();
    tempCanvas = recorder.beginRecording(100, 100, 0, 0);
    tempCanvas->drawBitmap(image->bitmap(), 0, 0);
    picture = adoptRef(recorder.endRecording());
    m_surface->getCanvas()->drawPicture(picture.get());

    SkBitmap canvasBitmap;
    canvasBitmap.allocN32Pixels(100, 100);
    ASSERT_TRUE(m_surface->getCanvas()->readPixels(&canvasBitmap, 0, 0));
    SkAutoLockPixels autoLock(canvasBitmap);
    EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), canvasBitmap.getColor(0, 0));
}
Example #5
0
static void test_peephole() {
    SkRandom rand;

    SkPictureRecorder recorder;

    for (int j = 0; j < 100; j++) {
        SkRandom rand2(rand); // remember the seed

        SkCanvas* canvas = recorder.beginRecording(100, 100);

        for (int i = 0; i < 1000; ++i) {
            rand_op(canvas, rand);
        }
        SkAutoTUnref<SkPicture> picture(recorder.endRecording());

        rand = rand2;
    }

    {
        SkCanvas* canvas = recorder.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();
        }
        SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    }
}
Example #6
0
SkPicture* SkDebugger::copyPicture() {
    // We can't just call clone here since we want to removed the "deleted"
    // commands. Playing back will strip those out.
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(fPictureWidth, fPictureHeight, NULL, 0);

    bool vizMode = fDebugCanvas->getMegaVizMode();
    fDebugCanvas->setMegaVizMode(false);
    bool overDraw = fDebugCanvas->getOverdrawViz();
    fDebugCanvas->setOverdrawViz(false);
    bool pathOps = fDebugCanvas->getAllowSimplifyClip();
    fDebugCanvas->setAllowSimplifyClip(false);
    int saveCount = fDebugCanvas->getOutstandingSaveCount();
    fDebugCanvas->setOutstandingSaveCount(0);

    fDebugCanvas->draw(canvas);

    int temp = fDebugCanvas->getOutstandingSaveCount();
    for (int i = 0; i < temp; ++i) {
        canvas->restore();
    }

    fDebugCanvas->setMegaVizMode(vizMode);
    fDebugCanvas->setOverdrawViz(overDraw);
    fDebugCanvas->setOutstandingSaveCount(saveCount);
    fDebugCanvas->setAllowSimplifyClip(pathOps);

    return recorder.endRecording();
}
Example #7
0
static SkImage* create_picture_image() {
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(10, 10);
    canvas->clear(SK_ColorCYAN);
    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    return SkImage::NewFromPicture(picture, SkISize::Make(10, 10), nullptr, nullptr);
};
Example #8
0
int DownloadHandler::handle(Request* request, MHD_Connection* connection,
                            const char* url, const char* method,
                            const char* upload_data, size_t* upload_data_size) {
    if (!request->hasPicture()) {
        return MHD_NO;
    }

    // TODO move to a function
    // Playback into picture recorder
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(Request::kImageWidth,
                                               Request::kImageHeight);

    request->fDebugCanvas->draw(canvas);

    SkAutoTUnref<SkPicture> picture(recorder.endRecording());

    SkDynamicMemoryWStream outStream;

    SkAutoTUnref<SkPixelSerializer> serializer(SkImageEncoder::CreatePixelSerializer());
    picture->serialize(&outStream, serializer);

    SkAutoTUnref<SkData> data(outStream.copyToData());

    // TODO fancier name handling
    return SendData(connection, data, "application/octet-stream", true,
                    "attachment; filename=something.skp;");
}
static const SkPicture* make_sub_picture(const SkPicture* tri) {
    SkPictureRecorder recorder;

    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
                                               SkIntToScalar(kPicHeight));

    canvas->scale(1.0f/2.0f, 1.0f/2.0f);

    canvas->save();
    canvas->translate(SkScalarHalf(kTriSide), 0);
    canvas->drawPicture(tri);
    canvas->restore();

    canvas->save();
    canvas->translate(SkIntToScalar(kTriSide), 1.5f * kTriSide / kRoot3);
    canvas->drawPicture(tri);
    canvas->restore();

    canvas->save();
    canvas->translate(0, 1.5f * kTriSide / kRoot3);
    canvas->drawPicture(tri);
    canvas->restore();

    return recorder.endRecording();
}
TEST_F(DeferredImageDecoderTest, decodeOnOtherThread)
{
    m_lazyDecoder->setData(*m_data, true);
    RefPtr<SkImage> image = m_lazyDecoder->createFrameAtIndex(0);
    ASSERT_TRUE(image);
    EXPECT_EQ(1, image->width());
    EXPECT_EQ(1, image->height());

    SkPictureRecorder recorder;
    SkCanvas* tempCanvas = recorder.beginRecording(100, 100, 0, 0);
    tempCanvas->drawImage(image.get(), 0, 0);
    RefPtr<SkPicture> picture = adoptRef(recorder.endRecording());
    EXPECT_EQ(0, m_decodeRequestCount);

    // Create a thread to rasterize SkPicture.
    OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("RasterThread"));
    thread->taskRunner()->postTask(BLINK_FROM_HERE, new Task(threadSafeBind(&rasterizeMain, AllowCrossThreadAccess(m_surface->getCanvas()), AllowCrossThreadAccess(picture.get()))));
    thread.clear();
    EXPECT_EQ(0, m_decodeRequestCount);

    SkBitmap canvasBitmap;
    canvasBitmap.allocN32Pixels(100, 100);
    ASSERT_TRUE(m_surface->getCanvas()->readPixels(&canvasBitmap, 0, 0));
    SkAutoLockPixels autoLock(canvasBitmap);
    EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), canvasBitmap.getColor(0, 0));
}
// Verify that associated bitmap cache entries are purged on SkImage destruction.
DEF_TEST(BitmapCache_discarded_image, reporter) {
    // Cache entries associated with SkImages fall into two categories:
    //
    // 1) generated image bitmaps (managed by the image cacherator)
    // 2) scaled/resampled bitmaps (cached when HQ filters are used)
    //
    // To exercise the first cache type, we use generated/picture-backed SkImages.
    // To exercise the latter, we draw scaled bitmap images using HQ filters.

    const SkMatrix xforms[] = {
        SkMatrix::MakeScale(1, 1),
        SkMatrix::MakeScale(1.7f, 0.5f),
    };

    for (size_t i = 0; i < SK_ARRAY_COUNT(xforms); ++i) {
        test_discarded_image(reporter, xforms[i], []() {
            SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(10, 10));
            surface->getCanvas()->clear(SK_ColorCYAN);
            return surface->newImageSnapshot();
        });

        test_discarded_image(reporter, xforms[i], []() {
            SkPictureRecorder recorder;
            SkCanvas* canvas = recorder.beginRecording(10, 10);
            canvas->clear(SK_ColorCYAN);
            SkAutoTUnref<SkPicture> picture(recorder.endRecording());
            return SkImage::NewFromPicture(picture, SkISize::Make(10, 10), nullptr, nullptr);
        });
    }
}
Example #12
0
static void serialize_and_compare_typeface(SkTypeface* typeface, const char* text,
                                           skiatest::Reporter* reporter)
{
    // Create a paint with the typeface.
    SkPaint paint;
    paint.setColor(SK_ColorGRAY);
    paint.setTextSize(SkIntToScalar(30));
    paint.setTypeface(typeface);

    // Paint some text.
    SkPictureRecorder recorder;
    SkIRect canvasRect = SkIRect::MakeWH(kBitmapSize, kBitmapSize);
    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(canvasRect.width()), 
                                               SkIntToScalar(canvasRect.height()), 
                                               nullptr, 0);
    canvas->drawColor(SK_ColorWHITE);
    canvas->drawText(text, 2, 24, 32, paint);
    SkAutoTUnref<SkPicture> picture(recorder.endRecording());

    // Serlialize picture and create its clone from stream.
    SkDynamicMemoryWStream stream;
    picture->serialize(&stream);
    SkAutoTDelete<SkStream> inputStream(stream.detachAsStream());
    SkAutoTUnref<SkPicture> loadedPicture(SkPicture::CreateFromStream(inputStream.get()));

    // Draw both original and clone picture and compare bitmaps -- they should be identical.
    SkBitmap origBitmap = draw_picture(*picture);
    SkBitmap destBitmap = draw_picture(*loadedPicture);
    compare_bitmaps(reporter, origBitmap, destBitmap);
}
Example #13
0
static void bench_record(SkPicture* src, const char* name, SkBBHFactory* bbhFactory) {
    BenchTimer timer;
    timer.start();
    const int width  = src ? src->width()  : FLAGS_nullSize;
    const int height = src ? src->height() : FLAGS_nullSize;

    for (int i = 0; i < FLAGS_loops; i++) {
        if (FLAGS_skr) {
            EXPERIMENTAL::SkRecording recording(width, height);
            if (NULL != src) {
                src->draw(recording.canvas());
            }
            // Release and delete the SkPlayback so that recording optimizes its SkRecord.
            SkDELETE(recording.releasePlayback());
        } else {
            SkPictureRecorder recorder;
            SkCanvas* canvas = recorder.beginRecording(width, height, bbhFactory, FLAGS_flags);
            if (NULL != src) {
                src->draw(canvas);
            }
            if (FLAGS_endRecording) {
                SkAutoTUnref<SkPicture> dst(recorder.endRecording());
            }
        }
    }
    timer.end();

    const double msPerLoop = timer.fCpu / (double)FLAGS_loops;
    printf("%f\t%s\n", scale_time(msPerLoop), name);
}
Example #14
0
    void onDrawContent(SkCanvas* canvas) override {
        this->drawSomething(canvas);

        SkPictureRecorder recorder;
        this->drawSomething(recorder.beginRecording(100, 100, NULL, 0));
        SkAutoTUnref<SkPicture> pict(recorder.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();
    }
Example #15
0
DEF_TEST(Picture_BitmapLeak, r) {
    SkBitmap mut, immut;
    mut.allocN32Pixels(300, 200);
    immut.allocN32Pixels(300, 200);
    immut.setImmutable();
    SkASSERT(!mut.isImmutable());
    SkASSERT(immut.isImmutable());

    // No one can hold a ref on our pixels yet.
    REPORTER_ASSERT(r, mut.pixelRef()->unique());
    REPORTER_ASSERT(r, immut.pixelRef()->unique());

    SkAutoTUnref<const SkPicture> pic;
    {
        // we want the recorder to go out of scope before our subsequent checks, so we
        // place it inside local braces.
        SkPictureRecorder rec;
        SkCanvas* canvas = rec.beginRecording(1920, 1200);
            canvas->drawBitmap(mut, 0, 0);
            canvas->drawBitmap(immut, 800, 600);
        pic.reset(rec.endRecording());
    }

    // The picture shares the immutable pixels but copies the mutable ones.
    REPORTER_ASSERT(r, mut.pixelRef()->unique());
    REPORTER_ASSERT(r, !immut.pixelRef()->unique());

    // When the picture goes away, it's just our bitmaps holding the refs.
    pic.reset(NULL);
    REPORTER_ASSERT(r, mut.pixelRef()->unique());
    REPORTER_ASSERT(r, immut.pixelRef()->unique());
}
TEST_F(DeferredImageDecoderTest, decodeOnOtherThread)
{
    m_lazyDecoder->setData(*m_data, true);
    RefPtr<NativeImageSkia> image = m_lazyDecoder->frameBufferAtIndex(0)->asNewNativeImage();
    EXPECT_EQ(1, image->bitmap().width());
    EXPECT_EQ(1, image->bitmap().height());
    EXPECT_FALSE(image->bitmap().isNull());
    EXPECT_TRUE(image->bitmap().isImmutable());

    SkPictureRecorder recorder;
    SkCanvas* tempCanvas = recorder.beginRecording(100, 100, 0, 0);
    tempCanvas->drawBitmap(image->bitmap(), 0, 0);
    RefPtr<SkPicture> picture = adoptRef(recorder.endRecording());
    EXPECT_EQ(0, m_frameBufferRequestCount);

    // Create a thread to rasterize SkPicture.
    OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("RasterThread"));
    thread->postTask(new Task(WTF::bind(&rasterizeMain, m_surface->getCanvas(), picture.get())));
    thread.clear();
    EXPECT_EQ(0, m_frameBufferRequestCount);

    SkBitmap canvasBitmap;
    canvasBitmap.allocN32Pixels(100, 100);
    ASSERT_TRUE(m_surface->getCanvas()->readPixels(&canvasBitmap, 0, 0));
    SkAutoLockPixels autoLock(canvasBitmap);
    EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), canvasBitmap.getColor(0, 0));
}
TEST_F(DeferredImageDecoderTest, drawIntoSkPicture)
{
    m_lazyDecoder->setData(*m_data, true);
    SkBitmap bitmap;
    EXPECT_TRUE(m_lazyDecoder->createFrameAtIndex(0, &bitmap));
    EXPECT_EQ(1, bitmap.width());
    EXPECT_EQ(1, bitmap.height());
    EXPECT_FALSE(bitmap.isNull());
    EXPECT_TRUE(bitmap.isImmutable());

    SkPictureRecorder recorder;
    SkCanvas* tempCanvas = recorder.beginRecording(100, 100, 0, 0);
    tempCanvas->drawBitmap(bitmap, 0, 0);
    RefPtr<SkPicture> picture = adoptRef(recorder.endRecording());
    EXPECT_EQ(0, m_decodeRequestCount);

    m_surface->getCanvas()->drawPicture(picture.get());
    EXPECT_EQ(0, m_decodeRequestCount);

    SkBitmap canvasBitmap;
    canvasBitmap.allocN32Pixels(100, 100);
    ASSERT_TRUE(m_surface->getCanvas()->readPixels(&canvasBitmap, 0, 0));
    SkAutoLockPixels autoLock(canvasBitmap);
    EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), canvasBitmap.getColor(0, 0));
}
Example #18
0
// Test that image encoding failures do not break picture serialization/deserialization.
DEF_TEST(Image_Serialize_Encoding_Failure, reporter) {
    SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(100, 100));
    surface->getCanvas()->clear(SK_ColorGREEN);
    SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
    REPORTER_ASSERT(reporter, image);

    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(100, 100);
    canvas->drawImage(image, 0, 0);
    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    REPORTER_ASSERT(reporter, picture);
    REPORTER_ASSERT(reporter, picture->approximateOpCount() > 0);

    MockSerializer emptySerializer([]() -> SkData* { return SkData::NewEmpty(); });
    MockSerializer nullSerializer([]() -> SkData* { return nullptr; });
    MockSerializer* serializers[] = { &emptySerializer, &nullSerializer };

    for (size_t i = 0; i < SK_ARRAY_COUNT(serializers); ++i) {
        SkDynamicMemoryWStream wstream;
        REPORTER_ASSERT(reporter, !serializers[i]->didEncode());
        picture->serialize(&wstream, serializers[i]);
        REPORTER_ASSERT(reporter, serializers[i]->didEncode());

        SkAutoTDelete<SkStream> rstream(wstream.detachAsStream());
        SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rstream));
        REPORTER_ASSERT(reporter, deserialized);
        REPORTER_ASSERT(reporter, deserialized->approximateOpCount() > 0);
    }
}
// Create a Sierpinkski-like picture that starts with a top row with a picture
// that just contains a triangle. Subsequent rows take the prior row's picture,
// shrinks it and replicates it 3 times then draws and appropriate number of
// copies of it.
static const SkPicture* make_sierpinski_picture() {
    SkAutoTUnref<const SkPicture> pic(make_tri_picture());

    SkPictureRecorder recorder;
    SkRTreeFactory bbhFactory;

    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
                                               SkIntToScalar(kPicHeight),
                                               &bbhFactory,
                                               SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag);

    static const int kNumLevels = 4;
    for (int i = 0; i < kNumLevels; ++i) {
        canvas->save();
            canvas->translate(kPicWidth/2 - (i+1) * (kTriSide/2.0f), 0.0f);
            for (int j = 0; j < i+1; ++j) {
                canvas->drawPicture(pic);
                canvas->translate(SkIntToScalar(kTriSide), 0);
            }
        canvas->restore();

        pic.reset(make_sub_picture(pic));

        canvas->translate(0, 1.5f * kTriSide / kRoot3);
    }

    return recorder.endRecording();
}
/**
 * Verify that we get the same culling bounds for text for (1) drawing glyphs
 * directly to a Canvas or (2) going through a SkPicture as an intermediate step.
 */
TEST(SkiaCanvasProxy, drawGlyphsViaPicture) {
    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
        // setup test variables
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setTextSize(20);
        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
        static const char* text = "testing text bounds";

        // draw text directly into Recording canvas
        TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 25, 25);

        // record the same text draw into a SkPicture and replay it into a Recording canvas
        SkPictureRecorder recorder;
        SkCanvas* skCanvas = recorder.beginRecording(200, 200, NULL, 0);
        std::unique_ptr<Canvas> pictCanvas(Canvas::create_canvas(skCanvas));
        TestUtils::drawUtf8ToCanvas(pictCanvas.get(), text, paint, 25, 25);
        SkAutoTUnref<const SkPicture> picture(recorder.endRecording());

        canvas.asSkCanvas()->drawPicture(picture);
    });

    // verify that the text bounds and matrices match
    ASSERT_EQ(2U, dl->getOps().size());
    auto directOp = dl->getOps()[0];
    auto pictureOp = dl->getOps()[1];
    ASSERT_EQ(RecordedOpId::TextOp, directOp->opId);
    EXPECT_EQ(directOp->opId, pictureOp->opId);
    EXPECT_EQ(directOp->unmappedBounds, pictureOp->unmappedBounds);
    EXPECT_EQ(directOp->localMatrix, pictureOp->localMatrix);
}
static const SkPicture* make_sub_picture(const SkPicture* tri) {
    SkPictureRecorder recorder;
    SkRTreeFactory bbhFactory;

    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
                                               SkIntToScalar(kPicHeight),
                                               &bbhFactory,
                                               SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag);

    canvas->scale(1.0f/2.0f, 1.0f/2.0f);

    canvas->save();
    canvas->translate(SkScalarHalf(kTriSide), 0);
    canvas->drawPicture(tri);
    canvas->restore();

    canvas->save();
    canvas->translate(SkIntToScalar(kTriSide), 1.5f * kTriSide / kRoot3);
    canvas->drawPicture(tri);
    canvas->restore();

    canvas->save();
    canvas->translate(0, 1.5f * kTriSide / kRoot3);
    canvas->drawPicture(tri);
    canvas->restore();

    return recorder.endRecording();
}
static const SkPicture* make_tri_picture() {
    SkPath tri = make_tri_path(SkScalarHalf(kTriSide), 0);

    SkPaint fill;
    fill.setStyle(SkPaint::kFill_Style);
    fill.setColor(sk_tool_utils::color_to_565(SK_ColorLTGRAY));

    SkPaint stroke;
    stroke.setStyle(SkPaint::kStroke_Style);
    stroke.setStrokeWidth(3);

    SkPictureRecorder recorder;
    SkRTreeFactory bbhFactory;

    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
                                               SkIntToScalar(kPicHeight),
                                               &bbhFactory,
                                               SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag);
    SkRect r = tri.getBounds();
    r.outset(2.0f, 2.0f);       // outset for stroke
    canvas->clipRect(r);
    // The saveLayer/restore block is to exercise layer hoisting
    canvas->saveLayer(nullptr, nullptr);
        canvas->drawPath(tri, fill);
        canvas->drawPath(tri, stroke);
    canvas->restore();

    return recorder.endRecording();
}
Example #23
0
// Make sure the abort callback works
DEF_TEST(RecordReplaceDraw_Abort, r) {
    SkAutoTUnref<const SkPicture> pic;

    {
        // Record two commands.
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));

        canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight)), SkPaint());
        canvas->clipRect(SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight)));

        pic.reset(recorder.endRecording());
    }

    SkRecord rerecord;
    SkRecorder canvas(&rerecord, kWidth, kHeight);

    JustOneDraw callback;
    GrRecordReplaceDraw(pic, &canvas, nullptr, SkMatrix::I(), &callback);

    switch (rerecord.count()) {
        case 3:
            assert_type<SkRecords::Save>(r, rerecord, 0);
            assert_type<SkRecords::DrawRect>(r, rerecord, 1);
            assert_type<SkRecords::Restore>(r, rerecord, 2);
            break;
        case 1:
            assert_type<SkRecords::DrawRect>(r, rerecord, 0);
            break;
        default:
            REPORTER_ASSERT(r, false);
    }
}
Example #24
0
// Ensure that serializing an empty picture does not assert. Likewise only runs in debug mode.
static void test_serializing_empty_picture() {
    SkPictureRecorder recorder;
    recorder.beginRecording(0, 0);
    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    SkDynamicMemoryWStream stream;
    picture->serialize(&stream);
}
Example #25
0
// Ensure that deleting an empty SkPicture does not assert. Asserts only fire
// in debug mode, so only run in debug mode.
static void test_deleting_empty_picture() {
    SkPictureRecorder recorder;
    // Creates an SkPictureRecord
    recorder.beginRecording(0, 0);
    // Turns that into an SkPicture
    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    // Ceates a new SkPictureRecord
    recorder.beginRecording(0, 0);
}
Example #26
0
static void rerecord(const SkPicture& src, SkBBHFactory* bbhFactory) {
    SkPictureRecorder recorder;
    if (FLAGS_skr) {
        src.draw(recorder.EXPERIMENTAL_beginRecording(src.width(), src.height(), bbhFactory));
    } else {
        src.draw(recorder.beginRecording(src.width(), src.height(), bbhFactory));
    }
    SkAutoTUnref<SkPicture> pic(recorder.endRecording());
}
Example #27
0
SkPicture* RecordPicture(skiagm::GM* gm, uint32_t recordFlags, SkBBHFactory* factory) {
    const SkISize size = gm->getISize();
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(size.width(), size.height(), factory, recordFlags);
    canvas->concat(gm->getInitialTransform());
    gm->draw(canvas);
    canvas->flush();
    return recorder.endRecording();
}
Example #28
0
SkPicture* SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* data) {
    if (!data) {
        return nullptr;
    }
    SkPicturePlayback playback(data);
    SkPictureRecorder r;
    playback.draw(r.beginRecording(info.fCullRect), nullptr/*no callback*/);
    return r.endRecording();
}
Example #29
0
static void test_gen_id(skiatest::Reporter* reporter) {

    SkPictureRecorder recorder;
    recorder.beginRecording(0, 0);
    SkAutoTUnref<SkPicture> empty(recorder.endRecording());

    // Empty pictures should still have a valid ID
    REPORTER_ASSERT(reporter, empty->uniqueID() != SK_InvalidGenID);

    SkCanvas* canvas = recorder.beginRecording(1, 1);
    canvas->drawARGB(255, 255, 255, 255);
    SkAutoTUnref<SkPicture> hasData(recorder.endRecording());
    // picture should have a non-zero id after recording
    REPORTER_ASSERT(reporter, hasData->uniqueID() != SK_InvalidGenID);

    // both pictures should have different ids
    REPORTER_ASSERT(reporter, hasData->uniqueID() != empty->uniqueID());
}
Example #30
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.endRecording()->unref();
        REPORTER_ASSERT(r, !rec.getRecordingCanvas());
    }
}