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