aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkEdgeBuilder.cpp
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-02 14:26:43 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-02 14:26:43 +0000
commitc8d640b1788822a8697816b645c327383a1d1f20 (patch)
treeb921a8de02e02fccf240404a9fcf7fb78b8885e4 /src/core/SkEdgeBuilder.cpp
parentbc7ef5a783c612d8bc391b8fa90767bb1d1c59e2 (diff)
special-case edge-building for polygons (paths with only lines)
makes the dashing bench faster (from 13.4 -> 11.5 ticks) Review URL: https://codereview.appspot.com/6449080 git-svn-id: http://skia.googlecode.com/svn/trunk@4916 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core/SkEdgeBuilder.cpp')
-rw-r--r--src/core/SkEdgeBuilder.cpp86
1 files changed, 83 insertions, 3 deletions
diff --git a/src/core/SkEdgeBuilder.cpp b/src/core/SkEdgeBuilder.cpp
index 7474ba9502..01a40f0f30 100644
--- a/src/core/SkEdgeBuilder.cpp
+++ b/src/core/SkEdgeBuilder.cpp
@@ -12,14 +12,16 @@
#include "SkLineClipper.h"
#include "SkGeometry.h"
-SkEdgeBuilder::SkEdgeBuilder() : fAlloc(16*1024) {}
-
template <typename T> static T* typedAllocThrow(SkChunkAlloc& alloc) {
return static_cast<T*>(alloc.allocThrow(sizeof(T)));
}
///////////////////////////////////////////////////////////////////////////////
+SkEdgeBuilder::SkEdgeBuilder() : fAlloc(16*1024) {
+ fEdgeList = NULL;
+}
+
void SkEdgeBuilder::addLine(const SkPoint pts[]) {
SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc);
if (edge->setLine(pts[0], pts[1], NULL, fShiftUp)) {
@@ -77,12 +79,90 @@ static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) {
SkIntToScalar(src.fBottom >> shift));
}
+int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip,
+ int shiftUp) {
+ SkPath::Iter iter(path, true);
+ SkPoint pts[4];
+ SkPath::Verb verb;
+
+ int maxEdgeCount = path.countPoints();
+ if (iclip) {
+ // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since
+ // we turn portions that are clipped out on the left/right into vertical
+ // segments.
+ maxEdgeCount *= SkLineClipper::kMaxClippedLineSegments;
+ }
+ size_t maxEdgeSize = maxEdgeCount * sizeof(SkEdge);
+ size_t maxEdgePtrSize = maxEdgeCount * sizeof(SkEdge*);
+
+ // 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);
+ // Record the beginning of our pointers, so we can return them to the caller
+ fEdgeList = edgePtr;
+
+ if (iclip) {
+ SkRect clip;
+ setShiftedClip(&clip, *iclip, shiftUp);
+
+ while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ case SkPath::kClose_Verb:
+ // we ignore these, and just get the whole segment from
+ // the corresponding line/quad/cubic verbs
+ break;
+ case SkPath::kLine_Verb: {
+ SkPoint lines[SkLineClipper::kMaxPoints];
+ int lineCount = SkLineClipper::ClipLine(pts, clip, lines);
+ SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments);
+ for (int i = 0; i < lineCount; i++) {
+ if (edge->setLine(lines[i], lines[i + 1], NULL, shiftUp)) {
+ *edgePtr++ = edge++;
+ }
+ }
+ break;
+ }
+ default:
+ SkDEBUGFAIL("unexpected verb");
+ break;
+ }
+ }
+ } else {
+ while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ case SkPath::kClose_Verb:
+ // 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], NULL, shiftUp)) {
+ *edgePtr++ = edge++;
+ }
+ break;
+ default:
+ SkDEBUGFAIL("unexpected verb");
+ break;
+ }
+ }
+ }
+ SkASSERT((char*)edge <= (char*)fEdgeList);
+ SkASSERT(edgePtr - fEdgeList <= maxEdgeCount);
+ return edgePtr - fEdgeList;
+}
+
int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip,
int shiftUp) {
fAlloc.reset();
fList.reset();
fShiftUp = shiftUp;
+ if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) {
+ return this->buildPoly(path, iclip, shiftUp);
+ }
+
SkPath::Iter iter(path, true);
SkPoint pts[4];
SkPath::Verb verb;
@@ -155,7 +235,7 @@ int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip,
}
}
}
+ fEdgeList = fList.begin();
return fList.count();
}
-