// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef TESTING_MOCK_CANVAS_H_ #define TESTING_MOCK_CANVAS_H_ #include #include #include #include "flutter/testing/assertions_skia.h" #include "gtest/gtest.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkCanvasVirtualEnforcer.h" #include "third_party/skia/include/core/SkClipOp.h" #include "third_party/skia/include/core/SkData.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/core/SkM44.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/utils/SkNWayCanvas.h" namespace flutter { namespace testing { static constexpr SkRect kEmptyRect = SkRect::MakeEmpty(); // Mock |SkCanvas|, useful for writing tests that use Skia but do not interact // with the GPU. // // The |MockCanvas| stores a list of |DrawCall| that the test can later verify // against the expected list of primitives to be drawn. class MockCanvas : public SkCanvasVirtualEnforcer { public: using SkCanvas::kHard_ClipEdgeStyle; using SkCanvas::kSoft_ClipEdgeStyle; struct SaveData { int save_to_layer; }; struct SaveLayerData { SkRect save_bounds; SkPaint restore_paint; sk_sp backdrop_filter; int save_to_layer; }; struct RestoreData { int restore_to_layer; }; struct ConcatMatrixData { SkMatrix matrix; }; struct ConcatMatrix44Data { SkM44 matrix; }; struct SetMatrixData { SkMatrix matrix; }; struct DrawRectData { SkRect rect; SkPaint paint; }; struct DrawPathData { SkPath path; SkPaint paint; }; struct DrawTextData { sk_sp serialized_text; SkPaint paint; SkPoint offset; }; struct DrawPictureData { sk_sp serialized_picture; SkPaint paint; SkMatrix matrix; }; struct DrawShadowData { SkPath path; }; struct ClipRectData { SkRect rect; SkClipOp clip_op; ClipEdgeStyle style; }; struct ClipRRectData { SkRRect rrect; SkClipOp clip_op; ClipEdgeStyle style; }; struct ClipPathData { SkPath path; SkClipOp clip_op; ClipEdgeStyle style; }; struct DrawPaint { SkPaint paint; }; // Discriminated union of all the different |DrawCall| types. It is roughly // equivalent to the different methods in |SkCanvas|' public API. using DrawCallData = std::variant; // A single call made against this canvas. struct DrawCall { int layer; DrawCallData data; }; MockCanvas(); ~MockCanvas() override; SkNWayCanvas* internal_canvas() { return &internal_canvas_; } const std::vector& draw_calls() const { return draw_calls_; } protected: // Save/restore/set operations that we track. void willSave() override; SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override; void willRestore() override; void didRestore() override {} void didConcat(const SkMatrix& matrix) override; void didConcat44(const SkM44&) override; void didScale(SkScalar x, SkScalar y) override; void didTranslate(SkScalar x, SkScalar y) override; void didSetMatrix(const SkMatrix& matrix) override; // Draw and clip operations that we track. void onDrawRect(const SkRect& rect, const SkPaint& paint) override; void onDrawPath(const SkPath& path, const SkPaint& paint) override; void onDrawTextBlob(const SkTextBlob* text, SkScalar x, SkScalar y, const SkPaint& paint) override; void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override; void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) override; void onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle style) override; void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle style) override; void onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle style) override; // Operations that we don't track. bool onDoSaveBehind(const SkRect*) override; void onDrawAnnotation(const SkRect&, const char[], SkData*) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; void onDrawDrawable(SkDrawable*, const SkMatrix*) override; void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode, const SkPaint&) override; void onDrawPaint(const SkPaint&) override; void onDrawBehind(const SkPaint&) override; void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override; void onDrawRegion(const SkRegion&, const SkPaint&) override; void onDrawOval(const SkRect&, const SkPaint&) override; void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override; void onDrawRRect(const SkRRect&, const SkPaint&) override; void onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) override; void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*, SrcRectConstraint) override; void onDrawImageNine(const SkImage*, const SkIRect&, const SkRect&, const SkPaint*) override; void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&, const SkPaint*) override; void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override; void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int, SkBlendMode, const SkRect*, const SkPaint*) override; void onDrawEdgeAAQuad(const SkRect&, const SkPoint[4], QuadAAFlags, const SkColor4f&, SkBlendMode) override; void onDrawEdgeAAImageSet(const ImageSetEntry[], int, const SkPoint[], const SkMatrix[], const SkPaint*, SrcRectConstraint) override; void onClipRegion(const SkRegion&, SkClipOp) override; private: SkNWayCanvas internal_canvas_; std::vector draw_calls_; int current_layer_; }; extern bool operator==(const MockCanvas::SaveData& a, const MockCanvas::SaveData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::SaveData& data); extern bool operator==(const MockCanvas::SaveLayerData& a, const MockCanvas::SaveLayerData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::SaveLayerData& data); extern bool operator==(const MockCanvas::RestoreData& a, const MockCanvas::RestoreData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::RestoreData& data); extern bool operator==(const MockCanvas::ConcatMatrixData& a, const MockCanvas::ConcatMatrixData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::ConcatMatrixData& data); extern bool operator==(const MockCanvas::ConcatMatrix44Data& a, const MockCanvas::ConcatMatrix44Data& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::ConcatMatrix44Data& data); extern bool operator==(const MockCanvas::SetMatrixData& a, const MockCanvas::SetMatrixData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::SetMatrixData& data); extern bool operator==(const MockCanvas::DrawRectData& a, const MockCanvas::DrawRectData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawRectData& data); extern bool operator==(const MockCanvas::DrawPathData& a, const MockCanvas::DrawPathData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawPathData& data); extern bool operator==(const MockCanvas::DrawTextData& a, const MockCanvas::DrawTextData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawTextData& data); extern bool operator==(const MockCanvas::DrawPictureData& a, const MockCanvas::DrawPictureData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawPictureData& data); extern bool operator==(const MockCanvas::DrawShadowData& a, const MockCanvas::DrawShadowData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawShadowData& data); extern bool operator==(const MockCanvas::ClipRectData& a, const MockCanvas::ClipRectData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::ClipRectData& data); extern bool operator==(const MockCanvas::ClipRRectData& a, const MockCanvas::ClipRRectData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::ClipRRectData& data); extern bool operator==(const MockCanvas::ClipPathData& a, const MockCanvas::ClipPathData& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::ClipPathData& data); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawCallData& data); extern bool operator==(const MockCanvas::DrawCall& a, const MockCanvas::DrawCall& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawCall& draw); extern bool operator==(const MockCanvas::DrawPaint& a, const MockCanvas::DrawPaint& b); extern std::ostream& operator<<(std::ostream& os, const MockCanvas::DrawPaint& data); } // namespace testing } // namespace flutter #endif // TESTING_MOCK_CANVAS_H_