aboutsummaryrefslogtreecommitdiffhomepage
path: root/gpu
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-05-16 17:21:57 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-05-16 17:21:57 +0000
commit07f3ee10d34f09342abb93d758b5e151ff78f7a5 (patch)
treeee95d5ac1d798dc2a0f52b37acfa61d2cfe140b4 /gpu
parentff174b39474df20945fc7cc5c9d5bb68916f39a8 (diff)
use SkPath for GrPath, removing GrPathIter entirely
Diffstat (limited to 'gpu')
-rw-r--r--gpu/include/GrClipIterator.h2
-rw-r--r--gpu/include/GrContext.h19
-rw-r--r--gpu/include/GrFontScaler.h4
-rw-r--r--gpu/include/GrGpu.h3
-rw-r--r--gpu/include/GrPath.h87
-rw-r--r--gpu/include/GrPathIter.h74
-rw-r--r--gpu/include/GrPathRenderer.h23
-rw-r--r--gpu/include/GrTesselatedPathRenderer.h10
-rw-r--r--gpu/src/GrClip.cpp2
-rw-r--r--gpu/src/GrContext.cpp22
-rw-r--r--gpu/src/GrGpu.cpp19
-rw-r--r--gpu/src/GrPath.cpp523
-rw-r--r--gpu/src/GrPathRenderer.cpp31
-rw-r--r--gpu/src/GrPathUtils.cpp10
-rw-r--r--gpu/src/GrPathUtils.h5
-rw-r--r--gpu/src/GrTesselatedPathRenderer.cpp22
-rw-r--r--gpu/src/GrTextContext.cpp4
-rw-r--r--gpu/src/gr_files.mk2
-rw-r--r--gpu/src/gr_unittests.cpp121
19 files changed, 196 insertions, 787 deletions
diff --git a/gpu/include/GrClipIterator.h b/gpu/include/GrClipIterator.h
index 1fcbdd178a..f7f74a76b1 100644
--- a/gpu/include/GrClipIterator.h
+++ b/gpu/include/GrClipIterator.h
@@ -47,7 +47,7 @@ public:
* Return the current path. It is an error to call this when isDone() is
* true or when getType() is kRect_Type.
*/
- virtual GrPathIter* getPathIter() = 0;
+ virtual const GrPath* getPath() = 0;
/**
* Return the fill rule for the path. It is an error to call this when
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 951c0e66e7..c29526ad17 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -25,7 +25,6 @@
class GrFontCache;
class GrGpu;
struct GrGpuStats;
-class GrPathIter;
class GrVertexBufferAllocPool;
class GrIndexBufferAllocPool;
class GrInOrderDrawBuffer;
@@ -323,22 +322,14 @@ public:
* Draws a path.
*
* @param paint describes how to color pixels.
- * @param pathIter the path to draw
+ * @param path the path to draw
* @param fill the path filling rule to use.
* @param translate optional additional translation applied to the
* path.
*/
- void drawPath(const GrPaint& paint,
- GrPathIter* pathIter,
- GrPathFill fill,
- const GrPoint* translate = NULL);
- /**
- * Helper version of drawPath that takes a GrPath
- */
- void drawPath(const GrPaint& paint,
- const GrPath& path,
- GrPathFill fill,
+ void drawPath(const GrPaint& paint, const GrPath& path, GrPathFill fill,
const GrPoint* translate = NULL);
+
/**
* Draws vertices with a paint.
*
@@ -585,9 +576,7 @@ private:
void drawClipIntoStencil();
- GrPathRenderer* getPathRenderer(const GrDrawTarget* target,
- GrPathIter* path,
- GrPathFill fill);
+ GrPathRenderer* getPathRenderer(const GrDrawTarget*, const GrPath&, GrPathFill);
struct OffscreenRecord;
// we currently only expose stage 0 through the paint so use stage 1. We
diff --git a/gpu/include/GrFontScaler.h b/gpu/include/GrFontScaler.h
index 77730d7eb9..ab73ea4f5c 100644
--- a/gpu/include/GrFontScaler.h
+++ b/gpu/include/GrFontScaler.h
@@ -21,7 +21,7 @@
#include "GrGlyph.h"
#include "GrKey.h"
-class GrPath;
+class SkPath;
/**
* This is a virtual base class which Gr's interface to the host platform's
@@ -37,7 +37,7 @@ public:
virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds) = 0;
virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height,
int rowBytes, void* image) = 0;
- virtual bool getGlyphPath(uint16_t glyphID, GrPath*) = 0;
+ virtual bool getGlyphPath(uint16_t glyphID, SkPath*) = 0;
};
#endif
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index e44956f709..1bb5c542e6 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -513,8 +513,7 @@ private:
void prepareIndexPool();
// determines the path renderer used to draw a clip path element.
- GrPathRenderer* getClipPathRenderer(GrPathIter* path,
- GrPathFill fill);
+ GrPathRenderer* getClipPathRenderer(const SkPath& path, GrPathFill fill);
void handleDirtyContext() {
if (fContextIsDirty) {
diff --git a/gpu/include/GrPath.h b/gpu/include/GrPath.h
index f958329d3f..c23cfc47c8 100644
--- a/gpu/include/GrPath.h
+++ b/gpu/include/GrPath.h
@@ -18,91 +18,10 @@
#ifndef GrPath_DEFINED
#define GrPath_DEFINED
-#include "GrPathSink.h"
-#include "GrPathIter.h"
-#include "GrTDArray.h"
-#include "GrPoint.h"
-#include "GrRect.h"
+#include "GrTypes.h"
+#include "SkPath.h"
-class GrPath : public GrPathSink {
-public:
- GrPath();
- GrPath(const GrPath&);
- explicit GrPath(GrPathIter&);
- virtual ~GrPath();
-
- GrConvexHint getConvexHint() const { return fConvexHint; }
- void setConvexHint(GrConvexHint hint) { fConvexHint = hint; }
-
- const GrRect& getConservativeBounds() const { return fConservativeBounds; }
-
- void resetFromIter(GrPathIter*);
-
- bool operator ==(const GrPath& path) const;
- bool operator !=(const GrPath& path) const { return !(*this == path); }
- // overrides from GrPathSink
-
- virtual void moveTo(GrScalar x, GrScalar y);
- virtual void lineTo(GrScalar x, GrScalar y);
- virtual void quadTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1);
- virtual void cubicTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1,
- GrScalar x2, GrScalar y2);
- virtual void close();
-
- /**
- * Offset the path by (tx, ty), adding tx to the horizontal position
- * and adds ty to the vertical position of every point.
- */
- void offset(GrScalar tx, GrScalar ty);
-
- class Iter : public GrPathIter {
- public:
- /**
- * Creates an uninitialized iterator
- */
- Iter();
-
- Iter(const GrPath& path);
-
- // overrides from GrPathIter
- virtual GrPathCmd next(GrPoint points[]);
- virtual GrConvexHint convexHint() const;
- virtual GrPathCmd next();
- virtual void rewind();
- virtual bool getConservativeBounds(GrRect* rect) const;
-
- /**
- * Sets iterator to begining of path
- */
- void reset(const GrPath& path);
- private:
- const GrPath* fPath;
- GrPoint fLastPt;
- int fCmdIndex;
- int fPtIndex;
- };
-
- static void ConvexUnitTest();
-
-private:
-
- GrTDArray<GrPathCmd> fCmds;
- GrTDArray<GrPoint> fPts;
- GrConvexHint fConvexHint;
- GrRect fConservativeBounds;
-
- // this ensures we have a moveTo at the start of each contour
- inline void ensureMoveTo();
-
- bool wasLastVerb(GrPathCmd cmd) const {
- int count = fCmds.count();
- return count > 0 && cmd == fCmds[count - 1];
- }
-
- friend class Iter;
-
- typedef GrPathSink INHERITED;
-};
+typedef SkPath GrPath;
#endif
diff --git a/gpu/include/GrPathIter.h b/gpu/include/GrPathIter.h
deleted file mode 100644
index e67ff69856..0000000000
--- a/gpu/include/GrPathIter.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- Copyright 2010 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-
-#ifndef GrPathIter_DEFINED
-#define GrPathIter_DEFINED
-
-#include "GrRect.h"
-
-/**
- 2D Path iterator. Porting layer creates a subclass of this. It allows Ganesh to
- parse the top-level API's 2D paths. Supports lines, quadratics, and cubic
- pieces and moves (multi-part paths).
- */
-class GrPathIter {
-public:
-
- virtual ~GrPathIter() {};
-
- /**
- * Iterates through the path. Should not be called after
- * kEnd_Command has been returned once. This version retrieves the
- * points for the command.
- * @param points The points relevant to returned commend. See Command
- * enum for number of points valid for each command.
- * @return The next command of the path.
- */
- virtual GrPathCmd next(GrPoint points[4]) = 0;
-
- /**
- * If the host API has knowledge of the convexity of the path
- * it can be communicated by this hint. Gr can analyze the path
- * as it is iterated. So it is not necessary to do additional work to
- * compute convexity status if it isn't already determined.
- *
- * @return a hint about the convexity of the path.
- */
- virtual GrConvexHint convexHint() const = 0;
-
- /**
- * Iterates through the path. Should not be called after
- * kEnd_Command has been returned once. This version does not retrieve the
- * points for the command.
- * @return The next command of the path.
- */
- virtual GrPathCmd next() = 0;
-
- /**
- * Returns conservative bounds on the path points. If returns false then
- * no bounds are available.
- */
- virtual bool getConservativeBounds(GrRect* rect) const = 0;
-
- /**
- Restarts iteration from the beginning.
- */
- virtual void rewind() = 0;
-
-};
-
-#endif
diff --git a/gpu/include/GrPathRenderer.h b/gpu/include/GrPathRenderer.h
index 21cab6bb1a..1ebad4f530 100644
--- a/gpu/include/GrPathRenderer.h
+++ b/gpu/include/GrPathRenderer.h
@@ -19,7 +19,7 @@
#include "GrDrawTarget.h"
-class GrPathIter;
+class SkPath;
struct GrPoint;
/**
@@ -37,8 +37,7 @@ public:
*
* @return true if the path can be drawn by this object, false otherwise.
*/
- virtual bool canDrawPath(const GrDrawTarget* target,
- GrPathIter* path,
+ virtual bool canDrawPath(const GrDrawTarget* target, const SkPath& path,
GrPathFill fill) const = 0;
/**
@@ -57,7 +56,7 @@ public:
*/
virtual void drawPath(GrDrawTarget* target,
GrDrawTarget::StageBitfield stages,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill,
const GrPoint* translate) = 0;
@@ -80,7 +79,7 @@ public:
* clips.
*/
virtual bool requiresStencilPass(const GrDrawTarget* target,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill) const { return false; }
/**
@@ -102,7 +101,7 @@ public:
* the path. NULL means (0,0).
*/
virtual void drawPathToStencil(GrDrawTarget* target,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill,
const GrPoint* translate) {
GrCrash("Unexpected call to drawPathToStencil.");
@@ -113,7 +112,7 @@ public:
* having FSAA enabled for a render target)
*/
virtual bool supportsAA(GrDrawTarget* target,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill) { return false; }
/**
@@ -138,26 +137,26 @@ public:
bool stencilWrapOpsSupport);
virtual bool canDrawPath(const GrDrawTarget* target,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill) const { return true; }
virtual void drawPath(GrDrawTarget* target,
GrDrawTarget::StageBitfield stages,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill,
const GrPoint* translate);
virtual bool requiresStencilPass(const GrDrawTarget* target,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill) const;
virtual void drawPathToStencil(GrDrawTarget* target,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill,
const GrPoint* translate);
private:
void onDrawPath(GrDrawTarget* target,
GrDrawTarget::StageBitfield stages,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill,
const GrPoint* translate,
bool stencilOnly);
diff --git a/gpu/include/GrTesselatedPathRenderer.h b/gpu/include/GrTesselatedPathRenderer.h
index accd114e4c..e37e66bdf8 100644
--- a/gpu/include/GrTesselatedPathRenderer.h
+++ b/gpu/include/GrTesselatedPathRenderer.h
@@ -25,22 +25,22 @@ public:
virtual void drawPath(GrDrawTarget* target,
GrDrawTarget::StageBitfield stages,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill,
const GrPoint* translate);
virtual bool canDrawPath(const GrDrawTarget* target,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill) const;
virtual bool requiresStencilPass(const GrDrawTarget* target,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill) const { return false; }
virtual void drawPathToStencil(GrDrawTarget* target,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill,
const GrPoint* translate);
virtual bool supportsAA(GrDrawTarget* target,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill);
};
diff --git a/gpu/src/GrClip.cpp b/gpu/src/GrClip.cpp
index 2d1680cff8..c2613bbe25 100644
--- a/gpu/src/GrClip.cpp
+++ b/gpu/src/GrClip.cpp
@@ -132,7 +132,7 @@ void GrClip::setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty,
}
break;
case kPath_ClipType:
- e.fPath.resetFromIter(iter->getPathIter());
+ e.fPath = *iter->getPath();
if (tx || ty) {
e.fPath.offset(tx, ty);
}
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 8cb932b2c4..3a4233a346 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -19,7 +19,6 @@
#include "GrTextureCache.h"
#include "GrTextStrike.h"
#include "GrMemory.h"
-#include "GrPathIter.h"
#include "GrClipIterator.h"
#include "GrIndexBuffer.h"
#include "GrInOrderDrawBuffer.h"
@@ -1155,10 +1154,8 @@ void GrContext::drawVertices(const GrPaint& paint,
///////////////////////////////////////////////////////////////////////////////
-void GrContext::drawPath(const GrPaint& paint,
- GrPathIter* path,
- GrPathFill fill,
- const GrPoint* translate) {
+void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
+ GrPathFill fill, const GrPoint* translate) {
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
GrPathRenderer* pr = this->getPathRenderer(target, path, fill);
@@ -1180,8 +1177,8 @@ void GrContext::drawPath(const GrPaint& paint,
return;
}
}
- GrRect pathBounds;
- if (path->getConservativeBounds(&pathBounds)) {
+ GrRect pathBounds = path.getBounds();
+ if (!pathBounds.isEmpty()) {
GrIRect pathIBounds;
target->getViewMatrix().mapRect(&pathBounds, pathBounds);
pathBounds.roundOut(&pathIBounds);
@@ -1204,15 +1201,6 @@ void GrContext::drawPath(const GrPaint& paint,
pr->drawPath(target, enabledStages, path, fill, translate);
}
-void GrContext::drawPath(const GrPaint& paint,
- const GrPath& path,
- GrPathFill fill,
- const GrPoint* translate) {
- GrPath::Iter iter(path);
- this->drawPath(paint, &iter, fill, translate);
-}
-
-
////////////////////////////////////////////////////////////////////////////////
void GrContext::flush(int flagsBitfield) {
@@ -1483,7 +1471,7 @@ const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
}
GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill) {
if (NULL != fCustomPathRenderer &&
fCustomPathRenderer->canDrawPath(target, path, fill)) {
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 9950afd27b..a64a8dbedc 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -467,17 +467,16 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
// resolve in/out status.
GrPathRenderer* pr = NULL;
- GrPath::Iter pathIter;
+ const GrPath* clipPath = NULL;
if (kRect_ClipType == clip.getElementType(c)) {
canRenderDirectToStencil = true;
fill = kEvenOdd_PathFill;
} else {
fill = clip.getPathFill(c);
- const GrPath& path = clip.getPath(c);
- pathIter.reset(path);
- pr = this->getClipPathRenderer(&pathIter, NonInvertedFill(fill));
+ clipPath = &clip.getPath(c);
+ pr = this->getClipPathRenderer(*clipPath, NonInvertedFill(fill));
canRenderDirectToStencil =
- !pr->requiresStencilPass(this, &pathIter,
+ !pr->requiresStencilPass(this, *clipPath,
NonInvertedFill(fill));
}
@@ -513,12 +512,10 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
} else {
if (canRenderDirectToStencil) {
this->setStencil(gDrawToStencil);
- pr->drawPath(this, 0,
- &pathIter,
- NonInvertedFill(fill),
+ pr->drawPath(this, 0, *clipPath, NonInvertedFill(fill),
NULL);
} else {
- pr->drawPathToStencil(this, &pathIter,
+ pr->drawPathToStencil(this, *clipPath,
NonInvertedFill(fill),
NULL);
}
@@ -537,7 +534,7 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
} else {
SET_RANDOM_COLOR
GrAssert(!IsFillInverted(fill));
- pr->drawPath(this, 0, &pathIter, fill, NULL);
+ pr->drawPath(this, 0, *clipPath, fill, NULL);
}
} else {
SET_RANDOM_COLOR
@@ -561,7 +558,7 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
return true;
}
-GrPathRenderer* GrGpu::getClipPathRenderer(GrPathIter* path,
+GrPathRenderer* GrGpu::getClipPathRenderer(const GrPath& path,
GrPathFill fill) {
if (NULL != fClientPathRenderer &&
fClientPathRenderer->canDrawPath(this, path, fill)) {
diff --git a/gpu/src/GrPath.cpp b/gpu/src/GrPath.cpp
deleted file mode 100644
index aa89d37382..0000000000
--- a/gpu/src/GrPath.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-#include "GrPath.h"
-
-GrPath::GrPath() {
- fConvexHint = kNone_ConvexHint;
- fConservativeBounds.setLargestInverted();
-}
-
-GrPath::GrPath(const GrPath& src) : INHERITED() {
- GrPath::Iter iter(src);
- this->resetFromIter(&iter);
-}
-
-GrPath::GrPath(GrPathIter& iter) {
- this->resetFromIter(&iter);
-}
-
-GrPath::~GrPath() {
-}
-
-bool GrPath::operator ==(const GrPath& path) const {
- if (fCmds.count() != path.fCmds.count() ||
- fPts.count() != path.fPts.count()) {
- return false;
- }
-
- for (int v = 0; v < fCmds.count(); ++v) {
- if (fCmds[v] != path.fCmds[v]) {
- return false;
- }
- }
-
- for (int p = 0; p < fPts.count(); ++p) {
- if (fPts[p] != path.fPts[p]) {
- return false;
- }
- }
- return true;
-}
-
-void GrPath::ensureMoveTo() {
- if (fCmds.isEmpty() || this->wasLastVerb(kClose_PathCmd)) {
- *fCmds.append() = kMove_PathCmd;
- fPts.append()->set(0, 0);
- fConservativeBounds.growToInclude(0,0);
- }
-}
-
-void GrPath::moveTo(GrScalar x, GrScalar y) {
- if (this->wasLastVerb(kMove_PathCmd)) {
- // overwrite prev kMove value
- fPts[fPts.count() - 1].set(x, y);
- } else {
- *fCmds.append() = kMove_PathCmd;
- fPts.append()->set(x, y);
- }
- fConservativeBounds.growToInclude(x,y);
-}
-
-void GrPath::lineTo(GrScalar x, GrScalar y) {
- this->ensureMoveTo();
- *fCmds.append() = kLine_PathCmd;
- fPts.append()->set(x, y);
- fConservativeBounds.growToInclude(x,y);
-}
-
-void GrPath::quadTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1) {
- this->ensureMoveTo();
- *fCmds.append() = kQuadratic_PathCmd;
- fPts.append()->set(x0, y0);
- fPts.append()->set(x1, y1);
- fConservativeBounds.growToInclude(x0,y0);
- fConservativeBounds.growToInclude(x1,y1);
-}
-
-void GrPath::cubicTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1,
- GrScalar x2, GrScalar y2) {
- this->ensureMoveTo();
- *fCmds.append() = kCubic_PathCmd;
- fPts.append()->set(x0, y0);
- fPts.append()->set(x1, y1);
- fPts.append()->set(x2, y2);
- fConservativeBounds.growToInclude(x0,y0);
- fConservativeBounds.growToInclude(x1,y1);
- fConservativeBounds.growToInclude(x2,y2);
-}
-
-void GrPath::close() {
- if (!fCmds.isEmpty() && !this->wasLastVerb(kClose_PathCmd)) {
- // should we allow kMove followed by kClose?
- *fCmds.append() = kClose_PathCmd;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GrPath::offset(GrScalar tx, GrScalar ty) {
- if (!tx && !ty) {
- return; // nothing to do
- }
-
- GrPoint* iter = fPts.begin();
- GrPoint* stop = fPts.end();
- while (iter < stop) {
- iter->offset(tx, ty);
- ++iter;
- }
- fConservativeBounds.offset(tx, ty);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static bool check_two_vecs(const GrVec& prevVec,
- const GrVec& currVec,
- GrScalar turnDir,
- int* xDir,
- int* yDir,
- int* flipX,
- int* flipY) {
- if (currVec.fX * *xDir < 0) {
- ++*flipX;
- if (*flipX > 2) {
- return false;
- }
- *xDir = -*xDir;
- }
- if (currVec.fY * *yDir < 0) {
- ++*flipY;
- if (*flipY > 2) {
- return false;
- }
- *yDir = -*yDir;
- }
- GrScalar d = prevVec.cross(currVec);
- return (d * turnDir) >= 0;
-}
-
-static void init_from_two_vecs(const GrVec& firstVec,
- const GrVec& secondVec,
- GrScalar* turnDir,
- int* xDir, int* yDir) {
- *turnDir = firstVec.cross(secondVec);
- if (firstVec.fX > 0) {
- *xDir = 1;
- } else if (firstVec.fX < 0) {
- *xDir = -1;
- } else {
- *xDir = 0;
- }
- if (firstVec.fY > 0) {
- *yDir = 1;
- } else if (firstVec.fY < 0) {
- *yDir = -1;
- } else {
- *yDir = 0;
- }
-}
-
-void GrPath::resetFromIter(GrPathIter* iter) {
- fPts.reset();
- fCmds.reset();
- fConservativeBounds.setLargestInverted();
-
- fConvexHint = iter->convexHint();
-
- // first point of the subpath
- GrPoint firstPt = { 0, 0 };
- // first edge of the subpath
- GrVec firstVec = { 0, 0 };
- // vec of most recently processed edge, that wasn't degenerate
- GrVec previousVec = { 0, 0 };
- // most recently processed point
- GrPoint previousPt = { 0, 0 };
-
- // sign indicates whether we're bending left or right
- GrScalar turnDir = 0;
- // number of times the direction has flipped in x or y
-
- // we track which direction we are moving in x/y and the
- // number of times it changes.
- int xDir = 0;
- int yDir = 0;
- int flipX = 0;
- int flipY = 0;
-
- // counts number of sub path pts that didn't add a degenerate edge.
- int subPathPts = 0;
- bool subPathClosed = false;
-
- int numSubPaths = 0;
- iter->rewind();
- GrPathCmd cmd;
- GrPoint pts[4];
- do {
- cmd = iter->next(pts);
- // If the convexity test is ever updated to handle multiple subpaths
- // the loop has to be adjusted to handle moving to a new subpath without
- // closing the previous one. Currently the implicit closing vectors for a
- // filled path would never be examined.
- switch (cmd) {
- case kMove_PathCmd:
- this->moveTo(pts[0].fX, pts[0].fY);
- subPathPts = 0;
- subPathClosed = false;
- break;
- case kLine_PathCmd:
- this->lineTo(pts[1].fX, pts[1].fY);
- break;
- case kQuadratic_PathCmd:
- this->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
- break;
- case kCubic_PathCmd:
- this->cubicTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
- pts[3].fX, pts[3].fY);
- break;
- case kClose_PathCmd:
- this->close();
- subPathClosed = true;
- break;
- case kEnd_PathCmd:
- break;
- }
- int n = NumPathCmdPoints(cmd);
- for (int i = 0; i < n; ++i) {
- fConservativeBounds.growToInclude(pts[i].fX, pts[i].fY);
- }
- if (0 == subPathPts && n > 0) {
- previousPt = pts[0];
- firstPt = previousPt;
- flipX = 0;
- flipY = 0;
- turnDir = 0;
- subPathPts = 1;
- ++numSubPaths;
- }
- // either we skip the first pt because it is redundant with
- // last point of the previous subpath cmd or we just ate it
- // in the above if.
- int consumed = 1;
- if (numSubPaths < 2 && kNone_ConvexHint == fConvexHint) {
- while (consumed < n) {
- GrAssert(pts[consumed-1] == previousPt);
- GrVec vec = pts[consumed] - previousPt;
-// vec.setBetween(previousPt, pts[consumed]);
- if (vec.fX || vec.fY) {
- if (subPathPts >= 2) {
- if (0 == turnDir) {
- firstVec = previousVec;
- init_from_two_vecs(firstVec, vec,
- &turnDir, &xDir, &yDir);
- // here we aren't checking whether the x/y dirs
- // change between the first and second edge. It
- // gets covered when the path is closed.
- } else {
- if (!check_two_vecs(previousVec, vec, turnDir,
- &xDir, &yDir,
- &flipX, &flipY)) {
- fConvexHint = kConcave_ConvexHint;
- break;
- }
- }
- }
- previousVec = vec;
- previousPt = pts[consumed];
- ++subPathPts;
- }
- ++consumed;
- }
- if (subPathPts > 2 && (kClose_PathCmd == cmd ||
- (!subPathClosed && kEnd_PathCmd == cmd ))) {
- // if an additional vector is needed to close the loop check
- // that it validates against the previous vector.
- GrVec vec = firstPt - previousPt;
-// vec.setBetween(previousPt, firstPt);
- if (vec.fX || vec.fY) {
- if (!check_two_vecs(previousVec, vec, turnDir,
- &xDir, &yDir, &flipX, &flipY)) {
- fConvexHint = kConcave_ConvexHint;
- break;
- }
- previousVec = vec;
- }
- // check that closing vector validates against the first vector.
- if (!check_two_vecs(previousVec, firstVec, turnDir,
- &xDir, &yDir, &flipX, &flipY)) {
- fConvexHint = kConcave_ConvexHint;
- break;
- }
- }
- }
- } while (cmd != kEnd_PathCmd);
- if (kNone_ConvexHint == fConvexHint && numSubPaths < 2) {
- fConvexHint = kConvex_ConvexHint;
- } else {
- bool recurse = false;
- if (recurse) {
- this->resetFromIter(iter);
- }
- }
-}
-
-void GrPath::ConvexUnitTest() {
- GrPath testPath;
- GrPath::Iter testIter;
-
- GrPath pt;
- pt.moveTo(0, 0);
- pt.close();
-
- testIter.reset(pt);
- testPath.resetFromIter(&testIter);
- GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
- GrPath line;
- line.moveTo(GrIntToScalar(12), GrIntToScalar(20));
- line.lineTo(GrIntToScalar(-12), GrIntToScalar(-20));
- line.close();
-
- testIter.reset(line);
- testPath.resetFromIter(&testIter);
- GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
- GrPath triLeft;
- triLeft.moveTo(0, 0);
- triLeft.lineTo(1, 0);
- triLeft.lineTo(1, 1);
- triLeft.close();
-
- testIter.reset(triLeft);
- testPath.resetFromIter(&testIter);
- GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
- GrPath triRight;
- triRight.moveTo(0, 0);
- triRight.lineTo(-1, 0);
- triRight.lineTo(1, 1);
- triRight.close();
-
- testIter.reset(triRight);
- testPath.resetFromIter(&testIter);
- GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
- GrPath square;
- square.moveTo(0, 0);
- square.lineTo(1, 0);
- square.lineTo(1, 1);
- square.lineTo(0, 1);
- square.close();
-
- testIter.reset(square);
- testPath.resetFromIter(&testIter);
- GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
- GrPath redundantSquare;
- square.moveTo(0, 0);
- square.lineTo(0, 0);
- square.lineTo(0, 0);
- square.lineTo(1, 0);
- square.lineTo(1, 0);
- square.lineTo(1, 0);
- square.lineTo(1, 1);
- square.lineTo(1, 1);
- square.lineTo(1, 1);
- square.lineTo(0, 1);
- square.lineTo(0, 1);
- square.lineTo(0, 1);
- square.close();
-
- testIter.reset(redundantSquare);
- testPath.resetFromIter(&testIter);
- GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
- GrPath bowTie;
- bowTie.moveTo(0, 0);
- bowTie.lineTo(0, 0);
- bowTie.lineTo(0, 0);
- bowTie.lineTo(1, 1);
- bowTie.lineTo(1, 1);
- bowTie.lineTo(1, 1);
- bowTie.lineTo(1, 0);
- bowTie.lineTo(1, 0);
- bowTie.lineTo(1, 0);
- bowTie.lineTo(0, 1);
- bowTie.lineTo(0, 1);
- bowTie.lineTo(0, 1);
- bowTie.close();
-
- testIter.reset(bowTie);
- testPath.resetFromIter(&testIter);
- GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
-
- GrPath spiral;
- spiral.moveTo(0, 0);
- spiral.lineTo(1, 0);
- spiral.lineTo(1, 1);
- spiral.lineTo(0, 1);
- spiral.lineTo(0,.5);
- spiral.lineTo(.5,.5);
- spiral.lineTo(.5,.75);
- spiral.close();
-
- testIter.reset(spiral);
- testPath.resetFromIter(&testIter);
- GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
-
- GrPath dent;
- dent.moveTo(0, 0);
- dent.lineTo(1, 1);
- dent.lineTo(0, 1);
- dent.lineTo(-.5,2);
- dent.lineTo(-2, 1);
- dent.close();
-
- testIter.reset(dent);
- testPath.resetFromIter(&testIter);
- GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
-}
-///////////////////////////////////////////////////////////////////////////////
-
-GrPath::Iter::Iter() : fPath(NULL) {
-}
-
-GrPath::Iter::Iter(const GrPath& path) : fPath(&path) {
- this->rewind();
-}
-
-#ifdef SK_DEBUG
-static bool containsInclusive(const GrRect& rect, const GrPoint& point) {
- return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
- point.fY >= rect.fTop && point.fY <= rect.fBottom;
-}
-#endif
-
-GrPathCmd GrPath::Iter::next(GrPoint points[]) {
- if (fCmdIndex == fPath->fCmds.count()) {
- GrAssert(fPtIndex == fPath->fPts.count());
- return kEnd_PathCmd;
- } else {
- GrAssert(fCmdIndex < fPath->fCmds.count());
- }
-
- GrPathCmd cmd = fPath->fCmds[fCmdIndex++];
- const GrPoint* srcPts = fPath->fPts.begin() + fPtIndex;
-
- switch (cmd) {
- case kMove_PathCmd:
- if (points) {
- points[0] = srcPts[0];
- }
- fLastPt = srcPts[0];
- GrAssert(fPtIndex <= fPath->fPts.count() + 1);
- GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
- fPtIndex += 1;
- break;
- case kLine_PathCmd:
- if (points) {
- points[0] = fLastPt;
- points[1] = srcPts[0];
- }
- fLastPt = srcPts[0];
- GrAssert(fPtIndex <= fPath->fPts.count() + 1);
- GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
- fPtIndex += 1;
- break;
- case kQuadratic_PathCmd:
- if (points) {
- points[0] = fLastPt;
- points[1] = srcPts[0];
- points[2] = srcPts[1];
- }
- fLastPt = srcPts[1];
- GrAssert(fPtIndex <= fPath->fPts.count() + 2);
- GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
- GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[1]));
- fPtIndex += 2;
- break;
- case kCubic_PathCmd:
- if (points) {
- points[0] = fLastPt;
- points[1] = srcPts[0];
- points[2] = srcPts[1];
- points[3] = srcPts[2];
- }
- fLastPt = srcPts[2];
- GrAssert(fPtIndex <= fPath->fPts.count() + 3);
- GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
- GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[1]));
- GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[2]));
- fPtIndex += 3;
- break;
- case kClose_PathCmd:
- break;
- default:
- GrAssert(!"unknown grpath cmd");
- break;
- }
- return cmd;
-}
-
-GrConvexHint GrPath::Iter::convexHint() const {
- return fPath->getConvexHint();
-}
-
-GrPathCmd GrPath::Iter::next() {
- return this->next(NULL);
-}
-
-void GrPath::Iter::rewind() {
- this->reset(*fPath);
-}
-
-void GrPath::Iter::reset(const GrPath& path) {
- fPath = &path;
- fCmdIndex = fPtIndex = 0;
-}
-
-bool GrPath::Iter::getConservativeBounds(GrRect* rect) const {
- if (!fPath->getConservativeBounds().isEmpty()) {
- *rect = fPath->getConservativeBounds();
- return true;
- }
- return false;
-}
-
diff --git a/gpu/src/GrPathRenderer.cpp b/gpu/src/GrPathRenderer.cpp
index 317b7d3571..5bea5e6b98 100644
--- a/gpu/src/GrPathRenderer.cpp
+++ b/gpu/src/GrPathRenderer.cpp
@@ -2,7 +2,6 @@
#include "GrPoint.h"
#include "GrDrawTarget.h"
-#include "GrPathIter.h"
#include "GrPathUtils.h"
#include "GrMemory.h"
#include "GrTexture.h"
@@ -147,20 +146,24 @@ static const GrStencilSettings gDirectToStencil = {
////////////////////////////////////////////////////////////////////////////////
// Helpers for drawPath
+static GrConvexHint getConvexHint(const SkPath& path) {
+ return path.isConvex() ? kConvex_ConvexHint : kConcave_ConvexHint;
+}
+
#define STENCIL_OFF 0 // Always disable stencil (even when needed)
static inline bool single_pass_path(const GrDrawTarget& target,
- const GrPathIter& path,
+ const GrPath& path,
GrPathFill fill) {
#if STENCIL_OFF
return true;
#else
if (kEvenOdd_PathFill == fill) {
- GrConvexHint hint = path.convexHint();
+ GrConvexHint hint = getConvexHint(path);
return hint == kConvex_ConvexHint ||
hint == kNonOverlappingConvexPieces_ConvexHint;
} else if (kWinding_PathFill == fill) {
- GrConvexHint hint = path.convexHint();
+ GrConvexHint hint = getConvexHint(path);
return hint == kConvex_ConvexHint ||
hint == kNonOverlappingConvexPieces_ConvexHint ||
(hint == kSameWindingConvexPieces_ConvexHint &&
@@ -172,14 +175,14 @@ static inline bool single_pass_path(const GrDrawTarget& target,
}
bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill) const {
- return !single_pass_path(*target, *path, fill);
+ return !single_pass_path(*target, path, fill);
}
void GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
GrDrawTarget::StageBitfield stages,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill,
const GrPoint* translate,
bool stencilOnly) {
@@ -205,8 +208,6 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
}
GrScalar tolSqd = GrMul(tol, tol);
- path->rewind();
-
int subpathCnt;
int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
@@ -226,8 +227,6 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
- path->rewind();
-
// TODO: use primitve restart if available rather than multiple draws
GrPrimitiveType type;
int passCount = 0;
@@ -248,7 +247,7 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
drawFace[0] = GrDrawTarget::kBoth_DrawFace;
} else {
type = kTriangleFan_PrimitiveType;
- if (single_pass_path(*target, *path, fill)) {
+ if (single_pass_path(*target, path, fill)) {
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
@@ -329,8 +328,10 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
bool first = true;
int subpath = 0;
+ SkPath::Iter iter(path, false);
+
for (;;) {
- GrPathCmd cmd = path->next(pts);
+ GrPathCmd cmd = (GrPathCmd)iter.next(pts);
switch (cmd) {
case kMove_PathCmd:
if (!first) {
@@ -431,14 +432,14 @@ FINISHED:
void GrDefaultPathRenderer::drawPath(GrDrawTarget* target,
GrDrawTarget::StageBitfield stages,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill,
const GrPoint* translate) {
this->onDrawPath(target, stages, path, fill, translate, false);
}
void GrDefaultPathRenderer::drawPathToStencil(GrDrawTarget* target,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill,
const GrPoint* translate) {
GrAssert(kInverseEvenOdd_PathFill != fill);
diff --git a/gpu/src/GrPathUtils.cpp b/gpu/src/GrPathUtils.cpp
index 115b0f6f2f..69dd0e6aef 100644
--- a/gpu/src/GrPathUtils.cpp
+++ b/gpu/src/GrPathUtils.cpp
@@ -15,8 +15,6 @@
*/
#include "GrPathUtils.h"
-
-#include "GrPathIter.h"
#include "GrPoint.h"
const GrScalar GrPathUtils::gTolerance = GR_Scalar1;
@@ -106,18 +104,18 @@ uint32_t GrPathUtils::generateCubicPoints(const GrPoint& p0,
return a + b;
}
-int GrPathUtils::worstCasePointCount(GrPathIter* path,
- int* subpaths,
- GrScalar tol) {
+int GrPathUtils::worstCasePointCount(const GrPath& path, int* subpaths,
+ GrScalar tol) {
int pointCount = 0;
*subpaths = 1;
bool first = true;
+ SkPath::Iter iter(path, false);
GrPathCmd cmd;
GrPoint pts[4];
- while ((cmd = path->next(pts)) != kEnd_PathCmd) {
+ while ((cmd = (GrPathCmd)iter.next(pts)) != kEnd_PathCmd) {
switch (cmd) {
case kLine_PathCmd:
diff --git a/gpu/src/GrPathUtils.h b/gpu/src/GrPathUtils.h
index af05682a4d..2cd00cbb84 100644
--- a/gpu/src/GrPathUtils.h
+++ b/gpu/src/GrPathUtils.h
@@ -19,15 +19,14 @@
#include "GrNoncopyable.h"
#include "GrPoint.h"
-
-class GrPathIter;
+#include "GrPath.h"
/**
* Utilities for evaluating paths.
*/
class GrPathUtils : public GrNoncopyable {
public:
- static int worstCasePointCount(GrPathIter* path,
+ static int worstCasePointCount(const GrPath&,
int* subpaths,
GrScalar tol);
static uint32_t quadraticPointCount(const GrPoint points[], GrScalar tol);
diff --git a/gpu/src/GrTesselatedPathRenderer.cpp b/gpu/src/GrTesselatedPathRenderer.cpp
index 19ee46d3f6..da6da5cad8 100644
--- a/gpu/src/GrTesselatedPathRenderer.cpp
+++ b/gpu/src/GrTesselatedPathRenderer.cpp
@@ -18,6 +18,8 @@
#include "GrMemory.h"
#include "GrPathUtils.h"
+#include "GrPoint.h"
+#include "GrTDArray.h"
#include <internal_glu.h>
@@ -137,7 +139,7 @@ static size_t computeEdgesAndOffsetVertices(const GrMatrix& matrix,
void GrTesselatedPathRenderer::drawPath(GrDrawTarget* target,
GrDrawTarget::StageBitfield stages,
- GrPathIter* path,
+ const GrPath& path,
GrPathFill fill,
const GrPoint* translate) {
GrDrawTarget::AutoStateRestore asr(target);
@@ -161,8 +163,6 @@ void GrTesselatedPathRenderer::drawPath(GrDrawTarget* target,
}
GrScalar tolSqd = GrMul(tol, tol);
- path->rewind();
-
int subpathCnt;
int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
@@ -184,16 +184,14 @@ void GrTesselatedPathRenderer::drawPath(GrDrawTarget* target,
GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
- path->rewind();
-
GrPoint pts[4];
+ SkPath::Iter iter(path, true);
bool first = true;
int subpath = 0;
for (;;) {
- GrPathCmd cmd = path->next(pts);
- switch (cmd) {
+ switch (iter.next(pts)) {
case kMove_PathCmd:
if (!first) {
subpathVertCount[subpath] = vert-subpathBase;
@@ -262,7 +260,7 @@ FINISHED:
return;
}
- if (subpathCnt == 1 && !inverted && path->convexHint() == kConvex_ConvexHint) {
+ if (subpathCnt == 1 && !inverted && path.isConvex()) {
if (target->isAntialiasState()) {
target->enableState(GrDrawTarget::kEdgeAA_StateBit);
EdgeArray edges;
@@ -347,25 +345,25 @@ FINISHED:
}
bool GrTesselatedPathRenderer::canDrawPath(const GrDrawTarget* target,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill) const {
return kHairLine_PathFill != fill;
}
void GrTesselatedPathRenderer::drawPathToStencil(GrDrawTarget* target,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill,
const GrPoint* translate) {
GrAlwaysAssert(!"multipass stencil should not be needed");
}
bool GrTesselatedPathRenderer::supportsAA(GrDrawTarget* target,
- GrPathIter* path,
+ const SkPath& path,
GrPathFill fill) {
int subpathCnt = 0;
int tol = GrPathUtils::gTolerance;
GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
return (subpathCnt == 1 &&
!IsFillInverted(fill) &&
- path->convexHint() == kConvex_ConvexHint);
+ path.isConvex());
}
diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp
index 0222042b37..9e8e40a9bd 100644
--- a/gpu/src/GrTextContext.cpp
+++ b/gpu/src/GrTextContext.cpp
@@ -201,11 +201,11 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
}
glyph->fPath = path;
}
- GrPath::Iter iter(*glyph->fPath);
+
GrPoint translate;
translate.set(GrFixedToScalar(vx - GrIntToFixed(glyph->fBounds.fLeft)),
GrFixedToScalar(vy - GrIntToFixed(glyph->fBounds.fTop)));
- fContext->drawPath(fPaint, &iter, kWinding_PathFill,
+ fContext->drawPath(fPaint, *glyph->fPath, kWinding_PathFill,
&translate);
return;
}
diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk
index fef97844c8..bd6f06148e 100644
--- a/gpu/src/gr_files.mk
+++ b/gpu/src/gr_files.mk
@@ -19,10 +19,10 @@ SOURCE := \
GrInOrderDrawBuffer.cpp \
GrMatrix.cpp \
GrMemory.cpp \
- GrPath.cpp \
GrPathUtils.cpp \
GrRectanizer_fifo.cpp \
GrResource.cpp \
+ GrTesselatedPathRenderer.cpp \
GrTexture.cpp \
GrTextureCache.cpp \
GrTextContext.cpp \
diff --git a/gpu/src/gr_unittests.cpp b/gpu/src/gr_unittests.cpp
index 320dd15bd7..7981bb15b4 100644
--- a/gpu/src/gr_unittests.cpp
+++ b/gpu/src/gr_unittests.cpp
@@ -148,12 +148,131 @@ static void test_binHashKey()
GrAssert(keyBust3.compare(keyBust2) == 0);
}
+static void test_convex() {
+#if 0
+ GrPath testPath;
+ GrPath::Iter testIter;
+
+ GrPath pt;
+ pt.moveTo(0, 0);
+ pt.close();
+
+ testIter.reset(pt);
+ testPath.resetFromIter(&testIter);
+ GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+
+ GrPath line;
+ line.moveTo(GrIntToScalar(12), GrIntToScalar(20));
+ line.lineTo(GrIntToScalar(-12), GrIntToScalar(-20));
+ line.close();
+
+ testIter.reset(line);
+ testPath.resetFromIter(&testIter);
+ GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+
+ GrPath triLeft;
+ triLeft.moveTo(0, 0);
+ triLeft.lineTo(1, 0);
+ triLeft.lineTo(1, 1);
+ triLeft.close();
+
+ testIter.reset(triLeft);
+ testPath.resetFromIter(&testIter);
+ GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+
+ GrPath triRight;
+ triRight.moveTo(0, 0);
+ triRight.lineTo(-1, 0);
+ triRight.lineTo(1, 1);
+ triRight.close();
+
+ testIter.reset(triRight);
+ testPath.resetFromIter(&testIter);
+ GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+
+ GrPath square;
+ square.moveTo(0, 0);
+ square.lineTo(1, 0);
+ square.lineTo(1, 1);
+ square.lineTo(0, 1);
+ square.close();
+
+ testIter.reset(square);
+ testPath.resetFromIter(&testIter);
+ GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+
+ GrPath redundantSquare;
+ square.moveTo(0, 0);
+ square.lineTo(0, 0);
+ square.lineTo(0, 0);
+ square.lineTo(1, 0);
+ square.lineTo(1, 0);
+ square.lineTo(1, 0);
+ square.lineTo(1, 1);
+ square.lineTo(1, 1);
+ square.lineTo(1, 1);
+ square.lineTo(0, 1);
+ square.lineTo(0, 1);
+ square.lineTo(0, 1);
+ square.close();
+
+ testIter.reset(redundantSquare);
+ testPath.resetFromIter(&testIter);
+ GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+
+ GrPath bowTie;
+ bowTie.moveTo(0, 0);
+ bowTie.lineTo(0, 0);
+ bowTie.lineTo(0, 0);
+ bowTie.lineTo(1, 1);
+ bowTie.lineTo(1, 1);
+ bowTie.lineTo(1, 1);
+ bowTie.lineTo(1, 0);
+ bowTie.lineTo(1, 0);
+ bowTie.lineTo(1, 0);
+ bowTie.lineTo(0, 1);
+ bowTie.lineTo(0, 1);
+ bowTie.lineTo(0, 1);
+ bowTie.close();
+
+ testIter.reset(bowTie);
+ testPath.resetFromIter(&testIter);
+ GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
+
+ GrPath spiral;
+ spiral.moveTo(0, 0);
+ spiral.lineTo(1, 0);
+ spiral.lineTo(1, 1);
+ spiral.lineTo(0, 1);
+ spiral.lineTo(0,.5);
+ spiral.lineTo(.5,.5);
+ spiral.lineTo(.5,.75);
+ spiral.close();
+
+ testIter.reset(spiral);
+ testPath.resetFromIter(&testIter);
+ GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
+
+ GrPath dent;
+ dent.moveTo(0, 0);
+ dent.lineTo(1, 1);
+ dent.lineTo(0, 1);
+ dent.lineTo(-.5,2);
+ dent.lineTo(-2, 1);
+ dent.close();
+
+ testIter.reset(dent);
+ testPath.resetFromIter(&testIter);
+ GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
+#endif
+}
+
void gr_run_unittests() {
test_tdarray();
test_bsearch();
test_binHashKey();
+ test_convex();
GrRedBlackTree<int>::UnitTest();
- GrPath::ConvexUnitTest();
GrDrawTarget::VertexLayoutUnitTest();
}