Flutter Engine
transform_layer.cc
Go to the documentation of this file.
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 #include "flutter/flow/layers/transform_layer.h"
6 
7 #include <optional>
8 
9 namespace flutter {
10 
12  : transform_(transform) {
13  // Checks (in some degree) that SkMatrix transform_ is valid and initialized.
14  //
15  // If transform_ is uninitialized, this assert may look flaky as it doesn't
16  // fail all the time, and some rerun may make it pass. But don't ignore it and
17  // just rerun the test if this is triggered, since even a flaky failure here
18  // may signify a potentially big problem in the code.
19  //
20  // We have to write this flaky test because there is no reliable way to test
21  // whether a variable is initialized or not in C++.
22  FML_DCHECK(transform_.isFinite());
23  if (!transform_.isFinite()) {
24  FML_LOG(ERROR) << "TransformLayer is constructed with an invalid matrix.";
25  transform_.setIdentity();
26  }
27 }
28 
29 #ifdef FLUTTER_ENABLE_DIFF_CONTEXT
30 
31 void TransformLayer::Diff(DiffContext* context, const Layer* old_layer) {
32  DiffContext::AutoSubtreeRestore subtree(context);
33  auto* prev = static_cast<const TransformLayer*>(old_layer);
34  if (!context->IsSubtreeDirty()) {
35  FML_DCHECK(prev);
36  if (transform_ != prev->transform_) {
37  context->MarkSubtreeDirty(context->GetOldLayerPaintRegion(old_layer));
38  }
39  }
40  context->PushTransform(transform_);
41  DiffChildren(context, prev);
42  context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion());
43 }
44 
45 #endif // FLUTTER_ENABLE_DIFF_CONTEXT
46 
47 void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
48  TRACE_EVENT0("flutter", "TransformLayer::Preroll");
49 
50  SkMatrix child_matrix;
51  child_matrix.setConcat(matrix, transform_);
52  context->mutators_stack.PushTransform(transform_);
53  SkRect previous_cull_rect = context->cull_rect;
54  SkMatrix inverse_transform_;
55  // Perspective projections don't produce rectangles that are useful for
56  // culling for some reason.
57  if (!transform_.hasPerspective() && transform_.invert(&inverse_transform_)) {
58  inverse_transform_.mapRect(&context->cull_rect);
59  } else {
60  context->cull_rect = kGiantRect;
61  }
62 
63  SkRect child_paint_bounds = SkRect::MakeEmpty();
64  PrerollChildren(context, child_matrix, &child_paint_bounds);
65 
66  transform_.mapRect(&child_paint_bounds);
67  set_paint_bounds(child_paint_bounds);
68 
69  context->cull_rect = previous_cull_rect;
70  context->mutators_stack.Pop();
71 }
72 
73 void TransformLayer::Paint(PaintContext& context) const {
74  TRACE_EVENT0("flutter", "TransformLayer::Paint");
75  FML_DCHECK(needs_painting(context));
76 
77  SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
78  context.internal_nodes_canvas->concat(transform_);
79 
80  PaintChildren(context);
81 }
82 
83 } // namespace flutter
void Paint(PaintContext &context) const override
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
#define FML_DCHECK(condition)
Definition: logging.h:86
TransformLayer(const SkMatrix &transform)
void PushTransform(const SkMatrix &matrix)
void Preroll(PrerollContext *context, const SkMatrix &matrix) override
#define FML_LOG(severity)
Definition: logging.h:65
void PrerollChildren(PrerollContext *context, const SkMatrix &child_matrix, SkRect *child_paint_bounds)
static constexpr SkRect kGiantRect
Definition: layer.h:37
bool needs_painting(PaintContext &context) const
Definition: layer.h:249
void set_paint_bounds(const SkRect &paint_bounds)
Definition: layer.h:240
SkCanvas * internal_nodes_canvas
Definition: layer.h:144
MutatorsStack & mutators_stack
Definition: layer.h:46
void PaintChildren(PaintContext &context) const