#include "flutter/flow/layers/transform_layer.h"
#include "include/core/SkMatrix.h"
namespace flutter {
TransformLayer::TransformLayer(const SkMatrix& transform)
: transform_(transform) {
FML_DCHECK(transform_.isFinite());
if (!transform_.isFinite()) {
FML_LOG(ERROR) << "TransformLayer is constructed with an invalid matrix.";
transform_.setIdentity();
}
}
TransformLayer::~TransformLayer() = default;
void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
SkMatrix child_matrix;
child_matrix.setConcat(matrix, transform_);
context->mutators_stack.PushTransform(transform_);
SkRect previous_cull_rect = context->cull_rect;
SkMatrix inverse_transform_;
if (!transform_.hasPerspective() && transform_.invert(&inverse_transform_)) {
inverse_transform_.mapRect(&context->cull_rect);
} else {
context->cull_rect = kGiantRect;
}
SkRect child_paint_bounds = SkRect::MakeEmpty();
PrerollChildren(context, child_matrix, &child_paint_bounds);
transform_.mapRect(&child_paint_bounds);
set_paint_bounds(child_paint_bounds);
context->cull_rect = previous_cull_rect;
context->mutators_stack.Pop();
}
#if defined(OS_FUCHSIA)
void TransformLayer::UpdateScene(SceneUpdateContext& context) {
FML_DCHECK(needs_system_composite());
SceneUpdateContext::Transform transform(context, transform_);
UpdateSceneChildren(context);
}
#endif
void TransformLayer::Paint(PaintContext& context) const {
TRACE_EVENT0("flutter", "TransformLayer::Paint");
FML_DCHECK(needs_painting());
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
context.internal_nodes_canvas->concat(transform_);
PaintChildren(context);
}
SkRect TransformLayer::MapRect(const SkRect& rect) {
SkRect dst_rect;
if (transform_.mapRect(&dst_rect, rect)) {
return dst_rect;
}
return rect;
}
void TransformLayer::MergeParentHole() {
auto* parent_layer = parent();
if (!parent_layer) {
return;
}
SkMatrix inverse_mat = transform_;
if (!inverse_mat.invert(&inverse_mat)) {
return;
}
for (const auto& [id, rect] : parent_layer->HoleRegions()) {
SkRect dst_rect;
if (inverse_mat.mapRect(&dst_rect, rect)) {
hole_regions_.try_emplace(id, dst_rect);
}
}
}
}