summaryrefslogtreecommitdiffstats
path: root/src/display/curve.h
blob: 5cd8bb12cadd1b04ca241308b3d890340e049b07 (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
#ifndef SEEN_DISPLAY_CURVE_H
#define SEEN_DISPLAY_CURVE_H

/** \file
 * Wrapper around an array of NArtBpath objects.
 *
 * Author:
 *   Lauris Kaplinski <lauris@kaplinski.com>
 *
 * Copyright (C) 2000 Lauris Kaplinski
 * Copyright (C) 2000-2001 Ximian, Inc.
 * Copyright (C) 2002 Lauris Kaplinski
 * Copyright (C) 2008 Johan Engelen
 *
 * Released under GNU GPL
 */

#include <glib/gtypes.h>
#include <glib/gslist.h>

#include "libnr/nr-forward.h"
#include "libnr/nr-rect.h"

#define SP_CURVE_LENSTEP 32

/// Wrapper around NArtBpath.
class SPCurve {
public:
    /* Constructors */
    SPCurve(guint length = SP_CURVE_LENSTEP);
    static SPCurve * new_from_bpath(NArtBpath *bpath);
    static SPCurve * new_from_foreign_bpath(NArtBpath const *bpath);
    static SPCurve * new_from_rect(NR::Maybe<NR::Rect> const &rect);

    virtual ~SPCurve();

    void set_bpath(NArtBpath * new_bpath);
    NArtBpath const * get_bpath() const;

    /// Index in bpath[] of NR_END element.
    guint _end;

    /// Allocated size (i.e., capacity) of bpath[] array.  Not to be confused 
    /// with the SP_CURVE_LENGTH macro, which returns the logical length of 
    /// the path (i.e., index of NR_END).
    guint _length;

    /// Index in bpath[] of the start (i.e., moveto element) of the last 
    /// subpath in this path.
    guint _substart;

    /// Previous moveto position.
    /// \note This is used for coalescing moveto's, whereas if we're to 
    /// conform to the SVG spec then we mustn't coalesce movetos if we have 
    /// midpoint markers.  Ref:
    /// http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
    /// (first subitem of the item about zero-length path segments)
    NR::Point _movePos;

    /// True iff current point is defined.  Initially false for a new curve; 
    /// becomes true after moveto; becomes false on closepath.  Curveto, 
    /// lineto etc. require hascpt; hascpt remains true after lineto/curveto.
    bool _hascpt : 1;
    
    /// True iff previous was moveto.
    bool _posSet : 1;

    /// True iff bpath end is moving.
    bool _moving : 1;
    
    /// True iff all subpaths are closed.
    bool _closed : 1;

    SPCurve * ref();
    SPCurve * unref();

    SPCurve * copy() const;

    GSList * split() const;
    void transform(NR::Matrix const &);
    void transform(NR::translate const &);
    void stretch_endpoints(NR::Point const &, NR::Point const &);
    void move_endpoints(NR::Point const &, NR::Point const &);

    void reset();

    void moveto(NR::Point const &p);
    void moveto(gdouble x, gdouble y);
    void lineto(NR::Point const &p);
    void lineto(gdouble x, gdouble y);
    void lineto_moving(gdouble x, gdouble y);
    void curveto(NR::Point const &p0, NR::Point const &p1, NR::Point const &p2);
    void curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdouble y2);
    void closepath();
    void closepath_current();

    SPCurve * append_continuous(SPCurve const *c1, gdouble tolerance);

    bool is_empty() const;
    bool is_closed() const;
    NArtBpath * last_bpath() const;
    NArtBpath * first_bpath() const;
    NR::Point first_point() const;
    NR::Point last_point() const;
    NR::Point second_point() const;
    NR::Point penultimate_point() const;

    void append(SPCurve const *curve2, bool use_lineto);
    SPCurve * create_reverse() const;
    void backspace();

    static SPCurve * concat(GSList const *list);

    void ensure_space(guint space);

protected:
    gint _refcount;

    NArtBpath *_bpath;

private:
    // Don't implement these:
    SPCurve(const SPCurve&);
    SPCurve& operator=(const SPCurve&);

    friend double sp_curve_distance_including_space(SPCurve const *const curve, double seg2len[]);
    friend double sp_curve_nonzero_distance_including_space(SPCurve const *const curve, double seg2len[]);
    template<class M> friend void tmpl_curve_transform(SPCurve *const curve, M const &m);
};

#define SP_CURVE_LENGTH(c) (((SPCurve const *)(c))->_end)
#define SP_CURVE_BPATH(c) ((c)->get_bpath())
#define SP_CURVE_SEGMENT(c,i) ((c)->get_bpath() + (i))

#endif /* !SEEN_DISPLAY_CURVE_H */

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :