chromium/third_party/skia/src/gpu/tessellate/WangsFormula.h

/*
 * Copyright 2020 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef skgpu_tessellate_WangsFormula_DEFINED
#define skgpu_tessellate_WangsFormula_DEFINED

#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPoint.h"
#include "include/core/SkTypes.h"
#include "src/base/SkFloatBits.h"
#include "src/base/SkUtils.h"
#include "src/base/SkVx.h"

#include <math.h>
#include <algorithm>
#include <cstdint>
#include <limits>

#define AI

// Wang's formula gives the minimum number of evenly spaced (in the parametric sense) line segments
// that a bezier curve must be chopped into in order to guarantee all lines stay within a distance
// of "1/precision" pixels from the true curve. Its definition for a bezier curve of degree "n" is
// as follows:
//
//     maxLength = max([length(p[i+2] - 2p[i+1] + p[i]) for (0 <= i <= n-2)])
//     numParametricSegments = sqrt(maxLength * precision * n*(n - 1)/8)
//
// (Goldman, Ron. (2003). 5.6.3 Wang's Formula. "Pyramid Algorithms: A Dynamic Programming Approach
// to Curves and Surfaces for Geometric Modeling". Morgan Kaufmann Publishers.)
namespace skgpu::wangs_formula {

// Returns the value by which to multiply length in Wang's formula. (See above.)
template<int Degree> constexpr float length_term(float precision) {}
template<int Degree> constexpr float length_term_p2(float precision) {}

AI float root4(float x) {}

// For finite positive x > 1, return ceil(log2(x)) otherwise, return 0.
// For +/- NaN return 0.
// For +infinity return 128.
// For -infinity return 0.
//
//     nextlog2((-inf..1]) -> 0
//     nextlog2((1..2]) -> 1
//     nextlog2((2..4]) -> 2
//     nextlog2((4..8]) -> 3
//     ...
AI int nextlog2(float x) {}

// Returns nextlog2(sqrt(x)):
//
//   log2(sqrt(x)) == log2(x^(1/2)) == log2(x)/2 == log2(x)/log2(4) == log4(x)
//
AI int nextlog4(float x) {}

// Returns nextlog2(sqrt(sqrt(x))):
//
//   log2(sqrt(sqrt(x))) == log2(x^(1/4)) == log2(x)/4 == log2(x)/log2(16) == log16(x)
//
AI int nextlog16(float x) {}

// Represents the upper-left 2x2 matrix of an affine transform for applying to vectors:
//
//     VectorXform(p1 - p0) == M * float3(p1, 1) - M * float3(p0, 1)
//
class VectorXform {};

// Returns Wang's formula, raised to the 4th power, specialized for a quadratic curve.
AI float quadratic_p4(float precision,
                      skvx::float2 p0, skvx::float2 p1, skvx::float2 p2,
                      const VectorXform& vectorXform = VectorXform()) {}
AI float quadratic_p4(float precision,
                      const SkPoint pts[],
                      const VectorXform& vectorXform = VectorXform()) {}

// Returns Wang's formula specialized for a quadratic curve.
AI float quadratic(float precision,
                   const SkPoint pts[],
                   const VectorXform& vectorXform = VectorXform()) {}

// Returns the log2 value of Wang's formula specialized for a quadratic curve, rounded up to the
// next int.
AI int quadratic_log2(float precision,
                      const SkPoint pts[],
                      const VectorXform& vectorXform = VectorXform()) {}

// Returns Wang's formula, raised to the 4th power, specialized for a cubic curve.
AI float cubic_p4(float precision,
                  skvx::float2 p0, skvx::float2 p1, skvx::float2 p2, skvx::float2 p3,
                  const VectorXform& vectorXform = VectorXform()) {}
AI float cubic_p4(float precision,
                  const SkPoint pts[],
                  const VectorXform& vectorXform = VectorXform()) {}

// Returns Wang's formula specialized for a cubic curve.
AI float cubic(float precision,
               const SkPoint pts[],
               const VectorXform& vectorXform = VectorXform()) {}

// Returns the log2 value of Wang's formula specialized for a cubic curve, rounded up to the next
// int.
AI int cubic_log2(float precision,
                  const SkPoint pts[],
                  const VectorXform& vectorXform = VectorXform()) {}

// Returns the maximum number of line segments a cubic with the given device-space bounding box size
// would ever need to be divided into, raised to the 4th power. This is simply a special case of the
// cubic formula where we maximize its value by placing control points on specific corners of the
// bounding box.
AI float worst_case_cubic_p4(float precision, float devWidth, float devHeight) {}

// Returns the maximum number of line segments a cubic with the given device-space bounding box size
// would ever need to be divided into.
AI float worst_case_cubic(float precision, float devWidth, float devHeight) {}

// Returns the maximum log2 number of line segments a cubic with the given device-space bounding box
// size would ever need to be divided into.
AI int worst_case_cubic_log2(float precision, float devWidth, float devHeight) {}

// Returns Wang's formula specialized for a conic curve, raised to the second power.
// Input points should be in projected space.
//
// This is not actually due to Wang, but is an analogue from (Theorem 3, corollary 1):
//   J. Zheng, T. Sederberg. "Estimating Tessellation Parameter Intervals for
//   Rational Curves and Surfaces." ACM Transactions on Graphics 19(1). 2000.
AI float conic_p2(float precision,
                  skvx::float2 p0, skvx::float2 p1, skvx::float2 p2,
                  float w,
                  const VectorXform& vectorXform = VectorXform()) {}
AI float conic_p2(float precision,
                  const SkPoint pts[],
                  float w,
                  const VectorXform& vectorXform = VectorXform()) {}

// Returns the value of Wang's formula specialized for a conic curve.
AI float conic(float tolerance,
               const SkPoint pts[],
               float w,
               const VectorXform& vectorXform = VectorXform()) {}

// Returns the log2 value of Wang's formula specialized for a conic curve, rounded up to the next
// int.
AI int conic_log2(float tolerance,
                  const SkPoint pts[],
                  float w,
                  const VectorXform& vectorXform = VectorXform()) {}

}  // namespace skgpu::wangs_formula

#undef AI

#endif  // skgpu_tessellate_WangsFormula_DEFINED