Compare commits

...

3 Commits

Author SHA1 Message Date
cb8006d362 Fix Flutter web compilation error (#109) 2020-10-23 23:13:53 +02:00
bf7d0ebf05 Increase version to 0.7.0 (#107) 2020-10-23 18:43:56 +02:00
57faea6f5e Fill Performance Improvements and other fixes (#100)
This PR improves some fill performance issues I found with various Lottie animations.
I think the real issue comes down to the render performance of Path.addPath(). The performance issue happens in the Render thread and seems directly related to how large the animation is on-screen. Flutter might be caching pre-rendered textures and running out of memory.

I've changed how Path.addPath() is called and how the path is rendered for fill_content.dart and gradient_fill_content.dart.

Just as an example, the example/assets/Tests/bm.json animation gets ~60 fps with this fix, compared to 34-52 fps with the lottie-flutter 0.6.0 release. (This is on a Pixel 3 XL)

There are a couple of other changes:

- I fixed a bug with the casing of "weather" in pubspec.yaml. Without this fix, the examples don't build on Ubuntu Linux.
The debugging class MeanCalculator wasn't initializing its fields, causing a null pointer exception when debugging.
- I added antiAliasingSuggested to LottieDrawable to allow fill paints to be anti-aliased. It is off by default. It also provides some minor performance improvements without any noticeable loss in quality. It is only applied to fills right now.
- I added PathFactory to create Paths rather than just new-ing them. path_factory.dart allows you to switch out the normal Path creation with a debug logging implementation so you can see all of the Path calls that are performed during a frame. Just create a DebugPath in the factory rather than Path.
2020-09-10 14:18:56 +02:00
108 changed files with 396 additions and 111 deletions

View File

@ -10,7 +10,7 @@ jobs:
name: Flutter analyze name: Flutter analyze
strategy: strategy:
matrix: matrix:
flutter: ['stable', 'dev'] flutter: ['stable']
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2

View File

@ -1,3 +1,9 @@
## [0.7.0+1]
- Fix Flutter Web compilation error
## [0.7.0]
- Performance improvement for complex animations.
## [0.6.0] ## [0.6.0]
- Runs the animation at the frame rate specified in the json file (ie. An animation encoded with a 20 FPS will only - Runs the animation at the frame rate specified in the json file (ie. An animation encoded with a 20 FPS will only
be paint 20 times per seconds even though the AnimationController will invalidate the widget 60 times per seconds). be paint 20 times per seconds even though the AnimationController will invalidate the widget 60 times per seconds).

View File

@ -8,7 +8,7 @@ animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-we
This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart. This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
It works on Android, iOS and macOS and web. It works on Android, iOS, macOS, linux, windows and web.
## Usage ## Usage

View File

@ -8,7 +8,7 @@ animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-we
This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart. This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
It works on Android, iOS and macOS and web. It works on Android, iOS, macOS, linux, windows and web.
## Usage ## Usage

View File

@ -21,42 +21,42 @@ packages:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.4.2" version: "2.5.0-nullsafety.1"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
name: boolean_selector name: boolean_selector
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.1.0-nullsafety.1"
characters: characters:
dependency: transitive dependency: transitive
description: description:
name: characters name: characters
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0-nullsafety" version: "1.1.0-nullsafety.3"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
name: charcode name: charcode
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.3" version: "1.2.0-nullsafety.1"
clock: clock:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1" version: "1.1.0-nullsafety.1"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.15.0-nullsafety" version: "1.15.0-nullsafety.3"
convert: convert:
dependency: transitive dependency: transitive
description: description:
@ -77,7 +77,14 @@ packages:
name: fake_async name: fake_async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.2.0-nullsafety.1"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -143,35 +150,35 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "0.6.0" version: "0.7.0+1"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.8" version: "0.12.10-nullsafety.1"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0-nullsafety" version: "1.3.0-nullsafety.3"
path: path:
dependency: transitive dependency: transitive
description: description:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.7.0" version: "1.8.0-nullsafety.1"
path_provider: path_provider:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.11" version: "1.6.21"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@ -185,14 +192,21 @@ packages:
name: path_provider_macos name: path_provider_macos
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.0.4+3" version: "0.0.4+4"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.2" version: "1.0.3"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4+1"
pedantic: pedantic:
dependency: transitive dependency: transitive
description: description:
@ -213,7 +227,7 @@ packages:
name: plugin_platform_interface name: plugin_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.2" version: "1.0.3"
process: process:
dependency: transitive dependency: transitive
description: description:
@ -232,63 +246,70 @@ packages:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.7.0" version: "1.8.0-nullsafety.2"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.9.5" version: "1.10.0-nullsafety.1"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.1.0-nullsafety.1"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.5" version: "1.1.0-nullsafety.1"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
name: term_glyph name: term_glyph
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.2.0-nullsafety.1"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.17" version: "0.2.19-nullsafety.2"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0-nullsafety" version: "1.3.0-nullsafety.3"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0-nullsafety" version: "2.1.0-nullsafety.3"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.3"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.0" version: "0.1.2"
sdks: sdks:
dart: ">=2.9.0-18.0 <2.9.0" dart: ">=2.10.0-110 <2.11.0"
flutter: ">=1.12.13+hotfix.5 <2.0.0" flutter: ">=1.12.13+hotfix.5 <2.0.0"

View File

@ -8,11 +8,11 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
flutter_colorpicker:
http:
lottie: lottie:
path: ../ path: ../
flutter_colorpicker:
path_provider: path_provider:
http:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
@ -34,7 +34,7 @@ flutter:
- assets/Logo/ - assets/Logo/
- assets/Images/ - assets/Images/
- assets/Images/WeAccept/ - assets/Images/WeAccept/
- assets/Weather/ - assets/weather/
- assets/example_with_images/ - assets/example_with_images/
- assets/example_with_images/images/ - assets/example_with_images/images/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -13,6 +13,7 @@ import '../../model/layer/base_layer.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../utils/dash_path.dart'; import '../../utils/dash_path.dart';
import '../../utils/misc.dart'; import '../../utils/misc.dart';
import '../../utils/path_factory.dart';
import '../../utils/utils.dart'; import '../../utils/utils.dart';
import '../../value/lottie_value_callback.dart'; import '../../value/lottie_value_callback.dart';
import '../keyframe/base_keyframe_animation.dart'; import '../keyframe/base_keyframe_animation.dart';
@ -25,8 +26,8 @@ import 'trim_path_content.dart';
abstract class BaseStrokeContent abstract class BaseStrokeContent
implements KeyPathElementContent, DrawingContent { implements KeyPathElementContent, DrawingContent {
final Path _path = Path(); final Path _path = PathFactory.create();
final Path _trimPathPath = Path(); final Path _trimPathPath = PathFactory.create();
final LottieDrawable lottieDrawable; final LottieDrawable lottieDrawable;
final BaseLayer layer; final BaseLayer layer;
final List<_PathGroup> _pathGroups = <_PathGroup>[]; final List<_PathGroup> _pathGroups = <_PathGroup>[];

View File

@ -9,6 +9,7 @@ import '../../model/key_path.dart';
import '../../model/key_path_element.dart'; import '../../model/key_path_element.dart';
import '../../model/layer/base_layer.dart'; import '../../model/layer/base_layer.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../utils/path_factory.dart';
import '../../value/lottie_value_callback.dart'; import '../../value/lottie_value_callback.dart';
import '../keyframe/transform_keyframe_animation.dart'; import '../keyframe/transform_keyframe_animation.dart';
import 'content.dart'; import 'content.dart';
@ -43,7 +44,7 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
} }
final Matrix4 _matrix = Matrix4.identity(); final Matrix4 _matrix = Matrix4.identity();
final Path _path = Path(); final Path _path = PathFactory.create();
@override @override
final String name; final String name;

View File

@ -7,6 +7,7 @@ import '../../model/key_path.dart';
import '../../model/layer/base_layer.dart'; import '../../model/layer/base_layer.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../utils/misc.dart'; import '../../utils/misc.dart';
import '../../utils/path_factory.dart';
import '../../value/lottie_value_callback.dart'; import '../../value/lottie_value_callback.dart';
import '../keyframe/base_keyframe_animation.dart'; import '../keyframe/base_keyframe_animation.dart';
import 'compound_trim_path_content.dart'; import 'compound_trim_path_content.dart';
@ -18,7 +19,7 @@ import 'trim_path_content.dart';
class EllipseContent implements PathContent, KeyPathElementContent { class EllipseContent implements PathContent, KeyPathElementContent {
static final double _ellipseControlPointPercentage = 0.55228; static final double _ellipseControlPointPercentage = 0.55228;
final Path _path = Path(); final Path _path = PathFactory.create();
@override @override
final String name; final String name;

View File

@ -8,6 +8,7 @@ import '../../model/key_path.dart';
import '../../model/layer/base_layer.dart'; import '../../model/layer/base_layer.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../utils/misc.dart'; import '../../utils/misc.dart';
import '../../utils/path_factory.dart';
import '../../value/lottie_value_callback.dart'; import '../../value/lottie_value_callback.dart';
import '../keyframe/base_keyframe_animation.dart'; import '../keyframe/base_keyframe_animation.dart';
import '../keyframe/value_callback_keyframe_animation.dart'; import '../keyframe/value_callback_keyframe_animation.dart';
@ -17,7 +18,7 @@ import 'key_path_element_content.dart';
import 'path_content.dart'; import 'path_content.dart';
class FillContent implements DrawingContent, KeyPathElementContent { class FillContent implements DrawingContent, KeyPathElementContent {
final Path _path = Path(); final Path _path = PathFactory.create();
final Paint _paint = Paint(); final Paint _paint = Paint();
final BaseLayer layer; final BaseLayer layer;
@override @override
@ -70,6 +71,9 @@ class FillContent implements DrawingContent, KeyPathElementContent {
var alpha = var alpha =
((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round(); ((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round();
_paint.setAlpha(alpha.clamp(0, 255).toInt()); _paint.setAlpha(alpha.clamp(0, 255).toInt());
if (lottieDrawable.antiAliasingSuggested) {
_paint.isAntiAlias = true;
}
if (_colorFilterAnimation != null) { if (_colorFilterAnimation != null) {
_paint.colorFilter = _colorFilterAnimation.value; _paint.colorFilter = _colorFilterAnimation.value;
@ -77,11 +81,13 @@ class FillContent implements DrawingContent, KeyPathElementContent {
_path.reset(); _path.reset();
for (var i = 0; i < _paths.length; i++) { for (var i = 0; i < _paths.length; i++) {
_path.addPath(_paths[i].getPath(), Offset.zero, _path.addPath(_paths[i].getPath(), Offset.zero);
matrix4: parentMatrix.storage);
} }
canvas.save();
canvas.transform(parentMatrix.storage);
canvas.drawPath(_path, _paint); canvas.drawPath(_path, _paint);
canvas.restore();
L.endSection('FillContent#draw'); L.endSection('FillContent#draw');
} }

View File

@ -10,6 +10,7 @@ import '../../model/key_path.dart';
import '../../model/layer/base_layer.dart'; import '../../model/layer/base_layer.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../utils/misc.dart'; import '../../utils/misc.dart';
import '../../utils/path_factory.dart';
import '../../value/lottie_value_callback.dart'; import '../../value/lottie_value_callback.dart';
import '../keyframe/base_keyframe_animation.dart'; import '../keyframe/base_keyframe_animation.dart';
import '../keyframe/value_callback_keyframe_animation.dart'; import '../keyframe/value_callback_keyframe_animation.dart';
@ -25,7 +26,7 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
final GradientFill _fill; final GradientFill _fill;
final _linearGradientCache = <int, Gradient>{}; final _linearGradientCache = <int, Gradient>{};
final _radialGradientCache = <int, Gradient>{}; final _radialGradientCache = <int, Gradient>{};
final _path = Path(); final _path = PathFactory.create();
final _paint = Paint(); final _paint = Paint();
final _paths = <PathContent>[]; final _paths = <PathContent>[];
final BaseKeyframeAnimation<GradientColor, GradientColor> _colorAnimation; final BaseKeyframeAnimation<GradientColor, GradientColor> _colorAnimation;
@ -85,15 +86,14 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
L.beginSection('GradientFillContent#draw'); L.beginSection('GradientFillContent#draw');
_path.reset(); _path.reset();
for (var i = 0; i < _paths.length; i++) { for (var i = 0; i < _paths.length; i++) {
_path.addPath(_paths[i].getPath(), Offset.zero, _path.addPath(_paths[i].getPath(), Offset.zero);
matrix4: parentMatrix.storage);
} }
Gradient gradient; Gradient gradient;
if (_fill.gradientType == GradientType.linear) { if (_fill.gradientType == GradientType.linear) {
gradient = _getLinearGradient(parentMatrix); gradient = _getLinearGradient();
} else { } else {
gradient = _getRadialGradient(parentMatrix); gradient = _getRadialGradient();
} }
_paint.shader = gradient; _paint.shader = gradient;
@ -105,8 +105,14 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
var alpha = var alpha =
((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round(); ((parentAlpha / 255.0 * _opacityAnimation.value / 100.0) * 255).round();
_paint.setAlpha(alpha.clamp(0, 255).toInt()); _paint.setAlpha(alpha.clamp(0, 255).toInt());
if (lottieDrawable.antiAliasingSuggested) {
_paint.isAntiAlias = true;
}
canvas.save();
canvas.transform(parentMatrix.storage);
canvas.drawPath(_path, _paint); canvas.drawPath(_path, _paint);
canvas.restore();
L.endSection('GradientFillContent#draw'); L.endSection('GradientFillContent#draw');
} }
@ -124,8 +130,8 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
outBounds.right + 1, outBounds.bottom + 1); outBounds.right + 1, outBounds.bottom + 1);
} }
Gradient _getLinearGradient(Matrix4 parentMatrix) { Gradient _getLinearGradient() {
var gradientHash = _getGradientHash(parentMatrix); var gradientHash = _getGradientHash();
var gradient = _linearGradientCache[gradientHash]; var gradient = _linearGradientCache[gradientHash];
if (gradient != null) { if (gradient != null) {
return gradient; return gradient;
@ -135,14 +141,14 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
var gradientColor = _colorAnimation.value; var gradientColor = _colorAnimation.value;
var colors = _applyDynamicColorsIfNeeded(gradientColor.colors); var colors = _applyDynamicColorsIfNeeded(gradientColor.colors);
var positions = gradientColor.positions; var positions = gradientColor.positions;
gradient = Gradient.linear(startPoint, endPoint, colors, positions, gradient = Gradient.linear(
TileMode.clamp, parentMatrix.storage); startPoint, endPoint, colors, positions, TileMode.clamp);
_linearGradientCache[gradientHash] = gradient; _linearGradientCache[gradientHash] = gradient;
return gradient; return gradient;
} }
Gradient _getRadialGradient(Matrix4 parentMatrix) { Gradient _getRadialGradient() {
var gradientHash = _getGradientHash(parentMatrix); var gradientHash = _getGradientHash();
var gradient = _radialGradientCache[gradientHash]; var gradient = _radialGradientCache[gradientHash];
if (gradient != null) { if (gradient != null) {
return gradient; return gradient;
@ -160,13 +166,13 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
if (radius <= 0) { if (radius <= 0) {
radius = 0.001; radius = 0.001;
} }
gradient = Gradient.radial(startPoint, radius, colors, positions, gradient =
TileMode.clamp, parentMatrix.storage); Gradient.radial(startPoint, radius, colors, positions, TileMode.clamp);
_radialGradientCache[gradientHash] = gradient; _radialGradientCache[gradientHash] = gradient;
return gradient; return gradient;
} }
int _getGradientHash(Matrix4 parentMatrix) { int _getGradientHash() {
var startPointProgress = var startPointProgress =
(_startPointAnimation.progress * _cacheSteps).round(); (_startPointAnimation.progress * _cacheSteps).round();
var endPointProgress = (_endPointAnimation.progress * _cacheSteps).round(); var endPointProgress = (_endPointAnimation.progress * _cacheSteps).round();
@ -181,7 +187,6 @@ class GradientFillContent implements DrawingContent, KeyPathElementContent {
if (colorProgress != 0) { if (colorProgress != 0) {
hash = hash * 31 * colorProgress; hash = hash * 31 * colorProgress;
} }
hash *= 31 * parentMatrix.hashCode;
return hash; return hash;
} }

View File

@ -1,15 +1,16 @@
import 'dart:ui'; import 'dart:ui';
import '../../model/content/merge_paths.dart'; import '../../model/content/merge_paths.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../utils/path_factory.dart';
import 'content.dart'; import 'content.dart';
import 'content_group.dart'; import 'content_group.dart';
import 'greedy_content.dart'; import 'greedy_content.dart';
import 'path_content.dart'; import 'path_content.dart';
class MergePathsContent implements PathContent, GreedyContent { class MergePathsContent implements PathContent, GreedyContent {
final Path _firstPath = Path(); final Path _firstPath = PathFactory.create();
final Path _remainderPath = Path(); final Path _remainderPath = PathFactory.create();
final Path _path = Path(); final Path _path = PathFactory.create();
final List<PathContent> _pathContents = <PathContent>[]; final List<PathContent> _pathContents = <PathContent>[];
final MergePaths _mergePaths; final MergePaths _mergePaths;

View File

@ -8,6 +8,7 @@ import '../../model/content/shape_trim_path.dart';
import '../../model/key_path.dart'; import '../../model/key_path.dart';
import '../../model/layer/base_layer.dart'; import '../../model/layer/base_layer.dart';
import '../../utils/misc.dart'; import '../../utils/misc.dart';
import '../../utils/path_factory.dart';
import '../../value/lottie_value_callback.dart'; import '../../value/lottie_value_callback.dart';
import '../keyframe/base_keyframe_animation.dart'; import '../keyframe/base_keyframe_animation.dart';
import 'compound_trim_path_content.dart'; import 'compound_trim_path_content.dart';
@ -23,7 +24,7 @@ class PolystarContent implements PathContent, KeyPathElementContent {
/// work otherwise. /// work otherwise.
static final _polystarMagicNumber = .47829; static final _polystarMagicNumber = .47829;
static final _polygonMagicNumber = .25; static final _polygonMagicNumber = .25;
final _path = Path(); final _path = PathFactory.create();
final LottieDrawable lottieDrawable; final LottieDrawable lottieDrawable;
final PolystarShape _polystarShape; final PolystarShape _polystarShape;

View File

@ -8,6 +8,7 @@ import '../../model/content/shape_trim_path.dart';
import '../../model/key_path.dart'; import '../../model/key_path.dart';
import '../../model/layer/base_layer.dart'; import '../../model/layer/base_layer.dart';
import '../../utils/misc.dart'; import '../../utils/misc.dart';
import '../../utils/path_factory.dart';
import '../../value/lottie_value_callback.dart'; import '../../value/lottie_value_callback.dart';
import '../keyframe/base_keyframe_animation.dart'; import '../keyframe/base_keyframe_animation.dart';
import 'compound_trim_path_content.dart'; import 'compound_trim_path_content.dart';
@ -17,7 +18,7 @@ import 'path_content.dart';
import 'trim_path_content.dart'; import 'trim_path_content.dart';
class RectangleContent implements KeyPathElementContent, PathContent { class RectangleContent implements KeyPathElementContent, PathContent {
final _path = Path(); final _path = PathFactory.create();
@override @override
final String name; final String name;

View File

@ -7,6 +7,7 @@ import '../../model/key_path.dart';
import '../../model/layer/base_layer.dart'; import '../../model/layer/base_layer.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../utils/misc.dart'; import '../../utils/misc.dart';
import '../../utils/path_factory.dart';
import '../../value/lottie_value_callback.dart'; import '../../value/lottie_value_callback.dart';
import '../keyframe/base_keyframe_animation.dart'; import '../keyframe/base_keyframe_animation.dart';
import '../keyframe/transform_keyframe_animation.dart'; import '../keyframe/transform_keyframe_animation.dart';
@ -24,7 +25,7 @@ class RepeaterContent
GreedyContent, GreedyContent,
KeyPathElementContent { KeyPathElementContent {
final Matrix4 _matrix = Matrix4.identity(); final Matrix4 _matrix = Matrix4.identity();
final _path = Path(); final _path = PathFactory.create();
final LottieDrawable lottieDrawable; final LottieDrawable lottieDrawable;
final BaseLayer layer; final BaseLayer layer;

View File

@ -4,6 +4,7 @@ import '../../model/content/shape_path.dart';
import '../../model/content/shape_trim_path.dart'; import '../../model/content/shape_trim_path.dart';
import '../../model/layer/base_layer.dart'; import '../../model/layer/base_layer.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../utils/path_factory.dart';
import '../keyframe/base_keyframe_animation.dart'; import '../keyframe/base_keyframe_animation.dart';
import 'compound_trim_path_content.dart'; import 'compound_trim_path_content.dart';
import 'content.dart'; import 'content.dart';
@ -11,7 +12,7 @@ import 'path_content.dart';
import 'trim_path_content.dart'; import 'trim_path_content.dart';
class ShapeContent implements PathContent { class ShapeContent implements PathContent {
final _path = Path(); final _path = PathFactory.create();
final ShapePath _shape; final ShapePath _shape;

View File

@ -1,12 +1,13 @@
import 'dart:ui'; import 'dart:ui';
import '../../model/content/shape_data.dart'; import '../../model/content/shape_data.dart';
import '../../utils/misc.dart'; import '../../utils/misc.dart';
import '../../utils/path_factory.dart';
import '../../value/keyframe.dart'; import '../../value/keyframe.dart';
import 'base_keyframe_animation.dart'; import 'base_keyframe_animation.dart';
class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> { class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> {
final ShapeData _tempShapeData = ShapeData.empty(); final ShapeData _tempShapeData = ShapeData.empty();
final Path _tempPath = Path(); final Path _tempPath = PathFactory.create();
ShapeKeyframeAnimation(List<Keyframe<ShapeData>> keyframes) ShapeKeyframeAnimation(List<Keyframe<ShapeData>> keyframes)
: super(keyframes); : super(keyframes);

View File

@ -18,6 +18,9 @@ class LottieDrawable {
bool _isDirty = true; bool _isDirty = true;
final bool enableMergePaths; final bool enableMergePaths;
/// Gives a suggestion whether to paint with anti-aliasing, or not. Default is true.
bool antiAliasingSuggested = true;
LottieDrawable(this.composition, LottieDrawable(this.composition,
{LottieDelegates delegates, bool enableMergePaths}) {LottieDelegates delegates, bool enableMergePaths})
: size = Size(composition.bounds.width.toDouble(), : size = Size(composition.bounds.width.toDouble(),

View File

@ -5,13 +5,14 @@ import '../../animation/keyframe/value_callback_keyframe_animation.dart';
import '../../lottie_drawable.dart'; import '../../lottie_drawable.dart';
import '../../lottie_property.dart'; import '../../lottie_property.dart';
import '../../utils.dart'; import '../../utils.dart';
import '../../utils/path_factory.dart';
import '../../value/lottie_value_callback.dart'; import '../../value/lottie_value_callback.dart';
import 'base_layer.dart'; import 'base_layer.dart';
import 'layer.dart'; import 'layer.dart';
class SolidLayer extends BaseLayer { class SolidLayer extends BaseLayer {
final Paint paint = Paint()..style = PaintingStyle.fill; final Paint paint = Paint()..style = PaintingStyle.fill;
final Path path = Path(); final Path path = PathFactory.create();
BaseKeyframeAnimation<ColorFilter, ColorFilter> /*?*/ _colorFilterAnimation; BaseKeyframeAnimation<ColorFilter, ColorFilter> /*?*/ _colorFilterAnimation;
SolidLayer(LottieDrawable lottieDrawable, Layer layerModel) SolidLayer(LottieDrawable lottieDrawable, Layer layerModel)

View File

@ -1,6 +1,7 @@
import 'dart:math'; import 'dart:math';
import 'dart:ui'; import 'dart:ui';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'path_factory.dart';
Path dashPath( Path dashPath(
Path source, { Path source, {
@ -14,7 +15,7 @@ Path dashPath(
} }
phase ??= 0; phase ??= 0;
var dest = Path(); var dest = PathFactory.create();
for (final metric in source.computeMetrics()) { for (final metric in source.computeMetrics()) {
for (var dash in _dashes(metric.length, intervals, phase)) { for (var dash in _dashes(metric.length, intervals, phase)) {
dest.addPath(metric.extractPath(dash.left, dash.right), Offset.zero); dest.addPath(metric.extractPath(dash.left, dash.right), Offset.zero);

View File

@ -0,0 +1,189 @@
import 'dart:typed_data';
import 'dart:ui';
class DebugPath extends Path {
void _log(String methodName) {
print('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);
}
}

View File

@ -1,6 +1,6 @@
class MeanCalculator { class MeanCalculator {
double _sum; double _sum = 0;
int _n; int _n = 0;
double get mean => _n == 0 ? 0 : _sum / _n; double get mean => _n == 0 ? 0 : _sum / _n;

Some files were not shown because too many files have changed in this diff Show More