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 ());
    }
    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
    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;
        paint.setShader(SkShader::MakeBitmapShader(bitmap, SkShader::kClamp_TileMode,
                                                   SkShader::kClamp_TileMode));
        REPORTER_ASSERT(reporter, paint.getShader()->isABitmap());

        canvas->drawRect(SkRect::MakeWH(10, 10), paint);
    }
    REPORTER_ASSERT(reporter, recorder.finishRecordingAsPicture()->willPlayBackBitmaps());
}
Example #2
0
// Test the kReturnNullForEmpty_FinishFlag option when recording
//
DEF_TEST(Picture_RecordEmpty, r) {
    const SkRect cull = SkRect::MakeWH(100, 100);

    CanvasProc procs[] { empty_ops, clip_ops, matrix_ops, matrixclip_ops };

    for (auto proc : procs) {
        {
            SkPictureRecorder rec;
            proc(rec.beginRecording(cull));
            sk_sp<SkPicture> pic = rec.finishRecordingAsPicture(0);
            REPORTER_ASSERT(r, pic.get());
            REPORTER_ASSERT(r, pic->approximateOpCount() == 0);
        }
        {
            SkPictureRecorder rec;
            proc(rec.beginRecording(cull));
            sk_sp<SkPicture> pic = rec.finishRecordingAsPicture(
                                                 SkPictureRecorder::kReturnNullForEmpty_FinishFlag);
            REPORTER_ASSERT(r, !pic.get());
        }
        {
            SkPictureRecorder rec;
            proc(rec.beginRecording(cull));
            sk_sp<SkDrawable> dr = rec.finishRecordingAsDrawable(0);
            REPORTER_ASSERT(r, dr.get());
        }
        {
            SkPictureRecorder rec;
            proc(rec.beginRecording(cull));
            sk_sp<SkDrawable> dr = rec.finishRecordingAsDrawable(
                                                 SkPictureRecorder::kReturnNullForEmpty_FinishFlag);
            REPORTER_ASSERT(r, !dr.get());
        }
    }
}
Example #3
0
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);
  sk_sp<SkImage> image = m_lazyDecoder->createFrameAtIndex(0);
  ASSERT_TRUE(image);
  SkPictureRecorder recorder;
  SkCanvas* tempCanvas = recorder.beginRecording(100, 100, 0, 0);
  tempCanvas->drawImage(image.get(), 0, 0);
  m_surface->getCanvas()->drawPicture(recorder.finishRecordingAsPicture());

  // Fully received the file and draw the SkPicture again.
  m_lazyDecoder->setData(m_data, true);
  image = m_lazyDecoder->createFrameAtIndex(0);
  ASSERT_TRUE(image);
  tempCanvas = recorder.beginRecording(100, 100, 0, 0);
  tempCanvas->drawImage(image.get(), 0, 0);
  m_surface->getCanvas()->drawPicture(recorder.finishRecordingAsPicture());

  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 #4
