180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc. 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef GrPathUtils_DEFINED 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GrPathUtils_DEFINED 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "GrPoint.h" 1258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkRect.h" 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPath.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTArray.h" 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerclass SkMatrix; 17363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Utilities for evaluating paths. 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace GrPathUtils { 22363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar scaleToleranceToSrc(SkScalar devTol, 23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const SkMatrix& viewM, 2458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const SkRect& pathBounds); 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /// Since we divide by tol if we're computing exact worst-case bounds, 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /// very small tolerances will be increased to gMinCurveTol. 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int worstCasePointCount(const SkPath&, 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int* subpaths, 30363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar tol); 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /// Since we divide by tol if we're computing exact worst-case bounds, 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /// very small tolerances will be increased to gMinCurveTol. 34363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger uint32_t quadraticPointCount(const GrPoint points[], SkScalar tol); 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t generateQuadraticPoints(const GrPoint& p0, 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrPoint& p1, 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrPoint& p2, 39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar tolSqd, 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPoint** points, 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t pointsLeft); 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /// Since we divide by tol if we're computing exact worst-case bounds, 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /// very small tolerances will be increased to gMinCurveTol. 45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger uint32_t cubicPointCount(const GrPoint points[], SkScalar tol); 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t generateCubicPoints(const GrPoint& p0, 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrPoint& p1, 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrPoint& p2, 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrPoint& p3, 51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar tolSqd, 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPoint** points, 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t pointsLeft); 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // A 2x3 matrix that goes from the 2d space coordinates to UV space where 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // u^2-v = 0 specifies the quad. The matrix is determined by the control 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // points of the quadratic. 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru class QuadUVMatrix { 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru public: 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru QuadUVMatrix() {}; 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Initialize the matrix from the control pts 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru QuadUVMatrix(const GrPoint controlPts[3]) { this->set(controlPts); } 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void set(const GrPoint controlPts[3]); 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Applies the matrix to vertex positions to compute UV coords. This 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * has been templated so that the compiler can easliy unroll the loop 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * and reorder to avoid stalling for loads. The assumption is that a 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * path renderer will have a small fixed number of vertices that it 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * uploads for each quad. 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * N is the number of vertices. 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * STRIDE is the size of each vertex. 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * UV_OFFSET is the offset of the UV values within each vertex. 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * vertices is a pointer to the first vertex. 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru template <int N, size_t STRIDE, size_t UV_OFFSET> 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void apply(const void* vertices) { 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru intptr_t xyPtr = reinterpret_cast<intptr_t>(vertices); 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru intptr_t uvPtr = reinterpret_cast<intptr_t>(vertices) + UV_OFFSET; 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float sx = fM[0]; 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float kx = fM[1]; 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float tx = fM[2]; 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float ky = fM[3]; 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float sy = fM[4]; 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float ty = fM[5]; 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 0; i < N; ++i) { 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const GrPoint* xy = reinterpret_cast<const GrPoint*>(xyPtr); 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GrPoint* uv = reinterpret_cast<GrPoint*>(uvPtr); 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uv->fX = sx * xy->fX + kx * xy->fY + tx; 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uv->fY = ky * xy->fX + sy * xy->fY + ty; 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru xyPtr += STRIDE; 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uvPtr += STRIDE; 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru private: 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float fM[6]; 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Converts a cubic into a sequence of quads. If working in device space 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // use tolScale = 1, otherwise set based on stretchiness of the matrix. The 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // result is sets of 3 points in quads (TODO: share endpoints in returned 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // array) 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // When we approximate a cubic {a,b,c,d} with a quadratic we may have to 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // ensure that the new control point lies between the lines ab and cd. The 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // convex path renderer requires this. It starts with a path where all the 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // control points taken together form a convex polygon. It relies on this 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // property and the quadratic approximation of cubics step cannot alter it. 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Setting constrainWithinTangents to true enforces this property. When this 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // is true the cubic must be simple and dir must specify the orientation of 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // the cubic. Otherwise, dir is ignored. 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void convertCubicToQuads(const GrPoint p[4], 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar tolScale, 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool constrainWithinTangents, 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPath::Direction dir, 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkTArray<SkPoint, true>* quads); 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 120