summaryrefslogtreecommitdiff
path: root/Build/source/texk/lcdf-typetools/lcdf-typetools-src/include/lcdf/bezier.hh
blob: fb1018ed0e5c4ccea2198d444d69dd28568d105b (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
// -*- related-file-name: "../../liblcdf/bezier.cc" -*-
#ifndef LCDF_BEZIER_HH
#define LCDF_BEZIER_HH
#include <lcdf/point.hh>
#include <lcdf/vector.hh>
#include <string.h>

class Bezier { public:

    Bezier()				: _bb(-1) { }
    inline Bezier(Point p[4]) noexcept;
    inline Bezier(const Point &, const Point &, const Point &, const Point &) noexcept;

    const Point *points() const		{ return _p; }
    const Point &point(int i) const	{ assert(i>=0&&i<4); return _p[i]; }
    Point &mpoint(int i)		{ assert(i>=0&&i<4); _bb = -1; return _p[i]; }
    void set_point(int i, const Point &p) { mpoint(i) = p; }

    Point eval(double) const noexcept;
    bool is_flat(double) const noexcept;
    bool in_bb(const Point &, double) const noexcept;
    bool hit(const Point &, double) const noexcept;

    inline double bb_left() const noexcept;
    inline double bb_right() const noexcept;
    inline double bb_top() const noexcept;
    inline double bb_bottom() const noexcept;

    inline double bb_left_x() const noexcept;
    inline double bb_right_x() const noexcept;
    inline double bb_top_x() const noexcept;
    inline double bb_bottom_x() const noexcept;

    void halve(Bezier &, Bezier &) const noexcept;

    inline void segmentize(Vector<Point> &) const;
    void segmentize(Vector<Point> &, bool) const;

    static void fit(const Vector<Point> &, double, Vector<Bezier> &);

  private:

    Point _p[4];
    mutable int _bb;

    void make_bb() const noexcept;
    inline void ensure_bb() const noexcept;

    double hit_recurse(const Point &, double, double, double, double, double) const noexcept;

};


inline
Bezier::Bezier(Point p[4]) noexcept
    : _bb(-1)
{
    memcpy(_p, p, sizeof(Point) * 4);
}

inline
Bezier::Bezier(const Point &p0, const Point &p1, const Point &p2, const Point &p3) noexcept
{
    _p[0] = p0;
    _p[1] = p1;
    _p[2] = p2;
    _p[3] = p3;
    _bb = -1;
}

inline void
Bezier::ensure_bb() const noexcept
{
    if (_bb < 0)
	make_bb();
}

inline double
Bezier::bb_top_x() const noexcept
{
    return _p[(_bb >> 4) & 3].y;
}

inline double
Bezier::bb_left_x() const noexcept
{
    return _p[(_bb >> 2) & 3].x;
}

inline double
Bezier::bb_bottom_x() const noexcept
{
    return _p[(_bb >> 6) & 3].y;
}

inline double
Bezier::bb_right_x() const noexcept
{
    return _p[(_bb >> 0) & 3].x;
}

inline double
Bezier::bb_top() const noexcept
{
    ensure_bb();
    return bb_top_x();
}

inline double
Bezier::bb_left() const noexcept
{
    ensure_bb();
    return bb_left_x();
}

inline double
Bezier::bb_bottom() const noexcept
{
    ensure_bb();
    return bb_bottom_x();
}

inline double
Bezier::bb_right() const noexcept
{
    ensure_bb();
    return bb_right_x();
}

inline void
Bezier::segmentize(Vector<Point> &v) const
{
    segmentize(v, v.size() == 0 || v.back() != _p[0]);
}

#endif