IMAGE_NAMESPACE #define SET_POINTS(a,b,c,d,e,f) { \ if( a==d ) points[0].flags.samepoint=1; else points[0].flags.samepoint=0; \ points[0].flags.no_left = points[0].flags.no_right = 0; \ points[0].left.x = x##a; \ points[0].left.y= y##a; \ points[0].left.vertex_number = a-1; \ points[0].right.x = x##d; \ points[0].right.y= y##d; \ points[0].right.vertex_number = d-1; \ if( b==e ) points[1].flags.samepoint=1; else points[1].flags.samepoint=0; \ points[1].flags.no_left = points[1].flags.no_right = 0; \ points[1].left.x = x##b; \ points[1].left.y= y##b; \ points[1].left.vertex_number = b-1; \ points[1].right.x = x##e; \ points[1].right.y= y##e; \ points[1].right.vertex_number = e-1; \ if( c==f ) points[2].flags.samepoint=1; else points[2].flags.samepoint=0; \ if( c ) { points[2].left.x = x##c; \ points[2].left.y= y##c; \ points[2].left.vertex_number = c-1; \ points[2].flags.no_left = 0;\ } else points[2].flags.no_left = 1;\ if( f ) { points[2].right.x = x##f; \ points[2].right.y= y##f; \ points[2].right.vertex_number = f-1; \ points[2].flags.no_right = 0;\ } else points[2].flags.no_right = 1;\ } #define SCALE_SHIFT 0 static void PlotArbitrary( Image dest , Image source , S_32 x1, S_32 y1 , S_32 x2, S_32 y2 , S_32 x3, S_32 y3 , S_32 x4, S_32 y4 , _32 alpha , _32 mode , _32 param1 , _32 param2 , _32 param3 ) { // x1, y1 define the position of the upper left corner of the image // x2, y2 define the position of the corner to the right of the upper left // x3, y3 define the position of the corner down from x2, y2 // x4, y4 define the position left of the corner at x3, y3 int lines = 0; int cols = 0; struct { struct { int samepoint : 1; int no_left : 1; int no_right : 1; } flags; struct { S_32 x, y; int vertex_number; // 0, 1, 2, 3 }left; struct { S_32 x, y; int vertex_number; // 0, 1, 2, 3 } right; } points[3]; struct { int x, y; } verts[4]; int x0 = 0; int y0 = 0; // needed cause macro isn't the smartest... #ifdef DEBUG_TIMING //lprintf( "-- Begin Setup" ); #endif verts[0].x = 0; verts[0].y = 0; verts[1].x = source->real_width << SCALE_SHIFT; verts[1].y = 0; verts[2].x = source->real_width << SCALE_SHIFT; verts[2].y = source->real_height << SCALE_SHIFT; verts[3].x = 0; verts[3].y = source->real_height << SCALE_SHIFT; #ifdef DEBUG_TIMING { //lprintf( WIDE("points : %d,%d %d,%d %d,%d %d,%d"), x1, y1, x2, y2, x3, y3, x4, y4 ); } #endif if( y1 < y2 ) { if( y1 < y3 ) { if( y1 < y4 ) { // y1 is the least if( ( y3 > y2 ) && ( y3 > y4 ) ) { SET_POINTS( 1, 4, 3, 1, 2, 3 ); } else if( y3 == y2 ) { SET_POINTS( 1, 4, 3, 1, 2, 0 ); } else if( y3 == y4 ) { SET_POINTS( 1, 4, 0, 1, 2, 3 ); } else { lprintf( WIDE("Invalid configuration ( convex? )") ); } } else if( y4 < y1 ) { // y4 is the least if( ( y2 > y3 ) && ( y2 > y1 ) ) { SET_POINTS( 4, 3, 2, 4, 1, 2 ); } else if( y2 == y3 ) { SET_POINTS( 4, 3, 0, 4, 1, 2 ); } else if( y2 == y1 ) { SET_POINTS( 4, 3, 2, 4, 1, 0 ); } else if( y3 == y2 ) { SET_POINTS( 4, 3, 0, 4, 1, 2 ); } else if( y2 == y1 ) { SET_POINTS( 4, 3, 2, 4, 1, 0 ); } else { lprintf( WIDE("Invalid configuration ( convex? )") ); } } else // y4 == y1 and these are the least { if( y2 > y3 ) { SET_POINTS( 4, 3, 2, 1, 2, 0 ); } else if( y3 > y2 ) { SET_POINTS( 4, 3, 0, 1, 2, 3 ); } else { SET_POINTS( 4, 3, 0, 1, 2, 0 ); } } } else if( y3 < y1 ) { if( y3 < y4 ) { // y3 is the least SET_POINTS( 3, 2, 1, 3, 4, 1 ); //SET_POINTS( 3, 2, 1, 3, } else if( y4 < y3 ) { // y4 is the least //if( ( y2 > y1 ) && ( y2 > y3 ) ) SET_POINTS( 4, 3, 2, 4, 1, 2 ); //else if( } else { // y3 and y4 are both least... if( y2 == y1 ) { SET_POINTS( 3, 2, 0, 4, 1, 0 ); } else if( y2 > y1 ) { SET_POINTS( 3, 2, 0, 4, 1, 2 ); } else { SET_POINTS( 3, 2, 1, 4, 1, 0 ); } } } else // y1 == y3 { if( y2 < y1 ) { SET_POINTS( 2, 3, 4, 2, 1, 4 ); } else if( y4 < y1 ) { SET_POINTS( 2, 3, 4, 2, 1, 4 ); } else lprintf( WIDE("Invalid Configuration!") ); } } else if( y2 < y1 ) { if( y2 < y3 ) { if( y2 < y4 ) { if( ( y4 > y1 ) && ( y4 > y3 ) ) { SET_POINTS( 2, 1, 4, 2, 3, 4 ); } else if( y4 == y1 ) { SET_POINTS( 2, 1, 0, 2, 3, 4 ); } else if( y4 == y3 ) { SET_POINTS( 2, 1, 4, 2, 3, 0 ); } else lprintf( WIDE("Invalid configuration!") ); // y2 is the least } else if( y4 <= y2 ) { lprintf( WIDE("Invalid configuration!") ); } } else if( y3 < y2 ) { if( y3 == y4 ) { SET_POINTS( 3, 2, 0, 4, 1, 0 ); } else if( ( y1 > y2 ) && ( y1 > y4 ) ) { SET_POINTS( 3, 2, 1, 3, 4, 1 ); } else if( y1 == y2 ) { SET_POINTS( 3, 2, 0, 3, 4, 1 ); } else if( y1 == y4 ) { SET_POINTS( 3, 2, 1, 3, 4, 0 ); } else lprintf( WIDE("Invalid configuration!") ); // y3 is the least } else //if( y2 == y3 ) { if( y4 > y1 ) { SET_POINTS( 2, 1, 4, 3, 4, 0 ); } else if( y4 < y1 ) { SET_POINTS( 2, 1, 0, 3, 4, 1 ); } else { SET_POINTS( 2, 1, 0, 3, 4, 0 ); } } /* else { // y4 is the least if( ( y2 > y3 ) && ( y2 > y1 ) ) { SET_POINTS( 4, 3, 2, 4, 1, 2 ); } else if( y2 == y3 ) { SET_POINTS( 4, 3, 0, 4, 1, 2 ); } else if( y2 == y1 ) { SET_POINTS( 4, 3, 2, 4, 1, 0 ); } else lprintf( "Invalid configuration!" ); } */ } else // y1 == y2 { if( y1 < y3 ) { if( y3 > y4 ) { SET_POINTS( 1, 4, 3, 2, 3, 0 ); } else if( y3 < y4 ) { SET_POINTS( 1, 4, 0, 2, 3, 4 ); } else // we're square! { SET_POINTS( 1, 4, 0, 2, 3, 0 ); } } else if( y3 < y1 ) { if( y3 == y4 ) { SET_POINTS( 3,2,0,4,1,0 ); } else // y3 is less than both y2 and y1 if( y3 < y4 ) { SET_POINTS( 3,2,1,3,4,1 ); // y3 is least } else if( y4 < y3 ) { SET_POINTS( 4,3,2,4,1,2 ); // y4 is least } } else lprintf( WIDE("Invalid configuration.. y1, y2, and y3 all equal") ); } #ifdef DEBUG_TIMING //lprintf( "-- End Setup" ); #endif { #ifdef DEBUG_TIMING int loops[20]; #endif int output = 0; struct { int idx; int curx, cury; // cury is common between left and right. struct { int x, y; int out, image; // delta output vs delta image } del; int incx, incy; int err; int err2; // accumulator for delta output vs delta image struct { int curx, cury; struct { int x, y; } del; int incx, incy; int err; } image; } right, left; struct { int curx, cury; // current pixel on stride from left.image. to right.image. struct { int x, y; } del; // current delta of left.image.current to right.image curre int err; int incx, incy; } image; struct { // delta of this are from min point to max point // and left.curx to right.curx // but int curx, cury; struct { int out, image; // except in this case it's } del; int incout; int err; } out; #ifdef DEBUG_TIMING for( output = 0; output<20;output++ ) loops[output] = 0; #endif output = 0; //out.cury = points[0].left.y; left.idx = 0; right.idx = 0; // need to cover the length of an edge in the Y length of the screen. // this is a fixed rule, since we scan always each Y of the screen and the // across on each X of the screen. the X is determined from // left.image.curx, left.image.cury to right.image.curx, right.image.cury // which is spanned in the delta from left.curx to right.curx. //-------------------------- left.curx = points[left.idx].left.x; left.cury = points[left.idx].left.y; // really this is common... but for properness I should set it. //-------------------------- right.curx = points[right.idx].right.x; right.cury = points[right.idx].right.y; // really this is common... but for properness I should set it. //-------------------------- //lprintf( "..." ); do { //if( ( left.cury - points[left.idx-1].left.y ) == 10 ) // DebugBreak(); //lprintf( "Begin line." ); lines++; if( left.idx > 0 ) { out.curx = left.curx; out.cury = left.cury; out.del.out = right.curx - left.curx; if( out.del.out < 0 ) { out.del.out = -out.del.out; out.incout = -1; } else out.incout = 1; image.curx = left.image.curx; image.cury = left.image.cury; //-------------------------- image.del.x = right.image.curx - left.image.curx; if( image.del.x < 0 ) { image.del.x = -image.del.x; image.incx = -1; } else image.incx = 1; //-------------------------- image.del.y = right.image.cury - left.image.cury; if( image.del.y < 0 ) { image.del.y = -image.del.y; image.incy = -1; } else image.incy = 1; image.err = (-image.del.x)/2; //-------------------------- // this loop iterates the image by one pixel... // but I don't really need THIS loop... so what's the next? // the iterator of curx's on the image, according to the step of // this pixel vs the whole line... //printf( "Line: %d (%d-%d)\n", out.cury, left.image.curx, right.image.curx ); //if( out.cury == 82 ) // DebugBreak(); if( image.del.x < image.del.y ) { out.del.image = image.del.y; { out.err = (-out.del.image)/2; image.err = (-image.del.y)/2; if( out.curx < dest->x ) out.curx = dest->x; if( right.curx > dest->width ) right.curx = dest->width; if( out.cury >= dest->y && out.cury < dest->height ) while( out.curx <= right.curx ) { #ifdef DEBUG_TIMING loops[0]++; #endif //if( //( out.curx >= dest->x ) && ( out.curx < (dest->x + dest->width) ) //( out.cury >= dest->y ) && ( out.cury < (dest->y + dest->height) ) // ) { int cx, cy; #ifdef OUTPUT_IMAGE if( ( (cx=image.curx>>SCALE_SHIFT) < source->width ) && ( (cy=image.cury>>SCALE_SHIFT) < source->height ) ) { CDATA c = *IMG_ADDRESS( source, cx, cy ); CDATA *po = IMG_ADDRESS(dest,out.curx,out.cury); int alpha1 = AlphaVal(c); *po = DOALPHA2( *po, c, alpha1 ) ; output++; } #endif } //plot( dest, out.curx, out.cury // , getpixel( source, image.curx >> SCALE_SHIFT, image.cury >> SCALE_SHIFT ) //, Color( image.curx*4, image.cury*4, 0 ) // ); out.err += out.del.image; out.curx++; while( out.curx <= right.curx && out.err > 0 ) { #ifdef DEBUG_TIMING loops[1]++; #endif out.err -= out.del.out; { // iterate the image one step. (ie out.image++ ) image.err += image.del.x; image.cury += image.incy; while( image.err > 0 ) { #ifdef DEBUG_TIMING loops[2]++; #endif image.err -= image.del.y; image.curx += image.incx; } } } } } } else { out.del.image = image.del.x; { out.err = (-out.del.image)/2; image.err = (-image.del.x)/2; //lprintf( "plot..." ); cols = 0; if( out.curx < dest->x ) out.curx = dest->x; if( right.curx > dest->width ) right.curx = dest->width; if( out.cury >= dest->y && out.cury < dest->height ) while( out.curx <= right.curx ) { int cx, cy; // = image.curx >> SCALE_SHIFT, cy = image.cury >> SCALE_SHIFT; #ifdef DEBUG_TIMING loops[3]++; #endif cols++; //printf( "c %d,", image.curx ); //if( //( out.curx >= dest->x ) && ( out.curx < (dest->x + dest->width) ) //&& //( out.cury >= dest->y ) && ( out.cury < (dest->y + dest->height) ) ) { #if defined( OUTPUT_IMAGE ) if( ( (cx=image.curx>>SCALE_SHIFT) < source->width ) && ( (cy=image.cury>>SCALE_SHIFT) < source->height ) ) { CDATA c; CDATA *po; int alpha1; c = *IMG_ADDRESS( source, cx, cy ); po = IMG_ADDRESS(dest,out.curx,out.cury); alpha1 = AlphaVal(c); *po = DOALPHA2( *po, c, alpha1 ) ; output++; } #endif } //plot( dest, out.curx, out.cury // , getpixel( source, image.curx >> SCALE_SHIFT, image.cury >> SCALE_SHIFT ) //, Color( image.curx*4, image.cury*4, 0 ) // ); out.err += out.del.image; out.curx++; while( out.curx <= right.curx && out.err > 0 ) { #ifdef DEBUG_TIMING loops[4]++; #endif out.err -= out.del.out; { // iterate the image one step. (ie out.image++ ) image.err += image.del.y; image.curx += image.incx; while( image.err > 0 ) { #ifdef DEBUG_TIMING loops[5]++; #endif image.err -= image.del.x; image.cury += image.incy; } } } } //lprintf( "end plot... %d", cols ); } } //printf( "\n" ); } // if ( left.idx > 0 ) //-------------- // check to see if we need to change the left or right // segments... if( left.idx ) { //--------------- // increment output X on left and right side. // always step by 1 Y therefore we always add the same del.x... // { // step the output coordinate.... left.err += left.del.x; /* incy will always be 1... perhaps effectively zero...*/ left.cury += left.incy; while( left.err > 0 ) { #ifdef DEBUG_TIMING loops[6]++; #endif if( !left.del.y ) DebugBreak(); left.err -= left.del.y; left.curx += left.incx; } } // step increment output vs image... left.err2 += left.del.image; if( left.image.del.x < left.image.del.y ) { while( left.err2 > 0 ) { #ifdef DEBUG_TIMING loops[7]++; #endif left.err2 -= left.del.out; // the larger distance to go on the line. left.image.err += left.image.del.x; // increment the longer distance by a unit increment. left.image.cury += left.image.incy; while( left.image.err > 0 ) { #ifdef DEBUG_TIMING loops[8]++; #endif left.image.err -= left.del.out; left.image.curx += left.image.incx; //printf( "," ); } } } else // left.image.del.x > left.image.del.y { while( left.err2 > 0 ) { #ifdef DEBUG_TIMING loops[9]++; #endif left.err2 -= left.del.out; // the larger distance to go on the line. left.image.err += left.image.del.y; // incement the longer distance by a unit distance. left.image.curx += left.image.incx; //DebugBreak(); //printf( "." ); while( left.image.err > 0 ) { #ifdef DEBUG_TIMING loops[10]++; #endif left.image.err -= left.image.del.x; left.image.cury += left.image.incy; } } } } // if left.cury == final y if( (left.cury == points[left.idx].left.y) ) { //DebugBreak(); if( points[left.idx+1].flags.no_left || ( left.idx == 2 ) ) { // done! break; } else { left.curx = points[left.idx].left.x; left.cury = points[left.idx].left.y; // really this is common... but for properness I should set it. left.image.curx = verts[points[left.idx].left.vertex_number].x; left.image.cury = verts[points[left.idx].left.vertex_number].y; left.del.x = points[left.idx+1].left.x - left.curx; if( left.del.x < 0 ) { left.del.x = -left.del.x; left.incx = -1; } else left.incx = 1; left.del.y = points[left.idx+1].left.y - left.cury; if( left.del.y < 0 ) { left.del.y = -left.del.y; left.incy = -1; } else left.incy = 1; left.del.out = left.del.y; left.image.del.x = verts[points[left.idx+1].left.vertex_number].x - left.image.curx; if( left.image.del.x < 0 ) { left.image.del.x = -left.image.del.x; left.image.incx = -1; } else if( left.image.del.x > 0 ) left.image.incx = 1; else left.image.incx = 0; left.image.del.y = verts[points[left.idx+1].left.vertex_number].y - left.image.cury; if( left.image.del.y < 0 ) { left.image.del.y = -left.image.del.y; left.image.incy = -1; } else if( left.image.del.y > 0 ) left.image.incy = 1; else left.image.incy = 0; left.err = (-left.del.x)/2; // always incremented by del.y ( +1 y ) therefore comparison starts at /2 x; if( left.image.del.x > left.image.del.y ) { left.del.image = left.image.del.x; left.err2 = ( -left.image.del.x ) / 2; left.image.err = (-left.image.del.y)/2; } else { left.del.image = left.image.del.y; left.err2 = ( -left.image.del.y ) / 2; left.image.err = (-left.image.del.x)/2; } left.idx++; } } if( right.idx ) // not at a point boundry ( cury != nexty ) { // step the output coordinate.... right.err += right.del.x; /* incy will always be 1... perhaps effectively zero...*/ right.cury += right.incy; while( right.err > 0 ) { #ifdef DEBUG_TIMING loops[11]++; #endif right.err -= right.del.y; right.curx += right.incx; } right.err2 += right.del.image; if( right.image.del.x < right.image.del.y ) { while( right.err2 > 0 ) { #ifdef DEBUG_TIMING loops[12]++; #endif right.err2 -= right.del.out; // the larger distance to go on the line. right.image.err += right.image.del.x; // increment the longer distance by a unit increment. right.image.cury += right.image.incy; while( right.image.err > 0 ) { #ifdef DEBUG_TIMING loops[13]++; #endif right.image.err -= right.image.del.y; right.image.curx += right.image.incx; } } } else // right.image.del.x < right.image.del.y { while( right.err2 > 0 ) { #ifdef DEBUG_TIMING loops[14]++; #endif right.err2 -= right.del.out; // the larger distance to go on the line. right.image.err += right.image.del.y; // increment the longer distance by a unit increment. right.image.curx += right.image.incx; while( right.image.err > 0 ) { #ifdef DEBUG_TIMING loops[15]++; #endif right.image.err -= right.image.del.x; right.image.cury += right.image.incy; } } } } // if right.cury == destination point. if( (right.cury == points[right.idx].right.y) ) { //DebugBreak(); if( points[right.idx+1].flags.no_right || ( right.idx == 2 ) ) { // done! break; } else { right.curx = points[right.idx].right.x; right.cury = points[right.idx].right.y; right.image.curx = verts[points[right.idx].right.vertex_number].x; right.image.cury = verts[points[right.idx].right.vertex_number].y; right.del.x = points[right.idx+1].right.x - right.curx; if( right.del.x < 0 ) { right.del.x = -right.del.x; right.incx = -1; } else right.incx = 1; right.del.y = points[right.idx+1].right.y - points[right.idx].right.y; if( right.del.y < 0 ) { right.del.y = -right.del.y; right.incy = -1; } else right.incy = 1; right.del.out = right.del.y; right.image.del.x = verts[points[right.idx+1].right.vertex_number].x - right.image.curx; if( right.image.del.x < 0 ) { right.image.del.x = -right.image.del.x; right.image.incx = -1; } else if( right.image.del.x > 0 ) right.image.incx = 1; else right.image.incx = 0; right.image.del.y = verts[points[right.idx+1].right.vertex_number].y - right.image.cury; if( right.image.del.y < 0 ) { right.image.del.y = -right.image.del.y; right.image.incy = -1; } else if( right.image.del.y > 0 ) right.image.incy = 1; else right.image.incy = 0; right.err = (-right.del.x)/2; // always incremented by del.y ( +1 y ) therefore comparison starts at /2 x; if( right.image.del.x > right.image.del.y ) { right.del.image = right.image.del.x; right.err2 = ( -right.image.del.x ) / 2; right.image.err = (-right.image.del.y)/2; } else { right.del.image = right.image.del.y; right.err2 = ( -right.image.del.y ) / 2; right.image.err = (-right.image.del.x)/2; } right.idx++; } } //lprintf( "end line." ); }
void BlotScaledImageSizedEx ( ImageFile *pifDest, ImageFile *pifSrc , int32_t xd, int32_t yd , uint32_t wd, uint32_t hd , int32_t xs, int32_t ys , uint32_t ws, uint32_t hs , uint32_t nTransparent , uint32_t method, ... ) // integer scalar... 0x10000 = 1 { CDATA *po, *pi; static uint32_t lock; uint32_t oo; uint32_t srcwidth; int errx, erry; uint32_t dhd, dwd, dhs, dws; va_list colors; va_start( colors, method ); //lprintf( WIDE("Blot enter (%d,%d)"), _wd, _hd ); if( nTransparent > ALPHA_TRANSPARENT_MAX ) { return; } if( !pifSrc || !pifDest || !pifSrc->image //|| !pifDest->image || !wd || !hd || !ws || !hs ) { return; } if( ( xd > ( pifDest->x + pifDest->width ) ) || ( yd > ( pifDest->y + pifDest->height ) ) || ( ( xd + (signed)wd ) < pifDest->x ) || ( ( yd + (signed)hd ) < pifDest->y ) ) { return; } dhd = hd; dhs = hs; dwd = wd; dws = ws; // ok - how to figure out how to do this // need to update the position and width to be within the // the bounds of pifDest.... //lprintf(" begin scaled output..." ); errx = -(signed)dwd; erry = -(signed)dhd; if( xd < pifDest->x ) { while( xd < pifDest->x ) { errx += (signed)dws; while( errx >= 0 ) { errx -= (signed)dwd; ws--; xs++; } wd--; xd++; } } //Log8( WIDE("Blot scaled params: %d %d %d %d / %d %d %d %d "), // xs, ys, ws, hs, xd, yd, wd, hd ); if( yd < pifDest->y ) { while( yd < pifDest->y ) { erry += (signed)dhs; while( erry >= 0 ) { erry -= (signed)dhd; hs--; ys++; } hd--; yd++; } } //Log8( WIDE("Blot scaled params: %d %d %d %d / %d %d %d %d "), // xs, ys, ws, hs, xd, yd, wd, hd ); if( ( xd + (signed)wd ) > ( pifDest->x + pifDest->width) ) { //int newwd = TOFIXED(pifDest->width); //ws -= ((int64_t)( (int)wd - newwd)* (int64_t)ws )/(int)wd; wd = ( pifDest->x + pifDest->width ) - xd; } //Log8( WIDE("Blot scaled params: %d %d %d %d / %d %d %d %d "), // xs, ys, ws, hs, xd, yd, wd, hd ); if( ( yd + (signed)hd ) > (pifDest->y + pifDest->height) ) { //int newhd = TOFIXED(pifDest->height); //hs -= ((int64_t)( hd - newhd)* hs )/hd; hd = (pifDest->y + pifDest->height) - yd; } if( (int32_t)wd <= 0 || (int32_t)hd <= 0 || (int32_t)ws <= 0 || (int32_t)hs <= 0 ) { return; } //Log9( WIDE("Image locations: %d(%d %d) %d(%d) %d(%d) %d(%d)") // , xs, FROMFIXED(xs), FIXEDPART(xs) // , ys, FROMFIXED(ys) // , xd, FROMFIXED(xd) // , yd, FROMFIXED(yd) ); #ifdef _INVERT_IMAGE // set pointer in to the starting x pixel // on the last line of the image to be copied pi = IMG_ADDRESS( pifSrc, (xs), (ys) ); po = IMG_ADDRESS( pifDest, (xd), (yd) ); oo = 4*(-((signed)wd) - (pifDest->pwidth) ); // w is how much we can copy... // adding in multiple of 4 because it's C... srcwidth = -(4* pifSrc->pwidth); #else // set pointer in to the starting x pixel // on the first line of the image to be copied... pi = IMG_ADDRESS( pifSrc, (xs), (ys) ); po = IMG_ADDRESS( pifDest, (xd), (yd) ); oo = 4*(pifDest->pwidth - (wd)); // w is how much we can copy... // adding in multiple of 4 because it's C... srcwidth = 4* pifSrc->pwidth; #endif while( LockedExchange( &lock, 1 ) ) Relinquish(); //Log8( WIDE("Do blot work...%d(%d),%d(%d) %d(%d) %d(%d)") // , ws, FROMFIXED(ws), hs, FROMFIXED(hs) // , wd, FROMFIXED(wd), hd, FROMFIXED(hd) ); if( ( pifDest->flags & IF_FLAG_FINAL_RENDER ) && !( pifDest->flags & IF_FLAG_IN_MEMORY ) ) { int updated = 0; Image topmost_parent; // closed loop to get the top imgae size. for( topmost_parent = pifSrc; topmost_parent->pParent; topmost_parent = topmost_parent->pParent ); ReloadOpenGlTexture( pifSrc, 0 ); if( !pifSrc->glActiveSurface ) { lprintf( WIDE( "gl texture hasn't downloaded or went away?" ) ); lock = 0; return; } //lprintf( WIDE( "use regular texture %p (%d,%d)" ), pifSrc, pifSrc->width, pifSrc->height ); { int glDepth = 1; VECTOR v1[2], v3[2], v4[2], v2[2]; int v = 0; double x_size, x_size2, y_size, y_size2; /* * only a portion of the image is actually used, the rest is filled with blank space * */ TranslateCoord( pifDest, &xd, &yd ); TranslateCoord( pifSrc, &xs, &ys ); v1[v][0] = xd; v1[v][1] = yd; v1[v][2] = 0.0; v2[v][0] = xd; v2[v][1] = yd+hd; v2[v][2] = 0.0; v3[v][0] = xd+wd; v3[v][1] = yd+hd; v3[v][2] = 0.0; v4[v][0] = xd+wd; v4[v][1] = yd; v4[v][2] = 0.0; x_size = (double) xs/ (double)topmost_parent->width; x_size2 = (double) (xs+ws)/ (double)topmost_parent->width; y_size = (double) ys/ (double)topmost_parent->height; y_size2 = (double) (ys+hs)/ (double)topmost_parent->height; while( pifDest && pifDest->pParent ) { glDepth = 0; if( pifDest->transform ) { Apply( pifDest->transform, v1[1-v], v1[v] ); Apply( pifDest->transform, v2[1-v], v2[v] ); Apply( pifDest->transform, v3[1-v], v3[v] ); Apply( pifDest->transform, v4[1-v], v4[v] ); v = 1-v; } pifDest = pifDest->pParent; } if( pifDest->transform ) { Apply( pifDest->transform, v1[1-v], v1[v] ); Apply( pifDest->transform, v2[1-v], v2[v] ); Apply( pifDest->transform, v3[1-v], v3[v] ); Apply( pifDest->transform, v4[1-v], v4[v] ); v = 1-v; } #if 0 if( glDepth ) { //lprintf( WIDE( "enqable depth..." ) ); glEnable( GL_DEPTH_TEST ); } else { //lprintf( WIDE( "disable depth..." ) ); glDisable( GL_DEPTH_TEST ); } #endif glBindTexture(GL_TEXTURE_2D, pifSrc->glActiveSurface); // Select Our Texture if( method == BLOT_COPY ) glColor4ub( 255,255,255,255 ); else if( method == BLOT_SHADED ) { CDATA tmp = va_arg( colors, CDATA ); glColor4ubv( (GLubyte*)&tmp ); } else if( method == BLOT_MULTISHADE ) { #if !defined( __ANDROID__ ) InitShader(); if( glUseProgram && l.glActiveSurface->shader.multi_shader ) { int err; CDATA r = va_arg( colors, CDATA ); CDATA g = va_arg( colors, CDATA ); CDATA b = va_arg( colors, CDATA ); glEnable(GL_FRAGMENT_PROGRAM_ARB); glUseProgram( l.glActiveSurface->shader.multi_shader ); err = glGetError(); glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 0, (float)GetRedValue( r )/255.0f, (float)GetGreenValue( r )/255.0f, (float)GetBlueValue( r )/255.0f, (float)GetAlphaValue( r )/255.0f ); err = glGetError(); glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 1, (float)GetRedValue( g )/255.0f, (float)GetGreenValue( g )/255.0f, (float)GetBlueValue( g )/255.0f, (float)GetAlphaValue( g )/255.0f ); err = glGetError(); glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 2, (float)GetRedValue( b )/255.0f, (float)GetGreenValue( b )/255.0f, (float)GetBlueValue( b )/255.0f, (float)GetAlphaValue( b )/255.0f ); err = glGetError(); } else #endif { Image output_image; CDATA r = va_arg( colors, CDATA ); CDATA g = va_arg( colors, CDATA ); CDATA b = va_arg( colors, CDATA ); output_image = GetShadedImage( pifSrc, r, g, b ); glBindTexture( GL_TEXTURE_2D, output_image->glActiveSurface ); glColor4ub( 255,255,255,255 ); } } else if( method == BLOT_INVERTED ) { #if !defined( __ANDROID__ ) InitShader(); if( l.glActiveSurface->shader.inverse_shader ) { int err; //lprintf( WIDE( "HAVE SHADER %d" ), l.glActiveSurface->shader.inverse_shader ); glEnable(GL_FRAGMENT_PROGRAM_ARB); glUseProgram( l.glActiveSurface->shader.inverse_shader ); err = glGetError(); } else #endif { Image output_image; //lprintf( WIDE( "DID NOT HAVE SHADER" ) ); output_image = GetInvertedImage( pifSrc ); glBindTexture( GL_TEXTURE_2D, output_image->glActiveSurface ); glColor4ub( 255,255,255,255 ); } } glBegin(GL_TRIANGLE_STRIP); //glBegin(GL_QUADS); // Front Face //glColor4ub( 255,120,32,192 ); scale( v1[v], v1[v], l.scale ); scale( v2[v], v2[v], l.scale ); scale( v3[v], v3[v], l.scale ); scale( v4[v], v4[v], l.scale ); glTexCoord2f(x_size, y_size); glVertex3fv(v1[v]); // Bottom Left Of The Texture and Quad glTexCoord2f(x_size, y_size2); glVertex3fv(v2[v]); // Bottom Right Of The Texture and Quad glTexCoord2f(x_size2, y_size); glVertex3fv(v4[v]); // Top Left Of The Texture and Quad glTexCoord2f(x_size2, y_size2); glVertex3fv(v3[v]); // Top Right Of The Texture and Quad // Back Face glEnd(); #if !defined( __ANDROID__ ) if( method == BLOT_MULTISHADE ) { if( l.glActiveSurface->shader.multi_shader ) { glDisable(GL_FRAGMENT_PROGRAM_ARB); } } else if( method == BLOT_INVERTED ) { if( l.glActiveSurface->shader.inverse_shader ) { glDisable(GL_FRAGMENT_PROGRAM_ARB); } } #endif glBindTexture(GL_TEXTURE_2D, 0); // Select Our Texture } } else switch( method ) { case BLOT_COPY: if( !nTransparent ) cBlotScaledT0( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth ); else if( nTransparent == 1 ) cBlotScaledT1( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth ); else if( nTransparent & ALPHA_TRANSPARENT ) cBlotScaledTImgA( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth, nTransparent&0xFF ); else if( nTransparent & ALPHA_TRANSPARENT_INVERT ) cBlotScaledTImgAI( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth, nTransparent&0xFF ); else cBlotScaledTA( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth, nTransparent ); break; case BLOT_SHADED: if( !nTransparent ) cBlotScaledShadedT0( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth, va_arg( colors, CDATA ) ); else if( nTransparent == 1 ) cBlotScaledShadedT1( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth, va_arg( colors, CDATA ) ); else if( nTransparent & ALPHA_TRANSPARENT ) cBlotScaledShadedTImgA( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth, nTransparent&0xFF, va_arg( colors, CDATA ) ); else if( nTransparent & ALPHA_TRANSPARENT_INVERT ) cBlotScaledShadedTImgAI( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth, nTransparent&0xFF, va_arg( colors, CDATA ) ); else cBlotScaledShadedTA( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth, nTransparent, va_arg( colors, CDATA ) ); break; case BLOT_MULTISHADE: { CDATA r,g,b; r = va_arg( colors, CDATA ); g = va_arg( colors, CDATA ); b = va_arg( colors, CDATA ); if( !nTransparent ) cBlotScaledMultiT0( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth , r, g, b ); else if( nTransparent == 1 ) cBlotScaledMultiT1( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth , r, g, b ); else if( nTransparent & ALPHA_TRANSPARENT ) cBlotScaledMultiTImgA( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth , nTransparent & 0xFF , r, g, b ); else if( nTransparent & ALPHA_TRANSPARENT_INVERT ) cBlotScaledMultiTImgAI( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth , nTransparent & 0xFF , r, g, b ); else cBlotScaledMultiTA( po, pi, errx, erry, wd, hd, dwd, dhd, dws, dhs, oo, srcwidth , nTransparent , r, g, b ); } break; } lock = 0; // Log( WIDE("Blot done") ); }
//--------------------------------------------------------------------------- // x, y is position // xs, ys is starting position on source bitmap (x, y is upper left) + xs, ys ) // w, h is height and width of the image to use. // default behavior is to omit copying 0 pixels for transparency // overlays.... void BlotImageSizedEx ( ImageFile *pifDest, ImageFile *pifSrc , int32_t xd, int32_t yd , int32_t xs, int32_t ys , uint32_t ws, uint32_t hs , uint32_t nTransparent , uint32_t method , ... ) { #define BROKEN_CODE PCDATA po, pi; //int hd, wd; uint32_t oo, oi; // treated as an adder... it is unsigned by math, but still results correct offset? static uint32_t lock; va_list colors; va_start( colors, method ); if( nTransparent > ALPHA_TRANSPARENT_MAX ) return; if( !pifSrc || !pifSrc->image || !pifDest //|| !pifDest->image ) { // this will happen when mixing modes... lprintf( WIDE( "sanity check failed %p %p %p" ), pifSrc, pifDest, pifSrc?pifSrc->image:NULL ); return; } //lprintf( WIDE( "BlotImageSized %d,%d to %d,%d by %d,%d" ), xs, ys, xd, yd, ws, hs ); { IMAGE_RECTANGLE r1; IMAGE_RECTANGLE r2; IMAGE_RECTANGLE rs; IMAGE_RECTANGLE rd; int tmp; //IMAGE_RECTANGLE r3; r1.x = xd; r1.y = yd; r1.width = ws; r1.height = hs; r2.x = pifDest->eff_x; r2.y = pifDest->eff_y; tmp = (pifDest->eff_maxx - pifDest->eff_x) + 1; if( tmp < 0 ) r2.width = 0; else r2.width = (IMAGE_SIZE_COORDINATE)tmp; tmp = (pifDest->eff_maxy - pifDest->eff_y) + 1; if( tmp < 0 ) r2.height = 0; else r2.height = (IMAGE_SIZE_COORDINATE)tmp; if( !IntersectRectangle( &rd, &r1, &r2 ) ) { //lprintf( WIDE( "Images do not overlap. %d,%d %d,%d vs %d,%d %d,%d" ), r1.x,r1.y,r1.width,r1.height // , r2.x,r2.y,r2.width,r2.height); return; } //lprintf( WIDE( "Correcting coordinates by %d,%d" ) // , rd.x - xd // , rd.y - yd // ); xs += rd.x - xd; ys += rd.y - yd; tmp = rd.x - xd; if( tmp > 0 && (unsigned)tmp > ws ) ws = 0; else { if( tmp < 0 ) ws += (unsigned)-tmp; else ws -= (unsigned)tmp; } tmp = rd.y - yd; if( tmp > 0 && (unsigned)tmp > hs ) hs = 0; else { if( tmp < 0 ) hs += (unsigned)-tmp; else hs -= (unsigned)tmp; } //lprintf( WIDE( "Resulting dest is %d,%d %d,%d" ), rd.x,rd.y,rd.width,rd.height ); xd = rd.x; yd = rd.y; r1.x = xs; r1.y = ys; r1.width = ws; r1.height = hs; r2.x = pifSrc->eff_x; r2.y = pifSrc->eff_y; tmp = (pifSrc->eff_maxx - pifSrc->eff_x) + 1; if( tmp < 0 ) r2.width = 0; else r2.width = (IMAGE_SIZE_COORDINATE)tmp; tmp = (pifSrc->eff_maxy - pifSrc->eff_y) + 1; if( tmp < 0 ) r2.height = 0; else r2.height = (IMAGE_SIZE_COORDINATE)tmp; if( !IntersectRectangle( &rs, &r1, &r2 ) ) { lprintf( WIDE( "Desired Output does not overlap..." ) ); return; } //lprintf( WIDE( "Resulting dest is %d,%d %d,%d" ), rs.x,rs.y,rs.width,rs.height ); ws = rs.width<rd.width?rs.width:rd.width; hs = rs.height<rd.height?rs.height:rd.height; xs = rs.x; ys = rs.y; //lprintf( WIDE( "Resulting rect is %d,%d to %d,%d dim: %d,%d" ), rs.x, rs.y, rd.x, rd.y, rs.width, rs.height ); //lprintf( WIDE( "Resulting rect is %d,%d to %d,%d dim: %d,%d" ), xs, ys, xd, yd, ws, hs ); } //lprintf( WIDE(WIDE( "Doing image (%d,%d)-(%d,%d) (%d,%d)-(%d,%d)" )), xs, ys, ws, hs, xd, yd, wd, hd ); if( (int32_t)ws <= 0 || (int32_t)hs <= 0 /*|| (int32_t)wd <= 0 || (int32_t)hd <= 0 */ ) { lprintf( WIDE( "out of bounds" ) ); return; } #ifdef _INVERT_IMAGE // set pointer in to the starting x pixel // on the last line of the image to be copied //pi = IMG_ADDRESS( pifSrc, xs, ys ); //po = IMG_ADDRESS( pifDest, xd, yd ); pi = IMG_ADDRESS( pifSrc, xs, ys ); po = IMG_ADDRESS( pifDest, xd, yd ); //cpg 19 Jan 2007 2>c:\work\sack\src\imglib\blotdirect.c(492) : warning C4146: unary minus operator applied to unsigned type, result still unsigned //cpg 19 Jan 2007 2>c:\work\sack\src\imglib\blotdirect.c(493) : warning C4146: unary minus operator applied to unsigned type, result still unsigned oo = 4*-(int)(ws+pifDest->pwidth); // w is how much we can copy... oi = 4*-(int)(ws+pifSrc->pwidth); // adding remaining width... #else // set pointer in to the starting x pixel // on the first line of the image to be copied... pi = IMG_ADDRESS( pifSrc, xs, ys ); po = IMG_ADDRESS( pifDest, xd, yd ); oo = 4*(pifDest->pwidth - ws); // w is how much we can copy... oi = 4*(pifSrc->pwidth - ws); // adding remaining width... #endif //lprintf( WIDE("Doing image (%d,%d)-(%d,%d) (%d,%d)-(%d,%d)"), xs, ys, ws, hs, xd, yd, wd, hd ); //oo = 4*(pifDest->pwidth - ws); // w is how much we can copy... //oi = 4*(pifSrc->pwidth - ws); // adding remaining width... while( LockedExchange( &lock, 1 ) ) Relinquish(); if( ( pifDest->flags & IF_FLAG_FINAL_RENDER ) && !( pifDest->flags & IF_FLAG_IN_MEMORY ) ) { Image topmost_parent; ReloadOpenGlTexture( pifSrc, 0 ); if( !pifSrc->glActiveSurface ) { //lprintf( WIDE( "gl texture hasn't updated or went away?" ) ); lock = 0; return; } //lprintf( WIDE( "use regular texture %p (%d,%d)" ), pifSrc, pifSrc->width, pifSrc->height ); //DebugBreak(); g // closed loop to get the top imgae size. for( topmost_parent = pifSrc; topmost_parent->pParent; topmost_parent = topmost_parent->pParent ); /* * only a portion of the image is actually used, the rest is filled with blank space * */ TranslateCoord( pifDest, &xd, &yd ); TranslateCoord( pifSrc, &xs, &ys ); { int glDepth = 1; double x_size, x_size2, y_size, y_size2; VECTOR v1[2], v3[2],v4[2],v2[2]; int v = 0; v1[v][0] = xd; v1[v][1] = yd; v1[v][2] = 0.0; v2[v][0] = xd; v2[v][1] = yd+hs; v2[v][2] = 0.0; v3[v][0] = xd+ws; v3[v][1] = yd+hs; v3[v][2] = 0.0; v4[v][0] = xd+ws; v4[v][1] = yd; v4[v][2] = 0.0; x_size = (double) xs/ (double)topmost_parent->width; x_size2 = (double) (xs+ws)/ (double)topmost_parent->width; y_size = (double) ys/ (double)topmost_parent->height; y_size2 = (double) (ys+hs)/ (double)topmost_parent->height; // Front Face //glColor4ub( 255,120,32,192 ); //lprintf( WIDE( "Texture size is %g,%g to %g,%g" ), x_size, y_size, x_size2, y_size2 ); while( pifDest && pifDest->pParent ) { glDepth = 0; if( pifDest->transform ) { Apply( pifDest->transform, v1[1-v], v1[v] ); Apply( pifDest->transform, v2[1-v], v2[v] ); Apply( pifDest->transform, v3[1-v], v3[v] ); Apply( pifDest->transform, v4[1-v], v4[v] ); v = 1-v; } pifDest = pifDest->pParent; } if( pifDest->transform ) { Apply( pifDest->transform, v1[1-v], v1[v] ); Apply( pifDest->transform, v2[1-v], v2[v] ); Apply( pifDest->transform, v3[1-v], v3[v] ); Apply( pifDest->transform, v4[1-v], v4[v] ); v = 1-v; } #if 0 if( glDepth ) { //lprintf( WIDE( "enqable depth..." ) ); glEnable( GL_DEPTH_TEST ); } else { //lprintf( WIDE( "disable depth..." ) ); glDisable( GL_DEPTH_TEST ); } #endif glBindTexture(GL_TEXTURE_2D, pifSrc->glActiveSurface); // Select Our Texture if( method == BLOT_COPY ) glColor4ub( 255,255,255,255 ); else if( method == BLOT_SHADED ) { CDATA tmp = va_arg( colors, CDATA ); glColor4ubv( (GLubyte*)&tmp ); } else if( method == BLOT_MULTISHADE ) { #if !defined( __ANDROID__ ) InitShader(); if( glUseProgram && l.glActiveSurface->shader.multi_shader ) { int err; CDATA r = va_arg( colors, CDATA ); CDATA g = va_arg( colors, CDATA ); CDATA b = va_arg( colors, CDATA ); glEnable(GL_FRAGMENT_PROGRAM_ARB); glUseProgram( l.glActiveSurface->shader.multi_shader ); err = glGetError(); glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 0, (float)GetRedValue( r )/255.0f, (float)GetGreenValue( r )/255.0f, (float)GetBlueValue( r )/255.0f, (float)GetAlphaValue( r )/255.0f ); err = glGetError(); glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 1, (float)GetRedValue( g )/255.0f, (float)GetGreenValue( g )/255.0f, (float)GetBlueValue( g )/255.0f, (float)GetAlphaValue( g )/255.0f ); err = glGetError(); glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 2, (float)GetRedValue( b )/255.0f, (float)GetGreenValue( b )/255.0f, (float)GetBlueValue( b )/255.0f, (float)GetAlphaValue( b )/255.0f ); err = glGetError(); } else #endif { Image output_image; CDATA r = va_arg( colors, CDATA ); CDATA g = va_arg( colors, CDATA ); CDATA b = va_arg( colors, CDATA ); output_image = GetShadedImage( pifSrc, r, g, b ); glBindTexture( GL_TEXTURE_2D, output_image->glActiveSurface ); glColor4ub( 255,255,255,255 ); } } else if( method == BLOT_INVERTED ) { #if !defined( __ANDROID__ ) InitShader(); if( l.glActiveSurface->shader.inverse_shader ) { int err; glEnable(GL_FRAGMENT_PROGRAM_ARB); glUseProgram( l.glActiveSurface->shader.inverse_shader ); err = glGetError(); } else #endif { Image output_image; output_image = GetInvertedImage( pifSrc ); glBindTexture( GL_TEXTURE_2D, output_image->glActiveSurface ); glColor4ub( 255,255,255,255 ); } } glBegin(GL_TRIANGLE_STRIP); //glBegin(GL_QUADS); scale( v1[v], v1[v], l.scale ); scale( v2[v], v2[v], l.scale ); scale( v3[v], v3[v], l.scale ); scale( v4[v], v4[v], l.scale ); glTexCoord2f(x_size, y_size); glVertex3fv(v1[v]); // Bottom Left Of The Texture and Quad glTexCoord2f(x_size, y_size2); glVertex3fv(v2[v]); // Top Left Of The Texture and Quad glTexCoord2f(x_size2, y_size); glVertex3fv(v4[v]); // Bottom Right Of The Texture and Quad glTexCoord2f(x_size2, y_size2); glVertex3fv(v3[v]); // Top Right Of The Texture and Quad // Back Face glEnd(); #if !defined( __ANDROID__ ) if( method == BLOT_MULTISHADE ) { if( l.glActiveSurface->shader.multi_shader ) { glDisable(GL_FRAGMENT_PROGRAM_ARB); } } else if( method == BLOT_INVERTED ) { if( l.glActiveSurface->shader.inverse_shader ) { glDisable(GL_FRAGMENT_PROGRAM_ARB); } } #endif glBindTexture(GL_TEXTURE_2D, 0); // Select Our Texture } } else { switch( method ) { case BLOT_COPY: if( !nTransparent ) CopyPixelsT0( po, pi, oo, oi, ws, hs ); else if( nTransparent == 1 ) CopyPixelsT1( po, pi, oo, oi, ws, hs ); else if( nTransparent & ALPHA_TRANSPARENT ) CopyPixelsTImgA( po, pi, oo, oi, ws, hs, nTransparent & 0xFF); else if( nTransparent & ALPHA_TRANSPARENT_INVERT ) CopyPixelsTImgAI( po, pi, oo, oi, ws, hs, nTransparent & 0xFF ); else CopyPixelsTA( po, pi, oo, oi, ws, hs, nTransparent ); break; case BLOT_SHADED: if( !nTransparent ) CopyPixelsShadedT0( po, pi, oo, oi, ws, hs , va_arg( colors, CDATA ) ); else if( nTransparent == 1 ) CopyPixelsShadedT1( po, pi, oo, oi, ws, hs , va_arg( colors, CDATA ) ); else if( nTransparent & ALPHA_TRANSPARENT ) CopyPixelsShadedTImgA( po, pi, oo, oi, ws, hs, nTransparent & 0xFF , va_arg( colors, CDATA ) ); else if( nTransparent & ALPHA_TRANSPARENT_INVERT ) CopyPixelsShadedTImgAI( po, pi, oo, oi, ws, hs, nTransparent & 0xFF , va_arg( colors, CDATA ) ); else CopyPixelsShadedTA( po, pi, oo, oi, ws, hs, nTransparent , va_arg( colors, CDATA ) ); break; case BLOT_MULTISHADE: { CDATA r,g,b; r = va_arg( colors, CDATA ); g = va_arg( colors, CDATA ); b = va_arg( colors, CDATA ); //lprintf( WIDE( "r g b %08x %08x %08x" ), r,g, b ); if( !nTransparent ) CopyPixelsMultiT0( po, pi, oo, oi, ws, hs , r, g, b ); else if( nTransparent == 1 ) CopyPixelsMultiT1( po, pi, oo, oi, ws, hs , r, g, b ); else if( nTransparent & ALPHA_TRANSPARENT ) CopyPixelsMultiTImgA( po, pi, oo, oi, ws, hs, nTransparent & 0xFF , r, g, b ); else if( nTransparent & ALPHA_TRANSPARENT_INVERT ) CopyPixelsMultiTImgAI( po, pi, oo, oi, ws, hs, nTransparent & 0xFF , r, g, b ); else CopyPixelsMultiTA( po, pi, oo, oi, ws, hs, nTransparent , r, g, b ); } break; } MarkImageUpdated( pifDest ); } lock = 0; //lprintf( WIDE( "Image done.." ) ); }