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