twonly-app-dependencies/lottie/lib/src/utils.dart
2026-07-15 19:04:30 +02:00

135 lines
3.4 KiB
Dart

import 'dart:math';
import 'package:flutter/rendering.dart';
import 'package:vector_math/vector_math_64.dart';
extension PaintExtension on Paint {
void setAlpha(int alpha) {
color = color.withAlpha(alpha);
}
}
extension PathExtension on Path {
void set(Path path) {
reset();
addPath(path, Offset.zero);
}
void offset(Offset offset) {
set(shift(offset));
}
}
extension Matrix4Extension on Matrix4 {
void preConcat(Matrix4 matrix) {
multiply(matrix);
}
void reset() {
setIdentity();
}
void set(Matrix4 matrix) {
matrix.copyInto(this);
}
Rect mapRect(Rect rect) {
return MatrixUtils.transformRect(this, rect);
}
/// Apply this matrix to the array of 2D points, and write the transformed points back into the
/// array
///
/// @param pts The array [x0, y0, x1, y1, ...] of points to transform.
void mapPoints(List<double> array) {
for (var i = 0; i < array.length; i += 2) {
final v = MatrixUtils.transformPoint(
this,
Offset(array[i], array[i + 1]),
);
array[i] = v.dx;
array[i + 1] = v.dy;
}
}
double getScale() {
var p0 = Vector3(0, 0, 0)..applyMatrix4(this);
var p1 = Vector3(1 / sqrt(2), 1 / sqrt(2), 0)..applyMatrix4(this);
var dx = p1.x - p0.x;
var dy = p1.y - p0.y;
return hypot(dx, dy).toDouble();
}
bool get hasZeroScaleAxis {
var p0 = Vector3(0, 0, 0)..applyMatrix4(this);
// Random numbers. The only way these should map to the same thing as 0,0 is if the scale is 0.
var p1 = Vector3(37394.729378, 39575.2343807, 0)..applyMatrix4(this);
return p0.x == p1.x || p0.y == p1.y;
}
/// Sets this matrix to map `p -> (p - sourceRect.topLeft) * scale`,
/// i.e. crop to [sourceRect] and scale it to fit [destinationSize].
void setSourceToDestinationScale(Rect sourceRect, Size destinationSize) {
var scaleX = destinationSize.width / sourceRect.width;
var scaleY = destinationSize.height / sourceRect.height;
setIdentity();
translateByDouble(
-sourceRect.left * scaleX,
-sourceRect.top * scaleY,
0,
1,
);
scaleByDouble(scaleX, scaleY, scaleX, 1);
}
}
extension CanvasExtension on Canvas {
/// Applies `destinationRect.topLeft + (p - sourceRect.topLeft) * scale`
/// to subsequent drawing, i.e. positions and crops/scales a source rect
/// into a destination rect.
void applySourceToDestinationTransform(
Rect sourceRect,
Rect destinationRect,
) {
var scaleX = destinationRect.width / sourceRect.width;
var scaleY = destinationRect.height / sourceRect.height;
translate(destinationRect.left, destinationRect.top);
scale(scaleX, scaleY);
translate(-sourceRect.left, -sourceRect.top);
}
}
extension OffsetExtension on Offset {
bool get isZero => dx == 0 && dy == 0;
}
num hypot(num x, num y) {
return sqrt(x * x + y * y);
}
extension IterableExtension<T> on Iterable<T> {
T? firstWhereOrNull(bool Function(T element) test) {
for (var element in this) {
if (test(element)) return element;
}
return null;
}
}
class ListEquality<E> {
const ListEquality();
bool equals(List<E>? list1, List<E>? list2) {
if (identical(list1, list2)) return true;
if (list1 == null || list2 == null) return false;
var length = list1.length;
if (length != list2.length) return false;
for (var i = 0; i < length; i++) {
if (list1[i] != list2[i]) return false;
}
return true;
}
}