From 7e38261e1a523acd2a95d9c908a6bc4a117df43d Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 4 Jun 2020 15:48:25 -0700 Subject: [PATCH] Record path memory usage in SkPictures (#18827) --- lib/ui/painting/canvas.cc | 3 +++ lib/ui/painting/path.cc | 7 +++++++ lib/ui/painting/path.h | 2 ++ testing/dart/canvas_test.dart | 19 +++++++++++++++++++ 4 files changed, 31 insertions(+) diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc index 367518b901..d3d0845a0e 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 7667b53c87..946177f14a 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 7deb50e4e7..dbd6d7a0d1 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 ac35140a51..7bf507206d 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)); + }); } -- GitLab