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