1 /* curve.h: data structures for the conversion from pixels to splines. */ 2 3 #ifndef CURVE_H 4 #define CURVE_H 5 6 #include "autotrace.h" 7 #include "vector.h" 8 9 10 /* We are simultaneously manipulating two different representations of 11 the same outline: one based on (x,y) positions in the plane, and one 12 based on parametric splines. (We are trying to match the latter to 13 the former.) Although the original (x,y)'s are pixel positions, 14 i.e., integers, after filtering they are reals. */ 15 16 typedef struct 17 { 18 at_real_coord coord; 19 at_real t; 20 } point_type; 21 22 23 /* It turns out to be convenient to break the list of all the pixels in 24 the outline into sublists, divided at ``corners''. Then each of the 25 sublists is treated independently. Each of these sublists is a `curve'. */ 26 27 struct curve 28 { 29 point_type *point_list; 30 unsigned length; 31 at_bool cyclic; 32 vector_type *start_tangent; 33 vector_type *end_tangent; 34 struct curve *previous; 35 struct curve *next; 36 }; 37 38 typedef struct curve *curve_type; 39 40 /* Get at the coordinates and the t values. */ 41 #define CURVE_POINT(c, n) ((c)->point_list[n].coord) 42 #define LAST_CURVE_POINT(c) ((c)->point_list[(c)->length-1].coord) 43 #define CURVE_T(c, n) ((c)->point_list[n].t) 44 #define LAST_CURVE_T(c) ((c)->point_list[(c)->length-1].t) 45 46 /* This is the length of `point_list'. */ 47 #define CURVE_LENGTH(c) ((c)->length) 48 49 /* A curve is ``cyclic'' if it didn't have any corners, after all, so 50 the last point is adjacent to the first. */ 51 #define CURVE_CYCLIC(c) ((c)->cyclic) 52 53 /* If the curve is cyclic, the next and previous points should wrap 54 around; otherwise, if we get to the end, we return CURVE_LENGTH and 55 -1, respectively. */ 56 #define CURVE_NEXT(c, n) \ 57 ((n) + 1 >= CURVE_LENGTH (c) \ 58 ? CURVE_CYCLIC (c) ? ((n) + 1) % CURVE_LENGTH (c) : CURVE_LENGTH (c) \ 59 : (n) + 1) 60 #define CURVE_PREV(c, n) \ 61 ((signed int) (n) - 1 < 0 \ 62 ? CURVE_CYCLIC (c) ? (signed int) CURVE_LENGTH (c) + (signed int) (n) - 1 : -1\ 63 : (signed int) (n) - 1) 64 65 /* The tangents at the endpoints are computed using the neighboring curves. */ 66 #define CURVE_START_TANGENT(c) ((c)->start_tangent) 67 #define CURVE_END_TANGENT(c) ((c)->end_tangent) 68 #define PREVIOUS_CURVE(c) ((c)->previous) 69 #define NEXT_CURVE(c) ((c)->next) 70 71 72 /* Return an entirely empty curve. */ 73 extern curve_type new_curve (void); 74 75 /* Return a curve the same as C, except without any points. */ 76 extern curve_type copy_most_of_curve (curve_type c); 77 78 /* Free the memory C uses. */ 79 extern void free_curve (curve_type c); 80 81 /* Append the point P to the end of C's list. */ 82 extern void append_pixel (curve_type c, at_coord p); 83 84 /* Like `append_pixel', for a point in real coordinates. */ 85 extern void append_point (curve_type c, at_real_coord p); 86 87 /* Write some or all, respectively, of the curve C in human-readable 88 form to the log file, if logging is enabled. */ 89 extern void log_curve (curve_type c, at_bool print_t); 90 extern void log_entire_curve (curve_type c); 91 92 /* Display the curve C online, if displaying is enabled. */ 93 extern void display_curve (curve_type); 94 95 /* So, an outline is a list of curves. */ 96 typedef struct 97 { 98 curve_type *data; 99 unsigned length; 100 at_bool clockwise; 101 at_bool open; 102 } curve_list_type; 103 104 /* Number of curves in the list. */ 105 #define CURVE_LIST_LENGTH(c_l) ((c_l).length) 106 107 /* Access the individual curves. */ 108 #define CURVE_LIST_ELT(c_l, n) ((c_l).data[n]) 109 #define LAST_CURVE_LIST_ELT(c_l) ((c_l).data[CURVE_LIST_LENGTH (c_l) - 1]) 110 111 /* Says whether the outline that this curve list represents moves 112 clockwise or counterclockwise. */ 113 #define CURVE_LIST_CLOCKWISE(c_l) ((c_l).clockwise) 114 115 116 extern curve_list_type new_curve_list (void); 117 extern void free_curve_list (curve_list_type *); 118 extern void append_curve (curve_list_type *, curve_type); 119 120 /* And a character is a list of outlines. I named this 121 `curve_list_array_type' because `curve_list_list_type' seemed pretty 122 monstrous. */ 123 typedef struct 124 { 125 curve_list_type *data; 126 unsigned length; 127 } curve_list_array_type; 128 129 /* Turns out we can use the same definitions for lists of lists as for 130 just lists. But we define the usual names, just in case. */ 131 #define CURVE_LIST_ARRAY_LENGTH CURVE_LIST_LENGTH 132 #define CURVE_LIST_ARRAY_ELT CURVE_LIST_ELT 133 #define LAST_CURVE_LIST_ARRAY_ELT LAST_CURVE_LIST_ELT 134 135 extern curve_list_array_type new_curve_list_array (void); 136 extern void free_curve_list_array (curve_list_array_type *, 137 at_progress_func, 138 at_address); 139 extern void append_curve_list (curve_list_array_type *, curve_list_type); 140 141 #endif /* not CURVE_H */ 142 143