/*static*/ void Surface::MaskBlendBlit( const Surface& Src, Surface& Dest, int dx, int dy, int w, int h, int sx, int sy, uint ColorKey ) { if( !ClipRectangles( Src, Dest, dx, dy, w, h, sx, sy ) ) { return; } int Length = w * BYTES; int SrcIncrement = ( Src.GetWidth() * BYTES ) + Src.GetPadding() + Length; int DestIncrement = ( Dest.GetWidth() * BYTES ) + Dest.GetPadding() + Length; byte* DestPixels = Dest.GetPointerAt( dx, dy ); const byte* SrcPixels = Src.GetPointerAt( sx, sy ); // Would it be faster to iterate forward (Pixels += ...)? for cache reasons...? for( int j = 0; j < h; ++j ) { for( int i = 0; i < w; ++i ) { // Conditional: bad, but coming up with a *faster* mathy way is hard if( ( *(unsigned int*)SrcPixels & 0x00ffffff ) != ColorKey ) { *DestPixels++ = ( *DestPixels + *SrcPixels++ ) >> 1; *DestPixels++ = ( *DestPixels + *SrcPixels++ ) >> 1; *DestPixels++ = ( *DestPixels + *SrcPixels++ ) >> 1; } else { DestPixels += BYTES; SrcPixels += BYTES; } }
// This assumes that both Surfaces are the same format and bit depth /*static*/ void Surface::ScaledBlit( const Surface& Src, Surface& Dest, int Scalar ) { PROFILE_FUNCTION; ASSERT( Src.GetWidth() * Scalar == Dest.GetWidth() ); ASSERT( Src.GetHeight() * Scalar == Dest.GetHeight() ); const byte* SrcPixels = Src.GetPointerAt( 0, 0 ); int SrcIncrement = Src.GetStride() * 2 - Src.GetPadding(); // Roll forward (padding) to end of line then roll back two lines (stride*2) int DestIncrement = Dest.GetStride() + Scalar * BYTES; // Roll back scalar width plus one line for( int SrcY = 0; SrcY < Src.GetHeight(); ++SrcY ) { for( int SrcX = 0; SrcX < Src.GetWidth(); ++SrcX ) { byte B = *SrcPixels++; byte G = *SrcPixels++; byte R = *SrcPixels++; byte* DestPixels = Dest.GetPointerAt( SrcX * Scalar, SrcY * Scalar ); for( int j = 0; j < Scalar; ++j ) { for( int i = 0; i < Scalar; ++i ) { *DestPixels++ = B; *DestPixels++ = G; *DestPixels++ = R; } DestPixels -= DestIncrement; } } SrcPixels -= SrcIncrement; } }
/*static*/ void Surface::MaskBlit( const Surface& Src, Surface& Dest, int dx, int dy, int w, int h, int sx, int sy, uint ColorKey ) { if( !ClipRectangles( Src, Dest, dx, dy, w, h, sx, sy ) ) { return; } int Length = w * BYTES; int SrcIncrement = ( Src.GetWidth() * BYTES ) + Src.GetPadding() + Length; int DestIncrement = ( Dest.GetWidth() * BYTES ) + Dest.GetPadding() + Length; byte* DestPixels = Dest.GetPointerAt( dx, dy ); const byte* SrcPixels = Src.GetPointerAt( sx, sy ); // Would it be faster to iterate forward (Pixels += ...)? for cache reasons...? for( int j = 0; j < h; ++j ) { for( int i = 0; i < w; ++i ) { // Fixed this when last three bytes can't be converted to a uint because end of block. // The other methods need to use this version when/if I ever actually dust this class off. byte B = *SrcPixels++; byte G = *SrcPixels++; byte R = *SrcPixels++; if( RGB_TO_COLOR( R, G, B ) == ColorKey ) { DestPixels += BYTES; } else { *DestPixels++ = B; *DestPixels++ = G; *DestPixels++ = R; } } DestPixels -= DestIncrement; SrcPixels -= SrcIncrement; } }
/*static*/ void Surface::StandardBlit( const Surface& Src, Surface& Dest, int dx, int dy, int w, int h, int sx, int sy ) { if( !ClipRectangles( Src, Dest, dx, dy, w, h, sx, sy ) ) { return; } int Length = w * BYTES; int SrcIncrement = ( Src.GetWidth() * BYTES ) + Src.GetPadding(); int DestIncrement = ( Dest.GetWidth() * BYTES ) + Dest.GetPadding(); byte* DestPixels = Dest.GetPointerAt( dx, dy ); const byte* SrcPixels = Src.GetPointerAt( sx, sy ); // Would it be faster to iterate forward (Pixels += ...)? for cache reasons...? for( int j = 0; j < h; ++j ) { memcpy( DestPixels, SrcPixels, Length ); DestPixels -= DestIncrement; SrcPixels -= SrcIncrement; } }