• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "include/core/SkMatrix.h"
7 
8 namespace flutter {
9 
TransformLayer(const SkMatrix & transform)10 TransformLayer::TransformLayer(const SkMatrix& transform)
11     : transform_(transform) {
12   // Checks (in some degree) that SkMatrix transform_ is valid and initialized.
13   //
14   // If transform_ is uninitialized, this assert may look flaky as it doesn't
15   // fail all the time, and some rerun may make it pass. But don't ignore it and
16   // just rerun the test if this is triggered, since even a flaky failure here
17   // may signify a potentially big problem in the code.
18   //
19   // We have to write this flaky test because there is no reliable way to test
20   // whether a variable is initialized or not in C++.
21   FML_DCHECK(transform_.isFinite());
22   if (!transform_.isFinite()) {
23     FML_LOG(ERROR) << "TransformLayer is constructed with an invalid matrix.";
24     transform_.setIdentity();
25   }
26 }
27 
28 TransformLayer::~TransformLayer() = default;
29 
Preroll(PrerollContext * context,const SkMatrix & matrix)30 void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
31   SkMatrix child_matrix;
32   child_matrix.setConcat(matrix, transform_);
33   context->mutators_stack.PushTransform(transform_);
34   SkRect previous_cull_rect = context->cull_rect;
35   SkMatrix inverse_transform_;
36   // Perspective projections don't produce rectangles that are useful for
37   // culling for some reason.
38   if (!transform_.hasPerspective() && transform_.invert(&inverse_transform_)) {
39     inverse_transform_.mapRect(&context->cull_rect);
40   } else {
41     context->cull_rect = kGiantRect;
42   }
43 
44   SkRect child_paint_bounds = SkRect::MakeEmpty();
45   PrerollChildren(context, child_matrix, &child_paint_bounds);
46 
47   transform_.mapRect(&child_paint_bounds);
48   set_paint_bounds(child_paint_bounds);
49 
50   context->cull_rect = previous_cull_rect;
51   context->mutators_stack.Pop();
52 }
53 
54 #if defined(OS_FUCHSIA)
55 
UpdateScene(SceneUpdateContext & context)56 void TransformLayer::UpdateScene(SceneUpdateContext& context) {
57   FML_DCHECK(needs_system_composite());
58 
59   SceneUpdateContext::Transform transform(context, transform_);
60   UpdateSceneChildren(context);
61 }
62 
63 #endif  // defined(OS_FUCHSIA)
64 
Paint(PaintContext & context) const65 void TransformLayer::Paint(PaintContext& context) const {
66   TRACE_EVENT0("flutter", "TransformLayer::Paint");
67   FML_DCHECK(needs_painting());
68 
69   SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
70   context.internal_nodes_canvas->concat(transform_);
71 
72   PaintChildren(context);
73 }
74 
MapRect(const SkRect & rect)75 SkRect TransformLayer::MapRect(const SkRect& rect) {
76   SkRect dst_rect;
77   if (transform_.mapRect(&dst_rect, rect)) {
78     return dst_rect;
79   }
80   return rect;
81 }
82 
MergeParentHole()83 void TransformLayer::MergeParentHole() {
84   auto* parent_layer = parent();
85   if (!parent_layer) {
86     return;
87   }
88   SkMatrix inverse_mat = transform_;
89   if (!inverse_mat.invert(&inverse_mat)) {
90     return;
91   }
92   for (const auto& [id, rect] : parent_layer->HoleRegions()) {
93     SkRect dst_rect;
94     if (inverse_mat.mapRect(&dst_rect, rect)) {
95       hole_regions_.try_emplace(id, dst_rect);
96     }
97   }
98 }
99 
100 }  // namespace flutter
101