add SkPath::shrinkToFit
Bug: skia: Change-Id: Ief647bcea53c0aeae2750473288bd31f16521772 Reviewed-on: https://skia-review.googlesource.com/150967 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Mike Reed <reed@google.com> Auto-Submit: Mike Reed <reed@google.com>
This commit is contained in:
parent
086679bc11
commit
3d69be51bb
@ -549,6 +549,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
void incReserve(unsigned extraPtCount);
|
void incReserve(unsigned extraPtCount);
|
||||||
|
|
||||||
|
void shrinkToFit();
|
||||||
|
|
||||||
/** Adds beginning of contour at SkPoint (x, y).
|
/** Adds beginning of contour at SkPoint (x, y).
|
||||||
|
|
||||||
@param x x-axis value of contour start
|
@param x x-axis value of contour start
|
||||||
@ -1667,6 +1669,8 @@ public:
|
|||||||
bool pathRefIsValid() const { return fPathRef->isValid(); }
|
bool pathRefIsValid() const { return fPathRef->isValid(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SkDEBUGCODE(size_t debugging_private_getFreeSpace() const;)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sk_sp<SkPathRef> fPathRef;
|
sk_sp<SkPathRef> fPathRef;
|
||||||
int fLastMoveToIndex;
|
int fLastMoveToIndex;
|
||||||
|
@ -555,6 +555,7 @@ private:
|
|||||||
|
|
||||||
friend class PathRefTest_Private;
|
friend class PathRefTest_Private;
|
||||||
friend class ForceIsRRect_Private; // unit test isRRect
|
friend class ForceIsRRect_Private; // unit test isRRect
|
||||||
|
friend class SkPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,6 +43,54 @@ SkPathRef::Editor::Editor(sk_sp<SkPathRef>* pathRef,
|
|||||||
SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);)
|
SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort of like makeSpace(0) but the the additional requirement that we actively shrink the
|
||||||
|
// allocations to just fit the current needs. makeSpace() will only grow, but never shrinks.
|
||||||
|
//
|
||||||
|
void SkPath::shrinkToFit() {
|
||||||
|
const size_t kMinFreeSpaceForShrink = 8; // just made up a small number
|
||||||
|
|
||||||
|
if (fPathRef->fFreeSpace <= kMinFreeSpaceForShrink) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pointCount = fPathRef->fPointCnt;
|
||||||
|
int verbCount = fPathRef->fVerbCnt;
|
||||||
|
|
||||||
|
size_t ptsSize = sizeof(SkPoint) * pointCount;
|
||||||
|
size_t vrbSize = sizeof(uint8_t) * verbCount;
|
||||||
|
size_t minSize = ptsSize + vrbSize;
|
||||||
|
|
||||||
|
void* newAlloc = sk_malloc_canfail(minSize);
|
||||||
|
if (!newAlloc) {
|
||||||
|
return; // couldn't allocate the smaller buffer, but that's ok
|
||||||
|
}
|
||||||
|
memcpy(newAlloc, fPathRef->fPoints, ptsSize);
|
||||||
|
memcpy((char*)newAlloc + minSize - vrbSize, fPathRef->fVerbs, vrbSize);
|
||||||
|
|
||||||
|
SkPathRef* pr = fPathRef.get();
|
||||||
|
if (fPathRef->unique()) {
|
||||||
|
sk_free(fPathRef->fPoints);
|
||||||
|
} else {
|
||||||
|
pr = new SkPathRef;
|
||||||
|
pr->fPointCnt = pointCount;
|
||||||
|
pr->fVerbCnt = verbCount;
|
||||||
|
pr->fConicWeights = fPathRef->fConicWeights;
|
||||||
|
fPathRef.reset(pr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pr->fPoints = static_cast<SkPoint*>(newAlloc);
|
||||||
|
pr->fVerbs = (uint8_t*)newAlloc + minSize;
|
||||||
|
pr->fFreeSpace = 0;
|
||||||
|
pr->fConicWeights.shrinkToFit();
|
||||||
|
SkDEBUGCODE(pr->validate();)
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
size_t SkPath::debugging_private_getFreeSpace() const {
|
||||||
|
return fPathRef->fFreeSpace;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SkPathRef::~SkPathRef() {
|
SkPathRef::~SkPathRef() {
|
||||||
|
@ -5103,3 +5103,40 @@ DEF_TEST(triangle_big, reporter) {
|
|||||||
draw_triangle(surface->getCanvas(), pts);
|
draw_triangle(surface->getCanvas(), pts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_verbs(SkPath* path, int count) {
|
||||||
|
path->moveTo(0, 0);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
switch (i & 3) {
|
||||||
|
case 0: path->lineTo(10, 20); break;
|
||||||
|
case 1: path->quadTo(5, 6, 7, 8); break;
|
||||||
|
case 2: path->conicTo(1, 2, 3, 4, 0.5f); break;
|
||||||
|
case 3: path->cubicTo(2, 4, 6, 8, 10, 12); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure when we call shrinkToFit() that we always shrink (or stay the same)
|
||||||
|
// and that if we call twice, we stay the same.
|
||||||
|
DEF_TEST(Path_shrinkToFit, reporter) {
|
||||||
|
SkPath path;
|
||||||
|
size_t max_free = 0;
|
||||||
|
for (int verbs = 0; verbs < 100; ++verbs) {
|
||||||
|
SkPath path;
|
||||||
|
add_verbs(&path, verbs);
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
size_t before = path.debugging_private_getFreeSpace();
|
||||||
|
#endif
|
||||||
|
path.shrinkToFit();
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
size_t after = path.debugging_private_getFreeSpace();
|
||||||
|
REPORTER_ASSERT(reporter, before >= after);
|
||||||
|
max_free = std::max(max_free, before - after);
|
||||||
|
|
||||||
|
size_t after2 = path.debugging_private_getFreeSpace();
|
||||||
|
REPORTER_ASSERT(reporter, after == after2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (false) {
|
||||||
|
SkDebugf("max_free %zu\n", max_free);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user