Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
fe0032a6c2 | |||
b0bc35196e | |||
0600c44384 | |||
8a9ef53c63 | |||
6ffeaa603f | |||
08e629adaa | |||
bf3118b4cf | |||
434ae88aa8 | |||
6b752d829c | |||
124ba6997b | |||
fdc4018f57 | |||
b61ea14116 |
7
.github/workflows/publish-on-pub.yaml
vendored
@ -12,18 +12,17 @@ jobs:
|
||||
with:
|
||||
channel: 'stable'
|
||||
- run: flutter pub get
|
||||
- run: flutter pub run tool/publish/comment_dependency_overrides.dart
|
||||
- run: flutter pub get
|
||||
- run: flutter pub run tool/publish/check_version.dart ${GITHUB_REF}
|
||||
- name: Setup credentials
|
||||
run: |
|
||||
cat <<EOF > $PUB_CACHE/credentials.json
|
||||
mkdir -p $XDG_CONFIG_HOME/dart
|
||||
cat <<EOF > $XDG_CONFIG_HOME/dart/pub-credentials.json
|
||||
{
|
||||
"accessToken":"${{ secrets.OAUTH_ACCESS_TOKEN }}",
|
||||
"refreshToken":"${{ secrets.OAUTH_REFRESH_TOKEN }}",
|
||||
"tokenEndpoint":"https://accounts.google.com/o/oauth2/token",
|
||||
"scopes": [ "openid", "https://www.googleapis.com/auth/userinfo.email" ],
|
||||
"expiration": 1580681402856
|
||||
"expiration": 1691492965565
|
||||
}
|
||||
EOF
|
||||
- name: Publish package
|
||||
|
12
CHANGELOG.md
@ -1,3 +1,15 @@
|
||||
## 2.6.0
|
||||
- Accept `List<int>` instead of `Uint8List` in `LottieComposition.fromBytes`
|
||||
- Stroke line cap defaults to butt instead of square
|
||||
|
||||
## 2.5.0
|
||||
- Add layer-level opacity option to LottieOptions
|
||||
- Fix TextLayer opacity calculation
|
||||
|
||||
## 2.4.0
|
||||
- Require minimum Dart 3.0.0 and Flutter 3.10.0
|
||||
- Fix a parsing bug when the name property in RoundedCorner was null
|
||||
|
||||
## 2.3.2
|
||||
- Fix a bug when running on the web due to [bitwise operations difference](https://dart.dev/guides/language/numbers#bitwise-operations).
|
||||
|
||||
|
@ -8,26 +8,52 @@ linter:
|
||||
avoid_print: false
|
||||
|
||||
always_declare_return_types: true
|
||||
avoid_bool_literals_in_conditional_expressions: true
|
||||
avoid_double_and_int_checks: true
|
||||
avoid_dynamic_calls: true
|
||||
avoid_equals_and_hash_code_on_mutable_classes: true
|
||||
avoid_escaping_inner_quotes: true
|
||||
avoid_final_parameters: true
|
||||
avoid_function_literals_in_foreach_calls: true
|
||||
avoid_js_rounded_ints: true
|
||||
avoid_positional_boolean_parameters: true
|
||||
avoid_redundant_argument_values: true
|
||||
avoid_returning_null_for_future: true
|
||||
avoid_setters_without_getters: true
|
||||
avoid_type_to_string: true
|
||||
avoid_unused_constructor_parameters: true
|
||||
cancel_subscriptions: true
|
||||
cast_nullable_to_non_nullable: true
|
||||
close_sinks: true
|
||||
collection_methods_unrelated_type: true
|
||||
combinators_ordering: true
|
||||
conditional_uri_does_not_exist: true
|
||||
dangling_library_doc_comments: true
|
||||
deprecated_consistency: true
|
||||
implicit_reopen: true
|
||||
invalid_case_patterns: true
|
||||
leading_newlines_in_multiline_strings: true
|
||||
library_annotations: true
|
||||
no_adjacent_strings_in_list: true
|
||||
no_default_cases: true
|
||||
noop_primitive_operations: true
|
||||
omit_local_variable_types: true
|
||||
only_throw_errors: true
|
||||
prefer_if_elements_to_conditional_expressions: true
|
||||
prefer_relative_imports: true
|
||||
prefer_single_quotes: true
|
||||
sort_child_properties_last: true
|
||||
sort_pub_dependencies: true
|
||||
test_types_in_equals: true
|
||||
unawaited_futures: true
|
||||
unnecessary_breaks: true
|
||||
unnecessary_library_directive: true
|
||||
unnecessary_parenthesis: true
|
||||
unnecessary_statements: true
|
||||
unnecessary_to_list_in_spreads: true
|
||||
unsafe_html: true
|
||||
use_enums: true
|
||||
use_if_null_to_convert_nulls_to_bools: true
|
||||
use_named_constants: true
|
||||
use_raw_strings: true
|
||||
use_super_parameters: true
|
||||
|
1
example/assets/Tests/1669133489622.json
Normal file
5855
example/assets/Tests/DefaultLineJoinCap.json
Normal file
16284
example/assets/Tests/issue_288.json
Normal file
1
example/assets/Tests/opacity_layers.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.1.20","fr":30,"ip":0,"op":100,"w":600,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"test Outlines","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":0,"s":[100],"e":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":30,"s":[0],"e":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":50,"s":[0],"e":[100]},{"t":80}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,200,0],"ix":2},"a":{"a":0,"k":[400,300,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-66.274],[66.274,0],[0,66.274],[-66.274,0]],"o":[[0,66.274],[-66.274,0],[0,-66.274],[66.274,0]],"v":[[120,0],[0,120],[-120,0],[0,-120]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[488,300],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-66.274],[66.274,0],[0,66.274],[-66.274,0]],"o":[[0,66.274],[-66.274,0],[0,-66.274],[66.274,0]],"v":[[120,0],[0,120],[-120,0],[0,-120]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40800000359,0.40800000359,0.40800000359,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[312,300],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":100,"st":0,"bm":0}],"markers":[]}
|
1
example/assets/Tests/text_with_parent_alpha.json
Normal file
130
example/lib/examples/draw_cache.dart
Normal file
@ -0,0 +1,130 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/material.dart' hide Image;
|
||||
import 'package:flutter/material.dart' as material;
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
/// This example shows how to cache the animation as a List<Image>.
|
||||
/// After the initial cache of each frame, drawing the animation is almost free
|
||||
/// in term of CPU usage.
|
||||
/// The animation will run at a specific framerate (not FrameRate.max) and specific size
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Pre-load the animation for simplicity in this example
|
||||
var animation = await AssetLottie('assets/AndroidWave.json').load();
|
||||
|
||||
// Pick a specific size for our cache.
|
||||
// In a real app, we may want to defer choosing the size after an initial
|
||||
// Layout (ie. using LayoutBuilder)
|
||||
var cachedAnimation = CachedLottie(const Size(150, 200), animation);
|
||||
runApp(_Example(
|
||||
lottie: cachedAnimation,
|
||||
));
|
||||
}
|
||||
|
||||
class _Example extends StatelessWidget {
|
||||
final CachedLottie lottie;
|
||||
|
||||
const _Example({required this.lottie});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Cache'),
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
for (var i = 0; i < 20; i++)
|
||||
Stack(
|
||||
children: [
|
||||
for (var j = 0; j < 50; j++)
|
||||
Transform.translate(
|
||||
offset: Offset(j.toDouble() * 20, 0),
|
||||
child: CachedLottiePlayer(
|
||||
lottie: lottie,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CachedLottie {
|
||||
final Size size;
|
||||
final LottieComposition composition;
|
||||
final List<Image?> images;
|
||||
late final _drawable = LottieDrawable(composition);
|
||||
|
||||
CachedLottie(this.size, this.composition)
|
||||
: images = List.filled(composition.durationFrames.ceil(), null);
|
||||
|
||||
Duration get duration => composition.duration;
|
||||
|
||||
Image imageAt(BuildContext context, double progress) {
|
||||
var index = (images.length * progress).round() % images.length;
|
||||
return images[index] ??= _takeImage(context, progress);
|
||||
}
|
||||
|
||||
Image _takeImage(BuildContext context, double progress) {
|
||||
var recorder = PictureRecorder();
|
||||
var canvas = Canvas(recorder);
|
||||
|
||||
var devicePixelRatio = View.of(context).devicePixelRatio;
|
||||
|
||||
_drawable
|
||||
..setProgress(progress)
|
||||
..draw(canvas, Offset.zero & (size * devicePixelRatio));
|
||||
var picture = recorder.endRecording();
|
||||
return picture.toImageSync((size.width * devicePixelRatio).round(),
|
||||
(size.height * devicePixelRatio).round());
|
||||
}
|
||||
}
|
||||
|
||||
class CachedLottiePlayer extends StatefulWidget {
|
||||
final CachedLottie lottie;
|
||||
final AnimationController? controller;
|
||||
|
||||
const CachedLottiePlayer({
|
||||
super.key,
|
||||
required this.lottie,
|
||||
this.controller,
|
||||
});
|
||||
|
||||
@override
|
||||
State<CachedLottiePlayer> createState() => _CachedLottiePlayerState();
|
||||
}
|
||||
|
||||
class _CachedLottiePlayerState extends State<CachedLottiePlayer>
|
||||
with TickerProviderStateMixin {
|
||||
late final AnimationController _autoController =
|
||||
AnimationController(vsync: this, duration: widget.lottie.duration)
|
||||
..repeat();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var controller = widget.controller ?? _autoController;
|
||||
return AnimatedBuilder(
|
||||
animation: controller,
|
||||
builder: (context, _) {
|
||||
var image = widget.lottie.imageAt(context, controller.value);
|
||||
return material.RawImage(
|
||||
image: image,
|
||||
width: widget.lottie.size.width,
|
||||
height: widget.lottie.size.height,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_autoController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
@ -16,8 +16,8 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
|
||||
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
|
||||
|
||||
COCOAPODS: 1.12.0
|
||||
COCOAPODS: 1.12.1
|
||||
|
@ -5,10 +5,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d
|
||||
sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.6"
|
||||
version: "3.3.7"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -61,10 +61,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
version: "3.0.3"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -77,18 +77,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978
|
||||
sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "2.0.2"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -106,10 +98,10 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c
|
||||
sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.0.2"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -127,10 +119,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482"
|
||||
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.5"
|
||||
version: "1.1.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -151,25 +143,25 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593"
|
||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.1.1"
|
||||
logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logging
|
||||
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "1.2.0"
|
||||
lottie:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "2.3.2"
|
||||
version: "2.6.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -206,50 +198,50 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4
|
||||
sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.14"
|
||||
version: "2.0.15"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7"
|
||||
sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.24"
|
||||
version: "2.1.0"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "818b2dc38b0f178e0ea3f7cf3b28146faab11375985d815942a68eee11c2d0f7"
|
||||
sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
version: "2.3.0"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
|
||||
sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.10"
|
||||
version: "2.2.0"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
|
||||
sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.6"
|
||||
version: "2.1.0"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130
|
||||
sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
version: "2.2.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -262,26 +254,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc"
|
||||
sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.1.5"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: c3120a968135aead39699267f4c74bc9a08e4e909e86bc1b0af5bfd78691123c
|
||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.7.2"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
version: "3.7.3"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -339,10 +323,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.3.2"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -355,18 +339,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46
|
||||
sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
version: "5.0.6"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1
|
||||
sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
sdks:
|
||||
dart: ">=3.0.0-0 <4.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.10.0"
|
||||
|
@ -3,7 +3,7 @@ description: A sample app for the Lottie player
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ">=2.18.0 <3.0.0"
|
||||
sdk: "^3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
@ -10,7 +10,7 @@ export 'src/options.dart' show LottieOptions;
|
||||
export 'src/providers/asset_provider.dart' show AssetLottie;
|
||||
export 'src/providers/file_provider.dart' show FileLottie;
|
||||
export 'src/providers/load_image.dart' show LottieImageProviderFactory;
|
||||
export 'src/providers/lottie_provider.dart' show LottieProvider, LottieCache;
|
||||
export 'src/providers/lottie_provider.dart' show LottieCache, LottieProvider;
|
||||
export 'src/providers/memory_provider.dart' show MemoryLottie;
|
||||
export 'src/providers/network_provider.dart' show NetworkLottie;
|
||||
export 'src/raw_lottie.dart' show RawLottie;
|
||||
|
@ -144,7 +144,7 @@ abstract class BaseStrokeContent
|
||||
}
|
||||
var alpha =
|
||||
((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round();
|
||||
paint.setAlpha(alpha.clamp(0, 255).toInt());
|
||||
paint.setAlpha(alpha.clamp(0, 255));
|
||||
paint.strokeWidth = _widthAnimation.value * parentMatrix.getScale();
|
||||
if (paint.strokeWidth <= 0) {
|
||||
// Android draws a hairline stroke for 0, After Effects doesn't.
|
||||
|
@ -58,12 +58,14 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
|
||||
lottieDrawable,
|
||||
layer,
|
||||
shapeGroup.name,
|
||||
shapeGroup.hidden,
|
||||
contentsFromModels(lottieDrawable, layer, shapeGroup.items),
|
||||
findTransform(shapeGroup.items));
|
||||
findTransform(shapeGroup.items),
|
||||
hidden: shapeGroup.hidden);
|
||||
|
||||
ContentGroup.copy(this._lottieDrawable, BaseLayer layer, this.name,
|
||||
this._hidden, this._contents, AnimatableTransform? transform) {
|
||||
this._contents, AnimatableTransform? transform,
|
||||
{required bool hidden})
|
||||
: _hidden = hidden {
|
||||
if (transform != null) {
|
||||
_transformAnimation = transform.createAnimation()
|
||||
..addAnimationsToLayer(layer)
|
||||
|
@ -89,7 +89,7 @@ class FillContent implements DrawingContent, KeyPathElementContent {
|
||||
_paint.color = _colorAnimation.value;
|
||||
var alpha =
|
||||
((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round();
|
||||
_paint.setAlpha(alpha.clamp(0, 255).toInt());
|
||||
_paint.setAlpha(alpha.clamp(0, 255));
|
||||
if (lottieDrawable.antiAliasingSuggested) {
|
||||
_paint.isAntiAlias = true;
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
|
||||
var alpha =
|
||||
((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round();
|
||||
_paint.setAlpha(alpha.clamp(0, 255).toInt());
|
||||
_paint.setAlpha(alpha.clamp(0, 255));
|
||||
if (lottieDrawable.antiAliasingSuggested) {
|
||||
_paint.isAntiAlias = true;
|
||||
}
|
||||
@ -175,8 +175,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
var gradientColor = _colorAnimation.value;
|
||||
var colors = _applyDynamicColorsIfNeeded(gradientColor.colors);
|
||||
var positions = gradientColor.positions;
|
||||
gradient = Gradient.linear(
|
||||
startPoint, endPoint, colors, positions, TileMode.clamp);
|
||||
gradient = Gradient.linear(startPoint, endPoint, colors, positions);
|
||||
_linearGradientCache[gradientHash] = gradient;
|
||||
return gradient;
|
||||
}
|
||||
@ -200,8 +199,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
|
||||
if (radius <= 0) {
|
||||
radius = 0.001;
|
||||
}
|
||||
gradient =
|
||||
Gradient.radial(startPoint, radius, colors, positions, TileMode.clamp);
|
||||
gradient = Gradient.radial(startPoint, radius, colors, positions);
|
||||
_radialGradientCache[gradientHash] = gradient;
|
||||
return gradient;
|
||||
}
|
||||
|
@ -50,19 +50,14 @@ class MergePathsContent implements PathContent, GreedyContent {
|
||||
switch (_mergePaths.mode) {
|
||||
case MergePathsMode.merge:
|
||||
_addPaths();
|
||||
break;
|
||||
case MergePathsMode.add:
|
||||
_opFirstPathWithRest(PathOperation.union);
|
||||
break;
|
||||
case MergePathsMode.substract:
|
||||
_opFirstPathWithRest(PathOperation.reverseDifference);
|
||||
break;
|
||||
case MergePathsMode.intersect:
|
||||
_opFirstPathWithRest(PathOperation.intersect);
|
||||
break;
|
||||
case MergePathsMode.excludeIntersections:
|
||||
_opFirstPathWithRest(PathOperation.xor);
|
||||
break;
|
||||
}
|
||||
|
||||
return _path;
|
||||
|
@ -108,10 +108,8 @@ class PolystarContent implements PathContent, KeyPathElementContent {
|
||||
switch (_polystarShape.type) {
|
||||
case PolystarShapeType.star:
|
||||
_createStarPath();
|
||||
break;
|
||||
case PolystarShapeType.polygon:
|
||||
_createPolygonPath();
|
||||
break;
|
||||
}
|
||||
|
||||
_path.close();
|
||||
@ -253,7 +251,7 @@ class PolystarContent implements PathContent, KeyPathElementContent {
|
||||
_path.moveTo(x, y);
|
||||
currentAngle += anglePerPoint;
|
||||
|
||||
var numPoints = points.ceil().toDouble();
|
||||
var numPoints = points.toDouble();
|
||||
for (var i = 0; i < numPoints; i++) {
|
||||
previousX = x;
|
||||
previousY = y;
|
||||
|
@ -79,7 +79,8 @@ class RepeaterContent
|
||||
newContents = newContents.reversed.toList();
|
||||
|
||||
_contentGroup = ContentGroup.copy(
|
||||
lottieDrawable, layer, 'Repeater', _repeater.hidden, newContents, null);
|
||||
lottieDrawable, layer, 'Repeater', newContents, null,
|
||||
hidden: _repeater.hidden);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -216,7 +216,7 @@ class RoundedCornersContent implements ShapeModifierContent {
|
||||
this.shapeData = shapeData =
|
||||
ShapeData(newCurves, initialPoint: Offset.zero, closed: false);
|
||||
}
|
||||
shapeData.setClosed(isClosed);
|
||||
shapeData.isClosed = isClosed;
|
||||
return shapeData;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ class LottieComposition {
|
||||
name: name, imageProviderFactory: imageProviderFactory);
|
||||
}
|
||||
|
||||
static Future<LottieComposition> fromBytes(Uint8List bytes,
|
||||
static Future<LottieComposition> fromBytes(List<int> bytes,
|
||||
{String? name, LottieImageProviderFactory? imageProviderFactory}) async {
|
||||
Archive? archive;
|
||||
if (bytes[0] == 0x50 && bytes[1] == 0x4B) {
|
||||
|
@ -302,6 +302,7 @@ class Lottie extends StatefulWidget {
|
||||
|
||||
/// Some options to enable/disable some feature of Lottie
|
||||
/// - enableMergePaths: Enable merge path support
|
||||
/// - enableApplyingOpacityToLayers: Enable layer-level opacity
|
||||
final LottieOptions? options;
|
||||
|
||||
/// Indicate to automatically add a `RepaintBoundary` widget around the animation.
|
||||
|
@ -219,6 +219,7 @@ class LottieBuilder extends StatefulWidget {
|
||||
|
||||
/// Some options to enable/disable some feature of Lottie
|
||||
/// - enableMergePaths: Enable merge path support
|
||||
/// - enableApplyingOpacityToLayers: Enable layer-level opacity
|
||||
final LottieOptions? options;
|
||||
|
||||
/// A builder function responsible for creating the widget that represents
|
||||
|
@ -5,12 +5,12 @@ import '../cubic_curve_data.dart';
|
||||
class ShapeData {
|
||||
final List<CubicCurveData> curves;
|
||||
Offset _initialPoint;
|
||||
bool _closed;
|
||||
bool isClosed;
|
||||
|
||||
ShapeData(List<CubicCurveData> curves, {Offset? initialPoint, bool? closed})
|
||||
: curves = curves.toList(),
|
||||
_initialPoint = initialPoint ?? Offset.zero,
|
||||
_closed = closed ?? false;
|
||||
isClosed = closed ?? false;
|
||||
|
||||
ShapeData.empty() : this([]);
|
||||
|
||||
@ -22,17 +22,9 @@ class ShapeData {
|
||||
return _initialPoint;
|
||||
}
|
||||
|
||||
void setClosed(bool closed) {
|
||||
_closed = closed;
|
||||
}
|
||||
|
||||
bool get isClosed {
|
||||
return _closed;
|
||||
}
|
||||
|
||||
void interpolateBetween(
|
||||
ShapeData shapeData1, ShapeData shapeData2, double percentage) {
|
||||
_closed = shapeData1.isClosed || shapeData2.isClosed;
|
||||
isClosed = shapeData1.isClosed || shapeData2.isClosed;
|
||||
|
||||
if (shapeData1.curves.length != shapeData2.curves.length) {
|
||||
// TODO(xha): decide what to do? We don't have access to the LottieDrawble
|
||||
@ -86,7 +78,7 @@ class ShapeData {
|
||||
String toString() {
|
||||
return 'ShapeData{'
|
||||
'numCurves=${curves.length}'
|
||||
'closed=$_closed'
|
||||
'closed=$isClosed'
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ ui.StrokeCap lineCapTypeToPaintCap(LineCapType? cap) {
|
||||
return ui.StrokeCap.round;
|
||||
case LineCapType.unknown:
|
||||
case null:
|
||||
return ui.StrokeCap.square;
|
||||
return ui.StrokeCap.butt;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
enum Justification { leftAlign, rightAlign, center }
|
||||
|
||||
@immutable
|
||||
class DocumentData {
|
||||
final String text;
|
||||
final String? fontName;
|
||||
@ -19,7 +21,7 @@ class DocumentData {
|
||||
final Offset? boxPosition;
|
||||
final Offset? boxSize;
|
||||
|
||||
DocumentData({
|
||||
const DocumentData({
|
||||
required this.text,
|
||||
this.fontName,
|
||||
required this.size,
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'content/shape_group.dart';
|
||||
|
||||
@immutable
|
||||
class FontCharacter {
|
||||
static int hashFor(String character, String fontFamily, String style) {
|
||||
var result = character.hashCode;
|
||||
@ -15,7 +17,7 @@ class FontCharacter {
|
||||
final String style;
|
||||
final String fontFamily;
|
||||
|
||||
FontCharacter(
|
||||
const FontCharacter(
|
||||
{required this.shapes,
|
||||
required this.character,
|
||||
required this.size,
|
||||
|
@ -363,7 +363,6 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
_contentPaint.setAlpha(255);
|
||||
canvas.drawRect(bounds, _contentPaint);
|
||||
}
|
||||
break;
|
||||
case MaskMode.maskModeAdd:
|
||||
if (mask.isInverted) {
|
||||
_applyInvertedAddMask(
|
||||
@ -372,7 +371,6 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
_applyAddMask(
|
||||
canvas, matrix, mask, maskAnimation, opacityAnimation);
|
||||
}
|
||||
break;
|
||||
case MaskMode.maskModeSubstract:
|
||||
if (i == 0) {
|
||||
_contentPaint.color = const ui.Color(0xFF000000);
|
||||
@ -385,7 +383,6 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
_applySubtractMask(
|
||||
canvas, matrix, mask, maskAnimation, opacityAnimation);
|
||||
}
|
||||
break;
|
||||
case MaskMode.maskModeIntersect:
|
||||
if (mask.isInverted) {
|
||||
_applyInvertedIntersectMask(
|
||||
@ -394,7 +391,6 @@ abstract class BaseLayer implements DrawingContent, KeyPathElement {
|
||||
_applyIntersectMask(
|
||||
canvas, bounds, matrix, mask, maskAnimation, opacityAnimation);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
L.beginSection('Layer#restoreLayer');
|
||||
|
@ -50,7 +50,6 @@ class CompositionLayer extends BaseLayer {
|
||||
case MatteType.add:
|
||||
case MatteType.invert:
|
||||
mattedLayer = layer;
|
||||
break;
|
||||
case MatteType.luma:
|
||||
case MatteType.lumaInverted:
|
||||
case MatteType.none:
|
||||
|
@ -100,7 +100,7 @@ class TextLayer extends BaseLayer {
|
||||
canvas.save();
|
||||
canvas.transform(parentMatrix.storage);
|
||||
|
||||
_configurePaint(documentData, parentMatrix);
|
||||
_configurePaint(documentData, parentAlpha);
|
||||
|
||||
if (lottieDrawable.useTextGlyphs) {
|
||||
_drawTextWithGlyphs(documentData, parentMatrix, font, canvas);
|
||||
@ -111,7 +111,7 @@ class TextLayer extends BaseLayer {
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _configurePaint(DocumentData documentData, Matrix4 parentMatrix) {
|
||||
void _configurePaint(DocumentData documentData, int parentAlpha) {
|
||||
Color fillPaintColor;
|
||||
if (_colorCallbackAnimation != null) {
|
||||
fillPaintColor = _colorCallbackAnimation!.value;
|
||||
@ -133,7 +133,7 @@ class TextLayer extends BaseLayer {
|
||||
_strokePaint.color = strokePaintColor.withAlpha(_strokePaint.color.alpha);
|
||||
|
||||
var opacity = transform.opacity?.value ?? 100;
|
||||
var alpha = (opacity * 255 / 100).round();
|
||||
var alpha = opacity * 255 / 100 * parentAlpha ~/ 255;
|
||||
_fillPaint.setAlpha(alpha);
|
||||
_strokePaint.setAlpha(alpha);
|
||||
|
||||
@ -195,8 +195,7 @@ class TextLayer extends BaseLayer {
|
||||
void _drawGlyphTextLine(Characters text, DocumentData documentData, Font font,
|
||||
Canvas canvas, double parentScale, double fontScale, double tracking) {
|
||||
for (var c in text) {
|
||||
var characterHash =
|
||||
FontCharacter.hashFor(c.toString(), font.family, font.style);
|
||||
var characterHash = FontCharacter.hashFor(c, font.family, font.style);
|
||||
var character = _composition.characters[characterHash];
|
||||
if (character == null) {
|
||||
// Something is wrong. Potentially, they didn't export the text as a glyph.
|
||||
@ -269,14 +268,11 @@ class TextLayer extends BaseLayer {
|
||||
switch (documentData.justification) {
|
||||
case Justification.leftAlign:
|
||||
canvas.translate(lineStart, lineOffset);
|
||||
break;
|
||||
case Justification.rightAlign:
|
||||
canvas.translate(lineStart + boxWidth - lineWidth, lineOffset);
|
||||
break;
|
||||
case Justification.center:
|
||||
canvas.translate(
|
||||
lineStart + boxWidth / 2.0 - lineWidth / 2.0, lineOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,16 @@ class LottieOptions {
|
||||
/// instead of using merge paths.
|
||||
final bool enableMergePaths;
|
||||
|
||||
LottieOptions({bool? enableMergePaths})
|
||||
: enableMergePaths = enableMergePaths ?? false;
|
||||
/// Enable layer-level opacity.
|
||||
///
|
||||
/// Add the ability to render opacity on the layer level rather than the shape level.
|
||||
/// Opacity is normally applied directly to a shape. In cases where translucent shapes overlap,
|
||||
/// applying opacity to a layer will be more accurate at the expense of performance.
|
||||
/// Details: https://github.com/airbnb/lottie-android/issues/902
|
||||
final bool enableApplyingOpacityToLayers;
|
||||
|
||||
LottieOptions({
|
||||
this.enableMergePaths = false,
|
||||
this.enableApplyingOpacityToLayers = false,
|
||||
});
|
||||
}
|
||||
|
@ -47,7 +47,6 @@ class AnimatablePathValueParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
pathAnimation = AnimatablePathValueParser.parse(reader, composition);
|
||||
break;
|
||||
case 1:
|
||||
if (reader.peek() == Token.string) {
|
||||
hasExpressions = true;
|
||||
@ -55,7 +54,6 @@ class AnimatablePathValueParser {
|
||||
} else {
|
||||
xAnimation = AnimatableValueParser.parseFloat(reader, composition);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (reader.peek() == Token.string) {
|
||||
hasExpressions = true;
|
||||
@ -63,7 +61,6 @@ class AnimatablePathValueParser {
|
||||
} else {
|
||||
yAnimation = AnimatableValueParser.parseFloat(reader, composition);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -21,7 +21,6 @@ class AnimatableTextPropertiesParser {
|
||||
switch (reader.selectName(_propertiesNames)) {
|
||||
case 0:
|
||||
anim = _parseAnimatableTextProperties(reader, composition);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -47,16 +46,12 @@ class AnimatableTextPropertiesParser {
|
||||
switch (reader.selectName(_animatablePropertiesNames)) {
|
||||
case 0:
|
||||
color = AnimatableValueParser.parseColor(reader, composition);
|
||||
break;
|
||||
case 1:
|
||||
stroke = AnimatableValueParser.parseColor(reader, composition);
|
||||
break;
|
||||
case 2:
|
||||
strokeWidth = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
tracking = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -45,21 +45,17 @@ class AnimatableTransformParser {
|
||||
case 0:
|
||||
anchorPoint =
|
||||
AnimatablePathValueParser.parse(reader, composition);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
break;
|
||||
case 1:
|
||||
position =
|
||||
AnimatablePathValueParser.parseSplitPath(reader, composition);
|
||||
break;
|
||||
case 2:
|
||||
scale = AnimatableValueParser.parseScale(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
if (name == 3) {
|
||||
@ -79,33 +75,25 @@ class AnimatableTransformParser {
|
||||
rotation.keyframes.add(Keyframe(composition,
|
||||
startValue: 0.0,
|
||||
endValue: 0.0,
|
||||
interpolator: null,
|
||||
startFrame: 0.0,
|
||||
endFrame: composition.endFrame));
|
||||
} else if (rotation.keyframes.first.startValue == null) {
|
||||
rotation.keyframes.first = Keyframe(composition,
|
||||
startValue: 0.0,
|
||||
endValue: 0.0,
|
||||
interpolator: null,
|
||||
startFrame: 0.0,
|
||||
endFrame: composition.endFrame);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
opacity = AnimatableValueParser.parseInteger(reader, composition);
|
||||
break;
|
||||
case 6:
|
||||
startOpacity = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 7:
|
||||
endOpacity = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 8:
|
||||
skew = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 9:
|
||||
skewAngle = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -22,7 +22,6 @@ class BlurEffectParser {
|
||||
}
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -40,7 +39,6 @@ class BlurEffectParser {
|
||||
switch (reader.selectName(_innerBlurEffectNames)) {
|
||||
case 0:
|
||||
isCorrectType = reader.nextInt() == 0;
|
||||
break;
|
||||
case 1:
|
||||
if (isCorrectType) {
|
||||
blurEffect = BlurEffect(
|
||||
@ -48,7 +46,6 @@ class BlurEffectParser {
|
||||
} else {
|
||||
reader.skipValue();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -25,21 +25,16 @@ class CircleShapeParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
position =
|
||||
AnimatablePathValueParser.parseSplitPath(reader, composition);
|
||||
break;
|
||||
case 2:
|
||||
size = AnimatableValueParser.parsePoint(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
case 4:
|
||||
// "d" is 2 for normal and 3 for reversed.
|
||||
reversed = reader.nextInt() == 3;
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -37,7 +37,6 @@ class ContentModelParser {
|
||||
break typeLoop;
|
||||
case 1:
|
||||
d = reader.nextInt();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -52,46 +51,32 @@ class ContentModelParser {
|
||||
switch (type) {
|
||||
case 'gr':
|
||||
model = ShapeGroupParser.parse(reader, composition);
|
||||
break;
|
||||
case 'st':
|
||||
model = ShapeStrokeParser.parse(reader, composition);
|
||||
break;
|
||||
case 'gs':
|
||||
model = GradientStrokeParser.parse(reader, composition);
|
||||
break;
|
||||
case 'fl':
|
||||
model = ShapeFillParser.parse(reader, composition);
|
||||
break;
|
||||
case 'gf':
|
||||
model = GradientFillParser.parse(reader, composition);
|
||||
break;
|
||||
case 'tr':
|
||||
model = AnimatableTransformParser.parse(reader, composition);
|
||||
break;
|
||||
case 'sh':
|
||||
model = ShapePathParser.parse(reader, composition);
|
||||
break;
|
||||
case 'el':
|
||||
model = CircleShapeParser.parse(reader, composition, d);
|
||||
break;
|
||||
case 'rc':
|
||||
model = RectangleShapeParser.parse(reader, composition);
|
||||
break;
|
||||
case 'tm':
|
||||
model = ShapeTrimPathParser.parse(reader, composition);
|
||||
break;
|
||||
case 'sr':
|
||||
model = PolystarShapeParser.parse(reader, composition, d: d);
|
||||
break;
|
||||
case 'mm':
|
||||
model = MergePathsParser.parse(reader);
|
||||
break;
|
||||
case 'rp':
|
||||
model = RepeaterParser.parse(reader, composition);
|
||||
break;
|
||||
case 'rd':
|
||||
model = RoundedCornersParser.parse(reader, composition);
|
||||
break;
|
||||
default:
|
||||
composition.addWarning('Unknown shape type $type');
|
||||
}
|
||||
|
@ -39,13 +39,10 @@ DocumentData documentDataParser(JsonReader reader) {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
text = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
fontName = reader.nextString();
|
||||
break;
|
||||
case 2:
|
||||
size = reader.nextDouble();
|
||||
break;
|
||||
case 3:
|
||||
var justificationInt = reader.nextInt();
|
||||
if (justificationInt > Justification.center.index ||
|
||||
@ -54,38 +51,28 @@ DocumentData documentDataParser(JsonReader reader) {
|
||||
} else {
|
||||
justification = Justification.values[justificationInt];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
tracking = reader.nextInt();
|
||||
break;
|
||||
case 5:
|
||||
lineHeight = reader.nextDouble();
|
||||
break;
|
||||
case 6:
|
||||
baselineShift = reader.nextDouble();
|
||||
break;
|
||||
case 7:
|
||||
fillColor = JsonUtils.jsonToColor(reader);
|
||||
break;
|
||||
case 8:
|
||||
strokeColor = JsonUtils.jsonToColor(reader);
|
||||
break;
|
||||
case 9:
|
||||
strokeWidth = reader.nextDouble();
|
||||
break;
|
||||
case 10:
|
||||
strokeOverFill = reader.nextBoolean();
|
||||
break;
|
||||
case 11:
|
||||
reader.beginArray();
|
||||
boxPosition = Offset(reader.nextDouble(), reader.nextDouble());
|
||||
reader.endArray();
|
||||
break;
|
||||
case 12:
|
||||
reader.beginArray();
|
||||
boxSize = Offset(reader.nextDouble(), reader.nextDouble());
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -27,7 +27,6 @@ class DropShadowEffectParser {
|
||||
_maybeParseInnerEffect(reader, composition);
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -62,30 +61,23 @@ class DropShadowEffectParser {
|
||||
switch (reader.selectName(_innerEffectNames)) {
|
||||
case 0:
|
||||
currentEffectName = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
switch (currentEffectName) {
|
||||
case 'Shadow Color':
|
||||
_color = AnimatableValueParser.parseColor(reader, composition);
|
||||
break;
|
||||
case 'Opacity':
|
||||
_opacity = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 'Direction':
|
||||
_direction =
|
||||
AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 'Distance':
|
||||
_distance = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 'Softness':
|
||||
_radius = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -24,19 +24,14 @@ class FontCharacterParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
character = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
size = reader.nextDouble();
|
||||
break;
|
||||
case 2:
|
||||
width = reader.nextDouble();
|
||||
break;
|
||||
case 3:
|
||||
style = reader.nextString();
|
||||
break;
|
||||
case 4:
|
||||
fontFamily = reader.nextString();
|
||||
break;
|
||||
case 5:
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
@ -44,18 +39,18 @@ class FontCharacterParser {
|
||||
case 0:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
shapes.add(ContentModelParser.parse(reader, composition)!
|
||||
as ShapeGroup);
|
||||
if (ContentModelParser.parse(reader, composition)
|
||||
case var shape?) {
|
||||
shapes.add(shape as ShapeGroup);
|
||||
}
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -18,16 +18,12 @@ class FontParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
family = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 2:
|
||||
style = reader.nextString();
|
||||
break;
|
||||
case 3:
|
||||
ascent = reader.nextDouble();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -69,17 +69,13 @@ class GradientColorParser {
|
||||
case 0:
|
||||
// position
|
||||
positions[colorIndex] = value;
|
||||
break;
|
||||
case 1:
|
||||
r = (value * 255).round();
|
||||
break;
|
||||
case 2:
|
||||
g = (value * 255).round();
|
||||
break;
|
||||
case 3:
|
||||
var b = (value * 255).round();
|
||||
colors[colorIndex] = Color.fromARGB(255, r, g, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,6 @@ class GradientFillParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
var points = -1;
|
||||
reader.beginObject();
|
||||
@ -39,39 +38,30 @@ class GradientFillParser {
|
||||
switch (reader.selectName(_gradientNames)) {
|
||||
case 0:
|
||||
points = reader.nextInt();
|
||||
break;
|
||||
case 1:
|
||||
color = AnimatableValueParser.parseGradientColor(
|
||||
reader, composition, points);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
break;
|
||||
case 2:
|
||||
opacity = AnimatableValueParser.parseInteger(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
gradientType =
|
||||
reader.nextInt() == 1 ? GradientType.linear : GradientType.radial;
|
||||
break;
|
||||
case 4:
|
||||
startPoint = AnimatableValueParser.parsePoint(reader, composition);
|
||||
break;
|
||||
case 5:
|
||||
endPoint = AnimatableValueParser.parsePoint(reader, composition);
|
||||
break;
|
||||
case 6:
|
||||
fillType = reader.nextInt() == 1
|
||||
? PathFillType.nonZero
|
||||
: PathFillType.evenOdd;
|
||||
break;
|
||||
case 7:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -90,8 +80,6 @@ class GradientFillParser {
|
||||
opacity: opacity,
|
||||
startPoint: startPoint!,
|
||||
endPoint: endPoint!,
|
||||
highlightLength: null,
|
||||
highlightAngle: null,
|
||||
hidden: hidden,
|
||||
);
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ class GradientStrokeParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
var points = -1;
|
||||
reader.beginObject();
|
||||
@ -48,46 +47,34 @@ class GradientStrokeParser {
|
||||
switch (reader.selectName(_gradientNames)) {
|
||||
case 0:
|
||||
points = reader.nextInt();
|
||||
break;
|
||||
case 1:
|
||||
color = AnimatableValueParser.parseGradientColor(
|
||||
reader, composition, points);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
break;
|
||||
case 2:
|
||||
opacity = AnimatableValueParser.parseInteger(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
gradientType =
|
||||
reader.nextInt() == 1 ? GradientType.linear : GradientType.radial;
|
||||
break;
|
||||
case 4:
|
||||
startPoint = AnimatableValueParser.parsePoint(reader, composition);
|
||||
break;
|
||||
case 5:
|
||||
endPoint = AnimatableValueParser.parsePoint(reader, composition);
|
||||
break;
|
||||
case 6:
|
||||
width = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 7:
|
||||
capType = LineCapType.values[reader.nextInt() - 1];
|
||||
break;
|
||||
case 8:
|
||||
joinType = LineJoinType.values[reader.nextInt() - 1];
|
||||
break;
|
||||
case 9:
|
||||
miterLimit = reader.nextDouble();
|
||||
break;
|
||||
case 10:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
case 11:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
@ -98,10 +85,8 @@ class GradientStrokeParser {
|
||||
switch (reader.selectName(_dashPatternNames)) {
|
||||
case 0:
|
||||
n = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
val = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -121,7 +106,6 @@ class GradientStrokeParser {
|
||||
// If there is only 1 value then it is assumed to be equal parts on and off.
|
||||
lineDashPattern.add(lineDashPattern[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -35,8 +35,14 @@ class JsonUtils {
|
||||
return _jsonArrayToPoint(reader);
|
||||
case Token.beginObject:
|
||||
return _jsonObjectToPoint(reader);
|
||||
// ignore: no_default_cases
|
||||
default:
|
||||
case Token.nullToken:
|
||||
return Offset.zero;
|
||||
case Token.endArray:
|
||||
case Token.endObject:
|
||||
case Token.name:
|
||||
case Token.string:
|
||||
case Token.boolean:
|
||||
case Token.endDocument:
|
||||
throw Exception('Unknown point starts with ${reader.peek()}');
|
||||
}
|
||||
}
|
||||
@ -73,10 +79,8 @@ class JsonUtils {
|
||||
switch (reader.selectName(_pointNames)) {
|
||||
case 0:
|
||||
x = valueFromObject(reader);
|
||||
break;
|
||||
case 1:
|
||||
y = valueFromObject(reader);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -99,8 +103,14 @@ class JsonUtils {
|
||||
}
|
||||
reader.endArray();
|
||||
return val;
|
||||
// ignore: no_default_cases
|
||||
default:
|
||||
case Token.endArray:
|
||||
case Token.beginObject:
|
||||
case Token.endObject:
|
||||
case Token.name:
|
||||
case Token.string:
|
||||
case Token.boolean:
|
||||
case Token.nullToken:
|
||||
case Token.endDocument:
|
||||
throw Exception('Unknown value for token of type $token');
|
||||
}
|
||||
}
|
||||
|
@ -58,28 +58,20 @@ class KeyframeParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
startFrame = reader.nextDouble();
|
||||
break;
|
||||
case 1:
|
||||
startValue = valueParser(reader);
|
||||
break;
|
||||
case 2:
|
||||
endValue = valueParser(reader);
|
||||
break;
|
||||
case 3:
|
||||
cp1 = JsonUtils.jsonToPoint(reader);
|
||||
break;
|
||||
case 4:
|
||||
cp2 = JsonUtils.jsonToPoint(reader);
|
||||
break;
|
||||
case 5:
|
||||
hold = reader.nextInt() == 1;
|
||||
break;
|
||||
case 6:
|
||||
pathCp1 = JsonUtils.jsonToPoint(reader);
|
||||
break;
|
||||
case 7:
|
||||
pathCp2 = JsonUtils.jsonToPoint(reader);
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
@ -96,12 +88,13 @@ class KeyframeParser {
|
||||
interpolator = _linearInterpolator;
|
||||
}
|
||||
|
||||
var keyframe = Keyframe<T>(composition,
|
||||
startValue: startValue,
|
||||
endValue: endValue,
|
||||
interpolator: interpolator,
|
||||
startFrame: startFrame,
|
||||
endFrame: null);
|
||||
var keyframe = Keyframe<T>(
|
||||
composition,
|
||||
startValue: startValue,
|
||||
endValue: endValue,
|
||||
interpolator: interpolator,
|
||||
startFrame: startFrame,
|
||||
);
|
||||
keyframe.pathCp1 = pathCp1;
|
||||
keyframe.pathCp2 = pathCp2;
|
||||
return keyframe;
|
||||
@ -136,13 +129,10 @@ class KeyframeParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0: // t
|
||||
startFrame = reader.nextDouble();
|
||||
break;
|
||||
case 1: // s
|
||||
startValue = valueParser(reader);
|
||||
break;
|
||||
case 2: // e
|
||||
endValue = valueParser(reader);
|
||||
break;
|
||||
case 3: // o
|
||||
if (reader.peek() == Token.beginObject) {
|
||||
reader.beginObject();
|
||||
@ -166,7 +156,6 @@ class KeyframeParser {
|
||||
}
|
||||
reader.endArray();
|
||||
}
|
||||
break;
|
||||
case 1: // y
|
||||
if (reader.peek() == Token.number) {
|
||||
xCp1y = reader.nextDouble();
|
||||
@ -181,7 +170,6 @@ class KeyframeParser {
|
||||
}
|
||||
reader.endArray();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
@ -192,7 +180,6 @@ class KeyframeParser {
|
||||
} else {
|
||||
cp1 = JsonUtils.jsonToPoint(reader);
|
||||
}
|
||||
break;
|
||||
case 4: // i
|
||||
if (reader.peek() == Token.beginObject) {
|
||||
reader.beginObject();
|
||||
@ -216,7 +203,6 @@ class KeyframeParser {
|
||||
}
|
||||
reader.endArray();
|
||||
}
|
||||
break;
|
||||
case 1: // y
|
||||
if (reader.peek() == Token.number) {
|
||||
xCp2y = reader.nextDouble();
|
||||
@ -231,7 +217,6 @@ class KeyframeParser {
|
||||
}
|
||||
reader.endArray();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
@ -242,16 +227,12 @@ class KeyframeParser {
|
||||
} else {
|
||||
cp2 = JsonUtils.jsonToPoint(reader);
|
||||
}
|
||||
break;
|
||||
case 5: // h
|
||||
hold = reader.nextInt() == 1;
|
||||
break;
|
||||
case 6: // to
|
||||
pathCp1 = JsonUtils.jsonToPoint(reader);
|
||||
break;
|
||||
case 7: // ti
|
||||
pathCp2 = JsonUtils.jsonToPoint(reader);
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
|
@ -44,7 +44,6 @@ class KeyframesParser {
|
||||
keyframes.add(KeyframeParser.parse(reader, composition, valueParser,
|
||||
animated: false, multiDimensional: multiDimensional));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
|
@ -58,7 +58,6 @@ class LayerParser {
|
||||
id: -1,
|
||||
layerType: LayerType.preComp,
|
||||
parentId: -1,
|
||||
refId: null,
|
||||
masks: <Mask>[],
|
||||
transform: AnimatableTransform(),
|
||||
solidWidth: 0,
|
||||
@ -68,11 +67,8 @@ class LayerParser {
|
||||
startFrame: 0,
|
||||
preCompWidth: bounds.width,
|
||||
preCompHeight: bounds.height,
|
||||
text: null,
|
||||
textProperties: null,
|
||||
inOutKeyframes: <Keyframe<double>>[],
|
||||
matteType: MatteType.none,
|
||||
timeRemapping: null,
|
||||
isHidden: false);
|
||||
}
|
||||
|
||||
@ -117,13 +113,10 @@ class LayerParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
layerName = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
layerId = reader.nextInt();
|
||||
break;
|
||||
case 2:
|
||||
refId = reader.nextString();
|
||||
break;
|
||||
case 3:
|
||||
var layerTypeInt = reader.nextInt();
|
||||
if (layerTypeInt < LayerType.unknown.index) {
|
||||
@ -131,23 +124,17 @@ class LayerParser {
|
||||
} else {
|
||||
layerType = LayerType.unknown;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
parentId = reader.nextInt();
|
||||
break;
|
||||
case 5:
|
||||
solidWidth = reader.nextInt();
|
||||
break;
|
||||
case 6:
|
||||
solidHeight = reader.nextInt();
|
||||
break;
|
||||
case 7:
|
||||
solidColor = MiscUtils.parseColor(reader.nextString(),
|
||||
warningCallback: composition.addWarning);
|
||||
break;
|
||||
case 8:
|
||||
transform = AnimatableTransformParser.parse(reader, composition);
|
||||
break;
|
||||
case 9:
|
||||
var matteTypeIndex = reader.nextInt();
|
||||
if (matteTypeIndex >= MatteType.values.length) {
|
||||
@ -161,7 +148,6 @@ class LayerParser {
|
||||
composition.addWarning('Unsupported matte type: Luma Inverted');
|
||||
}
|
||||
composition.incrementMatteOrMaskCount(1);
|
||||
break;
|
||||
case 10:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
@ -169,7 +155,6 @@ class LayerParser {
|
||||
}
|
||||
composition.incrementMatteOrMaskCount(masks.length);
|
||||
reader.endArray();
|
||||
break;
|
||||
case 11:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
@ -179,7 +164,6 @@ class LayerParser {
|
||||
}
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
case 12:
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
@ -187,7 +171,6 @@ class LayerParser {
|
||||
case 0:
|
||||
text = AnimatableValueParser.parseDocumentData(
|
||||
reader, composition);
|
||||
break;
|
||||
case 1:
|
||||
reader.beginArray();
|
||||
if (reader.hasNext()) {
|
||||
@ -198,14 +181,12 @@ class LayerParser {
|
||||
reader.skipValue();
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
break;
|
||||
case 13:
|
||||
reader.beginArray();
|
||||
var effectNames = <String>[];
|
||||
@ -221,11 +202,9 @@ class LayerParser {
|
||||
dropShadowEffect =
|
||||
DropShadowEffectParser().parse(reader, composition);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
var effectName = reader.nextString();
|
||||
effectNames.add(effectName);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -238,34 +217,24 @@ class LayerParser {
|
||||
"Lottie doesn't support layer effects. If you are using them for "
|
||||
' fills, strokes, trim paths etc. then try adding them directly as contents '
|
||||
' in your shape. Found: $effectNames');
|
||||
break;
|
||||
case 14:
|
||||
timeStretch = reader.nextDouble();
|
||||
break;
|
||||
case 15:
|
||||
startFrame = reader.nextDouble();
|
||||
break;
|
||||
case 16:
|
||||
preCompWidth = reader.nextInt();
|
||||
break;
|
||||
case 17:
|
||||
preCompHeight = reader.nextInt();
|
||||
break;
|
||||
case 18:
|
||||
inFrame = reader.nextDouble();
|
||||
break;
|
||||
case 19:
|
||||
outFrame = reader.nextDouble();
|
||||
break;
|
||||
case 20:
|
||||
timeRemapping = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 21:
|
||||
cl = reader.nextString();
|
||||
break;
|
||||
case 22:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -277,11 +246,7 @@ class LayerParser {
|
||||
// Before the in frame
|
||||
if (inFrame > 0) {
|
||||
var preKeyframe = Keyframe<double>(composition,
|
||||
startValue: 0.0,
|
||||
endValue: 0.0,
|
||||
interpolator: null,
|
||||
startFrame: 0.0,
|
||||
endFrame: inFrame);
|
||||
startValue: 0.0, endValue: 0.0, startFrame: 0.0, endFrame: inFrame);
|
||||
inOutKeyframes.add(preKeyframe);
|
||||
}
|
||||
|
||||
@ -289,7 +254,6 @@ class LayerParser {
|
||||
var visibleKeyframe = Keyframe<double>(composition,
|
||||
startValue: 1.0,
|
||||
endValue: 1.0,
|
||||
interpolator: null,
|
||||
startFrame: inFrame,
|
||||
endFrame: outFrame);
|
||||
inOutKeyframes.add(visibleKeyframe);
|
||||
@ -297,7 +261,6 @@ class LayerParser {
|
||||
var outKeyframe = Keyframe<double>(composition,
|
||||
startValue: 0.0,
|
||||
endValue: 0.0,
|
||||
interpolator: null,
|
||||
startFrame: outFrame,
|
||||
endFrame: double.maxFinite);
|
||||
inOutKeyframes.add(outKeyframe);
|
||||
|
@ -33,20 +33,15 @@ class LottieCompositionParser {
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
parameters.bounds.width = reader.nextInt().round();
|
||||
break;
|
||||
parameters.bounds.width = reader.nextInt();
|
||||
case 1:
|
||||
parameters.bounds.height = reader.nextInt().round();
|
||||
break;
|
||||
parameters.bounds.height = reader.nextInt();
|
||||
case 2:
|
||||
parameters.startFrame = reader.nextDouble();
|
||||
break;
|
||||
case 3:
|
||||
parameters.endFrame = reader.nextDouble() - 0.01;
|
||||
break;
|
||||
case 4:
|
||||
parameters.frameRate = reader.nextDouble();
|
||||
break;
|
||||
case 5:
|
||||
var version = reader.nextString();
|
||||
var versions = version.split('.');
|
||||
@ -57,24 +52,18 @@ class LottieCompositionParser {
|
||||
majorVersion, minorVersion, patchVersion, 4, 4, 0)) {
|
||||
composition.addWarning('Lottie only supports bodymovin >= 4.4.0');
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
_parseLayers(
|
||||
reader, composition, parameters.layers, parameters.layerMap);
|
||||
break;
|
||||
case 7:
|
||||
_parseAssets(
|
||||
reader, composition, parameters.precomps, parameters.images);
|
||||
break;
|
||||
case 8:
|
||||
_parseFonts(reader, parameters.fonts);
|
||||
break;
|
||||
case 9:
|
||||
_parseChars(reader, composition, parameters.characters);
|
||||
break;
|
||||
case 10:
|
||||
_parseMarkers(reader, composition, parameters.markers);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -136,7 +125,6 @@ class LottieCompositionParser {
|
||||
switch (reader.selectName(_assetsNames)) {
|
||||
case 0:
|
||||
id = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
@ -145,19 +133,14 @@ class LottieCompositionParser {
|
||||
layers.add(layer);
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
case 2:
|
||||
width = reader.nextInt();
|
||||
break;
|
||||
case 3:
|
||||
height = reader.nextInt();
|
||||
break;
|
||||
case 4:
|
||||
imageFileName = reader.nextString();
|
||||
break;
|
||||
case 5:
|
||||
relativeFolder = reader.nextString();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -192,7 +175,6 @@ class LottieCompositionParser {
|
||||
fonts[font.name] = font;
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -226,13 +208,10 @@ class LottieCompositionParser {
|
||||
switch (reader.selectName(_markerNames)) {
|
||||
case 0:
|
||||
comment = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
frame = reader.nextDouble();
|
||||
break;
|
||||
case 2:
|
||||
durationFrames = reader.nextDouble();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -23,33 +23,25 @@ class MaskParser {
|
||||
switch (modeName) {
|
||||
case 'a':
|
||||
maskMode = MaskMode.maskModeAdd;
|
||||
break;
|
||||
case 's':
|
||||
maskMode = MaskMode.maskModeSubstract;
|
||||
break;
|
||||
case 'n':
|
||||
maskMode = MaskMode.maskModeNone;
|
||||
break;
|
||||
case 'i':
|
||||
composition.addWarning(
|
||||
'Animation contains intersect masks. They are not supported but will be treated like add masks.');
|
||||
maskMode = MaskMode.maskModeIntersect;
|
||||
break;
|
||||
default:
|
||||
composition.addWarning(
|
||||
'Unknown mask mode $modeName. Defaulting to Add.');
|
||||
maskMode = MaskMode.maskModeAdd;
|
||||
}
|
||||
break;
|
||||
case 'pt':
|
||||
maskPath = AnimatableValueParser.parseShapeData(reader, composition);
|
||||
break;
|
||||
case 'o':
|
||||
opacity = AnimatableValueParser.parseInteger(reader, composition);
|
||||
break;
|
||||
case 'inv':
|
||||
inverted = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
|
@ -16,13 +16,10 @@ class MergePathsParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
mode = MergePaths.modeForId(reader.nextInt());
|
||||
break;
|
||||
case 2:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -1,11 +1,10 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
|
||||
class Buffer {
|
||||
Buffer(this.buffer);
|
||||
|
||||
final Uint8List buffer;
|
||||
final List<int> buffer;
|
||||
int _start = 0, _size = 0;
|
||||
int get size => _size;
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'buffer.dart';
|
||||
import 'json_scope.dart';
|
||||
import 'json_utf8_reader.dart';
|
||||
@ -167,7 +166,7 @@ abstract class JsonReader {
|
||||
bool failOnUnknown = false;
|
||||
|
||||
/// Returns a new instance that reads UTF-8 encoded JSON from {@code source}.
|
||||
static JsonReader fromBytes(Uint8List source) {
|
||||
static JsonReader fromBytes(List<int> source) {
|
||||
return JsonUtf8Reader(Buffer(source));
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,6 @@ class JsonScope {
|
||||
..write('[')
|
||||
..write(pathIndices[i])
|
||||
..write(']');
|
||||
break;
|
||||
|
||||
case emptyObject:
|
||||
case danglingName:
|
||||
@ -52,7 +51,6 @@ class JsonScope {
|
||||
if (pathNames[i] != null) {
|
||||
result.write(pathNames[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case nonEmptyDocument:
|
||||
case emptyDocument:
|
||||
|
@ -200,7 +200,6 @@ class JsonUtf8Reader extends JsonReader {
|
||||
return _peeked = peekedEndArray;
|
||||
case $semicolon:
|
||||
_checkLenient();
|
||||
break;
|
||||
case $comma:
|
||||
break;
|
||||
default:
|
||||
@ -218,7 +217,6 @@ class JsonUtf8Reader extends JsonReader {
|
||||
return _peeked = peekedEndObject;
|
||||
case $semicolon:
|
||||
_checkLenient(); // fall-through
|
||||
break;
|
||||
case $comma:
|
||||
break;
|
||||
default:
|
||||
@ -262,7 +260,6 @@ class JsonUtf8Reader extends JsonReader {
|
||||
if (buffer.request(1) && buffer.getByte(0) == $greaterThan) {
|
||||
buffer.readByte(); // Consume '>'.
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw syntaxError("Expected ':'");
|
||||
}
|
||||
|
@ -31,41 +31,30 @@ class PolystarShapeParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
type = PolystarShapeType.forValue(reader.nextInt());
|
||||
break;
|
||||
case 2:
|
||||
points = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
position =
|
||||
AnimatablePathValueParser.parseSplitPath(reader, composition);
|
||||
break;
|
||||
case 4:
|
||||
rotation = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 5:
|
||||
outerRadius = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 6:
|
||||
outerRoundedness =
|
||||
AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 7:
|
||||
innerRadius = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 8:
|
||||
innerRoundedness =
|
||||
AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 9:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
case 10:
|
||||
// "d" is 2 for normal and 3 for reversed.
|
||||
reversed = reader.nextInt() == 3;
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -25,20 +25,15 @@ class RectangleShapeParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
position =
|
||||
AnimatablePathValueParser.parseSplitPath(reader, composition);
|
||||
break;
|
||||
case 2:
|
||||
size = AnimatableValueParser.parsePoint(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
roundedness = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 4:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
|
@ -23,19 +23,14 @@ class RepeaterParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
copies = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 2:
|
||||
offset = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
transform = AnimatableTransformParser.parse(reader, composition);
|
||||
break;
|
||||
case 4:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
|
@ -21,18 +21,15 @@ class RoundedCornersParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0: //nm
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1: // r
|
||||
cornerRadius = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 2: // hd
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
}
|
||||
|
||||
return hidden ? null : RoundedCorners(name!, cornerRadius!);
|
||||
return hidden ? null : RoundedCorners(name ?? '', cornerRadius!);
|
||||
}
|
||||
}
|
||||
|
@ -23,16 +23,12 @@ ShapeData shapeDataParser(JsonReader reader) {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
closed = reader.nextBoolean();
|
||||
break;
|
||||
case 1:
|
||||
pointsArray = JsonUtils.jsonToPoints(reader);
|
||||
break;
|
||||
case 2:
|
||||
inTangents = JsonUtils.jsonToPoints(reader);
|
||||
break;
|
||||
case 3:
|
||||
outTangents = JsonUtils.jsonToPoints(reader);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -51,7 +47,7 @@ ShapeData shapeDataParser(JsonReader reader) {
|
||||
|
||||
if (pointsArray.isEmpty) {
|
||||
return ShapeData(<CubicCurveData>[],
|
||||
initialPoint: const Offset(0, 0), closed: false);
|
||||
initialPoint: Offset.zero, closed: false);
|
||||
}
|
||||
|
||||
var length = pointsArray.length;
|
||||
|
@ -25,22 +25,16 @@ class ShapeFillParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
color = AnimatableValueParser.parseColor(reader, composition);
|
||||
break;
|
||||
case 2:
|
||||
opacity = AnimatableValueParser.parseInteger(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
fillEnabled = reader.nextBoolean();
|
||||
break;
|
||||
case 4:
|
||||
fillTypeInt = reader.nextInt();
|
||||
break;
|
||||
case 5:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
|
@ -18,10 +18,8 @@ class ShapeGroupParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
case 2:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
@ -31,7 +29,6 @@ class ShapeGroupParser {
|
||||
}
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
|
@ -20,16 +20,12 @@ class ShapePathParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
ind = reader.nextInt();
|
||||
break;
|
||||
case 2:
|
||||
shape = AnimatableValueParser.parseShapeData(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
|
@ -32,28 +32,20 @@ class ShapeStrokeParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
color = AnimatableValueParser.parseColor(reader, composition);
|
||||
break;
|
||||
case 2:
|
||||
width = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
opacity = AnimatableValueParser.parseInteger(reader, composition);
|
||||
break;
|
||||
case 4:
|
||||
capType = LineCapType.values[reader.nextInt() - 1];
|
||||
break;
|
||||
case 5:
|
||||
joinType = LineJoinType.values[reader.nextInt() - 1];
|
||||
break;
|
||||
case 6:
|
||||
miterLimit = reader.nextDouble();
|
||||
break;
|
||||
case 7:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
case 8:
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
@ -65,10 +57,8 @@ class ShapeStrokeParser {
|
||||
switch (reader.selectName(_dashPatternNames)) {
|
||||
case 0:
|
||||
n = reader.nextString();
|
||||
break;
|
||||
case 1:
|
||||
val = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
default:
|
||||
reader.skipName();
|
||||
reader.skipValue();
|
||||
@ -79,12 +69,10 @@ class ShapeStrokeParser {
|
||||
switch (n) {
|
||||
case 'o':
|
||||
offset = val;
|
||||
break;
|
||||
case 'd':
|
||||
case 'g':
|
||||
composition.hasDashPattern = true;
|
||||
lineDashPattern.add(val!);
|
||||
break;
|
||||
}
|
||||
}
|
||||
reader.endArray();
|
||||
@ -93,7 +81,6 @@ class ShapeStrokeParser {
|
||||
// If there is only 1 value then it is assumed to be equal parts on and off.
|
||||
lineDashPattern.add(lineDashPattern.first);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
|
@ -20,22 +20,16 @@ class ShapeTrimPathParser {
|
||||
switch (reader.selectName(_names)) {
|
||||
case 0:
|
||||
start = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 1:
|
||||
end = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 2:
|
||||
offset = AnimatableValueParser.parseFloat(reader, composition);
|
||||
break;
|
||||
case 3:
|
||||
name = reader.nextString();
|
||||
break;
|
||||
case 4:
|
||||
type = ShapeTrimPath.typeForId(reader.nextInt());
|
||||
break;
|
||||
case 5:
|
||||
hidden = reader.nextBoolean();
|
||||
break;
|
||||
default:
|
||||
reader.skipValue();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import '../lottie_image_asset.dart';
|
||||
import 'load_image.dart';
|
||||
import 'lottie_provider.dart';
|
||||
|
||||
@immutable
|
||||
class AssetLottie extends LottieProvider {
|
||||
AssetLottie(
|
||||
this.assetName, {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import '../composition.dart';
|
||||
import '../lottie_image_asset.dart';
|
||||
@ -6,6 +7,7 @@ import 'load_image.dart';
|
||||
import 'lottie_provider.dart';
|
||||
import 'provider_io.dart' if (dart.library.html) 'provider_web.dart' as io;
|
||||
|
||||
@immutable
|
||||
class FileLottie extends LottieProvider {
|
||||
FileLottie(this.file, {super.imageProviderFactory});
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import '../composition.dart';
|
||||
@ -7,6 +7,7 @@ import '../lottie_image_asset.dart';
|
||||
import 'load_image.dart';
|
||||
import 'lottie_provider.dart';
|
||||
|
||||
@immutable
|
||||
class MemoryLottie extends LottieProvider {
|
||||
MemoryLottie(this.bytes, {super.imageProviderFactory});
|
||||
|
||||
|
@ -8,6 +8,7 @@ import 'load_image.dart';
|
||||
import 'lottie_provider.dart';
|
||||
import 'provider_io.dart' if (dart.library.html) 'provider_web.dart' as network;
|
||||
|
||||
@immutable
|
||||
class NetworkLottie extends LottieProvider {
|
||||
NetworkLottie(this.url, {this.headers, super.imageProviderFactory});
|
||||
|
||||
|
@ -86,6 +86,7 @@ class RawLottie extends LeafRenderObjectWidget {
|
||||
composition: composition,
|
||||
delegates: delegates,
|
||||
enableMergePaths: options?.enableMergePaths,
|
||||
enableApplyingOpacityToLayers: options?.enableApplyingOpacityToLayers,
|
||||
progress: progress,
|
||||
frameRate: frameRate,
|
||||
width: width,
|
||||
@ -105,6 +106,7 @@ class RawLottie extends LeafRenderObjectWidget {
|
||||
frameRate: frameRate,
|
||||
delegates: delegates,
|
||||
enableMergePaths: options?.enableMergePaths,
|
||||
enableApplyingOpacityToLayers: options?.enableApplyingOpacityToLayers,
|
||||
filterQuality: filterQuality,
|
||||
)
|
||||
..width = width
|
||||
|
@ -13,6 +13,7 @@ class RenderLottie extends RenderBox {
|
||||
required LottieComposition? composition,
|
||||
LottieDelegates? delegates,
|
||||
bool? enableMergePaths,
|
||||
bool? enableApplyingOpacityToLayers,
|
||||
double progress = 0.0,
|
||||
FrameRate? frameRate,
|
||||
double? width,
|
||||
@ -26,6 +27,8 @@ class RenderLottie extends RenderBox {
|
||||
..setProgress(progress, frameRate: frameRate)
|
||||
..delegates = delegates
|
||||
..enableMergePaths = enableMergePaths ?? false
|
||||
..isApplyingOpacityToLayersEnabled =
|
||||
enableApplyingOpacityToLayers ?? false
|
||||
..filterQuality = filterQuality)
|
||||
: null,
|
||||
_width = width,
|
||||
@ -42,9 +45,11 @@ class RenderLottie extends RenderBox {
|
||||
required FrameRate? frameRate,
|
||||
required LottieDelegates? delegates,
|
||||
bool? enableMergePaths,
|
||||
bool? enableApplyingOpacityToLayers,
|
||||
FilterQuality? filterQuality}) {
|
||||
var drawable = _drawable;
|
||||
enableMergePaths ??= false;
|
||||
enableApplyingOpacityToLayers ??= false;
|
||||
|
||||
var needsLayout = false;
|
||||
var needsPaint = false;
|
||||
@ -71,6 +76,12 @@ class RenderLottie extends RenderBox {
|
||||
drawable.enableMergePaths = enableMergePaths;
|
||||
needsPaint = true;
|
||||
}
|
||||
if (enableApplyingOpacityToLayers !=
|
||||
drawable.isApplyingOpacityToLayersEnabled) {
|
||||
drawable.isApplyingOpacityToLayersEnabled =
|
||||
enableApplyingOpacityToLayers;
|
||||
needsPaint = true;
|
||||
}
|
||||
if (filterQuality != drawable.filterQuality) {
|
||||
drawable.filterQuality = filterQuality;
|
||||
needsPaint = true;
|
||||
@ -91,6 +102,7 @@ class RenderLottie extends RenderBox {
|
||||
/// aspect ratio.
|
||||
double? get width => _width;
|
||||
double? _width;
|
||||
|
||||
set width(double? value) {
|
||||
if (value == _width) {
|
||||
return;
|
||||
@ -105,6 +117,7 @@ class RenderLottie extends RenderBox {
|
||||
/// aspect ratio.
|
||||
double? get height => _height;
|
||||
double? _height;
|
||||
|
||||
set height(double? value) {
|
||||
if (value == _height) {
|
||||
return;
|
||||
@ -116,6 +129,7 @@ class RenderLottie extends RenderBox {
|
||||
/// How to inscribe the composition into the space allocated during layout.
|
||||
BoxFit? get fit => _fit;
|
||||
BoxFit? _fit;
|
||||
|
||||
set fit(BoxFit? value) {
|
||||
if (value == _fit) {
|
||||
return;
|
||||
@ -130,6 +144,7 @@ class RenderLottie extends RenderBox {
|
||||
/// not be null.
|
||||
AlignmentGeometry get alignment => _alignment;
|
||||
AlignmentGeometry _alignment;
|
||||
|
||||
set alignment(AlignmentGeometry value) {
|
||||
if (value == _alignment) {
|
||||
return;
|
||||
|
@ -1,189 +0,0 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class DebugPath extends Path {
|
||||
void _log(String methodName) {
|
||||
debugPrint('Path.$methodName');
|
||||
}
|
||||
|
||||
@override
|
||||
void addArc(Rect oval, double startAngle, double sweepAngle) {
|
||||
_log('addArc');
|
||||
super.addArc(oval, startAngle, sweepAngle);
|
||||
}
|
||||
|
||||
@override
|
||||
void addOval(Rect oval) {
|
||||
_log('addOval');
|
||||
super.addOval(oval);
|
||||
}
|
||||
|
||||
@override
|
||||
void addPath(Path path, Offset offset, {Float64List? matrix4}) {
|
||||
_log('addPath');
|
||||
super.addPath(path, offset, matrix4: matrix4);
|
||||
}
|
||||
|
||||
@override
|
||||
void addPolygon(List<Offset> points, bool close) {
|
||||
_log('addPolygon');
|
||||
super.addPolygon(points, close);
|
||||
}
|
||||
|
||||
@override
|
||||
void addRRect(RRect rrect) {
|
||||
_log('addRRect');
|
||||
super.addRRect(rrect);
|
||||
}
|
||||
|
||||
@override
|
||||
void addRect(Rect rect) {
|
||||
_log('addRect');
|
||||
super.addRect(rect);
|
||||
}
|
||||
|
||||
@override
|
||||
void arcTo(
|
||||
Rect rect, double startAngle, double sweepAngle, bool forceMoveTo) {
|
||||
_log('arcTo');
|
||||
super.arcTo(rect, startAngle, sweepAngle, forceMoveTo);
|
||||
}
|
||||
|
||||
@override
|
||||
void arcToPoint(Offset arcEnd,
|
||||
{Radius radius = Radius.zero,
|
||||
double rotation = 0.0,
|
||||
bool largeArc = false,
|
||||
bool clockwise = true}) {
|
||||
_log('arcToPoint');
|
||||
super.arcToPoint(arcEnd,
|
||||
radius: radius,
|
||||
rotation: rotation,
|
||||
largeArc: largeArc,
|
||||
clockwise: clockwise);
|
||||
}
|
||||
|
||||
@override
|
||||
void close() {
|
||||
_log('close');
|
||||
super.close();
|
||||
}
|
||||
|
||||
@override
|
||||
PathMetrics computeMetrics({bool forceClosed = false}) {
|
||||
_log('computeMetrics');
|
||||
return super.computeMetrics();
|
||||
}
|
||||
|
||||
@override
|
||||
void conicTo(double x1, double y1, double x2, double y2, double w) {
|
||||
_log('conicTo');
|
||||
super.conicTo(x1, y1, x2, y2, w);
|
||||
}
|
||||
|
||||
@override
|
||||
bool contains(Offset point) {
|
||||
_log('contains');
|
||||
return super.contains(point);
|
||||
}
|
||||
|
||||
@override
|
||||
void cubicTo(
|
||||
double x1, double y1, double x2, double y2, double x3, double y3) {
|
||||
_log('cubicTo');
|
||||
super.cubicTo(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
@override
|
||||
void extendWithPath(Path path, Offset offset, {Float64List? matrix4}) {
|
||||
_log('extendWithPath');
|
||||
super.extendWithPath(path, offset, matrix4: matrix4);
|
||||
}
|
||||
|
||||
@override
|
||||
Rect getBounds() {
|
||||
_log('getBounds');
|
||||
return super.getBounds();
|
||||
}
|
||||
|
||||
@override
|
||||
void lineTo(double x, double y) {
|
||||
_log('lineTo');
|
||||
super.lineTo(x, y);
|
||||
}
|
||||
|
||||
@override
|
||||
void moveTo(double x, double y) {
|
||||
_log('moveTo');
|
||||
super.moveTo(x, y);
|
||||
}
|
||||
|
||||
@override
|
||||
void quadraticBezierTo(double x1, double y1, double x2, double y2) {
|
||||
_log('quadraticBezierTo');
|
||||
super.quadraticBezierTo(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
@override
|
||||
void relativeArcToPoint(Offset arcEndDelta,
|
||||
{Radius radius = Radius.zero,
|
||||
double rotation = 0.0,
|
||||
bool largeArc = false,
|
||||
bool clockwise = true}) {
|
||||
_log('relativeArcToPoint');
|
||||
super.relativeArcToPoint(arcEndDelta,
|
||||
radius: radius,
|
||||
rotation: rotation,
|
||||
largeArc: largeArc,
|
||||
clockwise: clockwise);
|
||||
}
|
||||
|
||||
@override
|
||||
void relativeConicTo(double x1, double y1, double x2, double y2, double w) {
|
||||
_log('relativeConicTo');
|
||||
super.relativeConicTo(x1, y1, x2, y2, w);
|
||||
}
|
||||
|
||||
@override
|
||||
void relativeCubicTo(
|
||||
double x1, double y1, double x2, double y2, double x3, double y3) {
|
||||
_log('relativeCubicTo');
|
||||
super.relativeCubicTo(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
@override
|
||||
void relativeLineTo(double dx, double dy) {
|
||||
_log('relativeLineTo');
|
||||
super.relativeLineTo(dx, dy);
|
||||
}
|
||||
|
||||
@override
|
||||
void relativeMoveTo(double dx, double dy) {
|
||||
_log('relativeMoveTo');
|
||||
super.relativeMoveTo(dx, dy);
|
||||
}
|
||||
|
||||
@override
|
||||
void relativeQuadraticBezierTo(double x1, double y1, double x2, double y2) {
|
||||
_log('relativeQuadraticBezierTo');
|
||||
super.relativeQuadraticBezierTo(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
@override
|
||||
void reset() {
|
||||
_log('reset');
|
||||
super.reset();
|
||||
}
|
||||
|
||||
@override
|
||||
Path shift(Offset offset) {
|
||||
_log('shift');
|
||||
return super.shift(offset);
|
||||
}
|
||||
|
||||
@override
|
||||
Path transform(Float64List matrix4) {
|
||||
_log('transform');
|
||||
return super.transform(matrix4);
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ class GammaEvaluator {
|
||||
// IEC 61966-2-1:1999
|
||||
return linear <= 0.0031308
|
||||
? linear * 12.92
|
||||
: ((pow(linear, 1.0 / 2.4) * 1.055) - 0.055).toDouble();
|
||||
: ((pow(linear, 1.0 / 2.4) * 1.055) - 0.055);
|
||||
}
|
||||
|
||||
// Electro-optical conversion function for the sRGB color space
|
||||
|
@ -104,16 +104,13 @@ class Utils {
|
||||
newStart -= length;
|
||||
}
|
||||
|
||||
var tempPath =
|
||||
pathMeasure.extractPath(newStart, newEnd, startWithMoveTo: true);
|
||||
var tempPath = pathMeasure.extractPath(newStart, newEnd);
|
||||
|
||||
if (newEnd > length) {
|
||||
var tempPath2 =
|
||||
pathMeasure.extractPath(0, newEnd % length, startWithMoveTo: true);
|
||||
var tempPath2 = pathMeasure.extractPath(0, newEnd % length);
|
||||
tempPath.addPath(tempPath2, Offset.zero);
|
||||
} else if (newStart < 0) {
|
||||
var tempPath2 = pathMeasure.extractPath(length + newStart, length,
|
||||
startWithMoveTo: true);
|
||||
var tempPath2 = pathMeasure.extractPath(length + newStart, length);
|
||||
tempPath.addPath(tempPath2, Offset.zero);
|
||||
}
|
||||
path.set(tempPath);
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/painting.dart';
|
||||
|
||||
@immutable
|
||||
class DropShadow {
|
||||
final Color color;
|
||||
final double direction;
|
||||
|
64
pubspec.lock
@ -5,34 +5,34 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: a36ec4843dc30ea6bf652bf25e3448db6c5e8bcf4aa55f063a5d1dad216d8214
|
||||
sha256: "58826e40314219b223f4723dd4205845040161cdc2df3e6a1cdceed5d8165084"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "58.0.0"
|
||||
version: "63.0.0"
|
||||
analyzer:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: cc4242565347e98424ce9945c819c192ec0838cb9d1f6aa4a97cc96becbc5b27
|
||||
sha256: f85566ec7b3d25cbea60f7dd4f157c5025f2f19233ca4feeed33b616c78a26a3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.10.0"
|
||||
version: "6.1.0"
|
||||
archive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: archive
|
||||
sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d
|
||||
sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.6"
|
||||
version: "3.3.7"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440"
|
||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
version: "2.4.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -85,18 +85,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
version: "3.0.3"
|
||||
dart_style:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: "6d691edde054969f0e0f26abb1b30834b5138b963793e56f69d3a9a4435e6352"
|
||||
sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
version: "2.3.2"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -109,10 +109,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "7.0.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -122,10 +122,10 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c
|
||||
sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.0.2"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -135,10 +135,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -151,10 +151,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593"
|
||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.1.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -199,18 +199,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: c3120a968135aead39699267f4c74bc9a08e4e909e86bc1b0af5bfd78691123c
|
||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.7.2"
|
||||
version: "3.7.3"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17"
|
||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.1.4"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -268,10 +268,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.3.2"
|
||||
vector_math:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -284,18 +284,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
|
||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
version: "1.1.0"
|
||||
yaml:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370"
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.0.0-0 <4.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.10.0"
|
||||
|
@ -1,11 +1,11 @@
|
||||
name: lottie
|
||||
description: Render After Effects animations natively on Flutter. This package is a pure Dart implementation of a Lottie player.
|
||||
version: 2.3.2
|
||||
version: 2.6.0
|
||||
repository: https://github.com/xvrh/lottie-flutter
|
||||
|
||||
environment:
|
||||
sdk: '>=2.18.0 <3.0.0'
|
||||
flutter: '>=3.3.0'
|
||||
sdk: '^3.0.0'
|
||||
flutter: '>=3.10.0'
|
||||
|
||||
dependencies:
|
||||
archive: ^3.0.0
|
||||
|
@ -9,8 +9,8 @@ import 'utils.dart';
|
||||
void main() {
|
||||
testWidgets('Can specify ImageProvider with zip file ', (tester) async {
|
||||
var size = const Size(500, 400);
|
||||
tester.binding.window.physicalSizeTestValue = size;
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
tester.view.physicalSize = size;
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
|
||||
var callCount = 0;
|
||||
ImageProvider imageProviderFactory(LottieImageAsset image) {
|
||||
@ -32,8 +32,8 @@ void main() {
|
||||
|
||||
testWidgets('Can specify image delegate', (tester) async {
|
||||
var size = const Size(500, 400);
|
||||
tester.binding.window.physicalSizeTestValue = size;
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
tester.view.physicalSize = size;
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
|
||||
var image = await tester.runAsync(() async =>
|
||||
loadImage(FileImage(File('example/assets/Images/WeAccept/img_0.png'))));
|
||||
|
@ -276,7 +276,7 @@ void main() {
|
||||
|
||||
testGolden(
|
||||
'Null Color Filter',
|
||||
ValueDelegate.colorFilter(['**'], value: null),
|
||||
ValueDelegate.colorFilter(['**']),
|
||||
);
|
||||
|
||||
testGolden(
|
||||
@ -320,8 +320,8 @@ void main() {
|
||||
|
||||
testWidgets('warningShimmer', (tester) async {
|
||||
var size = const Size(500, 400);
|
||||
tester.binding.window.physicalSizeTestValue = size;
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
tester.view.physicalSize = size;
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
|
||||
var composition = await LottieComposition.fromBytes(
|
||||
File('test/data/warningShimmer.json').readAsBytesSync());
|
||||
|
@ -10,8 +10,8 @@ void main() {
|
||||
|
||||
testWidgets('Mirror animation', (tester) async {
|
||||
var size = const Size(500, 400);
|
||||
tester.binding.window.physicalSizeTestValue = size;
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
tester.view.physicalSize = size;
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
|
||||
var composition = (await tester.runAsync(() =>
|
||||
FileLottie(File('$root/Tests/MatteTimeStretchScan.json')).load()))!;
|
||||
|
@ -9,8 +9,8 @@ import 'utils.dart';
|
||||
void main() {
|
||||
testWidgets('Animations with stroke', (tester) async {
|
||||
var size = const Size(500, 400);
|
||||
tester.binding.window.physicalSizeTestValue = size;
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
tester.view.physicalSize = size;
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
|
||||
var composition = await LottieComposition.fromBytes(
|
||||
File('example/assets/17297-fireworks.json').readAsBytesSync());
|
||||
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
@ -14,8 +14,8 @@ void main() {
|
||||
.where((f) => const ['.json', '.zip'].contains(p.extension(f.path)))) {
|
||||
testWidgets('Goldens ${asset.path}', (tester) async {
|
||||
var size = const Size(500, 400);
|
||||
tester.binding.window.physicalSizeTestValue = size;
|
||||
tester.binding.window.devicePixelRatioTestValue = 1.0;
|
||||
tester.view.physicalSize = size;
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
var composition =
|
||||
(await tester.runAsync(() => FileLottie(asset).load()))!;
|
||||
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
BIN
test/goldens/all/Tests/1669133489622.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
BIN
test/goldens/all/Tests/defaultlinejoincap.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
BIN
test/goldens/all/Tests/issue_288.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
test/goldens/all/Tests/opacity_layers.png
Normal file
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
BIN
test/goldens/all/Tests/text_with_parent_alpha.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |