Flutter Engine
The Flutter Engine
Classes | Functions
PictureTest.cpp File Reference
#include "include/core/SkBBHFactory.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkClipOp.h"
#include "include/core/SkColor.h"
#include "include/core/SkData.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkPixelRef.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "src/base/SkRandom.h"
#include "src/core/SkBigPicture.h"
#include "src/core/SkPicturePriv.h"
#include "src/core/SkRectPriv.h"
#include "tests/Test.h"
#include "tools/fonts/FontToolUtils.h"
#include <cstddef>
#include <memory>
#include <vector>

Go to the source code of this file.

Classes

class  SaveCountingCanvas
 
class  SkPictureRecorderReplayTester
 
class  ClipCountingCanvas
 
struct  CountingBBH
 
class  SpoonFedBBHFactory
 

Functions

static void make_bm (SkBitmap *bm, int w, int h, SkColor color, bool immutable)
 
static void rand_op (SkCanvas *canvas, SkRandom &rand)
 
static void set_canvas_to_save_count_4 (SkCanvas *canvas)
 
void check_save_state (skiatest::Reporter *reporter, SkPicture *picture, unsigned int numSaves, unsigned int numSaveLayers, unsigned int numRestores)
 
static void create_imbalance (SkCanvas *canvas)
 
static void check_balance (skiatest::Reporter *reporter, SkPicture *picture)
 
 DEF_TEST (PictureRecorder_replay, reporter)
 
static void test_unbalanced_save_restores (skiatest::Reporter *reporter)
 
static void test_peephole ()
 
static void test_bad_bitmap (skiatest::Reporter *reporter)
 
static void test_clip_bound_opt (skiatest::Reporter *reporter)
 
static void test_cull_rect_reset (skiatest::Reporter *reporter)
 
static void test_gen_id (skiatest::Reporter *reporter)
 
static void test_typeface (skiatest::Reporter *reporter)
 
 DEF_TEST (Picture, reporter)
 
static void draw_bitmaps (const SkBitmap &bitmap, SkCanvas *canvas)
 
static void test_draw_bitmaps (SkCanvas *canvas)
 
 DEF_TEST (Picture_EmptyBitmap, r)
 
 DEF_TEST (Canvas_EmptyBitmap, r)
 
 DEF_TEST (DontOptimizeSaveLayerDrawDrawRestore, reporter)
 
 DEF_TEST (Picture_SkipBBH, r)
 
 DEF_TEST (Picture_BitmapLeak, r)
 
 DEF_TEST (Picture_getRecordingCanvas, r)
 
 DEF_TEST (Picture_preserveCullRect, r)
 
 DEF_TEST (Picture_UpdatedCull_1, r)
 
 DEF_TEST (Picture_UpdatedCull_2, r)
 
 DEF_TEST (Placeholder, r)
 
 DEF_TEST (Picture_empty_serial, reporter)
 
 DEF_TEST (Picture_drawsNothing, r)
 
 DEF_TEST (Picture_emptyNestedPictureBug, r)
 
 DEF_TEST (Picture_fillsBBH, r)
 
 DEF_TEST (Picture_nested_op_count, r)
 

Function Documentation

◆ check_balance()

static void check_balance ( skiatest::Reporter reporter,
SkPicture picture 
)
static

Definition at line 195 of file PictureTest.cpp.

195 {
196 SkBitmap bm;
197 bm.allocN32Pixels(4, 3);
198 SkCanvas canvas(bm);
199
200 int beforeSaveCount = canvas.getSaveCount();
201
202 SkMatrix beforeMatrix = canvas.getTotalMatrix();
203
204 SkRect beforeClip = canvas.getLocalClipBounds();
205
206 canvas.drawPicture(picture);
207
208 REPORTER_ASSERT(reporter, beforeSaveCount == canvas.getSaveCount());
209 REPORTER_ASSERT(reporter, beforeMatrix == canvas.getTotalMatrix());
210
211 SkRect afterClip = canvas.getLocalClipBounds();
212
213 REPORTER_ASSERT(reporter, afterClip == beforeClip);
214}
reporter
Definition: FontMgrTest.cpp:39
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition: SkBitmap.cpp:232
sk_sp< const SkPicture > picture
Definition: SkRecords.h:299

◆ check_save_state()

void check_save_state ( skiatest::Reporter reporter,
SkPicture picture,
unsigned int  numSaves,
unsigned int  numSaveLayers,
unsigned int  numRestores 
)

Definition at line 151 of file PictureTest.cpp.

153 {
156
157 picture->playback(&canvas);
158
159 // Optimizations may have removed these,
160 // so expect to have seen no more than num{Saves,SaveLayers,Restores}.
161 REPORTER_ASSERT(reporter, numSaves >= canvas.getSaveCount());
162 REPORTER_ASSERT(reporter, numSaveLayers >= canvas.getSaveLayerCount());
163 REPORTER_ASSERT(reporter, numRestores >= canvas.getRestoreCount());
164}
#define SkScalarCeilToInt(x)
Definition: SkScalar.h:36
virtual SkRect cullRect() const =0
virtual void playback(SkCanvas *canvas, AbortCallback *callback=nullptr) const =0
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762

