blob: 2e31f097b9bdafdcb49f1c1feaf015524fa4aa56 [file] [log] [blame]
/*
* Copyright 2021 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Initial import from skia:src/gpu/tessellate/Tessellation.h
* skia:src/core/SkGeometry.h
*
* Copyright 2022 Rive
*/
#pragma once
#include "rive/math/vec2d.hpp"
#include <math.h>
namespace rive::pathutils
{
// Decides the number of polar segments the tessellator adds for each curve. (Uniform steps in
// tangent angle.) The tessellator will add this number of polar segments for each radian of
// rotation in local path space.
template <int Precision> float CalcPolarSegmentsPerRadian(float approxDevStrokeRadius)
{
float cosTheta = 1.f - (1.f / Precision) / approxDevStrokeRadius;
return .5f / acosf(std::max(cosTheta, -1.f));
}
Vec2D EvalCubicAt(const Vec2D p[4], float t);
// Given a src cubic bezier, chop it at the specified t value,
// where 0 <= t <= 1, and return the two new cubics in dst:
// dst[0..3] and dst[3..6]
void ChopCubicAt(const Vec2D src[4], Vec2D dst[7], float t);
// Given a src cubic bezier, chop it at the specified t0 and t1 values,
// where 0 <= t0 <= t1 <= 1, and return the three new cubics in dst:
// dst[0..3], dst[3..6], and dst[6..9]
void ChopCubicAt(const Vec2D src[4], Vec2D dst[10], float t0, float t1);
// Given a src cubic bezier, chop it at the specified t values,
// where 0 <= t0 <= t1 <= ... <= 1, and return the new cubics in dst:
// dst[0..3],dst[3..6],...,dst[3*t_count..3*(t_count+1)]
void ChopCubicAt(const Vec2D src[4], Vec2D dst[], const float tValues[], int tCount);
// Measures the angle between two vectors, in the range [0, pi].
float MeasureAngleBetweenVectors(Vec2D a, Vec2D b);
// Returns 0, 1, or 2 T values at which to chop the given curve in order to guarantee the resulting
// cubics are convex and rotate no more than 180 degrees.
//
// - If the cubic is "serpentine", then the T values are any inflection points in [0 < T < 1].
// - If the cubic is linear, then the T values are any 180-degree cusp points in [0 < T < 1].
// - Otherwise the T value is the point at which rotation reaches 180 degrees, iff in [0 < T < 1].
//
// 'areCusps' is set to true if the chop point occurred at a cusp (within tolerance), or if the chop
// point(s) occurred at 180-degree turnaround points on a degenerate flat line.
int FindCubicConvex180Chops(const Vec2D[], float T[2], bool* areCusps);
#if 0
// Returns a new path, equivalent to 'path' within the given viewport, whose verbs can all be drawn
// with 'maxSegments' tessellation segments or fewer, while staying within '1/tessellationPrecision'
// pixels of the true curve. Curves and chops that fall completely outside the viewport are
// flattened into lines.
SkPath PreChopPathCurves(float tessellationPrecision,
const SkPath&,
const SkMatrix&,
const SkRect& viewport);
#endif
} // namespace rive::pathutils