Flutter Engine
The 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
9namespace flutter {
10
12 // Checks (in some degree) that SkM44 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
28void TransformLayer::Diff(DiffContext* context, const Layer* old_layer) {
29 DiffContext::AutoSubtreeRestore subtree(context);
30 auto* prev = static_cast<const TransformLayer*>(old_layer);
31 if (!context->IsSubtreeDirty()) {
33 if (transform_ != prev->transform_) {
34 context->MarkSubtreeDirty(context->GetOldLayerPaintRegion(old_layer));
35 }
36 }
37 context->PushTransform(transform_);
38 DiffChildren(context, prev);
39 context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion());
40}
41
43 auto mutator = context->state_stack.save();
44 mutator.transform(transform_);
45
48
49 // We convert to a 3x3 matrix here primarily because the SkM44 object
50 // does not support a mapRect operation.
51 // https://bugs.chromium.org/p/skia/issues/detail?id=11720&q=mapRect&can=2
52 //
53 // All geometry is X,Y only which means the 3rd row of the 4x4 matrix
54 // is ignored and the output of the 3rd column is also ignored.
55 // So we can transform the rectangle using just the 3x3 SkMatrix
56 // equivalent without any loss of information.
57 //
58 // Performance consideration:
59 // Skia has an internal mapRect for their SkM44 object that is faster
60 // than what SkMatrix does when it has perspective elements. But SkMatrix
61 // is otherwise optimal for non-perspective matrices. If SkM44 ever exposes
62 // a mapRect operation, or if SkMatrix ever optimizes its handling of
63 // the perspective elements, this issue will become moot.
64 transform_.asM33().mapRect(&child_paint_bounds);
66}
67
68void TransformLayer::Paint(PaintContext& context) const {
69 FML_DCHECK(needs_painting(context));
70
71 auto mutator = context.state_stack.save();
72 mutator.transform(transform_);
73
74 PaintChildren(context);
75}
76
77} // namespace flutter
static float prev(float f)
Definition: SkM44.h:150
bool isFinite() const
Definition: SkM44.h:378
SkMatrix asM33() const
Definition: SkM44.h:409
SkM44 & setIdentity()
Definition: SkM44.h:293
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkMatrix.cpp:1141
void PrerollChildren(PrerollContext *context, SkRect *child_paint_bounds)
void PaintChildren(PaintContext &context) const override
virtual void DiffChildren(DiffContext *context, const ContainerLayer *old_layer)
const SkRect & child_paint_bounds() const
void PushTransform(const SkMatrix &transform)
Definition: diff_context.cc:49
void SetLayerPaintRegion(const Layer *layer, const PaintRegion &region)
void MarkSubtreeDirty(const PaintRegion &previous_paint_region=PaintRegion())
PaintRegion CurrentSubtreeRegion() const
PaintRegion GetOldLayerPaintRegion(const Layer *layer) const
bool IsSubtreeDirty() const
Definition: diff_context.h:108
bool needs_painting(PaintContext &context) const
Definition: layer.h:232
void set_paint_bounds(const SkRect &paint_bounds)
Definition: layer.h:223
void Diff(DiffContext *context, const Layer *old_layer) override
void Preroll(PrerollContext *context) override
void Paint(PaintContext &context) const override
TransformLayer(const SkMatrix &transform)
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_DCHECK(condition)
Definition: logging.h:103
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595
LayerStateStack & state_stack
Definition: layer.h:101
LayerStateStack & state_stack
Definition: layer.h:59
#define ERROR(message)
Definition: elf_loader.cc:260