0
    virtual void onDraw(SkCanvas* canvas) {
        constexpr SkScalar kOffset = 35000.0f;
        constexpr SkScalar kExtents = 1000.0f;

        SkPictureRecorder recorder;
        // 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.
        SkCanvas* rec = recorder.beginRecording(kExtents, kOffset + kExtents, nullptr, 0);
        rec->drawColor(SK_ColorRED);
        rec->save();
        SkRect r = SkRect::MakeXYWH(-kExtents, kOffset - kExtents, 2 * kExtents, 2 * kExtents);
        SkPath p;
        p.addRoundRect(r, 5, 5);
        rec->clipPath(p, true);
        rec->drawColor(SK_ColorGREEN);
        rec->restore();
        sk_sp<SkPicture> pict(recorder.finishRecordingAsPicture());

        // Next we play that picture into another picture of the same size.
        pict->playback(recorder.beginRecording(pict->cullRect().width(),
                                               pict->cullRect().height(),
                                               nullptr, 0));
        sk_sp<SkPicture> pict2(recorder.finishRecordingAsPicture());

        // Finally we play the part of that second picture that should be green into the canvas.
        canvas->save();
        canvas->translate(kExtents / 2, -(kOffset - kExtents / 2));
        pict2->playback(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.
    }
Example #5
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);
        sk_sp<SkPicture> extraSavePicture(recorder.finishRecordingAsPicture());

        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();
        sk_sp<SkPicture> extraRestorePicture(recorder.finishRecordingAsPicture());

        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);
        sk_sp<SkPicture> noSavePicture(recorder.finishRecordingAsPicture());

        testCanvas.drawPicture(noSavePicture);
        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
        REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity());
    }
}
Example #6
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);
        }
        sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());

        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();
        }
        sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
    }
}
Example #7
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;
        }
        sk_sp<SkPicture> src(SkPicture::MakeFromStream(stream));
        if (!src) {
            SkDebugf("Could not read %s as an SkPicture.\n", FLAGS_skps[i]);
            return 1;
        }
        if (FLAGS_defer) {
            SkPictureRecorder recorder;
            SkDeferredCanvas deferred(recorder.beginRecording(src->cullRect()));
            src->playback(&deferred);
            src = recorder.finishRecordingAsPicture();
        }
        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);
            sk_sp<SkPicture> dst(r.finishRecordingAsPicture());
            SkFILEWStream ostream(FLAGS_write[0]);
            dst->serialize(&ostream);
        }
    }

    return 0;
}
Example #8
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);
    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
    SkDynamicMemoryWStream stream;
    picture->serialize(&stream);
}
Example #9
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], []() {
            auto surface(SkSurface::MakeRasterN32Premul(10, 10));
            surface->getCanvas()->clear(SK_ColorCYAN);
            return surface->makeImageSnapshot();
        });

        test_discarded_image(reporter, xforms[i], []() {
            SkPictureRecorder recorder;
            SkCanvas* canvas = recorder.beginRecording(10, 10);
            canvas->clear(SK_ColorCYAN);
            return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
                                            SkISize::Make(10, 10), nullptr, nullptr,
                                            SkImage::BitDepth::kU8,
                                            SkColorSpace::MakeSRGB());
        });
    }
}
Example #10
0
TEST_F(DeferredImageDecoderTest, decodeOnOtherThread) {
  m_lazyDecoder->setData(m_data, true);
  sk_sp<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);
  sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
  EXPECT_EQ(0, m_decodeRequestCount);

  // Create a thread to rasterize SkPicture.
  std::unique_ptr<WebThread> thread =
      WTF::wrapUnique(Platform::current()->createThread("RasterThread"));
  thread->getWebTaskRunner()->postTask(
      BLINK_FROM_HERE,
      crossThreadBind(&rasterizeMain,
                      crossThreadUnretained(m_surface->getCanvas()),
                      crossThreadUnretained(picture.get())));
  thread.reset();
  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 #11