◆ create_imbalance()

static void create_imbalance ( SkCanvas canvas)
static

Definition at line 181 of file PictureTest.cpp.

181 {
183 SkRect drawRect = SkRect::MakeWH(10, 10);
184 canvas->save();
186 canvas->translate(1.0f, 1.0f);
187 SkPaint p;
188 p.setColor(SK_ColorGREEN);
189 canvas->drawRect(drawRect, p);
190 // no restore
191}
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1361
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
int save()
Definition: SkCanvas.cpp:447
clipRect(r.rect, r.opAA.op(), r.opAA.aa())) template<> void Draw
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609

◆ DEF_TEST() [1/17]

DEF_TEST ( Canvas_EmptyBitmap  ,
 
)

Definition at line 558 of file PictureTest.cpp.

558 {
560 dst.allocN32Pixels(10, 10);
561 SkCanvas canvas(dst);
562
563 test_draw_bitmaps(&canvas);
564}
static void test_draw_bitmaps(SkCanvas *canvas)
dst
Definition: cp.py:12

◆ DEF_TEST() [2/17]

DEF_TEST ( DontOptimizeSaveLayerDrawDrawRestore  ,
reporter   
)

Definition at line 566 of file PictureTest.cpp.

566 {
567 // This test is from crbug.com/344987.
568 // The commands are:
569 // saveLayer with paint that modifies alpha
570 // drawBitmapRect
571 // drawBitmapRect
572 // restore
573 // The bug was that this structure was modified so that:
574 // - The saveLayer and restore were eliminated
575 // - The alpha was only applied to the first drawBitmapRectToRect
576
577 // This test draws blue and red squares inside a 50% transparent
578 // layer. Both colours should show up muted.
579 // When the bug is present, the red square (the second bitmap)
580 // shows upwith full opacity.
581
582 SkBitmap blueBM;
583 make_bm(&blueBM, 100, 100, SkColorSetARGB(255, 0, 0, 255), true);
584 SkBitmap redBM;
585 make_bm(&redBM, 100, 100, SkColorSetARGB(255, 255, 0, 0), true);
586 SkPaint semiTransparent;
587 semiTransparent.setAlpha(0x80);
588
589 SkPictureRecorder recorder;
590 SkCanvas* canvas = recorder.beginRecording(100, 100);
591 canvas->drawColor(0);
592
593 canvas->saveLayer(nullptr, &semiTransparent);
594 canvas->drawImage(blueBM.asImage(), 25, 25);
595 canvas->drawImage(redBM.asImage(), 50, 50);
596 canvas->restore();
597
599
600 // Now replay the picture back on another canvas
601 // and check a couple of its pixels.
602 SkBitmap replayBM;
603 make_bm(&replayBM, 100, 100, SK_ColorBLACK, false);
604 SkCanvas replayCanvas(replayBM);
605 picture->playback(&replayCanvas);
606
607 // With the bug present, at (55, 55) we would get a fully opaque red
608 // intead of a dark red.
609 REPORTER_ASSERT(reporter, replayBM.getColor(30, 30) == 0xff000080);
610 REPORTER_ASSERT(reporter, replayBM.getColor(55, 55) == 0xff800000);
611}
static void make_bm(SkBitmap *bm, int w, int h, SkColor color, bool immutable)
Definition: PictureTest.cpp:46
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColor.h:49
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
sk_sp< SkImage > asImage() const
Definition: SkBitmap.cpp:645
SkColor getColor(int x, int y) const
Definition: SkBitmap.h:874
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition: SkCanvas.cpp:496
void restore()
Definition: SkCanvas.cpp:461
void drawColor(SkColor color, SkBlendMode mode=SkBlendMode::kSrcOver)
Definition: SkCanvas.h:1182
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
void setAlpha(U8CPU a)
Definition: SkPaint.h:279
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()

◆ DEF_TEST() [3/17]

DEF_TEST ( Picture  ,
reporter   
)

Definition at line 520 of file PictureTest.cpp.

520 {
522#ifdef SK_DEBUG
523 test_deleting_empty_picture();
524 test_serializing_empty_picture();
525#endif
532}
static void test_cull_rect_reset(skiatest::Reporter *reporter)
static void test_unbalanced_save_restores(skiatest::Reporter *reporter)
static void test_typeface(skiatest::Reporter *reporter)
static void test_peephole()
static void test_gen_id(skiatest::Reporter *reporter)
static void test_bad_bitmap(skiatest::Reporter *reporter)
static void test_clip_bound_opt(skiatest::Reporter *reporter)

◆ DEF_TEST() [4/17]

DEF_TEST ( Picture_BitmapLeak  ,
 
)

Definition at line 659 of file PictureTest.cpp.

