2015-10-30 19:03:06 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2015 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "SubsetPath.h"
|
2016-06-08 00:21:10 +00:00
|
|
|
#include "SkMathPriv.h"
|
2015-10-30 19:03:06 +00:00
|
|
|
|
|
|
|
SubsetPath::SubsetPath(const SkPath& path)
|
|
|
|
: fPath(path)
|
|
|
|
, fSubset(1) {
|
|
|
|
}
|
|
|
|
|
|
|
|
int SubsetPath::range(int* end) const {
|
|
|
|
int leadingZero = SkCLZ(fSubset);
|
|
|
|
int parts = 1 << (31 - leadingZero);
|
|
|
|
int partIndex = fSubset - parts;
|
|
|
|
SkASSERT(partIndex >= 0);
|
|
|
|
int count = fSelected.count();
|
|
|
|
int start = count * partIndex / parts;
|
|
|
|
*end = count * (partIndex + 1) / parts;
|
|
|
|
return start;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SubsetPath::subset(bool testFailed, SkPath* sub) {
|
|
|
|
int start, end;
|
|
|
|
if (!testFailed) {
|
|
|
|
start = range(&end);
|
|
|
|
for (; start < end; ++start) {
|
|
|
|
fSelected[start] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
do {
|
|
|
|
do {
|
|
|
|
++fSubset;
|
|
|
|
start = range(&end);
|
|
|
|
// SkDebugf("%d s=%d e=%d t=%d\n", fSubset, start, end, fTries);
|
|
|
|
if (end - start > 1) {
|
|
|
|
fTries = fSelected.count();
|
|
|
|
} else if (end - start == 1) {
|
|
|
|
if (--fTries <= 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (start == end);
|
|
|
|
} while (!fSelected[start]);
|
|
|
|
for (; start < end; ++start) {
|
|
|
|
fSelected[start] = false;
|
|
|
|
}
|
|
|
|
#if 1
|
|
|
|
SkDebugf("selected: ");
|
|
|
|
for (int index = 0; index < fSelected.count(); ++index) {
|
|
|
|
SkDebugf("%c", fSelected[index] ? 'x' : '-');
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
*sub = getSubsetPath();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
SubsetContours::SubsetContours(const SkPath& path)
|
|
|
|
: SubsetPath(path) {
|
|
|
|
SkPath::RawIter iter(fPath);
|
|
|
|
uint8_t verb;
|
|
|
|
SkPoint pts[4];
|
|
|
|
bool foundCurve = false;
|
|
|
|
int contourCount = 0;
|
|
|
|
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
|
|
|
|
switch (verb) {
|
|
|
|
case SkPath::kMove_Verb:
|
|
|
|
break;
|
|
|
|
case SkPath::kLine_Verb:
|
|
|
|
case SkPath::kQuad_Verb:
|
|
|
|
case SkPath::kConic_Verb:
|
|
|
|
case SkPath::kCubic_Verb:
|
|
|
|
foundCurve = true;
|
|
|
|
break;
|
|
|
|
case SkPath::kClose_Verb:
|
|
|
|
++contourCount;
|
|
|
|
foundCurve = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SkDEBUGFAIL("bad verb");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
contourCount += foundCurve;
|
|
|
|
for (int index = 0; index < contourCount; ++index) {
|
|
|
|
*fSelected.append() = true;
|
|
|
|
}
|
|
|
|
fTries = contourCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkPath SubsetContours::getSubsetPath() const {
|
|
|
|
SkPath result;
|
|
|
|
result.setFillType(fPath.getFillType());
|
|
|
|
if (!fSelected.count()) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
SkPath::RawIter iter(fPath);
|
|
|
|
uint8_t verb;
|
|
|
|
SkPoint pts[4];
|
|
|
|
int contourCount = 0;
|
|
|
|
bool enabled = fSelected[0];
|
|
|
|
bool addMoveTo = true;
|
|
|
|
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
|
|
|
|
if (enabled && addMoveTo) {
|
|
|
|
result.moveTo(pts[0]);
|
|
|
|
addMoveTo = false;
|
|
|
|
}
|
|
|
|
switch (verb) {
|
|
|
|
case SkPath::kMove_Verb:
|
|
|
|
break;
|
|
|
|
case SkPath::kLine_Verb:
|
|
|
|
if (enabled) {
|
|
|
|
result.lineTo(pts[1]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkPath::kQuad_Verb:
|
|
|
|
if (enabled) {
|
|
|
|
result.quadTo(pts[1], pts[2]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkPath::kConic_Verb:
|
|
|
|
if (enabled) {
|
|
|
|
result.conicTo(pts[1], pts[2], iter.conicWeight());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkPath::kCubic_Verb:
|
|
|
|
if (enabled) {
|
|
|
|
result.cubicTo(pts[1], pts[2], pts[3]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkPath::kClose_Verb:
|
|
|
|
if (enabled) {
|
|
|
|
result.close();
|
|
|
|
}
|
|
|
|
if (++contourCount >= fSelected.count()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
enabled = fSelected[contourCount];
|
|
|
|
addMoveTo = true;
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
SkDEBUGFAIL("bad verb");
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
SubsetVerbs::SubsetVerbs(const SkPath& path)
|
|
|
|
: SubsetPath(path) {
|
|
|
|
SkPath::RawIter iter(fPath);
|
|
|
|
uint8_t verb;
|
|
|
|
SkPoint pts[4];
|
|
|
|
int verbCount = 0;
|
|
|
|
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
|
|
|
|
switch (verb) {
|
|
|
|
case SkPath::kMove_Verb:
|
|
|
|
break;
|
|
|
|
case SkPath::kLine_Verb:
|
|
|
|
case SkPath::kQuad_Verb:
|
|
|
|
case SkPath::kConic_Verb:
|
|
|
|
case SkPath::kCubic_Verb:
|
|
|
|
++verbCount;
|
|
|
|
break;
|
|
|
|
case SkPath::kClose_Verb:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SkDEBUGFAIL("bad verb");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int index = 0; index < verbCount; ++index) {
|
|
|
|
*fSelected.append() = true;
|
|
|
|
}
|
|
|
|
fTries = verbCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkPath SubsetVerbs::getSubsetPath() const {
|
|
|
|
SkPath result;
|
|
|
|
result.setFillType(fPath.getFillType());
|
|
|
|
if (!fSelected.count()) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
SkPath::RawIter iter(fPath);
|
|
|
|
uint8_t verb;
|
|
|
|
SkPoint pts[4];
|
|
|
|
int verbIndex = 0;
|
|
|
|
bool addMoveTo = true;
|
|
|
|
bool addLineTo = false;
|
|
|
|
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
|
|
|
|
bool enabled = SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb
|
Revert "implement SkTDArray with std::vector"
This reverts commit 80e1d56e198c5fd9fe6db0c945bd558053a8dc6a.
Reason for revert: SkRTree.cpp:57 asserting, probably this?
Original change's description:
> implement SkTDArray with std::vector
>
> It's always worth seeing if we can get away with replacing custom data
> structures with ones from the standard library. Our array-like types
> are all good candidates to replace with std::vector, and it's especially
> easy to start with SkTDArray. Unlike the others, it has no preallocated
> S-variant, which is tricky to make work with std::vector.
>
> SkTDArray also has known integer overflow bugs, leading to out of range
> writes. It'd be _very_ nice to ditch it for a better standard vector.
>
> I removed a bunch of unused or little-used methods, and updated a couple
> call sites that used methods in unusual or dangerous ways.
>
> I've had to tweak GrAAConvexTessellator and SkBaseShadowTessellator just
> a touch to work within the constraints of an std::vector impl. It's not
> intended to be legal to write to the reserved-but-not-counted elements
> of an SkTDArray, but you can get away with it in our old implementation.
> This version now uses setCount() to actually reserve and count them, and
> should have the same performance and use the same amount of memory.
>
> The PathMeasure_explosion GM I added recently to reproduce this bug now
> draws without triggering undefined behavior or ASAN errors, provided you
> have ~40GB of RAM.
>
> Bug: skia:7674
>
> Change-Id: I4eacae18a976cd4a6d218102f8ca5d973d4d7d0e
> Reviewed-on: https://skia-review.googlesource.com/115982
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Mike Klein <mtklein@chromium.org>
TBR=mtklein@chromium.org,bungeman@google.com,brianosman@google.com
Change-Id: Icffd9f22fe89746a970ff598e1a05c774960bc0e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:7674
Reviewed-on: https://skia-review.googlesource.com/117901
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Mike Klein <mtklein@chromium.org>
2018-04-02 20:37:42 +00:00
|
|
|
? fSelected[verbIndex++] : false;
|
2015-10-30 19:03:06 +00:00
|
|
|
if (enabled) {
|
|
|
|
if (addMoveTo) {
|
|
|
|
result.moveTo(pts[0]);
|
|
|
|
addMoveTo = false;
|
|
|
|
} else if (addLineTo) {
|
|
|
|
result.lineTo(pts[0]);
|
|
|
|
addLineTo = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (verb) {
|
|
|
|
case SkPath::kMove_Verb:
|
|
|
|
break;
|
|
|
|
case SkPath::kLine_Verb:
|
|
|
|
if (enabled) {
|
|
|
|
result.lineTo(pts[1]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkPath::kQuad_Verb:
|
|
|
|
if (enabled) {
|
|
|
|
result.quadTo(pts[1], pts[2]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkPath::kConic_Verb:
|
|
|
|
if (enabled) {
|
|
|
|
result.conicTo(pts[1], pts[2], iter.conicWeight());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkPath::kCubic_Verb:
|
|
|
|
if (enabled) {
|
|
|
|
result.cubicTo(pts[1], pts[2], pts[3]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SkPath::kClose_Verb:
|
|
|
|
result.close();
|
|
|
|
addMoveTo = true;
|
|
|
|
addLineTo = false;
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
SkDEBUGFAIL("bad verb");
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
addLineTo = !enabled;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|