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 // 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 {
22 s_bitmap *b;
23 ptrdiff_t psize, extrab;
24 if(width * height == 0)
25 {
26 return NULL;
27 }
28 psize = width * height * pixelbytes[(int)format];
29 extrab = (4 - psize % 4) % 4;
30 if(format == PIXEL_x8)
31 {
32 b = (s_bitmap *)malloc(sizeof(s_bitmap) + psize + extrab + PAL_BYTES);
33 }
34 else
35 {
36 b = (s_bitmap *)malloc(sizeof(s_bitmap) + psize);
37 }
38 if(b)
39 {
40 b->width = width;
41 b->height = height;
42 b->pixelformat = format;
43 b->magic = bitmap_magic;
44 if(format == PIXEL_x8)
45 {
46 b->palette = ((unsigned char *)b->data) + psize + extrab;
47 }
48 else
49 {
50 b->palette = NULL;
51 }
52 }
53 return b;
54 }
55
freebitmap(s_bitmap * bitmap)56 void freebitmap(s_bitmap *bitmap)
57 {
58 if(bitmap != NULL)
59 {
60 free(bitmap);
61 bitmap = NULL;
62 }
63 }
64
65 // Sluggish getbitmap function. Should be redone in ASM.
getbitmap(int x,int y,int width,int height,s_bitmap * bitmap,s_screen * screen)66 void getbitmap(int x, int y, int width, int height, s_bitmap *bitmap, s_screen *screen)
67 {
68
69 int s, d;
70 //int i;
71 int j;
72
73 // Clip width and height
74 if(x < 0)
75 {
76 width += x;
77 x = 0;
78 }
79 if(y < 0)
80 {
81 height += y;
82 y = 0;
83 }
84 if(x + width > screen->width)
85 {
86 width = screen->width - x;
87 }
88 if(y + height > screen->height)
89 {
90 height = screen->height - y;
91 }
92 if(width <= 0 || height <= 0)
93 {
94 bitmap->width = 0;
95 bitmap->height = 0;
96 return;
97 }
98
99 bitmap->width = width;
100 bitmap->height = height;
101
102 d = 0;
103 for(j = 0; j < height; j++)
104 {
105 s = x + (y + j) * screen->width;
106 memcpy(((char *)bitmap->data) + d, ((char *)screen->data) + s, width);
107 d += width;
108 /*
109 for(i=0; i<width; i++){
110 bitmap->data[d] = screen->data[s];
111 ++d;
112 ++s;
113 }
114 */
115 }
116 }
117
118
119
120 // Clipped putbitmap. Slow.
putbitmap(int x,int y,s_bitmap * bitmap,s_screen * screen)121 void putbitmap(int x, int y, s_bitmap *bitmap, s_screen *screen)
122 {
123 int skipleft = 0;
124 int skiptop = 0;
125 int width = bitmap->width;
126 int height = bitmap->height;
127 int s, d;
128 int i;
129
130 // Clip width and height
131 if(x < 0)
132 {
133 skipleft = -x;
134 width -= skipleft;
135 x = 0;
136 }
137 if(y < 0)
138 {
139 skiptop = -y;
140 height -= skiptop;
141 y = 0;
142 }
143 if(x + width > screen->width)
144 {
145 width = screen->width - x;
146 }
147 if(y + height > screen->height)
148 {
149 height = screen->height - y;
150 }
151 if(width <= 0 || height <= 0)
152 {
153 return;
154 }
155
156 d = (y * screen->width) + x;
157
158 do
159 {
160 s = skiptop * bitmap->width + skipleft;
161 ++skiptop;
162 for(i = 0; i < width; i++)
163 {
164 screen->data[d] = bitmap->data[s];
165 ++d;
166 ++s;
167 }
168 d += screen->width;
169 d -= width;
170 }
171 while(--height);
172 }
173
174
175
176
177 // Flip horizontally
flipbitmap(s_bitmap * bitmap)178 void flipbitmap(s_bitmap *bitmap)
179 {
180 int x, xo, y;
181 unsigned char t;
182 int xsize = bitmap->width;
183 int ysize = bitmap->height;
184
185 for(y = 0; y < ysize; y++)
186 {
187 for(x = 0, xo = xsize - 1; x < xsize / 2; x++, xo--)
188 {
189 t = bitmap->data[y * xsize + x];
190 bitmap->data[y * xsize + x] = bitmap->data[y * xsize + xo];
191 bitmap->data[y * xsize + xo] = t;
192 }
193 }
194 }
195
196
197
198
199
200 // Clipbitmap: cuts off transparent edges to optimize a bitmap.
clipbitmap(s_bitmap * bitmap,int * clipl,int * clipr,int * clipt,int * clipb)201 void clipbitmap(s_bitmap *bitmap, int *clipl, int *clipr, int *clipt, int *clipb)
202 {
203
204 int x, y, i;
205 int clip, clear;
206 int xsize = bitmap->width;
207 int ysize = bitmap->height;
208 int tclipmove = 0;
209 int lclipmove = 0;
210 int bclipmove = 0;
211 int rclipmove = 0;
212
213
214
215 // Determine size of empty top
216 clip = 0;
217 for(y = 0; y < ysize; y++)
218 {
219 clear = 1;
220 for(x = 0; x < xsize && clear; x++)
221 {
222 if(bitmap->data[y * xsize + x] != TRANS_INDEX)
223 {
224 clear = 0;
225 }
226 }
227 if(clear)
228 {
229 ++clip;
230 }
231 else
232 {
233 break;
234 }
235 }
236
237 if(clip)
238 {
239 // Cut off empty top
240 ysize -= clip;
241 if(ysize < 1)
242 {
243 // If nothing is left of the bitmap, return...
244 if(clipl)
245 {
246 *clipl = 0;
247 }
248 if(clipr)
249 {
250 *clipr = 0;
251 }
252 if(clipt)
253 {
254 *clipt = 0;
255 }
256 if(clipb)
257 {
258 *clipb = 0;
259 }
260 bitmap->width = 0;
261 bitmap->height = 0;
262 return;
263 }
264 bitmap->height = ysize;
265 for(i = 0; i < xsize * ysize; i++)
266 {
267 bitmap->data[i] = bitmap->data[i + (clip * xsize)];
268 }
269 tclipmove = clip;
270 }
271
272
273
274 // Determine size of empty bottom
275 clip = 0;
276 for(y = ysize - 1; y >= 0; y--)
277 {
278 clear = 1;
279 for(x = 0; x < xsize && clear; x++)
280 {
281 if(bitmap->data[y * xsize + x] != TRANS_INDEX)
282 {
283 clear = 0;
284 }
285 }
286 if(clear)
287 {
288 ++clip;
289 }
290 else
291 {
292 break;
293 }
294 }
295
296 // Cut off empty bottom
297 ysize -= clip;
298 bitmap->height = ysize;
299 bclipmove = clip;
300
301
302 // Determine size of empty left side
303 clip = 2000000000;
304 for(y = 0; y < ysize; y++)
305 {
306 clear = 0;
307 for(x = 0; x < xsize; x++)
308 {
309 if(bitmap->data[y * xsize + x] != TRANS_INDEX)
310 {
311 break;
312 }
313 ++clear;
314 }
315 if(clear < clip)
316 {
317 clip = clear;
318 }
319 }
320
321 // Cut off empty pixels on the left side
322 if(clip)
323 {
324 xsize -= clip;
325 bitmap->width = xsize;
326 for(y = 0; y < ysize; y++)
327 {
328 for(x = 0; x < xsize; x++)
329 {
330 bitmap->data[y * xsize + x] = bitmap->data[y * xsize + x + (clip * (y + 1))];
331 }
332 }
333 lclipmove = clip;
334 }
335
336 // Determine size of empty right side
337 clip = 2000000000;
338 for(y = 0; y < ysize; y++)
339 {
340 clear = 0;
341 for(x = xsize - 1; x >= 0; x--)
342 {
343 if(bitmap->data[y * xsize + x] != TRANS_INDEX)
344 {
345 break;
346 }
347 ++clear;
348 }
349 if(clear < clip)
350 {
351 clip = clear;
352 }
353 }
354
355 // Cut off empty pixels on the right side
356 if(clip)
357 {
358 xsize -= clip;
359 bitmap->width = xsize;
360 for(y = 0; y < ysize; y++)
361 {
362 for(x = 0; x < xsize; x++)
363 {
364 bitmap->data[y * xsize + x] = bitmap->data[y * xsize + x + (clip * y)];
365 }
366 }
367 rclipmove = clip;
368 }
369
370 if(clipl)
371 {
372 *clipl = lclipmove;
373 }
374 if(clipr)
375 {
376 *clipr = rclipmove;
377 }
378 if(clipt)
379 {
380 *clipt = tclipmove;
381 }
382 if(clipb)
383 {
384 *clipb = bclipmove;
385 }
386 }
387
388
389
390