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
9namespace flutter {
10
11TransformLayer::TransformLayer(const SkMatrix& transform)
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
29void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
30 TRACE_EVENT0("flutter", "TransformLayer::Preroll");
31
32 SkMatrix child_matrix;
33 child_matrix.setConcat(matrix, transform_);
34 context->mutators_stack.PushTransform(transform_);
35 SkRect previous_cull_rect = context->cull_rect;
36 SkMatrix inverse_transform_;
37 // Perspective projections don't produce rectangles that are useful for
38 // culling for some reason.
39 if (!transform_.hasPerspective() && transform_.invert(&inverse_transform_)) {
40 inverse_transform_.mapRect(&context->cull_rect);
41 } else {
42 context->cull_rect = kGiantRect;
43 }
44
45 SkRect child_paint_bounds = SkRect::MakeEmpty();
46 PrerollChildren(context, child_matrix, &child_paint_bounds);
47
48 transform_.mapRect(&child_paint_bounds);
49 set_paint_bounds(child_paint_bounds);
50
51 context->cull_rect = previous_cull_rect;
52 context->mutators_stack.Pop();
53}
54
55#if defined(LEGACY_FUCHSIA_EMBEDDER)
56
57void TransformLayer::UpdateScene(SceneUpdateContext& context) {
58 TRACE_EVENT0("flutter", "TransformLayer::UpdateScene");
59 FML_DCHECK(needs_system_composite());
60
61 std::optional<SceneUpdateContext::Transform> transform;
62 if (!transform_.isIdentity()) {
63 transform.emplace(context, transform_);
64 }
65
66 UpdateSceneChildren(context);
67}
68
69#endif
70
71void TransformLayer::Paint(PaintContext& context) const {
72 TRACE_EVENT0("flutter", "TransformLayer::Paint");
73 FML_DCHECK(needs_painting());
74
75 SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
76 context.internal_nodes_canvas->concat(transform_);
77
78 PaintChildren(context);
79}
80
81} // namespace flutter
82