OSDLConic.cc

Go to the documentation of this file.
00001 #include "OSDLConic.h"
00002 
00003 #include "OSDLFromGfx.h"        // for filledCircleRGBANotBlended
00004 #include "OSDLSurface.h"        // for Surface
00005 #include "OSDLPoint2D.h"        // for Point2D
00006 #include "OSDLVideo.h"          // for VideoModule
00007 
00008 #include "Ceylan.h"             // for Ceylan::LogPlug
00009 
00010 #include "SDL_gfxPrimitives.h"  // for graphic primitives exported by SDL_gfx
00011 
00012 
00013 #ifdef OSDL_USES_CONFIG_H
00014 #include <OSDLConfig.h>         // for OSDL_DEBUG_CONICS and al 
00015 #endif // OSDL_USES_CONFIG_H
00016 
00017 using namespace OSDL::Video ;
00018 
00019 using namespace Ceylan::Log ;
00020 
00021 
00022 
00023 // A return code of 0 for SDL_gfx functions means no error, contrary to -1.
00024 
00025 
00026 
00027 bool TwoDimensional::drawCircle( Surface & targetSurface, 
00028     Coordinate xCenter, Coordinate yCenter, Length radius, 
00029     Pixels::ColorElement red, Pixels::ColorElement green, 
00030     Pixels::ColorElement blue, Pixels::ColorElement alpha, 
00031     bool filled, bool blended ) throw()
00032 {
00033 
00034 
00035     /*
00036      * To avoid code duplication, this RGBA version of drawCircle may 
00037      * call the color definition-based one. 
00038      * However back-end functions take RGBA arguments, so a useless double 
00039      * conversion is spared here.
00040      *
00041      */
00042 #if OSDL_DEBUG_CONICS
00043 
00044     LogPlug::trace( "TwoDimensional::drawCircle (RGBA) : center = [" 
00045         + Ceylan::toString( xCenter ) + ";" + Ceylan::toString( yCenter ) 
00046         + "], radius = " + Ceylan::toString( radius )
00047         + ", color : "   + Pixels::toString( 
00048             Pixels::convertRGBAToColorDefinition( red, green, blue, alpha ) ) 
00049         + ", filled = "  + Ceylan::toString( filled ) 
00050         + ", blended = " + Ceylan::toString( blended ) ) ;
00051         
00052 #endif // OSDL_DEBUG_CONICS
00053     
00054     if ( blended )
00055     {
00056     
00057         if ( filled )
00058         {
00059     
00060             // Disc :
00061             return ( ::filledCircleRGBA( & targetSurface.getSDLSurface(),
00062                 xCenter, yCenter, radius, red, green, blue, alpha ) == 0 ) ;
00063         }
00064         else
00065         {
00066     
00067             // Circle :
00068     
00069             if ( VideoModule::GetAntiAliasingState() )
00070             {
00071                 return ( ::aacircleRGBA( & targetSurface.getSDLSurface(),
00072                     xCenter, yCenter, radius, red, green, blue, alpha ) == 0 ) ;
00073     
00074             }
00075             else
00076             {
00077                 return ( ::circleRGBA( & targetSurface.getSDLSurface(), 
00078                     xCenter, yCenter, radius, red, green, blue, alpha ) == 0 ) ;
00079     
00080             }
00081     
00082         }
00083         
00084     }
00085     else
00086     {
00087         
00088         /*
00089          * Here the disc should not be blended. 
00090          * As for circles, this is not implemented yet so they will still be
00091          * blended :
00092          *
00093          */
00094     
00095     
00096         if ( filled )
00097         {
00098     
00099             // Disc :
00100             return ( ::filledCircleRGBANotBlended( 
00101                 & targetSurface.getSDLSurface(), 
00102                 xCenter, yCenter, radius, red, green, blue, alpha ) == 0 ) ;
00103         }
00104         else
00105         {
00106     
00107             
00108             // Circle :
00109     
00110             if ( VideoModule::GetAntiAliasingState() )
00111             {
00112             
00113                 /* Not implemented yet :
00114                 
00115                 return ( ::aacircleRGBANotBlended( 
00116                     & targetSurface.getSDLSurface(), 
00117                     xCenter, yCenter, radius, red, green, blue, alpha ) == 0 ) ;
00118                     
00119                  */
00120                  
00121                 return ( ::aacircleRGBA( & targetSurface.getSDLSurface(), 
00122                     xCenter, yCenter, radius, red, green, blue, alpha ) == 0 ) ;
00123             }
00124             else
00125             {
00126 
00127                 /* Not implemented yet :
00128                 
00129                 return ( ::circleRGBANotBlended( 
00130                     & targetSurface.getSDLSurface(), xCenter, yCenter,
00131                     radius, red, green, blue, alpha ) == 0 ) ;
00132                  */
00133     
00134                 return ( ::circleRGBA( & targetSurface.getSDLSurface(), 
00135                     xCenter, yCenter, radius, red, green, blue, alpha ) == 0 ) ;
00136             }
00137     
00138         }
00139     
00140     }
00141         
00142 }
00143 
00144 
00145 
00146 bool TwoDimensional::drawCircle( Surface & targetSurface, 
00147     Coordinate xCenter, Coordinate yCenter,
00148     Length radius, Pixels::ColorDefinition colorDef, bool filled, bool blended ) throw()
00149 {
00150 
00151 #if OSDL_DEBUG_CONICS 
00152 
00153     LogPlug::trace( "TwoDimensional::drawCircle (color definition): center = [" 
00154         + Ceylan::toString( xCenter ) + ";" + Ceylan::toString( yCenter ) 
00155         + "], radius = " + Ceylan::toString( radius )
00156         + ", color : "   + Pixels::toString( colorDef ) 
00157         + ", filled = "  + Ceylan::toString( filled ) 
00158         + ", blended = " + Ceylan::toString( blended ) ) ;
00159         
00160 #endif // OSDL_DEBUG_CONICS
00161     
00162     
00163     if ( blended )
00164     {   
00165     
00166         if ( filled )
00167         {
00168     
00169             // Disc :
00170             return ( ::filledCircleColor( & targetSurface.getSDLSurface(),
00171                     xCenter, yCenter, radius,
00172                     Pixels::convertColorDefinitionToRawPixelColor( colorDef ) ) 
00173                         == 0 ) ;
00174         }
00175         else
00176         {
00177     
00178             // Circle :
00179     
00180             if ( VideoModule::GetAntiAliasingState() )
00181             {
00182             
00183                 return ( ::aacircleColor( & targetSurface.getSDLSurface(),
00184                     xCenter, yCenter, radius,
00185                     Pixels::convertColorDefinitionToRawPixelColor( colorDef ) )
00186                         == 0 ) ;
00187     
00188             }
00189             else
00190             {
00191             
00192                 return ( ::circleColor( & targetSurface.getSDLSurface(),
00193                     xCenter, yCenter, radius,
00194                     Pixels::convertColorDefinitionToRawPixelColor( colorDef ) )
00195                         == 0 ) ;
00196     
00197             }
00198     
00199         }
00200         
00201     }
00202     else // Not blended here :
00203     {
00204 
00205         /*
00206          * Here the disc should not be blended. As for circles, this is not
00207          * implemented yet so they will still be blended :
00208          *
00209          */
00210          
00211         if ( filled )
00212         {
00213     
00214             // Disc :
00215 
00216 #if OSDL_DEBUG_CONICS
00217             LogPlug::trace( "TwoDimensional::drawCircle : "
00218                 "before filledCircleColorNotBlended, "
00219                 + targetSurface.describePixelAt( xCenter, yCenter ) ) ;
00220             
00221             bool result = ( ::filledCircleRGBANotBlended( 
00222                     & targetSurface.getSDLSurface(), xCenter, yCenter, radius, 
00223                 colorDef.r, colorDef.g, colorDef.b, colorDef.unused ) == 0 ) ;  
00224                 
00225             LogPlug::trace( "TwoDimensional::drawCircle : "
00226                 "after filledCircleColorNotBlended, "
00227                 + targetSurface.describePixelAt( xCenter, yCenter ) ) ;
00228             
00229             return result ; 
00230 
00231 #endif // OSDL_DEBUG_CONICS
00232 
00233             return ( ::filledCircleRGBANotBlended( 
00234                 & targetSurface.getSDLSurface(), xCenter, yCenter, radius, 
00235                 colorDef.r, colorDef.g, colorDef.b, colorDef.unused ) == 0 ) ;
00236                 
00237         }
00238         else
00239         {
00240     
00241             
00242             // Circle :
00243     
00244             if ( VideoModule::GetAntiAliasingState() )
00245             {
00246             
00247                 /* Not implemented yet :
00248                 
00249                 return ( ::aacircleRGBANotBlended( 
00250                     & targetSurface.getSDLSurface(), 
00251                     xCenter, yCenter, radius, 
00252                     colorDef.r, colorDef.g, colorDef.b, colorDef.unused )
00253                         == 0 ) ;
00254                         
00255                  */
00256                  
00257                 return ( ::aacircleRGBA( & targetSurface.getSDLSurface(), 
00258                     xCenter, yCenter, radius, 
00259                     colorDef.r, colorDef.g, colorDef.b, colorDef.unused ) 
00260                         == 0 ) ;
00261             }
00262             else
00263             {
00264 
00265                 /* Not implemented yet :
00266                 
00267                 return ( ::circleRGBANotBlended( 
00268                     & targetSurface.getSDLSurface(), xCenter, yCenter, radius,
00269                      colorDef.r, colorDef.g, colorDef.b, colorDef.unused ) 
00270                         == 0 ) ;
00271                         
00272                  */
00273     
00274                 return ( ::circleRGBA( & targetSurface.getSDLSurface(), 
00275                     xCenter, yCenter, radius,
00276                     colorDef.r, colorDef.g, colorDef.b, colorDef.unused ) 
00277                         == 0 ) ;
00278                         
00279             }
00280     
00281         }
00282     
00283     }
00284         
00285 }
00286 
00287 
00288 
00289 bool TwoDimensional::drawDiscWithEdge( Surface & targetSurface, 
00290     Coordinate xCenter, Coordinate yCenter,     
00291     Length outerRadius, Length innerRadius, 
00292     Pixels::ColorDefinition ringColorDef, 
00293     Pixels::ColorDefinition discColorDef, bool blended ) throw()
00294 {
00295 
00296     if ( innerRadius >= outerRadius )
00297         return false ;
00298                 
00299                 
00300     /*
00301      * Special case if inner color is not totally opaque <b>and</b> 
00302      * blending is requested :
00303      *
00304      */
00305     if ( discColorDef.unused != AlphaOpaque && blended )
00306     {
00307     
00308         
00309         /*
00310          * Drawing directly the whole edged disc cannot be achieved unless
00311          * writing a dedicated primitive. 
00312          * The work is done here in two steps, each of them drawing a 
00313          * basic disc, so that the final result is the expected edged disc.
00314          *
00315          */
00316         
00317         /*
00318          * Previous solution was OSDL_MUST_RECTIFY_DISC_ALPHA :
00319          *
00320          * In this case, we have to create a temporary surface where both 
00321          * discs (first the outer one for the ring, then the inner one) are
00322          * blitted : as the latter must replace the former instead of being
00323          * blended with it, the inner disc is blitted as if it was totally
00324          * opaque (so the ring color is not taken into account), then its 
00325          * alpha is corrected.
00326          *
00327          * Current solution is : do the same but draw the inner circle with 
00328          * a putPixel involving no blending to avoid having to fix alpha.
00329          *
00330          */
00331     
00332     
00333         /*
00334          * Uncomment to switch back to former (more expensive) deprecated
00335          * solution (useless with newer circle primitive) :
00336          *
00337          */
00338         //#define OSDL_MUST_RECTIFY_DISC_ALPHA
00339         
00340 #ifdef OSDL_MUST_RECTIFY_DISC_ALPHA
00341         
00342         // 'blended' not taken into account here (always considered as true).
00343         
00344         // First create the overall surface which will contain both discs :
00345         Surface * fullEdgedDiscSurface = new Surface( 
00346             Surface::Software | Surface::AlphaBlendingBlit, 
00347             /* width */ 2 * outerRadius, /* height */ 2 * outerRadius ) ;
00348                             
00349         // From here 'fullEdgedDiscSurface' is a totally transparent surface.
00350         
00351         // Draw an opaque ring :
00352         ColorElement ringAlpha = ringColorDef.unused ;
00353         ringColorDef.unused = Pixels::AlphaOpaque ;
00354         
00355         // Draw the outer disc in it, for the ring :
00356         if ( ! fullEdgedDiscSurface->drawCircle( outerRadius, 
00357             outerRadius, outerRadius, ringColorDef, /* filled */ true ) )
00358         {
00359             delete fullEdgedDiscSurface ;
00360             return false ;
00361         }   
00362         
00363         // Draw the inner disc as if it were opaque :
00364         
00365         ColorElement discAlpha = discColorDef.unused ;
00366         discColorDef.unused = Pixels::AlphaOpaque ;
00367 
00368         fullEdgedDiscSurface->drawCircle( outerRadius, 
00369             outerRadius, innerRadius, discColorDef, /* filled */ true ) ;
00370 
00371         /*
00372          * Refreshes the alpha of the ring (ought to apply to a smaller 
00373          * area than the whole surface) :
00374          *
00375          */
00376         fullEdgedDiscSurface->setAlphaForColor( ringColorDef, ringAlpha ) ;
00377         
00378         
00379         /*
00380          * Refreshes the alpha of the disc (ought to apply to a smaller area
00381          * than the whole surface) :
00382          *
00383          */
00384         fullEdgedDiscSurface->setAlphaForColor( discColorDef, discAlpha ) ;
00385         
00386         LogPlug::debug( "fullEdgedDiscSurface : " 
00387             + fullEdgedDiscSurface->describePixelAt( 
00388                 outerRadius, outerRadius ) ) ;
00389             
00390         fullEdgedDiscSurface->blitTo( targetSurface, 
00391             xCenter - outerRadius, yCenter - outerRadius ) ;
00392         
00393         delete fullEdgedDiscSurface ;
00394         
00395         
00396 #else // OSDL_MUST_RECTIFY_DISC_ALPHA
00397         
00398         /*
00399          * Not using previous trick, preferring introducting a new circle
00400          * primitive ignoring blending so that the aimed alpha is already 
00401          * there, hence does not have to be fixed afterwards.
00402          *
00403          */
00404 
00405         // First, create the overall surface which will contain both discs :
00406         Surface * fullEdgedDiscSurface = new Surface( 
00407             Surface::Software | Surface::AlphaBlendingBlit, 
00408             /* width */ 2 * outerRadius, /* height */ 2 * outerRadius ) ;
00409          
00410         /*
00411          * RGBA surfaces are created with all pixels set to [0;0;0;0] 
00412          * (totally transparent black), which is convenient since it 
00413          * allows that nothing of the outside of the ring will appear
00414          * with the final blit (apparently color key and pixel-level 
00415          * alpha blending cannot be used together).
00416          *
00417          * Hence 'fullEdgedDiscSurface->fill( Pixels::Transparent ) ;' 
00418          * would be useless.
00419          *
00420          */
00421                 
00422         /*
00423          * Draws the outer ring (including the inside disc, which be 
00424          * replaced later) :
00425          *
00426          */
00427         if ( ! fullEdgedDiscSurface->drawCircle(
00428             outerRadius, outerRadius, outerRadius,
00429             ringColorDef, /* filled */ true, /* blended */ false ) )
00430         {
00431             delete fullEdgedDiscSurface ;
00432             return false ;
00433         }   
00434     
00435         // Draws inside the inner disc :
00436     
00437         if ( ! fullEdgedDiscSurface->drawCircle( 
00438             outerRadius, outerRadius, innerRadius,
00439             discColorDef, /* filled */ true, /* blended */ false ) )
00440         {
00441             delete fullEdgedDiscSurface ;
00442             return false ;
00443         }
00444         
00445         fullEdgedDiscSurface->blitTo( targetSurface, 
00446             xCenter - outerRadius, yCenter - outerRadius ) ;
00447         
00448         delete fullEdgedDiscSurface ;
00449         
00450 
00451 #endif // OSDL_MUST_RECTIFY_DISC_ALPHA
00452 
00453         
00454         return true ;   
00455         
00456         
00457     }
00458     
00459 
00460     /*
00461      * Here the inner color is totally opaque and/or no blending is 
00462      * requested (the easy case !) :
00463      *
00464      */
00465     
00466     // Draws the outer ring (and the inside which be replaced) :
00467     if ( ! drawCircle( targetSurface, xCenter, yCenter, 
00468         outerRadius, ringColorDef, /* filled */ true, blended ) )
00469     {
00470         return false ;
00471     }   
00472     
00473     
00474     // Draws inside the inner disc :
00475     if ( ! drawCircle( targetSurface, xCenter, yCenter, 
00476         innerRadius, discColorDef,  /* filled */ true, blended ) )
00477     {
00478         return false ;
00479     }
00480     
00481     return true ;   
00482     
00483 }   
00484 
00485 
00486 
00487 bool TwoDimensional::drawEllipse( Surface & targetSurface, 
00488     Coordinate xCenter, Coordinate yCenter, 
00489     Length horizontalRadius, Length verticalRadius,
00490     Pixels::ColorElement red, Pixels::ColorElement green, 
00491     Pixels::ColorElement blue, Pixels::ColorElement alpha, bool filled ) throw()
00492 {
00493 
00494     if ( filled )
00495     {
00496                 
00497         return ( ::filledEllipseRGBA( & targetSurface.getSDLSurface(), 
00498             xCenter, yCenter, horizontalRadius, verticalRadius, 
00499             red, green, blue, alpha ) == 0 ) ;
00500     }
00501     else
00502     {
00503         
00504         if ( VideoModule::GetAntiAliasingState() )
00505         {
00506         
00507             return ( ::aaellipseRGBA( & targetSurface.getSDLSurface(), 
00508                 xCenter, yCenter, horizontalRadius, verticalRadius, 
00509                 red, green, blue, alpha ) == 0 ) ;
00510                 
00511             
00512         }
00513         else
00514         {
00515         
00516             return ( ::ellipseRGBA( & targetSurface.getSDLSurface(), 
00517                 xCenter, yCenter, horizontalRadius, verticalRadius, 
00518                 red, green, blue, alpha ) == 0 ) ;
00519         
00520         }
00521     
00522     }
00523         
00524 }
00525 
00526 
00527 
00528 bool TwoDimensional::drawEllipse( Surface & targetSurface, 
00529     Coordinate xCenter, Coordinate yCenter,     
00530     Length horizontalRadius, Length verticalRadius,
00531     Pixels::ColorDefinition colorDef, bool filled ) throw()
00532 {
00533 
00534     if ( filled )
00535     {
00536                 
00537         return ( ::filledEllipseColor( & targetSurface.getSDLSurface(), 
00538             xCenter, yCenter, horizontalRadius, verticalRadius, 
00539             Pixels::convertColorDefinitionToRawPixelColor( colorDef ) ) == 0 ) ;
00540     
00541     }
00542     else
00543     {
00544         
00545         if ( VideoModule::GetAntiAliasingState() )
00546         {
00547         
00548             return ( ::aaellipseColor( & targetSurface.getSDLSurface(), 
00549                 xCenter, yCenter, horizontalRadius, verticalRadius, 
00550                 Pixels::convertColorDefinitionToRawPixelColor( colorDef ) ) 
00551                     == 0 ) ;
00552             
00553         }
00554         else
00555         {
00556         
00557             return ( ::ellipseColor( & targetSurface.getSDLSurface(), 
00558                 xCenter, yCenter, horizontalRadius, verticalRadius, 
00559                 Pixels::convertColorDefinitionToRawPixelColor( colorDef ) ) 
00560                     == 0 ) ;
00561         
00562         }
00563     
00564     }
00565         
00566 }
00567 

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