diff options
author | jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-12-18 14:13:46 +0000 |
---|---|---|
committer | jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-12-18 14:13:46 +0000 |
commit | 24b4f97d00988efefb856abdbd4357cafdc36c86 (patch) | |
tree | c17c633eff2971a99f03b51999e31098b599cd08 | |
parent | 7a03d86a3d9adcb13432fbd82039725149487c97 (diff) |
Add AndroidPathRenderer to experimental gyp and get it compiling with Skia code.
https://codereview.appspot.com/6938074/
git-svn-id: http://skia.googlecode.com/svn/trunk@6874 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | experimental/AndroidPathRenderer/AndroidPathRenderer.cpp | 404 | ||||
-rw-r--r-- | experimental/AndroidPathRenderer/AndroidPathRenderer.h | 25 | ||||
-rw-r--r-- | gyp/experimental.gyp | 2 |
3 files changed, 227 insertions, 204 deletions
diff --git a/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp b/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp index e762eb2859..ef4ade24bf 100644 --- a/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp +++ b/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp @@ -18,20 +18,28 @@ #include <stdint.h> #include <sys/types.h> -#include <utils/Log.h> -#include <utils/Trace.h> +#include <SkTypes.h> +#include <SkTrace.h> +#include <SkMatrix.h> +#include <SkPoint.h> + +#ifdef VERBOSE +#define ALOGV SkDebugf +#else +#define ALOGV(x, ...) +#endif -#include "PathRenderer.h" -#include "Matrix.h" -#include "Vector.h" +#include "AndroidPathRenderer.h" #include "Vertex.h" +#include "cutils/compiler.h" + namespace android { namespace uirenderer { #define THRESHOLD 0.5f -SkRect PathRenderer::computePathBounds(const SkPath& path, const SkPaint* paint) { +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; @@ -40,12 +48,12 @@ SkRect PathRenderer::computePathBounds(const SkPath& path, const SkPaint* paint) return bounds; } -void computeInverseScales(const mat4 *transform, float &inverseScaleX, float& inverseScaleY) { - if (CC_UNLIKELY(!transform->isPureTranslate())) { - float m00 = transform->data[Matrix4::kScaleX]; - float m01 = transform->data[Matrix4::kSkewY]; - float m10 = transform->data[Matrix4::kSkewX]; - float m11 = transform->data[Matrix4::kScaleY]; +void computeInverseScales(const SkMatrix* transform, float &inverseScaleX, float& inverseScaleY) { + if (CC_UNLIKELY(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 = sqrt(m00 * m00 + m01 * m01); float scaleY = sqrt(m10 * m10 + m11 * m11); inverseScaleX = (scaleX != 0) ? (1.0f / scaleX) : 1.0f; @@ -74,29 +82,31 @@ inline void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) { * * NOTE: assumes angles between normals 90 degrees or less */ -inline vec2 totalOffsetFromNormals(const vec2& normalA, const vec2& normalB) { - return (normalA + normalB) / (1 + fabs(normalA.dot(normalB))); +inline SkVector totalOffsetFromNormals(const SkVector& normalA, const SkVector& normalB) { + SkVector pseudoNormal = normalA + normalB; + pseudoNormal.scale(1.0f / (1.0f + fabs(normalA.dot(normalB)))); + return pseudoNormal; } -inline void scaleOffsetForStrokeWidth(vec2& offset, float halfStrokeWidth, +inline void scaleOffsetForStrokeWidth(SkVector& offset, float halfStrokeWidth, float inverseScaleX, float inverseScaleY) { if (halfStrokeWidth == 0.0f) { // hairline - compensate for scale - offset.x *= 0.5f * inverseScaleX; - offset.y *= 0.5f * inverseScaleY; + offset.fX *= 0.5f * inverseScaleX; + offset.fY *= 0.5f * inverseScaleY; } else { - offset *= halfStrokeWidth; + offset.scale(halfStrokeWidth); } } -void getFillVerticesFromPerimeter(const Vector<Vertex>& perimeter, VertexBuffer& vertexBuffer) { - Vertex* buffer = vertexBuffer.alloc<Vertex>(perimeter.size()); +void getFillVerticesFromPerimeter(const SkTArray<Vertex, true>& perimeter, VertexBuffer* vertexBuffer) { + Vertex* buffer = vertexBuffer->alloc<Vertex>(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.size() - 1; + int srcBindex = perimeter.count() - 1; while (srcAindex <= srcBindex) { copyVertex(&buffer[currentIndex++], &perimeter[srcAindex]); if (srcAindex == srcBindex) break; @@ -106,32 +116,34 @@ void getFillVerticesFromPerimeter(const Vector<Vertex>& perimeter, VertexBuffer& } } -void getStrokeVerticesFromPerimeter(const Vector<Vertex>& perimeter, float halfStrokeWidth, - VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) { - Vertex* buffer = vertexBuffer.alloc<Vertex>(perimeter.size() * 2 + 2); +void getStrokeVerticesFromPerimeter(const SkTArray<Vertex, true>& perimeter, float halfStrokeWidth, + VertexBuffer* vertexBuffer, float inverseScaleX, float inverseScaleY) { + Vertex* buffer = vertexBuffer->alloc<Vertex>(perimeter.count() * 2 + 2); int currentIndex = 0; - const Vertex* last = &(perimeter[perimeter.size() - 1]); + const Vertex* last = &(perimeter[perimeter.count() - 1]); const Vertex* current = &(perimeter[0]); - vec2 lastNormal(current->position[1] - last->position[1], - last->position[0] - current->position[0]); + SkVector lastNormal; + lastNormal.set(current->position[1] - last->position[1], + last->position[0] - current->position[0]); lastNormal.normalize(); - for (unsigned int i = 0; i < perimeter.size(); i++) { - const Vertex* next = &(perimeter[i + 1 >= perimeter.size() ? 0 : i + 1]); - vec2 nextNormal(next->position[1] - current->position[1], - current->position[0] - next->position[0]); + 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(); - vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); + SkVector totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); Vertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.x, - current->position[1] + totalOffset.y); + current->position[0] + totalOffset.fX, + current->position[1] + totalOffset.fY); Vertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.x, - current->position[1] - totalOffset.y); + current->position[0] - totalOffset.fX, + current->position[1] - totalOffset.fY); last = current; current = next; @@ -143,20 +155,21 @@ void getStrokeVerticesFromPerimeter(const Vector<Vertex>& perimeter, float halfS copyVertex(&buffer[currentIndex++], &buffer[1]); } -void getStrokeVerticesFromUnclosedVertices(const Vector<Vertex>& vertices, float halfStrokeWidth, - VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) { - Vertex* buffer = vertexBuffer.alloc<Vertex>(vertices.size() * 2); +void getStrokeVerticesFromUnclosedVertices(const SkTArray<Vertex, true>& vertices, float halfStrokeWidth, + VertexBuffer* vertexBuffer, float inverseScaleX, float inverseScaleY) { + Vertex* buffer = vertexBuffer->alloc<Vertex>(vertices.count() * 2); int currentIndex = 0; const Vertex* current = &(vertices[0]); - vec2 lastNormal; - for (unsigned int i = 0; i < vertices.size() - 1; i++) { + SkVector lastNormal; + for (int i = 0; i < vertices.count() - 1; i++) { const Vertex* next = &(vertices[i + 1]); - vec2 nextNormal(next->position[1] - current->position[1], - current->position[0] - next->position[0]); + SkVector nextNormal; + nextNormal.set(next->position[1] - current->position[1], + current->position[0] - next->position[0]); nextNormal.normalize(); - vec2 totalOffset; + SkVector totalOffset; if (i == 0) { totalOffset = nextNormal; } else { @@ -165,64 +178,66 @@ void getStrokeVerticesFromUnclosedVertices(const Vector<Vertex>& vertices, float scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); Vertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.x, - current->position[1] + totalOffset.y); + current->position[0] + totalOffset.fX, + current->position[1] + totalOffset.fY); Vertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.x, - current->position[1] - totalOffset.y); + current->position[0] - totalOffset.fX, + current->position[1] - totalOffset.fY); current = next; lastNormal = nextNormal; } - vec2 totalOffset = lastNormal; + SkVector totalOffset = lastNormal; scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); Vertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.x, - current->position[1] + totalOffset.y); + current->position[0] + totalOffset.fX, + current->position[1] + totalOffset.fY); Vertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.x, - current->position[1] - totalOffset.y); + current->position[0] - totalOffset.fX, + current->position[1] - totalOffset.fY); #if VERTEX_DEBUG for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { - ALOGD("point at %f %f", buffer[i].position[0], buffer[i].position[1]); + SkDebugf("point at %f %f", buffer[i].position[0], buffer[i].position[1]); } #endif } -void getFillVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, VertexBuffer& vertexBuffer, +void getFillVerticesFromPerimeterAA(const SkTArray<Vertex, true>& perimeter, VertexBuffer* vertexBuffer, float inverseScaleX, float inverseScaleY) { - AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(perimeter.size() * 3 + 2); + AlphaVertex* buffer = vertexBuffer->alloc<AlphaVertex>(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.size() - 1]); + const Vertex* last = &(perimeter[perimeter.count() - 1]); const Vertex* current = &(perimeter[0]); - vec2 lastNormal(current->position[1] - last->position[1], - last->position[0] - current->position[0]); + SkVector lastNormal; + lastNormal.set(current->position[1] - last->position[1], + last->position[0] - current->position[0]); lastNormal.normalize(); - for (unsigned int i = 0; i < perimeter.size(); i++) { - const Vertex* next = &(perimeter[i + 1 >= perimeter.size() ? 0 : i + 1]); - vec2 nextNormal(next->position[1] - current->position[1], - current->position[0] - next->position[0]); + 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 - vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - totalOffset.x *= 0.5f * inverseScaleX; - totalOffset.y *= 0.5f * inverseScaleY; + SkVector totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); + totalOffset.fX *= 0.5f * inverseScaleX; + totalOffset.fY *= 0.5f * inverseScaleY; AlphaVertex::set(&buffer[currentIndex++], - current->position[0] + totalOffset.x, - current->position[1] + totalOffset.y, + current->position[0] + totalOffset.fX, + current->position[1] + totalOffset.fY, 0.0f); AlphaVertex::set(&buffer[currentIndex++], - current->position[0] - totalOffset.x, - current->position[1] - totalOffset.y, + current->position[0] - totalOffset.fX, + current->position[1] - totalOffset.fY, 1.0f); last = current; @@ -238,7 +253,7 @@ void getFillVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, VertexBuffe // 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.size() - 1; + int srcBindex = perimeter.count() - 1; while (srcAindex <= srcBindex) { copyAlphaVertex(&buffer[currentIndex++], &buffer[srcAindex * 2 + 1]); if (srcAindex == srcBindex) break; @@ -249,15 +264,15 @@ void getFillVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, VertexBuffe #if VERTEX_DEBUG for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { - ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); + SkDebugf("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); } #endif } -void getStrokeVerticesFromUnclosedVerticesAA(const Vector<Vertex>& vertices, float halfStrokeWidth, - VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) { - AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(6 * vertices.size() + 2); +void getStrokeVerticesFromUnclosedVerticesAA(const SkTArray<Vertex, true>& vertices, float halfStrokeWidth, + VertexBuffer* vertexBuffer, float inverseScaleX, float inverseScaleY) { + AlphaVertex* buffer = vertexBuffer->alloc<AlphaVertex>(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) @@ -269,47 +284,49 @@ void getStrokeVerticesFromUnclosedVerticesAA(const Vector<Vertex>& vertices, flo } // there is no outer/inner here, using them for consistency with below approach - int offset = 2 * (vertices.size() - 2); + 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]); - vec2 lastNormal(current->position[1] - last->position[1], - last->position[0] - current->position[0]); + SkVector lastNormal; + lastNormal.set(current->position[1] - last->position[1], + last->position[0] - current->position[0]); lastNormal.normalize(); { // start cap - vec2 totalOffset = lastNormal; - vec2 AAOffset = totalOffset; - AAOffset.x *= 0.5f * inverseScaleX; - AAOffset.y *= 0.5f * inverseScaleY; + SkVector totalOffset = lastNormal; + SkVector AAOffset = totalOffset; + AAOffset.fX *= 0.5f * inverseScaleX; + AAOffset.fY *= 0.5f * inverseScaleY; - vec2 innerOffset = totalOffset; + SkVector innerOffset = totalOffset; scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - vec2 outerOffset = innerOffset + AAOffset; + SkVector outerOffset = innerOffset + AAOffset; innerOffset -= AAOffset; // TODO: support square cap by changing this offset to incorporate halfStrokeWidth - vec2 capAAOffset(AAOffset.y, -AAOffset.x); + SkVector capAAOffset; + capAAOffset.set(AAOffset.fY, -AAOffset.fX); AlphaVertex::set(&buffer[0], - last->position[0] + outerOffset.x + capAAOffset.x, - last->position[1] + outerOffset.y + capAAOffset.y, + last->position[0] + outerOffset.fX + capAAOffset.fX, + last->position[1] + outerOffset.fY + capAAOffset.fY, 0.0f); AlphaVertex::set(&buffer[1], - last->position[0] + innerOffset.x - capAAOffset.x, - last->position[1] + innerOffset.y - capAAOffset.y, + 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.x + capAAOffset.x, - last->position[1] - outerOffset.y + capAAOffset.y, + 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.x - capAAOffset.x, - last->position[1] - innerOffset.y - capAAOffset.y, + 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]); @@ -317,47 +334,48 @@ void getStrokeVerticesFromUnclosedVerticesAA(const Vector<Vertex>& vertices, flo copyAlphaVertex(&buffer[2 * offset + 11], &buffer[2 * offset + 7]); } - for (unsigned int i = 1; i < vertices.size() - 1; i++) { + for (int i = 1; i < vertices.count() - 1; i++) { const Vertex* next = &(vertices[i + 1]); - vec2 nextNormal(next->position[1] - current->position[1], - current->position[0] - next->position[0]); + SkVector nextNormal; + nextNormal.set(next->position[1] - current->position[1], + current->position[0] - next->position[0]); nextNormal.normalize(); - vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - vec2 AAOffset = totalOffset; - AAOffset.x *= 0.5f * inverseScaleX; - AAOffset.y *= 0.5f * inverseScaleY; + SkVector totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); + SkVector AAOffset = totalOffset; + AAOffset.fX *= 0.5f * inverseScaleX; + AAOffset.fY *= 0.5f * inverseScaleY; - vec2 innerOffset = totalOffset; + SkVector innerOffset = totalOffset; scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - vec2 outerOffset = innerOffset + AAOffset; + SkVector outerOffset = innerOffset + AAOffset; innerOffset -= AAOffset; AlphaVertex::set(&buffer[currentAAOuterIndex++], - current->position[0] + outerOffset.x, - current->position[1] + outerOffset.y, + current->position[0] + outerOffset.fX, + current->position[1] + outerOffset.fY, 0.0f); AlphaVertex::set(&buffer[currentAAOuterIndex++], - current->position[0] + innerOffset.x, - current->position[1] + innerOffset.y, + current->position[0] + innerOffset.fX, + current->position[1] + innerOffset.fY, maxAlpha); AlphaVertex::set(&buffer[currentStrokeIndex++], - current->position[0] + innerOffset.x, - current->position[1] + innerOffset.y, + current->position[0] + innerOffset.fX, + current->position[1] + innerOffset.fY, maxAlpha); AlphaVertex::set(&buffer[currentStrokeIndex++], - current->position[0] - innerOffset.x, - current->position[1] - innerOffset.y, + current->position[0] - innerOffset.fX, + current->position[1] - innerOffset.fY, maxAlpha); AlphaVertex::set(&buffer[currentAAInnerIndex--], - current->position[0] - innerOffset.x, - current->position[1] - innerOffset.y, + current->position[0] - innerOffset.fX, + current->position[1] - innerOffset.fY, maxAlpha); AlphaVertex::set(&buffer[currentAAInnerIndex--], - current->position[0] - outerOffset.x, - current->position[1] - outerOffset.y, + current->position[0] - outerOffset.fX, + current->position[1] - outerOffset.fY, 0.0f); last = current; @@ -367,52 +385,53 @@ void getStrokeVerticesFromUnclosedVerticesAA(const Vector<Vertex>& vertices, flo { // end cap - vec2 totalOffset = lastNormal; - vec2 AAOffset = totalOffset; - AAOffset.x *= 0.5f * inverseScaleX; - AAOffset.y *= 0.5f * inverseScaleY; + SkVector totalOffset = lastNormal; + SkVector AAOffset = totalOffset; + AAOffset.fX *= 0.5f * inverseScaleX; + AAOffset.fY *= 0.5f * inverseScaleY; - vec2 innerOffset = totalOffset; + SkVector innerOffset = totalOffset; scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - vec2 outerOffset = innerOffset + AAOffset; + SkVector outerOffset = innerOffset + AAOffset; innerOffset -= AAOffset; // TODO: support square cap by changing this offset to incorporate halfStrokeWidth - vec2 capAAOffset(-AAOffset.y, AAOffset.x); + SkVector capAAOffset; + capAAOffset.set(-AAOffset.fY, AAOffset.fX); AlphaVertex::set(&buffer[offset + 2], - current->position[0] + outerOffset.x + capAAOffset.x, - current->position[1] + outerOffset.y + capAAOffset.y, + 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.x - capAAOffset.x, - current->position[1] + innerOffset.y - capAAOffset.y, + current->position[0] + innerOffset.fX - capAAOffset.fX, + current->position[1] + innerOffset.fY - capAAOffset.fY, maxAlpha); AlphaVertex::set(&buffer[offset + 4], - current->position[0] - outerOffset.x + capAAOffset.x, - current->position[1] - outerOffset.y + capAAOffset.y, + 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.x - capAAOffset.x, - current->position[1] - innerOffset.y - capAAOffset.y, + 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]); + 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++) { - ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); + SkDebugf("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); } #endif } -void getStrokeVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, float halfStrokeWidth, - VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) { - AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(6 * perimeter.size() + 8); +void getStrokeVerticesFromPerimeterAA(const SkTArray<Vertex, true>& perimeter, float halfStrokeWidth, + VertexBuffer* vertexBuffer, float inverseScaleX, float inverseScaleY) { + AlphaVertex* buffer = vertexBuffer->alloc<AlphaVertex>(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) @@ -423,57 +442,59 @@ void getStrokeVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, float hal halfStrokeWidth = 0.0f; } - int offset = 2 * perimeter.size() + 3; + int offset = 2 * perimeter.count() + 3; int currentAAOuterIndex = 0; int currentStrokeIndex = offset; int currentAAInnerIndex = offset * 2; - const Vertex* last = &(perimeter[perimeter.size() - 1]); + const Vertex* last = &(perimeter[perimeter.count() - 1]); const Vertex* current = &(perimeter[0]); - vec2 lastNormal(current->position[1] - last->position[1], - last->position[0] - current->position[0]); + SkVector lastNormal; + lastNormal.set(current->position[1] - last->position[1], + last->position[0] - current->position[0]); lastNormal.normalize(); - for (unsigned int i = 0; i < perimeter.size(); i++) { - const Vertex* next = &(perimeter[i + 1 >= perimeter.size() ? 0 : i + 1]); - vec2 nextNormal(next->position[1] - current->position[1], - current->position[0] - next->position[0]); + 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(); - vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - vec2 AAOffset = totalOffset; - AAOffset.x *= 0.5f * inverseScaleX; - AAOffset.y *= 0.5f * inverseScaleY; + SkVector totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); + SkVector AAOffset = totalOffset; + AAOffset.fX *= 0.5f * inverseScaleX; + AAOffset.fY *= 0.5f * inverseScaleY; - vec2 innerOffset = totalOffset; + SkVector innerOffset = totalOffset; scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); - vec2 outerOffset = innerOffset + AAOffset; + SkVector outerOffset = innerOffset + AAOffset; innerOffset -= AAOffset; AlphaVertex::set(&buffer[currentAAOuterIndex++], - current->position[0] + outerOffset.x, - current->position[1] + outerOffset.y, + current->position[0] + outerOffset.fX, + current->position[1] + outerOffset.fY, 0.0f); AlphaVertex::set(&buffer[currentAAOuterIndex++], - current->position[0] + innerOffset.x, - current->position[1] + innerOffset.y, + current->position[0] + innerOffset.fX, + current->position[1] + innerOffset.fY, maxAlpha); AlphaVertex::set(&buffer[currentStrokeIndex++], - current->position[0] + innerOffset.x, - current->position[1] + innerOffset.y, + current->position[0] + innerOffset.fX, + current->position[1] + innerOffset.fY, maxAlpha); AlphaVertex::set(&buffer[currentStrokeIndex++], - current->position[0] - innerOffset.x, - current->position[1] - innerOffset.y, + current->position[0] - innerOffset.fX, + current->position[1] - innerOffset.fY, maxAlpha); AlphaVertex::set(&buffer[currentAAInnerIndex++], - current->position[0] - innerOffset.x, - current->position[1] - innerOffset.y, + current->position[0] - innerOffset.fX, + current->position[1] - innerOffset.fY, maxAlpha); AlphaVertex::set(&buffer[currentAAInnerIndex++], - current->position[0] - outerOffset.x, - current->position[1] - outerOffset.y, + current->position[0] - outerOffset.fX, + current->position[1] - outerOffset.fY, 0.0f); last = current; @@ -496,14 +517,14 @@ void getStrokeVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, float hal #if VERTEX_DEBUG for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { - ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); + 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 SkPaint* paint, - const mat4 *transform, VertexBuffer& vertexBuffer) { - ATRACE_CALL(); +void PathRenderer::ConvexPathVertices(const SkPath &path, const SkPaint* paint, + const SkMatrix* transform, VertexBuffer* vertexBuffer) { + SK_TRACE_EVENT0("PathRenderer::convexPathVertices"); SkPaint::Style style = paint->getStyle(); bool isAA = paint->isAntiAlias(); @@ -511,7 +532,7 @@ void PathRenderer::convexPathVertices(const SkPath &path, const SkPaint* paint, float inverseScaleX, inverseScaleY; computeInverseScales(transform, inverseScaleX, inverseScaleY); - Vector<Vertex> tempVertices; + SkTArray<Vertex, true> tempVertices; float threshInvScaleX = inverseScaleX; float threshInvScaleY = inverseScaleY; if (style == SkPaint::kStroke_Style) { @@ -526,17 +547,17 @@ void PathRenderer::convexPathVertices(const SkPath &path, const SkPaint* paint, // force close if we're filling the path, since fill path expects closed perimeter. bool forceClose = style != SkPaint::kStroke_Style; - bool wasClosed = convexPathPerimeterVertices(path, forceClose, threshInvScaleX * threshInvScaleX, - threshInvScaleY * threshInvScaleY, tempVertices); + bool wasClosed = ConvexPathPerimeterVertices(path, forceClose, threshInvScaleX * threshInvScaleX, + threshInvScaleY * threshInvScaleY, &tempVertices); - if (!tempVertices.size()) { + if (!tempVertices.count()) { // path was empty, return without allocating vertex buffer return; } #if VERTEX_DEBUG - for (unsigned int i = 0; i < tempVertices.size(); i++) { - ALOGD("orig path: point at %f %f", tempVertices[i].position[0], tempVertices[i].position[1]); + 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 @@ -571,16 +592,17 @@ void PathRenderer::convexPathVertices(const SkPath &path, const SkPaint* paint, } -void pushToVector(Vector<Vertex>& vertices, float x, float y) { +void pushToVector(SkTArray<Vertex, true>* vertices, float x, float y) { // TODO: make this not yuck - vertices.push(); - Vertex* newVertex = &(vertices.editArray()[vertices.size() - 1]); + 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, Vector<Vertex>& outputVertices) { - ATRACE_CALL(); +bool PathRenderer::ConvexPathPerimeterVertices(const SkPath& path, bool forceClose, + float sqrInvScaleX, float sqrInvScaleY, SkTArray<Vertex, true>* outputVertices) { + SK_TRACE_EVENT0("PathRenderer::convexPathPerimeterVertices"); + // 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. @@ -606,7 +628,7 @@ bool PathRenderer::convexPathPerimeterVertices(const SkPath& path, bool forceClo break; case SkPath::kQuad_Verb: ALOGV("kQuad_Verb"); - recursiveQuadraticBezierVertices( + RecursiveQuadraticBezierVertices( pts[0].x(), pts[0].y(), pts[2].x(), pts[2].y(), pts[1].x(), pts[1].y(), @@ -614,7 +636,7 @@ bool PathRenderer::convexPathPerimeterVertices(const SkPath& path, bool forceClo break; case SkPath::kCubic_Verb: ALOGV("kCubic_Verb"); - recursiveCubicBezierVertices( + RecursiveCubicBezierVertices( pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y(), pts[3].x(), pts[3].y(), @@ -626,19 +648,19 @@ bool PathRenderer::convexPathPerimeterVertices(const SkPath& path, bool forceClo } } - int size = outputVertices.size(); - if (size >= 2 && outputVertices[0].position[0] == outputVertices[size - 1].position[0] && - outputVertices[0].position[1] == outputVertices[size - 1].position[1]) { - outputVertices.pop(); + 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( +void PathRenderer::RecursiveCubicBezierVertices( float p1x, float p1y, float c1x, float c1y, float p2x, float p2y, float c2x, float c2y, - float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) { + float sqrInvScaleX, float sqrInvScaleY, SkTArray<Vertex, true>* outputVertices) { float dx = p2x - p1x; float dy = p2y - p1y; float d1 = fabs((c1x - p2x) * dy - (c1y - p2y) * dx); @@ -668,22 +690,22 @@ void PathRenderer::recursiveCubicBezierVertices( float mx = (p1c1c2x + p2c1c2x) * 0.5f; float my = (p1c1c2y + p2c1c2y) * 0.5f; - recursiveCubicBezierVertices( + RecursiveCubicBezierVertices( p1x, p1y, p1c1x, p1c1y, mx, my, p1c1c2x, p1c1c2y, sqrInvScaleX, sqrInvScaleY, outputVertices); - recursiveCubicBezierVertices( + RecursiveCubicBezierVertices( mx, my, p2c1c2x, p2c1c2y, p2x, p2y, p2c2x, p2c2y, sqrInvScaleX, sqrInvScaleY, outputVertices); } } -void PathRenderer::recursiveQuadraticBezierVertices( +void PathRenderer::RecursiveQuadraticBezierVertices( float ax, float ay, float bx, float by, float cx, float cy, - float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) { + float sqrInvScaleX, float sqrInvScaleY, SkTArray<Vertex, true>* outputVertices) { float dx = bx - ax; float dy = by - ay; float d = (cx - bx) * dy - (cy - by) * dx; @@ -701,9 +723,9 @@ void PathRenderer::recursiveQuadraticBezierVertices( float mx = (acx + bcx) * 0.5f; float my = (acy + bcy) * 0.5f; - recursiveQuadraticBezierVertices(ax, ay, mx, my, acx, acy, + RecursiveQuadraticBezierVertices(ax, ay, mx, my, acx, acy, sqrInvScaleX, sqrInvScaleY, outputVertices); - recursiveQuadraticBezierVertices(mx, my, bx, by, bcx, bcy, + RecursiveQuadraticBezierVertices(mx, my, bx, by, bcx, bcy, sqrInvScaleX, sqrInvScaleY, outputVertices); } } diff --git a/experimental/AndroidPathRenderer/AndroidPathRenderer.h b/experimental/AndroidPathRenderer/AndroidPathRenderer.h index a17ce9b6e3..64aebfa59e 100644 --- a/experimental/AndroidPathRenderer/AndroidPathRenderer.h +++ b/experimental/AndroidPathRenderer/AndroidPathRenderer.h @@ -8,16 +8,15 @@ #ifndef ANDROID_HWUI_PATH_RENDERER_H #define ANDROID_HWUI_PATH_RENDERER_H -#include <utils/Vector.h> +#include <SkTArray.h> #include "Vertex.h" +class SkMatrix; + namespace android { namespace uirenderer { -class Matrix4; -typedef Matrix4 mat4; - class VertexBuffer { public: VertexBuffer(): @@ -56,37 +55,37 @@ private: class PathRenderer { public: - static SkRect computePathBounds(const SkPath& path, const SkPaint* paint); + static SkRect ComputePathBounds(const SkPath& path, const SkPaint* paint); - static void convexPathVertices(const SkPath& path, const SkPaint* paint, - const mat4 *transform, VertexBuffer& vertexBuffer); + static void ConvexPathVertices(const SkPath& path, const SkPaint* paint, + const SkMatrix* transform, VertexBuffer* vertexBuffer); private: - static bool convexPathPerimeterVertices(const SkPath &path, bool forceClose, - float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex> &outputVertices); + static bool ConvexPathPerimeterVertices(const SkPath &path, bool forceClose, + float sqrInvScaleX, float sqrInvScaleY, SkTArray<Vertex, true>* outputVertices); /* endpoints a & b, control c */ - static void recursiveQuadraticBezierVertices( + static void RecursiveQuadraticBezierVertices( float ax, float ay, float bx, float by, float cx, float cy, float sqrInvScaleX, float sqrInvScaleY, - Vector<Vertex> &outputVertices); + SkTArray<Vertex, true>* outputVertices); /* endpoints p1, p2 control c1, c2 */ - static void recursiveCubicBezierVertices( + static void RecursiveCubicBezierVertices( float p1x, float p1y, float c1x, float c1y, float p2x, float p2y, float c2x, float c2y, float sqrInvScaleX, float sqrInvScaleY, - Vector<Vertex> &outputVertices); + SkTArray<Vertex, true>* outputVertices); }; }; // namespace uirenderer diff --git a/gyp/experimental.gyp b/gyp/experimental.gyp index 09711ac400..09d5944b52 100644 --- a/gyp/experimental.gyp +++ b/gyp/experimental.gyp @@ -6,11 +6,13 @@ 'include_dirs': [ '../include/config', '../include/core', + '../experimental/AndroidPathRenderer', ], 'sources': [ '../experimental/SkSetPoly3To3.cpp', '../experimental/SkSetPoly3To3_A.cpp', '../experimental/SkSetPoly3To3_D.cpp', + '../experimental/AndroidPathRenderer/AndroidPathRenderer.cpp', ], 'direct_dependent_settings': { 'include_dirs': [ |