diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc index 367518b90182db500704ed318d91282313c55c5d..d3d0845a0e112a66d39ab80a2b408a5b7d28106d 100644 --- a/lib/ui/painting/canvas.cc +++ b/lib/ui/painting/canvas.cc @@ -181,6 +181,7 @@ void Canvas::clipPath(const CanvasPath* path, bool doAntiAlias) { if (!path) Dart_ThrowException( ToDart("Canvas.clipPath called with non-genuine Path.")); + external_allocation_size_ += path->path().approximateBytesUsed(); canvas_->clipPath(path->path(), doAntiAlias); } @@ -280,6 +281,7 @@ void Canvas::drawPath(const CanvasPath* path, if (!path) Dart_ThrowException( ToDart("Canvas.drawPath called with non-genuine Path.")); + external_allocation_size_ += path->path().approximateBytesUsed(); canvas_->drawPath(path->path(), *paint.paint()); } @@ -425,6 +427,7 @@ void Canvas::drawShadow(const CanvasPath* path, ToDart("Canvas.drawShader called with non-genuine Path.")); SkScalar dpr = UIDartState::Current()->window()->viewport_metrics().device_pixel_ratio; + external_allocation_size_ += path->path().approximateBytesUsed(); flutter::PhysicalShapeLayer::DrawShadow(canvas_, path->path(), color, elevation, transparentOccluder, dpr); } diff --git a/lib/ui/painting/path.cc b/lib/ui/painting/path.cc index 7667b53c87bec1e7d77020ae304e570114af1e21..946177f14ad85c6700e4cfcc3aad0cc559a8bb9e 100644 --- a/lib/ui/painting/path.cc +++ b/lib/ui/painting/path.cc @@ -297,4 +297,11 @@ void CanvasPath::clone(Dart_Handle path_handle) { path->path_ = path_; } +// This is doomed to be called too early, since Paths are mutable. +// However, it can help for some of the clone/shift/transform type methods +// where the resultant path will initially have a meaningful size. +size_t CanvasPath::GetAllocationSize() const { + return sizeof(CanvasPath) + path_.approximateBytesUsed(); +} + } // namespace flutter diff --git a/lib/ui/painting/path.h b/lib/ui/painting/path.h index 7deb50e4e7d7c2f1b2a68ef206bf186b77f35ee2..dbd6d7a0d1cc2c20e5e52fd502cde852255db2d6 100644 --- a/lib/ui/painting/path.h +++ b/lib/ui/painting/path.h @@ -110,6 +110,8 @@ class CanvasPath : public RefCountedDartWrappable { const SkPath& path() const { return path_; } + size_t GetAllocationSize() const override; + static void RegisterNatives(tonic::DartLibraryNatives* natives); private: diff --git a/testing/dart/canvas_test.dart b/testing/dart/canvas_test.dart index ac35140a519862ab467df6e7b40416a032352884..7bf507206d0b1c23d2d49f7104c62034a480d98a 100644 --- a/testing/dart/canvas_test.dart +++ b/testing/dart/canvas_test.dart @@ -286,4 +286,23 @@ void main() { expect(picture2.approximateBytesUsed, greaterThan(minimumExpected)); }); + + test('Path reflected in picture size for drawPath, clipPath, and drawShadow', () async { + final PictureRecorder recorder = PictureRecorder(); + final Canvas canvas = Canvas(recorder); + final Path path = Path(); + for (int i = 0; i < 10000; i++) { + path.lineTo(5, 9); + path.lineTo(i.toDouble(), i.toDouble()); + } + path.close(); + canvas.drawPath(path, Paint()); + canvas.drawShadow(path, const Color(0xFF000000), 5.0, false); + canvas.clipPath(path); + final Picture picture = recorder.endRecording(); + + // Slightly fuzzy here to allow for platform specific differences + // Measurement on macOS: 541078 + expect(picture.approximateBytesUsed, greaterThan(530000)); + }); }