[google_maps_flutter_platform_interface] Adds size to BitmapDescriptor (1/2) (#6208)

Adds a size parameter to the BitmapDescriptor.fromBytes constructor, so web applications can specify the actual physical size of the bitmap.

The parameter is not needed (and ignored) in other platforms. Other platforms seem to be doing actual size / dpi to figure out the correct physical size.

Fixes (part 1) flutter/flutter#73789
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md
index 695a1b8..dd32d78 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md
@@ -1,5 +1,8 @@
-## NEXT
+## 2.2.2
 
+* Adds a `size` parameter to `BitmapDescriptor.fromBytes`, so **web** applications
+  can specify the actual *physical size* of the bitmap. The parameter is not needed
+  (and ignored) in other platforms. Issue [#73789](https://github.com/flutter/flutter/issues/73789).
 * Fixes avoid_redundant_argument_values lint warnings and minor typos.
 
 ## 2.2.1
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart
index 0ccc3e6..7dda43a 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart
@@ -157,8 +157,22 @@
 
   /// Creates a BitmapDescriptor using an array of bytes that must be encoded
   /// as PNG.
-  static BitmapDescriptor fromBytes(Uint8List byteData) {
-    return BitmapDescriptor._(<Object>[_fromBytes, byteData]);
+  /// On the web, the [size] parameter represents the *physical size* of the
+  /// bitmap, regardless of the actual resolution of the encoded PNG.
+  /// This helps the browser to render High-DPI images at the correct size.
+  /// `size` is not required (and ignored, if passed) in other platforms.
+  static BitmapDescriptor fromBytes(Uint8List byteData, {Size? size}) {
+    assert(byteData.isNotEmpty,
+        'Cannot create BitmapDescriptor with empty byteData');
+    return BitmapDescriptor._(<Object>[
+      _fromBytes,
+      byteData,
+      if (kIsWeb && size != null)
+        <Object>[
+          size.width,
+          size.height,
+        ]
+    ]);
   }
 
   final Object _json;
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml
index f1463c7..9f4b7c0 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml
@@ -4,7 +4,7 @@
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22
 # NOTE: We strongly prefer non-breaking changes, even at the expense of a
 # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 2.2.1
+version: 2.2.2
 
 environment:
   sdk: '>=2.12.0 <3.0.0'
diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart
index 7fbaf49..2499e87 100644
--- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart
@@ -2,8 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// ignore:unnecessary_import
 import 'dart:typed_data';
+import 'dart:ui';
 
+import 'package:flutter/foundation.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
@@ -26,6 +29,56 @@
       expect(identical(descriptorFromJson.toJson(), json), isTrue); // Same JSON
     });
 
+    group('fromBytes constructor', () {
+      test('with empty byte array, throws assertion error', () {
+        expect(() {
+          BitmapDescriptor.fromBytes(Uint8List.fromList(<int>[]));
+        }, throwsAssertionError);
+      });
+
+      test('with bytes', () {
+        final BitmapDescriptor descriptor = BitmapDescriptor.fromBytes(
+          Uint8List.fromList(<int>[1, 2, 3]),
+        );
+        expect(descriptor, isA<BitmapDescriptor>());
+        expect(
+            descriptor.toJson(),
+            equals(<Object>[
+              'fromBytes',
+              <int>[1, 2, 3],
+            ]));
+      });
+
+      test('with size, not on the web, size is ignored', () {
+        final BitmapDescriptor descriptor = BitmapDescriptor.fromBytes(
+          Uint8List.fromList(<int>[1, 2, 3]),
+          size: const Size(40, 20),
+        );
+
+        expect(
+            descriptor.toJson(),
+            equals(<Object>[
+              'fromBytes',
+              <int>[1, 2, 3],
+            ]));
+      }, skip: kIsWeb);
+
+      test('with size, on the web, size is preserved', () {
+        final BitmapDescriptor descriptor = BitmapDescriptor.fromBytes(
+          Uint8List.fromList(<int>[1, 2, 3]),
+          size: const Size(40, 20),
+        );
+
+        expect(
+            descriptor.toJson(),
+            equals(<Object>[
+              'fromBytes',
+              <int>[1, 2, 3],
+              <int>[40, 20],
+            ]));
+      }, skip: !kIsWeb);
+    });
+
     group('fromJson validation', () {
       group('type validation', () {
         test('correct type', () {