Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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
/*
39
Symmetric Double Step Line Algorithm
40
by Brian Wyvill
41
from "Graphics Gems", Academic Press, 1990
42
*/
43
 
44
/* non-zero flag indicates the pixels needing EXCHG back. */
45
static void plot(grs_canvas &canvas, int x, int y, int flag, const color_palette_index color)
46
#define plot(x,y,f)     plot(canvas,x,y,f,color)
47
{
48
        if (flag)
49
                std::swap(x, y);
50
        gr_upixel(canvas.cv_bitmap, x, y, color);
51
}
52
 
53
static void gr_hline(grs_canvas &canvas, int x1, int x2, const int y, const color_palette_index color)
54
{
55
        using std::swap;
56
        if (x1 > x2)
57
                swap(x1,x2);
58
        for (int i=x1; i<=x2; i++ )
59
                gr_upixel(canvas.cv_bitmap, i, y, color);
60
}
61
 
62
static void gr_vline(grs_canvas &canvas, int y1, int y2, const int x, const color_palette_index color)
63
{
64
        using std::swap;
65
        if (y1 > y2) swap(y1,y2);
66
        for (int i=y1; i<=y2; i++ )
67
                gr_upixel(canvas.cv_bitmap, x, i, color);
68
}
69
 
70
static void gr_universal_uline(grs_canvas &canvas, int a1, int b1, int a2, int b2, const color_palette_index color)
71
{
72
        int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
73
        int x1, y1;
74
        int sign_x = 1, sign_y = 1, step, reverse;
75
 
76
        if (a1==a2) {
77
                gr_vline(canvas, b1, b2, a1, color);
78
                return;
79
        }
80
 
81
        if (b1==b2) {
82
                gr_hline(canvas, a1, a2, b1, color);
83
                return;
84
        }
85
 
86
        dx = a2 - a1;
87
        dy = b2 - b1;
88
 
89
        if (dx < 0) {
90
                sign_x = -1;
91
                dx *= -1;
92
        }
93
        if (dy < 0) {
94
                sign_y = -1;
95
                dy *= -1;
96
        }
97
 
98
        /* decide increment sign by the slope sign */
99
        if (sign_x == sign_y)
100
                step = 1;
101
        else
102
                step = -1;
103
 
104
        if (dy > dx) {          /* chooses axis of greatest movement (make * dx) */
105
                using std::swap;
106
                swap(a1, b1);
107
                swap(a2, b2);
108
                swap(dx, dy);
109
                reverse = 1;
110
        } else
111
                reverse = 0;
112
        /* note error check for dx==0 should be included here */
113
        if (a1 > a2) {          /* start from the smaller coordinate */
114
                x = a2;
115
                y = b2;
116
                x1 = a1;
117
                y1 = b1;
118
        } else {
119
                x = a1;
120
                y = b1;
121
                x1 = a2;
122
                y1 = b2;
123
        }
124
 
125
 
126
        /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
127
        /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
128
        /* In fact (dx-1)/4 as 2 pixels are already plottted */
129
        xend = (dx - 1) / 4;
130
        pixels_left = (dx - 1) % 4;     /* number of pixels left over at the
131
                                         * end */
132
        plot(x, y, reverse);
133
        plot(x1, y1, reverse);  /* plot first two points */
134
        incr2 = 4 * dy - 2 * dx;
135
        if (incr2 < 0) {        /* slope less than 1/2 */
136
                c = 2 * dy;
137
                incr1 = 2 * c;
138
                D = incr1 - dx;
139
 
140
                for (uint_fast32_t i = xend; i--;)
141
                {    /* plotting loop */
142
                        ++x;
143
                        --x1;
144
                        if (D < 0) {
145
                                        /* pattern 1 forwards */
146
                                plot(x, y, reverse);
147
                                plot(++x, y, reverse);
148
                                /* pattern 1 backwards */
149
                                plot(x1, y1, reverse);
150
                                plot(--x1, y1, reverse);
151
                                D += incr1;
152
                        } else {
153
                                if (D < c) {
154
                                        /* pattern 2 forwards */
155
                                        plot(x, y, reverse);
156
                                        plot(++x, y += step, reverse);
157
                                        /* pattern 2 backwards */
158
                                        plot(x1, y1, reverse);
159
                                        plot(--x1, y1 -= step, reverse);
160
                                } else {
161
                                        /* pattern 3 forwards */
162
                                        plot(x, y += step, reverse);
163
                                        plot(++x, y, reverse);
164
                                        /* pattern 3 backwards */
165
                                        plot(x1, y1 -= step, reverse);
166
                                        plot(--x1, y1, reverse);
167
                                }
168
                                D += incr2;
169
                        }
170
                }               /* end for */
171
 
172
                /* plot last pattern */
173
                if (pixels_left) {
174
                        if (D < 0) {
175
                                plot(++x, y, reverse);  /* pattern 1 */
176
                                if (pixels_left > 1)
177
                                        plot(++x, y, reverse);
178
                                if (pixels_left > 2)
179
                                        plot(--x1, y1, reverse);
180
                        } else {
181
                                if (D < c) {
182
                                        plot(++x, y, reverse);  /* pattern 2  */
183
                                        if (pixels_left > 1)
184
                                                plot(++x, y += step, reverse);
185
                                        if (pixels_left > 2)
186
                                                plot(--x1, y1, reverse);
187
                                } else {
188
                                  /* pattern 3 */
189
                                        plot(++x, y += step, reverse);
190
                                        if (pixels_left > 1)
191
                                                plot(++x, y, reverse);
192
                                        if (pixels_left > 2)
193
                                                plot(--x1, y1 -= step, reverse);
194
                                }
195
                        }
196
                }               /* end if pixels_left */
197
        }
198
        /* end slope < 1/2 */
199
        else {                  /* slope greater than 1/2 */
200
                c = 2 * (dy - dx);
201
                incr1 = 2 * c;
202
                D = incr1 + dx;
203
                for (uint_fast32_t i = xend; i--;)
204
                {
205
                        ++x;
206
                        --x1;
207
                        if (D > 0) {
208
                          /* pattern 4 forwards */
209
                                plot(x, y += step, reverse);
210
                                plot(++x, y += step, reverse);
211
                          /* pattern 4 backwards */
212
                                plot(x1, y1 -= step, reverse);
213
                                plot(--x1, y1 -= step, reverse);
214
                                D += incr1;
215
                        } else {
216
                                if (D < c) {
217
                                  /* pattern 2 forwards */
218
                                        plot(x, y, reverse);
219
                                        plot(++x, y += step, reverse);
220
 
221
                                  /* pattern 2 backwards */
222
                                        plot(x1, y1, reverse);
223
                                        plot(--x1, y1 -= step, reverse);
224
                                } else {
225
                                  /* pattern 3 forwards */
226
                                        plot(x, y += step, reverse);
227
                                        plot(++x, y, reverse);
228
                                  /* pattern 3 backwards */
229
                                        plot(x1, y1 -= step, reverse);
230
                                        plot(--x1, y1, reverse);
231
                                }
232
                                D += incr2;
233
                        }
234
                }               /* end for */
235
                /* plot last pattern */
236
                if (pixels_left) {
237
                        if (D > 0) {
238
                                plot(++x, y += step, reverse);  /* pattern 4 */
239
                                if (pixels_left > 1)
240
                                        plot(++x, y += step, reverse);
241
                                if (pixels_left > 2)
242
                                        plot(--x1, y1 -= step, reverse);
243
                        } else {
244
                                if (D < c) {
245
                                        plot(++x, y, reverse);  /* pattern 2  */
246
                                        if (pixels_left > 1)
247
                                                plot(++x, y += step, reverse);
248
                                        if (pixels_left > 2)
249
                                                plot(--x1, y1, reverse);
250
                                } else {
251
                                  /* pattern 3 */
252
                                        plot(++x, y += step, reverse);
253
                                        if (pixels_left > 1)
254
                                                plot(++x, y, reverse);
255
                                        if (pixels_left > 2) {
256
                                                if (D > c) /* step 3 */
257
                                                   plot(--x1, y1 -= step, reverse);
258
                                                else /* step 2 */
259
                                                        plot(--x1, y1, reverse);
260
                                        }
261
                                }
262
                        }
263
                }
264
        }
265
}
266
 
