Merge branch 'horizontals'
[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 windstate_t circular_start(windcontext_t*context)
39 {
40     return windstate_nonfilled;
41 }
42
43 windstate_t circular_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
44 {
45     assert(edge);
46     /* which one is + and which one - doesn't actually make any difference */
47     if(dir == DIR_DOWN)
48         left.wind_nr++;
49     else
50         left.wind_nr--;
51
52     left.is_filled = left.wind_nr != 0;
53     return left;
54 }
55
56 edgestyle_t* circular_diff(windstate_t*left, windstate_t*right)
57 {
58     if(left->is_filled==right->is_filled)
59         return 0;
60     else
61         return &edgestyle_default;
62 }
63
64 windrule_t windrule_circular = {
65     start: circular_start,
66     add: circular_add,
67     diff: circular_diff,
68 };
69
70 // -------------------- intersect ----------------------
71
72 windstate_t intersect_start(windcontext_t*context)
73 {
74     return windstate_nonfilled;
75 }
76
77 windstate_t intersect_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
78 {
79     assert(master < context->num_polygons);
80
81     left.wind_nr ^= 1<<master;
82     left.is_filled = (left.wind_nr == (1<<context->num_polygons)-1);
83     return left;
84 }
85
86 edgestyle_t* intersect_diff(windstate_t*left, windstate_t*right)
87 {
88     if(left->is_filled==right->is_filled)
89         return 0;
90     else
91         return &edgestyle_default;
92 }
93
94 windrule_t windrule_intersect = {
95     start: intersect_start,
96     add: intersect_add,
97     diff: intersect_diff,
98 };
99
100 // -------------------- union ----------------------
101
102 windstate_t union_start(windcontext_t*context)
103 {
104     return windstate_nonfilled;
105 }
106
107 windstate_t union_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
108 {
109     assert(master<sizeof(left.wind_nr)*8); //up to 32/64 polygons max
110     left.wind_nr ^= 1<<master;
111     left.is_filled = (left.wind_nr!=0);
112     return left;
113 }
114
115 edgestyle_t* union_diff(windstate_t*left, windstate_t*right)
116 {
117     if(left->is_filled==right->is_filled)
118         return 0;
119     else
120         return &edgestyle_default;
121 }
122
123 windrule_t windrule_union = {
124     start: union_start,
125     add: union_add,
126     diff: union_diff,
127 };
128
129
130 /* 
131  } else if (rule == WIND_NONZERO) {
132      fill = wind!=0;
133  } else if (rule == WIND_ODDEVEN) {
134      fill = wind&1;
135  } else { // rule == WIND_POSITIVE
136      fill = wind>=1;
137  }
138  */