combine vertical overlapping edges
Paths outside clips, and sometimes paths inside clips, devolve to multiple adjacent or overlapping vertical edges. Combine these edges when possible to reduce the overall edge count. R=reed@google.com BUG=573166 GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1654433002 Review URL: https://codereview.chromium.org/1654433002
This commit is contained in:
parent
02a6bfaaaa
commit
afd25f703d
@ -22,11 +22,70 @@ SkEdgeBuilder::SkEdgeBuilder() : fAlloc(16*1024) {
|
|||||||
fEdgeList = nullptr;
|
fEdgeList = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkEdgeBuilder::Combine SkEdgeBuilder::CombineVertical(const SkEdge* edge, SkEdge* last) {
|
||||||
|
if (last->fCurveCount || last->fDX || edge->fX != last->fX) {
|
||||||
|
return kNo_Combine;
|
||||||
|
}
|
||||||
|
if (edge->fWinding == last->fWinding) {
|
||||||
|
if (edge->fLastY + 1 == last->fFirstY) {
|
||||||
|
last->fFirstY = edge->fFirstY;
|
||||||
|
return kPartial_Combine;
|
||||||
|
}
|
||||||
|
if (edge->fFirstY == last->fLastY + 1) {
|
||||||
|
last->fLastY = edge->fLastY;
|
||||||
|
return kPartial_Combine;
|
||||||
|
}
|
||||||
|
return kNo_Combine;
|
||||||
|
}
|
||||||
|
if (edge->fFirstY == last->fFirstY) {
|
||||||
|
if (edge->fLastY == last->fLastY) {
|
||||||
|
return kTotal_Combine;
|
||||||
|
}
|
||||||
|
if (edge->fLastY < last->fLastY) {
|
||||||
|
last->fFirstY = edge->fLastY + 1;
|
||||||
|
return kPartial_Combine;
|
||||||
|
}
|
||||||
|
last->fFirstY = last->fLastY + 1;
|
||||||
|
last->fLastY = edge->fLastY;
|
||||||
|
last->fWinding = edge->fWinding;
|
||||||
|
return kPartial_Combine;
|
||||||
|
}
|
||||||
|
if (edge->fLastY == last->fLastY) {
|
||||||
|
if (edge->fFirstY > last->fFirstY) {
|
||||||
|
last->fLastY = edge->fFirstY - 1;
|
||||||
|
return kPartial_Combine;
|
||||||
|
}
|
||||||
|
last->fLastY = last->fFirstY - 1;
|
||||||
|
last->fFirstY = edge->fFirstY;
|
||||||
|
last->fWinding = edge->fWinding;
|
||||||
|
return kPartial_Combine;
|
||||||
|
}
|
||||||
|
return kNo_Combine;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool vertical_line(const SkEdge* edge) {
|
||||||
|
#ifdef SK_SUPPORT_LEGACY_VERTICAL_EDGE // this disables combining vertical overlapping edges
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
return !edge->fDX && !edge->fCurveCount;
|
||||||
|
}
|
||||||
|
|
||||||
void SkEdgeBuilder::addLine(const SkPoint pts[]) {
|
void SkEdgeBuilder::addLine(const SkPoint pts[]) {
|
||||||
SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc);
|
SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc);
|
||||||
if (edge->setLine(pts[0], pts[1], fShiftUp)) {
|
if (edge->setLine(pts[0], pts[1], fShiftUp)) {
|
||||||
|
if (vertical_line(edge) && fList.count()) {
|
||||||
|
Combine combine = CombineVertical(edge, *(fList.end() - 1));
|
||||||
|
if (kNo_Combine != combine) {
|
||||||
|
if (kTotal_Combine == combine) {
|
||||||
|
fList.pop();
|
||||||
|
}
|
||||||
|
goto unallocate_edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
fList.push(edge);
|
fList.push(edge);
|
||||||
} else {
|
} else {
|
||||||
|
unallocate_edge:
|
||||||
|
;
|
||||||
// TODO: unallocate edge from storage...
|
// TODO: unallocate edge from storage...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,6 +138,11 @@ static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) {
|
|||||||
SkIntToScalar(src.fBottom >> shift));
|
SkIntToScalar(src.fBottom >> shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkEdge* edge, SkEdge** edgePtr) {
|
||||||
|
return !vertical_line(edge) || edgePtr <= fEdgeList ? kNo_Combine :
|
||||||
|
CombineVertical(edge, edgePtr[-1]);
|
||||||
|
}
|
||||||
|
|
||||||
int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shiftUp,
|
int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shiftUp,
|
||||||
bool canCullToTheRight) {
|
bool canCullToTheRight) {
|
||||||
SkPath::Iter iter(path, true);
|
SkPath::Iter iter(path, true);
|
||||||
@ -119,7 +183,12 @@ int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift
|
|||||||
SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments);
|
SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments);
|
||||||
for (int i = 0; i < lineCount; i++) {
|
for (int i = 0; i < lineCount; i++) {
|
||||||
if (edge->setLine(lines[i], lines[i + 1], shiftUp)) {
|
if (edge->setLine(lines[i], lines[i + 1], shiftUp)) {
|
||||||
*edgePtr++ = edge++;
|
Combine combine = checkVertical(edge, edgePtr);
|
||||||
|
if (kNo_Combine == combine) {
|
||||||
|
*edgePtr++ = edge++;
|
||||||
|
} else if (kTotal_Combine == combine) {
|
||||||
|
--edgePtr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -139,7 +208,12 @@ int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift
|
|||||||
break;
|
break;
|
||||||
case SkPath::kLine_Verb:
|
case SkPath::kLine_Verb:
|
||||||
if (edge->setLine(pts[0], pts[1], shiftUp)) {
|
if (edge->setLine(pts[0], pts[1], shiftUp)) {
|
||||||
*edgePtr++ = edge++;
|
Combine combine = checkVertical(edge, edgePtr);
|
||||||
|
if (kNo_Combine == combine) {
|
||||||
|
*edgePtr++ = edge++;
|
||||||
|
} else if (kTotal_Combine == combine) {
|
||||||
|
--edgePtr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -27,6 +27,15 @@ public:
|
|||||||
SkEdge** edgeList() { return fEdgeList; }
|
SkEdge** edgeList() { return fEdgeList; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum Combine {
|
||||||
|
kNo_Combine,
|
||||||
|
kPartial_Combine,
|
||||||
|
kTotal_Combine
|
||||||
|
};
|
||||||
|
|
||||||
|
static Combine CombineVertical(const SkEdge* edge, SkEdge* last);
|
||||||
|
Combine checkVertical(const SkEdge* edge, SkEdge** edgePtr);
|
||||||
|
|
||||||
SkChunkAlloc fAlloc;
|
SkChunkAlloc fAlloc;
|
||||||
SkTDArray<SkEdge*> fList;
|
SkTDArray<SkEdge*> fList;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user