コード例 #1
0
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." );
		}
コード例 #2
0
 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") );
}
コード例 #3
0
//---------------------------------------------------------------------------
// 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.." ) );
}