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