| Index: experimental/StrokePathRenderer/GrStrokePathRenderer.cpp
|
| diff --git a/experimental/StrokePathRenderer/GrStrokePathRenderer.cpp b/experimental/StrokePathRenderer/GrStrokePathRenderer.cpp
|
| deleted file mode 100644
|
| index e693c41a6690a73959d118db8c8c4d4827c6db35..0000000000000000000000000000000000000000
|
| --- a/experimental/StrokePathRenderer/GrStrokePathRenderer.cpp
|
| +++ /dev/null
|
| @@ -1,298 +0,0 @@
|
| -/*
|
| - * Copyright 2012 Google Inc.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -#include "GrStrokePathRenderer.h"
|
| -
|
| -#include "GrDrawTarget.h"
|
| -#include "SkPath.h"
|
| -#include "SkStrokeRec.h"
|
| -
|
| -static bool is_clockwise(const SkVector& before, const SkVector& after) {
|
| - return before.cross(after) > 0;
|
| -}
|
| -
|
| -enum IntersectionType {
|
| - kNone_IntersectionType,
|
| - kIn_IntersectionType,
|
| - kOut_IntersectionType
|
| -};
|
| -
|
| -static IntersectionType intersection(const SkPoint& p1, const SkPoint& p2,
|
| - const SkPoint& p3, const SkPoint& p4,
|
| - SkPoint& res) {
|
| - // Store the values for fast access and easy
|
| - // equations-to-code conversion
|
| - SkScalar x1 = p1.x(), x2 = p2.x(), x3 = p3.x(), x4 = p4.x();
|
| - SkScalar y1 = p1.y(), y2 = p2.y(), y3 = p3.y(), y4 = p4.y();
|
| -
|
| - SkScalar d = SkScalarMul(x1 - x2, y3 - y4) - SkScalarMul(y1 - y2, x3 - x4);
|
| - // If d is zero, there is no intersection
|
| - if (SkScalarNearlyZero(d)) {
|
| - return kNone_IntersectionType;
|
| - }
|
| -
|
| - // Get the x and y
|
| - SkScalar pre = SkScalarMul(x1, y2) - SkScalarMul(y1, x2),
|
| - post = SkScalarMul(x3, y4) - SkScalarMul(y3, x4);
|
| - // Compute the point of intersection
|
| - res.set((SkScalarMul(pre, x3 - x4) - SkScalarMul(x1 - x2, post) / d,
|
| - (SkScalarMul(pre, y3 - y4) - SkScalarMul(y1 - y2, post) / d);
|
| -
|
| - // Check if the x and y coordinates are within both lines
|
| - return (res.x() < GrMin(x1, x2) || res.x() > GrMax(x1, x2) ||
|
| - res.x() < GrMin(x3, x4) || res.x() > GrMax(x3, x4) ||
|
| - res.y() < GrMin(y1, y2) || res.y() > GrMax(y1, y2) ||
|
| - res.y() < GrMin(y3, y4) || res.y() > GrMax(y3, y4)) ?
|
| - kOut_IntersectionType : kIn_IntersectionType;
|
| -}
|
| -
|
| -GrStrokePathRenderer::GrStrokePathRenderer() {
|
| -}
|
| -
|
| -bool GrStrokePathRenderer::canDrawPath(const SkPath& path,
|
| - const SkStrokeRec& stroke,
|
| - const GrDrawTarget* target,
|
| - bool antiAlias) const {
|
| - // FIXME : put the proper condition once GrDrawTarget::isOpaque is implemented
|
| - const bool isOpaque = true; // target->isOpaque();
|
| -
|
| - // FIXME : remove this requirement once we have AA circles and implement the
|
| - // circle joins/caps appropriately in the ::onDrawPath() function.
|
| - const bool requiresAACircle = (stroke.getCap() == SkPaint::kRound_Cap) ||
|
| - (stroke.getJoin() == SkPaint::kRound_Join);
|
| -
|
| - // Indices being stored in uint16, we don't want to overflow the indices capacity
|
| - static const int maxVBSize = 1 << 16;
|
| - const int maxNbVerts = (path.countPoints() + 1) * 5;
|
| -
|
| - // Check that the path contains no curved lines, only straight lines
|
| - static const uint32_t unsupportedMask = SkPath::kQuad_SegmentMask | SkPath::kCubic_SegmentMask;
|
| -
|
| - // Must not be filled nor hairline nor semi-transparent
|
| - // Note : May require a check to path.isConvex() if AA is supported
|
| - return ((stroke.getStyle() == SkStrokeRec::kStroke_Style) && (maxNbVerts < maxVBSize) &&
|
| - !path.isInverseFillType() && isOpaque && !requiresAACircle && !antiAlias &&
|
| - ((path.getSegmentMasks() & unsupportedMask) == 0));
|
| -}
|
| -
|
| -bool GrStrokePathRenderer::onDrawPath(const SkPath& origPath,
|
| - const SkStrokeRec& stroke,
|
| - GrDrawTarget* target,
|
| - bool antiAlias) {
|
| - if (origPath.isEmpty()) {
|
| - return true;
|
| - }
|
| -
|
| - SkScalar width = stroke.getWidth();
|
| - if (width <= 0) {
|
| - return false;
|
| - }
|
| -
|
| - // Get the join type
|
| - SkPaint::Join join = stroke.getJoin();
|
| - SkScalar miterLimit = stroke.getMiter();
|
| - SkScalar sqMiterLimit = SkScalarMul(miterLimit, miterLimit);
|
| - if ((join == SkPaint::kMiter_Join) && (miterLimit <= SK_Scalar1)) {
|
| - // If the miter limit is small, treat it as a bevel join
|
| - join = SkPaint::kBevel_Join;
|
| - }
|
| - const bool isMiter = (join == SkPaint::kMiter_Join);
|
| - const bool isBevel = (join == SkPaint::kBevel_Join);
|
| - SkScalar invMiterLimit = isMiter ? SK_Scalar1 / miterLimit : 0;
|
| - SkScalar invMiterLimitSq = SkScalarMul(invMiterLimit, invMiterLimit);
|
| -
|
| - // Allocate vertices
|
| - const int nbQuads = origPath.countPoints() + 1; // Could be "-1" if path is not closed
|
| - const int extraVerts = isMiter || isBevel ? 1 : 0;
|
| - const int maxVertexCount = nbQuads * (4 + extraVerts);
|
| - const int maxIndexCount = nbQuads * (6 + extraVerts * 3); // Each extra vert adds a triangle
|
| - target->drawState()->setDefaultVertexAttribs();
|
| - GrDrawTarget::AutoReleaseGeometry arg(target, maxVertexCount, maxIndexCount);
|
| - if (!arg.succeeded()) {
|
| - return false;
|
| - }
|
| - SkPoint* verts = reinterpret_cast<SkPoint*>(arg.vertices());
|
| - uint16_t* idxs = reinterpret_cast<uint16_t*>(arg.indices());
|
| - int vCount = 0, iCount = 0;
|
| -
|
| - // Transform the path into a list of triangles
|
| - SkPath::Iter iter(origPath, false);
|
| - SkPoint pts[4];
|
| - const SkScalar radius = SkScalarMul(width, 0.5f);
|
| - SkPoint *firstPt = verts, *lastPt = NULL;
|
| - SkVector firstDir, dir;
|
| - firstDir.set(0, 0);
|
| - dir.set(0, 0);
|
| - bool isOpen = true;
|
| - for(SkPath::Verb v = iter.next(pts); v != SkPath::kDone_Verb; v = iter.next(pts)) {
|
| - switch(v) {
|
| - case SkPath::kMove_Verb:
|
| - // This will already be handled as pts[0] of the 1st line
|
| - break;
|
| - case SkPath::kClose_Verb:
|
| - isOpen = (lastPt == NULL);
|
| - break;
|
| - case SkPath::kLine_Verb:
|
| - {
|
| - SkVector v0 = dir;
|
| - dir = pts[1] - pts[0];
|
| - if (dir.setLength(radius)) {
|
| - SkVector dirT;
|
| - dirT.set(dir.fY, -dir.fX); // Get perpendicular direction
|
| - SkPoint l1a = pts[0]+dirT, l1b = pts[1]+dirT,
|
| - l2a = pts[0]-dirT, l2b = pts[1]-dirT;
|
| - SkPoint miterPt[2];
|
| - bool useMiterPoint = false;
|
| - int idx0(-1), idx1(-1);
|
| - if (NULL == lastPt) {
|
| - firstDir = dir;
|
| - } else {
|
| - SkVector v1 = dir;
|
| - if (v0.normalize() && v1.normalize()) {
|
| - SkScalar dotProd = v0.dot(v1);
|
| - // No need for bevel or miter join if the angle
|
| - // is either 0 or 180 degrees
|
| - if (!SkScalarNearlyZero(dotProd + SK_Scalar1) &&
|
| - !SkScalarNearlyZero(dotProd - SK_Scalar1)) {
|
| - bool ccw = !is_clockwise(v0, v1);
|
| - int offset = ccw ? 1 : 0;
|
| - idx0 = vCount-2+offset;
|
| - idx1 = vCount+offset;
|
| - const SkPoint* pt0 = &(lastPt[offset]);
|
| - const SkPoint* pt1 = ccw ? &l2a : &l1a;
|
| - switch(join) {
|
| - case SkPaint::kMiter_Join:
|
| - {
|
| - // *Note : Logic is from MiterJoiner
|
| -
|
| - // FIXME : Special case if we have a right angle ?
|
| - // if (SkScalarNearlyZero(dotProd)) {...}
|
| -
|
| - SkScalar sinHalfAngleSq =
|
| - SkScalarHalf(SK_Scalar1 + dotProd);
|
| - if (sinHalfAngleSq >= invMiterLimitSq) {
|
| - // Find the miter point (or points if it is further
|
| - // than the miter limit)
|
| - const SkPoint pt2 = *pt0+v0, pt3 = *pt1+v1;
|
| - if (intersection(*pt0, pt2, *pt1, pt3, miterPt[0]) !=
|
| - kNone_IntersectionType) {
|
| - SkPoint miterPt0 = miterPt[0] - *pt0;
|
| - SkPoint miterPt1 = miterPt[0] - *pt1;
|
| - SkScalar sqDist0 = miterPt0.dot(miterPt0);
|
| - SkScalar sqDist1 = miterPt1.dot(miterPt1);
|
| - const SkScalar rSq = radius*radius / sinHalfAngleSq;
|
| - const SkScalar sqRLimit =
|
| - SkScalarMul(sqMiterLimit, rSq);
|
| - if (sqDist0 > sqRLimit || sqDist1 > sqRLimit) {
|
| - if (sqDist1 > sqRLimit) {
|
| - v1.setLength(SkScalarSqrt(sqRLimit));
|
| - miterPt[1] = *pt1+v1;
|
| - } else {
|
| - miterPt[1] = miterPt[0];
|
| - }
|
| - if (sqDist0 > sqRLimit) {
|
| - v0.setLength(SkScalarSqrt(sqRLimit));
|
| - miterPt[0] = *pt0+v0;
|
| - }
|
| - } else {
|
| - miterPt[1] = miterPt[0];
|
| - }
|
| - useMiterPoint = true;
|
| - }
|
| - }
|
| - if (useMiterPoint && (miterPt[1] == miterPt[0])) {
|
| - break;
|
| - }
|
| - }
|
| - default:
|
| - case SkPaint::kBevel_Join:
|
| - {
|
| - // Note : This currently causes some overdraw where both
|
| - // lines initially intersect. We'd need to add
|
| - // another line intersection check here if the
|
| - // overdraw becomes an issue instead of using the
|
| - // current point directly.
|
| -
|
| - // Add center point
|
| - *verts++ = pts[0]; // Use current point directly
|
| - // This idx is passed the current point so increment it
|
| - ++idx1;
|
| - // Add center triangle
|
| - *idxs++ = idx0;
|
| - *idxs++ = vCount;
|
| - *idxs++ = idx1;
|
| - vCount++;
|
| - iCount += 3;
|
| - }
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - *verts++ = l1a;
|
| - *verts++ = l2a;
|
| - lastPt = verts;
|
| - *verts++ = l1b;
|
| - *verts++ = l2b;
|
| -
|
| - if (useMiterPoint && (idx0 >= 0) && (idx1 >= 0)) {
|
| - firstPt[idx0] = miterPt[0];
|
| - firstPt[idx1] = miterPt[1];
|
| - }
|
| -
|
| - // 1st triangle
|
| - *idxs++ = vCount+0;
|
| - *idxs++ = vCount+2;
|
| - *idxs++ = vCount+1;
|
| - // 2nd triangle
|
| - *idxs++ = vCount+1;
|
| - *idxs++ = vCount+2;
|
| - *idxs++ = vCount+3;
|
| -
|
| - vCount += 4;
|
| - iCount += 6;
|
| - }
|
| - }
|
| - break;
|
| - case SkPath::kQuad_Verb:
|
| - case SkPath::kCubic_Verb:
|
| - SkDEBUGFAIL("Curves not supported!");
|
| - default:
|
| - // Unhandled cases
|
| - SkASSERT(false);
|
| - }
|
| - }
|
| -
|
| - if (isOpen) {
|
| - // Add caps
|
| - switch (stroke.getCap()) {
|
| - case SkPaint::kSquare_Cap:
|
| - firstPt[0] -= firstDir;
|
| - firstPt[1] -= firstDir;
|
| - lastPt [0] += dir;
|
| - lastPt [1] += dir;
|
| - break;
|
| - case SkPaint::kRound_Cap:
|
| - SkDEBUGFAIL("Round caps not supported!");
|
| - default: // No cap
|
| - break;
|
| - }
|
| - }
|
| -
|
| - SkASSERT(vCount <= maxVertexCount);
|
| - SkASSERT(iCount <= maxIndexCount);
|
| -
|
| - if (vCount > 0) {
|
| - target->drawIndexed(kTriangles_GrPrimitiveType,
|
| - 0, // start vertex
|
| - 0, // start index
|
| - vCount,
|
| - iCount);
|
| - }
|
| -
|
| - return true;
|
| -}
|
|
|