Skip to content

Commit

Permalink
Fix GlyphsRasterizationMode crashing Snapshotter (#738)
Browse files Browse the repository at this point in the history
  • Loading branch information
evil159 authored Oct 17, 2024
1 parent f7586dd commit ea010e2
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 75 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ onCameraChangeListener(CameraChangedEventData data) {
* Print to console native Maps SDK logs in debug configuration.
Logs are proxied only in debug configuration and can be disabled completely by passing environment flag `MAPBOX_LOG_DEBUG` with false value.
* Fix rare crash in `Snapshotter`. The crash could happen when creating/destroying multiple instances of `Snapshotter` in succession.
* Fix crash in Snapshotter when GlyphsRasterizationMode is specified in MapSnapshotOptions.

# 2.3.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,61 +82,66 @@ private open class SnapshotterMessengerPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
129.toByte() -> {
return (readValue(buffer) as Long?)?.let {
GlyphsRasterizationMode.ofRaw(it.toInt())
}
}
130.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
PointDecoder.fromList(it)
}
}
130.toByte() -> {
131.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
MbxEdgeInsets.fromList(it)
}
}
131.toByte() -> {
132.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
ScreenCoordinate.fromList(it)
}
}
132.toByte() -> {
133.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
CameraOptions.fromList(it)
}
}
133.toByte() -> {
134.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
Size.fromList(it)
}
}
134.toByte() -> {
135.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
CoordinateBounds.fromList(it)
}
}
135.toByte() -> {
136.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
CameraState.fromList(it)
}
}
136.toByte() -> {
137.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
MbxImage.fromList(it)
}
}
137.toByte() -> {
138.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
GlyphsRasterizationOptions.fromList(it)
}
}
138.toByte() -> {
139.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
TileCoverOptions.fromList(it)
}
}
139.toByte() -> {
140.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
CanonicalTileID.fromList(it)
}
}
140.toByte() -> {
141.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
MapSnapshotOptions.fromList(it)
}
Expand All @@ -146,52 +151,56 @@ private open class SnapshotterMessengerPigeonCodec : StandardMessageCodec() {
}
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is Point -> {
is GlyphsRasterizationMode -> {
stream.write(129)
writeValue(stream, value.raw)
}
is Point -> {
stream.write(130)
writeValue(stream, value.toList())
}
is MbxEdgeInsets -> {
stream.write(130)
stream.write(131)
writeValue(stream, value.toList())
}
is ScreenCoordinate -> {
stream.write(131)
stream.write(132)
writeValue(stream, value.toList())
}
is CameraOptions -> {
stream.write(132)
stream.write(133)
writeValue(stream, value.toList())
}
is Size -> {
stream.write(133)
stream.write(134)
writeValue(stream, value.toList())
}
is CoordinateBounds -> {
stream.write(134)
stream.write(135)
writeValue(stream, value.toList())
}
is CameraState -> {
stream.write(135)
stream.write(136)
writeValue(stream, value.toList())
}
is MbxImage -> {
stream.write(136)
stream.write(137)
writeValue(stream, value.toList())
}
is GlyphsRasterizationOptions -> {
stream.write(137)
stream.write(138)
writeValue(stream, value.toList())
}
is TileCoverOptions -> {
stream.write(138)
stream.write(139)
writeValue(stream, value.toList())
}
is CanonicalTileID -> {
stream.write(139)
stream.write(140)
writeValue(stream, value.toList())
}
is MapSnapshotOptions -> {
stream.write(140)
stream.write(141)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
Expand Down
2 changes: 1 addition & 1 deletion example/integration_test/snapshotter/snapshotter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void main() {
final snapshotter = await Snapshotter.create(
options: options,
onStyleLoadedListener: styleLoaded.complete,
onStyleDataLoadedListener: styleDataLoaded.complete,
onStyleDataLoadedListener: (e) { if(!styleDataLoaded.isCompleted) styleDataLoaded.complete(e); },
);

await snapshotter.style.setStyleURI(MapboxStyles.LIGHT);
Expand Down
6 changes: 5 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ class MapsDemo extends StatelessWidget {
leading: example.leading,
title: Text(example.title),
subtitle: (example.subtitle?.isNotEmpty == true)
? Text(example.subtitle!, maxLines: 2, overflow: TextOverflow.ellipsis,)
? Text(
example.subtitle!,
maxLines: 2,
overflow: TextOverflow.ellipsis,
)
: null,
onTap: () => _pushPage(context, _allPages[index]),
);
Expand Down
6 changes: 4 additions & 2 deletions example/lib/offline_map_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class OfflineMapExample extends StatefulWidget implements Example {
@override
final String title = 'Offline Map';
@override
final String subtitle = "Shows how to use OfflineManager and TileStore to download regions for offline use.";
final String subtitle =
"Shows how to use OfflineManager and TileStore to download regions for offline use.";

@override
State createState() => OfflineMapExampleState();
Expand Down Expand Up @@ -88,7 +89,8 @@ class OfflineMapExampleState extends State<OfflineMapExample> {
acceptExpired: true,
networkRestriction: NetworkRestriction.NONE);

_tileStore?.loadTileRegion(_tileRegionId, tileRegionLoadOptions, (progress) {
_tileStore?.loadTileRegion(_tileRegionId, tileRegionLoadOptions,
(progress) {
final percentage =
progress.completedResourceCount / progress.requiredResourceCount;
if (!_tileRegionLoadProgress.isClosed) {
Expand Down
3 changes: 2 additions & 1 deletion example/lib/snapshotter_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class SnapshotterExample extends StatefulWidget implements Example {
@override
final String title = 'Create a static map snapshot';
@override
final String subtitle = "Create a static, non-interactive image of a map style with specified camera position.";
final String subtitle =
"Create a static, non-interactive image of a map style with specified camera position.";

@override
State<StatefulWidget> createState() => SnapshotterExampleState();
Expand Down
55 changes: 32 additions & 23 deletions ios/Classes/Generated/SnapshotterMessenger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,28 +116,34 @@ private class SnapshotterMessengerPigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 129:
return Point.fromList(self.readValue() as! [Any?])
let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?)
if let enumResultAsInt = enumResultAsInt {
return GlyphsRasterizationMode(rawValue: enumResultAsInt)
}
return nil
case 130:
return MbxEdgeInsets.fromList(self.readValue() as! [Any?])
return Point.fromList(self.readValue() as! [Any?])
case 131:
return ScreenCoordinate.fromList(self.readValue() as! [Any?])
return MbxEdgeInsets.fromList(self.readValue() as! [Any?])
case 132:
return CameraOptions.fromList(self.readValue() as! [Any?])
return ScreenCoordinate.fromList(self.readValue() as! [Any?])
case 133:
return Size.fromList(self.readValue() as! [Any?])
return CameraOptions.fromList(self.readValue() as! [Any?])
case 134:
return CoordinateBounds.fromList(self.readValue() as! [Any?])
return Size.fromList(self.readValue() as! [Any?])
case 135:
return CameraState.fromList(self.readValue() as! [Any?])
return CoordinateBounds.fromList(self.readValue() as! [Any?])
case 136:
return MbxImage.fromList(self.readValue() as! [Any?])
return CameraState.fromList(self.readValue() as! [Any?])
case 137:
return GlyphsRasterizationOptions.fromList(self.readValue() as! [Any?])
return MbxImage.fromList(self.readValue() as! [Any?])
case 138:
return TileCoverOptions.fromList(self.readValue() as! [Any?])
return GlyphsRasterizationOptions.fromList(self.readValue() as! [Any?])
case 139:
return CanonicalTileID.fromList(self.readValue() as! [Any?])
return TileCoverOptions.fromList(self.readValue() as! [Any?])
case 140:
return CanonicalTileID.fromList(self.readValue() as! [Any?])
case 141:
return MapSnapshotOptions.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
Expand All @@ -147,41 +153,44 @@ private class SnapshotterMessengerPigeonCodecReader: FlutterStandardReader {

private class SnapshotterMessengerPigeonCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? Point {
if let value = value as? GlyphsRasterizationMode {
super.writeByte(129)
super.writeValue(value.rawValue)
} else if let value = value as? Point {
super.writeByte(130)
super.writeValue(value.toList())
} else if let value = value as? MbxEdgeInsets {
super.writeByte(130)
super.writeByte(131)
super.writeValue(value.toList())
} else if let value = value as? ScreenCoordinate {
super.writeByte(131)
super.writeByte(132)
super.writeValue(value.toList())
} else if let value = value as? CameraOptions {
super.writeByte(132)
super.writeByte(133)
super.writeValue(value.toList())
} else if let value = value as? Size {
super.writeByte(133)
super.writeByte(134)
super.writeValue(value.toList())
} else if let value = value as? CoordinateBounds {
super.writeByte(134)
super.writeByte(135)
super.writeValue(value.toList())
} else if let value = value as? CameraState {
super.writeByte(135)
super.writeByte(136)
super.writeValue(value.toList())
} else if let value = value as? MbxImage {
super.writeByte(136)
super.writeByte(137)
super.writeValue(value.toList())
} else if let value = value as? GlyphsRasterizationOptions {
super.writeByte(137)
super.writeByte(138)
super.writeValue(value.toList())
} else if let value = value as? TileCoverOptions {
super.writeByte(138)
super.writeByte(139)
super.writeValue(value.toList())
} else if let value = value as? CanonicalTileID {
super.writeByte(139)
super.writeByte(140)
super.writeValue(value.toList())
} else if let value = value as? MapSnapshotOptions {
super.writeByte(140)
super.writeByte(141)
super.writeValue(value.toList())
} else {
super.writeValue(value)
Expand Down
3 changes: 2 additions & 1 deletion lib/src/snapshotter/snapshotter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ final class Snapshotter {
snapshotter._mapEvents.eventTypes.map((e) => e.index).toList(),
options);

Snapshotter._finalizer.attach(snapshotter, snapshotter._suffix, detach: snapshotter);
Snapshotter._finalizer
.attach(snapshotter, snapshotter._suffix, detach: snapshotter);
return snapshotter;
}

Expand Down
Loading

0 comments on commit ea010e2

Please sign in to comment.