Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 4979039

Browse files
authored
Fix Path.from. (#15268)
* Fix Path.from to deep copy. Add regression test.
1 parent 3339c42 commit 4979039

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

lib/web_ui/lib/src/engine/surface/painting.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,28 @@ class SurfacePath implements ui.Path {
287287
/// This copy is fast and does not require additional memory unless either
288288
/// the `source` path or the path returned by this constructor are modified.
289289
SurfacePath.from(SurfacePath source)
290+
: subpaths = _deepCopy(source.subpaths);
291+
292+
SurfacePath._shallowCopy(SurfacePath source)
290293
: subpaths = List<Subpath>.from(source.subpaths);
291294

292295
SurfacePath._clone(this.subpaths, this._fillType);
293296

297+
static List<Subpath> _deepCopy(List<Subpath> source) {
298+
// The last sub path can potentially still be mutated by calling ops.
299+
// Copy all sub paths except the last active one which needs a deep copy.
300+
final List<Subpath> paths = [];
301+
int len = source.length;
302+
if (len != 0) {
303+
--len;
304+
for (int i = 0; i < len; i++) {
305+
paths.add(source[i]);
306+
}
307+
paths.add(source[len].shift(const ui.Offset(0, 0)));
308+
}
309+
return paths;
310+
}
311+
294312
/// Determines how the interior of this path is calculated.
295313
///
296314
/// Defaults to the non-zero winding rule, [PathFillType.nonZero].

lib/web_ui/lib/src/engine/surface/recording_canvas.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ class RecordingCanvas {
309309
}
310310
_paintBounds.grow(pathBounds);
311311
// Clone path so it can be reused for subsequent draw calls.
312-
final ui.Path clone = ui.Path.from(path);
312+
final ui.Path clone = SurfacePath._shallowCopy(path);
313313
clone.fillType = path.fillType;
314314
_commands.add(PaintDrawPath(clone, paint.paintData));
315315
}

lib/web_ui/test/path_test.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,4 +238,18 @@ void main() {
238238
distance: 0.1,
239239
from: const Rect.fromLTRB(220.0, 124.1, 382.9, 300.0)));
240240
});
241+
242+
// Regression test for https://github.com/flutter/flutter/issues/46813.
243+
test('Should deep copy path', () {
244+
final SurfacePath path = SurfacePath();
245+
path.moveTo(25, 30);
246+
path.lineTo(100, 200);
247+
expect(path.getBounds(), const Rect.fromLTRB(25, 30, 100, 200));
248+
249+
final SurfacePath path2 = SurfacePath.from(path);
250+
path2.lineTo(250, 300);
251+
expect(path2.getBounds(), const Rect.fromLTRB(25, 30, 250, 300));
252+
// Expect original path to stay the same.
253+
expect(path.getBounds(), const Rect.fromLTRB(25, 30, 100, 200));
254+
});
241255
}

0 commit comments

Comments
 (0)