Home | History | Annotate | Download | only in hwui
      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 
     26 namespace android {
     27 namespace uirenderer {
     28 
     29 class VertexBuffer {
     30 public:
     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 
     89 private:
     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 
    103 class PathTessellator {
    104 public:
    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 
    116 private:
    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