1 /*
2 * OpenBOR - http://www.chronocrash.com
3 * -----------------------------------------------------------------------
4 * All rights reserved, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2014 OpenBOR Team
7 */
8
9 // draw functions with 32bit pixel format, with alpha blending
10
11 #include <string.h>
12 #include "types.h"
13
14 #ifndef NULL
15 #define NULL ((void*)0)
16 #endif
17
18 #define abso(x) (x<0?-x:x)
19
20 #define __putpixel32(p) \
21 if(blendfp )\
22 {\
23 *(p) = blendfp(colour, *(p));\
24 }\
25 else\
26 {\
27 *(p) = colour;\
28 }
29
30 // same as the one in draw.c, this is 32bit version
31 // blendfp is the blending function pointer
line32(int sx,int sy,int ex,int ey,unsigned colour,s_screen * screen,int alpha)32 void line32(int sx, int sy, int ex, int ey, unsigned colour, s_screen *screen, int alpha)
33 {
34 int diffx, diffy;
35 int absdiffx, absdiffy;
36 int xdir, ydir;
37 int thres;
38 int d;
39 unsigned *data;
40 unsigned(*blendfp)(unsigned, unsigned);
41
42 // Some off-screen lines may slip through this test!
43 if(sx < 0 && ex < 0)
44 {
45 return;
46 }
47 if(sy < 0 && ey < 0)
48 {
49 return;
50 }
51 if(sx >= screen->width && ex >= screen->width)
52 {
53 return;
54 }
55 if(sy >= screen->height && ey >= screen->height)
56 {
57 return;
58 }
59
60
61 // Check clipping and calculate new coords if necessary
62
63 diffx = ex - sx;
64 diffy = ey - sy;
65
66 if(sx < 0)
67 {
68 sy -= (sx * diffy / diffx);
69 sx = 0;
70 }
71 if(sy < 0)
72 {
73 sx -= (sy * diffx / diffy);
74 sy = 0;
75 }
76 if(sx >= screen->width)
77 {
78 sy -= ((sx - screen->width) * diffy / diffx);
79 sx = screen->width - 1;
80 }
81 if(sy >= screen->height)
82 {
83 sx -= ((sy - screen->height) * diffx / diffy);
84 sy = screen->height - 1;
85 }
86
87 if(ex < 0)
88 {
89 ey -= (ex * diffy / diffx);
90 ex = 0;
91 }
92 if(ey < 0)
93 {
94 ex -= (ey * diffx / diffy);
95 ey = 0;
96 }
97 if(ex >= screen->width)
98 {
99 ey -= ((ex - screen->width) * diffy / diffx);
100 ex = screen->width - 1;
101 }
102 if(ey >= screen->height)
103 {
104 ex -= ((ey - screen->height) * diffx / diffy);
105 ey = screen->height - 1;
106 }
107
108
109 // Second test: the lines that passed test 1 won't pass this time!
110 if(sx < 0 || ex < 0)
111 {
112 return;
113 }
114 if(sy < 0 || ey < 0)
115 {
116 return;
117 }
118 if(sx >= screen->width || ex >= screen->width)
119 {
120 return;
121 }
122 if(sy >= screen->height || ey >= screen->height)
123 {
124 return;
125 }
126
127
128 // Recalculate directions
129 diffx = ex - sx;
130 diffy = ey - sy;
131
132 absdiffx = abso(diffx);
133 absdiffy = abso(diffy);
134
135 sy *= screen->width;
136 ey *= screen->width;
137
138 data = (unsigned *)screen->data;
139
140 colour &= 0x00FFFFFF;
141
142 blendfp = getblendfunction32(alpha);
143
144 if(absdiffx > absdiffy)
145 {
146 // Draw a flat line
147 thres = absdiffx >> 1;
148 xdir = 1;
149 if(diffx < 0)
150 {
151 xdir = -xdir;
152 }
153 ydir = screen->width;
154 if(diffy < 0)
155 {
156 ydir = -ydir;
157 }
158 while(sx != ex)
159 {
160 d = sx + sy;
161 __putpixel32(data + d);
162 sx += xdir;
163 if((thres -= absdiffy) <= 0)
164 {
165 sy += ydir;
166 thres += absdiffx;
167 }
168 }
169 d = ex + ey;
170 __putpixel32(data + d);
171 return;
172 }
173
174 // Draw a high line
175 thres = absdiffy >> 1;
176 xdir = 1;
177 if(diffx < 0)
178 {
179 xdir = -1;
180 }
181 ydir = screen->width;
182 if(diffy < 0)
183 {
184 ydir = -ydir;
185 }
186 while(sy != ey)
187 {
188 d = sx + sy;
189 __putpixel32(data + d);
190 sy += ydir;
191 if((thres -= absdiffx) <= 0)
192 {
193 sx += xdir;
194 thres += absdiffy;
195 }
196 }
197 d = ex + ey;
198 __putpixel32(data + d);
199 }
200
201
202
203
204 // drawbox, 32bit version
drawbox32(int x,int y,int width,int height,unsigned colour,s_screen * screen,int alpha)205 void drawbox32(int x, int y, int width, int height, unsigned colour, s_screen *screen, int alpha)
206 {
207 unsigned *cp;
208 unsigned(*blendfp)(unsigned, unsigned);
209
210 if(width <= 0)
211 {
212 return;
213 }
214 if(height <= 0)
215 {
216 return;
217 }
218 if(screen == NULL)
219 {
220 return;
221 }
222
223 if(x < 0)
224 {
225 if((width += x) <= 0)
226 {
227 return;
228 }
229 x = 0;
230 }
231 else if(x >= screen->width)
232 {
233 return;
234 }
235 if(y < 0)
236 {
237 if((height += y) <= 0)
238 {
239 return;
240 }
241 y = 0;
242 }
243 else if(y >= screen->height)
244 {
245 return;
246 }
247 if(x + width > screen->width)
248 {
249 width = screen->width - x;
250 }
251 if(y + height > screen->height)
252 {
253 height = screen->height - y;
254 }
255
256 cp = ((unsigned *)screen->data) + (y * screen->width + x);
257 colour &= 0x00FFFFFF;
258
259 blendfp = getblendfunction32(alpha);
260
261 while(--height >= 0)
262 {
263 for(x = 0; x < width; x++)
264 {
265 __putpixel32(cp);
266 cp++;
267 }
268 cp += (screen->width - width);
269 }
270 }
271
272
273
274 // Putpixel 32bit version
_putpixel32(unsigned x,unsigned y,unsigned colour,s_screen * screen,int alpha)275 void _putpixel32(unsigned x, unsigned y, unsigned colour, s_screen *screen, int alpha)
276 {
277 int pixind;
278 unsigned *data ;
279 unsigned(*blendfp)(unsigned, unsigned);
280 if(x > screen->width || y > screen->height)
281 {
282 return;
283 }
284 pixind = x + y * screen->width;
285 data = (unsigned *)screen->data + pixind;
286 colour &= 0x00FFFFFF;
287 blendfp = getblendfunction32(alpha);
288 __putpixel32(data);
289 }
290
291
292