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