|
12 | 12 |
|
13 | 13 | namespace flutter {
|
14 | 14 |
|
| 15 | +/// The LayerStateStack manages the inherited state passed down between |
| 16 | +/// |Layer| objects in a |LayerTree| during |Preroll| and |Paint|. |
| 17 | +/// |
| 18 | +/// More specifically, it manages the clip and transform state during |
| 19 | +/// recursive rendering and will hold and lazily apply opacity, ImageFilter |
| 20 | +/// and ColorFilter attributes to recursive content. This is not a truly |
| 21 | +/// general state management mechnanism as it makes assumptions that code |
| 22 | +/// will be applying the attributes to rendered content that happens in |
| 23 | +/// recursive calls. The automatic save/restore mechanisms only work in |
| 24 | +/// a context where C++ auto-destruct calls will engage the restore at |
| 25 | +/// the end of a code block and that any applied attributes will only |
| 26 | +/// be applied to the content rendered inside that block. These restrictions |
| 27 | +/// match the organization of the |LayerTree| precisely. |
| 28 | +/// |
| 29 | +/// The stack can manage a single state delegate. The stack will both |
| 30 | +/// record the state internally regardless of any delegate and will also |
| 31 | +/// apply it to a delegate as needed. The delegate can be swapped out |
| 32 | +/// on the fly (as is typically done by PlatformViewLayer when recording |
| 33 | +/// the state for multiple inter-embedded-view sub-trees) and the old |
| 34 | +/// delegate will be restored to its original state (before it became a |
| 35 | +/// delegate) and the new delegate will have all of the state recorded |
| 36 | +/// by the stack replayed into it to bring it up to speed with the |
| 37 | +/// current rendering context. |
| 38 | +/// |
| 39 | +/// The delegate can be any one of: |
| 40 | +/// - MutatorsStack: used during Preroll to remember the outstanding |
| 41 | +/// state for embedded platform layers |
| 42 | +/// - SkCanvas: used during Paint for the default output to a Skia |
| 43 | +/// surface |
| 44 | +/// - DisplayListBuilder: used during Paint to construct a DisplayList |
| 45 | +/// for Impeller output |
| 46 | +/// The stack will know which state needs to be conveyed to any of these |
| 47 | +/// delegates and when is the best time to convey that state (i.e. lazy |
| 48 | +/// saveLayer calls for example). |
| 49 | +/// |
| 50 | +/// The rendering state attributes will be automatically applied to the |
| 51 | +/// nested content using a |saveLayer| call at the point at which we |
| 52 | +/// encounter rendered content (i.e. various nested layers that exist only |
| 53 | +/// to apply new state will not trigger the |saveLayer| and the attributes |
| 54 | +/// can accumulate until we reach actual content that is rendered.) Some |
| 55 | +/// rendered content can avoid the |saveLayer| if it reports to the object |
| 56 | +/// that it is able to apply all of the attributes that happen to be |
| 57 | +/// outstanding (accumulated from parent state-modifiers). A |ContainerLayer| |
| 58 | +/// can also monitor the attribute rendering capabilities of a list of |
| 59 | +/// children and can ask the object to apply a protective |saveLayer| or |
| 60 | +/// not based on the negotiated capabilities of the entire group. |
| 61 | +/// |
| 62 | +/// Any code that is planning to modify the clip, transform, or rendering |
| 63 | +/// attributes for its child content must start by calling the |save| method |
| 64 | +/// which returns a MutatorContext object. The methods that modify such |
| 65 | +/// state only exist on the MutatorContext object so it is difficult to get |
| 66 | +/// that wrong, but the caller must make sure that the call happens within |
| 67 | +/// a C++ code block that will define the "rendering scope" of those |
| 68 | +/// state changes as they will be automatically restored on exit from that |
| 69 | +/// block. Note that the layer might make similar state calls directly on |
| 70 | +/// the canvas or builder during the Paint cycle (via saveLayer, transform, |
| 71 | +/// or clip calls), but should avoid doing so if there is any nested content |
| 72 | +/// that needs to track or react to those state calls. |
| 73 | +/// |
| 74 | +/// Code that needs to render content can simply inform the parent of their |
| 75 | +/// abilities by setting the |PrerollContext::renderable_state_flags| during |
| 76 | +/// |Preroll| and then render with those attributes during |Paint| by |
| 77 | +/// requesting the outstanding values of those attributes from the state_stack |
| 78 | +/// object. Individual leaf layers can ignore this feature as the default |
| 79 | +/// behavior during |Preroll| will have their parent |ContainerLayer| assume |
| 80 | +/// that they cannot render any outstanding state attributes and will apply |
| 81 | +/// the protective saveLayer on their behalf if needed. As such, this object |
| 82 | +/// only provides "opt-in" features for leaf layers and no responsibilities |
| 83 | +/// otherwise. |
| 84 | +/// See |LayerStateStack::fill| |
| 85 | +/// See |LayerStateStack::outstanding_opacity| |
| 86 | +/// See |LayerStateStack::outstanding_color_filter| |
| 87 | +/// See |LayerStateStack::outstanding_image_filter| |
| 88 | +/// |
| 89 | +/// State-modifying layers should contain code similar to this pattern in both |
| 90 | +/// their |Preroll| and |Paint| methods. |
| 91 | +/// |
| 92 | +/// void [LayerType]::[Preroll/Paint](context) { |
| 93 | +/// auto mutator = context.state_stack.save(); |
| 94 | +/// mutator.translate(origin.x, origin.y); |
| 95 | +/// mutator.applyOpacity(content_bounds, opacity_value); |
| 96 | +/// mutator.applyColorFilter(content_bounds, color_filter); |
| 97 | +/// |
| 98 | +/// // Children will react to the state applied above during their |
| 99 | +/// // Preroll/Paint methods or ContainerLayer will protect them |
| 100 | +/// // conservatively by default. |
| 101 | +/// [Preroll/Paint]Children(context); |
| 102 | +/// |
| 103 | +/// // here the mutator will be auto-destructed and the state accumulated |
| 104 | +/// // by it will be restored out of the state_stack and its associated |
| 105 | +/// // delegates. |
| 106 | +/// } |
15 | 107 | class LayerStateStack {
|
16 | 108 | public:
|
17 | 109 | explicit LayerStateStack(const SkRect* cull_rect = nullptr);
|
|
0 commit comments