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
|
|
|
|
|
|
|
} |