0
// Test that the SkPictureShader cache is purged on shader deletion.
DEF_TEST(PictureShader_caching, reporter) {
    auto makePicture = [] () {
        SkPictureRecorder recorder;
        recorder.beginRecording(100, 100)->drawColor(SK_ColorGREEN);
        return recorder.finishRecordingAsPicture();
    };

    sk_sp<SkPicture> picture = makePicture();
    REPORTER_ASSERT(reporter, picture->unique());

    sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(100, 100);

    {
        SkPaint paint;
        paint.setShader(picture->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat));
        surface->getCanvas()->drawPaint(paint);

        // We should have about 3 refs by now: local + shader + shader cache.
        REPORTER_ASSERT(reporter, !picture->unique());
    }

    // Draw another picture shader to have a chance to purge.
    {
        SkPaint paint;
        paint.setShader(makePicture()->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat));
        surface->getCanvas()->drawPaint(paint);

    }

    // All but the local ref should be gone now.
    REPORTER_ASSERT(reporter, picture->unique());
}
PassRefPtr<PictureSnapshot> PictureSnapshot::load(const Vector<RefPtr<TilePictureStream>>& tiles)
{
    ASSERT(!tiles.isEmpty());
    Vector<sk_sp<SkPicture>> pictures;
    pictures.reserveCapacity(tiles.size());
    FloatRect unionRect;
    for (const auto& tileStream : tiles) {
        SkMemoryStream stream(tileStream->data.begin(), tileStream->data.size());
        sk_sp<SkPicture> picture = SkPicture::MakeFromStream(&stream, decodeBitmap);
        if (!picture)
            return nullptr;
        FloatRect cullRect(picture->cullRect());
        cullRect.moveBy(tileStream->layerOffset);
        unionRect.unite(cullRect);
        pictures.append(std::move(picture));
    }
    if (tiles.size() == 1)
        return adoptRef(new PictureSnapshot(fromSkSp(std::move(pictures[0]))));
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(unionRect.width(), unionRect.height(), 0, 0);
    for (size_t i = 0; i < pictures.size(); ++i) {
        canvas->save();
        canvas->translate(tiles[i]->layerOffset.x() - unionRect.x(), tiles[i]->layerOffset.y() - unionRect.y());
        pictures[i]->playback(canvas, 0);
        canvas->restore();
    }
    return adoptRef(new PictureSnapshot(fromSkSp(recorder.finishRecordingAsPicture())));
}
Example #13
0
    void onDraw(SkCanvas* canvas) override {
        SkPictureRecorder recorder;
        SkCanvas* rec = recorder.beginRecording(1200, 900, nullptr, 0);
        SkPath p;
        SkRect r = {
            SkIntToScalar(100),
            SkIntToScalar(200),
            SkIntToScalar(400),
            SkIntToScalar(700)
        };
        p.addRoundRect(r, SkIntToScalar(50), SkIntToScalar(50));
        rec->clipPath(p, SkRegion::kIntersect_Op, true);
        rec->translate(SkIntToScalar(250), SkIntToScalar(250));
        rec->clipPath(p, SkRegion::kIntersect_Op, true);
        rec->drawColor(0xffff0000);
        sk_sp<SkPicture> pict(recorder.finishRecordingAsPicture());

        canvas->setAllowSimplifyClip(true);
        canvas->save();
        canvas->drawPicture(pict);
        canvas->restore();

        canvas->setAllowSimplifyClip(false);
        canvas->save();
        canvas->translate(SkIntToScalar(1200 / 2), 0);
        canvas->drawPicture(pict);
        canvas->restore();
    }
Example #14
0
PictureCentricBench::PictureCentricBench(const char* name, const SkPicture* pic) : fName(name) {
    // Flatten the source picture in case it's trivially nested (useless for timing).
    SkPictureRecorder rec;
    pic->playback(rec.beginRecording(pic->cullRect(), nullptr,
                                     SkPictureRecorder::kPlaybackDrawPicture_RecordFlag));
    fSrc = rec.finishRecordingAsPicture();
}
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());

    sk_sp<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 = rec.finishRecordingAsPicture();
    }

    // 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 = nullptr;
    REPORTER_ASSERT(r, mut.pixelRef()->unique());
    REPORTER_ASSERT(r, immut.pixelRef()->unique());
}
Example #16
0
 void onOnceBeforeDraw() override {
     const SkRect rect = SkRect::MakeWH(kPictureWidth, kPictureHeight);
     SkPictureRecorder recorder;
     SkCanvas* canvas = recorder.beginRecording(rect);
     draw_vector_logo(canvas, rect);
     fPicture = recorder.finishRecordingAsPicture();
 }