659 {
660 SkBitmap mut, immut;
661 mut.allocN32Pixels(300, 200);
662 immut.allocN32Pixels(300, 200);
663 immut.setImmutable();
664 SkASSERT(!mut.isImmutable());
665 SkASSERT(immut.isImmutable());
666
667 // No one can hold a ref on our pixels yet.
668 REPORTER_ASSERT(r, mut.pixelRef()->unique());
669 REPORTER_ASSERT(r, immut.pixelRef()->unique());
670
672 {
673 // we want the recorder to go out of scope before our subsequent checks, so we
674 // place it inside local braces.
676 SkCanvas* canvas = rec.beginRecording(1920, 1200);
677 canvas->drawImage(mut.asImage(), 0, 0);
678 canvas->drawImage(immut.asImage(), 800, 600);
679 pic = rec.finishRecordingAsPicture();
680 }
681
682 // The picture shares the immutable pixels but copies the mutable ones.
683 REPORTER_ASSERT(r, mut.pixelRef()->unique());
684 REPORTER_ASSERT(r, !immut.pixelRef()->unique());
685
686 // When the picture goes away, it's just our bitmaps holding the refs.
687 pic = nullptr;
688 REPORTER_ASSERT(r, mut.pixelRef()->unique());
689 REPORTER_ASSERT(r, immut.pixelRef()->unique());
690}
#define SkASSERT(cond)
Definition: SkAssert.h:116
void setImmutable()
Definition: SkBitmap.cpp:400
SkPixelRef * pixelRef() const
Definition: SkBitmap.h:720
bool isImmutable() const
Definition: SkBitmap.cpp:396
bool unique() const
Definition: SkRefCnt.h:50

◆ DEF_TEST() [5/17]

DEF_TEST ( Picture_drawsNothing  ,
 
)

Definition at line 797 of file PictureTest.cpp.

797 {
798 // Tests that pic->cullRect().isEmpty() is a good way to test a picture
799 // recorded with an R-tree draws nothing.
800 struct {
801 bool draws_nothing;
802 void (*fn)(SkCanvas*);
803 } cases[] = {
804 { true, [](SkCanvas* c) { } },
805 { true, [](SkCanvas* c) { c->save(); c->restore(); } },
806 { true, [](SkCanvas* c) { c->save(); c->clipRect({0,0,5,5}); c->restore(); } },
807 { true, [](SkCanvas* c) { c->clipRect({0,0,5,5}); } },
808
809 { false, [](SkCanvas* c) { c->drawRect({0,0,5,5}, SkPaint{}); } },
810 { false, [](SkCanvas* c) { c->save(); c->drawRect({0,0,5,5}, SkPaint{}); c->restore(); } },
811 { false, [](SkCanvas* c) {
812 c->drawRect({0,0, 5, 5}, SkPaint{});
813 c->drawRect({5,5,10,10}, SkPaint{});
814 }},
815 };
816
817 for (const auto& c : cases) {
819 SkRTreeFactory factory;
820 c.fn(rec.beginRecording(10,10, &factory));
822
823 REPORTER_ASSERT(r, pic->cullRect().isEmpty() == c.draws_nothing);
824 }
825}
bool isEmpty() const
Definition: SkRect.h:693

◆ DEF_TEST() [6/17]

DEF_TEST ( Picture_empty_serial  ,
reporter   
)

Definition at line 783 of file PictureTest.cpp.

783 {
785 (void)rec.beginRecording(10, 10);
786 auto pic = rec.finishRecordingAsPicture();
788
789 auto data = pic->serialize(); // explicitly testing the default SkSerialProcs
791
792 auto pic2 = SkPicture::MakeFromData(data->data(), data->size());
794}
static sk_sp< SkPicture > MakeFromData(const SkData *data, const SkDeserialProcs *procs=nullptr)
Definition: SkPicture.cpp:160
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ DEF_TEST() [7/17]

DEF_TEST ( Picture_EmptyBitmap  ,
 
)

Definition at line 552 of file PictureTest.cpp.

552 {
553 SkPictureRecorder recorder;
554 test_draw_bitmaps(recorder.beginRecording(10, 10));
556}

◆ DEF_TEST() [8/17]

DEF_TEST ( Picture_emptyNestedPictureBug  ,
 
)

Definition at line 827 of file PictureTest.cpp.

