1 /*
2 * Portions of this file are copyright Rebirth contributors and licensed as
3 * described in COPYING.txt.
4 * Portions of this file are copyright Parallax Software and licensed
5 * according to the Parallax license below.
6 * See COPYING.txt for license details.
7
8 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
10 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
16 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
18 */
19
20 /*
21 *
22 * Graphical routines for drawing lines.
23 *
24 */
25
26 #include <stdlib.h>
27 #include "u_mem.h"
28 #include "gr.h"
29 #include "grdef.h"
30 #include "maths.h"
31 #include "clip.h"
32 #if DXX_USE_OGL
33 #include "ogl_init.h"
34 #endif
35
36 namespace dcx {
37
38 namespace {
39
40 /*
41 Symmetric Double Step Line Algorithm
42 by Brian Wyvill
43 from "Graphics Gems", Academic Press, 1990
44 */
45
46 /* non-zero flag indicates the pixels needing EXCHG back. */
plot(grs_canvas & canvas,int x,int y,int flag,const color_palette_index color)47 static void plot(grs_canvas &canvas, int x, int y, int flag, const color_palette_index color)
48 #define plot(x,y,f) plot(canvas,x,y,f,color)
49 {
50 if (flag)
51 std::swap(x, y);
52 gr_upixel(canvas.cv_bitmap, x, y, color);
53 }
54
gr_hline(grs_canvas & canvas,int x1,int x2,const int y,const color_palette_index color)55 static void gr_hline(grs_canvas &canvas, int x1, int x2, const int y, const color_palette_index color)
56 {
57 using std::swap;
58 if (x1 > x2)
59 swap(x1,x2);
60 for (int i=x1; i<=x2; i++ )
61 gr_upixel(canvas.cv_bitmap, i, y, color);
62 }
63
gr_vline(grs_canvas & canvas,int y1,int y2,const int x,const color_palette_index color)64 static void gr_vline(grs_canvas &canvas, int y1, int y2, const int x, const color_palette_index color)
65 {
66 using std::swap;
67 if (y1 > y2) swap(y1,y2);
68 for (int i=y1; i<=y2; i++ )
69 gr_upixel(canvas.cv_bitmap, x, i, color);
70 }
71
gr_universal_uline(grs_canvas & canvas,int a1,int b1,int a2,int b2,const color_palette_index color)72 static void gr_universal_uline(grs_canvas &canvas, int a1, int b1, int a2, int b2, const color_palette_index color)
73 {
74 int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
75 int x1, y1;
76 int sign_x = 1, sign_y = 1, step, reverse;
77
78 if (a1==a2) {
79 gr_vline(canvas, b1, b2, a1, color);
80 return;
81 }
82
83 if (b1==b2) {
84 gr_hline(canvas, a1, a2, b1, color);
85 return;
86 }
87
88 dx = a2 - a1;
89 dy = b2 - b1;
90
91 if (dx < 0) {
92 sign_x = -1;
93 dx *= -1;
94 }
95 if (dy < 0) {
96 sign_y = -1;
97 dy *= -1;
98 }
99
100 /* decide increment sign by the slope sign */
101 if (sign_x == sign_y)
102 step = 1;
103 else
104 step = -1;
105
106 if (dy > dx) { /* chooses axis of greatest movement (make * dx) */
107 using std::swap;
108 swap(a1, b1);
109 swap(a2, b2);
110 swap(dx, dy);
111 reverse = 1;
112 } else
113 reverse = 0;
114 /* note error check for dx==0 should be included here */
115 if (a1 > a2) { /* start from the smaller coordinate */
116 x = a2;
117 y = b2;
118 x1 = a1;
119 y1 = b1;
120 } else {
121 x = a1;
122 y = b1;
123 x1 = a2;
124 y1 = b2;
125 }
126
127
128 /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
129 /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
130 /* In fact (dx-1)/4 as 2 pixels are already plottted */
131 xend = (dx - 1) / 4;
132 pixels_left = (dx - 1) % 4; /* number of pixels left over at the
133 * end */
134 plot(x, y, reverse);
135 plot(x1, y1, reverse); /* plot first two points */
136 incr2 = 4 * dy - 2 * dx;
137 if (incr2 < 0) { /* slope less than 1/2 */
138 c = 2 * dy;
139 incr1 = 2 * c;
140 D = incr1 - dx;
141
142 for (uint_fast32_t i = xend; i--;)
143 { /* plotting loop */
144 ++x;
145 --x1;
146 if (D < 0) {
147 /* pattern 1 forwards */
148 plot(x, y, reverse);
149 plot(++x, y, reverse);
150 /* pattern 1 backwards */
151 plot(x1, y1, reverse);
152 plot(--x1, y1, reverse);
153 D += incr1;
154 } else {
155 if (D < c) {
156 /* pattern 2 forwards */
157 plot(x, y, reverse);
158 plot(++x, y += step, reverse);
159 /* pattern 2 backwards */
160 plot(x1, y1, reverse);
161 plot(--x1, y1 -= step, reverse);
162 } else {
163 /* pattern 3 forwards */
164 plot(x, y += step, reverse);
165 plot(++x, y, reverse);
166 /* pattern 3 backwards */
167 plot(x1, y1 -= step, reverse);
168 plot(--x1, y1, reverse);
169 }
170 D += incr2;
171 }
172 } /* end for */
173
174 /* plot last pattern */
175 if (pixels_left) {
176 if (D < 0) {
177 plot(++x, y, reverse); /* pattern 1 */
178 if (pixels_left > 1)
179 plot(++x, y, reverse);
180 if (pixels_left > 2)
181 plot(--x1, y1, reverse);
182 } else {
183 if (D < c) {
184 plot(++x, y, reverse); /* pattern 2 */
185 if (pixels_left > 1)
186 plot(++x, y += step, reverse);
187 if (pixels_left > 2)
188 plot(--x1, y1, reverse);
189 } else {
190 /* pattern 3 */
191 plot(++x, y += step, reverse);
192 if (pixels_left > 1)
193 plot(++x, y, reverse);
194 if (pixels_left > 2)
195 plot(--x1, y1 -= step, reverse);
196 }
197 }
198 } /* end if pixels_left */
199 }
200 /* end slope < 1/2 */
201 else { /* slope greater than 1/2 */
202 c = 2 * (dy - dx);
203 incr1 = 2 * c;
204 D = incr1 + dx;
205 for (uint_fast32_t i = xend; i--;)
206 {
207 ++x;
208 --x1;
209 if (D > 0) {
210 /* pattern 4 forwards */
211 plot(x, y += step, reverse);
212 plot(++x, y += step, reverse);
213 /* pattern 4 backwards */
214 plot(x1, y1 -= step, reverse);
215 plot(--x1, y1 -= step, reverse);
216 D += incr1;
217 } else {
218 if (D < c) {
219 /* pattern 2 forwards */
220 plot(x, y, reverse);
221 plot(++x, y += step, reverse);
222
223 /* pattern 2 backwards */
224 plot(x1, y1, reverse);
225 plot(--x1, y1 -= step, reverse);
226 } else {
227 /* pattern 3 forwards */
228 plot(x, y += step, reverse);
229 plot(++x, y, reverse);
230 /* pattern 3 backwards */
231 plot(x1, y1 -= step, reverse);
232 plot(--x1, y1, reverse);
233 }
234 D += incr2;
235 }
236 } /* end for */
237 /* plot last pattern */
238 if (pixels_left) {
239 if (D > 0) {
240 plot(++x, y += step, reverse); /* pattern 4 */
241 if (pixels_left > 1)
242 plot(++x, y += step, reverse);
243 if (pixels_left > 2)
244 plot(--x1, y1 -= step, reverse);
245 } else {
246 if (D < c) {
247 plot(++x, y, reverse); /* pattern 2 */
248 if (pixels_left > 1)
249 plot(++x, y += step, reverse);
250 if (pixels_left > 2)
251 plot(--x1, y1, reverse);
252 } else {
253 /* pattern 3 */
254 plot(++x, y += step, reverse);
255 if (pixels_left > 1)
256 plot(++x, y, reverse);
257 if (pixels_left > 2) {
258 if (D > c) /* step 3 */
259 plot(--x1, y1 -= step, reverse);
260 else /* step 2 */
261 plot(--x1, y1, reverse);
262 }
263 }
264 }
265 }
266 }
267 }
268
269 }
270
271 //unclipped version just calls clipping version for now
gr_uline(grs_canvas & canvas,const fix _a1,const fix _b1,const fix _a2,const fix _b2,const color_palette_index color)272 void gr_uline(grs_canvas &canvas, const fix _a1, const fix _b1, const fix _a2, const fix _b2, const color_palette_index color)
273 {
274 int a1,b1,a2,b2;
275 a1 = f2i(_a1); b1 = f2i(_b1); a2 = f2i(_a2); b2 = f2i(_b2);
276 switch(canvas.cv_bitmap.get_type())
277 {
278 case bm_mode::ilbm:
279 case bm_mode::rgb15:
280 break;
281 #if DXX_USE_OGL
282 case bm_mode::ogl:
283 ogl_ulinec(canvas, a1, b1, a2, b2, color);
284 return;
285 #endif
286 case bm_mode::linear:
287 gr_universal_uline(canvas, a1, b1, a2, b2, color);
288 return;
289 }
290 return;
291 }
292
293 // Returns 0 if drawn with no clipping, 1 if drawn but clipped, and
294 // 2 if not drawn at all.
295
gr_line(grs_canvas & canvas,fix a1,fix b1,fix a2,fix b2,const color_palette_index color)296 void gr_line(grs_canvas &canvas, fix a1, fix b1, fix a2, fix b2, const color_palette_index color)
297 {
298 int x1, y1, x2, y2;
299 x1 = i2f(MINX);
300 y1 = i2f(MINY);
301 x2 = i2f(canvas.cv_bitmap.bm_w - 1);
302 y2 = i2f(canvas.cv_bitmap.bm_h - 1);
303
304 CLIPLINE(a1,b1,a2,b2,x1,y1,x2,y2,return,, FIXSCALE );
305 gr_uline(canvas, a1, b1, a2, b2, color);
306 }
307
308 }
309