1/*
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),
33        mVertexCount(0),
34        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>
47    TYPE* alloc(int vertexCount) {
48        if (mVertexCount) {
49            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            }
55            mReallocBuffer = reallocBuffer + vertexCount;
56            return reallocBuffer;
57        }
58        mVertexCount = vertexCount;
59        mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount];
60        mCleanupMethod = &(cleanup<TYPE>);
61
62        return (TYPE*)mBuffer;
63    }
64
65    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; }
79
80    template <class TYPE>
81    void createDegenerateSeparators(int allocSize) {
82        TYPE* end = (TYPE*)mBuffer + mVertexCount;
83        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;
96    unsigned int mVertexCount;
97
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
110    static void tessellatePoints(const float* points, int count, SkPaint* paint,
111            const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
112
113    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
148