refine SkPath::approximateBytesUsed()

Instead of looking at point/verb/weight counts, add an
SkPathRef::approximateBytesUsed() using their reserve counts.

This shows SkPathBuilder::snapshot() can return more memory-efficient
SkPaths than SkPathBuilder::detach(), at the cost of a copy.

Change-Id: I4e208c41643480d7682daba6ac674ffa63c74de2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/326608
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
Mike Klein 2020-10-14 09:13:14 -05:00 committed by Skia Commit-Bot
parent 53cf44cfaf
commit f4c6463695
4 changed files with 30 additions and 4 deletions

View File

@ -294,6 +294,8 @@ public:
int countVerbs() const { return fVerbs.count(); }
int countWeights() const { return fConicWeights.count(); }
size_t approximateBytesUsed() const;
/**
* Returns a pointer one beyond the first logical verb (last verb in memory order).
*/

View File

@ -525,11 +525,8 @@ int SkPath::getVerbs(uint8_t dst[], int max) const {
size_t SkPath::approximateBytesUsed() const {
size_t size = sizeof (SkPath);
if (fPathRef != nullptr) {
size += fPathRef->countPoints() * sizeof(SkPoint)
+ fPathRef->countVerbs()
+ fPathRef->countWeights() * sizeof(SkScalar);
size += fPathRef->approximateBytesUsed();
}
return size;
}

View File

@ -50,6 +50,13 @@ void SkPath::shrinkToFit() {
//////////////////////////////////////////////////////////////////////////////
size_t SkPathRef::approximateBytesUsed() const {
return sizeof(SkPathRef)
+ fPoints .reserved() * sizeof(fPoints [0])
+ fVerbs .reserved() * sizeof(fVerbs [0])
+ fConicWeights.reserved() * sizeof(fConicWeights[0]);
}
SkPathRef::~SkPathRef() {
// Deliberately don't validate() this path ref, otherwise there's no way
// to read one that's not valid and then free its memory without asserting.

View File

@ -270,3 +270,23 @@ DEF_TEST(pathbuilder_addPolygon, reporter) {
}
}
}
DEF_TEST(pathbuilder_shrinkToFit, reporter) {
// SkPathBuilder::snapshot() creates copies of its arrays for perfectly sized paths,
// where SkPathBuilder::detach() moves its larger scratch arrays for speed.
bool any_smaller = false;
for (int pts = 0; pts < 10; pts++) {
SkPathBuilder b;
for (int i = 0; i < pts; i++) {
b.lineTo(i,i);
}
b.close();
SkPath s = b.snapshot(),
d = b.detach();
REPORTER_ASSERT(reporter, s.approximateBytesUsed() <= d.approximateBytesUsed());
any_smaller |= s.approximateBytesUsed() < d.approximateBytesUsed();
}
REPORTER_ASSERT(reporter, any_smaller);
}