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: n:/project/lib/src/2d/RCS/fl8lin.h $
21  * $Revision: 1.1 $
22  * $Author: lmfeeney $
23  * $Date: 1994/06/11 00:51:50 $
24  */
25 
26 /* this was originally the guts of flat8_fix_uline */
27 
28 fix x0, y0, x1, y1;
29 fix dx, dy; /* deltas in x and y */
30 fix t;      /* temporary fix */
31 
32 uchar *p; /* pointer into canvas */
33 
34 x0 = v0->x;
35 y0 = v0->y;
36 x1 = v1->x;
37 y1 = v1->y;
38 
39 /* set endpoints
40    note that this cannot go negative or change octant, since the ==
41    case is excluded */
42 
43 if (x0 < x1) {
44     x1 -= 1; /* e.g. - epsilon */
45 } else if (x0 > x1) {
46     x0 -= 1;
47 }
48 
49 if (y0 < y1) {
50     y1 -= 1;
51 } else if (y0 > y1) {
52     y0 -= 1;
53 }
54 
55 dx = fix_trunc(x1) - fix_trunc(x0); /* x extent in pixels, (macro is flakey) */
56 dx = fix_abs(dx);
57 dy = fix_trunc(y1) - fix_trunc(y0); /* y extent in pixels */
58 dy = fix_abs(dy);
59 
60 if (dx == 0 && dy == 0)
61     return;
62 
63 flat8_pixel_fill_init;
64 
65 /* three cases: absolute value dx < = > dy
66 
67    along the longer dimension, the fixpoint x0 (or y0) is treated
68    as an int
69 
70    the points are swapped if needed and the rgb initial and deltas
71    are calculated accordingly
72 
73    there are two or three sub-cases - a horizontal or vertical line,
74    and the dx or dy being added or subtracted.  dx and dy
75    are kept as absolute values and +/- is managed in
76    two separate inner loops if it is a y change, since you need to
77    manage the canvas pointer
78 
79    if y is being changed by 'dy' and x is being incremented, do a
80    FunkyBitCheck (TM) to see whether the integer part of y has changed
81    and if it has, resetting the the canvas pointer to the next row
82 
83    if x is being changed by 'dx' and y is being incremented, just
84    add or subtract row to increment y in the canvas
85 
86    the endpoints are walked inclusively in all cases, see above
87 
88    45' degree lines are explicitly special cased -- because it
89    all runs as integers, but it's probably not frequent enough
90    to justify the check
91 
92  */
93 
94 if (dx > dy) {
95 
96     x0 = fix_int(x0);
97     x1 = fix_int(x1);
98 
99     if (x0 > x1) {
100         t = x0;
101         x0 = x1;
102         x1 = t;
103         t = y0;
104         y0 = y1;
105         y1 = t;
106     }
107     p = grd_bm.bits + grd_bm.row * (fix_int(y0));
108 
109     if ((fix_int(y0)) == (fix_int(y1))) {
110         flat8_pixel_fill_row;
111     } else if (y0 < y1) {
112         dy = fix_div((y1 - y0), dx);
113         while (x0 <= x1) {
114             flat8_pixel_fill_xi;
115             x0++;
116             y0 += dy;
117             p += (grd_bm.row & (-(fix_frac(y0) < dy)));
118         }
119     } else {
120         dy = fix_div((y0 - y1), dx);
121         while (x0 <= x1) {
122             flat8_pixel_fill_xi;
123             x0++;
124             p -= (grd_bm.row & (-(fix_frac(y0) < dy)));
125             y0 -= dy;
126         }
127     }
128 }
129 
130 else if (dy > dx) {
131 
132     y0 = fix_int(y0);
133     y1 = fix_int(y1);
134 
135     if (y0 > y1) {
136         t = x0;
137         x0 = x1;
138         x1 = t;
139         t = y0;
140         y0 = y1;
141         y1 = t;
142     }
143 
144     p = grd_bm.bits + grd_bm.row * y0;
145 
146     if ((fix_int(x0)) == (fix_int(x1))) {
147         x0 = fix_int(x0);
148         while (y0 <= y1) {
149             flat8_pixel_fill_xi;
150             y0++;
151             p += grd_bm.row;
152         }
153     } else {
154         dx = fix_div((x1 - x0), dy);
155         while (y0 <= y1) {
156             flat8_pixel_fill_xf;
157             x0 += dx;
158             y0++;
159             p += grd_bm.row;
160         }
161     }
162 } else { /* dy == dx, walk the x axis, all integers */
163 
164     x0 = fix_int(x0);
165     x1 = fix_int(x1);
166     y0 = fix_int(y0);
167     y1 = fix_int(y1);
168 
169     if (x0 > x1) {
170         t = x0;
171         x0 = x1;
172         x1 = t;
173         t = y0;
174         y0 = y1;
175         y1 = t;
176     }
177     p = grd_bm.bits + grd_bm.row * y0;
178 
179     if (y0 < y1) {
180         while (y0 <= y1) {
181             flat8_pixel_fill_xi;
182             x0++;
183             y0++;
184             p += grd_bm.row;
185         }
186     } else {
187         while (y0 >= y1) {
188             flat8_pixel_fill_xi;
189             x0++;
190             y0--;
191             p -= grd_bm.row;
192         }
193     }
194 }
195