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