827 {
828 const SkRect bounds = {-5000, -5000, 5000, 5000};
829
830 SkPictureRecorder recorder;
831 SkRTreeFactory factory;
832
833 // These three pictures should all draw the same but due to bugs they don't:
834 //
835 // 1) inner has enough content that it is recoreded as an SkBigPicture,
836 // and all its content falls outside the positive/positive quadrant,
837 // and it is recorded with an R-tree so we contract the cullRect to those bounds;
838 //
839 // 2) middle wraps inner,
840 // and it its recorded with an R-tree so we update middle's cullRect to inner's;
841 //
842 // 3) outer wraps inner,
843 // and notices that middle contains only one op, drawPicture(inner),
844 // so it plays middle back during recording rather than ref'ing middle,
845 // querying middle's R-tree with its SkCanvas' bounds* {0,0, 5000,5000},
846 // finding nothing to draw.
847 //
848 // * The bug was that these bounds were not tracked as {-5000,-5000, 5000,5000}.
849 {
850 SkCanvas* canvas = recorder.beginRecording(bounds, &factory);
851 canvas->translate(-100,-100);
852 canvas->drawRect({0,0,50,50}, SkPaint{});
853 }
855
856 recorder.beginRecording(bounds, &factory)->drawPicture(inner);
857 sk_sp<SkPicture> middle = recorder.finishRecordingAsPicture();
858
859 // This doesn't need &factory to reproduce the bug,
860 // but it's nice to see we come up with the same {-100,-100, -50,-50} bounds.
861 recorder.beginRecording(bounds, &factory)->drawPicture(middle);
863
864 REPORTER_ASSERT(r, (inner ->cullRect() == SkRect{-100,-100, -50,-50}));
865 REPORTER_ASSERT(r, (middle->cullRect() == SkRect{-100,-100, -50,-50}));
866 REPORTER_ASSERT(r, (outer ->cullRect() == SkRect{-100,-100, -50,-50})); // Used to fail.
867}
void drawPicture(const SkPicture *picture)
Definition: SkCanvas.h:1961
Optional< SkRect > bounds
Definition: SkRecords.h:189

◆ DEF_TEST() [9/17]

DEF_TEST ( Picture_fillsBBH  ,
 
)

Definition at line 869 of file PictureTest.cpp.

869 {
870 // Test empty (0 draws), mini (1 draw), and big (2+) pictures, making sure they fill the BBH.
871 const SkRect rects[] = {
872 { 0, 0, 20,20},
873 {20,20, 40,40},
874 };
875
876 for (int n = 0; n <= 2; n++) {
877 SkRTreeFactory factory;
879
880 sk_sp<SkBBoxHierarchy> bbh = factory();
881
882 SkCanvas* c = rec.beginRecording({0,0, 100,100}, bbh);
883 for (int i = 0; i < n; i++) {
884 c->drawRect(rects[i], SkPaint{});
885 }
887
888 std::vector<int> results;
889 bbh->search({0,0, 100,100}, &results);
890 REPORTER_ASSERT(r, (int)results.size() == n,
891 "results.size() == %d, want %d\n", (int)results.size(), n);
892 }
893}
virtual void search(const SkRect &query, std::vector< int > *results) const =0

◆ DEF_TEST() [10/17]

DEF_TEST ( Picture_getRecordingCanvas  ,
 
)

Definition at line 693 of file PictureTest.cpp.

693 {
696 for (int i = 0; i < 3; i++) {
697 rec.beginRecording(100, 100);
701 }
702}
SkCanvas * getRecordingCanvas()

◆ DEF_TEST() [11/17]

DEF_TEST ( Picture_nested_op_count  ,
 
)

Definition at line 895 of file PictureTest.cpp.

895 {
896 auto make_pic = [](int n, const sk_sp<SkPicture>& pic) {
898 SkCanvas* c = rec.beginRecording({0,0, 100,100});
899 for (int i = 0; i < n; i++) {
900 if (pic) {
901 c->drawPicture(pic);
902 } else {
903 c->drawRect({0,0, 100,100}, SkPaint{});
904 }
905 }
906 return rec.finishRecordingAsPicture();
907 };
908
909 auto check = [r](const sk_sp<SkPicture>& pic, int shallow, int nested) {
910 int s = pic->approximateOpCount(false);
911 int n = pic->approximateOpCount(true);
912 REPORTER_ASSERT(r, s == shallow);
913 REPORTER_ASSERT(r, n == nested);
914 };
915
916 sk_sp<SkPicture> leaf1 = make_pic(1, nullptr);
917 check(leaf1, 1, 1);
918
919 sk_sp<SkPicture> leaf10 = make_pic(10, nullptr);
920 check(leaf10, 10, 10);
921
922 check(make_pic( 1, leaf1), 1, 1);
923 check(make_pic( 1, leaf10), 1, 10);
924 check(make_pic(10, leaf1), 10, 10);
925 check(make_pic(10, leaf10), 10, 100);
926}
#define check(reporter, ref, unref, make, kill)
Definition: RefCntTest.cpp:85
static sk_sp< SkPicture > make_pic(const std::function< void(SkCanvas *)> &drawer)
virtual int approximateOpCount(bool nested=false) const =0
struct MyStruct s

◆ DEF_TEST() [12/17]

DEF_TEST ( Picture_preserveCullRect  ,
 
)

Definition at line 704 of file PictureTest.cpp.

