1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkPathOpsConic_DEFINED
9#define SkPathOpsConic_DEFINED
10
11#include "SkPathOpsPoint.h"
12#include "SkPathOpsQuad.h"
13
14struct SkDConic {
15    static const int kPointCount = 3;
16    static const int kPointLast = kPointCount - 1;
17    static const int kMaxIntersections = 4;
18
19    SkDQuad fPts;
20    SkScalar fWeight;
21
22    bool collapsed() const {
23        return fPts.collapsed();
24    }
25
26    bool controlsInside() const {
27        return fPts.controlsInside();
28    }
29
30    void debugInit() {
31        fPts.debugInit();
32    }
33
34    void debugSet(const SkDPoint* pts, SkScalar weight);
35
36    SkDConic flip() const {
37        SkDConic result = {{{fPts[2], fPts[1], fPts[0]}
38                SkDEBUGPARAMS(fPts.fDebugGlobalState) }, fWeight};
39        return result;
40    }
41
42#ifdef SK_DEBUG
43    SkOpGlobalState* globalState() const { return fPts.globalState(); }
44#endif
45
46    static bool IsConic() { return true; }
47
48    const SkDConic& set(const SkPoint pts[kPointCount], SkScalar weight
49            SkDEBUGPARAMS(SkOpGlobalState* state = nullptr)) {
50        fPts.set(pts  SkDEBUGPARAMS(state));
51        fWeight = weight;
52        return *this;
53    }
54
55    const SkDPoint& operator[](int n) const { return fPts[n]; }
56    SkDPoint& operator[](int n) { return fPts[n]; }
57
58    static int AddValidTs(double s[], int realRoots, double* t) {
59        return SkDQuad::AddValidTs(s, realRoots, t);
60    }
61
62    void align(int endIndex, SkDPoint* dstPt) const {
63        fPts.align(endIndex, dstPt);
64    }
65
66    SkDVector dxdyAtT(double t) const;
67    static int FindExtrema(const double src[], SkScalar weight, double tValue[1]);
68
69    bool hullIntersects(const SkDQuad& quad, bool* isLinear) const {
70        return fPts.hullIntersects(quad, isLinear);
71    }
72
73    bool hullIntersects(const SkDConic& conic, bool* isLinear) const {
74        return fPts.hullIntersects(conic.fPts, isLinear);
75    }
76
77    bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const;
78
79    bool isLinear(int startIndex, int endIndex) const {
80        return fPts.isLinear(startIndex, endIndex);
81    }
82
83    bool monotonicInX() const {
84        return fPts.monotonicInX();
85    }
86
87    bool monotonicInY() const {
88        return fPts.monotonicInY();
89    }
90
91    void otherPts(int oddMan, const SkDPoint* endPt[2]) const {
92        fPts.otherPts(oddMan, endPt);
93    }
94
95    SkDPoint ptAtT(double t) const;
96
97    static int RootsReal(double A, double B, double C, double t[2]) {
98        return SkDQuad::RootsReal(A, B, C, t);
99    }
100
101    static int RootsValidT(const double A, const double B, const double C, double s[2]) {
102        return SkDQuad::RootsValidT(A, B, C, s);
103    }
104
105    SkDConic subDivide(double t1, double t2) const;
106
107    static SkDConic SubDivide(const SkPoint a[kPointCount], SkScalar weight, double t1, double t2) {
108        SkDConic conic;
109        conic.set(a, weight);
110        return conic.subDivide(t1, t2);
111    }
112
113    SkDPoint subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2,
114            SkScalar* weight) const;
115
116    static SkDPoint SubDivide(const SkPoint pts[kPointCount], SkScalar weight,
117                              const SkDPoint& a, const SkDPoint& c,
118                              double t1, double t2, SkScalar* newWeight) {
119        SkDConic conic;
120        conic.set(pts, weight);
121        return conic.subDivide(a, c, t1, t2, newWeight);
122    }
123
124    // utilities callable by the user from the debugger when the implementation code is linked in
125    void dump() const;
126    void dumpID(int id) const;
127    void dumpInner() const;
128
129};
130
131
132#endif
133