OSDLUprightRectangle.cc

Go to the documentation of this file.
00001 #include "OSDLUprightRectangle.h"
00002 
00003 #include "OSDLPoint2D.h"       // for Point2D
00004 #include "OSDLSurface.h"       // for Surface
00005 
00006 #include "Ceylan.h"            // for LogPlug
00007 
00008 #include "SDL_gfxPrimitives.h" // for rectangleRGBA
00009 
00010 
00011 #ifdef OSDL_USES_CONFIG_H
00012 #include <OSDLConfig.h>        // for OSDL_DEBUG_RECTANGLES and al 
00013 #endif // OSDL_USES_CONFIG_H
00014 
00015 
00016 using std::string ;
00017 
00018 using namespace Ceylan::Log ;
00019 
00020 using namespace OSDL::Video ;
00021 using namespace OSDL::Video::TwoDimensional ;
00022 
00023 
00024 
00025 
00026 UprightRectangle::UprightRectangle( const Point2D & upperLeftCorner,
00027         const Point2D & lowerRightCorner ) throw( VideoException ) :
00028     _x( upperLeftCorner.getX() ),
00029     _y( upperLeftCorner.getY() ),
00030     _width( static_cast<Length>( 
00031         lowerRightCorner.getX() - upperLeftCorner.getX() ) ),
00032     _height( static_cast<Length>(
00033         lowerRightCorner.getY() - upperLeftCorner.getY() ) )
00034 {
00035 
00036     if ( lowerRightCorner.getX() < upperLeftCorner.getX() )
00037         throw VideoException( 
00038             "UprightRectangle constructor : width is negative ("
00039             + Ceylan::toString( static_cast<Ceylan::SignedLongInteger>( 
00040                 lowerRightCorner.getX() - upperLeftCorner.getX() ) )
00041             + ")." ) ;
00042         
00043     if ( lowerRightCorner.getY() < upperLeftCorner.getY() )
00044         throw VideoException(
00045             "UprightRectangle constructor : height is negative ("
00046             + Ceylan::toString( static_cast<Ceylan::SignedLongInteger>(
00047                 lowerRightCorner.getY() - upperLeftCorner.getY() ) )
00048             + " )." ) ;
00049         
00050 }
00051 
00052 
00053 UprightRectangle::UprightRectangle( const Point2D & upperLeftCorner,
00054         Length width, Length height ) throw() :
00055     _x( upperLeftCorner.getX() ),
00056     _y( upperLeftCorner.getY() ),
00057     _width( width ),
00058     _height( height )
00059 {
00060 
00061 }   
00062     
00063             
00064 UprightRectangle::UprightRectangle( Coordinate x, Coordinate y,
00065          Length width, Length height ) throw() :
00066     _x( x ),
00067     _y( y ),
00068     _width( width ),
00069     _height( height )
00070 {
00071 
00072 }
00073 
00074 
00075 UprightRectangle::UprightRectangle( const SDL_Rect & source ) throw() :
00076     _x( source.x ),
00077     _y( source.y ),
00078     _width( source.w ),
00079     _height( source.h )
00080 {
00081 
00082 }
00083 
00084 
00085 
00086 UprightRectangle::~UprightRectangle() throw()
00087 {
00088 
00089 }
00090 
00091 
00092 
00093 
00094 // Section for upper-left corner.
00095 
00096 
00097 
00098 Point2D UprightRectangle::getUpperLeftCorner() const throw()
00099 {
00100 
00101     return Point2D( _x, _y ) ;
00102     
00103 }
00104 
00105 
00106 void UprightRectangle::setUpperLeftCorner( Point2D & newUpperLeftCorner )
00107     throw()
00108 {
00109 
00110     _x = newUpperLeftCorner.getX() ;
00111     _y = newUpperLeftCorner.getY() ;    
00112     
00113 }
00114 
00115 
00116 
00117 Coordinate UprightRectangle::getUpperLeftAbscissa() const throw()
00118 {
00119 
00120     return _x ;
00121     
00122 }
00123 
00124  
00125 void UprightRectangle::setUpperLeftAbscissa( Coordinate newAbscissa ) throw()
00126 {
00127 
00128     _x = newAbscissa ;
00129     
00130 }
00131 
00132 
00133 
00134 Coordinate UprightRectangle::getUpperLeftOrdinate() const throw()
00135 {
00136 
00137     return _y ;
00138     
00139 }
00140 
00141  
00142 void UprightRectangle::setUpperLeftOrdinate( Coordinate newOrdinate ) throw()
00143 {
00144 
00145     _y = newOrdinate ;
00146     
00147 }
00148 
00149 
00150 
00151 
00152 // Section for lower-right corner.
00153 
00154 
00155 Point2D UprightRectangle::getLowerRightCorner() const throw()
00156 {
00157 
00158     return Point2D( static_cast<Coordinate>( _x + getWidth() ), 
00159         static_cast<Coordinate>( _y + getHeight() ) ) ;
00160         
00161 }
00162 
00163 
00164 void UprightRectangle::setLowerRightCorner( Point2D & newLowerRightCorner )
00165     throw( VideoException )
00166 {
00167 
00168     if ( newLowerRightCorner.getX() < _x || newLowerRightCorner.getY() < _y )
00169         throw VideoException( "UprightRectangle::setLowerRightCorner : "
00170             "misplaced lower right corner given (" 
00171             + newLowerRightCorner.toString() 
00172             + ") for rectangle : " + toString() ) ;
00173             
00174     _width  = newLowerRightCorner.getX() - _x ;
00175     _height = newLowerRightCorner.getY() - _y ; 
00176 
00177 }
00178 
00179 
00180 
00181 Coordinate UprightRectangle::getLowerRightAbscissa() const throw()
00182 {
00183 
00184     return _x + getWidth() ;
00185     
00186 }
00187 
00188  
00189 void UprightRectangle::setLowerRightAbscissa( Coordinate newAbscissa ) 
00190     throw( VideoException )
00191 {
00192 
00193     if ( newAbscissa < _x )
00194         throw VideoException( "UprightRectangle::setLowerRightAbscissa : "
00195             "misplaced lower right corner given (abscissa is " 
00196             + Ceylan::toString( newAbscissa ) 
00197             + ") for rectangle : " + toString() ) ;
00198 
00199     _width = newAbscissa - _x ;
00200     
00201 }
00202 
00203 
00204 
00205 Coordinate UprightRectangle::getLowerRightOrdinate() const throw()
00206 {
00207 
00208     return _y + getHeight() ;
00209     
00210 }
00211 
00212  
00213 void UprightRectangle::setLowerRightOrdinate( Coordinate newOrdinate ) 
00214     throw( VideoException )
00215 {
00216 
00217     if ( newOrdinate < _y )
00218         throw VideoException( "UprightRectangle::setLowerRightOrdinate : "
00219             "misplaced lower right corner given (ordinate is " 
00220             + Ceylan::toString( newOrdinate ) 
00221             + ") for rectangle : " + toString() ) ;
00222 
00223     _height = newOrdinate - _y ;
00224     
00225 }
00226 
00227 
00228 
00229 
00230  
00231 Length UprightRectangle::getWidth() const throw()
00232 {
00233 
00234     return _width ;
00235     
00236 }
00237 
00238 
00239 void UprightRectangle::setWidth( Length newWidth ) throw()
00240 {
00241 
00242     _width = newWidth ;
00243     
00244 }
00245 
00246 
00247 
00248 Length UprightRectangle::getHeight() const throw()
00249 {
00250 
00251     return _height ;
00252     
00253 }
00254 
00255 
00256 void UprightRectangle::setHeight( Length newHeight ) throw()
00257 {
00258 
00259     _height = newHeight ;
00260     
00261 }
00262         
00263     
00264         
00265 bool UprightRectangle::draw( Surface & target, 
00266     ColorElement red, ColorElement blue, ColorElement green, 
00267     ColorElement alpha, bool filled ) const throw()
00268 {
00269     
00270     return draw( target, Pixels::convertRGBAToColorDefinition( 
00271         red, green, blue, alpha ), filled ) ;
00272     
00273 }
00274 
00275 
00276 bool UprightRectangle::draw( Surface & target, 
00277     Pixels::ColorDefinition colorDef, bool filled ) const throw() 
00278 {
00279 
00280 
00281 #if OSDL_DEBUG_RECTANGLES
00282 
00283     LogPlug::trace( "Drawing a " + ( filled ? string( "" ) : string( "non " ) ) 
00284         + "filled rectangle from [" 
00285         + Ceylan::toString( _x ) + ";" + Ceylan::toString( _y ) 
00286         + "] to [" 
00287         + Ceylan::toString( _x + getWidth() ) + ";" 
00288         + Ceylan::toString( _y + getHeight() ) 
00289         + "] with color " + Pixels::toString( colorDef ) ) ;
00290         
00291 #endif // OSDL_DEBUG_RECTANGLES
00292     
00293     
00294     /*
00295      * Do not forget to substract one from both lengths, since starting 
00296      * from zero :
00297      * (ex : starting at 10, length 3 implies draw 10, 11, 12, and 
00298      * 12 = 10 + 3 - 1)
00299      *
00300      */
00301     
00302     if ( filled )
00303     {
00304     
00305         return ( ::boxColor( & target.getSDLSurface(), _x, _y, 
00306             _x + getWidth() - 1, _y + getHeight() - 1,
00307             Pixels::convertColorDefinitionToRawPixelColor( colorDef ) ) == 0 ) ;
00308             
00309     }
00310     else
00311     {
00312     
00313         return ( ::rectangleColor( & target.getSDLSurface(), _x, _y, 
00314             _x + getWidth() - 1, _y + getHeight() - 1,
00315             Pixels::convertColorDefinitionToRawPixelColor( colorDef ) ) == 0 ) ;
00316 
00317     }
00318         
00319 }
00320 
00321 
00322 
00323 bool UprightRectangle::drawWithRoundedCorners( Surface & target, 
00324     Length edgeWidth, Pixels::ColorDefinition edgeColorDef,
00325     Pixels::ColorDefinition backgroundColorDef ) const throw()
00326 {
00327 
00328     /*
00329      * This method has led to way too many issues with color correctness.
00330      *
00331      * After much efforts, the result is pixel perfect at last, after much
00332      * trouble, no matter if alphablending is to be taken into account or not.
00333      *
00334      */
00335         
00336     // Uncomment to debug boundaries :
00337     // draw( target, Pixels::Yellow, /* filled */ false ) ;
00338     
00339     /*
00340      * First render a full disc with a ring in it (with correct edge and
00341      * background colors), then split it in four equal parts to build the
00342      * corners, then finish with the drawing of the edges.
00343      *
00344      */
00345     
00346     Length radius ;
00347      
00348     try
00349     {
00350         radius = computeRadiusForRoundRectangle( edgeWidth ) ;
00351     }
00352     catch( const VideoException & e )
00353     {
00354         LogPlug::error( 
00355             "UprightRectangle::drawWithRoundedCorners : nothing drawn : " 
00356             + e.toString() ) ;
00357     }
00358         
00359             
00360     // Prepare the disc :
00361         
00362             
00363     /*
00364      * Note that 2 * radius is not always the same as 
00365      * Min( getWidth(), getHeight() ) due to rounding.
00366      *
00367      */
00368     
00369     Surface * disc ;
00370     
00371     Pixels::ColorMask redMask, greenMask, blueMask, alphaMask ;
00372     
00373     Pixels::getCurrentColorMasks( target.getPixelFormat(), 
00374         redMask, greenMask, blueMask, alphaMask ) ;
00375     
00376     if ( ( edgeColorDef.unused != Pixels::AlphaOpaque ) 
00377         || ( backgroundColorDef.unused != Pixels::AlphaOpaque ) )
00378     {
00379     
00380 
00381         /*
00382          * We are here in the case where alphablending must be managed.
00383          * 
00384          * Using alpha used to lead to nasty rounding errors in colors 
00385          * that make corners (actually the whole split disc) appear slightly
00386          * differently from other parts of the rectangle.
00387          *
00388          * One way of avoiding having different rounding errors for colors
00389          * between the disc and the rectangles would be to have the same 
00390          * pixel format for the disc than the target surface.
00391          * However the target surface may not have an alpha channel or room 
00392          * for it (ex : already fully packed 16 bit per pixel), hence we 
00393          * use a full 32 bit to make any new alpha fit in overall pixel.
00394          *
00395          * So the ugly artifact is corrected now, at the expense of a 
00396          * rather complicated code, which may fail with (very) uncommon 
00397          * pixel formats where there would be no room for a leading 
00398          * or trailing byte which could be dedicated to the alpha coordinate 
00399          * on a 32 bit pixel.
00400          *
00401          */
00402          
00403 
00404         bool alphaShiftModified = false ;
00405         Ceylan::Uint8 alphaShift = 0 ;
00406         
00407         if ( alphaMask == 0 )
00408         {
00409         
00410             alphaShiftModified = true ;
00411             
00412             // Alpha coordinate must be preserved :
00413             alphaMask = 0xff000000 ;
00414             
00415             if ( alphaMask & ( redMask | greenMask | blueMask ) )
00416             {
00417             
00418                 /*
00419                  * Damned, this one collides with other color masks, try 
00420                  * last chance :
00421                  *
00422                  */
00423                 alphaMask = 0x000000ff ;
00424                 
00425                 if ( alphaMask & ( redMask | greenMask | blueMask ) )
00426                 {
00427                     LogPlug::error( 
00428                         "UprightRectangle::drawWithRoundedCorners : "
00429                         "unable to correct alpha, blit will be opaque." ) ;
00430                     alphaMask = 0 ; 
00431                 }
00432                 else
00433                 {
00434                     /*
00435                      * Second alpha proposal is ok, let's keep it. 
00436                      * alphaShift is already ok (0).
00437                      *
00438                      */
00439                 }
00440             }
00441             else
00442             {
00443             
00444                 /*
00445                  * First alpha proposal is ok, let's keep it (3 byte offset 
00446                  * to have alpha) :
00447                  *
00448                  */
00449                 alphaShift = 24 ;
00450                 
00451             }
00452         }
00453         
00454         
00455 #if OSDL_DEBUG_RECTANGLES
00456 
00457         LogPlug::trace( 
00458             "UprightRectangle::drawWithRoundedCorners : alpha mask is : " 
00459             + Ceylan::toString( alphaMask, /* bitfield */ true )
00460             + ", alpha shift is : " 
00461             + Ceylan::toNumericalString( alphaShift ) ) ;
00462             
00463 #endif // OSDL_DEBUG_RECTANGLES
00464         
00465         disc = new Surface( Surface::Software | Surface::AlphaBlendingBlit, 
00466             2 * radius, 2 * radius, 32, 
00467             redMask, greenMask, blueMask, alphaMask ) ;
00468         
00469         if ( alphaShiftModified )   
00470             disc->getPixelFormat().Ashift = alphaShift ;
00471             
00472     }
00473     else
00474     {
00475     
00476         /*
00477          * No alphablending issue (full opaque colors).
00478          *
00479          * As the previous method does not work properly in this case 
00480          * (rounding errors which in this case make corners appear with a
00481          * slightly different color from the inner color, again !),
00482          * we use here a colorkey :
00483          *
00484          */
00485 
00486         disc = new Surface( Surface::Software | Surface::ColorkeyBlit, 
00487             2 * radius, 2 * radius, target.getBitsPerPixel(), 
00488             redMask, greenMask, blueMask, 0 ) ;
00489         
00490         /*
00491          * Picking a color key not corresponding to any of the two disc 
00492          * colors : rare colors (ex : Pixels::Bisque) are not used as 
00493          * color keys to avoid bugs very hard to detect.
00494          *
00495          */      
00496         ColorDefinition colorKey = Pixels::selectColorDifferentFrom(
00497             edgeColorDef, backgroundColorDef ) ;
00498         
00499         disc->setColorKey( Surface::ColorkeyBlit | Surface::RLEColorkeyBlit,
00500             colorKey ) ;
00501         
00502         disc->fill( colorKey ) ;
00503         
00504     }
00505 
00506         
00507 #if OSDL_DEBUG_RECTANGLES
00508 
00509     LogPlug::trace( "UprightRectangle::drawWithRoundedCorners : "
00510         "Pixel format of target surface is : " 
00511         + Pixels::toString( target.getPixelFormat() ) ) ;
00512     
00513     LogPlug::trace( "UprightRectangle::drawWithRoundedCorners : "
00514         "Pixel format of disc surface is : " 
00515         + Pixels::toString( disc->getPixelFormat() ) ) ;
00516         
00517     LogPlug::trace( "UprightRectangle::drawWithRoundedCorners : "
00518         "Center of disc location in target rectangle surface after creation : " 
00519         + disc->describePixelAt( radius, radius ) 
00520         + " in " + disc->toString() ) ;
00521         
00522     disc->savePNG( "disc-after-creation.png" ) ;
00523     
00524 #endif // OSDL_DEBUG_RECTANGLES
00525         
00526     if ( ! disc->drawDiscWithEdge( 
00527             /* x */ radius, 
00528             /* y */ radius, 
00529             /* outer radius */ radius,
00530             /* inner radius */ radius - edgeWidth -1, 
00531             /* ring */ edgeColorDef, 
00532             /* disc */ backgroundColorDef, 
00533             /* blended */ false ) )
00534          return false ;
00535          
00536 #if OSDL_DEBUG_RECTANGLES
00537 
00538     LogPlug::trace( "UprightRectangle::drawWithRoundedCorners : "
00539         "Center of disc location in target rectangle surface after drawing : " 
00540         + disc->describePixelAt( radius, radius ) 
00541         + " in " + disc->toString() ) ;
00542         
00543     disc->savePNG( "disc-after-drawing.png" ) ;
00544     
00545 #endif // OSDL_DEBUG_RECTANGLES
00546 
00547         
00548     /*
00549      * Blits in place the four corners (clipping might occur if 'target' 
00550      * is too small) :
00551      *
00552      */
00553     
00554     try 
00555     {
00556     
00557         /*
00558          * Both following '1' have be added so that the upper pixel of 
00559          * the disk, alone in its row (ordinate) does not seem to be a
00560          * disturbing visual artefact.
00561          *
00562          */
00563          
00564         // North-west :
00565         UprightRectangle rectangleCorner( 0, 1, radius, radius ) ;
00566         Point2D drawingPoint( _x, _y + 1 ) ;    
00567         
00568         if ( ! disc->blitTo( target, rectangleCorner, drawingPoint ) )
00569             return false ;
00570     
00571     
00572         // North-east :
00573         
00574         // Width unchanged :
00575         rectangleCorner.setUpperLeftAbscissa( radius + 1 ) ;
00576         
00577         drawingPoint.setX( _x + getWidth() - radius + 1 ) ;
00578         if ( ! disc->blitTo( target, rectangleCorner, drawingPoint ) )
00579             return false ;
00580 
00581     
00582         // South-east :
00583         
00584         // Height unchanged :
00585         rectangleCorner.setUpperLeftOrdinate( radius ) ;
00586         
00587         drawingPoint.setY( _y + getHeight() - radius ) ;
00588         if ( ! disc->blitTo( target, rectangleCorner, drawingPoint ) )
00589             return false ;
00590     
00591         // South-west :
00592         rectangleCorner.setUpperLeftAbscissa( 0 ) ;
00593         drawingPoint.setX( _x ) ;
00594         if ( ! disc->blitTo( target, rectangleCorner, drawingPoint ) )
00595             return false ;
00596 
00597 #if OSDL_DEBUG_RECTANGLES
00598 
00599         LogPlug::trace( "UprightRectangle::drawWithRoundedCorners : "
00600             "Point in blitted disc on target surface : " 
00601             + target.describePixelAt( _x + radius / 2, _y + radius / 2  ) ) ;
00602             
00603 #endif // OSDL_DEBUG_RECTANGLES
00604     
00605     }
00606     catch( const VideoException & e )
00607     {
00608         delete disc ; 
00609         return false ;
00610     }
00611         
00612     delete disc ; 
00613     
00614     
00615     // Draw the inner part of the rounded rectangle :
00616     
00617     UprightRectangle longerInnerRectangle( _x + edgeWidth + 1, _y + radius + 1, 
00618         getWidth() - 2 * edgeWidth - 1, getHeight() - 2 * radius - 1 ) ;
00619         
00620     longerInnerRectangle.draw( target, backgroundColorDef, /* filled */ true ) ;
00621     
00622     UprightRectangle topInnerRectangle( _x + radius, _y + edgeWidth + 2, 
00623         getWidth() - 2 * radius + 1, radius - edgeWidth - 1 ) ;
00624     topInnerRectangle.draw( target, backgroundColorDef, /* filled */ true ) ;
00625     
00626     UprightRectangle bottomInnerRectangle( _x + radius, 
00627         _y + getHeight() - radius, getWidth() - 2 * radius + 1, 
00628         radius - edgeWidth ) ;
00629         
00630     bottomInnerRectangle.draw( target, backgroundColorDef, /* filled */ true ) ;
00631 
00632 #if OSDL_DEBUG_RECTANGLES
00633 
00634     LogPlug::trace( "UprightRectangle::drawWithRoundedCorners : "
00635         "Point in blitted rectangle on target surface : " 
00636         + target.describePixelAt( _x + getWidth() / 2, 
00637             _y + getHeight() / 2  ) ) ;
00638             
00639 #endif // OSDL_DEBUG_RECTANGLES
00640     
00641     
00642     // Draw the parallel edges between the corners :
00643     
00644     // Upper horizontal edge :
00645     
00646     UprightRectangle rectangle( _x + radius, _y + 1, 
00647         getWidth() - 2 * radius + 1, edgeWidth + 1 ) ;
00648     rectangle.draw( target, edgeColorDef, /* filled */ true ) ;
00649     
00650     
00651     // Lower horizontal edge :
00652     
00653     rectangle.setUpperLeftOrdinate( _y + getHeight() - edgeWidth  ) ;
00654     rectangle.draw( target, edgeColorDef, /* filled */ true ) ;
00655     
00656     
00657     // Left vertical edge :
00658     
00659     /*
00660      * This edge seems, with careful watching, a little too on the left, but
00661      * actually it is a consequence of the disc drawing, which expands 
00662      * quite a lot of the left.
00663      *
00664      * Moving the edge one pixel to the right would lead to an offset with 
00665      * the top and bottom fronteer with the disc.
00666      *
00667      */
00668     rectangle.setUpperLeftAbscissa( _x ) ;
00669     rectangle.setWidth( edgeWidth + 1 ) ;
00670     rectangle.setUpperLeftOrdinate( _y + radius + 1 ) ;
00671     rectangle.setHeight( getHeight() - 2 * radius - 1 ) ;
00672     rectangle.draw( target, edgeColorDef, /* filled */ true ) ;
00673     
00674     
00675     // Right vertical edge :
00676     
00677     /*
00678      * With very thin edges, one may notice this edge is thinner. 
00679      * It is the cost of having circles that can finish on each side 
00680      * of a pixel. It can be hardly noticed, and prevents artefacts
00681      * that are a lot more visually disturbing.
00682      *
00683      */
00684     rectangle.setUpperLeftAbscissa( _x + getWidth() - edgeWidth ) ;
00685     rectangle.setWidth( edgeWidth ) ;
00686     rectangle.setUpperLeftOrdinate( _y + radius + 1 ) ;
00687     rectangle.draw( target, edgeColorDef, /* filled */ true ) ;
00688         
00689     return true ;
00690          
00691 }
00692 
00693     
00694 Length UprightRectangle::computeRadiusForRoundRectangle( Length edgeWidth )
00695     const throw( VideoException )
00696 {
00697 
00698     /*
00699      * Radius must be :
00700      *  - necessarily, strictly superior to (edge width + 1) : edge is in circle
00701      *  - necessarily, less than half of the smallest dimensions 
00702      * (otherwise cannot fit)
00703      *  - preferably, not too big (otherwise too much room lost in container)
00704      *  - preferably, not too close to edge width, so that there is really 
00705      * an inner disc
00706      *
00707      */ 
00708     Length min = edgeWidth + 1 ;
00709     
00710     Length max = Ceylan::Maths::Min<Length>( getWidth(), getHeight() ) / 2 ;
00711     
00712     if ( min > max )
00713         throw VideoException( 
00714             "UprightRectangle::computeRadiusForRoundRectangle : "
00715             "no radius could be found for edge width = " 
00716             + Ceylan::toString( edgeWidth ) + " and " + toString() ) ;
00717     
00718     // Mean value is a good choice : 
00719     return ( min + max ) / 2 ;
00720     
00721 }
00722 
00723                         
00724 SDL_Rect * UprightRectangle::toSDLRect() const throw( VideoException )
00725 {
00726 
00727     SDL_Rect * res = new SDL_Rect() ;
00728     
00729 #if OSDL_DEBUG
00730 
00731     if ( res == 0 )
00732         throw VideoException( 
00733             "UprightRectangle::toSDLRect() : not enough memory." ) ;
00734         
00735 #endif // OSDL_DEBUG
00736     
00737     res->x = _x ;
00738     res->y = _y ;
00739     res->w = getWidth() ;
00740     res->h = getHeight() ;
00741     
00742     return res ;
00743     
00744 }
00745 
00746 
00747 const string UprightRectangle::toString( Ceylan::VerbosityLevels level ) 
00748     const throw()
00749 {
00750 
00751     return "Rectangle whose upper-left corner is " 
00752         + Point2D( _x, _y ).toString( level ) 
00753         + " ( width = "  + Ceylan::toString( getWidth() )
00754         + " ; height = " + Ceylan::toString( getHeight() ) + " )" ;
00755         
00756 }
00757     
00758 
00759 bool operator == ( const UprightRectangle & first, 
00760     const UprightRectangle & second ) throw() 
00761 {
00762 
00763     if ( first._x != second._x )
00764         return false ;
00765         
00766     if ( first._y != second._y )
00767         return false ;
00768     
00769     if ( first.getWidth() != second.getWidth() )
00770         return false ;
00771     
00772     if ( first.getHeight() != second.getHeight() )
00773         return false ;
00774         
00775     return true ;   
00776         
00777 }
00778 
00779 
00780 bool operator != ( const UprightRectangle & first, 
00781     const UprightRectangle & second ) throw() 
00782 {
00783 
00784     return ! ( first == second ) ;  
00785         
00786 }
00787 
00788 
00789 std::ostream & operator << ( std::ostream & os, UprightRectangle & rect )
00790     throw()
00791 {
00792 
00793     return os << rect.toString() ;
00794     
00795 }
00796 

Generated on Fri Mar 30 14:47:00 2007 for OSDL by  doxygen 1.5.1