PassRefPtr<SkPicture> paintArtifactToSkPicture(const PaintArtifact& artifact, const SkRect& bounds)
{
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(bounds);
    paintArtifactToSkCanvas(artifact, canvas);
    return adoptRef(recorder.endRecordingAsPicture());
}
PassRefPtr<PictureSnapshot> PictureSnapshot::load(const Vector<RefPtr<TilePictureStream>>& tiles)
{
    ASSERT(!tiles.isEmpty());
    Vector<RefPtr<SkPicture>> pictures;
    pictures.reserveCapacity(tiles.size());
    FloatRect unionRect;
    for (const auto& tileStream : tiles) {
        SkMemoryStream stream(tileStream->data.begin(), tileStream->data.size());
        RefPtr<SkPicture> picture = adoptRef(SkPicture::CreateFromStream(&stream, decodeBitmap));
        if (!picture)
            return nullptr;
        FloatRect cullRect(picture->cullRect());
        cullRect.moveBy(tileStream->layerOffset);
        unionRect.unite(cullRect);
        pictures.append(picture);
    }
    if (tiles.size() == 1)
        return adoptRef(new PictureSnapshot(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(adoptRef(recorder.endRecordingAsPicture())));
}
Ejemplo n.º 3
0
DEF_TEST(RecordOpts_MergeSvgOpacityAndFilterLayers, r) {
    SkRecord record;
    SkRecorder recorder(&record, W, H);

    SkRect bounds = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(200));
    SkRect clip = SkRect::MakeWH(SkIntToScalar(50), SkIntToScalar(60));

    SkPaint alphaOnlyLayerPaint;
    alphaOnlyLayerPaint.setColor(0x03000000);  // Only alpha.
    SkPaint translucentLayerPaint;
    translucentLayerPaint.setColor(0x03040506);  // Not only alpha.
    SkPaint xfermodePaint;
    xfermodePaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
    SkPaint colorFilterPaint;
    colorFilterPaint.setColorFilter(
        SkColorFilter::CreateModeFilter(SK_ColorLTGRAY, SkXfermode::kSrcIn_Mode))->unref();

    SkPaint opaqueFilterLayerPaint;
    opaqueFilterLayerPaint.setColor(0xFF020202);  // Opaque.
    SkPaint translucentFilterLayerPaint;
    translucentFilterLayerPaint.setColor(0x0F020202);  // Not opaque.
    SkAutoTUnref<SkPicture> shape;
    {
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(100), SkIntToScalar(100));
        SkPaint shapePaint;
        shapePaint.setColor(SK_ColorWHITE);
        canvas->drawRect(SkRect::MakeWH(SkIntToScalar(50), SkIntToScalar(50)), shapePaint);
        shape.reset(recorder.endRecordingAsPicture());
    }
    translucentFilterLayerPaint.setImageFilter(SkPictureImageFilter::Create(shape))->unref();

    int index = 0;

    {
        // Any combination of these should cause the pattern to be optimized.
        SkRect* firstBounds[] = { NULL, &bounds };
        SkPaint* firstPaints[] = { NULL, &alphaOnlyLayerPaint };
        SkRect* secondBounds[] = { NULL, &bounds };
        SkPaint* secondPaints[] = { &opaqueFilterLayerPaint, &translucentFilterLayerPaint };

        for (size_t i = 0; i < SK_ARRAY_COUNT(firstBounds); ++ i) {
            for (size_t j = 0; j < SK_ARRAY_COUNT(firstPaints); ++j) {
                for (size_t k = 0; k < SK_ARRAY_COUNT(secondBounds); ++k) {
                    for (size_t m = 0; m < SK_ARRAY_COUNT(secondPaints); ++m) {
                        recorder.saveLayer(firstBounds[i], firstPaints[j]);
                        recorder.save();
                        recorder.clipRect(clip);
                        recorder.saveLayer(secondBounds[k], secondPaints[m]);
                        recorder.restore();
                        recorder.restore();
                        recorder.restore();
                        assert_merge_svg_opacity_and_filter_layers(r, &record, index, true);
                        index += 7;
                    }
                }
            }
        }
    }

    // These should cause the pattern to stay unoptimized:
    struct {
        SkPaint* firstPaint;
        SkPaint* secondPaint;
    } noChangeTests[] = {
        // No change: NULL filter layer paint not implemented.
        { &alphaOnlyLayerPaint, NULL },
        // No change: layer paint is not alpha-only.
        { &translucentLayerPaint, &opaqueFilterLayerPaint },
        // No change: layer paint has an xfereffect.
        { &xfermodePaint, &opaqueFilterLayerPaint },
        // No change: filter layer paint has an xfereffect.
        { &alphaOnlyLayerPaint, &xfermodePaint },
        // No change: layer paint has a color filter.
        { &colorFilterPaint, &opaqueFilterLayerPaint },
        // No change: filter layer paint has a color filter (until the optimization accounts for
        // constant color draws that can filter the color).
        { &alphaOnlyLayerPaint, &colorFilterPaint }
    };

    for (size_t i = 0; i < SK_ARRAY_COUNT(noChangeTests); ++i) {
        recorder.saveLayer(NULL, noChangeTests[i].firstPaint);
        recorder.save();
        recorder.clipRect(clip);
        recorder.saveLayer(NULL, noChangeTests[i].secondPaint);
        recorder.restore();
        recorder.restore();
        recorder.restore();
        assert_merge_svg_opacity_and_filter_layers(r, &record, index, false);
        index += 7;
    }

    // Test the folded alpha value.
    recorder.saveLayer(NULL, &alphaOnlyLayerPaint);
    recorder.save();
    recorder.clipRect(clip);
    recorder.saveLayer(NULL, &opaqueFilterLayerPaint);
    recorder.restore();
    recorder.restore();
    recorder.restore();
    assert_merge_svg_opacity_and_filter_layers(r, &record, index, true);

    const SkRecords::SaveLayer* saveLayer = assert_type<SkRecords::SaveLayer>(r, record, index + 3);
    REPORTER_ASSERT(r, saveLayer != NULL);
    REPORTER_ASSERT(r, saveLayer->paint->getColor() == 0x03020202);

    index += 7;

    // Test that currently we do not fold alphas for patterns without the clip. This is just not
    // implemented.
    recorder.saveLayer(NULL, &alphaOnlyLayerPaint);
    recorder.saveLayer(NULL, &opaqueFilterLayerPaint);
    recorder.restore();
    recorder.restore();
    SkRecordMergeSvgOpacityAndFilterLayers(&record);
    assert_type<SkRecords::SaveLayer>(r, record, index);
    assert_type<SkRecords::SaveLayer>(r, record, index + 1);
    assert_type<SkRecords::Restore>(r, record, index + 2);
    assert_type<SkRecords::Restore>(r, record, index + 3);
    index += 4;
}