00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "OSDLSurface.h"
00028
00029 #include "OSDLTypes.h"
00030 #include "OSDLVideo.h"
00031 #include "OSDLVideoTypes.h"
00032
00033 #include "OSDLVideoTypes.h"
00034 #include "OSDLUprightRectangle.h"
00035 #include "OSDLPoint2D.h"
00036 #include "OSDLLine.h"
00037 #include "OSDLFixedFont.h"
00038 #include "OSDLConic.h"
00039 #include "OSDLPixel.h"
00040 #include "OSDLPolygon.h"
00041 #include "OSDLWidget.h"
00042 #include "OSDLUtils.h"
00043 #include "OSDLGLTexture.h"
00044
00045
00046 #include "Ceylan.h"
00047
00048
00049 #include <cassert>
00050
00051
00052 #ifdef OSDL_USES_CONFIG_H
00053 #include <OSDLConfig.h>
00054 #endif // OSDL_USES_CONFIG_H
00055
00056
00057 #if OSDL_ARCH_NINTENDO_DS
00058 #include "OSDLConfigForNintendoDS.h"
00059 #endif // OSDL_ARCH_NINTENDO_DS
00060
00061
00062 #ifdef OSDL_HAVE_OPENGL
00063 #include "SDL_opengl.h"
00064 #endif // OSDL_HAVE_OPENGL
00065
00066
00067 #if OSDL_USES_SDL_GFX
00068 #include "SDL_rotozoom.h"
00069 #endif // OSDL_USES_SDL_GFX
00070
00071
00072
00073
00074 #include "OSDLIncludeCorrecter.h"
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 using std::string ;
00087 using std::list ;
00088
00089 using namespace Ceylan ;
00090 using namespace Ceylan::Log ;
00091
00092 using namespace OSDL::Video ;
00093 using namespace OSDL::Video::Pixels ;
00094 using namespace OSDL::Video::TwoDimensional ;
00095
00096
00097 using TwoDimensional::UprightRectangle ;
00098
00099
00100
00101
00102 SurfaceEvent::SurfaceEvent( Ceylan::EventSource & source ):
00103 Ceylan::Event( source )
00104 {
00105
00106 }
00107
00108
00109
00110 SurfaceEvent::~SurfaceEvent() throw()
00111 {
00112
00113 }
00114
00115
00116
00117
00118
00119 VideoMemoryLostException::VideoMemoryLostException(
00120 const std::string & message ):
00121 VideoException( message )
00122 {
00123
00124 }
00125
00126
00127
00128 VideoMemoryLostException::VideoMemoryLostException():
00129 VideoException( "Video memory lost, content needs to be reblitted" )
00130 {
00131
00132 }
00133
00134
00135
00136 VideoMemoryLostException::~VideoMemoryLostException() throw()
00137 {
00138
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 #if OSDL_USES_SDL_GFX
00151
00152
00153 const Ceylan::Flags Surface::Software = SDL_SWSURFACE ;
00154 const Ceylan::Flags Surface::Hardware = SDL_HWSURFACE ;
00155 const Ceylan::Flags Surface::AsynchronousBlit = SDL_ASYNCBLIT ;
00156 const Ceylan::Flags Surface::ExclusivePalette = SDL_HWPALETTE ;
00157 const Ceylan::Flags Surface::HardwareAcceleratedBlit = SDL_HWACCEL ;
00158 const Ceylan::Flags Surface::ColorkeyBlit = SDL_SRCCOLORKEY ;
00159 const Ceylan::Flags Surface::RLEColorkeyBlit = SDL_RLEACCEL ;
00160 const Ceylan::Flags Surface::AlphaBlendingBlit = SDL_SRCALPHA ;
00161 const Ceylan::Flags Surface::Preallocated = SDL_PREALLOC ;
00162
00163 const Ceylan::Flags OpenGLBlit = SDL_OPENGLBLIT ;
00164
00165
00166
00167 const Ceylan::Flags Surface::RLEColorkeyBlitAvailable = SDL_RLEACCELOK ;
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 const Ceylan::Flags Surface::AnyPixelFormat = SDL_ANYFORMAT ;
00178 const Ceylan::Flags Surface::DoubleBuffered = SDL_DOUBLEBUF ;
00179 const Ceylan::Flags Surface::FullScreen = SDL_FULLSCREEN ;
00180 const Ceylan::Flags Surface::OpenGL = SDL_OPENGL ;
00181 const Ceylan::Flags Surface::Resizable = SDL_RESIZABLE ;
00182
00183
00184 #else // OSDL_USES_SDL_GFX
00185
00186
00187
00188
00189 const Ceylan::Flags Surface::Software = 0x00000000 ;
00190 const Ceylan::Flags Surface::Hardware = 0x00000001 ;
00191 const Ceylan::Flags Surface::AsynchronousBlit = 0x00000004 ;
00192 const Ceylan::Flags Surface::ExclusivePalette = 0x20000000 ;
00193 const Ceylan::Flags Surface::HardwareAcceleratedBlit = 0x00000100 ;
00194 const Ceylan::Flags Surface::ColorkeyBlit = 0x00001000 ;
00195 const Ceylan::Flags Surface::RLEColorkeyBlit = 0x00004000 ;
00196 const Ceylan::Flags Surface::AlphaBlendingBlit = 0x00010000 ;
00197 const Ceylan::Flags Surface::Preallocated = 0x01000000 ;
00198
00199 const Ceylan::Flags OpenGLBlit = 0x0000000A ;
00200
00201
00202
00203 const Ceylan::Flags Surface::RLEColorkeyBlitAvailable = 0x00002000 ;
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 const Ceylan::Flags Surface::AnyPixelFormat = 0x10000000 ;
00214 const Ceylan::Flags Surface::DoubleBuffered = 0x40000000 ;
00215 const Ceylan::Flags Surface::FullScreen = 0x80000000 ;
00216 const Ceylan::Flags Surface::OpenGL = 0x00000002 ;
00217 const Ceylan::Flags Surface::Resizable = 0x00000010 ;
00218
00219
00220 #endif // OSDL_USES_SDL_GFX
00221
00222
00223
00224
00225 const Length Surface::graphAbscissaOffset = 10 ;
00226 const Length Surface::graphOrdinateOffset = 15 ;
00227
00228 const Length Surface::captionAbscissaOffset = 5 ;
00229 const Length Surface::captionOrdinateOffset = 10 ;
00230
00231
00232
00233
00234 #ifdef OSDL_COUNT_INSTANCES
00235
00236 #define CHECKPOINT(message) Ceylan::checkpoint( message )
00237
00238 #else // OSDL_COUNT_INSTANCES
00239
00240 #define CHECKPOINT(message)
00241
00242 #endif // OSDL_COUNT_INSTANCES
00243
00244
00245
00246
00247
00248 Surface::Surface( LowLevelSurface & surface, DisplayType displayType ):
00249 UprightRectangle( 0, 0, 0, 0 ),
00250 EventSource(),
00251 Lockable(),
00252 _surface( & surface ),
00253 _displayType( displayType ),
00254 _mustBeLocked( false ),
00255 _updateCount( 0 ),
00256 _needsRedraw( true )
00257 {
00258
00259 #if OSDL_USES_SDL
00260
00261 #if OSDL_DEBUG_WIDGET
00262
00263 CHECKPOINT( "Surface constructor from SDL surface." ) ;
00264
00265 LogPlug::trace( "Surface constructor from SDL surface." ) ;
00266
00267 #endif // OSDL_DEBUG_WIDGET
00268
00269 #else // OSDL_USES_SDL
00270
00271 throw VideoException( "Surface constructor failed: "
00272 "no SDL support available" ) ;
00273
00274 #endif // OSDL_USES_SDL
00275
00276 }
00277
00278
00279
00280 Surface::Surface( Flags flags, Length width, Length height, BitsPerPixel depth,
00281 Pixels::ColorMask redMask, Pixels::ColorMask greenMask,
00282 Pixels::ColorMask blueMask, Pixels::ColorMask alphaMask ):
00283 UprightRectangle( 0, 0,
00284 0, 0 ),
00285 EventSource(),
00286 Lockable(),
00287 _surface( 0 ),
00288 _displayType( BackBuffer ),
00289 _mustBeLocked( false ),
00290 _needsRedraw( true )
00291 {
00292
00293 #if OSDL_USES_SDL
00294
00295 #if OSDL_DEBUG_WIDGET
00296
00297 CHECKPOINT( "Surface constructor with full flags." ) ;
00298
00299 LogPlug::trace( "Surface constructor with flags = "
00300 + Ceylan::toString( flags, true )
00301 + ", with width = " + Ceylan::toString( width )
00302 + ", with height = " + Ceylan::toString( height )
00303 + ", with color depth = " + Ceylan::toNumericalString( depth )
00304 + ", with specified red mask = " + Ceylan::toHexString( redMask )
00305 + ", with specified green mask = " + Ceylan::toHexString( greenMask )
00306 + ", with specified blue mask = " + Ceylan::toHexString( blueMask )
00307 + ", with specified alpha mask = " + Ceylan::toHexString( alphaMask )
00308 + "." ) ;
00309
00310 #endif // OSDL_DEBUG_WIDGET
00311
00312
00313 if ( alphaMask != 0 )
00314 {
00315 flags |= AlphaBlendingBlit ;
00316
00317 }
00318 else
00319 {
00320
00321
00322
00323
00324
00325
00326
00327
00328 if ( redMask == 0 && greenMask == 0 && blueMask == 0 )
00329 Pixels::getRecommendedColorMasks( redMask, greenMask,
00330 blueMask, alphaMask ) ;
00331
00332
00333 if ( depth == 8 )
00334 alphaMask = 0 ;
00335
00336 }
00337
00338 #if OSDL_DEBUG_WIDGET
00339
00340 LogPlug::trace( "Surface constructor: actual surface flags are "
00341 + Ceylan::toString( flags, true )
00342 + ", red mask is " + Ceylan::toHexString( redMask )
00343 + ", green mask is " + Ceylan::toHexString( greenMask )
00344 + ", blue mask is " + Ceylan::toHexString( blueMask )
00345 + ", alpha mask is " + Ceylan::toHexString( alphaMask ) ) ;
00346
00347 #endif // OSDL_DEBUG_WIDGET
00348
00349 _surface = SDL_CreateRGBSurface( flags, width, height, depth,
00350 redMask, greenMask, blueMask, alphaMask ) ;
00351
00352
00353 if ( _surface == 0 )
00354 throw VideoException( "Blank surface constructor failed (width = "
00355 + Ceylan::toString( width )
00356 + ", height = " + Ceylan::toString( height ) + "): "
00357 + Utils::getBackendLastError() ) ;
00358
00359
00360
00361
00362
00363
00364
00365
00366 #else // OSDL_USES_SDL
00367
00368 throw VideoException( "Surface constructor failed: "
00369 "no SDL support available" ) ;
00370
00371 #endif // OSDL_USES_SDL
00372
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382 Surface::Surface():
00383 UprightRectangle( 0, 0, 0, 0 ),
00384 EventSource(),
00385 _surface( 0 ),
00386 _displayType( BackBuffer ),
00387 _mustBeLocked( false ),
00388 _needsRedraw( true )
00389 {
00390
00391 #if OSDL_USES_SDL
00392
00393
00394
00395 #if OSDL_DEBUG_WIDGET
00396 CHECKPOINT( "Empty Surface constructor." ) ;
00397 LogPlug::trace( "Empty Surface constructor." ) ;
00398 #endif // OSDL_DEBUG_WIDGET
00399
00400 #else // OSDL_USES_SDL
00401
00402 throw VideoException( "Surface empty constructor failed: "
00403 "no SDL support available" ) ;
00404
00405 #endif // OSDL_USES_SDL
00406
00407 }
00408
00409
00410
00411 Surface::~Surface() throw()
00412 {
00413
00414 #if OSDL_DEBUG_WIDGET
00415
00416 CHECKPOINT( "Surface destructor." ) ;
00417 LogPlug::trace( "Surface destructor, "
00418 + Ceylan::toString( _listeners.size() ) + " widget(s) registered." ) ;
00419
00420 #endif // OSDL_DEBUG_WIDGET
00421
00422 Ceylan::EventListener * widget ;
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 while ( ! _listeners.empty() )
00434 {
00435
00436 widget = _listeners.back() ;
00437 widget->unsubscribeFrom( *this ) ;
00438
00439
00440
00441
00442
00443
00444
00445 delete widget ;
00446
00447 }
00448
00449
00450 _listeners.clear() ;
00451
00452
00453 if ( _displayType == BackBuffer )
00454 flush() ;
00455
00456 }
00457
00458
00459
00460 Clonable & Surface::clone() const
00461 {
00462
00463 #if OSDL_USES_SDL
00464
00465 if ( _surface != 0 )
00466 {
00467
00468 #ifdef OSDL_USE_DEPRECATED_CLONING
00469
00470
00471
00472
00473 Pixels::ColorMask redMask, greenMask, blueMask, alphaMask ;
00474 Pixels::getCurrentColorMasks( getPixelFormat(),
00475 redMask, greenMask, blueMask, alphaMask ) ;
00476
00477
00478 LowLevelSurface * copied = SDL_CreateRGBSurface( getFlags(),
00479 getWidth(), getHeight(), getBitsPerPixel(),
00480 redMask, greenMask, blueMask, alphaMask ) ;
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 int returned = SDL_BlitSurface( _surface, 0, copied, 0 ) ;
00492 if ( returned != 0 )
00493 throw ClonableException( "Surface::clone: blit failed (returned "
00494 + Ceylan::toString( returned ) + "): "
00495 + Utils::getBackendLastError() + "." ) ;
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 #endif // OSDL_USE_DEPRECATED_CLONING
00507
00508
00509
00510 LowLevelSurface * copied = SDL_ConvertSurface( _surface,
00511 & getPixelFormat(), getFlags() ) ;
00512
00513
00514 if ( copied == 0 )
00515 throw ClonableException(
00516 "Surface::clone: creation of clone surface failed: "
00517 + Utils::getBackendLastError() + "." ) ;
00518
00519 return * new Surface( * copied,
00520 BackBuffer ) ;
00521
00522 }
00523 else
00524 {
00525 LogPlug::warning( "Surface::clone: cloning a mostly blank surface." ) ;
00526 return * new Surface() ;
00527 }
00528
00529 #else // OSDL_USES_SDL
00530
00531 throw ClonableException( "Surface::clone failed:"
00532 "no SDL support available" ) ;
00533
00534 #endif // OSDL_USES_SDL
00535
00536 }
00537
00538
00539
00540 LowLevelSurface & Surface::getSDLSurface() const
00541 {
00542
00543
00544 return * _surface ;
00545
00546 }
00547
00548
00549
00550 void Surface::setSDLSurface( LowLevelSurface & newSurface,
00551 DisplayType displayType )
00552 {
00553
00554
00555 flush() ;
00556
00557 _surface = & newSurface ;
00558 _displayType = displayType ;
00559
00560 }
00561
00562
00563
00564 Surface::DisplayType Surface::getDisplayType() const
00565 {
00566
00567 return _displayType ;
00568
00569 }
00570
00571
00572
00573 void Surface::setDisplayType( DisplayType newDisplayType )
00574 {
00575
00576 _displayType = newDisplayType ;
00577
00578 }
00579
00580
00581
00582 Ceylan::Flags Surface::getFlags() const
00583 {
00584
00585 #if OSDL_USES_SDL
00586
00587 return _surface->flags ;
00588
00589 #else // OSDL_USES_SDL
00590
00591 return 0 ;
00592
00593 #endif // OSDL_USES_SDL
00594
00595 }
00596
00597
00598
00599 void Surface::setFlags( Flags newFlags )
00600 {
00601
00602 #if OSDL_USES_SDL
00603
00604
00605 _surface->flags = newFlags ;
00606
00607 #endif // OSDL_USES_SDL
00608
00609 }
00610
00611
00612
00613 void Surface::convertToDisplay( bool alphaChannelWanted )
00614 {
00615
00616 #if OSDL_USES_SDL
00617
00618 if ( _surface == 0 )
00619 throw VideoException(
00620 "Surface::convertToDisplay: no available internal surface." ) ;
00621
00622 LowLevelSurface * old = _surface ;
00623
00624 if ( alphaChannelWanted )
00625 _surface = SDL_DisplayFormatAlpha( old ) ;
00626 else
00627 _surface = SDL_DisplayFormat( old ) ;
00628
00629 SDL_FreeSurface( old ) ;
00630
00631 if ( _surface == 0 )
00632 throw VideoException(
00633 "Surface::convertToDisplay: conversion failed." ) ;
00634
00635 #else // OSDL_USES_SDL
00636
00637 throw VideoException( "Surface::convertToDisplay failed: "
00638 "no SDL support available" ) ;
00639
00640 #endif // OSDL_USES_SDL
00641
00642 }
00643
00644
00645
00646 void Surface::setAlpha( Flags flags, Pixels::ColorElement newAlpha )
00647 {
00648
00649 #if OSDL_USES_SDL
00650
00651 if ( SDL_SetAlpha( _surface, flags, newAlpha ) != 0 )
00652 throw VideoException( "Surface::setAlpha failed: "
00653 + Utils::getBackendLastError() ) ;
00654
00655 #else // OSDL_USES_SDL
00656
00657 throw VideoException( "Surface::setAlpha failed: "
00658 "no SDL support available" ) ;
00659
00660 #endif // OSDL_USES_SDL
00661
00662 }
00663
00664
00665
00666 ColorDefinition Surface::guessColorKeyDefinition() const
00667 {
00668
00669 return Pixels::convertPixelColorToColorDefinition( getPixelFormat(),
00670 guessColorKey() ) ;
00671
00672 }
00673
00674
00675
00676 PixelColor Surface::guessColorKey() const
00677 {
00678
00679 Length width = getWidth() ;
00680 Length height = getHeight() ;
00681
00682 if ( width == 0 || height == 0 )
00683 throw VideoException( "Surface::guessColorKey failed: "
00684 "surface too small" ) ;
00685
00686 PixelColor firstCandidate = getPixelColorAt( 0, 0 ) ;
00687
00688 PixelColor secondCandidate = getPixelColorAt( width-1, height-1 ) ;
00689
00690 if ( Pixels::areEqual( firstCandidate, secondCandidate ) )
00691 return firstCandidate ;
00692
00693
00694
00695 PixelColor thirdCandidate = getPixelColorAt( width-1, 0 ) ;
00696
00697
00698 if ( Pixels::areEqual( firstCandidate, thirdCandidate ) )
00699 return firstCandidate ;
00700
00701 if ( Pixels::areEqual( secondCandidate, thirdCandidate ) )
00702 return secondCandidate ;
00703
00704 throw VideoException( "Surface::guessColorKey failed: "
00705 "three different colorkey candidates found" ) ;
00706
00707
00708 }
00709
00710
00711
00712 void Surface::setColorKey( Flags flags, Pixels::PixelColor keyPixelColor )
00713 {
00714
00715 #if OSDL_USES_SDL
00716
00717 if ( SDL_SetColorKey( _surface, flags, keyPixelColor ) != 0 )
00718 throw VideoException( "Surface::setColorKey (pixel color) failed: "
00719 + Utils::getBackendLastError() ) ;
00720
00721 #else // OSDL_USES_SDL
00722
00723 throw VideoException( "Surface::setColorKey failed: "
00724 "no SDL support available" ) ;
00725
00726 #endif // OSDL_USES_SDL
00727
00728
00729 }
00730
00731
00732
00733 void Surface::setColorKey( Flags flags, Pixels::ColorDefinition keyColorDef )
00734 {
00735
00736 #if OSDL_USES_SDL
00737
00738 Pixels::PixelColor keyPixelColor =
00739 Pixels::convertColorDefinitionToPixelColor( getPixelFormat(),
00740 keyColorDef ) ;
00741
00742 if ( SDL_SetColorKey( _surface, flags, keyPixelColor ) != 0 )
00743 throw VideoException(
00744 "Surface::setColorKey (color definition) failed: "
00745 + Utils::getBackendLastError() ) ;
00746
00747 #else // OSDL_USES_SDL
00748
00749 throw VideoException( "Surface::setColorKey failed: "
00750 "no SDL support available" ) ;
00751
00752 #endif // OSDL_USES_SDL
00753
00754 }
00755
00756
00757
00758 void Surface::convertFromColorKeyToAlphaChannel()
00759 {
00760
00761 if ( ( getFlags() & ColorkeyBlit ) == 0 )
00762 throw VideoException( "Surface::convertFromColorKeyToAlphaChannel: "
00763 "this surface does not use color key apparently: "
00764 + toString( Ceylan::low ) ) ;
00765
00766 convertToDisplay( true ) ;
00767
00768 }
00769
00770
00771
00772 Palette & Surface::getPalette() const
00773 {
00774
00775 #if OSDL_USES_SDL
00776
00777 if ( _surface->format->palette == 0 )
00778 throw VideoException( "Surface::getPalette failed: "
00779 "no available palette" ) ;
00780
00781 LogPlug::debug( "Surface::getPalette: low-level palette found." ) ;
00782
00783 return * new Palette( *_surface->format->palette ) ;
00784
00785 #else // OSDL_USES_SDL
00786
00787 throw VideoException( "Surface::getPalette failed: "
00788 "no SDL support available" ) ;
00789
00790 #endif // OSDL_USES_SDL
00791
00792 }
00793
00794
00795
00796 bool Surface::setPalette( const Palette & newPalette,
00797 ColorCount startingColorIndex, ColorCount numberOfColors,
00798 Flags targetedPalettes )
00799 {
00800
00801 #if OSDL_USES_SDL
00802
00803 if ( numberOfColors == 0 )
00804 {
00805
00806 if ( newPalette.getNumberOfColors() > startingColorIndex )
00807 {
00808 numberOfColors =
00809 newPalette.getNumberOfColors() - startingColorIndex ;
00810 }
00811 else
00812 {
00813
00814 throw VideoException( "Surface::setPalette failed: "
00815 "starting index out of bounds." ) ;
00816
00817 }
00818
00819 }
00820 else if ( startingColorIndex + numberOfColors >
00821 newPalette.getNumberOfColors() )
00822 {
00823
00824 throw VideoException( "Surface::setPalette failed: "
00825 "too many color index, out of bounds." ) ;
00826
00827 }
00828
00829
00830
00831
00832
00833
00834 return ( SDL_SetPalette( _surface, targetedPalettes,
00835 newPalette.getColorDefinitions(), startingColorIndex,
00836 numberOfColors ) == 1 ) ;
00837
00838 #else // OSDL_USES_SDL
00839
00840 throw VideoException( "Surface::setPalette failed: "
00841 "no SDL support available" ) ;
00842
00843 #endif // OSDL_USES_SDL
00844
00845 }
00846
00847
00848
00849 Surface & Surface::createColorReducedSurfaceFor( const Palette & palette,
00850 bool manageColorkey ) const
00851 {
00852
00853
00854 PixelColor sourceColorkey ;
00855
00856 if ( manageColorkey )
00857 sourceColorkey = guessColorKey() ;
00858
00859
00860 Length targetWidth = getWidth() ;
00861 Length targetHeight = getHeight() ;
00862
00863 Surface * res = new Surface( Software, targetWidth,
00864 targetHeight, 8 ) ;
00865
00866 res->setPalette( palette ) ;
00867
00868 PixelColor current ;
00869 ColorCount index ;
00870
00871
00872 for ( Length y = 0; y < targetHeight; y++ )
00873 for ( Length x = 0; x < targetWidth; x++ )
00874 {
00875
00876 current = getPixelColorAt( x, y ) ;
00877
00878 if ( manageColorkey && Pixels::areEqual( current, sourceColorkey ) )
00879 {
00880
00881 index = palette.getColorKeyIndex() ;
00882
00883 }
00884 else
00885 {
00886
00887
00888 ColorDefinition colorDef =
00889 Pixels::convertPixelColorToColorDefinition(
00890 getPixelFormat(), current ) ;
00891
00892
00893 index = palette.getClosestColorIndexTo( colorDef ) ;
00894
00895 }
00896
00897
00898
00899 res->putPixelColorAt( x, y, static_cast<PixelColor>( index ),
00900 AlphaOpaque, false,
00901 false, false ) ;
00902
00903 }
00904
00905 return *res ;
00906
00907 }
00908
00909
00910
00911 Pixels::PixelFormat & Surface::getPixelFormat() const
00912 {
00913
00914 #if OSDL_USES_SDL
00915
00916 if ( _surface->format == 0 )
00917 throw VideoException( "Surface::getPixelFormat failed: "
00918 "no pixel format available." ) ;
00919
00920 return * _surface->format ;
00921
00922 #else // OSDL_USES_SDL
00923
00924 throw VideoException( "Surface::getPixelFormat failed: "
00925 "no SDL support available" ) ;
00926
00927 #endif // OSDL_USES_SDL
00928
00929 }
00930
00931
00932
00933 void Surface::setPixelFormat( Pixels::PixelFormat & newFormat )
00934 {
00935
00936 #if OSDL_USES_SDL
00937
00938 _surface->format = & newFormat ;
00939
00940 #endif // OSDL_USES_SDL
00941
00942 }
00943
00944
00945
00946 bool Surface::fill( Pixels::ColorDefinition colorDef )
00947 {
00948
00949 #if OSDL_DEBUG_SURFACE
00950
00951 LogPlug::trace( "Surface::fill in rectangular area from ["
00952 + Ceylan::toString( _x ) + ";"
00953 + Ceylan::toString( _y ) + "] to ["
00954 + Ceylan::toString( _x + getWidth() ) + ";"
00955 + Ceylan::toString( _y + getHeight() ) + "]" ) ;
00956
00957 #endif // OSDL_DEBUG_SURFACE
00958
00959
00960 return drawBox( *this,
00961 colorDef, true ) ;
00962
00963 }
00964
00965
00966
00967 bool Surface::clear()
00968 {
00969
00970 if ( _displayType == OpenGLScreenSurface )
00971 {
00972
00973 #ifdef OSDL_USES_OPENGL
00974
00975
00976
00977
00978
00979
00980
00981 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
00982
00983 return true ;
00984
00985 #else // OSDL_USES_OPENGL
00986
00987 throw VideoException( "Surface::clear: no OpenGL support available." ) ;
00988
00989 #endif // OSDL_USES_OPENGL
00990
00991 }
00992 else
00993 {
00994
00995 return fill( Pixels::Black ) ;
00996
00997 }
00998
00999 }
01000
01001
01002
01003 Surface & Surface::flipVertical() const
01004 {
01005
01006 #if OSDL_USES_SDL
01007
01008 LowLevelSurface * result = SDL_CreateRGBSurface(
01009 _surface->flags,
01010 _surface->w,
01011 _surface->h,
01012 _surface->format->BytesPerPixel * 8,
01013 _surface->format->Rmask,
01014 _surface->format->Gmask,
01015 _surface->format->Bmask,
01016 _surface->format->Amask ) ;
01017
01018 BytesPerPixel bpp = _surface->format->BytesPerPixel ;
01019
01020 Ceylan::Uint16 scanline = _surface->pitch ;
01021
01022 Ceylan::Uint8 * src =
01023 reinterpret_cast<Ceylan::Uint8 *>( _surface->pixels ) ;
01024
01025 Ceylan::Uint8 * target =
01026 reinterpret_cast<Ceylan::Uint8 *>( result->pixels ) + scanline - bpp ;
01027
01028 const Coordinate height = result->h ;
01029 const Coordinate width = result->w ;
01030
01031
01032
01033
01034
01035
01036
01037 for ( Coordinate y = 0; y < height; y++ )
01038 for ( Coordinate x = 0; x < width; x++ )
01039 ::memcpy( target + ( ( scanline * y ) - ( x * bpp ) ),
01040 src + ( ( scanline * y ) + ( x * bpp ) ), bpp ) ;
01041
01042 return * new Surface( * result ) ;
01043
01044 #else // OSDL_USES_SDL
01045
01046 throw VideoException( "Surface::flipVertical failed: "
01047 "no SDL support available" ) ;
01048
01049 #endif // OSDL_USES_SDL
01050
01051 }
01052
01053
01054
01055 Surface & Surface::flipHorizontal() const
01056 {
01057
01058 #if OSDL_USES_SDL
01059
01060 LowLevelSurface * result = SDL_CreateRGBSurface(
01061 _surface->flags,
01062 _surface->w,
01063 _surface->h,
01064 _surface->format->BytesPerPixel * 8,
01065 _surface->format->Rmask,
01066 _surface->format->Gmask,
01067 _surface->format->Bmask,
01068 _surface->format->Amask ) ;
01069
01070 Ceylan::Uint16 scanline = _surface->pitch ;
01071
01072 Ceylan::Uint8 * src =
01073 reinterpret_cast<Ceylan::Uint8 *>( _surface->pixels ) ;
01074
01075 Ceylan::Uint8 * target =
01076 reinterpret_cast<Ceylan::Uint8 *>( result->pixels )
01077 + result->pitch * ( result->h - 1 ) ;
01078
01079 const Coordinate height = result->h ;
01080
01081
01082
01083 for ( Coordinate y = 0; y < height; y++ )
01084 ::memcpy ( target - ( scanline * y ),
01085 src + ( scanline * y ), scanline ) ;
01086
01087 return * new Surface( * result ) ;
01088
01089 #else // OSDL_USES_SDL
01090
01091 throw VideoException( "Surface::flipHorizontal failed: "
01092 "no SDL support available" ) ;
01093
01094 #endif // OSDL_USES_SDL
01095
01096 }
01097
01098
01099
01100 string Surface::describePixelAt( Coordinate x, Coordinate y )
01101 {
01102
01103 string res = "Pixel at [" + Ceylan::toString( x ) + ";"
01104 + Ceylan::toString( y ) + "]: " ;
01105
01106 lock() ;
01107 PixelColor p = getPixelColorAt( x, y ) ;
01108 unlock() ;
01109
01110 res += "pixel color is " + Ceylan::toHexString( p ) + ": " ;
01111
01112 return res + Pixels::toString( p, getPixelFormat() ) ;
01113
01114 }
01115
01116
01117
01118 Pitch Surface::getPitch() const
01119 {
01120
01121 #if OSDL_USES_SDL
01122
01123 return _surface->pitch ;
01124
01125 #else // OSDL_USES_SDL
01126
01127 return 0 ;
01128
01129 #endif // OSDL_USES_SDL
01130
01131 }
01132
01133
01134
01135 void Surface::setPitch( Pitch newPitch )
01136 {
01137
01138 #if OSDL_USES_SDL
01139
01140 _surface->pitch = newPitch ;
01141
01142 #endif // OSDL_USES_SDL
01143
01144 }
01145
01146
01147
01148 Length Surface::getWidth() const
01149 {
01150
01151 #if OSDL_USES_SDL
01152
01153 return _surface->w ;
01154
01155 #else // OSDL_USES_SDL
01156
01157 return 0 ;
01158
01159 #endif // OSDL_USES_SDL
01160
01161 }
01162
01163
01164
01165 void Surface::setWidth( Length newWidth )
01166 {
01167
01168 resize( newWidth, getHeight() ) ;
01169
01170 }
01171
01172
01173
01174 Length Surface::getHeight() const
01175 {
01176
01177 #if OSDL_USES_SDL
01178
01179 return _surface->h ;
01180
01181 #else // OSDL_USES_SDL
01182
01183 return 0 ;
01184
01185 #endif // OSDL_USES_SDL
01186
01187 }
01188
01189
01190
01191 void Surface::setHeight( Length newHeight )
01192 {
01193
01194 resize( getWidth(), newHeight ) ;
01195
01196 }
01197
01198
01199
01200 void Surface::resize( Length newWidth, Length newHeight, bool scaleContent )
01201 {
01202
01203 #if OSDL_USES_SDL
01204
01205 if ( ( newWidth == getWidth() ) && ( newHeight == getHeight() ) )
01206 return ;
01207
01208
01209 Pixels::ColorMask redMask, greenMask, blueMask, alphaMask ;
01210
01211 Pixels::getCurrentColorMasks( getPixelFormat(),
01212 redMask, greenMask, blueMask, alphaMask ) ;
01213
01214
01215 LowLevelSurface * resized = SDL_CreateRGBSurface( getFlags(),
01216 newWidth, newHeight, getBitsPerPixel(),
01217 redMask, greenMask, blueMask, alphaMask ) ;
01218
01219
01220 if ( resized == 0 )
01221 Ceylan::emergencyShutdown(
01222 "Surface::resize: creation of newer internal surface failed: "
01223 + Utils::getBackendLastError() ) ;
01224
01225
01226
01227 Flags colorKeyFlags = getFlags() & ( ColorkeyBlit | RLEColorkeyBlit ) ;
01228 Pixels::PixelColor colorkey = _surface->format->colorkey ;
01229
01230
01231 resized->format->alpha = _surface->format->alpha ;
01232
01233
01234
01235 Surface * zoomed ;
01236
01237 if ( scaleContent )
01238 {
01239
01240 try
01241 {
01242
01243 zoomed = & zoom(
01244 static_cast<Ceylan::Maths::Real>( newWidth ) / getWidth(),
01245 static_cast<Ceylan::Maths::Real>( newHeight ) / getHeight(),
01246 VideoModule::GetAntiAliasingState() ) ;
01247
01248 }
01249 catch( const VideoException & e )
01250 {
01251 Ceylan::emergencyShutdown(
01252 "Surface::resize: creation of scaled surface failed: "
01253 + e.toString() ) ;
01254 }
01255
01256 }
01257
01258 SDL_FreeSurface( _surface ) ;
01259
01260 _surface = resized ;
01261
01262 setColorKey( colorKeyFlags, colorkey ) ;
01263
01264 if ( scaleContent )
01265 {
01266
01267 try
01268 {
01269
01270 zoomed->blitTo( * this ) ;
01271 delete zoomed ;
01272
01273 }
01274 catch( const VideoException & e )
01275 {
01276 Ceylan::emergencyShutdown(
01277 "Surface::resize: blit of scaled surface failed: "
01278 + e.toString() ) ;
01279 }
01280
01281 }
01282 else
01283 {
01284 setRedrawState( true ) ;
01285 }
01286
01287 #else // OSDL_USES_SDL
01288
01289 throw VideoException( "Surface::resize failed: "
01290 "no SDL support available" ) ;
01291
01292 #endif // OSDL_USES_SDL
01293
01294 }
01295
01296
01297
01298 BitsPerPixel Surface::getBitsPerPixel() const
01299 {
01300
01301 #if OSDL_USES_SDL
01302
01303 return _surface->format->BitsPerPixel ;
01304
01305 #else // OSDL_USES_SDL
01306
01307 return 0 ;
01308
01309 #endif // OSDL_USES_SDL
01310
01311 }
01312
01313
01314
01315 void Surface::setBitsPerPixel( BitsPerPixel newBitsPerPixel )
01316 {
01317
01318 #if OSDL_USES_SDL
01319
01320 _surface->format->BitsPerPixel = newBitsPerPixel ;
01321
01322
01323
01324 #endif // OSDL_USES_SDL
01325
01326 }
01327
01328
01329
01330 BytesPerPixel Surface::getBytesPerPixel() const
01331 {
01332
01333 #if OSDL_USES_SDL
01334
01335 return _surface->format->BytesPerPixel ;
01336
01337 #else // OSDL_USES_SDL
01338
01339 return 0 ;
01340
01341 #endif // OSDL_USES_SDL
01342
01343 }
01344
01345
01346
01347 void Surface::setBytesPerPixel( BytesPerPixel newBytesPerPixel )
01348 {
01349
01350 #if OSDL_USES_SDL
01351
01352 _surface->format->BytesPerPixel = newBytesPerPixel ;
01353
01354
01355
01356 #endif // OSDL_USES_SDL
01357
01358 }
01359
01360
01361
01362 void * Surface::getPixels() const
01363 {
01364
01365 #if OSDL_USES_SDL
01366
01367 return _surface->pixels ;
01368
01369 #else // OSDL_USES_SDL
01370
01371 return 0 ;
01372
01373 #endif // OSDL_USES_SDL
01374
01375 }
01376
01377
01378
01379 void Surface::setPixels( void * newPixels )
01380 {
01381
01382 #if OSDL_USES_SDL
01383
01384 _surface->pixels = newPixels ;
01385
01386 #endif // OSDL_USES_SDL
01387
01388 }
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398 Pixels::PixelColor Surface::getPixelColorAt( Coordinate x, Coordinate y ) const
01399
01400 {
01401
01402 return Pixels::getPixelColor( *this, x, y ) ;
01403
01404 }
01405
01406
01407
01408 Pixels::ColorDefinition Surface::getColorDefinitionAt(
01409 Coordinate x, Coordinate y ) const
01410 {
01411
01412 return Pixels::convertPixelColorToColorDefinition( getPixelFormat(),
01413 Pixels::getPixelColor( *this, x, y ) ) ;
01414
01415 }
01416
01417
01418
01419 void Surface::putRGBAPixelAt( Coordinate x, Coordinate y,
01420 ColorElement red, ColorElement green, ColorElement blue,
01421 ColorElement alpha,
01422 bool blending, bool clipping, bool locking )
01423 {
01424
01425 Pixels::putRGBAPixel( *this, x, y, red, green, blue, alpha,
01426 blending, clipping, locking ) ;
01427
01428 }
01429
01430
01431
01432 void Surface::putColorDefinitionAt( Coordinate x, Coordinate y,
01433 ColorDefinition colorDef,
01434 bool blending, bool clipping, bool locking )
01435 {
01436
01437 Pixels::putRGBAPixel( *this, x, y, colorDef.r, colorDef.g, colorDef.b,
01438 colorDef.unused, blending, clipping, locking ) ;
01439
01440 }
01441
01442
01443
01444 void Surface::putPixelColorAt( Coordinate x, Coordinate y,
01445 PixelColor convertedColor, ColorElement alpha,
01446 bool blending, bool clipping, bool locking )
01447 {
01448
01449 Pixels::putPixelColor( *this, x, y, convertedColor, alpha,
01450 blending, clipping, locking ) ;
01451
01452 }
01453
01454
01455
01456 bool Surface::setAlphaForColor( Pixels::ColorDefinition colorDef,
01457 Pixels::ColorElement newAlpha )
01458 {
01459
01460 #if OSDL_DEBUG_COLOR
01461
01462 LogPlug::trace(
01463 "Surface::setAlphaForColor: scanning for color definition "
01464 + Pixels::toString( colorDef )
01465 + ", so that its alpha coordinate gets replaced by "
01466 + Ceylan::toNumericalString( newAlpha ) ) ;
01467
01468 #endif // OSDL_DEBUG_COLOR
01469
01470
01471
01472
01473
01474
01475 if ( ( getFlags() & AlphaBlendingBlit ) == 0 )
01476 return false ;
01477
01478 ColorDefinition currentDef ;
01479
01480 lock() ;
01481
01482 Length height = getHeight() ;
01483 Length width = getWidth() ;
01484
01485 for ( Coordinate y = 0; y < height; y++ )
01486 for ( Coordinate x = 0; x < width; x++ )
01487 {
01488
01489 currentDef = getColorDefinitionAt( x, y ) ;
01490
01491
01492 if ( Pixels::areEqual( currentDef, colorDef,
01493 false ) )
01494 {
01495
01496 #if OSDL_DEBUG_PIXEL
01497 if ( x % 20 == 0 && y % 20 == 0 )
01498 LogPlug::debug(
01499 "Surface::setAlphaForColor: replacing alpha of "
01500 + Pixels::toString( currentDef ) + " with new alpha = "
01501 + Ceylan::toNumericalString( newAlpha ) + " at ["
01502 + Ceylan::toString( x ) + ";" + Ceylan::toString( y )
01503 + "]" ) ;
01504 #endif // OSDL_DEBUG_PIXEL
01505
01506 currentDef.unused = newAlpha ;
01507
01508 putColorDefinitionAt( x, y, currentDef,
01509
01510 false ) ;
01511
01512 #if OSDL_DEBUG_PIXEL
01513
01514
01515 if ( x % 20 == 0 && y % 20 == 0 )
01516 {
01517
01518 ColorDefinition readDef = getColorDefinitionAt( x, y ) ;
01519
01520 if ( ! Pixels::areEqual( readDef, currentDef,
01521 true ) )
01522 LogPlug::error( "Surface::setAlphaForColor: "
01523 "alpha replacement failed: expecting "
01524 + Pixels::toString( readDef )
01525 + ", read " + Pixels::toString( currentDef ) ) ;
01526 }
01527
01528 #endif // OSDL_DEBUG_PIXEL
01529
01530 }
01531 else
01532 {
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542 }
01543
01544 }
01545
01546 unlock() ;
01547
01548 return true ;
01549
01550 }
01551
01552
01553
01554
01555 bool Surface::drawHorizontalLine( Coordinate xStart, Coordinate xStop,
01556 Coordinate y, Pixels::ColorElement red, Pixels::ColorElement green,
01557 Pixels::ColorElement blue, Pixels::ColorElement alpha )
01558 {
01559
01560 return Line::drawHorizontal( *this, xStart, xStop, y,
01561 red, green, blue, alpha ) ;
01562
01563 }
01564
01565
01566
01567 bool Surface::drawHorizontalLine( Coordinate xStart, Coordinate xStop,
01568 Coordinate y, Pixels::PixelColor actualColor )
01569 {
01570
01571 return Line::drawHorizontal( *this, xStart, xStop, y, actualColor ) ;
01572
01573 }
01574
01575
01576
01577 bool Surface::drawHorizontalLine( Coordinate xStart, Coordinate xStop,
01578 Coordinate y, Pixels::ColorDefinition colorDef )
01579 {
01580
01581 return Line::drawHorizontal( *this, xStart, xStop, y, colorDef ) ;
01582
01583 }
01584
01585
01586
01587
01588 bool Surface::drawVerticalLine( Coordinate x, Coordinate yStart,
01589 Coordinate yStop, Pixels::ColorElement red, Pixels::ColorElement green,
01590 Pixels::ColorElement blue, Pixels::ColorElement alpha)
01591 {
01592
01593 return Line::drawVertical( *this, x, yStart, yStop,
01594 red, green, blue, alpha ) ;
01595
01596 }
01597
01598
01599
01600 bool Surface::drawVerticalLine( Coordinate x, Coordinate yStart,
01601 Coordinate yStop, Pixels::ColorDefinition colorDef )
01602 {
01603
01604 return Line::drawVertical( *this, x, yStart, yStop, colorDef ) ;
01605
01606 }
01607
01608
01609
01610
01611 bool Surface::drawLine( Coordinate xStart, Coordinate yStart,
01612 Coordinate xStop, Coordinate yStop,
01613 Pixels::ColorElement red, Pixels::ColorElement green,
01614 Pixels::ColorElement blue, Pixels::ColorElement alpha )
01615 {
01616
01617 return Line::draw( *this, xStart, yStart, xStop, yStop,
01618 red, green, blue, alpha ) ;
01619
01620 }
01621
01622
01623
01624 bool Surface::drawLine( Coordinate xStart, Coordinate yStart,
01625 Coordinate xStop, Coordinate yStop, Pixels::ColorDefinition colorDef )
01626 {
01627
01628 return Line::draw( *this, xStart, yStart, xStop, yStop, colorDef ) ;
01629
01630 }
01631
01632
01633
01634
01635 bool Surface::drawCross( const Point2D & center,
01636 Pixels::ColorDefinition colorDef, Length squareEdge )
01637 {
01638
01639 return Line::drawCross( *this, center, colorDef, squareEdge ) ;
01640
01641 }
01642
01643
01644
01645 bool Surface::drawCross( Coordinate xCenter, Coordinate yCenter,
01646 Pixels::ColorDefinition colorDef, Length squareEdge )
01647 {
01648
01649 return Line::drawCross( *this, xCenter, yCenter, colorDef, squareEdge ) ;
01650
01651 }
01652
01653
01654
01655 bool Surface::drawEdges( Pixels::ColorDefinition edgeColor, Length edgeWidth )
01656 {
01657
01658 Coordinate xmin = 0 ;
01659 Coordinate xmax = getWidth() - 1 ;
01660
01661 Coordinate ymin = 0 ;
01662 Coordinate ymax = getHeight() - 1 ;
01663
01664 while ( edgeWidth != 0 )
01665 {
01666
01667 if ( ! drawVerticalLine( xmin, ymin, ymax, edgeColor ) )
01668 return false ;
01669
01670 if ( ! drawVerticalLine( xmax, ymin, ymax, edgeColor ) )
01671 return false ;
01672
01673 if ( ! drawHorizontalLine( xmin, xmax, ymin, edgeColor ) )
01674 return false ;
01675
01676 if ( ! drawHorizontalLine( xmin, xmax, ymax, edgeColor ) )
01677 return false ;
01678
01679 edgeWidth-- ;
01680
01681 xmin++ ;
01682 xmax -- ;
01683
01684 ymin++ ;
01685 ymax-- ;
01686 }
01687
01688 return true ;
01689
01690 }
01691
01692
01693
01694 bool Surface::drawBox( const UprightRectangle & rectangle,
01695 Pixels::ColorElement red, Pixels::ColorElement green,
01696 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled )
01697 {
01698
01699 return rectangle.draw( *this, red, green, blue, alpha, filled ) ;
01700
01701 }
01702
01703
01704
01705 bool Surface::drawBox( const UprightRectangle & rectangle,
01706 Pixels::ColorDefinition colorDef, bool filled )
01707 {
01708
01709 return rectangle.draw( *this, colorDef, filled ) ;
01710
01711 }
01712
01713
01714
01715
01716 bool Surface::drawCircle( Coordinate xCenter, Coordinate yCenter,
01717 Length radius, Pixels::ColorElement red, Pixels::ColorElement green,
01718 Pixels::ColorElement blue, Pixels::ColorElement alpha,
01719 bool filled, bool blended )
01720 {
01721
01722 return TwoDimensional::drawCircle( *this, xCenter, yCenter, radius,
01723 red, green, blue, alpha, filled, blended ) ;
01724
01725 }
01726
01727
01728
01729 bool Surface::drawCircle( Coordinate xCenter, Coordinate yCenter,
01730 Length radius, Pixels::ColorDefinition colorDef,
01731 bool filled, bool blended )
01732 {
01733
01734 return TwoDimensional::drawCircle( *this, xCenter, yCenter, radius,
01735 colorDef, filled, blended ) ;
01736
01737 }
01738
01739
01740
01741 bool Surface::drawDiscWithEdge( Coordinate xCenter, Coordinate yCenter,
01742 Length outerRadius, Length innerRadius,
01743 Pixels::ColorDefinition ringColorDef,
01744 Pixels::ColorDefinition discColorDef, bool blended )
01745 {
01746
01747 return TwoDimensional::drawDiscWithEdge( *this, xCenter, yCenter,
01748 outerRadius, innerRadius, ringColorDef, discColorDef, blended ) ;
01749
01750 }
01751
01752
01753
01754 bool Surface::drawEllipse( Coordinate xCenter, Coordinate yCenter,
01755 Length horizontalRadius, Length verticalRadius,
01756 Pixels::ColorElement red, Pixels::ColorElement green,
01757 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled )
01758 {
01759
01760 return TwoDimensional::drawEllipse( *this, xCenter, yCenter,
01761 horizontalRadius, verticalRadius, red, green, blue, alpha, filled ) ;
01762
01763 }
01764
01765
01766
01767 bool Surface::drawEllipse( Coordinate xCenter, Coordinate yCenter,
01768 Length horizontalRadius, Length verticalRadius,
01769 Pixels::ColorDefinition colorDef, bool filled )
01770 {
01771
01772 return TwoDimensional::drawEllipse( *this, xCenter, yCenter,
01773 horizontalRadius, verticalRadius, colorDef, filled ) ;
01774
01775 }
01776
01777
01778
01779 bool Surface::drawPie( Coordinate xCenter, Coordinate yCenter, Length radius,
01780 Ceylan::Maths::AngleInDegrees angleStart,
01781 Ceylan::Maths::AngleInDegrees angleStop,
01782 Pixels::ColorElement red, Pixels::ColorElement green,
01783 Pixels::ColorElement blue, Pixels::ColorElement alpha )
01784 {
01785
01786 return TwoDimensional::drawPie( *this, xCenter, yCenter, radius,
01787 angleStart, angleStop, red, green, blue, alpha ) ;
01788
01789 }
01790
01791
01792
01793 bool Surface::drawPie( Coordinate xCenter, Coordinate yCenter, Length radius,
01794 Ceylan::Maths::AngleInDegrees angleStart,
01795 Ceylan::Maths::AngleInDegrees angleStop,
01796 Pixels::ColorDefinition colorDef )
01797 {
01798
01799 return TwoDimensional::drawPie( *this, xCenter, yCenter,
01800 radius, angleStart, angleStop, colorDef ) ;
01801
01802 }
01803
01804
01805
01806
01807 bool Surface::drawTriangle( Coordinate x1, Coordinate y1,
01808 Coordinate x2, Coordinate y2, Coordinate x3, Coordinate y3,
01809 Pixels::ColorElement red, Pixels::ColorElement green,
01810 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled )
01811 {
01812
01813 return TwoDimensional::drawTriangle( *this, x1, y1, x2, y2, x3, y3,
01814 red, green, blue, alpha, filled ) ;
01815
01816 }
01817
01818
01819
01820 bool Surface::drawTriangle( Coordinate x1, Coordinate y1,
01821 Coordinate x2, Coordinate y2, Coordinate x3, Coordinate y3,
01822 Pixels::ColorDefinition colorDef, bool filled )
01823 {
01824
01825 return TwoDimensional::drawTriangle( *this, x1, y1, x2, y2, x3, y3,
01826 colorDef, filled ) ;
01827
01828 }
01829
01830
01831
01832 bool Surface::drawTriangle( const Point2D & p1, const Point2D & p2,
01833 const Point2D & p3,
01834 Pixels::ColorElement red, Pixels::ColorElement green,
01835 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled )
01836 {
01837
01838 return TwoDimensional::drawTriangle( *this, p1, p2, p3,
01839 red, green, blue, alpha, filled ) ;
01840
01841 }
01842
01843
01844
01845 bool Surface::drawTriangle( const Point2D & p1, const Point2D & p2,
01846 const Point2D & p3, Pixels::ColorDefinition colorDef, bool filled )
01847 {
01848
01849 return TwoDimensional::drawTriangle( *this, p1, p2, p3,
01850 colorDef, filled ) ;
01851
01852 }
01853
01854
01855
01856 bool Surface::drawPolygon( const list<Point2D *> summits,
01857 Coordinate x, Coordinate y,
01858 Pixels::ColorDefinition colorDef, bool filled )
01859 {
01860
01861 return TwoDimensional::drawPolygon( *this, summits, x, y,
01862 colorDef, filled ) ;
01863
01864 }
01865
01866
01867
01868 bool Surface::drawPolygon( const list<Point2D *> summits,
01869 Coordinate x, Coordinate y,
01870 Pixels::ColorElement red, Pixels::ColorElement green,
01871 Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled )
01872 {
01873
01874 return TwoDimensional::drawPolygon( *this, summits, x, y,
01875 red, green, blue, alpha, filled ) ;
01876
01877 }
01878
01879
01880
01881 bool Surface::drawGrid( Length columnStride, Length rowStride,
01882 Pixels::ColorDefinition lineColor,
01883 bool fillBackground, Pixels::ColorDefinition backColor )
01884 {
01885
01886 if ( fillBackground )
01887 {
01888 if ( fill( backColor ) == false )
01889 return false ;
01890 }
01891
01892 Length xBorder = getWidth() ;
01893 Length yBorder = getHeight() ;
01894
01895 Coordinate x = 0 ;
01896
01897
01898 while ( x < xBorder )
01899 {
01900 if ( ! drawVerticalLine( x, 0, yBorder, lineColor ) )
01901 return false ;
01902 x += columnStride ;
01903 }
01904
01905 Coordinate y = 0 ;
01906
01907
01908 while ( y < yBorder )
01909 {
01910 if ( ! drawHorizontalLine( 0, xBorder, y, lineColor ) )
01911 return false ;
01912 y += rowStride ;
01913 }
01914
01915 return true ;
01916
01917 }
01918
01919
01920
01921
01922 bool Surface::printText( const std::string & text, Coordinate x, Coordinate y,
01923 Pixels::ColorElement red, Pixels::ColorElement green,
01924 Pixels::ColorElement blue, Pixels::ColorElement alpha )
01925 {
01926
01927 return Text::printBasic( text, *this, x, y, red, green, blue, alpha ) ;
01928
01929 }
01930
01931
01932
01933 bool Surface::printText( const std::string & text, Coordinate x, Coordinate y,
01934 ColorDefinition colorDef )
01935 {
01936
01937 return Text::printBasic( text, *this, x, y, colorDef ) ;
01938
01939 }
01940
01941
01942
01943 bool Surface::blitTo( Surface & targetSurface ) const
01944 {
01945
01946 return blitTo( targetSurface, 0, 0 ) ;
01947
01948 }
01949
01950
01951
01952 bool Surface::blitTo( Surface & targetSurface, Coordinate x, Coordinate y )
01953 const
01954 {
01955
01956 #if OSDL_USES_SDL
01957
01958 #if OSDL_DEBUG_WIDGET
01959
01960 LogPlug::trace( "Surface::blitTo: blitting to [" + Ceylan::toString( x )
01961 + ";" + Ceylan::toString( y ) + "]." ) ;
01962
01963 #endif // OSDL_DEBUG_WIDGET
01964
01965
01966 #if OSDL_DEBUG
01967
01968 if ( isLocked() )
01969 throw VideoException( "Surface::blitTo with no source rectangle called "
01970 "whereas surface is locked." ) ;
01971
01972 #endif // OSDL_DEBUG
01973
01974 SDL_Rect destinationRect ;
01975
01976 destinationRect.x = x ;
01977 destinationRect.y = y ;
01978
01979
01980 switch( SDL_BlitSurface( & getSDLSurface(), 0,
01981 & targetSurface.getSDLSurface(), & destinationRect ) )
01982 {
01983
01984 case 0:
01985
01986 return true ;
01987 break ;
01988
01989 case -2:
01990
01991
01992
01993
01994
01995 throw VideoMemoryLostException() ;
01996 break ;
01997
01998 case -1:
01999 throw VideoException(
02000 "Surface::blitTo with no source rectangle: error in blit, "
02001 + Utils::getBackendLastError() ) ;
02002 break ;
02003
02004 default:
02005 LogPlug::error( "Unexpected returned value in Surface::blitTo "
02006 "with no source rectangle." ) ;
02007 return false ;
02008 break ;
02009 }
02010
02011 return false ;
02012
02013 #else // OSDL_USES_SDL
02014
02015 return false ;
02016
02017 #endif // OSDL_USES_SDL
02018
02019 }
02020
02021
02022
02023 bool Surface::blitTo( Surface & targetSurface,
02024 const TwoDimensional::Point2D & location ) const
02025 {
02026
02027 return blitTo( targetSurface, location.getX(), location.getY() ) ;
02028
02029 }
02030
02031
02032
02033 bool Surface::blitTo( Surface & targetSurface,
02034 const TwoDimensional::UprightRectangle & sourceRectangle,
02035 const TwoDimensional::Point2D & destinationLocation ) const
02036 {
02037
02038 #if OSDL_USES_SDL
02039
02040 #if OSDL_DEBUG
02041
02042 if ( isLocked() )
02043 throw VideoException( "Surface::blitTo with source rectangle called "
02044 "whereas surface is locked." ) ;
02045
02046 #endif // OSDL_DEBUG
02047
02048
02049 #if OSDL_DEBUG_BLIT
02050
02051 LogPlug::debug( "Surface::blitTo with source rectangle = "
02052 + sourceRectangle.toString() + " and destination location = "
02053 + destinationLocation.toString() ) ;
02054
02055 #endif // OSDL_DEBUG_BLIT
02056
02057 SDL_Rect destinationRect ;
02058
02059 destinationRect.x = destinationLocation.getX() ;
02060 destinationRect.y = destinationLocation.getY() ;
02061
02062
02063 switch( SDL_BlitSurface( & getSDLSurface(),
02064 sourceRectangle.toLowLevelRect(), & targetSurface.getSDLSurface(),
02065 & destinationRect ) )
02066 {
02067
02068 case 0:
02069
02070 return true ;
02071 break ;
02072
02073 case -2:
02074
02075 throw VideoMemoryLostException() ;
02076 break ;
02077
02078 case -1:
02079 throw VideoException(
02080 "Surface::blitTo with source rectangle: error in blit: "
02081 + Utils::getBackendLastError() ) ;
02082 break ;
02083
02084 default:
02085 LogPlug::error( "Unexpected returned value in Surface::blitTo "
02086 "with source rectangle." ) ;
02087 return false ;
02088 break ;
02089 }
02090
02091 return false ;
02092
02093 #else // OSDL_USES_SDL
02094
02095 throw VideoException( "Surface::blitTo failed:"
02096 "no SDL support available" ) ;
02097
02098 #endif // OSDL_USES_SDL
02099
02100 }
02101
02102
02103
02104 void Surface::displayAt( const OpenGL::GLTexture & texture,
02105 Coordinate x, Coordinate y ) const
02106 {
02107
02108 #if OSDL_USES_OPENGL
02109
02110
02111
02112
02113
02114
02115
02116 texture.setAsCurrent() ;
02117
02118 glBegin(GL_QUADS) ;
02119 {
02120
02121 glTexCoord2d( 0, 0 ) ;
02122 glVertex2d( x, y ) ;
02123
02124 glTexCoord2d( 0, 1 ) ;
02125 glVertex2d( x, y + texture.getHeight() ) ;
02126
02127 glTexCoord2d( 1, 1 ) ;
02128 glVertex2d( x + texture.getWidth(), y + texture.getHeight() ) ;
02129
02130 glTexCoord2d( 1, 0 ) ;
02131 glVertex2d( x + texture.getWidth(), y ) ;
02132
02133 }
02134 glEnd() ;
02135
02136
02137 #else // if OSDL_USES_OPENGL
02138
02139 throw VideoException( "Surface::displayAt failed: "
02140 "no OpenGL support available." ) ;
02141
02142 #endif // OSDL_USES_OPENGL
02143
02144 }
02145
02146
02147 void Surface::displayWithAlphaAt( const OpenGL::GLTexture & texture,
02148 Coordinate x, Coordinate y, Pixels::FloatColorElement alpha ) const
02149 {
02150
02151 #if OSDL_USES_OPENGL
02152
02153
02154
02155
02156
02157
02158
02159
02160 glColor4f( 1.0f, 1.0f, 1.0f, alpha ) ;
02161
02162 texture.setAsCurrent() ;
02163
02164 glBegin(GL_QUADS) ;
02165 {
02166
02167 glTexCoord2d( 0, 0 ) ;
02168 glVertex2d( x, y ) ;
02169
02170 glTexCoord2d( 0, 1 ) ;
02171 glVertex2d( x, y + texture.getHeight() ) ;
02172
02173 glTexCoord2d( 1, 1 ) ;
02174 glVertex2d( x + texture.getWidth(), y + texture.getHeight() ) ;
02175
02176 glTexCoord2d( 1, 0 ) ;
02177 glVertex2d( x + texture.getWidth(), y ) ;
02178
02179 }
02180 glEnd() ;
02181
02182
02183 #else // if OSDL_USES_OPENGL
02184
02185 throw VideoException( "Surface::displayWithAlphaAt failed: "
02186 "no OpenGL support available." ) ;
02187
02188 #endif // OSDL_USES_OPENGL
02189
02190 }
02191
02192
02193
02194 void Surface::displayCenteredHorizontallyAt( const OpenGL::GLTexture & texture,
02195 Coordinate y ) const
02196 {
02197
02198 #if OSDL_USES_OPENGL
02199
02200
02201
02202
02203
02204
02205
02206 texture.setAsCurrent() ;
02207
02208 Coordinate xBegin = ( getWidth() - texture.getWidth() ) / 2 ;
02209 Coordinate xEnd = xBegin + texture.getWidth() ;
02210
02211
02212
02213
02214
02215
02216 glBegin(GL_QUADS) ;
02217 {
02218
02219 glTexCoord2d( 0, 0 ) ;
02220 glVertex2d( xBegin, y ) ;
02221
02222 glTexCoord2d( 0, 1 ) ;
02223 glVertex2d( xBegin, y + texture.getHeight() ) ;
02224
02225 glTexCoord2d( 1, 1 ) ;
02226 glVertex2d( xEnd, y + texture.getHeight() ) ;
02227
02228 glTexCoord2d( 1, 0 ) ;
02229 glVertex2d( xEnd, y ) ;
02230
02231 }
02232 glEnd() ;
02233
02234
02235 #else // if OSDL_USES_OPENGL
02236
02237 throw VideoException( "Surface::displayCenteredHorizontallyAt failed: "
02238 "no OpenGL support available." ) ;
02239
02240 #endif // OSDL_USES_OPENGL
02241
02242 }
02243
02244
02245
02246 void Surface::displayCenteredHorizontallyWithAlphaAt(
02247 const OpenGL::GLTexture & texture, Coordinate y,
02248 Pixels::FloatColorElement alpha ) const
02249 {
02250
02251 #if OSDL_USES_OPENGL
02252
02253 Coordinate xBegin = ( getWidth() - texture.getWidth() ) / 2 ;
02254 Coordinate xEnd = xBegin + texture.getWidth() ;
02255
02256
02257
02258
02259
02260
02261
02262
02263 glColor4f( 1.0f, 1.0f, 1.0f, alpha ) ;
02264
02265
02266
02267 texture.setAsCurrent() ;
02268
02269
02270
02271
02272
02273
02274 glBegin(GL_QUADS) ;
02275 {
02276
02277 glTexCoord2d( 0, 0 ) ;
02278 glVertex2d( xBegin, y ) ;
02279
02280 glTexCoord2d( 0, 1 ) ;
02281 glVertex2d( xBegin, y + texture.getHeight() ) ;
02282
02283 glTexCoord2d( 1, 1 ) ;
02284 glVertex2d( xEnd, y + texture.getHeight() ) ;
02285
02286 glTexCoord2d( 1, 0 ) ;
02287 glVertex2d( xEnd, y ) ;
02288
02289 }
02290 glEnd() ;
02291
02292
02293 #else // if OSDL_USES_OPENGL
02294
02295 throw VideoException(
02296 "Surface::displayCenteredHorizontallyWithAlphaAt failed: "
02297 "no OpenGL support available." ) ;
02298
02299 #endif // OSDL_USES_OPENGL
02300
02301 }
02302
02303
02304
02305 void Surface::displayCenteredHorizontallyAt( const OpenGL::GLTexture & texture,
02306 Coordinate xOffset, Coordinate y ) const
02307 {
02308
02309 #if OSDL_USES_OPENGL
02310
02311
02312
02313
02314
02315
02316
02317 texture.setAsCurrent() ;
02318
02319 Coordinate xBegin = xOffset ;
02320 Coordinate xEnd = getWidth() - xBegin ;
02321
02322
02323
02324
02325
02326
02327 glBegin(GL_QUADS) ;
02328 {
02329
02330 glTexCoord2d( 0, 0 ) ;
02331 glVertex2d( xBegin, y ) ;
02332
02333 glTexCoord2d( 0, 1 ) ;
02334 glVertex2d( xBegin, y + texture.getHeight() ) ;
02335
02336 glTexCoord2d( 1, 1 ) ;
02337 glVertex2d( xEnd, y + texture.getHeight() ) ;
02338
02339 glTexCoord2d( 1, 0 ) ;
02340 glVertex2d( xEnd, y ) ;
02341
02342 }
02343 glEnd() ;
02344
02345
02346 #else // if OSDL_USES_OPENGL
02347
02348 throw VideoException( "Surface::displayCenteredHorizontallyAt failed: "
02349 "no OpenGL support available." ) ;
02350
02351 #endif // OSDL_USES_OPENGL
02352
02353 }
02354
02355
02356
02357
02358 void Surface::displayAtCenter( const OpenGL::GLTexture & texture ) const
02359 {
02360
02361 #if OSDL_USES_OPENGL
02362
02363
02364
02365
02366
02367
02368
02369 texture.setAsCurrent() ;
02370
02371 Length firstAbscissa = ( getWidth() - texture.getWidth() ) / 2 ;
02372 Length secondAbscissa = firstAbscissa + texture.getWidth() ;
02373
02374 Length firstOrdinate = ( getHeight() - texture.getHeight() ) / 2 ;
02375 Length secondOrdinate = firstOrdinate + texture.getHeight() ;
02376
02377
02378 glBegin(GL_QUADS) ;
02379 {
02380
02381 glTexCoord2d( 0, 0 ) ;
02382 glVertex2d( firstAbscissa, firstOrdinate ) ;
02383
02384 glTexCoord2d( 0, 1 ) ;
02385 glVertex2d( firstAbscissa, secondOrdinate ) ;
02386
02387 glTexCoord2d( 1, 1 ) ;
02388 glVertex2d( secondAbscissa, secondOrdinate ) ;
02389
02390 glTexCoord2d( 1, 0 ) ;
02391 glVertex2d( secondAbscissa, firstOrdinate ) ;
02392
02393 }
02394 glEnd() ;
02395
02396
02397 #else // if OSDL_USES_OPENGL
02398
02399 throw VideoException( "Surface::displayAtCenter failed: "
02400 "no OpenGL support available." ) ;
02401
02402 #endif // OSDL_USES_OPENGL
02403
02404 }
02405
02406
02407
02408 void Surface::displayAtCenterWithAlpha( const OpenGL::GLTexture & texture,
02409 Pixels::FloatColorElement alpha ) const
02410 {
02411
02412 #if OSDL_USES_OPENGL
02413
02414
02415 Length firstAbscissa = ( getWidth() - texture.getWidth() ) / 2 ;
02416 Length secondAbscissa = firstAbscissa + texture.getWidth() ;
02417
02418 Length firstOrdinate = ( getHeight() - texture.getHeight() ) / 2 ;
02419 Length secondOrdinate = firstOrdinate + texture.getHeight() ;
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429 glColor4f( 1.0f, 1.0f, 1.0f, alpha ) ;
02430
02431 texture.setAsCurrent() ;
02432
02433
02434 glBegin(GL_QUADS) ;
02435 {
02436
02437 glTexCoord2d( 0, 0 ) ;
02438 glVertex2d( firstAbscissa, firstOrdinate ) ;
02439
02440 glTexCoord2d( 0, 1 ) ;
02441 glVertex2d( firstAbscissa, secondOrdinate ) ;
02442
02443 glTexCoord2d( 1, 1 ) ;
02444 glVertex2d( secondAbscissa, secondOrdinate ) ;
02445
02446 glTexCoord2d( 1, 0 ) ;
02447 glVertex2d( secondAbscissa, firstOrdinate ) ;
02448
02449 }
02450 glEnd() ;
02451
02452
02453 #else // if OSDL_USES_OPENGL
02454
02455 throw VideoException( "Surface::displayAtCenterWithAlpha failed: "
02456 "no OpenGL support available." ) ;
02457
02458 #endif // OSDL_USES_OPENGL
02459
02460 }
02461
02462
02463
02464 void Surface::displayAtCenterWithFadeIn( const OpenGL::GLTexture & texture,
02465 Ceylan::System::Millisecond fadeInDuration )
02466 {
02467
02468 #if OSDL_USES_OPENGL
02469
02470
02471
02472
02473
02474
02475
02476
02477 texture.setAsCurrent() ;
02478
02479 Length firstAbscissa = ( getWidth() - texture.getWidth() ) / 2 ;
02480 Length secondAbscissa = firstAbscissa + texture.getWidth() ;
02481
02482 Length firstOrdinate = ( getHeight() - texture.getHeight() ) / 2 ;
02483 Length secondOrdinate = firstOrdinate + texture.getHeight() ;
02484
02485
02486
02487 FloatColorElement alpha = 0 ;
02488
02489 Ceylan::System::Second startingSecond, currentSecond ;
02490
02491 Ceylan::System::Microsecond startingMicrosecond, currentMicrosecond,
02492 elapsedMicrosecond ;
02493
02494 Ceylan::System::getPreciseTime( startingSecond, startingMicrosecond ) ;
02495
02496 do
02497 {
02498
02499 clear() ;
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509 glColor4f( 1.0f, 1.0f, 1.0f, alpha ) ;
02510
02511
02512 glBegin(GL_QUADS) ;
02513 {
02514
02515 glTexCoord2d( 0, 0 ) ;
02516 glVertex2d( firstAbscissa, firstOrdinate ) ;
02517
02518 glTexCoord2d( 0, 1 ) ;
02519 glVertex2d( firstAbscissa, secondOrdinate ) ;
02520
02521 glTexCoord2d( 1, 1 ) ;
02522 glVertex2d( secondAbscissa, secondOrdinate ) ;
02523
02524 glTexCoord2d( 1, 0 ) ;
02525 glVertex2d( secondAbscissa, firstOrdinate ) ;
02526
02527 }
02528 glEnd() ;
02529
02530 update() ;
02531
02532 Ceylan::System::atomicSleep() ;
02533
02534 Ceylan::System::getPreciseTime( currentSecond, currentMicrosecond ) ;
02535
02536 elapsedMicrosecond = Ceylan::System::getDurationBetween(
02537 startingSecond, startingMicrosecond,
02538 currentSecond, currentMicrosecond ) ;
02539
02540 alpha = elapsedMicrosecond / ( 1000.0f * fadeInDuration ) ;
02541
02542 }
02543 while ( alpha < 1.0 ) ;
02544
02545
02546 #else // if OSDL_USES_OPENGL
02547
02548 throw VideoException( "Surface::displayAtCenterWithFadeIn failed: "
02549 "no OpenGL support available." ) ;
02550
02551 #endif // OSDL_USES_OPENGL
02552
02553 }
02554
02555
02556
02557 void Surface::displayAtCenterWithFadeOut( const OpenGL::GLTexture & texture,
02558 Ceylan::System::Millisecond fadeOutDuration )
02559 {
02560
02561 #if OSDL_USES_OPENGL
02562
02563
02564
02565
02566
02567
02568
02569
02570 texture.setAsCurrent() ;
02571
02572 Length firstAbscissa = ( getWidth() - texture.getWidth() ) / 2 ;
02573 Length secondAbscissa = firstAbscissa + texture.getWidth() ;
02574
02575 Length firstOrdinate = ( getHeight() - texture.getHeight() ) / 2 ;
02576 Length secondOrdinate = firstOrdinate + texture.getHeight() ;
02577
02578
02579
02580 FloatColorElement alpha = 0 ;
02581
02582 Ceylan::System::Second startingSecond, currentSecond ;
02583
02584 Ceylan::System::Microsecond startingMicrosecond, currentMicrosecond,
02585 elapsedMicrosecond ;
02586
02587 Ceylan::System::getPreciseTime( startingSecond, startingMicrosecond ) ;
02588
02589 do
02590 {
02591
02592 clear() ;
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602 glColor4f( 1.0f, 1.0f, 1.0f, alpha ) ;
02603
02604
02605 glBegin(GL_QUADS) ;
02606 {
02607
02608 glTexCoord2d( 0, 0 ) ;
02609 glVertex2d( firstAbscissa, firstOrdinate ) ;
02610
02611 glTexCoord2d( 0, 1 ) ;
02612 glVertex2d( firstAbscissa, secondOrdinate ) ;
02613
02614 glTexCoord2d( 1, 1 ) ;
02615 glVertex2d( secondAbscissa, secondOrdinate ) ;
02616
02617 glTexCoord2d( 1, 0 ) ;
02618 glVertex2d( secondAbscissa, firstOrdinate ) ;
02619
02620 }
02621 glEnd() ;
02622
02623 update() ;
02624
02625 Ceylan::System::atomicSleep() ;
02626
02627 Ceylan::System::getPreciseTime( currentSecond, currentMicrosecond ) ;
02628
02629 elapsedMicrosecond = Ceylan::System::getDurationBetween(
02630 startingSecond, startingMicrosecond,
02631 currentSecond, currentMicrosecond ) ;
02632
02633 alpha = static_cast<Pixels::FloatColorElement>(
02634 1.0 - elapsedMicrosecond / ( 1000.0 * fadeOutDuration ) ) ;
02635
02636 }
02637 while ( alpha > 0.0 ) ;
02638
02639
02640 #else // if OSDL_USES_OPENGL
02641
02642 throw VideoException( "Surface::displayAtCenterWithFadeOut failed: "
02643 "no OpenGL support available." ) ;
02644
02645 #endif // OSDL_USES_OPENGL
02646
02647 }
02648
02649
02650
02651 void Surface::displayInFullscreen( const OpenGL::GLTexture & texture ) const
02652 {
02653
02654 #if OSDL_USES_OPENGL
02655
02656
02657
02658
02659
02660
02661
02662 texture.setAsCurrent() ;
02663
02664 Length firstAbscissa = 0 ;
02665 Length secondAbscissa = getWidth() ;
02666
02667 Length firstOrdinate = 0 ;
02668 Length secondOrdinate = getHeight() ;
02669
02670
02671 glBegin(GL_QUADS) ;
02672 {
02673
02674 glTexCoord2d( 0, 0 ) ;
02675 glVertex2d( firstAbscissa, firstOrdinate ) ;
02676
02677 glTexCoord2d( 0, 1 ) ;
02678 glVertex2d( firstAbscissa, secondOrdinate ) ;
02679
02680 glTexCoord2d( 1, 1 ) ;
02681 glVertex2d( secondAbscissa, secondOrdinate ) ;
02682
02683 glTexCoord2d( 1, 0 ) ;
02684 glVertex2d( secondAbscissa, firstOrdinate ) ;
02685
02686 }
02687 glEnd() ;
02688
02689
02690 #else // if OSDL_USES_OPENGL
02691
02692 throw VideoException( "Surface::displayInFullscreen failed: "
02693 "no OpenGL support available." ) ;
02694
02695 #endif // OSDL_USES_OPENGL
02696
02697 }
02698
02699
02700
02701 void Surface::displayInFullscreenWithAlpha( const OpenGL::GLTexture & texture,
02702 Pixels::FloatColorElement alpha ) const
02703 {
02704
02705 #if OSDL_USES_OPENGL
02706
02707
02708 Length firstAbscissa = 0 ;
02709 Length secondAbscissa = getWidth() ;
02710
02711 Length firstOrdinate = 0 ;
02712 Length secondOrdinate = getHeight() ;
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722 glColor4f( 1.0f, 1.0f, 1.0f, alpha ) ;
02723
02724
02725
02726 texture.setAsCurrent() ;
02727
02728 glBegin(GL_QUADS) ;
02729 {
02730
02731 glTexCoord2d( 0, 0 ) ;
02732 glVertex2d( firstAbscissa, firstOrdinate ) ;
02733
02734 glTexCoord2d( 0, 1 ) ;
02735 glVertex2d( firstAbscissa, secondOrdinate ) ;
02736
02737 glTexCoord2d( 1, 1 ) ;
02738 glVertex2d( secondAbscissa, secondOrdinate ) ;
02739
02740 glTexCoord2d( 1, 0 ) ;
02741 glVertex2d( secondAbscissa, firstOrdinate ) ;
02742
02743 }
02744 glEnd() ;
02745
02746
02747 #else // if OSDL_USES_OPENGL
02748
02749 throw VideoException( "Surface::displayInFullscreenWithAlpha failed: "
02750 "no OpenGL support available." ) ;
02751
02752 #endif // OSDL_USES_OPENGL
02753
02754 }
02755
02756
02757
02758 void Surface::displayInFullscreenSizeWithAlphaAt(
02759 const OpenGL::GLTexture & texture,
02760 Pixels::FloatColorElement alpha, Coordinate x, Coordinate y ) const
02761 {
02762
02763 #if OSDL_USES_OPENGL
02764
02765
02766 Length firstAbscissa = x ;
02767 Length secondAbscissa = x+ getWidth() ;
02768
02769 Length firstOrdinate = y ;
02770 Length secondOrdinate = y + getHeight() ;
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780 glColor4f( 1.0f, 1.0f, 1.0f, alpha ) ;
02781
02782
02783
02784 texture.setAsCurrent() ;
02785
02786 glBegin(GL_QUADS) ;
02787 {
02788
02789 glTexCoord2d( 0, 0 ) ;
02790 glVertex2d( firstAbscissa, firstOrdinate ) ;
02791
02792 glTexCoord2d( 0, 1 ) ;
02793 glVertex2d( firstAbscissa, secondOrdinate ) ;
02794
02795 glTexCoord2d( 1, 1 ) ;
02796 glVertex2d( secondAbscissa, secondOrdinate ) ;
02797
02798 glTexCoord2d( 1, 0 ) ;
02799 glVertex2d( secondAbscissa, firstOrdinate ) ;
02800
02801 }
02802 glEnd() ;
02803
02804
02805 #else // if OSDL_USES_OPENGL
02806
02807 throw VideoException( "Surface::displayInFullscreenSizeWithAlphaAt failed: "
02808 "no OpenGL support available." ) ;
02809
02810 #endif // OSDL_USES_OPENGL
02811
02812 }
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822 Surface & Surface::zoom( Ceylan::Maths::Real abscissaZoomFactor,
02823 Ceylan::Maths::Real ordinateZoomFactor, bool antialiasing ) const
02824 {
02825
02826 #if OSDL_USES_SDL_GFX
02827
02828
02829 if ( abscissaZoomFactor < 0 || ordinateZoomFactor < 0 )
02830 antialiasing = false ;
02831
02832 LowLevelSurface * res =::zoomSurface(
02833 const_cast<LowLevelSurface *>( _surface ),
02834 abscissaZoomFactor,
02835 ordinateZoomFactor,
02836 antialiasing ? SMOOTHING_ON: SMOOTHING_OFF ) ;
02837
02838 if ( res == 0 )
02839 throw VideoException( "Surface::zoom: unable to zoom surface." ) ;
02840
02841
02842 return * new Surface( *res ) ;
02843
02844 #else // OSDL_USES_SDL_GFX
02845
02846 throw VideoException( "Surface::zoom failed:"
02847 "no SDL_gfx support available" ) ;
02848
02849 #endif // OSDL_USES_SDL_GFX
02850
02851 }
02852
02853
02854
02855 Surface & Surface::rotoZoom( Ceylan::Maths::AngleInDegrees angle,
02856 Ceylan::Maths::Real zoomFactor, bool antialiasing ) const
02857 {
02858
02859 return rotoZoom( angle, zoomFactor, zoomFactor, antialiasing ) ;
02860
02861 }
02862
02863
02864 Surface & Surface::rotoZoom(
02865 Ceylan::Maths::AngleInDegrees angle,
02866 Ceylan::Maths::Real abscissaZoomFactor,
02867 Ceylan::Maths::Real ordinateZoomFactor,
02868 bool antialiasing ) const
02869 {
02870
02871 #if OSDL_USES_SDL_GFX
02872
02873
02874 if ( abscissaZoomFactor < 0 || ordinateZoomFactor < 0 )
02875 antialiasing = false ;
02876
02877 LowLevelSurface * res =::rotozoomSurfaceXY(
02878 const_cast<LowLevelSurface *>( _surface ), angle, abscissaZoomFactor,
02879 ordinateZoomFactor, antialiasing ? SMOOTHING_ON: SMOOTHING_OFF ) ;
02880
02881 if ( res == 0 )
02882 throw VideoException(
02883 "Surface::rotoZoom: unable to rotozoom surface." ) ;
02884
02885 return * new Surface( *res ) ;
02886
02887 #else // OSDL_USES_SDL_GFX
02888
02889 throw VideoException( "Surface::rotoZoom failed:"
02890 "no SDL_gfx support available" ) ;
02891
02892 #endif // OSDL_USES_SDL_GFX
02893
02894 }
02895
02896
02897
02898
02899 UprightRectangle & Surface::getClippingArea() const
02900 {
02901
02902 #if OSDL_USES_SDL
02903
02904 return * new UprightRectangle( _surface->clip_rect ) ;
02905
02906 #else // OSDL_USES_SDL
02907
02908 throw VideoException( "Surface::getClippingArea failed: "
02909 "no SDL support available" ) ;
02910
02911 #endif // OSDL_USES_SDL
02912
02913 }
02914
02915
02916
02917 void Surface::setClippingArea( UprightRectangle & newClippingArea )
02918 {
02919
02920 #if OSDL_USES_SDL
02921
02922 TwoDimensional::Point2D corner = newClippingArea.getUpperLeftCorner() ;
02923
02924 _surface->clip_rect.x = corner.getX() ;
02925 _surface->clip_rect.y = corner.getY() ;
02926
02927 _surface->clip_rect.w = newClippingArea.getWidth() ;
02928 _surface->clip_rect.h = newClippingArea.getHeight() ;
02929
02930 #endif // OSDL_USES_SDL
02931
02932 }
02933
02934
02935
02936 UprightRectangle & Surface::getContentArea() const
02937 {
02938
02939
02940 Length width = getWidth() ;
02941 Length minWidth = width ;
02942 Length maxWidth = 0 ;
02943
02944 Length height = getHeight() ;
02945 Length minHeight = height ;
02946 Length maxHeight = 0 ;
02947
02948 PixelColor colorkey = guessColorKey() ;
02949 PixelColor current ;
02950
02951 for ( Length y = 0; y < height; y++ )
02952 for ( Length x = 0; x < width; x++ )
02953 {
02954
02955 current = getPixelColorAt( x, y ) ;
02956
02957 if ( ! areEqual( current, colorkey ) )
02958 {
02959
02960
02961
02962 if ( x < minWidth )
02963 minWidth = x ;
02964
02965 if ( x > maxWidth )
02966 maxWidth = x ;
02967
02968
02969 if ( y < minHeight )
02970 minHeight = y ;
02971
02972 if ( y > maxHeight )
02973 maxHeight = y ;
02974
02975 }
02976
02977 }
02978
02979 return * new UprightRectangle( minWidth, minHeight,
02980 maxWidth - minWidth + 1,
02981 maxHeight - minHeight + 1 ) ;
02982
02983 }
02984
02985
02986
02987
02988
02989
02990
02991 void Surface::loadImage( const string & filename, bool blitOnly,
02992 bool convertToDisplayFormat, bool convertWithAlpha )
02993 {
02994
02995 TwoDimensional::Image::Load( *this, filename, blitOnly,
02996 convertToDisplayFormat, convertWithAlpha ) ;
02997
02998 }
02999
03000
03001
03002 void Surface::loadJPG( const string & filename, bool blitOnly,
03003 bool convertToDisplayFormat, bool convertWithAlpha )
03004 {
03005
03006 TwoDimensional::Image::LoadJPG( *this, filename, blitOnly,
03007 convertToDisplayFormat, convertWithAlpha ) ;
03008
03009 }
03010
03011
03012
03013 void Surface::loadPNG( const string & filename, bool blitOnly,
03014 bool convertToDisplayFormat, bool convertWithAlpha )
03015 {
03016
03017 TwoDimensional::Image::LoadPNG( *this, filename, blitOnly,
03018 convertToDisplayFormat, convertWithAlpha ) ;
03019
03020 }
03021
03022
03023
03024 void Surface::loadBMP( const string & filename, bool blitOnly,
03025 bool convertToDisplayFormat, bool convertWithAlpha )
03026 {
03027
03028 TwoDimensional::Image::LoadBMP( *this, filename, blitOnly,
03029 convertToDisplayFormat, convertWithAlpha ) ;
03030
03031 }
03032
03033
03034
03035 void Surface::loadGIF( const string & filename, bool blitOnly,
03036 bool convertToDisplayFormat, bool convertWithAlpha )
03037 {
03038
03039 TwoDimensional::Image::LoadGIF( *this, filename, blitOnly,
03040 convertToDisplayFormat, convertWithAlpha ) ;
03041
03042 }
03043
03044
03045
03046 void Surface::loadLBM( const string & filename, bool blitOnly,
03047 bool convertToDisplayFormat, bool convertWithAlpha )
03048 {
03049
03050 TwoDimensional::Image::LoadLBM( *this, filename, blitOnly,
03051 convertToDisplayFormat, convertWithAlpha ) ;
03052
03053 }
03054
03055
03056
03057 void Surface::loadPCX( const string & filename, bool blitOnly,
03058 bool convertToDisplayFormat, bool convertWithAlpha )
03059 {
03060
03061 TwoDimensional::Image::LoadPCX( *this, filename, blitOnly,
03062 convertToDisplayFormat, convertWithAlpha ) ;
03063
03064 }
03065
03066
03067
03068 void Surface::loadPNM( const string & filename, bool blitOnly,
03069 bool convertToDisplayFormat, bool convertWithAlpha )
03070 {
03071
03072 TwoDimensional::Image::LoadPNM( *this, filename, blitOnly,
03073 convertToDisplayFormat, convertWithAlpha ) ;
03074
03075 }
03076
03077
03078
03079 void Surface::loadTGA( const string & filename, bool blitOnly,
03080 bool convertToDisplayFormat, bool convertWithAlpha )
03081 {
03082
03083 TwoDimensional::Image::LoadTGA( *this, filename, blitOnly,
03084 convertToDisplayFormat, convertWithAlpha ) ;
03085
03086 }
03087
03088
03089
03090 void Surface::loadXPM( const string & filename, bool blitOnly,
03091 bool convertToDisplayFormat, bool convertWithAlpha )
03092 {
03093
03094 TwoDimensional::Image::LoadXPM( *this, filename, blitOnly,
03095 convertToDisplayFormat, convertWithAlpha ) ;
03096
03097 }
03098
03099
03100
03101 void Surface::savePNG( const std::string & filename, bool overwrite )
03102 {
03103
03104 TwoDimensional::Image::SavePNG( *this, filename, overwrite ) ;
03105
03106 }
03107
03108
03109
03110 void Surface::saveBMP( const std::string & filename, bool overwrite )
03111 {
03112
03113 #if OSDL_USES_SDL
03114
03115 if ( ( overwrite == false ) && Ceylan::System::File::Exists( filename ) )
03116 throw TwoDimensional::ImageException(
03117 "Surface::saveBMP: target file " + filename
03118 + " already exists, and overwrite mode is off." ) ;
03119
03120 if ( SDL_SaveBMP( _surface, filename.c_str() ) == -1 )
03121 throw TwoDimensional::ImageException(
03122 "Surface::saveBMP: unable to save image: "
03123 + Utils::getBackendLastError() ) ;
03124
03125 #else // OSDL_USES_SDL
03126
03127 throw TwoDimensional::ImageException( "Surface::saveBMP failed:"
03128 "no SDL support available" ) ;
03129
03130 #endif // OSDL_USES_SDL
03131
03132 }
03133
03134
03135
03136 void Surface::update()
03137 {
03138
03139 #if OSDL_USES_SDL
03140
03141
03142 #if OSDL_DEBUG_WIDGET
03143 LogPlug::trace( "Surface::update" ) ;
03144 #endif // OSDL_DEBUG_WIDGET
03145
03146 _updateCount++ ;
03147
03148 #if OSDL_DEBUG
03149 if ( isLocked() )
03150 throw VideoException(
03151 "Surface::update called whereas surface is locked." ) ;
03152 #endif // OSDL_DEBUG
03153
03154
03155 redraw() ;
03156
03157 switch( _displayType )
03158 {
03159
03160 case BackBuffer:
03161 LogPlug::warning( "Surface::update requested on a "
03162 "non-screen surface! (nothing done)" ) ;
03163 break ;
03164
03165
03166 case ClassicalScreenSurface:
03167 #if OSDL_DEBUG_WIDGET
03168 LogPlug::trace(
03169 "Surface::update: flipping classical screen buffer" ) ;
03170 #endif // OSDL_DEBUG_WIDGET
03171
03172
03173 if ( SDL_Flip( _surface ) != 0 )
03174 throw VideoException(
03175 "Surface::update: unable to flip classical screen: "
03176 + Utils::getBackendLastError() ) ;
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194 break ;
03195
03196
03197 case OpenGLScreenSurface:
03198 #if OSDL_DEBUG_WIDGET
03199 LogPlug::trace(
03200 "Surface::update: flipping OpenGL screen buffer" ) ;
03201 #endif // OSDL_DEBUG_WIDGET
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217 glFlush() ;
03218 SDL_GL_SwapBuffers() ;
03219 break ;
03220
03221
03222 default:
03223 LogPlug::error(
03224 "Surface::update: unknown display type, nothing done." ) ;
03225 break ;
03226
03227 }
03228
03229 #else // OSDL_USES_SDL
03230
03231 throw VideoException( "Surface::update failed:"
03232 "no SDL support available" ) ;
03233
03234 #endif // OSDL_USES_SDL
03235
03236 }
03237
03238
03239
03240 UpdateCount Surface::getUpdateCount() const
03241 {
03242
03243 return _updateCount ;
03244
03245 }
03246
03247
03248
03249 void Surface::updateRectangles( const list<UprightRectangle *> & listRects )
03250 {
03251
03252
03253
03254
03255
03256
03257
03258 for ( list<UprightRectangle *>::const_iterator it = listRects.begin() ;
03259 it != listRects.end() ; it++ )
03260 {
03261
03262 #if OSDL_DEBUG
03263 if ( *it == 0 )
03264 {
03265 LogPlug::error( "Surface::updateRectangles: "
03266 "null pointer in rectangle list." ) ;
03267 break ;
03268 }
03269 #endif // OSDL_DEBUG
03270
03271 updateRectangle( * (*it) ) ;
03272
03273 }
03274
03275 }
03276
03277
03278
03279 void Surface::updateRectangle( const UprightRectangle & rect )
03280 {
03281
03282 updateRectangle( rect.getUpperLeftAbscissa(),
03283 rect.getUpperLeftOrdinate(), rect.getWidth(), rect.getHeight() ) ;
03284
03285 }
03286
03287
03288
03289 void Surface::updateRectangle( Coordinate x, Coordinate y,
03290 Length width, Length height )
03291 {
03292
03293 #if OSDL_USES_SDL
03294
03295 #if OSDL_DEBUG
03296 if ( isLocked() )
03297 LogPlug::error(
03298 "Surface::updateRectangle() called whereas surface is locked." ) ;
03299 #endif // OSDL_DEBUG
03300
03301 if ( _displayType != BackBuffer )
03302 {
03303 SDL_UpdateRect( _surface, x, y, width, height ) ;
03304 }
03305 else
03306 {
03307 throw VideoException(
03308 "Surface::updateRectangle requested on a non-screen surface" ) ;
03309 }
03310
03311 #else // OSDL_USES_SDL
03312
03313 throw VideoException( "Surface::updateRectangle failed:"
03314 "no SDL support available" ) ;
03315
03316 #endif // OSDL_USES_SDL
03317
03318 }
03319
03320
03321
03322 void Surface::setRedrawState( bool needsToBeRedrawn )
03323 {
03324
03325 _needsRedraw = needsToBeRedrawn ;
03326
03327 }
03328
03329
03330
03331 bool Surface::getRedrawState() const
03332 {
03333
03334 return _needsRedraw ;
03335
03336 }
03337
03338
03339
03340 void Surface::redraw()
03341 {
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355 if ( getRedrawState() )
03356 {
03357
03358
03359 redrawInternal() ;
03360
03361
03362 RedrawRequestEvent redrawEvent( *this ) ;
03363
03364
03365
03366
03367
03368
03369
03370 notifyAllListeners( redrawEvent ) ;
03371
03372 setRedrawState( false ) ;
03373
03374 }
03375
03376
03377
03378 }
03379
03380
03381
03382 void Surface::redrawInternal()
03383 {
03384
03385 #if OSDL_DEBUG_WIDGET
03386 LogPlug::trace( "Surface::redrawInternal (non overridden version)." ) ;
03387 #endif // OSDL_DEBUG_WIDGET
03388
03389
03390
03391
03392
03393
03394
03395 }
03396
03397
03398
03399 bool Surface::isInternalSurfaceAvailable() const
03400 {
03401
03402 return ( _surface != 0 ) ;
03403
03404 }
03405
03406
03407
03408 void Surface::addWidget( TwoDimensional::Widget & widget )
03409 {
03410
03411 #if OSDL_DEBUG_WIDGET
03412 LogPlug::trace( "Surface::addWidget: adding " + widget.toString() ) ;
03413 #endif // OSDL_DEBUG_WIDGET
03414
03415
03416
03417
03418
03419
03420
03421 try
03422 {
03423 add( widget ) ;
03424 }
03425 catch( const Ceylan::EventException & e )
03426 {
03427 throw VideoException(
03428 "Surface::addWidget: unable to add new listener widget: "
03429 + e.toString() ) ;
03430 }
03431
03432 }
03433
03434
03435
03436 Surface & Surface::getWidgetRenderTarget()
03437 {
03438
03439
03440
03441
03442
03443
03444 return *this ;
03445
03446 }
03447
03448
03449
03450 void Surface::putWidgetToFront( TwoDimensional::Widget & widget )
03451 {
03452
03453
03454
03455
03456
03457
03458
03459
03460 _listeners.remove( & widget ) ;
03461
03462
03463 _listeners.push_back( & widget ) ;
03464
03465 }
03466
03467
03468
03469 void Surface::putWidgetToBack( TwoDimensional::Widget & widget )
03470 {
03471
03472
03473
03474
03475
03476
03477
03478
03479
03480 _listeners.remove( & widget ) ;
03481
03482
03483 _listeners.push_front( & widget ) ;
03484
03485 }
03486
03487
03488
03489 void Surface::centerMousePosition()
03490 {
03491
03492 setMousePosition( getWidth() / 2, getHeight() / 2 ) ;
03493
03494 }
03495
03496
03497
03498 void Surface::setMousePosition( Coordinate newX, Coordinate newY )
03499 {
03500
03501 #if OSDL_USES_SDL
03502
03503 #if OSDL_DEBUG
03504
03505 if ( _displayType == BackBuffer )
03506 throw VideoException( "Surface::setMousePosition failed: "
03507 "called on a non-screen surface." ) ;
03508
03509 #endif // OSDL_DEBUG
03510
03511 SDL_WarpMouse( newX, newY ) ;
03512
03513 #else // OSDL_USES_SDL
03514
03515 throw VideoException( "Surface::setMousePosition failed: "
03516 "no SDL support available" ) ;
03517
03518 #endif // OSDL_USES_SDL
03519
03520 }
03521
03522
03523
03524 bool Surface::mustBeLocked() const
03525 {
03526
03527 #if OSDL_USES_SDL
03528
03529
03530 return SDL_MUSTLOCK( _surface ) ;
03531
03532 #else // OSDL_USES_SDL
03533
03534 return true ;
03535
03536 #endif // OSDL_USES_SDL
03537
03538 }
03539
03540
03541
03542 void Surface::preUnlock()
03543 {
03544
03545 #if OSDL_USES_SDL
03546
03547
03548
03549
03550
03551
03552 SDL_UnlockSurface( _surface ) ;
03553
03554 #endif // OSDL_USES_SDL
03555
03556 }
03557
03558
03559
03560 void Surface::postLock()
03561 {
03562
03563 #if OSDL_USES_SDL
03564
03565
03566
03567
03568
03569
03570 SDL_LockSurface( _surface ) ;
03571
03572 #endif // OSDL_USES_SDL
03573
03574 }
03575
03576
03577
03578 Ceylan::System::Size Surface::getSizeInMemory() const
03579 {
03580
03581 #if OSDL_USES_SDL
03582
03583 Ceylan::System::Size currentSize = sizeof( Surface ) ;
03584
03585 if ( _surface != 0 )
03586 {
03587
03588 currentSize += sizeof( LowLevelSurface ) ;
03589
03590
03591 if ( _surface->format != 0 )
03592 {
03593
03594 currentSize += sizeof( SDL_PixelFormat ) ;
03595
03596 if ( _surface->format->palette != 0 )
03597 {
03598 currentSize += sizeof( SDL_Palette ) ;
03599 currentSize += _surface->format->palette->ncolors
03600 * sizeof( SDL_Color ) ;
03601 }
03602
03603 if ( _surface->pixels != 0 )
03604 currentSize += _surface->w * _surface->h *
03605 _surface->format->BytesPerPixel ;
03606
03607 }
03608
03609 }
03610
03611
03612
03613 return currentSize ;
03614
03615 #else // OSDL_USES_SDL
03616
03617 return 0 ;
03618
03619 #endif // OSDL_USES_SDL
03620
03621 }
03622
03623
03624
03625 bool Surface::displayData( const Ceylan::Maths::IntegerData * dataArray,
03626 Ceylan::Uint32 dataCount,
03627 Pixels::ColorDefinition pencilColor, Pixels::ColorDefinition captionColor,
03628 Pixels::ColorDefinition backgroundColor,
03629 const string & caption, const UprightRectangle * inBox )
03630 {
03631
03632
03633 #define OSDL_DEBUG_DISPLAY_DATA 0
03634
03635 Coordinate x, y ;
03636 Length width, height ;
03637
03638 if ( inBox == 0 )
03639 {
03640 x = 0 ;
03641 y = 0 ;
03642 width = getWidth() ;
03643 height = getHeight() ;
03644 }
03645 else
03646 {
03647
03648
03649
03650
03651
03652
03653
03654 x = inBox->getUpperLeftAbscissa() ;
03655 y = inBox->getUpperLeftOrdinate() ;
03656 width = inBox->getWidth() ;
03657 height = inBox->getHeight() ;
03658 }
03659
03660 UprightRectangle drawingArea( x, y, width, height ) ;
03661
03662 #if OSDL_DEBUG_DISPLAY_DATA
03663 LogPlug::debug( "Drawing area will be: " + drawingArea.toString() ) ;
03664 #endif // OSDL_DEBUG_DISPLAY_DATA
03665
03666
03667 drawBox( drawingArea, backgroundColor, true ) ;
03668
03669
03670 drawBox( drawingArea, pencilColor, false ) ;
03671
03672
03673
03674
03675
03676 Coordinate xstart = drawingArea.getUpperLeftAbscissa()
03677 + graphAbscissaOffset ;
03678
03679 Coordinate xmax = drawingArea.getUpperLeftAbscissa()
03680 + drawingArea.getWidth() - graphAbscissaOffset ;
03681 Coordinate xstop ;
03682
03683
03684
03685
03686
03687
03688
03689 Coordinate stride = static_cast<Coordinate>(
03690 Ceylan::Maths::Floor( static_cast<Ceylan::Float32>(
03691 ( drawingArea.getWidth() - 2 * graphAbscissaOffset )
03692 / static_cast<Ceylan::Float32>( dataCount ) ) ) ) ;
03693
03694 #if OSDL_DEBUG_DISPLAY_DATA
03695 LogPlug::debug( "Abscissa stride is "
03696 + Ceylan::toString( stride ) + "." ) ;
03697 #endif // OSDL_DEBUG_DISPLAY_DATA
03698
03699 if ( stride < 1 )
03700 {
03701 LogPlug::error(
03702 "Surface::displayData: available width too small to draw." ) ;
03703 return false ;
03704 }
03705
03706
03707 if ( xstart + static_cast<Coordinate>( dataCount ) > xmax )
03708 {
03709 LogPlug::warning(
03710 "Surface::displayData: graph will be truncated to x = "
03711 + Ceylan::toString( xmax ) + " (insufficient width)." ) ;
03712 xstop = xmax ;
03713 }
03714 else
03715 {
03716 xstop = xstart + stride * dataCount ;
03717 }
03718
03719
03720 if ( xstart > xstop )
03721 {
03722
03723 LogPlug::error(
03724 "Surface::displayData: available width too small to draw." ) ;
03725 return false ;
03726 }
03727
03728
03729
03730
03731 Ceylan::Maths::IntegerData maxData = dataArray[ 0 ] ;
03732 Ceylan::Maths::IntegerData minData = dataArray[ 0 ] ;
03733
03734 for ( Ceylan::Uint32 i = 1; i < dataCount; i++ )
03735 {
03736
03737 if ( dataArray[i] > maxData )
03738 maxData = dataArray[i] ;
03739
03740 if ( dataArray[i] < minData )
03741 minData = dataArray[i] ;
03742
03743 }
03744
03745
03746 #if OSDL_DEBUG_DISPLAY_DATA
03747 LogPlug::debug( "Dynamic range from " + Ceylan::toString( minData )
03748 + " to " + Ceylan::toString( maxData ) + "." ) ;
03749 #endif // OSDL_DEBUG_DISPLAY_DATA
03750
03751 Ceylan::Maths::IntegerData ordinateDrawRange =
03752 drawingArea.getHeight() - 2 * graphOrdinateOffset ;
03753
03754 if ( ordinateDrawRange < 0 )
03755 {
03756 LogPlug::error( "Surface::displayData: height too small to draw." ) ;
03757 return false ;
03758 }
03759
03760 Ceylan::Float32 yScaleFactor ;
03761
03762 if ( maxData != minData )
03763 yScaleFactor = static_cast<Ceylan::Float32>( ordinateDrawRange )
03764 / ( maxData - minData ) ;
03765 else
03766 yScaleFactor = 1 ;
03767
03768
03769 #if OSDL_DEBUG_DISPLAY_DATA
03770
03771 LogPlug::debug( "Ordinate scale factor is "
03772 + Ceylan::toString( yScaleFactor )
03773 + " (" + Ceylan::toString( ordinateDrawRange )
03774 + " / " + Ceylan::toString( maxData - minData ) + ")." ) ;
03775
03776 #endif // OSDL_DEBUG_DISPLAY_DATA
03777
03778 Coordinate yplotBase = drawingArea.getUpperLeftOrdinate()
03779 + drawingArea.getHeight() - graphOrdinateOffset ;
03780
03781
03782
03783 Ceylan::Uint32 dataCurrent = 0 ;
03784
03785 Coordinate xplot = xstart ;
03786
03787 Coordinate yplotPrevious = yplotBase ;
03788 Coordinate yplot ;
03789
03790 while ( xplot < xstop )
03791 {
03792 yplot = static_cast<Coordinate>(
03793 ( dataArray[ dataCurrent ] - minData ) * yScaleFactor ) ;
03794
03795 drawLine( xplot, yplotPrevious, xplot+1, yplotBase - yplot,
03796 pencilColor ) ;
03797 yplotPrevious = yplotBase - yplot ;
03798
03799
03800
03801
03802
03803
03804
03805 dataCurrent++ ;
03806 xplot += stride ;
03807
03808 }
03809
03810
03811
03812
03813
03814
03815
03816 ColorDefinition axisColor = Pixels::Ivory ;
03817
03818 drawHorizontalLine( xstart, xstop, yplotBase, axisColor ) ;
03819 drawVerticalLine( xstart, yplotBase,
03820 drawingArea.getUpperLeftOrdinate() + graphOrdinateOffset, axisColor ) ;
03821
03822
03823
03824
03825
03826
03827
03828 if( caption.size() > 0 )
03829 printText( caption,
03830 drawingArea.getUpperLeftAbscissa() + captionAbscissaOffset,
03831 drawingArea.getUpperLeftOrdinate() + drawingArea.getHeight()
03832 - captionOrdinateOffset,
03833 captionColor ) ;
03834
03835 return true ;
03836
03837 }
03838
03839
03840
03841 const string Surface::toString( Ceylan::VerbosityLevels level ) const
03842 {
03843
03844 #if OSDL_USES_SDL
03845
03846 std::list<string> surfaceList ;
03847
03848 switch( _displayType )
03849 {
03850
03851 case BackBuffer:
03852 surfaceList.push_back( "This is a back buffer surface." ) ;
03853 break ;
03854
03855 case ClassicalScreenSurface:
03856 surfaceList.push_back( "This is a classical screen surface." ) ;
03857 break ;
03858
03859 case OpenGLScreenSurface:
03860 surfaceList.push_back( "This is an OpenGL screen surface." ) ;
03861 break ;
03862
03863 default:
03864 surfaceList.push_back(
03865 "This is a surface of unknown type (abnormal)." ) ;
03866 break ;
03867
03868 }
03869
03870 surfaceList.push_back( "Dimensions: ( width = "
03871 + Ceylan::toString( getWidth() ) + " ; height = "
03872 + getHeight() + " )" ) ;
03873
03874 if ( level == Ceylan::low )
03875 return "Surface description: "
03876 + Ceylan::formatStringList( surfaceList ) ;
03877
03878 surfaceList.push_back( "Pitch: " + Ceylan::toString( getPitch() ) ) ;
03879
03880 surfaceList.push_back( "Pixel format: bits per pixel = "
03881 + Ceylan::toString(
03882 static_cast<Ceylan::Uint16>( getBitsPerPixel() ) ) ) ;
03883
03884 surfaceList.push_back( "Video flags: " + InterpretFlags( getFlags() ) ) ;
03885
03886 if ( _surface->format->palette == 0 )
03887 surfaceList.push_back(
03888 "Surface uses direct color definitions (no palette used)" ) ;
03889 else
03890 surfaceList.push_back( "Surface uses a palette (indexed colors)" ) ;
03891
03892 surfaceList.push_back( "Pitch: " + Ceylan::toString( getPitch() ) ) ;
03893
03894 surfaceList.push_back( "Clipping area: "
03895 + UprightRectangle( _surface->clip_rect ).toString( level ) ) ;
03896
03897 surfaceList.push_back( "Size in memory: "
03898 + Ceylan::toString(
03899 static_cast<Ceylan::Uint32>( getSizeInMemory() ) ) + " bytes" ) ;
03900
03901
03902
03903
03904
03905
03906
03907 surfaceList.push_back( "Widget relationship: "
03908 + EventSource::toString( level ) ) ;
03909
03910
03911 return "Surface description: " + Ceylan::formatStringList( surfaceList ) ;
03912
03913 #else // OSDL_USES_SDL
03914
03915 return "" ;
03916
03917 #endif // OSDL_USES_SDL
03918
03919 }
03920
03921
03922
03923 Surface & Surface::LoadImage( const std::string & filename,
03924 bool convertToDisplayFormat, bool convertWithAlpha )
03925 {
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935 Surface * toLoad = new Surface() ;
03936
03937 try
03938 {
03939
03940 toLoad->loadImage( filename, false,
03941 convertToDisplayFormat, convertWithAlpha ) ;
03942
03943 }
03944 catch( const TwoDimensional::ImageException & e )
03945 {
03946
03947 delete toLoad ;
03948 throw ;
03949
03950 }
03951
03952 return * toLoad ;
03953
03954 }
03955
03956
03957
03958 Surface & Surface::LoadPNG( const std::string & filename,
03959 bool convertToDisplayFormat, bool convertWithAlpha )
03960 {
03961
03962 Surface * toLoad = new Surface() ;
03963
03964 try
03965 {
03966 toLoad->loadPNG( filename, false,
03967 convertToDisplayFormat, convertWithAlpha ) ;
03968 }
03969 catch( const TwoDimensional::ImageException & e )
03970 {
03971 delete toLoad ;
03972 throw ;
03973 }
03974
03975 return * toLoad ;
03976
03977 }
03978
03979
03980
03981 Surface & Surface::LoadJPG( const std::string & filename,
03982 bool convertToDisplayFormat, bool convertWithAlpha )
03983 {
03984
03985 Surface * toLoad = new Surface() ;
03986
03987 try
03988 {
03989 toLoad->loadJPG( filename, false,
03990 convertToDisplayFormat, convertWithAlpha ) ;
03991 }
03992 catch( const TwoDimensional::ImageException & e )
03993 {
03994 delete toLoad ;
03995 throw ;
03996 }
03997
03998 return * toLoad ;
03999
04000 }
04001
04002
04003
04004
04005 string Surface::InterpretFlags( Flags flags )
04006 {
04007
04008
04009
04010
04011
04012
04013
04014 std::list<string> res ;
04015
04016 if ( flags & ( AnyPixelFormat | DoubleBuffered
04017 | FullScreen | OpenGL | OpenGLBlit ) )
04018 {
04019
04020 res.push_back( "This surface should be a display surface." ) ;
04021
04022 if ( flags & AnyPixelFormat )
04023 res.push_back(
04024 "Allows any pixel format for the display surface." ) ;
04025 else
04026 res.push_back( "Only specified pixel format "
04027 "is accepted for the display surface." ) ;
04028
04029 if ( flags & DoubleBuffered )
04030 res.push_back( "Display surface is double buffered." ) ;
04031 else
04032 res.push_back( "Display surface is not double buffered." ) ;
04033
04034 if ( flags & FullScreen )
04035 res.push_back( "Display surface is fullscreen." ) ;
04036 else
04037 res.push_back( "Display surface is in windowed mode "
04038 "(not full screen)." ) ;
04039
04040 if ( flags & OpenGL )
04041 res.push_back( "Display surface has an OpenGL context." ) ;
04042 else
04043 res.push_back( "Display surface has no OpenGL context." ) ;
04044
04045 if ( flags & OpenGLBlit )
04046 res.push_back(
04047 "Display surface supports OpenGL blitting (deprecated)." ) ;
04048
04049
04050
04051
04052
04053
04054
04055
04056
04057
04058
04059
04060 if ( flags & Resizable )
04061 res.push_back( "Display surface is resizable." ) ;
04062 else
04063 res.push_back( "Display surface is not resizable." ) ;
04064
04065 }
04066 else
04067 {
04068 res.push_back( "No flag dedicated to display surfaces "
04069 "is used for this surface." ) ;
04070 }
04071
04072
04073 if ( flags & Software )
04074 res.push_back( "Surface is to be stored in system memory." ) ;
04075 else
04076 res.push_back(
04077 "Surface is not required to be stored in system memory." ) ;
04078
04079
04080 if ( flags & Hardware )
04081 res.push_back( "Surface is to be stored in video memory." ) ;
04082 else
04083 res.push_back(
04084 "Surface is not required to be stored in video memory." ) ;
04085
04086
04087 if ( flags & AsynchronousBlit )
04088 res.push_back( "Surface should use asynchronous blits if possible." ) ;
04089 else
04090 res.push_back(
04091 "Surface is not required to use asynchronous blits if possible." ) ;
04092
04093
04094 if ( flags & ExclusivePalette )
04095 res.push_back( "Surface should have an exclusive palette." ) ;
04096 else
04097 res.push_back( "Surface has not an exclusive palette." ) ;
04098
04099
04100 if ( flags & HardwareAcceleratedBlit )
04101 res.push_back( "Surface is to use hardware-accelerated blits." ) ;
04102 else
04103 res.push_back(
04104 "Surface is not required to use hardware-accelerated blits." ) ;
04105
04106
04107 if ( flags & ColorkeyBlit )
04108 res.push_back( "Surface is to use colorkey blitting." ) ;
04109 else
04110 res.push_back( "Surface is not required to use colorkey blitting." ) ;
04111
04112
04113 if ( flags & RLEColorkeyBlit )
04114 res.push_back( "Surface is to use RLE-accelerated colorkey blits." ) ;
04115 else
04116 res.push_back(
04117 "Surface is not required to use RLE-accelerated colorkey blits." ) ;
04118
04119
04120 if ( flags & AlphaBlendingBlit )
04121 res.push_back( "Surface is to use alpha blending blits." ) ;
04122 else
04123 res.push_back(
04124 "Surface is not required to use alpha blending blits." ) ;
04125
04126
04127 if ( flags & Preallocated )
04128 res.push_back( "Surface is to use preallocated memory." ) ;
04129 else
04130 res.push_back( "Surface is not required to use preallocated memory." ) ;
04131
04132
04133 return "The specified surface flags, whose value is "
04134 + Ceylan::toString( flags, true )
04135 + ", mean: "
04136 + Ceylan::formatStringList( res, false,
04137 2 ) ;
04138
04139 }
04140
04141
04142
04143 Offset Surface::getOffset() const
04144 {
04145
04146 #if OSDL_USES_SDL
04147
04148 return _surface->offset ;
04149
04150 #else // OSDL_USES_SDL
04151
04152 return 0 ;
04153
04154 #endif // OSDL_USES_SDL
04155
04156 }
04157
04158
04159
04160 void Surface::setOffset( Offset offset )
04161 {
04162
04163 #if OSDL_USES_SDL
04164
04165 _surface->offset = offset ;
04166
04167 #endif // OSDL_USES_SDL
04168
04169 }
04170
04171
04172
04173 void Surface::flush()
04174 {
04175
04176 #if OSDL_USES_SDL
04177
04178 if ( _surface != 0 )
04179 {
04180
04181 #if OSDL_DEBUG_SURFACE
04182 LogPlug::trace( "Surface::flush: flushing surface." ) ;
04183 #endif // OSDL_DEBUG_SURFACE
04184
04185 if ( _displayType != BackBuffer )
04186 inconsistencyDetected(
04187 "Surface::flush: trying to delete a screen surface." ) ;
04188
04189 SDL_FreeSurface( _surface ) ;
04190 _surface = 0 ;
04191
04192 }
04193
04194 #endif // OSDL_USES_SDL
04195
04196 }
04197
04198
04199
04200 void Surface::inconsistencyDetected( const string & message ) const
04201 {
04202
04203 Ceylan::emergencyShutdown( "Inconsistency detected in OSDL Surface: "
04204 + message ) ;
04205
04206 }
04207
04208
04209
04210 Surface::Surface( const Surface & source ):
04211 TwoDimensional::UprightRectangle( 0, 0, 0, 0 ),
04212 Ceylan::EventSource(),
04213 Ceylan::Lockable(),
04214 Ceylan::SmartResource(),
04215 _surface( 0 ),
04216 _displayType( BackBuffer ),
04217 _mustBeLocked( false ),
04218 _needsRedraw( true )
04219 {
04220
04221
04222 Ceylan::emergencyShutdown(
04223 "Surface copy constructor called, whereas should never be used." ) ;
04224
04225 }
04226
04227
04228
04229 std::ostream & operator << ( std::ostream & os, Surface & s )
04230 {
04231 return os << s.toString() ;
04232 }