reworked edgestyle logic
[swftools.git] / lib / gfxpoly / wind.c
1 #include "poly.h"
2
3 edgestyle_t edgestyle_default;
4
5 windstate_t windstate_nonfilled = {
6     is_filled: 0,
7     wind_nr: 0,
8 };
9
10 // -------------------- even/odd ----------------------
11
12 windstate_t evenodd_start(windcontext_t*context)
13 {
14     return windstate_nonfilled;
15 }
16 windstate_t evenodd_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
17 {
18     assert(edge);
19     left.is_filled ^= 1;
20     return left;
21 }
22 edgestyle_t* evenodd_diff(windstate_t*left, windstate_t*right)
23 {
24     if(left->is_filled==right->is_filled)
25         return 0;
26     else
27         return &edgestyle_default;
28 }
29
30 windrule_t windrule_evenodd = {
31     start: evenodd_start,
32     add: evenodd_add,
33     diff: evenodd_diff,
34 };
35
36 // -------------------- circular ----------------------
37
38 edgestyle_t edgestyle_down;
39 edgestyle_t edgestyle_up;
40
41 windstate_t circular_start(windcontext_t*context)
42 {
43     return windstate_nonfilled;
44 }
45
46 windstate_t circular_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
47 {
48     assert(edge);
49     /* which one is + and which one - doesn't actually make any difference */
50     if(dir == DIR_DOWN)
51         left.wind_nr++;
52     else
53         left.wind_nr--;
54
55     left.is_filled = left.wind_nr != 0;
56     return left;
57 }
58
59 edgestyle_t* circular_diff(windstate_t*left, windstate_t*right)
60 {
61     if(left->is_filled==right->is_filled) {
62         return 0;
63     } else if(left->is_filled) {
64         return &edgestyle_down;
65     } else {//right->is_filled
66         return &edgestyle_up;
67     }
68 }
69
70 windrule_t windrule_circular = {
71     start: circular_start,
72     add: circular_add,
73     diff: circular_diff,
74 };
75
76 // -------------------- intersect ----------------------
77
78 windstate_t intersect_start(windcontext_t*context)
79 {
80     return windstate_nonfilled;
81 }
82
83 windstate_t intersect_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
84 {
85     assert(master < context->num_polygons);
86
87     left.wind_nr ^= 1<<master;
88     left.is_filled = (left.wind_nr == (1<<context->num_polygons)-1);
89     return left;
90 }
91
92 edgestyle_t* intersect_diff(windstate_t*left, windstate_t*right)
93 {
94     if(left->is_filled==right->is_filled)
95         return 0;
96     else
97         return &edgestyle_default;
98 }
99
100 windrule_t windrule_intersect = {
101     start: intersect_start,
102     add: intersect_add,
103     diff: intersect_diff,
104 };
105
106 // -------------------- union ----------------------
107
108 windstate_t union_start(windcontext_t*context)
109 {
110     return windstate_nonfilled;
111 }
112
113 windstate_t union_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
114 {
115     assert(master<sizeof(left.wind_nr)*8); //up to 32/64 polygons max
116     left.wind_nr ^= 1<<master;
117     left.is_filled = (left.wind_nr!=0);
118     return left;
119 }
120
121 edgestyle_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 &edgestyle_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  */