1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: r:/prj/lib/src/2d/RCS/fl8lp.c $
21  * $Revision: 1.23 $
22  * $Author: kevin $
23  * $Date: 1994/11/02 19:39:45 $
24  *
25  * lit full perspective texture mapper.
26  *
27  */
28 
29 // ************************************************************************************
30 // ************************************************************************************
31 //
32 //  MLA - don't think we need to optimize this, its in C on the PC too
33 //
34 // ************************************************************************************
35 // ************************************************************************************
36 
37 #include "cnvdat.h"
38 #include "pertyp.h"
39 #include "plytyp.h"
40 #define safe_fix_cint(x) ((fix_frac(x) == 0) ? (fix_int(x)) : (fix_int(x) + 1))
41 #define fix_16_20(a) ((a) >> 4)
42 
43 /**************************************************************
44 Routines to scan polygon.  hscan=standard horizontal scanlines.
45 vscan=vertical scanlines.
46 **************************************************************/
47 
48 // prototypes
49 void gri_lit_per_umap_hscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
50 void gri_lit_per_umap_vscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
51 
gri_lit_per_umap_hscan(grs_bitmap * bm,int n,grs_vertex ** vpl,grs_per_setup * ps)52 void gri_lit_per_umap_hscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps) {
53     grs_per_info pi;
54     fix y_prime[10];
55     fix yp_left, yp_right;
56     fix x_left, x_right;
57     fix y_left, y_right;
58     fix dx_left, dx_right;
59     fix i_left, i_right;
60     fix di_left, di_right;
61     int yp_min, yp_max, yp_next;
62     int x_min, x_max, xr_min, xr_max, xl_min, xl_max;
63     int n_min, n_left, n_right;
64     int j;
65 
66     pi.scale = grd_bm.w;
67     pi.scan_slope = ps->scan_slope;
68     pi.dp = ps->dp;
69     pi.clut = ps->clut;
70     if (fix_abs(pi.scan_slope) > FIX_UNIT)
71         return;
72 
73     if (bm->row != 1 << (bm->wlog))
74         return;
75     if (bm->h != 1 << (bm->hlog))
76         return;
77     pi.u_mask = bm->row - 1;
78     pi.v_mask = (bm->h - 1) << bm->wlog;
79     pi.v_shift = 16 - bm->wlog;
80 
81     yp_min = yp_max = fix_cint(y_prime[n_min = 0] = vpl[0]->y - fix_mul(vpl[0]->x, ps->scan_slope));
82     for (j = 1; j < n; j++) {
83         pi.yp = fix_cint(y_prime[j] = vpl[j]->y - fix_mul(vpl[j]->x, ps->scan_slope));
84         if (pi.yp < yp_min) {
85             yp_min = pi.yp;
86             n_min = j;
87         }
88         if (pi.yp > yp_max)
89             yp_max = pi.yp;
90     }
91     if (yp_max == yp_min)
92         return;
93     pi.denom = fix_16_20(ps->c + fix_mul(ps->b, y_prime[0]));
94     pi.u0 =
95         vpl[0]->u - fix_div(fix_mul(vpl[0]->x, ps->alpha_u) + fix_mul(vpl[0]->y, ps->beta_u) + ps->gamma_u, pi.denom);
96     pi.v0 =
97         vpl[0]->v - fix_div(fix_mul(vpl[0]->x, ps->alpha_v) + fix_mul(vpl[0]->y, ps->beta_v) + ps->gamma_v, pi.denom);
98 
99     n_left = n_right = n_min;
100     pi.yp = yp_min;
101     while (fix_cint(y_prime[(n_left + n - 1) % n]) == pi.yp)
102         n_left = (n_left + n - 1) % n;
103     while (fix_cint(y_prime[(n_right + 1) % n]) == pi.yp)
104         n_right = (n_right + 1) % n;
105 
106     pi.yp--;
107     pi.denom = fix_16_20(ps->c + pi.yp * ps->b);
108     pi.unum = ps->gamma_u + pi.yp * ps->beta_u;
109     pi.dunum = ps->alpha_u + fix_mul(ps->scan_slope, ps->beta_u);
110     pi.vnum = ps->gamma_v + pi.yp * ps->beta_v;
111     pi.dvnum = ps->alpha_v + fix_mul(ps->scan_slope, ps->beta_v);
112 
113     if (n_right != n_left) {
114 
115         pi.dxl = (vpl[n_right]->x - vpl[n_left]->x) / pi.scale;
116         pi.dyl = (vpl[n_right]->y - vpl[n_left]->y) / pi.scale;
117         pi.x = fix_cint(vpl[n_left]->x);
118         pi.xl = fix_cint(vpl[n_right]->x);
119         if (pi.scan_slope > 0) {
120             x_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.bot - 1) - pi.yp, 1), pi.scan_slope));
121             x_min = fix_int(fix_div(fix_make((grd_int_clip.top - 1) - pi.yp, 1), pi.scan_slope)) + 1;
122         } else {
123             x_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.top - 1) - pi.yp, 1), pi.scan_slope));
124             x_min = fix_int(fix_div(fix_make((grd_int_clip.bot - 1) - pi.yp, 1), pi.scan_slope)) + 1;
125         }
126         if (pi.x < x_min)
127             pi.x = x_min;
128         if (pi.xl > x_max)
129             pi.xl = x_max;
130         pi.xr0 = pi.xr = pi.xl;
131         pi.i = vpl[n_left]->i;
132         if (pi.xr - pi.x)
133             pi.di = (vpl[n_right]->i - pi.i) / (pi.xr - pi.x);
134         else {
135             pi.di = 0x7fffffff;
136             if (vpl[n_right]->i - pi.i < 0)
137                 pi.di = -pi.di;
138         }
139 
140         pi.cl = fix_mul(pi.dxl, vpl[n_left]->y) - fix_mul(pi.dyl, vpl[n_left]->x);
141         if (pi.x * pi.dyl - fix_mul(fix_make(pi.yp - 1, 0) + pi.x * pi.scan_slope, pi.dxl) + pi.cl < 0) {
142             pi.dyl = -pi.dyl;
143             pi.dxl = -pi.dxl;
144             pi.cl = -pi.cl;
145         }
146         if (pi.scan_slope > 0)
147             pi.dtl = pi.dyl - pi.dxl;
148         else
149             pi.dtl = pi.dyl + pi.dxl;
150 
151         ((void (*)(grs_per_info *, grs_bitmap *))(ps->scanline_func))(&pi, bm);
152 
153         pi.denom += fix_16_20(ps->b), pi.unum += ps->beta_u, pi.vnum += ps->beta_v;
154         yp_min--; /* first line already done */
155     }
156     pi.yp++;
157     while (pi.yp < yp_max) {
158         /* check left edge */
159         if (fix_cint(y_prime[n_left]) <= pi.yp) {
160             int n_prev, dyp;
161             fix d;
162             do {
163                 if (fix_cint(y_prime[n_left]) == pi.yp)
164                     n_prev = n_left;
165                 if (--n_left < 0)
166                     n_left = n - 1;
167             } while (fix_cint(y_prime[n_left]) <= pi.yp);
168             yp_left = y_prime[n_prev];
169             x_left = vpl[n_prev]->x;
170             y_left = vpl[n_prev]->y;
171             i_left = vpl[n_prev]->i;
172             dyp = fix_cint(y_prime[n_left]) - fix_cint(yp_left);
173             di_left = (vpl[n_left]->i - i_left) / dyp;
174             xl_min = fix_cint(x_left);
175             xl_max = fix_cint(vpl[n_left]->x);
176             pi.dxl = (vpl[n_left]->x - x_left) / pi.scale;
177             pi.dyl = (vpl[n_left]->y - y_left) / pi.scale;
178             pi.cl = fix_mul(pi.dxl, y_left) - fix_mul(pi.dyl, x_left);
179             d = pi.dyl - fix_mul(pi.dxl, pi.scan_slope);
180             dx_left = fix_div(pi.dxl, d);
181             x_left = fix_div(fix_mul(pi.dyl, x_left) + fix_mul(pi.dxl, fix_ceil(yp_left) - y_left), d);
182             if (xl_max < xl_min) {
183                 fix foo = xl_min;
184                 xl_min = xl_max;
185                 xl_max = foo;
186             }
187             if (fix_mul(vpl[n_left]->x - FIX_UNIT, pi.dyl) - fix_mul(vpl[n_left]->y - pi.scan_slope, pi.dxl) + pi.cl <
188                 0) {
189                 pi.dyl = -pi.dyl;
190                 pi.dxl = -pi.dxl;
191                 pi.cl = -pi.cl;
192             }
193             if (pi.scan_slope > 0)
194                 pi.dtl = pi.dyl - pi.dxl;
195             else
196                 pi.dtl = pi.dyl + pi.dxl;
197             yp_left = y_prime[n_left];
198         }
199 
200         /* check right edge */
201         if (fix_cint(y_prime[n_right]) <= pi.yp) {
202             int n_prev, dyp;
203             fix d;
204             do {
205                 if (fix_cint(y_prime[n_right]) == pi.yp)
206                     n_prev = n_right;
207                 if (++n_right == n)
208                     n_right = 0;
209             } while (fix_cint(y_prime[n_right]) <= pi.yp);
210             yp_right = y_prime[n_prev];
211             x_right = vpl[n_prev]->x;
212             y_right = vpl[n_prev]->y;
213             i_right = vpl[n_prev]->i;
214             dyp = fix_cint(y_prime[n_right]) - fix_cint(yp_right);
215             di_right = (vpl[n_right]->i - i_right) / dyp;
216             xr_min = fix_cint(x_right);
217             xr_max = fix_cint(vpl[n_right]->x);
218             pi.dxr = (vpl[n_right]->x - x_right) / pi.scale;
219             pi.dyr = (vpl[n_right]->y - y_right) / pi.scale;
220             pi.cr = fix_mul(pi.dxr, y_right) - fix_mul(pi.dyr, x_right);
221             d = pi.dyr - fix_mul(pi.dxr, pi.scan_slope);
222             dx_right = fix_div(pi.dxr, d);
223             x_right = fix_div(fix_mul(pi.dyr, x_right) + fix_mul(pi.dxr, fix_ceil(yp_right) - y_right), d);
224             if (xr_max < xr_min) {
225                 fix foo = xr_min;
226                 xr_min = xr_max;
227                 xr_max = foo;
228             }
229             if (fix_mul(vpl[n_right]->x - FIX_UNIT, pi.dyr) - fix_mul(vpl[n_right]->y - pi.scan_slope, pi.dxr) + pi.cr <
230                 0) {
231                 pi.dyr = -pi.dyr;
232                 pi.dxr = -pi.dxr;
233                 pi.cr = -pi.cr;
234             }
235             if (pi.scan_slope > 0)
236                 pi.dtr = pi.dyr - pi.dxr;
237             else
238                 pi.dtr = pi.dyr + pi.dxr;
239             yp_right = y_prime[n_right];
240         }
241         yp_next = (yp_right < yp_left) ? fix_cint(yp_right) : fix_cint(yp_left);
242 
243         /* do 0th scanline if at yp_min */
244         if (pi.yp == yp_min) {
245             x_left -= dx_left;
246             x_right -= dx_right;
247             pi.yp--;
248         }
249         for (; pi.yp < yp_next; pi.yp++) {
250             if ((pi.yp + 1 == yp_max) && (n_left != n_right)) {
251                 pi.dxl = (vpl[n_right]->x - vpl[n_left]->x) / pi.scale;
252                 pi.dyl = (vpl[n_right]->y - vpl[n_left]->y) / pi.scale;
253                 pi.x = fix_cint(vpl[n_left]->x);
254                 pi.xl = fix_cint(vpl[n_right]->x);
255                 if (pi.scan_slope > 0) {
256                     x_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.bot - 1) - pi.yp, 1), pi.scan_slope));
257                     x_min = fix_int(fix_div(fix_make((grd_int_clip.top - 1) - pi.yp, 1), pi.scan_slope)) + 1;
258                 } else {
259                     x_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.top - 1) - pi.yp, 1), pi.scan_slope));
260                     x_min = fix_int(fix_div(fix_make((grd_int_clip.bot - 1) - pi.yp, 1), pi.scan_slope)) + 1;
261                 }
262                 if (pi.x < x_min)
263                     pi.x = x_min;
264                 if (pi.xl > x_max)
265                     pi.xl = x_max;
266                 pi.xr0 = pi.xr = pi.xl;
267                 pi.i = i_left;
268                 if (pi.xr - pi.x)
269                     pi.di = (i_right - pi.i) / (pi.xr - pi.x);
270                 else {
271                     pi.di = 0x7fffffff;
272                     if (i_right - pi.i < 0)
273                         pi.di = -pi.di;
274                 }
275 
276                 pi.cl = fix_mul(pi.dxl, vpl[n_left]->y) - fix_mul(pi.dyl, vpl[n_left]->x);
277                 if (pi.x * pi.dyl - fix_mul(fix_make(pi.yp + 1, 0) + pi.x * pi.scan_slope, pi.dxl) + pi.cl < 0) {
278                     pi.dyl = -pi.dyl;
279                     pi.dxl = -pi.dxl;
280                     pi.cl = -pi.cl;
281                 }
282                 if (pi.scan_slope > 0)
283                     pi.dtl = pi.dyl - pi.dxl;
284                 else
285                     pi.dtl = pi.dyl + pi.dxl;
286 
287                 ((void (*)(grs_per_info *, grs_bitmap *))(ps->scanline_func))(&pi, bm);
288 
289                 pi.yp = yp_max;
290                 break;
291             }
292 
293             if (dx_left > 0) {
294                 pi.x = fix_fint(x_left);
295                 pi.xl = fix_cint(x_left + dx_left);
296             } else {
297                 pi.x = fix_fint(x_left + dx_left);
298                 pi.xl = fix_cint(x_left);
299             }
300             if (dx_right > 0) {
301                 pi.xr0 = fix_fint(x_right);
302                 pi.xr = fix_cint(x_right + dx_right);
303             } else {
304                 pi.xr0 = fix_fint(x_right + dx_right);
305                 pi.xr = fix_cint(x_right);
306             }
307             if (pi.scan_slope > 0) {
308                 x_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.bot - 1) - pi.yp, 1), pi.scan_slope));
309                 x_min = fix_int(fix_div(fix_make((grd_int_clip.top - 1) - pi.yp, 1), pi.scan_slope)) + 1;
310             } else {
311                 x_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.top - 1) - pi.yp, 1), pi.scan_slope));
312                 x_min = fix_int(fix_div(fix_make((grd_int_clip.bot - 1) - pi.yp, 1), pi.scan_slope)) + 1;
313             }
314             if (xl_min > x_min)
315                 x_min = xl_min;
316             if (xr_max < x_max)
317                 x_max = xr_max;
318             if (pi.xr > x_max)
319                 pi.xr = x_max;
320             if (pi.xr0 > x_max)
321                 pi.xr0 = x_max;
322             if (pi.xl > pi.xr0)
323                 pi.xl = pi.xr0;
324             if (pi.x < x_min)
325                 pi.x = x_min;
326             pi.i = i_left;
327             if (pi.xr - pi.x)
328                 pi.di = (i_right - pi.i) / (pi.xr - pi.x);
329             else {
330                 pi.di = 0x7fffffff;
331                 if (i_right - pi.i < 0)
332                     pi.di = -pi.di;
333             }
334 
335             ((void (*)(grs_per_info *, grs_bitmap *))(ps->scanline_func))(&pi, bm);
336 
337             if (pi.yp >= yp_min) {
338                 i_left += di_left, i_right += di_right;
339             }
340             x_left += dx_left, x_right += dx_right;
341             pi.denom += fix_16_20(ps->b), pi.unum += ps->beta_u, pi.vnum += ps->beta_v;
342         }
343     }
344 }
345 
gri_lit_per_umap_vscan(grs_bitmap * bm,int n,grs_vertex ** vpl,grs_per_setup * ps)346 void gri_lit_per_umap_vscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps) {
347     grs_per_info pi;
348     fix x_prime[10];
349     fix xp_top, xp_bot;
350     fix x_top, x_bot;
351     fix y_top, y_bot;
352     fix dy_top, dy_bot;
353     fix i_top, i_bot;
354     fix di_top, di_bot;
355     int xp_min, xp_max, xp_next;
356     int y_min, y_max, yr_min, yr_max, yl_min, yl_max;
357     int n_min, n_top, n_bot;
358     int j;
359 
360     pi.scale = grd_bm.w;
361     pi.scan_slope = ps->scan_slope;
362     pi.dp = ps->dp;
363     pi.clut = ps->clut;
364     if (fix_abs(pi.scan_slope) >= FIX_UNIT)
365         return;
366 
367     if (bm->row != 1 << (bm->wlog))
368         return;
369     if (bm->h != 1 << (bm->hlog))
370         return;
371     pi.u_mask = bm->row - 1;
372     pi.v_mask = (bm->h - 1) << bm->wlog;
373     pi.v_shift = 16 - bm->wlog;
374 
375     xp_min = xp_max = fix_cint(x_prime[n_min = 0] = vpl[0]->x - fix_mul(vpl[0]->y, ps->scan_slope));
376     for (j = 1; j < n; j++) {
377         pi.xp = fix_cint(x_prime[j] = vpl[j]->x - fix_mul(vpl[j]->y, ps->scan_slope));
378         if (pi.xp < xp_min) {
379             xp_min = pi.xp;
380             n_min = j;
381         }
382         if (pi.xp > xp_max)
383             xp_max = pi.xp;
384     }
385     if (xp_max == xp_min)
386         return;
387     pi.denom = fix_16_20(ps->c + fix_mul(ps->a, x_prime[0]));
388     pi.u0 =
389         vpl[0]->u - fix_div(fix_mul(vpl[0]->x, ps->alpha_u) + fix_mul(vpl[0]->y, ps->beta_u) + ps->gamma_u, pi.denom);
390     pi.v0 =
391         vpl[0]->v - fix_div(fix_mul(vpl[0]->x, ps->alpha_v) + fix_mul(vpl[0]->y, ps->beta_v) + ps->gamma_v, pi.denom);
392 
393     n_top = n_bot = n_min;
394     pi.xp = xp_min;
395     while (fix_cint(x_prime[(n_top + 1) % n]) == pi.xp)
396         n_top = (n_top + 1) % n;
397     while (fix_cint(x_prime[(n_bot + n - 1) % n]) == pi.xp)
398         n_bot = (n_bot + n - 1) % n;
399 
400     pi.xp--;
401     pi.denom = fix_16_20(ps->c + pi.xp * ps->a);
402     pi.unum = ps->gamma_u + pi.xp * ps->alpha_u;
403     pi.dunum = ps->beta_u + fix_mul(ps->scan_slope, ps->alpha_u);
404     pi.vnum = ps->gamma_v + pi.xp * ps->alpha_v;
405     pi.dvnum = ps->beta_v + fix_mul(ps->scan_slope, ps->alpha_v);
406 
407     if (n_bot != n_top) {
408 
409         pi.dxl = (vpl[n_bot]->x - vpl[n_top]->x) / pi.scale;
410         pi.dyl = (vpl[n_bot]->y - vpl[n_top]->y) / pi.scale;
411         pi.y = fix_cint(vpl[n_top]->y);
412         pi.yl = fix_cint(vpl[n_bot]->y);
413         if (pi.scan_slope > 0) {
414             y_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.right - 1) - pi.xp, 1), pi.scan_slope));
415             y_min = fix_int(fix_div(fix_make((grd_int_clip.left - 1) - pi.xp, 1), pi.scan_slope)) + 1;
416         } else {
417             y_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.left - 1) - pi.xp, 1), pi.scan_slope));
418             y_min = fix_int(fix_div(fix_make((grd_int_clip.right - 1) - pi.xp, 1), pi.scan_slope)) + 1;
419         }
420         if (pi.y < y_min)
421             pi.y = y_min;
422         if (pi.yl > y_max)
423             pi.yl = y_max;
424         pi.yr0 = pi.yr = pi.yl;
425         pi.i = vpl[n_top]->i;
426         if (pi.yr - pi.y)
427             pi.di = (vpl[n_bot]->i - pi.i) / (pi.yr - pi.y);
428         else {
429             pi.di = 0x7fffffff;
430             if (vpl[n_bot]->i - pi.i < 0)
431                 pi.di = -pi.di;
432         }
433 
434         pi.cl = -fix_mul(pi.dxl, vpl[n_top]->y) + fix_mul(pi.dyl, vpl[n_top]->x);
435         if (pi.y * pi.dxl - fix_mul(fix_make(pi.xp - 1, 0) + pi.y * pi.scan_slope, pi.dyl) + pi.cl < 0) {
436             pi.dyl = -pi.dyl;
437             pi.dxl = -pi.dxl;
438             pi.cl = -pi.cl;
439         }
440         if (pi.scan_slope > 0)
441             pi.dtl = pi.dxl - pi.dyl;
442         else
443             pi.dtl = pi.dyl + pi.dxl;
444 
445         ((void (*)(grs_per_info *, grs_bitmap *))(ps->scanline_func))(&pi, bm);
446 
447         pi.denom += fix_16_20(ps->a), pi.unum += ps->alpha_u, pi.vnum += ps->alpha_v;
448         xp_min--; /* first line already done */
449     }
450     pi.xp++;
451     while (pi.xp < xp_max) {
452         /* check top edge */
453         if (fix_cint(x_prime[n_top]) <= pi.xp) {
454             int n_prev, dxp;
455             fix d;
456             do {
457                 if (fix_cint(x_prime[n_top]) == pi.xp)
458                     n_prev = n_top;
459                 if (++n_top == n)
460                     n_top = 0;
461             } while (fix_cint(x_prime[n_top]) <= pi.xp);
462             xp_top = x_prime[n_prev];
463             x_top = vpl[n_prev]->x;
464             y_top = vpl[n_prev]->y;
465             i_top = vpl[n_prev]->i;
466             dxp = fix_cint(x_prime[n_top]) - fix_cint(xp_top);
467             di_top = (vpl[n_top]->i - i_top) / dxp;
468             yl_min = fix_cint(y_top);
469             yl_max = fix_cint(vpl[n_top]->y);
470             pi.dxl = (vpl[n_top]->x - x_top) / pi.scale;
471             pi.dyl = (vpl[n_top]->y - y_top) / pi.scale;
472             pi.cl = -fix_mul(pi.dxl, y_top) + fix_mul(pi.dyl, x_top);
473             d = pi.dxl - fix_mul(pi.dyl, pi.scan_slope);
474             dy_top = fix_div(pi.dyl, d);
475             y_top = fix_div(fix_mul(pi.dxl, y_top) + fix_mul(pi.dyl, fix_ceil(xp_top) - x_top), d);
476             if (yl_max < yl_min) {
477                 fix foo = yl_min;
478                 yl_min = yl_max;
479                 yl_max = foo;
480             }
481             if (fix_mul(vpl[n_top]->y - FIX_UNIT, pi.dxl) - fix_mul(vpl[n_top]->x - pi.scan_slope, pi.dyl) + pi.cl <
482                 0) {
483                 pi.dyl = -pi.dyl;
484                 pi.dxl = -pi.dxl;
485                 pi.cl = -pi.cl;
486             }
487             if (pi.scan_slope > 0)
488                 pi.dtl = pi.dxl - pi.dyl;
489             else
490                 pi.dtl = pi.dyl + pi.dxl;
491             xp_top = x_prime[n_top];
492         }
493 
494         /* check bot edge */
495         if (fix_cint(x_prime[n_bot]) <= pi.xp) {
496             int n_prev, dxp;
497             fix d;
498             do {
499                 if (fix_cint(x_prime[n_bot]) == pi.xp)
500                     n_prev = n_bot;
501                 if (--n_bot < 0)
502                     n_bot = n - 1;
503             } while (fix_cint(x_prime[n_bot]) <= pi.xp);
504             xp_bot = x_prime[n_prev];
505             x_bot = vpl[n_prev]->x;
506             y_bot = vpl[n_prev]->y;
507             i_bot = vpl[n_prev]->i;
508             dxp = fix_cint(x_prime[n_bot]) - fix_cint(xp_bot);
509             di_bot = (vpl[n_bot]->i - i_bot) / dxp;
510             yr_min = fix_cint(y_bot);
511             yr_max = fix_cint(vpl[n_bot]->y);
512             pi.dxr = (vpl[n_bot]->x - x_bot) / pi.scale;
513             pi.dyr = (vpl[n_bot]->y - y_bot) / pi.scale;
514             pi.cr = -fix_mul(pi.dxr, y_bot) + fix_mul(pi.dyr, x_bot);
515             d = pi.dxr - fix_mul(pi.dyr, pi.scan_slope);
516             dy_bot = fix_div(pi.dyr, d);
517             y_bot = fix_div(fix_mul(pi.dxr, y_bot) + fix_mul(pi.dyr, fix_ceil(xp_bot) - x_bot), d);
518             if (yr_max < yr_min) {
519                 fix foo = yr_min;
520                 yr_min = yr_max;
521                 yr_max = foo;
522             }
523             if (fix_mul(vpl[n_bot]->y - FIX_UNIT, pi.dxr) - fix_mul(vpl[n_bot]->x - pi.scan_slope, pi.dyr) + pi.cr <
524                 0) {
525                 pi.dyr = -pi.dyr;
526                 pi.dxr = -pi.dxr;
527                 pi.cr = -pi.cr;
528             }
529             if (pi.scan_slope > 0)
530                 pi.dtr = pi.dxr - pi.dyr;
531             else
532                 pi.dtr = pi.dyr + pi.dxr;
533             xp_bot = x_prime[n_bot];
534         }
535         xp_next = (xp_bot < xp_top) ? fix_cint(xp_bot) : fix_cint(xp_top);
536 
537         /* do 0th scanline if at xp_min */
538         if (pi.xp == xp_min) {
539             y_top -= dy_top;
540             y_bot -= dy_bot;
541             pi.xp--;
542         }
543         for (; pi.xp < xp_next; pi.xp++) {
544             if ((pi.xp + 1 == xp_max) && (n_top != n_bot)) {
545                 pi.dxl = (vpl[n_bot]->x - vpl[n_top]->x) / pi.scale;
546                 pi.dyl = (vpl[n_bot]->y - vpl[n_top]->y) / pi.scale;
547                 pi.y = fix_cint(vpl[n_top]->y);
548                 pi.yl = fix_cint(vpl[n_bot]->y);
549                 if (pi.scan_slope > 0) {
550                     y_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.right - 1) - pi.xp, 1), pi.scan_slope));
551                     y_min = fix_int(fix_div(fix_make((grd_int_clip.left - 1) - pi.xp, 1), pi.scan_slope)) + 1;
552                 } else {
553                     y_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.left - 1) - pi.xp, 1), pi.scan_slope));
554                     y_min = fix_int(fix_div(fix_make((grd_int_clip.right - 1) - pi.xp, 1), pi.scan_slope)) + 1;
555                 }
556                 if (pi.y < y_min)
557                     pi.y = y_min;
558                 if (pi.yl > y_max)
559                     pi.yl = y_max;
560                 pi.yr0 = pi.yr = pi.yl;
561                 pi.i = i_top;
562                 if (pi.yr - pi.y)
563                     pi.di = (i_bot - pi.i) / (pi.yr - pi.y);
564                 else {
565                     pi.di = 0x7fffffff;
566                     if (i_bot - pi.i < 0)
567                         pi.di = -pi.di;
568                 }
569 
570                 pi.cl = -fix_mul(pi.dxl, vpl[n_top]->y) + fix_mul(pi.dyl, vpl[n_top]->x);
571                 if (pi.y * pi.dxl - fix_mul(fix_make(pi.xp + 1, 0) + pi.y * pi.scan_slope, pi.dyl) + pi.cl < 0) {
572                     pi.dyl = -pi.dyl;
573                     pi.dxl = -pi.dxl;
574                     pi.cl = -pi.cl;
575                 }
576                 if (pi.scan_slope > 0)
577                     pi.dtl = pi.dxl - pi.dyl;
578                 else
579                     pi.dtl = pi.dyl + pi.dxl;
580 
581                 ((void (*)(grs_per_info *, grs_bitmap *))(ps->scanline_func))(&pi, bm);
582 
583                 pi.xp = xp_max;
584                 break;
585             }
586 
587             if (dy_top > 0) {
588                 pi.y = fix_fint(y_top);
589                 pi.yl = fix_cint(y_top + dy_top);
590             } else {
591                 pi.y = fix_fint(y_top + dy_top);
592                 pi.yl = fix_cint(y_top);
593             }
594             if (dy_bot > 0) {
595                 pi.yr0 = fix_fint(y_bot);
596                 pi.yr = fix_cint(y_bot + dy_bot);
597             } else {
598                 pi.yr0 = fix_fint(y_bot + dy_bot);
599                 pi.yr = fix_cint(y_bot);
600             }
601             if (pi.scan_slope > 0) {
602                 y_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.right - 1) - pi.xp, 1), pi.scan_slope));
603                 y_min = fix_int(fix_div(fix_make((grd_int_clip.left - 1) - pi.xp, 1), pi.scan_slope)) + 1;
604             } else {
605                 y_max = safe_fix_cint(fix_div(fix_make((grd_int_clip.left - 1) - pi.xp, 1), pi.scan_slope));
606                 y_min = fix_int(fix_div(fix_make((grd_int_clip.right - 1) - pi.xp, 1), pi.scan_slope)) + 1;
607             }
608             if (yl_min > y_min)
609                 y_min = yl_min;
610             if (yr_max < y_max)
611                 y_max = yr_max;
612             if (pi.yr > y_max)
613                 pi.yr = y_max;
614             if (pi.yr0 > y_max)
615                 pi.yr0 = y_max;
616             if (pi.yl > pi.yr0)
617                 pi.yl = pi.yr0;
618             if (pi.y < y_min)
619                 pi.y = y_min;
620             pi.i = i_top;
621             if (pi.yr - pi.y)
622                 pi.di = (i_bot - pi.i) / (pi.yr - pi.y);
623             else {
624                 pi.di = 0x7fffffff;
625                 if (i_bot - pi.i < 0)
626                     pi.di = -pi.di;
627             }
628 
629             ((void (*)(grs_per_info *, grs_bitmap *))(ps->scanline_func))(&pi, bm);
630 
631             if (pi.xp >= xp_min) {
632                 i_top += di_top, i_bot += di_bot;
633             }
634 
635             y_top += dy_top, y_bot += dy_bot;
636             pi.denom += fix_16_20(ps->a), pi.unum += ps->alpha_u, pi.vnum += ps->alpha_v;
637         }
638     }
639 }
640