Skip to content

Commit 31c41ed

Browse files
fix: prevent infinite looping when polygon labels displayed on rotated map (#2054)
Co-authored-by: JaffaKetchup <[email protected]>
1 parent 5250313 commit 31c41ed

File tree

6 files changed

+50
-13
lines changed

6 files changed

+50
-13
lines changed

CHANGELOG.md

+13-3
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,26 @@ Please consider [donating](https://docs.fleaflet.dev/supporters#support-us) or [
44

55
This CHANGELOG does not include every commit and/or PR - it is a hand picked selection of the ones that have an effect on you. For a full list of changes, please check the GitHub repository releases/tags.
66

7-
## [8.1.0] - 2025/02/XX
7+
## [8.1.1] - 2025/03/08
8+
9+
Contains the following user-affecting bug fixes:
10+
11+
- Prevent infinite looping when polygon labels displayed on rotated map - [#2054](https://github.com/fleaflet/flutter_map/pull/2054) for [#2052](https://github.com/fleaflet/flutter_map/issues/2052)
12+
13+
Many thanks to these contributors (in no particular order):
14+
15+
- @monsieurtanuki
16+
17+
## [8.1.0] - 2025/02/25
818

919
Contains the following user-affecting changes:
1020

1121
- Added multi-world support for `Polygon`s and `Polyline`s - [#2033](https://github.com/fleaflet/flutter_map/pull/2033)
1222

1323
Contains the following user-affecting bug fixes:
1424

15-
- Ensure movement gestures emit events when starting - [#2035](https://github.com/fleaflet/flutter_map/pull/2035)
16-
- Ensure `MapController.rotateAroundPoint` does not move map when already rotated - [#2029](https://github.com/fleaflet/flutter_map/pull/2029)
25+
- Ensure movement gestures emit events when starting - [#2035](https://github.com/fleaflet/flutter_map/pull/2035) for [#1939](https://github.com/fleaflet/flutter_map/issues/1939)
26+
- Ensure `MapController.rotateAroundPoint` does not move map when already rotated - [#2029](https://github.com/fleaflet/flutter_map/pull/2029) for [#2028](https://github.com/fleaflet/flutter_map/issues/2028)
1727

1828
Many thanks to these contributors (in no particular order):
1929

example/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: flutter_map_example
22
description: Example application for 'flutter_map' package
33
publish_to: "none"
4-
version: 8.1.0
4+
version: 8.1.1
55

66
environment:
77
sdk: ">=3.6.0 <4.0.0"

lib/src/layer/polygon_layer/label.dart

+19-6
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,26 @@ void Function(Canvas canvas)? _buildLabelTextPainter({
1717
// Cull labels where the polygon is still on the map but the label would not be.
1818
// Currently this is only enabled when the map isn't rotated, since the placementOffset
1919
// is relative to the MobileLayerTransformer rather than in actual screen coordinates.
20+
final double textWidth;
21+
final double textHeight;
22+
final double mapWidth;
23+
final double mapHeight;
2024
if (rotationRad == 0) {
21-
if (dx + width / 2 < 0 || dx - width / 2 > mapSize.width) {
22-
return null;
23-
}
24-
if (dy + height / 2 < 0 || dy - height / 2 > mapSize.height) {
25-
return null;
26-
}
25+
textWidth = width;
26+
textHeight = height;
27+
mapWidth = mapSize.width;
28+
mapHeight = mapSize.height;
29+
} else {
30+
// lazily we imagine the worst case scenario regarding sizes, instead of
31+
// computing the angles
32+
textWidth = textHeight = max(width, height);
33+
mapWidth = mapHeight = max(mapSize.width, mapSize.height);
34+
}
35+
if (dx + textWidth / 2 < 0 || dx - textWidth / 2 > mapWidth) {
36+
return null;
37+
}
38+
if (dy + textHeight / 2 < 0 || dy - textHeight / 2 > mapHeight) {
39+
return null;
2740
}
2841

2942
// Note: I'm pretty sure this doesn't work for concave shapes. It would be more

lib/src/layer/shared/feature_layer_utils.dart

+15-1
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,26 @@ mixin FeatureLayerUtils on CustomPainter {
5454
/// Internally, the worker is invoked in the 'negative' worlds (worlds to the
5555
/// left of the 'primary' world) until repetition is stopped, then in the
5656
/// 'positive' worlds: <--||-->.
57-
bool workAcrossWorlds(WorldWorkControl Function(double shift) work) {
57+
bool workAcrossWorlds(
58+
WorldWorkControl Function(double shift) work,
59+
) {
60+
// Protection in case of unexpected infinite loop if `work` never returns
61+
// `invisible`. e.g. https://github.com/fleaflet/flutter_map/issues/2052.
62+
const maxShiftsCount = 10;
63+
int shiftsCount = 0;
64+
65+
void protectInfiniteLoop() {
66+
if (++shiftsCount > maxShiftsCount) throw const StackOverflowError();
67+
}
68+
69+
protectInfiniteLoop();
5870
if (work(0) == WorldWorkControl.hit) return true;
5971

6072
if (worldWidth == 0) return false;
6173

6274
negativeWorldsLoop:
6375
for (double shift = -worldWidth;; shift -= worldWidth) {
76+
protectInfiniteLoop();
6477
switch (work(shift)) {
6578
case WorldWorkControl.hit:
6679
return true;
@@ -71,6 +84,7 @@ mixin FeatureLayerUtils on CustomPainter {
7184
}
7285

7386
for (double shift = worldWidth;; shift += worldWidth) {
87+
protectInfiniteLoop();
7488
switch (work(shift)) {
7589
case WorldWorkControl.hit:
7690
return true;

pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: flutter_map
22
description: A versatile mapping package for Flutter, that's simple and easy to learn, yet completely customizable and configurable
3-
version: 8.1.0
3+
version: 8.1.1
44

55
repository: https://github.com/fleaflet/flutter_map
66
issue_tracker: https://github.com/fleaflet/flutter_map/issues

windowsApplicationInstallerSetup.iss

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
33

44
#define MyAppName "flutter_map Demo"
5-
#define MyAppVersion "for 8.1.0"
5+
#define MyAppVersion "for 8.1.1"
66
#define MyAppPublisher "fleaflet"
77
#define MyAppURL "https://github.com/fleaflet/flutter_map"
88
#define MyAppSupportURL "https://github.com/fleaflet/flutter_map/issues"

0 commit comments

Comments
 (0)