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 // Simple bitmap code. Not fast, but useful nonetheless...
10 // 25-jan-2003
11 
12 #include <stdio.h>
13 #include <string.h>
14 #include <stddef.h>
15 #include "globals.h"
16 #include "types.h"
17 
18 #define		TRANS_INDEX		0x00
19 
allocbitmap(int width,int height,int format)20 s_bitmap * allocbitmap(int width, int height, int format){
21 	s_bitmap *b;
22 	ptrdiff_t psize, extrab;
23 	if(width * height == 0) return NULL;
24 	psize = width*height*pixelbytes[(int)format];
25 	extrab = (4-psize%4)%4;
26 	if(format==PIXEL_x8)
27 		b = (s_bitmap *)malloc(sizeof(s_bitmap) + psize + extrab +PAL_BYTES);
28 	else
29 		b = (s_bitmap *)malloc(sizeof(s_bitmap) + psize);
30 	if(b){
31 		b->width = width;
32 		b->height = height;
33 		b->pixelformat = format;
34 		if(format==PIXEL_x8)
35 			b->palette = ((unsigned char*)b->data) + psize + extrab;
36 		else
37 			b->palette = NULL;
38 	}
39 	return b;
40 }
41 
freebitmap(s_bitmap * bitmap)42 void freebitmap(s_bitmap *bitmap){
43 	if(bitmap != NULL){
44 		free(bitmap);
45 		bitmap = NULL;
46 	}
47 }
48 
49 // Sluggish getbitmap function. Should be redone in ASM.
getbitmap(int x,int y,int width,int height,s_bitmap * bitmap,s_screen * screen)50 void getbitmap(int x, int y, int width, int height, s_bitmap *bitmap, s_screen *screen){
51 
52 	int s, d;
53 	//int i;
54 	int j;
55 
56 	// Clip width and height
57 	if(x<0){
58 		width += x;
59 		x = 0;
60 	}
61 	if(y<0){
62 		height += y;
63 		y = 0;
64 	}
65 	if(x+width > screen->width){
66 		width = screen->width - x;
67 	}
68 	if(y+height > screen->height){
69 		height = screen->height - y;
70 	}
71 	if(width<=0 || height<=0){
72 		bitmap->width = 0;
73 		bitmap->height = 0;
74 		return;
75 	}
76 
77 	bitmap->width = width;
78 	bitmap->height = height;
79 
80 	d = 0;
81 	for(j=0; j<height; j++){
82 		s = x + (y+j) * screen->width;
83 		memcpy(((char*)bitmap->data) + d, ((char*)screen->data) + s, width);
84 		d+=width;
85 		/*
86 		for(i=0; i<width; i++){
87 			bitmap->data[d] = screen->data[s];
88 			++d;
89 			++s;
90 		}
91 		*/
92 	}
93 }
94 
95 
96 
97 // Clipped putbitmap. Slow.
putbitmap(int x,int y,s_bitmap * bitmap,s_screen * screen)98 void putbitmap(int x, int y, s_bitmap *bitmap, s_screen *screen){
99 	int skipleft = 0;
100 	int skiptop = 0;
101 	int width = bitmap->width;
102 	int height = bitmap->height;
103 	int s, d;
104 	int i;
105 
106 	// Clip width and height
107 	if(x<0){
108 		skipleft = -x;
109 		width -= skipleft;
110 		x = 0;
111 	}
112 	if(y<0){
113 		skiptop = -y;
114 		height -= skiptop;
115 		y = 0;
116 	}
117 	if(x+width > screen->width){
118 		width = screen->width - x;
119 	}
120 	if(y+height > screen->height){
121 		height = screen->height - y;
122 	}
123 	if(width<=0 || height<=0) return;
124 
125 	d = (y*screen->width) + x;
126 
127 	do{
128 		s = skiptop * bitmap->width + skipleft;
129 		++skiptop;
130 		for(i=0; i<width; i++){
131 			screen->data[d] = bitmap->data[s];
132 			++d;
133 			++s;
134 		}
135 		d += screen->width;
136 		d -= width;
137 	}while(--height);
138 }
139 
140 
141 
142 
143 // Flip horizontally
flipbitmap(s_bitmap * bitmap)144 void flipbitmap(s_bitmap *bitmap){
145 	int x, xo, y;
146 	unsigned char t;
147 	int xsize = bitmap->width;
148 	int ysize = bitmap->height;
149 
150 	for(y=0; y<ysize; y++){
151 		for(x=0, xo=xsize-1; x<xsize/2; x++, xo--){
152 			t = bitmap->data[y*xsize+x];
153 			bitmap->data[y*xsize+x] = bitmap->data[y*xsize+xo];
154 			bitmap->data[y*xsize+xo] = t;
155 		}
156 	}
157 }
158 
159 
160 
161 
162 
163 // Clipbitmap: cuts off transparent edges to optimize a bitmap.
clipbitmap(s_bitmap * bitmap,int * clipl,int * clipr,int * clipt,int * clipb)164 void clipbitmap(s_bitmap *bitmap, int *clipl, int *clipr, int *clipt, int *clipb){
165 
166 	int x, y, i;
167 	int clip, clear;
168 	int xsize = bitmap->width;
169 	int ysize = bitmap->height;
170 	int tclipmove = 0;
171 	int lclipmove = 0;
172 	int bclipmove = 0;
173 	int rclipmove = 0;
174 
175 
176 
177 	// Determine size of empty top
178 	clip = 0;
179 	for(y=0; y<ysize; y++){
180 		clear = 1;
181 		for(x=0; x<xsize && clear; x++){
182 			if(bitmap->data[y*xsize+x] != TRANS_INDEX) clear = 0;
183 		}
184 		if(clear) ++clip;
185 		else break;
186 	}
187 
188 	if(clip){
189 		// Cut off empty top
190 		ysize -= clip;
191 		if(ysize<1){
192 			// If nothing is left of the bitmap, return...
193 			if(clipl) *clipl = 0;
194 			if(clipr) *clipr = 0;
195 			if(clipt) *clipt = 0;
196 			if(clipb) *clipb = 0;
197 			bitmap->width = 0;
198 			bitmap->height = 0;
199 			return;
200 		}
201 		bitmap->height = ysize;
202 		for(i=0; i<xsize*ysize; i++) bitmap->data[i] = bitmap->data[i+(clip*xsize)];
203 		tclipmove = clip;
204 	}
205 
206 
207 
208 	// Determine size of empty bottom
209 	clip = 0;
210 	for(y=ysize-1; y>=0; y--){
211 		clear = 1;
212 		for(x=0; x<xsize && clear; x++){
213 			if(bitmap->data[y*xsize+x] != TRANS_INDEX) clear = 0;
214 		}
215 		if(clear) ++clip;
216 		else break;
217 	}
218 
219 	// Cut off empty bottom
220 	ysize -= clip;
221 	bitmap->height = ysize;
222 	bclipmove = clip;
223 
224 
225 	// Determine size of empty left side
226 	clip = 2000000000;
227 	for(y=0; y<ysize; y++){
228 		clear = 0;
229 		for(x=0; x<xsize; x++){
230 			if(bitmap->data[y*xsize+x] != TRANS_INDEX) break;
231 			++clear;
232 		}
233 		if(clear < clip) clip = clear;
234 	}
235 
236 	// Cut off empty pixels on the left side
237 	if(clip){
238 		xsize -= clip;
239 		bitmap->width = xsize;
240 		for(y=0; y<ysize; y++){
241 			for(x=0; x<xsize; x++) bitmap->data[y*xsize+x] = bitmap->data[y*xsize+x+(clip*(y+1))];
242 		}
243 		lclipmove = clip;
244 	}
245 
246 	// Determine size of empty right side
247 	clip = 2000000000;
248 	for(y=0; y<ysize; y++){
249 		clear = 0;
250 		for(x=xsize-1; x>=0; x--){
251 			if(bitmap->data[y*xsize+x] != TRANS_INDEX) break;
252 			++clear;
253 		}
254 		if(clear < clip) clip = clear;
255 	}
256 
257 	// Cut off empty pixels on the right side
258 	if(clip){
259 		xsize -= clip;
260 		bitmap->width = xsize;
261 		for(y=0; y<ysize; y++){
262 			for(x=0; x<xsize; x++) bitmap->data[y*xsize+x] = bitmap->data[y*xsize+x+(clip*y)];
263 		}
264 		rclipmove = clip;
265 	}
266 
267 	if(clipl) *clipl = lclipmove;
268 	if(clipr) *clipr = rclipmove;
269 	if(clipt) *clipt = tclipmove;
270 	if(clipb) *clipb = bclipmove;
271 }
272 
273 
274 
275