267
 
268
//unclipped version just calls clipping version for now
269
void gr_uline(grs_canvas &canvas, const fix _a1, const fix _b1, const fix _a2, const fix _b2, const color_palette_index color)
270
{
271
        int a1,b1,a2,b2;
272
        a1 = f2i(_a1); b1 = f2i(_b1); a2 = f2i(_a2); b2 = f2i(_b2);
273
        switch(canvas.cv_bitmap.get_type())
274
        {
275
#if DXX_USE_OGL
276
        case bm_mode::ogl:
277
                ogl_ulinec(canvas, a1, b1, a2, b2, color);
278
                return;
279
#endif
280
        case bm_mode::linear:
281
                gr_universal_uline(canvas, a1, b1, a2, b2, color);
282
                return;
283
        }
284
        return;
285
}
286
 
287
// Returns 0 if drawn with no clipping, 1 if drawn but clipped, and
288
// 2 if not drawn at all.
289
 
290
void gr_line(grs_canvas &canvas, fix a1, fix b1, fix a2, fix b2, const color_palette_index color)
291
{
292
        int x1, y1, x2, y2;
293
        x1 = i2f(MINX);
294
        y1 = i2f(MINY);
295
        x2 = i2f(canvas.cv_bitmap.bm_w - 1);
296
        y2 = i2f(canvas.cv_bitmap.bm_h - 1);
297
 
298
        CLIPLINE(a1,b1,a2,b2,x1,y1,x2,y2,return,, FIXSCALE );
299
        gr_uline(canvas, a1, b1, a2, b2, color);
300
}
301
 
302
}