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