32 const double adjust = sqrt(3.) / 36;
39 sub = cubic.subDivide(
start, 1);
43 double dx = c[3].fX - 3 * (c[2].fX - c[1].fX) - c[0].fX;
44 double dy = c[3].fY - 3 * (c[2].fY - c[1].fY) - c[0].fY;
45 double dist = sqrt(dx * dx + dy * dy);
46 double tDiv3 = precision / (adjust * dist);
47 double t = std::cbrt(tDiv3);
69 double parts = ceil(1.0 / tDiv);
70 for (
double index = 0; index < parts; ++index) {
72 if (newT > 0 && newT < 1) {
85 int inflections = cubic->findInflections(inflectT);
87 if (!cubic->endsAreExtremaInXOrY()) {
88 inflections += cubic->findMaxCurvature(&inflectT[inflections]);
91 SkTQSort<double>(inflectT, inflectT + inflections);
95 memmove(inflectT, &inflectT[1],
sizeof(inflectT[0]) * --inflections);
99 while (
next < inflections) {
105 memmove(&inflectT[
start], &inflectT[
next],
sizeof(inflectT[0]) * (--inflections -
start));
112 if (inflections == 1) {
113 pair = cubic->chopAt(inflectT[0]);
124 if (inflections == 0 &&
add_simple_ts(*cubic, precision, ts)) {
127 if (inflections == 1) {
128 pair = cubic->chopAt(inflectT[0]);
129 addTs(pair.
first(), precision, 0, inflectT[0], ts);
130 addTs(pair.
second(), precision, inflectT[0], 1, ts);
133 if (inflections > 1) {
134 SkDCubic part = cubic->subDivide(0, inflectT[0]);
135 addTs(part, precision, 0, inflectT[0], ts);
136 int last = inflections - 1;
137 for (
int idx = 0; idx < last; ++idx) {
138 part = cubic->subDivide(inflectT[idx], inflectT[idx + 1]);
139 addTs(part, precision, inflectT[idx], inflectT[idx + 1], ts);
141 part = cubic->subDivide(inflectT[last], 1);
142 addTs(part, precision, inflectT[last], 1, ts);
145 addTs(*cubic, precision, 0, 1, ts);
157 for (
int i1 = 0; i1 <= ts.
size(); ++i1) {
158 const double tEnd = i1 < ts.
size() ? ts[i1] : 1;
160 bounds.setBounds(cubic);
161 SkDCubic part = cubic.subDivide(tStart, tEnd);
163 if (quad[1].fX < bounds.fLeft) {
164 quad[1].fX = bounds.fLeft;
165 }
else if (quad[1].fX > bounds.fRight) {
166 quad[1].fX = bounds.fRight;
168 if (quad[1].fY < bounds.fTop) {
169 quad[1].fY = bounds.fTop;
170 }
else if (quad[1].fY > bounds.fBottom) {
171 quad[1].fY = bounds.fBottom;
185 quadPath->
moveTo(pts[0].fX, pts[0].fY);
188 quadPath->
lineTo(pts[1].fX, pts[1].fY);
191 quadPath->
quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
197 for (
int index = 0; index < quads.
size(); ++index) {
199 quads[index][1].asSkPoint(),
200 quads[index][2].asSkPoint()
202 quadPath->
quadTo(qPts[0].fX, qPts[0].fY, qPts[1].fX, qPts[1].fY);
221 simplePath->
moveTo(pts[0].fX, pts[0].fY);
224 simplePath->
lineTo(pts[1].fX, pts[1].fY);
227 simplePath->
quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
232 int inflections = cubic.findInflections(tInflects);
233 if (inflections > 1 && tInflects[0] > tInflects[1]) {
235 swap(tInflects[0], tInflects[1]);
238 for (
int index = 0; index <= inflections; ++index) {
239 double hi = index < inflections ? tInflects[index] : 1;
240 SkDCubic part = cubic.subDivide(lo, hi);
242 cPts[0] = part[1].asSkPoint();
243 cPts[1] = part[2].asSkPoint();
244 cPts[2] = part[3].asSkPoint();
245 simplePath->
cubicTo(cPts[0].fX, cPts[0].fY, cPts[1].fX, cPts[1].fY,
246 cPts[2].fX, cPts[2].fY);
271 return !
SkIsNaN(bounds.fBottom);
287 for (
int index = 0; index < 4; ++index) {
296 for (
int index = 0; index < 2; ++index) {
312 for (
int index = 0; index <
count; ++index) {
324 for (
int index = 0; index < 3; ++index) {
static float next(float f)
void CubicPathToQuads(const SkPath &cubicPath, SkPath *quadPath)
static bool add_simple_ts(const SkDCubic &cubic, double precision, TArray< double, true > *ts)
void CubicPathToSimple(const SkPath &cubicPath, SkPath *simplePath)
bool ValidCubic(const SkDCubic &cubic)
void CubicToQuads(const SkDCubic &cubic, double precision, TArray< SkDQuad, true > &quads)
bool ValidVector(const SkDVector &v)
bool ValidConic(const SkDConic &conic)
bool ValidPoints(const SkPoint *pts, int count)
static void addTs(const SkDCubic &cubic, double precision, double start, double end, TArray< double, true > *ts)
static void toQuadraticTs(const SkDCubic *cubic, double precision, TArray< double, true > *ts)
bool ValidPoint(const SkDPoint &pt)
bool ValidBounds(const SkPathOpsBounds &bounds)
bool ValidLine(const SkDLine &line)
static double calc_t_div(const SkDCubic &cubic, double precision, double start)
bool ValidQuad(const SkDQuad &quad)
#define SkDEBUGFAIL(message)
static bool SkDoubleIsNaN(double x)
bool approximately_less_than_zero(double x)
bool approximately_equal(double x, double y)
bool approximately_greater_than_one(double x)
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
SkPath & moveTo(SkScalar x, SkScalar y)
SkPath & lineTo(SkScalar x, SkScalar y)
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
static void swap(TArray< T, M > &a, TArray< T, M > &b)
static const int kPointCount
int reduce(const SkDCubic &cubic, Quadratics)