/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_HWUI_PATH_TESSELLATOR_H #define ANDROID_HWUI_PATH_TESSELLATOR_H #include "Matrix.h" #include "Rect.h" #include "Vertex.h" #include "VertexBuffer.h" #include <algorithm> #include <vector> class SkPath; class SkPaint; namespace android { namespace uirenderer { /** * Structure used for threshold values in outline path tessellation. * * TODO: PaintInfo should store one of this object, and initialized all values in constructor * depending on its type (point, line or path). */ struct PathApproximationInfo { PathApproximationInfo(float invScaleX, float invScaleY, float pixelThreshold) : thresholdSquared(pixelThreshold * pixelThreshold) , sqrInvScaleX(invScaleX * invScaleX) , sqrInvScaleY(invScaleY * invScaleY) , thresholdForConicQuads(pixelThreshold * std::min(invScaleX, invScaleY) / 2.0f) { }; const float thresholdSquared; const float sqrInvScaleX; const float sqrInvScaleY; const float thresholdForConicQuads; }; class PathTessellator { public: /** * Populates scaleX and scaleY with the 'tessellation scale' of the transform - the effective X * and Y scales that tessellation will take into account when generating the 1.0 pixel thick * ramp. * * Two instances of the same shape (size, paint, etc.) will only generate the same vertices if * their tessellation scales are equal. */ static void extractTessellationScales(const Matrix4& transform, float* scaleX, float* scaleY); /** * Populates a VertexBuffer with a tessellated approximation of the input convex path, as a single * triangle strip. Note: joins are not currently supported. * * @param path The path to be approximated * @param paint The paint the path will be drawn with, indicating AA, painting style * (stroke vs fill), stroke width, stroke cap & join style, etc. * @param transform The transform the path is to be drawn with, used to drive stretch-aware path * vertex approximation, and correct AA ramp offsetting. * @param vertexBuffer The output buffer */ static void tessellatePath(const SkPath& path, const SkPaint* paint, const mat4& transform, VertexBuffer& vertexBuffer); /** * Populates a VertexBuffer with a tessellated approximation of points as a single triangle * strip (with degenerate tris separating), respecting the shape defined by the paint cap. * * @param points The center vertices of the points to be drawn * @param count The number of floats making up the point vertices * @param paint The paint the points will be drawn with indicating AA, stroke width & cap * @param transform The transform the points will be drawn with, used to drive stretch-aware path * vertex approximation, and correct AA ramp offsetting * @param vertexBuffer The output buffer */ static void tessellatePoints(const float* points, int count, const SkPaint* paint, const mat4& transform, VertexBuffer& vertexBuffer); /** * Populates a VertexBuffer with a tessellated approximation of lines as a single triangle * strip (with degenerate tris separating). * * @param points Pairs of endpoints defining the lines to be drawn * @param count The number of floats making up the line vertices * @param paint The paint the lines will be drawn with indicating AA, stroke width & cap * @param transform The transform the points will be drawn with, used to drive stretch-aware path * vertex approximation, and correct AA ramp offsetting * @param vertexBuffer The output buffer */ static void tessellateLines(const float* points, int count, const SkPaint* paint, const mat4& transform, VertexBuffer& vertexBuffer); /** * Approximates a convex outline into a clockwise Vector of 2d vertices. * * @param path The outline to be approximated * @param threshold The threshold of acceptable error (in pixels) when approximating * @param outputVertices An empty Vector which will be populated with the output */ static bool approximatePathOutlineVertices(const SkPath &path, float threshold, std::vector<Vertex> &outputVertices); private: static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose, const PathApproximationInfo& approximationInfo, std::vector<Vertex> &outputVertices); /* endpoints a & b, control c */ static void recursiveQuadraticBezierVertices( float ax, float ay, float bx, float by, float cx, float cy, const PathApproximationInfo& approximationInfo, std::vector<Vertex> &outputVertices, int depth = 0); /* endpoints p1, p2 control c1, c2 */ static void recursiveCubicBezierVertices( float p1x, float p1y, float c1x, float c1y, float p2x, float p2y, float c2x, float c2y, const PathApproximationInfo& approximationInfo, std::vector<Vertex> &outputVertices, int depth = 0); }; }; // namespace uirenderer }; // namespace android #endif // ANDROID_HWUI_PATH_TESSELLATOR_H