small bugfixes and memory optimizations
[swftools.git] / lib / gfxpoly / wind.c
1 #include "wind.h"
2
3 fillstyle_t fillstyle_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, fillstyle_t*edge, segment_dir_t dir, int master)
17 {
18     left.is_filled ^= 1;
19     return left;
20 }
21 fillstyle_t* evenodd_diff(windstate_t*left, windstate_t*right)
22 {
23     if(left->is_filled==right->is_filled)
24         return 0;
25     else
26         return &fillstyle_default;
27 }
28
29 windrule_t windrule_evenodd = {
30     start: evenodd_start,
31     add: evenodd_add,
32     diff: evenodd_diff,
33 };
34
35 // -------------------- circular ----------------------
36
37 windstate_t circular_start(windcontext_t*context)
38 {
39     return windstate_nonfilled;
40 }
41
42 windstate_t circular_add(windcontext_t*context, windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master)
43 {
44     /* which one is + and which one - doesn't actually make any difference */
45     if(dir == DIR_DOWN)
46         left.wind_nr++;
47     else
48         left.wind_nr--;
49
50     left.is_filled = left.wind_nr != 0;
51     return left;
52 }
53
54 fillstyle_t* circular_diff(windstate_t*left, windstate_t*right)
55 {
56     if(left->is_filled==right->is_filled)
57         return 0;
58     else
59         return &fillstyle_default;
60 }
61
62 windrule_t windrule_circular = {
63     start: circular_start,
64     add: circular_add,
65     diff: circular_diff,
66 };
67
68 // -------------------- intersect ----------------------
69
70 windstate_t intersect_start(windcontext_t*context)
71 {
72     windstate_t w;
73     return w;
74 }
75
76 windstate_t intersect_add(windcontext_t*context, windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master)
77 {
78     assert(master < context->num_polygons);
79
80     left.wind_nr ^= 1<<master;
81     if(left.wind_nr == (1<<context->num_polygons)-1)
82         left.is_filled = 1;
83     return left;
84 }
85
86 fillstyle_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 &fillstyle_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, fillstyle_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     if(left.wind_nr!=0)
112         left.is_filled = 1;
113     return left;
114 }
115
116 fillstyle_t* union_diff(windstate_t*left, windstate_t*right)
117 {
118     if(left->is_filled==right->is_filled)
119         return 0;
120     else
121         return &fillstyle_default;
122 }
123
124 windrule_t windrule_union = {
125     start: union_start,
126     add: union_add,
127     diff: union_diff,
128 };
129
130
131 /* 
132  } else if (rule == WIND_NONZERO) {
133      fill = wind!=0;
134  } else if (rule == WIND_ODDEVEN) {
135      fill = wind&1;
136  } else { // rule == WIND_POSITIVE
137      fill = wind>=1;
138  }
139  */