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