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