Example #17
0
void GMSampleView::onDrawContent(SkCanvas* canvas) {
    SkPictureRecorder recorder;
    SkCanvas* origCanvas = canvas;

    if (false) {
        SkISize size = fGM->getISize();
        canvas = recorder.beginRecording(SkRect::MakeIWH(size.width(), size.height()));
    }

    {
        SkAutoCanvasRestore acr(canvas, fShowSize);
        fGM->drawContent(canvas);
    }

    if (origCanvas != canvas) {
        sk_sp<SkPicture> pic = recorder.finishRecordingAsPicture();
        if (false) {
            pic = round_trip_serialize(pic.get());
        }
        origCanvas->drawPicture(pic);
        canvas = origCanvas;
    }

    if (fShowSize) {
        SkISize size = fGM->getISize();
        SkRect r = SkRect::MakeWH(SkIntToScalar(size.width()),
                                  SkIntToScalar(size.height()));
        SkPaint paint;
        paint.setColor(0x40FF8833);
        canvas->drawRect(r, paint);
    }
}
Example #18
0
static void serialize_and_compare_typeface(sk_sp<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(std::move(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);
    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());

    // Serlialize picture and create its clone from stream.
    SkDynamicMemoryWStream stream;
    picture->serialize(&stream);
    std::unique_ptr<SkStream> inputStream(stream.detachAsStream());
    sk_sp<SkPicture> loadedPicture(SkPicture::MakeFromStream(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 #19
0
/*
 *  Test the 3 annotation types by recording them into a picture, serializing, and then playing
 *  them back into another canvas.
 */
DEF_TEST(Annotations, reporter) {
    SkPictureRecorder recorder;
    SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeWH(100, 100));

    const char* str0 = "rect-with-url";
    const SkRect r0 = SkRect::MakeWH(10, 10);
    sk_sp<SkData> d0(SkData::MakeWithCString(str0));
    SkAnnotateRectWithURL(recordingCanvas, r0, d0.get());

    const char* str1 = "named-destination";
    const SkRect r1 = SkRect::MakeXYWH(5, 5, 0, 0); // collapsed to a point
    sk_sp<SkData> d1(SkData::MakeWithCString(str1));
    SkAnnotateNamedDestination(recordingCanvas, {r1.x(), r1.y()}, d1.get());

    const char* str2 = "link-to-destination";
    const SkRect r2 = SkRect::MakeXYWH(20, 20, 5, 6);
    sk_sp<SkData> d2(SkData::MakeWithCString(str2));
    SkAnnotateLinkToDestination(recordingCanvas, r2, d2.get());

    const AnnotationRec recs[] = {
        { r0, SkAnnotationKeys::URL_Key(),                  std::move(d0) },
        { r1, SkAnnotationKeys::Define_Named_Dest_Key(),    std::move(d1) },
        { r2, SkAnnotationKeys::Link_Named_Dest_Key(),      std::move(d2) },
    };

    sk_sp<SkPicture> pict0(recorder.finishRecordingAsPicture());
    sk_sp<SkPicture> pict1(copy_picture_via_serialization(pict0.get()));

    TestAnnotationCanvas canvas(reporter, recs, SK_ARRAY_COUNT(recs));
    canvas.drawPicture(pict1);
}
Example #20
0
// Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to
// inner savelayer. We know that alpha folding happens to inner savelayer, so add detector there.
static void draw_svg_opacity_and_filter_layer_sequence(SkCanvas* canvas, SkColor shapeColor,
                                                       InstallDetectorFunc installDetector) {

    SkRect targetRect(SkRect::MakeWH(SkIntToScalar(kTestRectSize), SkIntToScalar(kTestRectSize)));
    sk_sp<SkPicture> shape;
    {
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kTestRectSize + 2),
                                                   SkIntToScalar(kTestRectSize + 2));
        SkPaint shapePaint;
        shapePaint.setColor(shapeColor);
        canvas->drawRect(targetRect, shapePaint);
        shape = recorder.finishRecordingAsPicture();
    }

    SkPaint layerPaint;
    layerPaint.setColor(SkColorSetARGB(130, 0, 0, 0));
    canvas->saveLayer(&targetRect, &layerPaint);
        canvas->save();
            canvas->clipRect(targetRect);
            SkPaint drawPaint;
            drawPaint.setImageFilter(SkPictureImageFilter::Create(shape.get()))->unref();
            installDetector(&drawPaint);
            canvas->saveLayer(&targetRect, &drawPaint);
            canvas->restore();
        canvas->restore();
    canvas->restore();
}
Example #21
0
    void onDraw(int loops, SkCanvas*) override {
        SkLiteRecorder lite;
        SkPictureRecorder rec;
        for (int i = 0; i < loops; i++) {
            SkRect bounds{0,0, 2000,3000};

            sk_sp<SkLiteDL> liteDL;
            SkCanvas* canvas;
            if (kLite) {
                liteDL = SkLiteDL::New(bounds);
                lite.reset(liteDL.get());
                canvas = &lite;
            } else {
                rec.beginRecording(bounds);
                canvas = rec.getRecordingCanvas();
            }

            for (int i = 0; i < kDraws; i++) {
                canvas->drawRect({10,10, 1000, 1000}, SkPaint{});
            }

            if (!kLite) {
                (void)rec.finishRecordingAsPicture();
            }
        }
    }
