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.
19 // John's new stuff below here....
22 int scale_initial_pixel_count;
25 int scale_final_pixel_count;
26 int scale_ydelta_minus_1;
28 ubyte * scale_source_ptr;
29 ubyte * scale_dest_ptr;
32 ubyte scale_rle_data[640];
34 void scale_up_bitmap(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 );
35 void scale_up_bitmap_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 );
36 void rls_stretch_scanline_setup( int XDelta, int YDelta );
37 void rls_stretch_scanline(void);
40 void decode_row( grs_bitmap * bmp, int y )
42 int i, offset=4+bmp->bm_h;
45 offset += bmp->bm_data[4+i];
46 gr_rle_decode( &bmp->bm_data[offset], scale_rle_data );
49 void scale_up_bitmap(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 )
54 dv = (v1-v0) / (y1-y0);
56 rls_stretch_scanline_setup( (int)(x1-x0), f2i(u1)-f2i(u0) );
57 if ( scale_ydelta_minus_1 < 1 ) return;
61 for (y=y0; y<=y1; y++ ) {
62 scale_source_ptr = &source_bmp->bm_data[source_bmp->bm_rowsize*f2i(v)+f2i(u0)];
63 scale_dest_ptr = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0];
64 rls_stretch_scanline();
72 void scale_up_bitmap_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 )
77 dv = (v1-v0) / (y1-y0);
79 rls_stretch_scanline_setup( (int)(x1-x0), f2i(u1)-f2i(u0) );
80 if ( scale_ydelta_minus_1 < 1 ) return;
84 for (y=y0; y<=y1; y++ ) {
85 if ( f2i(v) != last_row ) {
87 decode_row( source_bmp, last_row );
89 scale_source_ptr = &scale_rle_data[f2i(u0)];
90 scale_dest_ptr = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0];
91 rls_stretch_scanline();
96 void rls_stretch_scanline_setup( int XDelta, int YDelta )
98 scale_ydelta_minus_1 = YDelta - 1;
101 /* Minimum # of pixels in a run in this line */
102 scale_whole_step = XDelta / YDelta;
104 /* Error term adjust each time Y steps by 1; used to tell when one
105 extra pixel should be drawn as part of a run, to account for
106 fractional steps along the X axis per 1-pixel steps along Y */
107 scale_adj_up = (XDelta % YDelta) * 2;
109 /* Error term adjust when the error term turns over, used to factor
110 out the X step made at that time */
111 scale_adj_down = YDelta * 2;
113 /* Initial error term; reflects an initial step of 0.5 along the Y
115 scale_error_term = (XDelta % YDelta) - (YDelta * 2);
117 /* The initial and last runs are partial, because Y advances only 0.5
118 for these runs, rather than 1. Divide one full run, plus the
119 initial pixel, between the initial and last runs */
120 scale_initial_pixel_count = (scale_whole_step / 2) + 1;
121 scale_final_pixel_count = scale_initial_pixel_count;
123 /* If the basic run length is even and there's no fractional
124 advance, we have one pixel that could go to either the initial
125 or last partial run, which we'll arbitrarily allocate to the
127 if ((scale_adj_up == 0) && ((scale_whole_step & 0x01) == 0))
129 scale_initial_pixel_count--;
131 /* If there're an odd number of pixels per run, we have 1 pixel that can't
132 be allocated to either the initial or last partial run, so we'll add 0.5
133 to error term so this pixel will be handled by the normal full-run loop */
134 if ((scale_whole_step & 0x01) != 0)
136 scale_error_term += YDelta;
141 void rls_stretch_scanline()
144 int i, j, len, ErrorTerm, x;
146 // Setup initial variables
147 ErrorTerm = scale_error_term;
149 // Draw the first, partial run of pixels
151 c = *scale_source_ptr++;
152 if ( c != TRANSPARENCY_COLOR ) {
153 for (i=0; i<scale_initial_pixel_count; i++ )
154 *scale_dest_ptr++ = c;
156 scale_dest_ptr += scale_initial_pixel_count;
159 // Draw all full runs
161 for (j=0; j<scale_ydelta_minus_1; j++) {
162 len = scale_whole_step; // run is at least this long
164 // Advance the error term and add an extra pixel if the error term so indicates
165 if ((ErrorTerm += scale_adj_up) > 0) {
167 ErrorTerm -= scale_adj_down; // reset the error term
170 // Draw this run o' pixels
171 c = *scale_source_ptr++;
172 if ( c != TRANSPARENCY_COLOR ) {
175 while ((size_t)(scale_dest_ptr) & 0x3) { *scale_dest_ptr++ = c; len--; };
177 x = (c << 24) | (c << 16) | (c << 8) | c;
178 while (len > 4) { *((int *)scale_dest_ptr) = x; scale_dest_ptr += 4; len -= 4; };
180 while (len > 0) { *scale_dest_ptr++ = c; len--; };
182 for (i=0; i<len; i++ )
183 *scale_dest_ptr++ = c;
186 scale_dest_ptr += len;
190 // Draw the final run of pixels
191 c = *scale_source_ptr++;
192 if ( c != TRANSPARENCY_COLOR ) {
193 for (i=0; i<scale_final_pixel_count; i++ )
194 *scale_dest_ptr++ = c;
196 scale_dest_ptr += scale_final_pixel_count;
202 void scale_bitmap_c(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 )
206 ubyte * sbits, * dbits;
208 du = (u1-u0) / (x1-x0);
209 dv = (v1-v0) / (y1-y0);
213 for (y=y0; y<=y1; y++ ) {
214 sbits = &source_bmp->bm_data[source_bmp->bm_rowsize*f2i(v)];
215 dbits = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0];
218 for (x=x0; x<=x1; x++ ) {
219 *dbits++ = sbits[ u >> 16 ];
225 void scale_row_asm_transparent( ubyte * sbits, ubyte * dbits, int width, fix u, fix du )
231 for (i=0; i<width; i++ ) {
232 c = sbits[ u >> 16 ];
233 if ( c!=TRANSPARENCY_COLOR)
241 ubyte *dbits_end = &dbits[width-1];
248 next_u_int = f2i(u)+1;
249 c = sbits[ next_u_int ];
250 next_u = i2f(next_u_int);
251 if ( c != TRANSPARENCY_COLOR ) goto NonTransparent;
256 if ( dbits > dbits_end ) return;
259 next_u_int = f2i(u)+1;
260 c = sbits[ next_u_int ];
261 next_u = i2f(next_u_int);
262 if ( c != TRANSPARENCY_COLOR ) goto NonTransparent;
270 if ( dbits > dbits_end ) return;
273 next_u_int = f2i(u)+1;
274 c = sbits[ next_u_int ];
275 next_u = i2f(next_u_int);
276 if ( c == TRANSPARENCY_COLOR ) goto Transparent;
284 for ( i=0; i<width; i++ ) {
287 if ( c != TRANSPARENCY_COLOR )
296 void scale_bitmap_c_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1 )
301 du = (u1-u0) / (x1-x0);
302 dv = (v1-v0) / (y1-y0);
306 for (y=y0; y<=y1; y++ ) {
307 if ( f2i(v) != last_row ) {
309 decode_row( source_bmp, last_row );
311 scale_row_asm_transparent( scale_rle_data, &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0], x1-x0+1, u0, du );
316 #define FIND_SCALED_NUM(x,x0,x1,y0,y1) (fixmuldiv((x)-(x0),(y1)-(y0),(x1)-(x0))+(y0))
318 // Scales bitmap, bp, into vertbuf[0] to vertbuf[1]
319 void scale_bitmap(grs_bitmap *bp, grs_point *vertbuf ,int orientation)
321 grs_bitmap * dbp = &grd_curcanv->cv_bitmap;
324 fix clipped_x0, clipped_y0, clipped_x1, clipped_y1;
325 fix clipped_u0, clipped_v0, clipped_u1, clipped_v1;
326 fix xmin, xmax, ymin, ymax;
327 int dx0, dy0, dx1, dy1;
329 // Set initial variables....
331 x0 = vertbuf[0].x; y0 = vertbuf[0].y;
332 x1 = vertbuf[2].x; y1 = vertbuf[2].y;
335 xmax = i2f(dbp->bm_w)-fl2f(.5); ymax = i2f(dbp->bm_h)-fl2f(.5);
337 u0 = i2f(0); v0 = i2f(0);
338 u1 = i2f(bp->bm_w-1); v1 = i2f(bp->bm_h-1);
340 // Check for obviously offscreen bitmaps...
341 if ( (y1<=y0) || (x1<=x0) ) return;
342 if ( (x1<0 ) || (x0>=xmax) ) return;
343 if ( (y1<0 ) || (y0>=ymax) ) return;
345 clipped_u0 = u0; clipped_v0 = v0;
346 clipped_u1 = u1; clipped_v1 = v1;
348 clipped_x0 = x0; clipped_y0 = y0;
349 clipped_x1 = x1; clipped_y1 = y1;
351 // Clip the left, moving u0 right as necessary
353 clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1);
357 // Clip the right, moving u1 left as necessary
359 clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1);
363 // Clip the top, moving v0 down as necessary
365 clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1);
369 // Clip the bottom, moving v1 up as necessary
371 clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1);
375 dx0 = f2i(clipped_x0); dx1 = f2i(clipped_x1);
376 dy0 = f2i(clipped_y0); dy1 = f2i(clipped_y1);
378 if (dx1<=dx0) return;
379 if (dy1<=dy0) return;
383 // Assert( dx1<dbp->bm_w );
384 // Assert( dy1<dbp->bm_h );
385 // Assert( f2i(u0)<=f2i(u1) );
386 // Assert( f2i(v0)<=f2i(v1) );
387 // Assert( f2i(u0)>=0 );
388 // Assert( f2i(v0)>=0 );
389 // Assert( u1<i2f(bp->bm_w) );
390 // Assert( v1<i2f(bp->bm_h) );
391 //mprintf( 0, "(%.2f,%.2f) to (%.2f,%.2f) using (%.2f,%.2f) to (%.2f,%.2f)\n", f2fl(clipped_x0), f2fl(clipped_y0), f2fl(clipped_x1), f2fl(clipped_y1), f2fl(clipped_u0), f2fl(clipped_v0), f2fl(clipped_u1), f2fl(clipped_v1) );
393 dtemp = f2i(clipped_u1)-f2i(clipped_u0);
396 if ( bp->bm_flags & BM_FLAG_RLE )
397 scale_bitmap_c_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 );
399 scale_bitmap_c(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 );
401 if ( bp->bm_flags & BM_FLAG_RLE ) {
402 if ( (dtemp < (f2i(clipped_x1)-f2i(clipped_x0))) && (dtemp>0) )
403 scale_up_bitmap_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 );
405 scale_bitmap_c_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 );
407 if ( (dtemp < (f2i(clipped_x1)-f2i(clipped_x0))) && (dtemp>0) )
408 scale_up_bitmap(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 );
410 scale_bitmap_c(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1 );