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