Example #22
0
static sk_sp<SkPicture> make_sub_picture(const SkPicture* tri) {
    SkPictureRecorder recorder;
    SkRTreeFactory bbhFactory;

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

    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.finishRecordingAsPicture();
}
Example #23
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 sk_sp<SkPicture> make_sierpinski_picture() {
    sk_sp<SkPicture> pic(make_tri_picture());

    SkPictureRecorder recorder;
    SkRTreeFactory bbhFactory;

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

    constexpr 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 = make_sub_picture(pic.get());

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

    return recorder.finishRecordingAsPicture();
}
Example #24
0
// Make sure GrRecordReplaceDraw balances unbalanced saves
DEF_TEST(RecordReplaceDraw_Unbalanced, r) {
    sk_sp<SkPicture> pic;

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

        // We won't balance this, but GrRecordReplaceDraw will for us.
        canvas->save();
        canvas->scale(2, 2);
        pic = recorder.finishRecordingAsPicture();

        // we may have optimized everything away. If so, just return
        if (pic->approximateOpCount() == 0) {
            return;
        }
    }

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

    GrRecordReplaceDraw(pic.get(), &canvas, nullptr, SkMatrix::I(), nullptr/*callback*/);

    // ensure rerecord is balanced (in this case by checking that the count is odd)
    REPORTER_ASSERT(r, (rerecord.count() & 1) == 1);
}
Example #25
0
static sk_sp<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);
    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.finishRecordingAsPicture();
}
Example #26
0
// Make sure the abort callback works
DEF_TEST(RecordReplaceDraw_Abort, r) {
    sk_sp<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 = recorder.finishRecordingAsPicture();
    }

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

    JustOneDraw callback;
    GrRecordReplaceDraw(pic.get(), &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);
    }
}
static sk_sp<SkImage> make_picture_image() {
    SkPictureRecorder recorder;
    draw_contents(recorder.beginRecording(SkRect::MakeIWH(kWidth, kHeight)));
    return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
                                    SkISize::Make(kWidth, kHeight), nullptr, nullptr,
                                    SkImage::BitDepth::kU8,
                                    SkColorSpace::MakeSRGB());
}
Example #28
0
DEF_TEST(PictureGpuAnalyzer, r) {
    SkPictureRecorder recorder;

    {
        SkCanvas* canvas = recorder.beginRecording(10, 10);
        SkPaint paint;
        SkScalar intervals [] = { 10, 20 };
        paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 25));

        for (int i = 0; i < 50; ++i) {
            canvas->drawRect(SkRect::MakeWH(10, 10), paint);
        }
    }
    sk_sp<SkPicture> vetoPicture(recorder.finishRecordingAsPicture());

    SkPictureGpuAnalyzer analyzer;
    REPORTER_ASSERT(r, analyzer.suitableForGpuRasterization());

    analyzer.analyzePicture(vetoPicture.get());
    REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization());

    analyzer.reset();
    REPORTER_ASSERT(r, analyzer.suitableForGpuRasterization());

    recorder.beginRecording(10, 10)->drawPicture(vetoPicture);
    sk_sp<SkPicture> nestedVetoPicture(recorder.finishRecordingAsPicture());

    analyzer.analyzePicture(nestedVetoPicture.get());
    REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization());

    analyzer.reset();

    const SkPath convexClip = make_convex_path();
    const SkPath concaveClip = make_concave_path();
    for (int i = 0; i < 50; ++i) {
        analyzer.analyzeClipPath(convexClip, SkRegion::kIntersect_Op, false);
        analyzer.analyzeClipPath(convexClip, SkRegion::kIntersect_Op, true);
        analyzer.analyzeClipPath(concaveClip, SkRegion::kIntersect_Op, false);
    }
    REPORTER_ASSERT(r, analyzer.suitableForGpuRasterization());

    for (int i = 0; i < 50; ++i) {
        analyzer.analyzeClipPath(concaveClip, SkRegion::kIntersect_Op, true);
    }
    REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization());
}
Example #29
0
void draw(SkCanvas* canvas) {
    SkPictureRecorder recorder;
    recorder.beginRecording({0, 0, 0, 0});
    sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
    SkDebugf("empty picture id = %d\n", picture->uniqueID());
    sk_sp<SkPicture> placeholder = SkPicture::MakePlaceholder({0, 0, 0, 0});
    SkDebugf("placeholder id = %d\n", placeholder->uniqueID());
}
Example #30
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
    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
    // Ceates a new SkPictureRecord
    recorder.beginRecording(0, 0);
}