about summary refs log tree commit diff
path: root/converter/other/pamtosvg/curve.h
blob: ba5f18339ebe86ed0a8e0e2aed5a6078d45e6c79 (plain) (blame)
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
/* curve.h: data structures for the conversion from pixels to splines. */

#ifndef CURVE_H
#define CURVE_H

#include "autotrace.h"
#include "point.h"
#include "vector.h"

/* We are simultaneously manipulating two different representations of
   the same outline: one based on (x,y) positions in the plane, and one
   based on parametric splines.  (We are trying to match the latter to
   the former.)  Although the original (x,y)'s are pixel positions,
   i.e., integers, after filtering they are reals.  */

typedef struct {
    float_coord coord;
    float       t;
} point_type;



typedef struct curve {
/*----------------------------------------------------------------------------
  An ordered list of contiguous points in the raster, with no corners
  in it.  I.e. something that could reasonably be fit to a spline.
-----------------------------------------------------------------------------*/
    point_type *   point_list;
        /* Array of the points in the curve.  Malloc'ed.  Size is 'length'.
           if 'length' is zero, this is meaningless and no memory is
           allocated.
        */
    unsigned       length;
        /* Number of points in the curve */
    bool           cyclic;

    /* 'previous' and 'next' links are for the doubly linked list which is
       a chain of all curves in an outline.  The chain is a cycle for a
       closed outline and linear for an open outline.
    */
    struct curve * previous;
    struct curve * next;
} curve;

typedef struct curve * curve_type;

/* Get at the coordinates and the t values.  */
#define CURVE_POINT(c, n) ((c)->point_list[n].coord)
#define LAST_CURVE_POINT(c) ((c)->point_list[(c)->length-1].coord)
#define CURVE_T(c, n) ((c)->point_list[n].t)
#define LAST_CURVE_T(c) ((c)->point_list[(c)->length-1].t)

/* This is the length of `point_list'.  */
#define CURVE_LENGTH(c)  ((c)->length)

/* A curve is ``cyclic'' if it didn't have any corners, after all, so
   the last point is adjacent to the first.  */
#define CURVE_CYCLIC(c)  ((c)->cyclic)

/* If the curve is cyclic, the next and previous points should wrap
   around; otherwise, if we get to the end, we return CURVE_LENGTH and
   -1, respectively.  */
#define CURVE_NEXT(c, n)						\
  ((n) + 1 >= CURVE_LENGTH (c)						\
  ? CURVE_CYCLIC (c) ? ((n) + 1) % CURVE_LENGTH (c) : CURVE_LENGTH (c)	\
  : (n) + 1)
#define CURVE_PREV(c, n)						\
  ((signed int) (n) - 1 < 0							\
  ? CURVE_CYCLIC (c) ? (signed int) CURVE_LENGTH (c) + (signed int) (n) - 1 : -1\
  : (signed int) (n) - 1)

#define PREVIOUS_CURVE(c) ((c)->previous)
#define NEXT_CURVE(c) ((c)->next)


/* Return an entirely empty curve.  */
extern curve_type new_curve (void);

/* Return a curve the same as C, except without any points.  */
extern curve_type copy_most_of_curve (curve_type c);

void
move_curve(curve * const dstP,
           curve * const srcP);

void
free_curve(curve * const curveP);

/* Like `append_pixel', for a point in real coordinates.  */
void
append_point(curve_type  const curve,
             float_coord const coord);

/* Append the point P to the end of C's list.  */
void
append_pixel(curve_type    const c,
             pm_pixelcoord const p);

/* Write some or all, respectively, of the curve C in human-readable
   form to the log file, if logging is enabled.  */
extern void log_curve (curve_type c, bool print_t);
extern void log_entire_curve (curve_type c);

/* Display the curve C online, if displaying is enabled.  */
extern void display_curve (curve_type);



typedef struct {
/*----------------------------------------------------------------------------
   An ordered list of contiguous curves of a particular color.
-----------------------------------------------------------------------------*/
    curve ** data;
        /* data[i] is the handle of the ith curve in the list */
    unsigned length;
    bool     clockwise;
    pixel    color;
    bool     open;
        /* The curve list does not form a closed shape;  i.e. the last
           curve doesn't end where the first one starts.
        */
} curve_list_type;

/* Number of curves in the list.  */
#define CURVE_LIST_LENGTH(c_l)  ((c_l).length)
#define CURVE_LIST_EMPTY(c_l) ((c_l).length == 0)

/* Access the individual curves.  */
#define CURVE_LIST_ELT(c_l, n) ((c_l).data[n])
#define LAST_CURVE_LIST_ELT(c_l) ((c_l).data[CURVE_LIST_LENGTH (c_l) - 1])

/* Says whether the outline that this curve list represents moves
   clockwise or counterclockwise.  */
#define CURVE_LIST_CLOCKWISE(c_l) ((c_l).clockwise)


extern curve_list_type new_curve_list (void);

void
free_curve_list(curve_list_type * const curve_list);

extern void append_curve (curve_list_type *, curve_type);

/* And a character is a list of outlines.  I named this
   `curve_list_array_type' because `curve_list_list_type' seemed pretty
   monstrous.  */
typedef struct
{
  curve_list_type *data;
  unsigned length;
} curve_list_array_type;

/* Turns out we can use the same definitions for lists of lists as for
   just lists.  But we define the usual names, just in case.  */
#define CURVE_LIST_ARRAY_LENGTH CURVE_LIST_LENGTH
#define CURVE_LIST_ARRAY_ELT CURVE_LIST_ELT
#define LAST_CURVE_LIST_ARRAY_ELT LAST_CURVE_LIST_ELT

curve_list_array_type
new_curve_list_array(void);

void
free_curve_list_array(const curve_list_array_type * const curve_list_array,
                      at_progress_func                    notify_progress, 
                      void *                        const client_data);

void
append_curve_list(curve_list_array_type * const curve_list_array,
                  curve_list_type         const curve_list);

#endif