This commit was manufactured by cvs2svn to create tag 'd2x-0_1_2'.
[btb/d2x.git] / 2d / ibitblt.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13 /*
14  *  Routines to to inverse bitblitting -- well not really.
15  *  We don't inverse bitblt like in the PC, but this code
16  *  does set up a structure that blits around the cockpit
17  *
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #include <string.h>
25 #include "pstypes.h"
26 #include "gr.h"
27 #include "grdef.h"
28 #include "ibitblt.h"
29 #include "error.h"
30 //added 05/17/99 Matt Mueller
31 #include "u_mem.h"
32 //end addition -MM
33
34 #define FIND_START              1
35 #define FIND_STOP               2
36
37 #define MAX_WIDTH                       1280    
38 #define MAX_SCANLINES           1024    
39 #define MAX_HOLES                               10
40
41 static short start_points[MAX_SCANLINES][MAX_HOLES];
42 static short hole_length[MAX_SCANLINES][MAX_HOLES];
43 static double *scanline = NULL;
44
45 // adb: gr_linear_movsd assumes c >= 4
46 #define gr_linear_movsd(s,d,c) memcpy(d,s,c)
47
48 void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp, ubyte pixel_double)
49 {
50         int x, y, sw, sh, srowsize, drowsize, dstart, sy, dy;
51         ubyte *src, *dest;
52         short *current_hole, *current_hole_length;
53
54 // variable setup
55
56         sw = src_bmp->bm_w;
57         sh = src_bmp->bm_h;
58         srowsize = src_bmp->bm_rowsize;
59         drowsize = dest_bmp->bm_rowsize;
60         src = src_bmp->bm_data;
61         dest = dest_bmp->bm_data;
62
63         sy = 0;
64         while (start_points[sy][0] == -1) {
65                 sy++;
66                 dest += drowsize;
67         }
68         
69         if (pixel_double) {
70                 ubyte *scan = (ubyte *)scanline;                // set up for byte processing of scanline
71                 
72                 dy = sy;
73                 for (y = sy; y < sy + sh; y++) {
74                         gr_linear_rep_movsd_2x(src, scan, sw);
75                         current_hole = start_points[dy];
76                         current_hole_length = hole_length[dy];
77                         for (x = 0; x < MAX_HOLES; x++) {
78                                 if (*current_hole == -1)
79                                         break;
80                                 dstart = *current_hole;
81                                 gr_linear_movsd(&(scan[dstart]), &(dest[dstart]), *current_hole_length);
82                                 current_hole++;
83                                 current_hole_length++;
84                         }
85                         dy++;
86                         dest += drowsize;
87                         current_hole = start_points[dy];
88                         current_hole_length = hole_length[dy];
89                         for (x = 0;x < MAX_HOLES; x++) {
90                                 if (*current_hole == -1)
91                                         break;
92                                 dstart = *current_hole;
93                                 gr_linear_movsd(&(scan[dstart]), &(dest[dstart]), *current_hole_length);
94                                 current_hole++;
95                                 current_hole_length++;
96                         }
97                         dy++;
98                         dest += drowsize;
99                         src += srowsize;
100                 }
101         } else {
102                 Assert(sw <= MAX_WIDTH);
103                 Assert(sh <= MAX_SCANLINES);
104                 for (y = sy; y < sy + sh; y++) {
105                         for (x = 0; x < MAX_HOLES; x++) {
106                                 if (start_points[y][x] == -1)
107                                         break;
108                                 dstart = start_points[y][x];
109                                 gr_linear_movsd(&(src[dstart]), &(dest[dstart]), hole_length[y][x]);
110                         }
111                         dest += drowsize;
112                         src += srowsize;
113                 }
114         }
115 }
116
117 void gr_ibitblt_create_mask(grs_bitmap *mask_bmp, int sx, int sy, int sw, int sh, int srowsize)
118 {
119         int x, y;
120         ubyte mode;
121         int count = 0;
122         
123         Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
124
125         for (y = 0; y < MAX_SCANLINES; y++) {
126                 for (x = 0; x < MAX_HOLES; x++) {
127                         start_points[y][x] = -1;
128                         hole_length[y][x] = -1;
129                 }
130         }
131         
132         for (y = sy; y < sy+sh; y++) {
133                 count = 0;
134                 mode = FIND_START;
135                 for (x = sx; x < sx + sw; x++) {
136                         if ((mode == FIND_START) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] == TRANSPARENCY_COLOR)) {
137                                 start_points[y][count] = x;
138                                 mode = FIND_STOP;
139                         } else if ((mode == FIND_STOP) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] != TRANSPARENCY_COLOR)) {
140                                 hole_length[y][count] = x - start_points[y][count];
141                                 count++;
142                                 mode = FIND_START;
143                         }
144                 }
145                 if (mode == FIND_STOP) {
146                         hole_length[y][count] = x - start_points[y][count];
147                         count++;
148                 }
149                 Assert(count <= MAX_HOLES);
150         }
151 }
152
153 //added 7/11/99 by adb to prevent memleaks
154 static void free_scanline(void)
155 {
156         if (scanline) d_free(scanline);
157 }
158 //end additions - adb
159
160
161 void gr_ibitblt_find_hole_size(grs_bitmap *mask_bmp, int *minx, int *miny, int *maxx, int *maxy)
162 {
163         ubyte c;
164         int x, y, count = 0;
165         
166         Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
167         Assert( mask_bmp->bm_flags&BM_FLAG_TRANSPARENT );
168         
169         *minx = mask_bmp->bm_w - 1;
170         *maxx = 0;
171         *miny = mask_bmp->bm_h - 1;
172         *maxy = 0;
173
174         //changed 7/11/99 by adb to prevent memleaks
175         if (scanline == NULL) {
176                 scanline = (double *)d_malloc(sizeof(double) * (MAX_WIDTH / sizeof(double)));
177                 atexit(free_scanline);
178         }
179         //end changes - adb
180                 
181         for (y = 0; y < mask_bmp->bm_h; y++) {
182                 for (x = 0; x < mask_bmp->bm_w; x++) {
183                         c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x];
184                         if (c == TRANSPARENCY_COLOR) {                          // don't look for transparancy color here.
185                                 count++;
186                                 if (x < *minx) *minx = x;
187                                 if (y < *miny) *miny = y;
188                                 if (x > *maxx) *maxx = x;
189                                 if (y > *maxy) *maxy = y;
190                         }
191                 }
192         }
193         Assert (count);
194 }