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 "Matrix.h"
     21 #include "Rect.h"
     22 #include "Vertex.h"
     23 #include "VertexBuffer.h"
     24 
     25 #include <algorithm>
     26 #include <vector>
     27 
     28 class SkPath;
     29 class SkPaint;
     30 
     31 namespace android {
     32 namespace uirenderer {
     33 
     34 /**
     35  * Structure used for threshold values in outline path tessellation.
     36  *
     37  * TODO: PaintInfo should store one of this object, and initialized all values in constructor
     38  * depending on its type (point, line or path).
     39  */
     40 struct PathApproximationInfo {
     41     PathApproximationInfo(float invScaleX, float invScaleY, float pixelThreshold)
     42             : thresholdSquared(pixelThreshold * pixelThreshold)
     43             , sqrInvScaleX(invScaleX * invScaleX)
     44             , sqrInvScaleY(invScaleY * invScaleY)
     45             , thresholdForConicQuads(pixelThreshold * std::min(invScaleX, invScaleY) / 2.0f){};
     46 
     47     const float thresholdSquared;
     48     const float sqrInvScaleX;
     49     const float sqrInvScaleY;
     50     const float thresholdForConicQuads;
     51 };
     52 
     53 class PathTessellator {
     54 public:
     55     /**
     56      * Populates scaleX and scaleY with the 'tessellation scale' of the transform - the effective X
     57      * and Y scales that tessellation will take into account when generating the 1.0 pixel thick
     58      * ramp.
     59      *
     60      * Two instances of the same shape (size, paint, etc.) will only generate the same vertices if
     61      * their tessellation scales are equal.
     62      */
     63     static void extractTessellationScales(const Matrix4& transform, float* scaleX, float* scaleY);
     64 
     65     /**
     66      * Populates a VertexBuffer with a tessellated approximation of the input convex path, as a
     67      * single
     68      * triangle strip. Note: joins are not currently supported.
     69      *
     70      * @param path The path to be approximated
     71      * @param paint The paint the path will be drawn with, indicating AA, painting style
     72      *        (stroke vs fill), stroke width, stroke cap & join style, etc.
     73      * @param transform The transform the path is to be drawn with, used to drive stretch-aware path
     74      *        vertex approximation, and correct AA ramp offsetting.
     75      * @param vertexBuffer The output buffer
     76      */
     77     static void tessellatePath(const SkPath& path, const SkPaint* paint, const mat4& transform,
     78                                VertexBuffer& vertexBuffer);
     79 
     80     /**
     81      * Populates a VertexBuffer with a tessellated approximation of points as a single triangle
     82      * strip (with degenerate tris separating), respecting the shape defined by the paint cap.
     83      *
     84      * @param points The center vertices of the points to be drawn
     85      * @param count The number of floats making up the point vertices
     86      * @param paint The paint the points will be drawn with indicating AA, stroke width & cap
     87      * @param transform The transform the points will be drawn with, used to drive stretch-aware
     88      * path
     89      *        vertex approximation, and correct AA ramp offsetting
     90      * @param vertexBuffer The output buffer
     91      */
     92     static void tessellatePoints(const float* points, int count, const SkPaint* paint,
     93                                  const mat4& transform, VertexBuffer& vertexBuffer);
     94 
     95     /**
     96      * Populates a VertexBuffer with a tessellated approximation of lines as a single triangle
     97      * strip (with degenerate tris separating).
     98      *
     99      * @param points Pairs of endpoints defining the lines to be drawn
    100      * @param count The number of floats making up the line vertices
    101      * @param paint The paint the lines will be drawn with indicating AA, stroke width & cap
    102      * @param transform The transform the points will be drawn with, used to drive stretch-aware
    103      * path
    104      *        vertex approximation, and correct AA ramp offsetting
    105      * @param vertexBuffer The output buffer
    106      */
    107     static void tessellateLines(const float* points, int count, const SkPaint* paint,
    108                                 const mat4& transform, VertexBuffer& vertexBuffer);
    109 
    110     /**
    111      * Approximates a convex outline into a clockwise Vector of 2d vertices.
    112      *
    113      * @param path The outline to be approximated
    114      * @param threshold The threshold of acceptable error (in pixels) when approximating
    115      * @param outputVertices An empty Vector which will be populated with the output
    116      */
    117     static bool approximatePathOutlineVertices(const SkPath& path, float threshold,
    118                                                std::vector<Vertex>& outputVertices);
    119 
    120 private:
    121     static bool approximatePathOutlineVertices(const SkPath& path, bool forceClose,
    122                                                const PathApproximationInfo& approximationInfo,
    123                                                std::vector<Vertex>& outputVertices);
    124 
    125     /*
    126       endpoints a & b,
    127       control c
    128      */
    129     static void recursiveQuadraticBezierVertices(float ax, float ay, float bx, float by, float cx,
    130                                                  float cy,
    131                                                  const PathApproximationInfo& approximationInfo,
    132                                                  std::vector<Vertex>& outputVertices,
    133                                                  int depth = 0);
    134 
    135     /*
    136       endpoints p1, p2
    137       control c1, c2
    138      */
    139     static void recursiveCubicBezierVertices(float p1x, float p1y, float c1x, float c1y, float p2x,
    140                                              float p2y, float c2x, float c2y,
    141                                              const PathApproximationInfo& approximationInfo,
    142                                              std::vector<Vertex>& outputVertices, int depth = 0);
    143 };
    144 
    145 };  // namespace uirenderer
    146 };  // namespace android
    147 
    148 #endif  // ANDROID_HWUI_PATH_TESSELLATOR_H
    149