704 {
705 SkPictureRecorder recorder;
706
707 SkCanvas* c = recorder.beginRecording(SkRect::MakeLTRB(1, 2, 3, 4));
709
712 picture->serialize(&wstream, nullptr); // default SkSerialProcs
713
714 std::unique_ptr<SkStream> rstream(wstream.detachAsStream());
715 sk_sp<SkPicture> deserializedPicture(SkPicture::MakeFromStream(rstream.get()));
716
717 REPORTER_ASSERT(r, deserializedPicture != nullptr);
718 REPORTER_ASSERT(r, deserializedPicture->cullRect().left() == 1);
719 REPORTER_ASSERT(r, deserializedPicture->cullRect().top() == 2);
720 REPORTER_ASSERT(r, deserializedPicture->cullRect().right() == 3);
721 REPORTER_ASSERT(r, deserializedPicture->cullRect().bottom() == 4);
722}
constexpr SkColor SK_ColorCYAN
Definition: SkColor.h:143
void clear(SkColor color)
Definition: SkCanvas.h:1199
std::unique_ptr< SkStreamAsset > detachAsStream()
Definition: SkStream.cpp:876
sk_sp< SkData > serialize(const SkSerialProcs *procs=nullptr) const
Definition: SkPicture.cpp:249
static sk_sp< SkPicture > MakeFromStream(SkStream *stream, const SkDeserialProcs *procs=nullptr)
Definition: SkPicture.cpp:147
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646

◆ DEF_TEST() [13/17]

DEF_TEST ( Picture_SkipBBH  ,
 
)

Definition at line 637 of file PictureTest.cpp.

637 {
638 SkRect bound = SkRect::MakeWH(320, 240);
639
640 auto bbh = sk_make_sp<CountingBBH>();
641 SpoonFedBBHFactory factory(bbh);
642
643 SkPictureRecorder recorder;
644 SkCanvas* c = recorder.beginRecording(bound, &factory);
645 // Record a few ops so we don't hit a small- or empty- picture optimization.
646 c->drawRect(bound, SkPaint());
647 c->drawRect(bound, SkPaint());
649
650 SkCanvas big(640, 480), small(300, 200);
651
652 picture->playback(&big);
653 REPORTER_ASSERT(r, bbh->searchCalls == 0);
654
655 picture->playback(&small);
656 REPORTER_ASSERT(r, bbh->searchCalls == 1);
657}

◆ DEF_TEST() [14/17]

DEF_TEST ( Picture_UpdatedCull_1  ,
 
)

Definition at line 728 of file PictureTest.cpp.

728 {
729 SkRTreeFactory factory;
730 SkPictureRecorder recorder;
731
732 auto canvas = recorder.beginRecording(SkRectPriv::MakeLargest(), &factory);
733 canvas->drawRect(SkRect::MakeWH(20,20), SkPaint{});
734 auto pic = recorder.finishRecordingAsPicture();
735 REPORTER_ASSERT(r, pic->cullRect() == SkRect::MakeWH(20,20));
736
737 canvas = recorder.beginRecording(SkRectPriv::MakeLargest());
738 canvas->drawRect(SkRect::MakeWH(20,20), SkPaint{});
739 pic = recorder.finishRecordingAsPicture();
740 REPORTER_ASSERT(r, pic->cullRect() == SkRectPriv::MakeLargest());
741}
static SkRect MakeLargest()
Definition: SkRectPriv.h:39

◆ DEF_TEST() [15/17]

DEF_TEST ( Picture_UpdatedCull_2  ,
 
)

Definition at line 742 of file PictureTest.cpp.

742 {
743 SkRTreeFactory factory;
744 SkPictureRecorder recorder;
745
746 auto canvas = recorder.beginRecording(SkRectPriv::MakeLargest(), &factory);
747 canvas->drawRect(SkRect::MakeWH(20,20), SkPaint{});
748 canvas->drawRect(SkRect::MakeWH(10,40), SkPaint{});
749 auto pic = recorder.finishRecordingAsPicture();
750 REPORTER_ASSERT(r, pic->cullRect() == SkRect::MakeWH(20,40));
751
752 canvas = recorder.beginRecording(SkRectPriv::MakeLargest());
753 canvas->drawRect(SkRect::MakeWH(20,20), SkPaint{});
754 canvas->drawRect(SkRect::MakeWH(10,40), SkPaint{});
755 pic = recorder.finishRecordingAsPicture();
756 REPORTER_ASSERT(r, pic->cullRect() == SkRectPriv::MakeLargest());
757}

◆ DEF_TEST() [16/17]

DEF_TEST ( PictureRecorder_replay  ,
reporter   
)

Definition at line 217 of file PictureTest.cpp.

