[web] roll CanvasKit 0.32.0; fix frame order in animated images (flutter/engine#30680)
* roll CanvasKit 0.32.0 * Fix frame order in WASM image codecs
This commit is contained in:
2
DEPS
2
DEPS
@@ -31,7 +31,7 @@ vars = {
|
||||
|
||||
# WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY
|
||||
# See `lib/web_ui/README.md` for how to roll CanvasKit to a new version.
|
||||
'canvaskit_cipd_instance': 'NcwvqeeKK7urddCbEdDvHytdaCiCA_8-4oS_T_ouGfgC',
|
||||
'canvaskit_cipd_instance': 'CQJGaIvKwSuYCIi4hxn3jdY-Pcrdkcnnu65ZVt18oW8C',
|
||||
|
||||
# When updating the Dart revision, ensure that all entries that are
|
||||
# dependencies of Dart are also updated to match the entries in the
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Specifies the version of CanvasKit to use for Flutter Web apps.
|
||||
#
|
||||
# See `lib/web_ui/README.md` for how to update this file.
|
||||
canvaskit_version: "0.31.0"
|
||||
canvaskit_version: "0.32.0"
|
||||
|
||||
@@ -758,9 +758,14 @@ class SkColorType {
|
||||
class SkAnimatedImage {
|
||||
external int getFrameCount();
|
||||
|
||||
/// Returns duration in milliseconds.
|
||||
external int getRepetitionCount();
|
||||
|
||||
/// Returns duration in milliseconds.
|
||||
external int currentFrameDuration();
|
||||
|
||||
/// Advances to the next frame and returns its duration in milliseconds.
|
||||
external int decodeNextFrame();
|
||||
|
||||
external SkImage makeImageAtCurrentFrame();
|
||||
external int width();
|
||||
external int height();
|
||||
|
||||
@@ -31,8 +31,8 @@ class CkAnimatedImage extends ManagedSkiaObject<SkAnimatedImage>
|
||||
int _frameCount = 0;
|
||||
int _repetitionCount = -1;
|
||||
|
||||
/// The index to the next frame to be decoded.
|
||||
int _nextFrameIndex = 0;
|
||||
/// Current frame index.
|
||||
int _currentFrameIndex = 0;
|
||||
|
||||
@override
|
||||
SkAnimatedImage createDefault() {
|
||||
@@ -48,11 +48,16 @@ class CkAnimatedImage extends ManagedSkiaObject<SkAnimatedImage>
|
||||
_frameCount = animatedImage.getFrameCount();
|
||||
_repetitionCount = animatedImage.getRepetitionCount();
|
||||
|
||||
// If the object has been deleted then resurrected, it may already have
|
||||
// iterated over some frames. We need to skip over them.
|
||||
for (int i = 0; i < _nextFrameIndex; i++) {
|
||||
// Normally CanvasKit initializes `SkAnimatedImage` to point to the first
|
||||
// frame in the animation. However, if the Skia object has been deleted then
|
||||
// resurrected, the framework/app may already have advanced to one of the
|
||||
// subsequent frames. When that happens the value of _currentFrameIndex will
|
||||
// be something other than zero, and we need to tell the decoder to skip
|
||||
// over the previous frames to point to the current one.
|
||||
for (int i = 0; i < _currentFrameIndex; i++) {
|
||||
animatedImage.decodeNextFrame();
|
||||
}
|
||||
|
||||
return animatedImage;
|
||||
}
|
||||
|
||||
@@ -100,10 +105,23 @@ class CkAnimatedImage extends ManagedSkiaObject<SkAnimatedImage>
|
||||
@override
|
||||
Future<ui.FrameInfo> getNextFrame() {
|
||||
assert(_debugCheckIsNotDisposed());
|
||||
final int durationMillis = skiaObject.decodeNextFrame();
|
||||
final Duration duration = Duration(milliseconds: durationMillis);
|
||||
final CkImage image = CkImage(skiaObject.makeImageAtCurrentFrame());
|
||||
_nextFrameIndex = (_nextFrameIndex + 1) % _frameCount;
|
||||
return Future<ui.FrameInfo>.value(AnimatedImageFrameInfo(duration, image));
|
||||
final SkAnimatedImage animatedImage = skiaObject;
|
||||
|
||||
// SkAnimatedImage comes pre-initialized to point to the current frame (by
|
||||
// default the first frame, and, with some special resurrection logic in
|
||||
// `createDefault`, to a subsequent frame if resurrection happens in the
|
||||
// middle of animation). Flutter's `Codec` semantics is to initialize to
|
||||
// point to "just before the first frame", i.e. the first invocation of
|
||||
// `getNextFrame` returns the first frame. Therefore, we have to read the
|
||||
// current Skia frame, then advance SkAnimatedImage to the next frame, and
|
||||
// return the current frame.
|
||||
final ui.FrameInfo currentFrame = AnimatedImageFrameInfo(
|
||||
Duration(milliseconds: animatedImage.currentFrameDuration()),
|
||||
CkImage(animatedImage.makeImageAtCurrentFrame()),
|
||||
);
|
||||
|
||||
animatedImage.decodeNextFrame();
|
||||
_currentFrameIndex = (_currentFrameIndex + 1) % _frameCount;
|
||||
return Future<ui.FrameInfo>.value(currentFrame);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import 'package:js/js.dart';
|
||||
/// The version of CanvasKit used by the web engine by default.
|
||||
// DO NOT EDIT THE NEXT LINE OF CODE MANUALLY
|
||||
// See `lib/web_ui/README.md` for how to roll CanvasKit to a new version.
|
||||
const String _canvaskitVersion = '0.31.0';
|
||||
const String _canvaskitVersion = '0.32.0';
|
||||
|
||||
/// The Web Engine configuration for the current application.
|
||||
FlutterConfiguration get configuration => _configuration ??= FlutterConfiguration(_jsConfiguration);
|
||||
|
||||
@@ -94,9 +94,9 @@ void _testForImageCodecs({required bool useBrowserImageDecoder}) {
|
||||
expect(image.repetitionCount, -1);
|
||||
|
||||
final ui.FrameInfo frame1 = await image.getNextFrame();
|
||||
await expectFrameData(frame1, <int>[0, 255, 0, 255]);
|
||||
await expectFrameData(frame1, <int>[255, 0, 0, 255]);
|
||||
final ui.FrameInfo frame2 = await image.getNextFrame();
|
||||
await expectFrameData(frame2, <int>[0, 0, 255, 255]);
|
||||
await expectFrameData(frame2, <int>[0, 255, 0, 255]);
|
||||
|
||||
// Pretend that the image is temporarily deleted.
|
||||
image.delete();
|
||||
@@ -104,7 +104,7 @@ void _testForImageCodecs({required bool useBrowserImageDecoder}) {
|
||||
|
||||
// Check that we got the 3rd frame after resurrection.
|
||||
final ui.FrameInfo frame3 = await image.getNextFrame();
|
||||
await expectFrameData(frame3, <int>[255, 0, 0, 255]);
|
||||
await expectFrameData(frame3, <int>[0, 0, 255, 255]);
|
||||
|
||||
testCollector.collectNow();
|
||||
});
|
||||
@@ -548,11 +548,10 @@ void _testCkAnimatedImage() {
|
||||
|
||||
test('CkAnimatedImage toByteData(RGBA)', () async {
|
||||
final CkAnimatedImage image = CkAnimatedImage.decodeFromBytes(kAnimatedGif, 'test');
|
||||
// TODO(yjbanov): frame sequence is wrong (https://github.com/flutter/flutter/issues/95281)
|
||||
const List<List<int>> expectedColors = <List<int>>[
|
||||
<int>[255, 0, 0, 255],
|
||||
<int>[0, 255, 0, 255],
|
||||
<int>[0, 0, 255, 255],
|
||||
<int>[255, 0, 0, 255],
|
||||
];
|
||||
for (int i = 0; i < image.frameCount; i++) {
|
||||
final ui.FrameInfo frame = await image.getNextFrame();
|
||||
|
||||
Reference in New Issue
Block a user