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 16bit 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 __putpixel16(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 16bit version
31 // blendfp is the blending function pointer
line16(int sx,int sy,int ex,int ey,unsigned short colour,s_screen * screen,int alpha)32 void line16(int sx, int sy, int ex, int ey, unsigned short 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 short *data;
40     unsigned short(*blendfp)(unsigned short, unsigned short);
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 short *)screen->data;
139 
140     blendfp = getblendfunction16(alpha);
141 
142     if(absdiffx > absdiffy)
143     {
144         // Draw a flat line
145         thres = absdiffx >> 1;
146         xdir = 1;
147         if(diffx < 0)
148         {
149             xdir = -xdir;
150         }
151         ydir = screen->width;
152         if(diffy < 0)
153         {
154             ydir = -ydir;
155         }
156         while(sx != ex)
157         {
158             d = sx + sy;
159             __putpixel16(data + d);
160             sx += xdir;
161             if((thres -= absdiffy) <= 0)
162             {
163                 sy += ydir;
164                 thres += absdiffx;
165             }
166         }
167         d = ex + ey;
168         __putpixel16(data + d);
169         return;
170     }
171 
172     // Draw a high line
173     thres = absdiffy >> 1;
174     xdir = 1;
175     if(diffx < 0)
176     {
177         xdir = -1;
178     }
179     ydir = screen->width;
180     if(diffy < 0)
181     {
182         ydir = -ydir;
183     }
184     while(sy != ey)
185     {
186         d = sx + sy;
187         __putpixel16(data + d);
188         sy += ydir;
189         if((thres -= absdiffx) <= 0)
190         {
191             sx += xdir;
192             thres += absdiffy;
193         }
194     }
195     d = ex + ey;
196     __putpixel16(data + d);
197 }
198 
199 
200 
201 
202 // drawbox, 16bit version
drawbox16(int x,int y,int width,int height,unsigned short colour,s_screen * screen,int alpha)203 void drawbox16(int x, int y, int width, int height, unsigned short colour, s_screen *screen, int alpha)
204 {
205     unsigned short *cp;
206     unsigned short(*blendfp)(unsigned short, unsigned short);
207 
208     if(width <= 0)
209     {
210         return;
211     }
212     if(height <= 0)
213     {
214         return;
215     }
216     if(screen == NULL)
217     {
218         return;
219     }
220 
221     if(x < 0)
222     {
223         if((width += x) <= 0)
224         {
225             return;
226         }
227         x = 0;
228     }
229     else if(x >= screen->width)
230     {
231         return;
232     }
233     if(y < 0)
234     {
235         if((height += y) <= 0)
236         {
237             return;
238         }
239         y = 0;
240     }
241     else if(y >= screen->height)
242     {
243         return;
244     }
245     if(x + width > screen->width)
246     {
247         width = screen->width - x;
248     }
249     if(y + height > screen->height)
250     {
251         height = screen->height - y;
252     }
253 
254     cp = ((unsigned short *)screen->data) + (y * screen->width + x);
255 
256     blendfp = getblendfunction16(alpha);
257 
258     while(--height >= 0)
259     {
260         for(x = 0; x < width; x++)
261         {
262             __putpixel16(cp);
263             cp++;
264         }
265         cp += (screen->width - width);
266     }
267 }
268 
269 
270 
271 // Putpixel 16bit version
_putpixel16(unsigned x,unsigned y,unsigned short colour,s_screen * screen,int alpha)272 void _putpixel16(unsigned x, unsigned y, unsigned short colour, s_screen *screen, int alpha)
273 {
274     int pixind;
275     unsigned short *data ;
276     unsigned short(*blendfp)(unsigned short, unsigned short);
277     if(x > screen->width || y > screen->height)
278     {
279         return;
280     }
281     pixind = x + y * screen->width;
282     data = (unsigned short *)screen->data + pixind;
283     blendfp = getblendfunction16(alpha);
284     __putpixel16(data);
285 }
286 
287 
288