Compare commits

...

11 Commits

Author SHA1 Message Date
dc43a532b0 Recognize some textstyle (#257) 2023-01-10 14:46:00 +01:00
1b752bf341 Apply latest fixes from Lottie-Android (#256)
- Overhaul text layout
- Fix rounded corners modifying already rounded corners
- Support box position in Document Data
- Allow interpolating between gradients with different opacity stops
- De-dupe gradient stops
- Add support for gradient opacity stops
2023-01-10 10:07:07 +01:00
21f34e6334 Add lint avoid_final_parameter (#254) 2023-01-03 16:31:41 +01:00
8dcb052fe1 Rework the cache so animation can be loaded without flickering 1 frame (#246)
Now, the cache can return a `SynchronousFuture` when the composition is
already available.
2022-12-14 14:06:34 +01:00
a333a42f01 Enable use_super_parameters lint (#242) 2022-11-10 14:14:28 +01:00
8ce429cdf4 Breaking change: Remove window.devicePixelRatio from the parser (#240) 2022-11-09 14:38:50 +01:00
fc450a88f4 Fix some warnings with Flutter 3.3 (#235) 2022-09-14 13:21:29 +02:00
c0bc257f4f use FilterQuality.low to default when draw image layer to fix some image render sawtooth (#230) 2022-08-25 11:55:26 +02:00
0e7499d82e Allow AlignmentGeometry for alignment (#228)
Thanks for the contribution
2022-08-03 11:52:58 +02:00
4cd9ec759a Update publish-on-pub action 2022-07-27 11:15:31 +02:00
d8f5b872ef [feat] support image layer quality setting (#214) 2022-07-27 11:11:26 +02:00
507 changed files with 9482 additions and 866 deletions

View File

@ -34,7 +34,7 @@ jobs:
&& exit 1)
shell: bash
build_web_version:
name: Check that the web version compile
name: Check that the web version can compile
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

View File

@ -8,9 +8,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: subosito/flutter-action@v1
- uses: subosito/flutter-action@v2
with:
channel: 'beta'
channel: 'stable'
- run: flutter pub get
- run: flutter pub run tool/publish/comment_dependency_overrides.dart
- run: flutter pub get

View File

@ -1,3 +1,61 @@
## [2.2.0]
Apply the latest fixes from Lottie-Android:
- Overhaul text layout
- Fix rounded corners modifying already rounded corners
- Support box position in Document Data
- Allow interpolating between gradients with different opacity stops
- Add support for gradient opacity stops
## [2.1.0]
- Improve the cache to ensure that there is not an empty frame each time we load an animation.
The method `AssetLottie('anim.json').load()` returns a `SynchronousFuture` if it has been loaded previously.
- Expose the `LottieCache` singleton.
It allows to change the cache behaviour and clear the entries.
```dart
void main() {
Lottie.cache.maximumSize = 10;
Lottie.cache.clear();
Lottie.cache.evict(NetworkLottie('https://lottie.com/anim.json'));
}
```
## [2.0.0]
- **Breaking change**: the lottie widget will be smaller if it relies on the intrinsic size of the composition.
Previously the lottie parser was automatically multiplying the size of the composition by `window.devicePixelRatio`.
This was incorrect as it results in a widget of a different size depending on the pixel ratio of the monitor.
Furthermore, it created some bugs when the property `window.devicePixelRatio` was not available immediately at the start
of the app (on Android release builds).
The code can be adapted to specify explicitly the size of the animation with `width`, `height` and `fit` properties.
```dart
Scaffold(
body: Center(
child: Lottie.asset(
'assets/LottieLogo1.json',
height: 800,
fit: BoxFit.contain,
),
),
);
```
## [1.4.3]
- Fixed some lints with Flutter 3.3.
## [1.4.2]
- Use `FilterQuality.low` as default to draw image layers.
## [1.4.1]
- Allow `AlignmentGeometry` for `alignment`.
## [1.4.0]
- Added `filterQuality` property to control the performance vs quality trade-off to use when drawing images
## [1.3.0]
- Added support for rounded corners on shapes and rects
- Add support for text in dynamic properties (`ValueDelegate`)

View File

@ -23,7 +23,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {
@ -61,10 +61,10 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
_MyAppState createState() => _MyAppState();
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
@ -136,10 +136,10 @@ This example shows how to load and parse a Lottie composition from a json file.
```dart
class MyWidget extends StatefulWidget {
const MyWidget({Key? key}) : super(key: key);
const MyWidget({super.key});
@override
_MyWidgetState createState() => _MyWidgetState();
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@ -182,7 +182,7 @@ a specific position and size.
class CustomDrawer extends StatelessWidget {
final LottieComposition composition;
const CustomDrawer(this.composition, {Key? key}) : super(key: key);
const CustomDrawer(this.composition, {super.key});
@override
Widget build(BuildContext context) {

View File

@ -10,14 +10,17 @@ linter:
always_declare_return_types: true
avoid_dynamic_calls: true
avoid_escaping_inner_quotes: true
avoid_final_parameters: true
avoid_returning_null_for_future: true
avoid_setters_without_getters: true
cancel_subscriptions: true
cast_nullable_to_non_nullable: true
close_sinks: true
no_adjacent_strings_in_list: true
no_default_cases: true
omit_local_variable_types: true
only_throw_errors: true
prefer_interpolation_to_compose_strings: true
prefer_relative_imports: true
prefer_single_quotes: true
sort_child_properties_last: true
sort_pub_dependencies: true
@ -27,3 +30,4 @@ linter:
unnecessary_statements: true
unsafe_html: true
use_raw_strings: true
use_super_parameters: true

View File

@ -9,7 +9,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {

View File

@ -0,0 +1 @@
{"v":"5.8.2","fr":23.9759979248047,"ip":0,"op":71.9999937681822,"w":400,"h":400,"nm":"BeyondBounds","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[510.547,510.547],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"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":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":71.9999937681822,"st":0,"bm":0}],"markers":[]}

Binary file not shown.

View File

@ -0,0 +1 @@
{"v":"5.9.6","fr":3,"ip":0,"op":3,"w":200,"h":200,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[30,30,0],"to":[21.667,21.667,0],"ti":[-21.667,-21.667,0]},{"t":2,"s":[160,160,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[58.742,58.742],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"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":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3,"st":0,"ct":1,"bm":0}],"markers":[]}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
{"v":"5.8.1","fr":25,"ip":0,"op":2,"w":2000,"h":4000,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1000,2000,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1554.562,597.062],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.220496237278,1,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1.281,-21.469],"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":"Rectangle 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1780.188,3801.75],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.116727701823,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[2.094,12.875],"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":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":2,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":1,"nm":"Red Solid 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1000,2000,0],"ix":2,"l":2},"a":{"a":0,"k":[1000,2000,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"sw":2000,"sh":4000,"sc":"#ff0000","ip":0,"op":2,"st":0,"bm":0}],"markers":[]}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,494 @@
{
"tgs": 1,
"v": "5.5.2",
"fr": 60,
"ip": 0,
"op": 180,
"w": 512,
"h": 512,
"nm": "02_ricl_klass - 3:00",
"ddd": 0,
"assets": [],
"layers": [
{
"ddd": 0,
"ind": 6,
"ty": 4,
"parent": 5,
"sr": 1,
"ks": {
"o": {
"a": 1,
"k": [
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": -105,
"s": [
0
]
},
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": -104,
"s": [
100
]
},
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": 34,
"s": [
100
]
},
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": 35,
"s": [
0
]
},
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": 75,
"s": [
0
]
},
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": 76,
"s": [
100
]
},
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": 214,
"s": [
100
]
},
{
"t": 215,
"s": [
0
]
}
]
},
"p": {
"a": 0,
"k": [
0,
-0.031,
0
]
},
"a": {
"a": 0,
"k": [
-87,
-18.182,
0
]
},
"s": {
"a": 0,
"k": [
50,
33,
100
]
}
},
"ao": 0,
"shapes": [
{
"ty": "gr",
"it": [
{
"ind": 0,
"ty": "sh",
"ks": {
"a": 1,
"k": [
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 213,
"s": [
{
"i": [
[
0,
0
],
[
0,
0
],
[
0,
0
],
[
0,
0
]
],
"o": [
[
0,
0
],
[
0,
0
],
[
0,
0
],
[
0,
0
]
],
"v": [
[
571.25,
-298.22
],
[
-192.5,
-267.902
],
[
-182.875,
510.152
],
[
575.125,
547.848
]
],
"c": true
}
]
},
{
"t": 214,
"s": [
{
"i": [
[
0,
0
],
[
0,
0
],
[
0,
0
],
[
0,
0
]
],
"o": [
[
0,
0
],
[
0,
0
],
[
0,
0
],
[
0,
0
]
],
"v": [
[
122.25,
-242.159
],
[
-192.5,
-267.902
],
[
-181.875,
178.333
],
[
175.125,
141.788
]
],
"c": true
}
]
}
]
},
"hd": false
},
{
"ty": "gf",
"o": {
"a": 0,
"k": 100
},
"r": 1,
"bm": 0,
"g": {
"p": 5,
"k": {
"a": 0,
"k": [
0.832,
0.275,
0.89,
0.086,
0.86,
0.275,
0.89,
0.086,
0.887,
0.275,
0.89,
0.086,
0.944,
0.275,
0.89,
0.086,
1,
0.275,
0.89,
0.086,
0.65,
0,
0.785,
0.5,
0.84,
1,
0.862,
1,
0.885,
1,
0.896,
0.5,
0.908,
0
]
}
},
"s": {
"a": 0,
"k": [
457.898,
-71.143
]
},
"e": {
"a": 0,
"k": [
-182.411,
-47.941
]
},
"t": 2,
"h": {
"a": 0,
"k": 0
},
"a": {
"a": 0,
"k": 97.679
},
"hd": false
},
{
"ty": "tr",
"p": {
"a": 0,
"k": [
0,
0
]
},
"a": {
"a": 0,
"k": [
0,
0
]
},
"s": {
"a": 0,
"k": [
100,
100
]
},
"r": {
"a": 0,
"k": 0
},
"o": {
"a": 0,
"k": 100
},
"sk": {
"a": 0,
"k": 0
},
"sa": {
"a": 0,
"k": 0
}
}
],
"bm": 0,
"hd": false
}
],
"ip": 0,
"op": 180,
"st": -120,
"bm": 0
}
]
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,386 @@
{
"v": "5.9.1",
"fr": 60,
"ip": 0,
"op": 56,
"w": 1080,
"h": 1080,
"nm": "Warning",
"ddd": 0,
"assets": [
{
"id": "comp_0",
"nm": "Warning_2",
"fr": 60,
"layers": [
{
"ddd": 0,
"ind": 3,
"ty": 4,
"nm": "CERCHIO contorni",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 0,
"k": [
24.5,
24.5,
0
],
"ix": 2,
"l": 2
},
"a": {
"a": 0,
"k": [
29.5,
29.5,
0
],
"ix": 1,
"l": 2
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6,
"l": 2
}
},
"ao": 0,
"shapes": [
{
"ty": "gr",
"it": [
{
"ind": 0,
"ty": "sh",
"ix": 1,
"ks": {
"a": 0,
"k": {
"i": [
[
-12.15,
0
],
[
0,
-12.15
],
[
12.15,
0
],
[
0,
12.15
]
],
"o": [
[
12.15,
0
],
[
0,
12.15
],
[
-12.15,
0
],
[
0,
-12.15
]
],
"v": [
[
0,
-22
],
[
22,
0
],
[
0,
22
],
[
-22,
0
]
],
"c": true
},
"ix": 2
},
"nm": "Tracciato 1",
"mn": "ADBE Vector Shape - Group",
"hd": false
},
{
"ty": "st",
"c": {
"a": 0,
"k": [
0.956862804936,
0.290196078431,
0.239215701234,
1
],
"ix": 3
},
"o": {
"a": 0,
"k": 100,
"ix": 4
},
"w": {
"a": 0,
"k": 3,
"ix": 5
},
"lc": 2,
"lj": 2,
"bm": 0,
"nm": "Traccia 1",
"mn": "ADBE Vector Graphic - Stroke",
"hd": false
},
{
"ty": "tr",
"p": {
"a": 0,
"k": [
29.5,
29.5
],
"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": "Gruppo 1",
"np": 2,
"cix": 2,
"bm": 0,
"ix": 1,
"mn": "ADBE Vector Group",
"hd": false
},
{
"ty": "tm",
"s": {
"a": 1,
"k": [
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": 0,
"s": [
0
]
},
{
"t": 36,
"s": [
0
]
}
],
"ix": 1
},
"e": {
"a": 1,
"k": [
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": 0,
"s": [
0
]
},
{
"t": 36,
"s": [
100
]
}
],
"ix": 2
},
"o": {
"a": 0,
"k": 0,
"ix": 3
},
"m": 1,
"ix": 2,
"nm": "Taglia tracciati 1",
"mn": "ADBE Vector Filter - Trim",
"hd": false
},
{
"ty": "rd",
"nm": "Angoli arrotondati 1",
"r": {
"a": 0,
"k": 10,
"ix": 1
},
"ix": 3,
"mn": "ADBE Vector Filter - RC",
"hd": false
}
],
"ip": 0,
"op": 57,
"st": 0,
"bm": 0
}
]
}
],
"layers": [
{
"ddd": 0,
"ind": 1,
"ty": 0,
"nm": "Warning_2",
"refId": "comp_0",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 0,
"k": [
530,
530,
0
],
"ix": 2,
"l": 2
},
"a": {
"a": 0,
"k": [
24,
24,
0
],
"ix": 1,
"l": 2
},
"s": {
"a": 0,
"k": [
2000,
2000,
100
],
"ix": 6,
"l": 2
}
},
"ao": 0,
"w": 48,
"h": 48,
"ip": 0,
"op": 57,
"st": 0,
"bm": 0
}
],
"markers": []
}

View File

@ -0,0 +1 @@
{"v":"5.7.4","fr":60,"ip":0,"op":63,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.984],"y":[0.777]},"o":{"x":[0.411],"y":[0.047]},"t":0,"s":[200]},{"t":62,"s":[460]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.926],"y":[0.943]},"o":{"x":[0.028],"y":[1.152]},"t":0,"s":[200]},{"t":62,"s":[460]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[119.332,119.332],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-130.404,-126.932],"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":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":63,"st":0,"bm":0}],"markers":[]}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
{"v":"5.9.6","fr":29.9700012207031,"ip":0,"op":190.000007738859,"w":24,"h":24,"nm":"Thumb","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12,12,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sr","sy":1,"d":1,"pt":{"a":0,"k":5,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":0,"k":0,"ix":5},"ir":{"a":0,"k":5,"ix":6},"is":{"a":0,"k":0,"ix":8},"or":{"a":0,"k":12,"ix":7},"os":{"a":0,"k":0,"ix":9},"ix":1,"nm":"Polystar Path 1","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.922702133656,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"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":"Polystar 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":190.000007738859,"st":0,"ct":1,"bm":0}],"markers":[]}

View File

@ -0,0 +1 @@
{"v":"5.5.8","fr":60,"ip":0,"op":166,"w":828,"h":1215,"nm":"Залитые дуги 10 + opacity","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Sinie 2","td":1,"sr":1.53474205216067,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[413.199,607.88,0],"ix":2},"a":{"a":0,"k":[168.949,195.88,0],"ix":1},"s":{"a":0,"k":[207.219,207.219,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[11.998,6.913],[13.844,0.193],[-28.149,-0.401]],"o":[[-11.991,-6.921],[14.447,24.162],[-7.102,-11.886]],"v":[[5.137,-8.915],[-34.263,-19.764],[34.265,19.754]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-14.745,-25.464],[0.311,-0.18],[0.113,0],[14.745,25.466],[-0.31,0.179],[-0.114,0]],"o":[[29.425,0.007],[0.178,0.311],[-0.098,0.056],[-29.427,-0.005],[-0.179,-0.31],[0.099,-0.057],[0,0]],"v":[[-35.4,-21.063],[35.964,20.09],[35.725,20.977],[35.403,21.063],[-35.963,-20.09],[-35.725,-20.976],[-35.401,-21.063]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.894117706897,0,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[132.535,174.966],"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":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":48,"op":166,"st":-37.8760708166762,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Krug siniy 2","tt":1,"sr":0.98917079207921,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[412.455,610.955,0],"ix":2},"a":{"a":0,"k":[135.603,464.717,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[0.252,0.252,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":55,"s":[0,0,100]},{"t":111.000102732441,"s":[79.385,79.385,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,105.185],[105.185,0],[0,-105.185],[-105.186,0]],"o":[[0,-105.185],[-105.186,0],[0,105.185],[105.185,0]],"v":[[190.455,0],[0,-190.455],[-190.455,0],[0,190.456]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[135.603,464.717],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[174.179,174.179],"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,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":48,"op":166,"st":25.2165841584158,"bm":0}],"markers":[]}

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const App());
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
Widget build(BuildContext context) {
@ -25,7 +25,7 @@ class __PageState extends State<_Page> {
void initState() {
super.initState();
SchedulerBinding.instance!.addPostFrameCallback((_) => _showLoader());
SchedulerBinding.instance.addPostFrameCallback((_) => _showLoader());
}
void _showLoader() {

View File

@ -6,7 +6,7 @@ void main() async {
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
Widget build(BuildContext context) {

View File

@ -4,10 +4,10 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
_MyAppState createState() => _MyAppState();
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {

View File

@ -12,10 +12,10 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
_MyAppState createState() => _MyAppState();
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {

View File

@ -4,7 +4,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {

View File

@ -0,0 +1,59 @@
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
void main() => runApp(const App());
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(body: _Page()),
);
}
}
class _Page extends StatefulWidget {
@override
__PageState createState() => __PageState();
}
class __PageState extends State<_Page> {
var _animationKey = UniqueKey();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Lottie.network(
'https://assets10.lottiefiles.com/datafiles/QeC7XD39x4C1CIj/data.json',
key: _animationKey,
fit: BoxFit.contain,
width: 200,
height: 200,
),
ElevatedButton(
onPressed: () {
Lottie.cache.clear();
Lottie.cache.maximumSize = 10;
},
child: const Text('Clear cache'),
),
ElevatedButton(
onPressed: () {
setState(() {
_animationKey = UniqueKey();
});
},
child: const Text('Recreate animation'),
),
],
);
}
}

View File

@ -5,7 +5,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {
@ -18,10 +18,10 @@ class MyApp extends StatelessWidget {
}
class MyWidget extends StatefulWidget {
const MyWidget({Key? key}) : super(key: key);
const MyWidget({super.key});
@override
_MyWidgetState createState() => _MyWidgetState();
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@ -60,7 +60,7 @@ class _MyWidgetState extends State<MyWidget> {
class CustomDrawer extends StatelessWidget {
final LottieComposition composition;
const CustomDrawer(this.composition, {Key? key}) : super(key: key);
const CustomDrawer(this.composition, {super.key});
@override
Widget build(BuildContext context) {

View File

@ -5,7 +5,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {
@ -19,10 +19,10 @@ class MyApp extends StatelessWidget {
//--- example
class MyWidget extends StatefulWidget {
const MyWidget({Key? key}) : super(key: key);
const MyWidget({super.key});
@override
_MyWidgetState createState() => _MyWidgetState();
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {

View File

@ -4,7 +4,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {

View File

@ -7,10 +7,10 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
_AppState createState() => _AppState();
State<App> createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {

View File

@ -7,10 +7,10 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
_AppState createState() => _AppState();
State<App> createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {

View File

@ -4,7 +4,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {

View File

@ -4,7 +4,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {

View File

@ -6,10 +6,10 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
_AppState createState() => _AppState();
State<App> createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {

View File

@ -9,10 +9,10 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
_AppState createState() => _AppState();
State<App> createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {
@ -48,7 +48,7 @@ class _AppState extends State<App> with TickerProviderStateMixin {
class _LottieDetails extends StatefulWidget {
final LottieComposition composition;
const _LottieDetails(this.composition, {Key? key}) : super(key: key);
const _LottieDetails(this.composition);
@override
_LottieDetailsState createState() => _LottieDetailsState();

View File

@ -4,10 +4,10 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
_MyAppState createState() => _MyAppState();
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {

View File

@ -12,10 +12,10 @@ void main() async {
}
class App extends StatefulWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
_AppState createState() => _AppState();
State<App> createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {

View File

@ -10,10 +10,10 @@ import 'package:path_provider/path_provider.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
_MyAppState createState() => _MyAppState();
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {

View File

@ -4,7 +4,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {

View File

@ -4,7 +4,7 @@ import 'package:lottie/lottie.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});
@override
Widget build(BuildContext context) {

View File

@ -14,7 +14,7 @@ void main() {
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
Widget build(BuildContext context) {
@ -24,37 +24,37 @@ class App extends StatelessWidget {
appBar: AppBar(
title: const Text('Lottie Flutter'),
),
body: Scrollbar(
child: GridView.builder(
itemCount: files.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4),
itemBuilder: (context, index) {
var assetName = files[index];
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => Detail(assetName)));
},
child: _Item(
child: Lottie.asset(
assetName,
onWarning: (w) => _logger.info('$assetName - $w'),
frameBuilder: (context, child, composition) {
return AnimatedOpacity(
opacity: composition == null ? 0 : 1,
duration: const Duration(seconds: 1),
curve: Curves.easeOut,
child: child,
);
},
),
body: GridView.builder(
primary: true,
itemCount: files.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4),
itemBuilder: (context, index) {
var assetName = files[index];
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => Detail(assetName)));
},
child: _Item(
child: Lottie.asset(
assetName,
fit: BoxFit.contain,
onWarning: (w) => _logger.info('$assetName - $w'),
frameBuilder: (context, child, composition) {
return AnimatedOpacity(
opacity: composition == null ? 0 : 1,
duration: const Duration(seconds: 1),
curve: Curves.easeOut,
child: child,
);
},
),
);
},
),
),
);
},
),
),
);
@ -64,7 +64,7 @@ class App extends StatelessWidget {
class _Item extends StatelessWidget {
final Widget child;
const _Item({Key? key, required this.child}) : super(key: key);
const _Item({required this.child});
@override
Widget build(BuildContext context) {
@ -89,10 +89,10 @@ class _Item extends StatelessWidget {
class Detail extends StatefulWidget {
final String assetName;
const Detail(this.assetName, {Key? key}) : super(key: key);
const Detail(this.assetName, {super.key});
@override
_DetailState createState() => _DetailState();
State<Detail> createState() => _DetailState();
}
class _DetailState extends State<Detail> with TickerProviderStateMixin {

View File

@ -13,7 +13,7 @@ void main() async {
class App extends StatelessWidget {
final LottieComposition composition;
const App({Key? key, required this.composition}) : super(key: key);
const App({super.key, required this.composition});
@override
Widget build(BuildContext context) {
@ -103,8 +103,7 @@ class _Lottie extends StatefulWidget {
final AlignmentGeometry? alignment;
const _Lottie(this.composition,
{Key? key, this.width, this.height, this.fit, this.alignment})
: super(key: key);
{this.width, this.height, this.fit, this.alignment});
@override
__LottieState createState() => __LottieState();

View File

@ -6,7 +6,7 @@ void main() async {
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
Widget build(BuildContext context) {

View File

@ -6,7 +6,7 @@ void main() async {
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
const App({super.key});
@override
Widget build(BuildContext context) {

View File

@ -0,0 +1,11 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
void fl_register_plugins(FlPluginRegistry* registry) {
}

View File

@ -0,0 +1,15 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_

View File

@ -0,0 +1,23 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)

View File

@ -14,9 +14,9 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
SPEC CHECKSUMS:
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
path_provider_macos: a0a3fd666cb7cd0448e936fb4abad4052961002b
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
COCOAPODS: 1.10.1
COCOAPODS: 1.11.3

View File

@ -7,14 +7,14 @@ packages:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "3.3.0"
version: "3.3.5"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
@ -28,56 +28,56 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
version: "1.16.0"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.1"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
version: "3.0.2"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
version: "2.0.1"
file:
dependency: transitive
description:
name: file
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
version: "6.1.4"
flutter:
dependency: "direct main"
description: flutter
@ -96,7 +96,7 @@ packages:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
version: "2.0.1"
flutter_test:
dependency: "direct dev"
description: flutter
@ -108,119 +108,126 @@ packages:
name: golden_toolkit
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.0"
version: "0.14.0"
http:
dependency: "direct main"
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.4"
version: "0.13.5"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
version: "4.0.2"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.5"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "2.0.1"
logging:
dependency: "direct main"
description:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
version: "1.1.0"
lottie:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "1.3.0"
version: "2.2.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0"
path:
dependency: transitive
dependency: "direct main"
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
version: "1.8.2"
path_provider:
dependency: "direct main"
description:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.9"
version: "2.0.11"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.12"
version: "2.0.22"
path_provider_ios:
dependency: transitive
description:
name: path_provider_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
version: "2.0.11"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
version: "2.1.7"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "2.0.6"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
version: "2.0.5"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "2.1.3"
platform:
dependency: transitive
description:
@ -234,7 +241,14 @@ packages:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
version: "2.1.3"
pointycastle:
dependency: transitive
description:
name: pointycastle
url: "https://pub.dartlang.org"
source: hosted
version: "3.6.2"
process:
dependency: transitive
description:
@ -253,7 +267,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
version: "1.9.0"
stack_trace:
dependency: transitive
description:
@ -274,49 +288,49 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.8"
version: "0.4.12"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.3.1"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "2.1.2"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.5.1"
version: "3.1.2"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0+1"
version: "0.2.0+2"
sdks:
dart: ">=2.15.0 <3.0.0"
flutter: ">=2.10.0"
dart: ">=2.18.4 <3.0.0"
flutter: ">=3.3.0"

View File

@ -3,7 +3,7 @@ description: A sample app for the Lottie player
publish_to: none
environment:
sdk: ">=2.12.0-0 <3.0.0"
sdk: ">=2.18.0 <3.0.0"
dependencies:
flutter:
@ -13,6 +13,7 @@ dependencies:
logging:
lottie:
path: ../
path:
path_provider:
dev_dependencies:

View File

@ -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;
export 'src/providers/lottie_provider.dart' show LottieProvider, LottieCache;
export 'src/providers/memory_provider.dart' show MemoryLottie;
export 'src/providers/network_provider.dart' show NetworkLottie;
export 'src/raw_lottie.dart' show RawLottie;

View File

@ -52,8 +52,8 @@ class ContentGroup implements DrawingContent, PathContent, KeyPathElement {
List<PathContent>? _pathContents;
TransformKeyframeAnimation? _transformAnimation;
ContentGroup(final LottieDrawable lottieDrawable, BaseLayer layer,
ShapeGroup shapeGroup)
ContentGroup(
LottieDrawable lottieDrawable, BaseLayer layer, ShapeGroup shapeGroup)
: this.copy(
lottieDrawable,
layer,

View File

@ -31,8 +31,8 @@ class GradientStrokeContent extends BaseStrokeContent {
ValueCallbackKeyframeAnimation<List<Color>, List<Color>>?
_colorCallbackAnimation;
GradientStrokeContent(final LottieDrawable lottieDrawable, BaseLayer layer,
GradientStroke stroke)
GradientStrokeContent(
LottieDrawable lottieDrawable, BaseLayer layer, GradientStroke stroke)
: name = stroke.name,
_type = stroke.gradientType,
_hidden = stroke.hidden,

View File

@ -168,12 +168,12 @@ class RoundedCornersContent implements ShapeModifierContent {
var previousCurveData = modifiedCurves[
floorMod(modifiedCurvesIndex - 1, modifiedCurves.length)];
var currentCurveData = modifiedCurves[modifiedCurvesIndex];
previousCurveData.controlPoint2 =
Offset(previousCurve.vertex.dx, previousCurve.vertex.dy);
previousCurveData.controlPoint2 = Offset(
previousCurve.controlPoint2.dx, previousCurve.controlPoint2.dy);
previousCurveData.vertex =
Offset(previousCurve.vertex.dx, previousCurve.vertex.dy);
currentCurveData.controlPoint1 =
Offset(startingCurve.vertex.dx, startingCurve.vertex.dy);
currentCurveData.controlPoint1 = Offset(
startingCurve.controlPoint1.dx, startingCurve.controlPoint1.dy);
modifiedCurvesIndex++;
}
}

View File

@ -17,7 +17,7 @@ class StrokeContent extends BaseStrokeContent {
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
StrokeContent(
final LottieDrawable lottieDrawable, BaseLayer layer, ShapeStroke stroke)
LottieDrawable lottieDrawable, BaseLayer layer, ShapeStroke stroke)
: name = stroke.name,
_hidden = stroke.hidden,
_colorAnimation = stroke.color.createAnimation(),

View File

@ -4,7 +4,7 @@ import '../../value/keyframe.dart';
import 'keyframe_animation.dart';
class ColorKeyframeAnimation extends KeyframeAnimation<Color> {
ColorKeyframeAnimation(List<Keyframe<Color>> keyframes) : super(keyframes);
ColorKeyframeAnimation(super.keyframes);
@override
Color getValue(Keyframe<Color> keyframe, double keyframeProgress) {

View File

@ -3,7 +3,7 @@ import '../../value/keyframe.dart';
import 'keyframe_animation.dart';
class DoubleKeyframeAnimation extends KeyframeAnimation<double> {
DoubleKeyframeAnimation(List<Keyframe<double>> keyframes) : super(keyframes);
DoubleKeyframeAnimation(super.keyframes);
@override
double getValue(Keyframe<double> keyframe, double keyframeProgress) {

View File

@ -3,7 +3,7 @@ import '../../value/keyframe.dart';
import 'keyframe_animation.dart';
class IntegerKeyframeAnimation extends KeyframeAnimation<int> {
IntegerKeyframeAnimation(List<Keyframe<int>> keyframes) : super(keyframes);
IntegerKeyframeAnimation(super.keyframes);
@override
int getValue(Keyframe<int> keyframe, double keyframeProgress) {

View File

@ -1,7 +1,6 @@
import '../../value/keyframe.dart';
import 'base_keyframe_animation.dart';
abstract class KeyframeAnimation<T extends Object>
extends BaseKeyframeAnimation<T, T> {
KeyframeAnimation(List<Keyframe<T>> keyframes) : super(keyframes);
KeyframeAnimation(super.keyframes);
}

View File

@ -7,9 +7,9 @@ class PathKeyframe extends Keyframe<Offset> {
Path? _path;
final Keyframe<Offset> _pointKeyFrame;
PathKeyframe(LottieComposition composition, Keyframe<Offset> keyframe)
PathKeyframe(LottieComposition super.composition, Keyframe<Offset> keyframe)
: _pointKeyFrame = keyframe,
super(composition,
super(
startValue: keyframe.startValue,
endValue: keyframe.endValue,
interpolator: keyframe.interpolator,

View File

@ -7,7 +7,7 @@ class PathKeyframeAnimation extends KeyframeAnimation<Offset> {
PathKeyframe? _pathMeasureKeyframe;
late PathMetric _pathMeasure;
PathKeyframeAnimation(List<Keyframe<Offset>> keyframes) : super(keyframes);
PathKeyframeAnimation(super.keyframes);
@override
Offset getValue(Keyframe<Offset> keyframe, double keyframeProgress) {

View File

@ -3,7 +3,7 @@ import '../../value/keyframe.dart';
import 'keyframe_animation.dart';
class PointKeyframeAnimation extends KeyframeAnimation<Offset> {
PointKeyframeAnimation(List<Keyframe<Offset>> keyframes) : super(keyframes);
PointKeyframeAnimation(super.keyframes);
@override
Offset getValue(Keyframe<Offset> keyframe, double keyframeProgress) {

View File

@ -11,8 +11,7 @@ class ShapeKeyframeAnimation extends BaseKeyframeAnimation<ShapeData, Path> {
final Path _tempPath = PathFactory.create();
List<ShapeModifierContent>? _shapeModifiers;
ShapeKeyframeAnimation(List<Keyframe<ShapeData>> keyframes)
: super(keyframes);
ShapeKeyframeAnimation(super.keyframes);
@override
Path getValue(Keyframe<ShapeData> keyframe, double keyframeProgress) {

View File

@ -5,8 +5,7 @@ import '../../value/lottie_value_callback.dart';
import 'keyframe_animation.dart';
class TextKeyframeAnimation extends KeyframeAnimation<DocumentData> {
TextKeyframeAnimation(List<Keyframe<DocumentData>> keyframes)
: super(keyframes);
TextKeyframeAnimation(super.keyframes);
@override
DocumentData getValue(
@ -53,16 +52,19 @@ class _DocumentDataValueCallback extends LottieValueCallback<DocumentData> {
? frameInfo.endValue!
: frameInfo.startValue!;
return DocumentData(
text: text,
fontName: baseDocumentData.fontName,
size: baseDocumentData.size,
justification: baseDocumentData.justification,
tracking: baseDocumentData.tracking,
lineHeight: baseDocumentData.lineHeight,
baselineShift: baseDocumentData.baselineShift,
color: baseDocumentData.color,
strokeColor: baseDocumentData.strokeColor,
strokeWidth: baseDocumentData.strokeWidth,
strokeOverFill: baseDocumentData.strokeOverFill);
text: text,
fontName: baseDocumentData.fontName,
size: baseDocumentData.size,
justification: baseDocumentData.justification,
tracking: baseDocumentData.tracking,
lineHeight: baseDocumentData.lineHeight,
baselineShift: baseDocumentData.baselineShift,
color: baseDocumentData.color,
strokeColor: baseDocumentData.strokeColor,
strokeWidth: baseDocumentData.strokeWidth,
strokeOverFill: baseDocumentData.strokeOverFill,
boxPosition: baseDocumentData.boxPosition,
boxSize: baseDocumentData.boxSize,
);
}
}

View File

@ -4,6 +4,7 @@ import '../lottie.dart';
import 'composition.dart';
import 'l.dart';
import 'lottie_builder.dart';
import 'providers/lottie_provider.dart';
/// A widget to display a loaded [LottieComposition].
/// The [controller] property allows to specify a custom AnimationController that
@ -11,8 +12,11 @@ import 'lottie_builder.dart';
/// automatically and the behavior could be adjusted with the properties [animate],
/// [repeat] and [reverse].
class Lottie extends StatefulWidget {
/// The cache instance for recently loaded Lottie compositions.
static LottieCache get cache => sharedLottieCache;
const Lottie({
Key? key,
super.key,
required this.composition,
this.controller,
this.width,
@ -26,11 +30,11 @@ class Lottie extends StatefulWidget {
this.delegates,
this.options,
bool? addRepaintBoundary,
this.filterQuality,
}) : animate = animate ?? true,
reverse = reverse ?? false,
repeat = repeat ?? true,
addRepaintBoundary = addRepaintBoundary ?? true,
super(key: key);
addRepaintBoundary = addRepaintBoundary ?? true;
/// Creates a widget that displays an [LottieComposition] obtained from an [AssetBundle].
static LottieBuilder asset(
@ -51,9 +55,10 @@ class Lottie extends StatefulWidget {
double? width,
double? height,
BoxFit? fit,
Alignment? alignment,
AlignmentGeometry? alignment,
String? package,
bool? addRepaintBoundary,
FilterQuality? filterQuality,
WarningCallback? onWarning,
}) =>
LottieBuilder.asset(
@ -77,6 +82,7 @@ class Lottie extends StatefulWidget {
alignment: alignment,
package: package,
addRepaintBoundary: addRepaintBoundary,
filterQuality: filterQuality,
onWarning: onWarning,
);
@ -98,8 +104,9 @@ class Lottie extends StatefulWidget {
double? width,
double? height,
BoxFit? fit,
Alignment? alignment,
AlignmentGeometry? alignment,
bool? addRepaintBoundary,
FilterQuality? filterQuality,
WarningCallback? onWarning,
}) =>
LottieBuilder.file(
@ -121,6 +128,7 @@ class Lottie extends StatefulWidget {
fit: fit,
alignment: alignment,
addRepaintBoundary: addRepaintBoundary,
filterQuality: filterQuality,
onWarning: onWarning,
);
@ -142,8 +150,9 @@ class Lottie extends StatefulWidget {
double? width,
double? height,
BoxFit? fit,
Alignment? alignment,
AlignmentGeometry? alignment,
bool? addRepaintBoundary,
FilterQuality? filterQuality,
WarningCallback? onWarning,
}) =>
LottieBuilder.memory(
@ -165,6 +174,7 @@ class Lottie extends StatefulWidget {
fit: fit,
alignment: alignment,
addRepaintBoundary: addRepaintBoundary,
filterQuality: filterQuality,
onWarning: onWarning,
);
@ -186,8 +196,9 @@ class Lottie extends StatefulWidget {
double? width,
double? height,
BoxFit? fit,
Alignment? alignment,
AlignmentGeometry? alignment,
bool? addRepaintBoundary,
FilterQuality? filterQuality,
WarningCallback? onWarning,
}) =>
LottieBuilder.network(
@ -209,6 +220,7 @@ class Lottie extends StatefulWidget {
fit: fit,
alignment: alignment,
addRepaintBoundary: addRepaintBoundary,
filterQuality: filterQuality,
onWarning: onWarning,
);
@ -299,13 +311,19 @@ class Lottie extends StatefulWidget {
/// This property is `true` by default.
final bool addRepaintBoundary;
/// The quality of the image layer. See [FilterQuality]
/// [FilterQuality.high] is highest quality but slowest.
///
/// Defaults to [FilterQuality.low]
final FilterQuality? filterQuality;
static bool get traceEnabled => L.traceEnabled;
static set traceEnabled(bool enabled) {
L.traceEnabled = enabled;
}
@override
_LottieState createState() => _LottieState();
State<Lottie> createState() => _LottieState();
}
class _LottieState extends State<Lottie> with TickerProviderStateMixin {
@ -366,6 +384,7 @@ class _LottieState extends State<Lottie> with TickerProviderStateMixin {
height: widget.height,
fit: widget.fit,
alignment: widget.alignment,
filterQuality: widget.filterQuality,
);
},
);

View File

@ -1,5 +1,4 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'composition.dart';
@ -33,16 +32,16 @@ typedef LottieErrorWidgetBuilder = Widget Function(
/// Several constructors are provided for the various ways that a Lottie file
/// can be provided:
///
/// * [new Lottie], for obtaining a composition from a [LottieProvider].
/// * [new Lottie.asset], for obtaining a Lottie file from an [AssetBundle]
/// * [Lottie], for obtaining a composition from a [LottieProvider].
/// * [Lottie.asset], for obtaining a Lottie file from an [AssetBundle]
/// using a key.
/// * [new Lottie.network], for obtaining a lottie file from a URL.
/// * [new Lottie.file], for obtaining a lottie file from a [File].
/// * [new Lottie.memory], for obtaining a lottie file from a [Uint8List].
/// * [Lottie.network], for obtaining a lottie file from a URL.
/// * [Lottie.file], for obtaining a lottie file from a [File].
/// * [Lottie.memory], for obtaining a lottie file from a [Uint8List].
///
class LottieBuilder extends StatefulWidget {
const LottieBuilder({
Key? key,
super.key,
required this.lottie,
this.controller,
this.frameRate,
@ -59,8 +58,9 @@ class LottieBuilder extends StatefulWidget {
this.fit,
this.alignment,
this.addRepaintBoundary,
this.filterQuality,
this.onWarning,
}) : super(key: key);
});
/// Creates a widget that displays an [LottieComposition] obtained from the network.
LottieBuilder.network(
@ -75,7 +75,7 @@ class LottieBuilder extends StatefulWidget {
this.options,
LottieImageProviderFactory? imageProviderFactory,
this.onLoaded,
Key? key,
super.key,
this.frameBuilder,
this.errorBuilder,
this.width,
@ -83,10 +83,10 @@ class LottieBuilder extends StatefulWidget {
this.fit,
this.alignment,
this.addRepaintBoundary,
this.filterQuality,
this.onWarning,
}) : lottie = NetworkLottie(src,
headers: headers, imageProviderFactory: imageProviderFactory),
super(key: key);
}) : lottie = NetworkLottie(src,
headers: headers, imageProviderFactory: imageProviderFactory);
/// Creates a widget that displays an [LottieComposition] obtained from a [File].
///
@ -109,7 +109,7 @@ class LottieBuilder extends StatefulWidget {
this.options,
LottieImageProviderFactory? imageProviderFactory,
this.onLoaded,
Key? key,
super.key,
this.frameBuilder,
this.errorBuilder,
this.width,
@ -117,9 +117,9 @@ class LottieBuilder extends StatefulWidget {
this.fit,
this.alignment,
this.addRepaintBoundary,
this.filterQuality,
this.onWarning,
}) : lottie = FileLottie(file, imageProviderFactory: imageProviderFactory),
super(key: key);
}) : lottie = FileLottie(file, imageProviderFactory: imageProviderFactory);
/// Creates a widget that displays an [LottieComposition] obtained from an [AssetBundle].
LottieBuilder.asset(
@ -133,7 +133,7 @@ class LottieBuilder extends StatefulWidget {
this.options,
LottieImageProviderFactory? imageProviderFactory,
this.onLoaded,
Key? key,
super.key,
AssetBundle? bundle,
this.frameBuilder,
this.errorBuilder,
@ -143,12 +143,12 @@ class LottieBuilder extends StatefulWidget {
this.alignment,
String? package,
this.addRepaintBoundary,
this.filterQuality,
this.onWarning,
}) : lottie = AssetLottie(name,
}) : lottie = AssetLottie(name,
bundle: bundle,
package: package,
imageProviderFactory: imageProviderFactory),
super(key: key);
imageProviderFactory: imageProviderFactory);
/// Creates a widget that displays an [LottieComposition] obtained from a [Uint8List].
LottieBuilder.memory(
@ -163,17 +163,16 @@ class LottieBuilder extends StatefulWidget {
LottieImageProviderFactory? imageProviderFactory,
this.onLoaded,
this.errorBuilder,
Key? key,
super.key,
this.frameBuilder,
this.width,
this.height,
this.fit,
this.alignment,
this.addRepaintBoundary,
this.filterQuality,
this.onWarning,
}) : lottie =
MemoryLottie(bytes, imageProviderFactory: imageProviderFactory),
super(key: key);
}) : lottie = MemoryLottie(bytes, imageProviderFactory: imageProviderFactory);
/// The lottie animation to load.
/// Example of providers: [AssetLottie], [NetworkLottie], [FileLottie], [MemoryLottie]
@ -361,6 +360,12 @@ class LottieBuilder extends StatefulWidget {
/// This property is `true` by default.
final bool? addRepaintBoundary;
/// The quality of the image layer. See [FilterQuality]
/// [FilterQuality.high] is highest quality but slowest.
///
/// Defaults to [FilterQuality.low]
final FilterQuality? filterQuality;
/// A callback called when there is a warning during the loading or painting
/// of the animation.
final WarningCallback? onWarning;
@ -398,7 +403,7 @@ class LottieBuilder extends StatefulWidget {
final ImageErrorWidgetBuilder? errorBuilder;
@override
_LottieBuilderState createState() => _LottieBuilderState();
State<LottieBuilder> createState() => _LottieBuilderState();
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
@ -482,6 +487,7 @@ class _LottieBuilderState extends State<LottieBuilder> {
fit: widget.fit,
alignment: widget.alignment,
addRepaintBoundary: widget.addRepaintBoundary,
filterQuality: widget.filterQuality,
);
if (widget.frameBuilder != null) {

View File

@ -5,9 +5,22 @@ import 'lottie_drawable.dart';
import 'lottie_image_asset.dart';
import 'value_delegate.dart';
// TODO(xha): recognize style Bold, Medium, Regular, SemiBold, etc...
TextStyle defaultTextStyleDelegate(LottieFontStyle font) =>
TextStyle(fontFamily: font.fontFamily);
TextStyle defaultTextStyleDelegate(LottieFontStyle font) {
var style = font.style.toLowerCase();
var fontStyle = style.contains('italic') ? FontStyle.italic : null;
FontWeight? fontWeight;
if (style.contains('semibold') || style.contains('semi bold')) {
fontWeight = FontWeight.w600;
} else if (style.contains('bold')) {
fontWeight = FontWeight.bold;
}
return TextStyle(
fontFamily: font.fontFamily,
fontStyle: fontStyle,
fontWeight: fontWeight);
}
@immutable
class LottieDelegates {
@ -82,5 +95,5 @@ class LottieDelegates {
values == other.values;
@override
int get hashCode => hashValues(text, textStyle, values);
int get hashCode => Object.hash(text, textStyle, values);
}

View File

@ -16,16 +16,15 @@ class LottieDrawable {
final Size size;
LottieDelegates? _delegates;
bool _isDirty = true;
final bool enableMergePaths;
bool enableMergePaths = false;
FilterQuality? filterQuality;
/// Gives a suggestion whether to paint with anti-aliasing, or not. Default is true.
bool antiAliasingSuggested = true;
LottieDrawable(this.composition,
{LottieDelegates? delegates, bool? enableMergePaths})
LottieDrawable(this.composition, {LottieDelegates? delegates})
: size = Size(composition.bounds.width.toDouble(),
composition.bounds.height.toDouble()),
enableMergePaths = enableMergePaths ?? false {
composition.bounds.height.toDouble()) {
this.delegates = delegates;
_compositionLayer = CompositionLayer(
this, LayerParser.parse(composition), composition.layers, composition);

View File

@ -1,11 +1,9 @@
import 'dart:ui';
import '../../animation/keyframe/color_keyframe_animation.dart';
import '../../value/keyframe.dart';
import 'base_animatable_value.dart';
class AnimatableColorValue extends BaseAnimatableValue<Color, Color> {
AnimatableColorValue.fromKeyframes(List<Keyframe<Color>> keyframes)
: super.fromKeyframes(keyframes);
AnimatableColorValue.fromKeyframes(super.keyframes) : super.fromKeyframes();
@override
ColorKeyframeAnimation createAnimation() {

View File

@ -1,12 +1,10 @@
import '../../animation/keyframe/double_keyframe_animation.dart';
import '../../value/keyframe.dart';
import 'base_animatable_value.dart';
class AnimatableDoubleValue extends BaseAnimatableValue<double, double> {
AnimatableDoubleValue() : super.fromValue(0.0);
AnimatableDoubleValue.fromKeyframes(List<Keyframe<double>> keyframes)
: super.fromKeyframes(keyframes);
AnimatableDoubleValue.fromKeyframes(super.keyframes) : super.fromKeyframes();
@override
DoubleKeyframeAnimation createAnimation() {

View File

@ -7,7 +7,51 @@ class AnimatableGradientColorValue
extends BaseAnimatableValue<GradientColor, GradientColor> {
AnimatableGradientColorValue.fromKeyframes(
List<Keyframe<GradientColor>> keyframes)
: super.fromKeyframes(keyframes);
: super.fromKeyframes(_ensureInterpolatableKeyframes(keyframes));
static List<Keyframe<GradientColor>> _ensureInterpolatableKeyframes(
List<Keyframe<GradientColor>> keyframes) {
for (var i = 0; i < keyframes.length; i++) {
keyframes[i] = _ensureInterpolatableKeyframe(keyframes[i]);
}
return keyframes;
}
static Keyframe<GradientColor> _ensureInterpolatableKeyframe(
Keyframe<GradientColor> keyframe) {
var startValue = keyframe.startValue;
var endValue = keyframe.endValue;
if (startValue == null ||
endValue == null ||
startValue.positions.length == endValue.positions.length) {
return keyframe;
}
var mergedPositions =
_mergePositions(startValue.positions, endValue.positions);
// The start/end has opacity stops which required adding extra positions in between the existing colors.
return keyframe.copyWith(startValue.copyWithPositions(mergedPositions),
endValue.copyWithPositions(mergedPositions));
}
static List<double> _mergePositions(
List<double> startPositions, List<double> endPositions) {
var mergedArray =
List<double>.filled(startPositions.length + endPositions.length, 0);
mergedArray.setRange(0, startPositions.length, startPositions);
mergedArray.setRange(startPositions.length,
startPositions.length + endPositions.length, endPositions);
mergedArray.sort();
var uniqueValues = 0;
var lastValue = double.nan;
for (var i = 0; i < mergedArray.length; i++) {
if (mergedArray[i] != lastValue) {
mergedArray[uniqueValues] = mergedArray[i];
uniqueValues++;
lastValue = mergedArray[i];
}
}
return mergedArray.take(uniqueValues).toList();
}
@override
GradientColorKeyframeAnimation createAnimation() {

View File

@ -1,13 +1,11 @@
import '../../animation/keyframe/base_keyframe_animation.dart';
import '../../animation/keyframe/integer_keyframe_animation.dart';
import '../../value/keyframe.dart';
import 'base_animatable_value.dart';
class AnimatableIntegerValue extends BaseAnimatableValue<int, int> {
AnimatableIntegerValue() : super.fromValue(100);
AnimatableIntegerValue.fromKeyframes(List<Keyframe<int>> keyframes)
: super.fromKeyframes(keyframes);
AnimatableIntegerValue.fromKeyframes(super.keyframes) : super.fromKeyframes();
@override
BaseKeyframeAnimation<int, int> createAnimation() {

View File

@ -1,11 +1,9 @@
import 'dart:ui';
import '../../animation/keyframe/point_keyframe_animation.dart';
import '../../value/keyframe.dart';
import 'base_animatable_value.dart';
class AnimatablePointValue extends BaseAnimatableValue<Offset, Offset> {
AnimatablePointValue.fromKeyframes(List<Keyframe<Offset>> keyframes)
: super.fromKeyframes(keyframes);
AnimatablePointValue.fromKeyframes(super.keyframes) : super.fromKeyframes();
@override
PointKeyframeAnimation createAnimation() {

View File

@ -1,16 +1,14 @@
import 'dart:ui';
import '../../animation/keyframe/base_keyframe_animation.dart';
import '../../animation/keyframe/point_keyframe_animation.dart';
import '../../value/keyframe.dart';
import 'base_animatable_value.dart';
class AnimatableScaleValue extends BaseAnimatableValue<Offset, Offset> {
AnimatableScaleValue.one() : this(const Offset(1, 1));
AnimatableScaleValue(Offset value) : super.fromValue(value);
AnimatableScaleValue(super.value) : super.fromValue();
AnimatableScaleValue.fromKeyframes(List<Keyframe<Offset>> keyframes)
: super.fromKeyframes(keyframes);
AnimatableScaleValue.fromKeyframes(super.keyframes) : super.fromKeyframes();
@override
BaseKeyframeAnimation<Offset, Offset> createAnimation() {

View File

@ -1,12 +1,10 @@
import 'dart:ui';
import '../../animation/keyframe/shape_keyframe_animation.dart';
import '../../value/keyframe.dart';
import '../content/shape_data.dart';
import 'base_animatable_value.dart';
class AnimatableShapeValue extends BaseAnimatableValue<ShapeData, Path> {
AnimatableShapeValue.fromKeyframes(List<Keyframe<ShapeData>> keyframes)
: super.fromKeyframes(keyframes);
AnimatableShapeValue.fromKeyframes(super.keyframes) : super.fromKeyframes();
@override
ShapeKeyframeAnimation createAnimation() {

View File

@ -1,12 +1,10 @@
import '../../animation/keyframe/text_keyframe_animation.dart';
import '../../value/keyframe.dart';
import '../document_data.dart';
import 'base_animatable_value.dart';
class AnimatableTextFrame
extends BaseAnimatableValue<DocumentData, DocumentData> {
AnimatableTextFrame.fromKeyframes(List<Keyframe<DocumentData>> keyframes)
: super.fromKeyframes(keyframes);
AnimatableTextFrame.fromKeyframes(super.keyframes) : super.fromKeyframes();
@override
TextKeyframeAnimation createAnimation() {

View File

@ -1,4 +1,5 @@
import 'dart:ui';
import '../../utils/collection.dart';
import '../../utils/gamma_evaluator.dart';
class GradientColor {
@ -21,4 +22,33 @@ class GradientColor {
GammaEvaluator.evaluate(progress, gc1.colors[i], gc2.colors[i]);
}
}
GradientColor copyWithPositions(List<double> positions) {
var colors = List<Color>.filled(positions.length, const Color(0x00000000));
for (var i = 0; i < positions.length; i++) {
colors[i] = _getColorForPosition(positions[i]);
}
return GradientColor(positions, colors);
}
Color _getColorForPosition(double position) {
var existingIndex = binarySearch(positions, position);
if (existingIndex >= 0) {
return colors[existingIndex];
}
// binarySearch returns -insertionPoint - 1 if it is not found.
var insertionPoint = -(existingIndex + 1);
if (insertionPoint == 0) {
return colors[0];
} else if (insertionPoint == colors.length - 1) {
return colors[colors.length - 1];
}
var startPosition = positions[insertionPoint - 1];
var endPosition = positions[insertionPoint];
var startColor = colors[insertionPoint - 1];
var endColor = colors[insertionPoint];
var fraction = (position - startPosition) / (endPosition - startPosition);
return GammaEvaluator.evaluate(fraction, startColor, endColor);
}
}

View File

@ -8,12 +8,16 @@ class DocumentData {
final double size;
final Justification justification;
final int tracking;
/// Extra space in between lines. */
final double lineHeight;
final double baselineShift;
final Color color;
final Color strokeColor;
final double strokeWidth;
final bool strokeOverFill;
final Offset? boxPosition;
final Offset? boxSize;
DocumentData({
required this.text,
@ -27,22 +31,27 @@ class DocumentData {
required this.strokeColor,
required this.strokeWidth,
required this.strokeOverFill,
required this.boxPosition,
required this.boxSize,
});
@override
int get hashCode {
return hashValues(
text,
fontName,
size,
justification.index,
tracking,
lineHeight,
baselineShift,
color,
strokeColor,
strokeWidth,
strokeOverFill);
return Object.hash(
text,
fontName,
size,
justification.index,
tracking,
lineHeight,
baselineShift,
color,
strokeColor,
strokeWidth,
strokeOverFill,
boxPosition,
boxSize,
);
}
@override
@ -60,5 +69,7 @@ class DocumentData {
color == other.color &&
strokeColor == other.strokeColor &&
strokeWidth == other.strokeWidth &&
strokeOverFill == other.strokeOverFill;
strokeOverFill == other.strokeOverFill &&
boxPosition == other.boxPosition &&
boxSize == other.boxSize;
}

View File

@ -2,8 +2,7 @@ import 'content/shape_group.dart';
class FontCharacter {
static int hashFor(String character, String fontFamily, String style) {
var result = 0;
result = 31 * result + character.hashCode;
var result = character.hashCode;
result = 31 * result + fontFamily.hashCode;
result = 31 * result + style.hashCode;
return result;

View File

@ -2,19 +2,16 @@ import 'dart:ui';
import 'package:vector_math/vector_math_64.dart';
import '../../animation/keyframe/base_keyframe_animation.dart';
import '../../animation/keyframe/value_callback_keyframe_animation.dart';
import '../../lottie_drawable.dart';
import '../../lottie_property.dart';
import '../../utils.dart';
import '../../value/lottie_value_callback.dart';
import 'base_layer.dart';
import 'layer.dart';
class ImageLayer extends BaseLayer {
final Paint paint = Paint();
BaseKeyframeAnimation<ColorFilter, ColorFilter?>? _colorFilterAnimation;
ImageLayer(LottieDrawable lottieDrawable, Layer layerModel)
: super(lottieDrawable, layerModel);
ImageLayer(super.lottieDrawable, super.layerModel);
@override
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,
@ -23,8 +20,8 @@ class ImageLayer extends BaseLayer {
if (bitmap == null) {
return;
}
var density = window.devicePixelRatio;
paint.filterQuality = lottieDrawable.filterQuality ?? FilterQuality.low;
paint.setAlpha(parentAlpha);
if (_colorFilterAnimation != null) {
paint.colorFilter = _colorFilterAnimation!.value;
@ -33,8 +30,8 @@ class ImageLayer extends BaseLayer {
canvas.transform(parentMatrix.storage);
var src =
Rect.fromLTWH(0, 0, bitmap.width.toDouble(), bitmap.height.toDouble());
var dst = Rect.fromLTWH(
0, 0, bitmap.width * density, bitmap.height.toDouble() * density);
var dst =
Rect.fromLTWH(0, 0, bitmap.width.toDouble(), bitmap.height.toDouble());
canvas.drawImageRect(bitmap, src, dst, paint);
canvas.restore();
}
@ -44,8 +41,8 @@ class ImageLayer extends BaseLayer {
var superBounds = super.getBounds(parentMatrix, applyParents: applyParents);
var bitmap = getBitmap();
if (bitmap != null) {
var bounds = Rect.fromLTWH(0, 0, bitmap.width * window.devicePixelRatio,
bitmap.height * window.devicePixelRatio);
var bounds = Rect.fromLTWH(
0, 0, bitmap.width.toDouble(), bitmap.height.toDouble());
return boundsMatrix.mapRect(bounds);
}
return superBounds;

View File

@ -1,12 +1,9 @@
import 'dart:ui';
import 'package:vector_math/vector_math_64.dart';
import '../../lottie_drawable.dart';
import 'base_layer.dart';
import 'layer.dart';
class NullLayer extends BaseLayer {
NullLayer(LottieDrawable lottieDrawable, Layer layerModel)
: super(lottieDrawable, layerModel);
NullLayer(super.lottieDrawable, super.layerModel);
@override
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,

View File

@ -1,4 +1,3 @@
import 'dart:ui';
import 'package:flutter/widgets.dart';
import '../../animation/content/content_group.dart';
import '../../animation/keyframe/base_keyframe_animation.dart';
@ -8,6 +7,7 @@ import '../../composition.dart';
import '../../lottie_drawable.dart';
import '../../lottie_property.dart';
import '../../utils.dart';
import '../../utils/characters.dart';
import '../../value/lottie_value_callback.dart';
import '../document_data.dart';
import '../font.dart';
@ -22,6 +22,9 @@ class TextLayer extends BaseLayer {
final _fillPaint = Paint()..style = PaintingStyle.fill;
final _strokePaint = Paint()..style = PaintingStyle.stroke;
final _contentsForCharacter = <FontCharacter, List<ContentGroup>>{};
/// If this is paragraph text, one line may wrap depending on the size of the document data box.
final _textSubLines = <_TextSubLine>[];
final TextKeyframeAnimation _textAnimation;
final LottieComposition _composition;
@ -89,18 +92,26 @@ class TextLayer extends BaseLayer {
@override
void drawLayer(Canvas canvas, Size size, Matrix4 parentMatrix,
{required int parentAlpha}) {
canvas.save();
if (!lottieDrawable.useTextGlyphs) {
canvas.transform(parentMatrix.storage);
}
var documentData = _textAnimation.value;
var font = _composition.fonts[documentData.fontName];
if (font == null) {
// Something is wrong.
canvas.restore();
return;
}
canvas.save();
canvas.transform(parentMatrix.storage);
_configurePaint(documentData, parentMatrix);
if (lottieDrawable.useTextGlyphs) {
_drawTextWithGlyphs(documentData, parentMatrix, font, canvas);
} else {
_drawTextWithFont(documentData, font, canvas);
}
canvas.restore();
}
void _configurePaint(DocumentData documentData, Matrix4 parentMatrix) {
Color fillPaintColor;
if (_colorCallbackAnimation != null) {
fillPaintColor = _colorCallbackAnimation!.value;
@ -131,21 +142,11 @@ class TextLayer extends BaseLayer {
} else if (_strokeWidthAnimation != null) {
_strokePaint.strokeWidth = _strokeWidthAnimation!.value;
} else {
var parentScale = parentMatrix.getScale();
_strokePaint.strokeWidth =
documentData.strokeWidth * window.devicePixelRatio * parentScale;
_strokePaint.strokeWidth = documentData.strokeWidth;
}
if (lottieDrawable.useTextGlyphs) {
_drawTextGlyphs(documentData, parentMatrix, font, canvas);
} else {
_drawTextWithFont(documentData, font, parentMatrix, canvas);
}
canvas.restore();
}
void _drawTextGlyphs(DocumentData documentData, Matrix4 parentMatrix,
void _drawTextWithGlyphs(DocumentData documentData, Matrix4 parentMatrix,
Font font, Canvas canvas) {
double textSize;
if (_textSizeCallbackAnimation != null) {
@ -160,70 +161,54 @@ class TextLayer extends BaseLayer {
var text = documentData.text;
// Line height
var lineHeight = documentData.lineHeight * window.devicePixelRatio;
// Split full text in multiple lines
var textLines = _getTextLines(text);
var textLineCount = textLines.length;
for (var l = 0; l < textLineCount; l++) {
var textLine = textLines[l];
var textLineWidth =
_getTextLineWidthForGlyphs(textLine, font, fontScale, parentScale);
// Add tracking
var tracking = documentData.tracking / 10;
if (_trackingCallbackAnimation != null) {
tracking += _trackingCallbackAnimation!.value;
} else if (_trackingAnimation != null) {
tracking += _trackingAnimation!.value;
}
var lineIndex = -1;
for (var i = 0; i < textLineCount; i++) {
var textLine = textLines[i];
var boxWidth = documentData.boxSize?.dx ?? 0.0;
var lines = _splitGlyphTextIntoLines(
textLine, boxWidth, font, fontScale, tracking, null);
for (var j = 0; j < lines.length; j++) {
var line = lines[j];
lineIndex++;
canvas.save();
canvas.save();
// Apply horizontal justification
_applyJustification(documentData.justification, canvas, textLineWidth);
_offsetCanvas(canvas, documentData, lineIndex, line.width);
_drawGlyphTextLine(line.text, documentData, font, canvas, parentScale,
fontScale, tracking);
// Center text vertically
var multilineTranslateY = (textLineCount - 1) * lineHeight / 2;
var translateY = l * lineHeight - multilineTranslateY;
canvas.translate(0, translateY);
// Draw each line
_drawGlyphTextLine(textLine, documentData, parentMatrix, font, canvas,
parentScale, fontScale);
// Reset canvas
canvas.restore();
canvas.restore();
}
}
}
void _drawGlyphTextLine(
String text,
DocumentData documentData,
Matrix4 parentMatrix,
Font font,
Canvas canvas,
double parentScale,
double fontScale) {
for (var i = 0; i < text.length; i++) {
var c = text[i];
var characterHash = FontCharacter.hashFor(c, font.family, font.style);
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 character = _composition.characters[characterHash];
if (character == null) {
// Something is wrong. Potentially, they didn't export the text as a glyph.
continue;
}
_drawCharacterAsGlyph(
character, parentMatrix, fontScale, documentData, canvas);
var tx =
character.width * fontScale * window.devicePixelRatio * parentScale;
// Add tracking
var tracking = documentData.tracking / 10.0;
if (_trackingCallbackAnimation != null) {
tracking += _trackingCallbackAnimation!.value;
} else if (_trackingAnimation != null) {
tracking += _trackingAnimation!.value;
}
tx += tracking * parentScale;
_drawCharacterAsGlyph(character, fontScale, documentData, canvas);
var tx = character.width * fontScale + tracking;
canvas.translate(tx, 0);
}
}
void _drawTextWithFont(DocumentData documentData, Font font,
Matrix4 parentMatrix, Canvas canvas) {
void _drawTextWithFont(DocumentData documentData, Font font, Canvas canvas) {
var textStyle = lottieDrawable.getTextStyle(font.family, font.style);
var text = documentData.text;
var textDelegate = lottieDrawable.delegates?.text;
@ -238,11 +223,7 @@ class TextLayer extends BaseLayer {
} else {
textSize = documentData.size;
}
textStyle =
textStyle.copyWith(fontSize: textSize * window.devicePixelRatio);
// Line height
var lineHeight = documentData.lineHeight * window.devicePixelRatio;
textStyle = textStyle.copyWith(fontSize: textSize);
// Calculate tracking
var tracking = documentData.tracking / 10;
@ -251,49 +232,65 @@ class TextLayer extends BaseLayer {
} else if (_trackingAnimation != null) {
tracking += _trackingAnimation!.value;
}
tracking = tracking * window.devicePixelRatio * textSize / 100.0;
tracking = tracking * textSize / 100.0;
// Split full text in multiple lines
var textLines = _getTextLines(text);
var textLineCount = textLines.length;
for (var l = 0; l < textLineCount; l++) {
var textLine = textLines[l];
var textPainter = TextPainter(
text: TextSpan(text: textLine, style: textStyle),
textDirection: _textDirection);
textPainter.layout();
var textLineWidth = textPainter.width;
// We have to manually add the tracking between characters as the strokePaint ignores it
textLineWidth += (textLine.length - 1) * tracking;
var lineIndex = -1;
for (var i = 0; i < textLineCount; i++) {
var textLine = textLines[i];
var boxWidth = documentData.boxSize?.dx ?? 0.0;
var lines = _splitGlyphTextIntoLines(
textLine, boxWidth, font, 0.0, tracking, textStyle);
for (var j = 0; j < lines.length; j++) {
var line = lines[j];
lineIndex++;
canvas.save();
canvas.save();
// Apply horizontal justification
_applyJustification(documentData.justification, canvas, textLineWidth);
_offsetCanvas(canvas, documentData, lineIndex, line.width);
_drawFontTextLine(line.text, textStyle, documentData, canvas, tracking);
// Center text vertically
var multilineTranslateY = (textLineCount - 1) * lineHeight / 2;
var translateY = l * lineHeight - multilineTranslateY;
canvas.translate(0, translateY);
// Draw each line
_drawFontTextLine(textLine, textStyle, documentData, canvas, tracking);
// Reset canvas
canvas.restore();
canvas.restore();
}
}
}
List<String> _getTextLines(String text) {
// Split full text by carriage return character
var formattedText = text.replaceAll('\r\n', '\r').replaceAll('\n', '\r');
var textLinesArray = formattedText.split('\r');
return textLinesArray;
void _offsetCanvas(Canvas canvas, DocumentData documentData, int lineIndex,
double lineWidth) {
var position = documentData.boxPosition;
var size = documentData.boxSize;
var lineOffset = lineIndex * documentData.lineHeight;
var lineStart = position?.dx ?? 0.0;
var boxWidth = size?.dx ?? 0.0;
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;
}
}
void _drawFontTextLine(String text, TextStyle textStyle,
List<Characters> _getTextLines(String text) {
// Split full text by carriage return character
var formattedText = text
.replaceAll('\r\n', '\r')
.replaceAll('\u0003', '\r')
.replaceAll('\n', '\r');
var textLinesArray = formattedText.split('\r');
return textLinesArray.map((l) => l.characters).toList();
}
void _drawFontTextLine(Characters text, TextStyle textStyle,
DocumentData documentData, Canvas canvas, double tracking) {
for (var char in text.characters) {
for (var char in text) {
var charString = char;
_drawCharacterFromFont(charString, textStyle, documentData, canvas);
var textPainter = TextPainter(
@ -306,46 +303,110 @@ class TextLayer extends BaseLayer {
}
}
double _getTextLineWidthForGlyphs(
String textLine, Font font, double fontScale, double parentScale) {
var textLineWidth = 0.0;
for (var i = 0; i < textLine.length; i++) {
var c = textLine[i];
var characterHash = FontCharacter.hashFor(c, font.family, font.style);
var character = _composition.characters[characterHash];
if (character == null) {
continue;
List<_TextSubLine> _splitGlyphTextIntoLines(
Characters textLine,
double boxWidth,
Font font,
double fontScale,
double tracking,
TextStyle? textStyle) {
var usingGlyphs = textStyle == null;
var lineCount = 0;
var currentLineWidth = 0.0;
var currentLineStartIndex = 0;
var currentWordStartIndex = 0;
var currentWordWidth = 0.0;
var nextCharacterStartsWord = false;
// The measured size of a space.
var spaceWidth = 0.0;
var textPainter = TextPainter(
text: TextSpan(text: '', style: textStyle),
textDirection: _textDirection);
var i = 0;
for (var c in textLine) {
double currentCharWidth;
if (usingGlyphs) {
var characterHash = FontCharacter.hashFor(c, font.family, font.style);
var character = _composition.characters[characterHash];
if (character == null) {
continue;
}
currentCharWidth = character.width * fontScale + tracking;
} else {
textPainter.text = TextSpan(text: c, style: textStyle);
textPainter.layout();
currentCharWidth = textPainter.width + tracking;
}
textLineWidth +=
character.width * fontScale * window.devicePixelRatio * parentScale;
if (c == ' ') {
spaceWidth = currentCharWidth;
nextCharacterStartsWord = true;
} else if (nextCharacterStartsWord) {
nextCharacterStartsWord = false;
currentWordStartIndex = i;
currentWordWidth = currentCharWidth;
} else {
currentWordWidth += currentCharWidth;
}
currentLineWidth += currentCharWidth;
if (boxWidth > 0 && currentLineWidth >= boxWidth) {
if (c == ' ') {
// Spaces at the end of a line don't do anything. Ignore it.
// The next non-space character will hit the conditions below.
continue;
}
var subLine = _ensureEnoughSubLines(++lineCount);
if (currentWordStartIndex == currentLineStartIndex) {
// Only word on line is wider than box, start wrapping mid-word.
var substr = textLine.getRange(currentLineStartIndex, i);
var trimmed = substr.trim(' '.characters);
var trimmedSpace = (trimmed.length - substr.length) * spaceWidth;
subLine.set(
trimmed, currentLineWidth - currentCharWidth - trimmedSpace);
currentLineStartIndex = i;
currentLineWidth = currentCharWidth;
currentWordStartIndex = currentLineStartIndex;
currentWordWidth = currentCharWidth;
} else {
var substr = textLine.getRange(
currentLineStartIndex, currentWordStartIndex - 1);
var trimmed = substr.trim(' '.characters);
var trimmedSpace = (substr.length - trimmed.length) * spaceWidth;
subLine.set(trimmed,
currentLineWidth - currentWordWidth - trimmedSpace - spaceWidth);
currentLineStartIndex = currentWordStartIndex;
currentLineWidth = currentWordWidth;
}
}
++i;
}
return textLineWidth;
if (currentLineWidth > 0) {
var line = _ensureEnoughSubLines(++lineCount);
line.set(textLine.getRange(currentLineStartIndex), currentLineWidth);
}
return _textSubLines.sublist(0, lineCount);
}
void _applyJustification(
Justification justification, Canvas canvas, double textLineWidth) {
switch (justification) {
case Justification.leftAlign:
// Do nothing. Default is left aligned.
break;
case Justification.rightAlign:
canvas.translate(-textLineWidth, 0);
break;
case Justification.center:
canvas.translate(-textLineWidth / 2, 0);
break;
/// Elements are reused and not deleted to save allocations.
_TextSubLine _ensureEnoughSubLines(int numLines) {
for (var i = _textSubLines.length; i < numLines; i++) {
_textSubLines.add(_TextSubLine());
}
return _textSubLines[numLines - 1];
}
void _drawCharacterAsGlyph(FontCharacter character, Matrix4 parentMatrix,
double fontScale, DocumentData documentData, Canvas canvas) {
void _drawCharacterAsGlyph(FontCharacter character, double fontScale,
DocumentData documentData, Canvas canvas) {
var contentGroups = _getContentsForCharacter(character);
for (var j = 0; j < contentGroups.length; j++) {
var path = contentGroups[j].getPath();
path.getBounds();
_matrix.set(parentMatrix);
_matrix.translate(
0.0, -documentData.baselineShift * window.devicePixelRatio);
_matrix.reset();
_matrix.translate(0.0, -documentData.baselineShift);
_matrix.scale(fontScale, fontScale);
path = path.transform(_matrix.storage);
if (documentData.strokeOverFill) {
@ -492,3 +553,13 @@ class TextLayer extends BaseLayer {
}
}
}
class _TextSubLine {
Characters text = Characters.empty;
double width = 0.0;
void set(Characters text, double width) {
this.text = text;
this.width = width;
}
}

View File

@ -27,8 +27,8 @@ class AnimatablePathValueParser {
reader.endArray();
KeyframesParser.setEndFrames(keyframes);
} else {
keyframes.add(Keyframe<Offset>.nonAnimated(
JsonUtils.jsonToPoint(reader, window.devicePixelRatio)));
keyframes
.add(Keyframe<Offset>.nonAnimated(JsonUtils.jsonToPoint(reader)));
}
return AnimatablePathValue.fromKeyframes(keyframes);
}

View File

@ -74,8 +74,7 @@ class AnimatableTransformParser {
// ]
// },
// which doesn't parse to a real keyframe.
rotation = AnimatableValueParser.parseFloat(reader, composition,
isDp: false);
rotation = AnimatableValueParser.parseFloat(reader, composition);
if (rotation.keyframes.isEmpty) {
rotation.keyframes.add(Keyframe(composition,
startValue: 0.0,
@ -96,20 +95,16 @@ class AnimatableTransformParser {
opacity = AnimatableValueParser.parseInteger(reader, composition);
break;
case 6:
startOpacity = AnimatableValueParser.parseFloat(reader, composition,
isDp: false);
startOpacity = AnimatableValueParser.parseFloat(reader, composition);
break;
case 7:
endOpacity = AnimatableValueParser.parseFloat(reader, composition,
isDp: false);
endOpacity = AnimatableValueParser.parseFloat(reader, composition);
break;
case 8:
skew = AnimatableValueParser.parseFloat(reader, composition,
isDp: false);
skew = AnimatableValueParser.parseFloat(reader, composition);
break;
case 9:
skewAngle = AnimatableValueParser.parseFloat(reader, composition,
isDp: false);
skewAngle = AnimatableValueParser.parseFloat(reader, composition);
break;
default:
reader.skipName();

View File

@ -1,4 +1,3 @@
import 'dart:ui';
import '../composition.dart';
import '../model/animatable/animatable_color_value.dart';
import '../model/animatable/animatable_double_value.dart';
@ -25,12 +24,9 @@ class AnimatableValueParser {
AnimatableValueParser._();
static AnimatableDoubleValue parseFloat(
JsonReader reader, LottieComposition composition,
{bool? isDp}) {
isDp ??= true;
return AnimatableDoubleValue.fromKeyframes(parse(
reader, composition, floatParser,
scale: isDp ? window.devicePixelRatio : 1.0));
JsonReader reader, LottieComposition composition) {
return AnimatableDoubleValue.fromKeyframes(
parse(reader, composition, floatParser));
}
static AnimatableIntegerValue parseInteger(
@ -42,7 +38,7 @@ class AnimatableValueParser {
static AnimatablePointValue parsePoint(
JsonReader reader, LottieComposition composition) {
return AnimatablePointValue.fromKeyframes(KeyframesParser.parse(
reader, composition, window.devicePixelRatio, offsetParser,
reader, composition, offsetParser,
multiDimensional: true));
}
@ -54,9 +50,8 @@ class AnimatableValueParser {
static AnimatableShapeValue parseShapeData(
JsonReader reader, LottieComposition composition) {
return AnimatableShapeValue.fromKeyframes(parse(
reader, composition, shapeDataParser,
scale: window.devicePixelRatio));
return AnimatableShapeValue.fromKeyframes(
parse(reader, composition, shapeDataParser));
}
static AnimatableTextFrame parseDocumentData(
@ -78,9 +73,7 @@ class AnimatableValueParser {
}
static List<Keyframe<T>> parse<T>(JsonReader reader,
LottieComposition composition, ValueParser<T> valueParser,
{double? scale}) {
scale ??= 1.0;
return KeyframesParser.parse(reader, composition, scale, valueParser);
LottieComposition composition, ValueParser<T> valueParser) {
return KeyframesParser.parse(reader, composition, valueParser);
}
}

View File

@ -1,7 +1,7 @@
import 'dart:ui';
import 'moshi/json_reader.dart';
Color colorParser(JsonReader reader, {required double scale}) {
Color colorParser(JsonReader reader) {
var isArray = reader.peek() == Token.beginArray;
if (isArray) {
reader.beginArray();

View File

@ -15,9 +15,11 @@ final JsonReaderOptions _names = JsonReaderOptions.of([
'sc', // 8
'sw', // 9
'of', // 10
'ps', // 11
'sz', // 12
]);
DocumentData documentDataParser(JsonReader reader, {required double scale}) {
DocumentData documentDataParser(JsonReader reader) {
String? text;
String? fontName;
var size = 0.0;
@ -29,6 +31,8 @@ DocumentData documentDataParser(JsonReader reader, {required double scale}) {
var strokeColor = const Color(0x00000000);
var strokeWidth = 0.0;
var strokeOverFill = true;
Offset? boxPosition;
Offset? boxSize;
reader.beginObject();
while (reader.hasNext()) {
@ -72,6 +76,16 @@ DocumentData documentDataParser(JsonReader reader, {required double scale}) {
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();
@ -80,15 +94,18 @@ DocumentData documentDataParser(JsonReader reader, {required double scale}) {
reader.endObject();
return DocumentData(
text: text ?? '',
fontName: fontName,
size: size,
justification: justification,
tracking: tracking,
lineHeight: lineHeight,
baselineShift: baselineShift,
color: fillColor,
strokeColor: strokeColor,
strokeWidth: strokeWidth,
strokeOverFill: strokeOverFill);
text: text ?? '',
fontName: fontName,
size: size,
justification: justification,
tracking: tracking,
lineHeight: lineHeight,
baselineShift: baselineShift,
color: fillColor,
strokeColor: strokeColor,
strokeWidth: strokeWidth,
strokeOverFill: strokeOverFill,
boxPosition: boxPosition,
boxSize: boxSize,
);
}

View File

@ -69,12 +69,11 @@ class DropShadowEffectParser {
_color = AnimatableValueParser.parseColor(reader, composition);
break;
case 'Opacity':
_opacity = AnimatableValueParser.parseFloat(reader, composition,
isDp: false);
_opacity = AnimatableValueParser.parseFloat(reader, composition);
break;
case 'Direction':
_direction = AnimatableValueParser.parseFloat(reader, composition,
isDp: false);
_direction =
AnimatableValueParser.parseFloat(reader, composition);
break;
case 'Distance':
_distance = AnimatableValueParser.parseFloat(reader, composition);

View File

@ -1,6 +1,6 @@
import 'json_utils.dart';
import 'moshi/json_reader.dart';
double floatParser(JsonReader reader, {required double scale}) {
return JsonUtils.valueFromObject(reader) * scale;
double floatParser(JsonReader reader) {
return JsonUtils.valueFromObject(reader);
}

View File

@ -1,5 +1,7 @@
import 'dart:ui';
import '../model/content/gradient_color.dart';
import '../utils/collection.dart';
import '../utils/gamma_evaluator.dart';
import 'moshi/json_reader.dart';
class GradientColorParser {
@ -26,7 +28,7 @@ class GradientColorParser {
/// opacity,
/// ...
/// ]
GradientColor parse(JsonReader reader, {required double scale}) {
GradientColor parse(JsonReader reader) {
var array = <double>[];
// The array was started by Keyframe because it thought that this may be an array of keyframes
// but peek returned a number so it considered it a static array of numbers.
@ -82,7 +84,7 @@ class GradientColorParser {
}
var gradientColor = GradientColor(positions, colors);
_addOpacityStopsToGradientIfNeeded(gradientColor, array);
gradientColor = _addOpacityStopsToGradientIfNeeded(gradientColor, array);
return gradientColor;
}
@ -93,50 +95,159 @@ class GradientColorParser {
/// <p>
/// This should be a good approximation is nearly all cases. However, if there are many more
/// opacity stops than color stops, information will be lost.
void _addOpacityStopsToGradientIfNeeded(
GradientColor _addOpacityStopsToGradientIfNeeded(
GradientColor gradientColor, List<double> array) {
var startIndex = _colorPoints * 4;
if (array.length <= startIndex) {
return;
return gradientColor;
}
// When there are opacity stops, we create a merged list of color stops and opacity stops.
// For a given color stop, we linearly interpolate the opacity for the two opacity stops around it.
// For a given opacity stop, we linearly interpolate the color for the two color stops around it.
var colorStopPositions = gradientColor.positions;
var colorStopColors = gradientColor.colors;
var opacityStops = (array.length - startIndex) ~/ 2;
var positions = List<double>.filled(opacityStops, 0.0);
var opacities = List<double>.filled(opacityStops, 0.0);
var opacityStopPositions = List<double>.filled(opacityStops, 0.0);
var opacityStopOpacities = List<double>.filled(opacityStops, 0.0);
for (var i = startIndex, j = 0; i < array.length; i++) {
if (i % 2 == 0) {
positions[j] = array[i];
opacityStopPositions[j] = array[i];
} else {
opacities[j] = array[i];
opacityStopOpacities[j] = array[i];
j++;
}
}
for (var i = 0; i < gradientColor.size; i++) {
var color = gradientColor.colors[i];
color = color.withAlpha(_getOpacityAtPosition(
gradientColor.positions[i], positions, opacities));
gradientColor.colors[i] = color;
}
}
// Pre-SKIA (Oreo) devices render artifacts when there is two stops in the same position.
// As a result, we have to de-dupe the merge color and opacity stop positions.
var newPositions =
mergeUniqueElements(gradientColor.positions, opacityStopPositions);
var newColorPoints = newPositions.length;
var newColors = List<Color>.filled(newColorPoints, const Color(0xff000000));
int _getOpacityAtPosition(
double position, List<double> positions, List<double> opacities) {
for (var i = 1; i < positions.length; i++) {
var lastPosition = positions[i - 1];
var thisPosition = positions[i];
if (positions[i] >= position) {
var progress =
(position - lastPosition) / (thisPosition - lastPosition);
progress = progress.clamp(0, 1);
if (progress.isNaN) {
progress = 0.0;
for (var i = 0; i < newColorPoints; i++) {
var position = newPositions[i];
var colorStopIndex = binarySearch(colorStopPositions, position);
var opacityIndex = binarySearch(opacityStopPositions, position);
if (colorStopIndex < 0 || opacityIndex > 0) {
// This is a stop derived from an opacity stop.
if (opacityIndex < 0) {
// The formula here is derived from the return value for binarySearch. When an item isn't found, it returns -insertionPoint - 1.
opacityIndex = -(opacityIndex + 1);
}
return (255 * lerpDouble(opacities[i - 1], opacities[i], progress)!)
.round();
newColors[i] = _getColorInBetweenColorStops(
position,
opacityStopOpacities[opacityIndex],
colorStopPositions,
colorStopColors);
} else {
// This os a step derived from a color stop.
newColors[i] = _getColorInBetweenOpacityStops(
position,
colorStopColors[colorStopIndex],
opacityStopPositions,
opacityStopOpacities);
}
}
return (255 * opacities[opacities.length - 1]).round();
return GradientColor(newPositions, newColors);
}
Color _getColorInBetweenColorStops(double position, double opacity,
List<double> colorStopPositions, List<Color> colorStopColors) {
if (colorStopColors.length < 2 || position == colorStopPositions[0]) {
return colorStopColors[0];
}
for (var i = 1; i < colorStopPositions.length; i++) {
var colorStopPosition = colorStopPositions[i];
if (colorStopPosition < position && i != colorStopPositions.length - 1) {
continue;
}
// We found the position in which position is between i - 1 and i.
var distanceBetweenColors =
colorStopPositions[i] - colorStopPositions[i - 1];
var distanceToLowerColor = position - colorStopPositions[i - 1];
var percentage = distanceToLowerColor / distanceBetweenColors;
var upperColor = colorStopColors[i];
var lowerColor = colorStopColors[i - 1];
return GammaEvaluator.evaluate(
percentage, upperColor.withOpacity(1), lowerColor.withOpacity(1))
.withOpacity(opacity);
}
throw Exception('Unreachable code.');
}
Color _getColorInBetweenOpacityStops(double position, Color color,
List<double> opacityStopPositions, List<double> opacityStopOpacities) {
if (opacityStopOpacities.length < 2 ||
position <= opacityStopPositions[0]) {
return color.withOpacity(opacityStopOpacities[0]);
}
for (var i = 1; i < opacityStopPositions.length; i++) {
var opacityStopPosition = opacityStopPositions[i];
if (opacityStopPosition < position &&
i != opacityStopPositions.length - 1) {
continue;
}
final double opacity;
if (opacityStopPosition <= position) {
opacity = opacityStopOpacities[i];
} else {
// We found the position in which position in between i - 1 and i.
var distanceBetweenOpacities =
opacityStopPositions[i] - opacityStopPositions[i - 1];
var distanceToLowerOpacity = position - opacityStopPositions[i - 1];
var percentage = distanceToLowerOpacity / distanceBetweenOpacities;
opacity = lerpDouble(
opacityStopOpacities[i - 1], opacityStopOpacities[i], percentage)!;
}
return color.withOpacity(opacity);
}
throw Exception('Unreachable code.');
}
/// Takes two sorted float arrays and merges their elements while removing duplicates.
static List<double> mergeUniqueElements(
List<double> arrayA, List<double> arrayB) {
if (arrayA.isEmpty) {
return arrayB;
} else if (arrayB.isEmpty) {
return arrayA;
}
var aIndex = 0;
var bIndex = 0;
var numDuplicates = 0;
// This will be the merged list but may be longer than what is needed if there are duplicates.
// If there are, the 0 elements at the end need to be truncated.
var mergedNotTruncated =
List<double>.filled(arrayA.length + arrayB.length, 0);
for (var i = 0; i < mergedNotTruncated.length; i++) {
final a = aIndex < arrayA.length ? arrayA[aIndex] : double.nan;
final b = bIndex < arrayB.length ? arrayB[bIndex] : double.nan;
if (b.isNaN || a < b) {
mergedNotTruncated[i] = a;
aIndex++;
} else if (a.isNaN || b < a) {
mergedNotTruncated[i] = b;
bIndex++;
} else {
mergedNotTruncated[i] = a;
aIndex++;
bIndex++;
numDuplicates++;
}
}
if (numDuplicates == 0) {
return mergedNotTruncated;
}
return mergedNotTruncated
.take(mergedNotTruncated.length - numDuplicates)
.toList();
}
}

View File

@ -1,6 +1,6 @@
import 'json_utils.dart';
import 'moshi/json_reader.dart';
int integerParser(JsonReader reader, {required double scale}) {
return (JsonUtils.valueFromObject(reader) * scale).round();
int integerParser(JsonReader reader) {
return JsonUtils.valueFromObject(reader).round();
}

View File

@ -14,43 +14,43 @@ class JsonUtils {
return Color.fromARGB(255, r, g, b);
}
static List<Offset> jsonToPoints(JsonReader reader, double scale) {
static List<Offset> jsonToPoints(JsonReader reader) {
var points = <Offset>[];
reader.beginArray();
while (reader.peek() == Token.beginArray) {
reader.beginArray();
points.add(jsonToPoint(reader, scale));
points.add(jsonToPoint(reader));
reader.endArray();
}
reader.endArray();
return points;
}
static Offset jsonToPoint(JsonReader reader, double scale) {
static Offset jsonToPoint(JsonReader reader) {
switch (reader.peek()) {
case Token.number:
return _jsonNumbersToPoint(reader, scale);
return _jsonNumbersToPoint(reader);
case Token.beginArray:
return _jsonArrayToPoint(reader, scale);
return _jsonArrayToPoint(reader);
case Token.beginObject:
return _jsonObjectToPoint(reader, scale: scale);
return _jsonObjectToPoint(reader);
// ignore: no_default_cases
default:
throw Exception('Unknown point starts with ${reader.peek()}');
}
}
static Offset _jsonNumbersToPoint(JsonReader reader, double scale) {
static Offset _jsonNumbersToPoint(JsonReader reader) {
var x = reader.nextDouble();
var y = reader.nextDouble();
while (reader.hasNext()) {
reader.skipValue();
}
return Offset(x * scale, y * scale);
return Offset(x, y);
}
static Offset _jsonArrayToPoint(JsonReader reader, double scale) {
static Offset _jsonArrayToPoint(JsonReader reader) {
double x;
double y;
reader.beginArray();
@ -60,12 +60,12 @@ class JsonUtils {
reader.skipValue();
}
reader.endArray();
return Offset(x * scale, y * scale);
return Offset(x, y);
}
static final JsonReaderOptions _pointNames = JsonReaderOptions.of(['x', 'y']);
static Offset _jsonObjectToPoint(JsonReader reader, {required double scale}) {
static Offset _jsonObjectToPoint(JsonReader reader) {
var x = 0.0;
var y = 0.0;
reader.beginObject();
@ -83,7 +83,7 @@ class JsonUtils {
}
}
reader.endObject();
return Offset(x * scale, y * scale);
return Offset(x, y);
}
static double valueFromObject(JsonReader reader) {

View File

@ -26,22 +26,21 @@ class KeyframeParser {
/// @param multiDimensional When true, the keyframe interpolators can be independent for the X and Y axis.
static Keyframe<T> parse<T>(JsonReader reader, LottieComposition composition,
double scale, ValueParser<T> valueParser,
ValueParser<T> valueParser,
{required bool animated, bool multiDimensional = false}) {
if (animated && multiDimensional) {
return _parseMultiDimensionalKeyframe(
composition, reader, scale, valueParser);
return _parseMultiDimensionalKeyframe(composition, reader, valueParser);
} else if (animated) {
return _parseKeyframe(composition, reader, scale, valueParser);
return _parseKeyframe(composition, reader, valueParser);
} else {
return _parseStaticValue(reader, scale, valueParser);
return _parseStaticValue(reader, valueParser);
}
}
/// beginObject will already be called on the keyframe so it can be differentiated with
/// a non animated value.
static Keyframe<T> _parseKeyframe<T>(LottieComposition composition,
JsonReader reader, double scale, ValueParser<T> valueParser) {
JsonReader reader, ValueParser<T> valueParser) {
Offset? cp1;
Offset? cp2;
var startFrame = 0.0;
@ -61,25 +60,25 @@ class KeyframeParser {
startFrame = reader.nextDouble();
break;
case 1:
startValue = valueParser(reader, scale: scale);
startValue = valueParser(reader);
break;
case 2:
endValue = valueParser(reader, scale: scale);
endValue = valueParser(reader);
break;
case 3:
cp1 = JsonUtils.jsonToPoint(reader, 1);
cp1 = JsonUtils.jsonToPoint(reader);
break;
case 4:
cp2 = JsonUtils.jsonToPoint(reader, 1);
cp2 = JsonUtils.jsonToPoint(reader);
break;
case 5:
hold = reader.nextInt() == 1;
break;
case 6:
pathCp1 = JsonUtils.jsonToPoint(reader, scale);
pathCp1 = JsonUtils.jsonToPoint(reader);
break;
case 7:
pathCp2 = JsonUtils.jsonToPoint(reader, scale);
pathCp2 = JsonUtils.jsonToPoint(reader);
break;
default:
reader.skipValue();
@ -111,7 +110,6 @@ class KeyframeParser {
static Keyframe<T> _parseMultiDimensionalKeyframe<T>(
LottieComposition composition,
JsonReader reader,
double scale,
ValueParser<T> valueParser) {
Offset? cp1;
Offset? cp2;
@ -140,10 +138,10 @@ class KeyframeParser {
startFrame = reader.nextDouble();
break;
case 1: // s
startValue = valueParser(reader, scale: scale);
startValue = valueParser(reader);
break;
case 2: // e
endValue = valueParser(reader, scale: scale);
endValue = valueParser(reader);
break;
case 3: // o
if (reader.peek() == Token.beginObject) {
@ -192,7 +190,7 @@ class KeyframeParser {
yCp1 = Offset(yCp1x, yCp1y);
reader.endObject();
} else {
cp1 = JsonUtils.jsonToPoint(reader, scale);
cp1 = JsonUtils.jsonToPoint(reader);
}
break;
case 4: // i
@ -242,17 +240,17 @@ class KeyframeParser {
yCp2 = Offset(yCp2x, yCp2y);
reader.endObject();
} else {
cp2 = JsonUtils.jsonToPoint(reader, scale);
cp2 = JsonUtils.jsonToPoint(reader);
}
break;
case 5: // h
hold = reader.nextInt() == 1;
break;
case 6: // to
pathCp1 = JsonUtils.jsonToPoint(reader, scale);
pathCp1 = JsonUtils.jsonToPoint(reader);
break;
case 7: // ti
pathCp2 = JsonUtils.jsonToPoint(reader, scale);
pathCp2 = JsonUtils.jsonToPoint(reader);
break;
default:
reader.skipValue();
@ -322,8 +320,8 @@ class KeyframeParser {
}
static Keyframe<T> _parseStaticValue<T>(
JsonReader reader, double scale, ValueParser<T> valueParser) {
var value = valueParser(reader, scale: scale);
JsonReader reader, ValueParser<T> valueParser) {
var value = valueParser(reader);
return Keyframe<T>.nonAnimated(value);
}
}

View File

@ -11,7 +11,7 @@ class KeyframesParser {
KeyframesParser._();
static List<Keyframe<T>> parse<T>(JsonReader reader,
LottieComposition composition, double scale, ValueParser<T> valueParser,
LottieComposition composition, ValueParser<T> valueParser,
{bool multiDimensional = false}) {
var keyframes = <Keyframe<T>>[];
@ -30,19 +30,18 @@ class KeyframesParser {
if (reader.peek() == Token.number) {
// For properties in which the static value is an array of numbers.
keyframes.add(KeyframeParser.parse(
reader, composition, scale, valueParser,
reader, composition, valueParser,
animated: false, multiDimensional: multiDimensional));
} else {
while (reader.hasNext()) {
keyframes.add(KeyframeParser.parse(
reader, composition, scale, valueParser,
reader, composition, valueParser,
animated: true, multiDimensional: multiDimensional));
}
}
reader.endArray();
} else {
keyframes.add(KeyframeParser.parse(
reader, composition, scale, valueParser,
keyframes.add(KeyframeParser.parse(reader, composition, valueParser,
animated: false, multiDimensional: multiDimensional));
}
break;

View File

@ -136,10 +136,10 @@ class LayerParser {
parentId = reader.nextInt();
break;
case 5:
solidWidth = (reader.nextInt() * window.devicePixelRatio).round();
solidWidth = reader.nextInt();
break;
case 6:
solidHeight = (reader.nextInt() * window.devicePixelRatio).round();
solidHeight = reader.nextInt();
break;
case 7:
solidColor = MiscUtils.parseColor(reader.nextString(),
@ -246,10 +246,10 @@ class LayerParser {
startFrame = reader.nextDouble();
break;
case 16:
preCompWidth = (reader.nextInt() * window.devicePixelRatio).round();
preCompWidth = reader.nextInt();
break;
case 17:
preCompHeight = (reader.nextInt() * window.devicePixelRatio).round();
preCompHeight = reader.nextInt();
break;
case 18:
inFrame = reader.nextDouble();
@ -258,8 +258,7 @@ class LayerParser {
outFrame = reader.nextDouble();
break;
case 20:
timeRemapping = AnimatableValueParser.parseFloat(reader, composition,
isDp: false);
timeRemapping = AnimatableValueParser.parseFloat(reader, composition);
break;
case 21:
cl = reader.nextString();

View File

@ -1,4 +1,3 @@
import 'dart:ui';
import '../composition.dart';
import '../lottie_image_asset.dart';
import '../model/font.dart';
@ -29,16 +28,15 @@ class LottieCompositionParser {
static LottieComposition parse(
LottieComposition composition, JsonReader reader) {
var parameters = CompositionParameters.forComposition(composition);
var scale = window.devicePixelRatio;
reader.beginObject();
while (reader.hasNext()) {
switch (reader.selectName(_names)) {
case 0:
parameters.bounds.width = (reader.nextInt() * scale).round();
parameters.bounds.width = (reader.nextInt()).round();
break;
case 1:
parameters.bounds.height = (reader.nextInt() * scale).round();
parameters.bounds.height = (reader.nextInt()).round();
break;
case 2:
parameters.startFrame = reader.nextDouble();

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