Skip to content

Commit 3e946d9

Browse files
ignatzJaffaKetchup
andauthoredMay 21, 2023
Remove saveLayers from the public PolygonLayer API and call canvas.saveLayer only when needed based on the polygon properties. (#1519)
Co-authored-by: JaffaKetchup <github@jaffaketchup.dev>
1 parent 9a13031 commit 3e946d9

File tree

2 files changed

+75
-45
lines changed

2 files changed

+75
-45
lines changed
 

‎example/lib/pages/polyline.dart

+37-2
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,50 @@ class _PolylinePageState extends State<PolylinePage> {
1616
late Future<List<Polyline>> polylines;
1717

1818
Future<List<Polyline>> getPolylines() async {
19-
final polyLines = [
19+
final polyLines = <Polyline>[
2020
Polyline(
2121
points: [
2222
LatLng(50.5, -0.09),
2323
LatLng(51.3498, -6.2603),
2424
LatLng(53.8566, 2.3522),
2525
],
26-
strokeWidth: 50,
26+
strokeWidth: 20,
27+
color: Colors.blue.withOpacity(0.6),
28+
borderStrokeWidth: 20,
29+
borderColor: Colors.red.withOpacity(0.4),
30+
),
31+
Polyline(
32+
points: [
33+
LatLng(50.2, -0.08),
34+
LatLng(51.2498, -7.2603),
35+
LatLng(54.8566, 1.3522),
36+
],
37+
strokeWidth: 20,
38+
color: Colors.black.withOpacity(0.2),
39+
borderStrokeWidth: 20,
40+
borderColor: Colors.white30,
41+
),
42+
Polyline(
43+
points: [
44+
LatLng(49.1, -0.06),
45+
LatLng(51.15, -7.4),
46+
LatLng(55.5, 0.8),
47+
],
48+
strokeWidth: 10,
49+
color: Colors.yellow,
50+
borderStrokeWidth: 10,
51+
borderColor: Colors.blue.withOpacity(0.5),
52+
),
53+
Polyline(
54+
points: [
55+
LatLng(48.1, -0.03),
56+
LatLng(50.5, -7.8),
57+
LatLng(56.5, 0.4),
58+
],
59+
strokeWidth: 10,
2760
color: Colors.amber,
61+
borderStrokeWidth: 10,
62+
borderColor: Colors.blue.withOpacity(0.5),
2863
),
2964
];
3065
await Future<void>.delayed(const Duration(seconds: 3));

‎lib/src/layer/polyline_layer.dart

+38-43
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:core';
12
import 'dart:ui' as ui;
23

34
import 'package:flutter/widgets.dart';
@@ -58,21 +59,12 @@ class PolylineLayer extends StatelessWidget {
5859

5960
final bool polylineCulling;
6061

61-
/// {@macro newPolylinePainter.saveLayers}
62-
///
63-
/// By default, this value is set to `false` to improve performance on
64-
/// layers containing a lot of polylines.
65-
///
66-
/// You might want to set this to `true` if you get unwanted darker lines
67-
/// where they overlap but, keep in mind that this might reduce the
68-
/// performance of the layer.
69-
final bool saveLayers;
70-
7162
const PolylineLayer({
7263
super.key,
7364
this.polylines = const [],
7465
this.polylineCulling = false,
75-
this.saveLayers = false,
66+
@Deprecated('No longer needed and will be removed.')
67+
bool saveLayers = false,
7668
});
7769

7870
@override
@@ -87,7 +79,7 @@ class PolylineLayer extends StatelessWidget {
8779
: polylines;
8880

8981
return CustomPaint(
90-
painter: PolylinePainter(lines, saveLayers, map),
82+
painter: PolylinePainter(lines, map),
9183
size: size,
9284
isComplex: true,
9385
);
@@ -97,17 +89,10 @@ class PolylineLayer extends StatelessWidget {
9789
class PolylinePainter extends CustomPainter {
9890
final List<Polyline> polylines;
9991

100-
/// {@template newPolylinePainter.saveLayers}
101-
/// If `true`, the canvas will be updated on every frame by calling the
102-
/// methods [Canvas.saveLayer] and [Canvas.restore].
103-
/// {@endtemplate}
104-
final bool saveLayers;
105-
10692
final FlutterMapState map;
10793
final LatLngBounds bounds;
10894

109-
PolylinePainter(this.polylines, this.saveLayers, this.map)
110-
: bounds = map.bounds;
95+
PolylinePainter(this.polylines, this.map) : bounds = map.bounds;
11196

11297
int get hash {
11398
_hash ??= Object.hashAll(polylines);
@@ -134,26 +119,35 @@ class PolylinePainter extends CustomPainter {
134119
var borderPath = ui.Path();
135120
var filterPath = ui.Path();
136121
var paint = Paint();
122+
bool needsLayerSaving = false;
123+
137124
Paint? borderPaint;
138125
Paint? filterPaint;
139126
int? lastHash;
140127

141128
void drawPaths() {
142-
canvas.drawPath(path, paint);
143-
path = ui.Path();
144-
paint = Paint();
129+
final hasBorder = borderPaint != null && filterPaint != null;
130+
if (hasBorder) {
131+
if (needsLayerSaving) {
132+
canvas.saveLayer(rect, Paint());
133+
}
145134

146-
if (borderPaint != null) {
147135
canvas.drawPath(borderPath, borderPaint!);
148136
borderPath = ui.Path();
149137
borderPaint = null;
150-
}
151138

152-
if (filterPaint != null) {
153-
canvas.drawPath(filterPath, filterPaint!);
154-
filterPath = ui.Path();
155-
filterPaint = null;
139+
if (needsLayerSaving) {
140+
canvas.drawPath(filterPath, filterPaint!);
141+
filterPath = ui.Path();
142+
filterPaint = null;
143+
144+
canvas.restore();
145+
}
156146
}
147+
148+
canvas.drawPath(path, paint);
149+
path = ui.Path();
150+
paint = Paint();
157151
}
158152

159153
for (final polyline in polylines) {
@@ -163,10 +157,12 @@ class PolylinePainter extends CustomPainter {
163157
}
164158

165159
final hash = polyline.renderHashCode;
166-
if (lastHash != null && lastHash != hash) {
160+
if (needsLayerSaving || (lastHash != null && lastHash != hash)) {
167161
drawPaths();
168162
}
169163
lastHash = hash;
164+
needsLayerSaving = polyline.color.opacity < 1.0 ||
165+
(polyline.gradientColors?.any((c) => c.opacity < 1.0) ?? false);
170166

171167
late final double strokeWidth;
172168
if (polyline.useStrokeWidthInMeter) {
@@ -200,30 +196,30 @@ class PolylinePainter extends CustomPainter {
200196
: paint.color = polyline.color;
201197
}
202198

203-
if (polyline.borderColor != null) {
204-
filterPaint = Paint()
205-
..color = polyline.borderColor!.withAlpha(255)
206-
..strokeWidth = strokeWidth
207-
..strokeCap = polyline.strokeCap
208-
..strokeJoin = polyline.strokeJoin
209-
..style = isDotted ? PaintingStyle.fill : PaintingStyle.stroke
210-
..blendMode = BlendMode.dstOut;
211-
}
212-
213-
if (polyline.borderStrokeWidth > 0.0) {
199+
if (polyline.borderColor != null && polyline.borderStrokeWidth > 0.0) {
200+
// Outlined lines are drawn by drawing a thicker path underneath, then
201+
// stenciling the middle (in case the line fill is transparent), and
202+
// finally drawing the line fill.
214203
borderPaint = Paint()
215204
..color = polyline.borderColor ?? const Color(0x00000000)
216205
..strokeWidth = strokeWidth + polyline.borderStrokeWidth
217206
..strokeCap = polyline.strokeCap
218207
..strokeJoin = polyline.strokeJoin
219208
..style = isDotted ? PaintingStyle.fill : PaintingStyle.stroke
220209
..blendMode = BlendMode.srcOver;
210+
211+
filterPaint = Paint()
212+
..color = polyline.borderColor!.withAlpha(255)
213+
..strokeWidth = strokeWidth
214+
..strokeCap = polyline.strokeCap
215+
..strokeJoin = polyline.strokeJoin
216+
..style = isDotted ? PaintingStyle.fill : PaintingStyle.stroke
217+
..blendMode = BlendMode.dstOut;
221218
}
222219

223220
final radius = paint.strokeWidth / 2;
224221
final borderRadius = (borderPaint?.strokeWidth ?? 0) / 2;
225222

226-
if (saveLayers) canvas.saveLayer(rect, Paint());
227223
if (isDotted) {
228224
final spacing = strokeWidth * 1.5;
229225
if (borderPaint != null && filterPaint != null) {
@@ -238,7 +234,6 @@ class PolylinePainter extends CustomPainter {
238234
}
239235
_paintLine(path, offsets);
240236
}
241-
if (saveLayers) canvas.restore();
242237
}
243238

244239
drawPaths();

0 commit comments

Comments
 (0)