OSDLBackBufferedWidget.cc

Go to the documentation of this file.
00001 #include "OSDLBackBufferedWidget.h"
00002 
00003 
00004 #include "OSDLSurface.h"            // for Surface
00005 #include "OSDLPoint2D.h"            // for Point2D
00006 
00007 
00008 #ifdef OSDL_USES_CONFIG_H
00009 #include <OSDLConfig.h>             // for OSDL_DEBUG_WIDGET and al 
00010 #endif // OSDL_USES_CONFIG_H
00011 
00012 
00013 
00014 using namespace Ceylan::Log ;
00015 
00016 using namespace OSDL::Video ;
00017 using namespace OSDL::Video::TwoDimensional ;
00018 
00019 using std::string ;
00020 
00021 
00022 
00023 
00024 BackBufferedWidget::BackBufferedWidget( 
00025     Surface & container, 
00026     const Point2D & relativePosition, 
00027     Length width,
00028     Length height, 
00029     BaseColorMode baseColorMode, 
00030     Pixels::ColorDefinition baseColor,
00031     const string & title,
00032     bool minMaximizable, 
00033     bool draggable, 
00034     bool wrappable, 
00035     bool closable ) 
00036         throw( VideoException ) :
00037     Widget( container, 
00038             relativePosition, 
00039             width, 
00040             height,
00041             baseColorMode,
00042             baseColor,
00043             title, 
00044             minMaximizable, 
00045             draggable, 
00046             wrappable, 
00047             closable ), 
00048     _overallSurface( 0 ),
00049     _needsBackBufferRedraw( true )
00050 {
00051 
00052 #if OSDL_DEBUG_WIDGET
00053 
00054     LogPlug::trace( "Back-buffered widget constructor" ) ; 
00055     
00056 #endif // OSDL_DEBUG_WIDGET
00057 
00058     /*
00059      * Creates a shadow surface that will act as a cache for this widget 
00060      * own rendering : clones the container except for the dimensions.
00061      *
00062      */
00063     _overallSurface = new Surface( 
00064         container.getFlags(), 
00065         width, 
00066         height, 
00067         container.getBitsPerPixel(), 
00068         container.getPixelFormat().Rmask, 
00069         container.getPixelFormat().Gmask,
00070         container.getPixelFormat().Bmask,
00071         container.getPixelFormat().Amask ) ;    
00072 
00073     /*
00074      * Speed boost : an alpha channel will be used iff the backbuffer 
00075      * (hence, the container too) already use it.
00076      *
00077      */
00078     _overallSurface->convertToDisplay( /* useAlphaChannel */ 
00079         static_cast<bool>( getFlags() & Surface::AlphaBlendingBlit ) ) ;
00080         
00081 }
00082 
00083 
00084 
00085 BackBufferedWidget::~BackBufferedWidget() throw()
00086 {
00087 
00088 #if OSDL_DEBUG_WIDGET
00089 
00090     LogPlug::trace( "Back-buffered widget destructor" ) ; 
00091     
00092 #endif // OSDL_DEBUG_WIDGET
00093 
00094     delete _overallSurface ;
00095     
00096 }
00097 
00098 
00099 
00100 void BackBufferedWidget::resize( Length newWidth, Length newHeight, 
00101     bool ignored ) throw()  
00102 {   
00103     
00104     // Sets the 'need for redraw' state to true, and updates the client area :  
00105     Widget::resize( newWidth, newHeight ) ;
00106     
00107     _overallSurface->resize( newWidth, newHeight ) ;
00108     
00109     setBackBufferRedrawState( true ) ;
00110     
00111 }
00112 
00113 
00114 
00115 void BackBufferedWidget::setBaseColorMode( BaseColorMode newBaseColorMode, 
00116     Pixels::ColorDefinition newBaseColor ) throw( VideoException )
00117 {
00118     
00119     /*
00120      * Same as Widget::setBaseColorMode except the back-buffer is modified 
00121      * as well :
00122      *
00123      */
00124 
00125     bool mustUpdateColor = ( ( _baseColorMode == NotInitialized )
00126              && ( newBaseColorMode != NotInitialized ) ) 
00127         || ( ! Pixels::areEqual( newBaseColor, _baseColor ) ) ;
00128         
00129     bool mustUpdateColorKey = false ;
00130      
00131      
00132     if ( newBaseColorMode != _baseColorMode )
00133     {
00134     
00135         // Here the base color mode changed :
00136         
00137         // Deactivate color key if needed :
00138         if ( _baseColorMode == Colorkey )
00139         {
00140             
00141             // Thus newBaseColorMode != Colorkey, so :
00142             
00143             setColorKey( /* no more color-keying */ 0, 
00144                 /* do not care */ _actualBaseColor ) ;
00145                 
00146             _overallSurface->setColorKey( /* no more color-keying */ 0, 
00147                 /* do not care */ _actualBaseColor ) ;
00148                 
00149         }   
00150         else
00151         {
00152             // Activate color key if needed :
00153             if ( newBaseColorMode == Colorkey )
00154                 mustUpdateColorKey = true ;
00155         }
00156         
00157         _baseColorMode = newBaseColorMode ;
00158         
00159     }
00160     else
00161     {
00162         // Here the base color mode did not change, but base color may have :
00163         
00164         if ( ( _baseColorMode == Colorkey ) && mustUpdateColor )
00165             mustUpdateColorKey = true ;
00166     }
00167     
00168     if ( mustUpdateColor )
00169     {
00170     
00171         _baseColor = newBaseColor ;
00172         _actualBaseColor = Pixels::convertColorDefinitionToPixelColor(
00173             getPixelFormat(), _baseColor ) ;
00174         
00175         // Sets the widget redraw state to true as well :   
00176         setBackBufferRedrawState( true ) ;
00177                 
00178     }
00179     
00180         
00181     if ( mustUpdateColorKey )
00182     {
00183                 
00184         /*
00185          * Comment following two lines to see the colorkey 
00186          * (generally, Pixels::Red) :
00187          *
00188          */
00189         setColorKey( ColorkeyBlit | RLEColorkeyBlit, _actualBaseColor ) ;
00190         
00191         _overallSurface->setColorKey( ColorkeyBlit | RLEColorkeyBlit,
00192             _actualBaseColor ) ;
00193         
00194         // Sets the widget redraw state to true as well :   
00195         setBackBufferRedrawState( true ) ;
00196     
00197     }   
00198         
00199     
00200 }
00201 
00202 
00203 
00204 void BackBufferedWidget::redraw() throw() 
00205 {
00206 
00207 #if OSDL_DEBUG_WIDGET
00208 
00209     LogPlug::trace( "BackBufferedWidget::redraw : needs redraw attribute is " 
00210         + Ceylan::toString( getRedrawState() ) + "." ) ; 
00211         
00212 #endif // OSDL_DEBUG_WIDGET
00213 
00214     /*
00215      * Triggers its own redraw, then the full recursive redraw for 
00216      * all internal subwidgets :
00217      *
00218      */
00219     Surface::redraw() ;
00220     
00221     // Once done, draw the result on the container :
00222     try
00223     {
00224         
00225         // Uncomment to debug blits :
00226         /*
00227         
00228         savePNG( Ceylan::toString( this ) + "-redrawn-backbuffer.png" ) ;
00229                 
00230         _overallSurface->savePNG( Ceylan::toString( this ) 
00231             + "-redrawn-frontbuffer.png" ) ;        
00232             
00233         */
00234         
00235         _overallSurface->blitTo( getContainer().getWidgetRenderTarget(),
00236             _upperLeftCorner ) ;
00237     }
00238     catch( const VideoException & e )
00239     {
00240         LogPlug::error( 
00241             "BackBufferedWidget::redraw : blit to container failed : " 
00242             + e.toString() ) ;
00243     }   
00244     
00245 }
00246 
00247 
00248 
00249 void BackBufferedWidget::redrawInternal() throw() 
00250 {
00251 
00252 #if OSDL_DEBUG_WIDGET
00253 
00254     LogPlug::trace( "BackBufferedWidget::redrawInternal : "
00255         "needs back-buffer redraw attribute is " 
00256         + Ceylan::toString( getBackBufferRedrawState() ) + "." ) ; 
00257         
00258 #endif // OSDL_DEBUG_WIDGET
00259 
00260     /*
00261      * Here we know that this widget and its subwidgets have to be redrawn 
00262      * as a whole.
00263      *
00264      * But this widget may or may not reuse any previously cached own 
00265      * rendering.
00266      * If not, it will have to paint itself first : 
00267      *
00268      */
00269     if ( getBackBufferRedrawState() )
00270     {
00271     
00272         /*
00273          * Here the widget has to paint itself again :
00274          * (will ultimately set the back-buffer need for redraw state to false)
00275          *
00276          */
00277         redrawBackBuffer() ;
00278     
00279     }
00280     else
00281     {   
00282     
00283 #if OSDL_DEBUG_WIDGET
00284 
00285         LogPlug::trace( "BackBufferedWidget::redrawInternal :"
00286             " back-buffer already available." ) ; 
00287             
00288 #endif // OSDL_DEBUG_WIDGET
00289         
00290     }
00291 
00292 
00293 #if OSDL_DEBUG_WIDGET
00294 
00295     LogPlug::trace( "BackBufferedWidget::redrawInternal : "
00296         "blitting back-buffer to front buffer." ) ;
00297         
00298 #endif // OSDL_DEBUG_WIDGET
00299     
00300     
00301     /*
00302      * We can now reuse our own previously cached rendering on both cases. 
00303      * But before blitting from back-buffer to overall surface, we must 
00304      * fill the latter with the color key, if any, otherwise color-keing 
00305      * will be lost for the blit from this overall surface to the container.
00306      *
00307      */
00308     
00309     if ( getBaseColorMode() == Colorkey ) 
00310         _overallSurface->fill( _baseColor ) ;
00311         
00312     blitTo( *_overallSurface ) ;
00313     
00314     setRedrawState( false ) ;
00315     
00316 }
00317 
00318 
00319 
00320 void BackBufferedWidget::redrawBackBuffer() throw()
00321 {
00322 
00323 #if OSDL_DEBUG_WIDGET
00324 
00325     LogPlug::trace( "BackBufferedWidget::redrawBackBuffer" ) ; 
00326     
00327 #endif // OSDL_DEBUG_WIDGET
00328 
00329 
00330     // (...) [real rendering should take place here in overriden methods]
00331     
00332     // This inherited Surface (not _overallSurface !) should be updated here.
00333         
00334     
00335     /*
00336      * This mostly empty method should be overriden, but all versions 
00337      * should end with :    
00338      *
00339      */
00340     setBackBufferRedrawState( false ) ;
00341     
00342 }
00343 
00344 
00345 
00346 Surface & BackBufferedWidget::getWidgetRenderTarget() throw()
00347 {   
00348 
00349     // Sub-widgets must target overall surface, not back-buffer :
00350     return *_overallSurface ;
00351     
00352 }
00353 
00354 
00355 
00356 const string BackBufferedWidget::toString( Ceylan::VerbosityLevels level ) 
00357     const throw()
00358 {
00359 
00360     string res ;
00361     
00362     if ( getBackBufferRedrawState() )
00363         res += "needs to be redrawn. " ;
00364     else        
00365         res += "does not need to be redrawn. " ;
00366     
00367     res += "Overall surface is : " + _overallSurface->toString( level ) ;
00368         
00369     return "Back-buffered widget description whose back-buffer " 
00370         + res + Widget::toString( level ) ;
00371     
00372 }
00373 
00374 
00375 
00376 void BackBufferedWidget::setBackBufferRedrawState( bool needsToBeRedrawn )
00377     throw()
00378 {
00379 
00380     /*
00381      * If back-buffer redraw state goes from false to true, then the 
00382      * general redraw state should do as well, so that it propagates 
00383      * the need of redraw to the container :
00384      *
00385      */
00386     if ( ( getBackBufferRedrawState() == false ) && needsToBeRedrawn )
00387     {
00388         _needsBackBufferRedraw = true ;
00389         setRedrawState( true ) ;
00390     }   
00391 
00392 }
00393 
00394     
00395     
00396 bool BackBufferedWidget::getBackBufferRedrawState() const throw()
00397 {
00398     return _needsBackBufferRedraw ;
00399 }
00400 

Generated on Fri Mar 30 14:46:59 2007 for OSDL by  doxygen 1.5.1