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