Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

blitter.h

Go to the documentation of this file.
00001 /*
00002     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00003     Copyright (C) 1994-2004  Martin Bickel  and  Marc Schellenberger
00004  
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009  
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014  
00015     You should have received a copy of the GNU General Public License
00016     along with this program; see the file COPYING. If not, write to the
00017     Free Software Foundation, Inc., 59 Temple Place, Suite 330,
00018     Boston, MA  02111-1307  USA
00019 */
00020 
00021 #ifndef blitterH
00022  #define blitterH
00023 
00024 #include <cmath>
00025  #include <map>
00026  #include "../libs/loki/static_check.h"
00027  #include "../libs/sdlmm/src/sdlmm.h"
00028  #include "surface.h"
00029 
00030 #include "../misc.h"
00031  #include "../palette.h"
00032  #include "../basegfx.h"
00033 
00034 typedef SDLmm::Color Color;
00035 
00036 class NullParamType
00037    {}
00038 ;
00039 extern NullParamType nullParam;
00040 
00041 
00042 template<int BytesPerPixel>
00043 class PixelSize2Type;
00044 
00045 template<>
00046 class PixelSize2Type<1>
00047 {
00048    public:
00049       typedef Uint8  PixelType;
00050 };
00051 template<>
00052 class PixelSize2Type<2>
00053 {
00054    public:
00055       typedef Uint16 PixelType;
00056 };
00057 template<>
00058 class PixelSize2Type<4>
00059 {
00060    public:
00061       typedef Uint32 PixelType;
00062 };
00063 
00064 
00065 
00066 class TargetPixelSelector_All
00067 {
00068    protected:
00069       int skipTarget( int x, int y )
00070       {
00071          return 0;
00072       };
00073       void init( const Surface& srv, const SPoint& pos, int xrange, int yrange )
00074       {}
00075       ;
00076    public:
00077       TargetPixelSelector_All ( NullParamType npt = nullParam )
00078       {}
00079       ;
00080 };
00081 
00082 class TargetPixelSelector_Valid
00083 {
00084       int w,h;
00085       int xrange;
00086       SPoint dstPos;
00087    protected:
00088       int skipTarget( int x, int y )
00089       {
00090          x += dstPos.x;
00091          y += dstPos.y;
00092 
00093          if ( x >= 0 && y >= 0 && x < w && y < h )
00094             return 0;
00095          else
00096             if ( x < 0 )
00097                return -x;
00098             else
00099                return xrange - x + dstPos.x;
00100       };
00101       void init( const Surface& srv, const SPoint& pos, int xrange, int yrange )
00102       {
00103          w = srv.w();
00104          h = srv.h();
00105          dstPos = pos;
00106          this->xrange = xrange;
00107       };
00108    public:
00109       TargetPixelSelector_Valid ( NullParamType npt = nullParam ) :w(0xffffff),h(0xffffff),xrange(1)
00110       {}
00111       ;
00112 };
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 template<int pixelsize>
00121 class SourcePixelSelector_Plain
00122 {
00123       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00124       const PixelType* pointer;
00125       int pitch;
00126       int linelength;
00127       const Surface* surface;
00128    protected:
00129       SourcePixelSelector_Plain() : pointer(NULL), surface(NULL)
00130       {}
00131       ;
00132 
00133       void init ( const Surface& srv )
00134       {
00135          surface = &srv;
00136          pointer = (const PixelType*)(srv.pixels());
00137          linelength = srv.pitch()/sizeof(PixelType);
00138          pitch = linelength - srv.w();
00139       };
00140 
00141       PixelType getPixel(int x, int y)
00142       {
00143          if ( x >= 0 && y >= 0 && x < surface->w() && y < surface->h() )
00144             return surface->GetPixel(SPoint(x,y));
00145          else
00146             return surface->GetPixelFormat().colorkey();
00147       };
00148 
00149       PixelType nextPixel()
00150       {
00151          return *(pointer++);
00152       };
00153       void nextLine()
00154       {
00155          pointer += pitch;
00156       };
00157       void skipPixels( int pixNum )
00158       {
00159          pointer += pixNum;
00160       };
00161 
00162       int getSourcePixelSkip()
00163       {
00164          return 0;
00165       };
00166       
00167       void skipWholeLine()
00168       {
00169          pointer += linelength;
00170       };
00171 
00172       int getWidth()
00173       {
00174          return surface->w();
00175       };
00176       int getHeight()
00177       {
00178          return surface->h();
00179       };
00180    public:
00181       SourcePixelSelector_Plain ( NullParamType npt )
00182       {}
00183       ;
00184 };
00185 
00186 
00187 template<
00188 int BytesPerSourcePixel,
00189 int BytesPerTargetPixel
00190 >
00191 class ColorConverter
00192 {
00193    public:
00194       typedef typename PixelSize2Type<BytesPerTargetPixel>::PixelType SourcePixelType;
00195       typedef typename PixelSize2Type<BytesPerTargetPixel>::PixelType TargetPixelType;
00196    private:
00197       SourcePixelType srcColorKey;
00198       TargetPixelType destColorKey;
00199    public:
00200       ColorConverter( const Surface& sourceSurface, Surface& targetSurface )
00201       {}
00202       ;
00203       TargetPixelType convert ( SourcePixelType sp )
00204       {
00205          return sp;
00206       };
00207 };
00208 
00209 
00210 template<>
00211 class ColorConverter<4,1>
00212 {
00213       int rshift, gshift, bshift;
00214    public:
00215       typedef  PixelSize2Type<4>::PixelType SourcePixelType;
00216       typedef  PixelSize2Type<1>::PixelType TargetPixelType;
00217    private:
00218       SourcePixelType srcColorKey;
00219       TargetPixelType destColorKey;
00220       bool srcHasColorKey;
00221       int srcColorMask;
00222    public:
00223 
00224       ColorConverter( const Surface& sourceSurface, Surface& targetSurface )
00225       {
00226          rshift = sourceSurface.GetPixelFormat().Rshift() + 2;
00227          gshift = sourceSurface.GetPixelFormat().Gshift() + 2;
00228          bshift = sourceSurface.GetPixelFormat().Bshift() + 2;
00229          srcColorMask = ~sourceSurface.GetPixelFormat().Amask();
00230          srcColorKey = sourceSurface.GetPixelFormat().colorkey() & srcColorMask;
00231 
00232          srcHasColorKey = sourceSurface.flags() & SDL_SRCCOLORKEY;
00233          if ( targetSurface.flags() & SDL_SRCCOLORKEY )
00234             destColorKey = targetSurface.GetPixelFormat().colorkey();
00235          else
00236             destColorKey = 0xff;
00237 
00238 
00239       };
00240       TargetPixelType convert ( SourcePixelType sp )
00241       {
00242          #ifdef use_truecolor2pal
00243          if ( srcHasColorKey && (sp & srcColorMask) == srcColorKey )
00244             return destColorKey;
00245          else
00246             return truecolor2pal_table[ ((sp >> rshift) & 0x3f) + (((sp >> gshift) & 0x3f) << 6) + (((sp >> bshift) & 0x3f) << 12)];
00247          #else
00248          return destColorKey;
00249          #endif
00250       };
00251 };
00252 
00253 template<>
00254 class ColorConverter<1,4>
00255 {
00256    public:
00257       typedef  PixelSize2Type<1>::PixelType SourcePixelType;
00258       typedef  PixelSize2Type<4>::PixelType TargetPixelType;
00259    private:
00260       SDL_Color* palette;
00261       int rshift, gshift, bshift,ashift;
00262       bool hasColorKey;
00263       TargetPixelType colorKey;
00264    public:
00265 
00266       ColorConverter( const Surface& sourceSurface, Surface& targetSurface )
00267       {
00268          if ( targetSurface.flags() & SDL_SRCCOLORKEY ) {
00269             hasColorKey = true;
00270             colorKey = targetSurface.GetPixelFormat().colorkey();
00271          } else {
00272             hasColorKey = false;
00273             colorKey = 0;
00274          }
00275 
00276          palette = sourceSurface.GetPixelFormat().palette()->colors;
00277          rshift = targetSurface.GetPixelFormat().Rshift();
00278          gshift = targetSurface.GetPixelFormat().Gshift();
00279          bshift = targetSurface.GetPixelFormat().Bshift();
00280          if ( targetSurface.GetPixelFormat().Amask() )
00281             ashift = targetSurface.GetPixelFormat().Ashift();
00282          else
00283             ashift = firstBit( ~( targetSurface.GetPixelFormat().Rmask() | targetSurface.GetPixelFormat().Gmask() | targetSurface.GetPixelFormat().Bmask()));
00284 
00285       };
00286 
00287       TargetPixelType convert ( SourcePixelType sp )
00288       {
00289          if ( sp == 0xff ) {
00290             if ( hasColorKey )
00291                return colorKey;
00292             else
00293                return Surface::transparent << ashift;
00294          } else {
00295             TargetPixelType a = Surface::opaque;
00296             a <<= ashift;
00297             return TargetPixelType(palette[sp].r << rshift) + TargetPixelType(palette[sp].g << gshift) + TargetPixelType(palette[sp].b << bshift) + a;
00298          }
00299       };
00300 
00301 };
00302 
00303 
00304 
00305 template<
00306 int BytesPerSourcePixel,
00307 int BytesPerTargetPixel,
00308 template<int> class SourceColorTransform, // = ColorTransform_None,
00309 template<int> class ColorMerger, // = ColorMerger_PlainOverwrite,
00310 template<int> class SourcePixelSelector = SourcePixelSelector_Plain,
00311 class TargetPixelSelector = TargetPixelSelector_All,
00312 template<int,int> class MyColorConverter = ColorConverter
00313 >
00314 class MegaBlitter : public SourceColorTransform<BytesPerSourcePixel>,
00315          public ColorMerger<BytesPerTargetPixel>,
00316          public SourcePixelSelector<BytesPerSourcePixel>,
00317          public TargetPixelSelector
00318 {
00319       typedef typename PixelSize2Type<BytesPerSourcePixel>::PixelType SourcePixelType;
00320       typedef typename PixelSize2Type<BytesPerTargetPixel>::PixelType TargetPixelType;
00321    public:
00322       MegaBlitter()
00323       { }
00324       ;
00325       MegaBlitter( const SourceColorTransform<BytesPerSourcePixel>& scm, const ColorMerger<BytesPerTargetPixel>& cm, const SourcePixelSelector<BytesPerSourcePixel>& sps, const TargetPixelSelector& tps ) :
00326             SourceColorTransform<BytesPerSourcePixel>( scm ),
00327             ColorMerger<BytesPerTargetPixel>( cm ),
00328             SourcePixelSelector<BytesPerSourcePixel>( sps ),
00329             TargetPixelSelector( tps )
00330       { }
00331       ;
00332 
00333       int getWidth()
00334       {
00335          return SourcePixelSelector<BytesPerTargetPixel>::getWidth();
00336       };
00337       int getHeight()
00338       {
00339          return SourcePixelSelector<BytesPerTargetPixel>::getHeight();
00340       };
00341 
00342       void initSource( const Surface& src )
00343       {
00344          SourcePixelSelector<BytesPerSourcePixel>::init( src );
00345       }
00346 
00347 
00348       void blit( const Surface& src, Surface& dst, SPoint dstPos )
00349       {
00350          assert( src.GetPixelFormat().BytesPerPixel() == BytesPerSourcePixel );
00351          assert( dst.GetPixelFormat().BytesPerPixel() == BytesPerTargetPixel );
00352 
00353          SurfaceLock sl( dst );
00354 
00355          ColorMerger<BytesPerTargetPixel>::init( BytesPerSourcePixel == BytesPerTargetPixel ? src : dst );
00356          SourcePixelSelector<BytesPerSourcePixel>::init( src );
00357 
00358          MyColorConverter<BytesPerSourcePixel,BytesPerTargetPixel> colorConverter( src, dst );
00359 
00360          SourceColorTransform<BytesPerSourcePixel>::init( src );
00361 
00362          int h = SourcePixelSelector<BytesPerSourcePixel>::getHeight();
00363          int w = SourcePixelSelector<BytesPerSourcePixel>::getWidth();
00364 
00365          TargetPixelSelector::init( dst, dstPos, w, h );
00366          
00367          TargetPixelType* pix = (TargetPixelType*)( dst.pixels() );
00368 
00369          pix += dstPos.y * dst.pitch()/BytesPerTargetPixel + dstPos.x;
00370 
00371          int pitch = dst.pitch()/BytesPerTargetPixel - w;
00372 
00373          typedef SourcePixelSelector<BytesPerTargetPixel> SPS;
00374          for ( int y = 0; y < h; ++y ) {
00375             for ( int x = 0; x < w; ++x ) {
00376                int s = TargetPixelSelector::skipTarget(x,y);
00377                if ( s >= 0 && SourcePixelSelector<BytesPerSourcePixel>::getSourcePixelSkip() > s )
00378                   s = SourcePixelSelector<BytesPerSourcePixel>::getSourcePixelSkip();
00379                
00380                if ( s==0 ) {
00381                   ColorMerger<BytesPerTargetPixel>::assign ( colorConverter.convert( SourceColorTransform<BytesPerSourcePixel>::transform( SourcePixelSelector<BytesPerSourcePixel>::nextPixel())), pix );
00382                   ++pix;
00383                } else {
00384                   if ( s > 0 ) {
00385                      SourcePixelSelector<BytesPerSourcePixel>::skipPixels( s );
00386                      pix += s;
00387                      x += s - 1 ;
00388                   } else
00389                      return;
00390                }
00391             }
00392             SourcePixelSelector<BytesPerSourcePixel>::nextLine();
00393             pix += pitch;
00394          }
00395       };
00396 
00397 };
00398 
00399 
00400 template<
00401 template<int> class SourceColorTransform,
00402 template<int> class ColorMerger,
00403 template<int> class SourcePixelSelector,
00404 class TargetPixelSelector,
00405 typename SourceColorTransformParameter,
00406 typename ColorMergerParameter,
00407 typename SourcePixelSelectorParameter,
00408 typename TargetPixelSelectorParameter
00409 >
00410 void megaBlitter  ( const Surface& src,
00411                     Surface& dst,
00412                     const SPoint& pos,
00413                     const SourceColorTransformParameter& scmp = nullParam,
00414                     const ColorMergerParameter& cmp  = nullParam,
00415                     const SourcePixelSelectorParameter spsp  = nullParam,
00416                     const TargetPixelSelectorParameter tpsp  = nullParam )
00417 {
00418    switch ( src.GetPixelFormat().BytesPerPixel() ) {
00419       case 1: {
00420             switch ( dst.GetPixelFormat().BytesPerPixel() ) {
00421                case 1: {
00422                      MegaBlitter<
00423                      1,1,
00424                      SourceColorTransform,
00425                      ColorMerger,
00426                      SourcePixelSelector,
00427                      TargetPixelSelector
00428                      >  blitter (
00429                         (SourceColorTransform<1>)( scmp ),
00430                         (ColorMerger<1>)( cmp ),
00431                         (SourcePixelSelector<1>)( spsp ),
00432                         TargetPixelSelector(tpsp)
00433                      );
00434                      blitter.blit( src, dst, pos );
00435                   }
00436                   break;
00437                case 3:
00438                case 4: {
00439                      MegaBlitter<
00440                      1,4,
00441                      SourceColorTransform,
00442                      ColorMerger,
00443                      SourcePixelSelector,
00444                      TargetPixelSelector
00445                      >  blitter (
00446                         (SourceColorTransform<1>)( scmp ),
00447                         (ColorMerger<4>)( cmp ),
00448                         (SourcePixelSelector<1>)( spsp ),
00449                         TargetPixelSelector(tpsp)
00450                      );
00451                      blitter.blit( src, dst, pos );
00452                   }
00453                   break;
00454             };
00455          }
00456          break;
00457       case 3:
00458       case 4:  {
00459             switch ( dst.GetPixelFormat().BytesPerPixel() ) {
00460                case 1: {
00461                      MegaBlitter<
00462                      4,1,
00463                      SourceColorTransform,
00464                      ColorMerger,
00465                      SourcePixelSelector,
00466                      TargetPixelSelector
00467                      >  blitter (
00468                         (SourceColorTransform<4>)( scmp ),
00469                         (ColorMerger<1>)( cmp ),
00470                         (SourcePixelSelector<4>)( spsp ),
00471                         TargetPixelSelector(tpsp)
00472                      );
00473                      blitter.blit( src, dst, pos );
00474                   }
00475                   break;
00476                case 3:
00477                case 4: {
00478                      MegaBlitter<
00479                      4,4,
00480                      SourceColorTransform,
00481                      ColorMerger,
00482                      SourcePixelSelector,
00483                      TargetPixelSelector
00484                      >  blitter (
00485                         (SourceColorTransform<4>)( scmp ),
00486                         (ColorMerger<4>)( cmp ),
00487                         (SourcePixelSelector<4>)( spsp ),
00488                         TargetPixelSelector(tpsp)
00489                      );
00490                      blitter.blit( src, dst, pos );
00491                   }
00492                   break;
00493             };
00494          }
00495          break;
00496    }
00497 }
00498 
00499 
00500 
00502 
00503 class Player;
00504 
00505 
00506 template<int pixelsize>
00507 class ColorTransform_None
00508 {
00509       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00510    protected:
00511       ColorTransform_None()
00512       {}
00513       ;
00514       PixelType transform( PixelType col)
00515       {
00516          return col;
00517       };
00518       void init( const Surface& src )
00519       {}
00520       ;
00521    public:
00522       ColorTransform_None ( NullParamType npt )
00523       {}
00524       ;
00525 };
00526 
00527 
00528 
00529 
00530 template<int pixelSize>
00531 class ColorTransform_XLAT
00532 {
00533       const char* table;
00534 
00535    protected:
00536       ColorTransform_XLAT() : table(NULL)
00537       {}
00538       ;
00539 
00540       void init( const Surface& src )
00541       {}
00542       ;
00543 
00544       Color transform( Color col)
00545       {
00546          if ( table )
00547             return table[col];
00548          else
00549             return col;
00550       };
00551 
00552    public:
00553       void setTranslationTable( const char* translationTable )
00554       {
00555          table = translationTable;
00556       };
00557 
00558       ColorTransform_XLAT ( NullParamType npt ) : table(NULL)
00559       {}
00560       ;
00561 
00562       ColorTransform_XLAT ( const char* t ) : table ( t )
00563       {}
00564       ;
00565 };
00566 
00567 
00568 template<int pixelSize>
00569 class ColorTransform_Gray
00570    { }
00571 ;
00572 
00573 
00574 template<>
00575 class ColorTransform_Gray<4>
00576 {
00577    protected:
00578       ColorTransform_Gray()
00579       {}
00580       ;
00581 
00582       Color transform( Color col)
00583       {
00584          int i = ((col & 0xff) + ((col >> 8) & 0xff) + ((col >> 16) & 0xff)) / 3;
00585          return i + (i<<8) + (i <<16) + (col & 0xff000000);
00586       };
00587 
00588       void init( const Surface& src )
00589       {}
00590       ;
00591 
00592    public:
00593       ColorTransform_Gray ( NullParamType npt )
00594       {}
00595       ;
00596 };
00597 
00598 
00600 
00601 template<int pixelsize>
00602 class ColorMerger_PlainOverwrite
00603 {
00604       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00605    protected:
00606       ColorMerger_PlainOverwrite()
00607       {}
00608       ;
00609       void init( const Surface& dst )
00610       {}
00611       ;
00612       void assign ( PixelType src, PixelType* dest )
00613       {
00614          *dest = src;
00615       };
00616    public:
00617       ColorMerger_PlainOverwrite ( NullParamType npt )
00618       {}
00619       ;
00620 };
00621 
00622 template<int pixelsize>
00623 class ColorMerger_ColoredOverwrite
00624 {
00625       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00626       DI_Color col;
00627       mutable PixelType transformedColor;
00628    public:
00629       void init( const Surface& dst ) const
00630       {
00631          transformedColor =  dst.GetPixelFormat().MapRGB( col );
00632       };
00633       void assign ( PixelType src, PixelType* dest ) const
00634       {
00635          *dest = src;
00636       };
00637       void assign ( PixelType* dest ) const
00638       {
00639          *dest = transformedColor;
00640       };
00641       ColorMerger_ColoredOverwrite ( DI_Color color ) : col(color)
00642       {}
00643       ;
00644 };
00645 
00646 
00647 template<int pixelsize>
00648 class ColorMerger_AlphaHandler
00649 {
00650       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00651       int colorKey;
00652       int mask;
00653    protected:
00654       ColorMerger_AlphaHandler() : mask ( -1 )
00655       {}
00656       ;
00657 
00658       void init( const Surface& srf )
00659       {
00660          if ( srf.flags() & SDL_SRCCOLORKEY ) {
00661             colorKey = srf.GetPixelFormat().colorkey();
00662             if ( pixelsize > 1 )
00663                mask = srf.GetPixelFormat().Rmask() | srf.GetPixelFormat().Gmask() | srf.GetPixelFormat().Bmask();
00664          } else
00665             if ( pixelsize == 1 )
00666                colorKey = 0xff;
00667             else
00668                colorKey = 0xfefefe00;
00669       };
00670 
00671       bool isOpaque( PixelType src )
00672       {
00673          return (src & mask ) != colorKey;
00674       }
00675 };
00676 
00677 
00678 template<>
00679 class ColorMerger_AlphaHandler<1>
00680 {
00681       typedef PixelSize2Type<1>::PixelType PixelType;
00682       int colorKey;
00683       int mask;
00684    protected:
00685       ColorMerger_AlphaHandler() : mask ( -1 )
00686       {}
00687       ;
00688 
00689       void init( const Surface& srf )
00690       {
00691          if ( srf.flags() & SDL_SRCCOLORKEY ) {
00692             colorKey = srf.GetPixelFormat().colorkey();
00693          } else
00694             colorKey = 0xff;
00695       };
00696 
00697       bool isOpaque( PixelType src )
00698       {
00699          return (src & mask ) != colorKey;
00700       }
00701 };
00702 
00703 template<>
00704 class ColorMerger_AlphaHandler<4>
00705 {
00706       typedef PixelSize2Type<4>::PixelType PixelType;
00707    protected:
00708       int amask, ashift;
00709       PixelType colorKey;
00710       bool hasColorKey;
00711       int ckmask;
00712    protected:
00713       ColorMerger_AlphaHandler() : amask ( -1 ), ashift(0), colorKey(0), hasColorKey(false), ckmask(0)
00714       {}
00715       ;
00716 
00717       void init( const Surface& srf )
00718       {
00719          if ( srf.flags() & SDL_SRCCOLORKEY ) {
00720             hasColorKey = true;
00721             colorKey = srf.GetPixelFormat().colorkey();
00722             ckmask = srf.GetPixelFormat().Rmask() | srf.GetPixelFormat().Gmask() | srf.GetPixelFormat().Bmask();
00723          } else {
00724             if ( srf.GetPixelFormat().Amask() ) {
00725                amask = srf.GetPixelFormat().Amask();
00726                ashift = srf.GetPixelFormat().Ashift();
00727             } else {
00728                amask = ~( srf.GetPixelFormat().Rmask() | srf.GetPixelFormat().Gmask() | srf.GetPixelFormat().Bmask() );
00729                ashift = firstBit(amask);
00730             }
00731          }
00732       };
00733 
00734       bool isOpaque( PixelType src )
00735       {
00736          if ( hasColorKey )
00737             return (src & ckmask) != colorKey;
00738          else
00739             return PixelType((src & amask ) >> ashift) >= 128;
00740       };
00741 };
00742 
00743 
00744 template<int pixelsize>
00745 class ColorMerger_AlphaOverwrite : public ColorMerger_AlphaHandler<pixelsize>
00746 {
00747       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00748    protected:
00749 
00750       void assign ( PixelType src, PixelType* dest )
00751       {
00752          if ( isOpaque(src ) ) {
00753             *dest = src;
00754          }
00755       };
00756 
00757    public:
00758       ColorMerger_AlphaOverwrite( NullParamType npt = nullParam )
00759       {}
00760       ;
00761 };
00762 
00763 
00764 template<int pixelsize>
00765 class ColorMerger_AlphaMerge : public ColorMerger_AlphaHandler<pixelsize>
00766 {
00767       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00768    protected:
00769 
00770       void assign ( PixelType src, PixelType* dest )
00771       {
00772          if ( isOpaque(src ) ) {
00773             *dest = src;
00774          }
00775       };
00776 
00777    public:
00778       ColorMerger_AlphaMerge( NullParamType npt = nullParam )
00779       {}
00780       ;
00781 };
00782 
00783 template<>
00784 class ColorMerger_AlphaMerge<4> : public ColorMerger_AlphaHandler<4>
00785 {
00786       typedef  PixelSize2Type<4>::PixelType PixelType;
00787    protected:
00788 
00789       void assign ( PixelType src, PixelType* dest )
00790       {
00791          if ( hasColorKey ) {
00792             if ( (src & ckmask) != colorKey )
00793                *dest = src;
00794          } else {
00795             PixelType alpha = PixelType((src & amask ) >> ashift);
00796             if ( alpha == PixelType(Surface::opaque))
00797                *dest = src;
00798             else
00799                if ( alpha != PixelType(Surface::transparent)) {
00800                   // copied from SDL
00801 
00802                   /*
00803                    * take out the middle component (green), and process
00804                    * the other two in parallel. One multiply less.
00805                    */
00806                   PixelType d = *dest;
00807                   PixelType dalpha = d & 0xff000000;
00808                   PixelType s1 = src & 0xff00ff;
00809                   PixelType d1 = d & 0xff00ff;
00810                   d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff;
00811                   src &= 0xff00;
00812                   d &= 0xff00;
00813                   d = (d + ((src - d) * alpha >> 8)) & 0xff00;
00814                   *dest = d1 | d | dalpha;
00815                }
00816 
00817          }
00818       };
00819 
00820    public:
00821       ColorMerger_AlphaMerge( NullParamType npt = nullParam )
00822       {}
00823       ;
00824 };
00825 
00826 
00827 
00828 
00829 template<int pixelsize>
00830 class ColorMerger_AlphaShadow
00831    {}
00832 ;
00833 
00834 
00835 template<>
00836 class ColorMerger_AlphaShadow<1> : public ColorMerger_AlphaHandler<1>
00837 {
00838       typedef PixelSize2Type<1>::PixelType PixelType;
00839       const char* table;
00840    protected:
00841 
00842       void assign ( PixelType src, PixelType* dest )
00843       {
00844          // STATIC_CHECK ( pixelsize == 1, wrong_pixel_size );
00845          if ( isOpaque(src ) ) {
00846             *dest = table[*dest];
00847          }
00848       };
00849    public:
00850       ColorMerger_AlphaShadow ( NullParamType npt = nullParam) : table ( xlattables.a.dark1 )
00851       {}
00852       ;
00853       ColorMerger_AlphaShadow ( const char* translationTable ) : table ( translationTable )
00854       {}
00855       ;
00856 };
00857 
00858 template<>
00859 class ColorMerger_AlphaShadow<4> : public ColorMerger_AlphaHandler<4>
00860 {
00861       typedef PixelSize2Type<4>::PixelType PixelType;
00862    protected:
00863 
00864       void init( const Surface& srf )
00865       {
00866          ColorMerger_AlphaHandler<4>::init(srf);
00867       };
00868 
00869 
00870       void assign ( PixelType src, PixelType* dest )
00871       {
00872          if ( isOpaque(src ) ) {
00873             *dest = ((*dest >> 1) & 0x7f7f7f7f) | (*dest & 0xff000000 );
00874          }
00875       };
00876    public:
00877       ColorMerger_AlphaShadow ( NullParamType npt = nullParam)
00878       {}
00879       ;
00880       ColorMerger_AlphaShadow ( const char* translationTable )
00881       {}
00882       ;
00883 };
00884 
00885 
00886 
00887 template<int pixelsize>
00888 class ColorMerger_AlphaMixer
00889    {}
00890 ;
00891 
00892 
00893 template<>
00894 class ColorMerger_AlphaMixer<1> : public ColorMerger_AlphaHandler<1>
00895 {
00896       typedef  PixelSize2Type<1>::PixelType PixelType;
00897    protected:
00898       void assign ( PixelType src, PixelType* dest )
00899       {
00900          if ( isOpaque(src ) )
00901             *dest = colormixbufchar[*dest + src*256 ];
00902       };
00903    public:
00904       ColorMerger_AlphaMixer ( NullParamType npt = nullParam )
00905    {}
00906       ;
00907 };
00908 
00909 template<>
00910 class ColorMerger_AlphaMixer<4> : public ColorMerger_AlphaHandler<4>
00911 {
00912       typedef  PixelSize2Type<4>::PixelType PixelType;
00913    protected:
00914       void assign ( PixelType src, PixelType* dest )
00915       {
00916          // STATIC_CHECK ( pixelsize == 1, wrong_pixel_size );
00917          if ( isOpaque(src ) ) {
00918             *dest = ((*dest >> 1) & 0x7f7f7f7f) + ((src >> 1) & 0x7f7f7f7f);
00919          }
00920       };
00921    public:
00922       ColorMerger_AlphaMixer ( NullParamType npt = nullParam )
00923       {}
00924       ;
00925 };
00926 
00927 
00928 
00929 extern const int ColorMerger_Alpha_XLAT_Table_shadings[8]; 
00930 
00931 template<int pixelsize>
00932 class ColorMerger_Alpha_XLAT_TableShifter : public ColorMerger_AlphaHandler<pixelsize>
00933 {
00934       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00935       const char* table;
00936    protected:
00937       void assign ( PixelType src, PixelType* dest )
00938       {
00939          if ( src == 0 || src >= 8 )
00940             return;
00941 
00942          *dest = lighten_Color( *dest, ColorMerger_Alpha_XLAT_Table_shadings[src] );
00943          /*
00944                      // STATIC_CHECK ( pixelsize == 1, wrong_pixel_size );
00945                      if ( isOpaque(src ) ) {
00946                         *dest = table[ *dest + src*256 ];
00947                      }
00948                      */
00949       };
00950 
00951    public:
00952       void setNeutralTranslationTable( const char* translationTable )
00953       {
00954          table = translationTable;
00955       };
00956 
00957       ColorMerger_Alpha_XLAT_TableShifter( NullParamType npt = nullParam ) : table ( NULL )
00958       {}
00959       ;
00960       ColorMerger_Alpha_XLAT_TableShifter ( const char* translationTable ) : table ( translationTable )
00961       {}
00962       ;
00963 };
00964 
00965 template<>
00966 class ColorMerger_Alpha_XLAT_TableShifter<1> : public ColorMerger_AlphaHandler<1>
00967 {
00968       typedef PixelSize2Type<1>::PixelType PixelType;
00969       const char* table;
00970    protected:
00971       void assign ( PixelType src, PixelType* dest )
00972       {
00973          // STATIC_CHECK ( pixelsize == 1, wrong_pixel_size );
00974          if ( isOpaque(src ) ) {
00975             *dest = table[ *dest + src*256 ];
00976          }
00977       };
00978 
00979    public:
00980       void setNeutralTranslationTable( const char* translationTable )
00981       {
00982          table = translationTable;
00983       };
00984 
00985       ColorMerger_Alpha_XLAT_TableShifter( NullParamType npt = nullParam ) : table ( NULL )
00986       {}
00987       ;
00988       ColorMerger_Alpha_XLAT_TableShifter ( const char* translationTable ) : table ( translationTable )
00989       {}
00990       ;
00991 };
00992 
00993 
00994 template<int pixelsize>
00995 class ColorMerger_Brightness
00996 {
00997       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
00998       float b;
00999    public:
01000 
01001       void assign ( PixelType src, PixelType* dest ) const
01002       {
01003          PixelType d = 0;
01004          for ( int i = 0; i < 3; ++i)
01005             d |= min( max( int( float(((*dest) >> (i*8)) & 0xff) * b ), 0 ), 255) << (i*8);
01006          d |= (*dest & 0xff000000);
01007 
01008          *dest = d;
01009       };
01010 
01011       ColorMerger_Brightness( float brightness )
01012       {
01013          b = brightness;
01014       };
01015 };
01016 
01017 
01018 template<int pixelsize>
01019 class ColorMerger_Set
01020 {
01021       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01022       SDLmm::Color col;
01023    public:
01024 
01025       void assign ( PixelType src, PixelType* dest ) const
01026       {
01027          *dest = col;
01028       };
01029 
01030      
01031       ColorMerger_Set( SDLmm::Color color )
01032       {
01033          col = color;
01034       };
01035 };
01036 
01037 
01039 
01040 
01041 
01042 template<int pixelsize, class SourcePixelSelector = SourcePixelSelector_Plain<pixelsize> >
01043 class SourcePixelSelector_Rotation: public SourcePixelSelector
01044 {
01045       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01046       int degrees;
01047       int x,y;
01048       int w,h;
01049    protected:
01050 
01051       void init ( const Surface& srv )
01052       {
01053          SourcePixelSelector::init(srv);
01054          w = SourcePixelSelector::getWidth();
01055          h = SourcePixelSelector::getHeight();
01056       };
01057 
01058 
01059       PixelType getPixel(int x, int y)
01060       {
01061          SPoint newpos = ::getPixelRotationLocation( SPoint(x,y), w, h, degrees );
01062          return SourcePixelSelector::getPixel ( newpos.x, newpos.y );
01063       };
01064 
01065       PixelType nextPixel()
01066       {
01067          return getPixel(x++, y);
01068       };
01069 
01070       void skipPixels( int pixNum )
01071       {
01072          x += pixNum;
01073       };
01074 
01075       int getSourcePixelSkip()
01076       {
01077          return 0;
01078       };
01079 
01080       void nextLine()
01081       {
01082          x = 0;
01083          y +=1;
01084       };
01085 
01086    public:
01087       void setAngle( int degrees )
01088       {
01089          this->degrees = degrees;
01090       };
01091 
01092       SourcePixelSelector_Rotation( NullParamType npt = nullParam )  : degrees(0),x(0),y(0),w(0),h(0)
01093       {}
01094 
01095       SourcePixelSelector_Rotation( int degreesToRotate )  : degrees(degreesToRotate),x(0),y(0),w(0),h(0)
01096       {}
01097 };
01098 
01099 template<int pixelsize>
01100 class SourcePixelSelector_DirectRotation: public SourcePixelSelector_Rotation<pixelsize>
01101 {
01102    public:
01103       SourcePixelSelector_DirectRotation( NullParamType npt = nullParam )
01104       {}
01105       SourcePixelSelector_DirectRotation( int degreesToRotate )  : SourcePixelSelector_Rotation<pixelsize>(degreesToRotate)
01106       {}
01107 }
01108 ;
01109 
01110 
01111 
01112 class RotationCache
01113 {
01114    protected:
01115       static map<int,int*> cache;
01116       static int xsize;
01117       static int ysize;
01118 };
01119 
01120 template<int pixelsize>
01121 class SourcePixelSelector_CacheRotation : public RotationCache
01122 {
01123       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01124       const Surface* surface;
01125       int degrees;
01126       bool useCache;
01127       const PixelType* pixelStart;
01128       const PixelType* currentPixel;
01129       int tableIndex;
01130       int pitch;
01131       int* cacheIndex;
01132       int x,y,w,h;
01133    protected:
01134 
01135       void init ( const Surface& srv )
01136       {
01137          if ( !surface ) {
01138             surface = &srv;
01139          } else {
01140             assert ( surface == &srv );
01141          }
01142          tableIndex = 0;
01143          pixelStart = currentPixel = (PixelType*)surface->pixels();
01144          pitch = srv.pitch()/sizeof(PixelType) - srv.w();
01145          w = srv.w();
01146          h = srv.h();
01147       }
01148 
01149       PixelType nextPixel()
01150       {
01151          if ( useCache && degrees != 0 ) {
01152             ++currentPixel;
01153 
01154             assert ( cacheIndex );
01155             int index = cacheIndex[tableIndex++];
01156             if ( index >= 0 )
01157                return pixelStart[index];
01158             else
01159                return surface->GetPixelFormat().colorkey();
01160          } else {
01161             if ( degrees == 0 ) {
01162                ++tableIndex;
01163                return *(currentPixel++);
01164             } else {
01165                SPoint newpos = ::getPixelRotationLocation( SPoint(x++,y), w, h, degrees );
01166                return getSourcePixel ( newpos.x, newpos.y );
01167             }
01168          }
01169       };
01170 
01171       void skipPixels( int pixNum )
01172       {
01173          currentPixel += pixNum;
01174          tableIndex += pixNum;
01175          x += pixNum;
01176       };
01177 
01178       int getSourcePixelSkip()
01179       {
01180          return 0;
01181       };
01182 
01183       void nextLine()
01184       {
01185          currentPixel += pitch;
01186          ++y;
01187          x = 0;
01188       };
01189 
01190       int getWidth()
01191       {
01192          return surface->w();
01193       };
01194       int getHeight()
01195       {
01196          return surface->h();
01197       };
01198 
01199    private:
01200       PixelType getSourcePixel(int x, int y)
01201       {
01202          if ( x >= 0 && y >= 0 && x < surface->w() && y < surface->h() )
01203             return surface->GetPixel(SPoint(x,y));
01204          else
01205             return surface->GetPixelFormat().colorkey();
01206       };
01207 
01208 
01209    public:
01210       void setAngle( const Surface& srv, int degrees )
01211       {
01212          init ( srv );
01213 
01214          if ( xsize == -1 ) {
01215             xsize = surface->w();
01216             ysize = surface->h();
01217          }
01218 
01219          this->degrees = degrees;
01220          if ( degrees != 0 && surface->w() == xsize && surface->h() == ysize ) {
01221             useCache = true;
01222             if ( cache.find( degrees ) == cache.end() ) {
01223                int* index = new int[surface->w() * surface->h()];
01224                cache[degrees] = index;
01225                for ( int y = 0; y < surface->h(); ++y )
01226                   for ( int x = 0; x < surface->w(); ++x ) {
01227                      SPoint pnt = getPixelRotationLocation( SPoint(x,y), surface->w(),surface->h(), degrees );
01228                      if ( pnt.x >= 0 && pnt.y >= 0 && pnt.x < surface->w() && pnt.y < surface->h() )
01229                         *index++ = pnt.x + pnt.y * surface->pitch()/pixelsize;
01230                      else
01231                         *index++ = -1;
01232                   }
01233             }
01234             cacheIndex = cache[degrees];
01235          }
01236       }
01237 
01238       SourcePixelSelector_CacheRotation( NullParamType npt = nullParam ) : surface(NULL), degrees(0), useCache(false),pixelStart(NULL), currentPixel(NULL),tableIndex(0),pitch(0), cacheIndex(NULL),x(0),y(0),w(0),h(0)
01239    {}
01240       ;
01241 
01242       SourcePixelSelector_CacheRotation( const Surface& srv, int degrees ) : surface(NULL), degrees(0), useCache(false),pixelStart(NULL), currentPixel(NULL),tableIndex(0),pitch(0), cacheIndex(NULL),x(0),y(0),w(0),h(0)
01243       {
01244          setAngle ( srv, degrees );
01245       };
01246 
01247       SourcePixelSelector_CacheRotation( pair<const Surface*, int> p ) : surface(NULL), degrees(0), useCache(false),pixelStart(NULL), currentPixel(NULL),tableIndex(0),pitch(0), cacheIndex(NULL),x(0),y(0),w(0),h(0)
01248       {
01249          setAngle ( *(p.first), p.second );
01250       };
01251 
01252 
01253 };
01254 
01255 
01256 template<int pixelsize, class SourcePixelSelector = SourcePixelSelector_Plain<pixelsize> >
01257 class SourcePixelSelector_Zoom: public SourcePixelSelector
01258 {
01259       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01260       float zoomFactorX;
01261       float zoomFactorY;
01262       int x,y;
01263    protected:
01264 
01265       int getWidth()
01266       {
01267          return int( zoomFactorX * SourcePixelSelector::getWidth()  );
01268       };
01269       int getHeight()
01270       {
01271          return int( zoomFactorY * SourcePixelSelector::getHeight() );
01272       };
01273 
01274       PixelType getPixel(int x, int y)
01275       {
01276          return SourcePixelSelector::getPixel( int(float(x) / zoomFactorX), int(float(y) / zoomFactorY));
01277       };
01278 
01279       PixelType nextPixel()
01280       {
01281          return getPixel(x++, y);
01282       };
01283 
01284       void skipPixels( int pixNum )
01285       {
01286          x += pixNum;
01287       };
01288 
01289       int getSourcePixelSkip()
01290       {
01291          return 0;
01292       };
01293       
01294       void nextLine()
01295       {
01296          x= 0;
01297          ++y;
01298       };
01299 
01300    public:
01301       void setZoom( float factor )
01302       {
01303          this->zoomFactorX = factor;
01304          this->zoomFactorY = factor;
01305       };
01306       void setZoom( float factorX, float factorY )
01307       {
01308          this->zoomFactorX = factorX;
01309          this->zoomFactorY = factorY;
01310       };
01311 
01312       float getZoomX()
01313       {
01314          return zoomFactorX;
01315       };
01316       float getZoomY()
01317       {
01318          return zoomFactorY;
01319       };
01320 
01321       void setSize( int sourceWidth, int sourceHeight, int targetWidth, int targetHeight, bool forceSquare = true )
01322       {
01323          float zw = float(targetWidth) / float(sourceWidth);
01324          float zh = float(targetHeight)/ float(sourceHeight);
01325          if ( forceSquare )
01326             setZoom( min ( zw,zh));
01327          else
01328             setZoom( zw,zh );
01329       };
01330 
01331       SourcePixelSelector_Zoom( NullParamType npt = nullParam) : zoomFactorX(1),zoomFactorY(1),x(0),y(0)
01332    {}
01333       ;
01334 
01335 };
01336 
01337 template<int pixelsize>
01338 class SourcePixelSelector_DirectZoom: public SourcePixelSelector_Zoom<pixelsize>
01339 {
01340    public:
01341       SourcePixelSelector_DirectZoom( NullParamType npt = nullParam)
01342       {}
01343       ;
01344 };
01345 
01346 
01347 class ZoomCache
01348 {
01349    protected:
01350       typedef map<float,int*> ZoomMap;
01351       static ZoomMap zoomCache;
01352 };
01353 
01354 
01355 template<int pixelsize, class SourcePixelSelector = SourcePixelSelector_Plain<pixelsize> >
01356 class SourcePixelSelector_CacheZoom : private ZoomCache, public SourcePixelSelector
01357 {
01358       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01359       const Surface* surface;
01360       float zoomFactor;
01361 
01362       int currSrcX;
01363       int currSrcY;
01364       int* xp;
01365       int* yp;
01366       int offsetx;
01367       int offsety;
01368       ZoomMap::iterator cacheit;
01369    protected:
01370 
01371       int getWidth()
01372       {
01373          return int( zoomFactor * SourcePixelSelector::getWidth()  );
01374       };
01375       int getHeight()
01376       {
01377          return int( zoomFactor * SourcePixelSelector::getHeight() );
01378       };
01379 
01380       PixelType getPixel(int x, int y)
01381       {
01382          return SourcePixelSelector::getPixel( int(float(x) / zoomFactor), int(float(y) / zoomFactor));
01383       };
01384 
01385       PixelType nextPixel()
01386       {
01387          for ( int i = 0; i < *xp; ++i )
01388             SourcePixelSelector::nextPixel();
01389          ++xp;
01390 
01391          return SourcePixelSelector::nextPixel();
01392       };
01393 
01394       void skipPixels( int pixNum )
01395       {
01396          int count = pixNum;
01397          for ( int i = 0; i < pixNum; ++i ) {
01398             count += *xp;
01399             ++xp;
01400          }
01401          SourcePixelSelector::skipPixels( count );
01402       };
01403 
01404       int getSourcePixelSkip()
01405       {
01406          int s = SourcePixelSelector::getSourcePixelSkip();
01407          if ( s ) {
01408             s = int(floor( float(s) * zoomFactor )) -2;  // to prevent rounding errors
01409             if ( s < 1 )
01410                return 1;
01411             else
01412                return s;
01413          } else
01414             return 0;
01415       };
01416 
01417       
01418       void nextLine()
01419       {
01420          SourcePixelSelector::nextLine();
01421          for ( int i = 0; i < *yp; ++i )
01422             SourcePixelSelector::skipWholeLine();
01423 
01424          xp = &cacheit->second[offsetx];
01425          yp++;
01426       };
01427 
01428 
01429    public:
01430 
01431       
01432       void setZoomOffset( int x, int y )
01433       {
01434          offsetx = x;
01435          offsety = y;
01436          /*
01437          for ( int i = 0; i < y; ++y )
01438             next
01439          */
01440       }
01441       
01442       
01443       void setZoom( float factor )
01444       {
01445          this->zoomFactor = factor;
01446          assert ( factor > 0 );
01447          assert ( factor <= 1 );
01448 
01449          cacheit = zoomCache.find( factor );
01450          if ( cacheit == zoomCache.end() ) {
01451             int size  = max ( SDLmm::Display::GetDisplay().w(), SDLmm::Display::GetDisplay().h() );
01452 
01453             int* buf = new int[size+1];
01454             buf[0] = 0;
01455 
01456             for ( int i = 0; i < size; ++i ) {
01457                int a1 =  int( floor( float(i) / zoomFactor ));
01458                int a2 =  int( floor( float(i+1) / zoomFactor ));
01459 
01460                buf[i+1] = a2 - a1 - 1;
01461             }
01462 
01463             zoomCache[zoomFactor] = buf;
01464             cacheit = zoomCache.find( factor );
01465          }
01466          xp = &cacheit->second[offsetx];
01467          yp = &cacheit->second[offsety];
01468       }
01469 
01470       SourcePixelSelector_CacheZoom( NullParamType npt = nullParam ) : surface(NULL), zoomFactor(1), xp(NULL), yp(NULL), offsetx(0), offsety(0)
01471       {
01472          cacheit = zoomCache.end();
01473       };
01474 
01475       SourcePixelSelector_CacheZoom( float zoom ) : surface(NULL), zoomFactor(1), xp(NULL), yp(NULL), offsetx(0), offsety(0)
01476       {
01477          cacheit = zoomCache.end();
01478          setZoom ( zoom );
01479       };
01480 
01481 
01482 };
01483 
01484 
01485 
01486 
01487 template<int pixelsize, class SourcePixelSelector = SourcePixelSelector_Plain<pixelsize> >
01488 class SourcePixelSelector_Flip: public SourcePixelSelector
01489 {
01490       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01491       bool hflip;
01492       bool vflip;
01493       int x,y;
01494       int w,h;
01495    protected:
01496 
01497       void init ( const Surface& srv )
01498       {
01499          SourcePixelSelector::init(srv);
01500          w = SourcePixelSelector::getWidth()-1;
01501          h = SourcePixelSelector::getHeight()-1;
01502       };
01503 
01504 
01505 
01506       PixelType getPixel(int x, int y)
01507       {
01508          return SourcePixelSelector::getPixel( hflip? w-x : x , vflip ? h-y : y );
01509       };
01510 
01511       PixelType nextPixel()
01512       {
01513          return getPixel(x++, y);
01514       };
01515 
01516       void skipPixels( int pixNum )
01517       {
01518          x += pixNum;
01519       };
01520       
01521       int getSourcePixelSkip()
01522       {
01523          return 0;
01524       };
01525 
01526       void nextLine()
01527       {
01528          x= 0;
01529          ++y;
01530       };
01531 
01532    public:
01533       void setFlipping( bool horizontal, bool vertical )
01534       {
01535          hflip = horizontal;
01536          vflip = vertical;
01537       };
01538 
01539       SourcePixelSelector_Flip( NullParamType npt = nullParam) : hflip(false),vflip(false),x(0),y(0),w(0),h(0)
01540       {}
01541       ;
01542 
01543       SourcePixelSelector_Flip( int flip) : hflip(flip&1),vflip(flip&2),x(0),y(0),w(0),h(0)
01544       {}
01545       ;
01546 
01547 };
01548 
01549 template<int pixelsize>
01550 class SourcePixelSelector_DirectFlip : public SourcePixelSelector_Flip<pixelsize>
01551 {
01552    public:
01553       SourcePixelSelector_DirectFlip( NullParamType npt = nullParam)
01554       {}
01555       ;
01556       SourcePixelSelector_DirectFlip( int flip) : SourcePixelSelector_Flip<pixelsize>(flip)
01557       {}
01558       ;
01559 };
01560 
01561 // template<int pixelsize, class SourcePixelSelector = SourcePixelSelector_Plain<pixelsize> > // MSVC7 fails to understand that...
01562 template<int pixelsize>
01563 class SourcePixelSelector_Rectangle: public SourcePixelSelector_Plain<pixelsize>
01564 {
01565       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01566       int x,y,x1,y1;
01567       int w,h;
01568    protected:
01569       SourcePixelSelector_Rectangle() : x(0),y(0),x1(0),y1(0),w(0),h(0)
01570       {}
01571       ;
01572 public:
01573 
01574       SourcePixelSelector_Rectangle( const SDLmm::SRect& rect ) : x(0),y(0),x1(0),y1(0),w(0),h(0)
01575       {
01576          setSrcRectangle( rect );
01577       }
01578 protected:
01579 
01580       int getWidth()
01581       {
01582          return min(w, SourcePixelSelector_Plain<pixelsize>::getWidth() -x1 );
01583       };
01584       int getHeight()
01585       {
01586          return min(h, SourcePixelSelector_Plain<pixelsize>::getHeight()-y1 );
01587       };
01588 
01589 
01590       PixelType getPixel(int x, int y)
01591       {
01592          return SourcePixelSelector_Plain<pixelsize>::getPixel( x + x1, y + y1 );
01593       };
01594 
01595       PixelType nextPixel()
01596       {
01597          return getPixel(x++, y);
01598       };
01599 
01600       void skipWholeLine()
01601       {
01602          ++y;
01603       };
01604 
01605       void skipPixels( int pixNum )
01606       {
01607          x += pixNum;
01608       };
01609 
01610       int getSourcePixelSkip()
01611       {
01612          return 0;
01613       };
01614       
01615       void nextLine()
01616       {
01617          x= 0;
01618          ++y;
01619       };
01620 
01621    public:
01622       void setSrcRectangle( SPoint pos, int width, int height )
01623       {
01624          x1 = pos.x;
01625          y1 = pos.y;
01626          w = width;
01627          h = height;
01628       };
01629       void setSrcRectangle( const SDLmm::SRect& rect )
01630       {
01631          x1 = rect.x;
01632          y1 = rect.y;
01633          w = rect.w;
01634          h = rect.h;
01635       };
01636 
01637 };
01638 
01639 template<int pixelsize>
01640 class SourcePixelSelector_DirectRectangle
01641 {
01642       typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01643       int y,x1,y1;
01644       int w,h;
01645 
01646       const PixelType* pointer;
01647       const PixelType* startPointer;
01648       int pitch;
01649       int linelength;
01650       const Surface* surface;
01651    protected:
01652       SourcePixelSelector_DirectRectangle() : y(0),x1(0),y1(0),w(0),h(0),pointer(NULL), surface(NULL)
01653       {}
01654       ;
01655 
01656       int getWidth()
01657       {
01658          return min(w, surface->w() -x1 );
01659       };
01660       int getHeight()
01661       {
01662          return min(h, surface->h()-y1 );
01663       };
01664 
01665 
01666       void init ( const Surface& srv )
01667       {
01668          surface = &srv;
01669          startPointer = pointer = (const PixelType*)(srv.pixels());
01670          linelength = srv.pitch()/sizeof(PixelType);
01671          pitch = linelength - w -1  ;
01672          y = y1;
01673          pointer += x1 + y1 * linelength;
01674       };
01675 
01676       PixelType getPixel(int x, int y)
01677       {
01678          x += x1;
01679          y += y1;
01680          if ( x >= 0 && y >= 0 && x < surface->w() && y < surface->h() )
01681             return surface->GetPixel(SPoint(x,y));
01682          else
01683             return surface->GetPixelFormat().colorkey();
01684       };
01685 
01686 
01687       PixelType nextPixel()
01688       {
01689          return *(pointer++);
01690       };
01691 
01692 
01693       void skipWholeLine()
01694       {
01695          pointer += linelength;
01696          ++y;
01697       };
01698 
01699       void skipPixels( int pixNum )
01700       {
01701          pointer += pixNum;
01702       };
01703 
01704       int