1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef FLUTTER_DISPLAY_LIST_UTILS_DL_BOUNDS_ACCUMULATOR_H_
6#define FLUTTER_DISPLAY_LIST_UTILS_DL_BOUNDS_ACCUMULATOR_H_
7
8#include <functional>
9
10#include "flutter/display_list/geometry/dl_rtree.h"
11#include "flutter/fml/logging.h"
12
13// This file contains various utility classes to ease implementing
14// a Flutter DisplayList DlOpReceiver, including:
15//
16// IgnoreAttributeDispatchHelper:
17// IgnoreClipDispatchHelper:
18// IgnoreTransformDispatchHelper
19// Empty overrides of all of the associated methods of DlOpReceiver
20// for receivers that only track some of the rendering operations
21
22namespace flutter {
23
24enum class BoundsAccumulatorType {
25 kRect,
26 kRTree,
27};
28
29class BoundsAccumulator {
30 public:
31 /// function definition for modifying the bounds of a rectangle
32 /// during a restore operation. The function is used primarily
33 /// to account for the bounds impact of an ImageFilter on a
34 /// saveLayer on a per-rect basis. The implementation may apply
35 /// this function at whatever granularity it can manage easily
36 /// (for example, a Rect accumulator might apply it to the entire
37 /// local bounds being restored, whereas an RTree accumulator might
38 /// apply it individually to each element in the local RTree).
39 ///
40 /// The function will do a best faith attempt at determining the
41 /// modified bounds and store the results in the supplied |dest|
42 /// rectangle and return true. If the function is unable to
43 /// accurately determine the modifed bounds, it will set the
44 /// |dest| rectangle to a copy of the input bounds (or a best
45 /// guess) and return false to indicate that the bounds should not
46 /// be trusted.
47 typedef bool BoundsModifier(const SkRect& original, SkRect* dest);
48
49 virtual ~BoundsAccumulator() = default;
50
51 virtual void accumulate(const SkRect& r, int index = 0) = 0;
52
53 /// Save aside the rects/bounds currently being accumulated and start
54 /// accumulating a new set of rects/bounds. When restore is called,
55 /// some additional modifications may be applied to these new bounds
56 /// before they are accumulated back into the surrounding bounds.
57 virtual void save() = 0;
58
59 /// Restore to the previous accumulation and incorporate the bounds of
60 /// the primitives that were recorded since the last save (if needed).
61 virtual void restore() = 0;
62
63 /// Restore the previous set of accumulation rects/bounds and accumulate
64 /// the current rects/bounds that were accumulated since the most recent
65 /// call to |save| into them with modifications specified by the |map|
66 /// parameter and clipping to the clip parameter if it is not null.
67 ///
68 /// The indicated map function is applied to the various rects and bounds
69 /// that have been accumulated in this save/restore cycle before they
70 /// are then accumulated into the previous accumulations. The granularity
71 /// of the application of the map function to the rectangles that were
72 /// accumulated during the save period is left up to the implementation.
73 ///
74 /// This method will return true if the map function returned true on
75 /// every single invocation. A false return value means that the
76 /// bounds accumulated during this restore may not be trusted (as
77 /// determined by the map function).
78 ///
79 /// If there are no saved accumulations to restore to, this method will
80 /// NOP ignoring the map function and the optional clip entirely.
81 virtual bool restore(
82 std::function<bool(const SkRect& original, SkRect& modified)> map,
83 const SkRect* clip = nullptr) = 0;
84
85 virtual SkRect bounds() const = 0;
86
87 virtual sk_sp<DlRTree> rtree() const = 0;
88
89 virtual BoundsAccumulatorType type() const = 0;
90};
91
92class RectBoundsAccumulator final : public virtual BoundsAccumulator {
93 public:
94 void accumulate(SkScalar x, SkScalar y) { rect_.accumulate(x, y); }
95 void accumulate(const SkPoint& p) { rect_.accumulate(x: p.fX, y: p.fY); }
96 void accumulate(const SkRect& r, int index) override;
97
98 bool is_empty() const { return rect_.is_empty(); }
99 bool is_not_empty() const { return rect_.is_not_empty(); }
100
101 void save() override;
102 void restore() override;
103 bool restore(std::function<bool(const SkRect&, SkRect&)> mapper,
104 const SkRect* clip) override;
105
106 SkRect bounds() const override {
107 FML_DCHECK(saved_rects_.empty());
108 return rect_.bounds();
109 }
110
111 BoundsAccumulatorType type() const override {
112 return BoundsAccumulatorType::kRect;
113 }
114
115 sk_sp<DlRTree> rtree() const override { return nullptr; }
116
117 private:
118 class AccumulationRect {
119 public:
120 AccumulationRect();
121
122 void accumulate(SkScalar x, SkScalar y);
123
124 bool is_empty() const { return min_x_ >= max_x_ || min_y_ >= max_y_; }
125 bool is_not_empty() const { return min_x_ < max_x_ && min_y_ < max_y_; }
126
127 SkRect bounds() const;
128
129 private:
130 SkScalar min_x_;
131 SkScalar min_y_;
132 SkScalar max_x_;
133 SkScalar max_y_;
134 };
135
136 void pop_and_accumulate(SkRect& layer_bounds, const SkRect* clip);
137
138 AccumulationRect rect_;
139 std::vector<AccumulationRect> saved_rects_;
140};
141
142class RTreeBoundsAccumulator final : public virtual BoundsAccumulator {
143 public:
144 void accumulate(const SkRect& r, int index) override;
145 void save() override;
146 void restore() override;
147
148 bool restore(
149 std::function<bool(const SkRect& original, SkRect& modified)> map,
150 const SkRect* clip = nullptr) override;
151
152 SkRect bounds() const override;
153
154 sk_sp<DlRTree> rtree() const override;
155
156 BoundsAccumulatorType type() const override {
157 return BoundsAccumulatorType::kRTree;
158 }
159
160 private:
161 std::vector<SkRect> rects_;
162 std::vector<int> rect_indices_;
163 std::vector<size_t> saved_offsets_;
164};
165
166} // namespace flutter
167
168#endif // FLUTTER_DISPLAY_LIST_UTILS_DL_BOUNDS_ACCUMULATOR_H_
169

source code of flutter_engine/flutter/display_list/utils/dl_bounds_accumulator.h