surface.cpp

Go to the documentation of this file.
00001 
00002 /*
00003     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00004     Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; see the file COPYING. If not, write to the
00018     Free Software Foundation, Inc., 59 Temple Place, Suite 330,
00019     Boston, MA  02111-1307  USA
00020 */
00021 
00022 #include <SDL_image.h>
00023 #include <cmath>
00024 #include "../sdl/sdlstretch.h"
00025 #include "surface.h"
00026 #include "blitter.h"
00027 #include "../basegfx.h"
00028 #include "../basestrm.h"
00029 #include "../misc.h"
00030 #include "../util/messaginghub.h"
00031 #include <iostream>
00032 
00033 DI_Color::DI_Color() {
00034         r = 0;
00035         g = 0;
00036         b = 0;
00037 }
00038 
00039 DI_Color::DI_Color(const SDL_Color& c) {
00040         *this = c;
00041 }
00042 
00043 DI_Color::DI_Color(Uint32 c) {
00044         *this = c;
00045 }
00046 
00047 DI_Color::DI_Color(Uint8 r, Uint8 g, Uint8 b) {
00048         *this = (Uint32)((r << 16) | (g << 8) | b);
00049 }
00050 
00051 DI_Color& DI_Color::operator=(const SDL_Color& c) {
00052         r = c.r;
00053         g = c.g;
00054         b = c.b;
00055         
00056         return *this;
00057 }
00058 
00059 DI_Color& DI_Color::operator=(Uint32 c) {
00060         r = (c >> 16) & 0xFF;
00061         g = (c >> 8) & 0xFF;
00062         b = c & 0xFF;
00063         
00064         return *this;
00065 }
00066 
00067 /*
00068 DI_Color::operator Uint32() const {
00069         return (r << 16) | (g << 8) | b;
00070 }
00071 */
00072 
00073 
00074 
00075  SDLmm::PixelFormat* Surface::default8bit  = NULL;
00076  SDLmm::PixelFormat* Surface::default32bit = NULL;
00077 
00078 void Surface::SetScreen( SDL_Surface* screen )
00079 {
00080   if ( screen && screen->format->BitsPerPixel == 32 )    
00081      default32bit = new SDLmm::PixelFormat ( screen->format );
00082 }
00083 
00084 
00085 Surface Surface::Duplicate() const 
00086 {
00087    Surface new_surface(CreateSurface(*this));
00088 
00089    megaBlitter<ColorTransform_None, ColorMerger_PlainOverwrite, SourcePixelSelector_Plain, TargetPixelSelector_All>(*this, new_surface, SPoint(0,0), nullParam, nullParam, nullParam, nullParam); 
00090 
00091    new_surface.Blit(*this); 
00092    return new_surface;
00093 }
00094  
00095  
00096  void writeDefaultPixelFormat ( SDLmm::PixelFormat pf, tnstream& stream )
00097  {
00098     stream.writeInt( 1 );
00099     stream.writeInt(pf.BitsPerPixel()) ;
00100     stream.writeInt(pf.BytesPerPixel()) ;
00101     stream.writeInt(pf.Rmask()) ;
00102     stream.writeInt(pf.Gmask()) ;
00103     stream.writeInt(pf.Bmask()) ;
00104     stream.writeInt(pf.Amask()) ;
00105     stream.writeInt(pf.Rshift()) ;
00106     stream.writeInt(pf.Gshift()) ;
00107     stream.writeInt(pf.Bshift()) ;
00108     stream.writeInt(pf.Ashift()) ; 
00109     stream.writeInt(pf.Rloss()) ;
00110     stream.writeInt(pf.Gloss()) ;
00111     stream.writeInt(pf.Bloss()) ;
00112     stream.writeInt(pf.Aloss()) ;
00113     stream.writeInt(pf.colorkey()) ;
00114     stream.writeInt(pf.alpha()) ;
00115  }
00116 
00117  SDL_PixelFormat* readSDLPixelFormat( tnstream& stream )
00118  {
00119     SDL_PixelFormat* pf = new SDL_PixelFormat;
00120     int version = stream.readInt();
00121     if ( version != 1 )
00122        throw tinvalidversion( stream.getLocation(), 1, version );
00123        
00124     pf->BitsPerPixel = stream.readInt();
00125     pf->BytesPerPixel = stream.readInt();
00126     pf->Rmask = stream.readInt();
00127     pf->Gmask = stream.readInt();
00128     pf->Bmask = stream.readInt();
00129     pf->Amask = stream.readInt();
00130     pf->Rshift = stream.readInt();
00131     pf->Gshift = stream.readInt();
00132     pf->Bshift = stream.readInt();
00133     pf->Ashift = stream.readInt();
00134     pf->Rloss = stream.readInt();
00135     pf->Gloss = stream.readInt();
00136     pf->Bloss = stream.readInt();
00137     pf->Aloss = stream.readInt();
00138     pf->colorkey = stream.readInt();
00139     pf->alpha = stream.readInt();
00140     return pf;
00141  }
00142 
00143  
00144  
00145 Surface::Surface( SDL_Surface *surface) : SDLmm::Surface ( surface ), pixelDataPointer(NULL)
00146 {
00147    if ( me )
00148       convert();
00149 }
00150 
00151 void Surface::convert()
00152 {
00153    if ( GetPixelFormat().BitsPerPixel() == 24 ) {
00154       Surface s = Surface::createSurface(w(), h(), 32 );
00155       s.Blit( *this );
00156       if ( flags() & SDL_SRCCOLORKEY ) 
00157          s.SetColorKey( SDL_SRCCOLORKEY, GetPixelFormat().colorkey() );
00158       *this = s;   
00159    }
00160 
00161    if ( default32bit && GetPixelFormat().BytesPerPixel() == 4 )  {
00162       if ( default32bit->Rmask() != GetPixelFormat().Rmask() || default32bit->Gmask() != GetPixelFormat().Gmask() || default32bit->Bmask() != GetPixelFormat().Bmask() ) {
00163          SDL_Surface *tmp;
00164          if ( flags() & SDL_SRCALPHA )
00165             tmp  = SDL_DisplayFormatAlpha(me);
00166          else
00167             tmp  = SDL_DisplayFormat(me);
00168 
00169          if ( !tmp )
00170             return;
00171 
00172          SetSurface(tmp);
00173       }
00174    }
00175 
00176 }
00177 
00178 /*
00179 SDLmm::ColorRGB  Surface::GetRGB(SDLmm::Color pixel) const
00180 {
00181    if ( GetPixelFormat().BytesPerPixel() == 1 ) {
00182       assert( pixel < 256 );
00183       return SDLmm::ColorRGB( pal[pixel][0] * 4, pal[pixel][1] * 4, pal[pixel][2] * 4 );
00184    } else
00185       return GetPixelFormat().GetRGB( pixel );
00186 }
00187 
00188 SDLmm::ColorRGBA Surface::GetRGBA(SDLmm::Color pixel) const
00189 {
00190    if ( GetPixelFormat().BytesPerPixel() == 1 ) {
00191       assert( pixel < 256 );
00192       return SDLmm::ColorRGBA( pal[pixel][0] * 4, pal[pixel][1] * 4, pal[pixel][2] * 4, opaque );
00193    } else
00194       return GetPixelFormat().GetRGBA( pixel );
00195 }
00196 */
00197 
00198 Surface::Surface(const SDLmm::Surface& other) : SDLmm::Surface ( other ), pixelDataPointer(NULL)
00199 {
00200    if ( me )
00201       convert();
00202 }
00203 
00204  
00205  void Surface::readDefaultPixelFormat ( tnstream& stream )
00206  {
00207      default8bit = new SDLmm::PixelFormat( readSDLPixelFormat( stream ) );
00208      default32bit = new SDLmm::PixelFormat( readSDLPixelFormat( stream ) );
00209  }
00210 
00211  void Surface::writeDefaultPixelFormat ( tnstream& stream )
00212  {
00213      ::writeDefaultPixelFormat( GetPixelFormat(),stream );
00214  }
00215 
00216  const int surfaceVersion = 2;
00217 
00218 void Surface::write ( tnstream& stream ) const
00219 {
00220    if ( !valid() ) {
00221       stream.writeWord( 16974 );
00222       stream.writeWord ( 1 );
00223       stream.writeChar ( 0 );
00224       stream.writeWord ( 0 );
00225       stream.writeWord ( 0 );
00226       return;
00227    } 
00228    stream.writeWord( 16974 );
00229    stream.writeWord ( 1 );
00230    stream.writeChar ( 0 );
00231    stream.writeWord ( w() );
00232    stream.writeWord ( h() );
00233    stream.writeInt( surfaceVersion );
00234 
00235    SDLmm::PixelFormat pf = GetPixelFormat();
00236 
00237    stream.writeChar ( pf.BitsPerPixel() );
00238    stream.writeChar ( pf.BytesPerPixel() );
00239    stream.writeInt ( GetPixelFormat().colorkey());
00240    stream.writeInt( flags() );
00241    if ( pf.BytesPerPixel() == 1 ) {
00242       for ( int y = 0; y < h(); ++y )
00243          stream.writedata( ((char*)me->pixels) + y*pitch(), w() );
00244       /*
00245       for ( int y = 0; y < h(); ++y )
00246          for ( int x = 0; x < w(); ++x )
00247             stream.writeChar( GetPixel(x,y));
00248       */      
00249    } else {
00250       SDLmm::PixelFormat pf = GetPixelFormat();
00251       stream.writeInt(pf.Rmask()) ;
00252       stream.writeInt(pf.Gmask()) ;
00253       stream.writeInt(pf.Bmask()) ;
00254       stream.writeInt(pf.Amask()) ;
00255       for ( int y = 0; y < h(); ++y ) {
00256          for ( int x = 0; x < w(); ++x )
00257             stream.writeInt( GetPixel(x,y));
00258             
00259       }
00260    }
00261 
00262 }
00263 
00264  
00265 void Surface::read ( tnstream& stream )
00266 {
00267   trleheader   hd;
00268 
00269   hd.id = stream.readWord();
00270   hd.size = stream.readWord();
00271   hd.rle = stream.readChar();
00272   hd.x = stream.readWord();
00273   hd.y = stream.readWord();
00274   
00275   if ( hd.x == 0 && hd.y == 0 ) {
00276       SetSurface( NULL );
00277       return;  
00278   }
00279 
00280    if (hd.id == 16973) {
00281       char *pnter = new char [ hd.size + sizeof(hd) ];
00282       memcpy( pnter, &hd, sizeof(hd));
00283       char* q = pnter + sizeof(hd);
00284 
00285       stream.readdata( q, hd.size);  // endian ok ?
00286 
00287       char* uncomp = (char*) uncompress_rlepict ( pnter );
00288       pixelDataPointer = uncomp;
00289       
00290       // TODO fix memory leak: uncomp will not be deleted
00291       delete[] pnter;
00292 
00293       SDL_Surface* surface = SDL_CreateRGBSurface( SDL_SWSURFACE, hd.x+1, hd.y+1, 8,  0, 0, 0, 0 );
00294       for ( int y = 0; y <= hd.y; ++y ) {
00295          char* dest = ((char*)surface->pixels) + y * surface->pitch;
00296          memcpy( dest, uncomp+4 + y * (hd.x+1), hd.x+1);
00297       } 
00298       free ( uncomp );
00299       
00300       SetSurface( surface );
00301       SetColorKey( SDL_SRCCOLORKEY, 255 );
00302       assignDefaultPalette();
00303    }
00304    else {
00305       if (hd.id == 16974) {
00306          int version = stream.readInt();
00307          if ( version > surfaceVersion )
00308             throw tinvalidversion( stream.getLocation(), version, surfaceVersion );
00309              
00310          stream.readChar(); // int bitsPerPixel = 
00311          int bytesPerPixel = stream.readChar();
00312          int colorkey = stream.readInt();
00313          int flags = stream.readInt();
00314          if ( bytesPerPixel == 1 ) {
00315             SDL_Surface* s = SDL_CreateRGBSurface ( SDL_SWSURFACE, hd.x, hd.y, 8, 0xff, 0xff, 0xff, 0xff );
00316             Uint8* p = (Uint8*)( s->pixels );
00317             for ( int y = 0; y < hd.y; ++y )
00318                stream.readdata( p + y*s->pitch, hd.x );
00319             
00320                /*for ( int x = 0; x< hd.x; ++x )
00321                   *(p++) = stream.readChar();*/
00322                   
00323             SetSurface( s );
00324             assignDefaultPalette();
00325 
00326          } else {
00327             int Rmask = stream.readInt();
00328             int Gmask = stream.readInt();
00329             int Bmask = stream.readInt();
00330             int Amask = stream.readInt();
00331 
00332             SDL_Surface* s = SDL_CreateRGBSurface ( SDL_SWSURFACE, hd.x, hd.y, 32, Rmask, Gmask, Bmask, Amask );
00333             Uint32* p = (Uint32*)( s->pixels );
00334             for ( int y = 0; y < hd.y; ++y ) {
00335                for ( int x = 0; x< hd.x; ++x )
00336                   *(p++) = stream.readInt();
00337             }
00338             SetSurface( s );
00339          }
00340          if ( flags & SDL_SRCCOLORKEY )
00341             SetColorKey( SDL_SRCCOLORKEY, colorkey );
00342             
00343          if ( flags & SDL_SRCALPHA )
00344             SetAlpha ( SDL_SRCALPHA, GetPixelFormat().alpha());
00345          else
00346             SetAlpha ( 0, SDL_ALPHA_OPAQUE);
00347             
00348       } else {
00349          // int w =  (hd.id + 1) * (hd.size + 1) ;
00350          
00351          SDL_Surface* s = SDL_CreateRGBSurface( SDL_SWSURFACE, hd.id+1, hd.size+1, 8, 0,0,0,0 );
00352 
00353          for ( int y = 0; y <= hd.size; ++y ) {
00354             char* pixeldata = (char*)(s->pixels) + y * s->pitch;
00355             if ( y == 0 ) {
00356                memcpy ( pixeldata, ((char*)&hd) + 4, sizeof ( hd ) - 4);
00357                char* q = pixeldata + sizeof(hd) - 4;
00358                stream.readdata ( q, s->w - sizeof(hd) + 4 ); 
00359             } else {
00360                stream.readdata ( pixeldata, s->w ); 
00361             }
00362          }
00363 /*
00364 
00365          char* pntr = (char*) asc_malloc( w );
00366          stream.readdata ( q, w - sizeof(hd) + 4 ); // endian ok ?
00367 
00368          SDL_SWSURFACE
00369          SDL_Surface* s = SDL_CreateRGBSurfaceFrom(pntr, hd.id+1, hd.size+1, 8, hd.id+1, 0, 0, 0, 0 );
00370 //         s->flags &= ~SDL_PREALLOC;
00371   */       
00372          SetSurface( s );
00373          SetColorKey( SDL_SRCCOLORKEY, 255 );
00374          assignDefaultPalette();
00375       }
00376    }
00377    convert();
00378 }
00379 
00380 void Surface::readImageFile( tnstream& stream )
00381 {
00382    SetSurface( IMG_Load_RW( SDL_RWFromStream ( &stream ), true ));
00383    convert();
00384 }
00385 
00386 
00387 Surface Surface::createSurface( int width, int height, SDLmm::Color color )
00388 {
00389    Surface s = createSurface ( width, height, 8, color );
00390    s.SetColorKey( SDL_SRCCOLORKEY, 255 );
00391    return s;
00392 }
00393 
00394 Surface Surface::createSurface( int width, int height, int depth, SDLmm::Color color )
00395 {
00396    assert ( depth == 32 || depth == 8 );
00397 
00398    SDL_Surface* surf = NULL;   
00399    if ( depth == 32 && default32bit ) {
00400       int rmask = default32bit->Rmask();
00401       int gmask = default32bit->Gmask();
00402       int bmask = default32bit->Bmask();
00403       int amask = ~(rmask | gmask | bmask );
00404       surf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, depth, rmask, gmask, bmask, amask );
00405    } else
00406       surf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, depth, 0xff, 0xff00, 0xff0000, 0xff000000 );
00407    
00408    Surface s ( surf );
00409    if ( depth == 32 )
00410       s.Fill(color);
00411    else {
00412       s.Fill(color & 0xff );
00413       s.assignDefaultPalette();
00414    }
00415    // s.SetColorKey( SDL_SRCCOLORKEY, 255 );
00416    return s;
00417 }
00418 
00419 void Surface::FillTransparent()
00420 {
00421    if ( GetPixelFormat().BitsPerPixel() == 32 ) {
00422       Fill( 0 );
00423    } else {
00424       Fill( GetPixelFormat().colorkey() );
00425    }      
00426 }
00427 
00428 
00429 void Surface::assignDefaultPalette()
00430 {
00431    if ( me && GetPixelFormat().BytesPerPixel() == 1 ) {
00432         SDL_Color spal[256];
00433         memset ( spal, 0, 256* sizeof(SDL_Color));
00434         for ( int i = 0; i < 256; i++ ) {
00435            spal[i].r = pal[i][0] * 4;;
00436            spal[i].g = pal[i][1] * 4;;
00437            spal[i].b = pal[i][2] * 4;;
00438          }
00439          SDL_SetColors ( me, spal, 0, 256 );
00440    }
00441 }
00442 
00443 
00444 void Surface::assignPalette(SDL_Color* colors, int startColor, int colorNum )
00445 {
00446    if ( me )
00447       SDL_SetColors ( me, colors, startColor, colorNum );
00448 }
00449 
00450 
00451 /*
00452 void SDL_StretchSurface(SDL_Surface* src_surface, int xs1, int ys1, int xs2, int ys2, SDL_Surface* dst_surface, int xd1, int yd1, int xd2, int yd2, Uint32* lutVOI)
00453 {
00454 }
00455 */
00456 
00457 void Surface::strech ( int width, int height )
00458 {
00459    if ( width != w() || height != h() ) {
00460       SDL_Surface* s;
00461       if( GetPixelFormat().BytesPerPixel() == 1 )
00462          s = SDL_CreateRGBSurface ( SDL_SWSURFACE, width, height, 8, 0,0,0,0 );
00463       else
00464          s = SDL_CreateRGBSurface ( SDL_SWSURFACE, width, height, 32, 0xff, 0xff00, 0xff0000, 0xff000000 );
00465          
00466       SDL_StretchSurface( me,0,0,w()-1,h()-1, s, 0,0,width-1, height-1);
00467 
00468       SetSurface(s);
00469       if( GetPixelFormat().BytesPerPixel() == 1 ) {
00470          assignDefaultPalette();
00471          detectColorKey();
00472       }
00473    }
00474 }
00475 
00476 bool Surface::hasAlpha() 
00477 {
00478    if ( GetPixelFormat().BitsPerPixel() > 8 ) {
00479       for ( int y = 0; y < h(); ++y )
00480          for ( int x = 0; x < w(); ++x )
00481             if ( (GetPixel(x,y) >> GetPixelFormat().Ashift())  != SDL_ALPHA_OPAQUE ) {
00482                // GetSurface()->flags |= SDL_SRCALPHA;
00483                return true;
00484             }
00485 
00486       // GetSurface()->flags &= ~SDL_SRCALPHA; 
00487    }
00488    return false;
00489 }
00490 
00491 
00492 
00493 void Surface::detectColorKey ( bool RLE )
00494 {
00495 
00496    // detect if image has per pixel alpha - don't use ColorKey then
00497    if ( GetPixelFormat().BitsPerPixel() > 8 ) 
00498       if ( hasAlpha() ) 
00499          return;
00500    
00501    int flags = SDL_SRCCOLORKEY;
00502    if ( RLE )
00503       flags |= SDL_RLEACCEL;
00504       
00505    SetAlpha ( 0, 0 );
00506       
00507    if ( GetPixelFormat().BitsPerPixel() > 8 ) {
00508       SetColorKey( flags, GetPixel(0,0) & ( GetPixelFormat().Rmask() | GetPixelFormat().Gmask() | GetPixelFormat().Bmask()));
00509    } else
00510       SetColorKey( flags, GetPixel(0,0));
00511       // SetColorKey( flags, 255 );
00512 }
00513 
00514 
00515 bool Surface::isTransparent( SDLmm::Color col ) const
00516 {
00517    if ( flags() & SDL_SRCCOLORKEY ) 
00518       return (col & (GetPixelFormat().Rmask() | GetPixelFormat().Gmask() | GetPixelFormat().Bmask())) == GetPixelFormat().colorkey();
00519    else {
00520       if ( GetPixelFormat().BitsPerPixel() == 8 )
00521          return false;
00522       else {
00523          if ( ((col & GetPixelFormat().Amask()) >> GetPixelFormat().Ashift()) < opaque/2)
00524             return true;
00525          else
00526             return false;
00527       }
00528    }
00529 }
00530 
00531 Surface::~Surface()
00532 {/*
00533    if ( pixelDataPointer ) {
00534       asc_free( pixelDataPointer );
00535       pixelDataPointer = NULL;
00536    }
00537    */
00538 }
00539 
00540 
00541 
00542 
00543 Surface& getFieldMask()
00544 {
00545    static Surface* mask8 = NULL;
00546    if ( !mask8 ) {
00547       try {
00548          tnfilestream st ( "largehex.pcx", tnstream::reading );
00549          RWOPS_Handler rwo ( SDL_RWFromStream( &st ) );
00550          mask8 = new Surface ( IMG_LoadPCX_RW ( rwo.Get() ));
00551          rwo.Close();
00552 
00553          assert ( mask8->GetPixelFormat().BitsPerPixel() == 8);
00554          mask8->SetColorKey( SDL_SRCCOLORKEY, 0 );
00555       }
00556       catch ( tfileerror err ) {
00557          fatalError( "could not access " + err.getFileName() );
00558       }
00559       
00560    }
00561    return *mask8;
00562 
00563 }
00564 
00565 
00566 template<int pixelsize>
00567 class ColorMerger_MaskApply : public ColorMerger_AlphaHandler<pixelsize>
00568 {
00569       int alphamask;
00570       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00571    protected:
00572 
00573       void init( const Surface& srf )
00574       {
00575          alphamask = ~(srf.GetPixelFormat().Amask());
00576          ColorMerger_AlphaHandler<pixelsize>::init(srf);
00577       }
00578 
00579 
00580       void assign ( PixelType src, PixelType* dest )
00581       {
00582          if ( !this->isOpaque(src ) )
00583             *dest &= alphamask;
00584       };
00585 
00586    public:
00587       ColorMerger_MaskApply( NullParamType npt = nullParam )
00588       {}
00589       ;
00590 };
00591 
00592 
00593 void applyFieldMask( Surface& s, int x, int y, bool detecColorKey )
00594 {
00595    if ( s.GetPixelFormat().BitsPerPixel() == 8 ) {
00596       // we don't want any transformations from one palette to another; we just assume that all 8-Bit images use the same colorspace
00597       MegaBlitter<1,1,ColorTransform_None,ColorMerger_AlphaOverwrite> blitter;
00598       blitter.blit( getFieldMask(), s, SPoint(0,0)  );
00599       s.detectColorKey (  );
00600    } else {
00601       if ( detecColorKey ) {
00602          s.Blit( getFieldMask() );
00603          s.detectColorKey (  );
00604       } else {
00605          MegaBlitter<1,4,ColorTransform_None,ColorMerger_MaskApply> blitter;
00606          blitter.blit( getFieldMask(), s, SPoint(0,0)  );
00607       }
00608    }
00609 }
00610 
00611 void applyLegacyFieldMask( Surface& s, int x, int y, bool detectColorKey )
00612 {
00613    static Surface* mask32 = NULL;
00614    if ( !mask32 ) {
00615       Surface& mask8 = getFieldMask();
00616       
00617       mask32 = new Surface ( Surface::createSurface( mask8.w(), mask8.h(), 32 ));
00618       for ( int y = 0; y < mask8.h(); ++y ) {
00619          Uint8* s = ((Uint8*) mask8.pixels()) + mask8.pitch() * y;
00620          Uint32* d = (Uint32*) ((Uint8*)(mask32->pixels()) + mask32->pitch() * y);
00621          for ( int x = 0; x < mask8.w(); ++x, ++s, ++d)
00622             if ( *s == 0 )
00623                *d = 0;   
00624             else
00625                *d = 0xfffefefe;
00626       }
00627               
00628       mask32->SetColorKey( SDL_SRCCOLORKEY, 0 );
00629       
00630    }
00631    if ( s.GetPixelFormat().BitsPerPixel() == 8 ) {
00632       // we don't want any transformations from one palette to another; we just assume that all 8-Bit images use the same colorspace
00633       MegaBlitter<1,1,ColorTransform_None,ColorMerger_AlphaOverwrite> blitter;
00634       blitter.blit( getFieldMask(), s, SPoint(0,0)  );
00635       s.detectColorKey (  );
00636    } else {
00637       if ( !detectColorKey || s.hasAlpha() ) {
00638          MegaBlitter<1,4,ColorTransform_None,ColorMerger_MaskApply> blitter;
00639          blitter.blit( getFieldMask(), s, SPoint(0,0)  );
00640       } else {
00641          s.Blit( *mask32 );
00642          s.detectColorKey (  );
00643       }
00644    }
00645 }
00646 
00647 /*
00648 void colorShift ( Surface& s, int startcolor, int colNum, int shift )
00649 {
00650    if ( s.GetPixelFormat().BitsPerPixel() != 8)
00651       fatalError ( "colorShift can only be done with 8 Bit surfaces");
00652 
00653    SDL_Color spal[256];
00654    int col;
00655    for ( int i = 0; i < 256; i++ ) {
00656       int src;
00657       if ( i >= startcolor && i < startcolor + colNum )
00658          src = i + shift;
00659       else
00660          src = i;
00661       for ( int c = 0; c < 3; c++ ) {
00662          col = pal[src][c];
00663          switch ( c ) {
00664             case 0: spal[i].r = col * 4; break;
00665             case 1: spal[i].g = col * 4; break;
00666             case 2: spal[i].b = col * 4; break;
00667          };
00668       }
00669    }
00670    s.assignPalette( spal, 0, 256 );
00671 }
00672 */
00673 
00674 Surface rotateSurface( Surface& s, int degrees )
00675 {
00676    SurfaceLock sl1 ( s );
00677 
00678    Surface dest = s.Duplicate();
00679 
00680    SurfaceLock sl2( dest );
00681 
00682    if ( s.GetPixelFormat().BitsPerPixel() == 8 )
00683       dest.Fill ( 255 );
00684    else {
00685       dest.Fill(0xfefefe);
00686    }
00687    dest.detectColorKey();
00688 
00689    for ( int y = 0; y < s.h(); y++ ) {
00690       for ( int x = 0; x < s.w(); x++ ) {
00691          SPoint newpos = getPixelRotationLocation( SPoint(x,y), s.w(),s.h(), degrees );
00692 
00693          if ( newpos.x >= 0 && newpos.y >= 0 && newpos.x < s.w() && newpos.y < s.h() )
00694             dest.SetPixel( x, y, s.GetPixel ( newpos ));
00695       }
00696    }
00697 
00698    return dest;
00699 }
00700 
00701 
00702 void* Surface::toBGI() const
00703 {
00704    void* p = malloc( imagesize(1,1,w(),h()) );
00705    char* c = (char*) p;
00706    Uint16* ww = (Uint16*) p;
00707    ww[0] = w()-1;
00708    ww[1] = h()-1;
00709    c += 4;
00710    for ( int y = 0; y < h(); ++y )
00711       for ( int x = 0; x < w(); ++x )
00712           *c++ = GetPixel(x,y);
00713    return p;
00714 }
00715 
00716 int Surface::getMemoryFootprint() const
00717 {
00718    int size = sizeof(*this);
00719    
00720    const SDL_Surface* s = getBaseSurface();
00721    if ( s ) {
00722       size += sizeof( SDL_Surface );
00723       if ( s->format ) {
00724          size += sizeof( SDL_PixelFormat );
00725          if ( s->format->palette )
00726             size += sizeof ( SDL_Palette ) + s->format->palette->ncolors * sizeof(SDL_Color);
00727       }
00728       size += s->h * s->pitch;
00729    }
00730    return size;
00731 }
00732 
00733 
00734 void Surface::ColorKey2AlphaChannel() 
00735 {
00736    Lock();
00737    for ( int y = 0; y < h(); ++y ) {
00738       char* cp = (char*) pixels();
00739       cp += y * pitch();
00740       int* ip = (int*) cp;
00741       for ( int x = 0; x < w(); ++x, ++ip ) 
00742          if ( (*ip & ~(0xff << GetPixelFormat().Ashift())) == GetPixelFormat().colorkey())
00743             *ip &= ~(Surface::transparent << GetPixelFormat().Ashift());
00744    }
00745    GetSurface()->flags &= ~SDL_SRCCOLORKEY;
00746    Unlock();
00747 }
00748 

Generated on Mon May 21 01:26:37 2012 for Advanced Strategic Command by  doxygen 1.5.1