summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/pathops/SkPathOpsConic.h
blob: 334dbebb60d542a7b828ebc66f2373a64d88d26d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkPathOpsConic_DEFINED
#define SkPathOpsConic_DEFINED

#include "include/core/SkPoint.h"
#include "include/core/SkScalar.h"
#include "include/private/base/SkDebug.h"
#include "src/base/SkArenaAlloc.h"
#include "src/pathops/SkPathOpsDebug.h"
#include "src/pathops/SkPathOpsPoint.h"
#include "src/pathops/SkPathOpsQuad.h"
#include "src/pathops/SkPathOpsTCurve.h"

class SkIntersections;
class SkOpGlobalState;
struct SkDCubic;
struct SkDLine;
struct SkDRect;

struct SkDConic {
    static const int kPointCount = 3;
    static const int kPointLast = kPointCount - 1;
    static const int kMaxIntersections = 4;

    SkDQuad fPts;
    SkScalar fWeight;

    bool collapsed() const {
        return fPts.collapsed();
    }

    bool controlsInside() const {
        return fPts.controlsInside();
    }

    void debugInit() {
        fPts.debugInit();
        fWeight = 0;
    }

    void debugSet(const SkDPoint* pts, SkScalar weight);

    SkDConic flip() const {
        SkDConic result = {{{fPts[2], fPts[1], fPts[0]}
                SkDEBUGPARAMS(fPts.fDebugGlobalState) }, fWeight};
        return result;
    }

#ifdef SK_DEBUG
    SkOpGlobalState* globalState() const { return fPts.globalState(); }
#endif

    static bool IsConic() { return true; }

    const SkDConic& set(const SkPoint pts[kPointCount], SkScalar weight
            SkDEBUGPARAMS(SkOpGlobalState* state = nullptr)) {
        fPts.set(pts  SkDEBUGPARAMS(state));
        fWeight = weight;
        return *this;
    }

    const SkDPoint& operator[](int n) const { return fPts[n]; }
    SkDPoint& operator[](int n) { return fPts[n]; }

    static int AddValidTs(double s[], int realRoots, double* t) {
        return SkDQuad::AddValidTs(s, realRoots, t);
    }

    void align(int endIndex, SkDPoint* dstPt) const {
        fPts.align(endIndex, dstPt);
    }

    SkDVector dxdyAtT(double t) const;
    static int FindExtrema(const double src[], SkScalar weight, double tValue[1]);

    bool hullIntersects(const SkDQuad& quad, bool* isLinear) const {
        return fPts.hullIntersects(quad, isLinear);
    }

    bool hullIntersects(const SkDConic& conic, bool* isLinear) const {
        return fPts.hullIntersects(conic.fPts, isLinear);
    }

    bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const;

    bool isLinear(int startIndex, int endIndex) const {
        return fPts.isLinear(startIndex, endIndex);
    }

    static int maxIntersections() { return kMaxIntersections; }

    bool monotonicInX() const {
        return fPts.monotonicInX();
    }

    bool monotonicInY() const {
        return fPts.monotonicInY();
    }

    void otherPts(int oddMan, const SkDPoint* endPt[2]) const {
        fPts.otherPts(oddMan, endPt);
    }

    static int pointCount() { return kPointCount; }
    static int pointLast() { return kPointLast; }
    SkDPoint ptAtT(double t) const;

    static int RootsReal(double A, double B, double C, double t[2]) {
        return SkDQuad::RootsReal(A, B, C, t);
    }

    static int RootsValidT(const double A, const double B, const double C, double s[2]) {
        return SkDQuad::RootsValidT(A, B, C, s);
    }

    SkDConic subDivide(double t1, double t2) const;
    void subDivide(double t1, double t2, SkDConic* c) const { *c = this->subDivide(t1, t2); }

    static SkDConic SubDivide(const SkPoint a[kPointCount], SkScalar weight, double t1, double t2) {
        SkDConic conic;
        conic.set(a, weight);
        return conic.subDivide(t1, t2);
    }

    SkDPoint subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2,
            SkScalar* weight) const;

    static SkDPoint SubDivide(const SkPoint pts[kPointCount], SkScalar weight,
                              const SkDPoint& a, const SkDPoint& c,
                              double t1, double t2, SkScalar* newWeight) {
        SkDConic conic;
        conic.set(pts, weight);
        return conic.subDivide(a, c, t1, t2, newWeight);
    }

    // utilities callable by the user from the debugger when the implementation code is linked in
    void dump() const;
    void dumpID(int id) const;
    void dumpInner() const;

};

class SkTConic : public SkTCurve {
public:
    SkDConic fConic;

    SkTConic() {}

    SkTConic(const SkDConic& c)
        : fConic(c) {
    }

    ~SkTConic() override {}

    const SkDPoint& operator[](int n) const override { return fConic[n]; }
    SkDPoint& operator[](int n) override { return fConic[n]; }

    bool collapsed() const override { return fConic.collapsed(); }
    bool controlsInside() const override { return fConic.controlsInside(); }
    void debugInit() override { return fConic.debugInit(); }
#if DEBUG_T_SECT
    void dumpID(int id) const override { return fConic.dumpID(id); }
#endif
    SkDVector dxdyAtT(double t) const override { return fConic.dxdyAtT(t); }
#ifdef SK_DEBUG
    SkOpGlobalState* globalState() const override { return fConic.globalState(); }
#endif
    bool hullIntersects(const SkDQuad& quad, bool* isLinear) const override;

    bool hullIntersects(const SkDConic& conic, bool* isLinear) const override {
        return conic.hullIntersects(fConic, isLinear);
    }

    bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const override;

    bool hullIntersects(const SkTCurve& curve, bool* isLinear) const override {
        return curve.hullIntersects(fConic, isLinear);
    }

    int intersectRay(SkIntersections* i, const SkDLine& line) const override;
    bool IsConic() const override { return true; }
    SkTCurve* make(SkArenaAlloc& heap) const override { return heap.make<SkTConic>(); }

    int maxIntersections() const override { return SkDConic::kMaxIntersections; }

    void otherPts(int oddMan, const SkDPoint* endPt[2]) const override {
        fConic.otherPts(oddMan, endPt);
    }

    int pointCount() const override { return SkDConic::kPointCount; }
    int pointLast() const override { return SkDConic::kPointLast; }
    SkDPoint ptAtT(double t) const override { return fConic.ptAtT(t); }
    void setBounds(SkDRect* ) const override;

    void subDivide(double t1, double t2, SkTCurve* curve) const override {
        ((SkTConic*) curve)->fConic = fConic.subDivide(t1, t2);
    }
};

#endif