Index: src/core/SkEdgeBuilder.cpp |
diff --git a/src/core/SkEdgeBuilder.cpp b/src/core/SkEdgeBuilder.cpp |
index af68e0ff656ea0130851ce5bf0934403a34ebf9c..1a160882d466d3b3d71355ec560da7aa96f4a632 100644 |
--- a/src/core/SkEdgeBuilder.cpp |
+++ b/src/core/SkEdgeBuilder.cpp |
@@ -7,6 +7,7 @@ |
#include "SkEdgeBuilder.h" |
#include "SkPath.h" |
#include "SkEdge.h" |
+#include "SkAnalyticEdge.h" |
#include "SkEdgeClipper.h" |
#include "SkLineClipper.h" |
#include "SkGeometry.h" |
@@ -62,45 +63,135 @@ SkEdgeBuilder::Combine SkEdgeBuilder::CombineVertical(const SkEdge* edge, SkEdge |
return kNo_Combine; |
} |
-static bool vertical_line(const SkEdge* edge) { |
+SkEdgeBuilder::Combine SkEdgeBuilder::CombineVertical( |
+ const SkAnalyticEdge* edge, SkAnalyticEdge* last) { |
+ SkASSERT(fAnalyticAA); |
+ if (last->fCurveCount || last->fDX || edge->fX != last->fX) { |
+ return kNo_Combine; |
+ } |
+ if (edge->fWinding == last->fWinding) { |
+ if (edge->fLowerY == last->fUpperY) { |
+ last->fUpperY = edge->fUpperY; |
+ last->fY = last->fUpperY; |
+ return kPartial_Combine; |
+ } |
+ if (edge->fUpperY == last->fLowerY) { |
+ last->fLowerY = edge->fLowerY; |
+ return kPartial_Combine; |
+ } |
+ return kNo_Combine; |
+ } |
+ if (edge->fUpperY == last->fUpperY) { |
+ if (edge->fLowerY == last->fLowerY) { |
+ return kTotal_Combine; |
+ } |
+ if (edge->fLowerY < last->fLowerY) { |
+ last->fUpperY = edge->fLowerY; |
+ last->fY = last->fUpperY; |
+ return kPartial_Combine; |
+ } |
+ last->fUpperY = last->fLowerY; |
+ last->fY = last->fUpperY; |
+ last->fLowerY = edge->fLowerY; |
+ last->fWinding = edge->fWinding; |
+ return kPartial_Combine; |
+ } |
+ if (edge->fLowerY == last->fLowerY) { |
+ if (edge->fUpperY > last->fUpperY) { |
+ last->fLowerY = edge->fUpperY; |
+ return kPartial_Combine; |
+ } |
+ last->fLowerY = last->fUpperY; |
+ last->fUpperY = edge->fUpperY; |
+ last->fY = last->fUpperY; |
+ last->fWinding = edge->fWinding; |
+ return kPartial_Combine; |
+ } |
+ return kNo_Combine; |
+} |
+ |
+bool SkEdgeBuilder::vertical_line(const SkEdge* edge) { |
+ return !edge->fDX && !edge->fCurveCount; |
+} |
+ |
+bool SkEdgeBuilder::vertical_line(const SkAnalyticEdge* edge) { |
+ SkASSERT(fAnalyticAA); |
return !edge->fDX && !edge->fCurveCount; |
} |
void SkEdgeBuilder::addLine(const SkPoint pts[]) { |
- SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc); |
- 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(); |
+ if (fAnalyticAA) { |
+ SkAnalyticEdge* edge = typedAllocThrow<SkAnalyticEdge>(fAlloc); |
+ if (edge->setLine(pts[0], pts[1])) { |
+ if (vertical_line(edge) && fList.count()) { |
+ Combine combine = CombineVertical(edge, (SkAnalyticEdge*)*(fList.end() - 1)); |
+ if (kNo_Combine != combine) { |
+ if (kTotal_Combine == combine) { |
+ fList.pop(); |
+ } |
+ goto unallocate_analytic_edge; |
} |
- goto unallocate_edge; |
} |
+ fList.push(edge); |
+ } else { |
+unallocate_analytic_edge: |
+ ; |
+ // TODO: unallocate edge from storage... |
} |
- fList.push(edge); |
} else { |
+ SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc); |
+ if (edge->setLine(pts[0], pts[1], fShiftUp)) { |
+ if (vertical_line(edge) && fList.count()) { |
+ Combine combine = CombineVertical(edge, (SkEdge*)*(fList.end() - 1)); |
+ if (kNo_Combine != combine) { |
+ if (kTotal_Combine == combine) { |
+ fList.pop(); |
+ } |
+ goto unallocate_edge; |
+ } |
+ } |
+ fList.push(edge); |
+ } else { |
unallocate_edge: |
- ; |
- // TODO: unallocate edge from storage... |
+ ; |
+ // TODO: unallocate edge from storage... |
+ } |
} |
} |
void SkEdgeBuilder::addQuad(const SkPoint pts[]) { |
- SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc); |
- if (edge->setQuadratic(pts, fShiftUp)) { |
- fList.push(edge); |
+ if (fAnalyticAA) { |
+ SkAnalyticQuadraticEdge* edge = typedAllocThrow<SkAnalyticQuadraticEdge>(fAlloc); |
+ if (edge->setQuadratic(pts)) { |
+ fList.push(edge); |
+ } else { |
+ // TODO: unallocate edge from storage... |
+ } |
} else { |
- // TODO: unallocate edge from storage... |
+ SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc); |
+ if (edge->setQuadratic(pts, fShiftUp)) { |
+ fList.push(edge); |
+ } else { |
+ // TODO: unallocate edge from storage... |
+ } |
} |
} |
void SkEdgeBuilder::addCubic(const SkPoint pts[]) { |
- SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc); |
- if (edge->setCubic(pts, fShiftUp)) { |
- fList.push(edge); |
+ if (fAnalyticAA) { |
+ SkAnalyticCubicEdge* edge = typedAllocThrow<SkAnalyticCubicEdge>(fAlloc); |
+ if (edge->setCubic(pts)) { |
+ fList.push(edge); |
+ } else { |
+ // TODO: unallocate edge from storage... |
+ } |
} else { |
- // TODO: unallocate edge from storage... |
+ SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc); |
+ if (edge->setCubic(pts, fShiftUp)) { |
+ fList.push(edge); |
+ } else { |
+ // TODO: unallocate edge from storage... |
+ } |
} |
} |
@@ -135,7 +226,14 @@ static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) { |
} |
SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkEdge* edge, SkEdge** edgePtr) { |
- return !vertical_line(edge) || edgePtr <= fEdgeList ? kNo_Combine : |
+ return !vertical_line(edge) || edgePtr <= (SkEdge**)fEdgeList ? kNo_Combine : |
+ CombineVertical(edge, edgePtr[-1]); |
+} |
+ |
+SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkAnalyticEdge* edge, |
+ SkAnalyticEdge** edgePtr) { |
+ SkASSERT(fAnalyticAA); |
+ return !vertical_line(edge) || edgePtr <= (SkAnalyticEdge**)fEdgeList ? kNo_Combine : |
CombineVertical(edge, edgePtr[-1]); |
} |
@@ -152,15 +250,16 @@ int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift |
// segments. |
maxEdgeCount *= SkLineClipper::kMaxClippedLineSegments; |
} |
- size_t maxEdgeSize = maxEdgeCount * sizeof(SkEdge); |
- size_t maxEdgePtrSize = maxEdgeCount * sizeof(SkEdge*); |
+ size_t edgeSize = fAnalyticAA ? sizeof(SkAnalyticEdge) : sizeof(SkEdge); |
+ size_t maxEdgeSize = maxEdgeCount * edgeSize; |
+ size_t maxEdgePtrSize = maxEdgeCount * sizeof(char*); |
// lets store the edges and their pointers in the same block |
char* storage = (char*)fAlloc.allocThrow(maxEdgeSize + maxEdgePtrSize); |
- SkEdge* edge = reinterpret_cast<SkEdge*>(storage); |
- SkEdge** edgePtr = reinterpret_cast<SkEdge**>(storage + maxEdgeSize); |
+ char* edge = (char*)storage; |
+ char** edgePtr = (char**)(storage + maxEdgeSize); |
// Record the beginning of our pointers, so we can return them to the caller |
- fEdgeList = edgePtr; |
+ fEdgeList = (void**)edgePtr; |
if (iclip) { |
SkRect clip; |
@@ -178,10 +277,16 @@ int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift |
int lineCount = SkLineClipper::ClipLine(pts, clip, lines, canCullToTheRight); |
SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments); |
for (int i = 0; i < lineCount; i++) { |
- if (edge->setLine(lines[i], lines[i + 1], shiftUp)) { |
- Combine combine = checkVertical(edge, edgePtr); |
+ bool setLineResult = fAnalyticAA ? |
+ ((SkAnalyticEdge*)edge)->setLine(lines[i], lines[i + 1]) : |
+ ((SkEdge*)edge)->setLine(lines[i], lines[i + 1], shiftUp); |
+ if (setLineResult) { |
+ Combine combine = fAnalyticAA ? |
+ checkVertical((SkAnalyticEdge*)edge, (SkAnalyticEdge**)edgePtr) : |
+ checkVertical((SkEdge*)edge, (SkEdge**)edgePtr); |
if (kNo_Combine == combine) { |
- *edgePtr++ = edge++; |
+ *edgePtr++ = edge; |
+ edge += edgeSize; |
} else if (kTotal_Combine == combine) { |
--edgePtr; |
} |
@@ -202,16 +307,23 @@ int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift |
// we ignore these, and just get the whole segment from |
// the corresponding line/quad/cubic verbs |
break; |
- case SkPath::kLine_Verb: |
- if (edge->setLine(pts[0], pts[1], shiftUp)) { |
- Combine combine = checkVertical(edge, edgePtr); |
+ case SkPath::kLine_Verb: { |
+ bool setLineResult = fAnalyticAA ? |
+ ((SkAnalyticEdge*)edge)->setLine(pts[0], pts[1]) : |
+ ((SkEdge*)edge)->setLine(pts[0], pts[1], shiftUp); |
+ if (setLineResult) { |
+ Combine combine = fAnalyticAA ? |
+ checkVertical((SkAnalyticEdge*)edge, (SkAnalyticEdge**)edgePtr) : |
+ checkVertical((SkEdge*)edge, (SkEdge**)edgePtr); |
if (kNo_Combine == combine) { |
- *edgePtr++ = edge++; |
+ *edgePtr++ = edge; |
+ edge += edgeSize; |
} else if (kTotal_Combine == combine) { |
--edgePtr; |
} |
} |
break; |
+ } |
default: |
SkDEBUGFAIL("unexpected verb"); |
break; |
@@ -219,8 +331,8 @@ int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift |
} |
} |
SkASSERT((char*)edge <= (char*)fEdgeList); |
- SkASSERT(edgePtr - fEdgeList <= maxEdgeCount); |
- return SkToInt(edgePtr - fEdgeList); |
+ SkASSERT(edgePtr - (char**)fEdgeList <= maxEdgeCount); |
+ return SkToInt(edgePtr - (char**)fEdgeList); |
} |
static void handle_quad(SkEdgeBuilder* builder, const SkPoint pts[3]) { |
@@ -232,10 +344,11 @@ static void handle_quad(SkEdgeBuilder* builder, const SkPoint pts[3]) { |
} |
int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, int shiftUp, |
- bool canCullToTheRight) { |
+ bool canCullToTheRight, bool analyticAA) { |
fAlloc.reset(); |
fList.reset(); |
fShiftUp = shiftUp; |
+ fAnalyticAA = analyticAA; |
if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) { |
return this->buildPoly(path, iclip, shiftUp, canCullToTheRight); |