// 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 FLOW_TESTING_MOCK_LAYER_H_ #define FLOW_TESTING_MOCK_LAYER_H_ #include #include #include "flutter/flow/diff_context.h" #include "flutter/flow/layers/cacheable_layer.h" #include "flutter/flow/layers/container_layer.h" #include "flutter/flow/layers/layer.h" #include "flutter/flow/layers/layer_raster_cache_item.h" #include "flutter/flow/raster_cache.h" #include "flutter/flow/raster_cache_item.h" namespace flutter { namespace testing { // Mock implementation of the |Layer| interface that does nothing but paint // the specified |path| into the canvas. It records the |PrerollContext| and // |PaintContext| data passed in by its parent |Layer|, so the test can later // verify the data against expected values. class MockLayer : public Layer { public: explicit MockLayer(const SkPath& path, DlPaint paint = DlPaint()); static std::shared_ptr Make(SkPath path, DlPaint paint = DlPaint()) { return std::make_shared(path, paint); } static std::shared_ptr MakeOpacityCompatible(SkPath path) { auto mock_layer = std::make_shared(path, DlPaint()); mock_layer->set_fake_opacity_compatible(true); return mock_layer; } void Preroll(PrerollContext* context) override; void Paint(PaintContext& context) const override; const MutatorsStack& parent_mutators() { return parent_mutators_; } const SkMatrix& parent_matrix() { return parent_matrix_; } const SkRect& parent_cull_rect() { return parent_cull_rect_; } bool IsReplacing(DiffContext* context, const Layer* layer) const override; void Diff(DiffContext* context, const Layer* old_layer) override; const MockLayer* as_mock_layer() const override { return this; } bool parent_has_platform_view() { return mock_flags_ & kParentHasPlatformView; } bool parent_has_texture_layer() { return mock_flags_ & kParentHasTextureLayer; } bool fake_has_platform_view() { return mock_flags_ & kFakeHasPlatformView; } bool fake_reads_surface() { return mock_flags_ & kFakeReadsSurface; } bool fake_opacity_compatible() { return mock_flags_ & kFakeOpacityCompatible; } bool fake_has_texture_layer() { return mock_flags_ & kFakeHasTextureLayer; } MockLayer& set_parent_has_platform_view(bool flag) { flag ? (mock_flags_ |= kParentHasPlatformView) : (mock_flags_ &= ~(kParentHasPlatformView)); return *this; } MockLayer& set_parent_has_texture_layer(bool flag) { flag ? (mock_flags_ |= kParentHasTextureLayer) : (mock_flags_ &= ~(kParentHasTextureLayer)); return *this; } MockLayer& set_fake_has_platform_view(bool flag) { flag ? (mock_flags_ |= kFakeHasPlatformView) : (mock_flags_ &= ~(kFakeHasPlatformView)); return *this; } MockLayer& set_fake_reads_surface(bool flag) { flag ? (mock_flags_ |= kFakeReadsSurface) : (mock_flags_ &= ~(kFakeReadsSurface)); return *this; } MockLayer& set_fake_opacity_compatible(bool flag) { flag ? (mock_flags_ |= kFakeOpacityCompatible) : (mock_flags_ &= ~(kFakeOpacityCompatible)); return *this; } MockLayer& set_fake_has_texture_layer(bool flag) { flag ? (mock_flags_ |= kFakeHasTextureLayer) : (mock_flags_ &= ~(kFakeHasTextureLayer)); return *this; } void set_expected_paint_matrix(const SkMatrix& matrix) { expected_paint_matrix_ = matrix; } private: MutatorsStack parent_mutators_; SkMatrix parent_matrix_; SkRect parent_cull_rect_ = SkRect::MakeEmpty(); SkPath fake_paint_path_; DlPaint fake_paint_; std::optional expected_paint_matrix_; static constexpr int kParentHasPlatformView = 1 << 0; static constexpr int kParentHasTextureLayer = 1 << 1; static constexpr int kFakeHasPlatformView = 1 << 2; static constexpr int kFakeReadsSurface = 1 << 3; static constexpr int kFakeOpacityCompatible = 1 << 4; static constexpr int kFakeHasTextureLayer = 1 << 5; int mock_flags_ = 0; FML_DISALLOW_COPY_AND_ASSIGN(MockLayer); }; class MockCacheableContainerLayer : public CacheableContainerLayer { public: // if render more than 3 frames, try to cache itself. // if less 3 frames, cache his children static std::shared_ptr CacheLayerOrChildren() { return std::make_shared(true); } // if render more than 3 frames, try to cache itself. // if less 3 frames, cache nothing static std::shared_ptr CacheLayerOnly() { return std::make_shared(); } void Preroll(PrerollContext* context) override; explicit MockCacheableContainerLayer(bool cache_children = false) : CacheableContainerLayer(3, cache_children) {} }; class MockLayerCacheableItem : public LayerRasterCacheItem { public: using LayerRasterCacheItem::LayerRasterCacheItem; }; class MockCacheableLayer : public MockLayer { public: explicit MockCacheableLayer(SkPath path, DlPaint paint = DlPaint(), int render_limit = 3) : MockLayer(path, paint) { raster_cache_item_ = std::make_unique(this, render_limit); } const LayerRasterCacheItem* raster_cache_item() const { return raster_cache_item_.get(); } void Preroll(PrerollContext* context) override; private: std::unique_ptr raster_cache_item_; }; } // namespace testing } // namespace flutter #endif // FLOW_TESTING_MOCK_LAYER_H_