summaryrefslogtreecommitdiff
path: root/thirdparty/msdfgen/core/edge-segments.h
blob: 1c8fb599ff2486af9479fad058dae87b7486f6bb (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

#pragma once

#include "Vector2.h"
#include "SignedDistance.h"
#include "EdgeColor.h"

namespace msdfgen {

// Parameters for iterative search of closest point on a cubic Bezier curve. Increase for higher precision.
#define MSDFGEN_CUBIC_SEARCH_STARTS 4
#define MSDFGEN_CUBIC_SEARCH_STEPS 4

/// An abstract edge segment.
class EdgeSegment {

public:
    EdgeColor color;

    EdgeSegment(EdgeColor edgeColor = WHITE) : color(edgeColor) { }
    virtual ~EdgeSegment() { }
    /// Creates a copy of the edge segment.
    virtual EdgeSegment * clone() const = 0;
    /// Returns the point on the edge specified by the parameter (between 0 and 1).
    virtual Point2 point(double param) const = 0;
    /// Returns the direction the edge has at the point specified by the parameter.
    virtual Vector2 direction(double param) const = 0;
    /// Returns the change of direction (second derivative) at the point specified by the parameter.
    virtual Vector2 directionChange(double param) const = 0;
    /// Returns the minimum signed distance between origin and the edge.
    virtual SignedDistance signedDistance(Point2 origin, double &param) const = 0;
    /// Converts a previously retrieved signed distance from origin to pseudo-distance.
    virtual void distanceToPseudoDistance(SignedDistance &distance, Point2 origin, double param) const;
    /// Outputs a list of (at most three) intersections (their X coordinates) with an infinite horizontal scanline at y and returns how many there are.
    virtual int scanlineIntersections(double x[3], int dy[3], double y) const = 0;
    /// Adjusts the bounding box to fit the edge segment.
    virtual void bound(double &l, double &b, double &r, double &t) const = 0;

    /// Reverses the edge (swaps its start point and end point).
    virtual void reverse() = 0;
    /// Moves the start point of the edge segment.
    virtual void moveStartPoint(Point2 to) = 0;
    /// Moves the end point of the edge segment.
    virtual void moveEndPoint(Point2 to) = 0;
    /// Splits the edge segments into thirds which together represent the original edge.
    virtual void splitInThirds(EdgeSegment *&part1, EdgeSegment *&part2, EdgeSegment *&part3) const = 0;

};

/// A line segment.
class LinearSegment : public EdgeSegment {

public:
    Point2 p[2];

    LinearSegment(Point2 p0, Point2 p1, EdgeColor edgeColor = WHITE);
    LinearSegment * clone() const;
    Point2 point(double param) const;
    Vector2 direction(double param) const;
    Vector2 directionChange(double param) const;
    double length() const;
    SignedDistance signedDistance(Point2 origin, double &param) const;
    int scanlineIntersections(double x[3], int dy[3], double y) const;
    void bound(double &l, double &b, double &r, double &t) const;

    void reverse();
    void moveStartPoint(Point2 to);
    void moveEndPoint(Point2 to);
    void splitInThirds(EdgeSegment *&part1, EdgeSegment *&part2, EdgeSegment *&part3) const;

};

/// A quadratic Bezier curve.
class QuadraticSegment : public EdgeSegment {

public:
    Point2 p[3];

    QuadraticSegment(Point2 p0, Point2 p1, Point2 p2, EdgeColor edgeColor = WHITE);
    QuadraticSegment * clone() const;
    Point2 point(double param) const;
    Vector2 direction(double param) const;
    Vector2 directionChange(double param) const;
    double length() const;
    SignedDistance signedDistance(Point2 origin, double &param) const;
    int scanlineIntersections(double x[3], int dy[3], double y) const;
    void bound(double &l, double &b, double &r, double &t) const;

    void reverse();
    void moveStartPoint(Point2 to);
    void moveEndPoint(Point2 to);
    void splitInThirds(EdgeSegment *&part1, EdgeSegment *&part2, EdgeSegment *&part3) const;

    EdgeSegment * convertToCubic() const;

};

/// A cubic Bezier curve.
class CubicSegment : public EdgeSegment {

public:
    Point2 p[4];

    CubicSegment(Point2 p0, Point2 p1, Point2 p2, Point2 p3, EdgeColor edgeColor = WHITE);
    CubicSegment * clone() const;
    Point2 point(double param) const;
    Vector2 direction(double param) const;
    Vector2 directionChange(double param) const;
    SignedDistance signedDistance(Point2 origin, double &param) const;
    int scanlineIntersections(double x[3], int dy[3], double y) const;
    void bound(double &l, double &b, double &r, double &t) const;

    void reverse();
    void moveStartPoint(Point2 to);
    void moveEndPoint(Point2 to);
    void splitInThirds(EdgeSegment *&part1, EdgeSegment *&part2, EdgeSegment *&part3) const;

    void deconverge(int param, double amount);

};

}