217 {
218 // check save/saveLayer state
219 {
220 SkPictureRecorder recorder;
221
222 SkCanvas* canvas = recorder.beginRecording(10, 10);
223
224 canvas->saveLayer(nullptr, nullptr);
225
227
228 // The extra save and restore comes from the Copy process.
229 check_save_state(reporter, copy.get(), 2, 1, 3);
230
231 canvas->saveLayer(nullptr, nullptr);
232
234
235 check_save_state(reporter, final.get(), 1, 2, 3);
236
237 // The copy shouldn't pick up any operations added after it was made
238 check_save_state(reporter, copy.get(), 2, 1, 3);
239 }
240
241 // Recreate the Android partialReplay test case
242 {
243 SkPictureRecorder recorder;
244
245 SkCanvas* canvas = recorder.beginRecording(4, 3);
246 create_imbalance(canvas);
247
248 int expectedSaveCount = canvas->getSaveCount();
249
252
253 REPORTER_ASSERT(reporter, expectedSaveCount = canvas->getSaveCount());
254
255 // End the recording of source to test the picture finalization
256 // process isn't complicated by the partialReplay step
258 }
259}
void check_save_state(skiatest::Reporter *reporter, SkPicture *picture, unsigned int numSaves, unsigned int numSaveLayers, unsigned int numRestores)
static void create_imbalance(SkCanvas *canvas)
static void check_balance(skiatest::Reporter *reporter, SkPicture *picture)
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
Definition: SkSwizzler.cpp:31
int getSaveCount() const
Definition: SkCanvas.cpp:431
static sk_sp< SkPicture > Copy(SkPictureRecorder *recorder)
Definition: copy.py:1
const myers::Point & get(const myers::Segment &)

◆ DEF_TEST() [17/17]

DEF_TEST ( Placeholder  ,
 
)

Definition at line 759 of file PictureTest.cpp.

759 {
760 SkRect cull = { 0,0, 10,20 };
761
762 // Each placeholder is unique.
765 REPORTER_ASSERT(r, p1->cullRect() == p2->cullRect());
766 REPORTER_ASSERT(r, p1->cullRect() == cull);
767 REPORTER_ASSERT(r, p1->uniqueID() != p2->uniqueID());
768
769 // Placeholders are never unrolled by SkCanvas (while other small pictures may be).
770 SkPictureRecorder recorder;
771 SkCanvas* canvas = recorder.beginRecording(cull);
772 canvas->drawPicture(p1);
773 canvas->drawPicture(p2);
775 REPORTER_ASSERT(r, pic->approximateOpCount() == 2);
776
777 // Any upper limit when recursing into nested placeholders is fine as long
778 // as it doesn't overflow an int.
779 REPORTER_ASSERT(r, pic->approximateOpCount(/*nested?*/true) >= 2);
780 REPORTER_ASSERT(r, pic->approximateOpCount(/*nested?*/true) <= 10);
781}
uint32_t uniqueID() const
Definition: SkPicture.h:155
static sk_sp< SkPicture > MakePlaceholder(SkRect cull)
Definition: SkPicture.cpp:337

◆ draw_bitmaps()

static void draw_bitmaps ( const SkBitmap bitmap,
SkCanvas canvas 
)
static

Definition at line 534 of file PictureTest.cpp.

