From 611cc5f96457446b0b5476653856fc8072e96598 Mon Sep 17 00:00:00 2001 From: joshualitt Date: Fri, 29 May 2015 07:09:09 -0700 Subject: delete experimental path renderers BUG=skia: Review URL: https://codereview.chromium.org/1160863006 --- .../AndroidPathRenderer/AndroidPathRenderer.cpp | 729 --------------------- .../AndroidPathRenderer/AndroidPathRenderer.h | 94 --- .../AndroidPathRenderer/GrAndroidPathRenderer.cpp | 89 --- .../AndroidPathRenderer/GrAndroidPathRenderer.h | 29 - experimental/AndroidPathRenderer/Vertex.h | 84 --- experimental/AndroidPathRenderer/cutils/compiler.h | 35 - .../StrokePathRenderer/GrStrokePathRenderer.cpp | 298 --------- .../StrokePathRenderer/GrStrokePathRenderer.h | 30 - 8 files changed, 1388 deletions(-) delete mode 100644 experimental/AndroidPathRenderer/AndroidPathRenderer.cpp delete mode 100644 experimental/AndroidPathRenderer/AndroidPathRenderer.h delete mode 100644 experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp delete mode 100644 experimental/AndroidPathRenderer/GrAndroidPathRenderer.h delete mode 100644 experimental/AndroidPathRenderer/Vertex.h delete mode 100644 experimental/AndroidPathRenderer/cutils/compiler.h delete mode 100644 experimental/StrokePathRenderer/GrStrokePathRenderer.cpp delete mode 100644 experimental/StrokePathRenderer/GrStrokePathRenderer.h (limited to 'experimental') diff --git a/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp b/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp deleted file mode 100644 index ca9873cddb..0000000000 --- a/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp +++ /dev/null @@ -1,729 +0,0 @@ -/* - * Copyright 2012 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define LOG_TAG "PathRenderer" -#define LOG_NDEBUG 1 -#define ATRACE_TAG ATRACE_TAG_GRAPHICS - -#define VERTEX_DEBUG 0 - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#ifdef VERBOSE -#define ALOGV SkDebugf -#else -#define ALOGV(x, ...) -#endif - -#include "AndroidPathRenderer.h" -#include "Vertex.h" - -namespace android { -namespace uirenderer { - -#define THRESHOLD 0.5f - -SkRect PathRenderer::ComputePathBounds(const SkPath& path, const SkPaint* paint) { - SkRect bounds = path.getBounds(); - if (paint->getStyle() != SkPaint::kFill_Style) { - float outset = paint->getStrokeWidth() * 0.5f; - bounds.outset(outset, outset); - } - return bounds; -} - -inline void computeInverseScales(const SkMatrix* transform, float &inverseScaleX, float& inverseScaleY) { - if (transform && transform->getType() & (SkMatrix::kScale_Mask|SkMatrix::kAffine_Mask|SkMatrix::kPerspective_Mask)) { - float m00 = transform->getScaleX(); - float m01 = transform->getSkewY(); - float m10 = transform->getSkewX(); - float m11 = transform->getScaleY(); - float scaleX = sk_float_sqrt(m00 * m00 + m01 * m01); - float scaleY = sk_float_sqrt(m10 * m10 + m11 * m11); - inverseScaleX = (scaleX != 0) ? (1.0f / scaleX) : 1.0f; - inverseScaleY = (scaleY != 0) ? (1.0f / scaleY) : 1.0f; - } else { - inverseScaleX = 1.0f; - inverseScaleY = 1.0f; - } -} - -inline void copyVertex(Vertex* destPtr, const Vertex* srcPtr) { - Vertex::set(destPtr, srcPtr->position[0], srcPtr->position[1]); -} - -inline void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) { - AlphaVertex::set(destPtr, srcPtr->position[0], srcPtr->position[1], srcPtr->alpha); -} - -/** - * Produces a pseudo-normal for a vertex, given the normals of the two incoming lines. If the offset - * from each vertex in a perimeter is calculated, the resultant lines connecting the offset vertices - * will be offset by 1.0 - * - * Note that we can't add and normalize the two vectors, that would result in a rectangle having an - * offset of (sqrt(2)/2, sqrt(2)/2) at each corner, instead of (1, 1) - * - * NOTE: assumes angles between normals 90 degrees or less - */ -inline SkVector totalOffsetFromNormals(const SkVector& normalA, const SkVector& normalB) { - SkVector pseudoNormal = normalA + normalB; - pseudoNormal.scale(1.0f / (1.0f + sk_float_abs(normalA.dot(normalB)))); - return pseudoNormal; -} - -inline void scaleOffsetForStrokeWidth(SkVector& offset, float halfStrokeWidth, - float inverseScaleX, float inverseScaleY) { - if (halfStrokeWidth == 0.0f) { - // hairline - compensate for scale - offset.fX *= 0.5f * inverseScaleX; - offset.fY *= 0.5f * inverseScaleY; - } else { - offset.scale(halfStrokeWidth); - } -} - -static void getFillVerticesFromPerimeter(const SkTArray& perimeter, VertexBuffer* vertexBuffer) { - Vertex* buffer = vertexBuffer->alloc(perimeter.count()); - - int currentIndex = 0; - // zig zag between all previous points on the inside of the hull to create a - // triangle strip that fills the hull - int srcAindex = 0; - int srcBindex = perimeter.count() - 1; - while (srcAindex <= srcBindex) { - copyVertex(&buffer[currentIndex++], &perimeter[srcAindex]); - if (srcAindex == srcBindex) break; - copyVertex(&buffer[currentIndex++], &perimeter[srcBindex]); - srcAindex++; - srcBindex--; - } -} - -static void getStrokeVerticesFromPerimeter(const SkTArray& perimeter, float halfStrokeWidth, - VertexBuffer* vertexBuffer, float inverseScaleX, float inverseScaleY) { - Vertex* buffer = vertexBuffer->alloc(perimeter.count() * 2 + 2); - - int currentIndex = 0; - const Vertex* last = &(perimeter[perimeter.count() - 1]); - const Vertex* current = &(perimeter[0]); - SkVector lastNormal; - lastNormal.set(current->position[1] - last->position[1], - last->position[0] - current->position[0]); - lastNormal.normalize(); - for (int i = 0; i < perimeter.count(); i++) { - const Vertex* next = &(perimeter[i + 1 >= perimeter.count() ? 0 : i + 1]); - SkVector nextNormal; - nextNormal.set(next->position[1] - current->position[1], - current->position[0] - next->position[0]); - nextNormal.normalize(); - - SkVector totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - - Vertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.fX, - current->position[1] + totalOffset.fY); - - Vertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.fX, - current->position[1] - totalOffset.fY); - - last = current; - current = next; - lastNormal = nextNormal; - } - - // wrap around to beginning - copyVertex(&buffer[currentIndex++], &buffer[0]); - copyVertex(&buffer[currentIndex++], &buffer[1]); -} - -static void getStrokeVerticesFromUnclosedVertices(const SkTArray& vertices, float halfStrokeWidth, - VertexBuffer* vertexBuffer, float inverseScaleX, float inverseScaleY) { - Vertex* buffer = vertexBuffer->alloc(vertices.count() * 2); - - int currentIndex = 0; - const Vertex* current = &(vertices[0]); - SkVector lastNormal; - for (int i = 0; i < vertices.count() - 1; i++) { - const Vertex* next = &(vertices[i + 1]); - SkVector nextNormal; - nextNormal.set(next->position[1] - current->position[1], - current->position[0] - next->position[0]); - nextNormal.normalize(); - - SkVector totalOffset; - if (i == 0) { - totalOffset = nextNormal; - } else { - totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - } - scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - - Vertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.fX, - current->position[1] + totalOffset.fY); - - Vertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.fX, - current->position[1] - totalOffset.fY); - - current = next; - lastNormal = nextNormal; - } - - SkVector totalOffset = lastNormal; - scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - - Vertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.fX, - current->position[1] + totalOffset.fY); - Vertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.fX, - current->position[1] - totalOffset.fY); -#if VERTEX_DEBUG - for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { - SkDebugf("point at %f %f", buffer[i].position[0], buffer[i].position[1]); - } -#endif -} - -static void getFillVerticesFromPerimeterAA(const SkTArray& perimeter, VertexBuffer* vertexBuffer, - float inverseScaleX, float inverseScaleY) { - AlphaVertex* buffer = vertexBuffer->alloc(perimeter.count() * 3 + 2); - - // generate alpha points - fill Alpha vertex gaps in between each point with - // alpha 0 vertex, offset by a scaled normal. - int currentIndex = 0; - const Vertex* last = &(perimeter[perimeter.count() - 1]); - const Vertex* current = &(perimeter[0]); - SkVector lastNormal; - lastNormal.set(current->position[1] - last->position[1], - last->position[0] - current->position[0]); - lastNormal.normalize(); - for (int i = 0; i < perimeter.count(); i++) { - const Vertex* next = &(perimeter[i + 1 >= perimeter.count() ? 0 : i + 1]); - SkVector nextNormal; - nextNormal.set(next->position[1] - current->position[1], - current->position[0] - next->position[0]); - nextNormal.normalize(); - - // AA point offset from original point is that point's normal, such that each side is offset - // by .5 pixels - SkVector totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - totalOffset.fX *= 0.5f * inverseScaleX; - totalOffset.fY *= 0.5f * inverseScaleY; - - AlphaVertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.fX, - current->position[1] + totalOffset.fY, - 0.0f); - AlphaVertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.fX, - current->position[1] - totalOffset.fY, - 1.0f); - - last = current; - current = next; - lastNormal = nextNormal; - } - - // wrap around to beginning - copyAlphaVertex(&buffer[currentIndex++], &buffer[0]); - copyAlphaVertex(&buffer[currentIndex++], &buffer[1]); - - // zig zag between all previous points on the inside of the hull to create a - // triangle strip that fills the hull, repeating the first inner point to - // create degenerate tris to start inside path - int srcAindex = 0; - int srcBindex = perimeter.count() - 1; - while (srcAindex <= srcBindex) { - copyAlphaVertex(&buffer[currentIndex++], &buffer[srcAindex * 2 + 1]); - if (srcAindex == srcBindex) break; - copyAlphaVertex(&buffer[currentIndex++], &buffer[srcBindex * 2 + 1]); - srcAindex++; - srcBindex--; - } - -#if VERTEX_DEBUG - for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { - SkDebugf("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); - } -#endif -} - - -static void getStrokeVerticesFromUnclosedVerticesAA(const SkTArray& vertices, float halfStrokeWidth, - VertexBuffer* vertexBuffer, float inverseScaleX, float inverseScaleY) { - AlphaVertex* buffer = vertexBuffer->alloc(6 * vertices.count() + 2); - - // avoid lines smaller than hairline since they break triangle based sampling. instead reducing - // alpha value (TODO: support different X/Y scale) - float maxAlpha = 1.0f; - if (halfStrokeWidth != 0 && inverseScaleX == inverseScaleY && - halfStrokeWidth * inverseScaleX < 0.5f) { - maxAlpha *= (2 * halfStrokeWidth) / inverseScaleX; - halfStrokeWidth = 0.0f; - } - - // there is no outer/inner here, using them for consistency with below approach - int offset = 2 * (vertices.count() - 2); - int currentAAOuterIndex = 2; - int currentAAInnerIndex = 2 * offset + 5; // reversed - int currentStrokeIndex = currentAAInnerIndex + 7; - - const Vertex* last = &(vertices[0]); - const Vertex* current = &(vertices[1]); - SkVector lastNormal; - lastNormal.set(current->position[1] - last->position[1], - last->position[0] - current->position[0]); - lastNormal.normalize(); - - { - // start cap - SkVector totalOffset = lastNormal; - SkVector AAOffset = totalOffset; - AAOffset.fX *= 0.5f * inverseScaleX; - AAOffset.fY *= 0.5f * inverseScaleY; - - SkVector innerOffset = totalOffset; - scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - SkVector outerOffset = innerOffset + AAOffset; - innerOffset -= AAOffset; - - // TODO: support square cap by changing this offset to incorporate halfStrokeWidth - SkVector capAAOffset; - capAAOffset.set(AAOffset.fY, -AAOffset.fX); - AlphaVertex::set(&buffer[0], - last->position[0] + outerOffset.fX + capAAOffset.fX, - last->position[1] + outerOffset.fY + capAAOffset.fY, - 0.0f); - AlphaVertex::set(&buffer[1], - last->position[0] + innerOffset.fX - capAAOffset.fX, - last->position[1] + innerOffset.fY - capAAOffset.fY, - maxAlpha); - - AlphaVertex::set(&buffer[2 * offset + 6], - last->position[0] - outerOffset.fX + capAAOffset.fX, - last->position[1] - outerOffset.fY + capAAOffset.fY, - 0.0f); - AlphaVertex::set(&buffer[2 * offset + 7], - last->position[0] - innerOffset.fX - capAAOffset.fX, - last->position[1] - innerOffset.fY - capAAOffset.fY, - maxAlpha); - copyAlphaVertex(&buffer[2 * offset + 8], &buffer[0]); - copyAlphaVertex(&buffer[2 * offset + 9], &buffer[1]); - copyAlphaVertex(&buffer[2 * offset + 10], &buffer[1]); // degenerate tris (the only two!) - copyAlphaVertex(&buffer[2 * offset + 11], &buffer[2 * offset + 7]); - } - - for (int i = 1; i < vertices.count() - 1; i++) { - const Vertex* next = &(vertices[i + 1]); - SkVector nextNormal; - nextNormal.set(next->position[1] - current->position[1], - current->position[0] - next->position[0]); - nextNormal.normalize(); - - SkVector totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - SkVector AAOffset = totalOffset; - AAOffset.fX *= 0.5f * inverseScaleX; - AAOffset.fY *= 0.5f * inverseScaleY; - - SkVector innerOffset = totalOffset; - scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - SkVector outerOffset = innerOffset + AAOffset; - innerOffset -= AAOffset; - - AlphaVertex::set(&buffer[currentAAOuterIndex++], - current->position[0] + outerOffset.fX, - current->position[1] + outerOffset.fY, - 0.0f); - AlphaVertex::set(&buffer[currentAAOuterIndex++], - current->position[0] + innerOffset.fX, - current->position[1] + innerOffset.fY, - maxAlpha); - - AlphaVertex::set(&buffer[currentStrokeIndex++], - current->position[0] + innerOffset.fX, - current->position[1] + innerOffset.fY, - maxAlpha); - AlphaVertex::set(&buffer[currentStrokeIndex++], - current->position[0] - innerOffset.fX, - current->position[1] - innerOffset.fY, - maxAlpha); - - AlphaVertex::set(&buffer[currentAAInnerIndex--], - current->position[0] - innerOffset.fX, - current->position[1] - innerOffset.fY, - maxAlpha); - AlphaVertex::set(&buffer[currentAAInnerIndex--], - current->position[0] - outerOffset.fX, - current->position[1] - outerOffset.fY, - 0.0f); - - last = current; - current = next; - lastNormal = nextNormal; - } - - { - // end cap - SkVector totalOffset = lastNormal; - SkVector AAOffset = totalOffset; - AAOffset.fX *= 0.5f * inverseScaleX; - AAOffset.fY *= 0.5f * inverseScaleY; - - SkVector innerOffset = totalOffset; - scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - SkVector outerOffset = innerOffset + AAOffset; - innerOffset -= AAOffset; - - // TODO: support square cap by changing this offset to incorporate halfStrokeWidth - SkVector capAAOffset; - capAAOffset.set(-AAOffset.fY, AAOffset.fX); - - AlphaVertex::set(&buffer[offset + 2], - current->position[0] + outerOffset.fX + capAAOffset.fX, - current->position[1] + outerOffset.fY + capAAOffset.fY, - 0.0f); - AlphaVertex::set(&buffer[offset + 3], - current->position[0] + innerOffset.fX - capAAOffset.fX, - current->position[1] + innerOffset.fY - capAAOffset.fY, - maxAlpha); - - AlphaVertex::set(&buffer[offset + 4], - current->position[0] - outerOffset.fX + capAAOffset.fX, - current->position[1] - outerOffset.fY + capAAOffset.fY, - 0.0f); - AlphaVertex::set(&buffer[offset + 5], - current->position[0] - innerOffset.fX - capAAOffset.fX, - current->position[1] - innerOffset.fY - capAAOffset.fY, - maxAlpha); - - copyAlphaVertex(&buffer[vertexBuffer->getSize() - 2], &buffer[offset + 3]); - copyAlphaVertex(&buffer[vertexBuffer->getSize() - 1], &buffer[offset + 5]); - } - -#if VERTEX_DEBUG - for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { - SkDebugf("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); - } -#endif -} - - -static void getStrokeVerticesFromPerimeterAA(const SkTArray& perimeter, float halfStrokeWidth, - VertexBuffer* vertexBuffer, float inverseScaleX, float inverseScaleY) { - AlphaVertex* buffer = vertexBuffer->alloc(6 * perimeter.count() + 8); - - // avoid lines smaller than hairline since they break triangle based sampling. instead reducing - // alpha value (TODO: support different X/Y scale) - float maxAlpha = 1.0f; - if (halfStrokeWidth != 0 && inverseScaleX == inverseScaleY && - halfStrokeWidth * inverseScaleX < 0.5f) { - maxAlpha *= (2 * halfStrokeWidth) / inverseScaleX; - halfStrokeWidth = 0.0f; - } - - int offset = 2 * perimeter.count() + 3; - int currentAAOuterIndex = 0; - int currentStrokeIndex = offset; - int currentAAInnerIndex = offset * 2; - - const Vertex* last = &(perimeter[perimeter.count() - 1]); - const Vertex* current = &(perimeter[0]); - SkVector lastNormal; - lastNormal.set(current->position[1] - last->position[1], - last->position[0] - current->position[0]); - lastNormal.normalize(); - for (int i = 0; i < perimeter.count(); i++) { - const Vertex* next = &(perimeter[i + 1 >= perimeter.count() ? 0 : i + 1]); - SkVector nextNormal; - nextNormal.set(next->position[1] - current->position[1], - current->position[0] - next->position[0]); - nextNormal.normalize(); - - SkVector totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - SkVector AAOffset = totalOffset; - AAOffset.fX *= 0.5f * inverseScaleX; - AAOffset.fY *= 0.5f * inverseScaleY; - - SkVector innerOffset = totalOffset; - scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - SkVector outerOffset = innerOffset + AAOffset; - innerOffset -= AAOffset; - - AlphaVertex::set(&buffer[currentAAOuterIndex++], - current->position[0] + outerOffset.fX, - current->position[1] + outerOffset.fY, - 0.0f); - AlphaVertex::set(&buffer[currentAAOuterIndex++], - current->position[0] + innerOffset.fX, - current->position[1] + innerOffset.fY, - maxAlpha); - - AlphaVertex::set(&buffer[currentStrokeIndex++], - current->position[0] + innerOffset.fX, - current->position[1] + innerOffset.fY, - maxAlpha); - AlphaVertex::set(&buffer[currentStrokeIndex++], - current->position[0] - innerOffset.fX, - current->position[1] - innerOffset.fY, - maxAlpha); - - AlphaVertex::set(&buffer[currentAAInnerIndex++], - current->position[0] - innerOffset.fX, - current->position[1] - innerOffset.fY, - maxAlpha); - AlphaVertex::set(&buffer[currentAAInnerIndex++], - current->position[0] - outerOffset.fX, - current->position[1] - outerOffset.fY, - 0.0f); - - last = current; - current = next; - lastNormal = nextNormal; - } - - // wrap each strip around to beginning, creating degenerate tris to bridge strips - copyAlphaVertex(&buffer[currentAAOuterIndex++], &buffer[0]); - copyAlphaVertex(&buffer[currentAAOuterIndex++], &buffer[1]); - copyAlphaVertex(&buffer[currentAAOuterIndex++], &buffer[1]); - - copyAlphaVertex(&buffer[currentStrokeIndex++], &buffer[offset]); - copyAlphaVertex(&buffer[currentStrokeIndex++], &buffer[offset + 1]); - copyAlphaVertex(&buffer[currentStrokeIndex++], &buffer[offset + 1]); - - copyAlphaVertex(&buffer[currentAAInnerIndex++], &buffer[2 * offset]); - copyAlphaVertex(&buffer[currentAAInnerIndex++], &buffer[2 * offset + 1]); - // don't need to create last degenerate tri - -#if VERTEX_DEBUG - for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { - SkDebugf("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); - } -#endif -} - -void PathRenderer::ConvexPathVertices(const SkPath &path, const SkStrokeRec& stroke, bool isAA, - const SkMatrix* transform, VertexBuffer* vertexBuffer) { - - SkStrokeRec::Style style = stroke.getStyle(); - - float inverseScaleX, inverseScaleY; - computeInverseScales(transform, inverseScaleX, inverseScaleY); - - SkTArray tempVertices; - float threshInvScaleX = inverseScaleX; - float threshInvScaleY = inverseScaleY; - if (style == SkStrokeRec::kStroke_Style) { - // alter the bezier recursion threshold values we calculate in order to compensate for - // expansion done after the path vertices are found - SkRect bounds = path.getBounds(); - if (!bounds.isEmpty()) { - threshInvScaleX *= bounds.width() / (bounds.width() + stroke.getWidth()); - threshInvScaleY *= bounds.height() / (bounds.height() + stroke.getWidth()); - } - } - - // force close if we're filling the path, since fill path expects closed perimeter. - bool forceClose = style != SkStrokeRec::kStroke_Style; - bool wasClosed = ConvexPathPerimeterVertices(path, forceClose, threshInvScaleX * threshInvScaleX, - threshInvScaleY * threshInvScaleY, &tempVertices); - - if (!tempVertices.count()) { - // path was empty, return without allocating vertex buffer - return; - } - -#if VERTEX_DEBUG - for (unsigned int i = 0; i < tempVertices.count(); i++) { - SkDebugf("orig path: point at %f %f", tempVertices[i].position[0], tempVertices[i].position[1]); - } -#endif - - if (style == SkStrokeRec::kStroke_Style) { - float halfStrokeWidth = stroke.getWidth() * 0.5f; - if (!isAA) { - if (wasClosed) { - getStrokeVerticesFromPerimeter(tempVertices, halfStrokeWidth, vertexBuffer, - inverseScaleX, inverseScaleY); - } else { - getStrokeVerticesFromUnclosedVertices(tempVertices, halfStrokeWidth, vertexBuffer, - inverseScaleX, inverseScaleY); - } - - } else { - if (wasClosed) { - getStrokeVerticesFromPerimeterAA(tempVertices, halfStrokeWidth, vertexBuffer, - inverseScaleX, inverseScaleY); - } else { - getStrokeVerticesFromUnclosedVerticesAA(tempVertices, halfStrokeWidth, vertexBuffer, - inverseScaleX, inverseScaleY); - } - } - } else { - // For kStrokeAndFill style, the path should be adjusted externally, as it will be treated as a fill here. - if (!isAA) { - getFillVerticesFromPerimeter(tempVertices, vertexBuffer); - } else { - getFillVerticesFromPerimeterAA(tempVertices, vertexBuffer, inverseScaleX, inverseScaleY); - } - } -} - - -static void pushToVector(SkTArray* vertices, float x, float y) { - // TODO: make this not yuck - vertices->push_back(); - Vertex* newVertex = &((*vertices)[vertices->count() - 1]); - Vertex::set(newVertex, x, y); -} - -bool PathRenderer::ConvexPathPerimeterVertices(const SkPath& path, bool forceClose, - float sqrInvScaleX, float sqrInvScaleY, SkTArray* outputVertices) { - - - // TODO: to support joins other than sharp miter, join vertices should be labelled in the - // perimeter, or resolved into more vertices. Reconsider forceClose-ing in that case. - SkPath::Iter iter(path, forceClose); - SkPoint pts[4]; - SkPath::Verb v; - - while (SkPath::kDone_Verb != (v = iter.next(pts))) { - switch (v) { - case SkPath::kMove_Verb: - pushToVector(outputVertices, pts[0].x(), pts[0].y()); - ALOGV("Move to pos %f %f", pts[0].x(), pts[0].y()); - break; - case SkPath::kClose_Verb: - ALOGV("Close at pos %f %f", pts[0].x(), pts[0].y()); - break; - case SkPath::kLine_Verb: - ALOGV("kLine_Verb %f %f -> %f %f", - pts[0].x(), pts[0].y(), - pts[1].x(), pts[1].y()); - - pushToVector(outputVertices, pts[1].x(), pts[1].y()); - break; - case SkPath::kQuad_Verb: - ALOGV("kQuad_Verb"); - RecursiveQuadraticBezierVertices( - pts[0].x(), pts[0].y(), - pts[2].x(), pts[2].y(), - pts[1].x(), pts[1].y(), - sqrInvScaleX, sqrInvScaleY, outputVertices); - break; - case SkPath::kCubic_Verb: - ALOGV("kCubic_Verb"); - RecursiveCubicBezierVertices( - pts[0].x(), pts[0].y(), - pts[1].x(), pts[1].y(), - pts[3].x(), pts[3].y(), - pts[2].x(), pts[2].y(), - sqrInvScaleX, sqrInvScaleY, outputVertices); - break; - default: - break; - } - } - - int size = outputVertices->count(); - if (size >= 2 && (*outputVertices)[0].position[0] == (*outputVertices)[size - 1].position[0] && - (*outputVertices)[0].position[1] == (*outputVertices)[size - 1].position[1]) { - outputVertices->pop_back(); - return true; - } - return false; -} - -void PathRenderer::RecursiveCubicBezierVertices( - float p1x, float p1y, float c1x, float c1y, - float p2x, float p2y, float c2x, float c2y, - float sqrInvScaleX, float sqrInvScaleY, SkTArray* outputVertices) { - float dx = p2x - p1x; - float dy = p2y - p1y; - float d1 = sk_float_abs((c1x - p2x) * dy - (c1y - p2y) * dx); - float d2 = sk_float_abs((c2x - p2x) * dy - (c2y - p2y) * dx); - float d = d1 + d2; - - // multiplying by sqrInvScaleY/X equivalent to multiplying in dimensional scale factors - - if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) { - // below thresh, draw line by adding endpoint - pushToVector(outputVertices, p2x, p2y); - } else { - float p1c1x = (p1x + c1x) * 0.5f; - float p1c1y = (p1y + c1y) * 0.5f; - float p2c2x = (p2x + c2x) * 0.5f; - float p2c2y = (p2y + c2y) * 0.5f; - - float c1c2x = (c1x + c2x) * 0.5f; - float c1c2y = (c1y + c2y) * 0.5f; - - float p1c1c2x = (p1c1x + c1c2x) * 0.5f; - float p1c1c2y = (p1c1y + c1c2y) * 0.5f; - - float p2c1c2x = (p2c2x + c1c2x) * 0.5f; - float p2c1c2y = (p2c2y + c1c2y) * 0.5f; - - float mx = (p1c1c2x + p2c1c2x) * 0.5f; - float my = (p1c1c2y + p2c1c2y) * 0.5f; - - RecursiveCubicBezierVertices( - p1x, p1y, p1c1x, p1c1y, - mx, my, p1c1c2x, p1c1c2y, - sqrInvScaleX, sqrInvScaleY, outputVertices); - RecursiveCubicBezierVertices( - mx, my, p2c1c2x, p2c1c2y, - p2x, p2y, p2c2x, p2c2y, - sqrInvScaleX, sqrInvScaleY, outputVertices); - } -} - -void PathRenderer::RecursiveQuadraticBezierVertices( - float ax, float ay, - float bx, float by, - float cx, float cy, - float sqrInvScaleX, float sqrInvScaleY, SkTArray* outputVertices) { - float dx = bx - ax; - float dy = by - ay; - float d = (cx - bx) * dy - (cy - by) * dx; - - if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) { - // below thresh, draw line by adding endpoint - pushToVector(outputVertices, bx, by); - } else { - float acx = (ax + cx) * 0.5f; - float bcx = (bx + cx) * 0.5f; - float acy = (ay + cy) * 0.5f; - float bcy = (by + cy) * 0.5f; - - // midpoint - float mx = (acx + bcx) * 0.5f; - float my = (acy + bcy) * 0.5f; - - RecursiveQuadraticBezierVertices(ax, ay, mx, my, acx, acy, - sqrInvScaleX, sqrInvScaleY, outputVertices); - RecursiveQuadraticBezierVertices(mx, my, bx, by, bcx, bcy, - sqrInvScaleX, sqrInvScaleY, outputVertices); - } -} - -}; // namespace uirenderer -}; // namespace android diff --git a/experimental/AndroidPathRenderer/AndroidPathRenderer.h b/experimental/AndroidPathRenderer/AndroidPathRenderer.h deleted file mode 100644 index 0e87aed1d1..0000000000 --- a/experimental/AndroidPathRenderer/AndroidPathRenderer.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2012 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef ANDROID_HWUI_PATH_RENDERER_H -#define ANDROID_HWUI_PATH_RENDERER_H - -#include - -#include "Vertex.h" - -class SkMatrix; - -namespace android { -namespace uirenderer { - -class VertexBuffer { -public: - VertexBuffer(): - mBuffer(0), - mSize(0), - mCleanupMethod(0) - {} - - ~VertexBuffer() { - if (mCleanupMethod) - mCleanupMethod(mBuffer); - } - - template - TYPE* alloc(int size) { - mSize = size; - mBuffer = (void*)new TYPE[size]; - mCleanupMethod = &(cleanup); - - return (TYPE*)mBuffer; - } - - void* getBuffer() { return mBuffer; } - unsigned int getSize() { return mSize; } - -private: - template - static void cleanup(void* buffer) { - delete[] (TYPE*)buffer; - } - - void* mBuffer; - unsigned int mSize; - void (*mCleanupMethod)(void*); -}; - -class PathRenderer { -public: - static SkRect ComputePathBounds(const SkPath& path, const SkPaint* paint); - - static void ConvexPathVertices(const SkPath& path, const SkStrokeRec& stroke, bool isAA, - const SkMatrix* transform, VertexBuffer* vertexBuffer); - -private: - static bool ConvexPathPerimeterVertices(const SkPath &path, bool forceClose, - float sqrInvScaleX, float sqrInvScaleY, SkTArray* outputVertices); - -/* - endpoints a & b, - control c - */ - static void RecursiveQuadraticBezierVertices( - float ax, float ay, - float bx, float by, - float cx, float cy, - float sqrInvScaleX, float sqrInvScaleY, - SkTArray* outputVertices); - -/* - endpoints p1, p2 - control c1, c2 - */ - static void RecursiveCubicBezierVertices( - float p1x, float p1y, - float c1x, float c1y, - float p2x, float p2y, - float c2x, float c2y, - float sqrInvScaleX, float sqrInvScaleY, - SkTArray* outputVertices); -}; - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_PATH_RENDERER_H diff --git a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp deleted file mode 100644 index 8faf49fe66..0000000000 --- a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp +++ /dev/null @@ -1,89 +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 "GrAndroidPathRenderer.h" -#include "AndroidPathRenderer.h" -#include "Vertex.h" - -GrAndroidPathRenderer::GrAndroidPathRenderer() { -} - -bool GrAndroidPathRenderer::canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, - const GrDrawTarget* target, - bool antiAlias) const { - return ((stroke.isFillStyle() || stroke.getStyle() == SkStrokeRec::kStroke_Style) - && !path.isInverseFillType() && path.isConvex()); -} - -struct ColorVertex { - SkPoint pos; - GrColor color; -}; - -bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath, - const SkStrokeRec& stroke, - GrDrawTarget* target, - bool antiAlias) { - - // generate verts using Android algorithm - android::uirenderer::VertexBuffer vertices; - android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL, - &vertices); - - // set vertex attributes depending on anti-alias - GrDrawState* drawState = target->drawState(); - if (antiAlias) { - // position + coverage - GrVertexAttrib attribs[] = { - GrVertexAttrib(kVec2f_GrVertexAttribType, 0), - GrVertexAttrib(kVec4ub_GrVertexAttribType, sizeof(GrPoint)) - }; - drawState->setVertexAttribs(attribs, SK_ARRAY_COUNT(attribs)); - drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); - drawState->setAttribIndex(GrDrawState::kCoverage_AttribIndex, 1); - drawState->setAttribBindings(GrDrawState::kCoverage_AttribBindingsBit); - } else { - drawState->setDefaultVertexAttribs(); - } - - // allocate our vert buffer - int vertCount = vertices.getSize(); - GrDrawTarget::AutoReleaseGeometry geo(target, vertCount, 0); - if (!geo.succeeded()) { - SkDebugf("Failed to get space for vertices!\n"); - return false; - } - - // copy android verts to our vertex buffer - if (antiAlias) { - SkASSERT(sizeof(ColorVertex) == drawState->getVertexSize()); - ColorVertex* outVert = reinterpret_cast(geo.vertices()); - android::uirenderer::AlphaVertex* inVert = - reinterpret_cast(vertices.getBuffer()); - - for (int i = 0; i < vertCount; ++i) { - // copy vertex position - outVert->pos.set(inVert->position[0], inVert->position[1]); - // copy alpha - int coverage = static_cast(inVert->alpha * 0xff); - outVert->color = GrColorPackRGBA(coverage, coverage, coverage, coverage); - ++outVert; - ++inVert; - } - } else { - size_t vsize = drawState->getVertexSize(); - size_t copySize = vsize*vertCount; - memcpy(geo.vertices(), vertices.getBuffer(), copySize); - } - - // render it - target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, vertCount); - - return true; -} diff --git a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.h b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.h deleted file mode 100644 index a7225fa660..0000000000 --- a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.h +++ /dev/null @@ -1,29 +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 "GrPathRenderer.h" - - -class GrAndroidPathRenderer : public GrPathRenderer { -public: - GrAndroidPathRenderer(); - - virtual bool canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, - const GrDrawTarget* target, - bool antiAlias) const override; - -protected: - virtual bool onDrawPath(const SkPath& path, - const SkStrokeRec& stroke, - GrDrawTarget* target, - bool antiAlias) override; - -private: - typedef GrPathRenderer INHERITED; -}; diff --git a/experimental/AndroidPathRenderer/Vertex.h b/experimental/AndroidPathRenderer/Vertex.h deleted file mode 100644 index c8e0ba7ea1..0000000000 --- a/experimental/AndroidPathRenderer/Vertex.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef ANDROID_HWUI_VERTEX_H -#define ANDROID_HWUI_VERTEX_H - -namespace android { -namespace uirenderer { - -/** - * Simple structure to describe a vertex with a position and a texture. - */ -struct Vertex { - float position[2]; - - static inline void set(Vertex* vertex, float x, float y) { - vertex[0].position[0] = x; - vertex[0].position[1] = y; - } -}; // struct Vertex - -/** - * Simple structure to describe a vertex with a position and a texture. - */ -/*struct TextureVertex { - float position[2]; - float texture[2]; - - static inline void set(TextureVertex* vertex, float x, float y, float u, float v) { - vertex[0].position[0] = x; - vertex[0].position[1] = y; - vertex[0].texture[0] = u; - vertex[0].texture[1] = v; - } - - static inline void setUV(TextureVertex* vertex, float u, float v) { - vertex[0].texture[0] = u; - vertex[0].texture[1] = v; - } -};*/ // struct TextureVertex - -/** - * Simple structure to describe a vertex with a position and an alpha value. - */ -struct AlphaVertex : Vertex { - float alpha; - - static inline void set(AlphaVertex* vertex, float x, float y, float alpha) { - Vertex::set(vertex, x, y); - vertex[0].alpha = alpha; - } - - static inline void setColor(AlphaVertex* vertex, float alpha) { - vertex[0].alpha = alpha; - } -}; // struct AlphaVertex - -/** - * Simple structure to describe a vertex with a position and an alpha value. - */ -/*struct AAVertex : Vertex { - float width; - float length; - - static inline void set(AAVertex* vertex, float x, float y, float width, float length) { - Vertex::set(vertex, x, y); - vertex[0].width = width; - vertex[0].length = length; - } - - static inline void setColor(AAVertex* vertex, float width, float length) { - vertex[0].width = width; - vertex[0].length = length; - } -};*/ // struct AlphaVertex - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_VERTEX_H diff --git a/experimental/AndroidPathRenderer/cutils/compiler.h b/experimental/AndroidPathRenderer/cutils/compiler.h deleted file mode 100644 index 56c623c42b..0000000000 --- a/experimental/AndroidPathRenderer/cutils/compiler.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2012 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef ANDROID_CUTILS_COMPILER_H -#define ANDROID_CUTILS_COMPILER_H - -/* - * helps the compiler's optimizer predicting branches - */ - -#ifdef __cplusplus -# define CC_LIKELY( exp ) (__builtin_expect( !!(exp), true )) -# define CC_UNLIKELY( exp ) (__builtin_expect( !!(exp), false )) -#else -# define CC_LIKELY( exp ) (__builtin_expect( !!(exp), 1 )) -# define CC_UNLIKELY( exp ) (__builtin_expect( !!(exp), 0 )) -#endif - -/** - * exports marked symbols - * - * if used on a C++ class declaration, this macro must be inserted - * after the "class" keyword. For instance: - * - * template - * class ANDROID_API Singleton { } - */ - -#define ANDROID_API __attribute__((visibility("default"))) - -#endif // ANDROID_CUTILS_COMPILER_H diff --git a/experimental/StrokePathRenderer/GrStrokePathRenderer.cpp b/experimental/StrokePathRenderer/GrStrokePathRenderer.cpp deleted file mode 100644 index e693c41a66..0000000000 --- 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(arg.vertices()); - uint16_t* idxs = reinterpret_cast(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; -} diff --git a/experimental/StrokePathRenderer/GrStrokePathRenderer.h b/experimental/StrokePathRenderer/GrStrokePathRenderer.h deleted file mode 100644 index 85752c5681..0000000000 --- a/experimental/StrokePathRenderer/GrStrokePathRenderer.h +++ /dev/null @@ -1,30 +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 "GrPathRenderer.h" - -// This path renderer is made to create geometry (i.e. primitives) from the original path (before -// the path is stroked) and render using the GPU directly rather than using any software rendering -// step. It can be rendered in a single pass for simple cases and use multiple passes for features -// like AA or opacity support. - -class GrStrokePathRenderer : public GrPathRenderer { - -public: - GrStrokePathRenderer(); - - virtual bool canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, - const GrDrawTarget* target, - bool antiAlias) const override; - -protected: - virtual bool onDrawPath(const SkPath& path, - const SkStrokeRec& stroke, - GrDrawTarget* target, - bool antiAlias) override; -}; -- cgit v1.2.3