From b4ec7a7ab4d357097ed72a8802a90bc2390a3914 Mon Sep 17 00:00:00 2001 From: mjtalbot Date: Thu, 20 Jul 2023 13:59:39 +0000 Subject: [PATCH] =?UTF-8?q?use=20the=20dimensions=20of=20the=20image=20at?= =?UTF-8?q?=20runtime,=20rather=20than=20of=20the=20ImageA=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …sset ok just "fixing" how we export .riv files, and no-longer rely on width and height form image assets, but take them from the image instead. its not "huge" difference, but basically it means that if we replace an existing image with an image of different dimensions we end up drawing the image from the centre of where the original image was, rather than the top left, which is a bit mroe forgiving example: got a few images in here, (they're all like 5k x 3k pixels, so all quite large) CleanShot 2023-07-03 at 16 28 34@2x before this change this would look like: CleanShot 2023-07-03 at 16 28 46@2x with this change we get CleanShot 2023-07-03 at 16 29 17@2x (the mesh is kinda interesting here) *note* i'm not touching the cpp runtime just yet, so this & other changes still need to make it down there Diffs= 235908221 use the dimensions of the image at runtime, rather than of the ImageA… (#5519) Co-authored-by: Maxwell Talbot --- .rive_head | 2 +- .../generated/assets/drawable_asset_base.dart | 55 ----------------- lib/src/generated/rive_core_context.dart | 27 --------- lib/src/rive_core/shapes/image.dart | 10 ++-- test/asset_test.dart | 60 +++++++++++++------ 5 files changed, 49 insertions(+), 105 deletions(-) diff --git a/.rive_head b/.rive_head index 3f3bf5f..1d1fe84 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -05c8632e88e89ba40c0fa006265d28d651150c0e +2359082217a57031dfaff5e7138fd974e9025aad diff --git a/lib/src/generated/assets/drawable_asset_base.dart b/lib/src/generated/assets/drawable_asset_base.dart index e0f1920..e804b94 100644 --- a/lib/src/generated/assets/drawable_asset_base.dart +++ b/lib/src/generated/assets/drawable_asset_base.dart @@ -12,59 +12,4 @@ abstract class DrawableAssetBase extends FileAsset { @override Set get coreTypes => {DrawableAssetBase.typeKey, FileAssetBase.typeKey, AssetBase.typeKey}; - - /// -------------------------------------------------------------------------- - /// Height field with key 207. - static const double heightInitialValue = 0; - double _height = heightInitialValue; - static const int heightPropertyKey = 207; - - /// Height of the original asset uploaded - double get height => _height; - - /// Change the [_height] field value. - /// [heightChanged] will be invoked only if the field's value has changed. - set height(double value) { - if (_height == value) { - return; - } - double from = _height; - _height = value; - if (hasValidated) { - heightChanged(from, value); - } - } - - void heightChanged(double from, double to); - - /// -------------------------------------------------------------------------- - /// Width field with key 208. - static const double widthInitialValue = 0; - double _width = widthInitialValue; - static const int widthPropertyKey = 208; - - /// Width of the original asset uploaded - double get width => _width; - - /// Change the [_width] field value. - /// [widthChanged] will be invoked only if the field's value has changed. - set width(double value) { - if (_width == value) { - return; - } - double from = _width; - _width = value; - if (hasValidated) { - widthChanged(from, value); - } - } - - void widthChanged(double from, double to); - - @override - void copy(covariant DrawableAssetBase source) { - super.copy(source); - _height = source._height; - _width = source._width; - } } diff --git a/lib/src/generated/rive_core_context.dart b/lib/src/generated/rive_core_context.dart index 2ba59a8..46bdc9d 100644 --- a/lib/src/generated/rive_core_context.dart +++ b/lib/src/generated/rive_core_context.dart @@ -19,7 +19,6 @@ import 'package:rive/src/generated/animation/state_machine_component_base.dart'; import 'package:rive/src/generated/animation/transition_condition_base.dart'; import 'package:rive/src/generated/animation/transition_value_condition_base.dart'; import 'package:rive/src/generated/assets/asset_base.dart'; -import 'package:rive/src/generated/assets/drawable_asset_base.dart'; import 'package:rive/src/generated/assets/file_asset_base.dart'; import 'package:rive/src/generated/component_base.dart'; import 'package:rive/src/generated/constraints/constraint_base.dart'; @@ -1514,16 +1513,6 @@ class RiveCoreContext { object.cdnBaseUrl = value; } break; - case DrawableAssetBase.heightPropertyKey: - if (object is DrawableAssetBase && value is double) { - object.height = value; - } - break; - case DrawableAssetBase.widthPropertyKey: - if (object is DrawableAssetBase && value is double) { - object.width = value; - } - break; case FileAssetContentsBase.bytesPropertyKey: if (object is FileAssetContentsBase && value is Uint8List) { object.bytes = value; @@ -1750,8 +1739,6 @@ class RiveCoreContext { case TextBase.heightPropertyKey: case TextBase.originXPropertyKey: case TextBase.originYPropertyKey: - case DrawableAssetBase.heightPropertyKey: - case DrawableAssetBase.widthPropertyKey: return doubleType; case TransformComponentConstraintBase.offsetPropertyKey: case TransformComponentConstraintBase.doesCopyPropertyKey: @@ -2218,10 +2205,6 @@ class RiveCoreContext { return (object as TextBase).originX; case TextBase.originYPropertyKey: return (object as TextBase).originY; - case DrawableAssetBase.heightPropertyKey: - return (object as DrawableAssetBase).height; - case DrawableAssetBase.widthPropertyKey: - return (object as DrawableAssetBase).width; } return 0.0; } @@ -3350,16 +3333,6 @@ class RiveCoreContext { object.originY = value; } break; - case DrawableAssetBase.heightPropertyKey: - if (object is DrawableAssetBase) { - object.height = value; - } - break; - case DrawableAssetBase.widthPropertyKey: - if (object is DrawableAssetBase) { - object.width = value; - } - break; } } diff --git a/lib/src/rive_core/shapes/image.dart b/lib/src/rive_core/shapes/image.dart index 212406a..295d2b3 100644 --- a/lib/src/rive_core/shapes/image.dart +++ b/lib/src/rive_core/shapes/image.dart @@ -19,6 +19,9 @@ class Image extends ImageBase Mesh? get mesh => _mesh; bool get hasMesh => _mesh != null; + double get width => image?.width.toDouble() ?? 0.0; + double get height => image?.width.toDouble() ?? 0.0; + AABB get localBounds { if (hasMesh && _mesh!.draws) { return _mesh!.bounds; @@ -26,8 +29,8 @@ class Image extends ImageBase if (asset == null) { return AABB.empty(); } - final halfWidth = asset!.width / 2; - final halfHeight = asset!.height / 2; + final halfWidth = width / 2; + final halfHeight = height / 2; return AABB.fromValues(-halfWidth, -halfHeight, halfWidth, halfHeight); } @@ -47,9 +50,6 @@ class Image extends ImageBase ..filterQuality = ui.FilterQuality.high ..blendMode = blendMode; - final width = asset!.width; - final height = asset!.height; - canvas.save(); canvas.transform(renderTransform.mat4); if (_mesh == null || !_mesh!.draws) { diff --git a/test/asset_test.dart b/test/asset_test.dart index ef40149..cac945d 100644 --- a/test/asset_test.dart +++ b/test/asset_test.dart @@ -22,8 +22,7 @@ void main() { registerFallbackValue(Stream.value([])); }); group("Test loading rive file with embedded asset.", () { - testWidgets('Default load does not hit any url', - (WidgetTester tester) async { + test('Default load does not hit any url', () async { final mockHttpClient = getMockHttpClient(); await HttpOverrides.runZoned(() async { @@ -36,8 +35,7 @@ void main() { verifyNever(() => mockHttpClient.openUrl(any(), any())); }); - testWidgets('Disabling embedded assets also does not hit a url', - (WidgetTester tester) async { + test('Disabling embedded assets also does not hit a url', () async { final mockHttpClient = getMockHttpClient(); await HttpOverrides.runZoned(() async { @@ -53,8 +51,7 @@ void main() { verifyNever(() => mockHttpClient.openUrl(any(), any())); }); - testWidgets('Disabling cdn also does not hit a url', - (WidgetTester tester) async { + test('Disabling cdn also does not hit a url', () async { final mockHttpClient = getMockHttpClient(); await HttpOverrides.runZoned(() async { @@ -79,8 +76,8 @@ void main() { verifyNever(() => mockHttpClient.openUrl(any(), any())); // by default we try to check for assets }); - testWidgets('test importing rive file, make sure we get a good callback', - (WidgetTester tester) async { + test('test importing rive file, make sure we get a good callback', + () async { // lets just return an image final riveBytes = loadFile('assets/sample_image.riv'); final imageBytes = loadFile('assets/file.png'); @@ -106,6 +103,37 @@ void main() { expect(fileAsset.assetId, 42981); expect(fileAsset.id, -1); }); + + test('Make sure the image gets the dimensions once the image is loaded', + () async { + // lets just return an image + final riveBytes = loadFile('assets/sample_image.riv'); + final imageBytes = loadFile('assets/file.png'); + final completer = Completer(); + + final file = RiveFile.import( + riveBytes, + loadEmbeddedAssets: false, + assetLoader: CallbackAssetLoader( + (asset) async { + await asset.decode(Uint8List.sublistView( + imageBytes, + )); + completer.complete(null); + return true; + }, + ), + ); + final image = file.artboards.first + .component("CleanShot 2023-06-08 at 08.51.19@2x.png"); + print(image); + + expect(image.width, 0); + expect(image.height, 0); + await completer.future; + expect(image.width, 256); + expect(image.height, 256); + }); }); group("Test loading rive file with cdn asset.", () { late MockHttpClient mockHttpClient; @@ -115,7 +143,7 @@ void main() { prepMockRequest(mockHttpClient, Uint8List.sublistView(imageBytes)); }); - testWidgets('Default load will his the cdn', (WidgetTester tester) async { + test('Default load will his the cdn', () async { await HttpOverrides.runZoned(() async { final riveBytes = loadFile('assets/cdn_image.riv'); RiveFile.import( @@ -131,8 +159,7 @@ void main() { )).called(1); }); - testWidgets('Disabling embedded assets also hits a url', - (WidgetTester tester) async { + test('Disabling embedded assets also hits a url', () async { await HttpOverrides.runZoned(() async { final riveBytes = loadFile('assets/cdn_image.riv'); runZonedGuarded(() { @@ -149,8 +176,7 @@ void main() { verify(() => mockHttpClient.openUrl(any(), any())).called(1); }); - testWidgets('Disabling cdn will mean no url hit', - (WidgetTester tester) async { + test('Disabling cdn will mean no url hit', () async { await HttpOverrides.runZoned(() async { final riveBytes = loadFile('assets/cdn_image.riv'); @@ -165,9 +191,9 @@ void main() { verifyNever(() => mockHttpClient.openUrl(any(), any())); // by default we try to check for assets }); - testWidgets( + test( 'If we provide a callback, we are hit first, and success means no cdn hit', - (WidgetTester tester) async { + () async { // lets just return an image final imageBytes = loadFile('assets/file.png'); final parameters = []; @@ -192,9 +218,9 @@ void main() { verifyNever(() => mockHttpClient.openUrl(any(), any())); }); - testWidgets( + test( 'If we provide a callback, we are hit first, a failure means we hit cdn', - (WidgetTester tester) async { + () async { // lets just return an image final parameters = []; await HttpOverrides.runZoned(() async {