00001 #include "OSDLSurface.h"
00002
00003 #include "OSDLTypes.h"
00004 #include "OSDLVideo.h"
00005 #include "OSDLVideoTypes.h"
00006
00007 #include "OSDLVideoTypes.h"
00008 #include "OSDLUprightRectangle.h"
00009 #include "OSDLPoint2D.h"
00010 #include "OSDLLine.h"
00011 #include "OSDLFixedFont.h"
00012 #include "OSDLConic.h"
00013 #include "OSDLPixel.h"
00014 #include "OSDLPolygon.h"
00015 #include "OSDLWidget.h"
00016 #include "OSDLUtils.h"
00017
00018 #include "Ceylan.h"
00019
00020 #include "SDL_rotozoom.h"
00021
00022 #include <cassert>
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 using std::string ;
00035 using std::list ;
00036
00037 using namespace Ceylan ;
00038 using namespace Ceylan::Log ;
00039
00040 using namespace OSDL::Video ;
00041 using namespace OSDL::Video::TwoDimensional ;
00042
00043
00044 using TwoDimensional::UprightRectangle ;
00045
00046
00047 #ifdef OSDL_USES_CONFIG_H
00048 #include <OSDLConfig.h>
00049 #endif // OSDL_USES_CONFIG_H
00050
00051
00052
00053 SurfaceEvent::SurfaceEvent( Ceylan::EventSource & source ) throw() :
00054 Ceylan::Event( source )
00055 {
00056
00057 }
00058
00059
00060 SurfaceEvent::~SurfaceEvent() throw()
00061 {
00062
00063 }
00064
00065
00066
00067 VideoMemoryLostException::VideoMemoryLostException(
00068 const std::string & message ) throw() :
00069 VideoException( message )
00070 {
00071
00072 }
00073
00074
00075 VideoMemoryLostException::VideoMemoryLostException() throw() :
00076 VideoException( "Video memory lost, content needs to be reblitted" )
00077 {
00078
00079 }
00080
00081
00082 VideoMemoryLostException::~VideoMemoryLostException() throw()
00083 {
00084
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 const Ceylan::Flags Surface::Software = SDL_SWSURFACE ;
00097 const Ceylan::Flags Surface::Hardware = SDL_HWSURFACE ;
00098 const Ceylan::Flags Surface::AsynchronousBlit = SDL_ASYNCBLIT ;
00099 const Ceylan::Flags Surface::ExclusivePalette = SDL_HWPALETTE ;
00100 const Ceylan::Flags Surface::HardwareAcceleratedBlit = SDL_HWACCEL ;
00101 const Ceylan::Flags Surface::ColorkeyBlit = SDL_SRCCOLORKEY ;
00102 const Ceylan::Flags Surface::RLEColorkeyBlit = SDL_RLEACCEL ;
00103 const Ceylan::Flags Surface::AlphaBlendingBlit = SDL_SRCALPHA ;
00104 const Ceylan::Flags Surface::Preallocated = SDL_PREALLOC ;
00105
00106
00107
00108 const Ceylan::Flags Surface::RLEColorkeyBlitAvailable = SDL_RLEACCELOK ;
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 const Ceylan::Flags Surface::AnyPixelFormat = SDL_ANYFORMAT ;
00119 const Ceylan::Flags Surface::DoubleBuffered = SDL_DOUBLEBUF ;
00120 const Ceylan::Flags Surface::FullScreen = SDL_FULLSCREEN ;
00121 const Ceylan::Flags Surface::OpenGL = SDL_OPENGL ;
00122 const Ceylan::Flags Surface::Resizable = SDL_RESIZABLE ;
00123
00124
00125 const Length Surface::graphAbscissaOffset = 10 ;
00126 const Length Surface::graphOrdinateOffset = 15 ;
00127
00128 const Length Surface::captionAbscissaOffset = 5 ;
00129 const Length Surface::captionOrdinateOffset = 10 ;
00130
00131
00132
00133 #ifdef OSDL_COUNT_INSTANCES
00134
00135 #define CHECKPOINT(message) Ceylan::checkpoint( message )
00136
00137 #else // OSDL_COUNT_INSTANCES
00138
00139 #define CHECKPOINT(message)
00140
00141 #endif // OSDL_COUNT_INSTANCES
00142
00143
00144 Surface::Surface( SDL_Surface & surface, DisplayType displayType ) throw() :
00145 UprightRectangle( 0, 0, 0, 0 ),
00146 EventSource(),
00147 Lockable(),
00148 _surface( & surface ),
00149 _displayType( displayType ),
00150 _mustBeLocked( false ),
00151 _needsRedraw( true )
00152 {
00153
00154 #if OSDL_DEBUG_WIDGET
00155
00156 CHECKPOINT( "Surface constructor from SDL surface." ) ;
00157
00158 LogPlug::trace( "Surface constructor from SDL surface." ) ;
00159
00160 #endif // OSDL_DEBUG_WIDGET
00161
00162 }
00163
00164
00165 Surface::Surface( Flags flags, Length width, Length height, BitsPerPixel depth,
00166 Pixels::ColorMask redMask, Pixels::ColorMask greenMask,
00167 Pixels::ColorMask blueMask, Pixels::ColorMask alphaMask )
00168 throw( VideoException ) :
00169 UprightRectangle( 0, 0,
00170 0, 0 ),
00171 EventSource(),
00172 Lockable(),
00173 _surface( 0 ),
00174 _displayType( BackBuffer ),
00175 _mustBeLocked( false ),
00176 _needsRedraw( true )
00177 {
00178
00179
00180 #if OSDL_DEBUG_WIDGET
00181
00182 CHECKPOINT( "Surface constructor with full flags." ) ;
00183
00184 LogPlug::trace( "Surface constructor with flags = "
00185 + Ceylan::toString( flags, true )
00186 + ", with width = " + Ceylan::toString( width )
00187 + ", with height = " + Ceylan::toString( height )
00188 + ", with color depth = " + Ceylan::toNumericalString( depth )
00189 + ", with specified red mask = " + Ceylan::toHexString( redMask )
00190 + ", with specified green mask = " + Ceylan::toHexString( greenMask )
00191 + ", with specified blue mask = " + Ceylan::toHexString( blueMask )
00192 + ", with specified alpha mask = " + Ceylan::toHexString( alphaMask )
00193 + "." ) ;
00194
00195 #endif // OSDL_DEBUG_WIDGET
00196
00197
00198 if ( alphaMask != 0 )
00199 {
00200 flags |= AlphaBlendingBlit ;
00201
00202 }
00203 else
00204 {
00205
00206
00207
00208
00209
00210
00211
00212
00213 if ( redMask == 0 && greenMask == 0 && blueMask == 0 )
00214 Pixels::getRecommendedColorMasks( redMask, greenMask,
00215 blueMask, alphaMask ) ;
00216
00217 }
00218
00219 #if OSDL_DEBUG_WIDGET
00220
00221 LogPlug::trace( "Surface constructor : actual surface flags are "
00222 + Ceylan::toString( flags, true )
00223 + ", red mask is " + Ceylan::toHexString( redMask )
00224 + ", green mask is " + Ceylan::toHexString( greenMask )
00225 + ", blue mask is " + Ceylan::toHexString( blueMask )
00226 + ", alpha mask is " + Ceylan::toHexString( alphaMask ) ) ;
00227
00228 #endif // OSDL_DEBUG_WIDGET
00229
00230 _surface = SDL_CreateRGBSurface( flags, width, height, depth,
00231 redMask, greenMask, blueMask, alphaMask ) ;
00232
00233 if ( _surface == 0 )
00234 throw VideoException( "Blank surface constructor failed (width = "
00235 + Ceylan::toString( width )
00236 + ", height = " + Ceylan::toString( height ) + ") : "
00237 + Utils::getBackendLastError() ) ;
00238
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 Surface::Surface() throw() :
00249 UprightRectangle( 0, 0, 0, 0 ),
00250 EventSource(),
00251 _surface( 0 ),
00252 _displayType( BackBuffer ),
00253 _mustBeLocked( false ),
00254 _needsRedraw( true )
00255 {
00256
00257
00258
00259
00260 #if OSDL_DEBUG_WIDGET
00261 CHECKPOINT( "Empty Surface constructor." ) ;
00262 LogPlug::trace( "Empty Surface constructor." ) ;
00263 #endif // OSDL_DEBUG_WIDGET
00264
00265 }
00266
00267
00268 Surface::~Surface() throw()
00269 {
00270
00271 #if OSDL_DEBUG_WIDGET
00272
00273 CHECKPOINT( "Surface destructor." ) ;
00274 LogPlug::trace( "Surface destructor, "
00275 + Ceylan::toString( _listeners.size() ) + " widget(s) registered." ) ;
00276
00277 #endif // OSDL_DEBUG_WIDGET
00278
00279 Ceylan::EventListener * widget ;
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 while ( ! _listeners.empty() )
00291 {
00292
00293 widget = _listeners.back() ;
00294 widget->unsubscribeFrom( *this ) ;
00295
00296
00297
00298
00299
00300
00301
00302 delete widget ;
00303
00304 }
00305
00306
00307 _listeners.clear() ;
00308
00309
00310 if ( _displayType == BackBuffer )
00311 flush() ;
00312
00313 }
00314
00315
00316 Clonable & Surface::clone() const throw( ClonableException )
00317 {
00318
00319
00320 if ( _surface != 0 )
00321 {
00322
00323 #ifdef OSDL_USE_DEPRECATED_CLONING
00324
00325
00326
00327
00328 Pixels::ColorMask redMask, greenMask, blueMask, alphaMask ;
00329 Pixels::getCurrentColorMasks( getPixelFormat(),
00330 redMask, greenMask, blueMask, alphaMask ) ;
00331
00332
00333 SDL_Surface * copied = SDL_CreateRGBSurface( getFlags(),
00334 getWidth(), getHeight(), getBitsPerPixel(),
00335 redMask, greenMask, blueMask, alphaMask ) ;
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 int returned = SDL_BlitSurface( _surface, 0, copied, 0 ) ;
00347 if ( returned != 0 )
00348 throw ClonableException( "Surface::clone : blit failed (returned "
00349 + Ceylan::toString( returned ) + ") : "
00350 + Utils::getBackendLastError() + "." ) ;
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 #endif // OSDL_USE_DEPRECATED_CLONING
00362
00363
00364
00365 SDL_Surface * copied = SDL_ConvertSurface( _surface,
00366 & getPixelFormat(), getFlags() ) ;
00367
00368
00369 if ( copied == 0 )
00370 throw ClonableException(
00371 "Surface::clone : creation of clone surface failed : "
00372 + Utils::getBackendLastError() + "." ) ;
00373
00374 return * new Surface( * copied,
00375 BackBuffer ) ;
00376
00377 }
00378 else
00379 {
00380 LogPlug::warning( "Surface::clone : cloning a mostly blank surface." ) ;
00381 return * new Surface() ;
00382 }
00383
00384 }
00385
00386
00387 SDL_Surface & Surface::getSDLSurface() const throw()
00388 {
00389
00390
00391 return * _surface ;
00392
00393 }
00394
00395
00396 void Surface::setSDLSurface( SDL_Surface & newSurface,
00397 DisplayType displayType ) throw()
00398 {
00399
00400
00401 flush() ;
00402
00403 _surface = & newSurface ;
00404 _displayType = displayType ;
00405
00406 }
00407
00408
00409 Surface::DisplayType Surface::getDisplayType() const throw()
00410 {
00411
00412 return _displayType ;
00413
00414 }
00415
00416
00417 void Surface::setDisplayType( DisplayType newDisplayType ) throw()
00418 {
00419
00420 _displayType = newDisplayType ;
00421
00422 }
00423
00424
00425 Ceylan::Flags Surface::getFlags() const throw()
00426 {
00427
00428 return _surface->flags ;
00429
00430 }
00431
00432
00433 void Surface::setFlags( Flags newFlags ) throw()
00434 {
00435
00436
00437 _surface->flags = newFlags ;
00438
00439 }
00440
00441
00442 void Surface::convertToDisplay( bool alphaChannelWanted )
00443 throw( VideoException )
00444 {
00445
00446 if ( _surface == 0 )
00447 throw VideoException(
00448 "Surface::convertToDisplay : no available internal surface." ) ;
00449
00450 SDL_Surface * old = _surface ;
00451
00452 if ( alphaChannelWanted )
00453 _surface = SDL_DisplayFormatAlpha( old ) ;
00454 else
00455 _surface = SDL_DisplayFormat( old ) ;
00456
00457 SDL_FreeSurface( old ) ;
00458
00459 if ( _surface == 0 )
00460 throw VideoException(
00461 "Surface::convertToDisplay : conversion failed." ) ;
00462
00463 }
00464
00465
00466 void Surface::setAlpha( Flags flags, Pixels::ColorElement newAlpha )
00467 throw( VideoException )
00468 {
00469
00470 if ( SDL_SetAlpha( _surface, flags, newAlpha ) != 0 )
00471 throw VideoException( "Surface::setAlpha failed : "
00472 + Utils::getBackendLastError() ) ;
00473
00474 }
00475
00476
00477 void Surface::setColorKey( Flags flags, Pixels::PixelColor keyPixelColor )
00478 throw( VideoException )
00479 {
00480
00481 if ( SDL_SetColorKey( _surface, flags, keyPixelColor ) != 0 )
00482 throw VideoException( "Surface::setColorKey (pixel color) failed : "
00483 + Utils::getBackendLastError() ) ;
00484
00485 }
00486
00487
00488 void Surface::setColorKey( Flags flags, Pixels::ColorDefinition keyColorDef )
00489 throw( VideoException )
00490 {
00491
00492 Pixels::PixelColor keyPixelColor =
00493 Pixels::convertColorDefinitionToPixelColor( getPixelFormat(),
00494 keyColorDef ) ;
00495
00496 if ( SDL_SetColorKey( _surface, flags, keyPixelColor ) != 0 )
00497 throw VideoException(
00498 "Surface::setColorKey (color definition) failed : "
00499 + Utils::getBackendLastError() ) ;
00500
00501 }
00502
00503
00504 void Surface::convertFromColorKeyToAlphaChannel() throw( VideoException )
00505 {
00506
00507 if ( ( getFlags() & ColorkeyBlit ) == 0 )
00508 throw VideoException( "Surface::convertFromColorKeyToAlphaChannel : "
00509 "this surface does not use color key apparently : "
00510 + toString( Ceylan::low ) ) ;
00511
00512 convertToDisplay( true ) ;
00513
00514 }
00515
00516
00517 bool Surface::setPalette( Palette & newPalette, ColorCount startingColorIndex,
00518 ColorCount numberOfColors, Flags targettedPalettes ) throw()
00519 {
00520
00521 if ( numberOfColors == 0 )
00522 {
00523
00524 if ( newPalette.getNumberOfColors() > startingColorIndex )
00525 {
00526 numberOfColors =
00527 newPalette.getNumberOfColors() - startingColorIndex ;
00528 }
00529 else
00530 {
00531 LogPlug::error(
00532 "Surface::setPalette : starting index out of bounds." );
00533 return false ;
00534 }
00535
00536 }
00537 else if ( startingColorIndex + numberOfColors >
00538 newPalette.getNumberOfColors() )
00539 {
00540 LogPlug::error(
00541 "Surface::setPalette : too many color indexes, out of bounds." );
00542 return false ;
00543 }
00544
00545 return static_cast<bool>( SDL_SetPalette( _surface, targettedPalettes,
00546 newPalette.getColorDefinitions(), startingColorIndex,
00547 numberOfColors ) ) ;
00548
00549 }
00550
00551
00552 Pixels::PixelFormat & Surface::getPixelFormat() const throw()
00553 {
00554
00555 if ( _surface->format == 0 )
00556 Ceylan::emergencyShutdown( "Surface::getPixelFormat called "
00557 "whereas no pixel format available." ) ;
00558
00559 return * _surface->format ;
00560
00561 }
00562
00563
00564 void Surface::setPixelFormat( Pixels::PixelFormat & newFormat ) throw()
00565 {
00566 _surface->format = & newFormat ;
00567 }
00568
00569
00570 bool Surface::fill( Pixels::ColorDefinition colorDef ) throw()
00571 {
00572
00573 #if OSDL_DEBUG_SURFACE
00574
00575 LogPlug::trace( "Surface::fill in rectangular area from ["
00576 + Ceylan::toString( _x ) + ";"
00577 + Ceylan::toString( _y ) + "] to ["
00578 + Ceylan::toString( _x + getWidth() ) + ";"
00579 + Ceylan::toString( _y + getHeight() ) + "]" ) ;
00580
00581 #endif // OSDL_DEBUG_SURFACE
00582
00583
00584 return drawBox( *this,
00585 colorDef, true ) ;
00586
00587 }
00588
00589
00590 bool Surface::clear() throw()
00591 {
00592
00593 return fill( Pixels::Black ) ;
00594
00595 }
00596
00597
00598 Surface & Surface::flipVertical() const throw()
00599 {
00600
00601 SDL_Surface * result = SDL_CreateRGBSurface(
00602 _surface->flags,
00603 _surface->w,
00604 _surface->h,
00605 _surface->format->BytesPerPixel * 8,
00606 _surface->format->Rmask,
00607 _surface->format->Gmask,
00608 _surface->format->Bmask,
00609 _surface->format->Amask ) ;
00610
00611 BytesPerPixel bpp = _surface->format->BytesPerPixel ;
00612
00613 Ceylan::Uint16 scanline = _surface->pitch ;
00614
00615 Ceylan::Uint8 * src =
00616 reinterpret_cast<Ceylan::Uint8 *>( _surface->pixels ) ;
00617
00618 Ceylan::Uint8 * target =
00619 reinterpret_cast<Ceylan::Uint8 *>( result->pixels ) + scanline - bpp ;
00620
00621 const Coordinate height = result->h ;
00622 const Coordinate width = result->w ;
00623
00624
00625
00626
00627
00628
00629
00630 for ( Coordinate y = 0; y < height; y++ )
00631 for ( Coordinate x = 0; x < width; x++ )
00632 ::memcpy( target + ( ( scanline * y ) - ( x * bpp ) ),
00633 src + ( ( scanline * y ) + ( x * bpp ) ), bpp ) ;
00634
00635 return * new Surface( * result ) ;
00636
00637 }
00638
00639
00640 Surface & Surface::flipHorizontal() const throw()
00641 {
00642
00643 SDL_Surface * result = SDL_CreateRGBSurface(
00644 _surface->flags,
00645 _surface->w,
00646 _surface->h,
00647 _surface->format->BytesPerPixel * 8,
00648 _surface->format->Rmask,
00649 _surface->format->Gmask,
00650 _surface->format->Bmask,
00651 _surface->format->Amask ) ;
00652
00653 Ceylan::Uint16 scanline = _surface->pitch ;
00654
00655 Ceylan::Uint8 * src =
00656 reinterpret_cast<Ceylan::Uint8 *>( _surface->pixels ) ;
00657
00658 Ceylan::Uint8 * target =
00659 reinterpret_cast<Ceylan::Uint8 *>( result->pixels )
00660 + result->pitch * ( result->h - 1 ) ;
00661
00662 const Coordinate height = result->h ;
00663
00664
00665
00666 for ( Coordinate y = 0; y < height; y++ )
00667 ::memcpy ( target - ( scanline * y ),
00668 src + ( scanline * y ), scanline ) ;
00669
00670 return * new Surface( * result ) ;
00671
00672 }
00673
00674
00675 string Surface::describePixelAt( Coordinate x, Coordinate y ) throw()
00676 {
00677
00678 string res = "Pixel at [" + Ceylan::toString( x ) + ";"
00679 + Ceylan::toString( y ) + "] : " ;
00680
00681 lock() ;
00682 PixelColor p = getPixelColorAt( x, y ) ;
00683 unlock() ;
00684
00685 res += "pixel color is " + Ceylan::toHexString( p ) + " : " ;
00686
00687 return res + Pixels::toString( p, getPixelFormat() ) ;
00688
00689 }
00690
00691
00692 Pitch Surface::getPitch() const throw()
00693 {
00694
00695 return _surface->pitch ;
00696
00697 }
00698
00699
00700 void Surface::setPitch( Pitch newPitch ) throw()
00701 {
00702
00703 _surface->pitch = newPitch ;
00704
00705 }
00706
00707
00708 Length Surface::getWidth() const throw()
00709 {
00710
00711 return _surface->w ;
00712
00713 }
00714
00715
00716 void Surface::setWidth( Length newWidth ) throw()
00717 {
00718
00719 resize( newWidth, getHeight() ) ;
00720
00721 }
00722
00723
00724 Length Surface::getHeight() const throw()
00725 {
00726
00727 return _surface->h ;
00728 }
00729
00730
00731
00732 void Surface::setHeight( Length newHeight ) throw()
00733 {
00734
00735 resize( getWidth(), newHeight ) ;
00736
00737 }
00738
00739
00740 void Surface::resize( Length newWidth, Length newHeight, bool scaleContent )
00741 throw()
00742 {
00743
00744 if ( ( newWidth == getWidth() ) && ( newHeight == getHeight() ) )
00745 return ;
00746
00747
00748 Pixels::ColorMask redMask, greenMask, blueMask, alphaMask ;
00749
00750 Pixels::getCurrentColorMasks( getPixelFormat(),
00751 redMask, greenMask, blueMask, alphaMask ) ;
00752
00753
00754 SDL_Surface * resized = SDL_CreateRGBSurface( getFlags(),
00755 newWidth, newHeight, getBitsPerPixel(),
00756 redMask, greenMask, blueMask, alphaMask ) ;
00757
00758
00759 if ( resized == 0 )
00760 Ceylan::emergencyShutdown(
00761 "Surface::resize : creation of newer internal surface failed : "
00762 + Utils::getBackendLastError() ) ;
00763
00764
00765
00766 Flags colorKeyFlags = getFlags() & ( ColorkeyBlit | RLEColorkeyBlit ) ;
00767 Pixels::PixelColor colorkey = _surface->format->colorkey ;
00768
00769
00770 resized->format->alpha = _surface->format->alpha ;
00771
00772
00773
00774 Surface * zoomed ;
00775
00776 if ( scaleContent )
00777 {
00778
00779 try
00780 {
00781
00782 zoomed = & zoom(
00783 static_cast<Ceylan::Maths::Real>( newWidth ) / getWidth(),
00784 static_cast<Ceylan::Maths::Real>( newHeight ) / getHeight(),
00785 VideoModule::GetAntiAliasingState() ) ;
00786
00787 }
00788 catch( const VideoException & e )
00789 {
00790 Ceylan::emergencyShutdown(
00791 "Surface::resize : creation of scaled surface failed : "
00792 + e.toString() ) ;
00793 }
00794
00795 }
00796
00797 SDL_FreeSurface( _surface ) ;
00798
00799 _surface = resized ;
00800
00801 setColorKey( colorKeyFlags, colorkey ) ;
00802
00803 if ( scaleContent )
00804 {
00805
00806 try
00807 {
00808
00809 zoomed->blitTo( * this ) ;
00810 delete zoomed ;
00811
00812 }
00813 catch( const VideoException & e )
00814 {
00815 Ceylan::emergencyShutdown(
00816 "Surface::resize : blit of scaled surface failed : "
00817 + e.toString() ) ;
00818 }
00819
00820 }
00821 else
00822 {
00823 setRedrawState( true ) ;
00824 }
00825
00826
00827 }
00828
00829
00830 BitsPerPixel Surface::getBitsPerPixel() const throw()
00831 {
00832
00833 return _surface->format->BitsPerPixel ;
00834
00835 }
00836
00837
00838 void Surface::setBitsPerPixel( BitsPerPixel newBitsPerPixel ) throw()
00839 {
00840
00841 _surface->format->BitsPerPixel = newBitsPerPixel ;
00842
00843
00844
00845 }
00846
00847
00848 BytesPerPixel Surface::getBytesPerPixel() const throw()
00849 {
00850
00851 return _surface->format->BytesPerPixel ;
00852
00853 }
00854
00855
00856 void Surface::setBytesPerPixel( BytesPerPixel newBytesPerPixel ) throw()
00857 {
00858
00859 _surface->format->BytesPerPixel = newBytesPerPixel ;
00860
00861
00862
00863 }
00864
00865
00866 void * Surface::getPixels() const throw()
00867 {
00868
00869 return _surface->pixels ;
00870
00871 }
00872
00873
00874
00875 void Surface::setPixels( void * newPixels ) throw()
00876 {
00877
00878 _surface->pixels = newPixels ;
00879
00880 }
00881
00882
00883
00884
00885
00886
00887
00888 Pixels::PixelColor Surface::getPixelColorAt( Coordinate x, Coordinate y ) const
00889 throw( VideoException )
00890 {
00891
00892 return Pixels::getPixelColor( *this, x, y ) ;
00893
00894 }
00895
00896
00897 Pixels::ColorDefinition Surface::getColorDefinitionAt(
00898 Coordinate x, Coordinate y ) const throw( VideoException )
00899 {
00900
00901 return Pixels::convertPixelColorToColorDefinition( getPixelFormat(),
00902 Pixels::getPixelColor( *this, x, y ) ) ;
00903
00904 }
00905
00906
00907
00908 void Surface::putRGBAPixelAt( Coordinate x, Coordinate y,
00909 ColorElement red, ColorElement green, ColorElement blue,
00910 ColorElement alpha,
00911 bool blending, bool clipping, bool locking ) throw( VideoException )
00912 {
00913
00914 Pixels::putRGBAPixel( *this, x, y, red, green, blue, alpha,
00915 blending, clipping, locking ) ;
00916
00917 }
00918
00919
00920
00921 void Surface::putColorDefinitionAt( Coordinate x, Coordinate y,
00922 ColorDefinition colorDef,
00923 bool blending, bool clipping, bool locking ) throw( VideoException )
00924 {
00925
00926 Pixels::putRGBAPixel( *this, x, y, colorDef.r, colorDef.g, colorDef.b,
00927 colorDef.unused, blending, clipping, locking ) ;
00928
00929 }
00930
00931
00932 void Surface::putPixelColorAt( Coordinate x, Coordinate y,
00933 PixelColor convertedColor, ColorElement alpha,
00934 bool blending, bool clipping, bool locking ) throw( VideoException )
00935 {
00936
00937 Pixels::putPixelColor( *this, x, y, convertedColor, alpha,
00938 blending, clipping, locking ) ;
00939
00940 }
00941
00942
00943
00944 bool Surface::setAlphaForColor( Pixels::ColorDefinition colorDef,
00945 Pixels::ColorElement newAlpha ) throw()
00946 {
00947
00948 #if OSDL_DEBUG_COLOR
00949
00950 LogPlug::trace(
00951 "Surface::setAlphaForColor : scanning for color definition "
00952 + Pixels::toString( colorDef )
00953 + ", so that its alpha coordinate gets replaced by "
00954 + Ceylan::toNumericalString( newAlpha ) ) ;
00955
00956 #endif // OSDL_DEBUG_COLOR
00957
00958
00959
00960
00961
00962
00963 if ( ( getFlags() & AlphaBlendingBlit ) == 0 )
00964 return false ;
00965
00966 ColorDefinition currentDef ;
00967
00968 lock() ;
00969
00970 Length height = getHeight() ;
00971 Length width = getWidth() ;
00972
00973 for ( Coordinate y = 0; y < height; y++ )
00974 for ( Coordinate x = 0; x < width; x++ )
00975 {
00976
00977 currentDef = getColorDefinitionAt( x, y ) ;
00978
00979
00980 if ( Pixels::areEqual( currentDef, colorDef,
00981 false ) )
00982 {
00983
00984 #if OSDL_DEBUG_PIXEL
00985 if ( x % 20 == 0 && y % 20 == 0 )
00986 LogPlug::debug(
00987 "Surface::setAlphaForColor : replacing alpha of "
00988 + Pixels::toString( currentDef ) + " with new alpha = "
00989 + Ceylan::toNumericalString( newAlpha ) + " at ["
00990 + Ceylan::toString( x ) + ";" + Ceylan::toString( y )
00991 + "]" ) ;
00992 #endif // OSDL_DEBUG_PIXEL
00993
00994 currentDef.unused = newAlpha ;
00995
00996 putColorDefinitionAt( x, y, currentDef,
00997
00998 false ) ;
00999
01000 #if OSDL_DEBUG_PIXEL
01001
01002
01003 if ( x % 20 == 0 && y % 20 == 0 )
01004 {
01005
01006 ColorDefinition readDef = getColorDefinitionAt( x, y ) ;
01007
01008 if ( ! Pixels::areEqual( readDef, currentDef,
01009 true ) )
01010 LogPlug::error( "Surface::setAlphaForColor : "
01011 "alpha replacement failed : expecting "
01012 + Pixels::toString( readDef )
01013 + ", read " + Pixels::toString( currentDef ) ) ;
01014 }
01015
01016 #endif // OSDL_DEBUG_PIXEL
01017
01018 }
01019 else
01020 {
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030 }
01031
01032 }
01033
01034 unlock() ;
01035
01036 return true ;
01037
01038 }
01039
01040
01041 bool Surface::drawHorizontalLine( Coordinate xStart, Coordinate xStop,
01042 Coordinate y, Pixels::ColorElement red, Pixels::ColorElement green,
01043 Pixels::ColorElement blue, Pixels::ColorElement alpha ) throw()
01044 {
01045
01046 return Line::drawHorizontal( *this, xStart, xStop, y,
01047 red, green, blue, alpha ) ;
01048
01049 }
01050
01051
01052 bool Surface::drawHorizontalLine( Coordinate xStart, Coordinate xStop,
01053 Coordinate y, Pixels::PixelColor actualColor ) throw()
01054 {
01055
01056 return Line::drawHorizontal( *this, xStart, xStop, y, actualColor ) ;
01057
01058 }
01059
01060
01061 bool Surface::drawHorizontalLine( Coordinate xStart, Coordinate xStop,
01062 Coordinate y, Pixels::ColorDefinition colorDef ) throw()
01063 {
01064
01065 return Line::drawHorizontal( *this, xStart, xStop, y, colorDef ) ;
01066
01067 }
01068
01069
01070
01071 bool Surface::drawVerticalLine( Coordinate x, Coordinate yStart,
01072 Coordinate yStop, Pixels::ColorElement red, Pixels::ColorElement green,
01073 Pixels::ColorElement blue, Pixels::ColorElement alpha) throw()
01074 {
01075
01076 return Line::drawVertical( *this, x, yStart, yStop,
01077 red, green, blue, alpha ) ;
01078
01079 }
01080
01081
01082 bool Surface::drawVerticalLine( Coordinate x, Coordinate yStart,
01083 Coordinate yStop, Pixels::ColorDefinition colorDef ) throw()
01084 {
01085
01086 return Line::drawVertical( *this, x, yStart, yStop, colorDef ) ;
01087
01088 }
01089
01090
01091
01092 bool Surface::drawLine( Coordinate xStart, Coordinate yStart,
01093 Coordinate xStop, Coordinate yStop,
01094 Pixels::ColorElement red, Pixels::ColorElement green,
01095 Pixels::ColorElement blue, Pixels::ColorElement alpha ) throw()
01096 {
01097
01098 return Line::draw( *this, xStart, yStart, xStop, yStop,
01099 red, green, blue, alpha ) ;
01100
01101 }
01102
01103
01104 bool Surface::drawLine( Coordinate xStart, Coordinate yStart,
01105 Coordinate xStop, Coordinate yStop, Pixels::ColorDefinition colorDef )
01106 throw()
01107 {
01108
01109 return Line::draw( *this, xStart, yStart, xStop, yStop, colorDef ) ;
01110
01111 }
01112
01113
01114 bool Surface::drawCross( const Point2D & center,
01115 Pixels::ColorDefinition colorDef, Length squareEdge ) throw()
01116 {
01117
01118 return Line::drawCross( *this, center, colorDef, squareEdge ) ;
01119
01120 }
01121
01122
01123 bool Surface::drawCross( Coordinate xCenter, Coordinate yCenter,
01124 Pixels::ColorDefinition colorDef, Length squareEdge ) throw()
01125 {
01126
01127 return Line::drawCross( *this, xCenter, yCenter, colorDef, squareEdge ) ;
01128
01129 }
01130
01131
01132 bool Surface::drawEdges( Pixels::ColorDefinition edgeColor, Length edgeWidth )
01133 throw()
01134 {
01135
01136 Coordinate xmin = 0 ;
01137 Coordinate xmax = getWidth() - 1 ;
01138
01139 Coordinate ymin = 0 ;
01140 Coordinate ymax = getHeight() - 1 ;
01141
01142 while ( edgeWidth != 0 )
01143 {
01144
01145 if ( ! drawVerticalLine( xmin, ymin, ymax, edgeColor ) )
01146 return false ;
01147
01148 if ( ! drawVerticalLine( xmax, ymin, ymax, edgeColor ) )
01149 return false ;
01150
01151 if ( ! drawHorizontalLine( xmin, xmax, ymin, edgeColor ) )
01152 return false ;
01153
01154 if ( ! drawHorizontalLine( xmin, xmax, ymax, edgeColor ) )
01155 return false ;
01156
01157 edgeWidth-- ;
01158
01159 xmin++ ;
01160 xmax -- ;
01161
01162 ymin++ ;
01163 ymax-- ;
01164 }
01165
01166 return true ;
01167
01168 }
01169
01170
01171 bool Surface::drawBox( const UprightRectangle & rectangle,
01172 Pixels::ColorElement red, Pixels::ColorElement green,
01173 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled )
01174 throw()
01175 {
01176
01177 return rectangle.draw( *this, red, green, blue, alpha, filled ) ;
01178
01179 }
01180
01181
01182 bool Surface::drawBox( const UprightRectangle & rectangle,
01183 Pixels::ColorDefinition colorDef, bool filled ) throw()
01184 {
01185
01186 return rectangle.draw( *this, colorDef, filled ) ;
01187
01188 }
01189
01190
01191
01192 bool Surface::drawCircle( Coordinate xCenter, Coordinate yCenter,
01193 Length radius, Pixels::ColorElement red, Pixels::ColorElement green,
01194 Pixels::ColorElement blue, Pixels::ColorElement alpha,
01195 bool filled, bool blended ) throw()
01196 {
01197
01198 return TwoDimensional::drawCircle( *this, xCenter, yCenter, radius,
01199 red, green, blue, alpha, filled, blended ) ;
01200
01201 }
01202
01203
01204 bool Surface::drawCircle( Coordinate xCenter, Coordinate yCenter,
01205 Length radius, Pixels::ColorDefinition colorDef,
01206 bool filled, bool blended ) throw()
01207 {
01208
01209 return TwoDimensional::drawCircle( *this, xCenter, yCenter, radius,
01210 colorDef, filled, blended ) ;
01211
01212 }
01213
01214
01215 bool Surface::drawDiscWithEdge( Coordinate xCenter, Coordinate yCenter,
01216 Length outerRadius, Length innerRadius,
01217 Pixels::ColorDefinition ringColorDef,
01218 Pixels::ColorDefinition discColorDef, bool blended ) throw()
01219 {
01220
01221 return TwoDimensional::drawDiscWithEdge( *this, xCenter, yCenter,
01222 outerRadius, innerRadius, ringColorDef, discColorDef, blended ) ;
01223
01224 }
01225
01226
01227 bool Surface::drawEllipse( Coordinate xCenter, Coordinate yCenter,
01228 Length horizontalRadius, Length verticalRadius,
01229 Pixels::ColorElement red, Pixels::ColorElement green,
01230 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled ) throw()
01231 {
01232
01233 return TwoDimensional::drawEllipse( *this, xCenter, yCenter,
01234 horizontalRadius, verticalRadius, red, green, blue, alpha, filled ) ;
01235
01236 }
01237
01238
01239 bool Surface::drawEllipse( Coordinate xCenter, Coordinate yCenter,
01240 Length horizontalRadius, Length verticalRadius,
01241 Pixels::ColorDefinition colorDef, bool filled ) throw()
01242 {
01243
01244 return TwoDimensional::drawEllipse( *this, xCenter, yCenter,
01245 horizontalRadius, verticalRadius, colorDef, filled ) ;
01246
01247 }
01248
01249
01250
01251 bool Surface::drawPie( Coordinate xCenter, Coordinate yCenter, Length radius,
01252 Ceylan::Maths::AngleInDegrees angleStart,
01253 Ceylan::Maths::AngleInDegrees angleStop,
01254 Pixels::ColorElement red, Pixels::ColorElement green,
01255 Pixels::ColorElement blue, Pixels::ColorElement alpha ) throw()
01256 {
01257
01258 return TwoDimensional::drawPie( *this, xCenter, yCenter, radius,
01259 angleStart, angleStop, red, green, blue, alpha ) ;
01260
01261 }
01262
01263
01264 bool Surface::drawPie( Coordinate xCenter, Coordinate yCenter, Length radius,
01265 Ceylan::Maths::AngleInDegrees angleStart,
01266 Ceylan::Maths::AngleInDegrees angleStop,
01267 Pixels::ColorDefinition colorDef ) throw()
01268 {
01269
01270 return TwoDimensional::drawPie( *this, xCenter, yCenter,
01271 radius, angleStart, angleStop, colorDef ) ;
01272
01273 }
01274
01275
01276
01277 bool Surface::drawTriangle( Coordinate x1, Coordinate y1,
01278 Coordinate x2, Coordinate y2, Coordinate x3, Coordinate y3,
01279 Pixels::ColorElement red, Pixels::ColorElement green,
01280 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled )
01281 throw()
01282 {
01283
01284 return TwoDimensional::drawTriangle( *this, x1, y1, x2, y2, x3, y3,
01285 red, green, blue, alpha, filled ) ;
01286
01287 }
01288
01289
01290
01291 bool Surface::drawTriangle( Coordinate x1, Coordinate y1,
01292 Coordinate x2, Coordinate y2, Coordinate x3, Coordinate y3,
01293 Pixels::ColorDefinition colorDef, bool filled ) throw()
01294 {
01295
01296 return TwoDimensional::drawTriangle( *this, x1, y1, x2, y2, x3, y3,
01297 colorDef, filled ) ;
01298
01299 }
01300
01301
01302
01303 bool Surface::drawTriangle( const Point2D & p1, const Point2D & p2,
01304 const Point2D & p3,
01305 Pixels::ColorElement red, Pixels::ColorElement green,
01306 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled )
01307 throw()
01308 {
01309
01310 return TwoDimensional::drawTriangle( *this, p1, p2, p3,
01311 red, green, blue, alpha, filled ) ;
01312
01313 }
01314
01315
01316
01317 bool Surface::drawTriangle( const Point2D & p1, const Point2D & p2,
01318 const Point2D & p3, Pixels::ColorDefinition colorDef, bool filled ) throw()
01319 {
01320
01321 return TwoDimensional::drawTriangle( *this, p1, p2, p3,
01322 colorDef, filled ) ;
01323
01324 }
01325
01326
01327
01328 bool Surface::drawPolygon( const list<Point2D *> summits,
01329 Coordinate x, Coordinate y,
01330 Pixels::ColorDefinition colorDef, bool filled ) throw()
01331 {
01332
01333 return TwoDimensional::drawPolygon( *this, summits, x, y,
01334 colorDef, filled ) ;
01335
01336 }
01337
01338
01339
01340 bool Surface::drawPolygon( const list<Point2D *> summits,
01341 Coordinate x, Coordinate y,
01342 Pixels::ColorElement red, Pixels::ColorElement green,
01343 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled ) throw()
01344 {
01345
01346 return TwoDimensional::drawPolygon( *this, summits, x, y,
01347 red, green, blue, alpha, filled ) ;
01348
01349 }
01350
01351
01352
01353 bool Surface::drawGrid( Length columnStride, Length rowStride,
01354 Pixels::ColorDefinition lineColor,
01355 bool fillBackground, Pixels::ColorDefinition backColor ) throw()
01356 {
01357
01358
01359 columnStride++ ;
01360 rowStride++ ;
01361
01362 if ( fillBackground )
01363 {
01364 if ( fill( backColor ) == false )
01365 return false ;
01366 }
01367
01368 Length xBorder = getWidth() ;
01369 Length yBorder = getHeight() ;
01370
01371 Coordinate x = 0 ;
01372
01373
01374 while ( x < xBorder )
01375 {
01376 if ( ! drawVerticalLine( x, 0, yBorder, lineColor ) )
01377 return false ;
01378 x += columnStride ;
01379 }
01380
01381 Coordinate y = 0 ;
01382
01383
01384 while ( y < yBorder )
01385 {
01386 if ( ! drawHorizontalLine( 0, xBorder, y, lineColor ) )
01387 return false ;
01388 y += rowStride ;
01389 }
01390
01391 return true ;
01392
01393 }
01394
01395
01396
01397
01398 bool Surface::printText( const std::string & text, Coordinate x, Coordinate y,
01399 Pixels::ColorElement red, Pixels::ColorElement green,
01400 Pixels::ColorElement blue, Pixels::ColorElement alpha ) throw()
01401 {
01402
01403 return Text::printBasic( text, *this, x, y, red, green, blue, alpha ) ;
01404
01405 }
01406
01407
01408
01409 bool Surface::printText( const std::string & text, Coordinate x, Coordinate y,
01410 ColorDefinition colorDef ) throw()
01411 {
01412
01413 return Text::printBasic( text, *this, x, y, colorDef ) ;
01414
01415 }
01416
01417
01418 bool Surface::blitTo( Surface & targetSurface ) const throw( VideoException )
01419 {
01420
01421 return blitTo( targetSurface, 0, 0 ) ;
01422
01423 }
01424
01425
01426 bool Surface::blitTo( Surface & targetSurface, Coordinate x, Coordinate y )
01427 const throw( VideoException )
01428 {
01429
01430 #if OSDL_DEBUG_WIDGET
01431
01432 LogPlug::trace( "Surface::blitTo : blitting to [" + Ceylan::toString( x )
01433 + ";" + Ceylan::toString( y ) + "]." ) ;
01434
01435 #endif // OSDL_DEBUG_WIDGET
01436
01437
01438 #if OSDL_DEBUG
01439
01440 if ( isLocked() )
01441 throw VideoException( "Surface::blitTo with no source rectangle called "
01442 "whereas surface is locked." ) ;
01443
01444 #endif // OSDL_DEBUG
01445
01446 SDL_Rect destinationRect ;
01447
01448 destinationRect.x = x ;
01449 destinationRect.y = y ;
01450
01451
01452 switch( SDL_BlitSurface( & getSDLSurface(), 0,
01453 & targetSurface.getSDLSurface(), & destinationRect ) )
01454 {
01455
01456 case 0:
01457
01458 return true ;
01459 break ;
01460
01461 case -2:
01462
01463
01464
01465
01466
01467 throw VideoMemoryLostException() ;
01468 break ;
01469
01470 case -1:
01471 throw VideoException(
01472 "Surface::blitTo with no source rectangle : error in blit, "
01473 + Utils::getBackendLastError() ) ;
01474 break ;
01475
01476 default:
01477 LogPlug::error( "Unexpected returned value in Surface::blitTo "
01478 "with no source rectangle." ) ;
01479 return false ;
01480 break ;
01481 }
01482
01483 return false ;
01484
01485 }
01486
01487
01488
01489 bool Surface::blitTo( Surface & targetSurface,
01490 const TwoDimensional::Point2D & location ) const throw( VideoException )
01491 {
01492
01493 return blitTo( targetSurface, location.getX(), location.getY() ) ;
01494
01495 }
01496
01497
01498
01499 bool Surface::blitTo( Surface & targetSurface,
01500 const TwoDimensional::UprightRectangle & sourceRectangle,
01501 const TwoDimensional::Point2D & destinationLocation )
01502 const throw( VideoException )
01503 {
01504
01505 #if OSDL_DEBUG
01506
01507 if ( isLocked() )
01508 throw VideoException( "Surface::blitTo with source rectangle called "
01509 "whereas surface is locked." ) ;
01510
01511 #endif // OSDL_DEBUG
01512
01513
01514 #if OSDL_DEBUG_BLIT
01515
01516 LogPlug::debug( "Surface::blitTo with source rectangle = "
01517 + sourceRectangle.toString() + " and destination location = "
01518 + destinationLocation.toString() ) ;
01519
01520 #endif // OSDL_DEBUG_BLIT
01521
01522 SDL_Rect destinationRect ;
01523
01524 destinationRect.x = destinationLocation.getX() ;
01525 destinationRect.y = destinationLocation.getY() ;
01526
01527
01528 switch( SDL_BlitSurface( & getSDLSurface(), sourceRectangle.toSDLRect(),
01529 & targetSurface.getSDLSurface(), & destinationRect ) )
01530 {
01531
01532 case 0:
01533
01534 return true ;
01535 break ;
01536
01537 case -2:
01538
01539 throw VideoMemoryLostException() ;
01540 break ;
01541
01542 case -1:
01543 throw VideoException(
01544 "Surface::blitTo with source rectangle : error in blit, "
01545 + Utils::getBackendLastError() ) ;
01546 break ;
01547
01548 default:
01549 LogPlug::error( "Unexpected returned value in Surface::blitTo "
01550 "with source rectangle." ) ;
01551 return false ;
01552 break ;
01553 }
01554
01555 return false ;
01556
01557 }
01558
01559
01560
01561 Surface & Surface::zoom( Ceylan::Maths::Real abscissaZoomFactor,
01562 Ceylan::Maths::Real ordinateZoomFactor, bool antialiasing )
01563 const throw( VideoException )
01564 {
01565
01566
01567 if ( abscissaZoomFactor < 0 || ordinateZoomFactor < 0 )
01568 antialiasing = false ;
01569
01570 SDL_Surface * res = ::zoomSurface(
01571 const_cast<SDL_Surface *>( _surface ),
01572 abscissaZoomFactor,
01573 ordinateZoomFactor,
01574 antialiasing ? SMOOTHING_ON : SMOOTHING_OFF ) ;
01575
01576 if ( res == 0 )
01577 throw VideoException( "Surface::zoom : unable to zoom surface." ) ;
01578
01579
01580 return * new Surface( *res ) ;
01581
01582 }
01583
01584
01585 Surface & Surface::rotoZoom( Ceylan::Maths::AngleInDegrees angle,
01586 Ceylan::Maths::Real zoomFactor, bool antialiasing )
01587 const throw( VideoException )
01588 {
01589
01590 return rotoZoom( angle, zoomFactor, zoomFactor, antialiasing ) ;
01591
01592 }
01593
01594
01595 Surface & Surface::rotoZoom(
01596 Ceylan::Maths::AngleInDegrees angle,
01597 Ceylan::Maths::Real abscissaZoomFactor,
01598 Ceylan::Maths::Real ordinateZoomFactor,
01599 bool antialiasing )
01600 const throw( VideoException )
01601 {
01602
01603
01604 if ( abscissaZoomFactor < 0 || ordinateZoomFactor < 0 )
01605 antialiasing = false ;
01606
01607 SDL_Surface * res = ::rotozoomSurfaceXY(
01608 const_cast<SDL_Surface *>( _surface ), angle, abscissaZoomFactor,
01609 ordinateZoomFactor, antialiasing ? SMOOTHING_ON : SMOOTHING_OFF ) ;
01610
01611 if ( res == 0 )
01612 throw VideoException(
01613 "Surface::rotoZoom : unable to rotozoom surface." ) ;
01614
01615 return * new Surface( *res ) ;
01616
01617 }
01618
01619
01620
01621 UprightRectangle & Surface::getClippingArea() const throw()
01622 {
01623 return * new UprightRectangle( _surface->clip_rect ) ;
01624 }
01625
01626
01627
01628 void Surface::setClippingArea( UprightRectangle & newClippingArea ) throw()
01629 {
01630
01631 TwoDimensional::Point2D corner = newClippingArea.getUpperLeftCorner() ;
01632
01633 _surface->clip_rect.x = corner.getX() ;
01634 _surface->clip_rect.y = corner.getY() ;
01635
01636 _surface->clip_rect.w = newClippingArea.getWidth() ;
01637 _surface->clip_rect.h = newClippingArea.getHeight() ;
01638
01639 }
01640
01641
01642
01643
01644
01645
01646
01647 void Surface::loadImage( const string & filename, bool blitOnly,
01648 bool convertToDisplayFormat, bool convertWithAlpha )
01649 throw( TwoDimensional::ImageException )
01650 {
01651
01652 TwoDimensional::Image::Load( *this, filename, blitOnly,
01653 convertToDisplayFormat, convertWithAlpha ) ;
01654
01655 }
01656
01657
01658 void Surface::loadJPG( const string & filename, bool blitOnly,
01659 bool convertToDisplayFormat, bool convertWithAlpha )
01660 throw( TwoDimensional::ImageException )
01661 {
01662
01663 TwoDimensional::Image::LoadJPG( *this, filename, blitOnly,
01664 convertToDisplayFormat, convertWithAlpha ) ;
01665
01666 }
01667
01668
01669 void Surface::loadPNG( const string & filename, bool blitOnly,
01670 bool convertToDisplayFormat, bool convertWithAlpha )
01671 throw( TwoDimensional::ImageException )
01672 {
01673
01674 TwoDimensional::Image::LoadPNG( *this, filename, blitOnly,
01675 convertToDisplayFormat, convertWithAlpha ) ;
01676
01677 }
01678
01679
01680 void Surface::loadBMP( const string & filename, bool blitOnly,
01681 bool convertToDisplayFormat, bool convertWithAlpha )
01682 throw( TwoDimensional::ImageException )
01683 {
01684
01685 TwoDimensional::Image::LoadBMP( *this, filename, blitOnly,
01686 convertToDisplayFormat, convertWithAlpha ) ;
01687
01688 }
01689
01690
01691 void Surface::loadGIF( const string & filename, bool blitOnly,
01692 bool convertToDisplayFormat, bool convertWithAlpha )
01693 throw( TwoDimensional::ImageException )
01694 {
01695
01696 TwoDimensional::Image::LoadGIF( *this, filename, blitOnly,
01697 convertToDisplayFormat, convertWithAlpha ) ;
01698
01699 }
01700
01701
01702 void Surface::loadLBM( const string & filename, bool blitOnly,
01703 bool convertToDisplayFormat, bool convertWithAlpha )
01704 throw( TwoDimensional::ImageException )
01705 {
01706
01707 TwoDimensional::Image::LoadLBM( *this, filename, blitOnly,
01708 convertToDisplayFormat, convertWithAlpha ) ;
01709
01710 }
01711
01712
01713 void Surface::loadPCX( const string & filename, bool blitOnly,
01714 bool convertToDisplayFormat, bool convertWithAlpha )
01715 throw( TwoDimensional::ImageException )
01716 {
01717
01718 TwoDimensional::Image::LoadPCX( *this, filename, blitOnly,
01719 convertToDisplayFormat, convertWithAlpha ) ;
01720
01721 }
01722
01723
01724 void Surface::loadPNM( const string & filename, bool blitOnly,
01725 bool convertToDisplayFormat, bool convertWithAlpha )
01726 throw( TwoDimensional::ImageException )
01727 {
01728
01729 TwoDimensional::Image::LoadPNM( *this, filename, blitOnly,
01730 convertToDisplayFormat, convertWithAlpha ) ;
01731
01732 }
01733
01734
01735 void Surface::loadTGA( const string & filename, bool blitOnly,
01736 bool convertToDisplayFormat, bool convertWithAlpha )
01737 throw( TwoDimensional::ImageException )
01738 {
01739
01740 TwoDimensional::Image::LoadTGA( *this, filename, blitOnly,
01741 convertToDisplayFormat, convertWithAlpha ) ;
01742
01743 }
01744
01745
01746 void Surface::loadXPM( const string & filename, bool blitOnly,
01747 bool convertToDisplayFormat, bool convertWithAlpha )
01748 throw( TwoDimensional::ImageException )
01749 {
01750
01751 TwoDimensional::Image::LoadXPM( *this, filename, blitOnly,
01752 convertToDisplayFormat, convertWithAlpha ) ;
01753
01754 }
01755
01756
01757 void Surface::savePNG( const std::string & filename, bool overwrite )
01758 throw( TwoDimensional::ImageException )
01759 {
01760
01761 TwoDimensional::Image::SavePNG( *this, filename, overwrite ) ;
01762
01763 }
01764
01765
01766 void Surface::saveBMP( const std::string & filename, bool overwrite )
01767 throw( TwoDimensional::ImageException )
01768 {
01769
01770 if ( ( overwrite == false ) && Ceylan::System::File::Exists( filename ) )
01771 throw TwoDimensional::ImageException(
01772 "Surface::saveBMP : target file " + filename
01773 + " already exists, and overwrite mode is off." ) ;
01774
01775 if ( SDL_SaveBMP( _surface, filename.c_str() ) == -1 )
01776 throw TwoDimensional::ImageException(
01777 "Surface::saveBMP : unable to save image : "
01778 + Utils::getBackendLastError() ) ;
01779 }
01780
01781
01782 void Surface::update() throw( VideoException )
01783 {
01784
01785 #if OSDL_DEBUG_WIDGET
01786 LogPlug::trace( "Surface::update" ) ;
01787 #endif // OSDL_DEBUG_WIDGET
01788
01789
01790 #if OSDL_DEBUG
01791 if ( isLocked() )
01792 throw VideoException(
01793 "Surface::update called whereas surface is locked." ) ;
01794 #endif // OSDL_DEBUG
01795
01796
01797 redraw() ;
01798
01799 switch( _displayType )
01800 {
01801
01802
01803 case BackBuffer:
01804 LogPlug::warning( "Surface::update requested on a "
01805 "non-screen surface ! (nothing done)" ) ;
01806 break ;
01807
01808
01809 case ClassicalScreenSurface:
01810 #if OSDL_DEBUG_WIDGET
01811 LogPlug::trace(
01812 "Surface::update : flipping classical screen buffer" ) ;
01813 #endif // OSDL_DEBUG_WIDGET
01814
01815
01816 if ( SDL_Flip( _surface ) != 0 )
01817 throw VideoException(
01818 "Surface::update : unable to flip classical screen : "
01819 + Utils::getBackendLastError() ) ;
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837 break ;
01838
01839
01840 case OpenGLScreenSurface:
01841 #if OSDL_DEBUG_WIDGET
01842 LogPlug::trace(
01843 "Surface::update : flipping OpenGL screen buffer" ) ;
01844 #endif // OSDL_DEBUG_WIDGET
01845
01846
01847 SDL_GL_SwapBuffers() ;
01848 break ;
01849
01850
01851 default:
01852 LogPlug::error(
01853 "Surface::update : unknown display type, nothing done." ) ;
01854 break ;
01855
01856 }
01857
01858 }
01859
01860
01861 void Surface::updateRectangles( const list<UprightRectangle *> & listRects )
01862 throw( VideoException )
01863 {
01864
01865
01866
01867
01868
01869
01870
01871 for ( list<UprightRectangle *>::const_iterator it = listRects.begin() ;
01872 it != listRects.end() ; it++ )
01873 {
01874
01875 #if OSDL_DEBUG
01876 if ( *it == 0 )
01877 {
01878 LogPlug::error( "Surface::updateRectangles : "
01879 "null pointer in rectangle list." ) ;
01880 break ;
01881 }
01882 #endif // OSDL_DEBUG
01883
01884 updateRectangle( * (*it) ) ;
01885
01886 }
01887
01888 }
01889
01890
01891 void Surface::updateRectangle( const UprightRectangle & rect )
01892 throw( VideoException )
01893 {
01894
01895 updateRectangle( rect.getUpperLeftAbscissa(),
01896 rect.getUpperLeftOrdinate(), rect.getWidth(), rect.getHeight() ) ;
01897
01898 }
01899
01900
01901 void Surface::updateRectangle( Coordinate x, Coordinate y,
01902 Length width, Length height ) throw( VideoException )
01903 {
01904
01905 #if OSDL_DEBUG
01906 if ( isLocked() )
01907 LogPlug::error(
01908 "Surface::updateRectangle() called whereas surface is locked." ) ;
01909 #endif // OSDL_DEBUG
01910
01911 if ( _displayType != BackBuffer )
01912 {
01913 SDL_UpdateRect( _surface, x, y, width, height ) ;
01914 }
01915 else
01916 {
01917 throw VideoException(
01918 "Surface::updateRectangle requested on a non-screen surface" ) ;
01919 }
01920
01921 }
01922
01923
01924 void Surface::setRedrawState( bool needsToBeRedrawn ) throw()
01925 {
01926
01927 _needsRedraw = needsToBeRedrawn ;
01928
01929 }
01930
01931
01932 bool Surface::getRedrawState() const throw()
01933 {
01934
01935 return _needsRedraw ;
01936
01937 }
01938
01939
01940 void Surface::redraw() throw()
01941 {
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955 if ( getRedrawState() )
01956 {
01957
01958
01959 redrawInternal() ;
01960
01961
01962 RedrawRequestEvent redrawEvent( *this ) ;
01963
01964
01965
01966
01967
01968
01969
01970 notifyAllListeners( redrawEvent ) ;
01971
01972 setRedrawState( false ) ;
01973
01974 }
01975
01976
01977
01978 }
01979
01980
01981 void Surface::redrawInternal() throw()
01982 {
01983
01984 #if OSDL_DEBUG_WIDGET
01985 LogPlug::trace( "Surface::redrawInternal (non overriden version)" ) ;
01986 #endif // OSDL_DEBUG_WIDGET
01987
01988
01989
01990
01991
01992
01993
01994 }
01995
01996
01997 bool Surface::isInternalSurfaceAvailable() const throw()
01998 {
01999
02000 return _surface ;
02001
02002 }
02003
02004
02005 void Surface::addWidget( TwoDimensional::Widget & widget )
02006 throw( VideoException )
02007 {
02008
02009 #if OSDL_DEBUG_WIDGET
02010 LogPlug::trace( "Surface::addWidget : adding " + widget.toString() ) ;
02011 #endif // OSDL_DEBUG_WIDGET
02012
02013
02014
02015
02016
02017
02018
02019 try
02020 {
02021 add( widget ) ;
02022 }
02023 catch( const Ceylan::EventException & e )
02024 {
02025 throw VideoException(
02026 "Surface::addWidget : unable to add new listener widget : "
02027 + e.toString() ) ;
02028 }
02029
02030 }
02031
02032
02033 Surface & Surface::getWidgetRenderTarget() throw()
02034 {
02035
02036
02037
02038
02039
02040
02041 return *this ;
02042
02043 }
02044
02045
02046 void Surface::putWidgetToFront( TwoDimensional::Widget & widget )
02047 throw( VideoException )
02048 {
02049
02050
02051
02052
02053
02054
02055 _listeners.remove( & widget ) ;
02056
02057
02058 _listeners.push_back( & widget ) ;
02059
02060 }
02061
02062
02063 void Surface::putWidgetToBack( TwoDimensional::Widget & widget )
02064 throw( VideoException )
02065 {
02066
02067
02068
02069
02070
02071
02072
02073 _listeners.remove( & widget ) ;
02074
02075
02076 _listeners.push_front( & widget ) ;
02077
02078 }
02079
02080
02081 void Surface::centerMousePosition() throw()
02082 {
02083
02084 setMousePosition( getWidth() / 2, getHeight() / 2 ) ;
02085
02086 }
02087
02088
02089 void Surface::setMousePosition( Coordinate newX, Coordinate newY ) throw()
02090 {
02091
02092 #if OSDL_DEBUG
02093
02094 if ( _displayType == BackBuffer )
02095 {
02096 Ceylan::emergencyShutdown(
02097 "Surface::setMousePosition called on a non-screen surface." ) ;
02098 }
02099
02100 #endif // OSDL_DEBUG
02101
02102 SDL_WarpMouse( newX, newY ) ;
02103
02104 }
02105
02106
02107 bool Surface::mustBeLocked() const throw()
02108 {
02109
02110
02111 return SDL_MUSTLOCK( _surface ) ;
02112
02113 }
02114
02115
02116 void Surface::preUnlock() throw()
02117 {
02118
02119
02120
02121
02122
02123
02124 SDL_UnlockSurface( _surface ) ;
02125
02126 }
02127
02128
02129 void Surface::postLock() throw()
02130 {
02131
02132
02133
02134
02135
02136
02137 SDL_LockSurface( _surface ) ;
02138
02139 }
02140
02141
02142 Ceylan::System::Size Surface::getSizeInMemory() const throw()
02143 {
02144
02145 Ceylan::System::Size currentSize = sizeof( Surface ) ;
02146
02147 if ( _surface != 0 )
02148 {
02149
02150 currentSize += sizeof( SDL_Surface ) ;
02151
02152
02153 if ( _surface->format != 0 )
02154 {
02155
02156 currentSize += sizeof( SDL_PixelFormat ) ;
02157
02158 if ( _surface->format->palette != 0 )
02159 {
02160 currentSize += sizeof( SDL_Palette ) ;
02161 currentSize += _surface->format->palette->ncolors
02162 * sizeof( SDL_Color ) ;
02163 }
02164
02165 if ( _surface->pixels != 0 )
02166 currentSize += _surface->w * _surface->h *
02167 _surface->format->BytesPerPixel ;
02168
02169 }
02170
02171 }
02172
02173
02174
02175 return currentSize ;
02176
02177 }
02178
02179
02180 bool Surface::displayData( const Ceylan::Maths::IntegerData * dataArray,
02181 Ceylan::Uint32 dataCount,
02182 Pixels::ColorDefinition pencilColor, Pixels::ColorDefinition captionColor,
02183 Pixels::ColorDefinition backgroundColor,
02184 const string & caption, const UprightRectangle * inBox ) throw()
02185 {
02186
02187
02188 #define OSDL_DEBUG_DISPLAY_DATA 0
02189
02190 Coordinate x, y ;
02191 Length width, height ;
02192
02193 if ( inBox == 0 )
02194 {
02195 x = 0 ;
02196 y = 0 ;
02197 width = getWidth() ;
02198 height = getHeight() ;
02199 }
02200 else
02201 {
02202
02203
02204
02205
02206
02207
02208
02209 x = inBox->getUpperLeftAbscissa() ;
02210 y = inBox->getUpperLeftOrdinate() ;
02211 width = inBox->getWidth() ;
02212 height = inBox->getHeight() ;
02213 }
02214
02215 UprightRectangle drawingArea( x, y, width, height ) ;
02216
02217 #if OSDL_DEBUG_DISPLAY_DATA
02218 LogPlug::debug( "Drawing area will be : " + drawingArea.toString() ) ;
02219 #endif // OSDL_DEBUG_DISPLAY_DATA
02220
02221
02222 drawBox( drawingArea, backgroundColor, true ) ;
02223
02224
02225 drawBox( drawingArea, pencilColor, false ) ;
02226
02227
02228
02229
02230
02231 Coordinate xstart = drawingArea.getUpperLeftAbscissa()
02232 + graphAbscissaOffset ;
02233
02234 Coordinate xmax = drawingArea.getUpperLeftAbscissa()
02235 + drawingArea.getWidth() - graphAbscissaOffset ;
02236 Coordinate xstop ;
02237
02238
02239
02240
02241
02242
02243
02244 Coordinate stride = static_cast<Coordinate>(
02245 Ceylan::Maths::Floor( static_cast<Ceylan::Float32>(
02246 ( drawingArea.getWidth() - 2 * graphAbscissaOffset )
02247 / static_cast<Ceylan::Float32>( dataCount ) ) ) ) ;
02248
02249 #if OSDL_DEBUG_DISPLAY_DATA
02250 LogPlug::debug( "Abscissa stride is "
02251 + Ceylan::toString( stride ) + "." ) ;
02252 #endif // OSDL_DEBUG_DISPLAY_DATA
02253
02254 if ( stride < 1 )
02255 {
02256 LogPlug::error(
02257 "Surface::displayData : available width too small to draw." ) ;
02258 return false ;
02259 }
02260
02261
02262 if ( xstart + static_cast<Coordinate>( dataCount ) > xmax )
02263 {
02264 LogPlug::warning(
02265 "Surface::displayData : graph will be truncated to x = "
02266 + Ceylan::toString( xmax ) + " (insufficient width)." ) ;
02267 xstop = xmax ;
02268 }
02269 else
02270 {
02271 xstop = xstart + stride * dataCount ;
02272 }
02273
02274
02275 if ( xstart > xstop )
02276 {
02277
02278 LogPlug::error(
02279 "Surface::displayData : available width too small to draw." ) ;
02280 return false ;
02281 }
02282
02283
02284
02285
02286 Ceylan::Maths::IntegerData maxData = dataArray[ 0 ] ;
02287 Ceylan::Maths::IntegerData minData = dataArray[ 0 ] ;
02288
02289 for ( Ceylan::Uint32 i = 1; i < dataCount; i++ )
02290 {
02291
02292 if ( dataArray[i] > maxData )
02293 maxData = dataArray[i] ;
02294
02295 if ( dataArray[i] < minData )
02296 minData = dataArray[i] ;
02297
02298 }
02299
02300
02301 #if OSDL_DEBUG_DISPLAY_DATA
02302 LogPlug::debug( "Dynamic range from " + Ceylan::toString( minData )
02303 + " to " + Ceylan::toString( maxData ) + "." ) ;
02304 #endif // OSDL_DEBUG_DISPLAY_DATA
02305
02306 Ceylan::Maths::IntegerData ordinateDrawRange =
02307 drawingArea.getHeight() - 2 * graphOrdinateOffset ;
02308
02309 if ( ordinateDrawRange < 0 )
02310 {
02311 LogPlug::error( "Surface::displayData : height too small to draw." ) ;
02312 return false ;
02313 }
02314
02315 Ceylan::Float32 yScaleFactor ;
02316
02317 if ( maxData != minData )
02318 yScaleFactor = static_cast<Ceylan::Float32>( ordinateDrawRange )
02319 / ( maxData - minData ) ;
02320 else
02321 yScaleFactor = 1 ;
02322
02323
02324 #if OSDL_DEBUG_DISPLAY_DATA
02325
02326 LogPlug::debug( "Ordinate scale factor is "
02327 + Ceylan::toString( yScaleFactor )
02328 + " (" + Ceylan::toString( ordinateDrawRange )
02329 + " / " + Ceylan::toString( maxData - minData ) + ")." ) ;
02330
02331 #endif // OSDL_DEBUG_DISPLAY_DATA
02332
02333 Coordinate yplotBase = drawingArea.getUpperLeftOrdinate()
02334 + drawingArea.getHeight() - graphOrdinateOffset ;
02335
02336
02337
02338 Ceylan::Uint32 dataCurrent = 0 ;
02339
02340 Coordinate xplot = xstart ;
02341
02342 Coordinate yplotPrevious = yplotBase ;
02343 Coordinate yplot ;
02344
02345 while ( xplot < xstop )
02346 {
02347 yplot = static_cast<Coordinate>(
02348 ( dataArray[ dataCurrent ] - minData ) * yScaleFactor ) ;
02349
02350 drawLine( xplot, yplotPrevious, xplot+1, yplotBase - yplot,
02351 pencilColor ) ;
02352 yplotPrevious = yplotBase - yplot ;
02353
02354
02355
02356
02357
02358
02359
02360 dataCurrent++ ;
02361 xplot += stride ;
02362
02363 }
02364
02365
02366
02367
02368
02369
02370
02371 ColorDefinition axisColor = Pixels::Ivory ;
02372
02373 drawHorizontalLine( xstart, xstop, yplotBase, axisColor ) ;
02374 drawVerticalLine( xstart, yplotBase,
02375 drawingArea.getUpperLeftOrdinate() + graphOrdinateOffset, axisColor ) ;
02376
02377
02378
02379
02380
02381
02382
02383 if( caption.size() > 0 )
02384 printText( caption,
02385 drawingArea.getUpperLeftAbscissa() + captionAbscissaOffset,
02386 drawingArea.getUpperLeftOrdinate() + drawingArea.getHeight()
02387 - captionOrdinateOffset,
02388 captionColor ) ;
02389
02390 return true ;
02391
02392 }
02393
02394
02395 const string Surface::toString( Ceylan::VerbosityLevels level ) const throw()
02396 {
02397
02398 std::list<string> surfaceList ;
02399
02400 switch( _displayType )
02401 {
02402
02403
02404 case BackBuffer:
02405 surfaceList.push_back( "This is a back buffer surface." ) ;
02406 break ;
02407
02408
02409 case ClassicalScreenSurface:
02410 surfaceList.push_back( "This is a classical screen surface." ) ;
02411 break ;
02412
02413 case OpenGLScreenSurface:
02414 surfaceList.push_back( "This is an OpenGL screen surface." ) ;
02415 break ;
02416
02417 default:
02418 surfaceList.push_back(
02419 "This is a surface of unknown type (abnormal)." ) ;
02420 break ;
02421
02422 }
02423
02424 surfaceList.push_back( "Dimensions : ( width = "
02425 + Ceylan::toString( getWidth() ) + " ; height = "
02426 + getHeight() + " )" ) ;
02427
02428 if ( level == Ceylan::low )
02429 return "Surface description : "
02430 + Ceylan::formatStringList( surfaceList ) ;
02431
02432 surfaceList.push_back( "Pitch : " + Ceylan::toString( getPitch() ) ) ;
02433
02434 surfaceList.push_back( "Pixel format : bits per pixel = "
02435 + Ceylan::toString(
02436 static_cast<Ceylan::Uint16>( getBitsPerPixel() ) ) ) ;
02437
02438 surfaceList.push_back( "Video flags : " + InterpretFlags( getFlags() ) ) ;
02439
02440
02441 surfaceList.push_back( "Clipping area : "
02442 + UprightRectangle( _surface->clip_rect ).toString( level ) ) ;
02443
02444 surfaceList.push_back( "Size in memory : "
02445 + Ceylan::toString( getSizeInMemory() ) + " bytes" ) ;
02446
02447
02448
02449
02450
02451
02452
02453 surfaceList.push_back( "Widget relationship : "
02454 + EventSource::toString( level ) ) ;
02455
02456
02457 return "Surface description : " + Ceylan::formatStringList( surfaceList ) ;
02458
02459 }
02460
02461
02462
02463 Surface & Surface::LoadImage( const std::string & filename,
02464 bool convertToDisplayFormat, bool convertWithAlpha )
02465 throw( TwoDimensional::ImageException )
02466 {
02467
02468 Surface * toLoad = new Surface() ;
02469
02470 try
02471 {
02472 toLoad->loadImage( filename, false,
02473 convertToDisplayFormat, convertWithAlpha ) ;
02474 }
02475 catch( const TwoDimensional::ImageException & e )
02476 {
02477 delete toLoad ;
02478 throw ;
02479 }
02480
02481 return * toLoad ;
02482
02483 }
02484
02485
02486 string Surface::InterpretFlags( Flags flags ) throw()
02487 {
02488
02489
02490
02491
02492
02493
02494
02495
02496 std::list<string> res ;
02497
02498 if ( flags & ( AnyPixelFormat | DoubleBuffered
02499 | FullScreen | OpenGL | SDL_OPENGLBLIT ) )
02500 {
02501
02502 res.push_back( "This surface should be a display surface." ) ;
02503
02504 if ( flags & AnyPixelFormat )
02505 res.push_back(
02506 "Allows any pixel format for the display surface." ) ;
02507 else
02508 res.push_back( "Only specified pixel format "
02509 "is accepted for the display surface." ) ;
02510
02511 if ( flags & DoubleBuffered )
02512 res.push_back( "Display surface is double buffered." ) ;
02513 else
02514 res.push_back( "Display surface is not double buffered." ) ;
02515
02516 if ( flags & FullScreen )
02517 res.push_back( "Display surface is fullscreen." ) ;
02518 else
02519 res.push_back( "Display surface is in windowed mode "
02520 "(not full screen)." ) ;
02521
02522 if ( flags & OpenGL )
02523 res.push_back( "Display surface has an OpenGL context." ) ;
02524 else
02525 res.push_back( "Display surface has no OpenGL context." ) ;
02526
02527 if ( flags & SDL_OPENGLBLIT )
02528 res.push_back(
02529 "Display surface supports OpenGL blitting (deprecated)." ) ;
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542 if ( flags & Resizable )
02543 res.push_back( "Display surface is resizable." ) ;
02544 else
02545 res.push_back( "Display surface is not resizable." ) ;
02546
02547 }
02548 else
02549 {
02550 res.push_back( "No flag dedicated to display surfaces "
02551 "is used for this surface." ) ;
02552 }
02553
02554
02555 if ( flags & Software )
02556 res.push_back( "Surface is to be stored in system memory." ) ;
02557 else
02558 res.push_back(
02559 "Surface is not required to be stored in system memory." ) ;
02560
02561
02562 if ( flags & Hardware )
02563 res.push_back( "Surface is to be stored in video memory." ) ;
02564 else
02565 res.push_back(
02566 "Surface is not required to be stored in video memory." ) ;
02567
02568
02569 if ( flags & AsynchronousBlit )
02570 res.push_back( "Surface should use asynchronous blits if possible." ) ;
02571 else
02572 res.push_back(
02573 "Surface is not required to use asynchronous blits if possible." ) ;
02574
02575
02576 if ( flags & ExclusivePalette )
02577 res.push_back( "Surface should have an exclusive palette." ) ;
02578 else
02579 res.push_back( "Surface has not an exclusive palette." ) ;
02580
02581
02582 if ( flags & HardwareAcceleratedBlit )
02583 res.push_back( "Surface is to use hardware-accelerated blits." ) ;
02584 else
02585 res.push_back(
02586 "Surface is not required to use hardware-accelerated blits." ) ;
02587
02588
02589 if ( flags & ColorkeyBlit )
02590 res.push_back( "Surface is to use colorkey blitting." ) ;
02591 else
02592 res.push_back( "Surface is not required to use colorkey blitting." ) ;
02593
02594
02595 if ( flags & RLEColorkeyBlit )
02596 res.push_back( "Surface is to use RLE-accelerated colorkey blits." ) ;
02597 else
02598 res.push_back(
02599 "Surface is not required to use RLE-accelerated colorkey blits." ) ;
02600
02601
02602 if ( flags & AlphaBlendingBlit )
02603 res.push_back( "Surface is to use alpha blending blits." ) ;
02604 else
02605 res.push_back(
02606 "Surface is not required to use alpha blending blits." ) ;
02607
02608
02609 if ( flags & Preallocated )
02610 res.push_back( "Surface is to use preallocated memory." ) ;
02611 else
02612 res.push_back( "Surface is not required to use preallocated memory." ) ;
02613
02614
02615 return "The specified surface flags, whose value is "
02616 + Ceylan::toString( flags, true )
02617 + ", means : " + Ceylan::formatStringList( res ) ;
02618
02619 }
02620
02621
02622
02623
02624 Offset Surface::getOffset() const throw()
02625 {
02626
02627 return _surface->offset ;
02628
02629 }
02630
02631
02632 void Surface::setOffset( Offset offset ) throw()
02633 {
02634
02635 _surface->offset = offset ;
02636
02637 }
02638
02639
02640
02641 void Surface::flush() throw()
02642 {
02643
02644 if ( _surface != 0 )
02645 {
02646
02647 #if OSDL_DEBUG_SURFACE
02648 LogPlug::trace( "Surface::flush : flushing surface." ) ;
02649 #endif // OSDL_DEBUG_SURFACE
02650
02651 if ( _displayType != BackBuffer )
02652 inconsistencyDetected(
02653 "Surface::flush : trying to delete a screen surface." ) ;
02654
02655 SDL_FreeSurface( _surface ) ;
02656 _surface = 0 ;
02657
02658 }
02659 }
02660
02661
02662
02663 void Surface::inconsistencyDetected( const string & message ) const throw()
02664 {
02665
02666 Ceylan::emergencyShutdown( "Incoherence detected in OSDL Surface : "
02667 + message ) ;
02668
02669 }
02670
02671
02672 Surface::Surface( const Surface & source ) throw() :
02673 TwoDimensional::UprightRectangle( 0, 0, 0, 0 ),
02674 Ceylan::EventSource(),
02675 Ceylan::Lockable(),
02676 Ceylan::SmartResource(),
02677 _surface( 0 ),
02678 _displayType( BackBuffer ),
02679 _mustBeLocked( false ),
02680 _needsRedraw( true )
02681 {
02682
02683
02684 Ceylan::emergencyShutdown(
02685 "Surface copy constructor called, whereas should never be used." ) ;
02686
02687 }
02688
02689
02690
02691 std::ostream & operator << ( std::ostream & os, Surface & s ) throw()
02692 {
02693 return os << s.toString() ;
02694 }
02695