blob: ba8759d46fec09777bc41b752b9cffd3e9a5abc7 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:typed_data';
import 'package:ui/ui.dart' as ui;
import '../dom.dart';
import '../util.dart';
import '../vector_math.dart';
import 'surface.dart';
/// A surface that transforms its children using CSS transform.
class PersistedTransform extends PersistedContainerSurface
implements ui.TransformEngineLayer {
PersistedTransform(PersistedTransform? super.oldLayer, this._matrixStorage);
/// The storage representing the transform of this surface.
final Float32List _matrixStorage;
/// The matrix representing the transform of this surface.
Matrix4 get matrix4 => _matrix4 ??= Matrix4.fromFloat32List(_matrixStorage);
Matrix4? _matrix4;
@override
void recomputeTransformAndClip() {
transform = parent!.transform!.multiplied(matrix4);
projectedClip = null;
}
/// Cached inverse of transform on this node. Unlike [transform], this
/// Matrix only contains local transform (not chain multiplied since root).
Matrix4? _localTransformInverse;
@override
Matrix4? get localTransformInverse {
_localTransformInverse ??= Matrix4.tryInvert(matrix4);
return _localTransformInverse;
}
@override
DomElement createElement() {
final DomElement element = domDocument.createElement('flt-transform');
setElementStyle(element, 'position', 'absolute');
setElementStyle(element, 'transform-origin', '0 0 0');
return element;
}
@override
void apply() {
rootElement!.style.transform = float64ListToCssTransform(_matrixStorage);
}
@override
void update(PersistedTransform oldSurface) {
super.update(oldSurface);
if (identical(oldSurface._matrixStorage, _matrixStorage)) {
// The matrix storage is identical, so we can copy the matrices from the
// old surface to avoid recomputing them.
_matrix4 = oldSurface._matrix4;
_localTransformInverse = oldSurface._localTransformInverse;
return;
}
bool matrixChanged = false;
for (int i = 0; i < _matrixStorage.length; i++) {
if (_matrixStorage[i] != oldSurface._matrixStorage[i]) {
matrixChanged = true;
break;
}
}
if (matrixChanged) {
apply();
} else {
// The matrix storage hasn't changed, so we can copy the matrices from the
// old surface to avoid recomputing them.
_matrix4 = oldSurface._matrix4;
_localTransformInverse = oldSurface._localTransformInverse;
}
}
}