blob: 85797fcf8538aa3358c1ff76bb6711a9c53ef3e6 [file] [log] [blame]
Chris Craik65cd6122012-12-10 17:56:27 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_HWUI_PATH_TESSELLATOR_H
18#define ANDROID_HWUI_PATH_TESSELLATOR_H
19
20#include <utils/Vector.h>
21
22#include "Matrix.h"
23#include "Rect.h"
24#include "Vertex.h"
25
26namespace android {
27namespace uirenderer {
28
29class VertexBuffer {
30public:
31 VertexBuffer():
32 mBuffer(0),
Chris Craik6d29c8d2013-05-08 18:35:44 -070033 mVertexCount(0),
Chris Craik65cd6122012-12-10 17:56:27 -080034 mCleanupMethod(NULL)
35 {}
36
37 ~VertexBuffer() {
38 if (mCleanupMethod) mCleanupMethod(mBuffer);
39 }
40
41 /**
42 This should be the only method used by the PathTessellator. Subsequent calls to alloc will
43 allocate space within the first allocation (useful if you want to eventually allocate
44 multiple regions within a single VertexBuffer, such as with PathTessellator::tesselateLines()
45 */
46 template <class TYPE>
Chris Craik6d29c8d2013-05-08 18:35:44 -070047 TYPE* alloc(int vertexCount) {
48 if (mVertexCount) {
Chris Craik65cd6122012-12-10 17:56:27 -080049 TYPE* reallocBuffer = (TYPE*)mReallocBuffer;
50 // already have allocated the buffer, re-allocate space within
51 if (mReallocBuffer != mBuffer) {
52 // not first re-allocation, leave space for degenerate triangles to separate strips
53 reallocBuffer += 2;
54 }
Chris Craik6d29c8d2013-05-08 18:35:44 -070055 mReallocBuffer = reallocBuffer + vertexCount;
Chris Craik65cd6122012-12-10 17:56:27 -080056 return reallocBuffer;
57 }
Chris Craik6d29c8d2013-05-08 18:35:44 -070058 mVertexCount = vertexCount;
59 mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount];
Chris Craik65cd6122012-12-10 17:56:27 -080060 mCleanupMethod = &(cleanup<TYPE>);
61
62 return (TYPE*)mBuffer;
63 }
64
Chris Craik6d29c8d2013-05-08 18:35:44 -070065 template <class TYPE>
66 void copyInto(const VertexBuffer& srcBuffer, float xOffset, float yOffset) {
67 int verticesToCopy = srcBuffer.getVertexCount();
68
69 TYPE* dst = alloc<TYPE>(verticesToCopy);
70 TYPE* src = (TYPE*)srcBuffer.getBuffer();
71
72 for (int i = 0; i < verticesToCopy; i++) {
73 TYPE::copyWithOffset(&dst[i], src[i], xOffset, yOffset);
74 }
75 }
76
77 void* getBuffer() const { return mBuffer; } // shouldn't be const, since not a const ptr?
78 unsigned int getVertexCount() const { return mVertexCount; }
Chris Craik65cd6122012-12-10 17:56:27 -080079
80 template <class TYPE>
81 void createDegenerateSeparators(int allocSize) {
Chris Craik6d29c8d2013-05-08 18:35:44 -070082 TYPE* end = (TYPE*)mBuffer + mVertexCount;
Chris Craik65cd6122012-12-10 17:56:27 -080083 for (TYPE* degen = (TYPE*)mBuffer + allocSize; degen < end; degen += 2 + allocSize) {
84 memcpy(degen, degen - 1, sizeof(TYPE));
85 memcpy(degen + 1, degen + 2, sizeof(TYPE));
86 }
87 }
88
89private:
90 template <class TYPE>
91 static void cleanup(void* buffer) {
92 delete[] (TYPE*)buffer;
93 }
94
95 void* mBuffer;
Chris Craik6d29c8d2013-05-08 18:35:44 -070096 unsigned int mVertexCount;
Chris Craik65cd6122012-12-10 17:56:27 -080097
98 void* mReallocBuffer; // used for multi-allocation
99
100 void (*mCleanupMethod)(void*);
101};
102
103class PathTessellator {
104public:
105 static void expandBoundsForStroke(SkRect& bounds, const SkPaint* paint, bool forceExpand);
106
107 static void tessellatePath(const SkPath& path, const SkPaint* paint,
108 const mat4 *transform, VertexBuffer& vertexBuffer);
109
Chris Craik6d29c8d2013-05-08 18:35:44 -0700110 static void tessellatePoints(const float* points, int count, SkPaint* paint,
111 const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
112
Chris Craik65cd6122012-12-10 17:56:27 -0800113 static void tessellateLines(const float* points, int count, SkPaint* paint,
114 const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
115
116private:
117 static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose,
118 float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex> &outputVertices);
119
120/*
121 endpoints a & b,
122 control c
123 */
124 static void recursiveQuadraticBezierVertices(
125 float ax, float ay,
126 float bx, float by,
127 float cx, float cy,
128 float sqrInvScaleX, float sqrInvScaleY,
129 Vector<Vertex> &outputVertices);
130
131/*
132 endpoints p1, p2
133 control c1, c2
134 */
135 static void recursiveCubicBezierVertices(
136 float p1x, float p1y,
137 float c1x, float c1y,
138 float p2x, float p2y,
139 float c2x, float c2y,
140 float sqrInvScaleX, float sqrInvScaleY,
141 Vector<Vertex> &outputVertices);
142};
143
144}; // namespace uirenderer
145}; // namespace android
146
147#endif // ANDROID_HWUI_PATH_TESSELLATOR_H