fixed off-by-one bug
[swftools.git] / lib / gfxpoly / wind.c
blob30a21fd24d9763c30b1030e2a8890d5cc2547b0e
1 #include "poly.h"
3 edgestyle_t edgestyle_default;
5 windstate_t windstate_nonfilled = {
6 is_filled: 0,
7 wind_nr: 0,
8 };
10 // -------------------- even/odd ----------------------
12 windstate_t evenodd_start(windcontext_t*context)
14 return windstate_nonfilled;
16 windstate_t evenodd_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
18 assert(edge);
19 left.is_filled ^= 1;
20 return left;
22 edgestyle_t* evenodd_diff(windstate_t*left, windstate_t*right)
24 if(left->is_filled==right->is_filled)
25 return 0;
26 else
27 return &edgestyle_default;
30 windrule_t windrule_evenodd = {
31 start: evenodd_start,
32 add: evenodd_add,
33 diff: evenodd_diff,
36 // -------------------- circular ----------------------
38 windstate_t circular_start(windcontext_t*context)
40 return windstate_nonfilled;
43 windstate_t circular_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
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--;
52 left.is_filled = left.wind_nr != 0;
53 return left;
56 edgestyle_t* circular_diff(windstate_t*left, windstate_t*right)
58 if(left->is_filled==right->is_filled)
59 return 0;
60 else
61 return &edgestyle_default;
64 windrule_t windrule_circular = {
65 start: circular_start,
66 add: circular_add,
67 diff: circular_diff,
70 // -------------------- intersect ----------------------
72 windstate_t intersect_start(windcontext_t*context)
74 return windstate_nonfilled;
77 windstate_t intersect_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
79 assert(master < context->num_polygons);
81 left.wind_nr ^= 1<<master;
82 left.is_filled = (left.wind_nr == (1<<context->num_polygons)-1);
83 return left;
86 edgestyle_t* intersect_diff(windstate_t*left, windstate_t*right)
88 if(left->is_filled==right->is_filled)
89 return 0;
90 else
91 return &edgestyle_default;
94 windrule_t windrule_intersect = {
95 start: intersect_start,
96 add: intersect_add,
97 diff: intersect_diff,
100 // -------------------- union ----------------------
102 windstate_t union_start(windcontext_t*context)
104 return windstate_nonfilled;
107 windstate_t union_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master)
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;
115 edgestyle_t* union_diff(windstate_t*left, windstate_t*right)
117 if(left->is_filled==right->is_filled)
118 return 0;
119 else
120 return &edgestyle_default;
123 windrule_t windrule_union = {
124 start: union_start,
125 add: union_add,
126 diff: union_diff,
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;