more improvements to, and bugfixes in, the new polygon intersector
[swftools.git] / lib / gfxpoly / wind.c
1 #include <assert.h>
2 #include "wind.h"
3
4 fillstyle_t fillstyle_default;
5
6 windstate_t windstate_nonfilled = {
7     is_filled: 0,
8     wind_nr: 0,
9
10     /* TODO: move num_polygons into windstate_t.internal */
11     num_polygons: 1,
12 };
13
14 // -------------------- even/odd ----------------------
15
16 windstate_t evenodd_start(int num_polygons)
17 {
18     return windstate_nonfilled;
19 }
20 windstate_t evenodd_add(windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master)
21 {
22     left.is_filled ^= 1;
23     return left;
24 }
25 fillstyle_t* evenodd_diff(windstate_t*left, windstate_t*right)
26 {
27     if(left->is_filled==right->is_filled)
28         return 0;
29     else
30         return &fillstyle_default;
31 }
32
33 windrule_t windrule_evenodd = {
34     start: evenodd_start,
35     add: evenodd_add,
36     diff: evenodd_diff,
37 };
38
39 // -------------------- circular ----------------------
40
41 windstate_t circular_start(int num_polygons)
42 {
43     return windstate_nonfilled;
44 }
45
46 windstate_t circular_add(windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master)
47 {
48     /* which one is + and which one - doesn't actually make any difference */
49     if(dir == DIR_DOWN)
50         left.wind_nr++;
51     else
52         left.wind_nr--;
53
54     left.is_filled = left.wind_nr != 0;
55     return left;
56 }
57
58 fillstyle_t* circular_diff(windstate_t*left, windstate_t*right)
59 {
60     if(left->is_filled==right->is_filled)
61         return 0;
62     else
63         return &fillstyle_default;
64 }
65
66 windrule_t windrule_circular = {
67     start: circular_start,
68     add: circular_add,
69     diff: circular_diff,
70 };
71
72 // -------------------- intersect ----------------------
73
74 windstate_t intersect_start(int num_polygons)
75 {
76     windstate_t w;
77     w.num_polygons = num_polygons;
78     return w;
79 }
80
81 windstate_t intersect_add(windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master)
82 {
83     assert(master < left.num_polygons);
84
85     left.wind_nr ^= 1<<master;
86     if(left.wind_nr == (1<<left.num_polygons)-1)
87         left.is_filled = 1;
88     return left;
89 }
90
91 fillstyle_t* intersect_diff(windstate_t*left, windstate_t*right)
92 {
93     if(left->is_filled==right->is_filled)
94         return 0;
95     else
96         return &fillstyle_default;
97 }
98
99 windrule_t windrule_intersect = {
100     start: intersect_start,
101     add: intersect_add,
102     diff: intersect_diff,
103 };
104
105 // -------------------- union ----------------------
106
107 windstate_t union_start(int num_polygons)
108 {
109     return windstate_nonfilled;
110 }
111
112 windstate_t union_add(windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master)
113 {
114     assert(master<sizeof(left.wind_nr)*8); //up to 32/64 polygons max
115     left.wind_nr ^= 1<<master;
116     if(left.wind_nr!=0)
117         left.is_filled = 1;
118     return left;
119 }
120
121 fillstyle_t* union_diff(windstate_t*left, windstate_t*right)
122 {
123     if(left->is_filled==right->is_filled)
124         return 0;
125     else
126         return &fillstyle_default;
127 }
128
129 windrule_t windrule_union = {
130     start: union_start,
131     add: union_add,
132     diff: union_diff,
133 };
134
135
136 /* 
137  } else if (rule == WIND_NONZERO) {
138      fill = wind!=0;
139  } else if (rule == WIND_ODDEVEN) {
140      fill = wind&1;
141  } else { // rule == WIND_POSITIVE
142      fill = wind>=1;
143  }
144  */