made gfxpoly_check test for correct circular filling
[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
64         return &edgestyle_default;
65 }
66
67 windrule_t windrule_circular = {
68     start: circular_start,
69     add: circular_add,
70     diff: circular_diff,
71 };
72
73 // -------------------- intersect ----------------------
74
75 windstate_t intersect_start(windcontext_t*context)
76 {
77     return windstate_nonfilled;
78 }
79
80 windstate_t intersect_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
81 {
82     assert(master < context->num_polygons);
83
84     left.wind_nr ^= 1<<master;
85     left.is_filled = (left.wind_nr == (1<<context->num_polygons)-1);
86     return left;
87 }
88
89 edgestyle_t* intersect_diff(windstate_t*left, windstate_t*right)
90 {
91     if(left->is_filled==right->is_filled)
92         return 0;
93     else
94         return &edgestyle_default;
95 }
96
97 windrule_t windrule_intersect = {
98     start: intersect_start,
99     add: intersect_add,
100     diff: intersect_diff,
101 };
102
103 // -------------------- union ----------------------
104
105 windstate_t union_start(windcontext_t*context)
106 {
107     return windstate_nonfilled;
108 }
109
110 windstate_t union_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
111 {
112     assert(master<sizeof(left.wind_nr)*8); //up to 32/64 polygons max
113     left.wind_nr ^= 1<<master;
114     left.is_filled = (left.wind_nr!=0);
115     return left;
116 }
117
118 edgestyle_t* union_diff(windstate_t*left, windstate_t*right)
119 {
120     if(left->is_filled==right->is_filled)
121         return 0;
122     else
123         return &edgestyle_default;
124 }
125
126 windrule_t windrule_union = {
127     start: union_start,
128     add: union_add,
129     diff: union_diff,
130 };
131
132
133 /* 
134  } else if (rule == WIND_NONZERO) {
135      fill = wind!=0;
136  } else if (rule == WIND_ODDEVEN) {
137      fill = wind&1;
138  } else { // rule == WIND_POSITIVE
139      fill = wind>=1;
140  }
141  */