1 /*
2  * OpenBOR - http://www.LavaLit.com
3  * -----------------------------------------------------------------------
4  * All rights reserved, see LICENSE in OpenBOR root for details.
5  *
6  * Copyright (c) 2004 - 2011 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) return;
44 	if(sy<0 && ey<0) return;
45 	if(sx>=screen->width && ex>=screen->width) return;
46 	if(sy>=screen->height && ey>=screen->height) return;
47 
48 
49 	// Check clipping and calculate new coords if necessary
50 
51 	diffx = ex - sx;
52 	diffy = ey - sy;
53 
54 	if(sx<0){
55 		sy -= (sx*diffy/diffx);
56 		sx = 0;
57 	}
58 	if(sy<0){
59 		sx -= (sy*diffx/diffy);
60 		sy = 0;
61 	}
62 	if(sx>=screen->width){
63 		sy -= ((sx-screen->width)*diffy/diffx);
64 		sx = screen->width-1;
65 	}
66 	if(sy>=screen->height){
67 		sx -= ((sy-screen->height)*diffx/diffy);
68 		sy = screen->height-1;
69 	}
70 
71 	if(ex<0){
72 		ey -= (ex*diffy/diffx);
73 		ex = 0;
74 	}
75 	if(ey<0){
76 		ex -= (ey*diffx/diffy);
77 		ey = 0;
78 	}
79 	if(ex>=screen->width){
80 		ey -= ((ex-screen->width)*diffy/diffx);
81 		ex = screen->width-1;
82 	}
83 	if(ey>=screen->height){
84 		ex -= ((ey-screen->height)*diffx/diffy);
85 		ey = screen->height-1;
86 	}
87 
88 
89 	// Second test: the lines that passed test 1 won't pass this time!
90 	if(sx<0 || ex<0) return;
91 	if(sy<0 || ey<0) return;
92 	if(sx>=screen->width || ex>=screen->width) return;
93 	if(sy>=screen->height || ey>=screen->height) return;
94 
95 
96 	// Recalculate directions
97 	diffx = ex - sx;
98 	diffy = ey - sy;
99 
100 	absdiffx = abso(diffx);
101 	absdiffy = abso(diffy);
102 
103 	sy *= screen->width;
104 	ey *= screen->width;
105 
106 	data = (unsigned short*)screen->data;
107 
108 	blendfp = alpha>0?blendfunctions16[alpha-1]:NULL;
109 
110 	if(absdiffx > absdiffy)
111 	{
112 		// Draw a flat line
113 		thres = absdiffx >> 1;
114 		xdir = 1;
115 		if(diffx<0) xdir = -xdir;
116 		ydir = screen->width;
117 		if(diffy<0) ydir = -ydir;
118 		while(sx!=ex)
119 		{
120 			d = sx+sy;
121 			__putpixel16(data+d);
122 			sx += xdir;
123 			if((thres-=absdiffy) <= 0){
124 				sy += ydir;
125 				thres += absdiffx;
126 			}
127 		}
128 		d = ex+ey;
129 		__putpixel16(data+d);
130 		return;
131 	}
132 
133 	// Draw a high line
134 	thres = absdiffy >> 1;
135 	xdir = 1;
136 	if(diffx<0) xdir = -1;
137 	ydir = screen->width;
138 	if(diffy<0) ydir = -ydir;
139 	while(sy!=ey){
140 		d = sx+sy;
141 		__putpixel16(data+d);
142 		sy += ydir;
143 		if((thres-=absdiffx) <= 0){
144 			sx += xdir;
145 			thres += absdiffy;
146 		}
147 	}
148 	d = ex+ey;
149 	__putpixel16(data+d);
150 }
151 
152 
153 
154 
155 // drawbox, 16bit version
drawbox16(int x,int y,int width,int height,unsigned short colour,s_screen * screen,int alpha)156 void drawbox16(int x, int y, int width, int height, unsigned short colour, s_screen *screen, int alpha)
157 {
158 	unsigned short *cp;
159 	unsigned short(*blendfp)(unsigned short,unsigned short);
160 
161 	if(width<=0) return;
162 	if(height<=0) return;
163 	if(screen==NULL) return;
164 
165 	if(x<0){
166 		if((width+=x)<=0) return;
167 		x = 0;
168 	}
169 	else if(x>=screen->width) return;
170 	if(y<0){
171 		if((height+=y)<=0) return;
172 		y = 0;
173 	}
174 	else if(y>=screen->height) return;
175 	if(x+width>screen->width) width = screen->width-x;
176 	if(y+height>screen->height) height = screen->height-y;
177 
178 	cp = ((unsigned short*)screen->data) + (y*screen->width + x);
179 
180 	blendfp = alpha>0?blendfunctions16[alpha-1]:NULL;
181 
182 	while(--height>=0){
183 		for(x=0;x<width;x++){
184 			__putpixel16(cp);
185 			cp++;
186 		}
187 		cp += (screen->width - width);
188 	}
189 }
190 
191 
192 
193 // Putpixel 16bit version
putpixel16(unsigned x,unsigned y,unsigned short colour,s_screen * screen,int alpha)194 void putpixel16(unsigned x, unsigned y, unsigned short colour, s_screen *screen, int alpha){
195 	int pixind;
196 	unsigned short* data ;
197 	unsigned short(*blendfp)(unsigned short,unsigned short);
198 	if(x>screen->width || y>screen->height) return;
199 	pixind = x+y*screen->width;
200 	data = (unsigned short*)screen->data + pixind;
201 	blendfp = alpha>0?blendfunctions16[alpha-1]:NULL;
202 	__putpixel16(data);
203 }
204 
205 
206