| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#define IMAGER_NO_CONTEXT |
|
2
|
|
|
|
|
|
|
#include "imager.h" |
|
3
|
|
|
|
|
|
|
#include "draw.h" |
|
4
|
|
|
|
|
|
|
#include "log.h" |
|
5
|
|
|
|
|
|
|
#include "imrender.h" |
|
6
|
|
|
|
|
|
|
#include "imageri.h" |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
#define IMTRUNC(x) ((int)((x)*16)) |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#define coarse(x) ((x)/16) |
|
11
|
|
|
|
|
|
|
#define fine(x) ((x)%16) |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
/*#define DEBUG_POLY*/ |
|
14
|
|
|
|
|
|
|
#ifdef DEBUG_POLY |
|
15
|
|
|
|
|
|
|
#define POLY_DEB(x) x |
|
16
|
|
|
|
|
|
|
#else |
|
17
|
|
|
|
|
|
|
#define POLY_DEB(x) |
|
18
|
|
|
|
|
|
|
#endif |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
typedef i_img_dim pcord; |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
typedef struct { |
|
24
|
|
|
|
|
|
|
size_t n; |
|
25
|
|
|
|
|
|
|
pcord x,y; |
|
26
|
|
|
|
|
|
|
} p_point; |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
typedef struct { |
|
29
|
|
|
|
|
|
|
size_t n; |
|
30
|
|
|
|
|
|
|
pcord x1,y1; |
|
31
|
|
|
|
|
|
|
pcord x2,y2; |
|
32
|
|
|
|
|
|
|
pcord miny,maxy; |
|
33
|
|
|
|
|
|
|
pcord minx,maxx; |
|
34
|
|
|
|
|
|
|
int updown; /* -1 means down, 0 vertical, 1 up */ |
|
35
|
|
|
|
|
|
|
int dir; /* 1 for down, -1 for up */ |
|
36
|
|
|
|
|
|
|
} p_line; |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
typedef struct { |
|
39
|
|
|
|
|
|
|
size_t n; |
|
40
|
|
|
|
|
|
|
double x; |
|
41
|
|
|
|
|
|
|
} p_slice; |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
typedef struct { |
|
44
|
|
|
|
|
|
|
int *line; /* temporary buffer for scanline */ |
|
45
|
|
|
|
|
|
|
i_img_dim linelen; /* length of scanline */ |
|
46
|
|
|
|
|
|
|
} ss_scanline; |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
static |
|
49
|
|
|
|
|
|
|
int |
|
50
|
7353
|
|
|
|
|
|
p_compy(const p_point *p1, const p_point *p2) { |
|
51
|
7353
|
100
|
|
|
|
|
if (p1->y > p2->y) return 1; |
|
52
|
3396
|
100
|
|
|
|
|
if (p1->y < p2->y) return -1; |
|
53
|
551
|
|
|
|
|
|
return 0; |
|
54
|
|
|
|
|
|
|
} |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
static |
|
57
|
|
|
|
|
|
|
int |
|
58
|
4052
|
|
|
|
|
|
p_compx(const p_slice *p1, const p_slice *p2) { |
|
59
|
4052
|
100
|
|
|
|
|
if (p1->x > p2->x) return 1; |
|
60
|
1824
|
100
|
|
|
|
|
if (p1->x < p2->x) return -1; |
|
61
|
14
|
|
|
|
|
|
return 0; |
|
62
|
|
|
|
|
|
|
} |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
/* Change this to int? and round right goddamn it! */ |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
static |
|
67
|
|
|
|
|
|
|
double |
|
68
|
93277
|
|
|
|
|
|
p_eval_aty(p_line *l, pcord y) { |
|
69
|
|
|
|
|
|
|
int t; |
|
70
|
93277
|
|
|
|
|
|
t=l->y2-l->y1; |
|
71
|
93277
|
50
|
|
|
|
|
if (t) return ( (y-l->y1)*l->x2 + (l->y2-y)*l->x1 )/t; |
|
72
|
0
|
|
|
|
|
|
return (l->x1+l->x2)/2.0; |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
static |
|
76
|
|
|
|
|
|
|
double |
|
77
|
57255
|
|
|
|
|
|
p_eval_atx(p_line *l, pcord x) { |
|
78
|
|
|
|
|
|
|
int t; |
|
79
|
57255
|
|
|
|
|
|
t = l->x2-l->x1; |
|
80
|
57255
|
50
|
|
|
|
|
if (t) return ( (x-l->x1)*l->y2 + (l->x2-x)*l->y1 )/t; |
|
81
|
0
|
|
|
|
|
|
return (l->y1+l->y2)/2.0; |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
static |
|
85
|
|
|
|
|
|
|
p_line * |
|
86
|
97
|
|
|
|
|
|
line_set_new(const i_polygon_t *polys, size_t count, size_t *line_count) { |
|
87
|
|
|
|
|
|
|
size_t i, j, n; |
|
88
|
|
|
|
|
|
|
p_line *lset, *line; |
|
89
|
97
|
|
|
|
|
|
size_t lines = 0; |
|
90
|
|
|
|
|
|
|
|
|
91
|
202
|
100
|
|
|
|
|
for (i = 0; i < count; ++i) |
|
92
|
105
|
|
|
|
|
|
lines += polys[i].count; |
|
93
|
|
|
|
|
|
|
|
|
94
|
97
|
|
|
|
|
|
line = lset = mymalloc(sizeof(p_line) * lines); |
|
95
|
|
|
|
|
|
|
|
|
96
|
97
|
|
|
|
|
|
n = 0; |
|
97
|
202
|
100
|
|
|
|
|
for (i = 0; i < count; ++i) { |
|
98
|
105
|
|
|
|
|
|
const i_polygon_t *p = polys + i; |
|
99
|
|
|
|
|
|
|
|
|
100
|
2077
|
100
|
|
|
|
|
for(j = 0; j < p->count; j++) { |
|
101
|
1972
|
|
|
|
|
|
line->x1 = IMTRUNC(p->x[j]); |
|
102
|
1972
|
|
|
|
|
|
line->y1 = IMTRUNC(p->y[j]); |
|
103
|
1972
|
|
|
|
|
|
line->x2 = IMTRUNC(p->x[(j + 1) % p->count]); |
|
104
|
1972
|
|
|
|
|
|
line->y2 = IMTRUNC(p->y[(j + 1) % p->count]); |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
/* don't include purely horizontal lines, we don't usefully |
|
107
|
|
|
|
|
|
|
intersect with them. */ |
|
108
|
1972
|
100
|
|
|
|
|
if (line->y1 == line->y2) |
|
109
|
94
|
|
|
|
|
|
continue; |
|
110
|
|
|
|
|
|
|
|
|
111
|
1878
|
|
|
|
|
|
line->miny = i_min(line->y1, line->y2); |
|
112
|
1878
|
|
|
|
|
|
line->maxy = i_max(line->y1, line->y2); |
|
113
|
1878
|
|
|
|
|
|
line->minx = i_min(line->x1, line->x2); |
|
114
|
1878
|
|
|
|
|
|
line->maxx = i_max(line->x1, line->x2); |
|
115
|
1878
|
|
|
|
|
|
line->n = n++; |
|
116
|
1878
|
|
|
|
|
|
++line; |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
} |
|
119
|
97
|
|
|
|
|
|
*line_count = n; |
|
120
|
|
|
|
|
|
|
|
|
121
|
97
|
|
|
|
|
|
return lset; |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
static |
|
125
|
|
|
|
|
|
|
p_point * |
|
126
|
97
|
|
|
|
|
|
point_set_new(const i_polygon_t *polys, size_t count, size_t *point_count) { |
|
127
|
|
|
|
|
|
|
size_t i, j, n; |
|
128
|
|
|
|
|
|
|
p_point *pset, *pt; |
|
129
|
97
|
|
|
|
|
|
size_t points = 0; |
|
130
|
|
|
|
|
|
|
|
|
131
|
202
|
100
|
|
|
|
|
for (i = 0; i < count; ++i) |
|
132
|
105
|
|
|
|
|
|
points += polys[i].count; |
|
133
|
|
|
|
|
|
|
|
|
134
|
97
|
|
|
|
|
|
*point_count = points; |
|
135
|
|
|
|
|
|
|
|
|
136
|
97
|
|
|
|
|
|
pt = pset = mymalloc(sizeof(p_point) * points); |
|
137
|
|
|
|
|
|
|
|
|
138
|
97
|
|
|
|
|
|
n = 0; |
|
139
|
202
|
100
|
|
|
|
|
for (i = 0; i < count; ++i) { |
|
140
|
105
|
|
|
|
|
|
const i_polygon_t *p = polys + i; |
|
141
|
|
|
|
|
|
|
|
|
142
|
2077
|
100
|
|
|
|
|
for(j = 0; j < p->count; j++) { |
|
143
|
1972
|
|
|
|
|
|
pt->n = n++; |
|
144
|
1972
|
|
|
|
|
|
pt->x = IMTRUNC(p->x[j]); |
|
145
|
1972
|
|
|
|
|
|
pt->y = IMTRUNC(p->y[j]); |
|
146
|
1972
|
|
|
|
|
|
++pt; |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
} |
|
149
|
97
|
|
|
|
|
|
return pset; |
|
150
|
|
|
|
|
|
|
} |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
static |
|
153
|
|
|
|
|
|
|
void |
|
154
|
5419
|
|
|
|
|
|
ss_scanline_reset(ss_scanline *ss) { |
|
155
|
5419
|
|
|
|
|
|
memset(ss->line, 0, sizeof(int) * ss->linelen); |
|
156
|
5419
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
static |
|
159
|
|
|
|
|
|
|
void |
|
160
|
97
|
|
|
|
|
|
ss_scanline_init(ss_scanline *ss, i_img_dim linelen, int linepairs) { |
|
161
|
97
|
|
|
|
|
|
ss->line = mymalloc( sizeof(int) * linelen ); |
|
162
|
97
|
|
|
|
|
|
ss->linelen = linelen; |
|
163
|
97
|
|
|
|
|
|
ss_scanline_reset(ss); |
|
164
|
97
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
static |
|
167
|
|
|
|
|
|
|
void |
|
168
|
97
|
|
|
|
|
|
ss_scanline_exorcise(ss_scanline *ss) { |
|
169
|
97
|
|
|
|
|
|
myfree(ss->line); |
|
170
|
97
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
/* returns the number of matches */ |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
static |
|
178
|
|
|
|
|
|
|
int |
|
179
|
1357
|
|
|
|
|
|
lines_in_interval(p_line *lset, int l, p_slice *tllist, pcord minc, pcord maxc) { |
|
180
|
|
|
|
|
|
|
int k; |
|
181
|
1357
|
|
|
|
|
|
int count = 0; |
|
182
|
179922
|
100
|
|
|
|
|
for(k=0; k
|
|
183
|
178565
|
100
|
|
|
|
|
if (lset[k].maxy > minc && lset[k].miny < maxc) { |
|
|
|
100
|
|
|
|
|
|
|
184
|
4298
|
50
|
|
|
|
|
if (lset[k].miny == lset[k].maxy) { |
|
185
|
|
|
|
|
|
|
POLY_DEB( printf(" HORIZONTAL - skipped\n") ); |
|
186
|
|
|
|
|
|
|
} else { |
|
187
|
4298
|
|
|
|
|
|
tllist[count].x=p_eval_aty(&lset[k],(minc+maxc)/2.0 ); |
|
188
|
4298
|
|
|
|
|
|
tllist[count].n=k; |
|
189
|
4298
|
|
|
|
|
|
count++; |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
} |
|
192
|
|
|
|
|
|
|
} |
|
193
|
1357
|
|
|
|
|
|
return count; |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
/* marks the up variable for all lines in a slice */ |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
static |
|
199
|
|
|
|
|
|
|
void |
|
200
|
1357
|
|
|
|
|
|
mark_updown_slices(pIMCTX, p_line *lset, p_slice *tllist, int count) { |
|
201
|
|
|
|
|
|
|
p_line *l, *r; |
|
202
|
|
|
|
|
|
|
int k; |
|
203
|
3506
|
100
|
|
|
|
|
for(k=0; k
|
|
204
|
2149
|
|
|
|
|
|
l = lset + tllist[k].n; |
|
205
|
|
|
|
|
|
|
|
|
206
|
2149
|
50
|
|
|
|
|
if (l->y1 == l->y2) { |
|
207
|
0
|
|
|
|
|
|
im_log((aIMCTX,1, "mark_updown_slices: horizontal line being marked: internal error!\n")); |
|
208
|
0
|
|
|
|
|
|
exit(3); |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
|
|
211
|
4298
|
|
|
|
|
|
l->updown = (l->x1 == l->x2) ? |
|
212
|
4220
|
100
|
|
|
|
|
0 : |
|
213
|
2071
|
|
|
|
|
|
(l->x1 > l->x2) |
|
214
|
|
|
|
|
|
|
? |
|
215
|
1053
|
100
|
|
|
|
|
(l->y1 > l->y2) ? -1 : 1 |
|
216
|
4142
|
100
|
|
|
|
|
: |
|
217
|
1018
|
100
|
|
|
|
|
(l->y1 > l->y2) ? 1 : -1; |
|
218
|
2149
|
100
|
|
|
|
|
l->dir = l->y1 < l->y2 ? 1 : -1; |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
POLY_DEB( printf("marking left line %d as %s(%d)\n", l->n, |
|
221
|
|
|
|
|
|
|
l->updown ? l->updown == 1 ? "up" : "down" : "vert", l->updown, l->updown) |
|
222
|
|
|
|
|
|
|
); |
|
223
|
|
|
|
|
|
|
|
|
224
|
2149
|
50
|
|
|
|
|
if (k+1 >= count) { |
|
225
|
0
|
|
|
|
|
|
im_log((aIMCTX, 1, "Invalid polygon spec, odd number of line crossings.\n")); |
|
226
|
0
|
|
|
|
|
|
return; |
|
227
|
|
|
|
|
|
|
} |
|
228
|
|
|
|
|
|
|
|
|
229
|
2149
|
|
|
|
|
|
r = lset + tllist[k+1].n; |
|
230
|
2149
|
50
|
|
|
|
|
if (r->y1 == r->y2) { |
|
231
|
0
|
|
|
|
|
|
im_log((aIMCTX, 1, "mark_updown_slices: horizontal line being marked: internal error!\n")); |
|
232
|
0
|
|
|
|
|
|
exit(3); |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
|
|
235
|
4298
|
|
|
|
|
|
r->updown = (r->x1 == r->x2) ? |
|
236
|
4239
|
100
|
|
|
|
|
0 : |
|
237
|
2090
|
|
|
|
|
|
(r->x1 > r->x2) |
|
238
|
|
|
|
|
|
|
? |
|
239
|
1041
|
100
|
|
|
|
|
(r->y1 > r->y2) ? -1 : 1 |
|
240
|
4180
|
100
|
|
|
|
|
: |
|
241
|
1049
|
100
|
|
|
|
|
(r->y1 > r->y2) ? 1 : -1; |
|
242
|
2149
|
100
|
|
|
|
|
r->dir = r->y1 < r->y2 ? 1 : -1; |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
POLY_DEB( printf("marking right line %d as %s(%d)\n", r->n, |
|
245
|
|
|
|
|
|
|
r->updown ? r->updown == 1 ? "up" : "down" : "vert", r->updown, r->updown) |
|
246
|
|
|
|
|
|
|
); |
|
247
|
|
|
|
|
|
|
} |
|
248
|
|
|
|
|
|
|
} |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
static |
|
251
|
|
|
|
|
|
|
unsigned char |
|
252
|
1672998
|
|
|
|
|
|
saturate(int in) { |
|
253
|
1672998
|
100
|
|
|
|
|
if (in>255) { return 255; } |
|
254
|
1484294
|
100
|
|
|
|
|
else if (in>0) return in; |
|
255
|
1465094
|
|
|
|
|
|
return 0; |
|
256
|
|
|
|
|
|
|
} |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
typedef void (*scanline_flusher)(i_img *im, ss_scanline *ss, int y, void *ctx); |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
/* This function must be modified later to do proper blending */ |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
static void |
|
263
|
4782
|
|
|
|
|
|
scanline_flush(i_img *im, ss_scanline *ss, int y, void *ctx) { |
|
264
|
|
|
|
|
|
|
int x, ch, tv; |
|
265
|
|
|
|
|
|
|
i_color t; |
|
266
|
4782
|
|
|
|
|
|
i_color *val = (i_color *)ctx; |
|
267
|
|
|
|
|
|
|
POLY_DEB( printf("Flushing line %d\n", y) ); |
|
268
|
1620262
|
100
|
|
|
|
|
for(x=0; xxsize; x++) { |
|
269
|
1615480
|
|
|
|
|
|
tv = saturate(ss->line[x]); |
|
270
|
1615480
|
|
|
|
|
|
i_gpix(im, x, y, &t); |
|
271
|
6461920
|
100
|
|
|
|
|
for(ch=0; chchannels; ch++) |
|
272
|
4846440
|
|
|
|
|
|
t.channel[ch] = tv/255.0 * val->channel[ch] + (1.0-tv/255.0) * t.channel[ch]; |
|
273
|
1615480
|
|
|
|
|
|
i_ppix(im, x, y, &t); |
|
274
|
|
|
|
|
|
|
} |
|
275
|
4782
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
static |
|
280
|
|
|
|
|
|
|
int |
|
281
|
5731
|
|
|
|
|
|
trap_square(pcord xlen, pcord ylen, double xl, double yl) { |
|
282
|
|
|
|
|
|
|
POLY_DEB( printf("trap_square: %d %d %.2f %.2f\n", xlen, ylen, xl, yl) ); |
|
283
|
5731
|
|
|
|
|
|
return xlen*ylen-(xl*yl)/2.0; |
|
284
|
|
|
|
|
|
|
} |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
/* |
|
288
|
|
|
|
|
|
|
pixel_coverage calculates the 'left side' pixel coverage of a pixel that is |
|
289
|
|
|
|
|
|
|
within the min/max ranges. The shape always corresponds to a square with some |
|
290
|
|
|
|
|
|
|
sort of a triangle cut from it (which can also yield a triangle). |
|
291
|
|
|
|
|
|
|
*/ |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
static |
|
295
|
|
|
|
|
|
|
int |
|
296
|
23091
|
|
|
|
|
|
pixel_coverage(p_line *line, pcord minx, pcord maxx, pcord miny, pcord maxy) { |
|
297
|
|
|
|
|
|
|
double lycross, rycross; |
|
298
|
|
|
|
|
|
|
int l, r; |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
POLY_DEB |
|
301
|
|
|
|
|
|
|
( |
|
302
|
|
|
|
|
|
|
printf(" pixel_coverage(..., minx %g, maxx%g, miny %g, maxy %g)\n", |
|
303
|
|
|
|
|
|
|
minx/16.0, maxx/16.0, miny/16.0, maxy/16.0) |
|
304
|
|
|
|
|
|
|
); |
|
305
|
|
|
|
|
|
|
|
|
306
|
23091
|
100
|
|
|
|
|
if (!line->updown) { |
|
307
|
520
|
|
|
|
|
|
l = r = 0; |
|
308
|
|
|
|
|
|
|
} else { |
|
309
|
22571
|
|
|
|
|
|
lycross = p_eval_atx(line, minx); |
|
310
|
22571
|
|
|
|
|
|
rycross = p_eval_atx(line, maxx); |
|
311
|
22571
|
100
|
|
|
|
|
l = lycross <= maxy && lycross >= miny; /* true if it enters through left side */ |
|
|
|
100
|
|
|
|
|
|
|
312
|
22571
|
100
|
|
|
|
|
r = rycross <= maxy && rycross >= miny; /* true if it enters through left side */ |
|
|
|
100
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
} |
|
314
|
|
|
|
|
|
|
POLY_DEB( |
|
315
|
|
|
|
|
|
|
printf(" %4s(%+d): ", line->updown ? line->updown == 1 ? "up" : "down" : "vert", line->updown); |
|
316
|
|
|
|
|
|
|
printf(" (%2d,%2d) [%3d-%3d, %3d-%3d] lycross=%.2f rycross=%.2f", coarse(minx), coarse(miny), minx, maxx, miny, maxy, lycross, rycross); |
|
317
|
|
|
|
|
|
|
printf(" l=%d r=%d\n", l, r) |
|
318
|
|
|
|
|
|
|
); |
|
319
|
|
|
|
|
|
|
|
|
320
|
23091
|
100
|
|
|
|
|
if (l && r) |
|
|
|
100
|
|
|
|
|
|
|
321
|
4237
|
100
|
|
|
|
|
return line->updown == 1 ? |
|
322
|
2016
|
|
|
|
|
|
(double)(maxx-minx) * (2.0*maxy-lycross-rycross)/2.0 /* up case */ |
|
323
|
|
|
|
|
|
|
: |
|
324
|
2221
|
|
|
|
|
|
(double)(maxx-minx) * (lycross+rycross-2*miny)/2.0; /* down case */ |
|
325
|
|
|
|
|
|
|
|
|
326
|
18854
|
100
|
|
|
|
|
if (!l && !r) return (maxy-miny)*(maxx*2-p_eval_aty(line, miny)-p_eval_aty(line, maxy))/2.0; |
|
|
|
100
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
|
|
328
|
12113
|
100
|
|
|
|
|
if (l && !r) |
|
|
|
50
|
|
|
|
|
|
|
329
|
5731
|
|
|
|
|
|
return line->updown == 1 ? |
|
330
|
8165
|
100
|
|
|
|
|
trap_square(maxx-minx, maxy-miny, p_eval_aty(line, miny)-minx, p_eval_atx(line, minx)-miny) : |
|
331
|
2434
|
|
|
|
|
|
trap_square(maxx-minx, maxy-miny, p_eval_aty(line, maxy)-minx, maxy-p_eval_atx(line, minx)); |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
|
|
334
|
6382
|
50
|
|
|
|
|
if (!l && r) { |
|
|
|
50
|
|
|
|
|
|
|
335
|
12764
|
100
|
|
|
|
|
int r = line->updown == 1 ? |
|
336
|
3194
|
|
|
|
|
|
(maxx-p_eval_aty(line, maxy))*(maxy-p_eval_atx(line, maxx))/2.0 : |
|
337
|
3188
|
|
|
|
|
|
(maxx-p_eval_aty(line, miny))*(p_eval_atx(line, maxx)-miny)/2.0; |
|
338
|
6382
|
|
|
|
|
|
return r; |
|
339
|
|
|
|
|
|
|
} |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
/* NOTREACHED */ |
|
342
|
0
|
|
|
|
|
|
return 0; /* silence compiler warning */ |
|
343
|
|
|
|
|
|
|
} |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
/* |
|
350
|
|
|
|
|
|
|
handle the scanline slice in three steps |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
1. Where only the left edge is inside a pixel |
|
353
|
|
|
|
|
|
|
2a. Where both left and right edge are inside a pixel |
|
354
|
|
|
|
|
|
|
2b. Where neither left or right edge are inside a pixel |
|
355
|
|
|
|
|
|
|
3. Where only the right edge is inside a pixel |
|
356
|
|
|
|
|
|
|
*/ |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
static |
|
359
|
|
|
|
|
|
|
void |
|
360
|
7923
|
|
|
|
|
|
render_slice_scanline(ss_scanline *ss, int y, p_line *l, p_line *r, pcord miny, pcord maxy) { |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
pcord lminx, lmaxx; /* left line min/max within y bounds in fine coords */ |
|
363
|
|
|
|
|
|
|
pcord rminx, rmaxx; /* right line min/max within y bounds in fine coords */ |
|
364
|
|
|
|
|
|
|
i_img_dim cpix; /* x-coordinate of current pixel */ |
|
365
|
|
|
|
|
|
|
i_img_dim startpix; /* temporary variable for "start of this interval" */ |
|
366
|
|
|
|
|
|
|
i_img_dim stoppix; /* temporary variable for "end of this interval" */ |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
/* Find the y bounds of scanline_slice */ |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
POLY_DEB |
|
371
|
|
|
|
|
|
|
( |
|
372
|
|
|
|
|
|
|
printf("render_slice_scanline(..., y=%d)\n"); |
|
373
|
|
|
|
|
|
|
printf(" left n=%d p1(%.2g, %.2g) p2(%.2g,%.2g) min(%.2g, %.2g) max(%.2g,%.2g) updown(%d)\n", |
|
374
|
|
|
|
|
|
|
l->n, l->x1/16.0, l->y1/16.0, l->x2/16.0, l->y2/16.0, |
|
375
|
|
|
|
|
|
|
l->minx/16.0, l->miny/16.0, l->maxx/16.0, l->maxy/16.0, |
|
376
|
|
|
|
|
|
|
l->updown); |
|
377
|
|
|
|
|
|
|
printf(" right n=%d p1(%.2g, %.2g) p2(%.2g,%.2g) min(%.2g, %.2g) max(%.2g,%.2g) updown(%d)\n", |
|
378
|
|
|
|
|
|
|
r->n, r->x1/16.0, r->y1/16.0, r->x2/16.0, r->y2/16.0, |
|
379
|
|
|
|
|
|
|
r->minx/16.0, r->miny/16.0, r->maxx/16.0, r->maxy/16.0, |
|
380
|
|
|
|
|
|
|
r->updown); |
|
381
|
|
|
|
|
|
|
); |
|
382
|
|
|
|
|
|
|
|
|
383
|
7923
|
|
|
|
|
|
lminx = i_min( p_eval_aty(l, maxy), p_eval_aty(l, miny) ); |
|
384
|
7923
|
|
|
|
|
|
lmaxx = i_max( p_eval_aty(l, maxy), p_eval_aty(l, miny) ); |
|
385
|
|
|
|
|
|
|
|
|
386
|
7923
|
|
|
|
|
|
rminx = i_min( p_eval_aty(r, maxy), p_eval_aty(r, miny) ); |
|
387
|
7923
|
|
|
|
|
|
rmaxx = i_max( p_eval_aty(r, maxy), p_eval_aty(r, miny) ); |
|
388
|
|
|
|
|
|
|
|
|
389
|
7923
|
|
|
|
|
|
startpix = i_max( coarse(lminx), 0 ); |
|
390
|
7923
|
|
|
|
|
|
stoppix = i_min( coarse(rmaxx-1), ss->linelen-1 ); |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
POLY_DEB( printf(" miny=%g maxy=%g\n", miny/16.0, maxy/16.0) ); |
|
393
|
|
|
|
|
|
|
|
|
394
|
290282
|
100
|
|
|
|
|
for(cpix=startpix; cpix<=stoppix; cpix++) { |
|
395
|
282359
|
|
|
|
|
|
int lt = coarse(lmaxx-1) >= cpix; |
|
396
|
282359
|
|
|
|
|
|
int rt = coarse(rminx) <= cpix; |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
int A, B, C; |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
POLY_DEB( printf(" (%d,%d) lt=%d rt=%d\n", cpix, y, lt, rt) ); |
|
401
|
|
|
|
|
|
|
|
|
402
|
282359
|
100
|
|
|
|
|
A = lt ? pixel_coverage(l, cpix*16, cpix*16+16, miny, maxy) : 0; |
|
403
|
282359
|
100
|
|
|
|
|
B = lt ? 0 : 16*(maxy-miny); |
|
404
|
282359
|
100
|
|
|
|
|
C = rt ? pixel_coverage(r, cpix*16, cpix*16+16, miny, maxy) : 0; |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
POLY_DEB( printf(" A=%d B=%d C=%d\n", A, B, C) ); |
|
407
|
|
|
|
|
|
|
|
|
408
|
282359
|
|
|
|
|
|
ss->line[cpix] += A+B-C; |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
} |
|
411
|
|
|
|
|
|
|
POLY_DEB( printf("end render_slice_scanline()\n") ); |
|
412
|
7923
|
|
|
|
|
|
} |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
/* Antialiasing polygon algorithm |
|
415
|
|
|
|
|
|
|
specs: |
|
416
|
|
|
|
|
|
|
1. only nice polygons - no crossovers |
|
417
|
|
|
|
|
|
|
2. 1/16 pixel resolution |
|
418
|
|
|
|
|
|
|
3. full antialiasing ( complete spectrum of blends ) |
|
419
|
|
|
|
|
|
|
4. uses hardly any memory |
|
420
|
|
|
|
|
|
|
5. no subsampling phase |
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
Algorithm outline: |
|
424
|
|
|
|
|
|
|
1. Split into vertical intervals. |
|
425
|
|
|
|
|
|
|
2. handle each interval |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
For each interval we must: |
|
428
|
|
|
|
|
|
|
1. find which lines are in it |
|
429
|
|
|
|
|
|
|
2. order the lines from in increasing x order. |
|
430
|
|
|
|
|
|
|
since we are assuming no crossovers it is sufficent |
|
431
|
|
|
|
|
|
|
to check a single point on each line. |
|
432
|
|
|
|
|
|
|
*/ |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
/* |
|
435
|
|
|
|
|
|
|
Definitions: |
|
436
|
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
1. Interval: A vertical segment in which no lines cross nor end. |
|
438
|
|
|
|
|
|
|
2. Scanline: A physical line, contains 16 subpixels in the horizontal direction |
|
439
|
|
|
|
|
|
|
3. Slice: A start stop line pair. |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
*/ |
|
442
|
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
static int |
|
445
|
99
|
|
|
|
|
|
i_poly_poly_aa_low(i_img *im, int count, const i_polygon_t *polys, |
|
446
|
|
|
|
|
|
|
i_poly_fill_mode_t mode, void *ctx, |
|
447
|
|
|
|
|
|
|
scanline_flusher flusher) { |
|
448
|
|
|
|
|
|
|
int i ,k; /* Index variables */ |
|
449
|
|
|
|
|
|
|
i_img_dim clc; /* Lines inside current interval */ |
|
450
|
|
|
|
|
|
|
/* initialize to avoid compiler warnings */ |
|
451
|
99
|
|
|
|
|
|
pcord tempy = 0; |
|
452
|
99
|
|
|
|
|
|
i_img_dim cscl = 0; /* Current scanline */ |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
ss_scanline templine; /* scanline accumulator */ |
|
455
|
|
|
|
|
|
|
p_point *pset; /* List of points in polygon */ |
|
456
|
|
|
|
|
|
|
p_line *lset; /* List of lines in polygon */ |
|
457
|
|
|
|
|
|
|
p_slice *tllist; /* List of slices */ |
|
458
|
|
|
|
|
|
|
size_t pcount, lcount; |
|
459
|
99
|
|
|
|
|
|
dIMCTX; |
|
460
|
|
|
|
|
|
|
|
|
461
|
99
|
|
|
|
|
|
im_log((aIMCTX, 1, "i_poly_poly_aa_low(im %p, count %d, polys %p, ctx %p, flusher %p)\n", im, count, polys, ctx, flusher)); |
|
462
|
|
|
|
|
|
|
|
|
463
|
99
|
|
|
|
|
|
i_clear_error(); |
|
464
|
|
|
|
|
|
|
|
|
465
|
99
|
50
|
|
|
|
|
if (count < 1) { |
|
466
|
0
|
|
|
|
|
|
i_push_error(0, "no polygons to draw"); |
|
467
|
0
|
|
|
|
|
|
return 0; |
|
468
|
|
|
|
|
|
|
} |
|
469
|
|
|
|
|
|
|
|
|
470
|
204
|
100
|
|
|
|
|
for (k = 0; k < count; ++k) { |
|
471
|
107
|
100
|
|
|
|
|
if (polys[k].count < 3) { |
|
472
|
2
|
|
|
|
|
|
i_push_error(0, "polygons must have at least 3 points"); |
|
473
|
2
|
|
|
|
|
|
return 0; |
|
474
|
|
|
|
|
|
|
} |
|
475
|
|
|
|
|
|
|
} |
|
476
|
|
|
|
|
|
|
|
|
477
|
202
|
100
|
|
|
|
|
for (k = 0; k < count; ++k) { |
|
478
|
105
|
|
|
|
|
|
const i_polygon_t *p = polys + k; |
|
479
|
105
|
|
|
|
|
|
im_log((aIMCTX, 2, "poly %d\n", k)); |
|
480
|
2077
|
100
|
|
|
|
|
for(i = 0; i < p->count; i++) { |
|
481
|
1972
|
|
|
|
|
|
im_log((aIMCTX, 2, " (%.2f, %.2f)\n", p->x[i], p->y[i])); |
|
482
|
|
|
|
|
|
|
} |
|
483
|
|
|
|
|
|
|
} |
|
484
|
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
POLY_DEB( |
|
487
|
|
|
|
|
|
|
fflush(stdout); |
|
488
|
|
|
|
|
|
|
setbuf(stdout, NULL); |
|
489
|
|
|
|
|
|
|
); |
|
490
|
|
|
|
|
|
|
|
|
491
|
97
|
|
|
|
|
|
pset = point_set_new(polys, count, &pcount); |
|
492
|
97
|
|
|
|
|
|
lset = line_set_new(polys, count, &lcount); |
|
493
|
|
|
|
|
|
|
|
|
494
|
97
|
|
|
|
|
|
ss_scanline_init(&templine, im->xsize, lcount); |
|
495
|
|
|
|
|
|
|
|
|
496
|
97
|
|
|
|
|
|
tllist = mymalloc(sizeof(p_slice) * lcount); |
|
497
|
|
|
|
|
|
|
|
|
498
|
97
|
|
|
|
|
|
qsort(pset, pcount, sizeof(p_point), (int(*)(const void *,const void *))p_compy); |
|
499
|
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
POLY_DEB( |
|
501
|
|
|
|
|
|
|
for(i=0;i
|
|
502
|
|
|
|
|
|
|
printf("%d [ %d ] (%d , %d) -> (%d , %d) yspan ( %d , %d )\n", |
|
503
|
|
|
|
|
|
|
i, lset[i].n, lset[i].x1, lset[i].y1, lset[i].x2, lset[i].y2, lset[i].miny, lset[i].maxy); |
|
504
|
|
|
|
|
|
|
} |
|
505
|
|
|
|
|
|
|
printf("MAIN LOOP\n\n"); |
|
506
|
|
|
|
|
|
|
); |
|
507
|
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
/* loop on intervals */ |
|
510
|
1972
|
100
|
|
|
|
|
for(i=0; i
|
|
511
|
1875
|
|
|
|
|
|
i_img_dim startscan = i_max( coarse(pset[i].y), 0); |
|
512
|
1875
|
|
|
|
|
|
i_img_dim stopscan = i_min( coarse(pset[i+1].y+15), im->ysize); |
|
513
|
|
|
|
|
|
|
pcord miny, maxy; /* y bounds in fine coordinates */ |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
POLY_DEB( pcord cc = (pset[i].y + pset[i+1].y)/2 ); |
|
516
|
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
POLY_DEB( |
|
518
|
|
|
|
|
|
|
printf("current slice is %d: %d to %d ( cpoint %d ) scanlines %d to %d\n", |
|
519
|
|
|
|
|
|
|
i, pset[i].y, pset[i+1].y, cc, startscan, stopscan) |
|
520
|
|
|
|
|
|
|
); |
|
521
|
|
|
|
|
|
|
|
|
522
|
1875
|
100
|
|
|
|
|
if (pset[i].y == pset[i+1].y) { |
|
523
|
|
|
|
|
|
|
POLY_DEB( printf("current slice thickness = 0 => skipping\n") ); |
|
524
|
518
|
|
|
|
|
|
continue; |
|
525
|
|
|
|
|
|
|
} |
|
526
|
|
|
|
|
|
|
|
|
527
|
1357
|
|
|
|
|
|
clc = lines_in_interval(lset, lcount, tllist, pset[i].y, pset[i+1].y); |
|
528
|
1357
|
|
|
|
|
|
qsort(tllist, clc, sizeof(p_slice), (int(*)(const void *,const void *))p_compx); |
|
529
|
|
|
|
|
|
|
|
|
530
|
1357
|
|
|
|
|
|
mark_updown_slices(aIMCTX, lset, tllist, clc); |
|
531
|
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
POLY_DEB |
|
533
|
|
|
|
|
|
|
( |
|
534
|
|
|
|
|
|
|
printf("Interval contains %d lines\n", clc); |
|
535
|
|
|
|
|
|
|
for(k=0; k
|
|
536
|
|
|
|
|
|
|
int lno = tllist[k].n; |
|
537
|
|
|
|
|
|
|
p_line *ln = lset+lno; |
|
538
|
|
|
|
|
|
|
printf("%d: line #%2d: (%2d, %2d)->(%2d, %2d) (%2d/%2d, %2d/%2d) -> (%2d/%2d, %2d/%2d) alignment=%s\n", |
|
539
|
|
|
|
|
|
|
k, lno, ln->x1, ln->y1, ln->x2, ln->y2, |
|
540
|
|
|
|
|
|
|
coarse(ln->x1), fine(ln->x1), |
|
541
|
|
|
|
|
|
|
coarse(ln->y1), fine(ln->y1), |
|
542
|
|
|
|
|
|
|
coarse(ln->x2), fine(ln->x2), |
|
543
|
|
|
|
|
|
|
coarse(ln->y2), fine(ln->y2), |
|
544
|
|
|
|
|
|
|
ln->updown == 0 ? "vert" : ln->updown == 1 ? "up" : "down"); |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
} |
|
547
|
|
|
|
|
|
|
); |
|
548
|
1357
|
|
|
|
|
|
maxy = im->ysize * 16; |
|
549
|
1357
|
|
|
|
|
|
miny = 0; |
|
550
|
5655
|
100
|
|
|
|
|
for (k = 0; k < clc; ++k) { |
|
551
|
4298
|
|
|
|
|
|
p_line const * line = lset + tllist[k].n; |
|
552
|
4298
|
100
|
|
|
|
|
if (line->miny > miny) |
|
553
|
2006
|
|
|
|
|
|
miny = line->miny; |
|
554
|
4298
|
100
|
|
|
|
|
if (line->maxy < maxy) |
|
555
|
1989
|
|
|
|
|
|
maxy = line->maxy; |
|
556
|
|
|
|
|
|
|
POLY_DEB( printf(" line miny %g maxy %g\n", line->miny/16.0, line->maxy/16.0) ); |
|
557
|
|
|
|
|
|
|
} |
|
558
|
|
|
|
|
|
|
POLY_DEB( printf("miny %g maxy %g\n", miny/16.0, maxy/16.0) ); |
|
559
|
|
|
|
|
|
|
|
|
560
|
7820
|
100
|
|
|
|
|
for(cscl=startscan; cscl
|
|
561
|
6463
|
|
|
|
|
|
pcord scan_miny = i_max(miny, cscl * 16); |
|
562
|
6463
|
|
|
|
|
|
pcord scan_maxy = i_min(maxy, (cscl + 1 ) * 16); |
|
563
|
|
|
|
|
|
|
|
|
564
|
6463
|
|
|
|
|
|
tempy = i_min(cscl*16+16, pset[i+1].y); |
|
565
|
|
|
|
|
|
|
POLY_DEB( printf("evaluating scan line %d \n", cscl) ); |
|
566
|
6463
|
100
|
|
|
|
|
if (mode == i_pfm_evenodd) { |
|
567
|
13826
|
100
|
|
|
|
|
for(k=0; k
|
|
568
|
|
|
|
|
|
|
POLY_DEB( printf("evaluating slice %d\n", k) ); |
|
569
|
7603
|
|
|
|
|
|
render_slice_scanline(&templine, cscl, lset+tllist[k].n, lset+tllist[k+1].n, scan_miny, scan_maxy); |
|
570
|
|
|
|
|
|
|
} |
|
571
|
|
|
|
|
|
|
} |
|
572
|
|
|
|
|
|
|
else { |
|
573
|
240
|
|
|
|
|
|
k = 0; |
|
574
|
560
|
100
|
|
|
|
|
while (k < clc) { |
|
575
|
320
|
|
|
|
|
|
p_line *left = lset + tllist[k++].n; |
|
576
|
320
|
|
|
|
|
|
p_line *current = NULL; |
|
577
|
320
|
|
|
|
|
|
int acc = left->dir; |
|
578
|
|
|
|
|
|
|
|
|
579
|
800
|
100
|
|
|
|
|
while (k < clc && acc) { |
|
|
|
100
|
|
|
|
|
|
|
580
|
480
|
|
|
|
|
|
current = lset + tllist[k++].n; |
|
581
|
480
|
|
|
|
|
|
acc += current->dir; |
|
582
|
|
|
|
|
|
|
} |
|
583
|
320
|
50
|
|
|
|
|
if (acc == 0) { |
|
584
|
320
|
|
|
|
|
|
render_slice_scanline(&templine, cscl, left, current, |
|
585
|
|
|
|
|
|
|
scan_miny, scan_maxy); |
|
586
|
|
|
|
|
|
|
} |
|
587
|
|
|
|
|
|
|
} |
|
588
|
|
|
|
|
|
|
} |
|
589
|
6463
|
100
|
|
|
|
|
if (16*coarse(tempy) == tempy) { |
|
590
|
|
|
|
|
|
|
POLY_DEB( printf("flushing scan line %d\n", cscl) ); |
|
591
|
5322
|
|
|
|
|
|
flusher(im, &templine, cscl, ctx); |
|
592
|
5322
|
|
|
|
|
|
ss_scanline_reset(&templine); |
|
593
|
|
|
|
|
|
|
} |
|
594
|
|
|
|
|
|
|
/* |
|
595
|
|
|
|
|
|
|
else { |
|
596
|
|
|
|
|
|
|
scanline_flush(im, &templine, cscl, val); |
|
597
|
|
|
|
|
|
|
ss_scanline_reset(&templine); |
|
598
|
|
|
|
|
|
|
return 0; |
|
599
|
|
|
|
|
|
|
} |
|
600
|
|
|
|
|
|
|
*/ |
|
601
|
|
|
|
|
|
|
} |
|
602
|
|
|
|
|
|
|
} /* Intervals */ |
|
603
|
97
|
100
|
|
|
|
|
if (16*coarse(tempy) != tempy) |
|
604
|
83
|
|
|
|
|
|
flusher(im, &templine, cscl-1, ctx); |
|
605
|
|
|
|
|
|
|
|
|
606
|
97
|
|
|
|
|
|
ss_scanline_exorcise(&templine); |
|
607
|
97
|
|
|
|
|
|
myfree(pset); |
|
608
|
97
|
|
|
|
|
|
myfree(lset); |
|
609
|
97
|
|
|
|
|
|
myfree(tllist); |
|
610
|
|
|
|
|
|
|
|
|
611
|
99
|
|
|
|
|
|
return 1; |
|
612
|
|
|
|
|
|
|
} |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
/* |
|
615
|
|
|
|
|
|
|
=item i_poly_poly_aa(im, count, polys, mode, color) |
|
616
|
|
|
|
|
|
|
=synopsis i_poly_poly_aa(im, 1, &poly, mode, color); |
|
617
|
|
|
|
|
|
|
=category Drawing |
|
618
|
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
Fill the C polygons defined by C the color specified by |
|
620
|
|
|
|
|
|
|
C. |
|
621
|
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
At least one polygon must be supplied. |
|
623
|
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
All polygons must have at least 3 points. |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
=cut |
|
627
|
|
|
|
|
|
|
*/ |
|
628
|
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
int |
|
630
|
94
|
|
|
|
|
|
i_poly_poly_aa(i_img *im, int count, const i_polygon_t *polys, |
|
631
|
|
|
|
|
|
|
i_poly_fill_mode_t mode, const i_color *val) { |
|
632
|
94
|
|
|
|
|
|
i_color c = *val; |
|
633
|
94
|
|
|
|
|
|
return i_poly_poly_aa_low(im, count, polys, mode, &c, scanline_flush); |
|
634
|
|
|
|
|
|
|
} |
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
/* |
|
637
|
|
|
|
|
|
|
=item i_poly_aa_m(im, count, x, y, mode, color) |
|
638
|
|
|
|
|
|
|
=synopsis i_poly_aa_m(im, count, x, y, mode, color); |
|
639
|
|
|
|
|
|
|
=category Drawing |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
Fill a polygon defined by the points specified by the x and y arrays with |
|
642
|
|
|
|
|
|
|
the color specified by C. |
|
643
|
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=cut |
|
645
|
|
|
|
|
|
|
*/ |
|
646
|
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
int |
|
648
|
63
|
|
|
|
|
|
i_poly_aa_m(i_img *im, int l, const double *x, const double *y, |
|
649
|
|
|
|
|
|
|
i_poly_fill_mode_t mode, const i_color *val) { |
|
650
|
|
|
|
|
|
|
i_polygon_t poly; |
|
651
|
|
|
|
|
|
|
|
|
652
|
63
|
|
|
|
|
|
poly.count = l; |
|
653
|
63
|
|
|
|
|
|
poly.x = x; |
|
654
|
63
|
|
|
|
|
|
poly.y = y; |
|
655
|
63
|
|
|
|
|
|
return i_poly_poly_aa(im, 1, &poly, mode, val); |
|
656
|
|
|
|
|
|
|
} |
|
657
|
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
int |
|
659
|
25
|
|
|
|
|
|
i_poly_aa(i_img *im, int l, const double *x, const double *y, const i_color *val) { |
|
660
|
|
|
|
|
|
|
i_polygon_t poly; |
|
661
|
|
|
|
|
|
|
|
|
662
|
25
|
|
|
|
|
|
poly.count = l; |
|
663
|
25
|
|
|
|
|
|
poly.x = x; |
|
664
|
25
|
|
|
|
|
|
poly.y = y; |
|
665
|
25
|
|
|
|
|
|
return i_poly_poly_aa(im, 1, &poly, i_pfm_evenodd, val); |
|
666
|
|
|
|
|
|
|
} |
|
667
|
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
struct poly_render_state { |
|
669
|
|
|
|
|
|
|
i_render render; |
|
670
|
|
|
|
|
|
|
i_fill_t *fill; |
|
671
|
|
|
|
|
|
|
unsigned char *cover; |
|
672
|
|
|
|
|
|
|
}; |
|
673
|
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
static void |
|
675
|
623
|
|
|
|
|
|
scanline_flush_render(i_img *im, ss_scanline *ss, int y, void *ctx) { |
|
676
|
|
|
|
|
|
|
i_img_dim x; |
|
677
|
|
|
|
|
|
|
i_img_dim left, right; |
|
678
|
623
|
|
|
|
|
|
struct poly_render_state *state = (struct poly_render_state *)ctx; |
|
679
|
|
|
|
|
|
|
|
|
680
|
623
|
|
|
|
|
|
left = 0; |
|
681
|
58408
|
50
|
|
|
|
|
while (left < im->xsize && ss->line[left] <= 0) |
|
|
|
100
|
|
|
|
|
|
|
682
|
57785
|
|
|
|
|
|
++left; |
|
683
|
623
|
50
|
|
|
|
|
if (left < im->xsize) { |
|
684
|
623
|
|
|
|
|
|
right = im->xsize; |
|
685
|
|
|
|
|
|
|
/* since going from the left found something, moving from the |
|
686
|
|
|
|
|
|
|
right should */ |
|
687
|
54820
|
100
|
|
|
|
|
while (/* right > left && */ ss->line[right-1] <= 0) |
|
688
|
54197
|
|
|
|
|
|
--right; |
|
689
|
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
/* convert to the format the render interface wants */ |
|
691
|
58141
|
100
|
|
|
|
|
for (x = left; x < right; ++x) { |
|
692
|
57518
|
|
|
|
|
|
state->cover[x-left] = saturate(ss->line[x]); |
|
693
|
|
|
|
|
|
|
} |
|
694
|
623
|
|
|
|
|
|
i_render_fill(&state->render, left, y, right-left, state->cover, |
|
695
|
|
|
|
|
|
|
state->fill); |
|
696
|
|
|
|
|
|
|
} |
|
697
|
623
|
|
|
|
|
|
} |
|
698
|
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
/* |
|
700
|
|
|
|
|
|
|
=item i_poly_poly_aa_cfill(im, count, polys, mode, fill) |
|
701
|
|
|
|
|
|
|
=synopsis i_poly_poly_aa_cfill(im, 1, &poly, mode, fill); |
|
702
|
|
|
|
|
|
|
=category Drawing |
|
703
|
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
Fill the C polygons defined by C the fill specified by |
|
705
|
|
|
|
|
|
|
C. |
|
706
|
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
At least one polygon must be supplied. |
|
708
|
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
All polygons must have at least 3 points. |
|
710
|
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
=cut |
|
712
|
|
|
|
|
|
|
*/ |
|
713
|
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
int |
|
715
|
5
|
|
|
|
|
|
i_poly_poly_aa_cfill(i_img *im, int count, const i_polygon_t *polys, |
|
716
|
|
|
|
|
|
|
i_poly_fill_mode_t mode, i_fill_t *fill) { |
|
717
|
|
|
|
|
|
|
struct poly_render_state ctx; |
|
718
|
|
|
|
|
|
|
int result; |
|
719
|
|
|
|
|
|
|
|
|
720
|
5
|
|
|
|
|
|
i_render_init(&ctx.render, im, im->xsize); |
|
721
|
5
|
|
|
|
|
|
ctx.fill = fill; |
|
722
|
5
|
|
|
|
|
|
ctx.cover = mymalloc(im->xsize); |
|
723
|
|
|
|
|
|
|
|
|
724
|
5
|
|
|
|
|
|
result = i_poly_poly_aa_low(im, count, polys, mode, &ctx, |
|
725
|
|
|
|
|
|
|
scanline_flush_render); |
|
726
|
|
|
|
|
|
|
|
|
727
|
5
|
|
|
|
|
|
myfree(ctx.cover); |
|
728
|
5
|
|
|
|
|
|
i_render_done(&ctx.render); |
|
729
|
|
|
|
|
|
|
|
|
730
|
5
|
|
|
|
|
|
return result; |
|
731
|
|
|
|
|
|
|
} |
|
732
|
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
/* |
|
734
|
|
|
|
|
|
|
=item i_poly_aa_cfill_m(im, count, x, y, mode, fill) |
|
735
|
|
|
|
|
|
|
=synopsis i_poly_aa_cfill(im, count, x, y, mode, fill); |
|
736
|
|
|
|
|
|
|
=category Drawing |
|
737
|
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
Fill a polygon defined by the points specified by the x and y arrays with |
|
739
|
|
|
|
|
|
|
the fill specified by C. |
|
740
|
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
=cut |
|
742
|
|
|
|
|
|
|
*/ |
|
743
|
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
int |
|
745
|
4
|
|
|
|
|
|
i_poly_aa_cfill_m(i_img *im, int l, const double *x, const double *y, |
|
746
|
|
|
|
|
|
|
i_poly_fill_mode_t mode, i_fill_t *fill) { |
|
747
|
|
|
|
|
|
|
i_polygon_t poly; |
|
748
|
|
|
|
|
|
|
|
|
749
|
4
|
|
|
|
|
|
poly.count = l; |
|
750
|
4
|
|
|
|
|
|
poly.x = x; |
|
751
|
4
|
|
|
|
|
|
poly.y = y; |
|
752
|
|
|
|
|
|
|
|
|
753
|
4
|
|
|
|
|
|
return i_poly_poly_aa_cfill(im, 1, &poly, mode, fill); |
|
754
|
|
|
|
|
|
|
} |
|
755
|
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
int |
|
757
|
1
|
|
|
|
|
|
i_poly_aa_cfill(i_img *im, int l, const double *x, const double *y, |
|
758
|
|
|
|
|
|
|
i_fill_t *fill) { |
|
759
|
|
|
|
|
|
|
i_polygon_t poly; |
|
760
|
|
|
|
|
|
|
|
|
761
|
1
|
|
|
|
|
|
poly.count = l; |
|
762
|
1
|
|
|
|
|
|
poly.x = x; |
|
763
|
1
|
|
|
|
|
|
poly.y = y; |
|
764
|
|
|
|
|
|
|
|
|
765
|
1
|
|
|
|
|
|
return i_poly_poly_aa_cfill(im, 1, &poly, i_pfm_evenodd, fill); |
|
766
|
|
|
|
|
|
|
} |