165cd612face362d054a85d0f7e5881c59cd523beChris Craik/*
265cd612face362d054a85d0f7e5881c59cd523beChris Craik * Copyright (C) 2012 The Android Open Source Project
365cd612face362d054a85d0f7e5881c59cd523beChris Craik *
465cd612face362d054a85d0f7e5881c59cd523beChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
565cd612face362d054a85d0f7e5881c59cd523beChris Craik * you may not use this file except in compliance with the License.
665cd612face362d054a85d0f7e5881c59cd523beChris Craik * You may obtain a copy of the License at
765cd612face362d054a85d0f7e5881c59cd523beChris Craik *
865cd612face362d054a85d0f7e5881c59cd523beChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
965cd612face362d054a85d0f7e5881c59cd523beChris Craik *
1065cd612face362d054a85d0f7e5881c59cd523beChris Craik * Unless required by applicable law or agreed to in writing, software
1165cd612face362d054a85d0f7e5881c59cd523beChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
1265cd612face362d054a85d0f7e5881c59cd523beChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365cd612face362d054a85d0f7e5881c59cd523beChris Craik * See the License for the specific language governing permissions and
1465cd612face362d054a85d0f7e5881c59cd523beChris Craik * limitations under the License.
1565cd612face362d054a85d0f7e5881c59cd523beChris Craik */
1665cd612face362d054a85d0f7e5881c59cd523beChris Craik
1765cd612face362d054a85d0f7e5881c59cd523beChris Craik#ifndef ANDROID_HWUI_PATH_TESSELLATOR_H
1865cd612face362d054a85d0f7e5881c59cd523beChris Craik#define ANDROID_HWUI_PATH_TESSELLATOR_H
1965cd612face362d054a85d0f7e5881c59cd523beChris Craik
2065cd612face362d054a85d0f7e5881c59cd523beChris Craik#include <utils/Vector.h>
2165cd612face362d054a85d0f7e5881c59cd523beChris Craik
2265cd612face362d054a85d0f7e5881c59cd523beChris Craik#include "Matrix.h"
2365cd612face362d054a85d0f7e5881c59cd523beChris Craik#include "Rect.h"
2465cd612face362d054a85d0f7e5881c59cd523beChris Craik#include "Vertex.h"
2565cd612face362d054a85d0f7e5881c59cd523beChris Craik
2665cd612face362d054a85d0f7e5881c59cd523beChris Craiknamespace android {
2765cd612face362d054a85d0f7e5881c59cd523beChris Craiknamespace uirenderer {
2865cd612face362d054a85d0f7e5881c59cd523beChris Craik
2965cd612face362d054a85d0f7e5881c59cd523beChris Craikclass VertexBuffer {
3065cd612face362d054a85d0f7e5881c59cd523beChris Craikpublic:
3165cd612face362d054a85d0f7e5881c59cd523beChris Craik    VertexBuffer():
3265cd612face362d054a85d0f7e5881c59cd523beChris Craik        mBuffer(0),
336d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        mVertexCount(0),
3465cd612face362d054a85d0f7e5881c59cd523beChris Craik        mCleanupMethod(NULL)
3565cd612face362d054a85d0f7e5881c59cd523beChris Craik    {}
3665cd612face362d054a85d0f7e5881c59cd523beChris Craik
3765cd612face362d054a85d0f7e5881c59cd523beChris Craik    ~VertexBuffer() {
3865cd612face362d054a85d0f7e5881c59cd523beChris Craik        if (mCleanupMethod) mCleanupMethod(mBuffer);
3965cd612face362d054a85d0f7e5881c59cd523beChris Craik    }
4065cd612face362d054a85d0f7e5881c59cd523beChris Craik
4165cd612face362d054a85d0f7e5881c59cd523beChris Craik    /**
4265cd612face362d054a85d0f7e5881c59cd523beChris Craik       This should be the only method used by the PathTessellator. Subsequent calls to alloc will
4365cd612face362d054a85d0f7e5881c59cd523beChris Craik       allocate space within the first allocation (useful if you want to eventually allocate
4465cd612face362d054a85d0f7e5881c59cd523beChris Craik       multiple regions within a single VertexBuffer, such as with PathTessellator::tesselateLines()
4565cd612face362d054a85d0f7e5881c59cd523beChris Craik     */
4665cd612face362d054a85d0f7e5881c59cd523beChris Craik    template <class TYPE>
476d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik    TYPE* alloc(int vertexCount) {
486d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        if (mVertexCount) {
4965cd612face362d054a85d0f7e5881c59cd523beChris Craik            TYPE* reallocBuffer = (TYPE*)mReallocBuffer;
5065cd612face362d054a85d0f7e5881c59cd523beChris Craik            // already have allocated the buffer, re-allocate space within
5165cd612face362d054a85d0f7e5881c59cd523beChris Craik            if (mReallocBuffer != mBuffer) {
5265cd612face362d054a85d0f7e5881c59cd523beChris Craik                // not first re-allocation, leave space for degenerate triangles to separate strips
5365cd612face362d054a85d0f7e5881c59cd523beChris Craik                reallocBuffer += 2;
5465cd612face362d054a85d0f7e5881c59cd523beChris Craik            }
556d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik            mReallocBuffer = reallocBuffer + vertexCount;
5665cd612face362d054a85d0f7e5881c59cd523beChris Craik            return reallocBuffer;
5765cd612face362d054a85d0f7e5881c59cd523beChris Craik        }
586d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        mVertexCount = vertexCount;
596d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount];
6065cd612face362d054a85d0f7e5881c59cd523beChris Craik        mCleanupMethod = &(cleanup<TYPE>);
6165cd612face362d054a85d0f7e5881c59cd523beChris Craik
6265cd612face362d054a85d0f7e5881c59cd523beChris Craik        return (TYPE*)mBuffer;
6365cd612face362d054a85d0f7e5881c59cd523beChris Craik    }
6465cd612face362d054a85d0f7e5881c59cd523beChris Craik
656d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik    template <class TYPE>
666d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik    void copyInto(const VertexBuffer& srcBuffer, float xOffset, float yOffset) {
676d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        int verticesToCopy = srcBuffer.getVertexCount();
686d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik
696d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        TYPE* dst = alloc<TYPE>(verticesToCopy);
706d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        TYPE* src = (TYPE*)srcBuffer.getBuffer();
716d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik
726d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        for (int i = 0; i < verticesToCopy; i++) {
736d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik            TYPE::copyWithOffset(&dst[i], src[i], xOffset, yOffset);
746d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        }
756d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik    }
766d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik
776d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik    void* getBuffer() const { return mBuffer; } // shouldn't be const, since not a const ptr?
786d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik    unsigned int getVertexCount() const { return mVertexCount; }
7965cd612face362d054a85d0f7e5881c59cd523beChris Craik
8065cd612face362d054a85d0f7e5881c59cd523beChris Craik    template <class TYPE>
8165cd612face362d054a85d0f7e5881c59cd523beChris Craik    void createDegenerateSeparators(int allocSize) {
826d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik        TYPE* end = (TYPE*)mBuffer + mVertexCount;
8365cd612face362d054a85d0f7e5881c59cd523beChris Craik        for (TYPE* degen = (TYPE*)mBuffer + allocSize; degen < end; degen += 2 + allocSize) {
8465cd612face362d054a85d0f7e5881c59cd523beChris Craik            memcpy(degen, degen - 1, sizeof(TYPE));
8565cd612face362d054a85d0f7e5881c59cd523beChris Craik            memcpy(degen + 1, degen + 2, sizeof(TYPE));
8665cd612face362d054a85d0f7e5881c59cd523beChris Craik        }
8765cd612face362d054a85d0f7e5881c59cd523beChris Craik    }
8865cd612face362d054a85d0f7e5881c59cd523beChris Craik
8965cd612face362d054a85d0f7e5881c59cd523beChris Craikprivate:
9065cd612face362d054a85d0f7e5881c59cd523beChris Craik    template <class TYPE>
9165cd612face362d054a85d0f7e5881c59cd523beChris Craik    static void cleanup(void* buffer) {
9265cd612face362d054a85d0f7e5881c59cd523beChris Craik        delete[] (TYPE*)buffer;
9365cd612face362d054a85d0f7e5881c59cd523beChris Craik    }
9465cd612face362d054a85d0f7e5881c59cd523beChris Craik
9565cd612face362d054a85d0f7e5881c59cd523beChris Craik    void* mBuffer;
966d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik    unsigned int mVertexCount;
9765cd612face362d054a85d0f7e5881c59cd523beChris Craik
9865cd612face362d054a85d0f7e5881c59cd523beChris Craik    void* mReallocBuffer; // used for multi-allocation
9965cd612face362d054a85d0f7e5881c59cd523beChris Craik
10065cd612face362d054a85d0f7e5881c59cd523beChris Craik    void (*mCleanupMethod)(void*);
10165cd612face362d054a85d0f7e5881c59cd523beChris Craik};
10265cd612face362d054a85d0f7e5881c59cd523beChris Craik
10365cd612face362d054a85d0f7e5881c59cd523beChris Craikclass PathTessellator {
10465cd612face362d054a85d0f7e5881c59cd523beChris Craikpublic:
10565cd612face362d054a85d0f7e5881c59cd523beChris Craik    static void expandBoundsForStroke(SkRect& bounds, const SkPaint* paint, bool forceExpand);
10665cd612face362d054a85d0f7e5881c59cd523beChris Craik
10765cd612face362d054a85d0f7e5881c59cd523beChris Craik    static void tessellatePath(const SkPath& path, const SkPaint* paint,
10865cd612face362d054a85d0f7e5881c59cd523beChris Craik            const mat4 *transform, VertexBuffer& vertexBuffer);
10965cd612face362d054a85d0f7e5881c59cd523beChris Craik
1106d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik    static void tessellatePoints(const float* points, int count, SkPaint* paint,
1116d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik            const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
1126d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik
11365cd612face362d054a85d0f7e5881c59cd523beChris Craik    static void tessellateLines(const float* points, int count, SkPaint* paint,
11465cd612face362d054a85d0f7e5881c59cd523beChris Craik            const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
11565cd612face362d054a85d0f7e5881c59cd523beChris Craik
11665cd612face362d054a85d0f7e5881c59cd523beChris Craikprivate:
11765cd612face362d054a85d0f7e5881c59cd523beChris Craik    static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose,
11865cd612face362d054a85d0f7e5881c59cd523beChris Craik        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex> &outputVertices);
11965cd612face362d054a85d0f7e5881c59cd523beChris Craik
12065cd612face362d054a85d0f7e5881c59cd523beChris Craik/*
12165cd612face362d054a85d0f7e5881c59cd523beChris Craik  endpoints a & b,
12265cd612face362d054a85d0f7e5881c59cd523beChris Craik  control c
12365cd612face362d054a85d0f7e5881c59cd523beChris Craik */
12465cd612face362d054a85d0f7e5881c59cd523beChris Craik    static void recursiveQuadraticBezierVertices(
12565cd612face362d054a85d0f7e5881c59cd523beChris Craik            float ax, float ay,
12665cd612face362d054a85d0f7e5881c59cd523beChris Craik            float bx, float by,
12765cd612face362d054a85d0f7e5881c59cd523beChris Craik            float cx, float cy,
12865cd612face362d054a85d0f7e5881c59cd523beChris Craik            float sqrInvScaleX, float sqrInvScaleY,
12965cd612face362d054a85d0f7e5881c59cd523beChris Craik            Vector<Vertex> &outputVertices);
13065cd612face362d054a85d0f7e5881c59cd523beChris Craik
13165cd612face362d054a85d0f7e5881c59cd523beChris Craik/*
13265cd612face362d054a85d0f7e5881c59cd523beChris Craik  endpoints p1, p2
13365cd612face362d054a85d0f7e5881c59cd523beChris Craik  control c1, c2
13465cd612face362d054a85d0f7e5881c59cd523beChris Craik */
13565cd612face362d054a85d0f7e5881c59cd523beChris Craik    static void recursiveCubicBezierVertices(
13665cd612face362d054a85d0f7e5881c59cd523beChris Craik            float p1x, float p1y,
13765cd612face362d054a85d0f7e5881c59cd523beChris Craik            float c1x, float c1y,
13865cd612face362d054a85d0f7e5881c59cd523beChris Craik            float p2x, float p2y,
13965cd612face362d054a85d0f7e5881c59cd523beChris Craik            float c2x, float c2y,
14065cd612face362d054a85d0f7e5881c59cd523beChris Craik            float sqrInvScaleX, float sqrInvScaleY,
14165cd612face362d054a85d0f7e5881c59cd523beChris Craik            Vector<Vertex> &outputVertices);
14265cd612face362d054a85d0f7e5881c59cd523beChris Craik};
14365cd612face362d054a85d0f7e5881c59cd523beChris Craik
14465cd612face362d054a85d0f7e5881c59cd523beChris Craik}; // namespace uirenderer
14565cd612face362d054a85d0f7e5881c59cd523beChris Craik}; // namespace android
14665cd612face362d054a85d0f7e5881c59cd523beChris Craik
14765cd612face362d054a85d0f7e5881c59cd523beChris Craik#endif // ANDROID_HWUI_PATH_TESSELLATOR_H
148