534 {
535 const SkRect rect = { 5.0f, 5.0f, 8.0f, 8.0f };
536 auto img = bitmap.asImage();
537
538 // Don't care what these record, as long as they're legal.
539 canvas->drawImage(img, 0.0f, 0.0f);
540 canvas->drawImageRect(img, rect, rect, SkSamplingOptions(), nullptr,
542 canvas->drawImage(img, 1, 1); // drawSprite
543}
@ kStrict_SrcRectConstraint
sample only inside bounds; slower
Definition: SkCanvas.h:1542
void drawImageRect(const SkImage *, const SkRect &src, const SkRect &dst, const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
Definition: SkCanvas.cpp:2333
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
Definition: bitmap.py:1
SkSamplingOptions(SkFilterMode::kLinear))

◆ make_bm()

static void make_bm ( SkBitmap bm,
int  w,
int  h,
SkColor  color,
bool  immutable 
)
static

Definition at line 46 of file PictureTest.cpp.

46 {
47 bm->allocN32Pixels(w, h);
48 bm->eraseColor(color);
49 if (immutable) {
50 bm->setImmutable();
51 }
52}
void eraseColor(SkColor4f) const
Definition: SkBitmap.cpp:442
DlColor color
SkScalar w
SkScalar h

◆ rand_op()

static void rand_op ( SkCanvas canvas,
SkRandom rand 
)
static

Definition at line 77 of file PictureTest.cpp.

77 {
79 SkRect rect = SkRect::MakeWH(50, 50);
80
81 SkScalar unit = rand.nextUScalar1();
82 if (unit <= 0.3) {
83// SkDebugf("save\n");
84 canvas->save();
85 } else if (unit <= 0.6) {
86// SkDebugf("restore\n");
87 canvas->restore();
88 } else if (unit <= 0.9) {
89// SkDebugf("clip\n");
90 canvas->clipRect(rect);
91 } else {
92// SkDebugf("draw\n");
93 canvas->drawPaint(paint);
94 }
95}
void drawPaint(const SkPaint &paint)
Definition: SkCanvas.cpp:1668
SkScalar nextUScalar1()
Definition: SkRandom.h:101
const Paint & paint
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12

◆ set_canvas_to_save_count_4()

static void set_canvas_to_save_count_4 ( SkCanvas canvas)
static

Definition at line 97 of file PictureTest.cpp.

97 {
98 canvas->restoreToCount(1);
99 canvas->save();
100 canvas->save();
101 canvas->save();
102}
void restoreToCount(int saveCount)
Definition: SkCanvas.cpp:478

◆ test_bad_bitmap()

static void test_bad_bitmap ( skiatest::Reporter reporter)
static

Definition at line 355 of file PictureTest.cpp.

355 {
356 // missing pixels should return null for image
357 SkBitmap bm;
359 auto img = bm.asImage();
361
362 // make sure we don't crash on a null image
363 SkPictureRecorder recorder;
364 SkCanvas* recordingCanvas = recorder.beginRecording(100, 100);
365 recordingCanvas->drawImage(nullptr, 0, 0);
367
368 SkCanvas canvas;
369 canvas.drawPicture(picture);
370}
bool setInfo(const SkImageInfo &imageInfo, size_t rowBytes=0)
Definition: SkBitmap.cpp:114
static SkImageInfo MakeN32Premul(int width, int height)

◆ test_clip_bound_opt()

static void test_clip_bound_opt ( skiatest::Reporter reporter)
static

Definition at line 372 of file PictureTest.cpp.

372 {
373 // Test for crbug.com/229011
380
381 SkPath invPath;
382 invPath.addOval(rect1);
384 SkPath path;
385 path.addOval(rect2);
387 path2.addOval(rect3);
388 SkIRect clipBounds;
389 SkPictureRecorder recorder;
390
391 // Testing conservative-raster-clip that is enabled by PictureRecord
392 {
393 SkCanvas* canvas = recorder.beginRecording(10, 10);
394 canvas->clipPath(invPath);
395 clipBounds = canvas->getDeviceClipBounds();
396 REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft);
397 REPORTER_ASSERT(reporter, 0 == clipBounds.fTop);
398 REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom);
399 REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
400 }
401 {
402 SkCanvas* canvas = recorder.beginRecording(10, 10);
403 canvas->clipPath(path);
404 canvas->clipPath(invPath);
405 clipBounds = canvas->getDeviceClipBounds();
406 REPORTER_ASSERT(reporter, 7 == clipBounds.fLeft);
407 REPORTER_ASSERT(reporter, 7 == clipBounds.fTop);
408 REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom);
409 REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
410 }
411 {
412 SkCanvas* canvas = recorder.beginRecording(10, 10);
414 clipBounds = canvas->getDeviceClipBounds();
415 REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft);
416 REPORTER_ASSERT(reporter, 0 == clipBounds.fTop);
417 REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom);
418 REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
419 }
420 {
421 SkCanvas* canvas = recorder.beginRecording(10, 10);
424 clipBounds = canvas->getDeviceClipBounds();
425 REPORTER_ASSERT(reporter, 7 == clipBounds.fLeft);
426 REPORTER_ASSERT(reporter, 7 == clipBounds.fTop);
427 REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom);
428 REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
429 }
430}
static SkPath path2()
#define SkIntToScalar(x)
Definition: SkScalar.h:57
void clipPath(const SkPath &path, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1456
SkIRect getDeviceClipBounds() const
Definition: SkCanvas.cpp:1607
Definition: SkPath.h:59
void setFillType(SkPathFillType ft)
Definition: SkPath.h:235
SkPath & addOval(const SkRect &oval, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:1106
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
Definition: SkRect.h:32
int32_t fBottom
larger y-axis bounds
Definition: SkRect.h:36
int32_t fTop
smaller y-axis bounds
Definition: SkRect.h:34
int32_t fLeft
smaller x-axis bounds
Definition: SkRect.h:33
int32_t fRight
larger x-axis bounds
Definition: SkRect.h:35
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659

◆ test_cull_rect_reset()

static void test_cull_rect_reset ( skiatest::Reporter reporter)
static

Definition at line 432 of file PictureTest.cpp.

432 {
433 SkPictureRecorder recorder;
434 SkRect bounds = SkRect::MakeWH(10, 10);
435 SkRTreeFactory factory;
436 SkCanvas* canvas = recorder.beginRecording(bounds, &factory);
437 bounds = SkRect::MakeWH(100, 100);
439 canvas->drawRect(bounds, paint);
440 canvas->drawRect(bounds, paint);
444
445 SkRect finalCullRect = picture->cullRect();
446 REPORTER_ASSERT(reporter, 0 == finalCullRect.fLeft);
447 REPORTER_ASSERT(reporter, 0 == finalCullRect.fTop);
448 REPORTER_ASSERT(reporter, 100 == finalCullRect.fBottom);
449 REPORTER_ASSERT(reporter, 100 == finalCullRect.fRight);
450}
static const SkBigPicture * AsSkBigPicture(const sk_sp< const SkPicture > &picture)
Definition: SkPicturePriv.h:36
sk_sp< SkPicture > finishRecordingAsPictureWithCull(const SkRect &cullRect)
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15

◆ test_draw_bitmaps()

static void test_draw_bitmaps ( SkCanvas canvas)
static

Definition at line 545 of file PictureTest.cpp.

545 {
547 draw_bitmaps(empty, canvas);
548 empty.setInfo(SkImageInfo::MakeN32Premul(10, 10));
549 draw_bitmaps(empty, canvas);
550}
static void draw_bitmaps(const SkBitmap &bitmap, SkCanvas *canvas)
EMSCRIPTEN_KEEPALIVE void empty()

◆ test_gen_id()

static void test_gen_id ( skiatest::Reporter reporter)
static

Definition at line 491 of file PictureTest.cpp.

491 {
492
493 SkPictureRecorder recorder;
494 recorder.beginRecording(0, 0);
496
497 // Empty pictures should still have a valid ID
499
500 SkCanvas* canvas = recorder.beginRecording(1, 1);
501 canvas->drawColor(SK_ColorWHITE);
502 sk_sp<SkPicture> hasData(recorder.finishRecordingAsPicture());
503 // picture should have a non-zero id after recording
504 REPORTER_ASSERT(reporter, hasData->uniqueID() != SK_InvalidGenID);
505
506 // both pictures should have different ids
507 REPORTER_ASSERT(reporter, hasData->uniqueID() != empty->uniqueID());
508}
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
static constexpr uint32_t SK_InvalidGenID
Definition: SkTypes.h:192

◆ test_peephole()

static void test_peephole ( )
static

Definition at line 322 of file PictureTest.cpp.

322 {
323 SkRandom rand;
324
325 SkPictureRecorder recorder;
326
327 for (int j = 0; j < 100; j++) {
328 SkRandom rand2(rand); // remember the seed
329
330 SkCanvas* canvas = recorder.beginRecording(100, 100);
331
332 for (int i = 0; i < 1000; ++i) {
333 rand_op(canvas, rand);
334 }
336
337 rand = rand2;
338 }
339
340 {
341 SkCanvas* canvas = recorder.beginRecording(100, 100);
342 SkRect rect = SkRect::MakeWH(50, 50);
343
344 for (int i = 0; i < 100; ++i) {
345 canvas->save();
346 }
347 while (canvas->getSaveCount() > 1) {
348 canvas->clipRect(rect);
349 canvas->restore();
350 }
352 }
353}
static void rand_op(SkCanvas *canvas, SkRandom &rand)
Definition: PictureTest.cpp:77

◆ test_typeface()

static void test_typeface ( skiatest::Reporter reporter)
static

Definition at line 510 of file PictureTest.cpp.

510 {
511 SkPictureRecorder recorder;
512 SkCanvas* canvas = recorder.beginRecording(10, 10);
514 canvas->drawString("Q", 0, 10, font, SkPaint());
517 picture->serialize(&stream, nullptr); // default SkSerialProcs
518}
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.h:1803
static constexpr SkFontStyle Italic()
Definition: SkFontStyle.h:72
Definition: SkFont.h:35
sk_sp< SkTypeface > CreateTestTypeface(const char *name, SkFontStyle style)
font
Font Metadata and Metrics.

◆ test_unbalanced_save_restores()

static void test_unbalanced_save_restores ( skiatest::Reporter reporter)
static

Definition at line 261 of file PictureTest.cpp.

261 {
262 SkCanvas testCanvas(100, 100);
263 set_canvas_to_save_count_4(&testCanvas);
264
265 REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
266
268 SkRect rect = SkRect::MakeLTRB(-10000000, -10000000, 10000000, 10000000);
269
270 SkPictureRecorder recorder;
271
272 {
273 // Create picture with 2 unbalanced saves
274 SkCanvas* canvas = recorder.beginRecording(100, 100);
275 canvas->save();
276 canvas->translate(10, 10);
277 canvas->drawRect(rect, paint);
278 canvas->save();
279 canvas->translate(10, 10);
280 canvas->drawRect(rect, paint);
281 sk_sp<SkPicture> extraSavePicture(recorder.finishRecordingAsPicture());
282
283 testCanvas.drawPicture(extraSavePicture);
284 REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
285 }
286
287 set_canvas_to_save_count_4(&testCanvas);
288
289 {
290 // Create picture with 2 unbalanced restores
291 SkCanvas* canvas = recorder.beginRecording(100, 100);
292 canvas->save();
293 canvas->translate(10, 10);
294 canvas->drawRect(rect, paint);
295 canvas->save();
296 canvas->translate(10, 10);
297 canvas->drawRect(rect, paint);
298 canvas->restore();
299 canvas->restore();
300 canvas->restore();
301 canvas->restore();
302 sk_sp<SkPicture> extraRestorePicture(recorder.finishRecordingAsPicture());
303
304 testCanvas.drawPicture(extraRestorePicture);
305 REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
306 }
307
308 set_canvas_to_save_count_4(&testCanvas);
309
310 {
311 SkCanvas* canvas = recorder.beginRecording(100, 100);
312 canvas->translate(10, 10);
313 canvas->drawRect(rect, paint);
314 sk_sp<SkPicture> noSavePicture(recorder.finishRecordingAsPicture());
315
316 testCanvas.drawPicture(noSavePicture);
317 REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
318 REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity());
319 }
320}
static void set_canvas_to_save_count_4(SkCanvas *canvas)
Definition: PictureTest.cpp:97