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 
     48     const float thresholdSquared;
     49     const float sqrInvScaleX;
     50     const float sqrInvScaleY;
     51     const float thresholdForConicQuads;
     52 };
     53 
     54 class PathTessellator {
     55 public:
     56     /**
     57      * Populates scaleX and scaleY with the 'tessellation scale' of the transform - the effective X
     58      * and Y scales that tessellation will take into account when generating the 1.0 pixel thick
     59      * ramp.
     60      *
     61      * Two instances of the same shape (size, paint, etc.) will only generate the same vertices if
     62      * their tessellation scales are equal.
     63      */
     64     static void extractTessellationScales(const Matrix4& transform, float* scaleX, float* scaleY);
     65 
     66     /**
     67      * Populates a VertexBuffer with a tessellated approximation of the input convex path, as a 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,
     78             const mat4& transform, 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 path
     88      *        vertex approximation, and correct AA ramp offsetting
     89      * @param vertexBuffer The output buffer
     90      */
     91     static void tessellatePoints(const float* points, int count, const SkPaint* paint,
     92             const mat4& transform, VertexBuffer& vertexBuffer);
     93 
     94     /**
     95      * Populates a VertexBuffer with a tessellated approximation of lines as a single triangle
     96      * strip (with degenerate tris separating).
     97      *
     98      * @param points Pairs of endpoints defining the lines to be drawn
     99      * @param count The number of floats making up the line vertices
    100      * @param paint The paint the lines will be drawn with indicating AA, stroke width & cap
    101      * @param transform The transform the points will be drawn with, used to drive stretch-aware path
    102      *        vertex approximation, and correct AA ramp offsetting
    103      * @param vertexBuffer The output buffer
    104      */
    105     static void tessellateLines(const float* points, int count, const SkPaint* paint,
    106             const mat4& transform, VertexBuffer& vertexBuffer);
    107 
    108     /**
    109      * Approximates a convex outline into a clockwise Vector of 2d vertices.
    110      *
    111      * @param path The outline to be approximated
    112      * @param threshold The threshold of acceptable error (in pixels) when approximating
    113      * @param outputVertices An empty Vector which will be populated with the output
    114      */
    115     static bool approximatePathOutlineVertices(const SkPath &path, float threshold,
    116             std::vector<Vertex> &outputVertices);
    117 
    118 private:
    119     static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose,
    120             const PathApproximationInfo& approximationInfo, std::vector<Vertex> &outputVertices);
    121 
    122 /*
    123   endpoints a & b,
    124   control c
    125  */
    126     static void recursiveQuadraticBezierVertices(
    127             float ax, float ay,
    128             float bx, float by,
    129             float cx, float cy,
    130             const PathApproximationInfo& approximationInfo,
    131             std::vector<Vertex> &outputVertices, int depth = 0);
    132 
    133 /*
    134   endpoints p1, p2
    135   control c1, c2
    136  */
    137     static void recursiveCubicBezierVertices(
    138             float p1x, float p1y,
    139             float c1x, float c1y,
    140             float p2x, float p2y,
    141             float c2x, float c2y,
    142             const PathApproximationInfo& approximationInfo,
    143             std::vector<Vertex> &outputVertices, int depth = 0);
    144 };
    145 
    146 }; // namespace uirenderer
    147 }; // namespace android
    148 
    149 #endif // ANDROID_HWUI_PATH_TESSELLATOR_H
    150